2016-05-17 01:01:34 +10:00
|
|
|
import * as helpers from '../helpers';
|
2015-05-09 13:58:18 -04:00
|
|
|
|
2016-05-17 01:01:34 +10:00
|
|
|
const SqlString = {};
|
|
|
|
export { SqlString as default };
|
2015-05-09 13:58:18 -04:00
|
|
|
|
|
|
|
SqlString.escape = function(val, timeZone) {
|
2016-03-26 09:01:00 +01:00
|
|
|
// Can't do require on top of file because Raw has not yet been initialized
|
|
|
|
// when this file is executed for the first time.
|
2016-05-17 01:01:34 +10:00
|
|
|
const Raw = require('../raw')
|
2015-11-04 11:17:41 +02:00
|
|
|
|
|
|
|
if (val === null || val === undefined) {
|
2015-05-09 13:58:18 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2015-11-04 11:17:41 +02:00
|
|
|
if (val instanceof Raw) {
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
2015-05-09 13:58:18 -04:00
|
|
|
if (typeof val === 'object') {
|
|
|
|
try {
|
|
|
|
val = JSON.stringify(val)
|
|
|
|
} catch (e) {
|
|
|
|
helpers.warn(e)
|
|
|
|
val = val + ''
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-24 11:33:48 +11:00
|
|
|
val = val.replace(/(\\\?)|[\0\n\r\b\t\\\'\x1a]/g, function(s) {
|
2015-05-09 13:58:18 -04:00
|
|
|
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";
|
2015-11-13 20:51:45 +02:00
|
|
|
case "\\?": return "?";
|
2015-12-24 11:33:48 +11:00
|
|
|
case "\'": return "''";
|
2016-07-02 00:45:50 +03:00
|
|
|
default: return `\\${s}`;
|
2015-05-09 13:58:18 -04:00
|
|
|
}
|
|
|
|
});
|
2016-05-17 01:01:34 +10:00
|
|
|
return `'${val}'`;
|
2015-05-09 13:58:18 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
SqlString.arrayToList = function(array, timeZone) {
|
2016-05-17 01:01:34 +10:00
|
|
|
const self = this;
|
2015-05-09 13:58:18 -04:00
|
|
|
return array.map(function(v) {
|
2016-05-17 01:01:34 +10:00
|
|
|
if (Array.isArray(v)) return `(${SqlString.arrayToList(v, timeZone)})`;
|
2015-11-29 18:11:45 -05:00
|
|
|
return self.escape(v, timeZone);
|
2015-05-09 13:58:18 -04:00
|
|
|
}).join(', ');
|
|
|
|
};
|
|
|
|
|
|
|
|
SqlString.format = function(sql, values, timeZone) {
|
2016-05-17 01:01:34 +10:00
|
|
|
const self = this;
|
2015-05-09 13:58:18 -04:00
|
|
|
values = values == null ? [] : [].concat(values);
|
2016-05-17 01:01:34 +10:00
|
|
|
let index = 0;
|
2015-11-13 20:51:45 +02:00
|
|
|
return sql.replace(/\\?\?/g, function(match) {
|
|
|
|
if (match === '\\?') return match;
|
2015-05-09 13:58:18 -04:00
|
|
|
if (index === values.length) {
|
|
|
|
return match;
|
|
|
|
}
|
2016-05-17 01:01:34 +10:00
|
|
|
const value = values[index++];
|
2015-11-29 18:11:45 -05:00
|
|
|
return self.escape(value, timeZone)
|
2015-11-13 20:51:45 +02:00
|
|
|
}).replace('\\?', '?');
|
2015-05-09 13:58:18 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
SqlString.dateToString = function(date, timeZone) {
|
2016-05-17 01:01:34 +10:00
|
|
|
const dt = new Date(date);
|
2015-05-09 13:58:18 -04:00
|
|
|
|
|
|
|
if (timeZone !== 'local') {
|
2016-05-17 01:01:34 +10:00
|
|
|
const tz = convertTimezone(timeZone);
|
2015-05-09 13:58:18 -04:00
|
|
|
|
|
|
|
dt.setTime(dt.getTime() + (dt.getTimezoneOffset() * 60000));
|
|
|
|
if (tz !== false) {
|
|
|
|
dt.setTime(dt.getTime() + (tz * 60000));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-18 19:59:24 +10:00
|
|
|
const year = dt.getFullYear();
|
|
|
|
const month = zeroPad(dt.getMonth() + 1, 2);
|
|
|
|
const day = zeroPad(dt.getDate(), 2);
|
|
|
|
const hour = zeroPad(dt.getHours(), 2);
|
2016-05-17 01:01:34 +10:00
|
|
|
const minute = zeroPad(dt.getMinutes(), 2);
|
|
|
|
const second = zeroPad(dt.getSeconds(), 2);
|
|
|
|
const millisecond = zeroPad(dt.getMilliseconds(), 3);
|
|
|
|
|
|
|
|
return (
|
|
|
|
year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' +
|
|
|
|
second + '.' + millisecond
|
|
|
|
);
|
2015-05-09 13:58:18 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
SqlString.bufferToString = function bufferToString(buffer) {
|
2016-05-17 01:01:34 +10:00
|
|
|
return `X'${buffer.toString('hex')}'`;
|
2015-05-09 13:58:18 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
function zeroPad(number, length) {
|
|
|
|
number = number.toString();
|
|
|
|
while (number.length < length) {
|
2016-05-17 01:01:34 +10:00
|
|
|
number = `0${number}`;
|
2015-05-09 13:58:18 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return number;
|
|
|
|
}
|
|
|
|
|
|
|
|
function convertTimezone(tz) {
|
|
|
|
if (tz === "Z") return 0;
|
|
|
|
|
2016-05-17 01:01:34 +10:00
|
|
|
const m = tz.match(/([\+\-\s])(\d\d):?(\d\d)?/);
|
2015-05-09 13:58:18 -04:00
|
|
|
if (m) {
|
2016-05-17 01:01:34 +10:00
|
|
|
return (
|
|
|
|
(m[1] === '-' ? -1 : 1) *
|
|
|
|
(parseInt(m[2], 10) +
|
|
|
|
((m[3] ? parseInt(m[3], 10) : 0) / 60)) * 60
|
|
|
|
);
|
2015-05-09 13:58:18 -04:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|