diff --git a/lib/client.js b/lib/client.js index 3eee5402..22026c1f 100644 --- a/lib/client.js +++ b/lib/client.js @@ -354,29 +354,25 @@ Client.prototype._pulseQueryQueue = function () { } }; -Client.prototype.copyFrom = function (text) { - throw new Error("For PostgreSQL COPY TO/COPY FROM support npm install pg-copy-streams"); -}; - -Client.prototype.copyTo = function (text) { - throw new Error("For PostgreSQL COPY TO/COPY FROM support npm install pg-copy-streams"); -}; - -const DeprecatedQuery = require('./utils').deprecateEventEmitter(Query) - Client.prototype.query = function (config, values, callback) { //can take in strings, config object or query object var query; var result; if (typeof config.submit == 'function') { - query = config - result = query + result = query = config if (typeof values == 'function') { query.callback = query.callback || values } } else { - query = new DeprecatedQuery(config, values, callback) - result = query + query = new Query(config, values, callback) + if (!query.callback) { + let resolve, reject; + result = new Promise((res, rej) => { + resolve = res + reject = rej + }) + query.callback = (err, res) => err ? reject(err) : resolve(res) + } } if (this.binary && !query.binary) { diff --git a/test/integration/client/api-tests.js b/test/integration/client/api-tests.js index f8f78f19..5f999482 100644 --- a/test/integration/client/api-tests.js +++ b/test/integration/client/api-tests.js @@ -1,173 +1,207 @@ -var helper = require(__dirname + '/../test-helper'); +var helper = require(__dirname + "/../test-helper"); var pg = helper.pg; -var log = function() { - //console.log.apply(console, arguments); -} +var suite = new helper.Suite(); -var sink = new helper.Sink(5, 10000, function() { - log("ending connection pool: %j", helper.config); - pg.end(helper.config); +suite.test("pool callback behavior", done => { + //test weird callback behavior with node-pool + const pool = new pg.Pool(); + pool.connect(function(err) { + assert.isNull(err); + arguments[1].emit("drain"); + arguments[2](); + pool.end(done); + }); }); -test('api', function() { - log("connecting to %j", helper.config) - //test weird callback behavior with node-pool - pg.connect(helper.config, function(err) { - assert.isNull(err); - arguments[1].emit('drain'); - arguments[2](); - }); - pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.equal(err, null, "Failed to connect: " + helper.sys.inspect(err)); +suite.test("callback API", done => { + const client = new helper.Client(); + client.query("CREATE TEMP TABLE peep(name text)"); + client.query("INSERT INTO peep(name) VALUES ($1)", ["brianc"]); + const config = { + text: "INSERT INTO peep(name) VALUES ($1)", + values: ["brian"] + }; + client.query(config); + client.query("INSERT INTO peep(name) VALUES ($1)", ["aaron"]); - if (helper.args.native) { - assert(client.native) - } else { - assert(!client.native) - } - - 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) { - var query = client.query("INSERT INTO band (name) VALUES ('"+ bandName +"')") - }); - - - test('simple query execution',assert.calls( function() { - log("executing simple query") - client.query("SELECT * FROM band WHERE name = 'the beach boys'", assert.calls(function(err, result) { - assert.lengthIs(result.rows, 1) - assert.equal(result.rows.pop().name, 'the beach boys') - log("simple query executed") - })); - - })) - - test('prepared statement execution',assert.calls( function() { - log("executing prepared statement 1") - client.query('SELECT * FROM band WHERE name = $1', ['dead black hearts'],assert.calls( function(err, result) { - log("Prepared statement 1 finished") - assert.lengthIs(result.rows, 1); - assert.equal(result.rows.pop().name, 'dead black hearts'); - })) - - log("executing prepared statement two") - client.query('SELECT * FROM band WHERE name LIKE $1 ORDER BY name', ['the %'], assert.calls(function(err, result) { - log("prepared statement two finished") - assert.lengthIs(result.rows, 2); - 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, done) { - assert.isNull(err); - log("connected for nested queriese") - 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() { - log('all nested queries recieved') - assert.ok('all queries hit') - sink.add(); - done(); - })) - })) - })) - })) -}) - -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, done) { - assert.ok(err, 'should have raised an error') - log("invalid connection supplied error to callback") - sink.add(); + client.query("SELECT * FROM peep ORDER BY name", (err, res) => { + assert(!err); + assert.equal(res.rowCount, 3); + assert.deepEqual(res.rows, [ + { + name: "aaron" + }, + { + name: "brian" + }, + { + name: "brianc" + } + ]); done(); - })) -}) + }); + client.connect(err => { + assert(!err); + client.once("drain", () => client.end()); + }); +}); -test("query errors are handled and do not bubble if callback is provded", function() { - 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(); - })) - })) -}) +suite.test("executing nested queries", function(done) { + const pool = new pg.Pool(); + pool.connect( + assert.calls(function(err, client, release) { + assert.isNull(err); + 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"); + release(); + pool.end(done); + }) + ); + }) + ); + }) + ); + }) + ); +}); -test('callback is fired once and only once', function() { - 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; - client.query([ - "INSERT INTO boom(name) VALUES('hai')", - "INSERT INTO boom(name) VALUES('boom')", - "INSERT INTO boom(name) VALUES('zoom')", - ].join(";"), function(err, callback) { - assert.equal(callCount++, 0, "Call count should be 0. More means this callback fired more than once."); - sink.add(); +suite.test("raises error if cannot connect", function() { + var connectionString = "pg://sfalsdkf:asdf@localhost/ieieie"; + const pool = new pg.Pool({ connectionString: connectionString }); + pool.connect( + assert.calls(function(err, client, done) { + assert.ok(err, "should have raised an error"); done(); }) - })) -}) + ); +}); -test('can provide callback and config object', function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.isNull(err); - client.query({ - name: 'boom', - text: 'select NOW()' - }, 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, done) { - assert.isNull(err); - var config = { - text: 'select $1::text as val' - }; - client.query(config, ['hi'], assert.calls(function(err, result) { - 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, 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 ]); - client.query("SELECT * FROM my_nulls", assert.calls(function(err, result) { +suite.test("query errors are handled and do not bubble if callback is provded", function(done) { + const pool = new pg.Pool(); + pool.connect( + assert.calls(function(err, client, release) { assert.isNull(err); - assert.equal(result.rows.length, 1); - assert.isNull(result.rows[0].a); - assert.isNull(result.rows[0].b); - assert.isNull(result.rows[0].c); - assert.isNull(result.rows[0].d); - assert.isNull(result.rows[0].e); - assert.isNull(result.rows[0].f); - done(); - })) - })) -}) + client.query( + "SELECT OISDJF FROM LEIWLISEJLSE", + assert.calls(function(err, result) { + assert.ok(err); + release() + pool.end(done) + }) + ); + }) + ); + } +); + +suite.test("callback is fired once and only once", function(done) { + const pool = new pg.Pool() + pool.connect( + assert.calls(function(err, client, release) { + assert.isNull(err); + client.query("CREATE TEMP TABLE boom(name varchar(10))"); + var callCount = 0; + client.query( + [ + "INSERT INTO boom(name) VALUES('hai')", + "INSERT INTO boom(name) VALUES('boom')", + "INSERT INTO boom(name) VALUES('zoom')" + ].join(";"), + function(err, callback) { + assert.equal( + callCount++, + 0, + "Call count should be 0. More means this callback fired more than once." + ); + release() + pool.end(done) + } + ); + }) + ); +}); + +suite.test("can provide callback and config object", function(done) { + const pool = new pg.Pool() + pool.connect( + assert.calls(function(err, client, release) { + assert.isNull(err); + client.query( + { + name: "boom", + text: "select NOW()" + }, + assert.calls(function(err, result) { + assert.isNull(err); + assert.equal(result.rows[0].now.getYear(), new Date().getYear()); + release(); + pool.end(done) + }) + ); + }) + ); +}); + +suite.test("can provide callback and config and parameters", function(done) { + const pool = new pg.Pool() + pool.connect( + assert.calls(function(err, client, release) { + assert.isNull(err); + var config = { + text: "select $1::text as val" + }; + client.query( + config, + ["hi"], + assert.calls(function(err, result) { + assert.isNull(err); + assert.equal(result.rows.length, 1); + assert.equal(result.rows[0].val, "hi"); + release() + pool.end(done) + }) + ); + }) + ); +}); + +suite.test("null and undefined are both inserted as NULL", function(done) { + const pool = new pg.Pool() + pool.connect( + assert.calls(function(err, client, release) { + 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] + ); + client.query( + "SELECT * FROM my_nulls", + assert.calls(function(err, result) { + assert.isNull(err); + assert.equal(result.rows.length, 1); + assert.isNull(result.rows[0].a); + assert.isNull(result.rows[0].b); + assert.isNull(result.rows[0].c); + assert.isNull(result.rows[0].d); + assert.isNull(result.rows[0].e); + assert.isNull(result.rows[0].f); + pool.end(done) + release(); + }) + ); + }) + ); +}); diff --git a/test/integration/client/deprecated-listener-tests.js b/test/integration/client/deprecated-listener-tests.js deleted file mode 100644 index 0687ff64..00000000 --- a/test/integration/client/deprecated-listener-tests.js +++ /dev/null @@ -1,30 +0,0 @@ -const helper = require('./test-helper') -const pg = helper.pg -const suite = new helper.Suite() - -suite.test('Query with a callback should still support event-listeners', (done) => { - const client = new pg.Client() - const sink = new helper.Sink(3, 1000, () => { - client.end() - done() - }) - client.connect() - const query = client.query('SELECT NOW()', (err, res) => { - sink.add() - }) - query.on('row', () => sink.add()) - query.on('end', () => sink.add()) -}) - -suite.test('Query with a promise should still support event-listeners', (done) => { - const client = new pg.Client() - const sink = new helper.Sink(3, 1000, () => { - client.end() - done() - }) - client.connect() - const query = client.query('SELECT NOW()') - query.on('row', () => sink.add()) - query.on('end', () => sink.add()) - query.then(() => sink.add()) -})