diff --git a/lib/connection.js b/lib/connection.js index bceb4999..811dc7b2 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -78,8 +78,12 @@ p.password = function(password) { this._send(0x70, this.writer.addCString(password)); }; -p._send = function(code, writer) { - return this.stream.write(writer.flush(code)); +p._send = function(code, more) { + if(more === true) { + this.writer.addHeader(code); + } else { + return this.stream.write(this.writer.flush(code)); + } } var termBuffer = new Buffer([0x58, 0, 0, 0, 4]); @@ -92,7 +96,9 @@ p.query = function(text) { this.stream.write(this.writer.addCString(text).flush(0x51)); }; -p.parse = function(query) { +//send parse message +//"more" === true to buffer the message until flush() is called +p.parse = function(query, more) { //expect something like this: // { name: 'queryName', // text: 'select * from blah', @@ -111,13 +117,13 @@ p.parse = function(query) { buffer.addInt32(query.types[i]); } - //0x50 = 'P' - this._send(0x50, buffer); - - return this; + var code = 0x50; + this._send(code, more); }; -p.bind = function(config) { +//send bind message +//"more" === true to buffer the message until flush() is called +p.bind = function(config, more) { //normalize config config = config || {}; config.portal = config.portal || ''; @@ -141,11 +147,12 @@ p.bind = function(config) { } buffer.addInt16(0); //no format codes, use text //0x42 = 'B' - - this._send(0x42, buffer); + this._send(0x42, more); }; -p.execute = function(config) { +//send execute message +//"more" === true to buffer the message until flush() is called +p.execute = function(config, more) { config = config || {}; config.portal = config.portal || ''; config.rows = config.rows || ''; @@ -154,28 +161,34 @@ p.execute = function(config) { .addInt32(config.rows); //0x45 = 'E' - this._send(0x45, buffer); + this._send(0x45, more); }; var emptyBuffer = Buffer(0); p.flush = function() { //0x48 = 'H' - this._send(0x48,this.writer.add(emptyBuffer)); + this.writer.add(emptyBuffer) + this._send(0x48); } p.sync = function() { - //0x53 = 'S' - this._send(0x53, this.writer.add(emptyBuffer)); + //clear out any pending data in the writer + this.writer.flush(0) + + this.writer.add(emptyBuffer); + this._send(0x53); }; p.end = function() { //0x58 = 'X' - this._send(0x58, this.writer.add(emptyBuffer)); + this.writer.add(emptyBuffer); + this._send(0x58); }; -p.describe = function(msg) { - this._send(0x44, this.writer.addCString(msg.type + (msg.name || ''))); +p.describe = function(msg, more) { + this.writer.addCString(msg.type + (msg.name || '')); + this._send(0x44, more); }; //parsing methods diff --git a/lib/query.js b/lib/query.js index 996f6cfc..0346bd07 100644 --- a/lib/query.js +++ b/lib/query.js @@ -106,7 +106,7 @@ p.getRows = function(connection) { connection.execute({ portal: this.name, rows: this.rows - }); + }, true); connection.flush(); }; @@ -121,7 +121,7 @@ p.prepare = function(connection) { text: self.text, name: self.name, types: self.types - }); + }, true); connection.parsedStatements[this.name] = true; } @@ -137,12 +137,12 @@ p.prepare = function(connection) { portal: self.name, statement: self.name, values: self.values - }); + }, true); connection.describe({ type: 'P', name: self.name || "" - }); + }, true); this.getRows(connection); }; diff --git a/lib/writer.js b/lib/writer.js index f87ba29f..0faf344e 100644 --- a/lib/writer.js +++ b/lib/writer.js @@ -2,6 +2,7 @@ var Writer = function(size) { this.size = size || 1024; this.buffer = new Buffer(this.size + 5); this.offset = 5; + this.headerPosition = 0; }; var p = Writer.prototype; @@ -70,18 +71,32 @@ p.add = function(otherBuffer) { } p.clear = function() { - this.offset=5; + this.offset = 5; + this.headerPosition = 0; + this.lastEnd = 0; +} + +//appends a header block to all the written data since the last +//subsequent header or to the beginning if there is only one data block +p.addHeader = function(code, last) { + var origOffset = this.offset; + this.offset = this.headerPosition; + this.buffer[this.offset++] = code; + //length is everything in this packet minus the code + this.addInt32(origOffset - (this.headerPosition+1)) + //set next header position + this.headerPosition = origOffset; + //make space for next header + this.offset = origOffset; + if(!last) { + this._ensure(5); + this.offset += 5; + } } p.join = function(code) { if(code) { - var end = this.offset; - this.offset = 0; - this.buffer[this.offset++] = code; - //write the length which is length of entire packet not including - //message type code byte - this.addInt32(end - 1); - this.offset = end; + this.addHeader(code, true); } return this.buffer.slice(code ? 0 : 5, this.offset); } diff --git a/test/unit/writer-tests.js b/test/unit/writer-tests.js index f2052bf4..be926302 100644 --- a/test/unit/writer-tests.js +++ b/test/unit/writer-tests.js @@ -156,7 +156,7 @@ test("resizing to much larger", function() { assert.equalBuffers(result, [33, 33, 33, 33, 33, 33, 33, 33, 0]) }) -test("header", function() { +test("flush", function() { test('added as a hex code to a full writer', function() { var subject = new Writer(2); var result = subject.addCString("!").flush(0x50) @@ -175,3 +175,15 @@ test("header", function() { assert.equalBuffers(result, [0x50, 0, 0, 0, 0x0D, 33, 33, 33, 33, 33, 33, 33, 33, 0]); }) }) + +test("header", function() { + test('adding two packets with headers', function() { + var subject = new Writer(10).addCString("!"); + subject.addHeader(0x50); + subject.addCString("!!"); + subject.addHeader(0x40); + subject.addCString("!"); + var result = subject.flush(0x10); + assert.equalBuffers(result, [0x50, 0, 0, 0, 6, 33, 0, 0x40, 0, 0, 0, 7, 33, 33, 0, 0x10, 0, 0, 0, 6, 33, 0 ]); + }) +})