From 9114bdd8b350a60092b607d99c8e0a930c49f14f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Lepist=C3=B6?= Date: Wed, 11 May 2016 21:01:56 +0300 Subject: [PATCH] Changed implementation of replacing undefined with DEFAULT already in query compiler for every dialect. --- src/client.js | 6 ++---- src/dialects/mssql/index.js | 9 --------- src/dialects/mssql/query/compiler.js | 2 +- src/dialects/oracle/index.js | 3 --- src/dialects/oracle/query/compiler.js | 11 +++++++---- src/dialects/postgres/utils.js | 5 +---- src/dialects/sqlite3/index.js | 10 ---------- src/dialects/sqlite3/query/compiler.js | 14 +++++++++++-- test/unit/query/builder.js | 27 +++++++++----------------- 9 files changed, 32 insertions(+), 55 deletions(-) diff --git a/src/client.js b/src/client.js index f6fc6fefe2..017e38c373 100644 --- a/src/client.js +++ b/src/client.js @@ -22,7 +22,7 @@ var inherits = require('inherits') var EventEmitter = require('events').EventEmitter var SqlString = require('./query/string') -import {assign, uniqueId, cloneDeep, map} from 'lodash' +import {assign, uniqueId, cloneDeep} from 'lodash' var debug = require('debug')('knex:client') var debugQuery = require('debug')('knex:query') @@ -141,9 +141,7 @@ assign(Client.prototype, { }, prepBindings: function(bindings) { - return map(bindings, (binding) => { - return binding === undefined ? this.valueForUndefined : binding - }); + return bindings; }, wrapIdentifier: function(value) { diff --git a/src/dialects/mssql/index.js b/src/dialects/mssql/index.js index 90136609cf..0fa244213a 100644 --- a/src/dialects/mssql/index.js +++ b/src/dialects/mssql/index.js @@ -85,15 +85,6 @@ assign(Client_MSSQL.prototype, { }) }, - prepBindings: function(bindings) { - return map(bindings, (value) => { - if (value === undefined) { - return this.valueForUndefined - } - return value - }) - }, - // Grab a connection, run the query via the MSSQL streaming interface, // and pass that through to the stream we've sent back to the client. _stream: function(connection, obj, stream, options) { diff --git a/src/dialects/mssql/query/compiler.js b/src/dialects/mssql/query/compiler.js index a41635698d..f087b2bc4a 100644 --- a/src/dialects/mssql/query/compiler.js +++ b/src/dialects/mssql/query/compiler.js @@ -44,7 +44,7 @@ assign(QueryCompiler_MSSQL.prototype, { var i = -1 while (++i < insertData.values.length) { if (i !== 0) sql += '), (' - sql += this.formatter.parameterize(insertData.values[i]) + sql += this.formatter.parameterize(insertData.values[i], this.client.valueForUndefined) } sql += ')'; } else if (insertValues.length === 1 && insertValues[0]) { diff --git a/src/dialects/oracle/index.js b/src/dialects/oracle/index.js index d4d2065e28..9037473da5 100644 --- a/src/dialects/oracle/index.js +++ b/src/dialects/oracle/index.js @@ -63,9 +63,6 @@ assign(Client_Oracle.prototype, { else if (Buffer.isBuffer(value)) { return SqlString.bufferToString(value) } - else if (value === undefined) { - return this.valueForUndefined - } return value }) }, diff --git a/src/dialects/oracle/query/compiler.js b/src/dialects/oracle/query/compiler.js index 96eb301450..5da01fd060 100644 --- a/src/dialects/oracle/query/compiler.js +++ b/src/dialects/oracle/query/compiler.js @@ -60,7 +60,7 @@ assign(QueryCompiler_Oracle.prototype, { sql.sql = 'begin ' + map(insertData.values, (value) => { var returningHelper; - var parameterizedValues = !insertDefaultsOnly ? this.formatter.parameterize(value) : ''; + var parameterizedValues = !insertDefaultsOnly ? this.formatter.parameterize(value, this.client.valueForUndefined) : ''; var returningValues = Array.isArray(returning) ? returning : [returning]; var subSql = 'insert into ' + this.tableName + ' '; @@ -79,11 +79,14 @@ assign(QueryCompiler_Oracle.prototype, { // pre bind position because subSql is an execute immediate parameter // later position binding will only convert the ? params + subSql = this.formatter.client.positionBindings(subSql); + + var parameterizedValuesWithoutDefault = parameterizedValues.replace('DEFAULT, ', '').replace(', DEFAULT', ''); return 'execute immediate \'' + subSql.replace(/'/g, "''") + - ((parameterizedValues || returning) ? '\' using ' : '') + - parameterizedValues + - ((parameterizedValues && returning) ? ', ' : '') + + ((parameterizedValuesWithoutDefault || returning) ? '\' using ' : '') + + parameterizedValuesWithoutDefault + + ((parameterizedValuesWithoutDefault && returning) ? ', ' : '') + (returning ? 'out ?' : '') + ';'; }).join(' ') + 'end;'; diff --git a/src/dialects/postgres/utils.js b/src/dialects/postgres/utils.js index 5c1ce48737..34015ee400 100644 --- a/src/dialects/postgres/utils.js +++ b/src/dialects/postgres/utils.js @@ -34,7 +34,7 @@ var arrayString; // to their 'raw' counterparts for use as a postgres parameter // note: you can override this function to provide your own conversion mechanism // for complex types, etc... -var prepareValue = function (val, seen, valueForUndefined) { +var prepareValue = function (val, seen /*, valueForUndefined*/) { if (val instanceof Buffer) { return val; } @@ -47,9 +47,6 @@ var prepareValue = function (val, seen, valueForUndefined) { if (val === null) { return null; } - if (val === undefined) { - return valueForUndefined; - } if (typeof val === 'object') { return prepareObject(val, seen); } diff --git a/src/dialects/sqlite3/index.js b/src/dialects/sqlite3/index.js index 530369dda7..606b63aba9 100644 --- a/src/dialects/sqlite3/index.js +++ b/src/dialects/sqlite3/index.js @@ -110,16 +110,6 @@ assign(Client_SQLite3.prototype, { }) }, - prepBindings: function(bindings) { - return map(bindings, (binding) => { - if (binding === undefined && this.valueForUndefined !== null) { - throw new TypeError("`sqlite` does not support inserting default values. Specify values explicitly or use the `useNullAsDefault` config flag. (see docs http://knexjs.org/#Builder-insert)."); - } else { - return binding - } - }); - }, - // Ensures the response is returned in the same format as other clients. processResponse: function(obj, runner) { var ctx = obj.context; diff --git a/src/dialects/sqlite3/query/compiler.js b/src/dialects/sqlite3/query/compiler.js index 74b60f9b75..5c365157ee 100644 --- a/src/dialects/sqlite3/query/compiler.js +++ b/src/dialects/sqlite3/query/compiler.js @@ -3,7 +3,7 @@ var inherits = require('inherits') var QueryCompiler = require('../../../query/compiler') -import {assign, isEmpty, isString, reduce} from 'lodash' +import {assign, isEmpty, isString, reduce, each} from 'lodash' function QueryCompiler_SQLite3(client, builder) { QueryCompiler.call(this, client, builder) @@ -47,8 +47,17 @@ assign(QueryCompiler_SQLite3.prototype, { sql += '(' + this.formatter.columnize(insertData.columns) + ')' + // backwards compatible error + each(insertData.values, bindings => { + each(bindings, binding => { + if (binding === undefined && this.client.valueForUndefined !== null) { + throw new TypeError("`sqlite` does not support inserting default values. Specify values explicitly or use the `useNullAsDefault` config flag. (see docs http://knexjs.org/#Builder-insert)."); + } + }); + }); + if (insertData.values.length === 1) { - return sql + ' values (' + this.formatter.parameterize(insertData.values[0]) + ')' + return sql + ' values (' + this.formatter.parameterize(insertData.values[0], this.client.valueForUndefined) + ')' } var blocks = [] @@ -56,6 +65,7 @@ assign(QueryCompiler_SQLite3.prototype, { while (++i < insertData.values.length) { var i2 = -1, block = blocks[i] = [] var current = insertData.values[i] + current = current === undefined ? this.client.valueForUndefined : current while (++i2 < insertData.columns.length) { block.push(this.formatter.alias( this.formatter.parameter(current[i2]), diff --git a/test/unit/query/builder.js b/test/unit/query/builder.js index 10bf10008f..d31cf805e9 100644 --- a/test/unit/query/builder.js +++ b/test/unit/query/builder.js @@ -28,15 +28,6 @@ var clientsWithNullAsDefault = { default: new Client(useNullAsDefaultConfig) } -var valuesForUndefined = { - mysql: clients.mysql.valueForUndefined, - sqlite3: clients.sqlite3.valueForUndefined, - oracle: clients.oracle.valueForUndefined, - postgres: clients.postgres.valueForUndefined, - mssql: clients.mssql.valueForUndefined, - default: clients.default.valueForUndefined -}; - function qb() { return clients.default.queryBuilder() } @@ -1831,7 +1822,7 @@ describe("QueryBuilder", function() { it("multiple inserts with partly undefined keys", function() { testquery(qb().from('users').insert([{email: 'foo', name: 'taylor'}, {name: 'dayle'}]), { mysql: "insert into `users` (`email`, `name`) values ('foo', 'taylor'), (DEFAULT, 'dayle')", - oracle: 'begin execute immediate \'insert into "users" ("email", "name") values (:1, :2)\' using \'foo\', \'taylor\'; execute immediate \'insert into "users" ("email", "name") values (:1, :2)\' using DEFAULT, \'dayle\';end;', + oracle: 'begin execute immediate \'insert into "users" ("email", "name") values (:1, :2)\' using \'foo\', \'taylor\'; execute immediate \'insert into "users" ("email", "name") values (DEFAULT, :1)\' using \'dayle\';end;', mssql: "insert into [users] ([email], [name]) values ('foo', 'taylor'), (DEFAULT, 'dayle')", default: 'insert into "users" ("email", "name") values (\'foo\', \'taylor\'), (DEFAULT, \'dayle\')' }); @@ -1956,12 +1947,12 @@ describe("QueryBuilder", function() { bindings: [1, undefined, undefined, undefined, 2, undefined, 2, undefined, 3] }, oracle: { - sql: "begin execute immediate 'insert into \"table\" (\"a\", \"b\", \"c\") values (:1, :2, :3)' using ?, ?, ?; execute immediate 'insert into \"table\" (\"a\", \"b\", \"c\") values (:1, :2, :3)' using ?, ?, ?; execute immediate 'insert into \"table\" (\"a\", \"b\", \"c\") values (:1, :2, :3)' using ?, ?, ?;end;", - bindings: [1, valuesForUndefined.oracle, valuesForUndefined.oracle, valuesForUndefined.oracle, 2, valuesForUndefined.oracle, 2, valuesForUndefined.oracle, 3] + sql: "begin execute immediate 'insert into \"table\" (\"a\", \"b\", \"c\") values (:1, DEFAULT, DEFAULT)' using ?; execute immediate 'insert into \"table\" (\"a\", \"b\", \"c\") values (DEFAULT, :1, DEFAULT)' using ?; execute immediate 'insert into \"table\" (\"a\", \"b\", \"c\") values (:1, DEFAULT, :2)' using ?, ?;end;", + bindings: [1, 2, 2, 3] }, mssql: { - sql: 'insert into [table] ([a], [b], [c]) values (?, ?, ?), (?, ?, ?), (?, ?, ?)', - bindings: [1, valuesForUndefined.mssql, valuesForUndefined.mssql, valuesForUndefined.mssql, 2, valuesForUndefined.mssql, 2, valuesForUndefined.mssql, 3] + sql: 'insert into [table] ([a], [b], [c]) values (?, DEFAULT, DEFAULT), (DEFAULT, ?, DEFAULT), (?, DEFAULT, ?)', + bindings: [1, 2, 2, 3] }, default: { sql: 'insert into "table" ("a", "b", "c") values (?, DEFAULT, DEFAULT), (DEFAULT, ?, DEFAULT), (?, DEFAULT, ?)', @@ -3308,12 +3299,12 @@ describe("QueryBuilder", function() { bindings: ['test', 1, 'none'] }, oracle: { - sql: 'begin execute immediate \'insert into "users" ("id", "name", "occupation") values (:1, :2, :3)\' using ?, ?, ?; execute immediate \'insert into "users" ("id", "name", "occupation") values (:1, :2, :3)\' using ?, ?, ?;end;', - bindings: [valuesForUndefined.oracle, 'test', valuesForUndefined.oracle, 1, valuesForUndefined.oracle, 'none'] + sql: 'begin execute immediate \'insert into "users" ("id", "name", "occupation") values (DEFAULT, :1, DEFAULT)\' using ?; execute immediate \'insert into "users" ("id", "name", "occupation") values (:1, DEFAULT, :2)\' using ?, ?;end;', + bindings: ['test', 1, 'none'] }, mssql: { - sql: 'insert into [users] ([id], [name], [occupation]) values (?, ?, ?), (?, ?, ?)', - bindings: [valuesForUndefined.mssql, 'test', valuesForUndefined.mssql, 1, valuesForUndefined.mssql, 'none'] + sql: 'insert into [users] ([id], [name], [occupation]) values (DEFAULT, ?, DEFAULT), (?, DEFAULT, ?)', + bindings: ['test', 1, 'none'] }, postgres: { sql: 'insert into "users" ("id", "name", "occupation") values (DEFAULT, ?, DEFAULT), (?, DEFAULT, ?)',