-
-
Notifications
You must be signed in to change notification settings - Fork 632
/
Copy pathexecute.js
109 lines (99 loc) · 3.3 KB
/
execute.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
var CursorType = require('../constants/cursor');
var CommandCodes = require('../constants/commands');
var Types = require('../constants/types');
var Packet = require('../packets/packet');
function Execute (id, parameters)
{
this.id = id;
this.parameters = parameters;
}
Execute.prototype.toPacket = function ()
{
// TODO: don't try to calculate packet length in advance, allocate some big buffer in advance (header + 256 bytes?)
// and copy + reallocate if not enough
var i;
// 0 + 4 - length, seqId
// 4 + 1 - COM_EXECUTE
// 5 + 4 - stmtId
// 9 + 1 - flags
// 10 + 4 - iteration-count (always 1)
var length = 14;
if (this.parameters && this.parameters.length > 0)
{
length += Math.floor((this.parameters.length + 7) / 8);
length += 1; // new-params-bound-flag
length += 2 * this.parameters.length; // type byte for each parameter if new-params-bound-flag is set
for (i = 0; i < this.parameters.length; i++)
{
if (this.parameters[i] !== null) {
if (Object.prototype.toString.call(this.parameters[i]) == '[object Date]') {
var d = this.parameters[i];
// TODO: move to asMysqlDateTime()
this.parameters[i] = [d.getFullYear(), d.getMonth() + 1, d.getDate()].join('-') +
' ' + [d.getHours(), d.getMinutes(), d.getSeconds()].join(':');
}
if (Buffer.isBuffer(this.parameters[i])) {
length += Packet.lengthCodedNumberLength(this.parameters[i].length);
length += this.parameters[i].length;
}
else {
var str = this.parameters[i].toString();
var byteLen = Buffer.byteLength(str, 'utf8');
length += Packet.lengthCodedNumberLength(byteLen);
length += byteLen;
}
}
}
}
var buffer = new Buffer(length);
var packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(CommandCodes.STMT_EXECUTE);
packet.writeInt32(this.id);
packet.writeInt8(CursorType.NO_CURSOR); // flags
packet.writeInt32(1); // iteration-count, always 1
if (this.parameters && this.parameters.length > 0) {
var bitmap = 0;
var bitValue = 1;
for (i = 0; i < this.parameters.length; i++)
{
if (this.parameters[i] === null) {
bitmap += bitValue;
}
bitValue *= 2;
if (bitValue == 256) {
packet.writeInt8(bitmap);
bitmap = 0;
bitValue = 1;
}
}
if (bitValue != 1) {
packet.writeInt8(bitmap);
}
// TODO: explain meaning of the flag
// afaik, if set n*2 bytes with type of parameter are sent before parameters
// if not, previous execution types are used (TODO prooflink)
packet.writeInt8(1); // new-params-bound-flag
// TODO: don't typecast always to sting, use parameters type
for (i = 0; i < this.parameters.length; i++)
{
if (this.parameters[i] !== null) {
packet.writeInt16(Types.VAR_STRING);
} else {
packet.writeInt16(Types.NULL);
}
}
for (i = 0; i < this.parameters.length; i++)
{
if (this.parameters[i] !== null) {
if (Buffer.isBuffer(this.parameters[i])) {
packet.writeLengthCodedBuffer(this.parameters[i]);
} else {
packet.writeLengthCodedString(this.parameters[i].toString());
}
}
}
}
return packet;
};
module.exports = Execute;