From 36f156e3dbeb56182ecc4188db9ccea1759c6ecb Mon Sep 17 00:00:00 2001 From: Frans-Willem Date: Mon, 23 Aug 2010 21:53:08 +0200 Subject: [PATCH 1/8] Replaced encoding with bufferlib's BufferBuilder --- lib/PostgresEncoder.js | 26 ++++++++++++++++++++++++++ lib/postgres-pure.js | 34 ++++++++++++++++++---------------- 2 files changed, 44 insertions(+), 16 deletions(-) create mode 100644 lib/PostgresEncoder.js diff --git a/lib/PostgresEncoder.js b/lib/PostgresEncoder.js new file mode 100644 index 0000000..eb25f45 --- /dev/null +++ b/lib/PostgresEncoder.js @@ -0,0 +1,26 @@ +var BufferBuilder=require("bufferlib/BufferBuilder").BufferBuilder; +var sys=require("sys"); + +function PostgresEncoder(header) { + BufferBuilder.call(this); + this.header=header || ""; +} +sys.inherits(PostgresEncoder,BufferBuilder); +exports.PostgresEncoder=PostgresEncoder; + +PostgresEncoder.prototype.pushHash=function(obj,encoding) { + var self=this; + Object.keys(obj).forEach(function(k) { + self.pushStringZero(k,encoding); + self.pushStringZero(String(obj[k]),encoding); + }); + self.pushStringZero("",encoding); + return this; +} +PostgresEncoder.prototype.frame=function() { + var writer=new BufferBuilder(); + writer.pushString(this.header,'ascii'); + writer.pushIntBE(this.length+4,4); + writer.pushBuilder(this); + return writer.toBuffer(); +} \ No newline at end of file diff --git a/lib/postgres-pure.js b/lib/postgres-pure.js index 67b052c..9d4e44d 100644 --- a/lib/postgres-pure.js +++ b/lib/postgres-pure.js @@ -24,13 +24,15 @@ var crypto = require('crypto'), net = require("net"), sys = require("sys"), sqllib = require('./sql'), - url = require('url'); + url = require('url'), + PostgresEncoder=require("./PostgresEncoder").PostgresEncoder; require('./buffer_extras'); exports.DEBUG = 0; function encoder(header) { - header = header || ""; + return new PostgresEncoder(header); + /*header = header || ""; var w = Buffer.makeWriter(); w.frame = function frame() { var message = w.toBuffer(); @@ -45,7 +47,7 @@ function encoder(header) { message.copy(buffer, offset); return buffer; } - return w; + return w;*/ } // http://www.postgresql.org/docs/8.3/static/protocol-message-formats.html @@ -58,13 +60,13 @@ var formatter = { }, Describe: function (name, type) { return (encoder('D')) - .push.string(type) - .push.cstring(name); + .pushString(type) + .pushStringZero(name); }, Execute: function (name, max_rows) { return (encoder('E')) - .push.cstring(name) - .push.int32(max_rows); + .pushStringZero(name) + .pushIntBE(max_rows,4); }, Flush: function () { return encoder('H'); @@ -74,31 +76,31 @@ var formatter = { }, Parse: function (name, query, var_types) { var builder = (encoder('P')) - .push.cstring(name) - .push.cstring(query) - .push.int16(var_types.length); + .pushStringZero(name) + .pushStringZero(query) + .pushIntBE(var_types.length,2); var_types.each(function (var_type) { - builder.push.int32(var_type); + builder.pushIntBE(var_type,4); }); return builder; }, PasswordMessage: function (password) { return (encoder('p')) - .push.cstring(password); + .pushStringZero(password); }, Query: function (query) { return (encoder('Q')) - .push.cstring(query); + .pushStringZero(query); }, SSLRequest: function () { return (encoder()) - .push.int32(0x4D2162F); + .pushIntBE(0x4D2162F,4); }, StartupMessage: function (options) { // Protocol version number 3 return encoder() - .push.int32(0x30000) - .push.hash(options); + .pushIntBE(0x30000,4) + .pushHash(options); }, Sync: function () { return encoder('S'); From b70698ac43530cd3ed80a33d71da8a05ec64bb11 Mon Sep 17 00:00:00 2001 From: Frans-Willem Date: Mon, 23 Aug 2010 22:01:52 +0200 Subject: [PATCH 2/8] Replaced Buffer.toReader usage with PostgresReader (inherits from BufferReader) --- lib/PostgresReader.js | 15 +++++++++++++++ lib/postgres-pure.js | 43 ++++++++++++++++++++++--------------------- 2 files changed, 37 insertions(+), 21 deletions(-) create mode 100644 lib/PostgresReader.js diff --git a/lib/PostgresReader.js b/lib/PostgresReader.js new file mode 100644 index 0000000..1976ab2 --- /dev/null +++ b/lib/PostgresReader.js @@ -0,0 +1,15 @@ +var BufferReader=require("bufferlib/BufferReader").BufferReader; +var sys=require("sys"); + +function PostgresReader(buffer) { + BufferReader.call(this,buffer); +} +sys.inherits(PostgresReader,BufferReader); +exports.PostgresReader=PostgresReader; + +PostgresReader.prototype.popMultiStringZero=function(encoding) { + var ret=[],cur; + while ((cur=this.popStringZero(encoding)).length>0) + ret.push(cur); + return ret; +} \ No newline at end of file diff --git a/lib/postgres-pure.js b/lib/postgres-pure.js index 9d4e44d..c0947b5 100644 --- a/lib/postgres-pure.js +++ b/lib/postgres-pure.js @@ -25,6 +25,7 @@ var crypto = require('crypto'), sys = require("sys"), sqllib = require('./sql'), url = require('url'), + PostgresReader=require("./PostgresReader").PostgresReader, PostgresEncoder=require("./PostgresEncoder").PostgresEncoder; require('./buffer_extras'); @@ -113,11 +114,11 @@ var formatter = { // Parse response streams from the server function parse_response(code, buffer) { var input, type, args, num_fields, data, size, i; - reader = buffer.toReader(); + reader = new PostgresReader(buffer); args = []; switch (code) { case 'R': - switch (reader.int32()) { + switch (reader.popIntBE(4)) { case 0: type = "AuthenticationOk"; break; @@ -129,11 +130,11 @@ function parse_response(code, buffer) { break; case 4: type = "AuthenticationCryptPassword"; - args = [reader.string(2)]; + args = [reader.popString(2)]; break; case 5: type = "AuthenticationMD5Password"; - args = [reader.buffer(4)]; + args = [reader.popBuffer(4)]; break; case 6: type = "AuthenticationSCMCredential"; @@ -153,35 +154,35 @@ function parse_response(code, buffer) { case 'E': type = "ErrorResponse"; args = [{}]; - reader.multicstring().forEach(function (field) { + reader.popMultiStringZero().forEach(function (field) { args[0][field[0]] = field.substr(1); }); break; case 'S': type = "ParameterStatus"; - args = [reader.cstring(), reader.cstring()]; + args = [reader.popStringZero(), reader.popStringZero()]; break; case 'K': type = "BackendKeyData"; - args = [reader.int32(), reader.int32()]; + args = [reader.popIntBE(4), reader.popIntBE(4)]; break; case 'Z': type = "ReadyForQuery"; - args = [reader.string(1)]; + args = [reader.popString(1)]; break; case 'T': type = "RowDescription"; - num_fields = reader.int16(); + num_fields = reader.popIntBE(2); data = []; for (i = 0; i < num_fields; i += 1) { data.push({ - field: reader.cstring(), - table_id: reader.int32(), - column_id: reader.int16(), - type_id: reader.int32(), - type_size: reader.int16(), - type_modifier: reader.int32(), - format_code: reader.int16() + field: reader.popStringZero(), + table_id: reader.popIntBE(4), + column_id: reader.popIntBE(2), + type_id: reader.popIntBE(4), + type_size: reader.popIntBE(2), + type_modifier: reader.popIntBE(4), + format_code: reader.popIntBE(2) }); } args = [data]; @@ -189,25 +190,25 @@ function parse_response(code, buffer) { case 'D': type = "DataRow"; data = []; - num_fields = reader.int16(); + num_fields = reader.popIntBE(2); for (i = 0; i < num_fields; i += 1) { - size = reader.int32(); + size = reader.popIntBE(4); if (size === -1) { data.push(null); } else { - data.push(reader.string(size)); + data.push(reader.popString(size)); } } args = [data]; break; case 'C': type = "CommandComplete"; - args = [reader.cstring()]; + args = [reader.popStringZero()]; break; case 'N': type = "NoticeResponse"; args = [{}]; - reader.multicstring().forEach(function (field) { + reader.popMultiStringZero().forEach(function (field) { args[0][field[0]] = field.substr(1); }); break; From 50ad8d6ce01dafc5f133166f727e151933b97de5 Mon Sep 17 00:00:00 2001 From: Frans-Willem Date: Mon, 23 Aug 2010 22:34:04 +0200 Subject: [PATCH 3/8] Using BufferQueueReader for parsing now --- lib/postgres-pure.js | 64 +++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/lib/postgres-pure.js b/lib/postgres-pure.js index c0947b5..5da0d9e 100644 --- a/lib/postgres-pure.js +++ b/lib/postgres-pure.js @@ -26,7 +26,8 @@ var crypto = require('crypto'), sqllib = require('./sql'), url = require('url'), PostgresReader=require("./PostgresReader").PostgresReader, - PostgresEncoder=require("./PostgresEncoder").PostgresEncoder; + PostgresEncoder=require("./PostgresEncoder").PostgresEncoder, + BufferQueueReader=require("bufferlib/BufferQueueReader").BufferQueueReader; require('./buffer_extras'); exports.DEBUG = 0; @@ -260,46 +261,31 @@ function Connection(args) { connection.write(buffer); } - var queue = []; + var queue = new BufferQueueReader(); function checkInput() { - if (queue.length === 0) { return; } - var first = queue[0]; - var code = String.fromCharCode(first[0]); - var length = first.int32Read(1) - 4; - - // Make sure we have a whole message, TCP comes in chunks - if (first.length < length + 5) { - if (queue.length > 1) { - // Merge the first two buffers - queue.shift(); - var b = new Buffer(first.length + queue[0].length); - first.copy(b); - queue[0].copy(b, first.length); - queue[0] = b; - return checkInput(); - } else { - return; - } - } - var message = first.slice(5, 5 + length); - if (first.length === 5 + length) { - queue.shift(); - } else { - queue[0] = first.slice(length + 5, first.length); - } + while (queue.length>=5) { + var code = queue.readChar(0); + var length = queue.readIntBE(1,4) - 4; + + // Make sure we have a whole message, TCP comes in chunks + if (queue.length < length + 5) { + return; + } + queue.skip(5); + var message = queue.popBuffer(length); - if (exports.DEBUG > 1) { - sys.debug("stream: " + code + " " + message.inspect()); - } - command = parse_response(code, message); - if (command.type) { - if (exports.DEBUG > 0) { - sys.debug("Received " + command.type + ": " + JSON.stringify(command.args)); - } - command.args.unshift(command.type); - events.emit.apply(events, command.args); - } - checkInput(); + if (exports.DEBUG > 1) { + sys.debug("stream: " + code + " " + message.inspect()); + } + command = parse_response(code, message); + if (command.type) { + if (exports.DEBUG > 0) { + sys.debug("Received " + command.type + ": " + JSON.stringify(command.args)); + } + command.args.unshift(command.type); + events.emit.apply(events, command.args); + } + } } // Set up tcp client From 07ce3ddf23714956a0b65c4d5398c99e863320f6 Mon Sep 17 00:00:00 2001 From: Frans-Willem Date: Mon, 23 Aug 2010 22:34:58 +0200 Subject: [PATCH 4/8] Removed buffer_extras require --- lib/postgres-pure.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/postgres-pure.js b/lib/postgres-pure.js index 5da0d9e..f0d763a 100644 --- a/lib/postgres-pure.js +++ b/lib/postgres-pure.js @@ -28,7 +28,6 @@ var crypto = require('crypto'), PostgresReader=require("./PostgresReader").PostgresReader, PostgresEncoder=require("./PostgresEncoder").PostgresEncoder, BufferQueueReader=require("bufferlib/BufferQueueReader").BufferQueueReader; -require('./buffer_extras'); exports.DEBUG = 0; From 65783a5ff28d8c52ee4f543890e84c4328827bd0 Mon Sep 17 00:00:00 2001 From: Frans-Willem Date: Thu, 26 Aug 2010 11:10:56 +0200 Subject: [PATCH 5/8] Fixed query results leaking onto queries without results (e.g. DELETE after SELECT would still get SELECT's results), Added support for row-count for UPDATE/DELETE, Fixed bug for NULL values --- lib/postgres-pure.js | 13 +++++++++---- lib/sql.js | 14 ++++++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/lib/postgres-pure.js b/lib/postgres-pure.js index f0d763a..6fa5f38 100644 --- a/lib/postgres-pure.js +++ b/lib/postgres-pure.js @@ -193,7 +193,7 @@ function parse_response(code, buffer) { num_fields = reader.popIntBE(2); for (i = 0; i < num_fields; i += 1) { size = reader.popIntBE(4); - if (size === -1) { + if (size>>0 === -1) { data.push(null); } else { data.push(reader.popString(size)); @@ -330,6 +330,7 @@ function Connection(args) { var query = query_queue.shift(); query_callback = query.callback; row_callback = query.row_callback; + results = []; sendMessage('Query', [query.sql]); readyState = false; } else { @@ -374,7 +375,7 @@ function Connection(args) { } }); events.addListener('CommandComplete', function (data) { - query_callback.call(this, null, results); + query_callback.call(this, null, results, data.split(" ",2)[1]); }); conn.execute = function (sql/*, *parameters*/) { @@ -416,8 +417,12 @@ function Connection(args) { callback(); }}); } else { - query_queue.push({sql: sql, callback: function (err, data) { - callback(err, data); + query_queue.push({sql: sql, callback: function (err, data, rows) { + if (rows!==undefined) { + callback(err, data, rows); + } else { + callback(err, data); + } }}); } diff --git a/lib/sql.js b/lib/sql.js index b9772e1..4706471 100644 --- a/lib/sql.js +++ b/lib/sql.js @@ -31,11 +31,12 @@ function sql_escape(value) { if (value === false) { return "FALSE"; } - if (value.constructor.name === 'String') { - return "'" + value.replace("'", "''") + "'"; + if (typeof(value)==="string") { + return "'" + value.replace(/\'/g, "''") + "'"; } - return value.toString(); + return sql_escape(value.toString()); } +exports.sql_escape=sql_escape; // Fill in the placeholders with native values function merge(sql, parameters) { @@ -55,9 +56,10 @@ function merge(sql, parameters) { parameters = parameters[0]; } // ordered parameters - parameters.forEach(function (param) { - sql = sql.replace("?", sql_escape(param)); - }); + var index=0; + sql=sql.replace(/\?/g,function(m) { + return sql_escape(parameters[index++]); + }); } return sql; } From 0b53f49c0cbe647e44027707477bea8c3ec54bb8 Mon Sep 17 00:00:00 2001 From: Zhang Yichao Date: Sun, 19 Sep 2010 11:28:51 +0800 Subject: [PATCH 6/8] insert may have more than one tag: oid and row count --- lib/postgres-pure.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/postgres-pure.js b/lib/postgres-pure.js index 6fa5f38..129a76d 100644 --- a/lib/postgres-pure.js +++ b/lib/postgres-pure.js @@ -375,7 +375,8 @@ function Connection(args) { } }); events.addListener('CommandComplete', function (data) { - query_callback.call(this, null, results, data.split(" ",2)[1]); + var tag = data.split (" "); + query_callback.call(this, null, results, tag.slice (1, tag.length)); }); conn.execute = function (sql/*, *parameters*/) { @@ -417,11 +418,11 @@ function Connection(args) { callback(); }}); } else { - query_queue.push({sql: sql, callback: function (err, data, rows) { - if (rows!==undefined) { - callback(err, data, rows); + query_queue.push({sql: sql, callback: function (err, data, tag) { + if (tag !== undefined) { + callback (err, data, tag); } else { - callback(err, data); + callback (err, data); } }}); } From f291df0e069a3514274ec5f2dd014371a79a2edc Mon Sep 17 00:00:00 2001 From: Zhang Yichao Date: Mon, 20 Sep 2010 09:34:20 +0800 Subject: [PATCH 7/8] node crashed with version with bufferlib; try otherwise --- lib/PostgresEncoder.js | 26 ------- lib/PostgresReader.js | 15 ---- lib/postgres-pure.js | 151 +++++++++++++++++++++-------------------- lib/sql.js | 14 ++-- 4 files changed, 85 insertions(+), 121 deletions(-) delete mode 100644 lib/PostgresEncoder.js delete mode 100644 lib/PostgresReader.js diff --git a/lib/PostgresEncoder.js b/lib/PostgresEncoder.js deleted file mode 100644 index eb25f45..0000000 --- a/lib/PostgresEncoder.js +++ /dev/null @@ -1,26 +0,0 @@ -var BufferBuilder=require("bufferlib/BufferBuilder").BufferBuilder; -var sys=require("sys"); - -function PostgresEncoder(header) { - BufferBuilder.call(this); - this.header=header || ""; -} -sys.inherits(PostgresEncoder,BufferBuilder); -exports.PostgresEncoder=PostgresEncoder; - -PostgresEncoder.prototype.pushHash=function(obj,encoding) { - var self=this; - Object.keys(obj).forEach(function(k) { - self.pushStringZero(k,encoding); - self.pushStringZero(String(obj[k]),encoding); - }); - self.pushStringZero("",encoding); - return this; -} -PostgresEncoder.prototype.frame=function() { - var writer=new BufferBuilder(); - writer.pushString(this.header,'ascii'); - writer.pushIntBE(this.length+4,4); - writer.pushBuilder(this); - return writer.toBuffer(); -} \ No newline at end of file diff --git a/lib/PostgresReader.js b/lib/PostgresReader.js deleted file mode 100644 index 1976ab2..0000000 --- a/lib/PostgresReader.js +++ /dev/null @@ -1,15 +0,0 @@ -var BufferReader=require("bufferlib/BufferReader").BufferReader; -var sys=require("sys"); - -function PostgresReader(buffer) { - BufferReader.call(this,buffer); -} -sys.inherits(PostgresReader,BufferReader); -exports.PostgresReader=PostgresReader; - -PostgresReader.prototype.popMultiStringZero=function(encoding) { - var ret=[],cur; - while ((cur=this.popStringZero(encoding)).length>0) - ret.push(cur); - return ret; -} \ No newline at end of file diff --git a/lib/postgres-pure.js b/lib/postgres-pure.js index 129a76d..0abfc72 100644 --- a/lib/postgres-pure.js +++ b/lib/postgres-pure.js @@ -24,16 +24,13 @@ var crypto = require('crypto'), net = require("net"), sys = require("sys"), sqllib = require('./sql'), - url = require('url'), - PostgresReader=require("./PostgresReader").PostgresReader, - PostgresEncoder=require("./PostgresEncoder").PostgresEncoder, - BufferQueueReader=require("bufferlib/BufferQueueReader").BufferQueueReader; + url = require('url'); +require('./buffer_extras'); exports.DEBUG = 0; function encoder(header) { - return new PostgresEncoder(header); - /*header = header || ""; + header = header || ""; var w = Buffer.makeWriter(); w.frame = function frame() { var message = w.toBuffer(); @@ -48,7 +45,7 @@ function encoder(header) { message.copy(buffer, offset); return buffer; } - return w;*/ + return w; } // http://www.postgresql.org/docs/8.3/static/protocol-message-formats.html @@ -61,13 +58,13 @@ var formatter = { }, Describe: function (name, type) { return (encoder('D')) - .pushString(type) - .pushStringZero(name); + .push.string(type) + .push.cstring(name); }, Execute: function (name, max_rows) { return (encoder('E')) - .pushStringZero(name) - .pushIntBE(max_rows,4); + .push.cstring(name) + .push.int32(max_rows); }, Flush: function () { return encoder('H'); @@ -77,31 +74,31 @@ var formatter = { }, Parse: function (name, query, var_types) { var builder = (encoder('P')) - .pushStringZero(name) - .pushStringZero(query) - .pushIntBE(var_types.length,2); + .push.cstring(name) + .push.cstring(query) + .push.int16(var_types.length); var_types.each(function (var_type) { - builder.pushIntBE(var_type,4); + builder.push.int32(var_type); }); return builder; }, PasswordMessage: function (password) { return (encoder('p')) - .pushStringZero(password); + .push.cstring(password); }, Query: function (query) { return (encoder('Q')) - .pushStringZero(query); + .push.cstring(query); }, SSLRequest: function () { return (encoder()) - .pushIntBE(0x4D2162F,4); + .push.int32(0x4D2162F); }, StartupMessage: function (options) { // Protocol version number 3 return encoder() - .pushIntBE(0x30000,4) - .pushHash(options); + .push.int32(0x30000) + .push.hash(options); }, Sync: function () { return encoder('S'); @@ -114,11 +111,11 @@ var formatter = { // Parse response streams from the server function parse_response(code, buffer) { var input, type, args, num_fields, data, size, i; - reader = new PostgresReader(buffer); + reader = buffer.toReader(); args = []; switch (code) { case 'R': - switch (reader.popIntBE(4)) { + switch (reader.int32()) { case 0: type = "AuthenticationOk"; break; @@ -130,11 +127,11 @@ function parse_response(code, buffer) { break; case 4: type = "AuthenticationCryptPassword"; - args = [reader.popString(2)]; + args = [reader.string(2)]; break; case 5: type = "AuthenticationMD5Password"; - args = [reader.popBuffer(4)]; + args = [reader.buffer(4)]; break; case 6: type = "AuthenticationSCMCredential"; @@ -154,35 +151,35 @@ function parse_response(code, buffer) { case 'E': type = "ErrorResponse"; args = [{}]; - reader.popMultiStringZero().forEach(function (field) { + reader.multicstring().forEach(function (field) { args[0][field[0]] = field.substr(1); }); break; case 'S': type = "ParameterStatus"; - args = [reader.popStringZero(), reader.popStringZero()]; + args = [reader.cstring(), reader.cstring()]; break; case 'K': type = "BackendKeyData"; - args = [reader.popIntBE(4), reader.popIntBE(4)]; + args = [reader.int32(), reader.int32()]; break; case 'Z': type = "ReadyForQuery"; - args = [reader.popString(1)]; + args = [reader.string(1)]; break; case 'T': type = "RowDescription"; - num_fields = reader.popIntBE(2); + num_fields = reader.int16(); data = []; for (i = 0; i < num_fields; i += 1) { data.push({ - field: reader.popStringZero(), - table_id: reader.popIntBE(4), - column_id: reader.popIntBE(2), - type_id: reader.popIntBE(4), - type_size: reader.popIntBE(2), - type_modifier: reader.popIntBE(4), - format_code: reader.popIntBE(2) + field: reader.cstring(), + table_id: reader.int32(), + column_id: reader.int16(), + type_id: reader.int32(), + type_size: reader.int16(), + type_modifier: reader.int32(), + format_code: reader.int16() }); } args = [data]; @@ -190,25 +187,25 @@ function parse_response(code, buffer) { case 'D': type = "DataRow"; data = []; - num_fields = reader.popIntBE(2); + num_fields = reader.int16(); for (i = 0; i < num_fields; i += 1) { - size = reader.popIntBE(4); - if (size>>0 === -1) { + size = reader.int32(); + if (size === -1) { data.push(null); } else { - data.push(reader.popString(size)); + data.push(reader.string(size)); } } args = [data]; break; case 'C': type = "CommandComplete"; - args = [reader.popStringZero()]; + args = [reader.cstring()]; break; case 'N': type = "NoticeResponse"; args = [{}]; - reader.popMultiStringZero().forEach(function (field) { + reader.multicstring().forEach(function (field) { args[0][field[0]] = field.substr(1); }); break; @@ -260,31 +257,46 @@ function Connection(args) { connection.write(buffer); } - var queue = new BufferQueueReader(); + var queue = []; function checkInput() { - while (queue.length>=5) { - var code = queue.readChar(0); - var length = queue.readIntBE(1,4) - 4; - - // Make sure we have a whole message, TCP comes in chunks - if (queue.length < length + 5) { - return; - } - queue.skip(5); - var message = queue.popBuffer(length); + if (queue.length === 0) { return; } + var first = queue[0]; + var code = String.fromCharCode(first[0]); + var length = first.int32Read(1) - 4; + + // Make sure we have a whole message, TCP comes in chunks + if (first.length < length + 5) { + if (queue.length > 1) { + // Merge the first two buffers + queue.shift(); + var b = new Buffer(first.length + queue[0].length); + first.copy(b); + queue[0].copy(b, first.length); + queue[0] = b; + return checkInput(); + } else { + return; + } + } + var message = first.slice(5, 5 + length); + if (first.length === 5 + length) { + queue.shift(); + } else { + queue[0] = first.slice(length + 5, first.length); + } - if (exports.DEBUG > 1) { - sys.debug("stream: " + code + " " + message.inspect()); - } - command = parse_response(code, message); - if (command.type) { - if (exports.DEBUG > 0) { - sys.debug("Received " + command.type + ": " + JSON.stringify(command.args)); - } - command.args.unshift(command.type); - events.emit.apply(events, command.args); - } - } + if (exports.DEBUG > 1) { + sys.debug("stream: " + code + " " + message.inspect()); + } + command = parse_response(code, message); + if (command.type) { + if (exports.DEBUG > 0) { + sys.debug("Received " + command.type + ": " + JSON.stringify(command.args)); + } + command.args.unshift(command.type); + events.emit.apply(events, command.args); + } + checkInput(); } // Set up tcp client @@ -330,7 +342,6 @@ function Connection(args) { var query = query_queue.shift(); query_callback = query.callback; row_callback = query.row_callback; - results = []; sendMessage('Query', [query.sql]); readyState = false; } else { @@ -375,7 +386,7 @@ function Connection(args) { } }); events.addListener('CommandComplete', function (data) { - var tag = data.split (" "); + var tag = data.split (' '); query_callback.call(this, null, results, tag.slice (1, tag.length)); }); @@ -419,11 +430,7 @@ function Connection(args) { }}); } else { query_queue.push({sql: sql, callback: function (err, data, tag) { - if (tag !== undefined) { - callback (err, data, tag); - } else { - callback (err, data); - } + callback(err, data, tag); }}); } diff --git a/lib/sql.js b/lib/sql.js index 4706471..44deb47 100644 --- a/lib/sql.js +++ b/lib/sql.js @@ -31,12 +31,11 @@ function sql_escape(value) { if (value === false) { return "FALSE"; } - if (typeof(value)==="string") { - return "'" + value.replace(/\'/g, "''") + "'"; + if (value.constructor.name === 'String') { + return "'" + value.replace(/'/g, "''") + "'"; } - return sql_escape(value.toString()); + return value.toString(); } -exports.sql_escape=sql_escape; // Fill in the placeholders with native values function merge(sql, parameters) { @@ -56,10 +55,9 @@ function merge(sql, parameters) { parameters = parameters[0]; } // ordered parameters - var index=0; - sql=sql.replace(/\?/g,function(m) { - return sql_escape(parameters[index++]); - }); + parameters.forEach(function (param) { + sql = sql.replace("?", sql_escape(param)); + }); } return sql; } From ff1e9c2c1e5cabb59d0e8fb8ad3f5f7475b81b99 Mon Sep 17 00:00:00 2001 From: Zhang Yichao Date: Fri, 29 Oct 2010 16:30:46 +0800 Subject: [PATCH 8/8] may have try to extract 4 byte ints from fewer bytes --- lib/postgres-pure.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/postgres-pure.js b/lib/postgres-pure.js index 0abfc72..c0e642f 100644 --- a/lib/postgres-pure.js +++ b/lib/postgres-pure.js @@ -262,7 +262,7 @@ function Connection(args) { if (queue.length === 0) { return; } var first = queue[0]; var code = String.fromCharCode(first[0]); - var length = first.int32Read(1) - 4; + var length = first.length >= 5 ? first.int32Read(1) - 4 : 0; // Make sure we have a whole message, TCP comes in chunks if (first.length < length + 5) {