You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Explain what kind of behavior you are getting and how you think it should work.
When using the SQLite driver with a JSON column, the behavior between inserting a single record and multiple records is different.
awaitknex.from('my_table').insert([{my_column: {a: 1}},])// Results in conversion being done via JSON.stringify:// sql: 'insert into `my_table` (`my_column`) values (?)',// bindings: [ '{"a":1}' ]awaitknex.from('my_table').insert([{my_column: {b: 2}},{my_column: {c: 3}},])// Results in conversion NOT being done:// sql: 'insert into `my_table` (`my_column`) select ? as `my_column` union all select ? as `my_column`',// bindings: [ { b: 2 }, { c: 3 } ]// This causes the string `[object Object]` to be inserted as `.toString()` is called by the SQLite3 driver.
Error message
None, this occurs silently.
Reduced test code, for example in https://npm.runkit.com/knex or if it needs real database connection to MySQL or PostgreSQL, then single file example which initializes needed data and demonstrates the problem.
importKnexfrom'knex'asyncfunctionmain(){console.log('Creating in-memory database ...')constknex=Knex({client: 'sqlite3',connection: ':memory:',useNullAsDefault: true,})console.log('Creating table `my_table` ...')awaitknex.schema.createTable('my_table',(table)=>{table.json('my_column').notNullable()})console.log('Doing single insert ...')constsingleInsert=knex.from('my_table').insert([{my_column: {a: 1}},])console.log('Single insert SQL:',singleInsert.toSQL().toNative())awaitsingleInsertconsole.log('Doing multi insert ...')constmultiInsert=knex.from('my_table').insert([{my_column: {b: 2}},{my_column: {c: 3}},])console.log('Multi insert SQL:',multiInsert.toSQL().toNative())awaitmultiInsertconsole.log('Getting all rows from table...')constrows=awaitknex.from('my_table').select('*')console.log(rows)awaitknex.destroy()}main()// Output:// Creating in-memory database ...// Creating table `my_table` ...// Doing single insert ...// Single insert SQL: {// sql: 'insert into `my_table` (`my_column`) values (?)',// bindings: [ '{"a":1}' ]// }// Doing multi insert ...// Multi insert SQL: {// sql: 'insert into `my_table` (`my_column`) select ? as `my_column` union all select ? as `my_column`',// bindings: [ { b: 2 }, { c: 3 } ]// }// Getting all rows from table...// [// { my_column: '{"a":1}' },// { my_column: '[object Object]' },// { my_column: '[object Object]' }// ]
Additional Notes
Also, an initial quick dive into the codebase seems to suggest the following code is the cause of this. The difference between inserting a single item and multiple is this.client.parameterize() for the single and this.client.parameter() for multiple.
The Sqlite driver also appears to NOT correctly to JSON.stringify() as shown above for values passed to .update() as well. This also seems to be from _prepUpdate() using this.client.parameter() instead of this.client.parameterize().
Environment
Knex version: 3.0.1
Database + version:
sqlite3
version 5.1.6OS: MacOS 14.1
Node: 20.3.1
Bug
When using the SQLite driver with a JSON column, the behavior between inserting a single record and multiple records is different.
None, this occurs silently.
Also, an initial quick dive into the codebase seems to suggest the following code is the cause of this. The difference between inserting a single item and multiple is
this.client.parameterize()
for the single andthis.client.parameter()
for multiple.The Sqlite driver also appears to NOT correctly to
JSON.stringify()
as shown above for values passed to.update()
as well. This also seems to be from_prepUpdate()
usingthis.client.parameter()
instead ofthis.client.parameterize()
.knex/lib/dialects/sqlite3/query/sqlite-querycompiler.js
Lines 85 to 133 in 4ca3dd5
The text was updated successfully, but these errors were encountered: