Comparing version 0.5.0 to 0.5.1
@@ -0,1 +1,12 @@ | ||
v0.5.1 (2014-04-01) | ||
------------------- | ||
[change] Updated to new Tedious 0.2.1 | ||
[new] You can now easily setup type's length/scale (sql.VarChar(50)) | ||
[new] Serialization of Geography and Geometry CLR types | ||
[new] Support for creating Table-Value Parameters (var tvp = new sql.Table()) | ||
[new] Output parameters are now Input-Output and can handle initial value | ||
[new] Option to choose whether to pass/receive times in UTC or local time | ||
[new] Connecting to named instances simplified | ||
[change] Default SQL data type for JS String type is now NVarChar (was VarChar) | ||
v0.5.0 (2014-01-25) | ||
@@ -2,0 +13,0 @@ ------------------- |
@@ -1,86 +0,178 @@ | ||
// Generated by CoffeeScript 1.6.3 | ||
// Generated by CoffeeScript 1.7.1 | ||
(function() { | ||
var TYPES, key, value; | ||
var TYPES, key, value, _fn; | ||
TYPES = { | ||
VarChar: { | ||
name: 'varchar' | ||
VarChar: function(length) { | ||
return { | ||
type: TYPES.VarChar, | ||
length: length | ||
}; | ||
}, | ||
NVarChar: { | ||
name: 'nvarchar' | ||
NVarChar: function(length) { | ||
return { | ||
type: TYPES.NVarChar, | ||
length: length | ||
}; | ||
}, | ||
Text: { | ||
name: 'text' | ||
Text: function() { | ||
return { | ||
type: TYPES.Text | ||
}; | ||
}, | ||
Int: { | ||
name: 'int' | ||
Int: function() { | ||
return { | ||
type: TYPES.Int | ||
}; | ||
}, | ||
BigInt: { | ||
name: 'bigint' | ||
BigInt: function() { | ||
return { | ||
type: TYPES.BigInt | ||
}; | ||
}, | ||
TinyInt: { | ||
name: 'tinyint' | ||
TinyInt: function() { | ||
return { | ||
type: TYPES.TinyInt | ||
}; | ||
}, | ||
SmallInt: { | ||
name: 'smallint' | ||
SmallInt: function() { | ||
return { | ||
type: TYPES.SmallInt | ||
}; | ||
}, | ||
Bit: { | ||
name: 'bit' | ||
Bit: function() { | ||
return { | ||
type: TYPES.Bit | ||
}; | ||
}, | ||
Float: { | ||
name: 'float' | ||
Float: function() { | ||
return { | ||
type: TYPES.Float | ||
}; | ||
}, | ||
Numeric: { | ||
name: 'numeric' | ||
Numeric: function(precision, scale) { | ||
return { | ||
type: TYPES.Numeric, | ||
precision: precision, | ||
scale: scale | ||
}; | ||
}, | ||
Decimal: { | ||
name: 'decimal' | ||
Decimal: function(precision, scale) { | ||
return { | ||
type: TYPES.Decimal, | ||
precision: precision, | ||
scale: scale | ||
}; | ||
}, | ||
Real: { | ||
name: 'real' | ||
Real: function() { | ||
return { | ||
type: TYPES.Real | ||
}; | ||
}, | ||
Date: { | ||
name: 'date' | ||
Date: function() { | ||
return { | ||
type: TYPES.Date | ||
}; | ||
}, | ||
DateTime: { | ||
name: 'datetime' | ||
DateTime: function() { | ||
return { | ||
type: TYPES.DateTime | ||
}; | ||
}, | ||
DateTimeOffset: { | ||
name: 'datetimeoffset' | ||
DateTime2: function(scale) { | ||
return { | ||
type: TYPES.DateTime2, | ||
scale: scale | ||
}; | ||
}, | ||
SmallDateTime: { | ||
name: 'smalldatetime' | ||
DateTimeOffset: function(scale) { | ||
return { | ||
type: TYPES.DateTimeOffset, | ||
scale: scale | ||
}; | ||
}, | ||
Time: { | ||
name: 'time' | ||
SmallDateTime: function() { | ||
return { | ||
type: TYPES.SmallDateTime | ||
}; | ||
}, | ||
UniqueIdentifier: { | ||
name: 'uniqueidentifier' | ||
Time: function(scale) { | ||
return { | ||
type: TYPES.Time, | ||
scale: scale | ||
}; | ||
}, | ||
SmallMoney: { | ||
name: 'smallmoney' | ||
UniqueIdentifier: function() { | ||
return { | ||
type: TYPES.UniqueIdentifier | ||
}; | ||
}, | ||
Money: { | ||
name: 'money' | ||
SmallMoney: function() { | ||
return { | ||
type: TYPES.SmallMoney | ||
}; | ||
}, | ||
Binary: { | ||
name: 'binary' | ||
Money: function() { | ||
return { | ||
type: TYPES.Money | ||
}; | ||
}, | ||
VarBinary: { | ||
name: 'varbinary' | ||
Binary: function(length) { | ||
return { | ||
type: TYPES.Binary, | ||
length: length | ||
}; | ||
}, | ||
Image: { | ||
name: 'image' | ||
VarBinary: function(length) { | ||
return { | ||
type: TYPES.VarBinary, | ||
length: length | ||
}; | ||
}, | ||
Xml: { | ||
name: 'xml' | ||
Image: function() { | ||
return { | ||
type: TYPES.Image | ||
}; | ||
}, | ||
Char: { | ||
name: 'char' | ||
Xml: function() { | ||
return { | ||
type: TYPES.Xml | ||
}; | ||
}, | ||
NChar: { | ||
name: 'nchar' | ||
Char: function(length) { | ||
return { | ||
type: TYPES.Char, | ||
length: length | ||
}; | ||
}, | ||
NText: { | ||
name: 'ntext' | ||
NChar: function(length) { | ||
return { | ||
type: TYPES.NChar, | ||
length: length | ||
}; | ||
}, | ||
NText: function() { | ||
return { | ||
type: TYPES.NText | ||
}; | ||
}, | ||
TVP: function() { | ||
return { | ||
type: TYPES.TVP | ||
}; | ||
}, | ||
UDT: function() { | ||
return { | ||
type: TYPES.UDT | ||
}; | ||
}, | ||
Geography: function() { | ||
return { | ||
type: TYPES.Geography | ||
}; | ||
}, | ||
Geometry: function() { | ||
return { | ||
type: TYPES.Geometry | ||
}; | ||
} | ||
@@ -93,7 +185,14 @@ }; | ||
_fn = function(key, value) { | ||
return value.inspect = function() { | ||
return "[sql." + key + "]"; | ||
}; | ||
}; | ||
for (key in TYPES) { | ||
value = TYPES[key]; | ||
module.exports.DECLARATIONS[value.name] = value; | ||
value.declaration = key.toLowerCase(); | ||
module.exports.DECLARATIONS[value.declaration] = value; | ||
_fn(key, value); | ||
} | ||
}).call(this); |
@@ -1,2 +0,2 @@ | ||
// Generated by CoffeeScript 1.6.3 | ||
// Generated by CoffeeScript 1.7.1 | ||
(function() { | ||
@@ -3,0 +3,0 @@ module.exports = { |
343
lib/main.js
@@ -1,4 +0,4 @@ | ||
// Generated by CoffeeScript 1.6.3 | ||
// Generated by CoffeeScript 1.7.1 | ||
(function() { | ||
var Connection, ConnectionError, DRIVERS, EventEmitter, ISOLATION_LEVEL, Request, RequestError, TYPES, Transaction, TransactionError, getTypeByValue, global_connection, key, map, util, value, | ||
var Connection, ConnectionError, DRIVERS, EventEmitter, ISOLATION_LEVEL, Request, RequestError, TYPES, Table, Transaction, TransactionError, getTypeByValue, global_connection, key, map, util, value, | ||
__hasProp = {}.hasOwnProperty, | ||
@@ -18,2 +18,4 @@ __extends = 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; }, | ||
Table = require('./table'); | ||
global_connection = null; | ||
@@ -23,2 +25,3 @@ | ||
/* | ||
@@ -39,5 +42,4 @@ Register you own type map. | ||
@param {*} sqltype SQL data type. | ||
*/ | ||
*/ | ||
map.register = function(jstype, sqltype) { | ||
@@ -60,3 +62,3 @@ var index, item, _i, _len; | ||
map.register(String, TYPES.VarChar); | ||
map.register(String, TYPES.NVarChar); | ||
@@ -69,11 +71,15 @@ map.register(Number, TYPES.Int); | ||
map.register(Buffer, TYPES.VarBinary); | ||
map.register(Table, TYPES.TVP); | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
getTypeByValue = function(value) { | ||
var item, _i, _j, _k, _l, _len, _len1, _len2, _len3; | ||
if (value === null || value === void 0) { | ||
return TYPES.VarChar; | ||
return TYPES.NVarChar; | ||
} | ||
@@ -88,3 +94,3 @@ switch (typeof value) { | ||
} | ||
return TYPES.VarChar; | ||
return TYPES.NVarChar; | ||
case 'number': | ||
@@ -113,8 +119,9 @@ for (_j = 0, _len1 = map.length; _j < _len1; _j++) { | ||
} | ||
return TYPES.VarChar; | ||
return TYPES.NVarChar; | ||
default: | ||
return TYPES.VarChar; | ||
return TYPES.NVarChar; | ||
} | ||
}; | ||
/* | ||
@@ -129,5 +136,4 @@ Class Connection. | ||
@event close Dispatched after connection has closed a pool (by calling close). | ||
*/ | ||
*/ | ||
Connection = (function(_super) { | ||
@@ -142,2 +148,3 @@ __extends(Connection, _super); | ||
/* | ||
@@ -149,7 +156,6 @@ Create new Connection. | ||
@param {Error} err Error on error, otherwise null. | ||
*/ | ||
*/ | ||
function Connection(config, callback) { | ||
var err, _base, _base1, _ref; | ||
var err, _base, _base1, _base2, _ref; | ||
this.config = config; | ||
@@ -162,2 +168,9 @@ if ((_base = this.config).driver == null) { | ||
} | ||
if ((_base2 = this.config).options == null) { | ||
_base2.options = {}; | ||
} | ||
if (/^(.*)\\(.*)$/.exec(this.config.server)) { | ||
this.config.server = RegExp.$1; | ||
this.config.options.instanceName = RegExp.$2; | ||
} | ||
if (_ref = this.config.driver, __indexOf.call(DRIVERS, _ref) >= 0) { | ||
@@ -169,3 +182,3 @@ this.driver = this.initializeDriver(require("./" + this.config.driver)); | ||
} else { | ||
err = new ConnectionError("Unknown driver " + this.config.driver + "!"); | ||
err = new ConnectionError("Unknown driver " + this.config.driver + "!", 'EDRIVER'); | ||
if (callback) { | ||
@@ -182,2 +195,3 @@ callback(err); | ||
/* | ||
@@ -190,5 +204,4 @@ Initializes driver for this connection. Separated from constructor and used by co-mssql. | ||
@returns {Connection} | ||
*/ | ||
*/ | ||
Connection.prototype.initializeDriver = function(driver) { | ||
@@ -198,2 +211,3 @@ return driver(Connection, Transaction, Request, ConnectionError, TransactionError, RequestError); | ||
/* | ||
@@ -206,10 +220,8 @@ Create connection to the server. | ||
@returns {Connection} | ||
*/ | ||
*/ | ||
Connection.prototype.connect = function(callback) { | ||
var err, | ||
_this = this; | ||
var err; | ||
if (this.connected) { | ||
err = new ConnectionError("Database is already connected! Call close before connecting to different database."); | ||
err = new ConnectionError("Database is already connected! Call close before connecting to different database.", 'EALREADYCONNECTED'); | ||
if (callback) { | ||
@@ -222,3 +234,3 @@ callback(err); | ||
if (this.connecting) { | ||
err = new ConnectionError("Already connecting to database! Call close before connecting to different database."); | ||
err = new ConnectionError("Already connecting to database! Call close before connecting to different database.", 'EALREADYCONNECTING'); | ||
if (callback) { | ||
@@ -231,16 +243,19 @@ callback(err); | ||
this.connecting = true; | ||
this.driver.Connection.prototype.connect.call(this, this.config, function(err) { | ||
if (!_this.connecting) { | ||
return; | ||
} | ||
_this.connecting = false; | ||
if (!err) { | ||
_this.connected = true; | ||
_this.emit('connect'); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
}); | ||
this.driver.Connection.prototype.connect.call(this, this.config, (function(_this) { | ||
return function(err) { | ||
if (!_this.connecting) { | ||
return; | ||
} | ||
_this.connecting = false; | ||
if (!err) { | ||
_this.connected = true; | ||
_this.emit('connect'); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
}; | ||
})(this)); | ||
return this; | ||
}; | ||
/* | ||
@@ -253,22 +268,24 @@ Close connection to the server. | ||
@returns {Connection} | ||
*/ | ||
*/ | ||
Connection.prototype.close = function(callback) { | ||
var _this = this; | ||
if (this.connecting) { | ||
this.connecting = false; | ||
this.driver.Connection.prototype.close.call(this, function(err) { | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
}); | ||
this.driver.Connection.prototype.close.call(this, (function(_this) { | ||
return function(err) { | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
}; | ||
})(this)); | ||
this.driver = null; | ||
} else if (this.connected) { | ||
this.connected = false; | ||
this.driver.Connection.prototype.close.call(this, function(err) { | ||
if (!err) { | ||
_this.connected = false; | ||
_this.emit('close'); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
}); | ||
this.driver.Connection.prototype.close.call(this, (function(_this) { | ||
return function(err) { | ||
if (!err) { | ||
_this.connected = false; | ||
_this.emit('close'); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
}; | ||
})(this)); | ||
this.driver = null; | ||
@@ -279,2 +296,3 @@ } | ||
/* | ||
@@ -284,5 +302,4 @@ Returns new request using this connection. | ||
@returns {Request} | ||
*/ | ||
*/ | ||
Connection.prototype.request = function() { | ||
@@ -292,2 +309,3 @@ return new Request(this); | ||
/* | ||
@@ -297,5 +315,4 @@ Returns new transaction using this connection. | ||
@returns {Transaction} | ||
*/ | ||
*/ | ||
Connection.prototype.transaction = function() { | ||
@@ -309,2 +326,3 @@ return new Transaction(this); | ||
/* | ||
@@ -320,5 +338,4 @@ Class Transaction. | ||
@event rollback Dispatched on successful rollback. | ||
*/ | ||
*/ | ||
Transaction = (function(_super) { | ||
@@ -337,2 +354,3 @@ __extends(Transaction, _super); | ||
/* | ||
@@ -342,5 +360,4 @@ Create new Transaction. | ||
@param {Connection} connection If ommited, global connection is used instead. | ||
*/ | ||
*/ | ||
function Transaction(connection) { | ||
@@ -351,2 +368,3 @@ this.connection = connection != null ? connection : global_connection; | ||
/* | ||
@@ -359,7 +377,5 @@ Begin a transaction. | ||
@returns {Transaction} | ||
*/ | ||
*/ | ||
Transaction.prototype.begin = function(isolationLevel, callback) { | ||
var _this = this; | ||
if (isolationLevel instanceof Function) { | ||
@@ -378,11 +394,14 @@ callback = isolationLevel; | ||
} | ||
this.connection.driver.Transaction.prototype.begin.call(this, function(err) { | ||
if (!err) { | ||
_this.emit('begin'); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
}); | ||
this.connection.driver.Transaction.prototype.begin.call(this, (function(_this) { | ||
return function(err) { | ||
if (!err) { | ||
_this.emit('begin'); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
}; | ||
})(this)); | ||
return this; | ||
}; | ||
/* | ||
@@ -394,7 +413,5 @@ Commit a transaction. | ||
@returns {Transaction} | ||
*/ | ||
*/ | ||
Transaction.prototype.commit = function(callback) { | ||
var _this = this; | ||
if (!this._pooledConnection) { | ||
@@ -406,11 +423,14 @@ if (typeof callback === "function") { | ||
} | ||
this.connection.driver.Transaction.prototype.commit.call(this, function(err) { | ||
if (!err) { | ||
_this.emit('commit'); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
}); | ||
this.connection.driver.Transaction.prototype.commit.call(this, (function(_this) { | ||
return function(err) { | ||
if (!err) { | ||
_this.emit('commit'); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
}; | ||
})(this)); | ||
return this; | ||
}; | ||
/* | ||
@@ -421,5 +441,4 @@ Execute next request in queue. | ||
@returns {Transaction} | ||
*/ | ||
*/ | ||
Transaction.prototype.next = function() { | ||
@@ -433,2 +452,3 @@ if (this._queue.length) { | ||
/* | ||
@@ -442,5 +462,4 @@ Add request to queue for connection. If queue is empty, execute the request immediately. | ||
@returns {Transaction} | ||
*/ | ||
*/ | ||
Transaction.prototype.queue = function(callback) { | ||
@@ -459,2 +478,3 @@ if (!this._pooledConnection) { | ||
/* | ||
@@ -464,5 +484,4 @@ Returns new request using this transaction. | ||
@returns {Request} | ||
*/ | ||
*/ | ||
Transaction.prototype.request = function() { | ||
@@ -472,2 +491,3 @@ return new Request(this); | ||
/* | ||
@@ -479,7 +499,5 @@ Rollback a transaction. | ||
@returns {Transaction} | ||
*/ | ||
*/ | ||
Transaction.prototype.rollback = function(callback) { | ||
var _this = this; | ||
if (!this._pooledConnection) { | ||
@@ -491,8 +509,10 @@ if (typeof callback === "function") { | ||
} | ||
this.connection.driver.Transaction.prototype.rollback.call(this, function(err) { | ||
if (!err) { | ||
_this.emit('rollback'); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
}); | ||
this.connection.driver.Transaction.prototype.rollback.call(this, (function(_this) { | ||
return function(err) { | ||
if (!err) { | ||
_this.emit('rollback'); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
}; | ||
})(this)); | ||
return this; | ||
@@ -505,2 +525,3 @@ }; | ||
/* | ||
@@ -514,2 +535,3 @@ Class Request. | ||
@property {Boolean} multiple If `true`, `query` will handle multiple recordsets (`execute` always expect multiple recordsets). | ||
@property {Boolean} canceled `true` if request was canceled. | ||
@@ -519,5 +541,4 @@ @event recordset Dispatched when new recordset is parsed (with all rows). | ||
@event done Dispatched when request is complete. | ||
*/ | ||
*/ | ||
Request = (function(_super) { | ||
@@ -536,2 +557,5 @@ __extends(Request, _super); | ||
Request.prototype.canceled = false; | ||
/* | ||
@@ -541,5 +565,4 @@ Create new Request. | ||
@param {Connection|Transaction} connection If ommited, global connection is used instead. | ||
*/ | ||
*/ | ||
function Request(connection) { | ||
@@ -557,7 +580,7 @@ if (connection instanceof Transaction) { | ||
/* | ||
Acquire connection for this request from connection. | ||
*/ | ||
*/ | ||
Request.prototype._acquire = function(callback) { | ||
@@ -567,7 +590,7 @@ return this.connection.driver.Request.prototype._acquire.call(this, callback); | ||
/* | ||
Release connection used by this request. | ||
*/ | ||
*/ | ||
Request.prototype._release = function(connection) { | ||
@@ -577,2 +600,3 @@ return this.connection.driver.Request.prototype._release.call(this, connection); | ||
/* | ||
@@ -591,8 +615,7 @@ Add an input parameter to the request. | ||
@returns {Request} | ||
*/ | ||
*/ | ||
Request.prototype.input = function(name, type, value) { | ||
if (arguments.length === 1) { | ||
throw new RequestError("Invalid number of arguments. At least 2 arguments expected."); | ||
throw new RequestError("Invalid number of arguments. At least 2 arguments expected.", 'EARGS'); | ||
} else if (arguments.length === 2) { | ||
@@ -611,7 +634,13 @@ value = type; | ||
} | ||
if (type instanceof Function) { | ||
type = type(); | ||
} | ||
this.parameters[name] = { | ||
name: name, | ||
type: type, | ||
type: type.type, | ||
io: 1, | ||
value: value | ||
value: value, | ||
length: type.length, | ||
scale: type.scale, | ||
precision: type.precision | ||
}; | ||
@@ -621,2 +650,3 @@ return this; | ||
/* | ||
@@ -628,2 +658,3 @@ Add an output parameter to the request. | ||
request.output('output_parameter', sql.Int); | ||
request.output('output_parameter', sql.VarChar(50), 'abc'); | ||
``` | ||
@@ -633,19 +664,33 @@ | ||
@param {*} type SQL data type of output parameter. | ||
@param {Number} [length] Expected length. | ||
@param {*} [value] Output parameter value initial value. `undefined` and `NaN` values are automatically converted to `null` values. Optional. | ||
@returns {Request} | ||
*/ | ||
*/ | ||
Request.prototype.output = function(name, type, length) { | ||
Request.prototype.output = function(name, type, value) { | ||
if (!type) { | ||
type = TYPES.VarChar; | ||
type = TYPES.NVarChar; | ||
} | ||
if (type === TYPES.Text || type === TYPES.NText || type === TYPES.Image) { | ||
throw new RequestError("Deprecated types (Text, NText, Image) are not supported as OUTPUT parameters."); | ||
throw new RequestError("Deprecated types (Text, NText, Image) are not supported as OUTPUT parameters.", 'EDEPRECATED'); | ||
} | ||
if ((value != null ? value.valueOf : void 0) && !(value instanceof Date)) { | ||
value = value.valueOf(); | ||
} | ||
if (value === void 0) { | ||
value = null; | ||
} | ||
if (value !== value) { | ||
value = null; | ||
} | ||
if (type instanceof Function) { | ||
type = type(); | ||
} | ||
this.parameters[name] = { | ||
name: name, | ||
type: type, | ||
type: type.type, | ||
io: 2, | ||
length: length | ||
value: value, | ||
length: type.length, | ||
scale: type.scale, | ||
precision: type.precision | ||
}; | ||
@@ -655,2 +700,3 @@ return this; | ||
/* | ||
@@ -689,21 +735,23 @@ Execute the SQL command. | ||
@returns {Request} | ||
*/ | ||
*/ | ||
Request.prototype.query = function(command, callback) { | ||
var _this = this; | ||
if (!this.connection) { | ||
return process.nextTick(function() { | ||
return typeof callback === "function" ? callback(new RequestError("No connection is specified for that request.")) : void 0; | ||
return typeof callback === "function" ? callback(new RequestError("No connection is specified for that request.", 'ENOCONN')) : void 0; | ||
}); | ||
} | ||
this.connection.driver.Request.prototype.query.call(this, command, function(err, recordset) { | ||
if (!err) { | ||
_this.emit('done', err, recordset); | ||
} | ||
return typeof callback === "function" ? callback(err, recordset) : void 0; | ||
}); | ||
this.canceled = false; | ||
this.connection.driver.Request.prototype.query.call(this, command, (function(_this) { | ||
return function(err, recordset) { | ||
if (!err) { | ||
_this.emit('done', err, recordset); | ||
} | ||
return typeof callback === "function" ? callback(err, recordset) : void 0; | ||
}; | ||
})(this)); | ||
return this; | ||
}; | ||
/* | ||
@@ -736,19 +784,21 @@ Call a stored procedure. | ||
@returns {Request} | ||
*/ | ||
*/ | ||
Request.prototype.execute = function(procedure, callback) { | ||
var _this = this; | ||
if (!this.connection) { | ||
return process.nextTick(function() { | ||
return typeof callback === "function" ? callback(new RequestError("No connection is specified for that request.")) : void 0; | ||
return typeof callback === "function" ? callback(new RequestError("No connection is specified for that request.", 'ENOCONN')) : void 0; | ||
}); | ||
} | ||
this.connection.driver.Request.prototype.execute.call(this, procedure, function(err, recordsets, returnValue) { | ||
_this.emit('done', err, recordsets); | ||
return typeof callback === "function" ? callback(err, recordsets, returnValue) : void 0; | ||
}); | ||
this.canceled = false; | ||
this.connection.driver.Request.prototype.execute.call(this, procedure, (function(_this) { | ||
return function(err, recordsets, returnValue) { | ||
_this.emit('done', err, recordsets); | ||
return typeof callback === "function" ? callback(err, recordsets, returnValue) : void 0; | ||
}; | ||
})(this)); | ||
return this; | ||
}; | ||
/* | ||
@@ -758,6 +808,6 @@ Cancel currently executed request. | ||
@returns {Request} | ||
*/ | ||
*/ | ||
Request.prototype.cancel = function() { | ||
this.canceled = true; | ||
this.connection.driver.Request.prototype.cancel.call(this); | ||
@@ -774,7 +824,7 @@ return this; | ||
function ConnectionError(message) { | ||
function ConnectionError(message, code) { | ||
var err; | ||
if (!(this instanceof ConnectionError)) { | ||
if (message instanceof Error) { | ||
err = new ConnectionError(message.message); | ||
err = new ConnectionError(message.message, message.code); | ||
err.originalError = message; | ||
@@ -791,2 +841,3 @@ Error.captureStackTrace(err, arguments.callee); | ||
this.message = message; | ||
this.code = code; | ||
ConnectionError.__super__.constructor.call(this); | ||
@@ -803,7 +854,7 @@ Error.captureStackTrace(this, this.constructor); | ||
function TransactionError(message) { | ||
function TransactionError(message, code) { | ||
var err; | ||
if (!(this instanceof TransactionError)) { | ||
if (message instanceof Error) { | ||
err = new TransactionError(message.message); | ||
err = new TransactionError(message.message, message.code); | ||
err.originalError = message; | ||
@@ -820,2 +871,3 @@ Error.captureStackTrace(err, arguments.callee); | ||
this.message = message; | ||
this.code = code; | ||
TransactionError.__super__.constructor.call(this); | ||
@@ -832,7 +884,7 @@ Error.captureStackTrace(this, this.constructor); | ||
function RequestError(message) { | ||
function RequestError(message, code) { | ||
var err; | ||
if (!(this instanceof RequestError)) { | ||
if (message instanceof Error) { | ||
err = new RequestError(message.message); | ||
err = new RequestError(message.message, message.code); | ||
err.originalError = message; | ||
@@ -849,2 +901,3 @@ Error.captureStackTrace(err, arguments.callee); | ||
this.message = message; | ||
this.code = code; | ||
RequestError.__super__.constructor.call(this); | ||
@@ -858,2 +911,3 @@ Error.captureStackTrace(this, this.constructor); | ||
/* | ||
@@ -867,5 +921,4 @@ Open global connection. | ||
@returns {Connection} | ||
*/ | ||
*/ | ||
module.exports.connect = function(config, callback) { | ||
@@ -876,2 +929,3 @@ global_connection = new Connection(config); | ||
/* | ||
@@ -881,5 +935,4 @@ Close global connection. | ||
@returns {Connection} | ||
*/ | ||
*/ | ||
module.exports.close = function(callback) { | ||
@@ -895,2 +948,4 @@ return global_connection != null ? global_connection.close(callback) : void 0; | ||
module.exports.Table = Table; | ||
module.exports.ConnectionError = ConnectionError; | ||
@@ -908,2 +963,4 @@ | ||
module.exports.MAX = 65535; | ||
module.exports.map = map; | ||
@@ -931,2 +988,3 @@ | ||
/* | ||
@@ -936,5 +994,4 @@ Initialize Tedious connection pool. | ||
@deprecated | ||
*/ | ||
*/ | ||
module.exports.init = function() { | ||
@@ -941,0 +998,0 @@ return module.exports.connect({ |
@@ -1,4 +0,4 @@ | ||
// Generated by CoffeeScript 1.6.3 | ||
// Generated by CoffeeScript 1.7.1 | ||
(function() { | ||
var DECLARATIONS, EMPTY_BUFFER, ISOLATION_LEVEL, Pool, TYPES, castParameter, createColumns, isolationLevelDeclaration, msnodesql, typeDeclaration, util, | ||
var CONNECTION_STRING_NAMED_INSTANCE, CONNECTION_STRING_PORT, DECLARATIONS, EMPTY_BUFFER, ISOLATION_LEVEL, Pool, TYPES, UDT, castParameter, createColumns, isolationLevelDeclaration, msnodesql, typeDeclaration, util, valueCorrection, | ||
__hasProp = {}.hasOwnProperty, | ||
@@ -15,2 +15,4 @@ __extends = 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; }; | ||
UDT = require('./udt').PARSERS; | ||
ISOLATION_LEVEL = require('./isolationlevel'); | ||
@@ -22,7 +24,11 @@ | ||
CONNECTION_STRING_PORT = 'Driver={SQL Server Native Client 11.0};Server={#{server},#{port}};Database={#{database}};Uid={#{user}};Pwd={#{password}};Trusted_Connection={#{trusted}};'; | ||
CONNECTION_STRING_NAMED_INSTANCE = 'Driver={SQL Server Native Client 11.0};Server={#{server}\\#{instance}};Database={#{database}};Uid={#{user}};Pwd={#{password}};Trusted_Connection={#{trusted}};'; | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
castParameter = function(value, type) { | ||
@@ -94,7 +100,7 @@ if (value == null) { | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
createColumns = function(meta) { | ||
@@ -107,5 +113,13 @@ var out, value, _i, _len; | ||
name: value.name, | ||
size: value.size, | ||
length: value.size, | ||
type: DECLARATIONS[value.sqlType] | ||
}; | ||
if (value.udtType != null) { | ||
out[value.name].udt = { | ||
name: value.udtType | ||
}; | ||
if (DECLARATIONS[value.udtType]) { | ||
out[value.name].type = DECLARATIONS[value.udtType]; | ||
} | ||
} | ||
} | ||
@@ -115,8 +129,9 @@ return out; | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
typeDeclaration = function(type, length) { | ||
typeDeclaration = function(type, options) { | ||
var _ref, _ref1; | ||
switch (type) { | ||
@@ -126,17 +141,21 @@ case TYPES.VarChar: | ||
case TYPES.VarBinary: | ||
return "" + type.name + " (MAX)"; | ||
return "" + type.declaration + " (MAX)"; | ||
case TYPES.Char: | ||
case TYPES.NChar: | ||
case TYPES.Binary: | ||
return "" + type.name + " (" + (length != null ? length : 1) + ")"; | ||
return "" + type.declaration + " (" + ((_ref = options.length) != null ? _ref : 1) + ")"; | ||
case TYPES.Time: | ||
case TYPES.DateTime2: | ||
case TYPES.DateTimeOffset: | ||
return "" + type.declaration + " (" + ((_ref1 = options.scale) != null ? _ref1 : 7) + ")"; | ||
default: | ||
return type.name; | ||
return type.declaration; | ||
} | ||
}; | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
isolationLevelDeclaration = function(type) { | ||
@@ -159,9 +178,29 @@ switch (type) { | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
valueCorrection = function(value, metadata) { | ||
if (metadata.sqlType === 'time' && (value != null)) { | ||
value.setFullYear(1970); | ||
return value; | ||
} else if (metadata.sqlType === 'udt' && (value != null)) { | ||
if (UDT[metadata.udtType]) { | ||
return UDT[metadata.udtType](value); | ||
} else { | ||
return value; | ||
} | ||
} else { | ||
return value; | ||
} | ||
}; | ||
/* | ||
@ignore | ||
*/ | ||
module.exports = function(Connection, Transaction, Request, ConnectionError, TransactionError, RequestError) { | ||
var MsnodesqlConnection, MsnodesqlRequest, MsnodesqlTransaction, _ref, _ref1, _ref2; | ||
var MsnodesqlConnection, MsnodesqlRequest, MsnodesqlTransaction; | ||
MsnodesqlConnection = (function(_super) { | ||
@@ -171,4 +210,3 @@ __extends(MsnodesqlConnection, _super); | ||
function MsnodesqlConnection() { | ||
_ref = MsnodesqlConnection.__super__.constructor.apply(this, arguments); | ||
return _ref; | ||
return MsnodesqlConnection.__super__.constructor.apply(this, arguments); | ||
} | ||
@@ -179,14 +217,23 @@ | ||
MsnodesqlConnection.prototype.connect = function(config, callback) { | ||
var cfg, cfg_pool, key, value, _ref1, _ref2, | ||
_this = this; | ||
var cfg, cfg_pool, defaultConnectionString, key, value, _ref, _ref1; | ||
defaultConnectionString = CONNECTION_STRING_PORT; | ||
if (config.options.instanceName != null) { | ||
defaultConnectionString = CONNECTION_STRING_NAMED_INSTANCE; | ||
} | ||
cfg = { | ||
connectionString: (_ref1 = config.connectionString) != null ? _ref1 : 'Driver={SQL Server Native Client 11.0};Server=#{server},#{port};Database=#{database};Uid=#{user};Pwd=#{password};Connection Timeout=#{timeout};' | ||
connectionString: (_ref = config.connectionString) != null ? _ref : defaultConnectionString | ||
}; | ||
cfg.connectionString = cfg.connectionString.replace(new RegExp('#{([^}]*)}', 'g'), function(p) { | ||
var key, _ref2, _ref3; | ||
var key, _ref1; | ||
key = p.substr(2, p.length - 3); | ||
if (key === 'timeout') { | ||
return Math.ceil(((_ref2 = config.timeout) != null ? _ref2 : 15000) / 1000); | ||
if (key === 'instance') { | ||
return config.options.instanceName; | ||
} else if (key === 'trusted') { | ||
if (config.options.trustedConnection) { | ||
return 'Yes'; | ||
} else { | ||
return 'No'; | ||
} | ||
} else { | ||
return (_ref3 = config[key]) != null ? _ref3 : ''; | ||
return (_ref1 = config[key]) != null ? _ref1 : ''; | ||
} | ||
@@ -199,13 +246,15 @@ }); | ||
idleTimeoutMillis: 30000, | ||
create: function(callback) { | ||
return msnodesql.open(cfg.connectionString, function(err, c) { | ||
if (err) { | ||
err = ConnectionError(err); | ||
} | ||
if (err) { | ||
return callback(err, null); | ||
} | ||
return callback(null, c); | ||
}); | ||
}, | ||
create: (function(_this) { | ||
return function(callback) { | ||
return msnodesql.open(cfg.connectionString, function(err, c) { | ||
if (err) { | ||
err = ConnectionError(err); | ||
} | ||
if (err) { | ||
return callback(err, null); | ||
} | ||
return callback(null, c); | ||
}); | ||
}; | ||
})(this), | ||
validate: function(c) { | ||
@@ -219,5 +268,5 @@ return c != null; | ||
if (config.pool) { | ||
_ref2 = config.pool; | ||
for (key in _ref2) { | ||
value = _ref2[key]; | ||
_ref1 = config.pool; | ||
for (key in _ref1) { | ||
value = _ref1[key]; | ||
cfg_pool[key] = value; | ||
@@ -227,21 +276,24 @@ } | ||
this.pool = Pool(cfg_pool, cfg); | ||
return this.pool.acquire(function(err, connection) { | ||
if (err && !(err instanceof Error)) { | ||
err = new Error(err); | ||
} | ||
_this.pool.release(connection); | ||
return callback(err); | ||
}); | ||
return this.pool.acquire((function(_this) { | ||
return function(err, connection) { | ||
if (err && !(err instanceof Error)) { | ||
err = new Error(err); | ||
} | ||
_this.pool.release(connection); | ||
return callback(err); | ||
}; | ||
})(this)); | ||
}; | ||
MsnodesqlConnection.prototype.close = function(callback) { | ||
var _this = this; | ||
if (!this.pool) { | ||
return callback(null); | ||
} | ||
return this.pool.drain(function() { | ||
_this.pool.destroyAllNow(); | ||
_this.pool = null; | ||
return callback(null); | ||
}); | ||
return this.pool.drain((function(_this) { | ||
return function() { | ||
_this.pool.destroyAllNow(); | ||
_this.pool = null; | ||
return callback(null); | ||
}; | ||
})(this)); | ||
}; | ||
@@ -256,33 +308,35 @@ | ||
function MsnodesqlTransaction() { | ||
_ref1 = MsnodesqlTransaction.__super__.constructor.apply(this, arguments); | ||
return _ref1; | ||
return MsnodesqlTransaction.__super__.constructor.apply(this, arguments); | ||
} | ||
MsnodesqlTransaction.prototype.begin = function(callback) { | ||
var _this = this; | ||
return this.connection.pool.acquire(function(err, connection) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
_this._pooledConnection = connection; | ||
return _this.request().query("begin tran; set transaction isolation level " + (isolationLevelDeclaration(_this.isolationLevel)) + ";", callback); | ||
}); | ||
return this.connection.pool.acquire((function(_this) { | ||
return function(err, connection) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
_this._pooledConnection = connection; | ||
return _this.request().query("set transaction isolation level " + (isolationLevelDeclaration(_this.isolationLevel)) + ";begin tran;", callback); | ||
}; | ||
})(this)); | ||
}; | ||
MsnodesqlTransaction.prototype.commit = function(callback) { | ||
var _this = this; | ||
return this.request().query('commit tran', function(err) { | ||
_this.connection.pool.release(_this._pooledConnection); | ||
_this._pooledConnection = null; | ||
return callback(err); | ||
}); | ||
return this.request().query('commit tran', (function(_this) { | ||
return function(err) { | ||
_this.connection.pool.release(_this._pooledConnection); | ||
_this._pooledConnection = null; | ||
return callback(err); | ||
}; | ||
})(this)); | ||
}; | ||
MsnodesqlTransaction.prototype.rollback = function(callback) { | ||
var _this = this; | ||
return this.request().query('rollback tran', function(err) { | ||
_this.connection.pool.release(_this._pooledConnection); | ||
_this._pooledConnection = null; | ||
return callback(err); | ||
}); | ||
return this.request().query('rollback tran', (function(_this) { | ||
return function(err) { | ||
_this.connection.pool.release(_this._pooledConnection); | ||
_this._pooledConnection = null; | ||
return callback(err); | ||
}; | ||
})(this)); | ||
}; | ||
@@ -297,4 +351,3 @@ | ||
function MsnodesqlRequest() { | ||
_ref2 = MsnodesqlRequest.__super__.constructor.apply(this, arguments); | ||
return _ref2; | ||
return MsnodesqlRequest.__super__.constructor.apply(this, arguments); | ||
} | ||
@@ -321,4 +374,3 @@ | ||
MsnodesqlRequest.prototype.query = function(command, callback) { | ||
var columns, handleOutput, input, name, output, param, recordset, recordsets, row, sets, started, | ||
_this = this; | ||
var columns, handleOutput, input, name, output, param, recordset, recordsets, row, sets, started; | ||
if (this.verbose && !this.nested) { | ||
@@ -347,8 +399,8 @@ console.log("---------- sql query ----------\n query: " + command); | ||
input = (function() { | ||
var _ref3, _results; | ||
_ref3 = this.parameters; | ||
var _ref, _results; | ||
_ref = this.parameters; | ||
_results = []; | ||
for (name in _ref3) { | ||
param = _ref3[name]; | ||
_results.push("@" + param.name + " " + (typeDeclaration(param.type, param.length))); | ||
for (name in _ref) { | ||
param = _ref[name]; | ||
_results.push("@" + param.name + " " + (typeDeclaration(param.type, param))); | ||
} | ||
@@ -358,7 +410,7 @@ return _results; | ||
sets = (function() { | ||
var _ref3, _results; | ||
_ref3 = this.parameters; | ||
var _ref, _results; | ||
_ref = this.parameters; | ||
_results = []; | ||
for (name in _ref3) { | ||
param = _ref3[name]; | ||
for (name in _ref) { | ||
param = _ref[name]; | ||
if (param.io === 1) { | ||
@@ -371,7 +423,7 @@ _results.push("set @" + param.name + "=?"); | ||
output = (function() { | ||
var _ref3, _results; | ||
_ref3 = this.parameters; | ||
var _ref, _results; | ||
_ref = this.parameters; | ||
_results = []; | ||
for (name in _ref3) { | ||
param = _ref3[name]; | ||
for (name in _ref) { | ||
param = _ref[name]; | ||
if (param.io === 2) { | ||
@@ -391,125 +443,127 @@ _results.push("@" + param.name + " as '" + param.name + "'"); | ||
} | ||
return this._acquire(function(err, connection) { | ||
var req; | ||
if (!err) { | ||
req = connection.queryRaw(command, (function() { | ||
var _ref3, _results; | ||
_ref3 = this.parameters; | ||
_results = []; | ||
for (name in _ref3) { | ||
param = _ref3[name]; | ||
if (param.io === 1) { | ||
_results.push(castParameter(param.value, param.type)); | ||
return this._acquire((function(_this) { | ||
return function(err, connection) { | ||
var req; | ||
if (!err) { | ||
req = connection.queryRaw(command, (function() { | ||
var _ref, _results; | ||
_ref = this.parameters; | ||
_results = []; | ||
for (name in _ref) { | ||
param = _ref[name]; | ||
if (param.io === 1) { | ||
_results.push(castParameter(param.value, param.type)); | ||
} | ||
} | ||
return _results; | ||
}).call(_this)); | ||
if (_this.verbose && !_this.nested) { | ||
console.log("---------- response -----------"); | ||
} | ||
return _results; | ||
}).call(_this)); | ||
if (_this.verbose && !_this.nested) { | ||
console.log("---------- response -----------"); | ||
} | ||
req.on('meta', function(metadata) { | ||
if (row) { | ||
if (_this.verbose) { | ||
console.log(util.inspect(row)); | ||
console.log("---------- --------------------"); | ||
req.on('meta', function(metadata) { | ||
if (row) { | ||
if (_this.verbose) { | ||
console.log(util.inspect(row)); | ||
console.log("---------- --------------------"); | ||
} | ||
if (row["___return___"] == null) { | ||
_this.emit('row', row); | ||
} | ||
} | ||
if (row["___return___"] == null) { | ||
_this.emit('row', row); | ||
} | ||
} | ||
if (recordset) { | ||
_this.emit('recordset', recordset); | ||
} | ||
row = null; | ||
columns = metadata; | ||
recordset = []; | ||
Object.defineProperty(recordset, 'columns', { | ||
enumerable: false, | ||
value: createColumns(metadata) | ||
}); | ||
return recordsets.push(recordset); | ||
}); | ||
req.on('row', function(rownumber) { | ||
if (row) { | ||
if (_this.verbose) { | ||
console.log(util.inspect(row)); | ||
console.log("---------- --------------------"); | ||
} | ||
if (row["___return___"] == null) { | ||
_this.emit('row', row); | ||
} | ||
} | ||
row = {}; | ||
return recordset.push(row); | ||
}); | ||
req.on('column', function(idx, data, more) { | ||
var exi; | ||
exi = row[columns[idx].name]; | ||
if (exi != null) { | ||
if (exi instanceof Array) { | ||
return exi.push(data); | ||
} else { | ||
return row[columns[idx].name] = [exi, data]; | ||
} | ||
} else { | ||
return row[columns[idx].name] = data; | ||
} | ||
}); | ||
req.once('error', function(err) { | ||
var elapsed; | ||
if (_this.verbose && !_this.nested) { | ||
elapsed = Date.now() - started; | ||
console.log(" error: " + err); | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
return typeof callback === "function" ? callback(RequestError(err)) : void 0; | ||
}); | ||
return req.once('done', function() { | ||
var elapsed, last, _ref3, _ref4; | ||
if (!_this.nested) { | ||
if (recordset) { | ||
_this.emit('recordset', recordset); | ||
} | ||
if (_this.verbose) { | ||
if (row) { | ||
row = null; | ||
columns = metadata; | ||
recordset = []; | ||
Object.defineProperty(recordset, 'columns', { | ||
enumerable: false, | ||
value: createColumns(metadata) | ||
}); | ||
return recordsets.push(recordset); | ||
}); | ||
req.on('row', function(rownumber) { | ||
if (row) { | ||
if (_this.verbose) { | ||
console.log(util.inspect(row)); | ||
console.log("---------- --------------------"); | ||
} | ||
if (row["___return___"] == null) { | ||
_this.emit('row', row); | ||
} | ||
} | ||
if (handleOutput) { | ||
last = (_ref3 = recordsets.pop()) != null ? _ref3[0] : void 0; | ||
_ref4 = _this.parameters; | ||
for (name in _ref4) { | ||
param = _ref4[name]; | ||
if (!(param.io === 2)) { | ||
continue; | ||
} | ||
param.value = last[param.name]; | ||
if (_this.verbose) { | ||
console.log(" output: @" + param.name + ", " + param.type.name + ", " + param.value); | ||
} | ||
row = {}; | ||
return recordset.push(row); | ||
}); | ||
req.on('column', function(idx, data, more) { | ||
var exi; | ||
data = valueCorrection(data, columns[idx]); | ||
exi = row[columns[idx].name]; | ||
if (exi != null) { | ||
if (exi instanceof Array) { | ||
return exi.push(data); | ||
} else { | ||
return row[columns[idx].name] = [exi, data]; | ||
} | ||
} else { | ||
return row[columns[idx].name] = data; | ||
} | ||
if (_this.verbose) { | ||
}); | ||
req.once('error', function(err) { | ||
var elapsed; | ||
if (_this.verbose && !_this.nested) { | ||
elapsed = Date.now() - started; | ||
console.log(" error: " + err); | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
return typeof callback === "function" ? callback(RequestError(err)) : void 0; | ||
}); | ||
return req.once('done', function() { | ||
var elapsed, last, _ref, _ref1; | ||
if (!_this.nested) { | ||
if (recordset) { | ||
_this.emit('recordset', recordset); | ||
} | ||
if (_this.verbose) { | ||
if (row) { | ||
console.log(util.inspect(row)); | ||
console.log("---------- --------------------"); | ||
} | ||
} | ||
if (handleOutput) { | ||
last = (_ref = recordsets.pop()) != null ? _ref[0] : void 0; | ||
_ref1 = _this.parameters; | ||
for (name in _ref1) { | ||
param = _ref1[name]; | ||
if (!(param.io === 2)) { | ||
continue; | ||
} | ||
param.value = last[param.name]; | ||
if (_this.verbose) { | ||
console.log(" output: @" + param.name + ", " + param.type.declaration + ", " + param.value); | ||
} | ||
} | ||
} | ||
if (_this.verbose) { | ||
elapsed = Date.now() - started; | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
} | ||
_this._release(connection); | ||
return typeof callback === "function" ? callback(null, _this.multiple || _this.nested ? recordsets : recordsets[0]) : void 0; | ||
}); | ||
} else { | ||
if (connection) { | ||
_this._release(connection); | ||
} | ||
_this._release(connection); | ||
return typeof callback === "function" ? callback(null, _this.multiple || _this.nested ? recordsets : recordsets[0]) : void 0; | ||
}); | ||
} else { | ||
if (connection) { | ||
_this._release(connection); | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
} | ||
}); | ||
}; | ||
})(this)); | ||
}; | ||
MsnodesqlRequest.prototype.execute = function(procedure, callback) { | ||
var cmd, name, param, spp, started, _ref3, | ||
_this = this; | ||
var cmd, name, param, spp, started, _ref; | ||
if (this.verbose) { | ||
@@ -520,9 +574,9 @@ console.log("---------- sql execute --------\n proc: " + procedure); | ||
cmd = "declare " + (['@___return___ int'].concat((function() { | ||
var _ref3, _results; | ||
_ref3 = this.parameters; | ||
var _ref, _results; | ||
_ref = this.parameters; | ||
_results = []; | ||
for (name in _ref3) { | ||
param = _ref3[name]; | ||
for (name in _ref) { | ||
param = _ref[name]; | ||
if (param.io === 2) { | ||
_results.push("@" + param.name + " " + (typeDeclaration(param.type, param.length))); | ||
_results.push("@" + param.name + " " + (typeDeclaration(param.type, param))); | ||
} | ||
@@ -534,5 +588,5 @@ } | ||
spp = []; | ||
_ref3 = this.parameters; | ||
for (name in _ref3) { | ||
param = _ref3[name]; | ||
_ref = this.parameters; | ||
for (name in _ref) { | ||
param = _ref[name]; | ||
if (param.io === 2) { | ||
@@ -542,3 +596,3 @@ spp.push("@" + param.name + "=@" + param.name + " output"); | ||
if (this.verbose) { | ||
console.log(" input: @" + param.name + ", " + param.type.name + ", " + param.value); | ||
console.log(" input: @" + param.name + ", " + param.type.declaration + ", " + param.value); | ||
} | ||
@@ -550,7 +604,7 @@ spp.push("@" + param.name + "=?"); | ||
cmd += "select " + (['@___return___ as \'___return___\''].concat((function() { | ||
var _ref4, _results; | ||
_ref4 = this.parameters; | ||
var _ref1, _results; | ||
_ref1 = this.parameters; | ||
_results = []; | ||
for (name in _ref4) { | ||
param = _ref4[name]; | ||
for (name in _ref1) { | ||
param = _ref1[name]; | ||
if (param.io === 2) { | ||
@@ -566,47 +620,50 @@ _results.push("@" + param.name + " as '" + param.name + "'"); | ||
this.nested = true; | ||
return MsnodesqlRequest.prototype.query.call(this, cmd, function(err, recordsets) { | ||
var elapsed, last, returnValue, _ref4, _ref5; | ||
_this.nested = false; | ||
if (err) { | ||
if (_this.verbose) { | ||
elapsed = Date.now() - started; | ||
console.log(" error: " + err); | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
} else { | ||
last = (_ref4 = recordsets.pop()) != null ? _ref4[0] : void 0; | ||
if (last && (last.___return___ != null)) { | ||
returnValue = last.___return___; | ||
_ref5 = _this.parameters; | ||
for (name in _ref5) { | ||
param = _ref5[name]; | ||
if (!(param.io === 2)) { | ||
continue; | ||
return MsnodesqlRequest.prototype.query.call(this, cmd, (function(_this) { | ||
return function(err, recordsets) { | ||
var elapsed, last, returnValue, _ref1, _ref2; | ||
_this.nested = false; | ||
if (err) { | ||
if (_this.verbose) { | ||
elapsed = Date.now() - started; | ||
console.log(" error: " + err); | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
} else { | ||
last = (_ref1 = recordsets.pop()) != null ? _ref1[0] : void 0; | ||
if (last && (last.___return___ != null)) { | ||
returnValue = last.___return___; | ||
_ref2 = _this.parameters; | ||
for (name in _ref2) { | ||
param = _ref2[name]; | ||
if (!(param.io === 2)) { | ||
continue; | ||
} | ||
param.value = last[param.name]; | ||
if (_this.verbose) { | ||
console.log(" output: @" + param.name + ", " + param.type.declaration + ", " + param.value); | ||
} | ||
} | ||
param.value = last[param.name]; | ||
if (_this.verbose) { | ||
console.log(" output: @" + param.name + ", " + param.type.name + ", " + param.value); | ||
} | ||
} | ||
if (_this.verbose) { | ||
elapsed = Date.now() - started; | ||
console.log(" return: " + returnValue); | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
recordsets.returnValue = returnValue; | ||
return typeof callback === "function" ? callback(null, recordsets, returnValue) : void 0; | ||
} | ||
if (_this.verbose) { | ||
elapsed = Date.now() - started; | ||
console.log(" return: " + returnValue); | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
recordsets.returnValue = returnValue; | ||
return typeof callback === "function" ? callback(null, recordsets, returnValue) : void 0; | ||
} | ||
}); | ||
}; | ||
})(this)); | ||
}; | ||
/* | ||
Cancel currently executed request. | ||
*/ | ||
MsnodesqlRequest.prototype.cancel = function() { | ||
/* | ||
Cancel currently executed request. | ||
*/ | ||
throw new Error("Request canceling is not implemented by msnodesql driver."); | ||
return false; | ||
}; | ||
@@ -613,0 +670,0 @@ |
@@ -1,2 +0,2 @@ | ||
// Generated by CoffeeScript 1.6.3 | ||
// Generated by CoffeeScript 1.7.1 | ||
(function() { | ||
@@ -9,6 +9,6 @@ var ex; | ||
} | ||
/* | ||
Fixed typing error in UniqueIdentifier | ||
*/ | ||
*/ | ||
require('tds/lib/tds-constants.js').TdsConstants.dataTypesByName.GUIDTYPE.sqlType = 'UniqueIdentifier'; | ||
@@ -15,0 +15,0 @@ } catch (_error) { |
502
lib/tds.js
@@ -1,2 +0,2 @@ | ||
// Generated by CoffeeScript 1.6.3 | ||
// Generated by CoffeeScript 1.7.1 | ||
(function() { | ||
@@ -19,7 +19,7 @@ var FIXED, ISOLATION_LEVEL, Pool, TYPES, castParameter, createColumns, createParameterHeader, formatHex, isolationLevelDeclaration, parseGuid, tds, typeDeclaration, util, | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
castParameter = function(value, type) { | ||
@@ -88,7 +88,7 @@ if (value == null) { | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
createParameterHeader = function(param) { | ||
@@ -113,7 +113,7 @@ var header, _ref, _ref1, _ref2; | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
createColumns = function(meta) { | ||
@@ -126,3 +126,3 @@ var key, out, value; | ||
name: value.name, | ||
size: value.length, | ||
length: value.length, | ||
type: TYPES[value.type.sqlType] | ||
@@ -134,8 +134,9 @@ }; | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
typeDeclaration = function(type, length) { | ||
typeDeclaration = function(type, options) { | ||
var _ref, _ref1; | ||
switch (type) { | ||
@@ -145,17 +146,21 @@ case TYPES.VarChar: | ||
case TYPES.VarBinary: | ||
return "" + type.name + " (MAX)"; | ||
return "" + type.declaration + " (MAX)"; | ||
case TYPES.Char: | ||
case TYPES.NChar: | ||
case TYPES.Binary: | ||
return "" + type.name + " (" + (length != null ? length : 1) + ")"; | ||
return "" + type.declaration + " (" + ((_ref = options.length) != null ? _ref : 1) + ")"; | ||
case TYPES.Time: | ||
case TYPES.DateTime2: | ||
case TYPES.DateTimeOffset: | ||
return "" + type.declaration + " (" + ((_ref1 = options.scale) != null ? _ref1 : 7) + ")"; | ||
default: | ||
return type.name; | ||
return type.declaration; | ||
} | ||
}; | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
isolationLevelDeclaration = function(type) { | ||
@@ -178,2 +183,3 @@ switch (type) { | ||
/* | ||
@@ -183,5 +189,4 @@ Taken from Tedious. | ||
@private | ||
*/ | ||
*/ | ||
formatHex = function(number) { | ||
@@ -196,2 +201,3 @@ var hex; | ||
/* | ||
@@ -201,5 +207,4 @@ Taken from Tedious. | ||
@private | ||
*/ | ||
*/ | ||
parseGuid = function(buffer) { | ||
@@ -211,9 +216,9 @@ var guid; | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
module.exports = function(Connection, Transaction, Request, ConnectionError, TransactionError, RequestError) { | ||
var TDSConnection, TDSRequest, TDSTransaction, _ref, _ref1, _ref2; | ||
var TDSConnection, TDSRequest, TDSTransaction; | ||
TDSConnection = (function(_super) { | ||
@@ -223,4 +228,3 @@ __extends(TDSConnection, _super); | ||
function TDSConnection() { | ||
_ref = TDSConnection.__super__.constructor.apply(this, arguments); | ||
return _ref; | ||
return TDSConnection.__super__.constructor.apply(this, arguments); | ||
} | ||
@@ -231,4 +235,3 @@ | ||
TDSConnection.prototype.connect = function(config, callback) { | ||
var cfg, cfg_pool, key, value, _ref1, | ||
_this = this; | ||
var cfg, cfg_pool, key, value, _ref; | ||
cfg = { | ||
@@ -246,25 +249,27 @@ userName: config.user, | ||
idleTimeoutMillis: 30000, | ||
create: function(callback) { | ||
var c, timeouted, tmr, _ref1; | ||
c = new tds.Connection(cfg); | ||
timeouted = false; | ||
tmr = setTimeout(function() { | ||
timeouted = true; | ||
c._client._socket.destroy(); | ||
return callback(new ConnectionError("Connection timeout.", null)); | ||
}, (_ref1 = config.timeout) != null ? _ref1 : 15000); | ||
return c.connect(function(err) { | ||
clearTimeout(tmr); | ||
if (timeouted) { | ||
return; | ||
} | ||
if (err) { | ||
err = ConnectionError(err); | ||
} | ||
if (err) { | ||
return callback(err, null); | ||
} | ||
return callback(null, c); | ||
}); | ||
}, | ||
create: (function(_this) { | ||
return function(callback) { | ||
var c, timeouted, tmr, _ref; | ||
c = new tds.Connection(cfg); | ||
timeouted = false; | ||
tmr = setTimeout(function() { | ||
timeouted = true; | ||
c._client._socket.destroy(); | ||
return callback(new ConnectionError("Connection timeout.", null)); | ||
}, (_ref = config.timeout) != null ? _ref : 15000); | ||
return c.connect(function(err) { | ||
clearTimeout(tmr); | ||
if (timeouted) { | ||
return; | ||
} | ||
if (err) { | ||
err = ConnectionError(err); | ||
} | ||
if (err) { | ||
return callback(err, null); | ||
} | ||
return callback(null, c); | ||
}); | ||
}; | ||
})(this), | ||
validate: function(c) { | ||
@@ -278,5 +283,5 @@ return c != null; | ||
if (config.pool) { | ||
_ref1 = config.pool; | ||
for (key in _ref1) { | ||
value = _ref1[key]; | ||
_ref = config.pool; | ||
for (key in _ref) { | ||
value = _ref[key]; | ||
cfg_pool[key] = value; | ||
@@ -286,21 +291,24 @@ } | ||
this.pool = Pool(cfg_pool, cfg); | ||
return this.pool.acquire(function(err, connection) { | ||
if (err && !(err instanceof Error)) { | ||
err = new Error(err); | ||
} | ||
_this.pool.release(connection); | ||
return callback(err); | ||
}); | ||
return this.pool.acquire((function(_this) { | ||
return function(err, connection) { | ||
if (err && !(err instanceof Error)) { | ||
err = new Error(err); | ||
} | ||
_this.pool.release(connection); | ||
return callback(err); | ||
}; | ||
})(this)); | ||
}; | ||
TDSConnection.prototype.close = function(callback) { | ||
var _this = this; | ||
if (!this.pool) { | ||
return callback(null); | ||
} | ||
return this.pool.drain(function() { | ||
_this.pool.destroyAllNow(); | ||
_this.pool = null; | ||
return callback(null); | ||
}); | ||
return this.pool.drain((function(_this) { | ||
return function() { | ||
_this.pool.destroyAllNow(); | ||
_this.pool = null; | ||
return callback(null); | ||
}; | ||
})(this)); | ||
}; | ||
@@ -315,44 +323,46 @@ | ||
function TDSTransaction() { | ||
_ref1 = TDSTransaction.__super__.constructor.apply(this, arguments); | ||
return _ref1; | ||
return TDSTransaction.__super__.constructor.apply(this, arguments); | ||
} | ||
TDSTransaction.prototype.begin = function(callback) { | ||
var _this = this; | ||
return this.connection.pool.acquire(function(err, connection) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
_this._pooledConnection = connection; | ||
return connection.setAutoCommit(false, function(err) { | ||
return this.connection.pool.acquire((function(_this) { | ||
return function(err, connection) { | ||
if (err) { | ||
return TransactionError(err); | ||
return callback(err); | ||
} | ||
return _this.request().query("set transaction isolation level " + (isolationLevelDeclaration(_this.isolationLevel)), callback); | ||
}); | ||
}); | ||
_this._pooledConnection = connection; | ||
return _this.request().query("set transaction isolation level " + (isolationLevelDeclaration(_this.isolationLevel)), function(err) { | ||
if (err) { | ||
return TransactionError(err); | ||
} | ||
return connection.setAutoCommit(false, callback); | ||
}); | ||
}; | ||
})(this)); | ||
}; | ||
TDSTransaction.prototype.commit = function(callback) { | ||
var _this = this; | ||
return this._pooledConnection.commit(function(err) { | ||
if (err) { | ||
err = TransactionError(err); | ||
} | ||
_this.connection.pool.release(_this._pooledConnection); | ||
_this._pooledConnection = null; | ||
return callback(err); | ||
}); | ||
return this._pooledConnection.commit((function(_this) { | ||
return function(err) { | ||
if (err) { | ||
err = TransactionError(err); | ||
} | ||
_this.connection.pool.release(_this._pooledConnection); | ||
_this._pooledConnection = null; | ||
return callback(err); | ||
}; | ||
})(this)); | ||
}; | ||
TDSTransaction.prototype.rollback = function(callback) { | ||
var _this = this; | ||
return this._pooledConnection.rollback(function(err) { | ||
if (err) { | ||
err = TransactionError(err); | ||
} | ||
_this.connection.pool.release(_this._pooledConnection); | ||
_this._pooledConnection = null; | ||
return callback(err); | ||
}); | ||
return this._pooledConnection.rollback((function(_this) { | ||
return function(err) { | ||
if (err) { | ||
err = TransactionError(err); | ||
} | ||
_this.connection.pool.release(_this._pooledConnection); | ||
_this._pooledConnection = null; | ||
return callback(err); | ||
}; | ||
})(this)); | ||
}; | ||
@@ -367,4 +377,3 @@ | ||
function TDSRequest() { | ||
_ref2 = TDSRequest.__super__.constructor.apply(this, arguments); | ||
return _ref2; | ||
return TDSRequest.__super__.constructor.apply(this, arguments); | ||
} | ||
@@ -391,4 +400,3 @@ | ||
TDSRequest.prototype.query = function(command, callback) { | ||
var columns, error, handleOutput, input, name, output, param, paramHeaders, paramValues, recordset, recordsets, started, _ref3, | ||
_this = this; | ||
var columns, error, handleOutput, input, name, output, param, paramHeaders, paramValues, recordset, recordsets, started, _ref; | ||
if (this.verbose && !this.nested) { | ||
@@ -417,5 +425,5 @@ console.log("---------- sql query ----------\n query: " + command); | ||
paramValues = {}; | ||
_ref3 = this.parameters; | ||
for (name in _ref3) { | ||
param = _ref3[name]; | ||
_ref = this.parameters; | ||
for (name in _ref) { | ||
param = _ref[name]; | ||
if (!(param.io === 1)) { | ||
@@ -429,9 +437,9 @@ continue; | ||
input = (function() { | ||
var _ref4, _results; | ||
_ref4 = this.parameters; | ||
var _ref1, _results; | ||
_ref1 = this.parameters; | ||
_results = []; | ||
for (name in _ref4) { | ||
param = _ref4[name]; | ||
for (name in _ref1) { | ||
param = _ref1[name]; | ||
if (param.io === 2) { | ||
_results.push("@" + param.name + " " + (typeDeclaration(param.type, param.length))); | ||
_results.push("@" + param.name + " " + (typeDeclaration(param.type, param))); | ||
} | ||
@@ -442,7 +450,7 @@ } | ||
output = (function() { | ||
var _ref4, _results; | ||
_ref4 = this.parameters; | ||
var _ref1, _results; | ||
_ref1 = this.parameters; | ||
_results = []; | ||
for (name in _ref4) { | ||
param = _ref4[name]; | ||
for (name in _ref1) { | ||
param = _ref1[name]; | ||
if (param.io === 2) { | ||
@@ -462,98 +470,99 @@ _results.push("@" + param.name + " as '" + param.name + "'"); | ||
} | ||
return this._acquire(function(err, connection) { | ||
var req; | ||
if (!err) { | ||
req = connection.createStatement(command, paramHeaders); | ||
req.on('row', function(tdsrow) { | ||
var col, exi, row, value, _i, _len, _ref4; | ||
row = {}; | ||
_ref4 = tdsrow.metadata.columns; | ||
for (_i = 0, _len = _ref4.length; _i < _len; _i++) { | ||
col = _ref4[_i]; | ||
value = tdsrow.getValue(col.name); | ||
if (value != null) { | ||
if (col.type.name === 'GUIDTYPE') { | ||
value = parseGuid(value); | ||
return this._acquire((function(_this) { | ||
return function(err, connection) { | ||
var req; | ||
if (!err) { | ||
req = connection.createStatement(command, paramHeaders); | ||
req.on('row', function(tdsrow) { | ||
var col, exi, row, value, _i, _len, _ref1; | ||
row = {}; | ||
_ref1 = tdsrow.metadata.columns; | ||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) { | ||
col = _ref1[_i]; | ||
value = tdsrow.getValue(col.name); | ||
if (value != null) { | ||
if (col.type.name === 'GUIDTYPE') { | ||
value = parseGuid(value); | ||
} | ||
} | ||
} | ||
exi = row[col.name]; | ||
if (exi != null) { | ||
if (exi instanceof Array) { | ||
exi.push(col.value); | ||
exi = row[col.name]; | ||
if (exi != null) { | ||
if (exi instanceof Array) { | ||
exi.push(col.value); | ||
} else { | ||
row[col.name] = [exi, value]; | ||
} | ||
} else { | ||
row[col.name] = [exi, value]; | ||
row[col.name] = value; | ||
} | ||
} else { | ||
row[col.name] = value; | ||
} | ||
} | ||
if (_this.verbose) { | ||
console.log(util.inspect(row)); | ||
console.log("---------- --------------------"); | ||
} | ||
if (row["___return___"] == null) { | ||
_this.emit('row', row); | ||
} | ||
return recordset.push(row); | ||
}); | ||
req.on('metadata', function(metadata) { | ||
if (recordset) { | ||
_this.emit('recordset', recordset); | ||
} | ||
columns = metadata.columnsByName; | ||
recordset = []; | ||
Object.defineProperty(recordset, 'columns', { | ||
enumerable: false, | ||
value: createColumns(metadata.columnsByName) | ||
}, _this.nested); | ||
return recordsets.push(recordset); | ||
}); | ||
req.on('done', function(res) { | ||
var elapsed, last, _ref4, _ref5; | ||
if (!_this.nested) { | ||
if (_this.verbose) { | ||
console.log(util.inspect(row)); | ||
console.log("---------- --------------------"); | ||
} | ||
if (row["___return___"] == null) { | ||
_this.emit('row', row); | ||
} | ||
return recordset.push(row); | ||
}); | ||
req.on('metadata', function(metadata) { | ||
if (recordset) { | ||
_this.emit('recordset', recordset); | ||
} | ||
if (handleOutput) { | ||
last = (_ref4 = recordsets.pop()) != null ? _ref4[0] : void 0; | ||
_ref5 = _this.parameters; | ||
for (name in _ref5) { | ||
param = _ref5[name]; | ||
if (!(param.io === 2)) { | ||
continue; | ||
columns = metadata.columnsByName; | ||
recordset = []; | ||
Object.defineProperty(recordset, 'columns', { | ||
enumerable: false, | ||
value: createColumns(metadata.columnsByName) | ||
}, _this.nested); | ||
return recordsets.push(recordset); | ||
}); | ||
req.on('done', function(res) { | ||
var elapsed, last, _ref1, _ref2; | ||
if (!_this.nested) { | ||
if (recordset) { | ||
_this.emit('recordset', recordset); | ||
} | ||
if (handleOutput) { | ||
last = (_ref1 = recordsets.pop()) != null ? _ref1[0] : void 0; | ||
_ref2 = _this.parameters; | ||
for (name in _ref2) { | ||
param = _ref2[name]; | ||
if (!(param.io === 2)) { | ||
continue; | ||
} | ||
param.value = last[param.name]; | ||
if (_this.verbose) { | ||
console.log(" output: @" + param.name + ", " + param.type.declaration + ", " + param.value); | ||
} | ||
} | ||
param.value = last[param.name]; | ||
if (_this.verbose) { | ||
console.log(" output: @" + param.name + ", " + param.type.name + ", " + param.value); | ||
} | ||
if (_this.verbose) { | ||
if (error) { | ||
console.log(" error: " + error); | ||
} | ||
elapsed = Date.now() - started; | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
} | ||
if (_this.verbose) { | ||
if (error) { | ||
console.log(" error: " + error); | ||
} | ||
elapsed = Date.now() - started; | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
_this._release(connection); | ||
return typeof callback === "function" ? callback(error, _this.multiple || _this.nested ? recordsets : recordsets[0]) : void 0; | ||
}); | ||
req.on('error', function(err) { | ||
return error = RequestError(err); | ||
}); | ||
return req.execute(paramValues); | ||
} else { | ||
if (connection) { | ||
_this._release(connection); | ||
} | ||
_this._release(connection); | ||
return typeof callback === "function" ? callback(error, _this.multiple || _this.nested ? recordsets : recordsets[0]) : void 0; | ||
}); | ||
req.on('error', function(err) { | ||
return error = RequestError(err); | ||
}); | ||
return req.execute(paramValues); | ||
} else { | ||
if (connection) { | ||
_this._release(connection); | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
} | ||
}); | ||
}; | ||
})(this)); | ||
}; | ||
TDSRequest.prototype.execute = function(procedure, callback) { | ||
var cmd, name, param, spp, started, _ref3, | ||
_this = this; | ||
var cmd, name, param, spp, started, _ref; | ||
if (this.verbose) { | ||
@@ -564,9 +573,9 @@ console.log("---------- sql execute --------\n proc: " + procedure); | ||
cmd = "declare " + (['@___return___ int'].concat((function() { | ||
var _ref3, _results; | ||
_ref3 = this.parameters; | ||
var _ref, _results; | ||
_ref = this.parameters; | ||
_results = []; | ||
for (name in _ref3) { | ||
param = _ref3[name]; | ||
for (name in _ref) { | ||
param = _ref[name]; | ||
if (param.io === 2) { | ||
_results.push("@" + param.name + " " + (typeDeclaration(param.type, param.length))); | ||
_results.push("@" + param.name + " " + (typeDeclaration(param.type, param))); | ||
} | ||
@@ -578,5 +587,5 @@ } | ||
spp = []; | ||
_ref3 = this.parameters; | ||
for (name in _ref3) { | ||
param = _ref3[name]; | ||
_ref = this.parameters; | ||
for (name in _ref) { | ||
param = _ref[name]; | ||
if (param.io === 2) { | ||
@@ -586,3 +595,3 @@ spp.push("@" + param.name + "=@" + param.name + " output"); | ||
if (this.verbose) { | ||
console.log(" input: @" + param.name + ", " + param.type.name + ", " + param.value); | ||
console.log(" input: @" + param.name + ", " + param.type.declaration + ", " + param.value); | ||
} | ||
@@ -594,7 +603,7 @@ spp.push("@" + param.name + "=@" + param.name); | ||
cmd += "select " + (['@___return___ as \'___return___\''].concat((function() { | ||
var _ref4, _results; | ||
_ref4 = this.parameters; | ||
var _ref1, _results; | ||
_ref1 = this.parameters; | ||
_results = []; | ||
for (name in _ref4) { | ||
param = _ref4[name]; | ||
for (name in _ref1) { | ||
param = _ref1[name]; | ||
if (param.io === 2) { | ||
@@ -610,47 +619,50 @@ _results.push("@" + param.name + " as '" + param.name + "'"); | ||
this.nested = true; | ||
return TDSRequest.prototype.query.call(this, cmd, function(err, recordsets) { | ||
var elapsed, last, returnValue, _ref4, _ref5; | ||
_this.nested = false; | ||
if (err) { | ||
if (_this.verbose) { | ||
elapsed = Date.now() - started; | ||
console.log(" error: " + err); | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
} else { | ||
last = (_ref4 = recordsets.pop()) != null ? _ref4[0] : void 0; | ||
if (last && (last.___return___ != null)) { | ||
returnValue = last.___return___; | ||
_ref5 = _this.parameters; | ||
for (name in _ref5) { | ||
param = _ref5[name]; | ||
if (!(param.io === 2)) { | ||
continue; | ||
return TDSRequest.prototype.query.call(this, cmd, (function(_this) { | ||
return function(err, recordsets) { | ||
var elapsed, last, returnValue, _ref1, _ref2; | ||
_this.nested = false; | ||
if (err) { | ||
if (_this.verbose) { | ||
elapsed = Date.now() - started; | ||
console.log(" error: " + err); | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
} else { | ||
last = (_ref1 = recordsets.pop()) != null ? _ref1[0] : void 0; | ||
if (last && (last.___return___ != null)) { | ||
returnValue = last.___return___; | ||
_ref2 = _this.parameters; | ||
for (name in _ref2) { | ||
param = _ref2[name]; | ||
if (!(param.io === 2)) { | ||
continue; | ||
} | ||
param.value = last[param.name]; | ||
if (_this.verbose) { | ||
console.log(" output: @" + param.name + ", " + param.type.declaration + ", " + param.value); | ||
} | ||
} | ||
param.value = last[param.name]; | ||
if (_this.verbose) { | ||
console.log(" output: @" + param.name + ", " + param.type.name + ", " + param.value); | ||
} | ||
} | ||
if (_this.verbose) { | ||
elapsed = Date.now() - started; | ||
console.log(" return: " + returnValue); | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
recordsets.returnValue = returnValue; | ||
return typeof callback === "function" ? callback(null, recordsets, returnValue) : void 0; | ||
} | ||
if (_this.verbose) { | ||
elapsed = Date.now() - started; | ||
console.log(" return: " + returnValue); | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
recordsets.returnValue = returnValue; | ||
return typeof callback === "function" ? callback(null, recordsets, returnValue) : void 0; | ||
} | ||
}); | ||
}; | ||
})(this)); | ||
}; | ||
/* | ||
Cancel currently executed request. | ||
*/ | ||
TDSRequest.prototype.cancel = function() { | ||
/* | ||
Cancel currently executed request. | ||
*/ | ||
throw new RequestError("Request canceling is not implemented by TDS driver."); | ||
return false; | ||
}; | ||
@@ -657,0 +669,0 @@ |
@@ -1,7 +0,6 @@ | ||
// Generated by CoffeeScript 1.6.3 | ||
// Generated by CoffeeScript 1.7.1 | ||
(function() { | ||
var FIXED, Pool, TYPES, createColumns, getMssqlType, getTediousType, tds, util, | ||
var DECLARATIONS, Pool, TYPES, Table, UDT, createColumns, getMssqlType, getTediousType, parameterCorrection, tds, util, valueCorrection, | ||
__hasProp = {}.hasOwnProperty, | ||
__extends = 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; }, | ||
__slice = [].slice; | ||
__extends = 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; }; | ||
@@ -14,11 +13,15 @@ Pool = require('generic-pool').Pool; | ||
FIXED = false; | ||
TYPES = require('./datatypes').TYPES; | ||
DECLARATIONS = require('./datatypes').DECLARATIONS; | ||
UDT = require('./udt').PARSERS; | ||
Table = require('./table'); | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
getTediousType = function(type) { | ||
@@ -45,13 +48,21 @@ switch (type) { | ||
case TYPES.Decimal: | ||
return tds.TYPES.Float; | ||
return tds.TYPES.Decimal; | ||
case TYPES.Numeric: | ||
return tds.TYPES.Float; | ||
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.DateTime; | ||
return tds.TYPES.DateN; | ||
case TYPES.DateTime: | ||
return tds.TYPES.DateTime; | ||
case TYPES.DateTime2: | ||
return tds.TYPES.DateTime2N; | ||
case TYPES.DateTimeOffset: | ||
return tds.TYPES.DateTime; | ||
return tds.TYPES.DateTimeOffsetN; | ||
case TYPES.SmallDateTime: | ||
@@ -75,2 +86,8 @@ return tds.TYPES.SmallDateTime; | ||
return tds.TYPES.VarBinary; | ||
case TYPES.UDT: | ||
case TYPES.Geography: | ||
case TYPES.Geometry: | ||
return tds.TYPES.UDT; | ||
case TYPES.TVP: | ||
return tds.TYPES.TVP; | ||
default: | ||
@@ -81,7 +98,7 @@ return type; | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
getMssqlType = function(type) { | ||
@@ -132,2 +149,10 @@ switch (type) { | ||
return TYPES.DateTime; | ||
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: | ||
@@ -145,10 +170,14 @@ return TYPES.SmallDateTime; | ||
return TYPES.Xml; | ||
case tds.TYPES.UDT: | ||
return TYPES.UDT; | ||
case tds.TYPES.TVP: | ||
return TYPES.TVP; | ||
} | ||
}; | ||
/* | ||
@ignore | ||
*/ | ||
*/ | ||
createColumns = function(meta) { | ||
@@ -161,5 +190,18 @@ var key, out, value; | ||
name: value.colName, | ||
size: value.dataLength, | ||
type: getMssqlType(value.type) | ||
length: value.dataLength, | ||
type: getMssqlType(value.type), | ||
scale: value.scale, | ||
precision: value.precision | ||
}; | ||
if (value.udtInfo != null) { | ||
out[key].udt = { | ||
name: value.udtInfo.typeName, | ||
database: value.udtInfo.dbname, | ||
schema: value.udtInfo.owningSchema, | ||
assembly: value.udtInfo.assemblyName | ||
}; | ||
if (DECLARATIONS[value.udtInfo.typeName]) { | ||
out[key].type = DECLARATIONS[value.udtInfo.typeName]; | ||
} | ||
} | ||
} | ||
@@ -169,9 +211,55 @@ 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, tvp, _i, _len, _ref; | ||
if (value instanceof Table) { | ||
tvp = { | ||
columns: [], | ||
rows: value.rows | ||
}; | ||
_ref = value.columns; | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
col = _ref[_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, _ref, _ref1, _ref2; | ||
var TediousConnection, TediousRequest, TediousTransaction; | ||
TediousConnection = (function(_super) { | ||
@@ -181,4 +269,3 @@ __extends(TediousConnection, _super); | ||
function TediousConnection() { | ||
_ref = TediousConnection.__super__.constructor.apply(this, arguments); | ||
return _ref; | ||
return TediousConnection.__super__.constructor.apply(this, arguments); | ||
} | ||
@@ -189,4 +276,3 @@ | ||
TediousConnection.prototype.connect = function(config, callback) { | ||
var cfg, cfg_pool, key, value, _base, _base1, _base2, _ref1, _ref2, | ||
_this = this; | ||
var cfg, cfg_pool, key, value, _base, _base1, _base2, _base3, _ref, _ref1; | ||
cfg = { | ||
@@ -198,5 +284,2 @@ userName: config.user, | ||
}; | ||
if (cfg.options == null) { | ||
cfg.options = {}; | ||
} | ||
if ((_base = cfg.options).database == null) { | ||
@@ -209,4 +292,10 @@ _base.database = config.database; | ||
if ((_base2 = cfg.options).connectTimeout == null) { | ||
_base2.connectTimeout = (_ref1 = config.timeout) != null ? _ref1 : 15000; | ||
_base2.connectTimeout = (_ref = config.timeout) != null ? _ref : 15000; | ||
} | ||
if ((_base3 = cfg.options).tdsVersion == null) { | ||
_base3.tdsVersion = '7_4'; | ||
} | ||
cfg.options.rowCollectionOnDone = false; | ||
cfg.options.rowCollectionOnRequestCompletion = false; | ||
cfg.options.useColumnNames = false; | ||
if (cfg.options.instanceName) { | ||
@@ -220,23 +309,17 @@ delete cfg.options.port; | ||
idleTimeoutMillis: 30000, | ||
create: function(callback) { | ||
var c, connect, connecting, defDE; | ||
c = new tds.Connection(cfg); | ||
connecting = true; | ||
defDE = c.dispatchEvent; | ||
c.dispatchEvent = function(event) { | ||
defDE.call.apply(defDE, [c].concat(__slice.call(arguments))); | ||
if (event === 'socketError' && connecting) { | ||
c.removeListener('connect', connect); | ||
return callback(arguments[1], null); | ||
} | ||
create: (function(_this) { | ||
return function(callback) { | ||
var c; | ||
c = new tds.Connection(cfg); | ||
return c.once('connect', function(err) { | ||
if (err) { | ||
err = ConnectionError(err); | ||
} | ||
if (err) { | ||
return callback(err, null); | ||
} | ||
return callback(null, c); | ||
}); | ||
}; | ||
connect = function(err) { | ||
connecting = false; | ||
if (err) { | ||
return callback(err, null); | ||
} | ||
return callback(null, c); | ||
}; | ||
return c.once('connect', connect); | ||
}, | ||
})(this), | ||
validate: function(c) { | ||
@@ -250,5 +333,5 @@ return (c != null) && !c.closed; | ||
if (config.pool) { | ||
_ref2 = config.pool; | ||
for (key in _ref2) { | ||
value = _ref2[key]; | ||
_ref1 = config.pool; | ||
for (key in _ref1) { | ||
value = _ref1[key]; | ||
cfg_pool[key] = value; | ||
@@ -258,21 +341,21 @@ } | ||
this.pool = Pool(cfg_pool, cfg); | ||
return this.pool.acquire(function(err, connection) { | ||
if (err) { | ||
err = ConnectionError(err); | ||
} | ||
_this.pool.release(connection); | ||
return callback(err); | ||
}); | ||
return this.pool.acquire((function(_this) { | ||
return function(err, connection) { | ||
_this.pool.release(connection); | ||
return callback(err); | ||
}; | ||
})(this)); | ||
}; | ||
TediousConnection.prototype.close = function(callback) { | ||
var _this = this; | ||
if (!this.pool) { | ||
return callback(null); | ||
} | ||
return this.pool.drain(function() { | ||
_this.pool.destroyAllNow(); | ||
_this.pool = null; | ||
return callback(null); | ||
}); | ||
return this.pool.drain((function(_this) { | ||
return function() { | ||
_this.pool.destroyAllNow(); | ||
_this.pool = null; | ||
return callback(null); | ||
}; | ||
})(this)); | ||
}; | ||
@@ -287,44 +370,46 @@ | ||
function TediousTransaction() { | ||
_ref1 = TediousTransaction.__super__.constructor.apply(this, arguments); | ||
return _ref1; | ||
return TediousTransaction.__super__.constructor.apply(this, arguments); | ||
} | ||
TediousTransaction.prototype.begin = function(callback) { | ||
var _this = this; | ||
return this.connection.pool.acquire(function(err, connection) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
_this._pooledConnection = connection; | ||
return connection.beginTransaction(function(err) { | ||
return this.connection.pool.acquire((function(_this) { | ||
return function(err, connection) { | ||
if (err) { | ||
err = TransactionError(err); | ||
return callback(err); | ||
} | ||
return callback(err); | ||
}, _this.name, _this.isolationLevel); | ||
}); | ||
_this._pooledConnection = connection; | ||
return connection.beginTransaction(function(err) { | ||
if (err) { | ||
err = TransactionError(err); | ||
} | ||
return callback(err); | ||
}, _this.name, _this.isolationLevel); | ||
}; | ||
})(this)); | ||
}; | ||
TediousTransaction.prototype.commit = function(callback) { | ||
var _this = this; | ||
return this._pooledConnection.commitTransaction(function(err) { | ||
if (err) { | ||
err = TransactionError(err); | ||
} | ||
_this.connection.pool.release(_this._pooledConnection); | ||
_this._pooledConnection = null; | ||
return callback(err); | ||
}); | ||
return this._pooledConnection.commitTransaction((function(_this) { | ||
return function(err) { | ||
if (err) { | ||
err = TransactionError(err); | ||
} | ||
_this.connection.pool.release(_this._pooledConnection); | ||
_this._pooledConnection = null; | ||
return callback(err); | ||
}; | ||
})(this)); | ||
}; | ||
TediousTransaction.prototype.rollback = function(callback) { | ||
var _this = this; | ||
return this._pooledConnection.rollbackTransaction(function(err) { | ||
if (err) { | ||
err = TransactionError(err); | ||
} | ||
_this.connection.pool.release(_this._pooledConnection); | ||
_this._pooledConnection = null; | ||
return callback(err); | ||
}); | ||
return this._pooledConnection.rollbackTransaction((function(_this) { | ||
return function(err) { | ||
if (err) { | ||
err = TransactionError(err); | ||
} | ||
_this.connection.pool.release(_this._pooledConnection); | ||
_this._pooledConnection = null; | ||
return callback(err); | ||
}; | ||
})(this)); | ||
}; | ||
@@ -339,4 +424,3 @@ | ||
function TediousRequest() { | ||
_ref2 = TediousRequest.__super__.constructor.apply(this, arguments); | ||
return _ref2; | ||
return TediousRequest.__super__.constructor.apply(this, arguments); | ||
} | ||
@@ -360,10 +444,9 @@ | ||
/* | ||
Execute specified sql command. | ||
*/ | ||
*/ | ||
TediousRequest.prototype.query = function(command, callback) { | ||
var columns, recordset, recordsets, started, | ||
_this = this; | ||
var columns, recordset, recordsets, started; | ||
columns = {}; | ||
@@ -373,138 +456,161 @@ recordset = []; | ||
started = Date.now(); | ||
return this._acquire(function(err, connection) { | ||
var name, param, req, _ref3, _ref4; | ||
if (!err) { | ||
if (_this.verbose) { | ||
console.log("---------- sql query ----------\n query: " + command); | ||
} | ||
req = new tds.Request(command, function(err) { | ||
var elapsed; | ||
if (err) { | ||
err = RequestError(err); | ||
return this._acquire((function(_this) { | ||
return function(err, connection) { | ||
var name, param, req, _ref, _ref1; | ||
if (!err) { | ||
if (_this.verbose) { | ||
console.log("---------- sql query ----------\n query: " + command); | ||
} | ||
if (_this.verbose) { | ||
if (_this.canceled) { | ||
if (_this.verbose) { | ||
console.log("---------- canceling ----------"); | ||
} | ||
_this._release(connection); | ||
return typeof callback === "function" ? callback(new RequestError("Canceled.", 'ECANCEL')) : void 0; | ||
} | ||
_this._cancel = function() { | ||
if (_this.verbose) { | ||
console.log("---------- canceling ----------"); | ||
} | ||
return connection.cancel(); | ||
}; | ||
req = new tds.Request(command, function(err) { | ||
var elapsed; | ||
if (err) { | ||
console.log(" error: " + err); | ||
err = RequestError(err); | ||
} | ||
elapsed = Date.now() - started; | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
if (recordset) { | ||
if (_this.verbose) { | ||
if (err) { | ||
console.log(" error: " + err); | ||
} | ||
elapsed = Date.now() - started; | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
if (recordset) { | ||
Object.defineProperty(recordset, 'columns', { | ||
enumerable: false, | ||
value: columns | ||
}); | ||
} | ||
_this._cancel = null; | ||
_this._release(connection); | ||
return typeof callback === "function" ? callback(err, _this.multiple ? recordsets : recordsets[0]) : void 0; | ||
}); | ||
req.on('columnMetadata', function(metadata) { | ||
var col, _i, _len, _results; | ||
_results = []; | ||
for (_i = 0, _len = metadata.length; _i < _len; _i++) { | ||
col = metadata[_i]; | ||
_results.push(columns[col.colName] = col); | ||
} | ||
return _results; | ||
}); | ||
req.on('doneInProc', function(rowCount, more, rows) { | ||
if (Object.keys(columns).length === 0) { | ||
return; | ||
} | ||
Object.defineProperty(recordset, 'columns', { | ||
enumerable: false, | ||
value: columns | ||
value: createColumns(columns) | ||
}); | ||
} | ||
_this._release(connection); | ||
return typeof callback === "function" ? callback(err, _this.multiple ? recordsets : recordsets[0]) : void 0; | ||
}); | ||
req.on('columnMetadata', function(metadata) { | ||
var col, _i, _len, _results; | ||
_results = []; | ||
for (_i = 0, _len = metadata.length; _i < _len; _i++) { | ||
col = metadata[_i]; | ||
_results.push(columns[col.colName] = col); | ||
} | ||
return _results; | ||
}); | ||
req.on('doneInProc', function(rowCount, more, rows) { | ||
if (Object.keys(columns).length === 0) { | ||
return; | ||
} | ||
Object.defineProperty(recordset, 'columns', { | ||
enumerable: false, | ||
value: createColumns(columns) | ||
Object.defineProperty(recordset, 'toTable', { | ||
enumerable: false, | ||
value: function() { | ||
return Table.fromRecordset(this); | ||
} | ||
}); | ||
_this.emit('recordset', recordset); | ||
recordsets.push(recordset); | ||
recordset = []; | ||
return columns = {}; | ||
}); | ||
_this.emit('recordset', recordset); | ||
recordsets.push(recordset); | ||
recordset = []; | ||
return columns = {}; | ||
}); | ||
req.on('returnValue', function(parameterName, value, metadata) { | ||
if (_this.verbose) { | ||
if (value === tds.TYPES.Null) { | ||
console.log(" output: @" + parameterName + ", null"); | ||
} else { | ||
console.log(" output: @" + parameterName + ", " + (_this.parameters[parameterName].type.name.toLowerCase()) + ", " + value); | ||
req.on('returnValue', function(parameterName, value, metadata) { | ||
if (_this.verbose) { | ||
if (value === tds.TYPES.Null) { | ||
console.log(" output: @" + parameterName + ", null"); | ||
} else { | ||
console.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, row, _i, _len; | ||
if (!recordset) { | ||
recordset = []; | ||
} | ||
row = {}; | ||
for (_i = 0, _len = columns.length; _i < _len; _i++) { | ||
col = columns[_i]; | ||
if (col.value != null) { | ||
if (col.metadata.type === tds.TYPES.Binary || col.metadata.type === tds.TYPES.VarBinary || col.metadata.type === tds.TYPES.Image) { | ||
col.value = new Buffer(col.value); | ||
return _this.parameters[parameterName].value = value === tds.TYPES.Null ? null : value; | ||
}); | ||
req.on('row', function(columns) { | ||
var col, exi, row, _i, _len; | ||
if (!recordset) { | ||
recordset = []; | ||
} | ||
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; | ||
} | ||
} | ||
exi = row[col.metadata.colName]; | ||
if (exi != null) { | ||
if (exi instanceof Array) { | ||
exi.push(col.value); | ||
if (_this.verbose) { | ||
console.log(util.inspect(row)); | ||
console.log("---------- --------------------"); | ||
} | ||
_this.emit('row', row); | ||
return recordset.push(row); | ||
}); | ||
_ref = _this.parameters; | ||
for (name in _ref) { | ||
param = _ref[name]; | ||
if (!(param.io === 1)) { | ||
continue; | ||
} | ||
if (_this.verbose) { | ||
if (param.value === tds.TYPES.Null) { | ||
console.log(" input: @" + param.name + ", null"); | ||
} else { | ||
row[col.metadata.colName] = [exi, col.value]; | ||
console.log(" input: @" + param.name + ", " + (param.type.declaration.toLowerCase()) + ", " + param.value); | ||
} | ||
} else { | ||
row[col.metadata.colName] = col.value; | ||
} | ||
req.addParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), { | ||
length: param.length, | ||
scale: param.scale, | ||
precision: param.precision | ||
}); | ||
} | ||
if (_this.verbose) { | ||
console.log(util.inspect(row)); | ||
console.log("---------- --------------------"); | ||
_ref1 = _this.parameters; | ||
for (name in _ref1) { | ||
param = _ref1[name]; | ||
if (param.io === 2) { | ||
req.addOutputParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), { | ||
length: param.length, | ||
scale: param.scale, | ||
precision: param.precision | ||
}); | ||
} | ||
} | ||
_this.emit('row', row); | ||
return recordset.push(row); | ||
}); | ||
_ref3 = _this.parameters; | ||
for (name in _ref3) { | ||
param = _ref3[name]; | ||
if (!(param.io === 1)) { | ||
continue; | ||
} | ||
if (_this.verbose) { | ||
if (param.value === tds.TYPES.Null) { | ||
console.log(" input: @" + param.name + ", null"); | ||
} else { | ||
console.log(" input: @" + param.name + ", " + (param.type.name.toLowerCase()) + ", " + param.value); | ||
} | ||
console.log("---------- response -----------"); | ||
} | ||
req.addParameter(param.name, getTediousType(param.type), param.value, null); | ||
} | ||
_ref4 = _this.parameters; | ||
for (name in _ref4) { | ||
param = _ref4[name]; | ||
if (param.io === 2) { | ||
req.addOutputParameter(param.name, getTediousType(param.type), { | ||
length: param.length | ||
}); | ||
return connection.execSql(req); | ||
} else { | ||
if (connection) { | ||
_this._release(connection); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
} | ||
if (_this.verbose) { | ||
console.log("---------- response -----------"); | ||
} | ||
return connection.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 columns, recordset, recordsets, returnValue, started, | ||
_this = this; | ||
var columns, recordset, recordsets, returnValue, started; | ||
columns = {}; | ||
@@ -515,139 +621,166 @@ recordset = []; | ||
started = Date.now(); | ||
return this._acquire(function(err, connection) { | ||
var name, param, req, _ref3, _ref4; | ||
if (!err) { | ||
if (_this.verbose) { | ||
console.log("---------- sql execute --------\n proc: " + procedure); | ||
} | ||
req = new tds.Request(procedure, function(err) { | ||
var elapsed; | ||
if (err) { | ||
err = RequestError(err); | ||
return this._acquire((function(_this) { | ||
return function(err, connection) { | ||
var name, param, req, _ref, _ref1; | ||
if (!err) { | ||
if (_this.verbose) { | ||
console.log("---------- sql execute --------\n proc: " + procedure); | ||
} | ||
if (_this.verbose) { | ||
if (_this.canceled) { | ||
if (_this.verbose) { | ||
console.log("---------- canceling ----------"); | ||
} | ||
_this._release(connection); | ||
return typeof callback === "function" ? callback(new RequestError("Canceled.", 'ECANCEL')) : void 0; | ||
} | ||
_this._cancel = function() { | ||
if (_this.verbose) { | ||
console.log("---------- canceling ----------"); | ||
} | ||
return connection.cancel(); | ||
}; | ||
req = new tds.Request(procedure, function(err) { | ||
var elapsed; | ||
if (err) { | ||
console.log(" error: " + err); | ||
err = RequestError(err); | ||
} | ||
elapsed = Date.now() - started; | ||
console.log(" return: " + returnValue); | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
_this._release(connection); | ||
recordsets.returnValue = returnValue; | ||
return typeof callback === "function" ? callback(err, recordsets, returnValue) : void 0; | ||
}); | ||
req.on('columnMetadata', function(metadata) { | ||
var col, _i, _len, _results; | ||
_results = []; | ||
for (_i = 0, _len = metadata.length; _i < _len; _i++) { | ||
col = metadata[_i]; | ||
_results.push(columns[col.colName] = col); | ||
} | ||
return _results; | ||
}); | ||
req.on('row', function(columns) { | ||
var col, exi, row, _i, _len; | ||
if (!recordset) { | ||
if (_this.verbose) { | ||
if (err) { | ||
console.log(" error: " + err); | ||
} | ||
elapsed = Date.now() - started; | ||
console.log(" return: " + returnValue); | ||
console.log(" duration: " + elapsed + "ms"); | ||
console.log("---------- completed ----------"); | ||
} | ||
_this._cancel = null; | ||
_this._release(connection); | ||
recordsets.returnValue = returnValue; | ||
return typeof callback === "function" ? callback(err, recordsets, returnValue) : void 0; | ||
}); | ||
req.on('columnMetadata', function(metadata) { | ||
var col, _i, _len, _results; | ||
_results = []; | ||
for (_i = 0, _len = metadata.length; _i < _len; _i++) { | ||
col = metadata[_i]; | ||
_results.push(columns[col.colName] = col); | ||
} | ||
return _results; | ||
}); | ||
req.on('row', function(columns) { | ||
var col, exi, row, _i, _len; | ||
if (!recordset) { | ||
recordset = []; | ||
} | ||
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) { | ||
console.log(util.inspect(row)); | ||
console.log("---------- --------------------"); | ||
} | ||
_this.emit('row', row); | ||
return recordset.push(row); | ||
}); | ||
req.on('doneInProc', function(rowCount, more, rows) { | ||
if (Object.keys(columns).length === 0) { | ||
return; | ||
} | ||
Object.defineProperty(recordset, 'columns', { | ||
enumerable: false, | ||
value: createColumns(columns) | ||
}); | ||
Object.defineProperty(recordset, 'toTable', { | ||
enumerable: false, | ||
value: function() { | ||
return Table.fromRecordset(this); | ||
} | ||
}); | ||
_this.emit('recordset', recordset); | ||
recordsets.push(recordset); | ||
recordset = []; | ||
} | ||
row = {}; | ||
for (_i = 0, _len = columns.length; _i < _len; _i++) { | ||
col = columns[_i]; | ||
if (col.value != null) { | ||
if (col.metadata.type === tds.TYPES.Binary || col.metadata.type === tds.TYPES.VarBinary || col.metadata.type === tds.TYPES.Image) { | ||
col.value = new Buffer(col.value); | ||
return columns = {}; | ||
}); | ||
req.on('doneProc', function(rowCount, more, returnStatus, rows) { | ||
return returnValue = returnStatus; | ||
}); | ||
req.on('returnValue', function(parameterName, value, metadata) { | ||
if (metadata.type === tds.TYPES.Binary || metadata.type === tds.TYPES.VarBinary || metadata.type === tds.TYPES.Image) { | ||
value = new Buffer(value); | ||
} | ||
if (_this.verbose) { | ||
if (value === tds.TYPES.Null) { | ||
console.log(" output: @" + parameterName + ", null"); | ||
} else { | ||
console.log(" output: @" + parameterName + ", " + (_this.parameters[parameterName].type.declaration.toLowerCase()) + ", " + value); | ||
} | ||
} | ||
exi = row[col.metadata.colName]; | ||
if (exi != null) { | ||
if (exi instanceof Array) { | ||
exi.push(col.value); | ||
return _this.parameters[parameterName].value = value === tds.TYPES.Null ? null : value; | ||
}); | ||
_ref = _this.parameters; | ||
for (name in _ref) { | ||
param = _ref[name]; | ||
if (!(param.io === 1)) { | ||
continue; | ||
} | ||
if (_this.verbose) { | ||
if (param.value === tds.TYPES.Null) { | ||
console.log(" input: @" + param.name + ", null"); | ||
} else { | ||
row[col.metadata.colName] = [exi, col.value]; | ||
console.log(" input: @" + param.name + ", " + (param.type.declaration.toLowerCase()) + ", " + param.value); | ||
} | ||
} else { | ||
row[col.metadata.colName] = col.value; | ||
} | ||
req.addParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), { | ||
length: param.length, | ||
scale: param.scale, | ||
precision: param.precision | ||
}); | ||
} | ||
if (_this.verbose) { | ||
console.log(util.inspect(row)); | ||
console.log("---------- --------------------"); | ||
} | ||
_this.emit('row', row); | ||
return recordset.push(row); | ||
}); | ||
req.on('doneInProc', function(rowCount, more, rows) { | ||
if (Object.keys(columns).length === 0) { | ||
return; | ||
} | ||
Object.defineProperty(recordset, 'columns', { | ||
enumerable: false, | ||
value: createColumns(columns) | ||
}); | ||
_this.emit('recordset', recordset); | ||
recordsets.push(recordset); | ||
recordset = []; | ||
return columns = {}; | ||
}); | ||
req.on('doneProc', function(rowCount, more, returnStatus, rows) { | ||
return returnValue = returnStatus; | ||
}); | ||
req.on('returnValue', function(parameterName, value, metadata) { | ||
if (metadata.type === tds.TYPES.Binary || metadata.type === tds.TYPES.VarBinary || metadata.type === tds.TYPES.Image) { | ||
value = new Buffer(value); | ||
} | ||
if (_this.verbose) { | ||
if (value === tds.TYPES.Null) { | ||
console.log(" output: @" + parameterName + ", null"); | ||
} else { | ||
console.log(" output: @" + parameterName + ", " + (_this.parameters[parameterName].type.name.toLowerCase()) + ", " + value); | ||
_ref1 = _this.parameters; | ||
for (name in _ref1) { | ||
param = _ref1[name]; | ||
if (param.io === 2) { | ||
req.addOutputParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), { | ||
length: param.length, | ||
scale: param.scale, | ||
precision: param.precision | ||
}); | ||
} | ||
} | ||
return _this.parameters[parameterName].value = value === tds.TYPES.Null ? null : value; | ||
}); | ||
_ref3 = _this.parameters; | ||
for (name in _ref3) { | ||
param = _ref3[name]; | ||
if (!(param.io === 1)) { | ||
continue; | ||
} | ||
if (_this.verbose) { | ||
if (param.value === tds.TYPES.Null) { | ||
console.log(" input: @" + param.name + ", null"); | ||
} else { | ||
console.log(" input: @" + param.name + ", " + (param.type.name.toLowerCase()) + ", " + param.value); | ||
} | ||
console.log("---------- response -----------"); | ||
} | ||
req.addParameter(param.name, getTediousType(param.type), param.value, null); | ||
} | ||
_ref4 = _this.parameters; | ||
for (name in _ref4) { | ||
param = _ref4[name]; | ||
if (param.io === 2) { | ||
req.addOutputParameter(param.name, getTediousType(param.type), { | ||
length: param.length | ||
}); | ||
return connection.callProcedure(req); | ||
} else { | ||
if (connection) { | ||
_this._release(connection); | ||
} | ||
return typeof callback === "function" ? callback(err) : void 0; | ||
} | ||
if (_this.verbose) { | ||
console.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() { | ||
throw new RequestError("Request canceling is not implemented by Tedious driver."); | ||
if (this._cancel) { | ||
return this._cancel(); | ||
} | ||
return true; | ||
}; | ||
@@ -662,8 +795,3 @@ | ||
Request: TediousRequest, | ||
fix: function() { | ||
if (!FIXED) { | ||
require('./tedious-fix'); | ||
return FIXED = true; | ||
} | ||
} | ||
fix: function() {} | ||
}; | ||
@@ -670,0 +798,0 @@ }; |
@@ -19,3 +19,3 @@ { | ||
], | ||
"version": "0.5.0", | ||
"version": "0.5.1", | ||
"main": "index.js", | ||
@@ -33,7 +33,7 @@ "repository": { | ||
"dependencies": { | ||
"tedious": ">=0.1.5", | ||
"tedious": ">=0.2.1", | ||
"generic-pool": ">=2.0.4" | ||
}, | ||
"devDependencies": { | ||
"coffee-script": ">=1.6.2", | ||
"coffee-script": ">=1.7.1", | ||
"mocha": ">=1.12.0" | ||
@@ -45,5 +45,5 @@ }, | ||
"scripts": { | ||
"test": "mocha --expose-gc", | ||
"test": "mocha", | ||
"prepublish": "coffee --compile --output ./lib ./src" | ||
} | ||
} |
251
README.md
@@ -5,3 +5,3 @@ # node-mssql [![Dependency Status](https://david-dm.org/patriksimek/node-mssql.png)](https://david-dm.org/patriksimek/node-mssql) [![NPM version](https://badge.fury.io/js/mssql.png)](http://badge.fury.io/js/mssql) | ||
There are some TDS modules which offer functionality to communicate with MSSQL databases but none of them does offer enough comfort - implementation takes a lot of lines of code. So I decided to create this module, that make work as easy as it could without loosing any important functionality. node-mssql uses other TDS modules as drivers and offer easy to use unified interface. It also add some extra features and bug fixes. | ||
There are some TDS modules which offer functionality to communicate with MSSQL databases but none of them does offer enough comfort - implementation takes a lot of lines of code. So I decided to create this module, that make work as easy as it could without losing any important functionality. node-mssql uses other TDS modules as drivers and offer easy to use unified interface. It also add extra features and bug fixes. | ||
@@ -14,2 +14,3 @@ There is also [co](https://github.com/visionmedia/co) warpper available - [co-mssql](https://github.com/patriksimek/co-mssql). | ||
- Parametrized Stored Procedures in [node-tds](https://github.com/cretz/node-tds) and [Microsoft Driver for Node.js for SQL Server](https://github.com/WindowsAzure/node-sqlserver) | ||
- Serialization of Geography and Geometry CLR types | ||
- Injects original TDS modules with enhancements and bug fixes | ||
@@ -22,22 +23,18 @@ | ||
## What's new in 0.5.0 | ||
## What's new in 0.5.1 (stable, npm) | ||
- You can now attach event listeners to `Connection` (`connect`, `close`), `Transaction` (`begin`, `commit`, `rollback`) and `Request` (`row`, `recordset`, `done`) | ||
- You can now set length of Char, NChar and Binary output parameters | ||
- You can now change default transaction isolation level | ||
- Errors are now splitted to three categories for better error handling - `ConnectionError`, `TransactionError`, `ReqestError` | ||
- New features and bug fixes for [Tedious](https://github.com/pekim/tedious) | ||
- Binary and VarBinary types are now available as input and output parameters | ||
- Image type is now available as input parameter | ||
- Binary, VarBinary and Image types are now returned as buffer (was array) | ||
- Transaction isolationLevel default is now `READ_COMMITED` (was `READ_UNCOMMITED`) | ||
- Fixed issue when zero value was casted as null when using BigInt as input parameter | ||
- Fixed issue when dates before 1900/01/01 in input parameters resulted in "Out of bounds" error | ||
- New features and bug fixes for [node-tds](https://github.com/cretz/node-tds) | ||
- UniqueIdentifier type in now available as input and output parameter | ||
- UniqueIdentifier type is now parsed correctly as string value (was buffer) | ||
- Text, NText, Char, NChar, VarChar and NVarChar input parameters has correct lengths | ||
- Fixed `Error` messages | ||
- New features and bug fixes for [Microsoft Driver for Node.js for SQL Server](https://github.com/WindowsAzure/node-sqlserver) | ||
- Char, NChar, Xml, Text, NText and VarBinary types are now correctly functional as output parameters | ||
- Updated to new Tedious 0.2.1 | ||
- Added support for TDS 7.4 | ||
- Added request cancelation | ||
- Added support for UDT, TVP, Time, Date, DateTime2 and DateTimeOffset data types | ||
- Numeric, Decimal, SmallMoney and Money are now supported as input parameters | ||
- Fixed compatibility with TDS 7.1 (SQL Server 2000) | ||
- Minor fixes | ||
- You can now easily setup type's length/scale (`sql.VarChar(50)`) | ||
- Serialization of [Geography and Geometry](#geography) CLR types | ||
- Support for creating [Table-Value Parameters](#tvp) (`var tvp = new sql.Table()`) | ||
- Output parameters are now Input-Output and can handle initial value | ||
- Option to choose whether to pass/receive times in UTC or local time | ||
- Connecting to named instances simplified | ||
- Default SQL data type for JS String type is now NVarChar (was VarChar) | ||
@@ -56,3 +53,3 @@ ## Installation | ||
password: '...', | ||
server: 'localhost', | ||
server: 'localhost', // You can use 'localhost\\instance' to connect to named instance | ||
database: '...' | ||
@@ -77,3 +74,3 @@ } | ||
request.input('input_parameter', sql.Int, 10); | ||
request.output('output_parameter', sql.Int); | ||
request.output('output_parameter', sql.VarChar(50)); | ||
request.execute('procedure_name', function(err, recordsets, returnValue) { | ||
@@ -96,3 +93,3 @@ // ... error checks | ||
password: '...', | ||
server: 'localhost', | ||
server: 'localhost', // You can use 'localhost\\instance' to connect to named instance | ||
database: '...' | ||
@@ -109,3 +106,3 @@ } | ||
// ... error checks | ||
console.dir(recordset); | ||
@@ -118,6 +115,6 @@ }); | ||
request.input('input_parameter', sql.Int, value); | ||
request.output('output_parameter', sql.Int); | ||
request.output('output_parameter', sql.VarChar(50)); | ||
request.execute('procedure_name', function(err, recordsets, returnValue) { | ||
// ... error checks | ||
console.dir(recordsets); | ||
@@ -151,2 +148,3 @@ }); | ||
* [query](#query) | ||
* [cancel](#cancel) | ||
@@ -162,2 +160,4 @@ ### Transactions | ||
* [Geography and Geometry](#geography) | ||
* [Table-Value Parameter](#tvp) | ||
* [Errors](#errors) | ||
@@ -188,9 +188,9 @@ * [Metadata](#meta) | ||
- **driver** - Driver to use (default: `tedious`). Possible values: `tedious` or `msnodesql`. | ||
- **driver** - Driver to use (default: `tedious`). Possible values: `tedious`, `msnodesql` or `tds`. | ||
- **user** - User name to use for authentication. | ||
- **password** - Password to use for authentication. | ||
- **server** - Hostname to connect to. | ||
- **port** - Port to connect to (default: `1433`). | ||
- **server** - Server to connect to. You can use 'localhost\\instance' to connect to named instance. | ||
- **port** - Port to connect to (default: `1433`). Don't set when connecting to named instance. | ||
- **database** - Database to connect to (default: dependent on server configuration). | ||
- **timeout** - Connection timeout in ms (default: 15000). | ||
- **timeout** - Connection timeout in ms (default: `15000`). | ||
- **pool.max** - The maximum number of connections there can be in the pool (default: `10`). | ||
@@ -203,5 +203,8 @@ - **pool.min** - The minimun of connections there can be in the pool (default: `0`). | ||
- **options** - Object of Tedious specific options. More information: http://pekim.github.io/tedious/api-connection.html | ||
- **options.instanceName** - The instance name to connect to. The SQL Server Browser service must be running on the database server, and UDP port 1444 on the database server must be reachable. | ||
- **options.useUTC** - A boolean determining whether or not use UTC time for values without time zone offset (default: `true`). | ||
- **options.encrypt** - A boolean determining whether or not the connection will be encrypted (default: `false`) Encryption support is experimental. | ||
- **options.tdsVersion** - The version of TDS to use (default: `7_4`, available: `7_2`, `7_3_A`, `7_3_B`, `7_4`). | ||
__This module update Tedious driver with some extra features and bug fixes by overriding some of its internal functions. If you want to disable this, require module with `var sql = require('mssql/nofix')`.__ | ||
More information about Tedious specific options: http://pekim.github.io/tedious/api-connection.html | ||
@@ -211,16 +214,25 @@ <a name="cfg-msnodesql" /> | ||
This driver is not part of the default package and must be installed separately by 'npm install msnodesql'. If you are looking for compiled binaries, see [node-sqlserver-binary](https://github.com/jorgeazevedo/node-sqlserver-binary). | ||
This driver is not part of the default package and must be installed separately by `npm install msnodesql`. If you are looking for compiled binaries, see [node-sqlserver-binary](https://github.com/jorgeazevedo/node-sqlserver-binary). | ||
- **options.instanceName** - The instance name to connect to. The SQL Server Browser service must be running on the database server, and UDP port 1444 on the database server must be reachable. | ||
- **connectionString** - Connection string (default: see below). | ||
- **options.trustedConnection** - Use Windows Authentication (default: `false`). | ||
- **options.useUTC** - A boolean determining whether or not use UTC time for values without time zone offset (default: `true`). | ||
Default connection string when connecting to port: | ||
``` | ||
Driver={SQL Server Native Client 11.0};Server=#{server},#{port};Database=#{database};Uid=#{user};Pwd=#{password};Connection Timeout=#{timeout}; | ||
Driver={SQL Server Native Client 11.0};Server={#{server},#{port}};Database={#{database}};Uid={#{user}};Pwd={#{password}};Trusted_Connection={#{trusted}}; | ||
``` | ||
Default connection string when connecting to named instance: | ||
``` | ||
Driver={SQL Server Native Client 11.0};Server={#{server}\\#{instance}};Database={#{database}};Uid={#{user}};Pwd={#{password}};Trusted_Connection={#{trusted}}; | ||
``` | ||
<a name="cfg-node-tds" /> | ||
### node-tds | ||
This driver is not part of the default package and must be installed separately by 'npm install tds'. | ||
This driver is not part of the default package and must be installed separately by `npm install tds`. | ||
__This module update node-tds driver with some extra features and bug fixes by overriding some of its internal functions. If you want to disable this, require module with `var sql = require('mssql/nofix')`.__ | ||
_This module update node-tds driver with extra features and bug fixes by overriding some of its internal functions. If you want to disable this, require module with `var sql = require('mssql/nofix')`._ | ||
@@ -347,8 +359,10 @@ <a name="connection" /> | ||
- `String` -> `sql.VarChar` | ||
- `String` -> `sql.NVarChar` | ||
- `Number` -> `sql.Int` | ||
- `Boolean` -> `sql.Bit` | ||
- `Date` -> `sql.DateTime` | ||
- `Buffer` -> `sql.VarBinary` | ||
- `sql.Table` -> `sql.TVP` | ||
Default data type for unknown object is `sql.VarChar`. | ||
Default data type for unknown object is `sql.NVarChar`. | ||
@@ -370,3 +384,3 @@ You can define you own type map. | ||
<a name="output" /> | ||
### output(name, type, [length]) | ||
### output(name, type, [value]) | ||
@@ -379,3 +393,3 @@ Add an output parameter to the request. | ||
- **type** - SQL data type of output parameter. | ||
- **length** - Expected length (for Char, Binary). Optional. | ||
- **value** - Output parameter value initial value. `undefined` and `NaN` values are automatically converted to `null` values. Optional. | ||
@@ -386,3 +400,3 @@ __Example__ | ||
request.output('output_parameter', sql.Int); | ||
request.output('output_parameter', sql.Char, 50); | ||
request.output('output_parameter', sql.VarChar(50), 'abc'); | ||
``` | ||
@@ -429,6 +443,28 @@ | ||
--------------------------------------- | ||
<a name="cancel" /> | ||
### cancel() | ||
Cancel currently executing request. Return `true` if cancelation packet was send successfully. Not available in `msnodesql` and `tds` drivers. | ||
__Example__ | ||
```javascript | ||
var request = new sql.Request(); | ||
request.query('waitfor delay \'00:00:05\'; select 1 as number', function(err, recordset) { | ||
console.log(err instanceof sql.RequestError); // true | ||
console.log(err.message); // Canceled. | ||
console.log(err.code); // ECANCEL | ||
// ... | ||
}); | ||
request.cancel(); | ||
``` | ||
<a name="transaction" /> | ||
## Transactions | ||
**Important:** always use `Transaction` class to create transactions - it ensures that all your requests are executed on one connection. Once you call `begin`, a single connection is aquired from the connection pool and all subsequent requests (initialized with the `Transaction` object) are executed exclusively on this connection. After you call `commit` or `rollback`, connection is then released back to the connection pool. | ||
**Important:** always use `Transaction` class to create transactions - it ensures that all your requests are executed on one connection. Once you call `begin`, a single connection is aquired from the connection pool and all subsequent requests (initialized with the `Transaction` object) are executed exclusively on this connection. Transaction also contains queue to make sure your requests are executed in series. After you call `commit` or `rollback`, connection is then released back to the connection pool. | ||
@@ -538,3 +574,76 @@ ```javascript | ||
<a name="data-types" /> | ||
<a name="geography" /> | ||
## Geography and Geometry | ||
node-mssql has built-in serializer for Geography and Geometry CLR data types. | ||
```sql | ||
select geography::STGeomFromText('LINESTRING(-122.360 47.656, -122.343 47.656 )', 4326) | ||
select geometry::STGeomFromText('LINESTRING (100 100 10.3 12, 20 180, 180 180)', 0) | ||
``` | ||
Results in: | ||
```javascript | ||
{ srid: 4326, | ||
version: 1, | ||
points: [ { x: 47.656, y: -122.36 }, { x: 47.656, y: -122.343 } ], | ||
figures: [ { attribute: 1, pointOffset: 0 } ], | ||
shapes: [ { parentOffset: -1, figureOffset: 0, type: 2 } ], | ||
segments: [] } | ||
{ srid: 0, | ||
version: 1, | ||
points: | ||
[ { x: 100, y: 100, z: 10.3, m: 12 }, | ||
{ x: 20, y: 180, z: NaN, m: NaN }, | ||
{ x: 180, y: 180, z: NaN, m: NaN } ], | ||
figures: [ { attribute: 1, pointOffset: 0 } ], | ||
shapes: [ { parentOffset: -1, figureOffset: 0, type: 2 } ], | ||
segments: [] } | ||
``` | ||
<a name="tvp" /> | ||
## Table-Value Parameter (TVP) | ||
Supported on SQL Server 2008 and later. Not supported by optional drivers `msnodesql` and `tds`. You can pass a data table as a parameter to stored procedure. First, we have to create custom type in our database. | ||
```sql | ||
CREATE TYPE TestType AS TABLE ( a VARCHAR(50), b INT ); | ||
``` | ||
Next we will need a stored procedure. | ||
```sql | ||
CREATE PROCEDURE MyCustomStoredProcedure (@tvp TestType readonly) AS SELECT * FROM @tvp | ||
``` | ||
Now let's go back to our Node.js app. | ||
```javascript | ||
var tvp = new sql.Table() | ||
// Columns must correspond with type we have created in database. | ||
tvp.columns.add('a', sql.VarChar(50)); | ||
tvp.columns.add('b', sql.Int); | ||
// Add rows | ||
tvp.rows.add('hello tvp', 777); // Values are in same order as columns. | ||
``` | ||
You can send table as a parameter to stored procedure. | ||
```javascript | ||
var request = new sql.Request(); | ||
request.input('tvp', tvp); | ||
request.execute('MyCustomStoredProcedure', function(err, recordsets, returnValue) { | ||
// ... error checks | ||
console.dir(recordsets[0][0]); // {a: 'hello tvp', b: 777} | ||
}); | ||
``` | ||
**TIP**: You can also create Table variable from any recordset with `recordset.toTable()`. | ||
<a name="errors" /> | ||
## Errors | ||
@@ -550,3 +659,3 @@ | ||
<a name="data-types" /> | ||
<a name="meta" /> | ||
## Metadata | ||
@@ -568,6 +677,6 @@ | ||
```javascript | ||
{ first: { name: 'first', length: 10, type: [sql.Int] }, | ||
second: { name: 'second', length: 4, type: [sql.VarChar] } } | ||
``` | ||
{ first: { name: 'first', size: 10, type: { name: 'int' } }, | ||
second: { name: 'second', size: 4, type: { name: 'varchar' } } } | ||
``` | ||
@@ -577,10 +686,29 @@ <a name="data-types" /> | ||
You can define data types with length/precision/scale: | ||
```javascript | ||
request.input("name", sql.VarChar, "abc"); // varchar(3) | ||
request.input("name", sql.VarChar(50), "abc"); // varchar(50) | ||
request.input("name", sql.VarChar(sql.MAX), "abc"); // varchar(MAX) | ||
request.output("name", sql.VarChar); // varchar(8000) | ||
request.output("name", sql.VarChar, "abc"); // varchar(3) | ||
request.input("name", sql.Decimal, 155.33); // decimal(18, 0) | ||
request.input("name", sql.Decimal(10), 155.33); // decimal(10, 0) | ||
request.input("name", sql.Decimal(10, 2), 155.33); // decimal(10, 2) | ||
request.input("name", sql.DateTime2, new Date()); // datetime2(7) | ||
request.input("name", sql.DateTime2(5), new Date()); // datetime2(5) | ||
``` | ||
List of supported data types: | ||
``` | ||
sql.Bit | ||
sql.BigInt | ||
sql.Decimal | ||
sql.Decimal ([precision], [scale]) | ||
sql.Float | ||
sql.Int | ||
sql.Money | ||
sql.Numeric | ||
sql.Numeric ([precision], [scale]) | ||
sql.SmallInt | ||
@@ -591,13 +719,15 @@ sql.SmallMoney | ||
sql.Char | ||
sql.NChar | ||
sql.Char ([length]) | ||
sql.NChar ([length]) | ||
sql.Text | ||
sql.NText | ||
sql.VarChar | ||
sql.NVarChar | ||
sql.VarChar ([length]) | ||
sql.NVarChar ([length]) | ||
sql.Xml | ||
sql.Time ([scale]) | ||
sql.Date | ||
sql.DateTime | ||
sql.DateTimeOffset | ||
sql.DateTime2 ([scale]) | ||
sql.DateTimeOffset ([scale]) | ||
sql.SmallDateTime | ||
@@ -608,6 +738,12 @@ | ||
sql.Binary | ||
sql.VarBinary | ||
sql.VarBinary ([length]) | ||
sql.Image | ||
sql.UDT | ||
sql.Geography | ||
sql.Geometry | ||
``` | ||
To setup MAX length for `VarChar`, `NVarChar` and `VarBinary` use `sql.MAX` length. | ||
<a name="verbose" /> | ||
@@ -651,5 +787,5 @@ ## Verbose Mode | ||
### Tedious | ||
### msnodesql | ||
- If you're facing problems with text codepage, try using NVarChar as default data type for string values - `sql.map.register(String, sql.NVarChar)`. | ||
- msnodesql 0.2.1 contains bug in DateTimeOffset ([reported](https://github.com/WindowsAzure/node-sqlserver/issues/160)) | ||
@@ -659,2 +795,3 @@ ### node-tds | ||
- If you're facing problems with date, try changing your tsql language `set language 'English';`. | ||
- node-tds 0.1.0 doesn't support connecting to named instances. | ||
- node-tds 0.1.0 contains bug and return same value for columns with same name. | ||
@@ -661,0 +798,0 @@ - node-tds 0.1.0 doesn't support codepage of input parameters. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
206707
27
3320
788
Updatedtedious@>=0.2.1