Skip to content
Permalink
Browse files

Merge af31a4e into e5972b8

  • Loading branch information
6uliver committed Aug 26, 2019
2 parents e5972b8 + af31a4e commit cfe5a7785adbb8f2f5fe4677c84782ecff5e2775
@@ -129,7 +129,8 @@ assign(SQLite3_DDL.prototype, {
},

_doReplace(sql, from, to) {
const matched = sql.match(/^CREATE TABLE (\S+) \((.*)\)/);
const oneLineSql = sql.replace(/\s+/g, ' ');
const matched = oneLineSql.match(/^CREATE TABLE (\S+) \((.*)\)/);

const tableName = matched[1];
const defs = matched[2];
@@ -166,23 +167,27 @@ assign(SQLite3_DDL.prototype, {
}
args.push(defs.slice(ptr, i));

// Backwards compatible for double quoted sqlite databases
// Detect CREATE TABLE "accounts" ("id"...)
// The "from" and "to" field use backsticks, because this is the default notation for
// SQlite3 since Knex 0.14.
// e.g. from: `about`
//
// We have to replace the from+to field with double slashes in case you created your SQlite3
// database with Knex < 0.14.
if (sql.match(/CREATE\sTABLE\s".*"\s\("/)) {
from = from.replace(/[`]/g, '"');
to = to.replace(/[`]/g, '"');
}
const fromIdentifier = from.replace(/[`"]/g, '');

args = args.map(function(item) {
let split = item.split(' ');
let split = item.trim().split(' ');

let normalizedFrom = from;

if (split[0] === from) {
// Backwards compatible for double quoted sqlite databases
// The "from" and "to" field use backsticks, because this is the default notation for
// SQlite3 since Knex 0.14.
// e.g. from: `about`
//
// We have to replace the from+to field with double slashes in case you created your SQlite3
// database with Knex < 0.14.
if (item.match(`"${fromIdentifier}"`)) {
normalizedFrom = `"${fromIdentifier}"`;
} else if (item.match(`\`${fromIdentifier}\``)) {
normalizedFrom = `\`${fromIdentifier}\``;
}

if (split[0] === normalizedFrom) {
// column definition
if (to) {
split[0] = to;
@@ -198,7 +203,9 @@ assign(SQLite3_DDL.prototype, {
// columns from this table listed between (); replace
// one if it matches
if (/primary|unique/i.test(split[idx])) {
return item.replace(/\(.*\)/, (columns) => columns.replace(from, to));
return item.replace(/\(.*\)/, (columns) =>
columns.replace(normalizedFrom, to)
);
}

// foreign keys have one or more columns from this table
@@ -210,19 +217,19 @@ assign(SQLite3_DDL.prototype, {
split = item.split(/ references /i);
// the quoted column names save us from having to do anything
// other than a straight replace here
split[0] = split[0].replace(from, to);
split[0] = split[0].replace(normalizedFrom, to);

if (split[1].slice(0, tableName.length) === tableName) {
split[1] = split[1].replace(/\(.*\)/, (columns) =>
columns.replace(from, to)
columns.replace(normalizedFrom, to)
);
}
return split.join(' references ');
}

return item;
});
return sql
return oneLineSql
.replace(/\(.*\)/, () => `(${args.join(', ')})`)
.replace(/,\s*([,)])/, '$1');
},
@@ -5,18 +5,22 @@ const logger = require('./logger');
const config = require('../knexfile');
const fs = require('fs');

const Bluebird = require('bluebird');

Object.keys(config).forEach((dialectName) => {
return require('./suite')(logger(knex(config[dialectName])));
});

after(function(done) {
before(function() {
if (config.sqlite3 && config.sqlite3.connection.filename !== ':memory:') {
fs.copyFileSync(
__dirname + '/../multilineCreateMasterSample.sqlite3',
__dirname + '/../multilineCreateMaster.sqlite3'
);
}
});

after(function() {
if (config.sqlite3 && config.sqlite3.connection.filename !== ':memory:') {
fs.unlink(config.sqlite3.connection.filename, function() {
done();
});
} else {
done();
fs.unlinkSync(config.sqlite3.connection.filename);
fs.unlinkSync(__dirname + '/../multilineCreateMaster.sqlite3');
}
});
@@ -6,6 +6,10 @@ const fs = require('fs');
const path = require('path');
const rimraf = require('rimraf');
const Bluebird = require('bluebird');
const knexLib = require('../../../knex');
const logger = require('../logger');
const config = require('../../knexfile');
const _ = require('lodash');
const testMemoryMigrations = require('./memory-migrations');

module.exports = function(knex) {
@@ -72,6 +76,25 @@ module.exports = function(knex) {
});
}

if (knex.client.driverName === 'sqlite3') {
it('should not fail rename-and-drop-column with multiline sql from legacy db', async () => {
const knexConfig = _.extend({}, config.sqlite3, {
connection: {
filename: __dirname + '/../../multilineCreateMaster.sqlite3',
},
migrations: {
directory:
'test/integration/migrate/rename-and-drop-column-with-multiline-sql-from-legacy-db',
},
});

const db = logger(knexLib(knexConfig));

await db.migrate.latest();
await db.migrate.rollback();
});
}

it('should not fail drop-and-recreate-column operation when using async/await', () => {
return knex.migrate
.latest({
@@ -0,0 +1,11 @@
exports.up = function(knex) {
return knex.schema.table('TestTableCreatedWithDBBrowser', function(table) {
table.renameColumn('id', 'testId');
});
};

exports.down = function(knex) {
return knex.schema.table('TestTableCreatedWithDBBrowser', function(table) {
table.renameColumn('testId', 'id');
});
};
@@ -0,0 +1,11 @@
exports.up = function(knex) {
return knex.schema.table('TestTableCreatedWithDBBrowser', function(table) {
table.dropColumn('description');
});
};

exports.down = function(knex) {
return knex.schema.table('TestTableCreatedWithDBBrowser', function(table) {
table.text('description');
});
};
Binary file not shown.
@@ -16,7 +16,7 @@ it('[backwards compatible] can rename column with double quotes', function() {

const newSql = ddl._doReplace(sql, '`about`', '`about_me`');
newSql.should.eql(
'CREATE TABLE "accounts" ("id" varchar(24) not null primary key, "about_me" varchar(24))'
'CREATE TABLE "accounts" ("id" varchar(24) not null primary key, `about_me` varchar(24))'
);
});

@@ -48,7 +48,7 @@ it('[backwards compatible] can rename column with double quotes', function() {

const newSql = ddl._doReplace(sql, '"about"', '`about_me`');
newSql.should.eql(
'CREATE TABLE "accounts" ("id" varchar(24) not null primary key, "about_me" varchar(24))'
'CREATE TABLE "accounts" ("id" varchar(24) not null primary key, `about_me` varchar(24))'
);
});

@@ -67,3 +67,35 @@ it('can rename column with back sticks', function() {
'CREATE TABLE `accounts` (`id` varchar(24) not null primary key, `about_me` varchar(24))'
);
});

it('can rename column with multiline and tabulated sql statement', function() {
const client = sinon.stub();
const tableCompiler = sinon.stub();
const pragma = sinon.stub();
const connection = sinon.stub();
const ddl = new DDL(client, tableCompiler, pragma, connection);

const sql =
'CREATE TABLE `accounts` (\n\n`id`\tvarchar(24) not null primary key,\r\n`about`\t \t\t \tvarchar(24)\n\n)';

const newSql = ddl._doReplace(sql, '`about`', '`about_me`');
newSql.should.eql(
'CREATE TABLE `accounts` (`id` varchar(24) not null primary key, `about_me` varchar(24))'
);
});

it('can drop column with multiline and tabulated sql statement', function() {
const client = sinon.stub();
const tableCompiler = sinon.stub();
const pragma = sinon.stub();
const connection = sinon.stub();
const ddl = new DDL(client, tableCompiler, pragma, connection);

const sql =
'CREATE TABLE `accounts` (\n\n`id`\tvarchar(24) not null primary key,\r\n`about`\t \tvarchar(24)\n)';

const newSql = ddl._doReplace(sql, '`about`', '');
newSql.should.eql(
'CREATE TABLE `accounts` (`id` varchar(24) not null primary key)'
);
});

0 comments on commit cfe5a77

Please sign in to comment.
You can’t perform that action at this time.