mssql2
Version:
Microsoft SQL Server client for Node.js (fork)
1,542 lines (1,151 loc) • 39.1 kB
text/coffeescript
{EventEmitter} = require 'events'
util = require 'util'
fs = require 'fs'
{TYPES, declare} = require './datatypes'
ISOLATION_LEVEL = require './isolationlevel'
DRIVERS = ['msnodesql', 'tedious', 'tds', 'msnodesqlv8']
Table = require './table'
ConnectionString = require './connectionstring'
global_connection = null
map = []
###
Register you own type map.
**Example:**
```
sql.map.register(MyClass, sql.Text);
```
You can also overwrite default type map.
```
sql.map.register(Number, sql.BigInt);
```
module.exports.map
{*} jstype JS data type.
{*} sqltype SQL data type.
###
map.register = (jstype, sqltype) ->
for item, index in @ when item.js is jstype
index, 1
break
js: jstype
sql: sqltype
null
map.register String, TYPES.NVarChar
map.register Number, TYPES.Int
map.register Boolean, TYPES.Bit
map.register Date, TYPES.DateTime
map.register Buffer, TYPES.VarBinary
map.register Table, TYPES.TVP
###
###
getTypeByValue = (value) ->
if value is null or value is undefined then return TYPES.NVarChar
switch typeof value
when 'string'
for item in map when item.js is String
return item.sql
return TYPES.NVarChar
when 'number'
for item in map when item.js is Number
return item.sql
return TYPES.Int
when 'boolean'
for item in map when item.js is Boolean
return item.sql
return TYPES.Bit
when 'object'
for item in map when value instanceof item.js
return item.sql
return TYPES.NVarChar
else
return TYPES.NVarChar
###
Class Connection.
Internally, each `Connection` instance is a separate pool of TDS connections. Once you create a new `Request`/`Transaction`/`Prepared Statement`, a new TDS connection is acquired from the pool and reserved for desired action. Once the action is complete, connection is released back to the pool.
{Boolean} connected If true, connection is established.
{Boolean} connecting If true, connection is being established.
{*} driver Reference to configured Driver.
connect Dispatched after connection has established.
close Dispatched after connection has closed a pool (by calling close).
###
class Connection extends EventEmitter
connected: false
connecting: false
driver: null
###
Create new Connection.
{Object|String} config Connection configuration object or connection string.
[callback] A callback which is called after connection has established, or an error has occurred.
{Error} err Error on error, otherwise null.
###
constructor: ( , callback) ->
if 'string' is typeof
try
= ConnectionString.resolve
catch ex
if callback
return callback ex
else
throw ex
# set defaults
.driver ?= 'tedious'
.port ?= 1433
.options ?= {}
.stream ?= false
.parseJSON ?= false
if /^(.*)\\(.*)$/.exec .server
.server = RegExp.$1
.options.instanceName = RegExp.$2
if .driver in DRIVERS
= require("./#{@config.driver}")
else if typeof .driver is 'function'
= .driver
else
err = new ConnectionError "Unknown driver #{@config.driver}!", 'EDRIVER'
if callback
return callback err
else
throw err
# fix the driver by default
if module.exports.fix then .fix()
if callback then callback
###
Write message to debug stream.
###
_debug: (msg) ->
?.write "#{String(msg).replace(/\x1B\[[0-9;]*m/g, '')}\n"
###
Initializes driver for this connection. Separated from constructor and used by co-mssql.
{Function} driver Loaded driver.
{Connection}
###
initializeDriver: (driver) ->
driver Connection, Transaction, Request, ConnectionError, TransactionError, RequestError
###
Creates a new connection pool with one active connection. This one initial connection serves as a probe to find out whether the configuration is valid.
[callback] A callback which is called after connection has established, or an error has occurred. If omited, method returns Promise.
{Error} err Error on error, otherwise null.
{Connection|Promise}
###
connect: (callback) ->
if callback?
return callback
new module.exports.Promise (resolve, reject) =>
(err) =>
if err then return reject err
resolve @
_connect: (callback) ->
if not
return callback new ConnectionError "Connection was closed. Create a new instance."
if
return callback new ConnectionError "Database is already connected! Call close before connecting to different database.", 'EALREADYCONNECTED'
if
return callback new ConnectionError "Already connecting to database! Call close before connecting to different database.", 'EALREADYCONNECTING'
go = =>
= true
.Connection::connect.call @, , (err) =>
unless then return
= false
if err
if
.removeAllListeners()
.end()
= null
else
= true
'connect'
callback err
if .debug
= fs.createWriteStream "./mssql_debug_#{Date.now()}.log"
.once 'open', go
.on 'error', (err) ->
if or
# error after successful open
console.error err.stack
else
.removeListener 'open', go
callback new ConnectionError("Failed to open debug stream. #{err.message}", 'EDEBUG')
else
go()
@
###
Close all active connections in the pool.
[callback] A callback which is called after connection has closed, or an error has occurred. If omited, method returns Promise.
{Error} err Error on error, otherwise null.
{Connection|Promise}
###
close: (callback) ->
if callback?
return callback
new module.exports.Promise (resolve, reject) =>
(err) ->
if err then return reject err
resolve()
_close: (callback) ->
if
.removeAllListeners()
.end()
= null
if
= false
.Connection::close.call @, (err) =>
callback err
= null
else if
= false
.Connection::close.call @, (err) =>
unless err
= false
'close'
callback err
= null
else
#if the connection was not connecting or connected, invoke the callback right away
callback null
@
###
Returns new request using this connection.
{Request}
###
request: ->
new Request @
###
Returns new transaction using this connection.
{Transaction}
###
transaction: ->
new Transaction @
###
Creates a new query using this connection from a tagged template string.
{Array} strings Array of string literals.
{...*} keys Values.
{Request}
###
query: (strings, values...) ->
new Request(@)._template 'query', strings, values
###
Creates a new batch using this connection from a tagged template string.
{Array} strings Array of string literals.
{...*} keys Values.
{Request}
###
batch: (strings, values...) ->
new Request(@)._template 'batch', strings, values
###
Class PreparedStatement.
IMPORTANT: Rememeber that each prepared statement means one reserved connection from the pool. Don't forget to unprepare a prepared statement!
{Connection} connection Reference to used connection.
{Boolean} multiple If `true`, `execute` will handle multiple recordsets.
{String} statement Prepared SQL statement.
{Request} lastRequest References instance of most recent Request created by executing a statement.
###
class PreparedStatement extends EventEmitter
_pooledConnection: null
_queue: null
_working: false # if true, there is a request running at the moment
_handle: 0 # sql prepared statement handle
connection: null # sql.Connection
transaction: null # !null in case we're in transaction
prepared: false
statement: null
parameters: null
multiple: false
stream: null
lastRequest: null
###
Create new Prepared Statement.
{String} statement SQL statement.
{Connection} [connection] If ommited, global connection is used instead.
###
constructor: (connection) ->
if connection instanceof Transaction
= connection
= connection.connection
else if connection instanceof Connection
= connection
else
= global_connection
= []
= {}
###
Add an input parameter to the prepared statement.
**Example:**
```
statement.input('input_parameter', sql.Int);
statement.input('input_parameter', sql.VarChar(50));
```
{String} name Name of the input parameter without @ char.
{*} type SQL data type of input parameter.
{PreparedStatement}
###
input: (name, type) ->
if (/(--| |\/\*|\*\/|')/).test name
throw new PreparedStatementError "SQL injection warning for param '#{name}'", 'EINJECT'
if arguments.length < 2
throw new PreparedStatementError "Invalid number of arguments. 2 arguments expected.", 'EARGS'
if type instanceof Function
type = type()
[name] =
name: name
type: type.type
io: 1
length: type.length
scale: type.scale
precision: type.precision
tvpType: type.tvpType
@
###
Add an output parameter to the prepared statement.
**Example:**
```
statement.output('output_parameter', sql.Int);
statement.output('output_parameter', sql.VarChar(50));
```
{String} name Name of the output parameter without @ char.
{*} type SQL data type of output parameter.
{PreparedStatement}
###
output: (name, type) ->
if (/(--| |\/\*|\*\/|')/).test name
throw new PreparedStatementError "SQL injection warning for param '#{name}'", 'EINJECT'
if arguments.length < 2
throw new PreparedStatementError "Invalid number of arguments. 2 arguments expected.", 'EARGS'
if type instanceof Function
type = type()
[name] =
name: name
type: type.type
io: 2
length: type.length
scale: type.scale
precision: type.precision
@
###
Prepare a statement.
{String} [statement] SQL statement to prepare.
[callback] A callback which is called after preparation has completed, or an error has occurred. If omited, method returns Promise.
{Error} err Error on error, otherwise null.
{PreparedStatement|Promise}
###
prepare: (statement, callback) ->
if callback?
return statement, callback
new module.exports.Promise (resolve, reject) =>
statement, (err) =>
if err then return reject err
resolve @
_prepare: (statement, callback) ->
if
callback new PreparedStatementError "Statement is already prepared.", 'EALREADYPREPARED'
return @
if typeof statement is 'function'
callback = statement
statement = undefined
= statement if statement?
done = (err, connection) =>
if err then return callback err
= connection
req = new Request @
req.stream = false
req.output 'handle', TYPES.Int
req.input 'params', TYPES.NVarChar, ("@#{name} #{declare(param.type, param)}#{if param.io is 2 then " output" else ""}" for name, param of ).join(',')
req.input 'stmt', TYPES.NVarChar,
req.execute 'sp_prepare', (err) =>
if err
if
.next()
else
.pool.release
= null
return callback err
= req.parameters.handle.value
callback null
if
unless ._pooledConnection
callback new TransactionError "Transaction has not begun. Call begin() first.", 'ENOTBEGUN'
return @
.queue done
else
.pool.acquire done
@
###
Execute next request in queue.
{PreparedStatement}
###
next: ->
if .length
# defer processing of next request
process.nextTick =>
.shift() null,
else
= false
@
###
Add request to queue for connection. If queue is empty, execute the request immediately.
callback A callback to call when connection in ready to execute request.
{Error} err Error on error, otherwise null.
{*} conn Internal driver's connection.
{PreparedStatement}
###
queue: (callback) ->
unless
callback new PreparedStatementError "Statement is not prepared. Call prepare() first.", 'ENOTPREPARED'
return @
if
.push callback
else
= true
callback null,
@
###
Execute a prepared statement.
{String} values An object whose names correspond to the names of parameters that were added to the prepared statement before it was prepared.
[callback] A callback which is called after execution has completed, or an error has occurred. If omited, method returns Promise.
{Error} err Error on error, otherwise null.
{Request|Promise}
###
execute: (values, callback) ->
if callback?
return values, callback
new module.exports.Promise (resolve, reject) =>
values, (err, recordset) ->
if err then return reject err
resolve recordset
_execute: (values, callback) ->
req = = new Request @
req.stream = if ?
req.input 'handle', TYPES.Int,
# copy parameters with new values
for name, param of
req.parameters[name] =
name: name
type: param.type
io: param.io
value: values[name]
length: param.length
scale: param.scale
precision: param.precision
req.execute 'sp_execute', (err, recordsets, returnValue) =>
if err then return callback err
callback null, (if then recordsets else recordsets[0]), req.rowsAffected
req
###
Unprepare a prepared statement.
[callback] A callback which is called after unpreparation has completed, or an error has occurred. If omited, method returns Promise.
{Error} err Error on error, otherwise null.
{PreparedStatement|Promise}
###
unprepare: (callback) ->
if callback?
return callback
new module.exports.Promise (resolve, reject) =>
(err) ->
if err then return reject err
resolve()
_unprepare: (callback) ->
unless
callback new PreparedStatementError "Statement is not prepared. Call prepare() first.", 'ENOTPREPARED'
return @
done = (err) =>
if err then return callback err
if
.next()
else
.pool.release
= null
= 0
callback null
req = new Request @
req.stream = false
req.input 'handle', TYPES.Int,
req.execute 'sp_unprepare', done
@
###
Class Transaction.
{Connection} connection Reference to used connection.
{Number} isolationLevel Controls the locking and row versioning behavior of TSQL statements issued by a connection. READ_COMMITTED by default.
{String} name Transaction name. Empty string by default.
begin Dispatched when transaction begin.
commit Dispatched on successful commit.
rollback Dispatched on successful rollback.
###
class Transaction extends EventEmitter
_pooledConnection: null
_queue: null
_aborted: false
_working: false # if true, there is a request running at the moment
name: ""
connection: null # sql.Connection
isolationLevel: ISOLATION_LEVEL.READ_COMMITTED
###
Create new Transaction.
{Connection} [connection] If ommited, global connection is used instead.
###
constructor: (connection) ->
= connection ? global_connection
= []
###
###
_abort: =>
.driver.Transaction::_abort.call @
###
Begin a transaction.
{Number} [isolationLevel] Controls the locking and row versioning behavior of TSQL statements issued by a connection.
[callback] A callback which is called after transaction has began, or an error has occurred. If omited, method returns Promise.
{Error} err Error on error, otherwise null.
{Transaction|Promise}
###
begin: (isolationLevel, callback) ->
if isolationLevel instanceof Function
callback = isolationLevel
isolationLevel = undefined
if callback?
return isolationLevel, callback
new module.exports.Promise (resolve, reject) =>
isolationLevel, (err) =>
if err then return reject err
resolve @
_begin: (isolationLevel, callback) ->
= isolationLevel if isolationLevel?
if
callback new TransactionError "Transaction has already begun.", 'EALREADYBEGUN'
return @
.driver.Transaction::begin.call @, (err) =>
unless err then 'begin'
callback err
@
###
Commit a transaction.
[callback] A callback which is called after transaction has commited, or an error has occurred. If omited, method returns Promise.
{Error} err Error on error, otherwise null.
{Transaction|Promise}
###
commit: (callback) ->
if callback?
return callback
new module.exports.Promise (resolve, reject) =>
(err) ->
if err then return reject err
resolve()
_commit: (callback) ->
unless
callback new TransactionError "Transaction has not begun. Call begin() first.", 'ENOTBEGUN'
return @
if
callback new TransactionError "Can't commit transaction. There is a request in progress.", 'EREQINPROG'
return @
if .length
callback new TransactionError "Can't commit transaction. There are request in queue.", 'EREQINPROG'
return @
.driver.Transaction::commit.call @, (err) =>
unless err then 'commit'
callback err
@
###
Execute next request in queue.
{Transaction}
###
next: ->
if
toAbort =
= []
# this must be async to ensure it is not processed earlier than the request that caused abortion of this transaction
process.nextTick =>
while toAbort.length
toAbort.shift() new TransactionError "Transaction aborted.", "EABORT"
# this must be synchronous so we can rollback a transaction or commit transaction in last request's callback
= false
if .length
process.nextTick =>
if then return () # transaction aborted manually
= true
.shift() null,
@
###
Add request to queue for connection. If queue is empty, execute the request immediately.
callback A callback to call when connection in ready to execute request.
{Error} err Error on error, otherwise null.
{*} conn Internal driver's connection.
{Transaction}
###
queue: (callback) ->
unless
callback new TransactionError "Transaction has not begun. Call begin() first.", 'ENOTBEGUN'
return @
if or .length
.push callback
else
= true
callback null,
@
###
Returns new request using this transaction.
{Request}
###
request: ->
new Request @
###
Rollback a transaction.
[callback] A callback which is called after transaction has rolled back, or an error has occurred. If omited, method returns Promise.
{Error} err Error on error, otherwise null.
{Transaction|Promise}
###
rollback: (callback) ->
if callback?
return callback
new module.exports.Promise (resolve, reject) =>
(err) ->
if err then return reject err
resolve()
_rollback: (callback) ->
if
callback new TransactionError "Transaction has been aborted.", 'EABORT'
return @
unless
callback new TransactionError "Transaction has not begun. Call begin() first.", 'ENOTBEGUN'
return @
if
callback new TransactionError "Can't rollback transaction. There is a request in progress.", 'EREQINPROG'
return @
if .length
= true
.driver.Transaction::rollback.call @, (err) =>
unless err then 'rollback',
callback err
@
###
Class Request.
{Connection} connection Reference to used connection.
{Transaction} transaction Reference to transaction when request was created in transaction.
{*} parameters Collection of input and output parameters.
{Boolean} verbose If `true`, debug messages are printed to message log.
{Boolean} multiple If `true`, `query` will handle multiple recordsets (`execute` always expect multiple recordsets).
{Boolean} canceled `true` if request was canceled.
recordset Dispatched when metadata for new recordset are parsed.
row Dispatched when new row is parsed.
done Dispatched when request is complete.
error Dispatched on error.
###
class Request extends EventEmitter
connection: null
transaction: null
pstatement: null
parameters: null
verbose: false
multiple: false
canceled: false
stream: null
rowsAffected: null
###
Create new Request.
{Connection|Transaction} connection If ommited, global connection is used instead.
###
constructor: (connection) ->
if connection instanceof Transaction
= connection
= connection.connection
else if connection instanceof PreparedStatement
= connection
= connection.connection
else if connection instanceof Connection
= connection
else
= global_connection
= {}
###
Log to a function if assigned. Else, use console.log.
###
_log: (out) ->
if typeof is "function" then out else console.log out
###
Fetch request from tagged template string.
###
_template: (method, strings, values) ->
command = [strings[0]]
for value, index in values
"param#{index + 1}", value
command.push "@param#{index + 1}", strings[index + 1]
@[method] command.join ''
###
Acquire connection for this request from connection.
###
_acquire: (callback) ->
if
.queue callback
else if
.queue callback
else
unless .pool
return callback new ConnectionError "Connection not yet open.", 'ENOTOPEN'
.pool.acquire callback
###
Makes the request dedicated to one connection.
###
_dedicated: (connection) ->
= (callback) -> callback null, connection
= ->
@
###
Release connection used by this request.
###
_release: (connection) ->
if
.next()
else if
.next()
else
.pool.release connection
###
Add an input parameter to the request.
**Example:**
```
request.input('input_parameter', value);
request.input('input_parameter', sql.Int, value);
```
{String} name Name of the input parameter without @ char.
{*} [type] SQL data type of input parameter. If you omit type, module automaticaly decide which SQL data type should be used based on JS data type.
{*} value Input parameter value. `undefined` and `NaN` values are automatically converted to `null` values.
{Request}
###
input: (name, type, value) ->
if (/(--| |\/\*|\*\/|')/).test name
throw new RequestError "SQL injection warning for param '#{name}'", 'EINJECT'
if arguments.length is 1
throw new RequestError "Invalid number of arguments. At least 2 arguments expected.", 'EARGS'
else if arguments.length is 2
value = type
type = getTypeByValue(value)
# support for custom data types
if value?.valueOf and value not instanceof Date then value = value.valueOf()
# undefined to null
if value is undefined then value = null
# NaN to null
if value isnt value then value = null
if type instanceof Function
type = type()
[name] =
name: name
type: type.type
io: 1
value: value
length: type.length
scale: type.scale
precision: type.precision
tvpType: type.tvpType
@
###
Add an output parameter to the request.
**Example:**
```
request.output('output_parameter', sql.Int);
request.output('output_parameter', sql.VarChar(50), 'abc');
```
{String} name Name of the output parameter without @ char.
{*} type SQL data type of output parameter.
{*} [value] Output parameter value initial value. `undefined` and `NaN` values are automatically converted to `null` values. Optional.
{Request}
###
output: (name, type, value) ->
unless type then type = TYPES.NVarChar
if (/(--| |\/\*|\*\/|')/).test name
throw new RequestError "SQL injection warning for param '#{name}'", 'EINJECT'
if type is TYPES.Text or type is TYPES.NText or type is TYPES.Image
throw new RequestError "Deprecated types (Text, NText, Image) are not supported as OUTPUT parameters.", 'EDEPRECATED'
# support for custom data types
if value?.valueOf and value not instanceof Date then value = value.valueOf()
# undefined to null
if value is undefined then value = null
# NaN to null
if value isnt value then value = null
if type instanceof Function
type = type()
[name] =
name: name
type: type.type
io: 2
value: value
length: type.length
scale: type.scale
precision: type.precision
@
###
Execute the SQL batch.
{String} batch T-SQL batch to be executed.
[callback] A callback which is called after execution has completed, or an error has occurred. If omited, method returns Promise.
{Error} err Error on error, otherwise null.
{*} recordset Recordset.
{Request|Promise}
###
batch: (batch, callback) ->
?= ?.config.stream
= 0
if or callback?
return batch, callback
new module.exports.Promise (resolve, reject) =>
batch, (err, recordset) ->
if err then return reject err
resolve recordset
_batch: (batch, callback) ->
unless
return process.nextTick =>
e = new RequestError "No connection is specified for that request.", 'ENOCONN'
if
'error', e
'done'
else
callback e
unless .connected
return process.nextTick =>
e = new ConnectionError "Connection is closed.", 'ECONNCLOSED'
if
'error', e
'done'
else
callback e
= false
.driver.Request::batch.call @, batch, (err, recordsets) =>
if
if err then 'error', err
'done',
else
callback err, recordsets,
@
###
Bulk load.
{Table} table SQL table.
[callback] A callback which is called after bulk load has completed, or an error has occurred. If omited, method returns Promise.
{Error} err Error on error, otherwise null.
{Request|Promise}
###
bulk: (table, callback) ->
?= ?.config.stream
if or callback?
return table, callback
new module.exports.Promise (resolve, reject) =>
table, (err, rowCount) ->
if err then return reject err
resolve rowCount
_bulk: (table, callback) ->
unless
return process.nextTick =>
e = new RequestError "No connection is specified for that request.", 'ENOCONN'
if
'error', e
'done'
else
callback e
unless .connected
return process.nextTick =>
e = new ConnectionError "Connection is closed.", 'ECONNCLOSED'
if
'error', e
'done'
else
callback e
= false
.driver.Request::bulk.call @, table, (err, rowCount) =>
if
if err then 'error', err
'done'
else
callback err, rowCount
@
###
Sets request to `stream` mode and pulls all rows from all recordsets to a given stream.
{Stream} stream Stream to pipe data into.
{Stream}
###
pipe: (stream) ->
= true
'row', stream.write.bind stream
'error', stream.emit.bind stream, 'error'
'done', -> setImmediate -> stream.end()
stream.emit 'pipe', @
stream
###
Execute the SQL command.
**Example:**
```
var request = new sql.Request();
request.query('select 1 as number', function(err, recordset) {
console.log(recordset[0].number); // return 1
// ...
});
```
You can enable multiple recordsets in querries by `request.multiple = true` command.
```
var request = new sql.Request();
request.multiple = true;
request.query('select 1 as number; select 2 as number', function(err, recordsets) {
console.log(recordsets[0][0].number); // return 1
console.log(recordsets[1][0].number); // return 2
// ...
});
```
{String} command T-SQL command to be executed.
[callback] A callback which is called after execution has completed, or an error has occurred. If omited, method returns Promise.
{Error} err Error on error, otherwise null.
{*} recordset Recordset.
{Request|Promise}
###
query: (command, callback) ->
?= ?.config.stream
= 0
if or callback?
return command, callback
new module.exports.Promise (resolve, reject) =>
command, (err, recordsets) ->
if err then return reject err
resolve recordsets
_query: (command, callback) ->
unless
return process.nextTick =>
e = new RequestError "No connection is specified for that request.", 'ENOCONN'
if
'error', e
'done'
else
callback e
unless .connected
return process.nextTick =>
e = new ConnectionError "Connection is closed.", 'ECONNCLOSED'
if
'error', e
'done'
else
callback e
= false
.driver.Request::query.call @, command, (err, recordsets) =>
if
if err then 'error', err
'done',
else
callback err, recordsets,
@
###
Call a stored procedure.
**Example:**
```
var request = new sql.Request();
request.input('input_parameter', sql.Int, value);
request.output('output_parameter', sql.Int);
request.execute('procedure_name', function(err, recordsets, returnValue) {
console.log(recordsets.length); // count of recordsets returned by procedure
console.log(recordset[0].length); // count of rows contained in first recordset
console.log(returnValue); // procedure return value
console.log(recordsets.returnValue); // procedure return value
console.log(request.parameters.output_parameter.value); // output value
// ...
});
```
{String} procedure Name of the stored procedure to be executed.
[callback] A callback which is called after execution has completed, or an error has occurred. If omited, method returns Promise.
{Error} err Error on error, otherwise null.
{Array} recordsets Recordsets.
{Number} returnValue Procedure return value.
{Request|Promise}
###
execute: (command, callback) ->
?= ?.config.stream
= 0
if or callback?
return command, callback
new module.exports.Promise (resolve, reject) =>
command, (err, recordset) ->
if err then return reject err
resolve recordset
_execute: (procedure, callback) ->
unless
return process.nextTick ->
e = new RequestError "No connection is specified for that request.", 'ENOCONN'
if
'error', e
'done'
else
callback e
unless .connected
return process.nextTick =>
e = new ConnectionError "Connection is closed.", 'ECONNCLOSED'
if
'error', e
'done'
else
callback e
= false
.driver.Request::execute.call @, procedure, (err, recordsets, returnValue) =>
if
if err then 'error', err
'done', returnValue,
else
callback err, recordsets, returnValue,
@
###
Cancel currently executed request.
{Request}
###
cancel: ->
= true
.driver.Request::cancel.call @
@
class ConnectionError extends Error
constructor: (message, code) ->
unless @ instanceof ConnectionError
if message instanceof Error
err = new ConnectionError message.message, message.code
Object.defineProperty err, 'originalError', value: message
Error.captureStackTrace err, arguments.callee
return err
else
err = new ConnectionError message
Error.captureStackTrace err, arguments.callee
return err
= .name
= message
= code if code?
super()
Error.captureStackTrace @,
class TransactionError extends Error
constructor: (message, code) ->
unless @ instanceof TransactionError
if message instanceof Error
err = new TransactionError message.message, message.code
Object.defineProperty err, 'originalError', value: message
Error.captureStackTrace err, arguments.callee
return err
else
err = new TransactionError message
Error.captureStackTrace err, arguments.callee
return err
= .name
= message
= code if code?
super()
Error.captureStackTrace @,
class RequestError extends Error
constructor: (message, code) ->
unless @ instanceof RequestError
if message instanceof Error
err = new RequestError message.message, message.code ? code
err.number = message.info?.number ? message.code # err.code is returned by msnodesql driver
err.lineNumber = message.info?.lineNumber
err.state = message.info?.state ? message.sqlstate # err.sqlstate is returned by msnodesql driver
err.class = message.info?.class ? message.info?.severity # err.severity is returned by tds
err.serverName = message.info?.serverName
err.procName = message.info?.procName
Object.defineProperty err, 'originalError', value: message
Error.captureStackTrace err, arguments.callee
return err
else
err = new RequestError message
Error.captureStackTrace err, arguments.callee
return err
= .name
= message
= code if code?
super()
Error.captureStackTrace @,
class PreparedStatementError extends Error
constructor: (message, code) ->
unless @ instanceof PreparedStatementError
if message instanceof Error
err = new PreparedStatementError message.message, message.code
err.originalError = message
Error.captureStackTrace err, arguments.callee
return err
else
err = new PreparedStatementError message
Error.captureStackTrace err, arguments.callee
return err
= .name
= message
= code
super()
Error.captureStackTrace @,
###
Open global connection.
{Object} config Connection configuration.
callback A callback which is called after connection has established, or an error has occurred.
{Error} err Error on error, otherwise null.
{Connection}
###
module.exports.connect = (config, callback) ->
global_connection = new Connection config
global_connection.connect callback
###
Close global connection.
{Connection}
###
module.exports.close = (callback) ->
global_connection?.close callback
###
Attach evnet handler to global connection.
{String} event Event name.
{Function} handler Event handler.
{Connection}
###
module.exports.on = (event, handler) ->
global_connection?.on event, handler
###
Creates a new query using global connection from a tagged template string.
{Array} strings Array of string literals.
{...*} keys Values.
{Request}
###
module.exports.query = (strings, values...) ->
new Request()._template 'query', strings, values
###
Creates a new batch using global connection from a tagged template string.
{Array} strings Array of string literals.
{...*} keys Values.
{Request}
###
module.exports.batch = (strings, values...) ->
new Request()._template 'batch', strings, values
module.exports.Connection = Connection
module.exports.Transaction = Transaction
module.exports.Request = Request
module.exports.Table = Table
module.exports.PreparedStatement = PreparedStatement
module.exports.ConnectionError = ConnectionError
module.exports.TransactionError = TransactionError
module.exports.RequestError = RequestError
module.exports.PreparedStatementError = PreparedStatementError
module.exports.ISOLATION_LEVEL = ISOLATION_LEVEL
module.exports.DRIVERS = DRIVERS
module.exports.TYPES = TYPES
module.exports.MAX = 65535 # (1 << 16) - 1
module.exports.map = map
module.exports.fix = true
module.exports.Promise = global.Promise ? require('promise')
# append datatypes to this modules export
for key, value of TYPES
module.exports[key] = value
module.exports[key.toUpperCase()] = value
# --- DEPRECATED IN 0.3.0 ------------------------------------------
module.exports.pool =
max: 10
min: 0
idleTimeoutMillis: 30000
module.exports.connection =
userName: ''
password: ''
server: ''
###
Initialize Tedious connection pool.
###
module.exports.init = ->
module.exports.connect
user: module.exports.connection.userName
password: module.exports.connection.password
server: module.exports.connection.server
options: module.exports.connection.options
driver: 'tedious'
pool: module.exports.pool