mssql2
Version:
Microsoft SQL Server client for Node.js (fork)
1,354 lines (1,291 loc) • 49.3 kB
JavaScript
// Generated by CoffeeScript 1.10.0
(function() {
var DECLARATIONS, JSON_COLUMN_ID, Pool, TYPES, Table, UDT, XML_COLUMN_ID, bindDomain, cast, createColumns, declare, getMssqlType, getTediousType, parameterCorrection, ref, tds, util, valueCorrection,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
Pool = require('generic-pool').Pool;
tds = require('tedious');
util = require('util');
ref = require('./datatypes'), TYPES = ref.TYPES, declare = ref.declare, cast = ref.cast;
DECLARATIONS = require('./datatypes').DECLARATIONS;
UDT = require('./udt').PARSERS;
Table = require('./table');
JSON_COLUMN_ID = 'JSON_F52E2B61-18A1-11d1-B105-00805F49916B';
XML_COLUMN_ID = 'XML_F52E2B61-18A1-11d1-B105-00805F49916B';
/*
@ignore
*/
bindDomain = function(cb) {
var ref1;
if (process.domain) {
return (ref1 = process.domain) != null ? ref1.bind(cb) : void 0;
} else {
return cb;
}
};
/*
@ignore
*/
getTediousType = function(type) {
switch (type) {
case TYPES.VarChar:
return tds.TYPES.VarChar;
case TYPES.NVarChar:
return tds.TYPES.NVarChar;
case TYPES.Text:
return tds.TYPES.Text;
case TYPES.Int:
return tds.TYPES.Int;
case TYPES.BigInt:
return tds.TYPES.BigInt;
case TYPES.TinyInt:
return tds.TYPES.TinyInt;
case TYPES.SmallInt:
return tds.TYPES.SmallInt;
case TYPES.Bit:
return tds.TYPES.Bit;
case TYPES.Float:
return tds.TYPES.Float;
case TYPES.Decimal:
return tds.TYPES.Decimal;
case TYPES.Numeric:
return tds.TYPES.Numeric;
case TYPES.Real:
return tds.TYPES.Real;
case TYPES.Money:
return tds.TYPES.Money;
case TYPES.SmallMoney:
return tds.TYPES.SmallMoney;
case TYPES.Time:
return tds.TYPES.TimeN;
case TYPES.Date:
return tds.TYPES.DateN;
case TYPES.DateTime:
return tds.TYPES.DateTime;
case TYPES.DateTime2:
return tds.TYPES.DateTime2N;
case TYPES.DateTimeOffset:
return tds.TYPES.DateTimeOffsetN;
case TYPES.SmallDateTime:
return tds.TYPES.SmallDateTime;
case TYPES.UniqueIdentifier:
return tds.TYPES.UniqueIdentifierN;
case TYPES.Xml:
return tds.TYPES.VarChar;
case TYPES.Char:
return tds.TYPES.Char;
case TYPES.NChar:
return tds.TYPES.NChar;
case TYPES.NText:
return tds.TYPES.NVarChar;
case TYPES.Image:
return tds.TYPES.Image;
case TYPES.Binary:
return tds.TYPES.Binary;
case TYPES.VarBinary:
return tds.TYPES.VarBinary;
case TYPES.UDT:
case TYPES.Geography:
case TYPES.Geometry:
return tds.TYPES.UDT;
case TYPES.TVP:
return tds.TYPES.TVP;
case TYPES.Variant:
return tds.TYPES.Variant;
default:
return type;
}
};
/*
@ignore
*/
getMssqlType = function(type, length) {
switch (type) {
case tds.TYPES.Char:
return TYPES.Char;
case tds.TYPES.NChar:
return TYPES.NChar;
case tds.TYPES.VarChar:
return TYPES.VarChar;
case tds.TYPES.NVarChar:
return TYPES.NVarChar;
case tds.TYPES.Text:
return TYPES.Text;
case tds.TYPES.NText:
return TYPES.NText;
case tds.TYPES.Int:
return TYPES.Int;
case tds.TYPES.IntN:
if (length === 8) {
return TYPES.BigInt;
}
if (length === 4) {
return TYPES.Int;
}
if (length === 2) {
return TYPES.SmallInt;
}
return TYPES.TinyInt;
case tds.TYPES.BigInt:
return TYPES.BigInt;
case tds.TYPES.TinyInt:
return TYPES.TinyInt;
case tds.TYPES.SmallInt:
return TYPES.SmallInt;
case tds.TYPES.Bit:
case tds.TYPES.BitN:
return TYPES.Bit;
case tds.TYPES.Float:
return TYPES.Float;
case tds.TYPES.FloatN:
if (length === 8) {
return TYPES.FloatN;
}
return TYPES.Real;
case tds.TYPES.Real:
return TYPES.Real;
case tds.TYPES.Money:
return TYPES.Money;
case tds.TYPES.MoneyN:
if (length === 8) {
return TYPES.Money;
}
return TYPES.SmallMoney;
case tds.TYPES.SmallMoney:
return TYPES.SmallMoney;
case tds.TYPES.Numeric:
case tds.TYPES.NumericN:
return TYPES.Numeric;
case tds.TYPES.Decimal:
case tds.TYPES.DecimalN:
return TYPES.Decimal;
case tds.TYPES.DateTime:
return TYPES.DateTime;
case tds.TYPES.DateTimeN:
if (length === 8) {
return TYPES.DateTime;
}
return TYPES.SmallDateTime;
case tds.TYPES.TimeN:
return TYPES.Time;
case tds.TYPES.DateN:
return TYPES.Date;
case tds.TYPES.DateTime2N:
return TYPES.DateTime2;
case tds.TYPES.DateTimeOffsetN:
return TYPES.DateTimeOffset;
case tds.TYPES.SmallDateTime:
return TYPES.SmallDateTime;
case tds.TYPES.UniqueIdentifierN:
return TYPES.UniqueIdentifier;
case tds.TYPES.Image:
return TYPES.Image;
case tds.TYPES.Binary:
return TYPES.Binary;
case tds.TYPES.VarBinary:
return TYPES.VarBinary;
case tds.TYPES.Xml:
return TYPES.Xml;
case tds.TYPES.UDT:
return TYPES.UDT;
case tds.TYPES.TVP:
return TYPES.TVP;
case tds.TYPES.Variant:
return TYPES.Variant;
}
};
/*
@ignore
*/
createColumns = function(metadata) {
var column, i, index, len, out;
out = {};
for (index = i = 0, len = metadata.length; i < len; index = ++i) {
column = metadata[index];
out[column.colName] = {
index: index,
name: column.colName,
length: column.dataLength,
type: getMssqlType(column.type, column.dataLength),
scale: column.scale,
precision: column.precision,
nullable: !!(column.flags & 0x01),
caseSensitive: !!(column.flags & 0x02),
identity: !!(column.flags & 0x10),
readOnly: !(column.flags & 0x0C)
};
if (column.udtInfo != null) {
out[column.colName].udt = {
name: column.udtInfo.typeName,
database: column.udtInfo.dbname,
schema: column.udtInfo.owningSchema,
assembly: column.udtInfo.assemblyName
};
if (DECLARATIONS[column.udtInfo.typeName]) {
out[column.colName].type = DECLARATIONS[column.udtInfo.typeName];
}
}
}
return out;
};
/*
@ignore
*/
valueCorrection = function(value, metadata) {
if (metadata.type === tds.TYPES.UDT && (value != null)) {
if (UDT[metadata.udtInfo.typeName]) {
return UDT[metadata.udtInfo.typeName](value);
} else {
return value;
}
} else {
return value;
}
};
/*
@ignore
*/
parameterCorrection = function(value) {
var col, i, len, ref1, tvp;
if (value instanceof Table) {
tvp = {
name: value.name,
schema: value.schema,
columns: [],
rows: value.rows
};
ref1 = value.columns;
for (i = 0, len = ref1.length; i < len; i++) {
col = ref1[i];
tvp.columns.push({
name: col.name,
type: getTediousType(col.type),
length: col.length,
scale: col.scale,
precision: col.precision
});
}
return tvp;
} else {
return value;
}
};
/*
@ignore
*/
module.exports = function(Connection, Transaction, Request, ConnectionError, TransactionError, RequestError) {
var TediousConnection, TediousRequest, TediousTransaction;
TediousConnection = (function(superClass) {
extend(TediousConnection, superClass);
function TediousConnection() {
return TediousConnection.__super__.constructor.apply(this, arguments);
}
TediousConnection.prototype.pool = null;
TediousConnection.prototype.connect = function(config, callback) {
var base, base1, base2, base3, base4, base5, cfg, cfg_pool, key, ref1, ref2, ref3, ref4, value;
cfg = {
userName: config.user,
password: config.password,
server: config.server,
options: config.options,
domain: config.domain
};
if ((base = cfg.options).database == null) {
base.database = config.database;
}
if ((base1 = cfg.options).port == null) {
base1.port = config.port;
}
if ((base2 = cfg.options).connectTimeout == null) {
base2.connectTimeout = (ref1 = (ref2 = config.connectionTimeout) != null ? ref2 : config.timeout) != null ? ref1 : 15000;
}
if ((base3 = cfg.options).requestTimeout == null) {
base3.requestTimeout = (ref3 = config.requestTimeout) != null ? ref3 : 15000;
}
if ((base4 = cfg.options).tdsVersion == null) {
base4.tdsVersion = '7_4';
}
cfg.options.rowCollectionOnDone = false;
cfg.options.rowCollectionOnRequestCompletion = false;
cfg.options.useColumnNames = false;
if ((base5 = cfg.options).appName == null) {
base5.appName = 'node-mssql';
}
if (cfg.options.instanceName) {
delete cfg.options.port;
}
if (isNaN(cfg.options.requestTimeout)) {
cfg.options.requestTimeout = 15000;
}
if (cfg.options.requestTimeout === Infinity) {
cfg.options.requestTimeout = 0;
}
if (cfg.options.requestTimeout < 0) {
cfg.options.requestTimeout = 0;
}
if (config.debug) {
cfg.options.debug = {
packet: true,
token: true,
data: true,
payload: true
};
}
cfg_pool = {
name: 'mssql',
max: 10,
min: 0,
idleTimeoutMillis: 30000,
create: (function(_this) {
return function(callback) {
var c;
c = new tds.Connection(cfg);
c.once('connect', function(err) {
if (err) {
err = ConnectionError(err);
}
if (err) {
return callback(err, null);
}
return callback(null, c);
});
c.on('error', function(err) {
if (err.code === 'ESOCKET') {
c.hasError = true;
return;
}
return _this.emit('error', err);
});
if (config.debug) {
return c.on('debug', function(msg) {
return _this._debug(msg);
});
}
};
})(this),
validate: function(c) {
return (c != null) && !c.closed && !c.hasError;
},
destroy: function(c) {
if (c != null) {
c.close();
}
return setTimeout(function() {
return c != null ? c.removeAllListeners() : void 0;
}, 500);
}
};
if (config.pool) {
ref4 = config.pool;
for (key in ref4) {
value = ref4[key];
cfg_pool[key] = value;
}
}
this.pool = Pool(cfg_pool, cfg);
return this.pool.acquire((function(_this) {
return function(err, connection) {
if (err) {
_this.pool.drain(function() {
var ref5;
if ((ref5 = _this.pool) != null) {
ref5.destroyAllNow();
}
return _this.pool = null;
});
} else {
_this.pool.release(connection);
}
return callback(err);
};
})(this));
};
TediousConnection.prototype.close = function(callback) {
if (!this.pool) {
return callback(null);
}
return this.pool.drain((function(_this) {
return function() {
var ref1;
if ((ref1 = _this.pool) != null) {
ref1.destroyAllNow();
}
_this.pool = null;
return callback(null);
};
})(this));
};
return TediousConnection;
})(Connection);
TediousTransaction = (function(superClass) {
extend(TediousTransaction, superClass);
function TediousTransaction() {
return TediousTransaction.__super__.constructor.apply(this, arguments);
}
TediousTransaction.prototype._abort = function() {
var pc;
if (!this._rollbackRequested) {
pc = this._pooledConnection;
setImmediate((function(_this) {
return function() {
return _this.connection.pool.release(pc);
};
})(this));
this._pooledConnection.removeListener('rollbackTransaction', this._abort);
this._pooledConnection = null;
this._aborted = true;
return this.emit('rollback', true);
}
};
TediousTransaction.prototype.begin = function(callback) {
this._aborted = false;
this._rollbackRequested = false;
return this.connection.pool.acquire((function(_this) {
return function(err, connection) {
if (err) {
return callback(err);
}
_this._pooledConnection = connection;
_this._pooledConnection.on('rollbackTransaction', _this._abort);
return connection.beginTransaction(bindDomain(function(err) {
if (err) {
err = TransactionError(err);
}
return callback(err);
}, _this.name, _this.isolationLevel));
};
})(this));
};
TediousTransaction.prototype.commit = function(callback) {
return this._pooledConnection.commitTransaction(bindDomain((function(_this) {
return function(err) {
if (err) {
err = TransactionError(err);
}
_this._pooledConnection.removeListener('rollbackTransaction', _this._abort);
_this.connection.pool.release(_this._pooledConnection);
_this._pooledConnection = null;
return callback(err);
};
})(this)));
};
TediousTransaction.prototype.rollback = function(callback) {
this._rollbackRequested = true;
return this._pooledConnection.rollbackTransaction(bindDomain((function(_this) {
return function(err) {
if (err) {
err = TransactionError(err);
}
_this._pooledConnection.removeListener('rollbackTransaction', _this._abort);
_this.connection.pool.release(_this._pooledConnection);
_this._pooledConnection = null;
return callback(err);
};
})(this)));
};
return TediousTransaction;
})(Transaction);
TediousRequest = (function(superClass) {
extend(TediousRequest, superClass);
function TediousRequest() {
return TediousRequest.__super__.constructor.apply(this, arguments);
}
/*
Execute specified sql batch.
*/
TediousRequest.prototype.batch = function(batch, callback) {
this._isBatch = true;
return TediousRequest.prototype.query.call(this, batch, callback);
};
/*
Bulk load.
*/
TediousRequest.prototype.bulk = function(table, callback) {
var errorHandlers, errors, handleError, handleInfo, hasReturned, started;
table._makeBulk();
if (!table.name) {
process.nextTick(function() {
return callback(RequestError("Table name must be specified for bulk insert.", "ENAME"));
});
}
if (table.name.charAt(0) === '@') {
process.nextTick(function() {
return callback(RequestError("You can't use table variables for bulk insert.", "ENAME"));
});
}
started = Date.now();
errors = [];
errorHandlers = {};
hasReturned = false;
handleError = (function(_this) {
return function(doReturn, connection, info) {
var e, err, event, handler;
err = new Error(info.message);
err.info = info;
e = RequestError(err, 'EREQUEST');
if (_this.stream) {
_this.emit('error', e);
} else {
if (doReturn && !hasReturned) {
if (connection != null) {
for (event in errorHandlers) {
handler = errorHandlers[event];
connection.removeListener(event, handler);
}
_this._release(connection);
}
hasReturned = true;
if (typeof callback === "function") {
callback(e);
}
}
}
return errors.push(e);
};
})(this);
handleInfo = (function(_this) {
return function(msg) {
return _this.emit('info', {
message: msg.message,
number: msg.number,
state: msg.state,
"class": msg["class"],
lineNumber: msg.lineNumber,
serverName: msg.serverName,
procName: msg.procName
});
};
})(this);
return this._acquire((function(_this) {
return function(err, connection) {
var bulk, col, done, i, j, len, len1, objectid, ref1, ref2, req, row;
if (!err) {
if (_this.verbose) {
_this._log("-------- sql bulk load --------\n table: " + table.name);
}
if (_this.canceled) {
if (_this.verbose) {
_this._log("---------- canceling ----------");
}
_this._release(connection);
return typeof callback === "function" ? callback(new RequestError("Canceled.", 'ECANCEL')) : void 0;
}
_this._cancel = function() {
if (_this.verbose) {
_this._log("---------- canceling ----------");
}
return connection.cancel();
};
errorHandlers['infoMessage'] = handleInfo;
errorHandlers['errorMessage'] = handleError.bind(void 0, false, connection);
errorHandlers['error'] = handleError.bind(void 0, true, connection);
connection.on('infoMessage', errorHandlers['infoMessage']);
connection.on('errorMessage', errorHandlers['errorMessage']);
connection.on('error', errorHandlers['error']);
done = bindDomain(function(err, rowCount) {
var elapsed, error, event, handler, i, len, ref1;
if (err && err.message !== ((ref1 = errors[errors.length - 1]) != null ? ref1.message : void 0)) {
err = RequestError(err, 'EREQUEST');
if (_this.stream) {
_this.emit('error', err);
}
errors.push(err);
}
if (_this.verbose) {
if (errors.length) {
for (i = 0, len = errors.length; i < len; i++) {
error = errors[i];
_this._log(" error: " + error);
}
}
elapsed = Date.now() - started;
_this._log(" duration: " + elapsed + "ms");
_this._log("---------- completed ----------");
}
_this._cancel = null;
if (errors.length && !_this.stream) {
error = errors.pop();
error.precedingErrors = errors;
}
if (!hasReturned) {
for (event in errorHandlers) {
handler = errorHandlers[event];
connection.removeListener(event, handler);
}
_this._release(connection);
hasReturned = true;
if (_this.stream) {
return callback(null, null);
} else {
return typeof callback === "function" ? callback(error, rowCount) : void 0;
}
}
});
bulk = connection.newBulkLoad(table.path, done);
ref1 = table.columns;
for (i = 0, len = ref1.length; i < len; i++) {
col = ref1[i];
bulk.addColumn(col.name, getTediousType(col.type), {
nullable: col.nullable,
length: col.length,
scale: col.scale,
precision: col.precision
});
}
ref2 = table.rows;
for (j = 0, len1 = ref2.length; j < len1; j++) {
row = ref2[j];
bulk.addRow(row);
}
if (_this.verbose) {
_this._log("---------- response -----------");
}
if (table.create) {
if (table.temporary) {
objectid = "tempdb..[" + table.name + "]";
} else {
objectid = table.path;
}
req = new tds.Request("if object_id('" + (objectid.replace(/'/g, '\'\'')) + "') is null " + (table.declare()), function(err) {
if (err) {
return done(err);
}
return connection.execBulkLoad(bulk);
});
return connection.execSqlBatch(req);
} else {
return connection.execBulkLoad(bulk);
}
}
};
})(this));
};
/*
Execute specified sql command.
*/
TediousRequest.prototype.query = function(command, callback) {
var batchHasOutput, batchLastRow, chunksBuffer, columns, errorHandlers, errors, handleError, handleInfo, hasReturned, isChunkedRecordset, isJSONRecordset, recordset, recordsets, started, xmlBuffer;
columns = {};
recordset = [];
recordsets = [];
started = Date.now();
errors = [];
batchLastRow = null;
batchHasOutput = false;
isJSONRecordset = false;
isChunkedRecordset = false;
chunksBuffer = null;
xmlBuffer = null;
hasReturned = false;
errorHandlers = {};
handleError = (function(_this) {
return function(doReturn, connection, info) {
var e, err, event, handler;
err = new Error(info.message);
err.info = info;
e = RequestError(err, 'EREQUEST');
if (_this.stream) {
_this.emit('error', e);
} else {
if (doReturn && !hasReturned) {
if (connection != null) {
for (event in errorHandlers) {
handler = errorHandlers[event];
connection.removeListener(event, handler);
}
_this._release(connection);
}
hasReturned = true;
if (typeof callback === "function") {
callback(e);
}
}
}
return errors.push(e);
};
})(this);
handleInfo = (function(_this) {
return function(msg) {
return _this.emit('info', {
message: msg.message,
number: msg.number,
state: msg.state,
"class": msg["class"],
lineNumber: msg.lineNumber,
serverName: msg.serverName,
procName: msg.procName
});
};
})(this);
return this._acquire((function(_this) {
return function(err, connection) {
var assigns, declarations, doneHandler, name, param, ref1, ref2, req, selects, value;
if (!err) {
if (_this.verbose) {
_this._log("---------- sql " + (_this._isBatch ? 'batch' : 'query') + " ----------\n " + (_this._isBatch ? 'batch' : 'query') + ": " + command);
}
if (_this.canceled) {
if (_this.verbose) {
_this._log("---------- canceling ----------");
}
_this._release(connection);
return typeof callback === "function" ? callback(new RequestError("Canceled.", 'ECANCEL')) : void 0;
}
_this._cancel = function() {
if (_this.verbose) {
_this._log("---------- canceling ----------");
}
return connection.cancel();
};
errorHandlers['infoMessage'] = handleInfo;
errorHandlers['errorMessage'] = handleError.bind(void 0, false, connection);
errorHandlers['error'] = handleError.bind(void 0, true, connection);
connection.on('infoMessage', errorHandlers['infoMessage']);
connection.on('errorMessage', errorHandlers['errorMessage']);
connection.on('error', errorHandlers['error']);
req = new tds.Request(command, bindDomain(function(err) {
var elapsed, error, event, handler, i, len, name, ref1, value;
if (err && err.message !== ((ref1 = errors[errors.length - 1]) != null ? ref1.message : void 0)) {
err = RequestError(err, 'EREQUEST');
if (_this.stream) {
_this.emit('error', err);
}
errors.push(err);
}
if (batchHasOutput) {
if (!_this.stream) {
batchLastRow = recordsets.pop()[0];
}
for (name in batchLastRow) {
value = batchLastRow[name];
if (!(name !== '___return___')) {
continue;
}
if (_this.verbose) {
if (value === tds.TYPES.Null) {
_this._log(" output: @" + name + ", null");
} else {
_this._log(" output: @" + name + ", " + (_this.parameters[name].type.declaration.toLowerCase()) + ", " + value);
}
}
_this.parameters[name].value = value === tds.TYPES.Null ? null : value;
}
}
if (_this.verbose) {
if (errors.length) {
for (i = 0, len = errors.length; i < len; i++) {
error = errors[i];
_this._log(" error: " + error);
}
}
elapsed = Date.now() - started;
_this._log(" duration: " + elapsed + "ms");
_this._log("---------- completed ----------");
}
_this._cancel = null;
if (errors.length && !_this.stream) {
error = errors.pop();
error.precedingErrors = errors;
}
if (!hasReturned) {
for (event in errorHandlers) {
handler = errorHandlers[event];
connection.removeListener(event, handler);
}
_this._release(connection);
hasReturned = true;
if (_this.stream) {
return callback(null, null);
} else {
return typeof callback === "function" ? callback(error, _this.multiple ? recordsets : recordsets[0]) : void 0;
}
}
}));
req.on('columnMetadata', function(metadata) {
var ref1;
columns = createColumns(metadata);
isChunkedRecordset = false;
if (metadata.length === 1 && ((ref1 = metadata[0].colName) === JSON_COLUMN_ID || ref1 === XML_COLUMN_ID)) {
isChunkedRecordset = true;
chunksBuffer = [];
}
if (_this.stream) {
if (_this._isBatch) {
if (columns["___return___"] == null) {
return _this.emit('recordset', columns);
}
} else {
return _this.emit('recordset', columns);
}
}
});
doneHandler = function(rowCount, more) {
var error1, ex, row;
if (Object.keys(columns).length === 0) {
if (rowCount > 0) {
_this.rowsAffected += rowCount;
}
return;
}
if (isChunkedRecordset) {
if (columns[JSON_COLUMN_ID] && _this.connection.config.parseJSON === true) {
try {
row = JSON.parse(chunksBuffer.join(''));
} catch (error1) {
ex = error1;
row = null;
ex = RequestError(new Error("Failed to parse incoming JSON. " + ex.message), 'EJSON');
if (_this.stream) {
_this.emit('error', ex);
}
errors.push(ex);
}
} else {
row = {};
row[Object.keys(columns)[0]] = chunksBuffer.join('');
}
chunksBuffer = null;
if (_this.verbose) {
_this._log(util.inspect(row));
_this._log("---------- --------------------");
}
if (_this.stream) {
_this.emit('row', row);
} else {
recordset.push(row);
}
}
if (!_this.stream) {
Object.defineProperty(recordset, 'columns', {
enumerable: false,
value: columns
});
Object.defineProperty(recordset, 'toTable', {
enumerable: false,
value: function() {
return Table.fromRecordset(this);
}
});
recordsets.push(recordset);
}
recordset = [];
return columns = {};
};
req.on('doneInProc', doneHandler);
req.on('done', doneHandler);
req.on('returnValue', function(parameterName, value, metadata) {
if (_this.verbose) {
if (value === tds.TYPES.Null) {
_this._log(" output: @" + parameterName + ", null");
} else {
_this._log(" output: @" + parameterName + ", " + (_this.parameters[parameterName].type.declaration.toLowerCase()) + ", " + value);
}
}
return _this.parameters[parameterName].value = value === tds.TYPES.Null ? null : value;
});
req.on('row', function(columns) {
var col, exi, i, len, row;
if (!recordset) {
recordset = [];
}
if (isChunkedRecordset) {
return chunksBuffer.push(columns[0].value);
} else {
row = {};
for (i = 0, len = columns.length; i < len; i++) {
col = columns[i];
col.value = valueCorrection(col.value, col.metadata);
exi = row[col.metadata.colName];
if (exi != null) {
if (exi instanceof Array) {
exi.push(col.value);
} else {
row[col.metadata.colName] = [exi, col.value];
}
} else {
row[col.metadata.colName] = col.value;
}
}
if (_this.verbose) {
_this._log(util.inspect(row));
_this._log("---------- --------------------");
}
if (_this.stream) {
if (_this._isBatch) {
if (row["___return___"] != null) {
return batchLastRow = row;
} else {
return _this.emit('row', row);
}
} else {
return _this.emit('row', row);
}
} else {
return recordset.push(row);
}
}
});
if (_this._isBatch) {
if (Object.keys(_this.parameters).length) {
ref1 = _this.parameters;
for (name in ref1) {
param = ref1[name];
value = getTediousType(param.type).validate(param.value);
if (value instanceof TypeError) {
value = new RequestError("Validation failed for parameter \'" + name + "\'. " + value.message, 'EPARAM');
if (_this.verbose) {
_this._log(" error: " + value);
_this._log("---------- completed ----------");
}
_this._release(connection);
return typeof callback === "function" ? callback(value) : void 0;
}
param.value = value;
}
declarations = (function() {
var ref2, results;
ref2 = this.parameters;
results = [];
for (name in ref2) {
param = ref2[name];
results.push("@" + name + " " + (declare(param.type, param)));
}
return results;
}).call(_this);
assigns = (function() {
var ref2, results;
ref2 = this.parameters;
results = [];
for (name in ref2) {
param = ref2[name];
results.push("@" + name + " = " + (cast(param.value, param.type, param)));
}
return results;
}).call(_this);
selects = (function() {
var ref2, results;
ref2 = this.parameters;
results = [];
for (name in ref2) {
param = ref2[name];
if (param.io === 2) {
results.push("@" + name + " as [" + name + "]");
}
}
return results;
}).call(_this);
batchHasOutput = selects.length > 0;
req.sqlTextOrProcedure = "declare " + (declarations.join(', ')) + ";select " + (assigns.join(', ')) + ";" + req.sqlTextOrProcedure + ";" + (batchHasOutput ? 'select 1 as [___return___], ' + selects.join(', ') : '');
}
} else {
ref2 = _this.parameters;
for (name in ref2) {
param = ref2[name];
if (_this.verbose) {
if (param.value === tds.TYPES.Null) {
_this._log(" " + (param.io === 1 ? " input" : "output") + ": @" + param.name + ", null");
} else {
_this._log(" " + (param.io === 1 ? " input" : "output") + ": @" + param.name + ", " + (param.type.declaration.toLowerCase()) + ", " + param.value);
}
}
if (param.io === 1) {
req.addParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), {
length: param.length,
scale: param.scale,
precision: param.precision
});
} else {
req.addOutputParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), {
length: param.length,
scale: param.scale,
precision: param.precision
});
}
}
}
if (_this.verbose) {
_this._log("---------- response -----------");
}
return connection[_this._isBatch ? 'execSqlBatch' : 'execSql'](req);
} else {
if (connection) {
_this._release(connection);
}
return typeof callback === "function" ? callback(err) : void 0;
}
};
})(this));
};
/*
Execute stored procedure with specified parameters.
*/
TediousRequest.prototype.execute = function(procedure, callback) {
var chunksBuffer, columns, errorHandlers, errors, handleError, hasReturned, isChunkedRecordset, recordset, recordsets, returnValue, started;
columns = {};
recordset = [];
recordsets = [];
returnValue = 0;
started = Date.now();
errors = [];
isChunkedRecordset = false;
chunksBuffer = null;
hasReturned = false;
errorHandlers = {};
handleError = (function(_this) {
return function(doReturn, connection, info) {
var e, err, event, handler;
err = new Error(info.message);
err.info = info;
e = RequestError(err, 'EREQUEST');
if (_this.stream) {
_this.emit('error', e);
} else {
if (doReturn && !hasReturned) {
if (connection != null) {
for (event in errorHandlers) {
handler = errorHandlers[event];
connection.removeListener(event, handler);
}
_this._release(connection);
}
hasReturned = true;
if (typeof callback === "function") {
callback(e);
}
}
}
return errors.push(e);
};
})(this);
return this._acquire((function(_this) {
return function(err, connection) {
var name, param, ref1, req;
if (!err) {
if (_this.verbose) {
_this._log("---------- sql execute --------\n proc: " + procedure);
}
if (_this.canceled) {
if (_this.verbose) {
_this._log("---------- canceling ----------");
}
_this._release(connection);
return typeof callback === "function" ? callback(new RequestError("Canceled.", 'ECANCEL')) : void 0;
}
_this._cancel = function() {
if (_this.verbose) {
_this._log("---------- canceling ----------");
}
return connection.cancel();
};
errorHandlers['errorMessage'] = handleError.bind(void 0, false, connection);
errorHandlers['error'] = handleError.bind(void 0, true, connection);
connection.on('errorMessage', errorHandlers['errorMessage']);
connection.on('error', errorHandlers['error']);
req = new tds.Request(procedure, bindDomain(function(err) {
var elapsed, error, event, handler, i, len, ref1;
if (err && err.message !== ((ref1 = errors[errors.length - 1]) != null ? ref1.message : void 0)) {
err = RequestError(err, 'EREQUEST');
if (_this.stream) {
_this.emit('error', err);
}
errors.push(err);
}
if (_this.verbose) {
if (errors.length) {
for (i = 0, len = errors.length; i < len; i++) {
error = errors[i];
_this._log(" error: " + error);
}
}
elapsed = Date.now() - started;
_this._log(" return: " + returnValue);
_this._log(" duration: " + elapsed + "ms");
_this._log("---------- completed ----------");
}
_this._cancel = null;
if (errors.length && !_this.stream) {
error = errors.pop();
error.precedingErrors = errors;
}
if (!hasReturned) {
for (event in errorHandlers) {
handler = errorHandlers[event];
connection.removeListener(event, handler);
}
_this._release(connection);
hasReturned = true;
if (_this.stream) {
return callback(null, null, returnValue);
} else {
recordsets.returnValue = returnValue;
return typeof callback === "function" ? callback(error, recordsets, returnValue) : void 0;
}
}
}));
req.on('columnMetadata', function(metadata) {
var ref1;
columns = createColumns(metadata);
isChunkedRecordset = false;
if (metadata.length === 1 && ((ref1 = metadata[0].colName) === JSON_COLUMN_ID || ref1 === XML_COLUMN_ID)) {
isChunkedRecordset = true;
chunksBuffer = [];
}
if (_this.stream) {
return _this.emit('recordset', columns);
}
});
req.on('row', function(columns) {
var col, exi, i, len, row;
if (!recordset) {
recordset = [];
}
if (isChunkedRecordset) {
return chunksBuffer.push(columns[0].value);
} else {
row = {};
for (i = 0, len = columns.length; i < len; i++) {
col = columns[i];
col.value = valueCorrection(col.value, col.metadata);
exi = row[col.metadata.colName];
if (exi != null) {
if (exi instanceof Array) {
exi.push(col.value);
} else {
row[col.metadata.colName] = [exi, col.value];
}
} else {
row[col.metadata.colName] = col.value;
}
}
if (_this.verbose) {
_this._log(util.inspect(row));
_this._log("---------- --------------------");
}
if (_this.stream) {
return _this.emit('row', row);
} else {
return recordset.push(row);
}
}
});
req.on('doneInProc', function(rowCount, more) {
var error1, ex, row;
if (Object.keys(columns).length === 0) {
if (rowCount > 0) {
_this.rowsAffected += rowCount;
}
return;
}
if (isChunkedRecordset) {
if (columns[JSON_COLUMN_ID] && _this.connection.config.parseJSON === true) {
try {
row = JSON.parse(chunksBuffer.join(''));
} catch (error1) {
ex = error1;
row = null;
ex = RequestError(new Error("Failed to parse incoming JSON. " + ex.message), 'EJSON');
if (_this.stream) {
_this.emit('error', ex);
}
errors.push(ex);
}
} else {
row = {};
row[Object.keys(columns)[0]] = chunksBuffer.join('');
}
chunksBuffer = null;
if (_this.verbose) {
_this._log(util.inspect(row));
_this._log("---------- --------------------");
}
if (_this.stream) {
_this.emit('row', row);
} else {
recordset.push(row);
}
}
if (!_this.stream) {
Object.defineProperty(recordset, 'columns', {
enumerable: false,
value: columns
});
Object.defineProperty(recordset, 'toTable', {
enumerable: false,
value: function() {
return Table.fromRecordset(this);
}
});
recordsets.push(recordset);
}
recordset = [];
return columns = {};
});
req.on('doneProc', function(rowCount, more, returnStatus) {
return returnValue = returnStatus;
});
req.on('returnValue', function(parameterName, value, metadata) {
if (_this.verbose) {
if (value === tds.TYPES.Null) {
_this._log(" output: @" + parameterName + ", null");
} else {
_this._log(" output: @" + parameterName + ", " + (_this.parameters[parameterName].type.declaration.toLowerCase()) + ", " + value);
}
}
return _this.parameters[parameterName].value = value === tds.TYPES.Null ? null : value;
});
ref1 = _this.parameters;
for (name in ref1) {
param = ref1[name];
if (_this.verbose) {
if (param.value === tds.TYPES.Null) {
_this._log(" " + (param.io === 1 ? " input" : "output") + ": @" + param.name + ", null");
} else {
_this._log(" " + (param.io === 1 ? " input" : "output") + ": @" + param.name + ", " + (param.type.declaration.toLowerCase()) + ", " + param.value);
}
}
if (param.io === 1) {
req.addParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), {
length: param.length,
scale: param.scale,
precision: param.precision
});
} else {
req.addOutputParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), {
length: param.length,
scale: param.scale,
precision: param.precision
});
}
}
if (_this.verbose) {
_this._log("---------- response -----------");
}
return connection.callProcedure(req);
} else {
if (connection) {
_this._release(connection);
}
return typeof callback === "function" ? callback(err) : void 0;
}
};
})(this));
};
/*
Cancel currently executed request.
*/
TediousRequest.prototype.cancel = function() {
if (this._cancel) {
return this._cancel();
}
return true;
};
return TediousRequest;
})(Request);
return {
Connection: TediousConnection,
Transaction: TediousTransaction,
Request: TediousRequest,
fix: function() {}
};
};
}).call(this);