@@ -21,7 +21,73 @@ function leftPad(num, value) {
21
21
return ( pad + s ) . slice ( - num ) ;
22
22
}
23
23
24
+ function toMysqlDateTime ( date ) {
25
+ return [ date . getFullYear ( ) , date . getMonth ( ) + 1 , date . getDate ( ) ] . join ( '-' ) + ' ' +
26
+ [ date . getHours ( ) , date . getMinutes ( ) , date . getSeconds ( ) ] . join ( ':' ) + '.' +
27
+ leftPad ( 3 , date . getMilliseconds ( ) ) ;
28
+ }
29
+
30
+ function isJSON ( value ) {
31
+ return Array . isArray ( value ) ||
32
+ value . constructor === Object ||
33
+ ( typeof value . toJSON === 'function' && ! Buffer . isBuffer ( value ) ) ;
34
+ }
35
+
36
+ /**
37
+ * Converts a value to an object describing type, String/Buffer representation and length
38
+ * @param {* } value
39
+ */
40
+ function toParameter ( value , encoding ) {
41
+ var type = Types . VAR_STRING ;
42
+ var length ;
43
+ var fixed = false ;
44
+ if ( value !== null ) {
45
+ switch ( typeof value ) {
46
+ case 'number' :
47
+ type = Types . DOUBLE ;
48
+ fixed = true ;
49
+ var bufferValue = Buffer . allocUnsafe ( 8 ) ;
50
+ bufferValue . writeDoubleLE ( value , 0 ) ;
51
+ value = bufferValue ;
52
+ break ;
53
+
54
+ case 'boolean' :
55
+ type = Types . TINY ;
56
+ fixed = true ;
57
+ var bufferValue = Buffer . allocUnsafe ( 1 ) ;
58
+ bufferValue . writeInt8 ( value | 0 , 0 ) ;
59
+ value = bufferValue ;
60
+ break ;
61
+
62
+ case 'object' :
63
+ if ( Object . prototype . toString . call ( value ) == '[object Date]' ) {
64
+ value = toMysqlDateTime ( value ) ;
65
+ } else if ( isJSON ( value ) ) {
66
+ type = Types . JSON ;
67
+ value = JSON . stringify ( value ) ;
68
+ }
69
+ break ;
70
+ }
71
+ } else {
72
+ type = Types . NULL ;
73
+ value = '' ;
74
+ }
75
+ if ( fixed ) {
76
+ length = value . length ;
77
+ } else {
78
+ if ( Buffer . isBuffer ( value ) ) {
79
+ length = Packet . lengthCodedNumberLength ( value . length ) + value . length ;
80
+ } else {
81
+ value = value . toString ( ) ;
82
+ length = Packet . lengthCodedStringLength ( value , encoding ) ;
83
+ }
84
+ }
85
+ return { type, value, length, fixed } ;
86
+ }
87
+
24
88
Execute . prototype . toPacket = function ( ) {
89
+ var self = this ;
90
+
25
91
// TODO: don't try to calculate packet length in advance, allocate some big buffer in advance (header + 256 bytes?)
26
92
// and copy + reallocate if not enough
27
93
@@ -32,33 +98,17 @@ Execute.prototype.toPacket = function() {
32
98
// 9 + 1 - flags
33
99
// 10 + 4 - iteration-count (always 1)
34
100
var length = 14 ;
101
+ var parameters ;
35
102
if ( this . parameters && this . parameters . length > 0 ) {
36
103
length += Math . floor ( ( this . parameters . length + 7 ) / 8 ) ;
37
104
length += 1 ; // new-params-bound-flag
38
105
length += 2 * this . parameters . length ; // type byte for each parameter if new-params-bound-flag is set
39
- for ( i = 0 ; i < this . parameters . length ; i ++ ) {
40
- if ( this . parameters [ i ] !== null ) {
41
- if (
42
- Object . prototype . toString . call ( this . parameters [ i ] ) == '[object Date]'
43
- ) {
44
- var d = this . parameters [ i ] ;
45
- // TODO: move to asMysqlDateTime()
46
- this . parameters [ i ] =
47
- [ d . getFullYear ( ) , d . getMonth ( ) + 1 , d . getDate ( ) ] . join ( '-' ) +
48
- ' ' +
49
- [ d . getHours ( ) , d . getMinutes ( ) , d . getSeconds ( ) ] . join ( ':' ) +
50
- '.' + leftPad ( 3 , d . getMilliseconds ( ) )
51
- ;
52
- }
53
- if ( Buffer . isBuffer ( this . parameters [ i ] ) ) {
54
- length += Packet . lengthCodedNumberLength ( this . parameters [ i ] . length ) ;
55
- length += this . parameters [ i ] . length ;
56
- } else {
57
- var str = this . parameters [ i ] . toString ( ) ;
58
- length += Packet . lengthCodedStringLength ( str , this . encoding ) ;
59
- }
60
- }
61
- }
106
+ parameters = this . parameters . map ( function ( value ) {
107
+ return toParameter ( value , self . encoding ) ;
108
+ } ) ;
109
+ length += parameters . reduce ( function ( accumulator , parameter ) {
110
+ return accumulator + parameter . length ;
111
+ } , 0 ) ;
62
112
}
63
113
64
114
var buffer = Buffer . allocUnsafe ( length ) ;
@@ -68,11 +118,11 @@ Execute.prototype.toPacket = function() {
68
118
packet . writeInt32 ( this . id ) ;
69
119
packet . writeInt8 ( CursorType . NO_CURSOR ) ; // flags
70
120
packet . writeInt32 ( 1 ) ; // iteration-count, always 1
71
- if ( this . parameters && this . parameters . length > 0 ) {
121
+ if ( parameters ) {
72
122
var bitmap = 0 ;
73
123
var bitValue = 1 ;
74
- for ( i = 0 ; i < this . parameters . length ; i ++ ) {
75
- if ( this . parameters [ i ] === null ) {
124
+ parameters . forEach ( function ( parameter ) {
125
+ if ( parameter . type === Types . NULL ) {
76
126
bitmap += bitValue ;
77
127
}
78
128
bitValue *= 2 ;
@@ -81,7 +131,7 @@ Execute.prototype.toPacket = function() {
81
131
bitmap = 0 ;
82
132
bitValue = 1 ;
83
133
}
84
- }
134
+ } ) ;
85
135
if ( bitValue != 1 ) {
86
136
packet . writeInt8 ( bitmap ) ;
87
137
}
@@ -91,27 +141,24 @@ Execute.prototype.toPacket = function() {
91
141
// if not, previous execution types are used (TODO prooflink)
92
142
packet . writeInt8 ( 1 ) ; // new-params-bound-flag
93
143
94
- // TODO: don't typecast always to sting, use parameters type
95
- for ( i = 0 ; i < this . parameters . length ; i ++ ) {
96
- if ( this . parameters [ i ] !== null ) {
97
- packet . writeInt16 ( Types . VAR_STRING ) ;
98
- } else {
99
- packet . writeInt16 ( Types . NULL ) ;
100
- }
101
- }
144
+ // Write parameter types
145
+ parameters . forEach ( function ( parameter ) {
146
+ packet . writeInt8 ( parameter . type ) ; // field type
147
+ packet . writeInt8 ( 0 ) ; // parameter flag
148
+ } ) ;
102
149
103
- for ( i = 0 ; i < this . parameters . length ; i ++ ) {
104
- if ( this . parameters [ i ] !== null ) {
105
- if ( Buffer . isBuffer ( this . parameters [ i ] ) ) {
106
- packet . writeLengthCodedBuffer ( this . parameters [ i ] ) ;
150
+ // Write parameter values
151
+ parameters . forEach ( function ( parameter ) {
152
+ if ( parameter . type !== Types . NULL ) {
153
+ if ( parameter . fixed ) {
154
+ packet . writeBuffer ( parameter . value ) ;
155
+ } else if ( Buffer . isBuffer ( parameter . value ) ) {
156
+ packet . writeLengthCodedBuffer ( parameter . value ) ;
107
157
} else {
108
- packet . writeLengthCodedString (
109
- this . parameters [ i ] . toString ( ) ,
110
- this . encoding
111
- ) ;
158
+ packet . writeLengthCodedString ( parameter . value , self . encoding ) ;
112
159
}
113
160
}
114
- }
161
+ } ) ;
115
162
}
116
163
return packet ;
117
164
} ;
0 commit comments