Skip to content

Commit aea984f

Browse files
committed
Merge pull request brianc#447 from eugeneware/buffer-params
Bind Buffer Variables as binary values (with Native implementation also)
2 parents 4fcfc66 + badb33a commit aea984f

File tree

4 files changed

+74
-4
lines changed

4 files changed

+74
-4
lines changed

lib/connection.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,15 +209,27 @@ Connection.prototype.bind = function(config, more) {
209209
config.binary = config.binary || false;
210210
var values = config.values || [];
211211
var len = values.length;
212+
var useBinary = false;
213+
for (var j = 0; j < len; j++)
214+
useBinary |= values[j] instanceof Buffer;
212215
var buffer = this.writer
213216
.addCString(config.portal)
214-
.addCString(config.statement)
215-
.addInt16(0) //always use default text format
216-
.addInt16(len); //number of parameters
217+
.addCString(config.statement);
218+
if (!useBinary)
219+
buffer.addInt16(0);
220+
else {
221+
buffer.addInt16(len);
222+
for (j = 0; j < len; j++)
223+
buffer.addInt16(values[j] instanceof Buffer);
224+
}
225+
buffer.addInt16(len);
217226
for(var i = 0; i < len; i++) {
218227
var val = values[i];
219228
if(val === null || typeof val === "undefined") {
220229
buffer.addInt32(-1);
230+
} else if (val instanceof Buffer) {
231+
buffer.addInt32(val.length);
232+
buffer.add(val);
221233
} else {
222234
buffer.addInt32(Buffer.byteLength(val));
223235
buffer.addString(val);

lib/utils.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ function arrayString(val) {
4646
//note: you can override this function to provide your own conversion mechanism
4747
//for complex types, etc...
4848
var prepareValue = function(val) {
49+
if (val instanceof Buffer) {
50+
return val;
51+
}
4952
if(val instanceof Date) {
5053
return dateToString(val);
5154
}

src/binding.cc

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -922,9 +922,17 @@ class Connection : public ObjectWrap {
922922
paramValues[i] = cString;
923923
} else if(val->IsNull()) {
924924
paramValues[i] = NULL;
925+
} else if(val->IsObject() && Buffer::HasInstance(val)) {
926+
char *cHexString = MallocCHexString(val->ToObject());
927+
if(!cHexString) {
928+
LOG("ArgToCStringArray: OUT OF MEMORY OR SOMETHING BAD!");
929+
ReleaseCStringArray(paramValues, i-1);
930+
return 0;
931+
}
932+
paramValues[i] = cHexString;
925933
} else {
926934
//a paramter was not a string
927-
LOG("Parameter not a string");
935+
LOG("Parameter not a string or buffer");
928936
ReleaseCStringArray(paramValues, i-1);
929937
return 0;
930938
}
@@ -952,6 +960,27 @@ class Connection : public ObjectWrap {
952960
strcpy(cString, *utf8String);
953961
return cString;
954962
}
963+
964+
//helper function to Malloc a Bytea encoded Hex string from a buffer
965+
static char* MallocCHexString(v8::Handle<Object> buf)
966+
{
967+
char* bufferData = Buffer::Data(buf);
968+
size_t hexStringLen = Buffer::Length(buf)*2 + 3;
969+
char *cHexString = (char *) malloc(hexStringLen);
970+
if(!cHexString) {
971+
return cHexString;
972+
}
973+
strcpy(cHexString, "\\x");
974+
for (uint32_t i = 0, k = 2; k < hexStringLen; i += 1, k += 2) {
975+
static const char hex[] = "0123456789abcdef";
976+
uint8_t val = static_cast<uint8_t>(bufferData[i]);
977+
cHexString[k + 0] = hex[val >> 4];
978+
cHexString[k + 1] = hex[val & 15];
979+
}
980+
cHexString[hexStringLen-1] = 0;
981+
return cHexString;
982+
}
983+
955984
void SendCopyFromChunk(Handle<Object> chunk) {
956985
PQputCopyData(connection_, Buffer::Data(chunk), Buffer::Length(chunk));
957986
}

test/unit/connection/outbound-sending-tests.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,32 @@ test('bind messages', function() {
116116
});
117117
});
118118

119+
test('with named statement, portal, and buffer value', function() {
120+
con.bind({
121+
portal: 'bang',
122+
statement: 'woo',
123+
values: ['1', 'hi', null, new Buffer('zing', 'UTF-8')]
124+
});
125+
var expectedBuffer = new BufferList()
126+
.addCString('bang') //portal name
127+
.addCString('woo') //statement name
128+
.addInt16(4)//value count
129+
.addInt16(0)//string
130+
.addInt16(0)//string
131+
.addInt16(0)//string
132+
.addInt16(1)//binary
133+
.addInt16(4)
134+
.addInt32(1)
135+
.add(Buffer("1"))
136+
.addInt32(2)
137+
.add(Buffer("hi"))
138+
.addInt32(-1)
139+
.addInt32(4)
140+
.add(new Buffer('zing', 'UTF-8'))
141+
.addInt16(0)
142+
.join(true, 'B');
143+
assert.received(stream, expectedBuffer);
144+
});
119145

120146
test("sends execute message", function() {
121147

0 commit comments

Comments
 (0)