diff --git a/lib/client.js b/lib/client.js index 7432c447..04ac63c6 100644 --- a/lib/client.js +++ b/lib/client.js @@ -50,94 +50,6 @@ p.md5 = function(string) { return crypto.createHash('md5').update(string).digest('hex'); }; -p.end = function() { - var terminationBuffer = new Buffer([0x58,0,0,0,4]); - var wrote = this.stream.end(terminationBuffer); -}; - -p.query = function(text) { - this.queryQueue.push({type: 'simpleQuery', text: text }); - this.pulseQueryQueue(); - return this; -}; - -p.parse = function(query) { - //expect something like this: - // { name: 'queryName', - // text: 'select * from blah', - // types: ['int8', 'bool'] } - - //normalize missing query names to allow for null - query.name = query.name || ''; - //normalize null type array - query.types = query.types || []; - - //append internal type identifier - query.type = 'preparedQuery'; - - this.queryQueue.push(query); - this.pulseQueryQueue(); - return this; -}; - -p.bind = function(config) { - //normalize config - config = config || {}; - config.portalName = config.portalName || ''; - config.statementName = config.statementName || ''; - config.values = config.values || []; - var buffer = new BufferList() - .addCString(config.portalName) - .addCString(config.statementName) - .addInt16(0) //always use default text format - .addInt16(0); //number of parameters - if(config.values.length > 0) { - sys.debug("Not supporting parameters yet"); - } - buffer.addInt16(0); //no format codes, use text - this.send('B', buffer.join()); -}; - -p.execute = function(name, rows) { - this.send('E',new BufferList().addCString(name||'').addInt32(rows||0).join()); -}; - -p.flush = function() { - this.send('H',Buffer(0)); -} - -p.sync = function() { - this.send('S', Buffer(0)); -}; - -p.pulseQueryQueue = function(ready) { - if(!this.readyForQuery) { - return; - }; - var query = this.queryQueue.shift(); - if(query) { - var self = this; - this.readyForQuery = false; - if(query.type === 'simpleQuery') { - this.send('Q', new Buffer(query.text + '\0', this.encoding)); - return; - } - if(query.type === 'preparedQuery') { - var buffer = new BufferList() - .addCString(query.name) //name of query - .addCString(query.text) //actual query text - .addInt16(0).join(); - if(query.types.length) { - sys.debug("Typed parameters not supported yet!"); - } - this.send('P', buffer); - return; - } - throw new Error("I don't know this query type " + sys.inspect(query)); - } -}; -//query handling - var intParser = { fromDbValue: parseInt }; @@ -195,207 +107,5 @@ p.processDataRow = function(dataRow) { this.emit('row',row); }; - -//parsing methods -p.setBuffer = function(buffer) { - if(this.lastBuffer) { //we have unfinished biznaz - //need to combine last two buffers - var remaining = this.lastBuffer.length - this.lastOffset; - var combinedBuffer = new Buffer(buffer.length + remaining); - this.lastBuffer.copy(combinedBuffer, 0, this.lastOffset); - buffer.copy(combinedBuffer, remaining, 0); - buffer = combinedBuffer; - } - this.buffer = buffer; - this.offset = 0; -}; - -var messageNames = { - R: 'authenticationOk', - S: 'parameterStatus', - K: 'backendKeyData', - C: 'commandComplete', - Z: 'readyForQuery', - T: 'rowDescription', - D: 'dataRow', - E: 'error', - 1: 'parseComplete', - 2: 'bindComplete' -}; - -p.parseMessage = function() { - var remaining = this.buffer.length - (this.offset); - if(remaining < 5) { - //cannot read id + length without at least 5 bytes - //just abort the read now - this.lastBuffer = this.buffer; - this.lastOffset = this.offset; - return; - } - - var id = this.readChar(); - - var message = { - id: id, - name: messageNames[id], - length: this.parseInt32() - }; - - if(remaining <= message.length) { - this.lastBuffer = this.buffer; - //rewind the last 5 bytes we read - this.lastOffset = this.offset-5; - return false; - } - - return this["parse"+message.id](message); -}; - -p.parseR = function(msg) { - var code = 0; - if(msg.length === 8) { - code = this.parseInt32(); - if(code === 3) { - msg.name = 'authenticationCleartextPassword'; - } - return msg; - } - if(msg.length === 12) { - code = this.parseInt32(); - if(code === 5) { //md5 required - msg.name = 'authenticationMD5Password'; - msg.salt = new Buffer(4); - this.buffer.copy(msg.salt, 0, this.offset, this.offset + 4); - this.offset += 4; - return msg; - } - } - throw new Error("Unknown authenticatinOk message type" + sys.inspect(msg)); -}; - -p.parseS = function(msg) { - msg.parameterName = this.parseCString(); - msg.parameterValue = this.parseCString(); - return msg; -}; - -p.parseK = function(msg) { - msg.processID = this.parseInt32(); - msg.secretKey = this.parseInt32(); - return msg; -}; - -p.parseC = function(msg) { - msg.text = this.parseCString(); - return msg; -}; - -p.parseZ = function(msg) { - msg.status = this.readChar(); - return msg; -}; - -p.parseT = function(msg) { - msg.fieldCount = this.parseInt16(); - var fields = []; - for(var i = 0; i < msg.fieldCount; i++){ - fields[i] = this.parseField(); - } - msg.fields = fields; - return msg; -}; - -p.parseField = function() { - var field = { - name: this.parseCString(), - tableID: this.parseInt32(), - columnID: this.parseInt16(), - dataTypeID: this.parseInt32(), - dataTypeSize: this.parseInt16(), - dataTypeModifier: this.parseInt32(), - format: this.parseInt16() === 0 ? 'text' : 'binary' - }; - return field; -}; - -p.parseD = function(msg) { - var fieldCount = this.parseInt16(); - var fields = []; - for(var i = 0; i < fieldCount; i++) { - var length = this.parseInt32(); - fields[i] = (length === -1 ? null : this.readString(length)) - }; - msg.fieldCount = fieldCount; - msg.fields = fields; - return msg; -}; - -//parses error -p.parseE = function(msg) { - var fields = {}; - var fieldType = this.readString(1); - while(fieldType != '\0') { - fields[fieldType] = this.parseCString(); - fieldType = this.readString(1); - } - msg.severity = fields.S; - msg.code = fields.C; - msg.message = fields.M; - msg.detail = fields.D; - msg.hint = fields.H; - msg.position = fields.P; - msg.internalPosition = fields.p; - msg.internalQuery = fields.q; - msg.where = fields.W; - msg.file = fields.F; - msg.line = fields.L; - msg.routine = fields.R; - return msg; -}; - -//parses parseComplete -p.parse1 = function(msg) { - return msg; -}; - -//parses bindComplete -p.parse2 = function(msg) { - return msg; -}; - -p.readChar = function() { - return Buffer([this.buffer[this.offset++]]).toString(this.encoding); -}; - -p.parseInt32 = function() { - var value = this.peekInt32(); - this.offset += 4; - return value; -}; - -p.peekInt32 = function(offset) { - offset = offset || this.offset; - var buffer = this.buffer; - return ((buffer[offset++] << 24) + - (buffer[offset++] << 16) + - (buffer[offset++] << 8) + - buffer[offset++]); -}; - - -p.parseInt16 = function() { - return ((this.buffer[this.offset++] << 8) + - (this.buffer[this.offset++] << 0)); -}; - -p.readString = function(length) { - return this.buffer.toString(this.encoding, this.offset, (this.offset += length)); -}; - -p.parseCString = function() { - var start = this.offset; - while(this.buffer[this.offset++]) { }; - return this.buffer.toString(this.encoding, start, this.offset - 1); -}; //end parsing methods module.exports = Client;