diff --git a/lib/client.js b/lib/client.js index fc68ba81..3eb2e072 100644 --- a/lib/client.js +++ b/lib/client.js @@ -79,21 +79,16 @@ p.connect = function() { }); }; - p.pulseQueryQueue = function() { if(this.readyForQuery===true) { if(this.queryQueue.length > 0) { this.readyForQuery = false; var query = this.queryQueue.shift(); this.activeQuery = query; + this.hasExecuted = true; query.submit(this.connection); - } else { - var self = this; - process.nextTick(function() { - if(this.queryQueue.length <= 0) { - this.emit('drain'); - } - }.bind(this)) + } else if(this.hasExecuted) { + this.emit('drain') } } }; diff --git a/lib/query.js b/lib/query.js index 0a0bd227..70c7e330 100644 --- a/lib/query.js +++ b/lib/query.js @@ -57,6 +57,15 @@ p.submit = function(connection) { } }; + var onCommandComplete = function() { + self.callback(null, {rows: rows}); + rows = []; + } + + if(self.callback) { + connection.on('commandComplete', onCommandComplete) + } + var onError = function(err) { //remove all listeners connection.removeListener('rowDescription', handleDatarow); @@ -65,6 +74,7 @@ p.submit = function(connection) { connection.removeListener('readyForQuery', onReadyForQuery); if(self.callback) { self.callback(err); + connection.removeListener('commandComplete', onCommandComplete); } self.emit('error', err); self.emit('end'); @@ -77,7 +87,7 @@ p.submit = function(connection) { connection.removeListener('readyForQuery', onReadyForQuery); connection.removeListener('error', onError); if(self.callback) { - self.callback(null, {rows: rows}); + connection.removeListener('commandComplete', onCommandComplete); } self.emit('end'); }; @@ -85,6 +95,7 @@ p.submit = function(connection) { connection.on('rowDescription', handleRowDescription); connection.on('dataRow', handleDatarow); connection.on('readyForQuery', onReadyForQuery); + connection.on('error', onError); }; diff --git a/test/integration/client/api-tests.js b/test/integration/client/api-tests.js index 4c4d7e76..efa8fb97 100644 --- a/test/integration/client/api-tests.js +++ b/test/integration/client/api-tests.js @@ -1,62 +1,58 @@ var helper = require(__dirname + '/../test-helper'); var pg = require(__dirname + '/../../../lib'); -var connected = false -var simpleCalled = false -var preparedCalled = false -var nestedCalled = false -pg.connect(helper.args, function(err, client) { - connected = true - assert.equal(err, null, "Failed to connect"); +test('api', function() { + pg.connect(helper.args, assert.calls(function(err, client) { + assert.equal(err, null, "Failed to connect"); - client.query('CREATE TEMP TABLE band(name varchar(100))'); + client.query('CREATE TEMP TABLE band(name varchar(100))'); - ['the flaming lips', 'wolf parade', 'radiohead', 'bright eyes', 'the beach boys', 'dead black hearts'].forEach(function(bandName) { - client.query("INSERT INTO band (name) VALUES ('"+ bandName +"')") - }); - - - test('simple query execution', function() { - client.query("SELECT * FROM band WHERE name = 'the beach boys'", function(err, result) { - simpleCalled = true - assert.length(result.rows, 1) - assert.equal(result.rows.pop().name, 'the beach boys') + ['the flaming lips', 'wolf parade', 'radiohead', 'bright eyes', 'the beach boys', 'dead black hearts'].forEach(function(bandName) { + var query = client.query("INSERT INTO band (name) VALUES ('"+ bandName +"')") }); - }) - test('prepared statement execution', function() { - client.query('SELECT * FROM band WHERE name = $1', ['dead black hearts'], function(err, result) { - preparedCalled = true; - assert.length(result.rows, 1); - assert.equal(result.rows.pop().name, 'dead black hearts'); - }) + test('simple query execution',assert.calls( function() { + client.query("SELECT * FROM band WHERE name = 'the beach boys'", function(err, result) { + assert.length(result.rows, 1) + assert.equal(result.rows.pop().name, 'the beach boys') + }); - client.query('SELECT * FROM band WHERE name LIKE $1 ORDER BY name', ['the %'], function(err, result) { - assert.length(result.rows, 2); - assert.equal(result.rows.pop().name, 'the flaming lips'); - assert.equal(result.rows.pop().name, 'the beach boys'); - }) - }) + })) - test('executing nested queries', function() { - client.query('select * FROM band', function(err, result) { - client.query('select * FROM band', function(err, result2) { - nestedCalled = true - }) - }) - }) + test('prepared statement execution',assert.calls( function() { + client.query('SELECT * FROM band WHERE name = $1', ['dead black hearts'],assert.calls( function(err, result) { + assert.length(result.rows, 1); + assert.equal(result.rows.pop().name, 'dead black hearts'); + })) + + client.query('SELECT * FROM band WHERE name LIKE $1 ORDER BY name', ['the %'], assert.calls(function(err, result) { + assert.length(result.rows, 2); + assert.equal(result.rows.pop().name, 'the flaming lips'); + assert.equal(result.rows.pop().name, 'the beach boys'); + })) + })) + + })) }) -process.on('exit', function() { - assert.ok(connected, 'never connected'); - assert.ok(nestedCalled, 'never called nested query') - assert.ok(simpleCalled, 'query result callback was never called'); - assert.ok(preparedCalled, 'prepared callback was never called'); + +test('executing nested queries', function() { + pg.connect(helper.args, assert.calls(function(err, client) { + client.query('select now as now from NOW()', assert.calls(function(err, result) { + assert.equal(new Date().getYear(), result.rows[0].now.getYear()) + client.query('select now as now_again FROM NOW()', assert.calls(function() { + client.query('select * FROM NOW()', assert.calls(function() { + assert.ok('all queries hit') + })) + })) + })) + })) }) + test('raises error if cannot connect', function() { - pg.connect({database:'asdlfkajsdf there is no way this is a real database, right?!'}, function(err, client) { - assert.ok(err, 'error was null') - }) + pg.connect({database:'asdlfkajsdf there is no way this is a real database, right?!'}, assert.calls(function(err, client) { + assert.ok(err, 'should have raised an error') + })) })