mysql2 0.2.2 → 0.2.3
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/.travis.yml +1 -1
- package/benchmarks/bench-insert-select-parallel.js +80 -0
- package/benchmarks/bench-insert-select-prepared.js +8 -6
- package/benchmarks/bench-insert-select.js +2 -2
- package/benchmarks/ticks.txt +228 -0
- package/examples/select.js +5 -0
- package/index.js +2 -0
- package/lib/commands/execute.js +46 -4
- package/lib/commands/query.js +2 -1
- package/lib/compile_binary_parser.js +66 -0
- package/lib/compile_text_parser.js +11 -12
- package/lib/connection.js +9 -3
- package/lib/packets/binary_row.js +21 -18
- package/lib/packets/packet.js +122 -2
- package/package.json +1 -1
package/.travis.yml
CHANGED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
var common = require('../test/common');
|
|
2
|
+
var connection = common.createConnection();
|
|
3
|
+
var assert = require('assert');
|
|
4
|
+
|
|
5
|
+
var table = 'insert_test';
|
|
6
|
+
//var text = "本日は晴天なり";
|
|
7
|
+
var text = "test abc xyz";
|
|
8
|
+
connection.query('drop table ' + table).on('error', function() {});
|
|
9
|
+
connection.query([
|
|
10
|
+
'CREATE TABLE `' + table + '` (',
|
|
11
|
+
'`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
|
|
12
|
+
'`title` varchar(255) NOT NULL,',
|
|
13
|
+
'PRIMARY KEY (`id`)',
|
|
14
|
+
') ENGINE=InnoDB DEFAULT CHARSET=utf8'
|
|
15
|
+
].join('\n'));
|
|
16
|
+
|
|
17
|
+
function benchmarkInsert(numLeft, callback) {
|
|
18
|
+
connection.query('INSERT INTO ' + table + ' SET title="' + text + '"', function(err, result) {
|
|
19
|
+
if (err) throw err;
|
|
20
|
+
if (numLeft > 1)
|
|
21
|
+
benchmarkInsert(numLeft-1, callback);
|
|
22
|
+
else
|
|
23
|
+
callback();
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function benchmarkInserts(n, cb) {
|
|
28
|
+
var numInsert = 50000;
|
|
29
|
+
var start = process.hrtime();
|
|
30
|
+
benchmarkInsert(numInsert, function() {
|
|
31
|
+
var end = process.hrtime();
|
|
32
|
+
var diff = common.hrdiff(start, end);
|
|
33
|
+
console.log(numInsert*1e9/diff + ' inserts/sec');
|
|
34
|
+
if (n > 1)
|
|
35
|
+
benchmarkInserts(n - 1, cb);
|
|
36
|
+
else
|
|
37
|
+
cb();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function benchmarkParallelSelects(n, size, cb) {
|
|
42
|
+
var start = process.hrtime();
|
|
43
|
+
var numRunning = 0;
|
|
44
|
+
|
|
45
|
+
function commandDone() {
|
|
46
|
+
console.log(numRunning);
|
|
47
|
+
numRunning--;
|
|
48
|
+
if (numRunning > 0)
|
|
49
|
+
return;
|
|
50
|
+
var end = process.hrtime();
|
|
51
|
+
var diff = common.hrdiff(start, end);
|
|
52
|
+
console.log(size + ' rows: ' + n*1e9/diff + ' results/sec, ' + size*n*1e9/diff + ' rows/sec');
|
|
53
|
+
cb();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
var connections = new Array(n);
|
|
57
|
+
for (var i=0; i < n; ++i)
|
|
58
|
+
{
|
|
59
|
+
numRunning++;
|
|
60
|
+
connections[i] = common.createConnection();
|
|
61
|
+
var cmd = connections[i].execute('select * from ' + table + ' limit ' + size, []);
|
|
62
|
+
cmd.on('end', commandDone);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = function(done) {
|
|
67
|
+
var testStart = process.hrtime();
|
|
68
|
+
benchmarkInserts(1, function() {
|
|
69
|
+
benchmarkParallelSelects(8, 50000, function() {
|
|
70
|
+
var testEnd = process.hrtime();
|
|
71
|
+
console.log('total time: ', common.hrdiff(testStart, testEnd)/1e9 );
|
|
72
|
+
if (done)
|
|
73
|
+
done();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
if (require.main === module) {
|
|
79
|
+
module.exports();
|
|
80
|
+
}
|
|
@@ -8,13 +8,15 @@ var text = "test abc xyz";
|
|
|
8
8
|
connection.query([
|
|
9
9
|
'CREATE TEMPORARY TABLE `' + table + '` (',
|
|
10
10
|
'`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
|
|
11
|
-
'`
|
|
11
|
+
'`id1` tinyint NOT NULL,',
|
|
12
|
+
// '`title` varchar(255),',
|
|
12
13
|
'PRIMARY KEY (`id`)',
|
|
13
14
|
') ENGINE=InnoDB DEFAULT CHARSET=utf8'
|
|
14
15
|
].join('\n'));
|
|
15
16
|
|
|
16
17
|
function benchmarkInsert(numLeft, callback) {
|
|
17
|
-
connection.execute('INSERT INTO ' + table + ' SET title="' + text + '"', [], function(err, result) {
|
|
18
|
+
//connection.execute('INSERT INTO ' + table + ' SET title="' + text + '"', [], function(err, result) {
|
|
19
|
+
connection.execute('INSERT INTO ' + table + ' SET id1=123', [], function(err, result) {
|
|
18
20
|
if (err) throw err;
|
|
19
21
|
if (numLeft > 1)
|
|
20
22
|
benchmarkInsert(numLeft-1, callback);
|
|
@@ -24,7 +26,7 @@ function benchmarkInsert(numLeft, callback) {
|
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
function benchmarkInserts(n, cb) {
|
|
27
|
-
var numInsert =
|
|
29
|
+
var numInsert = 500000;
|
|
28
30
|
var start = process.hrtime();
|
|
29
31
|
benchmarkInsert(numInsert, function() {
|
|
30
32
|
var end = process.hrtime();
|
|
@@ -64,9 +66,9 @@ function benchmarkSelects(n, size, cb) {
|
|
|
64
66
|
module.exports = function(done) {
|
|
65
67
|
var testStart = process.hrtime();
|
|
66
68
|
benchmarkInserts(1, function() {
|
|
67
|
-
benchmarkSelects(
|
|
68
|
-
benchmarkSelects(
|
|
69
|
-
benchmarkSelects(
|
|
69
|
+
benchmarkSelects(50, 100, function() {
|
|
70
|
+
benchmarkSelects(100, 1000, function() {
|
|
71
|
+
benchmarkSelects(20, 500000, function() {
|
|
70
72
|
var testEnd = process.hrtime();
|
|
71
73
|
console.log('total time: ', common.hrdiff(testStart, testEnd)/1e9 );
|
|
72
74
|
connection.end();
|
|
@@ -7,13 +7,13 @@ var text = "本日は晴天なり";
|
|
|
7
7
|
connection.query([
|
|
8
8
|
'CREATE TEMPORARY TABLE `' + table + '` (',
|
|
9
9
|
'`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
|
|
10
|
-
'`
|
|
10
|
+
'`ttt` int(11) unsigned NOT NULL,',
|
|
11
11
|
'PRIMARY KEY (`id`)',
|
|
12
12
|
') ENGINE=InnoDB DEFAULT CHARSET=utf8'
|
|
13
13
|
].join('\n'));
|
|
14
14
|
|
|
15
15
|
function benchmarkInsert(numLeft, callback) {
|
|
16
|
-
connection.query('INSERT INTO ' + table + ' SET
|
|
16
|
+
connection.query('INSERT INTO ' + table + ' SET ttt=123', function(err, result) {
|
|
17
17
|
if (err) throw err;
|
|
18
18
|
if (numLeft > 1)
|
|
19
19
|
benchmarkInsert(numLeft-1, callback);
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
Statistical profiling result from node, (156381 ticks, 1858 unaccounted, 0 excluded).
|
|
2
|
+
|
|
3
|
+
[Unknown]:
|
|
4
|
+
ticks total nonlib name
|
|
5
|
+
1858 1.2%
|
|
6
|
+
|
|
7
|
+
[Shared libraries]:
|
|
8
|
+
ticks total nonlib name
|
|
9
|
+
53890 34.5% 0.0% /usr/lib/system/libsystem_c.dylib
|
|
10
|
+
50720 32.4% 0.0% /usr/lib/system/libsystem_kernel.dylib
|
|
11
|
+
47085 30.1% 0.0% /usr/local/bin/node
|
|
12
|
+
31 0.0% 0.0% /usr/lib/libstdc++.6.dylib
|
|
13
|
+
15 0.0% 0.0% /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore
|
|
14
|
+
3 0.0% 0.0% /usr/lib/system/libsystem_m.dylib
|
|
15
|
+
|
|
16
|
+
[JavaScript]:
|
|
17
|
+
ticks total nonlib name
|
|
18
|
+
1474 0.9% 31.8% Script: ~native mirror.js
|
|
19
|
+
1038 0.7% 22.4% Script: ~native debug.js
|
|
20
|
+
447 0.3% 9.6% LazyCompile: *Socket._write net.js:515
|
|
21
|
+
345 0.2% 7.4% Stub: CEntryStub
|
|
22
|
+
217 0.1% 4.7% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
23
|
+
167 0.1% 3.6% Builtin: A builtin from the snapshot {4}
|
|
24
|
+
61 0.0% 1.3% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
25
|
+
43 0.0% 0.9% Stub: FastNewClosureStub
|
|
26
|
+
39 0.0% 0.8% LazyCompile: *Buffer buffer.js:205
|
|
27
|
+
32 0.0% 0.7% Builtin: A builtin from the snapshot {1}
|
|
28
|
+
31 0.0% 0.7% Stub: JSEntryStub
|
|
29
|
+
28 0.0% 0.6% LazyCompile: ~<anonymous> native liveedit.js:45
|
|
30
|
+
27 0.0% 0.6% Builtin: A builtin from the snapshot {3}
|
|
31
|
+
25 0.0% 0.5% LazyCompile: *PacketParser.execute /private/tmp/node-mysql2/lib/packet_parser.js:23
|
|
32
|
+
25 0.0% 0.5% CallMegamorphic: args_count: 2 {1}
|
|
33
|
+
23 0.0% 0.5% Stub: CallConstructStub_Recording
|
|
34
|
+
23 0.0% 0.5% LazyCompile: ~inherits native mirror.js:137
|
|
35
|
+
20 0.0% 0.4% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
36
|
+
19 0.0% 0.4% Stub: CallConstructStub
|
|
37
|
+
19 0.0% 0.4% Script: ~native liveedit.js
|
|
38
|
+
18 0.0% 0.4% LazyCompile: ~DoConstructRegExp native regexp.js:35
|
|
39
|
+
17 0.0% 0.4% LazyCompile: *Query.resultsetHeader /private/tmp/node-mysql2/lib/commands/query.js:25
|
|
40
|
+
16 0.0% 0.3% LazyCompile: *writeUInt16 buffer.js:887
|
|
41
|
+
15 0.0% 0.3% Stub: ToBooleanStub_NullSpecObject
|
|
42
|
+
15 0.0% 0.3% LazyCompile: *exports.active timers.js:151
|
|
43
|
+
14 0.0% 0.3% Stub: InstanceofStub
|
|
44
|
+
14 0.0% 0.3% LazyCompile: ~ClearMirrorCache native mirror.js:39
|
|
45
|
+
13 0.0% 0.3% LazyCompile: *onread net.js:377
|
|
46
|
+
13 0.0% 0.3% LazyCompile: *benchmarkInsert /private/tmp/node-mysql2/benchmarks/bench-insert-select-parallel.js:17
|
|
47
|
+
13 0.0% 0.3% LazyCompile: *Socket.write net.js:465
|
|
48
|
+
13 0.0% 0.3% LazyCompile: *Connection.query /private/tmp/node-mysql2/lib/connection.js:85
|
|
49
|
+
12 0.0% 0.3% LazyCompile: *Query /private/tmp/node-mysql2/lib/commands/query.js:6
|
|
50
|
+
11 0.0% 0.2% LazyCompile: *Query.start /private/tmp/node-mysql2/lib/commands/query.js:19
|
|
51
|
+
11 0.0% 0.2% LazyCompile: *EventEmitter events.js:25
|
|
52
|
+
10 0.0% 0.2% Stub: ConstructStub
|
|
53
|
+
10 0.0% 0.2% LazyCompile: *Buffer.write buffer.js:329
|
|
54
|
+
10 0.0% 0.2% Function: b native v8natives.js:1582
|
|
55
|
+
9 0.0% 0.2% Stub: FastCloneShallowObjectStub {2}
|
|
56
|
+
9 0.0% 0.2% LazyCompile: ToString native runtime.js:550
|
|
57
|
+
9 0.0% 0.2% LazyCompile: RegExpConstructor native regexp.js:86
|
|
58
|
+
9 0.0% 0.2% LazyCompile: *ok assert.js:121
|
|
59
|
+
9 0.0% 0.2% LazyCompile: *Packet.readLengthCodedString /private/tmp/node-mysql2/lib/packets/packet.js:143
|
|
60
|
+
9 0.0% 0.2% Function: ~<anonymous> /private/tmp/node-mysql2/benchmarks/bench-insert-select-parallel.js:18
|
|
61
|
+
8 0.0% 0.2% LazyCompile: *Query.toPacket /private/tmp/node-mysql2/lib/packets/query.js:9
|
|
62
|
+
8 0.0% 0.2% LazyCompile: *Packet.readInt8 /private/tmp/node-mysql2/lib/packets/packet.js:38
|
|
63
|
+
8 0.0% 0.2% LazyCompile: *EventEmitter.emit events.js:54
|
|
64
|
+
8 0.0% 0.2% Builtin: A builtin from the snapshot {2}
|
|
65
|
+
8 0.0% 0.2% Builtin: A builtin from the snapshot
|
|
66
|
+
7 0.0% 0.2% Stub: CompareICStub
|
|
67
|
+
7 0.0% 0.2% LazyCompile: *Connection.writePacket /private/tmp/node-mysql2/lib/connection.js:62
|
|
68
|
+
7 0.0% 0.2% LazyCompile: *Command /private/tmp/node-mysql2/lib/commands/command.js:4
|
|
69
|
+
7 0.0% 0.2% CallMegamorphic: args_count: 2
|
|
70
|
+
6 0.0% 0.1% Stub: ArgumentsAccessStub_NewStrict
|
|
71
|
+
6 0.0% 0.1% LazyCompile: ~c native mirror.js:138
|
|
72
|
+
6 0.0% 0.1% LazyCompile: INSTANCE_OF native runtime.js:367
|
|
73
|
+
6 0.0% 0.1% LazyCompile: *stream.ondata /private/tmp/node-mysql2/lib/connection.js:56
|
|
74
|
+
6 0.0% 0.1% LazyCompile: *Packet.readLengthCodedNumber /private/tmp/node-mysql2/lib/packets/packet.js:59
|
|
75
|
+
5 0.0% 0.1% LazyCompile: TextRow evalmachine.<anonymous>:1
|
|
76
|
+
5 0.0% 0.1% LazyCompile: *Packet.writeHeader /private/tmp/node-mysql2/lib/packets/packet.js:329
|
|
77
|
+
5 0.0% 0.1% LazyCompile: *Packet.isError /private/tmp/node-mysql2/lib/packets/packet.js:241
|
|
78
|
+
5 0.0% 0.1% Function: ~PacketParser.execute /private/tmp/node-mysql2/lib/packet_parser.js:23
|
|
79
|
+
4 0.0% 0.1% Stub: KeyedLoadElementStub {1}
|
|
80
|
+
4 0.0% 0.1% Stub: KeyedLoadElementStub
|
|
81
|
+
4 0.0% 0.1% Stub: FastCloneShallowObjectStub {3}
|
|
82
|
+
4 0.0% 0.1% LazyCompile: *isBuffer buffer.js:293
|
|
83
|
+
4 0.0% 0.1% LazyCompile: *isArray native array.js:1463
|
|
84
|
+
4 0.0% 0.1% LazyCompile: *ResultSetHeader /private/tmp/node-mysql2/lib/packets/resultset_header.js:4
|
|
85
|
+
4 0.0% 0.1% Function: ~stream.ondata /private/tmp/node-mysql2/lib/connection.js:56
|
|
86
|
+
4 0.0% 0.1% Function: ~Socket._write net.js:515
|
|
87
|
+
4 0.0% 0.1% Function: ~Packet.readInt8 /private/tmp/node-mysql2/lib/packets/packet.js:38
|
|
88
|
+
3 0.0% 0.1% Stub: StringAddStub
|
|
89
|
+
3 0.0% 0.1% Stub: JSEntryStub {1}
|
|
90
|
+
3 0.0% 0.1% Stub: FastNewContextStub {1}
|
|
91
|
+
3 0.0% 0.1% Stub: FastCloneShallowObjectStub {5}
|
|
92
|
+
3 0.0% 0.1% Stub: FastCloneShallowObjectStub
|
|
93
|
+
3 0.0% 0.1% Stub: CompareICStub {2}
|
|
94
|
+
3 0.0% 0.1% Stub: BinaryOpStub_MUL_Alloc_SMI
|
|
95
|
+
3 0.0% 0.1% LazyCompile: *toLowerCase native string.js:739
|
|
96
|
+
3 0.0% 0.1% LazyCompile: *isFinite native v8natives.js:103
|
|
97
|
+
2 0.0% 0.0% Stub: ToBooleanStub_UndefinedNullSpecObject
|
|
98
|
+
2 0.0% 0.0% Stub: FastNewContextStub
|
|
99
|
+
2 0.0% 0.0% Stub: ConstructStub {1}
|
|
100
|
+
2 0.0% 0.0% Stub: CompareICStub {1}
|
|
101
|
+
2 0.0% 0.0% LazyCompile: <anonymous> native string.js:36
|
|
102
|
+
2 0.0% 0.0% LazyCompile: *Packet.writeString /private/tmp/node-mysql2/lib/packets/packet.js:302
|
|
103
|
+
2 0.0% 0.0% LazyCompile: *Packet.parseInt /private/tmp/node-mysql2/lib/packets/packet.js:170
|
|
104
|
+
2 0.0% 0.0% LazyCompile: *Packet.isEOF /private/tmp/node-mysql2/lib/packets/packet.js:55
|
|
105
|
+
2 0.0% 0.0% LazyCompile: *Packet.haveMoreData /private/tmp/node-mysql2/lib/packets/packet.js:28
|
|
106
|
+
2 0.0% 0.0% KeyedLoadIC: args_count: 0
|
|
107
|
+
2 0.0% 0.0% KeyedLoadIC: A keyed load IC from the snapshot
|
|
108
|
+
2 0.0% 0.0% Function: ~Packet.readLengthCodedNumber /private/tmp/node-mysql2/lib/packets/packet.js:59
|
|
109
|
+
2 0.0% 0.0% Function: ~EventEmitter.emit events.js:54
|
|
110
|
+
2 0.0% 0.0% Builtin: A builtin from the snapshot {5}
|
|
111
|
+
1 0.0% 0.0% Stub: ToBooleanStub_UndefinedSmi
|
|
112
|
+
1 0.0% 0.0% Stub: ToBooleanStub
|
|
113
|
+
1 0.0% 0.0% Stub: InterruptStub
|
|
114
|
+
1 0.0% 0.0% Stub: FastCloneShallowObjectStub {4}
|
|
115
|
+
1 0.0% 0.0% Stub: FastCloneShallowObjectStub {1}
|
|
116
|
+
1 0.0% 0.0% Stub: FastCloneShallowArrayStub
|
|
117
|
+
1 0.0% 0.0% Stub: CompareStub
|
|
118
|
+
1 0.0% 0.0% Stub: CompareICStub {3}
|
|
119
|
+
1 0.0% 0.0% Stub: CallFunctionStub_Args2_Recording
|
|
120
|
+
1 0.0% 0.0% Stub: ArgumentsAccessStub
|
|
121
|
+
1 0.0% 0.0% LazyCompile: captureStackTrace native messages.js:1100
|
|
122
|
+
1 0.0% 0.0% LazyCompile: *Packet.writeInt8 /private/tmp/node-mysql2/lib/packets/packet.js:285
|
|
123
|
+
1 0.0% 0.0% LazyCompile: *Packet.parseLengthCodedInt /private/tmp/node-mysql2/lib/packets/packet.js:233
|
|
124
|
+
1 0.0% 0.0% KeyedLoadIC: args_count: 0 {2}
|
|
125
|
+
1 0.0% 0.0% KeyedLoadIC: args_count: 0 {1}
|
|
126
|
+
1 0.0% 0.0% Function: ~fs.statSync fs.js:523
|
|
127
|
+
1 0.0% 0.0% Function: ~Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
128
|
+
1 0.0% 0.0% Function: ~Packet.isError /private/tmp/node-mysql2/lib/packets/packet.js:241
|
|
129
|
+
1 0.0% 0.0% Function: ~Buffer.write buffer.js:329
|
|
130
|
+
1 0.0% 0.0% CallMiss: args_count: 3
|
|
131
|
+
|
|
132
|
+
[C++]:
|
|
133
|
+
ticks total nonlib name
|
|
134
|
+
|
|
135
|
+
[GC]:
|
|
136
|
+
ticks total nonlib name
|
|
137
|
+
2727 1.7%
|
|
138
|
+
|
|
139
|
+
[Bottom up (heavy) profile]:
|
|
140
|
+
Note: percentage shows a share of a particular caller in the total
|
|
141
|
+
amount of its parent calls.
|
|
142
|
+
Callers occupying less than 2.0% are not shown.
|
|
143
|
+
|
|
144
|
+
ticks parent name
|
|
145
|
+
53890 34.5% /usr/lib/system/libsystem_c.dylib
|
|
146
|
+
29167 54.1% Script: ~native mirror.js
|
|
147
|
+
28321 97.1% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
148
|
+
28321 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
149
|
+
28321 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
150
|
+
28321 100.0% Function: b native v8natives.js:1582
|
|
151
|
+
846 2.9% LazyCompile: TextRow evalmachine.<anonymous>:1
|
|
152
|
+
706 83.5% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
153
|
+
706 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
154
|
+
706 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
155
|
+
140 16.5% Function: ~Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
156
|
+
140 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
157
|
+
140 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
158
|
+
23246 43.1% Script: ~native debug.js
|
|
159
|
+
22584 97.2% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
160
|
+
22584 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
161
|
+
22584 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
162
|
+
22584 100.0% Function: b native v8natives.js:1582
|
|
163
|
+
662 2.8% LazyCompile: TextRow evalmachine.<anonymous>:1
|
|
164
|
+
543 82.0% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
165
|
+
543 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
166
|
+
543 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
167
|
+
119 18.0% Function: ~Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
168
|
+
119 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
169
|
+
119 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
170
|
+
|
|
171
|
+
50720 32.4% /usr/lib/system/libsystem_kernel.dylib
|
|
172
|
+
22714 44.8% Script: ~native mirror.js
|
|
173
|
+
22047 97.1% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
174
|
+
22047 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
175
|
+
22047 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
176
|
+
22047 100.0% Function: b native v8natives.js:1582
|
|
177
|
+
667 2.9% LazyCompile: TextRow evalmachine.<anonymous>:1
|
|
178
|
+
547 82.0% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
179
|
+
547 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
180
|
+
547 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
181
|
+
120 18.0% Function: ~Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
182
|
+
120 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
183
|
+
120 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
184
|
+
17884 35.3% Script: ~native debug.js
|
|
185
|
+
17380 97.2% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
186
|
+
17380 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
187
|
+
17380 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
188
|
+
17380 100.0% Function: b native v8natives.js:1582
|
|
189
|
+
504 2.8% LazyCompile: TextRow evalmachine.<anonymous>:1
|
|
190
|
+
414 82.1% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
191
|
+
414 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
192
|
+
414 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
193
|
+
90 17.9% Function: ~Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
194
|
+
90 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
195
|
+
90 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
196
|
+
|
|
197
|
+
47085 30.1% /usr/local/bin/node
|
|
198
|
+
20688 43.9% Script: ~native mirror.js
|
|
199
|
+
20090 97.1% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
200
|
+
20090 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
201
|
+
20090 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
202
|
+
20090 100.0% Function: b native v8natives.js:1582
|
|
203
|
+
570 2.8% LazyCompile: TextRow evalmachine.<anonymous>:1
|
|
204
|
+
470 82.5% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
205
|
+
470 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
206
|
+
470 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
207
|
+
100 17.5% Function: ~Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
208
|
+
100 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
209
|
+
100 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
210
|
+
16503 35.0% Script: ~native debug.js
|
|
211
|
+
15958 96.7% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
212
|
+
15958 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
213
|
+
15958 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
214
|
+
15958 100.0% Function: b native v8natives.js:1582
|
|
215
|
+
514 3.1% LazyCompile: TextRow evalmachine.<anonymous>:1
|
|
216
|
+
420 81.7% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
217
|
+
420 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
218
|
+
420 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
219
|
+
94 18.3% Function: ~Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
220
|
+
94 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
221
|
+
94 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
222
|
+
4108 8.7% LazyCompile: *Query.row /private/tmp/node-mysql2/lib/commands/query.js:68
|
|
223
|
+
4108 100.0% Function: Command.execute /private/tmp/node-mysql2/lib/commands/command.js:10
|
|
224
|
+
4108 100.0% LazyCompile: *Connection.handlePacket /private/tmp/node-mysql2/lib/connection.js:67
|
|
225
|
+
4108 100.0% Function: b native v8natives.js:1582
|
|
226
|
+
3479 84.7% LazyCompile: *PacketParser.execute /private/tmp/node-mysql2/lib/packet_parser.js:23
|
|
227
|
+
321 7.8% Function: ~PacketParser.execute /private/tmp/node-mysql2/lib/packet_parser.js:23
|
|
228
|
+
308 7.5% Function: ~stream.ondata /private/tmp/node-mysql2/lib/connection.js:56
|
package/index.js
CHANGED
package/lib/commands/execute.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
var Command = require('./command');
|
|
2
2
|
var Packets = require('../packets/index.js');
|
|
3
3
|
var util = require('util');
|
|
4
|
+
var compileParser = require('../compile_binary_parser');
|
|
4
5
|
|
|
5
6
|
function Execute(sql, parameters, callback)
|
|
6
7
|
{
|
|
@@ -19,6 +20,7 @@ function Execute(sql, parameters, callback)
|
|
|
19
20
|
this.parameters = parameters;
|
|
20
21
|
this.rows = [];
|
|
21
22
|
this.id = 0;
|
|
23
|
+
this.rowParser = null;
|
|
22
24
|
}
|
|
23
25
|
util.inherits(Execute, Command);
|
|
24
26
|
|
|
@@ -58,10 +60,34 @@ Execute.prototype.readParameter = function(packet) {
|
|
|
58
60
|
return this.doExecute();
|
|
59
61
|
};
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
// TODO: move to connection.js?
|
|
64
|
+
function getFieldsKey(fields) {
|
|
65
|
+
var res = '';
|
|
66
|
+
for (var i=0; i < fields.length; ++i)
|
|
67
|
+
res += '/' + fields[i].name + ':' + fields[i].columnType + ':' + fields[i].flags;
|
|
68
|
+
return res;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
Execute.prototype.readField = function(packet, connection) {
|
|
62
72
|
var def = new Packets.ColumnDefinition(packet);
|
|
63
73
|
this.fields.push(def);
|
|
74
|
+
|
|
75
|
+
// TODO: api to allow to flag "I'm not going to chnge schema for this statement"
|
|
76
|
+
// this way we can ignore column definitions in binary response and use
|
|
77
|
+
// definition from prepare phase. Note that it's what happens currently
|
|
78
|
+
// e.i if you do execute("select * from foo") and later add/remove/rename rows to foo
|
|
79
|
+
// (without reconnecting) you are in trouble
|
|
80
|
+
|
|
64
81
|
if (this.fields.length == this.fieldCount) {
|
|
82
|
+
// compile row parser
|
|
83
|
+
var parserKey = getFieldsKey(this.fields);
|
|
84
|
+
// try cached first
|
|
85
|
+
this.rowParser = connection.textProtocolParsers[parserKey];
|
|
86
|
+
if (!this.rowParser) {
|
|
87
|
+
this.rowParser = compileParser(this.fields);
|
|
88
|
+
console.log(this.rowParser.toString());
|
|
89
|
+
connection.textProtocolParsers[parserKey] = this.rowParser;
|
|
90
|
+
}
|
|
65
91
|
return Execute.prototype.fieldsEOF;
|
|
66
92
|
}
|
|
67
93
|
return Execute.prototype.readField;
|
|
@@ -104,8 +130,13 @@ Execute.prototype.resultesetHeader = function(packet) {
|
|
|
104
130
|
};
|
|
105
131
|
|
|
106
132
|
Execute.prototype.readResultField = function(packet) {
|
|
107
|
-
var def
|
|
108
|
-
this.
|
|
133
|
+
var def;
|
|
134
|
+
if (this.rowParser) // ignore result fields definition, we are reusing fields from prepare response
|
|
135
|
+
this.resultFields.push(null);
|
|
136
|
+
else {
|
|
137
|
+
def = new Packets.ColumnDefinition(packet);
|
|
138
|
+
this.resultFields.push(def);
|
|
139
|
+
}
|
|
109
140
|
if (this.resultFields.length == this.resultFieldCount) {
|
|
110
141
|
return Execute.prototype.resultFieldsEOF;
|
|
111
142
|
}
|
|
@@ -127,9 +158,20 @@ Execute.prototype.row = function(packet)
|
|
|
127
158
|
this.onResult(null, this.rows, this.fields);
|
|
128
159
|
return null;
|
|
129
160
|
}
|
|
161
|
+
|
|
162
|
+
if (this.rowParser)
|
|
163
|
+
{
|
|
164
|
+
var r = new this.rowParser(packet);
|
|
165
|
+
if (this.onResult)
|
|
166
|
+
this.rows.push(r);
|
|
167
|
+
else
|
|
168
|
+
this.emit('result', r);
|
|
169
|
+
return Execute.prototype.row;
|
|
170
|
+
}
|
|
171
|
+
|
|
130
172
|
var row = Packets.BinaryRow.fromPacket(this.fields, packet);
|
|
131
173
|
// TODO: here we'll have dynamically pre-compiled and cached row parser
|
|
132
|
-
if (true) // TODO: think of API to store raw
|
|
174
|
+
if (true) // TODO: think of API to store raw columns array (most probably connection options flags)
|
|
133
175
|
{
|
|
134
176
|
var r = {};
|
|
135
177
|
for (var i = 0; i < row.columns.length; ++i)
|
package/lib/commands/query.js
CHANGED
|
@@ -34,10 +34,11 @@ Query.prototype.resultsetHeader = function(packet) {
|
|
|
34
34
|
return Query.prototype.readField;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
// TODO: move to connection.js ?
|
|
37
38
|
function getFieldsKey(fields) {
|
|
38
39
|
var res = '';
|
|
39
40
|
for (var i=0; i < fields.length; ++i)
|
|
40
|
-
res += '/' + fields[i].name + ':' + fields[i].columnType;
|
|
41
|
+
res += '/' + fields[i].name + ':' + fields[i].columnType + ':' + fields[i].flags;
|
|
41
42
|
return res;
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
var constants = require('./constants');
|
|
2
|
+
var vm = require('vm');
|
|
3
|
+
|
|
4
|
+
function compile(fields) {
|
|
5
|
+
var result = [];
|
|
6
|
+
var i=0;
|
|
7
|
+
var j=0;
|
|
8
|
+
var nullBitmapLength = Math.floor((fields.length + 7 + 2) / 8);
|
|
9
|
+
result.push('function BinaryRow(packet) {');
|
|
10
|
+
result.push(' var statusByte = packet.readInt8();');
|
|
11
|
+
for (j=0; j < nullBitmapLength; ++j)
|
|
12
|
+
result.push(' var nullBitmaskByte' + j + ' = packet.readInt8();');
|
|
13
|
+
|
|
14
|
+
var currentFieldNullBit = 4;
|
|
15
|
+
var nullByteIndex = 0;
|
|
16
|
+
for (i = 0; i < fields.length; i++) {
|
|
17
|
+
//result.push(' // type = ' + fields[i].columnType + ' flags = ' + fields[i].flags);
|
|
18
|
+
if (fields[i].flags & constants.FIELD_NOT_NULL) { // don't need to check null bitmap if field can't be null.
|
|
19
|
+
result.push(' this[\'' + fields[i].name + '\'] = ' + readCodeFor(fields[i].columnType, fields[i].flags));
|
|
20
|
+
} else if (fields[i].columnType == constants.MYSQL_TYPE_NULL) {
|
|
21
|
+
result.push(' this[\'' + fields[i].name + '\'] = null;');
|
|
22
|
+
} else {
|
|
23
|
+
result.push(' if (nullBitmaskByte' + nullByteIndex + ' & ' + currentFieldNullBit + ')');
|
|
24
|
+
result.push(' this[\'' + fields[i].name + '\'] = null;');
|
|
25
|
+
result.push(' else');
|
|
26
|
+
result.push(' this[\'' + fields[i].name + '\'] = ' + readCodeFor(fields[i].columnType, fields[i].flags));
|
|
27
|
+
}
|
|
28
|
+
currentFieldNullBit *= 2;
|
|
29
|
+
if (currentFieldNullBit == 0x100)
|
|
30
|
+
{
|
|
31
|
+
currentFieldNullBit = 1;
|
|
32
|
+
nullByteIndex++;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
result.push('} BinaryRow;');
|
|
36
|
+
var src = result.join('\n');
|
|
37
|
+
return vm.runInNewContext(src);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function readCodeFor(type, flags) {
|
|
41
|
+
switch(type) {
|
|
42
|
+
case constants.MYSQL_TYPE_TINY:
|
|
43
|
+
return "packet.readInt8();";
|
|
44
|
+
case constants.MYSQL_TYPE_SHORT:
|
|
45
|
+
return "packet.readInt16();";
|
|
46
|
+
case constants.MYSQL_TYPE_LONG:
|
|
47
|
+
case constants.MYSQL_TYPE_INT24: // in binary protocol int24 is encoded in 4 bytes int32
|
|
48
|
+
return "packet.readInt32();";
|
|
49
|
+
case constants.MYSQL_TYPE_YEAR:
|
|
50
|
+
return "\'not implemented\';";
|
|
51
|
+
case constants.MYSQL_TYPE_FLOAT:
|
|
52
|
+
return "packet.readFloat();";
|
|
53
|
+
case constants.MYSQL_TYPE_DOUBLE:
|
|
54
|
+
return "packet.readDouble();";
|
|
55
|
+
case constants.MYSQL_TYPE_NULL:
|
|
56
|
+
return "null;";
|
|
57
|
+
case constants.MYSQL_TYPE_DATETIME:
|
|
58
|
+
return "packet.readDateTime();";
|
|
59
|
+
case constants.MYSQL_TYPE_LONGLONG: // TODO: 8 bytes. Implement as 4 bytes read for now
|
|
60
|
+
return "packet.readInt32() + 0xffffffff*packet.readInt32();";
|
|
61
|
+
default:
|
|
62
|
+
return "packet.readLengthCodedString();";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = compile;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
var constants = require('./constants');
|
|
1
2
|
var vm = require('vm');
|
|
2
3
|
|
|
3
4
|
function compile(fields) {
|
|
@@ -14,19 +15,17 @@ function compile(fields) {
|
|
|
14
15
|
|
|
15
16
|
function readCodeFor(type) {
|
|
16
17
|
switch(type) {
|
|
17
|
-
case
|
|
18
|
-
case
|
|
19
|
-
case
|
|
20
|
-
case
|
|
21
|
-
case
|
|
18
|
+
case constants.MYSQL_TYPE_TINY:
|
|
19
|
+
case constants.MYSQL_TYPE_SHORT:
|
|
20
|
+
case constants.MYSQL_TYPE_LONG:
|
|
21
|
+
case constants.MYSQL_TYPE_INT24:
|
|
22
|
+
case constants.MYSQL_TYPE_YEAR:
|
|
22
23
|
return "packet.parseLengthCodedInt();";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return "null;";
|
|
29
|
-
|
|
24
|
+
case constants.MYSQL_TYPE_FLOAT:
|
|
25
|
+
case constants.MYSQL_TYPE_DOUBLE:
|
|
26
|
+
return "packet.parseLengthCodedFloat();";
|
|
27
|
+
case constants.MYSQL_TYPE_NULL:
|
|
28
|
+
return "null; packet.skip(1);";
|
|
30
29
|
default:
|
|
31
30
|
return "packet.readLengthCodedString(); //" + type;
|
|
32
31
|
}
|
package/lib/connection.js
CHANGED
|
@@ -21,7 +21,8 @@ function Connection(opts)
|
|
|
21
21
|
opts.flags = params.query.flags.split(',');
|
|
22
22
|
_.extend(opts, _.pick(params.query, 'socketPath', 'charset', 'timesone', 'insecureAuth', 'typeCast', 'supportBigNumbers', 'debug'));
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
|
|
25
|
+
// TODO: fill defaults
|
|
25
26
|
// if no params, connect to /var/lib/mysql/mysql.sock ( /tmp/mysql.sock on OSX )
|
|
26
27
|
// if host is given, connect to host:3306
|
|
27
28
|
|
|
@@ -36,14 +37,19 @@ function Connection(opts)
|
|
|
36
37
|
this.opts = opts;
|
|
37
38
|
this.commands = [];
|
|
38
39
|
this.statements = {};
|
|
40
|
+
|
|
39
41
|
// TODO: make it lru cache
|
|
40
42
|
// https://github.com/mercadolibre/node-simple-lru-cache
|
|
41
43
|
// or https://github.com/rsms/js-lru
|
|
42
44
|
// or https://github.com/monsur/jscache
|
|
43
45
|
//
|
|
44
|
-
// key is field.name + ':' + field.columnType + '/'
|
|
46
|
+
// key is field.name + ':' + field.columnType + ':' field.flags + '/'
|
|
45
47
|
this.textProtocolParsers = {};
|
|
46
48
|
|
|
49
|
+
// TODO: not sure if cache should be separate (same key as with textProtocolParsers)
|
|
50
|
+
// or part of prepared statements cache (key is sql query)
|
|
51
|
+
this.binaryProtocolParsers = {};
|
|
52
|
+
|
|
47
53
|
var connection = this;
|
|
48
54
|
this.packetParser = new PacketParser(this.handlePacket.bind(this));
|
|
49
55
|
// TODO: check stream instanceof net.Stream, fallback if not
|
|
@@ -64,7 +70,7 @@ Connection.prototype.handlePacket = function(packet) {
|
|
|
64
70
|
if (done) {
|
|
65
71
|
commands.shift();
|
|
66
72
|
if (commands.length !== 0)
|
|
67
|
-
this.handlePacket(); // TODO: process.nextTick ?
|
|
73
|
+
this.handlePacket(); // TODO: process.nextTick to avoid recursion?
|
|
68
74
|
}
|
|
69
75
|
};
|
|
70
76
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
var constants = require('../constants');
|
|
2
2
|
var Packet = require('../packets/packet');
|
|
3
3
|
|
|
4
4
|
function BinaryRow(columns)
|
|
@@ -6,22 +6,25 @@ function BinaryRow(columns)
|
|
|
6
6
|
this.columns = columns || [];
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
var binaryReader = new Array(256);
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
binaryReader[
|
|
13
|
-
binaryReader[
|
|
14
|
-
binaryReader[
|
|
15
|
-
binaryReader[
|
|
16
|
-
binaryReader[
|
|
17
|
-
binaryReader[
|
|
18
|
-
binaryReader[
|
|
19
|
-
binaryReader[
|
|
20
|
-
binaryReader[
|
|
21
|
-
binaryReader[
|
|
22
|
-
binaryReader[
|
|
23
|
-
binaryReader[
|
|
24
|
-
|
|
9
|
+
var binaryReader = new Array(256);
|
|
10
|
+
|
|
11
|
+
// TODO: replace with constants.MYSQL_TYPE_*
|
|
12
|
+
binaryReader[0] = Packet.prototype.readLengthCodedString; // MYSQL_TYPE_DECIMAL
|
|
13
|
+
binaryReader[1] = Packet.prototype.readInt8; // tiny
|
|
14
|
+
binaryReader[2] = Packet.prototype.readInt16; // short
|
|
15
|
+
binaryReader[3] = Packet.prototype.readInt32; // long
|
|
16
|
+
binaryReader[4] = Packet.prototype.readFloat; // float
|
|
17
|
+
binaryReader[5] = Packet.prototype.readDouble; // double
|
|
18
|
+
binaryReader[6] = Packet.prototype.assertInvalid; // null, should be skipped vie null bitmap
|
|
19
|
+
binaryReader[7] = Packet.prototype.readTimestamp; // timestamp, http://dev.mysql.com/doc/internals/en/prepared-statements.html#packet-ProtocolBinary::MYSQL_TYPE_TIMESTAMP
|
|
20
|
+
binaryReader[8] = Packet.prototype.readInt64; // long long
|
|
21
|
+
binaryReader[9] = Packet.prototype.readInt32; // int24
|
|
22
|
+
binaryReader[10] = Packet.prototype.readTimestamp; // date
|
|
23
|
+
binaryReader[11] = Packet.prototype.readTime; // time, http://dev.mysql.com/doc/internals/en/prepared-statements.html#packet-ProtocolBinary::MYSQL_TYPE_TIME
|
|
24
|
+
binaryReader[12] = Packet.prototype.readDateTime; // datetime, http://dev.mysql.com/doc/internals/en/prepared-statements.html#packet-ProtocolBinary::MYSQL_TYPE_DATETIME
|
|
25
|
+
binaryReader[13] = Packet.prototype.readInt16; // year
|
|
26
|
+
binaryReader[constants.MYSQL_TYPE_VAR_STRING] = Packet.prototype.readLengthCodedString; // var string
|
|
27
|
+
// TODO: complete list of types...
|
|
25
28
|
|
|
26
29
|
BinaryRow.fromPacket = function(fields, packet) {
|
|
27
30
|
var columns = new Array(fields.length);
|
|
@@ -30,7 +33,7 @@ BinaryRow.fromPacket = function(fields, packet) {
|
|
|
30
33
|
// TODO: read and interpret null bitmap
|
|
31
34
|
packet.skip(nullBitmapLength);
|
|
32
35
|
for (var i = 0; i < columns.length; ++i)
|
|
33
|
-
columns[i] = binaryReader[fields[i].
|
|
36
|
+
columns[i] = binaryReader[fields[i].columnType].apply(packet);
|
|
34
37
|
return new BinaryRow(columns);
|
|
35
38
|
};
|
|
36
39
|
|
package/lib/packets/packet.js
CHANGED
|
@@ -75,11 +75,71 @@ Packet.prototype.readLengthCodedNumber = function() {
|
|
|
75
75
|
throw "Should not reach here: " + byte1;
|
|
76
76
|
};
|
|
77
77
|
|
|
78
|
+
Packet.prototype.readFloat = function() {
|
|
79
|
+
var res = this.buffer.readFloatLE(this.offset);
|
|
80
|
+
this.offset += 4;
|
|
81
|
+
return res;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
Packet.prototype.readDouble = function() {
|
|
85
|
+
var res = this.buffer.readDoubleLE(this.offset);
|
|
86
|
+
this.offset += 8;
|
|
87
|
+
return res;
|
|
88
|
+
};
|
|
89
|
+
|
|
78
90
|
Packet.prototype.readBuffer = function(len) {
|
|
79
91
|
this.offset += len;
|
|
80
92
|
return this.buffer.slice(this.offset - len, this.offset);
|
|
81
93
|
};
|
|
82
94
|
|
|
95
|
+
// DATE, DATETIME and TIMESTAMP
|
|
96
|
+
Packet.prototype.readDateTime = function(convertTtoMs) {
|
|
97
|
+
var length = this.readInt8();
|
|
98
|
+
var y = 0;
|
|
99
|
+
var m = 0;
|
|
100
|
+
var d = 0;
|
|
101
|
+
var H = 0;
|
|
102
|
+
var M = 0;
|
|
103
|
+
var S = 0;
|
|
104
|
+
var ms = 0;
|
|
105
|
+
if (length > 3) {
|
|
106
|
+
y = this.readInt16();
|
|
107
|
+
m = this.readInt8();
|
|
108
|
+
d = this.readInt8();
|
|
109
|
+
}
|
|
110
|
+
if (length > 6) {
|
|
111
|
+
H = this.readInt8();
|
|
112
|
+
M = this.readInt8();
|
|
113
|
+
}
|
|
114
|
+
if (length > 11)
|
|
115
|
+
ms = this.readInt32();
|
|
116
|
+
return new Date(y, m, d, H, M, S, ms);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// TIME - value in microseconds. Can be negative
|
|
120
|
+
Packet.prototype.readTime = function(convertTtoMs) {
|
|
121
|
+
var length = this.readInt8();
|
|
122
|
+
if (length === 0)
|
|
123
|
+
return 0;
|
|
124
|
+
|
|
125
|
+
var result = 0;
|
|
126
|
+
var sign = this.readInt8() ? -1 : 1; // 'isNegative' flag byte
|
|
127
|
+
var d = 0;
|
|
128
|
+
var H = 0;
|
|
129
|
+
var M = 0;
|
|
130
|
+
var S = 0;
|
|
131
|
+
var ms = 0;
|
|
132
|
+
if (length > 7) {
|
|
133
|
+
d = this.readInt32();
|
|
134
|
+
H = this.readInt8();
|
|
135
|
+
M = this.readInt8();
|
|
136
|
+
S = this.readInt8();
|
|
137
|
+
}
|
|
138
|
+
if (length > 11)
|
|
139
|
+
ms = this.readInt32();
|
|
140
|
+
return d*86400000 + H*3600000 + M*60000 + S*1000 + ms;
|
|
141
|
+
};
|
|
142
|
+
|
|
83
143
|
Packet.prototype.readLengthCodedString = function() {
|
|
84
144
|
var len = this.readLengthCodedNumber();
|
|
85
145
|
// TODO: check manually first byte here to avoid polymorphic return type?
|
|
@@ -104,28 +164,88 @@ Packet.prototype.readString = function(len) {
|
|
|
104
164
|
return this.buffer.utf8Slice(this.offset - len, this.offset);
|
|
105
165
|
};
|
|
106
166
|
|
|
167
|
+
var minus = '-'.charCodeAt(0);
|
|
168
|
+
var plus = '+'.charCodeAt(0);
|
|
107
169
|
// TODO: base? sign? parseFloat?
|
|
108
170
|
Packet.prototype.parseInt = function(len) {
|
|
109
171
|
var result = 0;
|
|
110
172
|
var end = this.offset + len;
|
|
173
|
+
var sign = 1;
|
|
174
|
+
if (len === 0)
|
|
175
|
+
return 0; // TODO: assert? exception?
|
|
176
|
+
if (this.buffer[this.offset] == minus) {
|
|
177
|
+
this.offset++;
|
|
178
|
+
sign = -1;
|
|
179
|
+
}
|
|
180
|
+
if (this.buffer[this.offset] == plus) {
|
|
181
|
+
this.offset++; // just ignore
|
|
182
|
+
}
|
|
111
183
|
while(this.offset < end) {
|
|
112
184
|
result *= 10;
|
|
113
185
|
result += this.buffer[this.offset] - 48;
|
|
114
186
|
this.offset++;
|
|
115
187
|
}
|
|
116
|
-
return result;
|
|
188
|
+
return result*sign;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
// TODO: handle E notation
|
|
193
|
+
var dot = '.'.charCodeAt(0);
|
|
194
|
+
var exponent = 'e'.charCodeAt(0);
|
|
195
|
+
var exponentCapital = 'E'.charCodeAt(0);
|
|
196
|
+
Packet.prototype.parseFloat = function(len) {
|
|
197
|
+
var result = 0;
|
|
198
|
+
var end = this.offset + len;
|
|
199
|
+
var factor = 1;
|
|
200
|
+
var pastDot = false;
|
|
201
|
+
var charCode = 0;
|
|
202
|
+
if (len === 0)
|
|
203
|
+
return 0; // TODO: assert? exception?
|
|
204
|
+
|
|
205
|
+
if (this.buffer[this.offset] == minus) {
|
|
206
|
+
this.offset++;
|
|
207
|
+
factor = -1;
|
|
208
|
+
}
|
|
209
|
+
if (this.buffer[this.offset] == plus) {
|
|
210
|
+
this.offset++; // just ignore
|
|
211
|
+
}
|
|
212
|
+
while(this.offset < end) {
|
|
213
|
+
charCode = this.buffer[this.offset];
|
|
214
|
+
if (charCode == dot)
|
|
215
|
+
{
|
|
216
|
+
pastDot = true;
|
|
217
|
+
this.offset++;
|
|
218
|
+
} else if (charCode == exponent || charCode == exponentCapital) {
|
|
219
|
+
this.offset++;
|
|
220
|
+
var exponentValue = this.parseInt(end - this.offset);
|
|
221
|
+
return (result/factor)*Math.pow(10, exponentValue);
|
|
222
|
+
} else {
|
|
223
|
+
result *= 10;
|
|
224
|
+
result += this.buffer[this.offset] - 48;
|
|
225
|
+
this.offset++;
|
|
226
|
+
if (pastDot)
|
|
227
|
+
factor = factor*10;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return result/factor;
|
|
117
231
|
};
|
|
118
232
|
|
|
119
233
|
Packet.prototype.parseLengthCodedInt = function() {
|
|
120
234
|
return this.parseInt(this.readLengthCodedNumber());
|
|
121
235
|
};
|
|
122
236
|
|
|
237
|
+
Packet.prototype.parseLengthCodedFloat = function() {
|
|
238
|
+
return this.parseFloat(this.readLengthCodedNumber());
|
|
239
|
+
};
|
|
240
|
+
|
|
123
241
|
Packet.prototype.isError = function() {
|
|
124
242
|
return this.buffer[this.offset] == 0xff;
|
|
125
243
|
};
|
|
126
244
|
|
|
127
245
|
Packet.prototype.asError = function() {
|
|
128
|
-
this.
|
|
246
|
+
this.reset();
|
|
247
|
+
this.skip(1);
|
|
248
|
+
|
|
129
249
|
var code = this.readInt8();
|
|
130
250
|
var sqlState = this.readBuffer(7);
|
|
131
251
|
var message = this.buffer.slice(this.offset);
|