From 4662d419720b149fe7384761119e909c3ceebfe6 Mon Sep 17 00:00:00 2001 From: Eugene Ware Date: Thu, 19 Sep 2013 01:50:42 +1000 Subject: [PATCH 1/4] bind Buffer variables as binary values --- lib/connection.js | 18 ++++++++++--- lib/utils.js | 3 +++ .../unit/connection/outbound-sending-tests.js | 26 +++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index df3b4e8e..6f230b1c 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -209,15 +209,27 @@ Connection.prototype.bind = function(config, more) { config.binary = config.binary || false; var values = config.values || []; var len = values.length; + var useBinary = false; + for (var j = 0; j < len; j++) + useBinary |= values[j] instanceof Buffer; var buffer = this.writer .addCString(config.portal) - .addCString(config.statement) - .addInt16(0) //always use default text format - .addInt16(len); //number of parameters + .addCString(config.statement); + if (!useBinary) + buffer.addInt16(0); + else { + buffer.addInt16(len); + for (j = 0; j < len; j++) + buffer.addInt16(values[j] instanceof Buffer); + } + buffer.addInt16(len); for(var i = 0; i < len; i++) { var val = values[i]; if(val === null || typeof val === "undefined") { buffer.addInt32(-1); + } else if (val instanceof Buffer) { + buffer.addInt32(val.length); + buffer.add(val); } else { buffer.addInt32(Buffer.byteLength(val)); buffer.addString(val); diff --git a/lib/utils.js b/lib/utils.js index 3d12d827..fb1f56eb 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -46,6 +46,9 @@ function arrayString(val) { //note: you can override this function to provide your own conversion mechanism //for complex types, etc... var prepareValue = function(val) { + if (val instanceof Buffer) { + return val; + } if(val instanceof Date) { return dateToString(val); } diff --git a/test/unit/connection/outbound-sending-tests.js b/test/unit/connection/outbound-sending-tests.js index 2d5c0a04..3dde8a3c 100644 --- a/test/unit/connection/outbound-sending-tests.js +++ b/test/unit/connection/outbound-sending-tests.js @@ -116,6 +116,32 @@ test('bind messages', function() { }); }); +test('with named statement, portal, and buffer value', function() { + con.bind({ + portal: 'bang', + statement: 'woo', + values: ['1', 'hi', null, new Buffer('zing', 'UTF-8')] + }); + var expectedBuffer = new BufferList() + .addCString('bang') //portal name + .addCString('woo') //statement name + .addInt16(4)//value count + .addInt16(0)//string + .addInt16(0)//string + .addInt16(0)//string + .addInt16(1)//binary + .addInt16(4) + .addInt32(1) + .add(Buffer("1")) + .addInt32(2) + .add(Buffer("hi")) + .addInt32(-1) + .addInt32(4) + .add(new Buffer('zing', 'UTF-8')) + .addInt16(0) + .join(true, 'B'); + assert.received(stream, expectedBuffer); +}); test("sends execute message", function() { From cd29f806f10d3bceaaa932583892725e96683499 Mon Sep 17 00:00:00 2001 From: Eugene Ware Date: Fri, 20 Sep 2013 00:33:22 +1000 Subject: [PATCH 2/4] Encode buffers as bytea hex strings --- src/binding.cc | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/binding.cc b/src/binding.cc index a9a7943f..92d6f958 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -891,6 +891,14 @@ private: paramValues[i] = cString; } else if(val->IsNull()) { paramValues[i] = NULL; + } else if(val->IsObject() && Buffer::HasInstance(val)) { + char *cHexString = MallocCHexString(val); + if(!cHexString) { + LOG("ArgToCStringArray: OUT OF MEMORY OR SOMETHING BAD!"); + ReleaseCStringArray(paramValues, i-1); + return 0; + } + paramValues[i] = cHexString; } else { //a paramter was not a string LOG("Parameter not a string"); @@ -921,6 +929,27 @@ private: strcpy(cString, *utf8String); return cString; } + + //helper function to Malloc a Bytea encoded Hex string from a buffer + static char* MallocCHexString(v8::Handle buf) + { + char* bufferData = Buffer::Data(buf); + size_t hexStringLen = Buffer::Length(buf)*2 + 3; + char *cHexString = (char *) malloc(hexStringLen); + if(!cHexString) { + return cHexString; + } + strcpy(cHexString, "\\x"); + for (uint32_t i = 0, k = 2; k < hexStringLen; i += 1, k += 2) { + static const char hex[] = "0123456789abcdef"; + uint8_t val = static_cast(bufferData[i]); + cHexString[k + 0] = hex[val >> 4]; + cHexString[k + 1] = hex[val & 15]; + } + cHexString[hexStringLen-1] = 0; + return cHexString; + } + void SendCopyFromChunk(Handle chunk) { PQputCopyData(connection_, Buffer::Data(chunk), Buffer::Length(chunk)); } From 99f76ca7d27e92020f558fe7df2973460cd5617d Mon Sep 17 00:00:00 2001 From: Eugene Ware Date: Fri, 20 Sep 2013 00:57:40 +1000 Subject: [PATCH 3/4] update error message to reference buffers --- src/binding.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/binding.cc b/src/binding.cc index 92d6f958..81863a2c 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -901,7 +901,7 @@ private: paramValues[i] = cHexString; } else { //a paramter was not a string - LOG("Parameter not a string"); + LOG("Parameter not a string or buffer"); ReleaseCStringArray(paramValues, i-1); return 0; } From badb33af84150500ed9e13f1c25d793a0f8e7038 Mon Sep 17 00:00:00 2001 From: Eugene Ware Date: Thu, 3 Oct 2013 12:47:19 +1000 Subject: [PATCH 4/4] Fixes for node 0.8. --- src/binding.cc | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/binding.cc b/src/binding.cc index 81863a2c..d2275a57 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -892,7 +892,7 @@ private: } else if(val->IsNull()) { paramValues[i] = NULL; } else if(val->IsObject() && Buffer::HasInstance(val)) { - char *cHexString = MallocCHexString(val); + char *cHexString = MallocCHexString(val->ToObject()); if(!cHexString) { LOG("ArgToCStringArray: OUT OF MEMORY OR SOMETHING BAD!"); ReleaseCStringArray(paramValues, i-1); @@ -931,23 +931,23 @@ private: } //helper function to Malloc a Bytea encoded Hex string from a buffer - static char* MallocCHexString(v8::Handle buf) + static char* MallocCHexString(v8::Handle buf) { - char* bufferData = Buffer::Data(buf); - size_t hexStringLen = Buffer::Length(buf)*2 + 3; - char *cHexString = (char *) malloc(hexStringLen); - if(!cHexString) { - return cHexString; - } - strcpy(cHexString, "\\x"); - for (uint32_t i = 0, k = 2; k < hexStringLen; i += 1, k += 2) { - static const char hex[] = "0123456789abcdef"; - uint8_t val = static_cast(bufferData[i]); - cHexString[k + 0] = hex[val >> 4]; - cHexString[k + 1] = hex[val & 15]; - } - cHexString[hexStringLen-1] = 0; + char* bufferData = Buffer::Data(buf); + size_t hexStringLen = Buffer::Length(buf)*2 + 3; + char *cHexString = (char *) malloc(hexStringLen); + if(!cHexString) { return cHexString; + } + strcpy(cHexString, "\\x"); + for (uint32_t i = 0, k = 2; k < hexStringLen; i += 1, k += 2) { + static const char hex[] = "0123456789abcdef"; + uint8_t val = static_cast(bufferData[i]); + cHexString[k + 0] = hex[val >> 4]; + cHexString[k + 1] = hex[val & 15]; + } + cHexString[hexStringLen-1] = 0; + return cHexString; } void SendCopyFromChunk(Handle chunk) {