Merge remote branch 'upstream/master'

Conflicts:
	lib/query.js
This commit is contained in:
Alexander Sulfrian 2011-01-29 01:19:33 +01:00
commit fa35c13658
2 changed files with 105 additions and 90 deletions

View File

@ -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

View File

@ -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;