mssql 3.2.1 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.txt +6 -0
- package/README.md +98 -112
- package/lib/connectionstring.js +15 -6
- package/lib/msnodesql.js +40 -4
- package/lib/msnodesqlv8.js +40 -4
- package/lib/tds.js +11 -0
- package/lib/tedious.js +32 -2
- package/package.json +1 -1
- package/src/connectionstring.coffee +7 -3
- package/src/msnodesql.coffee +34 -2
- package/src/msnodesqlv8.coffee +34 -2
- package/src/tds.coffee +10 -0
- package/src/tedious.coffee +24 -0
package/CHANGELOG.txt
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
v3.3.0 (2016-05-06)
|
|
2
|
+
-------------------
|
|
3
|
+
[new] Added support for receiving informational messages
|
|
4
|
+
[new] Added JSON support for msnodesql and msnodesqlv8 drivers
|
|
5
|
+
[fix] Minor fixes in connection string parsing
|
|
6
|
+
|
|
1
7
|
v3.2.1 (2016-04-16)
|
|
2
8
|
-------------------
|
|
3
9
|
[fix] Added PreparedStatement.lastRequest to access internal Request when using Promises
|
package/README.md
CHANGED
|
@@ -68,83 +68,83 @@ sql.connect("mssql://username:password@localhost/database").then(function() {
|
|
|
68
68
|
});
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
If you're on Windows Azure, add `?encrypt=true` to your connection string. See [docs](#
|
|
71
|
+
If you're on Windows Azure, add `?encrypt=true` to your connection string. See [docs](#configuration) to learn more.
|
|
72
72
|
|
|
73
73
|
## Documentation
|
|
74
74
|
|
|
75
|
-
* [2.x to 3.x changes](#
|
|
75
|
+
* [2.x to 3.x changes](#2x-to-3x-changes)
|
|
76
76
|
|
|
77
77
|
### Examples
|
|
78
78
|
|
|
79
79
|
* [Promises](#promises)
|
|
80
|
-
* [Nested callbacks](#callbacks)
|
|
80
|
+
* [Nested callbacks](#nested-callbacks)
|
|
81
81
|
* [Streaming](#streaming)
|
|
82
82
|
* [Multiple Connections](#multiple-connections)
|
|
83
83
|
|
|
84
84
|
### Configuration
|
|
85
85
|
|
|
86
|
-
* [General](#
|
|
87
|
-
* [Formats](#
|
|
86
|
+
* [General](#general-same-for-all-drivers)
|
|
87
|
+
* [Formats](#formats)
|
|
88
88
|
|
|
89
89
|
### Drivers
|
|
90
90
|
|
|
91
|
-
* [Tedious](#
|
|
92
|
-
* [Microsoft / Contributors Node V8 Driver for Node.js for SQL Server](#
|
|
93
|
-
* [Microsoft Driver for Node.js for SQL Server](#
|
|
94
|
-
* [node-tds](#
|
|
91
|
+
* [Tedious](#tedious)
|
|
92
|
+
* [Microsoft / Contributors Node V8 Driver for Node.js for SQL Server](#microsoft--contributors-node-v8-driver-for-nodejs-for-sql-server)
|
|
93
|
+
* [Microsoft Driver for Node.js for SQL Server](#microsoft-driver-for-nodejs-for-sql-server)
|
|
94
|
+
* [node-tds](#node-tds)
|
|
95
95
|
|
|
96
96
|
### Connections
|
|
97
97
|
|
|
98
98
|
* [Connection](#connection)
|
|
99
|
-
* [connect](#connect)
|
|
99
|
+
* [connect](#connect-callback)
|
|
100
100
|
* [close](#close)
|
|
101
101
|
|
|
102
102
|
### Requests
|
|
103
103
|
|
|
104
104
|
* [Request](#request)
|
|
105
|
-
* [execute](#execute)
|
|
106
|
-
* [input](#input)
|
|
107
|
-
* [output](#output)
|
|
108
|
-
* [pipe](#pipe)
|
|
109
|
-
* [query](#query)
|
|
110
|
-
* [batch](#batch)
|
|
111
|
-
* [bulk](#bulk)
|
|
105
|
+
* [execute](#execute-procedure-callback)
|
|
106
|
+
* [input](#input-name-type-value)
|
|
107
|
+
* [output](#output-name-type-value)
|
|
108
|
+
* [pipe](#pipe-stream)
|
|
109
|
+
* [query](#query-command-callback)
|
|
110
|
+
* [batch](#batch-batch-callback)
|
|
111
|
+
* [bulk](#bulk-table-callback)
|
|
112
112
|
* [cancel](#cancel)
|
|
113
113
|
|
|
114
114
|
### Transactions
|
|
115
115
|
|
|
116
116
|
* [Transaction](#transaction)
|
|
117
|
-
* [begin](#begin)
|
|
118
|
-
* [commit](#commit)
|
|
119
|
-
* [rollback](#rollback)
|
|
117
|
+
* [begin](#begin-isolationlevel-callback)
|
|
118
|
+
* [commit](#commit-callback)
|
|
119
|
+
* [rollback](#rollback-callback)
|
|
120
120
|
|
|
121
121
|
### Prepared Statements
|
|
122
122
|
|
|
123
123
|
* [PreparedStatement](#prepared-statement)
|
|
124
|
-
* [input](#
|
|
125
|
-
* [output](#
|
|
126
|
-
* [prepare](#prepare)
|
|
127
|
-
* [execute](#
|
|
128
|
-
* [unprepare](#unprepare)
|
|
124
|
+
* [input](#input-name-type)
|
|
125
|
+
* [output](#output-name-type)
|
|
126
|
+
* [prepare](#prepare-statement-callback)
|
|
127
|
+
* [execute](#execute-values-callback)
|
|
128
|
+
* [unprepare](#unprepare-callback)
|
|
129
129
|
|
|
130
130
|
### Other
|
|
131
131
|
|
|
132
132
|
* [CLI](#cli)
|
|
133
|
-
* [Geography and Geometry](#geography)
|
|
134
|
-
* [Table-Valued Parameter](#tvp)
|
|
133
|
+
* [Geography and Geometry](#geography-and-geometry)
|
|
134
|
+
* [Table-Valued Parameter](#table-valued-parameter-tvp)
|
|
135
135
|
* [Affected Rows](#affected-rows)
|
|
136
|
-
* [JSON support](#json)
|
|
136
|
+
* [JSON support](#json-support)
|
|
137
137
|
* [Errors](#errors)
|
|
138
|
-
* [
|
|
138
|
+
* [Informational messages](#informational-messages)
|
|
139
|
+
* [Metadata](#metadata)
|
|
139
140
|
* [Data Types](#data-types)
|
|
140
|
-
* [SQL injection](#injection)
|
|
141
|
-
* [Verbose Mode](#verbose)
|
|
142
|
-
* [Known Issues](#issues)
|
|
141
|
+
* [SQL injection](#sql-injection)
|
|
142
|
+
* [Verbose Mode](#verbose-mode)
|
|
143
|
+
* [Known Issues](#known-issues)
|
|
143
144
|
* [Contributing](https://github.com/patriksimek/node-mssql/wiki/Contributing)
|
|
144
145
|
|
|
145
146
|
## Examples
|
|
146
147
|
|
|
147
|
-
<a name="promises" />
|
|
148
148
|
### Promises
|
|
149
149
|
|
|
150
150
|
```javascript
|
|
@@ -205,7 +205,6 @@ sql.connect(config).then(function() {
|
|
|
205
205
|
|
|
206
206
|
All values are automatically sanitized against sql injection.
|
|
207
207
|
|
|
208
|
-
<a name="callbacks" />
|
|
209
208
|
### Nested callbacks
|
|
210
209
|
|
|
211
210
|
```javascript
|
|
@@ -250,7 +249,6 @@ sql.on('error', function(err) {
|
|
|
250
249
|
});
|
|
251
250
|
```
|
|
252
251
|
|
|
253
|
-
<a name="streaming" />
|
|
254
252
|
### Streaming
|
|
255
253
|
|
|
256
254
|
If you plan to work with large amount of rows, you should always use streaming. Once you enable this, you must listen for events to receive data.
|
|
@@ -299,7 +297,6 @@ sql.on('error', function(err) {
|
|
|
299
297
|
});
|
|
300
298
|
```
|
|
301
299
|
|
|
302
|
-
<a name="multiple-connections" />
|
|
303
300
|
## Multiple Connections
|
|
304
301
|
|
|
305
302
|
```javascript
|
|
@@ -370,7 +367,6 @@ new sql.Connection(config).connect().then(function(conn) {
|
|
|
370
367
|
|
|
371
368
|
All values are automatically sanitized against sql injection.
|
|
372
369
|
|
|
373
|
-
<a name="cfg" />
|
|
374
370
|
## Configuration
|
|
375
371
|
|
|
376
372
|
```javascript
|
|
@@ -387,7 +383,6 @@ var config = {
|
|
|
387
383
|
}
|
|
388
384
|
```
|
|
389
385
|
|
|
390
|
-
<a name="cfg-general" />
|
|
391
386
|
### General (same for all drivers)
|
|
392
387
|
|
|
393
388
|
- **driver** - Driver to use (default: `tedious`). Possible values: `tedious`, `msnodesqlv8` or `msnodesql` or `tds`.
|
|
@@ -400,12 +395,11 @@ var config = {
|
|
|
400
395
|
- **connectionTimeout** - Connection timeout in ms (default: `15000`).
|
|
401
396
|
- **requestTimeout** - Request timeout in ms (default: `15000`).
|
|
402
397
|
- **stream** - Stream recordsets/rows instead of returning them all at once as an argument of callback (default: `false`). You can also enable streaming for each request independently (`request.stream = true`). Always set to `true` if you plan to work with large amount of rows.
|
|
403
|
-
- **parseJSON** - Parse JSON recordsets to JS objects (default: `false`). For more information please see section [JSON support](#json).
|
|
398
|
+
- **parseJSON** - Parse JSON recordsets to JS objects (default: `false`). For more information please see section [JSON support](#json-support).
|
|
404
399
|
- **pool.max** - The maximum number of connections there can be in the pool (default: `10`).
|
|
405
400
|
- **pool.min** - The minimum of connections there can be in the pool (default: `0`).
|
|
406
401
|
- **pool.idleTimeoutMillis** - The Number of milliseconds before closing an unused connection (default: `30000`).
|
|
407
402
|
|
|
408
|
-
<a name="cfg-formats" />
|
|
409
403
|
### Formats
|
|
410
404
|
|
|
411
405
|
In addition to configuration object there is an option to pass config as a connection string. Two formats of connection string are supported.
|
|
@@ -430,7 +424,6 @@ __Version__
|
|
|
430
424
|
|
|
431
425
|
## Drivers
|
|
432
426
|
|
|
433
|
-
<a name="cfg-tedious" />
|
|
434
427
|
### Tedious
|
|
435
428
|
|
|
436
429
|
Default driver, actively maintained and production ready. Platform independent, runs everywhere Node.js runs.
|
|
@@ -446,7 +439,6 @@ Default driver, actively maintained and production ready. Platform independent,
|
|
|
446
439
|
|
|
447
440
|
More information about Tedious specific options: http://pekim.github.io/tedious/api-connection.html
|
|
448
441
|
|
|
449
|
-
<a name="cfg-msnodesqlv8" />
|
|
450
442
|
### Microsoft / Contributors Node V8 Driver for Node.js for SQL Server
|
|
451
443
|
|
|
452
444
|
**Requires Node.js 0.12.x/4.2.0. Windows only.** This driver is not part of the default package and must be installed separately by `npm install msnodesqlv8`.
|
|
@@ -468,7 +460,6 @@ Default connection string when connecting to named instance:
|
|
|
468
460
|
Driver={SQL Server Native Client 11.0};Server={#{server}\\#{instance}};Database={#{database}};Uid={#{user}};Pwd={#{password}};Trusted_Connection={#{trusted}};
|
|
469
461
|
```
|
|
470
462
|
|
|
471
|
-
<a name="cfg-msnodesql" />
|
|
472
463
|
### Microsoft Driver for Node.js for SQL Server
|
|
473
464
|
|
|
474
465
|
**Requires Node.js 0.6.x/0.8.x/0.10.x. Windows only.** 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-unofficial).
|
|
@@ -490,15 +481,13 @@ Default connection string when connecting to named instance:
|
|
|
490
481
|
Driver={SQL Server Native Client 11.0};Server={#{server}\\#{instance}};Database={#{database}};Uid={#{user}};Pwd={#{password}};Trusted_Connection={#{trusted}};
|
|
491
482
|
```
|
|
492
483
|
|
|
493
|
-
<a name="cfg-node-tds" />
|
|
494
484
|
### node-tds
|
|
495
485
|
|
|
496
486
|
**Legacy support, don't use this driver for new projects.** This driver is not part of the default package and must be installed separately by `npm install tds`.
|
|
497
487
|
|
|
498
488
|
_node-mssql updates this 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')`._
|
|
499
489
|
|
|
500
|
-
|
|
501
|
-
## Connections
|
|
490
|
+
## Connection
|
|
502
491
|
|
|
503
492
|
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. Connection health check is built-in so once the dead connection is discovered, it is immediately replaced with a new one.
|
|
504
493
|
|
|
@@ -519,8 +508,7 @@ __Errors__
|
|
|
519
508
|
|
|
520
509
|
---------------------------------------
|
|
521
510
|
|
|
522
|
-
|
|
523
|
-
### connect([callback])
|
|
511
|
+
### connect ([callback])
|
|
524
512
|
|
|
525
513
|
Create a new connection pool with one active connection. This one initial connection serves as a probe to find out whether the configuration is valid.
|
|
526
514
|
|
|
@@ -553,7 +541,6 @@ __Errors__
|
|
|
553
541
|
|
|
554
542
|
---------------------------------------
|
|
555
543
|
|
|
556
|
-
<a name="close" />
|
|
557
544
|
### close()
|
|
558
545
|
|
|
559
546
|
Close all active connections in the pool.
|
|
@@ -564,8 +551,7 @@ __Example__
|
|
|
564
551
|
connection.close();
|
|
565
552
|
```
|
|
566
553
|
|
|
567
|
-
|
|
568
|
-
## Requests
|
|
554
|
+
## Request
|
|
569
555
|
|
|
570
556
|
```javascript
|
|
571
557
|
var request = new sql.Request(/* [connection] */);
|
|
@@ -579,11 +565,11 @@ If you omit connection argument, global connection is used instead.
|
|
|
579
565
|
- **row(row)** - Dispatched when new row is parsed.
|
|
580
566
|
- **done(returnValue)** - Dispatched when request is complete.
|
|
581
567
|
- **error(err)** - Dispatched on error.
|
|
568
|
+
- **info(message)** - Dispatched on informational message.
|
|
582
569
|
|
|
583
570
|
---------------------------------------
|
|
584
571
|
|
|
585
|
-
|
|
586
|
-
### execute(procedure, [callback])
|
|
572
|
+
### execute (procedure, [callback])
|
|
587
573
|
|
|
588
574
|
Call a stored procedure.
|
|
589
575
|
|
|
@@ -626,8 +612,7 @@ __Errors__
|
|
|
626
612
|
|
|
627
613
|
---------------------------------------
|
|
628
614
|
|
|
629
|
-
|
|
630
|
-
### input(name, [type], value)
|
|
615
|
+
### input (name, [type], value)
|
|
631
616
|
|
|
632
617
|
Add an input parameter to the request.
|
|
633
618
|
|
|
@@ -673,8 +658,7 @@ __Errors__ (synchronous)
|
|
|
673
658
|
|
|
674
659
|
---------------------------------------
|
|
675
660
|
|
|
676
|
-
|
|
677
|
-
### output(name, type, [value])
|
|
661
|
+
### output (name, type, [value])
|
|
678
662
|
|
|
679
663
|
Add an output parameter to the request.
|
|
680
664
|
|
|
@@ -697,8 +681,7 @@ __Errors__ (synchronous)
|
|
|
697
681
|
|
|
698
682
|
---------------------------------------
|
|
699
683
|
|
|
700
|
-
|
|
701
|
-
### pipe(stream)
|
|
684
|
+
### pipe (stream)
|
|
702
685
|
|
|
703
686
|
Sets request to `stream` mode and pulls all rows from all recordsets to a given stream.
|
|
704
687
|
|
|
@@ -726,10 +709,9 @@ __Version__
|
|
|
726
709
|
|
|
727
710
|
---------------------------------------
|
|
728
711
|
|
|
729
|
-
|
|
730
|
-
### query(command, [callback])
|
|
712
|
+
### query (command, [callback])
|
|
731
713
|
|
|
732
|
-
Execute the SQL command. To execute commands like `create procedure` or if you plan to work with local temporary tables, use [batch](#batch) instead.
|
|
714
|
+
Execute the SQL command. To execute commands like `create procedure` or if you plan to work with local temporary tables, use [batch](#batch-batch-callback) instead.
|
|
733
715
|
|
|
734
716
|
__Arguments__
|
|
735
717
|
|
|
@@ -777,10 +759,9 @@ request.query('select 1 as number; select 2 as number', function(err, recordsets
|
|
|
777
759
|
|
|
778
760
|
---------------------------------------
|
|
779
761
|
|
|
780
|
-
|
|
781
|
-
### batch(batch, [callback])
|
|
762
|
+
### batch (batch, [callback])
|
|
782
763
|
|
|
783
|
-
Execute the SQL command. Unlike [query](#query), it doesn't use `sp_executesql`, so is not likely that SQL Server will reuse the execution plan it generates for the SQL. Use this only in special cases, for example when you need to execute commands like `create procedure` which can't be executed with [query](#query) or if you're executing statements longer than 4000 chars on SQL Server 2000. Also you should use this if you're plan to work with local temporary tables ([more information here](http://weblogs.sqlteam.com/mladenp/archive/2006/11/03/17197.aspx)).
|
|
764
|
+
Execute the SQL command. Unlike [query](#query-command-callback), it doesn't use `sp_executesql`, so is not likely that SQL Server will reuse the execution plan it generates for the SQL. Use this only in special cases, for example when you need to execute commands like `create procedure` which can't be executed with [query](#query-command-callback) or if you're executing statements longer than 4000 chars on SQL Server 2000. Also you should use this if you're plan to work with local temporary tables ([more information here](http://weblogs.sqlteam.com/mladenp/archive/2006/11/03/17197.aspx)).
|
|
784
765
|
|
|
785
766
|
NOTE: Table-Valued Parameter (TVP) is not supported in batch.
|
|
786
767
|
|
|
@@ -812,7 +793,6 @@ You can enable multiple recordsets in queries with the `request.multiple = true`
|
|
|
812
793
|
|
|
813
794
|
---------------------------------------
|
|
814
795
|
|
|
815
|
-
<a name="bulk" />
|
|
816
796
|
### bulk(table, [callback])
|
|
817
797
|
|
|
818
798
|
Perform a bulk insert.
|
|
@@ -856,7 +836,6 @@ __Errors__
|
|
|
856
836
|
|
|
857
837
|
---------------------------------------
|
|
858
838
|
|
|
859
|
-
<a name="cancel" />
|
|
860
839
|
### cancel()
|
|
861
840
|
|
|
862
841
|
Cancel currently executing request. Return `true` if cancellation packet was send successfully.
|
|
@@ -876,8 +855,7 @@ request.query('waitfor delay \'00:00:05\'; select 1 as number', function(err, re
|
|
|
876
855
|
request.cancel();
|
|
877
856
|
```
|
|
878
857
|
|
|
879
|
-
|
|
880
|
-
## Transactions
|
|
858
|
+
## Transaction
|
|
881
859
|
|
|
882
860
|
**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 acquired from the connection pool and all subsequent requests (initialized with the `Transaction` object) are executed exclusively on this connection. Transaction also contains a 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.
|
|
883
861
|
|
|
@@ -953,8 +931,7 @@ transaction.begin(function(err) {
|
|
|
953
931
|
|
|
954
932
|
---------------------------------------
|
|
955
933
|
|
|
956
|
-
|
|
957
|
-
### begin([isolationLevel], [callback])
|
|
934
|
+
### begin ([isolationLevel], [callback])
|
|
958
935
|
|
|
959
936
|
Begin a transaction.
|
|
960
937
|
|
|
@@ -978,8 +955,7 @@ __Errors__
|
|
|
978
955
|
|
|
979
956
|
---------------------------------------
|
|
980
957
|
|
|
981
|
-
|
|
982
|
-
### commit([callback])
|
|
958
|
+
### commit ([callback])
|
|
983
959
|
|
|
984
960
|
Commit a transaction.
|
|
985
961
|
|
|
@@ -1006,8 +982,7 @@ __Errors__
|
|
|
1006
982
|
|
|
1007
983
|
---------------------------------------
|
|
1008
984
|
|
|
1009
|
-
|
|
1010
|
-
### rollback([callback])
|
|
985
|
+
### rollback ([callback])
|
|
1011
986
|
|
|
1012
987
|
Rollback a transaction. If the queue isn't empty, all queued requests will be Cancelled and the transaction will be marked as aborted.
|
|
1013
988
|
|
|
@@ -1032,8 +1007,7 @@ __Errors__
|
|
|
1032
1007
|
- ENOTBEGUN (`TransactionError`) - Transaction has not begun.
|
|
1033
1008
|
- EREQINPROG (`TransactionError`) - Can't rollback transaction. There is a request in progress.
|
|
1034
1009
|
|
|
1035
|
-
|
|
1036
|
-
## PreparedStatement
|
|
1010
|
+
## Prepared Statement
|
|
1037
1011
|
|
|
1038
1012
|
**IMPORTANT:** always use `PreparedStatement` class to create prepared statements - it ensures that all your executions of prepared statement are executed on one connection. Once you call `prepare`, a single connection is acquired from the connection pool and all subsequent executions are executed exclusively on this connection. Prepared Statement also contains a queue to make sure your executions are executed in series. After you call `unprepare`, the connection is then released back to the connection pool.
|
|
1039
1013
|
|
|
@@ -1068,8 +1042,7 @@ ps.prepare('select @param as value', function(err) {
|
|
|
1068
1042
|
|
|
1069
1043
|
---------------------------------------
|
|
1070
1044
|
|
|
1071
|
-
|
|
1072
|
-
### input(name, type)
|
|
1045
|
+
### input (name, type)
|
|
1073
1046
|
|
|
1074
1047
|
Add an input parameter to the prepared statement.
|
|
1075
1048
|
|
|
@@ -1091,8 +1064,7 @@ __Errors__ (synchronous)
|
|
|
1091
1064
|
|
|
1092
1065
|
---------------------------------------
|
|
1093
1066
|
|
|
1094
|
-
|
|
1095
|
-
### output(name, type)
|
|
1067
|
+
### output (name, type)
|
|
1096
1068
|
|
|
1097
1069
|
Add an output parameter to the prepared statement.
|
|
1098
1070
|
|
|
@@ -1114,8 +1086,7 @@ __Errors__ (synchronous)
|
|
|
1114
1086
|
|
|
1115
1087
|
---------------------------------------
|
|
1116
1088
|
|
|
1117
|
-
|
|
1118
|
-
### prepare(statement, [callback])
|
|
1089
|
+
### prepare (statement, [callback])
|
|
1119
1090
|
|
|
1120
1091
|
Prepare a statement.
|
|
1121
1092
|
|
|
@@ -1140,8 +1111,7 @@ __Errors__
|
|
|
1140
1111
|
|
|
1141
1112
|
---------------------------------------
|
|
1142
1113
|
|
|
1143
|
-
|
|
1144
|
-
### execute(values, [callback])
|
|
1114
|
+
### execute (values, [callback])
|
|
1145
1115
|
|
|
1146
1116
|
Execute a prepared statement.
|
|
1147
1117
|
|
|
@@ -1240,8 +1210,7 @@ __Errors__
|
|
|
1240
1210
|
|
|
1241
1211
|
---------------------------------------
|
|
1242
1212
|
|
|
1243
|
-
|
|
1244
|
-
### unprepare([callback])
|
|
1213
|
+
### unprepare ([callback])
|
|
1245
1214
|
|
|
1246
1215
|
Unprepare a prepared statement.
|
|
1247
1216
|
|
|
@@ -1267,7 +1236,6 @@ ps.prepare('select @param as value', function(err, recordsets) {
|
|
|
1267
1236
|
__Errors__
|
|
1268
1237
|
- ENOTPREPARED (`PreparedStatementError`) - Statement is not prepared.
|
|
1269
1238
|
|
|
1270
|
-
<a name="cli" />
|
|
1271
1239
|
## CLI
|
|
1272
1240
|
|
|
1273
1241
|
Before you can start using CLI, you must install `mssql` globally with `npm install mssql -g`. Once you do that you will be able to execute `mssql` command.
|
|
@@ -1311,7 +1279,6 @@ __Version__
|
|
|
1311
1279
|
|
|
1312
1280
|
2.0
|
|
1313
1281
|
|
|
1314
|
-
<a name="geography" />
|
|
1315
1282
|
## Geography and Geometry
|
|
1316
1283
|
|
|
1317
1284
|
node-mssql has built-in serializer for Geography and Geometry CLR data types.
|
|
@@ -1342,7 +1309,6 @@ Results in:
|
|
|
1342
1309
|
segments: [] }
|
|
1343
1310
|
```
|
|
1344
1311
|
|
|
1345
|
-
<a name="tvp" />
|
|
1346
1312
|
## Table-Valued Parameter (TVP)
|
|
1347
1313
|
|
|
1348
1314
|
Supported on SQL Server 2008 and later. You can pass a data table as a parameter to stored procedure. First, we have to create custom type in our database.
|
|
@@ -1384,7 +1350,6 @@ request.execute('MyCustomStoredProcedure', function(err, recordsets, returnValue
|
|
|
1384
1350
|
|
|
1385
1351
|
**TIP**: You can also create Table variable from any recordset with `recordset.toTable()`.
|
|
1386
1352
|
|
|
1387
|
-
<a name="affected-rows">
|
|
1388
1353
|
## Affected Rows
|
|
1389
1354
|
|
|
1390
1355
|
If you're performing `INSERT`, `UPDATE` or `DELETE` in a query, you can read number of affected rows.
|
|
@@ -1424,8 +1389,7 @@ __Version__
|
|
|
1424
1389
|
|
|
1425
1390
|
3.0
|
|
1426
1391
|
|
|
1427
|
-
|
|
1428
|
-
## JSON support (works only with Tedious driver)
|
|
1392
|
+
## JSON support
|
|
1429
1393
|
|
|
1430
1394
|
SQL Server 2016 introduced built-in JSON serialization. By default, JSON is returned as a plain text in a special column named `JSON_F52E2B61-18A1-11d1-B105-00805F49916B`.
|
|
1431
1395
|
|
|
@@ -1457,7 +1421,6 @@ __Version__
|
|
|
1457
1421
|
|
|
1458
1422
|
2.3
|
|
1459
1423
|
|
|
1460
|
-
<a name="errors" />
|
|
1461
1424
|
## Errors
|
|
1462
1425
|
|
|
1463
1426
|
There are 4 types of errors you can handle:
|
|
@@ -1506,13 +1469,40 @@ Name | Code | Message
|
|
|
1506
1469
|
SQL errors (`RequestError` with `err.code` equal to `EREQUEST`) contains additional details.
|
|
1507
1470
|
|
|
1508
1471
|
- **err.number** - The error number.
|
|
1509
|
-
- **err.state** - The error state, used as a modifier to the
|
|
1472
|
+
- **err.state** - The error state, used as a modifier to the number.
|
|
1510
1473
|
- **err.class** - The class (severity) of the error. A class of less than 10 indicates an informational message. Detailed explanation can be found [here](https://msdn.microsoft.com/en-us/library/dd304156.aspx).
|
|
1511
1474
|
- **err.lineNumber** - The line number in the SQL batch or stored procedure that caused the error. Line numbers begin at 1; therefore, if the line number is not applicable to the message, the value of LineNumber will be 0.
|
|
1512
1475
|
- **err.serverName** - The server name.
|
|
1513
1476
|
- **err.procName** - The stored procedure name.
|
|
1514
1477
|
|
|
1515
|
-
|
|
1478
|
+
## Informational messages
|
|
1479
|
+
|
|
1480
|
+
To receive informational messages generated by `PRINT` or `RAISERROR` commands use:
|
|
1481
|
+
|
|
1482
|
+
```javascript
|
|
1483
|
+
var request = new sql.Request();
|
|
1484
|
+
request.on('info', function(info) {
|
|
1485
|
+
console.dir(info);
|
|
1486
|
+
});
|
|
1487
|
+
request.query('print \'Hello world.\';', function(err, recordset) {
|
|
1488
|
+
// ...
|
|
1489
|
+
});
|
|
1490
|
+
```
|
|
1491
|
+
|
|
1492
|
+
Structure of informational message:
|
|
1493
|
+
|
|
1494
|
+
- **info.message** - Message.
|
|
1495
|
+
- **info.number** - The message number.
|
|
1496
|
+
- **info.state** - The message state, used as a modifier to the number.
|
|
1497
|
+
- **info.class** - The class (severity) of the message. Equal or lower than 10. Detailed explanation can be found [here](https://msdn.microsoft.com/en-us/library/dd304156.aspx).
|
|
1498
|
+
- **info.lineNumber** - The line number in the SQL batch or stored procedure that generated the message. Line numbers begin at 1; therefore, if the line number is not applicable to the message, the value of LineNumber will be 0.
|
|
1499
|
+
- **info.serverName** - The server name.
|
|
1500
|
+
- **info.procName** - The stored procedure name.
|
|
1501
|
+
|
|
1502
|
+
__Version__
|
|
1503
|
+
|
|
1504
|
+
3.3
|
|
1505
|
+
|
|
1516
1506
|
## Metadata
|
|
1517
1507
|
|
|
1518
1508
|
Recordset metadata are accessible through the `recordset.columns` property.
|
|
@@ -1556,7 +1546,6 @@ Columns structure for example above:
|
|
|
1556
1546
|
}
|
|
1557
1547
|
```
|
|
1558
1548
|
|
|
1559
|
-
<a name="data-types" />
|
|
1560
1549
|
## Data Types
|
|
1561
1550
|
|
|
1562
1551
|
You can define data types with length/precision/scale:
|
|
@@ -1621,7 +1610,6 @@ sql.Geometry
|
|
|
1621
1610
|
|
|
1622
1611
|
To setup MAX length for `VarChar`, `NVarChar` and `VarBinary` use `sql.MAX` length. Types `sql.XML` and `sql.Variant` are not supported as input parameters.
|
|
1623
1612
|
|
|
1624
|
-
<a name="injection" />
|
|
1625
1613
|
## SQL injection
|
|
1626
1614
|
|
|
1627
1615
|
This module has built-in SQL injection protection. Always use parameters to pass sanitized values to your queries.
|
|
@@ -1634,7 +1622,6 @@ request.query('select @myval as myval', function(err, recordset) {
|
|
|
1634
1622
|
});
|
|
1635
1623
|
```
|
|
1636
1624
|
|
|
1637
|
-
<a name="verbose" />
|
|
1638
1625
|
## Verbose Mode
|
|
1639
1626
|
|
|
1640
1627
|
You can enable verbose mode by `request.verbose = true` command.
|
|
@@ -1669,35 +1656,36 @@ Output for the example above could look similar to this.
|
|
|
1669
1656
|
---------- completed ----------
|
|
1670
1657
|
```
|
|
1671
1658
|
|
|
1672
|
-
<a name="issues" />
|
|
1673
1659
|
## Known issues
|
|
1674
1660
|
|
|
1675
1661
|
### Tedious
|
|
1676
1662
|
|
|
1677
1663
|
- If you're facing problems with connecting SQL Server 2000, try setting the default TDS version to 7.1 with `config.options.tdsVersion = '7_1'` ([issue](https://github.com/patriksimek/node-mssql/issues/36))
|
|
1678
|
-
- If you're executing a statement longer than 4000 chars on SQL Server 2000, always use [batch](#batch) instead of [query](#query) ([issue](https://github.com/patriksimek/node-mssql/issues/68))
|
|
1664
|
+
- If you're executing a statement longer than 4000 chars on SQL Server 2000, always use [batch](#batch-batch-callback) instead of [query](#query-command-callback) ([issue](https://github.com/patriksimek/node-mssql/issues/68))
|
|
1679
1665
|
|
|
1680
1666
|
### msnodesqlv8
|
|
1681
1667
|
|
|
1682
1668
|
- msnodesqlv8 has problem with errors during transactions - [reported](https://github.com/patriksimek/node-mssql/issues/77).
|
|
1683
1669
|
- msnodesqlv8 doesn't timeout the connection reliably - [reported](https://github.com/TimelordUK/node-sqlserver-v8/issues/9).
|
|
1684
|
-
- msnodesqlv8 doesn't support [TVP](#tvp) data type.
|
|
1670
|
+
- msnodesqlv8 doesn't support [TVP](#table-valued-parameter-tvp) data type.
|
|
1685
1671
|
- msnodesqlv8 doesn't support Variant data type.
|
|
1686
1672
|
- msnodesqlv8 doesn't support request timeout.
|
|
1687
1673
|
- msnodesqlv8 doesn't support request cancellation.
|
|
1688
1674
|
- msnodesqlv8 doesn't support [detailed SQL errors](#detailed-sql-errors).
|
|
1675
|
+
- msnodesqlv8 doesn't support [Informational messages](#informational-messages).
|
|
1689
1676
|
|
|
1690
1677
|
### msnodesql
|
|
1691
1678
|
|
|
1692
1679
|
- msnodesql has problem with errors during transactions - [reported](https://github.com/patriksimek/node-mssql/issues/77).
|
|
1693
1680
|
- msnodesql contains bug in DateTimeOffset ([reported](https://github.com/Azure/node-sqlserver/issues/160))
|
|
1694
|
-
- msnodesql doesn't support [Bulk](#bulk) load.
|
|
1695
|
-
- msnodesql doesn't support [TVP](#tvp) data type.
|
|
1681
|
+
- msnodesql doesn't support [Bulk](#bulk-table-callback) load.
|
|
1682
|
+
- msnodesql doesn't support [TVP](#table-valued-parameter-tvp) data type.
|
|
1696
1683
|
- msnodesql doesn't support Variant data type.
|
|
1697
1684
|
- msnodesql doesn't support connection timeout.
|
|
1698
1685
|
- msnodesql doesn't support request timeout.
|
|
1699
1686
|
- msnodesql doesn't support request cancellation.
|
|
1700
1687
|
- msnodesql doesn't support [detailed SQL errors](#detailed-sql-errors).
|
|
1688
|
+
- msnodesql doesn't support [Informational messages](#informational-messages).
|
|
1701
1689
|
- msnodesql reports invalid number of affected rows in some cases.
|
|
1702
1690
|
|
|
1703
1691
|
### node-tds
|
|
@@ -1710,20 +1698,19 @@ Output for the example above could look similar to this.
|
|
|
1710
1698
|
- node-tds doesn't support Binary, VarBinary and Image as parameters.
|
|
1711
1699
|
- node-tds always return date/time values in local time.
|
|
1712
1700
|
- node-tds has serious problems with MAX types.
|
|
1713
|
-
- node-tds doesn't support [Bulk](#bulk) load.
|
|
1714
|
-
- node-tds doesn't support [TVP](#tvp) data type.
|
|
1701
|
+
- node-tds doesn't support [Bulk](#bulk-table-callback) load.
|
|
1702
|
+
- node-tds doesn't support [TVP](#table-valued-parameter-tvp) data type.
|
|
1715
1703
|
- node-tds doesn't support Variant data type.
|
|
1716
1704
|
- node-tds doesn't support request timeout.
|
|
1717
|
-
- node-tds doesn't support [built-in JSON serialization](#json) introduced in SQL Server 2016.
|
|
1705
|
+
- node-tds doesn't support [built-in JSON serialization](#json-support) introduced in SQL Server 2016.
|
|
1718
1706
|
- node-tds doesn't support [detailed SQL errors](#detailed-sql-errors).
|
|
1719
1707
|
- node-tds doesn't support [Affected Rows](#affected-rows)
|
|
1720
1708
|
|
|
1721
|
-
<a name="twotothree" />
|
|
1722
1709
|
## 2.x to 3.x changes
|
|
1723
1710
|
|
|
1724
1711
|
### Prepared Statement
|
|
1725
1712
|
|
|
1726
|
-
* [`execute`](#
|
|
1713
|
+
* [`execute`](#execute-values-callback) method now returns 3 arguments instead of 2.
|
|
1727
1714
|
|
|
1728
1715
|
```javascript
|
|
1729
1716
|
ps.execute(values, function(err, recordset, affected) { });
|
|
@@ -1737,7 +1724,7 @@ Output for the example above could look similar to this.
|
|
|
1737
1724
|
|
|
1738
1725
|
### Request
|
|
1739
1726
|
|
|
1740
|
-
* [`execute`](#execute) method now returns 4 arguments instead of 3.
|
|
1727
|
+
* [`execute`](#execute-procedure-callback) method now returns 4 arguments instead of 3.
|
|
1741
1728
|
|
|
1742
1729
|
```javascript
|
|
1743
1730
|
ps.execute(values, function(err, recordset, returnValue, affected) { });
|
|
@@ -1749,7 +1736,7 @@ Output for the example above could look similar to this.
|
|
|
1749
1736
|
request.on('done', function(returnValue, affected) { });
|
|
1750
1737
|
```
|
|
1751
1738
|
|
|
1752
|
-
* [`query`](#query) method now returns 3 arguments instead of 2.
|
|
1739
|
+
* [`query`](#query-command-callback) method now returns 3 arguments instead of 2.
|
|
1753
1740
|
|
|
1754
1741
|
```javascript
|
|
1755
1742
|
ps.execute(values, function(err, recordset, affected) { });
|
|
@@ -1761,7 +1748,6 @@ Output for the example above could look similar to this.
|
|
|
1761
1748
|
request.on('done', function(affected) { });
|
|
1762
1749
|
```
|
|
1763
1750
|
|
|
1764
|
-
<a name="license" />
|
|
1765
1751
|
## License
|
|
1766
1752
|
|
|
1767
1753
|
Copyright (c) 2013-2016 Patrik Simek
|
package/lib/connectionstring.js
CHANGED
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
};
|
|
187
187
|
|
|
188
188
|
resolveConnectionString = function(string) {
|
|
189
|
-
var config, parsed, ref, ref1, ref10, ref11, ref12, ref13, ref14, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, server, user;
|
|
189
|
+
var config, parsed, ref, ref1, ref10, ref11, ref12, ref13, ref14, ref15, ref16, ref17, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, server, user;
|
|
190
190
|
if (/^(mssql|tedious|msnodesql|tds)\:\/\//i.test(string)) {
|
|
191
191
|
parsed = parseConnectionURI(string);
|
|
192
192
|
} else {
|
|
@@ -211,13 +211,22 @@
|
|
|
211
211
|
driver: parsed.driver,
|
|
212
212
|
password: (ref6 = parsed.pwd) != null ? ref6 : parsed.password,
|
|
213
213
|
database: (ref7 = parsed.database) != null ? ref7 : parsed['initial catalog'],
|
|
214
|
-
connectionTimeout: (ref8 = (ref9 = parsed.timeout) != null ? ref9 : parsed['connect timeout']) != null ? ref8 : parsed['connection timeout'],
|
|
215
|
-
requestTimeout: parsed['request timeout'],
|
|
216
|
-
stream: (
|
|
214
|
+
connectionTimeout: (ref8 = (ref9 = (ref10 = parsed.connectionTimeout) != null ? ref10 : parsed.timeout) != null ? ref9 : parsed['connect timeout']) != null ? ref8 : parsed['connection timeout'],
|
|
215
|
+
requestTimeout: (ref11 = parsed.requestTimeout) != null ? ref11 : parsed['request timeout'],
|
|
216
|
+
stream: (ref12 = (ref13 = parsed.stream) != null ? ref13.toLowerCase() : void 0) === 'true' || ref12 === 'yes' || ref12 === '1',
|
|
217
217
|
options: {
|
|
218
|
-
encrypt: (
|
|
218
|
+
encrypt: (ref14 = (ref15 = parsed.encrypt) != null ? ref15.toLowerCase() : void 0) === 'true' || ref14 === 'yes' || ref14 === '1'
|
|
219
219
|
}
|
|
220
220
|
};
|
|
221
|
+
if (parsed.useUTC != null) {
|
|
222
|
+
config.options.useUTC = (ref16 = parsed.useUTC.toLowerCase()) === 'true' || ref16 === 'yes' || ref16 === '1';
|
|
223
|
+
}
|
|
224
|
+
if (config.connectionTimeout != null) {
|
|
225
|
+
config.connectionTimeout = parseInt(config.connectionTimeout);
|
|
226
|
+
}
|
|
227
|
+
if (config.requestTimeout != null) {
|
|
228
|
+
config.requestTimeout = parseInt(config.requestTimeout);
|
|
229
|
+
}
|
|
221
230
|
if (/^(.*)\\(.*)$/.exec(user)) {
|
|
222
231
|
config.domain = RegExp.$1;
|
|
223
232
|
user = RegExp.$2;
|
|
@@ -238,7 +247,7 @@
|
|
|
238
247
|
server = RegExp.$1.trim();
|
|
239
248
|
config.port = parseInt(RegExp.$2.trim());
|
|
240
249
|
}
|
|
241
|
-
if ((
|
|
250
|
+
if ((ref17 = server.toLowerCase()) === '.' || ref17 === '(.)' || ref17 === '(localdb)' || ref17 === '(local)') {
|
|
242
251
|
server = 'localhost';
|
|
243
252
|
}
|
|
244
253
|
}
|
package/lib/msnodesql.js
CHANGED
|
@@ -429,10 +429,28 @@
|
|
|
429
429
|
_this._log("---------- response -----------");
|
|
430
430
|
}
|
|
431
431
|
req.on('meta', function(metadata) {
|
|
432
|
-
var ref1;
|
|
432
|
+
var error, ex, ref1;
|
|
433
433
|
if (row) {
|
|
434
434
|
if (isChunkedRecordset) {
|
|
435
|
-
|
|
435
|
+
if (columns[0].name === JSON_COLUMN_ID && _this.connection.config.parseJSON === true) {
|
|
436
|
+
try {
|
|
437
|
+
row = JSON.parse(chunksBuffer.join(''));
|
|
438
|
+
if (!_this.stream) {
|
|
439
|
+
recordsets[recordsets.length - 1][0] = row;
|
|
440
|
+
}
|
|
441
|
+
} catch (error) {
|
|
442
|
+
ex = error;
|
|
443
|
+
row = null;
|
|
444
|
+
ex = RequestError(new Error("Failed to parse incoming JSON. " + ex.message), 'EJSON');
|
|
445
|
+
if (_this.stream) {
|
|
446
|
+
_this.emit('error', ex);
|
|
447
|
+
} else {
|
|
448
|
+
console.error(ex);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
} else {
|
|
452
|
+
row[columns[0].name] = chunksBuffer.join('');
|
|
453
|
+
}
|
|
436
454
|
chunksBuffer = null;
|
|
437
455
|
}
|
|
438
456
|
if (_this.verbose) {
|
|
@@ -528,11 +546,29 @@
|
|
|
528
546
|
return typeof callback === "function" ? callback(e) : void 0;
|
|
529
547
|
});
|
|
530
548
|
return req.once('done', function() {
|
|
531
|
-
var elapsed, last, ref1, ref2;
|
|
549
|
+
var elapsed, error, ex, last, ref1, ref2;
|
|
532
550
|
if (!_this.nested) {
|
|
533
551
|
if (row) {
|
|
534
552
|
if (isChunkedRecordset) {
|
|
535
|
-
|
|
553
|
+
if (columns[0].name === JSON_COLUMN_ID && _this.connection.config.parseJSON === true) {
|
|
554
|
+
try {
|
|
555
|
+
row = JSON.parse(chunksBuffer.join(''));
|
|
556
|
+
if (!_this.stream) {
|
|
557
|
+
recordsets[recordsets.length - 1][0] = row;
|
|
558
|
+
}
|
|
559
|
+
} catch (error) {
|
|
560
|
+
ex = error;
|
|
561
|
+
row = null;
|
|
562
|
+
ex = RequestError(new Error("Failed to parse incoming JSON. " + ex.message), 'EJSON');
|
|
563
|
+
if (_this.stream) {
|
|
564
|
+
_this.emit('error', ex);
|
|
565
|
+
} else {
|
|
566
|
+
console.error(ex);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
} else {
|
|
570
|
+
row[columns[0].name] = chunksBuffer.join('');
|
|
571
|
+
}
|
|
536
572
|
chunksBuffer = null;
|
|
537
573
|
}
|
|
538
574
|
if (_this.verbose) {
|
package/lib/msnodesqlv8.js
CHANGED
|
@@ -519,10 +519,28 @@
|
|
|
519
519
|
_this._log("---------- response -----------");
|
|
520
520
|
}
|
|
521
521
|
req.on('meta', function(metadata) {
|
|
522
|
-
var ref1;
|
|
522
|
+
var error, ex, ref1;
|
|
523
523
|
if (row) {
|
|
524
524
|
if (isChunkedRecordset) {
|
|
525
|
-
|
|
525
|
+
if (columns[0].name === JSON_COLUMN_ID && _this.connection.config.parseJSON === true) {
|
|
526
|
+
try {
|
|
527
|
+
row = JSON.parse(chunksBuffer.join(''));
|
|
528
|
+
if (!_this.stream) {
|
|
529
|
+
recordsets[recordsets.length - 1][0] = row;
|
|
530
|
+
}
|
|
531
|
+
} catch (error) {
|
|
532
|
+
ex = error;
|
|
533
|
+
row = null;
|
|
534
|
+
ex = RequestError(new Error("Failed to parse incoming JSON. " + ex.message), 'EJSON');
|
|
535
|
+
if (_this.stream) {
|
|
536
|
+
_this.emit('error', ex);
|
|
537
|
+
} else {
|
|
538
|
+
console.error(ex);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
} else {
|
|
542
|
+
row[columns[0].name] = chunksBuffer.join('');
|
|
543
|
+
}
|
|
526
544
|
chunksBuffer = null;
|
|
527
545
|
}
|
|
528
546
|
if (_this.verbose) {
|
|
@@ -618,11 +636,29 @@
|
|
|
618
636
|
return typeof callback === "function" ? callback(e) : void 0;
|
|
619
637
|
});
|
|
620
638
|
return req.once('done', function() {
|
|
621
|
-
var elapsed, last, ref1, ref2;
|
|
639
|
+
var elapsed, error, ex, last, ref1, ref2;
|
|
622
640
|
if (!_this.nested) {
|
|
623
641
|
if (row) {
|
|
624
642
|
if (isChunkedRecordset) {
|
|
625
|
-
|
|
643
|
+
if (columns[0].name === JSON_COLUMN_ID && _this.connection.config.parseJSON === true) {
|
|
644
|
+
try {
|
|
645
|
+
row = JSON.parse(chunksBuffer.join(''));
|
|
646
|
+
if (!_this.stream) {
|
|
647
|
+
recordsets[recordsets.length - 1][0] = row;
|
|
648
|
+
}
|
|
649
|
+
} catch (error) {
|
|
650
|
+
ex = error;
|
|
651
|
+
row = null;
|
|
652
|
+
ex = RequestError(new Error("Failed to parse incoming JSON. " + ex.message), 'EJSON');
|
|
653
|
+
if (_this.stream) {
|
|
654
|
+
_this.emit('error', ex);
|
|
655
|
+
} else {
|
|
656
|
+
console.error(ex);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
} else {
|
|
660
|
+
row[columns[0].name] = chunksBuffer.join('');
|
|
661
|
+
}
|
|
626
662
|
chunksBuffer = null;
|
|
627
663
|
}
|
|
628
664
|
if (_this.verbose) {
|
package/lib/tds.js
CHANGED
|
@@ -551,6 +551,17 @@
|
|
|
551
551
|
return typeof callback === "function" ? callback(error, _this.multiple || _this.nested ? recordsets : recordsets[0]) : void 0;
|
|
552
552
|
}
|
|
553
553
|
});
|
|
554
|
+
req.on('message', function(msg) {
|
|
555
|
+
return _this.emit('info', {
|
|
556
|
+
message: msg.text,
|
|
557
|
+
number: msg.number,
|
|
558
|
+
state: msg.state,
|
|
559
|
+
"class": msg.severity,
|
|
560
|
+
lineNumber: msg.lineNumber,
|
|
561
|
+
serverName: msg.serverName,
|
|
562
|
+
procName: msg.procName
|
|
563
|
+
});
|
|
564
|
+
});
|
|
554
565
|
req.on('error', function(err) {
|
|
555
566
|
var e;
|
|
556
567
|
e = RequestError(err, 'EREQUEST');
|
package/lib/tedious.js
CHANGED
|
@@ -551,7 +551,7 @@
|
|
|
551
551
|
*/
|
|
552
552
|
|
|
553
553
|
TediousRequest.prototype.bulk = function(table, callback) {
|
|
554
|
-
var errorHandlers, errors, handleError, hasReturned, started;
|
|
554
|
+
var errorHandlers, errors, handleError, handleInfo, hasReturned, started;
|
|
555
555
|
table._makeBulk();
|
|
556
556
|
if (!table.name) {
|
|
557
557
|
process.nextTick(function() {
|
|
@@ -593,6 +593,19 @@
|
|
|
593
593
|
return errors.push(e);
|
|
594
594
|
};
|
|
595
595
|
})(this);
|
|
596
|
+
handleInfo = (function(_this) {
|
|
597
|
+
return function(msg) {
|
|
598
|
+
return _this.emit('info', {
|
|
599
|
+
message: msg.message,
|
|
600
|
+
number: msg.number,
|
|
601
|
+
state: msg.state,
|
|
602
|
+
"class": msg["class"],
|
|
603
|
+
lineNumber: msg.lineNumber,
|
|
604
|
+
serverName: msg.serverName,
|
|
605
|
+
procName: msg.procName
|
|
606
|
+
});
|
|
607
|
+
};
|
|
608
|
+
})(this);
|
|
596
609
|
return this._acquire((function(_this) {
|
|
597
610
|
return function(err, connection) {
|
|
598
611
|
var bulk, col, done, i, j, len, len1, objectid, ref1, ref2, req, row;
|
|
@@ -613,8 +626,10 @@
|
|
|
613
626
|
}
|
|
614
627
|
return connection.cancel();
|
|
615
628
|
};
|
|
629
|
+
errorHandlers['infoMessage'] = handleInfo;
|
|
616
630
|
errorHandlers['errorMessage'] = handleError.bind(void 0, false, connection);
|
|
617
631
|
errorHandlers['error'] = handleError.bind(void 0, true, connection);
|
|
632
|
+
connection.on('infoMessage', errorHandlers['infoMessage']);
|
|
618
633
|
connection.on('errorMessage', errorHandlers['errorMessage']);
|
|
619
634
|
connection.on('error', errorHandlers['error']);
|
|
620
635
|
done = bindDomain(function(err, rowCount) {
|
|
@@ -702,7 +717,7 @@
|
|
|
702
717
|
*/
|
|
703
718
|
|
|
704
719
|
TediousRequest.prototype.query = function(command, callback) {
|
|
705
|
-
var batchHasOutput, batchLastRow, chunksBuffer, columns, errorHandlers, errors, handleError, hasReturned, isChunkedRecordset, isJSONRecordset, recordset, recordsets, started, xmlBuffer;
|
|
720
|
+
var batchHasOutput, batchLastRow, chunksBuffer, columns, errorHandlers, errors, handleError, handleInfo, hasReturned, isChunkedRecordset, isJSONRecordset, recordset, recordsets, started, xmlBuffer;
|
|
706
721
|
columns = {};
|
|
707
722
|
recordset = [];
|
|
708
723
|
recordsets = [];
|
|
@@ -742,6 +757,19 @@
|
|
|
742
757
|
return errors.push(e);
|
|
743
758
|
};
|
|
744
759
|
})(this);
|
|
760
|
+
handleInfo = (function(_this) {
|
|
761
|
+
return function(msg) {
|
|
762
|
+
return _this.emit('info', {
|
|
763
|
+
message: msg.message,
|
|
764
|
+
number: msg.number,
|
|
765
|
+
state: msg.state,
|
|
766
|
+
"class": msg["class"],
|
|
767
|
+
lineNumber: msg.lineNumber,
|
|
768
|
+
serverName: msg.serverName,
|
|
769
|
+
procName: msg.procName
|
|
770
|
+
});
|
|
771
|
+
};
|
|
772
|
+
})(this);
|
|
745
773
|
return this._acquire((function(_this) {
|
|
746
774
|
return function(err, connection) {
|
|
747
775
|
var assigns, declarations, doneHandler, name, param, ref1, ref2, req, selects, value;
|
|
@@ -762,8 +790,10 @@
|
|
|
762
790
|
}
|
|
763
791
|
return connection.cancel();
|
|
764
792
|
};
|
|
793
|
+
errorHandlers['infoMessage'] = handleInfo;
|
|
765
794
|
errorHandlers['errorMessage'] = handleError.bind(void 0, false, connection);
|
|
766
795
|
errorHandlers['error'] = handleError.bind(void 0, true, connection);
|
|
796
|
+
connection.on('infoMessage', errorHandlers['infoMessage']);
|
|
767
797
|
connection.on('errorMessage', errorHandlers['errorMessage']);
|
|
768
798
|
connection.on('error', errorHandlers['error']);
|
|
769
799
|
req = new tds.Request(command, bindDomain(function(err) {
|
package/package.json
CHANGED
|
@@ -159,7 +159,7 @@ resolveConnectionString = (string) ->
|
|
|
159
159
|
parsed = parseConnectionURI string
|
|
160
160
|
else
|
|
161
161
|
parsed = parseConnectionString string
|
|
162
|
-
|
|
162
|
+
|
|
163
163
|
if parsed.driver is 'msnodesql'
|
|
164
164
|
parsed.driver = 'SQL Server Native Client 11.0'
|
|
165
165
|
parsed.__original__?.driver = name: 'Driver', escape: ['{', '}']
|
|
@@ -172,11 +172,15 @@ resolveConnectionString = (string) ->
|
|
|
172
172
|
driver: parsed.driver
|
|
173
173
|
password: parsed.pwd ? parsed.password
|
|
174
174
|
database: parsed.database ? parsed['initial catalog']
|
|
175
|
-
connectionTimeout: parsed.timeout ? parsed['connect timeout'] ? parsed['connection timeout']
|
|
176
|
-
requestTimeout: parsed['request timeout']
|
|
175
|
+
connectionTimeout: parsed.connectionTimeout ? parsed.timeout ? parsed['connect timeout'] ? parsed['connection timeout']
|
|
176
|
+
requestTimeout: parsed.requestTimeout ? parsed['request timeout']
|
|
177
177
|
stream: parsed.stream?.toLowerCase() in ['true', 'yes', '1']
|
|
178
178
|
options:
|
|
179
179
|
encrypt: parsed.encrypt?.toLowerCase() in ['true', 'yes', '1']
|
|
180
|
+
|
|
181
|
+
if parsed.useUTC? then config.options.useUTC = parsed.useUTC.toLowerCase() in ['true', 'yes', '1']
|
|
182
|
+
if config.connectionTimeout? then config.connectionTimeout = parseInt config.connectionTimeout
|
|
183
|
+
if config.requestTimeout? then config.requestTimeout = parseInt config.requestTimeout
|
|
180
184
|
|
|
181
185
|
if (/^(.*)\\(.*)$/).exec user
|
|
182
186
|
config.domain = RegExp.$1
|
package/src/msnodesql.coffee
CHANGED
|
@@ -249,7 +249,23 @@ module.exports = (Connection, Transaction, Request, ConnectionError, Transaction
|
|
|
249
249
|
req.on 'meta', (metadata) =>
|
|
250
250
|
if row
|
|
251
251
|
if isChunkedRecordset
|
|
252
|
-
|
|
252
|
+
if columns[0].name is JSON_COLUMN_ID and @connection.config.parseJSON is true
|
|
253
|
+
try
|
|
254
|
+
row = JSON.parse chunksBuffer.join('')
|
|
255
|
+
if not @stream then recordsets[recordsets.length - 1][0] = row
|
|
256
|
+
catch ex
|
|
257
|
+
row = null
|
|
258
|
+
ex = RequestError new Error("Failed to parse incoming JSON. #{ex.message}"), 'EJSON'
|
|
259
|
+
|
|
260
|
+
if @stream
|
|
261
|
+
@emit 'error', ex
|
|
262
|
+
|
|
263
|
+
else
|
|
264
|
+
console.error ex
|
|
265
|
+
|
|
266
|
+
else
|
|
267
|
+
row[columns[0].name] = chunksBuffer.join ''
|
|
268
|
+
|
|
253
269
|
chunksBuffer = null
|
|
254
270
|
|
|
255
271
|
if @verbose
|
|
@@ -341,7 +357,23 @@ module.exports = (Connection, Transaction, Request, ConnectionError, Transaction
|
|
|
341
357
|
unless @nested
|
|
342
358
|
if row
|
|
343
359
|
if isChunkedRecordset
|
|
344
|
-
|
|
360
|
+
if columns[0].name is JSON_COLUMN_ID and @connection.config.parseJSON is true
|
|
361
|
+
try
|
|
362
|
+
row = JSON.parse chunksBuffer.join('')
|
|
363
|
+
if not @stream then recordsets[recordsets.length - 1][0] = row
|
|
364
|
+
catch ex
|
|
365
|
+
row = null
|
|
366
|
+
ex = RequestError new Error("Failed to parse incoming JSON. #{ex.message}"), 'EJSON'
|
|
367
|
+
|
|
368
|
+
if @stream
|
|
369
|
+
@emit 'error', ex
|
|
370
|
+
|
|
371
|
+
else
|
|
372
|
+
console.error ex
|
|
373
|
+
|
|
374
|
+
else
|
|
375
|
+
row[columns[0].name] = chunksBuffer.join ''
|
|
376
|
+
|
|
345
377
|
chunksBuffer = null
|
|
346
378
|
|
|
347
379
|
if @verbose
|
package/src/msnodesqlv8.coffee
CHANGED
|
@@ -322,7 +322,23 @@ module.exports = (Connection, Transaction, Request, ConnectionError, Transaction
|
|
|
322
322
|
req.on 'meta', (metadata) =>
|
|
323
323
|
if row
|
|
324
324
|
if isChunkedRecordset
|
|
325
|
-
|
|
325
|
+
if columns[0].name is JSON_COLUMN_ID and @connection.config.parseJSON is true
|
|
326
|
+
try
|
|
327
|
+
row = JSON.parse chunksBuffer.join('')
|
|
328
|
+
if not @stream then recordsets[recordsets.length - 1][0] = row
|
|
329
|
+
catch ex
|
|
330
|
+
row = null
|
|
331
|
+
ex = RequestError new Error("Failed to parse incoming JSON. #{ex.message}"), 'EJSON'
|
|
332
|
+
|
|
333
|
+
if @stream
|
|
334
|
+
@emit 'error', ex
|
|
335
|
+
|
|
336
|
+
else
|
|
337
|
+
console.error ex
|
|
338
|
+
|
|
339
|
+
else
|
|
340
|
+
row[columns[0].name] = chunksBuffer.join ''
|
|
341
|
+
|
|
326
342
|
chunksBuffer = null
|
|
327
343
|
|
|
328
344
|
if @verbose
|
|
@@ -414,7 +430,23 @@ module.exports = (Connection, Transaction, Request, ConnectionError, Transaction
|
|
|
414
430
|
unless @nested
|
|
415
431
|
if row
|
|
416
432
|
if isChunkedRecordset
|
|
417
|
-
|
|
433
|
+
if columns[0].name is JSON_COLUMN_ID and @connection.config.parseJSON is true
|
|
434
|
+
try
|
|
435
|
+
row = JSON.parse chunksBuffer.join('')
|
|
436
|
+
if not @stream then recordsets[recordsets.length - 1][0] = row
|
|
437
|
+
catch ex
|
|
438
|
+
row = null
|
|
439
|
+
ex = RequestError new Error("Failed to parse incoming JSON. #{ex.message}"), 'EJSON'
|
|
440
|
+
|
|
441
|
+
if @stream
|
|
442
|
+
@emit 'error', ex
|
|
443
|
+
|
|
444
|
+
else
|
|
445
|
+
console.error ex
|
|
446
|
+
|
|
447
|
+
else
|
|
448
|
+
row[columns[0].name] = chunksBuffer.join ''
|
|
449
|
+
|
|
418
450
|
chunksBuffer = null
|
|
419
451
|
|
|
420
452
|
if @verbose
|
package/src/tds.coffee
CHANGED
|
@@ -385,6 +385,16 @@ module.exports = (Connection, Transaction, Request, ConnectionError, Transaction
|
|
|
385
385
|
else
|
|
386
386
|
callback? error, if @multiple or @nested then recordsets else recordsets[0]
|
|
387
387
|
|
|
388
|
+
req.on 'message', (msg) =>
|
|
389
|
+
@emit 'info',
|
|
390
|
+
message: msg.text
|
|
391
|
+
number: msg.number
|
|
392
|
+
state: msg.state
|
|
393
|
+
class: msg.severity
|
|
394
|
+
lineNumber: msg.lineNumber
|
|
395
|
+
serverName: msg.serverName
|
|
396
|
+
procName: msg.procName
|
|
397
|
+
|
|
388
398
|
req.on 'error', (err) =>
|
|
389
399
|
e = RequestError err, 'EREQUEST'
|
|
390
400
|
|
package/src/tedious.coffee
CHANGED
|
@@ -386,6 +386,16 @@ module.exports = (Connection, Transaction, Request, ConnectionError, Transaction
|
|
|
386
386
|
|
|
387
387
|
# we must collect errors even in stream mode
|
|
388
388
|
errors.push e
|
|
389
|
+
|
|
390
|
+
handleInfo = (msg) =>
|
|
391
|
+
@emit 'info',
|
|
392
|
+
message: msg.message
|
|
393
|
+
number: msg.number
|
|
394
|
+
state: msg.state
|
|
395
|
+
class: msg.class
|
|
396
|
+
lineNumber: msg.lineNumber
|
|
397
|
+
serverName: msg.serverName
|
|
398
|
+
procName: msg.procName
|
|
389
399
|
|
|
390
400
|
@_acquire (err, connection) =>
|
|
391
401
|
unless err
|
|
@@ -401,8 +411,10 @@ module.exports = (Connection, Transaction, Request, ConnectionError, Transaction
|
|
|
401
411
|
connection.cancel()
|
|
402
412
|
|
|
403
413
|
# attach handler to handle multiple error messages
|
|
414
|
+
errorHandlers['infoMessage'] = handleInfo
|
|
404
415
|
errorHandlers['errorMessage'] = handleError.bind(undefined, false, connection)
|
|
405
416
|
errorHandlers['error'] = handleError.bind(undefined, true, connection)
|
|
417
|
+
connection.on 'infoMessage', errorHandlers['infoMessage']
|
|
406
418
|
connection.on 'errorMessage', errorHandlers['errorMessage']
|
|
407
419
|
connection.on 'error', errorHandlers['error']
|
|
408
420
|
|
|
@@ -510,6 +522,16 @@ module.exports = (Connection, Transaction, Request, ConnectionError, Transaction
|
|
|
510
522
|
# we must collect errors even in stream mode
|
|
511
523
|
errors.push e
|
|
512
524
|
|
|
525
|
+
handleInfo = (msg) =>
|
|
526
|
+
@emit 'info',
|
|
527
|
+
message: msg.message
|
|
528
|
+
number: msg.number
|
|
529
|
+
state: msg.state
|
|
530
|
+
class: msg.class
|
|
531
|
+
lineNumber: msg.lineNumber
|
|
532
|
+
serverName: msg.serverName
|
|
533
|
+
procName: msg.procName
|
|
534
|
+
|
|
513
535
|
@_acquire (err, connection) =>
|
|
514
536
|
unless err
|
|
515
537
|
if @verbose then @_log "---------- sql #{if @_isBatch then 'batch' else 'query'} ----------\n #{if @_isBatch then 'batch' else 'query'}: #{command}"
|
|
@@ -524,8 +546,10 @@ module.exports = (Connection, Transaction, Request, ConnectionError, Transaction
|
|
|
524
546
|
connection.cancel()
|
|
525
547
|
|
|
526
548
|
# attach handler to handle multiple error messages
|
|
549
|
+
errorHandlers['infoMessage'] = handleInfo
|
|
527
550
|
errorHandlers['errorMessage'] = handleError.bind(undefined, false, connection)
|
|
528
551
|
errorHandlers['error'] = handleError.bind(undefined, true, connection)
|
|
552
|
+
connection.on 'infoMessage', errorHandlers['infoMessage']
|
|
529
553
|
connection.on 'errorMessage', errorHandlers['errorMessage']
|
|
530
554
|
connection.on 'error', errorHandlers['error']
|
|
531
555
|
|