orange-orm
Version:
Object Relational Mapper
136 lines (120 loc) • 3.07 kB
JavaScript
var log = require('../table/log');
function wrapQuery(_context, connection) {
let CachedRequest = null;
let CachedTypes = null;
return runQuery;
function runQuery(query, onCompleted) {
if (!CachedRequest || !CachedTypes) {
import('tedious')
.then(({ Request, TYPES }) => {
CachedRequest = Request;
CachedTypes = TYPES;
doQuery(query, onCompleted);
})
.catch(err => onCompleted(extractError(err), []));
}
else {
doQuery(query, onCompleted);
}
}
function doQuery(query, onCompleted) {
const result = [];
const sql = replaceParamChar(query.sql(), query.parameters);
// Transaction statements
if (sql.length < 18 && query.parameters.length === 0) {
if (sql === 'BEGIN TRANSACTION') {
log.emitQuery({ sql, parameters: [] });
connection.beginTransaction((err) => {
onCompleted(extractError(err), []);
});
return;
}
else if (sql === 'COMMIT') {
log.emitQuery({ sql, parameters: [] });
connection.commitTransaction((err) => {
onCompleted(extractError(err), []);
});
return;
}
else if (sql === 'ROLLBACK') {
log.emitQuery({ sql, parameters: [] });
connection.rollbackTransaction((err) => {
onCompleted(extractError(err), []);
});
return;
}
}
let keys;
// Now we can safely create Request using CachedRequest
var request = new CachedRequest(sql, onInnerCompleted);
const params = addParameters(request, query.parameters, CachedTypes);
request.on('row', rows => {
const tmp = {};
if (!keys) {
keys = Object.keys(rows);
}
keys.forEach(cols => {
tmp[cols] = rows[cols].value;
});
result.push(tmp);
});
log.emitQuery({ sql, parameters: params });
connection.execSql(request);
function onInnerCompleted(err) {
if (err) {
onCompleted(extractError(err));
} else {
onCompleted(null, result);
}
}
}
}
// same helpers as before
function extractError(e) {
if (e && e.errors) {
return e.errors[0];
}
else {
return e;
}
}
function replaceParamChar(sql, params) {
if (params.length === 0)
return sql;
var splitted = sql.split('?');
sql = '';
var lastIndex = splitted.length - 1;
for (var i = 0; i < lastIndex; i++) {
sql += splitted[i] + '@' + i;
}
sql += splitted[lastIndex];
return sql;
}
function addParameters(request, params, TYPES) {
const res = [];
for (let i = 0; i < params.length; i++) {
const p = [`${i}`, toType(params[i]), params[i]];
request.addParameter.apply(request, p);
res.push(p);
}
return res;
function toType(p) {
if (typeof p === 'string')
return TYPES.VarChar;
else if (Number.isInteger(p))
return TYPES.Int;
else if (typeof p === 'number')
return TYPES.Money;
else if (p instanceof Date && !isNaN(p))
return TYPES.Date;
else if (Array.isArray(p))
return TYPES.NVarChar;
else if (Buffer.isBuffer(p))
return TYPES.VarBinary;
else if (typeof p === 'object' && p instanceof Object)
return TYPES.NVarChar;
else
throw new Error('Unknown data type');
}
}
module.exports = wrapQuery;