@@ -2,7 +2,7 @@ var DEBUG = 0;
2
2
3
3
include ( 'util.js' ) ;
4
4
5
- function add_int ( message , num ) {
5
+ function add_int32 ( message , num ) {
6
6
var part ;
7
7
part = Math . floor ( num / 0xffffff ) ;
8
8
message . push ( part ) ;
@@ -35,70 +35,70 @@ function add_string(message, text) {
35
35
36
36
function format_message ( type , body ) {
37
37
var message = [ type . charCodeAt ( 0 ) ] ;
38
- add_int ( message , body . length + 4 ) ;
38
+ add_int32 ( message , body . length + 4 ) ;
39
39
add_string ( message , body ) ;
40
40
41
41
return message ;
42
42
}
43
43
44
44
// http://www.postgresql.org/docs/8.3/static/protocol-message-formats.html
45
45
var formatter = {
46
+ AddHeader : function ( message , code ) {
47
+ var stream = [ ] ;
48
+ if ( code ) {
49
+ stream . push ( code . charCodeAt ( 0 ) ) ;
50
+ }
51
+ add_int32 ( stream , message . length + 4 ) ;
52
+ return stream . concat ( message ) ;
53
+ } ,
46
54
CopyData : function ( ) {
47
55
// TODO: implement
48
56
} ,
49
57
CopyDone : function ( ) {
50
58
// TODO: implement
51
59
} ,
52
60
Describe : function ( name , type ) {
53
- var message = [ 'D' . charCodeAt ( 0 ) ] ;
54
- add_int ( message , name . length + 6 ) ;
61
+ var message = [ ] ;
55
62
message . push ( type . charCodeAt ( 0 ) ) ;
56
63
add_string ( message , name ) ;
57
- return message ;
64
+ return formatter . AddHeader ( message , 'D' ) ;
58
65
} ,
59
66
Execute : function ( name , max_rows ) {
60
- var message = [ 'E' . charCodeAt ( 0 ) ] ;
61
- add_int ( message , name . length + 9 ) ;
67
+ var message = [ ] ;
62
68
add_string ( message , name ) ;
63
- add_int ( message , max_rows ) ;
64
- return message ;
69
+ add_int32 ( message , max_rows ) ;
70
+ return formatter . AddHeader ( message , 'E' ) ;
65
71
} ,
66
72
Flush : function ( ) {
67
- var message = [ 'H' . charCodeAt ( 0 ) ] ;
68
- add_int ( message , 4 ) ;
69
- return message ;
73
+ return formatter . AddHeader ( [ ] , 'H' ) ;
70
74
} ,
71
75
FunctionCall : function ( ) {
72
76
// TODO: implement
73
77
} ,
74
78
Parse : function ( name , query , var_types ) {
75
- var message = [ 'P' . charCodeAt ( 0 ) ] ;
76
- add_int ( message , 4 + name . length + query . length + 4 + var_types . length * 4 ) ;
79
+ var message = [ ] ;
77
80
add_string ( message , name ) ;
78
81
add_string ( message , query ) ;
79
82
add_int16 ( message , var_types . length ) ;
80
83
var_types . each ( function ( var_type ) {
81
- add_int ( message , var_type ) ;
84
+ add_int32 ( message , var_type ) ;
82
85
} ) ;
83
- return message ;
86
+ return formatter . AddHeader ( message , 'P' ) ;
84
87
} ,
85
88
PasswordMessage : function ( password ) {
86
- var message = [ 'p' . charCodeAt ( 0 ) ] ;
87
- add_int ( message , password . length + 5 ) ;
89
+ var message = [ ] ;
88
90
add_string ( message , password ) ;
89
- return message ;
91
+ return formatter . AddHeader ( message , 'p' ) ;
90
92
} ,
91
93
Query : function ( query ) {
92
- var message = [ 'Q' . charCodeAt ( 0 ) ] ;
93
- add_int ( message , query . length + 5 ) ;
94
+ var message = [ ] ;
94
95
add_string ( message , query ) ;
95
- return message ;
96
+ return formatter . AddHeader ( message , 'Q' ) ;
96
97
} ,
97
98
SSLRequest : function ( ) {
98
99
var message = [ ] ;
99
- add_int ( message , 8 ) ; // Message length
100
- add_int ( message , 80877103 ) ;
101
- return message ;
100
+ add_int32 ( message , 80877103 ) ;
101
+ return formatter . AddHeader ( message ) ;
102
102
} ,
103
103
StartupMessage : function ( options ) {
104
104
var message = [ ] ;
@@ -108,39 +108,34 @@ var formatter = {
108
108
text += k + String . fromCharCode ( 0 ) + options [ k ] + String . fromCharCode ( 0 ) ;
109
109
}
110
110
}
111
- add_int ( message , text . length + 9 ) ; // Message length
112
- add_int ( message , 196608 ) ; // Protocol version number
111
+ add_int32 ( message , 196608 ) ; // Protocol version number
113
112
add_string ( message , text ) ; // options
114
- return message ;
113
+ return formatter . AddHeader ( message ) ;
115
114
} ,
116
115
Sync : function ( ) {
117
- var message = [ 'S' . charCodeAt ( 0 ) ] ;
118
- add_int ( message , 4 ) ;
119
- return message ;
116
+ return formatter . AddHeader ( [ ] , 'S' ) ;
120
117
} ,
121
118
Terminate : function ( ) {
122
- var message = [ 'X' . charCodeAt ( 0 ) ] ;
123
- add_int ( message , 4 ) ;
124
- return message ;
119
+ return formatter . AddHeader ( [ ] , 'X' ) ;
125
120
}
126
121
} ;
127
122
123
+ // Convert 4 bytes to signed 32 bit integer
128
124
function parse_int32 ( message ) {
129
- return message . shift ( ) * 0xffffff + message . shift ( ) * 0xffff + message . shift ( ) * 0xff + message . shift ( ) ;
125
+ var unsigned = message . shift ( ) * 0x1000000 + message . shift ( ) * 0x10000 + message . shift ( ) * 0x100 + message . shift ( ) ;
126
+ return ( unsigned & 0x80000000 ) ? ( unsigned - 0x100000000 ) : unsigned ;
130
127
}
131
128
129
+ // Convert 2 bytes to signed 16 bit integer
132
130
function parse_int16 ( message ) {
133
- return message . shift ( ) * 0xff + message . shift ( ) ;
131
+ var unsigned = message . shift ( ) * 0x100 + message . shift ( ) ;
132
+ return ( unsigned & 0x8000 ) ? ( unsigned - 0x10000 ) : unsigned ;
134
133
}
135
134
136
135
function parse_string ( message ) {
137
136
var text = "" ;
138
- while ( message [ 0 ] !== 0 ) {
139
- var n = message . shift ( ) ;
140
- if ( n < 0 ) {
141
- n += 256 ;
142
- }
143
- text += String . fromCharCode ( n ) ;
137
+ while ( message . length > 0 && message [ 0 ] !== 0 ) {
138
+ text += String . fromCharCode ( message . shift ( ) ) ;
144
139
}
145
140
message . shift ( ) ;
146
141
return text ;
@@ -159,18 +154,12 @@ function parse_raw_string(message, len) {
159
154
var text = "" ;
160
155
while ( len > 0 ) {
161
156
len -= 1 ;
162
- var n = message . shift ( ) ;
163
- if ( n < 0 ) {
164
- n += 256 ;
165
- }
166
- text += String . fromCharCode ( n ) ;
157
+ text += String . fromCharCode ( message . shift ( ) ) ;
167
158
}
168
159
return text ;
169
160
}
170
161
171
- function parse_response ( message ) {
172
- var code = String . fromCharCode ( message . shift ( ) ) ;
173
- var len = parse_int32 ( message ) ;
162
+ function parse_response ( code , message ) {
174
163
var type ;
175
164
var args = [ ] ;
176
165
switch ( code ) {
@@ -250,7 +239,11 @@ function parse_response(message) {
250
239
var num_cols = parse_int16 ( message ) ;
251
240
for ( var i = 0 ; i < num_cols ; i += 1 ) {
252
241
var size = parse_int32 ( message ) ;
253
- row . push ( parse_raw_string ( message , size ) ) ;
242
+ if ( size === - 1 ) {
243
+ row . push ( null ) ;
244
+ } else {
245
+ row . push ( parse_raw_string ( message , size ) ) ;
246
+ }
254
247
}
255
248
args = [ row ] ;
256
249
break ;
@@ -282,11 +275,9 @@ exports.Connection = function (database, username, password) {
282
275
function sendMessage ( type , args ) {
283
276
var message = formatter [ type ] . apply ( this , args ) ;
284
277
if ( DEBUG > 0 ) {
285
- print ( "Sending " + type + ": " ) ;
286
- p ( args ) ;
287
- if ( DEBUG > 1 ) {
288
- print ( "->" ) ;
289
- p ( message ) ;
278
+ node . debug ( "Sending " + type + ": " + JSON . stringify ( args ) ) ;
279
+ if ( DEBUG > 2 ) {
280
+ node . debug ( "->" + JSON . stringify ( message ) ) ;
290
281
}
291
282
}
292
283
connection . send ( message , "raw" ) ;
@@ -298,16 +289,30 @@ exports.Connection = function (database, username, password) {
298
289
sendMessage ( 'StartupMessage' , [ { user : username , database : database } ] ) ;
299
290
} ) ;
300
291
connection . addListener ( "receive" , function ( data ) {
292
+
293
+ // Hack to work around bug in node
294
+ // TODO: remove once Ry fixes bug
295
+ for ( var i = 0 , l = data . length ; i < l ; i += 1 ) {
296
+ if ( data [ i ] < 0 ) {
297
+ data [ i ] += 256 ;
298
+ }
299
+ }
300
+
301
+ if ( DEBUG > 2 ) {
302
+ node . debug ( "<-" + JSON . stringify ( data ) ) ;
303
+ }
304
+
301
305
while ( data . length > 0 ) {
306
+ var code = String . fromCharCode ( data . shift ( ) ) ;
307
+ var len = parse_int32 ( data ) ;
308
+ var message = data . splice ( 0 , len - 4 ) ;
302
309
if ( DEBUG > 1 ) {
303
- print ( "<-" ) ;
304
- p ( data ) ;
310
+ node . debug ( "message: " + code + " " + JSON . stringify ( message ) ) ;
305
311
}
306
- var command = parse_response ( data ) ;
312
+ var command = parse_response ( code , message ) ;
307
313
if ( command . type ) {
308
314
if ( DEBUG > 0 ) {
309
- print ( "Received " + command . type + ": " ) ;
310
- p ( command . args ) ;
315
+ node . debug ( "Received " + command . type + ": " + JSON . stringify ( command . args ) ) ;
311
316
}
312
317
events . emit ( command . type , command . args ) ;
313
318
}
0 commit comments