From 03966ad0f8622c3452b267355d96b44573d9e745 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 18 Aug 2017 20:09:36 -0400 Subject: [PATCH 01/95] build: use precise dist on Travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 8b8dd04..38334b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ node_js: - "6.10" - "7.10" sudo: false +dist: precise cache: directories: - node_modules From c7bdf24736ee02da0be4afa59d0f3046a1ba1d00 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 18 Aug 2017 20:13:42 -0400 Subject: [PATCH 02/95] build: Node.js@6.11 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 38334b4..830eedc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ node_js: - "3.3" - "4.8" - "5.12" - - "6.10" + - "6.11" - "7.10" sudo: false dist: precise From c781ff52e9c8f049bcbcd93ddfff7e1812030c2d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 18 Aug 2017 20:19:04 -0400 Subject: [PATCH 03/95] build: support Node.js 8.x --- .gitignore | 1 + .travis.yml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 25e8bbd..207febb 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ coverage node_modules npm-debug.log +package-lock.json diff --git a/.travis.yml b/.travis.yml index 830eedc..53f2053 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,12 +11,15 @@ node_js: - "5.12" - "6.11" - "7.10" + - "8.4" sudo: false dist: precise cache: directories: - node_modules before_install: + # Skip updating shrinkwrap / lock + - "npm config set shrinkwrap false" # Setup Node.js version-specific dependencies - "test $TRAVIS_NODE_VERSION != '0.6' || npm rm --save-dev nyc" - "test $TRAVIS_NODE_VERSION != '0.8' || npm rm --save-dev nyc" From 8cc043df89341b0e541201760ca45fa7fece075f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 18 Aug 2017 20:29:45 -0400 Subject: [PATCH 04/95] build: eslint@4.4.1 --- lib/SqlString.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/SqlString.js b/lib/SqlString.js index 53e08b3..5887932 100644 --- a/lib/SqlString.js +++ b/lib/SqlString.js @@ -87,8 +87,8 @@ SqlString.format = function format(sql, values, stringifyObjects, timeZone) { while (valuesIndex < values.length && (match = placeholdersRegex.exec(sql))) { var value = match[0] === '??' - ? SqlString.escapeId(values[valuesIndex]) - : SqlString.escape(values[valuesIndex], stringifyObjects, timeZone); + ? SqlString.escapeId(values[valuesIndex]) + : SqlString.escape(values[valuesIndex], stringifyObjects, timeZone); result += sql.slice(chunkIndex, match.index) + value; chunkIndex = placeholdersRegex.lastIndex; diff --git a/package.json b/package.json index 6e1aebe..bddf7b2 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ ], "repository": "mysqljs/sqlstring", "devDependencies": { - "eslint": "3.19.0", + "eslint": "4.4.1", "eslint-plugin-markdown": "1.0.0-beta.6", "nyc": "10.3.2", "urun": "0.0.8", From 16e4c0e3c1cb7aca1fc483f238bc95c4e44a551d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 18 Aug 2017 20:48:31 -0400 Subject: [PATCH 05/95] lint: sync rules with mysqljs/mysql --- .eslintrc | 8 +++++++- README.md | 2 +- lib/SqlString.js | 4 ++-- test/unit/test-SqlString.js | 4 ++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.eslintrc b/.eslintrc index c1045a1..984104b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,8 +5,11 @@ "rules": { "comma-dangle": [2, "never"], "consistent-return": 2, - "indent": ["error", 2, {"SwitchCase": 1}], + "eqeqeq": [2, "allow-null"], + "indent": [2, 2, { "VariableDeclarator": 2, "SwitchCase": 1 }], "key-spacing": [2, { "align": { "beforeColon": true, "afterColon": true, "on": "colon" } }], + "keyword-spacing": 2, + "new-parens": 2, "no-cond-assign": 2, "no-constant-condition": 2, "no-control-regex": 2, @@ -23,6 +26,7 @@ "no-inner-declarations": 2, "no-invalid-regexp": 2, "no-irregular-whitespace": 2, + "no-multiple-empty-lines": [2, { "max": 1 }], "no-negated-in-lhs": 2, "no-obj-calls": 2, "no-regex-spaces": 2, @@ -31,7 +35,9 @@ "no-unexpected-multiline": 2, "no-unreachable": 2, "no-unused-vars": 2, + "quotes": [2, "single", { "avoidEscape": true, "allowTemplateLiterals": true }], "semi": [2, "always"], + "semi-spacing": 2, "space-infix-ops": 2, "use-isnan": 2, "valid-jsdoc": 2, diff --git a/README.md b/README.md index e9f9ca4..c81bc11 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ If you feel the need to escape queries by yourself, you can also use the escapin function directly: ```js -var sql = 'SELECT * FROM posts WHERE title=' + SqlString.escape("Hello MySQL"); +var sql = 'SELECT * FROM posts WHERE title=' + SqlString.escape('Hello MySQL'); console.log(sql); // SELECT * FROM posts WHERE title='Hello MySQL' ``` diff --git a/lib/SqlString.js b/lib/SqlString.js index 5887932..cb7e162 100644 --- a/lib/SqlString.js +++ b/lib/SqlString.js @@ -155,7 +155,7 @@ SqlString.dateToString = function dateToString(date, timeZone) { }; SqlString.bufferToString = function bufferToString(buffer) { - return "X" + escapeString(buffer.toString('hex')); + return 'X' + escapeString(buffer.toString('hex')); }; SqlString.objectToValues = function objectToValues(object, timeZone) { @@ -212,7 +212,7 @@ function convertTimezone(tz) { var m = tz.match(/([\+\-\s])(\d\d):?(\d\d)?/); if (m) { - return (m[1] == '-' ? -1 : 1) * (parseInt(m[2], 10) + ((m[3] ? parseInt(m[3], 10) : 0) / 60)) * 60; + return (m[1] === '-' ? -1 : 1) * (parseInt(m[2], 10) + ((m[3] ? parseInt(m[3], 10) : 0) / 60)) * 60; } return false; } diff --git a/test/unit/test-SqlString.js b/test/unit/test-SqlString.js index fe41b9b..26f7df3 100644 --- a/test/unit/test-SqlString.js +++ b/test/unit/test-SqlString.js @@ -28,11 +28,11 @@ test('SqlString.escapeId', { }, 'arrays are turned into lists': function() { - assert.equal(SqlString.escapeId(['a', 'b', 't.c']), "`a`, `b`, `t`.`c`"); + assert.equal(SqlString.escapeId(['a', 'b', 't.c']), '`a`, `b`, `t`.`c`'); }, 'nested arrays are flattened': function() { - assert.equal(SqlString.escapeId(['a', ['b', ['t.c']]]), "`a`, `b`, `t`.`c`"); + assert.equal(SqlString.escapeId(['a', ['b', ['t.c']]]), '`a`, `b`, `t`.`c`'); } }); From 046402ebad6a5aa03559a151020590cd99aed282 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 18 Aug 2017 20:56:10 -0400 Subject: [PATCH 06/95] build: ignore coverage when linting --- .eslintignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .eslintignore diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..c1cb757 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +.nyc_output/ +coverage/ From 00d34c21f5937b8a34aa10dd85d880e1f8af42a7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 20 Aug 2017 00:06:12 -0400 Subject: [PATCH 07/95] tests: fix actual vs expected in asserts --- test/unit/test-SqlString.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/unit/test-SqlString.js b/test/unit/test-SqlString.js index 26f7df3..40d5ff9 100644 --- a/test/unit/test-SqlString.js +++ b/test/unit/test-SqlString.js @@ -4,27 +4,27 @@ var test = require('utest'); test('SqlString.escapeId', { 'value is quoted': function() { - assert.equal('`id`', SqlString.escapeId('id')); + assert.equal(SqlString.escapeId('id'), '`id`'); }, 'value can be a number': function() { - assert.equal('`42`', SqlString.escapeId(42)); + assert.equal(SqlString.escapeId(42), '`42`'); }, 'value containing escapes is quoted': function() { - assert.equal('`i``d`', SqlString.escapeId('i`d')); + assert.equal(SqlString.escapeId('i`d'), '`i``d`'); }, 'value containing separator is quoted': function() { - assert.equal('`id1`.`id2`', SqlString.escapeId('id1.id2')); + assert.equal(SqlString.escapeId('id1.id2'), '`id1`.`id2`'); }, 'value containing separator and escapes is quoted': function() { - assert.equal('`id``1`.`i``d2`', SqlString.escapeId('id`1.i`d2')); + assert.equal(SqlString.escapeId('id`1.i`d2'), '`id``1`.`i``d2`'); }, 'value containing separator is fully escaped when forbidQualified': function() { - assert.equal('`id1.id2`', SqlString.escapeId('id1.id2', true)); + assert.equal(SqlString.escapeId('id1.id2', true), '`id1.id2`'); }, 'arrays are turned into lists': function() { From 940918b4a09783ee23cd666001dd44585122f1da Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 20 Aug 2017 00:20:04 -0400 Subject: [PATCH 08/95] tests: add escapeId object tests --- test/unit/test-SqlString.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/unit/test-SqlString.js b/test/unit/test-SqlString.js index 40d5ff9..fb5ae26 100644 --- a/test/unit/test-SqlString.js +++ b/test/unit/test-SqlString.js @@ -11,6 +11,18 @@ test('SqlString.escapeId', { assert.equal(SqlString.escapeId(42), '`42`'); }, + 'value can be an object': function() { + assert.equal(SqlString.escapeId({}), '`[object Object]`'); + }, + + 'value toString is called': function() { + assert.equal(SqlString.escapeId({ toString: function() { return 'foo'; } }), '`foo`'); + }, + + 'value toString is quoted': function() { + assert.equal(SqlString.escapeId({ toString: function() { return 'f`oo'; } }), '`f``oo`'); + }, + 'value containing escapes is quoted': function() { assert.equal(SqlString.escapeId('i`d'), '`i``d`'); }, From 03dc88e59d53715a1020a6dd31827277c828a9f4 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 20 Aug 2017 00:29:43 -0400 Subject: [PATCH 09/95] tests: add escape object toString tests --- test/unit/test-SqlString.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/unit/test-SqlString.js b/test/unit/test-SqlString.js index fb5ae26..3d6c622 100644 --- a/test/unit/test-SqlString.js +++ b/test/unit/test-SqlString.js @@ -78,6 +78,14 @@ test('SqlString.escape', { assert.equal(SqlString.escape({a: {nested: true}}), "`a` = '[object Object]'"); }, + 'nested objects use toString': function() { + assert.equal(SqlString.escape({a: { toString: function() { return 'foo'; } }}), "`a` = 'foo'"); + }, + + 'nested objects use toString is quoted': function() { + assert.equal(SqlString.escape({a: { toString: function() { return "f'oo"; } }}), "`a` = 'f\\'oo'"); + }, + 'arrays are turned into lists': function() { assert.equal(SqlString.escape([1, 2, 'c']), "1, 2, 'c'"); }, @@ -90,6 +98,10 @@ test('SqlString.escape', { assert.equal(SqlString.escape([1, {nested: true}, 2]), "1, '[object Object]', 2"); }, + 'nested objects inside arrays use toString': function() { + assert.equal(SqlString.escape([1, { toString: function() { return 'foo'; } }, 2]), "1, 'foo', 2"); + }, + 'strings are quoted': function() { assert.equal(SqlString.escape('Super'), "'Super'"); }, From 7aeeffee9993dffa1a81cfd74960976795214128 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 20 Aug 2017 00:40:05 -0400 Subject: [PATCH 10/95] docs: remove poor wording --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index c81bc11..266d851 100644 --- a/README.md +++ b/README.md @@ -79,8 +79,7 @@ Different value types are escaped differently, here is how: to insert them as values will trigger MySQL errors until they implement support. -If you paid attention, you may have noticed that this escaping allows you -to do neat things like this: +You may have noticed that this escaping allows you to do neat things like this: ```js var post = {id: 1, title: 'Hello MySQL'}; From 4c1f4a963e8069cc74791668bea5ce62873f4652 Mon Sep 17 00:00:00 2001 From: Kevin Jose Martin Date: Fri, 26 Aug 2016 20:45:26 -0400 Subject: [PATCH 11/95] Add .toSqlString() escape overriding closes #9 --- HISTORY.md | 5 +++++ README.md | 10 ++++++++++ lib/SqlString.js | 2 ++ package.json | 1 + test/unit/test-SqlString.js | 15 +++++++++++++++ 5 files changed, 33 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 1a0e0e3..6d9742a 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,8 @@ +unreleased +========== + + * Add `.toSqlString()` escape overriding + 2.2.0 / 2016-11-01 ================== diff --git a/README.md b/README.md index 266d851..052340a 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,8 @@ Different value types are escaped differently, here is how: * Arrays are turned into list, e.g. `['a', 'b']` turns into `'a', 'b'` * Nested arrays are turned into grouped lists (for bulk inserts), e.g. `[['a', 'b'], ['c', 'd']]` turns into `('a', 'b'), ('c', 'd')` +* Objects that have a `toSqlString` method will have `.toSqlString()` called + and the returned value is used as the raw SQL. * Objects are turned into `key = 'val'` pairs for each enumerable property on the object. If the property's value is a function, it is skipped; if the property's value is an object, toString() is called on it and the returned @@ -87,6 +89,14 @@ var sql = SqlString.format('INSERT INTO posts SET ?', post); console.log(sql); // INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL' ``` +And the `toSqlString` method allows you to form complex queries with functions: + +```js +var CURRENT_TIMESTAMP = { toSqlString: function() { return 'CURRENT_TIMESTAMP()'; } }; +var sql = SqlString.format('UPDATE posts SET modified = ? WHERE id = ?', [CURRENT_TIMESTAMP, 42]); +console.log(sql); // UPDATE posts SET modified = CURRENT_TIMESTAMP() WHERE id = 42 +``` + If you feel the need to escape queries by yourself, you can also use the escaping function directly: diff --git a/lib/SqlString.js b/lib/SqlString.js index cb7e162..5bfa2e7 100644 --- a/lib/SqlString.js +++ b/lib/SqlString.js @@ -45,6 +45,8 @@ SqlString.escape = function escape(val, stringifyObjects, timeZone) { return SqlString.arrayToList(val, timeZone); } else if (Buffer.isBuffer(val)) { return SqlString.bufferToString(val); + } else if (typeof val.toSqlString === 'function') { + return String(val.toSqlString()); } else if (stringifyObjects) { return escapeString(val.toString()); } else { diff --git a/package.json b/package.json index bddf7b2..9181829 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "Adri Van Houdt ", "Douglas Christopher Wilson ", "fengmk2 (http://fengmk2.github.com)", + "Kevin Jose Martin ", "Nathan Woltman " ], "license": "MIT", diff --git a/test/unit/test-SqlString.js b/test/unit/test-SqlString.js index 3d6c622..ae85233 100644 --- a/test/unit/test-SqlString.js +++ b/test/unit/test-SqlString.js @@ -74,6 +74,18 @@ test('SqlString.escape', { assert.equal(SqlString.escape({a: 'b', c: function() {}}), "`a` = 'b'"); }, + 'object values toSqlString is called': function() { + assert.equal(SqlString.escape({id: { toSqlString: function() { return 'LAST_INSERT_ID()'; } }}), '`id` = LAST_INSERT_ID()'); + }, + + 'objects toSqlString is called': function() { + assert.equal(SqlString.escape({ toSqlString: function() { return '@foo_id'; } }), '@foo_id'); + }, + + 'objects toSqlString is not quoted': function() { + assert.equal(SqlString.escape({ toSqlString: function() { return 'CURRENT_TIMESTAMP()'; } }), 'CURRENT_TIMESTAMP()'); + }, + 'nested objects are cast to strings': function() { assert.equal(SqlString.escape({a: {nested: true}}), "`a` = '[object Object]'"); }, @@ -272,6 +284,9 @@ test('SqlString.format', { var sql = SqlString.format('?', { toString: function () { return 'hello'; } }, true); assert.equal(sql, "'hello'"); + + var sql = SqlString.format('?', { toSqlString: function () { return '@foo'; } }, true); + assert.equal(sql, '@foo'); }, 'sql is untouched if no values are provided': function () { From e923171d3d4c085dc0797985d9acb218deb145af Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 23 Sep 2017 14:09:36 -0400 Subject: [PATCH 12/95] build: Node.js@8.5 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 53f2053..541bdcd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ node_js: - "5.12" - "6.11" - "7.10" - - "8.4" + - "8.5" sudo: false dist: precise cache: From c3321699caa4dc40477e560b8afc5924e292a1d2 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 23 Sep 2017 14:15:50 -0400 Subject: [PATCH 13/95] build: eslint@4.7.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9181829..0a8110b 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ ], "repository": "mysqljs/sqlstring", "devDependencies": { - "eslint": "4.4.1", + "eslint": "4.7.2", "eslint-plugin-markdown": "1.0.0-beta.6", "nyc": "10.3.2", "urun": "0.0.8", From 57f30b05d612dfb0db3ae8811d58d577e3261145 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 23 Sep 2017 14:21:29 -0400 Subject: [PATCH 14/95] lint: use capitals for constants --- lib/SqlString.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/SqlString.js b/lib/SqlString.js index 5bfa2e7..e7dd69e 100644 --- a/lib/SqlString.js +++ b/lib/SqlString.js @@ -1,6 +1,7 @@ var SqlString = exports; -var charsRegex = /[\0\b\t\n\r\x1a\"\'\\]/g; // eslint-disable-line no-control-regex -var charsMap = { + +var CHARS_GLOBAL_REGEXP = /[\0\b\t\n\r\x1a\"\'\\]/g; // eslint-disable-line no-control-regex +var CHARS_ESCAPE_MAP = { '\0' : '\\0', '\b' : '\\b', '\t' : '\\t', @@ -177,13 +178,13 @@ SqlString.objectToValues = function objectToValues(object, timeZone) { }; function escapeString(val) { - var chunkIndex = charsRegex.lastIndex = 0; + var chunkIndex = CHARS_GLOBAL_REGEXP.lastIndex = 0; var escapedVal = ''; var match; - while ((match = charsRegex.exec(val))) { - escapedVal += val.slice(chunkIndex, match.index) + charsMap[match[0]]; - chunkIndex = charsRegex.lastIndex; + while ((match = CHARS_GLOBAL_REGEXP.exec(val))) { + escapedVal += val.slice(chunkIndex, match.index) + CHARS_ESCAPE_MAP[match[0]]; + chunkIndex = CHARS_GLOBAL_REGEXP.lastIndex; } if (chunkIndex === 0) { From 79ea7b641dcb66fc25f54e16a3a65362c69c807f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 23 Sep 2017 14:50:04 -0400 Subject: [PATCH 15/95] bench: add simple benchmarks --- .travis.yml | 2 ++ benchmark/escape.js | 76 +++++++++++++++++++++++++++++++++++++++++++ benchmark/escapeId.js | 38 ++++++++++++++++++++++ benchmark/index.js | 39 ++++++++++++++++++++++ package.json | 3 ++ 5 files changed, 158 insertions(+) create mode 100644 benchmark/escape.js create mode 100644 benchmark/escapeId.js create mode 100644 benchmark/index.js diff --git a/.travis.yml b/.travis.yml index 541bdcd..52fcd50 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,8 @@ cache: before_install: # Skip updating shrinkwrap / lock - "npm config set shrinkwrap false" + # Remove all non-test dependencies + - "npm rm --save-dev benchmark beautify-benchmark" # Setup Node.js version-specific dependencies - "test $TRAVIS_NODE_VERSION != '0.6' || npm rm --save-dev nyc" - "test $TRAVIS_NODE_VERSION != '0.8' || npm rm --save-dev nyc" diff --git a/benchmark/escape.js b/benchmark/escape.js new file mode 100644 index 0000000..c195de4 --- /dev/null +++ b/benchmark/escape.js @@ -0,0 +1,76 @@ +var benchmark = require('benchmark'); +var benchmarks = require('beautify-benchmark'); + +global.SqlString = require('..'); + +global.arr = [ 42, 'foobar' ]; +global.buf = new Buffer('foobar'); +global.date = new Date(0); +global.func = { toSqlString: function () { return 'NOW()'; } }; +global.num = 42; +global.obj = { foo: 'bar' }; +global.str = 'foobar'; + +var suite = new benchmark.Suite(); + +suite.add({ + name : 'array', + minSamples : 100, + fn : 'var val = SqlString.escape(arr);' +}); + +suite.add({ + name : 'boolean', + minSamples : 100, + fn : 'var val = SqlString.escape(true);' +}); + +suite.add({ + name : 'date', + minSamples : 100, + fn : 'var val = SqlString.escape(date);' +}); + +suite.add({ + name : 'function', + minSamples : 100, + fn : 'var val = SqlString.escape(func);' +}); + +suite.add({ + name : 'null', + minSamples : 100, + fn : 'var val = SqlString.escape(null);' +}); + +suite.add({ + name : 'number', + minSamples : 100, + fn : 'var val = SqlString.escape(num);' +}); + +suite.add({ + name : 'object', + minSamples : 100, + fn : 'var val = SqlString.escape(obj);' +}); + +suite.add({ + name : 'string', + minSamples : 100, + fn : 'var val = SqlString.escape(str);' +}); + +suite.on('start', function onCycle() { + process.stdout.write(' escape\n\n'); +}); + +suite.on('cycle', function onCycle(event) { + benchmarks.add(event.target); +}); + +suite.on('complete', function onComplete() { + benchmarks.log(); +}); + +suite.run({async: false}); diff --git a/benchmark/escapeId.js b/benchmark/escapeId.js new file mode 100644 index 0000000..3113bd0 --- /dev/null +++ b/benchmark/escapeId.js @@ -0,0 +1,38 @@ +var benchmark = require('benchmark'); +var benchmarks = require('beautify-benchmark'); + +global.SqlString = require('..'); + +var suite = new benchmark.Suite(); + +suite.add({ + name : '"col"', + minSamples : 100, + fn : 'var val = SqlString.escapeId("col");' +}); + +suite.add({ + name : '"tbl.col"', + minSamples : 100, + fn : 'var val = SqlString.escapeId("tbl.col");' +}); + +suite.add({ + name : '["col1", "col2"]', + minSamples : 100, + fn : 'var val = SqlString.escapeId(["col1", "col2"]);' +}); + +suite.on('start', function onCycle() { + process.stdout.write(' escapeId\n\n'); +}); + +suite.on('cycle', function onCycle(event) { + benchmarks.add(event.target); +}); + +suite.on('complete', function onComplete() { + benchmarks.log(); +}); + +suite.run({async: false}); diff --git a/benchmark/index.js b/benchmark/index.js new file mode 100644 index 0000000..5c16f5e --- /dev/null +++ b/benchmark/index.js @@ -0,0 +1,39 @@ +var fs = require('fs'); +var path = require('path'); +var spawn = require('child_process').spawn; + +var exe = process.argv[0]; +var cwd = process.cwd(); + +for (var dep in process.versions) { + console.log(' %s@%s', dep, process.versions[dep]); +} + +console.log(''); + +runScripts(fs.readdirSync(__dirname)); + +function runScripts(fileNames) { + var fileName = fileNames.shift(); + + if (!fileName) { + return; + } + + if (!/\.js$/i.test(fileName) || fileName.toLowerCase() === 'index.js') { + runScripts(fileNames); + return; + } + + var fullPath = path.join(__dirname, fileName); + + console.log('> %s %s', exe, path.relative(cwd, fullPath)); + + var proc = spawn(exe, [fullPath], { + 'stdio': 'inherit' + }); + + proc.on('exit', function () { + runScripts(fileNames); + }); +} diff --git a/package.json b/package.json index 0a8110b..731ea1a 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,8 @@ ], "repository": "mysqljs/sqlstring", "devDependencies": { + "beautify-benchmark": "0.2.4", + "benchmark": "2.1.4", "eslint": "4.7.2", "eslint-plugin-markdown": "1.0.0-beta.6", "nyc": "10.3.2", @@ -35,6 +37,7 @@ "node": ">= 0.6" }, "scripts": { + "bench": "node benchmark/index.js", "lint": "eslint --plugin markdown --ext js,md .", "test": "node test/run.js", "test-ci": "nyc --reporter=text npm test", From bee9198a69a2330caf4bc0eb56931aae9bca766b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 23 Sep 2017 14:56:09 -0400 Subject: [PATCH 16/95] docs: fix formatting in history --- HISTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 6d9742a..010f45e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -27,7 +27,7 @@ unreleased 1.0.0 / 2014-11-09 ================== - * build: support Node.js 0.8.x + * Support Node.js 0.8.x 0.0.1 / 2014-02-25 ================== From bd181062272052261132f664ecc32c8d74e35dbb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 23 Sep 2017 14:59:42 -0400 Subject: [PATCH 17/95] docs: add changes to engines to history --- HISTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.md b/HISTORY.md index 010f45e..b647cd6 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -23,6 +23,7 @@ unreleased ================== * Bring repository up-to-date with `mysql` module changes + * Support Node.js 0.6.x 1.0.0 / 2014-11-09 ================== From 5cbf163bbe4af16b5acc0f53573b8bde7facda03 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 23 Sep 2017 15:38:44 -0400 Subject: [PATCH 18/95] Small performance improvement on escapeId --- HISTORY.md | 1 + lib/SqlString.js | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index b647cd6..2aa9e92 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,7 @@ unreleased ========== * Add `.toSqlString()` escape overriding + * Small performance improvement on `escapeId` 2.2.0 / 2016-11-01 ================== diff --git a/lib/SqlString.js b/lib/SqlString.js index e7dd69e..4a49827 100644 --- a/lib/SqlString.js +++ b/lib/SqlString.js @@ -1,5 +1,7 @@ var SqlString = exports; +var ID_GLOBAL_REGEXP = /`/g; +var QUAL_GLOBAL_REGEXP = /\./g; var CHARS_GLOBAL_REGEXP = /[\0\b\t\n\r\x1a\"\'\\]/g; // eslint-disable-line no-control-regex var CHARS_ESCAPE_MAP = { '\0' : '\\0', @@ -22,13 +24,11 @@ SqlString.escapeId = function escapeId(val, forbidQualified) { } return sql; + } else if (forbidQualified) { + return '`' + String(val).replace(ID_GLOBAL_REGEXP, '``') + '`'; + } else { + return '`' + String(val).replace(ID_GLOBAL_REGEXP, '``').replace(QUAL_GLOBAL_REGEXP, '`.`') + '`'; } - - if (forbidQualified) { - return '`' + String(val).replace(/`/g, '``') + '`'; - } - - return '`' + String(val).replace(/`/g, '``').replace(/\./g, '`.`') + '`'; }; SqlString.escape = function escape(val, stringifyObjects, timeZone) { From 4e64398097572b9980215c0d339a55ed9e2b18a7 Mon Sep 17 00:00:00 2001 From: Kip Robinson Date: Thu, 21 Sep 2017 16:03:42 -0400 Subject: [PATCH 19/95] docs: add note about use with NO_BACKSLASH_ESCAPES --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 052340a..722c494 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,10 @@ var SqlString = require('sqlstring'); ### Escaping query values +**Caution** These methods of escaping values only works when the +[NO_BACKSLASH_ESCAPES](https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_backslash_escapes) +SQL mode is disabled (which is the default state for MySQL servers). + In order to avoid SQL Injection attacks, you should always escape any user provided data before using it inside a SQL query. You can do so using the `SqlString.escape()` method: From a4db3d07073d4e4058e9620305ebc402689a4909 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 1 Oct 2017 20:22:14 -0400 Subject: [PATCH 20/95] build: eslint@4.8.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 731ea1a..85739e4 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "devDependencies": { "beautify-benchmark": "0.2.4", "benchmark": "2.1.4", - "eslint": "4.7.2", + "eslint": "4.8.0", "eslint-plugin-markdown": "1.0.0-beta.6", "nyc": "10.3.2", "urun": "0.0.8", From 971f4f08d05b6686c807cc3447835383e7bf3dea Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 1 Oct 2017 20:23:48 -0400 Subject: [PATCH 21/95] build: Node.js@8.6 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 52fcd50..f8d9b24 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ node_js: - "5.12" - "6.11" - "7.10" - - "8.5" + - "8.6" sudo: false dist: precise cache: From b22d66f427b195a432d8d2e60c2e731fde16f8dc Mon Sep 17 00:00:00 2001 From: Sergej Sintschilin Date: Thu, 31 Aug 2017 20:40:52 +0200 Subject: [PATCH 22/95] Add raw method to wrap raw strings for escape overriding closes #13 closes #21 --- HISTORY.md | 1 + README.md | 13 +++++++++++++ lib/SqlString.js | 10 ++++++++++ test/unit/test-SqlString.js | 30 ++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 2aa9e92..769f305 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,7 @@ unreleased ========== * Add `.toSqlString()` escape overriding + * Add `raw` method to wrap raw strings for escape overriding * Small performance improvement on `escapeId` 2.2.0 / 2016-11-01 diff --git a/README.md b/README.md index 722c494..12fce6c 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,19 @@ var sql = SqlString.format('UPDATE posts SET modified = ? WHERE id = ?', [CURREN console.log(sql); // UPDATE posts SET modified = CURRENT_TIMESTAMP() WHERE id = 42 ``` +To generate objects with a `toSqlString` method, the `SqlString.raw()` method can +be used. This creates an object that will be left un-touched when using in a `?` +placeholder, useful for using functions as dynamic values: + +**Caution** The string provided to `SqlString.raw()` will skip all escaping +functions when used, so be careful when passing in unvalidated input. + +```js +var CURRENT_TIMESTAMP = SqlString.raw('CURRENT_TIMESTAMP()'); +var sql = SqlString.format('UPDATE posts SET modified = ? WHERE id = ?', [CURRENT_TIMESTAMP, 42]); +console.log(sql); // UPDATE posts SET modified = CURRENT_TIMESTAMP() WHERE id = 42 +``` + If you feel the need to escape queries by yourself, you can also use the escaping function directly: diff --git a/lib/SqlString.js b/lib/SqlString.js index 4a49827..8bfafd4 100644 --- a/lib/SqlString.js +++ b/lib/SqlString.js @@ -177,6 +177,16 @@ SqlString.objectToValues = function objectToValues(object, timeZone) { return sql; }; +SqlString.raw = function raw(sql) { + if (typeof sql !== 'string') { + throw new TypeError('argument sql must be a string'); + } + + return { + toSqlString: function toSqlString() { return sql; } + }; +}; + function escapeString(val) { var chunkIndex = CHARS_GLOBAL_REGEXP.lastIndex = 0; var escapedVal = ''; diff --git a/test/unit/test-SqlString.js b/test/unit/test-SqlString.js index ae85233..0bd87a4 100644 --- a/test/unit/test-SqlString.js +++ b/test/unit/test-SqlString.js @@ -66,6 +66,10 @@ test('SqlString.escape', { assert.equal(SqlString.escape(5), '5'); }, + 'raw not escaped': function () { + assert.equal(SqlString.escape(SqlString.raw('NOW()')), 'NOW()'); + }, + 'objects are turned into key value pairs': function() { assert.equal(SqlString.escape({a: 'b', c: 'd'}), "`a` = 'b', `c` = 'd'"); }, @@ -299,3 +303,29 @@ test('SqlString.format', { assert.equal(sql, 'SELECT COUNT(*) FROM table'); } }); + +test('SqlString.raw', { + 'creates object': function() { + assert.equal(typeof SqlString.raw('NOW()'), 'object'); + }, + + 'rejects number': function() { + assert.throws(function () { + SqlString.raw(42); + }); + }, + + 'rejects undefined': function() { + assert.throws(function () { + SqlString.raw(); + }); + }, + + 'object has toSqlString': function() { + assert.equal(typeof SqlString.raw('NOW()').toSqlString, 'function'); + }, + + 'toSqlString returns sql as-is': function() { + assert.equal(SqlString.raw("NOW() AS 'current_time'").toSqlString(), "NOW() AS 'current_time'"); + } +}); From 9c88ed5d88623fe24c88b1d367dea7192294dfb0 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 1 Oct 2017 21:00:49 -0400 Subject: [PATCH 23/95] build: update package contributors --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 85739e4..61649d2 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "Douglas Christopher Wilson ", "fengmk2 (http://fengmk2.github.com)", "Kevin Jose Martin ", - "Nathan Woltman " + "Nathan Woltman ", + "Sergej Sintschilin " ], "license": "MIT", "keywords": [ From 222c873b58bb243dc0bdda2e1e1acdd339ceb19a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 1 Oct 2017 21:06:14 -0400 Subject: [PATCH 24/95] docs: add raw method mention to formatting section --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 12fce6c..fafe6f4 100644 --- a/README.md +++ b/README.md @@ -181,6 +181,16 @@ You also have the option (but are not required) to pass in `stringifyObject` and allowing you provide a custom means of turning objects into strings, as well as a location-specific/timezone-aware `Date`. +This can be further combined with the `SqlString.raw()` helper to generate SQL +that includes MySQL functions as dynamic vales: + +```js +var userId = 1; +var data = { email: 'foobar@example.com', modified: SqlString.raw('NOW()') }; +var sql = SqlString.format('UPDATE ?? SET ? WHERE `id` = ?', ['users', data, userId]); +console.log(sql); // UPDATE `users` SET `email` = 'foobar@example.com', `modified` = NOW() WHERE `id` = 1 +``` + ## License [MIT](LICENSE) From 8e919225b7ad8a126345e4903ff6e5acb6d42cf2 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 1 Oct 2017 23:15:53 -0400 Subject: [PATCH 25/95] Release 2.3.0 --- HISTORY.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 769f305..f59473b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,5 @@ -unreleased -========== +2.3.0 / 2017-10-01 +================== * Add `.toSqlString()` escape overriding * Add `raw` method to wrap raw strings for escape overriding diff --git a/package.json b/package.json index 61649d2..68ada43 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "sqlstring", "description": "Simple SQL escape and format for MySQL", - "version": "2.2.0", + "version": "2.3.0", "contributors": [ "Adri Van Houdt ", "Douglas Christopher Wilson ", From 7f72ec02c7b9116adbc1e11bb5a6e9587cf61cdf Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 24 Nov 2017 23:04:58 -0500 Subject: [PATCH 26/95] build: Node.js@6.12 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f8d9b24..4772767 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ node_js: - "3.3" - "4.8" - "5.12" - - "6.11" + - "6.12" - "7.10" - "8.6" sudo: false From 57eb1bb1bebbf3eccd21170111aa6b857e75dfab Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 24 Nov 2017 23:40:02 -0500 Subject: [PATCH 27/95] build: Node.js@8.9 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4772767..c636ac5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ node_js: - "5.12" - "6.12" - "7.10" - - "8.6" + - "8.9" sudo: false dist: precise cache: From a37f22dec0761f3f22ced62a60ff4c42ae4e75ef Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 25 Nov 2017 00:01:23 -0500 Subject: [PATCH 28/95] build: support Node.js 9.x --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c636ac5..7767d27 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ node_js: - "6.12" - "7.10" - "8.9" + - "9.2" sudo: false dist: precise cache: From 362fbb66903113bb841f8df0be94368095a4cbf8 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 25 Nov 2017 00:06:39 -0500 Subject: [PATCH 29/95] build: eslint@4.11.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 68ada43..d50bb35 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "devDependencies": { "beautify-benchmark": "0.2.4", "benchmark": "2.1.4", - "eslint": "4.8.0", + "eslint": "4.11.0", "eslint-plugin-markdown": "1.0.0-beta.6", "nyc": "10.3.2", "urun": "0.0.8", From 485caf63c8f292f91c07670d9a0ddc624b338901 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 24 Feb 2018 18:17:58 -0500 Subject: [PATCH 30/95] Fix incorrectly replacing non-placeholders in SQL fixes #31 --- HISTORY.md | 5 +++++ lib/SqlString.js | 10 ++++++++-- test/unit/test-SqlString.js | 5 +++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index f59473b..47bcb17 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,8 @@ +unreleased +========== + + * Fix incorrectly replacing non-placeholders in SQL + 2.3.0 / 2017-10-01 ================== diff --git a/lib/SqlString.js b/lib/SqlString.js index 8bfafd4..419adec 100644 --- a/lib/SqlString.js +++ b/lib/SqlString.js @@ -83,13 +83,19 @@ SqlString.format = function format(sql, values, stringifyObjects, timeZone) { } var chunkIndex = 0; - var placeholdersRegex = /\?\??/g; + var placeholdersRegex = /\?+/g; var result = ''; var valuesIndex = 0; var match; while (valuesIndex < values.length && (match = placeholdersRegex.exec(sql))) { - var value = match[0] === '??' + var len = match[0].length; + + if (len > 2) { + continue; + } + + var value = len === 2 ? SqlString.escapeId(values[valuesIndex]) : SqlString.escape(values[valuesIndex], stringifyObjects, timeZone); diff --git a/test/unit/test-SqlString.js b/test/unit/test-SqlString.js index 0bd87a4..c394d2f 100644 --- a/test/unit/test-SqlString.js +++ b/test/unit/test-SqlString.js @@ -257,6 +257,11 @@ test('SqlString.format', { assert.equal(sql, 'SELECT * FROM `table` WHERE id = 42'); }, + 'triple question marks are ignored': function () { + var sql = SqlString.format('? or ??? and ?', ['foo', 'bar', 'fizz', 'buzz']); + assert.equal(sql, "'foo' or ??? and 'bar'"); + }, + 'extra question marks are left untouched': function() { var sql = SqlString.format('? and ?', ['a']); assert.equal(sql, "'a' and ?"); From 8bc15edd2a94910ea113dba4e032ce08ca5cf9be Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 24 Feb 2018 18:20:03 -0500 Subject: [PATCH 31/95] build: Node.js@6.13 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7767d27..1c779c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ node_js: - "3.3" - "4.8" - "5.12" - - "6.12" + - "6.13" - "7.10" - "8.9" - "9.2" From c783ce6ca0bc1cf0baa435ff744f2b14545e4848 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 24 Feb 2018 18:20:15 -0500 Subject: [PATCH 32/95] build: Node.js@9.6 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1c779c1..51709f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ node_js: - "6.13" - "7.10" - "8.9" - - "9.2" + - "9.6" sudo: false dist: precise cache: From 6bdfc54e129a35addf2e4942a15d0485afd9e34c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 24 Feb 2018 18:22:27 -0500 Subject: [PATCH 33/95] build: eslint@4.18.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d50bb35..037f172 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "devDependencies": { "beautify-benchmark": "0.2.4", "benchmark": "2.1.4", - "eslint": "4.11.0", + "eslint": "4.18.1", "eslint-plugin-markdown": "1.0.0-beta.6", "nyc": "10.3.2", "urun": "0.0.8", From ec998b95f7ec27adba8a5aee487f8adbd3c53136 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 24 Feb 2018 18:24:07 -0500 Subject: [PATCH 34/95] lint: fix comma spacing --- .eslintrc | 1 + test/unit/test-SqlString.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.eslintrc b/.eslintrc index 984104b..7c3d515 100644 --- a/.eslintrc +++ b/.eslintrc @@ -4,6 +4,7 @@ }, "rules": { "comma-dangle": [2, "never"], + "comma-spacing": ["error", { "before": false, "after": true }], "consistent-return": 2, "eqeqeq": [2, "allow-null"], "indent": [2, 2, { "VariableDeclarator": 2, "SwitchCase": 1 }], diff --git a/test/unit/test-SqlString.js b/test/unit/test-SqlString.js index c394d2f..8a83387 100644 --- a/test/unit/test-SqlString.js +++ b/test/unit/test-SqlString.js @@ -107,7 +107,7 @@ test('SqlString.escape', { }, 'nested arrays are turned into grouped lists': function() { - assert.equal(SqlString.escape([[1,2,3], [4,5,6], ['a', 'b', {nested: true}]]), "(1, 2, 3), (4, 5, 6), ('a', 'b', '[object Object]')"); + assert.equal(SqlString.escape([[1, 2, 3], [4, 5, 6], ['a', 'b', {nested: true}]]), "(1, 2, 3), (4, 5, 6), ('a', 'b', '[object Object]')"); }, 'nested objects inside arrays are cast to strings': function() { From 8f193cae10a2208010102fd50f0b61e869e14dcb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 24 Feb 2018 18:52:13 -0500 Subject: [PATCH 35/95] Release 2.3.1 --- HISTORY.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 47bcb17..e2c7e51 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,5 @@ -unreleased -========== +2.3.1 / 2018-02-24 +================== * Fix incorrectly replacing non-placeholders in SQL diff --git a/package.json b/package.json index 037f172..2c951a3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "sqlstring", "description": "Simple SQL escape and format for MySQL", - "version": "2.3.0", + "version": "2.3.1", "contributors": [ "Adri Van Houdt ", "Douglas Christopher Wilson ", From e7871ef1915200b7cd3381b6d1c7409d44c90e19 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 17 May 2018 22:31:18 -0400 Subject: [PATCH 36/95] build: Node.js@4.9 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 51709f9..14aeea6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ node_js: - "1.8" - "2.5" - "3.3" - - "4.8" + - "4.9" - "5.12" - "6.13" - "7.10" From 5c6f02ca3d4d7e421c1c9b8d12a9de2c1079022d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 17 May 2018 22:36:54 -0400 Subject: [PATCH 37/95] build: Node.js@6.14 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 14aeea6..3f522b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ node_js: - "3.3" - "4.9" - "5.12" - - "6.13" + - "6.14" - "7.10" - "8.9" - "9.6" From c1d67c674a0ea00ccd1fcad3ff8575ebfcafa2fe Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 18 Jul 2018 17:22:49 -0400 Subject: [PATCH 38/95] build: Node.js@8.11 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3f522b7..d33be63 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ node_js: - "5.12" - "6.14" - "7.10" - - "8.9" + - "8.11" - "9.6" sudo: false dist: precise From 100ae8719b2f021571f8dbdbf3269de9eae865b5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 20 Jul 2018 23:09:47 -0400 Subject: [PATCH 39/95] build: Node.js@9.11 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d33be63..21d33b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ node_js: - "6.14" - "7.10" - "8.11" - - "9.6" + - "9.11" sudo: false dist: precise cache: From 0c9562d7ffc7182b1fac9819880b53a6c782a341 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 17 Dec 2018 20:43:24 -0500 Subject: [PATCH 40/95] build: nyc@13.1.0 --- .travis.yml | 3 +-- package.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 21d33b4..40e36ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,8 +24,7 @@ before_install: # Remove all non-test dependencies - "npm rm --save-dev benchmark beautify-benchmark" # Setup Node.js version-specific dependencies - - "test $TRAVIS_NODE_VERSION != '0.6' || npm rm --save-dev nyc" - - "test $TRAVIS_NODE_VERSION != '0.8' || npm rm --save-dev nyc" + - "test $(echo $TRAVIS_NODE_VERSION | cut -d'.' -f1) -ge 6 || npm rm --save-dev nyc" - "test $(echo $TRAVIS_NODE_VERSION | cut -d'.' -f1) -ge 4 || npm rm --save-dev eslint eslint-plugin-markdown" # Update Node.js modules - "test ! -d node_modules || npm prune" diff --git a/package.json b/package.json index 2c951a3..adbae7b 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "benchmark": "2.1.4", "eslint": "4.18.1", "eslint-plugin-markdown": "1.0.0-beta.6", - "nyc": "10.3.2", + "nyc": "13.1.0", "urun": "0.0.8", "utest": "0.0.8" }, From 116346f84b0923da97aac4df4325bb8323a5681d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 18 Dec 2018 02:11:42 -0500 Subject: [PATCH 41/95] build: Node.js@6.15 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 40e36ae..2026800 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ node_js: - "3.3" - "4.9" - "5.12" - - "6.14" + - "6.15" - "7.10" - "8.11" - "9.11" From 7953dc7e347fc2c7305854ac3a1c54acadbdffca Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 18 Dec 2018 02:17:05 -0500 Subject: [PATCH 42/95] build: Node.js@8.14 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2026800..7f99559 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ node_js: - "5.12" - "6.15" - "7.10" - - "8.11" + - "8.14" - "9.11" sudo: false dist: precise From 5fce54c28336c42f3ec433362b22126b8ffbe49f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 4 Feb 2019 21:42:48 -0500 Subject: [PATCH 43/95] build: support Node.js 10.x --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7f99559..8931359 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ node_js: - "7.10" - "8.14" - "9.11" + - "10.15" sudo: false dist: precise cache: From f231ca746746ac7058f6f42d4a3d7d296b546d72 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 13 Feb 2019 22:01:06 -0500 Subject: [PATCH 44/95] build: Node.js@6.16 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8931359..c557c22 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ node_js: - "3.3" - "4.9" - "5.12" - - "6.15" + - "6.16" - "7.10" - "8.14" - "9.11" From d2f6a1c89dc873d58d85bc67fba76bb3717893ac Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 14 Feb 2019 00:42:48 -0500 Subject: [PATCH 45/95] build: Node.js@8.15 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c557c22..673102c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ node_js: - "5.12" - "6.16" - "7.10" - - "8.14" + - "8.15" - "9.11" - "10.15" sudo: false From 5e238026316f5fffb45e380b79559baf08cab759 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 16 Feb 2019 21:44:17 -0500 Subject: [PATCH 46/95] build: nyc@13.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index adbae7b..acd3f2b 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "benchmark": "2.1.4", "eslint": "4.18.1", "eslint-plugin-markdown": "1.0.0-beta.6", - "nyc": "13.1.0", + "nyc": "13.3.0", "urun": "0.0.8", "utest": "0.0.8" }, From 94e8c5404e9fddf816945b69547ce869c0a2b270 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 2 Jun 2019 22:33:30 -0400 Subject: [PATCH 47/95] build: Node.js@6.17 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 673102c..159686b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ node_js: - "3.3" - "4.9" - "5.12" - - "6.16" + - "6.17" - "7.10" - "8.15" - "9.11" From b3c503c3f4fc7fd2999efef494def208283247be Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 2 Jun 2019 22:39:09 -0400 Subject: [PATCH 48/95] build: Node.js@8.16 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 159686b..84de09d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ node_js: - "5.12" - "6.17" - "7.10" - - "8.15" + - "8.16" - "9.11" - "10.15" sudo: false From 7f7ef8b67caa7a3eec2703f72997b21f17632ce1 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 3 Jun 2019 00:02:06 -0400 Subject: [PATCH 49/95] build: Node.js@10.16 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 84de09d..77852de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ node_js: - "7.10" - "8.16" - "9.11" - - "10.15" + - "10.16" sudo: false dist: precise cache: From c6a65bb007efe86d7d211bdf5bde7d436177b9d5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 3 Jun 2019 00:14:29 -0400 Subject: [PATCH 50/95] build: support Node.js 11.x --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 77852de..fb1bcb5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ node_js: - "8.16" - "9.11" - "10.16" + - "11.15" sudo: false dist: precise cache: From a139df5d9e924b8f51a2e2541e49518771d5a031 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 30 Jun 2019 20:43:53 -0400 Subject: [PATCH 51/95] build: migrate to Travis CI trusty image --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fb1bcb5..382d88c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,11 @@ node_js: - "10.16" - "11.15" sudo: false -dist: precise +dist: trusty +env: + global: + # Suppress Node.js 0.6 compile warnings + - "CXXCOM='$CXX -o $TARGET -c $CXXFLAGS $CCFLAGS -Wno-unused-local-typedefs -Wno-maybe-uninitialized -Wno-narrowing -Wno-strict-overflow $_CCCOMCOM $SOURCES'" cache: directories: - node_modules From cdbe4236d33cba1f5a0f9211c85bc46b6a6e4561 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 30 Jun 2019 20:56:33 -0400 Subject: [PATCH 52/95] build: support Node.js 12.x --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 382d88c..2c3b693 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ node_js: - "9.11" - "10.16" - "11.15" + - "12.5" sudo: false dist: trusty env: From 2bf23226585666cec15f909a1ef35f3fe43c9c90 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 30 Jun 2019 21:12:44 -0400 Subject: [PATCH 53/95] build: nyc@14.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index acd3f2b..7b7f4f3 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "benchmark": "2.1.4", "eslint": "4.18.1", "eslint-plugin-markdown": "1.0.0-beta.6", - "nyc": "13.3.0", + "nyc": "14.1.1", "urun": "0.0.8", "utest": "0.0.8" }, From 20c3200f75f862e365b65a88762e10e3870096a0 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 3 Nov 2019 19:05:10 -0500 Subject: [PATCH 54/95] build: Node.js@10.17 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2c3b693..ed0bf93 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ node_js: - "7.10" - "8.16" - "9.11" - - "10.16" + - "10.17" - "11.15" - "12.5" sudo: false From 682bd3f16e82db860090398f83eea504040e6b41 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 3 Nov 2019 19:09:39 -0500 Subject: [PATCH 55/95] build: Node.js@12.13 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ed0bf93..de0e7ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ node_js: - "9.11" - "10.17" - "11.15" - - "12.5" + - "12.13" sudo: false dist: trusty env: From 11d2ffe91e43a25d17d101e7150827d98ac4c9f7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 3 Nov 2019 19:14:59 -0500 Subject: [PATCH 56/95] build: support Node.js 13.x --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index de0e7ab..59ef1b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ node_js: - "10.17" - "11.15" - "12.13" + - "13.0" sudo: false dist: trusty env: From 29726f798a1213c2bdb691f74d217a1ddd3d1d26 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 19 Jan 2020 18:32:36 -0500 Subject: [PATCH 57/95] build: nyc@15.0.0 --- .travis.yml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 59ef1b7..bfa8d11 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,7 @@ before_install: # Remove all non-test dependencies - "npm rm --save-dev benchmark beautify-benchmark" # Setup Node.js version-specific dependencies - - "test $(echo $TRAVIS_NODE_VERSION | cut -d'.' -f1) -ge 6 || npm rm --save-dev nyc" + - "test $(echo $TRAVIS_NODE_VERSION | cut -d'.' -f1) -ge 8 || npm rm --save-dev nyc" - "test $(echo $TRAVIS_NODE_VERSION | cut -d'.' -f1) -ge 4 || npm rm --save-dev eslint eslint-plugin-markdown" # Update Node.js modules - "test ! -d node_modules || npm prune" diff --git a/package.json b/package.json index 7b7f4f3..d94ab87 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "benchmark": "2.1.4", "eslint": "4.18.1", "eslint-plugin-markdown": "1.0.0-beta.6", - "nyc": "14.1.1", + "nyc": "15.0.0", "urun": "0.0.8", "utest": "0.0.8" }, From 10bab80dca712f7d2da7f045d91422e57267c1a4 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 21 Jan 2020 02:26:32 -0500 Subject: [PATCH 58/95] build: eslint@5.16.0 closes #47 --- .travis.yml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index bfa8d11..591a539 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ before_install: - "npm rm --save-dev benchmark beautify-benchmark" # Setup Node.js version-specific dependencies - "test $(echo $TRAVIS_NODE_VERSION | cut -d'.' -f1) -ge 8 || npm rm --save-dev nyc" - - "test $(echo $TRAVIS_NODE_VERSION | cut -d'.' -f1) -ge 4 || npm rm --save-dev eslint eslint-plugin-markdown" + - "test $(echo $TRAVIS_NODE_VERSION | cut -d'.' -f1) -ge 6 || npm rm --save-dev eslint eslint-plugin-markdown" # Update Node.js modules - "test ! -d node_modules || npm prune" - "test ! -d node_modules || npm rebuild" diff --git a/package.json b/package.json index d94ab87..64fd36c 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "devDependencies": { "beautify-benchmark": "0.2.4", "benchmark": "2.1.4", - "eslint": "4.18.1", + "eslint": "5.16.0", "eslint-plugin-markdown": "1.0.0-beta.6", "nyc": "15.0.0", "urun": "0.0.8", From 14e4c059d1bce56717f484059940e23e415a3cac Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 21 Jan 2020 02:30:17 -0500 Subject: [PATCH 59/95] build: eslint-plugin-markdown@1.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 64fd36c..94a57cf 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "beautify-benchmark": "0.2.4", "benchmark": "2.1.4", "eslint": "5.16.0", - "eslint-plugin-markdown": "1.0.0-beta.6", + "eslint-plugin-markdown": "1.0.1", "nyc": "15.0.0", "urun": "0.0.8", "utest": "0.0.8" From acc02c4473db2fd184551cea69f19b35292c77ae Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 21 Jan 2020 02:31:53 -0500 Subject: [PATCH 60/95] lint: sync rules with mysqljs/mysql --- .eslintrc | 2 ++ README.md | 28 +++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/.eslintrc b/.eslintrc index 7c3d515..c50229d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -33,9 +33,11 @@ "no-regex-spaces": 2, "no-sparse-arrays": 2, "no-trailing-spaces": 2, + "no-undef": 2, "no-unexpected-multiline": 2, "no-unreachable": 2, "no-unused-vars": 2, + "one-var": ["error", { "initialized": "never" }], "quotes": [2, "single", { "avoidEscape": true, "allowTemplateLiterals": true }], "semi": [2, "always"], "semi-spacing": 2, diff --git a/README.md b/README.md index fafe6f4..bdde7a9 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ $ npm install sqlstring ## Usage - + ```js var SqlString = require('sqlstring'); @@ -32,6 +32,8 @@ In order to avoid SQL Injection attacks, you should always escape any user provided data before using it inside a SQL query. You can do so using the `SqlString.escape()` method: + + ```js var userId = 'some user provided value'; var sql = 'SELECT * FROM users WHERE id = ' + SqlString.escape(userId); @@ -41,6 +43,8 @@ console.log(sql); // SELECT * FROM users WHERE id = 'some user provided value' Alternatively, you can use `?` characters as placeholders for values you would like to have escaped like this: + + ```js var userId = 1; var sql = SqlString.format('SELECT * FROM users WHERE id = ?', [userId]); @@ -51,6 +55,8 @@ Multiple placeholders are mapped to values in the same order as passed. For exam in the following query `foo` equals `a`, `bar` equals `b`, `baz` equals `c`, and `id` will be `userId`: + + ```js var userId = 1; var sql = SqlString.format('UPDATE users SET foo = ?, bar = ?, baz = ? WHERE id = ?', @@ -87,6 +93,8 @@ Different value types are escaped differently, here is how: You may have noticed that this escaping allows you to do neat things like this: + + ```js var post = {id: 1, title: 'Hello MySQL'}; var sql = SqlString.format('INSERT INTO posts SET ?', post); @@ -95,6 +103,8 @@ console.log(sql); // INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL' And the `toSqlString` method allows you to form complex queries with functions: + + ```js var CURRENT_TIMESTAMP = { toSqlString: function() { return 'CURRENT_TIMESTAMP()'; } }; var sql = SqlString.format('UPDATE posts SET modified = ? WHERE id = ?', [CURRENT_TIMESTAMP, 42]); @@ -108,6 +118,8 @@ placeholder, useful for using functions as dynamic values: **Caution** The string provided to `SqlString.raw()` will skip all escaping functions when used, so be careful when passing in unvalidated input. + + ```js var CURRENT_TIMESTAMP = SqlString.raw('CURRENT_TIMESTAMP()'); var sql = SqlString.format('UPDATE posts SET modified = ? WHERE id = ?', [CURRENT_TIMESTAMP, 42]); @@ -117,6 +129,8 @@ console.log(sql); // UPDATE posts SET modified = CURRENT_TIMESTAMP() WHERE id = If you feel the need to escape queries by yourself, you can also use the escaping function directly: + + ```js var sql = 'SELECT * FROM posts WHERE title=' + SqlString.escape('Hello MySQL'); console.log(sql); // SELECT * FROM posts WHERE title='Hello MySQL' @@ -127,6 +141,8 @@ console.log(sql); // SELECT * FROM posts WHERE title='Hello MySQL' If you can't trust an SQL identifier (database / table / column name) because it is provided by a user, you should escape it with `SqlString.escapeId(identifier)` like this: + + ```js var sorter = 'date'; var sql = 'SELECT * FROM posts ORDER BY ' + SqlString.escapeId(sorter); @@ -135,6 +151,8 @@ console.log(sql); // SELECT * FROM posts ORDER BY `date` It also supports adding qualified identifiers. It will escape both parts. + + ```js var sorter = 'date'; var sql = 'SELECT * FROM posts ORDER BY ' + SqlString.escapeId('posts.' + sorter); @@ -144,6 +162,8 @@ console.log(sql); // SELECT * FROM posts ORDER BY `posts`.`date` If you do not want to treat `.` as qualified identifiers, you can set the second argument to `true` in order to keep the string as a literal identifier: + + ```js var sorter = 'date.2'; var sql = 'SELECT * FROM posts ORDER BY ' + SqlString.escapeId(sorter, true); @@ -153,6 +173,8 @@ console.log(sql); // SELECT * FROM posts ORDER BY `date.2` Alternatively, you can use `??` characters as placeholders for identifiers you would like to have escaped like this: + + ```js var userId = 1; var columns = ['username', 'email']; @@ -168,6 +190,8 @@ When you pass an Object to `.escape()` or `.format()`, `.escapeId()` is used to You can use `SqlString.format` to prepare a query with multiple insertion points, utilizing the proper escaping for ids and values. A simple example of this follows: + + ```js var userId = 1; var inserts = ['users', 'id', userId]; @@ -184,6 +208,8 @@ location-specific/timezone-aware `Date`. This can be further combined with the `SqlString.raw()` helper to generate SQL that includes MySQL functions as dynamic vales: + + ```js var userId = 1; var data = { email: 'foobar@example.com', modified: SqlString.raw('NOW()') }; From d3cd69ae47e83c610392c276e9e02357e0b740eb Mon Sep 17 00:00:00 2001 From: Nathan Woltman Date: Wed, 12 Jun 2019 14:10:44 -0400 Subject: [PATCH 61/95] perf: remove outdated array pattern closes #43 --- HISTORY.md | 5 +++++ lib/SqlString.js | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index e2c7e51..e99dbec 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,8 @@ +unreleased +========== + + * perf: remove outdated array pattern + 2.3.1 / 2018-02-24 ================== diff --git a/lib/SqlString.js b/lib/SqlString.js index 419adec..4567bfa 100644 --- a/lib/SqlString.js +++ b/lib/SqlString.js @@ -78,7 +78,7 @@ SqlString.format = function format(sql, values, stringifyObjects, timeZone) { return sql; } - if (!(values instanceof Array || Array.isArray(values))) { + if (!Array.isArray(values)) { values = [values]; } From 166b6d1a4a445a5f28d2a9f85ac220295cd199cc Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 30 Mar 2020 21:18:07 -0400 Subject: [PATCH 62/95] build: eslint-plugin-markdown@1.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 94a57cf..2bb13f0 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "beautify-benchmark": "0.2.4", "benchmark": "2.1.4", "eslint": "5.16.0", - "eslint-plugin-markdown": "1.0.1", + "eslint-plugin-markdown": "1.0.2", "nyc": "15.0.0", "urun": "0.0.8", "utest": "0.0.8" From 3add7c5d7d8c0a9263a1e873a46ddc0bf0fd19db Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 30 Mar 2020 21:20:28 -0400 Subject: [PATCH 63/95] build: Node.js@8.17 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 591a539..259c7f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ node_js: - "5.12" - "6.17" - "7.10" - - "8.16" + - "8.17" - "9.11" - "10.17" - "11.15" From 06ddb8da78b85aa8e5ba52544c1a313ed5a42b5f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 30 Mar 2020 21:26:27 -0400 Subject: [PATCH 64/95] build: Node.js@10.19 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 259c7f0..731c80f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ node_js: - "7.10" - "8.17" - "9.11" - - "10.17" + - "10.19" - "11.15" - "12.13" - "13.0" From 700b1e3a58c9d889409f50c14a082f1023cde3a1 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 30 Mar 2020 21:31:59 -0400 Subject: [PATCH 65/95] build: Node.js@12.16 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 731c80f..cf9a45d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ node_js: - "9.11" - "10.19" - "11.15" - - "12.13" + - "12.16" - "13.0" sudo: false dist: trusty From 18db7ad518c7d82ffa480b7a757b335fe73f6897 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 31 Mar 2020 01:08:59 -0400 Subject: [PATCH 66/95] build: Node.js@13.12 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cf9a45d..d35473c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ node_js: - "10.19" - "11.15" - "12.16" - - "13.0" + - "13.12" sudo: false dist: trusty env: From 38d34674be58ad47a798c0ebe2fbc9019f484c28 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 31 Mar 2020 01:12:24 -0400 Subject: [PATCH 67/95] build: remove deprecated Travis CI directive --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d35473c..7f8ec02 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,6 @@ node_js: - "11.15" - "12.16" - "13.12" -sudo: false dist: trusty env: global: From b580866cdedfd748e110a87fbfb27b5154b99545 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 15 Apr 2020 22:03:59 -0400 Subject: [PATCH 68/95] Release 2.3.2 --- HISTORY.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index e99dbec..e5afa0c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,5 @@ -unreleased -========== +2.3.2 / 2020-04-15 +================== * perf: remove outdated array pattern diff --git a/package.json b/package.json index 2bb13f0..d487f85 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "sqlstring", "description": "Simple SQL escape and format for MySQL", - "version": "2.3.1", + "version": "2.3.2", "contributors": [ "Adri Van Houdt ", "Douglas Christopher Wilson ", From fd27b08d9a90c0c33f07d633a9579d750f378598 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 25 May 2020 19:32:46 -0400 Subject: [PATCH 69/95] build: support Node.js 14.x --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7f8ec02..bce3ad0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ node_js: - "11.15" - "12.16" - "13.12" + - "14.3" dist: trusty env: global: From 0fdbbea71f29fc185d2828a8890b6e2d5494c636 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 25 May 2020 19:37:21 -0400 Subject: [PATCH 70/95] build: Node.js@12.17 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bce3ad0..678ff82 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ node_js: - "9.11" - "10.19" - "11.15" - - "12.16" + - "12.17" - "13.12" - "14.3" dist: trusty From 47c6ebf00d3d17eb093178d7fc18b6b015a9167d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 26 May 2020 00:22:10 -0400 Subject: [PATCH 71/95] build: Node.js@13.14 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 678ff82..a4c5a14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ node_js: - "10.19" - "11.15" - "12.17" - - "13.12" + - "13.14" - "14.3" dist: trusty env: From e822595fccc77ddd0f6aed1c49d73f2b34e7cecf Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 26 May 2020 00:24:04 -0400 Subject: [PATCH 72/95] build: nyc@15.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d487f85..2440f61 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "benchmark": "2.1.4", "eslint": "5.16.0", "eslint-plugin-markdown": "1.0.2", - "nyc": "15.0.0", + "nyc": "15.0.1", "urun": "0.0.8", "utest": "0.0.8" }, From 36ee7b9318b4c219fd0859cb8d89031d5ece260b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 22 Jun 2020 18:19:16 -0400 Subject: [PATCH 73/95] build: Node.js@10.22 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a4c5a14..439245c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ node_js: - "7.10" - "8.17" - "9.11" - - "10.19" + - "10.22" - "11.15" - "12.17" - "13.14" From 62de030b1e396ccca7734f26fa151aa9bd244718 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 23 Jun 2020 18:21:12 -0400 Subject: [PATCH 74/95] build: nyc@15.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2440f61..f49ae4c 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "benchmark": "2.1.4", "eslint": "5.16.0", "eslint-plugin-markdown": "1.0.2", - "nyc": "15.0.1", + "nyc": "15.1.0", "urun": "0.0.8", "utest": "0.0.8" }, From b3e1021bafe0e44fa16cff3475bd5eeb7e67aaaf Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 23 Jun 2020 18:25:22 -0400 Subject: [PATCH 75/95] build: Node.js@14.4 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 439245c..764a897 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ node_js: - "11.15" - "12.17" - "13.14" - - "14.3" + - "14.4" dist: trusty env: global: From 379e02ff223fcb11440a4f90d4ebca1fb5acf117 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 26 Jun 2020 17:58:39 -0400 Subject: [PATCH 76/95] build: Node.js@12.18 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 764a897..fe9dc6a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ node_js: - "9.11" - "10.22" - "11.15" - - "12.17" + - "12.18" - "13.14" - "14.4" dist: trusty From 8fb10dea575bbecfd37fd2b684b795c9bc8e798c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 12 Dec 2021 18:44:39 -0500 Subject: [PATCH 77/95] build: use GitHub Actions instead of Travis CI --- .github/workflows/ci.yml | 176 +++++++++++++++++++++++++++++++++++++++ .travis.yml | 47 ----------- README.md | 6 +- package.json | 2 +- 4 files changed, 180 insertions(+), 51 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..b9f9715 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,176 @@ +name: ci + +on: +- pull_request +- push + +jobs: + test: + runs-on: ubuntu-18.04 + strategy: + matrix: + name: + - Node.js 0.6 + - Node.js 0.8 + - Node.js 0.10 + - Node.js 0.12 + - io.js 1.x + - io.js 2.x + - io.js 3.x + - Node.js 4.x + - Node.js 5.x + - Node.js 6.x + - Node.js 7.x + - Node.js 8.x + - Node.js 9.x + - Node.js 10.x + - Node.js 11.x + - Node.js 12.x + - Node.js 13.x + - Node.js 14.x + + include: + - name: Node.js 0.6 + node-version: "0.6" + + - name: Node.js 0.8 + node-version: "0.8" + + - name: Node.js 0.10 + node-version: "0.10" + + - name: Node.js 0.12 + node-version: "0.12" + + - name: io.js 1.x + node-version: "1.8" + + - name: io.js 2.x + node-version: "2.5" + + - name: io.js 3.x + node-version: "3.3" + + - name: Node.js 4.x + node-version: "4.9" + + - name: Node.js 5.x + node-version: "5.12" + + - name: Node.js 6.x + node-version: "6.17" + + - name: Node.js 7.x + node-version: "7.10" + + - name: Node.js 8.x + node-version: "8.17" + + - name: Node.js 9.x + node-version: "9.11" + + - name: Node.js 10.x + node-version: "10.22" + + - name: Node.js 11.x + node-version: "11.15" + + - name: Node.js 12.x + node-version: "12.18" + + - name: Node.js 13.x + node-version: "13.14" + + - name: Node.js 14.x + node-version: "14.4" + + steps: + - uses: actions/checkout@v2 + + - name: Install Node.js ${{ matrix.node-version }} + shell: bash -eo pipefail -l {0} + run: | + if [[ "${{ matrix.node-version }}" == 0.6* ]]; then + sudo apt-get install g++-4.8 gcc-4.8 libssl1.0-dev + export CC=/usr/bin/gcc-4.8 + export CXX=/usr/bin/g++-4.8 + fi + nvm install --default ${{ matrix.node-version }} + if [[ "${{ matrix.node-version }}" == 0.* && "$(cut -d. -f2 <<< "${{ matrix.node-version }}")" -lt 10 ]]; then + nvm install --alias=npm 0.10 + nvm use ${{ matrix.node-version }} + if [[ "$(npm -v)" == 1.1.* ]]; then + nvm exec npm npm install -g npm@1.1 + ln -fs "$(which npm)" "$(dirname "$(nvm which npm)")/npm" + else + sed -i '1s;^.*$;'"$(printf '#!%q' "$(nvm which npm)")"';' "$(readlink -f "$(which npm)")" + fi + npm config set strict-ssl false + fi + dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH" + + - name: Configure npm + run: npm config set shrinkwrap false + + - name: Remove non-test npm modules + run: npm rm --silent --save-dev benchmark beautify-benchmark + + - name: Setup Node.js version-specific dependencies + shell: bash + run: | + # eslint for linting + # - remove on Node.js < 6 + if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 6 ]]; then + node -pe 'Object.keys(require("./package").devDependencies).join("\n")' | \ + grep -E '^eslint(-|$)' | \ + sort -r | \ + xargs -n1 npm rm --silent --save-dev + fi + # nyc for coverage + # - remove on Node.js < 8 + if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 8 ]]; then + npm rm --silent --save-dev nyc + fi + + - name: Install Node.js dependencies + run: npm install + + - name: List environment + id: list_env + shell: bash + run: | + echo "node@$(node -v)" + echo "npm@$(npm -v)" + npm -s ls ||: + (npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print "::set-output name=" $2 "::" $3 }' + + - name: Run tests + shell: bash + run: | + if npm -ps ls nyc | grep -q nyc; then + npm run test-ci + else + npm test + fi + + - name: Lint code + if: steps.list_env.outputs.eslint != '' + run: npm run lint + + - name: Collect code coverage + uses: coverallsapp/github-action@master + if: steps.list_env.outputs.nyc != '' + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + flag-name: run-${{ matrix.test_number }} + parallel: true + + coverage: + needs: test + runs-on: ubuntu-latest + steps: + - name: Upload code coverage + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + parallel-finished: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index fe9dc6a..0000000 --- a/.travis.yml +++ /dev/null @@ -1,47 +0,0 @@ -language: node_js -node_js: - - "0.6" - - "0.8" - - "0.10" - - "0.12" - - "1.8" - - "2.5" - - "3.3" - - "4.9" - - "5.12" - - "6.17" - - "7.10" - - "8.17" - - "9.11" - - "10.22" - - "11.15" - - "12.18" - - "13.14" - - "14.4" -dist: trusty -env: - global: - # Suppress Node.js 0.6 compile warnings - - "CXXCOM='$CXX -o $TARGET -c $CXXFLAGS $CCFLAGS -Wno-unused-local-typedefs -Wno-maybe-uninitialized -Wno-narrowing -Wno-strict-overflow $_CCCOMCOM $SOURCES'" -cache: - directories: - - node_modules -before_install: - # Skip updating shrinkwrap / lock - - "npm config set shrinkwrap false" - # Remove all non-test dependencies - - "npm rm --save-dev benchmark beautify-benchmark" - # Setup Node.js version-specific dependencies - - "test $(echo $TRAVIS_NODE_VERSION | cut -d'.' -f1) -ge 8 || npm rm --save-dev nyc" - - "test $(echo $TRAVIS_NODE_VERSION | cut -d'.' -f1) -ge 6 || npm rm --save-dev eslint eslint-plugin-markdown" - # Update Node.js modules - - "test ! -d node_modules || npm prune" - - "test ! -d node_modules || npm rebuild" -script: - # Run test script, depending on nyc install - - "test ! -z $(npm -ps ls nyc) || npm test" - - "test -z $(npm -ps ls nyc) || npm run-script test-ci" - # Run linter - - "test -z $(npm -ps ls eslint) || npm run-script lint" -after_script: - - "test -d .nyc_output && npm install coveralls@2 && nyc report --reporter=text-lcov | coveralls" diff --git a/README.md b/README.md index bdde7a9..82789b3 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![NPM Version][npm-version-image]][npm-url] [![NPM Downloads][npm-downloads-image]][npm-url] [![Node.js Version][node-image]][node-url] -[![Build Status][travis-image]][travis-url] +[![Build Status][github-actions-ci-image]][github-actions-ci-url] [![Coverage Status][coveralls-image]][coveralls-url] Simple SQL escape and format for MySQL @@ -224,9 +224,9 @@ console.log(sql); // UPDATE `users` SET `email` = 'foobar@example.com', `modifie [npm-version-image]: https://img.shields.io/npm/v/sqlstring.svg [npm-downloads-image]: https://img.shields.io/npm/dm/sqlstring.svg [npm-url]: https://npmjs.org/package/sqlstring -[travis-image]: https://img.shields.io/travis/mysqljs/sqlstring/master.svg -[travis-url]: https://travis-ci.org/mysqljs/sqlstring [coveralls-image]: https://img.shields.io/coveralls/mysqljs/sqlstring/master.svg [coveralls-url]: https://coveralls.io/r/mysqljs/sqlstring?branch=master +[github-actions-ci-image]: https://img.shields.io/github/workflow/status/mysqljs/sqlstring/ci/master?label=build +[github-actions-ci-url]: https://github.com/mysqljs/sqlstring/actions/workflows/ci.yml [node-image]: https://img.shields.io/node/v/sqlstring.svg [node-url]: https://nodejs.org/en/download diff --git a/package.json b/package.json index f49ae4c..5894413 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "bench": "node benchmark/index.js", "lint": "eslint --plugin markdown --ext js,md .", "test": "node test/run.js", - "test-ci": "nyc --reporter=text npm test", + "test-ci": "nyc --reporter=lcovonly --reporter=text npm test", "test-cov": "nyc --reporter=html --reporter=text npm test" } } From 98a952361ab7a55dc108f7d67fb0c211f56a9389 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 12 Dec 2021 18:49:23 -0500 Subject: [PATCH 78/95] build: Node.js@14.18 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9f9715..c847bfc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,7 +82,7 @@ jobs: node-version: "13.14" - name: Node.js 14.x - node-version: "14.4" + node-version: "14.18" steps: - uses: actions/checkout@v2 From 231f7c84040720af2e89438bf7d85f04ec56d8c6 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 12 Dec 2021 18:57:05 -0500 Subject: [PATCH 79/95] build: support Node.js 15.x --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c847bfc..f217cf7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,7 @@ jobs: - Node.js 12.x - Node.js 13.x - Node.js 14.x + - Node.js 15.x include: - name: Node.js 0.6 @@ -84,6 +85,9 @@ jobs: - name: Node.js 14.x node-version: "14.18" + - name: Node.js 15.x + node-version: "15.14" + steps: - uses: actions/checkout@v2 From f053871fe53bc1ad96780e3fd263c909838adbb9 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 13 Dec 2021 00:02:49 -0500 Subject: [PATCH 80/95] build: Node.js@12.22 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f217cf7..51a4e43 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,7 +77,7 @@ jobs: node-version: "11.15" - name: Node.js 12.x - node-version: "12.18" + node-version: "12.22" - name: Node.js 13.x node-version: "13.14" From 6d3bdb0dc95d3709d52db8008de1b3e16eec86c3 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 13 Dec 2021 00:09:50 -0500 Subject: [PATCH 81/95] build: support Node.js 16.x --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51a4e43..00b1943 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,7 @@ jobs: - Node.js 13.x - Node.js 14.x - Node.js 15.x + - Node.js 16.x include: - name: Node.js 0.6 @@ -88,6 +89,9 @@ jobs: - name: Node.js 15.x node-version: "15.14" + - name: Node.js 16.x + node-version: "16.13" + steps: - uses: actions/checkout@v2 From fdda9a563497a6e1a76952620f49494dfb854018 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 14 Dec 2021 19:54:02 -0500 Subject: [PATCH 82/95] build: Node.js@10.24 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00b1943..277a80d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,7 +72,7 @@ jobs: node-version: "9.11" - name: Node.js 10.x - node-version: "10.22" + node-version: "10.24" - name: Node.js 11.x node-version: "11.15" From 4e3eb5bd9bd3365bd3933e69253dd50db72a2594 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 19 Dec 2021 21:38:54 -0500 Subject: [PATCH 83/95] build: support Node.js 17.x --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 277a80d..80cefa3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,7 @@ jobs: - Node.js 14.x - Node.js 15.x - Node.js 16.x + - Node.js 17.x include: - name: Node.js 0.6 @@ -92,6 +93,9 @@ jobs: - name: Node.js 16.x node-version: "16.13" + - name: Node.js 17.x + node-version: "17.3" + steps: - uses: actions/checkout@v2 From 1260f6699a46e725c0e854c9308324bdfcab9d12 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 10 Jan 2022 20:41:39 -0500 Subject: [PATCH 84/95] build: eslint@6.8.0 --- .github/workflows/ci.yml | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 80cefa3..53a3934 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,8 +131,8 @@ jobs: shell: bash run: | # eslint for linting - # - remove on Node.js < 6 - if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 6 ]]; then + # - remove on Node.js < 8 + if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 8 ]]; then node -pe 'Object.keys(require("./package").devDependencies).join("\n")' | \ grep -E '^eslint(-|$)' | \ sort -r | \ diff --git a/package.json b/package.json index 5894413..7364351 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "devDependencies": { "beautify-benchmark": "0.2.4", "benchmark": "2.1.4", - "eslint": "5.16.0", + "eslint": "6.8.0", "eslint-plugin-markdown": "1.0.2", "nyc": "15.1.0", "urun": "0.0.8", From fc607ad680ab820089c28929a1767c6f46019456 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 10 Feb 2022 19:30:51 -0500 Subject: [PATCH 85/95] build: Node.js@16.14 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 53a3934..c181e7d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,7 +91,7 @@ jobs: node-version: "15.14" - name: Node.js 16.x - node-version: "16.13" + node-version: "16.14" - name: Node.js 17.x node-version: "17.3" From 4a9d6b1756ae3b1848927a14c7ef3314340c3346 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 10 Feb 2022 19:33:24 -0500 Subject: [PATCH 86/95] build: Node.js@17.5 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c181e7d..2fabe06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,7 +94,7 @@ jobs: node-version: "16.14" - name: Node.js 17.x - node-version: "17.3" + node-version: "17.5" steps: - uses: actions/checkout@v2 From 321f26a8a9cd3b73e4bc0a8f11411e66fb84a6a7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 11 Feb 2022 00:18:55 -0500 Subject: [PATCH 87/95] build: eslint@7.32.0 --- .github/workflows/ci.yml | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2fabe06..d161d0f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,8 +131,8 @@ jobs: shell: bash run: | # eslint for linting - # - remove on Node.js < 8 - if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 8 ]]; then + # - remove on Node.js < 10 + if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 10 ]]; then node -pe 'Object.keys(require("./package").devDependencies).join("\n")' | \ grep -E '^eslint(-|$)' | \ sort -r | \ diff --git a/package.json b/package.json index 7364351..b81f440 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "devDependencies": { "beautify-benchmark": "0.2.4", "benchmark": "2.1.4", - "eslint": "6.8.0", + "eslint": "7.32.0", "eslint-plugin-markdown": "1.0.2", "nyc": "15.1.0", "urun": "0.0.8", From 2a652cd76edbaf89662a46d4f6d11987bd6b27b7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 11 Feb 2022 00:27:34 -0500 Subject: [PATCH 88/95] build: eslint-plugin-markdown@2.2.1 --- .eslintrc | 16 ++++++++++++++++ README.md | 27 --------------------------- package.json | 4 ++-- 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/.eslintrc b/.eslintrc index c50229d..b9a8e31 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,6 +2,22 @@ "env": { "node": true }, + "plugins": [ + "markdown" + ], + "overrides": [ + { + "files": "**/*.md", + "processor": "markdown/markdown" + }, + { + "files": "**/*.md/*.js", + "rules": { + "no-undef": 0, + "no-unused-vars": 0 + } + } + ], "rules": { "comma-dangle": [2, "never"], "comma-spacing": ["error", { "before": false, "after": true }], diff --git a/README.md b/README.md index 82789b3..a00c560 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,6 @@ $ npm install sqlstring ## Usage - ```js var SqlString = require('sqlstring'); @@ -32,8 +31,6 @@ In order to avoid SQL Injection attacks, you should always escape any user provided data before using it inside a SQL query. You can do so using the `SqlString.escape()` method: - - ```js var userId = 'some user provided value'; var sql = 'SELECT * FROM users WHERE id = ' + SqlString.escape(userId); @@ -43,8 +40,6 @@ console.log(sql); // SELECT * FROM users WHERE id = 'some user provided value' Alternatively, you can use `?` characters as placeholders for values you would like to have escaped like this: - - ```js var userId = 1; var sql = SqlString.format('SELECT * FROM users WHERE id = ?', [userId]); @@ -55,8 +50,6 @@ Multiple placeholders are mapped to values in the same order as passed. For exam in the following query `foo` equals `a`, `bar` equals `b`, `baz` equals `c`, and `id` will be `userId`: - - ```js var userId = 1; var sql = SqlString.format('UPDATE users SET foo = ?, bar = ?, baz = ? WHERE id = ?', @@ -93,8 +86,6 @@ Different value types are escaped differently, here is how: You may have noticed that this escaping allows you to do neat things like this: - - ```js var post = {id: 1, title: 'Hello MySQL'}; var sql = SqlString.format('INSERT INTO posts SET ?', post); @@ -103,8 +94,6 @@ console.log(sql); // INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL' And the `toSqlString` method allows you to form complex queries with functions: - - ```js var CURRENT_TIMESTAMP = { toSqlString: function() { return 'CURRENT_TIMESTAMP()'; } }; var sql = SqlString.format('UPDATE posts SET modified = ? WHERE id = ?', [CURRENT_TIMESTAMP, 42]); @@ -118,8 +107,6 @@ placeholder, useful for using functions as dynamic values: **Caution** The string provided to `SqlString.raw()` will skip all escaping functions when used, so be careful when passing in unvalidated input. - - ```js var CURRENT_TIMESTAMP = SqlString.raw('CURRENT_TIMESTAMP()'); var sql = SqlString.format('UPDATE posts SET modified = ? WHERE id = ?', [CURRENT_TIMESTAMP, 42]); @@ -129,8 +116,6 @@ console.log(sql); // UPDATE posts SET modified = CURRENT_TIMESTAMP() WHERE id = If you feel the need to escape queries by yourself, you can also use the escaping function directly: - - ```js var sql = 'SELECT * FROM posts WHERE title=' + SqlString.escape('Hello MySQL'); console.log(sql); // SELECT * FROM posts WHERE title='Hello MySQL' @@ -141,8 +126,6 @@ console.log(sql); // SELECT * FROM posts WHERE title='Hello MySQL' If you can't trust an SQL identifier (database / table / column name) because it is provided by a user, you should escape it with `SqlString.escapeId(identifier)` like this: - - ```js var sorter = 'date'; var sql = 'SELECT * FROM posts ORDER BY ' + SqlString.escapeId(sorter); @@ -151,8 +134,6 @@ console.log(sql); // SELECT * FROM posts ORDER BY `date` It also supports adding qualified identifiers. It will escape both parts. - - ```js var sorter = 'date'; var sql = 'SELECT * FROM posts ORDER BY ' + SqlString.escapeId('posts.' + sorter); @@ -162,8 +143,6 @@ console.log(sql); // SELECT * FROM posts ORDER BY `posts`.`date` If you do not want to treat `.` as qualified identifiers, you can set the second argument to `true` in order to keep the string as a literal identifier: - - ```js var sorter = 'date.2'; var sql = 'SELECT * FROM posts ORDER BY ' + SqlString.escapeId(sorter, true); @@ -173,8 +152,6 @@ console.log(sql); // SELECT * FROM posts ORDER BY `date.2` Alternatively, you can use `??` characters as placeholders for identifiers you would like to have escaped like this: - - ```js var userId = 1; var columns = ['username', 'email']; @@ -190,8 +167,6 @@ When you pass an Object to `.escape()` or `.format()`, `.escapeId()` is used to You can use `SqlString.format` to prepare a query with multiple insertion points, utilizing the proper escaping for ids and values. A simple example of this follows: - - ```js var userId = 1; var inserts = ['users', 'id', userId]; @@ -208,8 +183,6 @@ location-specific/timezone-aware `Date`. This can be further combined with the `SqlString.raw()` helper to generate SQL that includes MySQL functions as dynamic vales: - - ```js var userId = 1; var data = { email: 'foobar@example.com', modified: SqlString.raw('NOW()') }; diff --git a/package.json b/package.json index b81f440..8a7777b 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "beautify-benchmark": "0.2.4", "benchmark": "2.1.4", "eslint": "7.32.0", - "eslint-plugin-markdown": "1.0.2", + "eslint-plugin-markdown": "2.2.1", "nyc": "15.1.0", "urun": "0.0.8", "utest": "0.0.8" @@ -39,7 +39,7 @@ }, "scripts": { "bench": "node benchmark/index.js", - "lint": "eslint --plugin markdown --ext js,md .", + "lint": "eslint .", "test": "node test/run.js", "test-ci": "nyc --reporter=lcovonly --reporter=text npm test", "test-cov": "nyc --reporter=html --reporter=text npm test" From c63f7c7cfc9430e7a709fd05e901ef0c4fe2e6f3 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 6 Mar 2022 15:50:26 -0500 Subject: [PATCH 89/95] build: Node.js@14.19 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d161d0f..4764191 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,7 +85,7 @@ jobs: node-version: "13.14" - name: Node.js 14.x - node-version: "14.18" + node-version: "14.19" - name: Node.js 15.x node-version: "15.14" From 2ab490151f784c3083e5ac92eebbc20d5631b6dd Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 6 Mar 2022 15:50:46 -0500 Subject: [PATCH 90/95] build: Node.js@17.6 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4764191..ba55cc9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,7 +94,7 @@ jobs: node-version: "16.14" - name: Node.js 17.x - node-version: "17.5" + node-version: "17.6" steps: - uses: actions/checkout@v2 From 5e768fd435f870b6df8e2453123cd64ddf5d352b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 6 Mar 2022 15:52:44 -0500 Subject: [PATCH 91/95] Fix escaping Date objects from foreign isolates fixes #67 --- HISTORY.md | 5 +++++ lib/SqlString.js | 2 +- test/unit/test-SqlString.js | 9 +++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index e5afa0c..9bdab64 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,8 @@ +unreleased +========== + + * Fix escaping `Date` objects from foreign isolates + 2.3.2 / 2020-04-15 ================== diff --git a/lib/SqlString.js b/lib/SqlString.js index 4567bfa..8206dad 100644 --- a/lib/SqlString.js +++ b/lib/SqlString.js @@ -40,7 +40,7 @@ SqlString.escape = function escape(val, stringifyObjects, timeZone) { case 'boolean': return (val) ? 'true' : 'false'; case 'number': return val + ''; case 'object': - if (val instanceof Date) { + if (Object.prototype.toString.call(val) === '[object Date]') { return SqlString.dateToString(val, timeZone || 'local'); } else if (Array.isArray(val)) { return SqlString.arrayToList(val, timeZone); diff --git a/test/unit/test-SqlString.js b/test/unit/test-SqlString.js index 8a83387..580aa4e 100644 --- a/test/unit/test-SqlString.js +++ b/test/unit/test-SqlString.js @@ -1,6 +1,7 @@ var assert = require('assert'); var SqlString = require('../../'); var test = require('utest'); +var vm = require('vm'); test('SqlString.escapeId', { 'value is quoted': function() { @@ -222,6 +223,14 @@ test('SqlString.escape', { assert.strictEqual(string, 'NULL'); }, + 'dates from other isolates are converted': function() { + var expected = '2012-05-07 11:42:03.002'; + var date = vm.runInNewContext('new Date(2012, 4, 7, 11, 42, 3, 2)'); + var string = SqlString.escape(date); + + assert.strictEqual(string, "'" + expected + "'"); + }, + 'buffers are converted to hex': function() { var buffer = new Buffer([0, 1, 254, 255]); var string = SqlString.escape(buffer); From 5aa85a7ae8ee1c1ace84e4b5d099836712f54275 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 6 Mar 2022 16:02:47 -0500 Subject: [PATCH 92/95] Release 2.3.3 --- HISTORY.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 9bdab64..aea1dfc 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,5 @@ -unreleased -========== +2.3.3 / 2022-03-06 +================== * Fix escaping `Date` objects from foreign isolates diff --git a/package.json b/package.json index 8a7777b..5aa57f1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "sqlstring", "description": "Simple SQL escape and format for MySQL", - "version": "2.3.2", + "version": "2.3.3", "contributors": [ "Adri Van Houdt ", "Douglas Christopher Wilson ", From 115ac83b9ebb6b820d937d4d84b65e90c3047db1 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 7 Mar 2022 00:24:59 -0500 Subject: [PATCH 93/95] docs: add explicit note regarding value shape validation --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index a00c560..5a9934f 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,18 @@ var SqlString = require('sqlstring'); [NO_BACKSLASH_ESCAPES](https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_backslash_escapes) SQL mode is disabled (which is the default state for MySQL servers). +**Caution** This library performs client-side escaping, as this is a library +to generate SQL strings on the client side. The syntax for functions like +`SqlString.format` may look similar to a prepared statement, but it is not +and the escaping rules from this module are used to generate a resulting SQL +string. The purpose of escaping input is to avoid SQL Injection attacks. +In order to support enhanced support like `SET` and `IN` formatting, this +module will escape based on the shape of the passed in JavaScript value, +and the resulting escaped string may be more than a single value. When +structured user input is provided as the value to escape, care should be taken +to validate the shape of the input to validate the output will be what is +expected. + In order to avoid SQL Injection attacks, you should always escape any user provided data before using it inside a SQL query. You can do so using the `SqlString.escape()` method: From eac0f22a9aad2f38525ecfd59e84158319c17286 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 7 Mar 2022 00:28:05 -0500 Subject: [PATCH 94/95] docs: add security policy --- SECURITY.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..53d27d9 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,24 @@ +# Security Policies and Procedures + +## Reporting a Bug + +The `sqlstring` team and community take all security bugs seriously. Thank you +for improving the security of this module. Your efforts and responsible disclosure +and every effort will be made to acknowledge your contributions, as long as they +were responsibility disclosed. + +Report security bugs by emailing the current owners of `sqlstring`. This information +can be found in the npm registry using the command `npm owner ls sqlstring`. +If unsure or unable to get the information from the above, open an issue +in the [project issue tracker](https://github.com/mysqljs/sqlstring/issues) +asking for the current contact information. + +To ensure the timely response to your report, please ensure that the entirety +of the report is contained within the email body and not solely behind a web +link or an attachment. + +At least one owner will acknowledge your email within 48 hours, and will send a +more detailed response within 48 hours indicating the next steps in handling +your report. After the initial reply to your report, the owners will +endeavor to keep you informed of the progress towards a fix and full +announcement, and may ask for additional information or guidance. From cd528556b4b6bcf300c3db515026935dedf7cfa1 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 7 Mar 2022 00:42:44 -0500 Subject: [PATCH 95/95] build: eslint@8.10.0 --- .github/workflows/ci.yml | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba55cc9..9b344e4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,8 +131,8 @@ jobs: shell: bash run: | # eslint for linting - # - remove on Node.js < 10 - if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 10 ]]; then + # - remove on Node.js < 12 + if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 12 ]]; then node -pe 'Object.keys(require("./package").devDependencies).join("\n")' | \ grep -E '^eslint(-|$)' | \ sort -r | \ diff --git a/package.json b/package.json index 5aa57f1..340e437 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "devDependencies": { "beautify-benchmark": "0.2.4", "benchmark": "2.1.4", - "eslint": "7.32.0", + "eslint": "8.10.0", "eslint-plugin-markdown": "2.2.1", "nyc": "15.1.0", "urun": "0.0.8",