From c43fd7269e417b42c67491348f2f6a3d5ce01315 Mon Sep 17 00:00:00 2001 From: Nicola Krumschmidt Date: Mon, 15 Feb 2021 18:03:48 +0100 Subject: [PATCH] Throw error if the array passed to insert is empty (#4289) --- UPGRADING.md | 2 ++ lib/dialects/mssql/index.js | 2 ++ lib/dialects/mysql/index.js | 4 ++++ lib/dialects/oracle/index.js | 2 ++ lib/dialects/postgres/index.js | 4 ++++ lib/dialects/sqlite3/index.js | 8 ++++++-- test/integration/query/inserts.js | 7 +++++++ 7 files changed, 27 insertions(+), 2 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 2a57dfceaf..c78e2093a3 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -68,6 +68,8 @@ CustomClient.prototype.driverName = 'abcd'; * "first" and "pluck" can no longer be both chained on the same operation. Previously only the last one chained was used, now this would throw an error. +* Trying to execute an operation resulting in an empty query such as inserting an empty array, will now throw an error on all database drivers. + ### Upgrading to version 0.21.0+ * Node.js older than 10 is no longer supported, make sure to update your environment; diff --git a/lib/dialects/mssql/index.js b/lib/dialects/mssql/index.js index 4cff737714..0549a5dda6 100644 --- a/lib/dialects/mssql/index.js +++ b/lib/dialects/mssql/index.js @@ -222,6 +222,8 @@ class Client_MSSQL extends Client { const sql = typeof query === 'string' ? query : query.sql; let rowCount = 0; + if (!sql) throw new Error('The query is empty'); + debug('request::request sql=%s', sql); const request = new Driver.Request(sql, (err, remoteRowCount) => { diff --git a/lib/dialects/mysql/index.js b/lib/dialects/mysql/index.js index cc285afeb8..7b819b9dc5 100644 --- a/lib/dialects/mysql/index.js +++ b/lib/dialects/mysql/index.js @@ -91,6 +91,8 @@ class Client_MySQL extends Client { // Grab a connection, run the query via the MySQL streaming interface, // and pass that through to the stream we've sent back to the client. _stream(connection, obj, stream, options) { + if (!obj.sql) throw new Error('The query is empty'); + options = options || {}; const queryOptions = Object.assign({ sql: obj.sql }, obj.options); return new Promise((resolver, rejecter) => { @@ -113,6 +115,8 @@ class Client_MySQL extends Client { // and any other necessary prep work. _query(connection, obj) { if (!obj || typeof obj === 'string') obj = { sql: obj }; + if (!obj.sql) throw new Error('The query is empty'); + return new Promise(function (resolver, rejecter) { if (!obj.sql) { resolver(); diff --git a/lib/dialects/oracle/index.js b/lib/dialects/oracle/index.js index cb184e3b44..af669f9380 100644 --- a/lib/dialects/oracle/index.js +++ b/lib/dialects/oracle/index.js @@ -43,6 +43,8 @@ class Client_Oracle extends Client { } _stream(connection, obj, stream, options) { + if (!obj.sql) throw new Error('The query is empty'); + return new Promise(function (resolver, rejecter) { stream.on('error', (err) => { if (isConnectionError(err)) { diff --git a/lib/dialects/postgres/index.js b/lib/dialects/postgres/index.js index 0bb9e8c3e0..0fa10a54cb 100644 --- a/lib/dialects/postgres/index.js +++ b/lib/dialects/postgres/index.js @@ -160,6 +160,8 @@ class Client_PG extends Client { } _stream(connection, obj, stream, options) { + if (!obj.sql) throw new Error('The query is empty'); + const PGQueryStream = process.browser ? undefined : require('pg-query-stream'); @@ -184,6 +186,8 @@ class Client_PG extends Client { // Runs the query on the specified connection, providing the bindings // and any other necessary prep work. _query(connection, obj) { + if (!obj.sql) throw new Error('The query is empty'); + let queryConfig = { text: obj.sql, values: obj.bindings || [], diff --git a/lib/dialects/sqlite3/index.js b/lib/dialects/sqlite3/index.js index 6bb64fae78..30816e51a1 100644 --- a/lib/dialects/sqlite3/index.js +++ b/lib/dialects/sqlite3/index.js @@ -84,6 +84,8 @@ class Client_SQLite3 extends Client { // Runs the query on the specified connection, providing the bindings and any // other necessary prep work. _query(connection, obj) { + if (!obj.sql) throw new Error('The query is empty'); + const { method } = obj; let callMethod; switch (method) { @@ -114,13 +116,15 @@ class Client_SQLite3 extends Client { }); } - _stream(connection, sql, stream) { + _stream(connection, obj, stream) { + if (!obj.sql) throw new Error('The query is empty'); + const client = this; return new Promise(function (resolver, rejecter) { stream.on('error', rejecter); stream.on('end', resolver); return client - ._query(connection, sql) + ._query(connection, obj) .then((obj) => obj.response) .then((rows) => rows.forEach((row) => stream.write(row))) .catch(function (err) { diff --git a/test/integration/query/inserts.js b/test/integration/query/inserts.js index d0a1676be8..08e7c521e6 100644 --- a/test/integration/query/inserts.js +++ b/test/integration/query/inserts.js @@ -797,6 +797,13 @@ module.exports = function (knex) { }); }); + it('should throw an error if the array passed in is empty', async function () { + expect(knex('account').insert([])).to.be.rejectedWith( + Error, + 'The query is empty' + ); + }); + it('should handle empty inserts', function () { return knex.schema .createTable('test_default_table', function (qb) {