diff --git a/lib/SqlString.js b/lib/SqlString.js index af7deb7..05a3923 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 (val instanceof SqlFunction) { + return val.toSQL(); } else if (stringifyObjects) { val = val.toString(); } else { @@ -169,6 +171,30 @@ SqlString.objectToValues = function objectToValues(object, timeZone) { return sql; }; +if (typeof Proxy === 'function') { + SqlString.fn = new Proxy({}, { + get: function get(target, name) { + if (name in target) { + return target[name]; + } + + return function sqlFunctionHelper() { + var args = Array.prototype.slice.call(arguments); + + return new SqlFunction(name, args); + }; + } + }); +} + +function SqlFunction(name, args) { + var escapedArgs = args.map(SqlString.escape).join(', '); + + this.toSQL = function toSQL() { + return name.toUpperCase() + '(' + escapedArgs + ')'; + }; +} + function escapeString(val) { var chunkIndex = charsRegex.lastIndex = 0; var escapedVal = ''; diff --git a/test/unit/test-SqlString.js b/test/unit/test-SqlString.js index 37f600b..5c37414 100644 --- a/test/unit/test-SqlString.js +++ b/test/unit/test-SqlString.js @@ -188,6 +188,32 @@ test('SqlString.escape', { assert.strictEqual(string, "X'00\\' OR \\'1\\'=\\'1'"); }, + 'SqlString.fn is available if Proxy is supported, otherwise not': function() { + assert.equal(!!SqlString.fn, typeof Proxy === 'function'); + }, + + 'SqlString.fn escapes SQL functions properly, if Proxy is supported': function() { + if (typeof Proxy !== 'function') { + return; + } + + var a = SqlString.fn.POINT(123, 456); + var b = SqlString.fn.CURRENT_TIMESTAMP(); + + assert.strictEqual(SqlString.escape(a), 'POINT(123, 456)'); + assert.strictEqual(SqlString.escape(b), 'CURRENT_TIMESTAMP()'); + }, + + 'SqlString.fn escapes nested SQL functions properly, if Proxy is supported': function() { + if (typeof Proxy !== 'function') { + return; + } + + var fn = SqlString.fn.CONCAT(SqlString.fn.UPPER('abc'), SqlString.fn.LOWER('ABC')); + + assert.strictEqual(SqlString.escape(fn), "CONCAT(UPPER('abc'), LOWER('ABC'))"); + }, + 'NaN -> NaN': function() { assert.equal(SqlString.escape(NaN), 'NaN'); },