diff --git a/lib/client.js b/lib/client.js index 23586481..b58b3c8f 100644 --- a/lib/client.js +++ b/lib/client.js @@ -143,12 +143,22 @@ Client.prototype.connect = function(callback) { }); con.on('readyForQuery', function() { + var error; if(self.activeQuery) { - self.activeQuery.handleReadyForQuery(); + //try/catch/rethrow to ensure exceptions don't prevent the queryQueue from + //being processed + try{ + self.activeQuery.handleReadyForQuery(); + } catch(e) { + error = e; + } } self.activeQuery = null; self.readyForQuery = true; self._pulseQueryQueue(); + if(error) { + throw error; + } }); con.on('error', function(error) { diff --git a/lib/native/index.js b/lib/native/index.js index 7ddc978d..69f38850 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -208,15 +208,23 @@ var clientBuilder = function(config) { }); connection.on('_readyForQuery', function() { + var error; var q = this._activeQuery; //a named query finished being prepared if(this._namedQuery) { this._namedQuery = false; this._sendQueryPrepared(q.name, q.values||[]); } else { - connection._activeQuery.handleReadyForQuery(connection._lastMeta); + //try/catch/rethrow to ensure exceptions don't prevent the queryQueue from + //being processed + try{ + connection._activeQuery.handleReadyForQuery(connection._lastMeta); + } catch(e) { + error = e; + } connection._activeQuery = null; connection._pulseQueryQueue(); + if(error) throw error; } }); connection.on('copyInResponse', function () { diff --git a/test/integration/client/query-callback-error-tests.js b/test/integration/client/query-callback-error-tests.js new file mode 100644 index 00000000..2edc1747 --- /dev/null +++ b/test/integration/client/query-callback-error-tests.js @@ -0,0 +1,22 @@ +var helper = require(__dirname + '/test-helper'); +var util = require('util'); + +test('error during query execution', function() { + var client = new Client(helper.args); + process.removeAllListeners('uncaughtException'); + assert.emits(process, 'uncaughtException', function() { + assert.equal(client.activeQuery, null, 'should remove active query even if error happens in callback'); + client.query('SELECT * FROM blah', assert.success(function(result) { + assert.equal(result.rows.length, 1); + client.end(); + })); + }); + client.connect(assert.success(function() { + client.query('CREATE TEMP TABLE "blah"(data text)', assert.success(function() { + var q = client.query('INSERT INTO blah(data) VALUES($1)', ['yo'], assert.success(function() { + assert.emits(client, 'drain'); + throw new Error('WHOOOAAAHH!!'); + })); + })); + })); +});