From 9c7a33cacae27dbb2d8efe9bc240a24e39da8961 Mon Sep 17 00:00:00 2001 From: brianc Date: Thu, 7 Mar 2013 15:57:00 -0600 Subject: [PATCH 01/16] remove 2 parameter pg.connect function --- lib/pool.js | 61 +++---------------- package.json | 2 +- script/test-connection.js | 3 +- test/integration/client/api-tests.js | 32 +++++----- test/integration/client/array-tests.js | 12 +--- test/integration/client/copy-tests.js | 23 +++---- test/integration/client/drain-tests.js | 55 ----------------- test/integration/client/huge-numeric-tests.js | 3 +- .../client/result-metadata-tests.js | 3 +- test/integration/client/transaction-tests.js | 10 +-- .../integration/client/type-coercion-tests.js | 6 +- .../connection-pool/ending-pool-tests.js | 3 +- .../connection-pool/error-tests.js | 19 ++++-- .../connection-pool/idle-timeout-tests.js | 3 +- .../connection-pool/optional-config-tests.js | 3 +- test/test-helper.js | 51 +++++++++++----- test/unit/pool/basic-tests.js | 19 +----- 17 files changed, 114 insertions(+), 194 deletions(-) delete mode 100644 test/integration/client/drain-tests.js diff --git a/lib/pool.js b/lib/pool.js index cd538204..1600ba7c 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -54,64 +54,17 @@ var pools = { pool.connect = function(cb) { pool.acquire(function(err, client) { if(err) return cb(err, null, function() {/*NOOP*/}); - //support both 2 (old) and 3 arguments - (cb.length > 2 ? newConnect : oldConnect)(pool, client, cb); + cb(null, client, function(err) { + if(err) { + pool.destroy(client); + } else { + pool.release(client); + } + }); }); }; return pool; } }; -//the old connect method of the pool -//would automatically subscribe to the 'drain' -//event and automatically return the client to -//the pool once 'drain' fired once. This caused -//a bunch of problems, but for backwards compatibility -//we're leaving it in -var alarmDuration = 5000; -var errorMessage = [ - 'A client has been checked out from the pool for longer than ' + alarmDuration + ' ms.', - 'You might have a leak!', - 'You should use the following new way to check out clients','pg.connect(function(err, client, done)) {', - ' //do something', - ' done(); //call done() to signal you are finished with the client', - '}' -].join(require('os').EOL); - -var oldConnect = function(pool, client, cb) { - deprecate('pg.connect(function(err, client) { ...}) is deprecated and will be removed it v1.0.0 (very soon)', - 'instead, use pg.connect(function(err, client, done) { ... })', - 'automatic releasing of clients back to the pool was a mistake and will be removed', - 'please see the following for more details:', - 'https://github.com/brianc/node-postgres/wiki/pg', - 'https://github.com/brianc/node-postgres/issues/227', - 'https://github.com/brianc/node-postgres/pull/274', - 'feel free to get in touch via github if you have questions'); - var tid = setTimeout(function() { - console.error(errorMessage); - }, alarmDuration); - var onError = function() { - clearTimeout(tid); - client.removeListener('drain', release); - }; - var release = function() { - clearTimeout(tid); - pool.release(client); - client.removeListener('error', onError); - }; - client.once('drain', release); - client.once('error', onError); - cb(null, client); -}; - -var newConnect = function(pool, client, cb) { - cb(null, client, function(err) { - if(err) { - pool.destroy(client); - } else { - pool.release(client); - } - }); -}; - module.exports = pools; diff --git a/package.json b/package.json index 7bd1fe23..140fd18c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "0.14.0", + "version": "1.0.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", diff --git a/script/test-connection.js b/script/test-connection.js index 81128610..a70ada39 100644 --- a/script/test-connection.js +++ b/script/test-connection.js @@ -3,7 +3,7 @@ var helper = require(__dirname + '/../test/test-helper'); console.log(); console.log("testing ability to connect to '%j'", helper.config); var pg = require(__dirname + '/../lib'); -pg.connect(helper.config, function(err, client) { +pg.connect(helper.config, function(err, client, done) { if(err !== null) { console.error("Recieved connection error when attempting to contact PostgreSQL:"); console.error(err); @@ -18,6 +18,7 @@ pg.connect(helper.config, function(err, client) { console.error(err); process.exit(255); } + done(); pg.end(); }) }) diff --git a/test/integration/client/api-tests.js b/test/integration/client/api-tests.js index de572d20..c3baca8f 100644 --- a/test/integration/client/api-tests.js +++ b/test/integration/client/api-tests.js @@ -1,9 +1,5 @@ var helper = require(__dirname + '/../test-helper'); -var pg = require(__dirname + '/../../../lib'); - -if(helper.args.native) { - pg = require(__dirname + '/../../../lib').native; -} +var pg = helper.pg; var log = function() { //console.log.apply(console, arguments); @@ -20,8 +16,9 @@ test('api', function() { pg.connect(helper.config, function(err) { assert.isNull(err); arguments[1].emit('drain'); + arguments[2](); }); - pg.connect(helper.config, assert.calls(function(err, client) { + pg.connect(helper.config, assert.calls(function(err, client, done) { assert.equal(err, null, "Failed to connect: " + helper.sys.inspect(err)); client.query('CREATE TEMP TABLE band(name varchar(100))'); @@ -56,14 +53,14 @@ test('api', function() { assert.equal(result.rows.pop().name, 'the flaming lips'); assert.equal(result.rows.pop().name, 'the beach boys'); sink.add(); + done(); })) })) - })) }) test('executing nested queries', function() { - pg.connect(helper.config, assert.calls(function(err, client) { + pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err); log("connected for nested queriese") client.query('select now as now from NOW()', assert.calls(function(err, result) { @@ -73,6 +70,7 @@ test('executing nested queries', function() { log('all nested queries recieved') assert.ok('all queries hit') sink.add(); + done(); })) })) })) @@ -82,27 +80,29 @@ test('executing nested queries', function() { test('raises error if cannot connect', function() { var connectionString = "pg://sfalsdkf:asdf@localhost/ieieie"; log("trying to connect to invalid place for error") - pg.connect(connectionString, assert.calls(function(err, client) { + pg.connect(connectionString, assert.calls(function(err, client, done) { assert.ok(err, 'should have raised an error') log("invalid connection supplied error to callback") sink.add(); + done(); })) }) test("query errors are handled and do not bubble if callback is provded", function() { - pg.connect(helper.config, assert.calls(function(err, client) { + pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err) log("checking for query error") client.query("SELECT OISDJF FROM LEIWLISEJLSE", assert.calls(function(err, result) { assert.ok(err); log("query error supplied error to callback") sink.add(); + done(); })) })) }) test('callback is fired once and only once', function() { - pg.connect(helper.config, assert.calls(function(err, client) { + pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err); client.query("CREATE TEMP TABLE boom(name varchar(10))"); var callCount = 0; @@ -113,12 +113,13 @@ test('callback is fired once and only once', function() { ].join(";"), function(err, callback) { assert.equal(callCount++, 0, "Call count should be 0. More means this callback fired more than once."); sink.add(); + done(); }) })) }) test('can provide callback and config object', function() { - pg.connect(helper.config, assert.calls(function(err, client) { + pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err); client.query({ name: 'boom', @@ -126,12 +127,13 @@ test('can provide callback and config object', function() { }, assert.calls(function(err, result) { assert.isNull(err); assert.equal(result.rows[0].now.getYear(), new Date().getYear()) + done(); })) })) }) test('can provide callback and config and parameters', function() { - pg.connect(helper.config, assert.calls(function(err, client) { + pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err); var config = { text: 'select $1::text as val' @@ -140,12 +142,13 @@ test('can provide callback and config and parameters', function() { assert.isNull(err); assert.equal(result.rows.length, 1); assert.equal(result.rows[0].val, 'hi'); + done(); })) })) }) test('null and undefined are both inserted as NULL', function() { - pg.connect(helper.config, assert.calls(function(err, client) { + pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err); client.query("CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)"); client.query("INSERT INTO my_nulls(a,b,c,d,e,f) VALUES ($1,$2,$3,$4,$5,$6)", [ null, undefined, null, undefined, null, undefined ]); @@ -158,6 +161,7 @@ test('null and undefined are both inserted as NULL', function() { assert.isNull(result.rows[0].d); assert.isNull(result.rows[0].e); assert.isNull(result.rows[0].f); + done(); })) })) }) diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index 074665b6..e01a252c 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -2,7 +2,7 @@ var helper = require(__dirname + "/test-helper"); var pg = helper.pg; test('parsing array results', function() { - pg.connect(helper.config, assert.calls(function(err, client) { + pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[])"); client.query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')').on('error', console.log); @@ -23,7 +23,6 @@ test('parsing array results', function() { assert.equal(names[0], 'aaron'); assert.equal(names[1], 'brian'); assert.equal(names[2], "a b c"); - pg.end(); })) }) @@ -31,7 +30,6 @@ test('parsing array results', function() { client.query("SELECT '{}'::text[] as names", assert.success(function(result) { var names = result.rows[0].names; assert.lengthIs(names, 0); - pg.end(); })) }) @@ -41,7 +39,6 @@ test('parsing array results', function() { assert.lengthIs(names, 2); assert.equal(names[0], 'joe,bob'); assert.equal(names[1], 'jim'); - pg.end(); })) }) @@ -51,7 +48,6 @@ test('parsing array results', function() { assert.lengthIs(names, 2); assert.equal(names[0], '{'); assert.equal(names[1], '}'); - pg.end(); })) }) @@ -63,7 +59,6 @@ test('parsing array results', function() { assert.equal(names[1], null); assert.equal(names[2], 'bob'); assert.equal(names[3], 'NULL'); - pg.end(); })) }) @@ -74,7 +69,6 @@ test('parsing array results', function() { assert.equal(names[0], 'joe\''); assert.equal(names[1], 'jim'); assert.equal(names[2], 'bob"'); - pg.end(); })) }) @@ -91,7 +85,6 @@ test('parsing array results', function() { assert.equal(names[1][0], '2'); assert.equal(names[1][1], 'bob'); - pg.end(); })) }) @@ -102,7 +95,6 @@ test('parsing array results', function() { assert.equal(names[0], 1); assert.equal(names[1], 2); assert.equal(names[2], 3); - pg.end(); })) }) @@ -118,7 +110,6 @@ test('parsing array results', function() { assert.equal(names[2][0], 3); assert.equal(names[2][1], 100); - pg.end(); })) }) @@ -134,6 +125,7 @@ test('parsing array results', function() { assert.equal(names[2][0], 3); assert.equal(names[2][1], 100); + done(); pg.end(); })) }) diff --git a/test/integration/client/copy-tests.js b/test/integration/client/copy-tests.js index d53360bc..98318bc5 100644 --- a/test/integration/client/copy-tests.js +++ b/test/integration/client/copy-tests.js @@ -14,7 +14,7 @@ var prepareTable = function (client, callback) { ); }; test('COPY FROM', function () { - pg.connect(helper.config, function (error, client) { + pg.connect(helper.config, function (error, client, done) { assert.equal(error, null, "Failed to connect: " + helper.sys.inspect(error)); prepareTable(client, function () { var stream = client.copyFrom("COPY copy_test (name, age) FROM stdin WITH CSV"); @@ -30,7 +30,7 @@ test('COPY FROM', function () { assert.lengthIs(result.rows, 1) assert.equal(result.rows[0].sum, ROWS_TO_INSERT * (0 + ROWS_TO_INSERT -1)/2); assert.equal(result.rows[0].count, ROWS_TO_INSERT); - pg.end(helper.config); + done(); }); }, "COPY FROM stream should emit close after query end"); stream.end(); @@ -38,7 +38,7 @@ test('COPY FROM', function () { }); }); test('COPY TO', function () { - pg.connect(helper.config, function (error, client) { + pg.connect(helper.config, function (error, client, done) { assert.equal(error, null, "Failed to connect: " + helper.sys.inspect(error)); prepareTable(client, function () { var stream = client.copyTo("COPY person (id, name, age) TO stdin WITH CSV"); @@ -53,7 +53,7 @@ test('COPY TO', function () { var lines = buf.toString().split('\n'); assert.equal(lines.length >= 0, true, "copy in should return rows saved by copy from"); assert.equal(lines[0].split(',').length, 3, "each line should consists of 3 fields"); - pg.end(helper.config); + done(); }, "COPY IN stream should emit end event after all rows"); }); }); @@ -61,7 +61,7 @@ test('COPY TO', function () { test('COPY TO, queue queries', function () { if(helper.config.native) return false; - pg.connect(helper.config, assert.calls(function (error, client) { + pg.connect(helper.config, assert.calls(function (error, client, done) { assert.equal(error, null, "Failed to connect: " + helper.sys.inspect(error)); prepareTable(client, function () { var query1Done = false, @@ -92,7 +92,7 @@ test('COPY TO, queue queries', function () { var lines = buf.toString().split('\n'); assert.equal(lines.length >= 0, true, "copy in should return rows saved by copy from"); assert.equal(lines[0].split(',').length, 3, "each line should consists of 3 fields"); - pg.end(helper.config); + done(); }, "COPY IN stream should emit end event after all rows"); }); })); @@ -105,7 +105,7 @@ test("COPY TO incorrect usage with large data", function () { //but if there are not so much data, cancel message may be //send after copy query ends //so we need to test both situations - pg.connect(helper.config, assert.calls(function (error, client) { + pg.connect(helper.config, assert.calls(function (error, client, done) { assert.equal(error, null, "Failed to connect: " + helper.sys.inspect(error)); //intentionally incorrect usage of copy. //this has to report error in standart way, instead of just throwing exception @@ -116,7 +116,7 @@ test("COPY TO incorrect usage with large data", function () { client.query("SELECT 1", assert.calls(function (error, result) { assert.isNull(error, "incorrect copy usage should not break connection"); assert.ok(result, "incorrect copy usage should not break connection"); - pg.end(helper.config); + done(); })); }) ); @@ -125,7 +125,7 @@ test("COPY TO incorrect usage with large data", function () { test("COPY TO incorrect usage with small data", function () { if(helper.config.native) return false; - pg.connect(helper.config, assert.calls(function (error, client) { + pg.connect(helper.config, assert.calls(function (error, client, done) { assert.equal(error, null, "Failed to connect: " + helper.sys.inspect(error)); //intentionally incorrect usage of copy. //this has to report error in standart way, instead of just throwing exception @@ -136,7 +136,7 @@ test("COPY TO incorrect usage with small data", function () { client.query("SELECT 1", assert.calls(function (error, result) { assert.isNull(error, "incorrect copy usage should not break connection"); assert.ok(result, "incorrect copy usage should not break connection"); - pg.end(helper.config); + done(); })); }) ); @@ -144,7 +144,7 @@ test("COPY TO incorrect usage with small data", function () { }); test("COPY FROM incorrect usage", function () { - pg.connect(helper.config, function (error, client) { + pg.connect(helper.config, function (error, client, done) { assert.equal(error, null, "Failed to connect: " + helper.sys.inspect(error)); prepareTable(client, function () { //intentionally incorrect usage of copy. @@ -156,6 +156,7 @@ test("COPY FROM incorrect usage", function () { client.query("SELECT 1", assert.calls(function (error, result) { assert.isNull(error, "incorrect copy usage should not break connection"); assert.ok(result, "incorrect copy usage should not break connection"); + done(); pg.end(helper.config); })); }) diff --git a/test/integration/client/drain-tests.js b/test/integration/client/drain-tests.js deleted file mode 100644 index b6a2434d..00000000 --- a/test/integration/client/drain-tests.js +++ /dev/null @@ -1,55 +0,0 @@ -var helper = require(__dirname + '/test-helper'); -var pg = require(__dirname + '/../../../lib'); - -if(helper.args.native) { - pg = require(__dirname + '/../../../lib').native; -} - -var testDrainOfClientWithPendingQueries = function() { - pg.connect(helper.config, assert.success(function(client) { - test('when there are pending queries and client is resumed', function() { - var drainCount = 0; - client.on('drain', function() { - drainCount++; - }); - client.pauseDrain(); - client.query('SELECT NOW()', function() { - client.query('SELECT NOW()', function() { - assert.equal(drainCount, 0); - process.nextTick(function() { - assert.equal(drainCount, 1); - pg.end(); - }); - }); - client.resumeDrain(); - assert.equal(drainCount, 0); - }); - }); - })); -}; - -pg.connect(helper.config, assert.success(function(client) { - var drainCount = 0; - client.on('drain', function() { - drainCount++; - }); - test('pauseDrain and resumeDrain on simple client', function() { - client.pauseDrain(); - client.resumeDrain(); - process.nextTick(assert.calls(function() { - assert.equal(drainCount, 0); - test('drain is paused', function() { - client.pauseDrain(); - client.query('SELECT NOW()', assert.success(function() { - process.nextTick(function() { - assert.equal(drainCount, 0); - client.resumeDrain(); - assert.equal(drainCount, 1); - testDrainOfClientWithPendingQueries(); - }); - })); - }); - })); - }); -})); - diff --git a/test/integration/client/huge-numeric-tests.js b/test/integration/client/huge-numeric-tests.js index b2a89f12..4165711f 100644 --- a/test/integration/client/huge-numeric-tests.js +++ b/test/integration/client/huge-numeric-tests.js @@ -1,6 +1,6 @@ var helper = require(__dirname + '/test-helper'); -helper.pg.connect(helper.config, assert.success(function(client) { +helper.pg.connect(helper.config, assert.success(function(client, done) { var types = require(__dirname + '/../../../lib/types'); //1231 = numericOID types.setTypeParser(1700, function(){ @@ -15,6 +15,7 @@ helper.pg.connect(helper.config, assert.success(function(client) { client.query('SELECT * FROM bignumz', assert.success(function(result) { assert.equal(result.rows[0].id, 'yes') helper.pg.end(); + done(); })) })); diff --git a/test/integration/client/result-metadata-tests.js b/test/integration/client/result-metadata-tests.js index ef8e7d44..98d065ea 100644 --- a/test/integration/client/result-metadata-tests.js +++ b/test/integration/client/result-metadata-tests.js @@ -2,7 +2,7 @@ var helper = require(__dirname + "/test-helper"); var pg = helper.pg; test('should return insert metadata', function() { - pg.connect(helper.config, assert.calls(function(err, client) { + pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err); client.query("CREATE TEMP TABLE zugzug(name varchar(10))", assert.calls(function(err, result) { @@ -25,6 +25,7 @@ test('should return insert metadata', function() { assert.emits(q, 'end', function(result) { assert.equal(result.command, "INSERT"); assert.equal(result.rowCount, 1); + done(); }); })); diff --git a/test/integration/client/transaction-tests.js b/test/integration/client/transaction-tests.js index 4fbfd18b..85ee7e53 100644 --- a/test/integration/client/transaction-tests.js +++ b/test/integration/client/transaction-tests.js @@ -5,8 +5,7 @@ var sink = new helper.Sink(2, function() { }); test('a single connection transaction', function() { - helper.pg.connect(helper.config, assert.calls(function(err, client) { - assert.isNull(err); + helper.pg.connect(helper.config, assert.success(function(client, done) { client.query('begin'); @@ -39,6 +38,7 @@ test('a single connection transaction', function() { client.query(getZed, assert.calls(function(err, result) { assert.isNull(err); assert.empty(result.rows); + done(); sink.add(); })) }) @@ -46,8 +46,7 @@ test('a single connection transaction', function() { }) test('gh#36', function() { - helper.pg.connect(helper.config, function(err, client) { - if(err) throw err; + helper.pg.connect(helper.config, assert.success(function(client, done) { client.query("BEGIN"); client.query({ name: 'X', @@ -67,6 +66,7 @@ test('gh#36', function() { })) client.query("COMMIT", function() { sink.add(); + done(); }) - }) + })); }) diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index fce8ff33..9e675586 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -2,7 +2,7 @@ var helper = require(__dirname + '/test-helper'); var sink; var testForTypeCoercion = function(type){ - helper.pg.connect(helper.config, function(err, client) { + helper.pg.connect(helper.config, function(err, client, done) { assert.isNull(err); client.query("create temp table test_type(col " + type.name + ")", assert.calls(function(err, result) { assert.isNull(err); @@ -31,6 +31,7 @@ var testForTypeCoercion = function(type){ client.query('drop table test_type', function() { sink.add(); + done(); }); }) })); @@ -133,7 +134,7 @@ test("timestampz round trip", function() { client.on('drain', client.end.bind(client)); }); -helper.pg.connect(helper.config, assert.calls(function(err, client) { +helper.pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err); client.query('select null as res;', assert.calls(function(err, res) { assert.isNull(err); @@ -143,6 +144,7 @@ helper.pg.connect(helper.config, assert.calls(function(err, client) { assert.isNull(err); assert.strictEqual(res.rows[0].res, null); sink.add(); + done(); }) })) diff --git a/test/integration/connection-pool/ending-pool-tests.js b/test/integration/connection-pool/ending-pool-tests.js index e46c0fc1..da057a55 100644 --- a/test/integration/connection-pool/ending-pool-tests.js +++ b/test/integration/connection-pool/ending-pool-tests.js @@ -8,12 +8,13 @@ test('disconnects', function() { helper.pg.end(); }); [helper.config, helper.config, helper.config, helper.config].forEach(function(config) { - helper.pg.connect(config, function(err, client) { + helper.pg.connect(config, function(err, client, done) { assert.isNull(err); client.query("SELECT * FROM NOW()", function(err, result) { process.nextTick(function() { assert.equal(called, false, "Should not have disconnected yet") sink.add(); + done(); }) }) }) diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index 11badf04..a4eccde7 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -1,28 +1,35 @@ var helper = require(__dirname + "/../test-helper"); var pg = require(__dirname + "/../../../lib"); -helper.pg = pg; +pg = pg; //first make pool hold 2 clients -helper.pg.defaults.poolSize = 2; +pg.defaults.poolSize = 2; var killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE \'\''; +return console.log('TEMP IGNORE THIS TO GET REST OF SUITE PASSING') //get first client -helper.pg.connect(helper.config, assert.success(function(client) { +pg.connect(helper.config, assert.success(function(client, done) { client.id = 1; - helper.pg.connect(helper.config, assert.success(function(client2) { + pg.connect(helper.config, assert.success(function(client2, done2) { client2.id = 2; + done2(); //subscribe to the pg error event - assert.emits(helper.pg, 'error', function(error, brokenClient) { + assert.emits(pg, 'error', function(error, brokenClient) { assert.ok(error); assert.ok(brokenClient); assert.equal(client.id, brokenClient.id); - helper.pg.end(); + console.log('got pg error') + console.log('calling pg.end()') + //done2(); + pg.end(); }); //kill the connection from client client2.query(killIdleQuery, assert.success(function(res) { //check to make sure client connection actually was killed + console.log('\nkilled query'); assert.lengthIs(res.rows, 1); + done(); })); })); })); diff --git a/test/integration/connection-pool/idle-timeout-tests.js b/test/integration/connection-pool/idle-timeout-tests.js index c6cbbd9f..34a403fa 100644 --- a/test/integration/connection-pool/idle-timeout-tests.js +++ b/test/integration/connection-pool/idle-timeout-tests.js @@ -3,10 +3,11 @@ var helper = require(__dirname + '/test-helper'); helper.pg.defaults.poolIdleTimeout = 200; test('idle timeout', function() { - helper.pg.connect(helper.config, assert.calls(function(err, client) { + helper.pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err); client.query('SELECT NOW()'); //just let this one time out //test will hang if pool doesn't timeout + done(); })); }); diff --git a/test/integration/connection-pool/optional-config-tests.js b/test/integration/connection-pool/optional-config-tests.js index 690be7f2..716d3153 100644 --- a/test/integration/connection-pool/optional-config-tests.js +++ b/test/integration/connection-pool/optional-config-tests.js @@ -8,12 +8,13 @@ helper.pg.defaults.port = helper.args.port; helper.pg.defaults.database = helper.args.database; helper.pg.defaults.poolSize = 1; -helper.pg.connect(assert.calls(function(err, client) { +helper.pg.connect(assert.calls(function(err, client, done) { assert.isNull(err); client.query('SELECT NOW()'); client.once('drain', function() { setTimeout(function() { helper.pg.end(); + done(); }, 10); }); diff --git a/test/test-helper.js b/test/test-helper.js index 398bc861..3a6cf8b7 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -7,8 +7,6 @@ var BufferList = require(__dirname+'/buffer-list') var Connection = require(__dirname + '/../lib/connection'); -require(__dirname + '/../lib').defaults.hideDeprecationWarnings = true; - Client = require(__dirname + '/../lib').Client; process.on('uncaughtException', function(d) { @@ -98,13 +96,25 @@ assert.empty = function(actual) { }; assert.success = function(callback) { - return assert.calls(function(err, arg) { - if(err) { - console.log(err); - } - assert.isNull(err); - callback(arg); - }) + if(callback.length === 1) { + return assert.calls(function(err, arg) { + if(err) { + console.log(err); + } + assert.isNull(err); + callback(arg); + }); + } else if (callback.length === 2) { + return assert.calls(function(err, arg1, arg2) { + if(err) { + console.log(err); + } + assert.isNull(err); + callback(arg1, arg2); + }); + } else { + throw new Error('need to preserve arrity of wrapped function'); + } } assert.throws = function(offender) { @@ -127,13 +137,26 @@ var expect = function(callback, timeout) { assert.ok(executed, "Expected execution of function to be fired"); }, timeout || 5000) - return function(err, queryResult) { - clearTimeout(id); - if (err) { - assert.ok(err instanceof Error, "Expected errors to be instances of Error: " + sys.inspect(err)); + if(callback.length < 3) { + return function(err, queryResult) { + clearTimeout(id); + if (err) { + assert.ok(err instanceof Error, "Expected errors to be instances of Error: " + sys.inspect(err)); + } + callback.apply(this, arguments) } - callback.apply(this, arguments) + } else if(callback.length == 3) { + return function(err, arg1, arg2) { + clearTimeout(id); + if (err) { + assert.ok(err instanceof Error, "Expected errors to be instances of Error: " + sys.inspect(err)); + } + callback.apply(this, arguments) + } + } else { + throw new Error("Unsupported arrity " + callback.length); } + } assert.calls = expect; diff --git a/test/unit/pool/basic-tests.js b/test/unit/pool/basic-tests.js index b96937ee..456f5e9f 100644 --- a/test/unit/pool/basic-tests.js +++ b/test/unit/pool/basic-tests.js @@ -68,19 +68,6 @@ test('pool follows defaults', function() { assert.equal(p.getPoolSize(), defaults.poolSize); }); -test('pool#connect with 2 parameters (legacy, for backwards compat)', function() { - var p = pools.getOrCreate(poolId++); - p.connect(assert.success(function(client) { - assert.ok(client); - assert.equal(p.availableObjectsCount(), 0); - assert.equal(p.getPoolSize(), 1); - client.emit('drain'); - assert.equal(p.availableObjectsCount(), 1); - assert.equal(p.getPoolSize(), 1); - p.destroyAllNow(); - })); -}); - test('pool#connect with 3 parameters', function() { var p = pools.getOrCreate(poolId++); var tid = setTimeout(function() { @@ -88,7 +75,7 @@ test('pool#connect with 3 parameters', function() { }, 100); p.connect(function(err, client, done) { clearTimeout(tid); - assert.equal(err, null); + assert.ifError(err, null); assert.ok(client); assert.equal(p.availableObjectsCount(), 0); assert.equal(p.getPoolSize(), 1); @@ -104,9 +91,9 @@ test('pool#connect with 3 parameters', function() { test('on client error, client is removed from pool', function() { var p = pools.getOrCreate(poolId++); - p.connect(assert.success(function(client) { + p.connect(assert.success(function(client, done) { assert.ok(client); - client.emit('drain'); + done(); assert.equal(p.availableObjectsCount(), 1); assert.equal(p.getPoolSize(), 1); //error event fires on pool BEFORE pool.destroy is called with client From aadb2917cca86abdc092512aee76a8569468f989 Mon Sep 17 00:00:00 2001 From: brianc Date: Thu, 7 Mar 2013 16:09:40 -0600 Subject: [PATCH 02/16] fix broken test --- test/integration/connection-pool/error-tests.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index a4eccde7..e1dd6614 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -7,7 +7,6 @@ pg.defaults.poolSize = 2; var killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE \'\''; -return console.log('TEMP IGNORE THIS TO GET REST OF SUITE PASSING') //get first client pg.connect(helper.config, assert.success(function(client, done) { client.id = 1; @@ -19,17 +18,12 @@ pg.connect(helper.config, assert.success(function(client, done) { assert.ok(error); assert.ok(brokenClient); assert.equal(client.id, brokenClient.id); - console.log('got pg error') - console.log('calling pg.end()') - //done2(); - pg.end(); }); //kill the connection from client client2.query(killIdleQuery, assert.success(function(res) { //check to make sure client connection actually was killed - console.log('\nkilled query'); assert.lengthIs(res.rows, 1); - done(); + pg.end(); })); })); })); From e93a4a5d669212fc51c9aff08f2530958c21a2eb Mon Sep 17 00:00:00 2001 From: brianc Date: Thu, 7 Mar 2013 16:12:09 -0600 Subject: [PATCH 03/16] remove pauseDrain/resumeDrain --- lib/client.js | 34 +-------------- test/unit/client/query-queue-tests.js | 60 --------------------------- 2 files changed, 1 insertion(+), 93 deletions(-) diff --git a/lib/client.js b/lib/client.js index 75c50350..4ab8cb5d 100644 --- a/lib/client.js +++ b/lib/client.js @@ -205,13 +205,7 @@ Client.prototype._pulseQueryQueue = function() { this.activeQuery.submit(this.connection); } else if(this.hasExecuted) { this.activeQuery = null; - //TODO remove pauseDrain for v1.0 - if(this._drainPaused > 0) { - this._drainPaused++; - } - else { - this.emit('drain'); - } + this.emit('drain'); } } }; @@ -255,32 +249,6 @@ Client.prototype.query = function(config, values, callback) { return query; }; -//prevents client from otherwise emitting 'drain' event until 'resumeDrain' is -//called -Client.prototype.pauseDrain = function() { - deprecate('Client.prototype.pauseDrain is deprecated and will be removed it v1.0.0 (very soon)', - 'please see the following for more details:', - 'https://github.com/brianc/node-postgres/wiki/pg', - 'https://github.com/brianc/node-postgres/issues/227', - 'https://github.com/brianc/node-postgres/pull/274', - 'feel free to get in touch via github if you have questions'); - this._drainPaused = 1; -}; - -//resume raising 'drain' event -Client.prototype.resumeDrain = function() { - deprecate('Client.prototype.resumeDrain is deprecated and will be removed it v1.0.0 (very soon)', - 'please see the following for more details:', - 'https://github.com/brianc/node-postgres/wiki/pg', - 'https://github.com/brianc/node-postgres/issues/227', - 'https://github.com/brianc/node-postgres/pull/274', - 'feel free to get in touch via github if you have questions'); - if(this._drainPaused > 1) { - this.emit('drain'); - } - this._drainPaused = 0; -}; - Client.prototype.end = function() { this.connection.end(); }; diff --git a/test/unit/client/query-queue-tests.js b/test/unit/client/query-queue-tests.js index cd87cfe9..62b38bd5 100644 --- a/test/unit/client/query-queue-tests.js +++ b/test/unit/client/query-queue-tests.js @@ -50,63 +50,3 @@ test('drain', function() { }); }); }); - -test('with drain paused', function() { - //mock out a fake connection - var con = new Connection({stream: "NO"}); - con.connect = function() { - con.emit('connect'); - }; - con.query = function() { - }; - - var client = new Client({connection:con}); - - client.connect(); - - var drainCount = 0; - client.on('drain', function() { - drainCount++; - }); - - test('normally unpaused', function() { - con.emit('readyForQuery'); - client.query('boom'); - assert.emits(client, 'drain', function() { - assert.equal(drainCount, 1); - }); - con.emit('readyForQuery'); - }); - - test('pausing', function() { - test('unpaused with no queries in between', function() { - client.pauseDrain(); - client.resumeDrain(); - assert.equal(drainCount, 1); - }); - - test('paused', function() { - test('resumeDrain after empty', function() { - client.pauseDrain(); - client.query('asdf'); - con.emit('readyForQuery'); - assert.equal(drainCount, 1); - client.resumeDrain(); - assert.equal(drainCount, 2); - }); - - test('resumDrain while still pending', function() { - client.pauseDrain(); - client.query('asdf'); - client.query('asdf1'); - con.emit('readyForQuery'); - client.resumeDrain(); - assert.equal(drainCount, 2); - con.emit('readyForQuery'); - assert.equal(drainCount, 3); - }); - - }); - }); - -}); From a5ee3651162e7dd176b0c6d0d0f76f2984c6ca44 Mon Sep 17 00:00:00 2001 From: brianc Date: Thu, 7 Mar 2013 16:19:11 -0600 Subject: [PATCH 04/16] remove parseFloat --- lib/types/textParsers.js | 30 +------------------ .../integration/client/type-coercion-tests.js | 9 +++--- test/unit/client/typed-query-results-tests.js | 6 ++-- 3 files changed, 8 insertions(+), 37 deletions(-) diff --git a/lib/types/textParsers.js b/lib/types/textParsers.js index 77d2a486..c7525e82 100644 --- a/lib/types/textParsers.js +++ b/lib/types/textParsers.js @@ -78,18 +78,8 @@ var parseIntegerArray = function(val) { }; var parseFloatArray = function(val) { - deprecate('parsing and returning floats from PostgreSQL server is deprecated', - 'JavaScript has a hard time with floats and there is precision loss which can cause', - 'unexpected, hard to trace, potentially bad bugs in your program', - 'for more information see the following:', - 'https://github.com/brianc/node-postgres/pull/271', - 'in node-postgres v1.0.0 all floats & decimals will be returned as strings', - 'feel free to get in touch via a github issue if you have any questions'); if(!val) { return null; } - var p = arrayParser.create(val, function(entry){ - if(entry !== null) { - entry = parseFloat(entry, 10); - } + var p = arrayParser.create(val, function(entry) { return entry; }); @@ -171,27 +161,11 @@ var parseInteger = function(val) { return parseInt(val, 10); }; -var parseFloatAndWarn = function(val) { - deprecate('parsing and returning floats from PostgreSQL server is deprecated', - 'JavaScript has a hard time with floats and there is precision loss which can cause', - 'unexpected, hard to trace, potentially bad bugs in your program', - 'for more information see the following:', - 'https://github.com/brianc/node-postgres/pull/271', - 'in node-postgres v1.0.0 all floats & decimals will be returned as strings'); - return parseFloat(val); -}; - var init = function(register) { register(20, parseInteger); register(21, parseInteger); register(23, parseInteger); register(26, parseInteger); - //TODO remove for v1.0 - register(1700, parseFloatAndWarn); - //TODO remove for v1.0 - register(700, parseFloatAndWarn); - //TODO remove for v1.0 - register(701, parseFloatAndWarn); register(16, parseBool); register(1082, parseDate); // date register(1114, parseDate); // timestamp without timezone @@ -199,8 +173,6 @@ var init = function(register) { register(1005, parseIntegerArray); // _int2 register(1007, parseIntegerArray); // _int4 register(1016, parseIntegerArray); // _int8 - register(1021, parseFloatArray); // _float4 - register(1022, parseFloatArray); // _float8 register(1231, parseIntegerArray); // _numeric register(1014, parseStringArray); //char register(1015, parseStringArray); //varchar diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index 9e675586..61204cf0 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -57,15 +57,14 @@ var types = [{ name: 'bool', values: [true, false, null] },{ - //TODO get some actual huge numbers here name: 'numeric', - values: [-12.34, 0, 12.34, null] + values: ['-12.34', '0', '12.34', null] },{ name: 'real', - values: [101.1, 0, -101.3, null] + values: ['101.1', '0', '-101.3', null] },{ name: 'double precision', - values: [-1.2, 0, 1.2, null] + values: ['-1.2', '0', '1.2', null] },{ name: 'timestamptz', values: [null] @@ -83,7 +82,7 @@ var types = [{ // ignore some tests in binary mode if (helper.config.binary) { types = types.filter(function(type) { - return !(type.name in {'real':1, 'timetz':1, 'time':1}); + return !(type.name in {'real':1, 'timetz':1, 'time':1, 'numeric': 1, 'double precision': 1}); }); } diff --git a/test/unit/client/typed-query-results-tests.js b/test/unit/client/typed-query-results-tests.js index 5520245f..eda34fb1 100644 --- a/test/unit/client/typed-query-results-tests.js +++ b/test/unit/client/typed-query-results-tests.js @@ -43,19 +43,19 @@ test('typed results', function() { format: 'text', dataTypeID: 1700, actual: '12.34', - expected: 12.34 + expected: '12.34' },{ name: 'real/float4', dataTypeID: 700, format: 'text', actual: '123.456', - expected: 123.456 + expected: '123.456' },{ name: 'double precision / float8', format: 'text', dataTypeID: 701, actual: '1.2', - expected: 1.2 + expected: '1.2' },{ name: 'boolean true', format: 'text', From cee5f1d8b32e240fd757571f74ecb7f6e30d278e Mon Sep 17 00:00:00 2001 From: brianc Date: Sat, 16 Mar 2013 11:51:26 -0500 Subject: [PATCH 05/16] move buffer-writer to external module --- lib/connection.js | 2 +- lib/writer.js | 128 ------------------------- package.json | 2 +- test/unit/writer-tests.js | 196 -------------------------------------- 4 files changed, 2 insertions(+), 326 deletions(-) delete mode 100644 lib/writer.js delete mode 100644 test/unit/writer-tests.js diff --git a/lib/connection.js b/lib/connection.js index 2f90af74..f8b7f044 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -4,7 +4,7 @@ var EventEmitter = require('events').EventEmitter; var util = require('util'); var utils = require(__dirname + '/utils'); -var Writer = require(__dirname + '/writer'); +var Writer = require('buffer-writer'); var Connection = function(config) { EventEmitter.call(this); diff --git a/lib/writer.js b/lib/writer.js deleted file mode 100644 index 96a5944f..00000000 --- a/lib/writer.js +++ /dev/null @@ -1,128 +0,0 @@ -//binary data writer tuned for creating -//postgres message packets as effeciently as possible by reusing the -//same buffer to avoid memcpy and limit memory allocations -var Writer = function(size) { - this.size = size || 1024; - this.buffer = Buffer(this.size + 5); - this.offset = 5; - this.headerPosition = 0; -}; - -//resizes internal buffer if not enough size left -Writer.prototype._ensure = function(size) { - var remaining = this.buffer.length - this.offset; - if(remaining < size) { - var oldBuffer = this.buffer; - this.buffer = new Buffer(oldBuffer.length + size); - oldBuffer.copy(this.buffer); - } -}; - -Writer.prototype.addInt32 = function(num) { - this._ensure(4); - this.buffer[this.offset++] = (num >>> 24 & 0xFF); - this.buffer[this.offset++] = (num >>> 16 & 0xFF); - this.buffer[this.offset++] = (num >>> 8 & 0xFF); - this.buffer[this.offset++] = (num >>> 0 & 0xFF); - return this; -}; - -Writer.prototype.addInt16 = function(num) { - this._ensure(2); - this.buffer[this.offset++] = (num >>> 8 & 0xFF); - this.buffer[this.offset++] = (num >>> 0 & 0xFF); - return this; -}; - -//for versions of node requiring 'length' as 3rd argument to buffer.write -var writeString = function(buffer, string, offset, len) { - buffer.write(string, offset, len); -}; - -//overwrite function for older versions of node -if(Buffer.prototype.write.length === 3) { - writeString = function(buffer, string, offset, len) { - buffer.write(string, offset); - }; -} - -Writer.prototype.addCString = function(string) { - //just write a 0 for empty or null strings - if(!string) { - this._ensure(1); - } else { - var len = Buffer.byteLength(string); - this._ensure(len + 1); //+1 for null terminator - writeString(this.buffer, string, this.offset, len); - this.offset += len; - } - - this.buffer[this.offset++] = 0; // null terminator - return this; -}; - -Writer.prototype.addChar = function(c) { - this._ensure(1); - writeString(this.buffer, c, this.offset, 1); - this.offset++; - return this; -}; - -Writer.prototype.addString = function(string) { - string = string || ""; - var len = Buffer.byteLength(string); - this._ensure(len); - this.buffer.write(string, this.offset); - this.offset += len; - return this; -}; - -Writer.prototype.getByteLength = function() { - return this.offset - 5; -}; - -Writer.prototype.add = function(otherBuffer) { - this._ensure(otherBuffer.length); - otherBuffer.copy(this.buffer, this.offset); - this.offset += otherBuffer.length; - return this; -}; - -Writer.prototype.clear = function() { - this.offset = 5; - this.headerPosition = 0; - this.lastEnd = 0; -}; - -//appends a header block to all the written data since the last -//subsequent header or to the beginning if there is only one data block -Writer.prototype.addHeader = function(code, last) { - var origOffset = this.offset; - this.offset = this.headerPosition; - this.buffer[this.offset++] = code; - //length is everything in this packet minus the code - this.addInt32(origOffset - (this.headerPosition+1)); - //set next header position - this.headerPosition = origOffset; - //make space for next header - this.offset = origOffset; - if(!last) { - this._ensure(5); - this.offset += 5; - } -}; - -Writer.prototype.join = function(code) { - if(code) { - this.addHeader(code, true); - } - return this.buffer.slice(code ? 0 : 5, this.offset); -}; - -Writer.prototype.flush = function(code) { - var result = this.join(code); - this.clear(); - return result; -}; - -module.exports = Writer; diff --git a/package.json b/package.json index 140fd18c..8d20483e 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "main": "./lib", "dependencies": { "generic-pool": "2.0.2", - "deprecate": "~0.1.0" + "buffer-writer": "1.0.0" }, "devDependencies": { "jshint": "git://github.com/jshint/jshint.git" diff --git a/test/unit/writer-tests.js b/test/unit/writer-tests.js deleted file mode 100644 index e5ade320..00000000 --- a/test/unit/writer-tests.js +++ /dev/null @@ -1,196 +0,0 @@ -require(__dirname + "/test-helper"); -var Writer = require(__dirname + "/../../lib/writer"); - -test('adding int32', function() { - var testAddingInt32 = function(int, expectedBuffer) { - test('writes ' + int, function() { - var subject = new Writer(); - var result = subject.addInt32(int).join(); - assert.equalBuffers(result, expectedBuffer); - }) - } - - testAddingInt32(0, [0, 0, 0, 0]); - testAddingInt32(1, [0, 0, 0, 1]); - testAddingInt32(256, [0, 0, 1, 0]); - test('writes largest int32', function() { - //todo need to find largest int32 when I have internet access - return false; - }) - - test('writing multiple int32s', function() { - var subject = new Writer(); - var result = subject.addInt32(1).addInt32(10).addInt32(0).join(); - assert.equalBuffers(result, [0, 0, 0, 1, 0, 0, 0, 0x0a, 0, 0, 0, 0]); - }) - - test('having to resize the buffer', function() { - test('after resize correct result returned', function() { - var subject = new Writer(10); - subject.addInt32(1).addInt32(1).addInt32(1) - assert.equalBuffers(subject.join(), [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1]) - }) - }) -}) - -test('int16', function() { - test('writes 0', function() { - var subject = new Writer(); - var result = subject.addInt16(0).join(); - assert.equalBuffers(result, [0,0]); - }) - - test('writes 400', function() { - var subject = new Writer(); - var result = subject.addInt16(400).join(); - assert.equalBuffers(result, [1, 0x90]) - }) - - test('writes many', function() { - var subject = new Writer(); - var result = subject.addInt16(0).addInt16(1).addInt16(2).join(); - assert.equalBuffers(result, [0, 0, 0, 1, 0, 2]) - }) - - test('resizes if internal buffer fills up', function() { - var subject = new Writer(3); - var result = subject.addInt16(2).addInt16(3).join(); - assert.equalBuffers(result, [0, 2, 0, 3]) - }) - -}) - -test('cString', function() { - test('writes empty cstring', function() { - var subject = new Writer(); - var result = subject.addCString().join(); - assert.equalBuffers(result, [0]) - }) - - test('writes two empty cstrings', function() { - var subject = new Writer(); - var result = subject.addCString("").addCString("").join(); - assert.equalBuffers(result, [0, 0]) - }) - - - test('writes non-empty cstring', function() { - var subject = new Writer(); - var result = subject.addCString("!!!").join(); - assert.equalBuffers(result, [33, 33, 33, 0]); - }) - - test('resizes if reached end', function() { - var subject = new Writer(3); - var result = subject.addCString("!!!").join(); - assert.equalBuffers(result, [33, 33, 33, 0]); - }) - - test('writes multiple cstrings', function() { - var subject = new Writer(); - var result = subject.addCString("!").addCString("!").join(); - assert.equalBuffers(result, [33, 0, 33, 0]); - }) - -}) - -test('writes char', function() { - var subject = new Writer(2); - var result = subject.addChar('a').addChar('b').addChar('c').join(); - assert.equalBuffers(result, [0x61, 0x62, 0x63]) -}) - -test('gets correct byte length', function() { - var subject = new Writer(5); - assert.equal(subject.getByteLength(), 0) - subject.addInt32(0) - assert.equal(subject.getByteLength(), 4) - subject.addCString("!") - assert.equal(subject.getByteLength(), 6) -}) - -test('can add arbitrary buffer to the end', function() { - var subject = new Writer(4); - subject.addCString("!!!") - var result = subject.add(Buffer("@@@")).join(); - assert.equalBuffers(result, [33, 33, 33, 0, 0x40, 0x40, 0x40]); -}) - -test('can write normal string', function() { - var subject = new Writer(4); - var result = subject.addString("!").join(); - assert.equalBuffers(result, [33]); - test('can write cString too', function() { - var result = subject.addCString("!").join(); - assert.equalBuffers(result, [33, 33, 0]); - test('can resize', function() { - var result = subject.addString("!!").join(); - assert.equalBuffers(result, [33, 33, 0, 33, 33]); - }) - - }) - -}) - - -test('clearing', function() { - var subject = new Writer(); - subject.addCString("@!!#!#"); - subject.addInt32(10401); - subject.clear(); - assert.equalBuffers(subject.join(), []); - test('can keep writing', function() { - var joinedResult = subject.addCString("!").addInt32(9).addInt16(2).join(); - assert.equalBuffers(joinedResult, [33, 0, 0, 0, 0, 9, 0, 2]); - test('flush', function() { - var flushedResult = subject.flush(); - test('returns result', function() { - assert.equalBuffers(flushedResult, [33, 0, 0, 0, 0, 9, 0, 2]) - }) - test('clears the writer', function() { - assert.equalBuffers(subject.join(), []) - assert.equalBuffers(subject.flush(), []) - }) - }) - }) - -}) - -test("resizing to much larger", function() { - var subject = new Writer(2); - var string = "!!!!!!!!"; - var result = subject.addCString(string).flush(); - assert.equalBuffers(result, [33, 33, 33, 33, 33, 33, 33, 33, 0]) -}) - -test("flush", function() { - test('added as a hex code to a full writer', function() { - var subject = new Writer(2); - var result = subject.addCString("!").flush(0x50) - assert.equalBuffers(result, [0x50, 0, 0, 0, 6, 33, 0]); - }) - - test('added as a hex code to a non-full writer', function() { - var subject = new Writer(10).addCString("!"); - var joinedResult = subject.join(0x50); - var result = subject.flush(0x50); - assert.equalBuffers(result, [0x50, 0, 0, 0, 6, 33, 0]); - }) - - test('added as a hex code to a buffer which requires resizing', function() { - var result = new Writer(2).addCString("!!!!!!!!").flush(0x50); - assert.equalBuffers(result, [0x50, 0, 0, 0, 0x0D, 33, 33, 33, 33, 33, 33, 33, 33, 0]); - }) -}) - -test("header", function() { - test('adding two packets with headers', function() { - var subject = new Writer(10).addCString("!"); - subject.addHeader(0x50); - subject.addCString("!!"); - subject.addHeader(0x40); - subject.addCString("!"); - var result = subject.flush(0x10); - assert.equalBuffers(result, [0x50, 0, 0, 0, 6, 33, 0, 0x40, 0, 0, 0, 7, 33, 33, 0, 0x10, 0, 0, 0, 6, 33, 0 ]); - }) -}) From 1d6541724e3e0b2faa2a4e24e1292786de26936c Mon Sep 17 00:00:00 2001 From: brianc Date: Sun, 17 Mar 2013 14:51:57 -0500 Subject: [PATCH 06/16] remove deprecation warnings & deprecate lib --- lib/client.js | 2 -- lib/defaults.js | 9 --------- lib/deprecate.js | 25 ------------------------- lib/pool.js | 2 -- lib/types/binaryParsers.js | 8 -------- lib/types/textParsers.js | 2 -- 6 files changed, 48 deletions(-) delete mode 100644 lib/deprecate.js diff --git a/lib/client.js b/lib/client.js index 4ab8cb5d..d21da7ba 100644 --- a/lib/client.js +++ b/lib/client.js @@ -10,8 +10,6 @@ var Connection = require(__dirname + '/connection'); var CopyFromStream = require(__dirname + '/copystream').CopyFromStream; var CopyToStream = require(__dirname + '/copystream').CopyToStream; -var deprecate = require('deprecate'); - var Client = function(config) { EventEmitter.call(this); diff --git a/lib/defaults.js b/lib/defaults.js index 9f3cbb98..738908ee 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -33,12 +33,3 @@ module.exports = { //pool log function / boolean poolLog: false }; - -var deprecate = require('deprecate'); -//getter/setter to disable deprecation warnings -module.exports.__defineGetter__("hideDeprecationWarnings", function() { - return deprecate.silent; -}); -module.exports.__defineSetter__("hideDeprecationWarnings", function(val) { - deprecate.silence = val; -}); diff --git a/lib/deprecate.js b/lib/deprecate.js deleted file mode 100644 index c5876231..00000000 --- a/lib/deprecate.js +++ /dev/null @@ -1,25 +0,0 @@ -var os = require('os'); -var defaults = require(__dirname + '/defaults'); - -var hits = { -}; -var deprecate = module.exports = function(methodName, message) { - if(defaults.hideDeprecationWarnings) return; - if(hits[deprecate.caller]) return; - hits[deprecate.caller] = true; - process.stderr.write(os.EOL); - process.stderr.write('\x1b[31;1m'); - process.stderr.write('WARNING!!'); - process.stderr.write(os.EOL); - process.stderr.write(methodName); - process.stderr.write(os.EOL); - for(var i = 1; i < arguments.length; i++) { - process.stderr.write(arguments[i]); - process.stderr.write(os.EOL); - } - process.stderr.write('\x1b[0m'); - process.stderr.write(os.EOL); - process.stderr.write("You can silence these warnings with `require('pg').defaults.hideDeprecationWarnings = true`"); - process.stderr.write(os.EOL); - process.stderr.write(os.EOL); -}; diff --git a/lib/pool.js b/lib/pool.js index 1600ba7c..9cf9aabf 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -3,8 +3,6 @@ var EventEmitter = require('events').EventEmitter; var defaults = require(__dirname + '/defaults'); var genericPool = require('generic-pool'); -var deprecate = require('deprecate'); - var pools = { //dictionary of all key:pool pairs all: {}, diff --git a/lib/types/binaryParsers.js b/lib/types/binaryParsers.js index b1bfdd3a..7f0a89c6 100644 --- a/lib/types/binaryParsers.js +++ b/lib/types/binaryParsers.js @@ -1,5 +1,3 @@ -var deprecate = require('deprecate'); - var parseBits = function(data, bits, offset, invert, callback) { offset = offset || 0; invert = invert || false; @@ -47,12 +45,6 @@ var parseBits = function(data, bits, offset, invert, callback) { }; var parseFloatFromBits = function(data, precisionBits, exponentBits) { - deprecate('parsing and returning floats from PostgreSQL server is deprecated', - 'JavaScript has a hard time with floats and there is precision loss which can cause', - 'unexpected, hard to trace, potentially bad bugs in your program', - 'for more information see the following:', - 'https://github.com/brianc/node-postgres/pull/271', - 'in node-postgres v1.0.0 all floats & decimals will be returned as strings'); var bias = Math.pow(2, exponentBits - 1) - 1; var sign = parseBits(data, 1); var exponent = parseBits(data, exponentBits, 1); diff --git a/lib/types/textParsers.js b/lib/types/textParsers.js index c7525e82..61008b57 100644 --- a/lib/types/textParsers.js +++ b/lib/types/textParsers.js @@ -1,5 +1,3 @@ -var deprecate = require('deprecate'); - var arrayParser = require(__dirname + "/arrayParser.js"); //parses PostgreSQL server formatted date strings into javascript date objects From 683d636501cff130ed76cea7c092431115bcafe1 Mon Sep 17 00:00:00 2001 From: brianc Date: Thu, 28 Mar 2013 13:24:33 -0500 Subject: [PATCH 07/16] better handling of client stream termination 1. Pass an error to an active query if the client is ended while a query is in progress. 2. actually emit 'end' event on the client when the stream ends 3. do not emit an error from native bindings if lasterror is null --- lib/client.js | 9 +++ lib/connection.js | 4 ++ lib/native/index.js | 9 +++ src/binding.cc | 29 +++++++-- .../client/error-handling-tests.js | 12 +++- .../client/query-error-handling-tests.js | 24 +++++++ test/native/error-tests.js | 62 +++++++++++-------- ...tream-and-query-error-interaction-tests.js | 26 ++++++++ 8 files changed, 142 insertions(+), 33 deletions(-) create mode 100644 test/integration/client/query-error-handling-tests.js create mode 100644 test/unit/client/stream-and-query-error-interaction-tests.js diff --git a/lib/client.js b/lib/client.js index 75c50350..33f761be 100644 --- a/lib/client.js +++ b/lib/client.js @@ -171,6 +171,15 @@ Client.prototype.connect = function(callback) { } }); + con.once('end', function() { + if(self.activeQuery) { + self.activeQuery.handleError(new Error('Stream unexpectedly ended during query execution')); + self.activeQuery = null; + } + self.emit('end'); + }); + + con.on('notice', function(msg) { self.emit('notice', msg); }); diff --git a/lib/connection.js b/lib/connection.js index 2f90af74..2f79016c 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -40,6 +40,10 @@ Connection.prototype.connect = function(port, host) { self.emit('error', error); }); + this.stream.on('end', function() { + self.emit('end'); + }); + if(this.ssl) { this.stream.once('data', function(buffer) { self.setBuffer(buffer); diff --git a/lib/native/index.js b/lib/native/index.js index 2918689e..7ddc978d 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -198,6 +198,15 @@ var clientBuilder = function(config) { } }); + connection.on('_end', function() { + process.nextTick(function() { + if(connection._activeQuery) { + connection._activeQuery.handleError(new Error("Connection was ended during query")); + } + connection.emit('end'); + }); + }); + connection.on('_readyForQuery', function() { var q = this._activeQuery; //a named query finished being prepared diff --git a/src/binding.cc b/src/binding.cc index a2d2d27d..e0b087e0 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -6,7 +6,7 @@ #include #define LOG(msg) printf("%s\n",msg); -#define TRACE(msg) //printf("%s\n", msg); +#define TRACE(msg) //printf(%s\n, msg); #define THROW(msg) return ThrowException(Exception::Error(String::New(msg))); @@ -434,12 +434,15 @@ protected: if(revents & UV_READABLE) { TRACE("revents & UV_READABLE"); + TRACE("about to consume input"); if(PQconsumeInput(connection_) == 0) { + TRACE("could not read, terminating"); End(); EmitLastError(); //LOG("Something happened, consume input is 0"); return; } + TRACE("Consumed"); //declare handlescope as this method is entered via a libuv callback //and not part of the public v8 interface @@ -450,8 +453,11 @@ protected: if (!this->copyInMode_ && !this->copyOutMode_ && PQisBusy(connection_) == 0) { PGresult *result; bool didHandleResult = false; + TRACE("PQgetResult"); while ((result = PQgetResult(connection_))) { + TRACE("HandleResult"); didHandleResult = HandleResult(result); + TRACE("PQClear"); PQclear(result); if(!didHandleResult) { //this means that we are in copy in or copy out mode @@ -469,6 +475,7 @@ protected: } PGnotify *notify; + TRACE("PQnotifies"); while ((notify = PQnotifies(connection_))) { Local result = Object::New(); result->Set(channel_symbol, String::New(notify->relname)); @@ -515,6 +522,7 @@ protected: } bool HandleResult(PGresult* result) { + TRACE("PQresultStatus"); ExecStatusType status = PQresultStatus(result); switch(status) { case PGRES_TUPLES_OK: @@ -526,6 +534,7 @@ protected: break; case PGRES_FATAL_ERROR: { + TRACE("HandleErrorResult"); HandleErrorResult(result); return true; } @@ -610,8 +619,15 @@ protected: { HandleScope scope; //instantiate the return object as an Error with the summary Postgres message - Local msg = Local::Cast(Exception::Error(String::New(PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY)))); - + TRACE("ReadResultField"); + const char* errorMessage = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY); + if(!errorMessage) { + //there is no error, it has already been consumed in the last + //read-loop callback + return; + } + Local msg = Local::Cast(Exception::Error(String::New(errorMessage))); + TRACE("AttachErrorFields"); //add the other information returned by Postgres to the error object AttachErrorField(result, msg, severity_symbol, PG_DIAG_SEVERITY); AttachErrorField(result, msg, code_symbol, PG_DIAG_SQLSTATE); @@ -625,6 +641,7 @@ protected: AttachErrorField(result, msg, line_symbol, PG_DIAG_SOURCE_LINE); AttachErrorField(result, msg, routine_symbol, PG_DIAG_SOURCE_FUNCTION); Handle m = msg; + TRACE("EmitError"); Emit("_error", &m); } @@ -638,9 +655,11 @@ protected: void End() { + TRACE("stopping read & write"); StopRead(); StopWrite(); DestroyConnection(); + Emit("_end"); } private: @@ -719,7 +738,7 @@ private: void StopWrite() { TRACE("write STOP"); - if(ioInitialized_) { + if(ioInitialized_ && writing_) { uv_poll_stop(&write_watcher_); writing_ = false; } @@ -739,7 +758,7 @@ private: void StopRead() { TRACE("read STOP"); - if(ioInitialized_) { + if(ioInitialized_ && reading_) { uv_poll_stop(&read_watcher_); reading_ = false; } diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index b35588c5..1f02597f 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -158,6 +158,16 @@ test('multiple connection errors (gh#31)', function() { var badConString = "tcp://aslkdfj:oi14081@"+helper.args.host+":"+helper.args.port+"/"+helper.args.database; return false; }); - +}); + +test('query receives error on client shutdown', function() { + var client = new Client(helper.config); + client.connect(assert.calls(function() { + client.query('SELECT pg_sleep(5)', assert.calls(function(err, res) { + assert(err); + })); + client.end(); + assert.emits(client, 'end'); + })); }); diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js new file mode 100644 index 00000000..5df23117 --- /dev/null +++ b/test/integration/client/query-error-handling-tests.js @@ -0,0 +1,24 @@ +var helper = require(__dirname + '/test-helper'); +var util = require('util'); + +test('error during query execution', function() { + var client = new Client(); + client.connect(assert.success(function() { + var sleepQuery = 'select pg_sleep(5)'; + client.query(sleepQuery, assert.calls(function(err, result) { + assert(err); + client.end(); + assert.emits(client, 'end'); + })); + var client2 = new Client(); + client2.connect(assert.success(function() { +var killIdleQuery = "SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query = $1"; + client2.query(killIdleQuery, [sleepQuery], assert.calls(function(err, res) { + assert.ifError(err); + assert.equal(res.rowCount, 1); + client2.end(); + assert.emits(client2, 'end'); + })); + })); + })); +}); diff --git a/test/native/error-tests.js b/test/native/error-tests.js index 3184df57..3a932705 100644 --- a/test/native/error-tests.js +++ b/test/native/error-tests.js @@ -5,26 +5,30 @@ test('query with non-text as first parameter throws error', function() { var client = new Client(helper.config); client.connect(); assert.emits(client, 'connect', function() { - assert.throws(function() { - client.query({text:{fail: true}}); - }) client.end(); - }) -}) + assert.emits(client, 'end', function() { + assert.throws(function() { + client.query({text:{fail: true}}); + }); + }); + }); +}); test('parameterized query with non-text as first parameter throws error', function() { var client = new Client(helper.config); client.connect(); assert.emits(client, 'connect', function() { - assert.throws(function() { - client.query({ - text: {fail: true}, - values: [1, 2] - }) - }) client.end(); - }) -}) + assert.emits(client, 'end', function() { + assert.throws(function() { + client.query({ + text: {fail: true}, + values: [1, 2] + }) + }); + }); + }); +}); var connect = function(callback) { var client = new Client(helper.config); @@ -37,24 +41,28 @@ var connect = function(callback) { test('parameterized query with non-array for second value', function() { test('inline', function() { connect(function(client) { - assert.throws(function() { - client.query("SELECT *", "LKSDJF") - }) client.end(); - }) - }) + assert.emits(client, 'end', function() { + assert.throws(function() { + client.query("SELECT *", "LKSDJF") + }); + }); + }); + }); test('config', function() { connect(function(client) { - assert.throws(function() { - client.query({ - text: "SELECT *", - values: "ALSDKFJ" - }) - }) client.end(); - }) - }) -}) + assert.emits(client, 'end', function() { + assert.throws(function() { + client.query({ + text: "SELECT *", + values: "ALSDKFJ" + }); + }); + }); + }); + }); +}); diff --git a/test/unit/client/stream-and-query-error-interaction-tests.js b/test/unit/client/stream-and-query-error-interaction-tests.js new file mode 100644 index 00000000..9b02caf8 --- /dev/null +++ b/test/unit/client/stream-and-query-error-interaction-tests.js @@ -0,0 +1,26 @@ +var helper = require(__dirname + '/test-helper'); +var Connection = require(__dirname + '/../../../lib/connection'); +var Client = require(__dirname + '/../../../lib/client'); + +test('emits end when not in query', function() { + var stream = new (require('events').EventEmitter)(); + stream.write = function() { + //NOOP + } + var client = new Client({connection: new Connection({stream: stream})}); + client.connect(assert.calls(function() { + client.query('SELECT NOW()', assert.calls(function(err, result) { + assert(err); + })); + })); + assert.emits(client, 'end'); + client.connection.emit('connect'); + process.nextTick(function() { + client.connection.emit('readyForQuery'); + assert.equal(client.queryQueue.length, 0); + assert(client.activeQuery, 'client should have issued query'); + process.nextTick(function() { + stream.emit('end'); + }); + }); +}); From 301f076f01d6a01b7f40708b83399e4a86104143 Mon Sep 17 00:00:00 2001 From: brianc Date: Thu, 28 Mar 2013 13:37:08 -0500 Subject: [PATCH 08/16] pin jshint version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 556333bc..2605b581 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "deprecate": "~0.1.0" }, "devDependencies": { - "jshint": "git://github.com/jshint/jshint.git" + "jshint": "1.1.0" }, "scripts": { "test": "make test-all connectionString=pg://postgres@localhost:5432/postgres", From 07a049df962747b60cbd9d89ddd1f5fb3f7fa1ff Mon Sep 17 00:00:00 2001 From: brianc Date: Thu, 28 Mar 2013 15:06:34 -0500 Subject: [PATCH 09/16] use supplied connection params in new tests --- test/integration/client/query-error-handling-tests.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index 5df23117..cef84060 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -2,7 +2,7 @@ var helper = require(__dirname + '/test-helper'); var util = require('util'); test('error during query execution', function() { - var client = new Client(); + var client = new Client(helper.args); client.connect(assert.success(function() { var sleepQuery = 'select pg_sleep(5)'; client.query(sleepQuery, assert.calls(function(err, result) { @@ -10,7 +10,7 @@ test('error during query execution', function() { client.end(); assert.emits(client, 'end'); })); - var client2 = new Client(); + var client2 = new Client(helper.args); client2.connect(assert.success(function() { var killIdleQuery = "SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query = $1"; client2.query(killIdleQuery, [sleepQuery], assert.calls(function(err, res) { From 95b1c75cfe85da3c34ebf7091555bb623077e148 Mon Sep 17 00:00:00 2001 From: brianc Date: Thu, 28 Mar 2013 15:35:59 -0500 Subject: [PATCH 10/16] version bump --- NEWS.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index c3926f31..72bf8ad4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,10 @@ - Client#pauseDrain() / Client#resumeDrain removed - numeric, decimal, and float data types no longer parsed into float before being returned. Will be returned from query results as `String` +### v0.15.0 + +- client now emits `end` when disconnected from back-end server +- if client is disconnected in the middle of a query, query receives an error ### v0.14.0 diff --git a/package.json b/package.json index 2605b581..93cf91f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "0.14.1", + "version": "0.15.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 6e3cc794c381a24a2c6d8695aebf23c046b79af9 Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 29 Mar 2013 09:38:49 -0500 Subject: [PATCH 11/16] ignore socket hangup. fixes #314 --- lib/connection.js | 7 +++++++ test/unit/connection/error-tests.js | 22 +++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/connection.js b/lib/connection.js index 2f79016c..3c0a067a 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -18,6 +18,7 @@ var Connection = function(config) { this.parsedStatements = {}; this.writer = new Writer(); this.ssl = config.ssl || false; + this._ending = false; }; util.inherits(Connection, EventEmitter); @@ -37,6 +38,11 @@ Connection.prototype.connect = function(port, host) { }); this.stream.on('error', function(error) { + //don't raise ECONNRESET errors - they can & should be ignored + //during disconnect + if(self._ending && error.code == 'ECONNRESET') { + return; + } self.emit('error', error); }); @@ -263,6 +269,7 @@ Connection.prototype.end = function() { //0x58 = 'X' this.writer.add(emptyBuffer); this._send(0x58); + this._ending = true; }; Connection.prototype.describe = function(msg, more) { diff --git a/test/unit/connection/error-tests.js b/test/unit/connection/error-tests.js index bccffac4..98eb20a8 100644 --- a/test/unit/connection/error-tests.js +++ b/test/unit/connection/error-tests.js @@ -1,10 +1,30 @@ var helper = require(__dirname + '/test-helper'); var Connection = require(__dirname + '/../../../lib/connection'); -var con = new Connection({stream: new MemoryStream()}); test("connection emits stream errors", function() { + var con = new Connection({stream: new MemoryStream()}); assert.emits(con, 'error', function(err) { assert.equal(err.message, "OMG!"); }); con.connect(); con.stream.emit('error', new Error("OMG!")); }); + +test('connection emits ECONNRESET errors during normal operation', function() { + var con = new Connection({stream: new MemoryStream()}); + con.connect(); + assert.emits(con, 'error', function(err) { + assert.equal(err.code, 'ECONNRESET'); + }); + var e = new Error('Connection Reset'); + e.code = 'ECONNRESET'; + con.stream.emit('error', e); +}); + +test('connection does not emit ECONNRESET errors during disconnect', function() { + var con = new Connection({stream: new MemoryStream()}); + con.connect(); + var e = new Error('Connection Reset'); + e.code = 'ECONNRESET'; + con.end(); + con.stream.emit('error', e); +}); From 3b2f4134b281bffc8a316dbd6c71b7d54c0b86ac Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 29 Mar 2013 10:39:05 -0500 Subject: [PATCH 12/16] version bump --- NEWS.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 72bf8ad4..2a55d3f6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,9 @@ +All major and minor releases are briefly explained below. + +For richer information consult the commit log on github with referenced pull requests. + +We do not include break-fix version release in this file. + ### v1.0 - not released yet - remove deprecated functionality diff --git a/package.json b/package.json index 93cf91f6..1d04852d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "0.15.0", + "version": "0.15.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 173f3f37b24539950f407b04a7ef9053439b037e Mon Sep 17 00:00:00 2001 From: bmc Date: Thu, 4 Apr 2013 11:45:41 -0500 Subject: [PATCH 13/16] fix end race in test --- test/integration/client/query-error-handling-tests.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index cef84060..068173ca 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -8,7 +8,6 @@ test('error during query execution', function() { client.query(sleepQuery, assert.calls(function(err, result) { assert(err); client.end(); - assert.emits(client, 'end'); })); var client2 = new Client(helper.args); client2.connect(assert.success(function() { From 21ca91d8019c7fea9522d861c66dc2695fac1b63 Mon Sep 17 00:00:00 2001 From: bmc Date: Thu, 4 Apr 2013 11:54:31 -0500 Subject: [PATCH 14/16] allow assert.success to accept 0 arity callback --- test/test-helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-helper.js b/test/test-helper.js index 3a6cf8b7..8d854b81 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -96,7 +96,7 @@ assert.empty = function(actual) { }; assert.success = function(callback) { - if(callback.length === 1) { + if(callback.length === 1 || callback.length === 0) { return assert.calls(function(err, arg) { if(err) { console.log(err); From 23be617f3adab2c430e40c9c27fbb9432f5dba25 Mon Sep 17 00:00:00 2001 From: bmc Date: Thu, 4 Apr 2013 11:58:38 -0500 Subject: [PATCH 15/16] fix missed merge conflict --- package.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/package.json b/package.json index 4305926c..151e33f4 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,6 @@ { "name": "pg", -<<<<<<< HEAD - "version": "0.15.1", -======= "version": "1.0.0", ->>>>>>> v1.0 "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From f98bbed610075a2f86f2b71d3ab1edd2d51d37b0 Mon Sep 17 00:00:00 2001 From: bmc Date: Thu, 4 Apr 2013 12:02:11 -0500 Subject: [PATCH 16/16] update news file --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 2a55d3f6..82e410fd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,7 +4,7 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. -### v1.0 - not released yet +### v1.0 - remove deprecated functionality - `pg.connect` now __requires__ 3 arguments