From d22880fa5b89e38ffd82a6e2cb32ea896a1de510 Mon Sep 17 00:00:00 2001 From: Volkmar Nissen Date: Thu, 9 Jan 2025 12:21:47 +0100 Subject: [PATCH 1/4] Support Array of values for bulk inserts --- src/main.js | 74 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 17 deletions(-) diff --git a/src/main.js b/src/main.js index bfb72f7..3eb471a 100644 --- a/src/main.js +++ b/src/main.js @@ -128,26 +128,66 @@ module.exports = (RED) => { return; } - const isAnObject = value => value === Object(value) && !Array.isArray(value); + const isAnObject = (value) => value === Object(value); if (msg.payload !== undefined && !isAnObject(msg.payload)) { - this.error('msg.payload should be an object containing the query arguments.'); + this.error( + "msg.payload should be an object or an array containing the query arguments." + ); return; } - - try { - const [ result ] = await this.serverConfig - .query( - msg.topic, - msg.payload - ); - this.setState('queryDone'); - msg.payload = result; - this.send(msg); - } - catch (error) { - this.error(error, msg); - this.setState('error', error.toString()); - } + let values = []; + if (!(msg.payload != undefined && Array.isArray(msg.payload))) + values = [msg.payload]; + else values = msg.payload; + let thisNode = this; + this.serverConfig.pool.getConnection(function (_err, connection) { + connection.beginTransaction(function (err) { + if (err) { + connection.rollback(function () { + connection.release(); + }); + } + let result = []; + let promisses = []; + msg.payload = values.forEach((value) => { + promisses.push( + new Promise(function (resolve, reject) { + connection.query( + msg.topic, + value, + function (error, results, _fields) { + if (error) + reject( error) + else resolve(results); + } + ); + }) + ); + }); + Promise.all(promisses).then((results) => { + connection + .commit(function (error) { + if (error) { + connection.rollback(function () { + connection.release(); + //Failure + thisNode.error(error); + thisNode.setState("error", error.toString()); + }); + } else { + connection.release(); + msg.payload = results; + thisNode.setState("queryDone"); + thisNode.send(msg); + } + }) + + }).catch((error) => { + thisNode.error(error); + thisNode.setState("error", error.toString()); + });; + }); + }); }); this.on('close', async () => { From f1b313f66da0e6371364e40df5fca17c82f2ea70 Mon Sep 17 00:00:00 2001 From: Volkmar Nissen Date: Thu, 9 Jan 2025 12:28:54 +0100 Subject: [PATCH 2/4] removed unused variable results --- src/main.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.js b/src/main.js index 3eb471a..87ebfa9 100644 --- a/src/main.js +++ b/src/main.js @@ -147,7 +147,6 @@ module.exports = (RED) => { connection.release(); }); } - let result = []; let promisses = []; msg.payload = values.forEach((value) => { promisses.push( From ea4701a82546192ad7c4ffee93da810f2986f94b Mon Sep 17 00:00:00 2001 From: volkmarnissen Date: Thu, 16 Jan 2025 08:07:55 +0100 Subject: [PATCH 3/4] Update README.md for array processing in one transaction --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a430c1..fcbdeea 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,19 @@ msg.topic = 'SELECT * FROM `users` WHERE `name` = :name AND `age` > :age;'; msg.payload = { name: 'Adrien', age: 30 }; return msg; ``` +If you have multiple arguments, put them in an array of objects in the `payload` variable. +You will get the result in the `payload` output variable. + +Example: +```javascript +msg.topic = 'INSERT INTO `users` (`name`, `age`) VALUES( :name, :age) ;'; +msg.payload = [ + { name: 'Adrien', age: 30 }, + { name: 'Maria', age: 62 } +] +return msg; +``` > Avoid SQL injections!! > > Do not NEVER EVER put variables content in `topic` directly! @@ -54,4 +66,4 @@ You have to connect using TLS encryption. Simply check the box in this node conf You are probably using another node than `node-red-contrib-stackhero-mysql` and tryin to connect to a MySQL >= 8 server using "Caching SHA2 password" authentication method. -To resolve that issue, simply use this node `node-red-contrib-stackhero-mysql`. \ No newline at end of file +To resolve that issue, simply use this node `node-red-contrib-stackhero-mysql`. From c75870a6e76cd73bab47f52accfa401271361bb1 Mon Sep 17 00:00:00 2001 From: Volkmar Nissen Date: Fri, 23 May 2025 11:57:40 +0200 Subject: [PATCH 4/4] Fix error handling issue with undefined connection --- src/main.js | 87 +++++++++++++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/src/main.js b/src/main.js index 87ebfa9..f207795 100644 --- a/src/main.js +++ b/src/main.js @@ -140,52 +140,55 @@ module.exports = (RED) => { values = [msg.payload]; else values = msg.payload; let thisNode = this; - this.serverConfig.pool.getConnection(function (_err, connection) { - connection.beginTransaction(function (err) { + this.serverConfig.pool.getConnection(function (err, connection) { if (err) { - connection.rollback(function () { - connection.release(); - }); + if(connection) + connection.rollback(function () { + connection.release(); + }); + return } - let promisses = []; - msg.payload = values.forEach((value) => { - promisses.push( - new Promise(function (resolve, reject) { - connection.query( - msg.topic, - value, - function (error, results, _fields) { - if (error) - reject( error) - else resolve(results); - } - ); - }) - ); - }); - Promise.all(promisses).then((results) => { - connection - .commit(function (error) { - if (error) { - connection.rollback(function () { + connection.beginTransaction(function (err) { + let promisses = []; + msg.payload = values.forEach((value) => { + promisses.push( + new Promise(function (resolve, reject) { + connection.query( + msg.topic, + value, + + function (error, results, _fields) { + if (error) + reject( error) + else resolve(results); + } + ); + }) + ); + }); + Promise.all(promisses).then((results) => { + connection + .commit(function (error) { + if (error) { + connection.rollback(function () { + connection.release(); + //Failure + thisNode.error(error); + thisNode.setState("error", error.toString()); + }); + } else { connection.release(); - //Failure - thisNode.error(error); - thisNode.setState("error", error.toString()); - }); - } else { - connection.release(); - msg.payload = results; - thisNode.setState("queryDone"); - thisNode.send(msg); - } - }) + msg.payload = results; + thisNode.setState("queryDone"); + thisNode.send(msg); + } + }) - }).catch((error) => { - thisNode.error(error); - thisNode.setState("error", error.toString()); - });; - }); + }).catch((error) => { + thisNode.error(error); + thisNode.setState("error", error.toString()); + });; + }); }); });