working on getting query to complete

This commit is contained in:
brianc 2010-09-29 01:01:52 -05:00
parent 6ba4575385
commit c68c365478
5 changed files with 103 additions and 21 deletions

View File

@ -3,12 +3,14 @@ var sys = require('sys');
var net = require('net');
var NUL = '\0';
var chars = Buffer('RSKZ','utf8');
var chars = Buffer('RSKZQC','utf8');
var UTF8 = {
R: chars[0],
S: chars[1],
K: chars[2],
Z: chars[3]
Z: chars[3],
Q: chars[4],
C: chars[5]
};
@ -18,6 +20,7 @@ var Client = function(config) {
this.user = config.user;
this.database = config.database;
this.port = config.port || 5432;
this.queryQueue = [];
};
sys.inherits(Client, EventEmitter);
@ -25,7 +28,6 @@ Client.prototype.connect = function() {
var con = net.createConnection(this.port);
var self = this;
con.on('connect', function() {
var data = ['user',self.user,'database', self.database,NUL].join(NUL);
var dataBuffer = Buffer(data);
var fullBuffer = Buffer(8 + dataBuffer.length);
@ -38,19 +40,57 @@ Client.prototype.connect = function() {
fullBuffer[6] = 0;
fullBuffer[7] = 0;
fullBuffer.write(data,8);
console.log(fullBuffer);
con.write(fullBuffer);
});
con.on('data', function(data) {
console.log('data!');
console.log(data);
var parser = new Parser(data);
con.end();
var result = parser.parse();
result.forEach(function(msg) {
console.log(msg);
self.emit('message', msg);
self.emit(msg.name, msg);
});
});
this.con = con;
this.on('ReadyForQuery', function() {
self.readyForQuery = true;
self.pulseQueryQueue();
});
this.on('message', function(msg) {
console.log(msg.name);
});
};
Client.prototype.query = function(queryText) {
this.queryQueue.push(new Query({
text: queryText
}));
this.pulseQueryQueue();
};
Client.prototype.pulseQueryQueue = function() {
if(!this.readyForQuery) {
return;
}
var query = this.queryQueue.shift();
if(!query) {
return;
}
var txt = query.text + "\0"
var queryTextBuffer = Buffer(txt);
var len = queryTextBuffer.length+4;
var messageBuffer = Buffer(queryTextBuffer.length + 5);
messageBuffer[0] = UTF8.Q;
messageBuffer[1] = len >>> 24;
messageBuffer[2] = len >>> 16;
messageBuffer[3] = len >>> 8;
messageBuffer[4] = len >>> 0;
messageBuffer.write(txt,5);
this.con.write(messageBuffer);
this.readyForQuery = false;
};
var Query = function(config) {
this.text = config.text;
};
var Parser = function(buffer) {
@ -83,6 +123,8 @@ p.parseMessage = function() {
return this.parseK();
case UTF8.Z:
return this.parseZ();
case UTF8.C:
return this.parseC();
default:
throw new Error("Unsupported message ID: " + Buffer([messageID]).toString('utf8') + " (" + messageID.toString(16) + ")");
}
@ -116,6 +158,12 @@ p.parseK = function() {
return msg;
};
p.parseC = function() {
var msg = this.parseStart('CommandComplete');
msg.text = this.parseCString();
return msg;
};
//parses common start of message packets
p.parseStart = function(name) {
return {

View File

@ -20,10 +20,7 @@ assert.equal(client.database, 'hello');
assert.equal(client.port, 321);
client.port = 5432;
client.connect(function() {
console.log('connected');
client.query('select count(*) from items',function(result) {
console.log('ran query');
});
});
client.connect();
var query = client.query('create temporary table bang (id integer)');

View File

@ -1,15 +1,18 @@
require(__dirname+'/test-helper');
test('Parser on single messages', function() {
var authenticationOkBuffer = Buffer([0x52, 00, 00, 00, 08, 00, 00, 00, 00]);
var authOkData = [0x52, 00, 00, 00, 08, 00, 00, 00, 00];
var authenticationOkBuffer = Buffer(authOkData);
var firstString = [0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0];
var secondString = [0x55, 0x54, 0x46, 0x38, 0];
var bytes = [0x53, 0, 0, 0, 0x19].concat(firstString).concat(secondString);
var parameterStatusBuffer = Buffer(bytes);
var paramStatusData = [0x53, 0, 0, 0, 0x19].concat(firstString).concat(secondString);
var parameterStatusBuffer = Buffer(paramStatusData);
var backendKeyDataBuffer = Buffer([0x4b, 0, 0, 0, 0x0c, 0, 0, 0, 1, 0, 0, 0, 2]);
var backendKeyData = [0x4b, 0, 0, 0, 0x0c, 0, 0, 0, 1, 0, 0, 0, 2];
var backendKeyDataBuffer = Buffer(backendKeyData);
var readyForQueryBuffer = Buffer([0x5a, 0, 0, 0, 5, 'I'.charCodeAt(0)])
var readyForQueryData = [0x5a, 0, 0, 0, 5, 'I'.charCodeAt(0)];
var readyForQueryBuffer = Buffer(readyForQueryData)
var expectedAuthenticationOkayMessage = {
@ -60,10 +63,37 @@ test('Parser on single messages', function() {
assert.same(result, expectedReadyForQueryMessage);
});
test('parses multiple messages', function() {
var message = authOkData
.concat(paramStatusData)
.concat(backendKeyData)
.concat(readyForQueryData);
var buffer = Buffer(message);
var result = new Parser(buffer).parse();
assert.equal(result.length, 4);
assert.same(result[0], expectedAuthenticationOkayMessage);
assert.same(result[1], expectedParameterStatusMessage);
assert.same(result[2], expectedBackendKeyDataMessage);
assert.same(result[3], expectedReadyForQueryMessage);
});
test('parses normal CString', function() {
var result = new Parser(Buffer([33,0])).parseCString();
assert.equal(result,"!");
});
var resultText = stringToHex("SELECT 3\0");
var length = resultText.length + 4;
var commandCompleteData = [0x43, 0, 0, 0, length].concat(resultText);
test('parses CommandComplete message', function() {
var result = new Parser(Buffer(commandCompleteData)).parse()[0];
assert.same(result, {
length: 13,
id: 'C',
text: "SELECT 3"
});
});
test('parses empty CString', function() {
var result = new Parser(Buffer([0])).parseCString();

View File

@ -23,7 +23,12 @@ test = function(name, action) {
test.tabout = 0;
stringToHex = function(string) {
var b = Buffer(string,'utf8');
var result = [];
for(var i = 0; i < b.length; i++) {
result.push(b[i]);
}
return result;
};
hexToString = function(hexArray) {

View File

@ -3,14 +3,16 @@
def run_parser_tests
system("node test/parser-tests.js")
puts ""
puts("waiting...")
puts("#{Time.now} waiting...")
puts ""
end
watch('lib/(.*)\.js') { |md|
puts "lib changed"
run_parser_tests
}
watch('test/(.*)\.js') { |md|
puts "test changed"
run_parser_tests
}