mirror of
https://github.com/brianc/node-postgres.git
synced 2025-12-08 20:16:25 +00:00
Merge remote branch 'upstream/master'
Conflicts: lib/query.js
This commit is contained in:
commit
fa35c13658
@ -75,21 +75,12 @@ p.startup = function(config) {
|
||||
|
||||
p.password = function(password) {
|
||||
//0x70 = 'p'
|
||||
this.send(0x70, this.writer.addCString(password).flush());
|
||||
this._send(0x70, this.writer.addCString(password));
|
||||
};
|
||||
|
||||
p.send = function(code, bodyBuffer) {
|
||||
var length = bodyBuffer.length + 4;
|
||||
var buffer = Buffer(length + 1);
|
||||
var offset = 0;
|
||||
buffer[offset++] = code;
|
||||
buffer[offset++] = length >>> 24 & 0xFF;
|
||||
buffer[offset++] = length >>> 16 & 0xFF;
|
||||
buffer[offset++] = length >>> 8 & 0xFF;
|
||||
buffer[offset++] = length >>> 0 & 0xFF;
|
||||
bodyBuffer.copy(buffer, offset, 0);
|
||||
return this.stream.write(buffer);
|
||||
};
|
||||
p._send = function(code, writer) {
|
||||
return this.stream.write(writer.flush(code));
|
||||
}
|
||||
|
||||
var termBuffer = new Buffer([0x58, 0, 0, 0, 4]);
|
||||
p.end = function() {
|
||||
@ -98,7 +89,7 @@ p.end = function() {
|
||||
|
||||
p.query = function(text) {
|
||||
//0x51 = Q
|
||||
this.send(0x51, this.writer.addCString(text).flush());
|
||||
this.stream.write(this.writer.addCString(text).flush(0x51));
|
||||
};
|
||||
|
||||
p.parse = function(query) {
|
||||
@ -121,7 +112,7 @@ p.parse = function(query) {
|
||||
}
|
||||
|
||||
//0x50 = 'P'
|
||||
this.send(0x50, buffer.flush());
|
||||
this._send(0x50, buffer);
|
||||
|
||||
return this;
|
||||
};
|
||||
@ -151,7 +142,8 @@ p.bind = function(config) {
|
||||
buffer.addInt16(1); // format codes to use binary
|
||||
buffer.addInt16(1);
|
||||
//0x42 = 'B'
|
||||
this.send(0x42, buffer.flush());
|
||||
|
||||
this._send(0x42, buffer);
|
||||
};
|
||||
|
||||
p.execute = function(config) {
|
||||
@ -160,30 +152,31 @@ p.execute = function(config) {
|
||||
config.rows = config.rows || '';
|
||||
var buffer = this.writer
|
||||
.addCString(config.portal)
|
||||
.addInt32(config.rows)
|
||||
.flush();
|
||||
|
||||
.addInt32(config.rows);
|
||||
|
||||
//0x45 = 'E'
|
||||
this.send(0x45, buffer);
|
||||
this._send(0x45, buffer);
|
||||
};
|
||||
|
||||
var emptyBuffer = Buffer(0);
|
||||
|
||||
p.flush = function() {
|
||||
//0x48 = 'H'
|
||||
this.send(0x48,Buffer(0));
|
||||
this._send(0x48,this.writer.add(emptyBuffer));
|
||||
}
|
||||
|
||||
p.sync = function() {
|
||||
//0x53 = 'S'
|
||||
this.send(0x53, Buffer(0));
|
||||
this._send(0x53, this.writer.add(emptyBuffer));
|
||||
};
|
||||
|
||||
p.end = function() {
|
||||
//0x58 = 'X'
|
||||
this.send(0x58, Buffer(0));
|
||||
this._send(0x58, this.writer.add(emptyBuffer));
|
||||
};
|
||||
|
||||
p.describe = function(msg) {
|
||||
this.send(0x44, this.writer.addCString(msg.type + (msg.name || '')).flush());
|
||||
this._send(0x44, this.writer.addCString(msg.type + (msg.name || '')));
|
||||
};
|
||||
|
||||
//parsing methods
|
||||
|
||||
154
lib/query.js
154
lib/query.js
@ -1,5 +1,6 @@
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var sys = require('sys');var sys = require('sys');
|
||||
var Result = require(__dirname + "/result");
|
||||
|
||||
var Query = function(config) {
|
||||
this.text = config.text;
|
||||
@ -26,6 +27,53 @@ var noParse = function(val) {
|
||||
return val;
|
||||
};
|
||||
|
||||
//creates datarow metatdata from the supplied
|
||||
//data row information
|
||||
var buildDataRowMetadata = function(msg, converters, names) {
|
||||
var len = msg.fields.length;
|
||||
for(var i = 0; i < len; i++) {
|
||||
var field = msg.fields[i];
|
||||
var dataTypeId = field.dataTypeID;
|
||||
names[i] = field.name;
|
||||
switch(dataTypeId) {
|
||||
case 20:
|
||||
converters[i] = parseBinaryInt64;
|
||||
break;
|
||||
case 21:
|
||||
converters[i] = parseBinaryInt16;
|
||||
break;
|
||||
case 23:
|
||||
converters[i] = parseBinaryInt32;
|
||||
break;
|
||||
case 26:
|
||||
converters[i] = parseBinaryInt64;
|
||||
break;
|
||||
case 1700:
|
||||
case 700:
|
||||
converters[i] = parseBinaryFloat32;
|
||||
case 701:
|
||||
converters[i] = parseBinaryFloat64;
|
||||
break;
|
||||
case 16:
|
||||
converters[i] = function(val) {
|
||||
return val == 1;
|
||||
};
|
||||
break;
|
||||
case 1114:
|
||||
case 1184:
|
||||
converters[i] = parseDate;
|
||||
break;
|
||||
case 1007:
|
||||
case 1008:
|
||||
converters[i] = arrayParser,
|
||||
break;
|
||||
default:
|
||||
converters[i] = dataTypeParsers[dataTypeId] || noParse;
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
p.submit = function(connection) {
|
||||
var self = this;
|
||||
if(this.requiresPreparation()) {
|
||||
@ -33,47 +81,38 @@ p.submit = function(connection) {
|
||||
} else {
|
||||
connection.query(this.text);
|
||||
}
|
||||
|
||||
var converters = [];
|
||||
var names = [];
|
||||
var rows = [];
|
||||
var handleRowDescription = function(msg) {
|
||||
for(var i = 0; i < msg.fields.length; i++) {
|
||||
converters[i] = dataTypeParsers[msg.fields[i].dataTypeID] || noParse;
|
||||
names[i] = msg.fields[i].name;
|
||||
};
|
||||
buildDataRowMetadata(msg, converters, names);
|
||||
};
|
||||
|
||||
var result = new Result();
|
||||
|
||||
var handleDatarow = function(msg) {
|
||||
var result = {};
|
||||
var row = {};
|
||||
for(var i = 0; i < msg.fields.length; i++) {
|
||||
var rawValue = msg.fields[i];
|
||||
result[names[i]] = rawValue === null ? null : converters[i](rawValue);
|
||||
row[names[i]] = rawValue === null ? null : converters[i](rawValue);
|
||||
}
|
||||
self.emit('row', result);
|
||||
self.emit('row', row);
|
||||
|
||||
//if no reciever, buffer rows
|
||||
//if there is a callback collect rows
|
||||
if(self.callback) {
|
||||
rows.push(result);
|
||||
result.addRow(row);
|
||||
}
|
||||
};
|
||||
|
||||
var onCommandComplete = function() {
|
||||
self.callback(null, {rows: rows});
|
||||
rows = [];
|
||||
}
|
||||
|
||||
if(self.callback) {
|
||||
connection.on('commandComplete', onCommandComplete)
|
||||
}
|
||||
var onCommandComplete = function(msg) {
|
||||
result.addCommandComplete(msg);
|
||||
};
|
||||
|
||||
var onError = function(err) {
|
||||
//remove all listeners
|
||||
connection.removeListener('rowDescription', handleDatarow);
|
||||
connection.removeListener('dataRow', handleDatarow);
|
||||
connection.removeListener('error', onError);
|
||||
connection.removeListener('readyForQuery', onReadyForQuery);
|
||||
removeListeners();
|
||||
if(self.callback) {
|
||||
self.callback(err);
|
||||
connection.removeListener('commandComplete', onCommandComplete);
|
||||
} else {
|
||||
self.emit('error', err);
|
||||
}
|
||||
@ -81,21 +120,26 @@ p.submit = function(connection) {
|
||||
};
|
||||
|
||||
var onReadyForQuery = function() {
|
||||
removeListeners();
|
||||
if(self.callback) {
|
||||
self.callback(null, result);
|
||||
}
|
||||
self.emit('end', result);
|
||||
};
|
||||
|
||||
var removeListeners = function() {
|
||||
//remove all listeners
|
||||
connection.removeListener('rowDescription', handleRowDescription);
|
||||
connection.removeListener('dataRow', handleDatarow);
|
||||
connection.removeListener('readyForQuery', onReadyForQuery);
|
||||
connection.removeListener('commandComplete', onCommandComplete);
|
||||
connection.removeListener('error', onError);
|
||||
if(self.callback) {
|
||||
connection.removeListener('commandComplete', onCommandComplete);
|
||||
}
|
||||
self.emit('end');
|
||||
};
|
||||
|
||||
connection.on('rowDescription', handleRowDescription);
|
||||
connection.on('dataRow', handleDatarow);
|
||||
connection.on('readyForQuery', onReadyForQuery);
|
||||
|
||||
connection.on('commandComplete', onCommandComplete);
|
||||
connection.on('error', onError);
|
||||
};
|
||||
|
||||
@ -107,12 +151,12 @@ p.prepare = function(connection) {
|
||||
var self = this;
|
||||
|
||||
if(!this.hasBeenParsed(connection)) {
|
||||
connection.parsedStatements[this.name] = true;
|
||||
connection.parse({
|
||||
text: self.text,
|
||||
name: self.name,
|
||||
types: self.types
|
||||
});
|
||||
connection.parsedStatements[this.name] = true;
|
||||
}
|
||||
|
||||
//TODO is there some btter way to prepare values for the database?
|
||||
@ -144,7 +188,6 @@ p.prepare = function(connection) {
|
||||
|
||||
getRows();
|
||||
|
||||
//TODO support EmptyQueryResponse, ErrorResponse, and PortalSuspended
|
||||
var onCommandComplete = function() {
|
||||
connection.removeListener('error', onCommandComplete);
|
||||
connection.removeListener('commandComplete', onCommandComplete);
|
||||
@ -159,32 +202,28 @@ p.prepare = function(connection) {
|
||||
};
|
||||
|
||||
var dateParser = function(isoDate) {
|
||||
//TODO find some regexp help
|
||||
//this method works but it's ooglay
|
||||
//if you wanna contribute...... ;)
|
||||
var split = isoDate.split(' ');
|
||||
var dateMatcher = /(\d{4})-(\d{2})-(\d{2})/;
|
||||
//TODO this could do w/ a refactor
|
||||
|
||||
var date = split[0];
|
||||
var time = split[1];
|
||||
var match = dateMatcher.exec(date);
|
||||
var splitDate = date.split('-');
|
||||
var dateMatcher = /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(\.\d{1,})?/;
|
||||
|
||||
var match = dateMatcher.exec(isoDate);
|
||||
var year = match[1];
|
||||
var month = parseInt(match[2],10)-1;
|
||||
var day = match[3];
|
||||
var hour = parseInt(match[4],10);
|
||||
var min = parseInt(match[5],10);
|
||||
var seconds = parseInt(match[6], 10);
|
||||
|
||||
var splitTime = time.split(':');
|
||||
var hour = parseInt(splitTime[0],10);
|
||||
var min = parseInt(splitTime[1],10);
|
||||
var end = splitTime[2];
|
||||
var seconds = /(\d{2})/.exec(end);
|
||||
seconds = (seconds ? seconds[1] : 0);
|
||||
seconds = parseInt(seconds,10);
|
||||
var mili = /\.(\d{1,})/.exec(end+"000");
|
||||
mili = mili ? mili[1].slice(0,3) : 0;
|
||||
var tZone = /([Z|+\-])(\d{2})?(\d{2})?/.exec(end);
|
||||
var miliString = match[7];
|
||||
var mili = 0;
|
||||
if(miliString) {
|
||||
mili = 1000 * parseFloat(miliString);
|
||||
}
|
||||
|
||||
var tZone = /([Z|+\-])(\d{2})?(\d{2})?/.exec(isoDate.split(' ')[1]);
|
||||
//minutes to adjust for timezone
|
||||
var tzAdjust = 0;
|
||||
|
||||
if(tZone) {
|
||||
var type = tZone[1];
|
||||
switch(type) {
|
||||
@ -408,23 +447,6 @@ var arrayParser = function(value) {
|
||||
Query.dateParser = dateParser;
|
||||
|
||||
var dataTypeParsers = {
|
||||
16: function(dbVal) { //boolean
|
||||
console.log(JSON.stringify(dbVal));
|
||||
return value[0] == 1;
|
||||
},
|
||||
|
||||
20: parseBinaryInt64,
|
||||
21: parseBinaryInt16,
|
||||
23: parseBinaryInt32,
|
||||
26: parseBinaryInt64,
|
||||
700: parseBinaryFloat32,
|
||||
701: parseBinaryFloat64,
|
||||
1007: arrayParser,
|
||||
1009: arrayParser,
|
||||
1114: parseDate,
|
||||
//1184: parseBinaryInt64
|
||||
// 1700: parseFloat,
|
||||
};
|
||||
|
||||
|
||||
module.exports = Query;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user