diff --git a/storage/mysql/68-mysql.js b/storage/mysql/68-mysql.js
index a3362fa50..ae29dee1d 100644
--- a/storage/mysql/68-mysql.js
+++ b/storage/mysql/68-mysql.js
@@ -102,6 +102,8 @@ module.exports = function(RED) {
RED.nodes.createNode(this,n);
this.mydb = n.mydb;
this.mydbConfig = RED.nodes.getNode(this.mydb);
+ this.query = n.query;
+ this.parameterSource = n.parameterSource || 'payload';
if (this.mydbConfig) {
this.mydbConfig.connect();
@@ -118,24 +120,67 @@ module.exports = function(RED) {
node.on("input", function(msg) {
if (node.mydbConfig.connected) {
- if (typeof msg.topic === 'string') {
- //console.log("query:",msg.topic);
- var bind = Array.isArray(msg.payload) ? msg.payload : [];
- node.mydbConfig.connection.query(msg.topic, bind, function(err, rows) {
- if (err) {
- node.error(err,msg);
- node.status({fill:"red",shape:"ring",text:"Error"});
- }
- else {
- msg.payload = rows;
- node.send(msg);
- node.status({fill:"green",shape:"dot",text:"OK"});
- }
- });
+ node.status({fill:"green",shape:"dot",text:"connected"});
+
+ // Query to be executed
+ var query = node.query;
+
+ // Array of input parameters
+ var parameters = [];
+
+ if(query.length){
+ // Search for all paramters in a query
+ var parametersUsed = node.query.match(/\{\{[A-z\.0-9]*?\}\}/g);
+ var parameterSourcePath = node.parameterSource.split('.');
+
+ var sourceObject = msg;
+
+ // Defaults to top level
+ var parameterSourceKey = parameterSourcePath.shift();
+ while(parameterSourceKey){
+ sourceObject = sourceObject[parameterSourceKey];
+
+ parameterSourceKey = parameterSourcePath.shift();
+ }
+ // Loop matched parameters in query
+ if(parametersUsed) {
+ for(var i=0; i < parametersUsed.length; i++){
+ var parameter = parametersUsed[i];
+ query = query.replace(parameter,'?');
+
+ // Clean out {{}} characters and create a dot deliminated array of keys to traverse.
+ var parameterPath = parameter.replace(/[^A-z\.0-9]/g,'')
+ .split('.');
+
+ // Default to key
+ var value = sourceObject;
+ var parameterPathKey = parameterPath.shift();
+ while(parameterPathKey){
+ value = value[parameterPathKey];
+ parameterPathKey = parameterPath.shift();
+ }
+
+ // Add to our parameter array for query execution
+ parameters.push(value);
+ }
+ }
}
- else {
- if (typeof msg.topic !== 'string') { node.error("msg.topic : the query is not defined as a string"); }
+ else if (typeof msg.topic === 'string') {
+ parameters = Array.isArray(msg.payload) ? msg.payload : [];
+ query = msg.topic;
}
+
+ node.mydbConfig.connection.query(query, parameters, function(err, rows) {
+ if (err) {
+ node.error(err,msg);
+ node.status({fill:"red",shape:"ring",text:"Error"});
+ }
+ else {
+ msg.payload = rows;
+ node.send(msg);
+ node.status({fill:"green",shape:"dot",text:"OK"});
+ }
+ });
}
else {
node.error("Database not connected",msg);
diff --git a/storage/mysql/README.md b/storage/mysql/README.md
index b3b769304..8e0ac9587 100644
--- a/storage/mysql/README.md
+++ b/storage/mysql/README.md
@@ -15,15 +15,38 @@ Usage
Allows basic access to a MySQL database.
-This node uses the query operation against the configured database. This does allow both INSERTS and DELETES.
+This node uses the query operation against the configured database. This does allow both INSERTS and DELETES.
-By it's very nature it allows SQL injection... so be careful out there...
+Using legacy method where queries are set in `msg.topic` allows SQL injection... so be careful out there...
-The `msg.topic` must hold the query for the database, and the result is returned in `msg.payload`.
+###Direct Inserted Queries
+
+With SQL queries that are directly added on the node, variables are escaped.
+
+SQL queries can use mustache style variable insertion. If our `msg.payload` has a property `key`, we would write a query as following:
+
+```
+ SELECT *
+ FROM table
+ WHERE column = {{key}};
+```
+
+For more escaped input information, you can refer to the documentation for [mysqljs/mysql](https://github.com/mysqljs/mysql).
+
+###Results
Typically the returned payload will be an array of the result rows.
-If nothing is found for the key then null is returned.
+If nothing is found for the key then null is returned,
+
+###Misc.
+
+The reconnect timeout in milliseconds can be changed by adding a line to settings.js
+
+`mysqlReconnectTime: 30000,`
+
+###Legacy
+
+`msg.topic` must hold the query for the database, and the result is returned in `msg.payload`.
-The reconnect retry timeout in milliseconds can be changed by adding a line to settings.js
-