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 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](#cfg) to learn more.
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](#twotothree)
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](#cfg-general)
87
- * [Formats](#cfg-formats)
86
+ * [General](#general-same-for-all-drivers)
87
+ * [Formats](#formats)
88
88
 
89
89
  ### Drivers
90
90
 
91
- * [Tedious](#cfg-tedious)
92
- * [Microsoft / Contributors Node V8 Driver for Node.js for SQL Server](#cfg-msnodesqlv8)
93
- * [Microsoft Driver for Node.js for SQL Server](#cfg-msnodesql)
94
- * [node-tds](#cfg-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](#prepared-statement-input)
125
- * [output](#prepared-statement-output)
126
- * [prepare](#prepare)
127
- * [execute](#prepared-statement-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
- * [Metadata](#meta)
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
- <a name="connection" />
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
- <a name="connect" />
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
- <a name="request" />
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
- <a name="execute" />
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
- <a name="input" />
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
- <a name="output" />
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
- <a name="pipe" />
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
- <a name="query" />
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
- <a name="batch" />
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
- <a name="transaction" />
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
- <a name="begin" />
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
- <a name="commit" />
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
- <a name="rollback" />
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
- <a name="prepared-statement" />
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
- <a name="prepared-statement-input" />
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
- <a name="prepared-statement-output" />
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
- <a name="prepare" />
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
- <a name="prepared-statement-execute" />
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
- <a name="unprepare" />
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
- <a name="json" />
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 error number.
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
- <a name="meta" />
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`](#prepared-statement-execute) method now returns 3 arguments instead of 2.
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
@@ -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: (ref10 = (ref11 = parsed.stream) != null ? ref11.toLowerCase() : void 0) === 'true' || ref10 === 'yes' || ref10 === '1',
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: (ref12 = (ref13 = parsed.encrypt) != null ? ref13.toLowerCase() : void 0) === 'true' || ref12 === 'yes' || ref12 === '1'
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 ((ref14 = server.toLowerCase()) === '.' || ref14 === '(.)' || ref14 === '(localdb)' || ref14 === '(local)') {
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
- row[columns[0].name] = chunksBuffer.join('');
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
- row[columns[0].name] = chunksBuffer.join('');
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) {
@@ -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
- row[columns[0].name] = chunksBuffer.join('');
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
- row[columns[0].name] = chunksBuffer.join('');
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
@@ -21,7 +21,7 @@
21
21
  "azure",
22
22
  "node-mssql"
23
23
  ],
24
- "version": "3.2.1",
24
+ "version": "3.3.0",
25
25
  "main": "index.js",
26
26
  "repository": {
27
27
  "type": "git",
@@ -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
@@ -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
- row[columns[0].name] = chunksBuffer.join ''
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
- row[columns[0].name] = chunksBuffer.join ''
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
@@ -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
- row[columns[0].name] = chunksBuffer.join ''
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
- row[columns[0].name] = chunksBuffer.join ''
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
 
@@ -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