table.dropColumns doesn't work with sqlite3
See original GitHub issueWhen using SQLite, table.dropColumns
doesn’t accept multiple column names the way it does with other drivers, per the documentation (I compared with how table.dropTimestamps
is implemented just to make sure that I was using it correctly). Here’s how to reproduce this, in a fresh directory:
$ npm init -y
$ npm i --save knex sqlite3
$ node_modules/.bin/knex init
$ node_modules/.bin/knex migrate:make start
$ cat >migrations/*_start.js
exports.up = function(knex, Promise) {
return Promise.all([
knex.schema.createTable('user', function(table) {
table.increments();
})
]);
};
exports.down = function(knex, Promise) {
return Promise.all([
knex.schema.dropTable('user')
]);
};
$ node_modules/.bin/knex migrate:make add-columns
$ cat >migrations/*_add-columns.js
exports.up = function(knex, Promise) {
return Promise.all([
knex.schema.table('user', function(table) {
table.text('name');
table.text('login');
})
]);
};
exports.down = function(knex, Promise) {
return Promise.all([
knex.schema.table('user', function(table) {
table.dropColumns(['name', 'login']);
})
]);
};
$ node_modules/.bin/knex migrate:latest
$ node_modules/.bin/knex migrate:rollback
Instead of successfully dropping the columns, the output is:
Using environment: development
Knex:warning - sqlite does not support inserting default values. Set the `useNullAsDefault` flag to hide this warning. (see docs http://knexjs.org/#Builder-insert).
Knex:warning - migrations failed with error: The column name,login is not in the user table
Error: The column name,login is not in the user table
at SQLite3_DDL.<anonymous> (/home/cjwatson/k/node_modules/knex/lib/dialects/sqlite3/schema/ddl.js:56:28)
at SQLite3_DDL.tryCatcher (/home/cjwatson/k/node_modules/bluebird/js/release/util.js:16:23)
at SQLite3_DDL.getColumn (/home/cjwatson/k/node_modules/bluebird/js/release/method.js:15:34)
at client.transaction.connection (/home/cjwatson/k/node_modules/knex/lib/dialects/sqlite3/schema/ddl.js:223:21)
at /home/cjwatson/k/node_modules/knex/lib/transaction.js:81:20
at tryCatcher (/home/cjwatson/k/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/cjwatson/k/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/home/cjwatson/k/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/home/cjwatson/k/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/home/cjwatson/k/node_modules/bluebird/js/release/promise.js:693:18)
at Async._drainQueue (/home/cjwatson/k/node_modules/bluebird/js/release/async.js:133:16)
at Async._drainQueues (/home/cjwatson/k/node_modules/bluebird/js/release/async.js:143:10)
at Immediate.Async.drainQueues (/home/cjwatson/k/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:637:20)
at tryOnImmediate (timers.js:610:5)
at processImmediate [as _immediateCallback] (timers.js:582:5)
I have to drop the columns one at a time instead (which is presumably particularly inefficient given how table alteration is implemented for SQLite).
I encountered this with knex 0.12.8.
Issue Analytics
- State:
- Created 7 years ago
- Reactions:1
- Comments:5 (1 by maintainers)
Top Results From Across the Web
How to delete or add column in SQLITE? - Stack Overflow
The DROP COLUMN syntax is used to remove an existing column from a table. The DROP COLUMN command removes the named column from...
Read more >ALTER TABLE - SQLite
The DROP COLUMN syntax is used to remove an existing column from a table. The DROP COLUMN command removes the named column from...
Read more >Why can't SQLite drop columns? - Quora
To remove a single column form a data frame, you can just set it to NULL: · myframe$SomeSillyVariableWhichIDontNeed = NULL · To remove...
Read more >Unable to drop a Column in SQLite - Databases - Xojo Forum
SqLite does not support dropping a column. You have to create a copy of the table (along with its data), drop the original...
Read more >Changing/renaming/dropping columns on sqlite doesn't work ...
I ran into the issue while running migrations in laravel 9.0, which uses docrine/dbal behind the curtains. Any kind of change (dropColumn, ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
I only mentioned performance in passing. Sure, I know that performance isn’t especially important here, but my point is that it’s a clear knex bug: the behaviour of the SQLite driver for this function is not the same as the documented behaviour. I reported it because it caused me to spend time figuring out why code that appeared to match your documentation didn’t work, not because I think anyone is going to be too worried about having to drop columns one at a time as such.
The query never makes it as far as the database:
src/dialects/sqlite3/schema/ddl.js
has adropColumn
function that always callsgetColumn
on its first parameter.getColumn
is defined in the same file and checks its own records of what columns are in the table, rejecting “name,login” before it gets as far as SQLite itself. Now look insrc/schema/tablebuilder.js
, wheretable.dropColumns
is defined: notice that it just converts its argument to an array and passes that totable.dropColumn
via the table compiler machinery.The generic
TableCompiler.prototype.dropColumn
implementation insrc/schema/tablecompiler.js
handles the case where its argument is an array of columns. The specificTableCompiler_SQLite3.prototype.dropColumn
implementation insrc/dialects/sqlite3/schema/tablecompiler.js
does not. I haven’t figured out exactly where the comma-join is coming from here, but that seems like a minor point.Hopefully this is enough to be going on with.
Same error when attempting to rename columns:
It seems this hasn’t worked at all in
0.12.*
. It works for mysql.PS: It does work if the sqlite file already has the tables created, thus only the second migration is run.