UNPKG

orange-orm

Version:

Object Relational Mapper

145 lines (125 loc) 3.81 kB
var log = require('../table/log'); function wrapCommand(_context, connection) { let CachedRequest = null; let CachedTypes = null; return runQuery; function runQuery(query, onCompleted) { enqueue(function(done) { function safeCompleted(err, result) { try { onCompleted(err, result); } finally { done(); } } if (!CachedRequest || !CachedTypes) { import('tedious') .then(({ Request, TYPES }) => { CachedRequest = Request; CachedTypes = TYPES; doQuery(query, safeCompleted); }) .catch((err) => safeCompleted(extractError(err), { rowsAffected: 0 })); } else { doQuery(query, safeCompleted); } }); } function doQuery(query, onCompleted) { log.emitQuery({ sql: query.sql(), parameters: query.parameters }); const sql = replaceParamChar(query.sql(), query.parameters); if (sql.length < 18 && query.parameters.length === 0) { if (sql === 'BEGIN TRANSACTION') { connection.beginTransaction((err) => { if (err) return onCompleted(extractError(err), { rowsAffected: 0 }); return onCompleted(null, { rowsAffected: 0 }); }); return; } else if (sql === 'COMMIT') { connection.commitTransaction((err) => { if (err) return onCompleted(extractError(err), { rowsAffected: 0 }); return onCompleted(null, { rowsAffected: 0 }); }); return; } else if (sql === 'ROLLBACK') { connection.rollbackTransaction((err) => { if (err) return onCompleted(extractError(err), { rowsAffected: 0 }); return onCompleted(null, { rowsAffected: 0 }); }); return; } } let affectedRows = 0; var request = new CachedRequest(sql, onInnerCompleted); addParameters(request, query.parameters, CachedTypes); request.on('doneInProc', (rowCount) => { if (typeof rowCount === 'number') affectedRows += rowCount; }); request.on('doneProc', (rowCount) => { if (typeof rowCount === 'number') affectedRows += rowCount; }); request.on('done', (rowCount) => { if (typeof rowCount === 'number') affectedRows += rowCount; }); connection.execSql(request); function onInnerCompleted(err) { if (err) return onCompleted(extractError(err), { rowsAffected: 0 }); return onCompleted(null, { rowsAffected: affectedRows }); } } function enqueue(task) { if (!connection.__orangeOrmQueue) connection.__orangeOrmQueue = Promise.resolve(); connection.__orangeOrmQueue = connection.__orangeOrmQueue.then(() => new Promise((resolve) => { try { task(resolve); } catch (_e) { resolve(); } })).catch(() => {}); } } 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)) { if (p >= -2147483648 && p <= 2147483647) { return TYPES.Int; } else { return TYPES.BigInt; } } 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 = wrapCommand;