tedious 1.12.3 → 1.14.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.
Files changed (62) hide show
  1. package/README.md +1 -1
  2. package/appveyor.yml +9 -5
  3. package/benchmarks/README.md +33 -0
  4. package/benchmarks/common.js +82 -0
  5. package/benchmarks/index.js +34 -0
  6. package/benchmarks/query/many-result-rows.js +49 -0
  7. package/benchmarks/query/nvarchar-large.js +44 -0
  8. package/benchmarks/query/nvarchar-small.js +44 -0
  9. package/benchmarks/query/varbinary-4.js +42 -0
  10. package/benchmarks/query/varbinary-huge.js +46 -0
  11. package/benchmarks/query/varbinary-large.js +46 -0
  12. package/benchmarks/query/varbinary-small.js +42 -0
  13. package/benchmarks/token-parser/colmetadata-token.js +42 -0
  14. package/benchmarks/token-parser/done-token.js +42 -0
  15. package/benchmarks/token-parser/simple-tokens.js +366 -0
  16. package/lib/all-headers.js +9 -11
  17. package/lib/buffertools.js +17 -13
  18. package/lib/bulk-load.js +196 -169
  19. package/lib/collation.js +80 -2
  20. package/lib/connection.js +1086 -1060
  21. package/lib/data-type.js +450 -253
  22. package/lib/debug.js +57 -51
  23. package/lib/errors.js +40 -55
  24. package/lib/guid-parser.js +12 -36
  25. package/lib/instance-lookup.js +57 -54
  26. package/lib/library.js +3 -2
  27. package/lib/login7-payload.js +187 -180
  28. package/lib/message-io.js +169 -199
  29. package/lib/metadata-parser.js +169 -255
  30. package/lib/ntlm-payload.js +173 -160
  31. package/lib/packet.js +166 -152
  32. package/lib/prelogin-payload.js +170 -160
  33. package/lib/request.js +122 -122
  34. package/lib/rpcrequest-payload.js +64 -38
  35. package/lib/special-stored-procedure.js +3 -2
  36. package/lib/sqlbatch-payload.js +20 -16
  37. package/lib/stream-parser.js +116 -104
  38. package/lib/tds-versions.js +5 -8
  39. package/lib/tedious.js +8 -14
  40. package/lib/token/colmetadata-token-parser.js +79 -125
  41. package/lib/token/done-token-parser.js +47 -129
  42. package/lib/token/env-change-token-parser.js +90 -126
  43. package/lib/token/infoerror-token-parser.js +47 -125
  44. package/lib/token/loginack-token-parser.js +36 -74
  45. package/lib/token/nbcrow-token-parser.js +40 -64
  46. package/lib/token/order-token-parser.js +26 -43
  47. package/lib/token/returnstatus-token-parser.js +11 -23
  48. package/lib/token/returnvalue-token-parser.js +31 -54
  49. package/lib/token/row-token-parser.js +39 -52
  50. package/lib/token/sspi-token-parser.js +14 -32
  51. package/lib/token/stream-parser.js +424 -304
  52. package/lib/token/token-stream-parser.js +39 -34
  53. package/lib/token/token.js +3 -6
  54. package/lib/tracking-buffer/bigint.js +45 -48
  55. package/lib/tracking-buffer/readable-tracking-buffer.js +238 -223
  56. package/lib/tracking-buffer/tracking-buffer.js +3 -9
  57. package/lib/tracking-buffer/writable-tracking-buffer.js +272 -244
  58. package/lib/transaction.js +112 -102
  59. package/lib/value-parser.js +559 -1154
  60. package/package.json +10 -9
  61. package/benchmarks/benchmarks.coffee +0 -122
  62. package/benchmarks/query.coffee +0 -57
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # Tedious (node implementation of TDS)
2
- [![Dependency Status](https://david-dm.org/pekim/tedious.png)](https://david-dm.org/pekim/tedious) [![NPM version](https://badge.fury.io/js/tedious.png)](http://badge.fury.io/js/tedious) [![Build Status](https://secure.travis-ci.org/pekim/tedious.png)](http://travis-ci.org/pekim/tedious) [![Build Status](https://ci.appveyor.com/api/projects/status/ike3p58hljpyffrl?svg=true)](https://ci.appveyor.com/project/pekim/tedious)
2
+ [![Dependency Status](https://david-dm.org/pekim/tedious.svg)](https://david-dm.org/pekim/tedious) [![NPM version](https://badge.fury.io/js/tedious.svg)](http://badge.fury.io/js/tedious) [![Build Status](https://secure.travis-ci.org/pekim/tedious.svg)](http://travis-ci.org/pekim/tedious) [![Build Status](https://ci.appveyor.com/api/projects/status/ike3p58hljpyffrl?svg=true)](https://ci.appveyor.com/project/pekim/tedious)
3
3
 
4
4
  Tedious is an implementation of the [TDS protocol](http://msdn.microsoft.com/en-us/library/dd304523.aspx),
5
5
  which is used to interact with instances of Microsoft's SQL Server. It is intended to be a fairly slim implementation of the protocol, with not too much additional functionality.
package/appveyor.yml CHANGED
@@ -4,10 +4,14 @@ environment:
4
4
  matrix:
5
5
  - nodejs_version: "0.10"
6
6
  - nodejs_version: "0.12"
7
- - nodejs_version: "1.0"
8
- - nodejs_version: "1.8"
9
- - nodejs_version: "2.0"
10
- - nodejs_version: "2.3"
7
+ - nodejs_version: "4"
8
+ - nodejs_version: "5"
9
+
10
+ branches:
11
+ only:
12
+ - master
13
+ - /^maint\/.+/
14
+ - /v\d+\.\d+\.\d+/
11
15
 
12
16
  install:
13
17
  - ps: Install-Product node $env:nodejs_version
@@ -36,7 +40,7 @@ test_script:
36
40
  powershell %cd%\scripts\appveyor\config.ps1 SQL2008R2SP2
37
41
  npm run-script test-integration || SET EXITVAL=1
38
42
  net stop MSSQL$SQL2008R2SP2
39
-
43
+
40
44
  powershell %cd%\scripts\appveyor\config.ps1 SQL2012SP1
41
45
  npm run-script test-integration || SET EXITVAL=1
42
46
  net stop MSSQL$SQL2012SP1
@@ -0,0 +1,33 @@
1
+ # Tedious Benchmarks
2
+
3
+ This folder contains a collection of benchmarks for `tedious`.
4
+
5
+ Running all existing benchmarks is easy, just execute the following from
6
+ inside the `tedious` root folder:
7
+
8
+ ```sh
9
+ node benchmarks
10
+ ```
11
+
12
+ **NOTE:** The benchmarks try to load `tedious` code from `lib`, so make sure
13
+ you run `npm run prepublish` first.
14
+
15
+ This will serially execute every available benchmark test in a
16
+ seperate Node.js process. Running each benchmark in a separate process
17
+ ensures that each benchmark is run with a clean slate.
18
+
19
+ You can also execute a specific benchmarks:
20
+
21
+ ```sh
22
+ node benchmarks/<type>/<benchmark-name>
23
+ ```
24
+
25
+ The benchmarks are executed by using the `benchmark` module. Unfortunately,
26
+ this module can add a bit of useless noise when trying to collect profiling
27
+ information. To reduce this noise, benchmarks can be run in a special "profile"
28
+ mode. This will execute the benchmark's code without making use of `benchmark`
29
+ library and with a fixed number of iterations.
30
+
31
+ ```sh
32
+ node benchmarks/<type>/<benchmark-name> --profile
33
+ ```
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+
3
+ var fs = require("fs");
4
+ var async = require("async");
5
+ var Benchmark = require("benchmark");
6
+ var Connection = require("../lib/tedious").Connection;
7
+
8
+ function createConnection(cb) {
9
+ var config = JSON.parse(fs.readFileSync(process.env.HOME + '/.tedious/test-connection.json', 'utf8')).config;
10
+
11
+ var connection = new Connection(config);
12
+ connection.on("connect", function() {
13
+ cb(connection);
14
+ });
15
+ }
16
+
17
+ function createBenchmark(test) {
18
+ if (process.argv.indexOf("--profile") != -1) {
19
+ process.nextTick(function() {
20
+ runProfile(test);
21
+ });
22
+ } else {
23
+ process.nextTick(function() {
24
+ runBenchmark(test);
25
+ });
26
+ }
27
+ }
28
+
29
+ function runBenchmark(test) {
30
+ var memStart, memMax = memStart = process.memoryUsage().rss;
31
+
32
+ test.setup(function(err) {
33
+ if (err) throw err;
34
+
35
+ var bm = new Benchmark(test.name, {
36
+ defer: true,
37
+ fn: function(deferred) {
38
+ test.exec(function(err) {
39
+ if (err) throw err;
40
+
41
+ memMax = Math.max(memMax, process.memoryUsage().rss);
42
+
43
+ deferred.resolve();
44
+ });
45
+ }
46
+ });
47
+
48
+ bm.on("complete", function(event) {
49
+ console.log(String(event.target))
50
+ console.log("Memory:", (memMax - memStart)/1024/1024, "MiB")
51
+
52
+ test.teardown(function(err) {
53
+ if (err) throw err;
54
+ });
55
+ });
56
+
57
+ bm.run({ "async": true });
58
+ });
59
+ }
60
+
61
+ function runProfile(test) {
62
+ test.setup(function(err) {
63
+ if (err) throw err;
64
+
65
+ async.timesSeries(test.profileIterations, function(n, done) {
66
+ async.setImmediate(function() {
67
+ console.log("[Iteration " + n + "]");
68
+ test.exec(done);
69
+ });
70
+ }, function(err) {
71
+ if (err) throw err;
72
+
73
+ test.teardown(function(err) {
74
+ if (err) throw err;
75
+ });
76
+ });
77
+ });
78
+ }
79
+
80
+ module.exports.createBenchmark = createBenchmark;
81
+ module.exports.createConnection = createConnection;
82
+
@@ -0,0 +1,34 @@
1
+ var fs = require("fs");
2
+ var path = require("path");
3
+ var childProcess = require("child_process")
4
+ var Benchmark = require("benchmark");
5
+
6
+ var Connection = require("../lib/tedious").Connection;
7
+ var Request = require("../lib/tedious").Request;
8
+
9
+ var types = ["query", "token-parser"];
10
+ var tests = [];
11
+
12
+ types.forEach(function(type) {
13
+ var dir = path.join(__dirname, type);
14
+ tests.push.apply(tests, fs.readdirSync(dir).map(function(file) {
15
+ return path.join(dir, file);
16
+ }));
17
+ });
18
+
19
+ runBenchmarks();
20
+
21
+ function runBenchmarks() {
22
+ var test = tests.shift();
23
+ if (!test)
24
+ return;
25
+
26
+ var child = childProcess.spawn(process.execPath, [ test ], { stdio: 'inherit' });
27
+ child.on('close', function(code) {
28
+ if (code) {
29
+ process.exit(code);
30
+ } else {
31
+ runBenchmarks();
32
+ }
33
+ });
34
+ }
@@ -0,0 +1,49 @@
1
+ var tedious = require("../../lib/tedious");
2
+ var Request = tedious.Request;
3
+ var TYPES = tedious.TYPES;
4
+ var async = require("async");
5
+
6
+ var common = require("../common");
7
+
8
+ var connection;
9
+ common.createBenchmark({
10
+ name: "Many result rows",
11
+ profileIterations: 10,
12
+
13
+ setup: function(cb) {
14
+ common.createConnection(function(_connection) {
15
+ connection = _connection;
16
+
17
+ var request = new Request("CREATE TABLE #benchmark ([id] int IDENTITY(1,1), [name] nvarchar(100), [description] nvarchar(max))", function(err) {
18
+ if (err) return cb(err);
19
+
20
+ async.timesSeries(10000, function(n, next) {
21
+ var request = new Request("INSERT INTO #benchmark ([name], [description]) VALUES (@name, @description)", next);
22
+
23
+ request.addParameter("name", TYPES.NVarChar, "Row " + n);
24
+ request.addParameter("description", TYPES.NVarChar, "Example Test Description for Row " + n);
25
+
26
+ connection.execSql(request);
27
+ }, cb);
28
+ });
29
+
30
+ connection.execSqlBatch(request);
31
+ });
32
+ },
33
+
34
+ exec: function(cb) {
35
+ var request = new Request("SELECT * FROM #benchmark", cb);
36
+ connection.execSql(request);
37
+ },
38
+
39
+ teardown: function(cb) {
40
+ var request = new Request("DROP TABLE #benchmark", function(err) {
41
+ if (err) {
42
+ return cb(err);
43
+ }
44
+
45
+ connection.close();
46
+ });
47
+ connection.execSqlBatch(request);
48
+ }
49
+ });
@@ -0,0 +1,44 @@
1
+ var tedious = require("../../lib/tedious");
2
+ var Request = tedious.Request;
3
+ var TYPES = tedious.TYPES;
4
+
5
+ var common = require("../common");
6
+
7
+ var connection;
8
+ common.createBenchmark({
9
+ name: "inserting nvarchar(max) with 5242880 chars",
10
+
11
+ profileIterations: 100,
12
+
13
+ setup: function(cb) {
14
+ common.createConnection(function(_connection) {
15
+ connection = _connection;
16
+
17
+ var request = new Request("CREATE TABLE #benchmark ([value] nvarchar(max))", function(err) {
18
+ if (err) return cb(err);
19
+
20
+ var request = new Request("INSERT INTO #benchmark ([value]) VALUES (@value)", cb);
21
+ request.addParameter("value", TYPES.NVarChar, new Array(5 * 1024 * 1024).join("x"));
22
+ connection.execSql(request);
23
+ });
24
+
25
+ connection.execSqlBatch(request);
26
+ });
27
+ },
28
+
29
+ exec: function(cb) {
30
+ var request = new Request("SELECT * FROM #benchmark", cb);
31
+ connection.execSql(request);
32
+ },
33
+
34
+ teardown: function(cb) {
35
+ var request = new Request("DROP TABLE #benchmark", function(err) {
36
+ if (err) {
37
+ return cb(err);
38
+ }
39
+
40
+ connection.close();
41
+ });
42
+ connection.execSqlBatch(request);
43
+ }
44
+ });
@@ -0,0 +1,44 @@
1
+ var tedious = require("../../lib/tedious");
2
+ var Request = tedious.Request;
3
+ var TYPES = tedious.TYPES;
4
+
5
+ var common = require("../common");
6
+
7
+ var connection;
8
+ common.createBenchmark({
9
+ name: "inserting nvarchar(max) with 4 chars",
10
+
11
+ profileIterations: 10000,
12
+
13
+ setup: function(cb) {
14
+ common.createConnection(function(_connection) {
15
+ connection = _connection;
16
+
17
+ var request = new Request("CREATE TABLE #benchmark ([value] nvarchar(max))", function(err) {
18
+ if (err) return cb(err);
19
+
20
+ var request = new Request("INSERT INTO #benchmark ([value]) VALUES (@value)", cb);
21
+ request.addParameter("value", TYPES.NVarChar, "asdf");
22
+ connection.execSql(request);
23
+ });
24
+
25
+ connection.execSqlBatch(request);
26
+ });
27
+ },
28
+
29
+ exec: function(cb) {
30
+ var request = new Request("SELECT * FROM #benchmark", cb);
31
+ connection.execSql(request);
32
+ },
33
+
34
+ teardown: function(cb) {
35
+ var request = new Request("DROP TABLE #benchmark", function(err) {
36
+ if (err) {
37
+ return cb(err);
38
+ }
39
+
40
+ connection.close();
41
+ });
42
+ connection.execSqlBatch(request);
43
+ }
44
+ });
@@ -0,0 +1,42 @@
1
+ var tedious = require("../../lib/tedious");
2
+ var Request = tedious.Request;
3
+ var TYPES = tedious.TYPES;
4
+
5
+ var common = require("../common");
6
+
7
+ var connection;
8
+ common.createBenchmark({
9
+ name: "inserting varbinary(4) with 4 bytes",
10
+
11
+ setup: function(cb) {
12
+ common.createConnection(function(_connection) {
13
+ connection = _connection;
14
+
15
+ var request = new Request("CREATE TABLE #benchmark ([value] varbinary(4))", function(err) {
16
+ if (err) return cb(err);
17
+
18
+ var request = new Request("INSERT INTO #benchmark ([value]) VALUES (@value)", cb);
19
+ request.addParameter("value", TYPES.VarBinary, new Buffer("asdf"));
20
+ connection.execSql(request);
21
+ });
22
+
23
+ connection.execSqlBatch(request);
24
+ });
25
+ },
26
+
27
+ exec: function(cb) {
28
+ var request = new Request("SELECT * FROM #benchmark", cb);
29
+ connection.execSql(request);
30
+ },
31
+
32
+ teardown: function(cb) {
33
+ var request = new Request("DROP TABLE #benchmark", function(err) {
34
+ if (err) {
35
+ return cb(err);
36
+ }
37
+
38
+ connection.close();
39
+ });
40
+ connection.execSqlBatch(request);
41
+ }
42
+ });
@@ -0,0 +1,46 @@
1
+ var tedious = require("../../lib/tedious");
2
+ var Request = tedious.Request;
3
+ var TYPES = tedious.TYPES;
4
+
5
+ var common = require("../common");
6
+
7
+ var connection;
8
+ common.createBenchmark({
9
+ name: "inserting varbinary(max) with 50 MiB",
10
+
11
+ profileIterations: 20,
12
+
13
+ setup: function(cb) {
14
+ common.createConnection(function(_connection) {
15
+ connection = _connection;
16
+
17
+ var request = new Request("CREATE TABLE #benchmark ([value] varbinary(max))", function(err) {
18
+ if (err) return cb(err);
19
+
20
+ var request = new Request("INSERT INTO #benchmark ([value]) VALUES (@value)", cb);
21
+ var buf = new Buffer(50 * 1024 * 1024);
22
+ buf.fill("x");
23
+ request.addParameter("value", TYPES.VarBinary, buf);
24
+ connection.execSql(request);
25
+ });
26
+
27
+ connection.execSqlBatch(request);
28
+ });
29
+ },
30
+
31
+ exec: function(cb) {
32
+ var request = new Request("SELECT * FROM #benchmark", cb);
33
+ connection.execSql(request);
34
+ },
35
+
36
+ teardown: function(cb) {
37
+ var request = new Request("DROP TABLE #benchmark", function(err) {
38
+ if (err) {
39
+ return cb(err);
40
+ }
41
+
42
+ connection.close();
43
+ });
44
+ connection.execSqlBatch(request);
45
+ }
46
+ });
@@ -0,0 +1,46 @@
1
+ var tedious = require("../../lib/tedious");
2
+ var Request = tedious.Request;
3
+ var TYPES = tedious.TYPES;
4
+
5
+ var common = require("../common");
6
+
7
+ var connection;
8
+ common.createBenchmark({
9
+ name: "inserting varbinary(max) with 5 MiB",
10
+
11
+ profileIterations: 100,
12
+
13
+ setup: function(cb) {
14
+ common.createConnection(function(_connection) {
15
+ connection = _connection;
16
+
17
+ var request = new Request("CREATE TABLE #benchmark ([value] varbinary(max))", function(err) {
18
+ if (err) return cb(err);
19
+
20
+ var request = new Request("INSERT INTO #benchmark ([value]) VALUES (@value)", cb);
21
+ var buf = new Buffer(5 * 1024 * 1024);
22
+ buf.fill("x");
23
+ request.addParameter("value", TYPES.VarBinary, buf);
24
+ connection.execSql(request);
25
+ });
26
+
27
+ connection.execSqlBatch(request);
28
+ });
29
+ },
30
+
31
+ exec: function(cb) {
32
+ var request = new Request("SELECT * FROM #benchmark", cb);
33
+ connection.execSql(request);
34
+ },
35
+
36
+ teardown: function(cb) {
37
+ var request = new Request("DROP TABLE #benchmark", function(err) {
38
+ if (err) {
39
+ return cb(err);
40
+ }
41
+
42
+ connection.close();
43
+ });
44
+ connection.execSqlBatch(request);
45
+ }
46
+ });
@@ -0,0 +1,42 @@
1
+ var tedious = require("../../lib/tedious");
2
+ var Request = tedious.Request;
3
+ var TYPES = tedious.TYPES;
4
+
5
+ var common = require("../common");
6
+
7
+ var connection;
8
+ common.createBenchmark({
9
+ name: "inserting varbinary(max) with 4 bytes",
10
+
11
+ setup: function(cb) {
12
+ common.createConnection(function(_connection) {
13
+ connection = _connection;
14
+
15
+ var request = new Request("CREATE TABLE #benchmark ([value] varbinary(max))", function(err) {
16
+ if (err) return cb(err);
17
+
18
+ var request = new Request("INSERT INTO #benchmark ([value]) VALUES (@value)", cb);
19
+ request.addParameter("value", TYPES.VarBinary, new Buffer("asdf"));
20
+ connection.execSql(request);
21
+ });
22
+
23
+ connection.execSqlBatch(request);
24
+ });
25
+ },
26
+
27
+ exec: function(cb) {
28
+ var request = new Request("SELECT * FROM #benchmark", cb);
29
+ connection.execSql(request);
30
+ },
31
+
32
+ teardown: function(cb) {
33
+ var request = new Request("DROP TABLE #benchmark", function(err) {
34
+ if (err) {
35
+ return cb(err);
36
+ }
37
+
38
+ connection.close();
39
+ });
40
+ connection.execSqlBatch(request);
41
+ }
42
+ });
@@ -0,0 +1,42 @@
1
+ var tedious = require("../../lib/tedious");
2
+ var Request = tedious.Request;
3
+ var TYPES = tedious.TYPES;
4
+
5
+ var Parser = require("../../lib/token/token-stream-parser").Parser;
6
+
7
+ var common = require("../common");
8
+
9
+ var parser = new Parser({ token: function() { } }, {}, {});
10
+
11
+ var tokenCount = 50;
12
+ var data = new Buffer(new Array(tokenCount).join("810300000000001000380269006400000000000900e7c8000904d00034046e0061006d006500000000000900e7ffff0904d000340b6400650073006300720069007000740069006f006e00"), "hex");
13
+
14
+ common.createBenchmark({
15
+ name: "parsing `COLMETADATA` tokens",
16
+
17
+ profileIterations: 3000,
18
+
19
+ setup: function(cb) {
20
+ cb();
21
+ },
22
+
23
+ exec: function(cb) {
24
+ var count = 0;
25
+
26
+ parser.on("columnMetadata", function() {
27
+ count += 1;
28
+
29
+ if (count === tokenCount - 1) {
30
+ parser.removeAllListeners("columnMetadata");
31
+
32
+ cb();
33
+ }
34
+ });
35
+
36
+ parser.addBuffer(data);
37
+ },
38
+
39
+ teardown: function(cb) {
40
+ cb();
41
+ }
42
+ });
@@ -0,0 +1,42 @@
1
+ var tedious = require("../../lib/tedious");
2
+ var Request = tedious.Request;
3
+ var TYPES = tedious.TYPES;
4
+
5
+ var Parser = require("../../lib/token/token-stream-parser").Parser;
6
+
7
+ var common = require("../common");
8
+
9
+ var parser = new Parser({ token: function() { } }, {}, {});
10
+
11
+ var tokenCount = 500;
12
+ var data = new Buffer(new Array(tokenCount).join("FE0000E0000000000000000000"), "hex");
13
+
14
+ common.createBenchmark({
15
+ name: "parsing `DONEPROC` tokens",
16
+
17
+ profileIterations: 3000,
18
+
19
+ setup: function(cb) {
20
+ cb();
21
+ },
22
+
23
+ exec: function(cb) {
24
+ var count = 0;
25
+
26
+ parser.on("doneProc", function() {
27
+ count += 1;
28
+
29
+ if (count === tokenCount - 1) {
30
+ parser.removeAllListeners("doneProc");
31
+
32
+ cb();
33
+ }
34
+ });
35
+
36
+ parser.addBuffer(data);
37
+ },
38
+
39
+ teardown: function(cb) {
40
+ cb();
41
+ }
42
+ });