Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added support for N1QL query parameter substitution.
Borrowed query formatting code from node-mysql. Change-Id: Ib0fb2803c2b7c1a0e60cd4b63f0be61e61bd05bd Reviewed-on: http://review.couchbase.org/33180 Reviewed-by: Mark Nunberg <mnunberg@haskalah.org> Tested-by: Brett Lawson <brett19@gmail.com>
- Loading branch information
Showing
6 changed files
with
194 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
/* | ||
Borrowed from node-mysql, see: | ||
https://github.com/felixge/node-mysql/ | ||
*/ | ||
var SqlString = exports; | ||
|
||
SqlString.escapeId = function (val, forbidQualified) { | ||
if (Array.isArray(val)) { | ||
return val.map(function(v) { | ||
return SqlString.escapeId(v, forbidQualified); | ||
}).join(', '); | ||
} | ||
|
||
if (forbidQualified) { | ||
return '`' + val.replace(/`/g, '``') + '`'; | ||
} | ||
return '`' + val.replace(/`/g, '``').replace(/\./g, '`.`') + '`'; | ||
}; | ||
|
||
SqlString.escape = function(val, stringifyObjects, timeZone) { | ||
if (val === undefined || val === null) { | ||
return 'NULL'; | ||
} | ||
|
||
switch (typeof val) { | ||
case 'boolean': return (val) ? 'true' : 'false'; | ||
case 'number': return val+''; | ||
} | ||
|
||
if (val instanceof Date) { | ||
val = SqlString.dateToString(val, timeZone || 'local'); | ||
} | ||
|
||
if (Buffer.isBuffer(val)) { | ||
return SqlString.bufferToString(val); | ||
} | ||
|
||
if (Array.isArray(val)) { | ||
return SqlString.arrayToList(val, timeZone); | ||
} | ||
|
||
if (typeof val === 'object') { | ||
if (stringifyObjects) { | ||
val = val.toString(); | ||
} else { | ||
return SqlString.objectToValues(val, timeZone); | ||
} | ||
} | ||
|
||
val = val.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) { | ||
switch(s) { | ||
case "\0": return "\\0"; | ||
case "\n": return "\\n"; | ||
case "\r": return "\\r"; | ||
case "\b": return "\\b"; | ||
case "\t": return "\\t"; | ||
case "\x1a": return "\\Z"; | ||
default: return "\\"+s; | ||
} | ||
}); | ||
return "'"+val+"'"; | ||
}; | ||
|
||
SqlString.arrayToList = function(array, timeZone) { | ||
return array.map(function(v) { | ||
if (Array.isArray(v)) return '(' + SqlString.arrayToList(v, timeZone) + ')'; | ||
return SqlString.escape(v, true, timeZone); | ||
}).join(', '); | ||
}; | ||
|
||
SqlString.format = function(sql, values, stringifyObjects, timeZone) { | ||
values = [].concat(values); | ||
|
||
return sql.replace(/\?\??/g, function(match) { | ||
if (!values.length) { | ||
return match; | ||
} | ||
|
||
if (match == "??") { | ||
return SqlString.escapeId(values.shift()); | ||
} | ||
return SqlString.escape(values.shift(), stringifyObjects, timeZone); | ||
}); | ||
}; | ||
|
||
SqlString.dateToString = function(date, timeZone) { | ||
var dt = new Date(date); | ||
|
||
if (timeZone != 'local') { | ||
var tz = convertTimezone(timeZone); | ||
|
||
dt.setTime(dt.getTime() + (dt.getTimezoneOffset() * 60000)); | ||
if (tz !== false) { | ||
dt.setTime(dt.getTime() + (tz * 60000)); | ||
} | ||
} | ||
|
||
var year = dt.getFullYear(); | ||
var month = zeroPad(dt.getMonth() + 1, 2); | ||
var day = zeroPad(dt.getDate(), 2); | ||
var hour = zeroPad(dt.getHours(), 2); | ||
var minute = zeroPad(dt.getMinutes(), 2); | ||
var second = zeroPad(dt.getSeconds(), 2); | ||
var millisecond = zeroPad(dt.getMilliseconds(), 3); | ||
|
||
return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second + '.' + millisecond; | ||
}; | ||
|
||
SqlString.bufferToString = function(buffer) { | ||
var hex = ''; | ||
try { | ||
hex = buffer.toString('hex'); | ||
} catch (err) { | ||
// node v0.4.x does not support hex / throws unknown encoding error | ||
for (var i = 0; i < buffer.length; i++) { | ||
var byte = buffer[i]; | ||
hex += zeroPad(byte.toString(16)); | ||
} | ||
} | ||
|
||
return "X'" + hex+ "'"; | ||
}; | ||
|
||
SqlString.objectToValues = function(object, timeZone) { | ||
var values = []; | ||
for (var key in object) { | ||
var value = object[key]; | ||
if(typeof value === 'function') { | ||
continue; | ||
} | ||
|
||
values.push(this.escapeId(key) + ' = ' + SqlString.escape(value, true, timeZone)); | ||
} | ||
|
||
return values.join(', '); | ||
}; | ||
|
||
function zeroPad(number, length) { | ||
number = number.toString(); | ||
while (number.length < length) { | ||
number = '0' + number; | ||
} | ||
|
||
return number; | ||
} | ||
|
||
function convertTimezone(tz) { | ||
if (tz == "Z") return 0; | ||
|
||
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 false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
var assert = require('assert'); | ||
var H = require('../test_harness.js'); | ||
|
||
describe('#query formatting', function() { | ||
|
||
it('should format query strings correctly', function(done) { | ||
var str = H.lib.formatQuery('SELECT ?? FROM ?? WHERE ??=?', ['name', 'default', 'id', 'frank']); | ||
assert(str === "SELECT `name` FROM `default` WHERE `id`='frank'", 'query should be correct'); | ||
done(); | ||
}); | ||
|
||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters