From 934ca3af16036986dbf2a687b80edcb36695830a Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 7 Jun 2017 20:45:32 -0700 Subject: [PATCH 01/58] Remove fallbacks for unsupported Node versions (#1304) * Remove unsupported Node versions 0.10 and 0.12 from CI * Replace deprecated Buffer constructor with .from/.alloc * Remove Promise polyfill * Make use of Object.assign * Remove checks for versions of Node earlier than 4 * Remove Buffer#indexOf fallback for Node 0.10 --- .travis.yml | 8 ----- lib/client.js | 2 +- lib/connection.js | 21 ++---------- package.json | 4 +-- test/buffer-list.js | 10 +++--- .../client/query-as-promise-tests.js | 5 --- .../connection-pool/idle-timeout-tests.js | 3 +- .../connection-pool/yield-support-body.js | 28 ---------------- .../connection-pool/yield-support-tests.js | 33 ++++++++++++++++--- test/integration/gh-issues/675-tests.js | 4 +-- test/test-buffers.js | 8 ++--- test/test-helper.js | 5 --- test/unit/client/md5-password-tests.js | 2 +- test/unit/connection/inbound-parser-tests.js | 16 ++++----- .../unit/connection/outbound-sending-tests.js | 16 ++++----- test/unit/utils-tests.js | 6 ++-- 16 files changed, 65 insertions(+), 106 deletions(-) delete mode 100644 test/integration/connection-pool/yield-support-body.js diff --git a/.travis.yml b/.travis.yml index 74f1e4c0..885cfa0e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,14 +12,6 @@ addons: matrix: include: - - node_js: "0.10" - addons: - postgresql: "9.6" - env: [] - - node_js: "0.12" - addons: - postgresql: "9.6" - env: [] - node_js: "4" addons: postgresql: "9.6" diff --git a/lib/client.js b/lib/client.js index a0d7f21c..a565ccbc 100644 --- a/lib/client.js +++ b/lib/client.js @@ -94,7 +94,7 @@ Client.prototype.connect = function(callback) { //password request handling con.on('authenticationMD5Password', checkPgPass(function(msg) { var inner = Client.md5(self.password + self.user); - var outer = Client.md5(Buffer.concat([new Buffer(inner), msg.salt])); + var outer = Client.md5(Buffer.concat([Buffer.from(inner), msg.salt])); var md5password = "md5" + outer; con.password(md5password); })); diff --git a/lib/connection.js b/lib/connection.js index 87d4f274..676b5f0c 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -13,21 +13,6 @@ var util = require('util'); var Writer = require('buffer-writer'); var Reader = require('packet-reader'); -var indexOf = - 'indexOf' in Buffer.prototype ? - function indexOf(buffer, value, start) { - return buffer.indexOf(value, start); - } : - function indexOf(buffer, value, start) { - for (var i = start, len = buffer.length; i < len; i++) { - if (buffer[i] === value) { - return i; - } - } - - return -1; - }; - var TEXT_MODE = 0; var BINARY_MODE = 1; var Connection = function(config) { @@ -311,7 +296,7 @@ Connection.prototype.execute = function(config, more) { this._send(0x45, more); }; -var emptyBuffer = Buffer(0); +var emptyBuffer = Buffer.alloc(0); Connection.prototype.flush = function() { //0x48 = 'H' @@ -450,7 +435,7 @@ Connection.prototype.parseR = function(buffer, length) { code = this.parseInt32(buffer); if(code === 5) { //md5 required msg.name = 'authenticationMD5Password'; - msg.salt = new Buffer(4); + msg.salt = Buffer.alloc(4); buffer.copy(msg.salt, 0, this.offset, this.offset + 4); this.offset += 4; return msg; @@ -665,7 +650,7 @@ Connection.prototype.readBytes = function(buffer, length) { Connection.prototype.parseCString = function(buffer) { var start = this.offset; - var end = indexOf(buffer, 0, start); + var end = buffer.indexOf(0, start); this.offset = end + 1; return buffer.toString(this.encoding, start, end); }; diff --git a/package.json b/package.json index 590a9155..d52ba05c 100644 --- a/package.json +++ b/package.json @@ -30,9 +30,7 @@ "async": "0.9.0", "co": "4.6.0", "jshint": "2.5.2", - "lodash": "4.13.1", - "pg-copy-streams": "0.3.0", - "promise-polyfill": "5.2.1" + "pg-copy-streams": "0.3.0" }, "minNativeVersion": "1.7.0", "scripts": { diff --git a/test/buffer-list.js b/test/buffer-list.js index 3aa24552..2b1ac73e 100644 --- a/test/buffer-list.js +++ b/test/buffer-list.js @@ -9,7 +9,7 @@ p.add = function(buffer, front) { }; p.addInt16 = function(val, front) { - return this.add(Buffer([(val >>> 8),(val >>> 0)]),front); + return this.add(Buffer.from([(val >>> 8),(val >>> 0)]),front); }; p.getByteLength = function(initial) { @@ -19,7 +19,7 @@ p.getByteLength = function(initial) { }; p.addInt32 = function(val, first) { - return this.add(Buffer([ + return this.add(Buffer.from([ (val >>> 24 & 0xFF), (val >>> 16 & 0xFF), (val >>> 8 & 0xFF), @@ -29,14 +29,14 @@ p.addInt32 = function(val, first) { p.addCString = function(val, front) { var len = Buffer.byteLength(val); - var buffer = new Buffer(len+1); + var buffer = Buffer.alloc(len+1); buffer.write(val); buffer[len] = 0; return this.add(buffer, front); }; p.addChar = function(char, first) { - return this.add(Buffer(char,'utf8'), first); + return this.add(Buffer.from(char,'utf8'), first); }; p.join = function(appendLength, char) { @@ -49,7 +49,7 @@ p.join = function(appendLength, char) { this.addChar(char, true); length++; } - var result = Buffer(length); + var result = Buffer.alloc(length); var index = 0; this.buffers.forEach(function(buffer) { buffer.copy(result, index, 0); diff --git a/test/integration/client/query-as-promise-tests.js b/test/integration/client/query-as-promise-tests.js index 8dcdeb51..ac958729 100644 --- a/test/integration/client/query-as-promise-tests.js +++ b/test/integration/client/query-as-promise-tests.js @@ -1,10 +1,5 @@ var helper = require(__dirname + '/../test-helper'); var pg = helper.pg; -var semver = require('semver') - -if (semver.lt(process.version, '0.12.0')) { - return console.log('promises are not supported in node < v0.10') -} process.on('unhandledRejection', function(e) { console.error(e, e.stack) diff --git a/test/integration/connection-pool/idle-timeout-tests.js b/test/integration/connection-pool/idle-timeout-tests.js index 0a60ce50..5a5db0ba 100644 --- a/test/integration/connection-pool/idle-timeout-tests.js +++ b/test/integration/connection-pool/idle-timeout-tests.js @@ -1,7 +1,6 @@ var helper = require(__dirname + '/test-helper'); -var _ = require('lodash') -const config = _.extend({ }, helper.config, { idleTimeoutMillis: 50 }) +const config = Object.assign({ }, helper.config, { idleTimeoutMillis: 50 }) test('idle timeout', function() { helper.pg.connect(config, assert.calls(function(err, client, done) { diff --git a/test/integration/connection-pool/yield-support-body.js b/test/integration/connection-pool/yield-support-body.js deleted file mode 100644 index 943ab3a2..00000000 --- a/test/integration/connection-pool/yield-support-body.js +++ /dev/null @@ -1,28 +0,0 @@ -var helper = require('./test-helper') -var co = require('co') - -var tid = setTimeout(function() { - throw new Error('Tests did not complete in time') -}, 1000) - -co(function * () { - var client = yield helper.pg.connect() - var res = yield client.query('SELECT $1::text as name', ['foo']) - assert.equal(res.rows[0].name, 'foo') - - var threw = false - try { - yield client.query('SELECT LKDSJDSLKFJ') - } catch(e) { - threw = true - } - assert(threw) - client.release() - helper.pg.end() - clearTimeout(tid) -}) -.catch(function(e) { - setImmediate(function() { - throw e - }) -}) diff --git a/test/integration/connection-pool/yield-support-tests.js b/test/integration/connection-pool/yield-support-tests.js index fb79ddc4..943ab3a2 100644 --- a/test/integration/connection-pool/yield-support-tests.js +++ b/test/integration/connection-pool/yield-support-tests.js @@ -1,5 +1,28 @@ -var semver = require('semver') -if (semver.lt(process.version, '1.0.0')) { - return console.log('yield is not supported in node <= v0.12') -} -require('./yield-support-body') +var helper = require('./test-helper') +var co = require('co') + +var tid = setTimeout(function() { + throw new Error('Tests did not complete in time') +}, 1000) + +co(function * () { + var client = yield helper.pg.connect() + var res = yield client.query('SELECT $1::text as name', ['foo']) + assert.equal(res.rows[0].name, 'foo') + + var threw = false + try { + yield client.query('SELECT LKDSJDSLKFJ') + } catch(e) { + threw = true + } + assert(threw) + client.release() + helper.pg.end() + clearTimeout(tid) +}) +.catch(function(e) { + setImmediate(function() { + throw e + }) +}) diff --git a/test/integration/gh-issues/675-tests.js b/test/integration/gh-issues/675-tests.js index f7d95427..c27d3632 100644 --- a/test/integration/gh-issues/675-tests.js +++ b/test/integration/gh-issues/675-tests.js @@ -11,11 +11,11 @@ helper.pg.connect(helper.config, function(err, client, done) { c = 'INSERT INTO posts (body) VALUES ($1) RETURNING *'; - var body = new Buffer('foo'); + var body = Buffer.from('foo'); client.query(c, [body], function(err) { if (err) throw err; - body = new Buffer([]); + body = Buffer.from([]); client.query(c, [body], function(err, res) { done(); diff --git a/test/test-buffers.js b/test/test-buffers.js index ddb6ba63..b16a7ab6 100644 --- a/test/test-buffers.js +++ b/test/test-buffers.js @@ -4,7 +4,7 @@ require(__dirname+'/test-helper'); var buffers = {}; buffers.readyForQuery = function() { return new BufferList() - .add(Buffer('I')) + .add(Buffer.from('I')) .join(true,'Z'); }; @@ -23,7 +23,7 @@ buffers.authenticationCleartextPassword = function() { buffers.authenticationMD5Password = function() { return new BufferList() .addInt32(5) - .add(Buffer([1,2,3,4])) + .add(Buffer.from([1,2,3,4])) .join(true, 'R'); }; @@ -71,7 +71,7 @@ buffers.dataRow = function(columns) { if(col == null) { buf.addInt32(-1); } else { - var strBuf = new Buffer(col, 'utf8'); + var strBuf = Buffer.from(col, 'utf8'); buf.addInt32(strBuf.length); buf.add(strBuf); } @@ -94,7 +94,7 @@ var errorOrNotice = function(fields) { buf.addChar(field.type); buf.addCString(field.value); }); - return buf.add(Buffer([0]));//terminator + return buf.add(Buffer.from([0]));//terminator } buffers.parseComplete = function() { diff --git a/test/test-helper.js b/test/test-helper.js index d8e06876..175cbbb9 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,11 +1,6 @@ //make assert a global... assert = require('assert'); -//support for node@0.10.x -if (typeof Promise == 'undefined') { - global.Promise = require('promise-polyfill') -} - var EventEmitter = require('events').EventEmitter; var sys = require('util'); var BufferList = require(__dirname+'/buffer-list') diff --git a/test/unit/client/md5-password-tests.js b/test/unit/client/md5-password-tests.js index 3c540368..315ef197 100644 --- a/test/unit/client/md5-password-tests.js +++ b/test/unit/client/md5-password-tests.js @@ -3,7 +3,7 @@ require(__dirname + '/test-helper'); test('md5 authentication', function() { var client = createClient(); client.password = "!"; - var salt = Buffer([1, 2, 3, 4]); + var salt = Buffer.from([1, 2, 3, 4]); client.connection.emit('authenticationMD5Password', {salt: salt}); test('responds', function() { diff --git a/test/unit/connection/inbound-parser-tests.js b/test/unit/connection/inbound-parser-tests.js index a9910966..2b822e44 100644 --- a/test/unit/connection/inbound-parser-tests.js +++ b/test/unit/connection/inbound-parser-tests.js @@ -158,7 +158,7 @@ test('Connection', function() { testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage); var msg = testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage); test('md5 has right salt', function() { - assert.equalBuffers(msg.salt, Buffer([1,2,3,4])); + assert.equalBuffers(msg.salt, Buffer.from([1,2,3,4])); }); testForMessage(paramStatusBuffer, expectedParameterStatusMessage); testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage); @@ -173,7 +173,7 @@ test('Connection', function() { }); test("no data message", function() { - testForMessage(Buffer([0x6e, 0, 0, 0, 4]), { + testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { name: 'noData' }); }); @@ -349,7 +349,7 @@ test('Connection', function() { }); test('parses replication start message', function() { - testForMessage(new Buffer([0x57, 0x00, 0x00, 0x00, 0x04]), { + testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { name: 'replicationStart', length: 4 }); @@ -383,8 +383,8 @@ test('split buffer, single message parsing', function() { }); var testMessageRecievedAfterSpiltAt = function(split) { - var firstBuffer = new Buffer(fullBuffer.length-split); - var secondBuffer = new Buffer(fullBuffer.length-firstBuffer.length); + var firstBuffer = Buffer.alloc(fullBuffer.length-split); + var secondBuffer = Buffer.alloc(fullBuffer.length-firstBuffer.length); fullBuffer.copy(firstBuffer, 0, 0); fullBuffer.copy(secondBuffer, 0, firstBuffer.length); stream.emit('data', firstBuffer); @@ -416,7 +416,7 @@ test('split buffer, single message parsing', function() { test('split buffer, multiple message parsing', function() { var dataRowBuffer = buffers.dataRow(['!']); var readyForQueryBuffer = buffers.readyForQuery(); - var fullBuffer = new Buffer(dataRowBuffer.length + readyForQueryBuffer.length); + var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length); dataRowBuffer.copy(fullBuffer, 0, 0); readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0); @@ -449,8 +449,8 @@ test('split buffer, multiple message parsing', function() { verifyMessages(); }); var splitAndVerifyTwoMessages = function(split) { - var firstBuffer = new Buffer(fullBuffer.length-split); - var secondBuffer = new Buffer(fullBuffer.length-firstBuffer.length); + var firstBuffer = Buffer.alloc(fullBuffer.length-split); + var secondBuffer = Buffer.alloc(fullBuffer.length-firstBuffer.length); fullBuffer.copy(firstBuffer, 0, 0); fullBuffer.copy(secondBuffer, 0, firstBuffer.length); stream.emit('data', firstBuffer); diff --git a/test/unit/connection/outbound-sending-tests.js b/test/unit/connection/outbound-sending-tests.js index 3dde8a3c..353c073b 100644 --- a/test/unit/connection/outbound-sending-tests.js +++ b/test/unit/connection/outbound-sending-tests.js @@ -104,12 +104,12 @@ test('bind messages', function() { .addInt16(0) .addInt16(4) .addInt32(1) - .add(Buffer("1")) + .add(Buffer.from("1")) .addInt32(2) - .add(Buffer("hi")) + .add(Buffer.from("hi")) .addInt32(-1) .addInt32(4) - .add(Buffer('zing')) + .add(Buffer.from('zing')) .addInt16(0) .join(true, 'B'); assert.received(stream, expectedBuffer); @@ -120,7 +120,7 @@ test('with named statement, portal, and buffer value', function() { con.bind({ portal: 'bang', statement: 'woo', - values: ['1', 'hi', null, new Buffer('zing', 'UTF-8')] + values: ['1', 'hi', null, Buffer.from('zing', 'utf8')] }); var expectedBuffer = new BufferList() .addCString('bang') //portal name @@ -132,12 +132,12 @@ test('with named statement, portal, and buffer value', function() { .addInt16(1)//binary .addInt16(4) .addInt32(1) - .add(Buffer("1")) + .add(Buffer.from("1")) .addInt32(2) - .add(Buffer("hi")) + .add(Buffer.from("hi")) .addInt32(-1) .addInt32(4) - .add(new Buffer('zing', 'UTF-8')) + .add(Buffer.from('zing', 'UTF-8')) .addInt16(0) .join(true, 'B'); assert.received(stream, expectedBuffer); @@ -181,7 +181,7 @@ test('sends sync command', function() { test('sends end command', function() { con.end(); - var expected = new Buffer([0x58, 0, 0, 0, 4]); + var expected = Buffer.from([0x58, 0, 0, 0, 4]); assert.received(stream, expected); }); diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index d640f988..82b11715 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -50,7 +50,7 @@ test('normalizing query configs', function() { }) test('prepareValues: buffer prepared properly', function() { - var buf = new Buffer("quack"); + var buf = Buffer.from("quack"); var out = utils.prepareValue(buf); assert.strictEqual(buf, out); }); @@ -142,7 +142,7 @@ test('prepareValue: objects with simple toPostgres prepared properly', function( }); test('prepareValue: objects with complex toPostgres prepared properly', function() { - var buf = new Buffer("zomgcustom!"); + var buf = Buffer.from("zomgcustom!"); var customType = { toPostgres: function() { return [1, 2]; @@ -165,7 +165,7 @@ test('prepareValue: objects with toPostgres receive prepareValue', function() { }); test('prepareValue: objects with circular toPostgres rejected', function() { - var buf = new Buffer("zomgcustom!"); + var buf = Buffer.from("zomgcustom!"); var customType = { toPostgres: function() { return { toPostgres: function () { return customType; } }; From aeb0c759f55cccc439bcaa9b4a4225a6dd812630 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 8 Jun 2017 21:53:47 -0500 Subject: [PATCH 02/58] Remove fallbacks for unsupported Node versions (#1304) (#1313) * Add client connectionString tests (#1310) * Remove redundant tests * Add client connectionString test Add test to ensure { connectionString } is respected as an argument to the client constructor * Add test for connection string property Also fixed some legacy require statements. * Normalize native error properties Map native error properties to the same property names we use for errors from the JS driver. Fixes #972 Fixes #938 --- lib/native/query.js | 18 ++++++++++++- lib/pool-factory.js | 1 - .../double-connection-tests.js | 2 +- .../ending-empty-pool-tests.js | 2 +- .../connection-pool/ending-pool-tests.js | 3 ++- .../connection-pool/error-tests.js | 4 +-- .../connection-pool/max-connection-tests.js | 2 +- .../connection-pool/native-instance-tests.js | 2 +- .../connection-pool/optional-config-tests.js | 2 +- .../single-connection-tests.js | 2 +- .../single-pool-on-object-config-tests.js | 4 +-- .../waiting-connection-tests.js | 2 +- test/native/native-vs-js-error-tests.js | 20 ++++++++++++++ test/unit/client/configuration-tests.js | 11 ++++++++ test/unit/client/connection-string-tests.js | 27 ------------------- 15 files changed, 61 insertions(+), 41 deletions(-) create mode 100644 test/native/native-vs-js-error-tests.js delete mode 100644 test/unit/client/connection-string-tests.js diff --git a/lib/native/query.js b/lib/native/query.js index fcb1eff4..a827af73 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -51,13 +51,29 @@ NativeQuery.prototype.promise = function() { return this._promise; }; +var errorFieldMap = { + 'sqlState': 'code', + 'statementPosition': 'position', + 'messagePrimary': 'message', + 'context': 'where', + 'schemaName': 'schema', + 'tableName': 'table', + 'columnName': 'column', + 'dataTypeName': 'dataType', + 'constraintName': 'constraint', + 'sourceFile': 'file', + 'sourceLine': 'line', + 'sourceFunction': 'routine', +}; + NativeQuery.prototype.handleError = function(err) { var self = this; //copy pq error fields into the error object var fields = self.native.pq.resultErrorFields(); if(fields) { for(var key in fields) { - err[key] = fields[key]; + var normalizedFieldName = errorFieldMap[key] || key; + err[normalizedFieldName] = fields[key]; } } if(self.callback) { diff --git a/lib/pool-factory.js b/lib/pool-factory.js index aa7bd0b1..85f0e6a5 100644 --- a/lib/pool-factory.js +++ b/lib/pool-factory.js @@ -3,7 +3,6 @@ var util = require('util'); var Pool = require('pg-pool'); module.exports = function(Client) { - var BoundPool = function(options) { var config = { Client: Client }; for (var key in options) { diff --git a/test/integration/connection-pool/double-connection-tests.js b/test/integration/connection-pool/double-connection-tests.js index ae7eb316..421e1f9e 100644 --- a/test/integration/connection-pool/double-connection-tests.js +++ b/test/integration/connection-pool/double-connection-tests.js @@ -1,2 +1,2 @@ -var helper = require(__dirname + "/test-helper") +var helper = require("./test-helper") helper.testPoolSize(2); diff --git a/test/integration/connection-pool/ending-empty-pool-tests.js b/test/integration/connection-pool/ending-empty-pool-tests.js index 4f5dd80a..d1acc6f2 100644 --- a/test/integration/connection-pool/ending-empty-pool-tests.js +++ b/test/integration/connection-pool/ending-empty-pool-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') var called = false; test('disconnects', function() { diff --git a/test/integration/connection-pool/ending-pool-tests.js b/test/integration/connection-pool/ending-pool-tests.js index 83f4b1bc..3a1ab46f 100644 --- a/test/integration/connection-pool/ending-pool-tests.js +++ b/test/integration/connection-pool/ending-pool-tests.js @@ -1,6 +1,7 @@ -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') var called = false; + test('disconnects', function() { var sink = new helper.Sink(4, function() { called = true; diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index 2cf0501f..59121a86 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -1,5 +1,5 @@ -var helper = require(__dirname + "/../test-helper"); -var pg = require(__dirname + "/../../../lib"); +var helper = require("../test-helper"); +var pg = require("../../../lib"); //first make pool hold 2 clients pg.defaults.poolSize = 2; diff --git a/test/integration/connection-pool/max-connection-tests.js b/test/integration/connection-pool/max-connection-tests.js index 68c0773f..944d2fb2 100644 --- a/test/integration/connection-pool/max-connection-tests.js +++ b/test/integration/connection-pool/max-connection-tests.js @@ -1,2 +1,2 @@ -var helper = require(__dirname + "/test-helper") +var helper = require("./test-helper") helper.testPoolSize(40); diff --git a/test/integration/connection-pool/native-instance-tests.js b/test/integration/connection-pool/native-instance-tests.js index 06fbdb45..314920c4 100644 --- a/test/integration/connection-pool/native-instance-tests.js +++ b/test/integration/connection-pool/native-instance-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + "/../test-helper") +var helper = require("./../test-helper") var pg = helper.pg var native = helper.args.native diff --git a/test/integration/connection-pool/optional-config-tests.js b/test/integration/connection-pool/optional-config-tests.js index f0ba2e76..be7063eb 100644 --- a/test/integration/connection-pool/optional-config-tests.js +++ b/test/integration/connection-pool/optional-config-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); //setup defaults helper.pg.defaults.user = helper.args.user; diff --git a/test/integration/connection-pool/single-connection-tests.js b/test/integration/connection-pool/single-connection-tests.js index 5ca0a888..89f6f069 100644 --- a/test/integration/connection-pool/single-connection-tests.js +++ b/test/integration/connection-pool/single-connection-tests.js @@ -1,2 +1,2 @@ -var helper = require(__dirname + "/test-helper") +var helper = require("./test-helper") helper.testPoolSize(1); diff --git a/test/integration/connection-pool/single-pool-on-object-config-tests.js b/test/integration/connection-pool/single-pool-on-object-config-tests.js index a28cbf5c..81cdf8e4 100644 --- a/test/integration/connection-pool/single-pool-on-object-config-tests.js +++ b/test/integration/connection-pool/single-pool-on-object-config-tests.js @@ -1,5 +1,5 @@ -var helper = require(__dirname + "/../test-helper"); -var pg = require(__dirname + "/../../../lib"); +var helper = require("../test-helper"); +var pg = require("../../../lib"); pg.connect(helper.config, assert.success(function(client, done) { assert.equal(Object.keys(pg._pools).length, 1); diff --git a/test/integration/connection-pool/waiting-connection-tests.js b/test/integration/connection-pool/waiting-connection-tests.js index f2519ec5..82572d1e 100644 --- a/test/integration/connection-pool/waiting-connection-tests.js +++ b/test/integration/connection-pool/waiting-connection-tests.js @@ -1,2 +1,2 @@ -var helper = require(__dirname + "/test-helper") +var helper = require("./test-helper") helper.testPoolSize(200); diff --git a/test/native/native-vs-js-error-tests.js b/test/native/native-vs-js-error-tests.js new file mode 100644 index 00000000..ee192ddc --- /dev/null +++ b/test/native/native-vs-js-error-tests.js @@ -0,0 +1,20 @@ +var assert = require('assert') +var Client = require('../../lib/client'); +var NativeClient = require('../../lib/native'); + +var client = new Client(); +var nativeClient = new NativeClient(); + +client.connect(); +nativeClient.connect((err) => { + client.query('SELECT alsdkfj', (err) => { + client.end(); + + nativeClient.query('SELECT lkdasjfasd', (nativeErr) => { + for(var key in nativeErr) { + assert.equal(err[key], nativeErr[key], `Expected err.${key} to equal nativeErr.${key}`) + } + nativeClient.end(); + }); + }); +}); diff --git a/test/unit/client/configuration-tests.js b/test/unit/client/configuration-tests.js index 0204af22..5548e5fb 100644 --- a/test/unit/client/configuration-tests.js +++ b/test/unit/client/configuration-tests.js @@ -59,6 +59,17 @@ test('client settings', function() { test('initializing from a config string', function() { + test('uses connectionString property', function () { + var client = new Client({ + connectionString: 'postgres://brian:pass@host1:333/databasename' + }) + assert.equal(client.user, 'brian'); + assert.equal(client.password, "pass"); + assert.equal(client.host, "host1"); + assert.equal(client.port, 333); + assert.equal(client.database, "databasename"); + }) + test('uses the correct values from the config string', function() { var client = new Client("postgres://brian:pass@host1:333/databasename") assert.equal(client.user, 'brian'); diff --git a/test/unit/client/connection-string-tests.js b/test/unit/client/connection-string-tests.js deleted file mode 100644 index 9316daa9..00000000 --- a/test/unit/client/connection-string-tests.js +++ /dev/null @@ -1,27 +0,0 @@ -require(__dirname + '/test-helper'); - -/* - * Perhaps duplicate of test named 'initializing from a config string' in - * configuration-tests.js - */ - -test("using connection string in client constructor", function() { - var client = new Client("postgres://brian:pw@boom:381/lala"); - - test("parses user", function() { - assert.equal(client.user,'brian'); - }); - test("parses password", function() { - assert.equal(client.password, 'pw'); - }); - test("parses host", function() { - assert.equal(client.host, 'boom'); - }); - test('parses port', function() { - assert.equal(client.port, 381) - }); - test('parses database', function() { - assert.equal(client.database, 'lala') - }); -}); - From f69108869e7c63aad079bf1b65655791752c28c8 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Fri, 9 Jun 2017 06:57:42 -0400 Subject: [PATCH 03/58] Remove default and normalize Travis-CI matrix Removes the default node 6 / PG 9.6 combination and adds it to the Travis-CI matrix of combinations. That way all combinations are defined in a single place. --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 885cfa0e..c50f2f13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,6 @@ before_script: env: - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres -node_js: "6" -addons: - postgresql: "9.6" - matrix: include: - node_js: "4" @@ -34,3 +30,6 @@ matrix: - node_js: "6" addons: postgresql: "9.5" + - node_js: "6" + addons: + postgresql: "9.6" From 61921aae1a6f98601db6904aae596237f4189767 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Fri, 9 Jun 2017 06:58:51 -0400 Subject: [PATCH 04/58] Add node 8.x to Travis-CI matrix --- .travis.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.travis.yml b/.travis.yml index c50f2f13..ec0b7e3d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,3 +33,22 @@ matrix: - node_js: "6" addons: postgresql: "9.6" + - node_js: "8" + addons: + postgresql: "9.1" + dist: precise + - node_js: "8" + addons: + postgresql: "9.2" + - node_js: "8" + addons: + postgresql: "9.3" + - node_js: "8" + addons: + postgresql: "9.4" + - node_js: "8" + addons: + postgresql: "9.5" + - node_js: "8" + addons: + postgresql: "9.6" From 31ee7590fde0609136a592980ab71215a85d4046 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 9 Jun 2017 13:15:26 -0500 Subject: [PATCH 05/58] Deprecate pg.* singleton methods --- lib/index.js | 4 + package.json | 1 + test/test-helper.js | 2 + yarn.lock | 248 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 yarn.lock diff --git a/lib/index.js b/lib/index.js index a2c2792f..343819cd 100644 --- a/lib/index.js +++ b/lib/index.js @@ -13,6 +13,7 @@ var defaults = require('./defaults'); var Connection = require('./connection'); var ConnectionParameters = require('./connection-parameters'); var poolFactory = require('./pool-factory'); +var deprecate = require('deprecate'); var PG = function(clientConstructor) { EventEmitter.call(this); @@ -28,6 +29,7 @@ var PG = function(clientConstructor) { util.inherits(PG, EventEmitter); PG.prototype.end = function() { + deprecate('pg.end() is deprecated - please construct pools directly via new pg.Pool()'); var self = this; var keys = Object.keys(this._pools); var count = keys.length; @@ -50,6 +52,7 @@ PG.prototype.end = function() { }; PG.prototype.connect = function(config, callback) { + deprecate('pg.connect() is deprecated - please construct pools directly via new pg.Pool()'); if(typeof config == "function") { callback = config; config = null; @@ -79,6 +82,7 @@ PG.prototype.connect = function(config, callback) { // cancel the query running on the given client PG.prototype.cancel = function(config, client, query) { + deprecate('pg.cancel() is deprecated - please create your own client instances to cancel queries'); if(client.native) { return client.cancel(query); } diff --git a/package.json b/package.json index d52ba05c..b7fd9d0c 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "main": "./lib", "dependencies": { "buffer-writer": "1.0.1", + "deprecate": "1.0.0", "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", "pg-pool": "1.*", diff --git a/test/test-helper.js b/test/test-helper.js index 175cbbb9..ad3e785b 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,6 +1,8 @@ //make assert a global... assert = require('assert'); +require('deprecate').silence = true; + var EventEmitter = require('events').EventEmitter; var sys = require('util'); var BufferList = require(__dirname+'/buffer-list') diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..7a50d7e3 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,248 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +ap@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" + +async@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.0.tgz#ac3613b1da9bed1b47510bb4651b8931e47146c7" + +buffer-writer@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-1.0.1.tgz#22a936901e3029afcd7547eb4487ceb697a3bf08" + +cli@0.6.x: + version "0.6.6" + resolved "https://registry.yarnpkg.com/cli/-/cli-0.6.6.tgz#02ad44a380abf27adac5e6f0cdd7b043d74c53e3" + dependencies: + exit "0.1.2" + glob "~ 3.2.1" + +co@4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +console-browserify@1.1.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + dependencies: + date-now "^0.1.4" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + +deprecate@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/deprecate/-/deprecate-1.0.0.tgz#661490ed2428916a6c8883d8834e5646f4e4a4a8" + +dom-serializer@0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + +domelementtype@1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + +domhandler@2.2: + version "2.2.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.2.1.tgz#59df9dcd227e808b365ae73e1f6684ac3d946fc2" + dependencies: + domelementtype "1" + +domutils@1.5: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + dependencies: + dom-serializer "0" + domelementtype "1" + +entities@1.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" + +entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + +exit@0.1.2, exit@0.1.x: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + +generic-pool@2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff" + +"glob@~ 3.2.1": + version "3.2.11" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" + dependencies: + inherits "2" + minimatch "0.3" + +htmlparser2@3.7.x: + version "3.7.3" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.7.3.tgz#6a64c77637c08c6f30ec2a8157a53333be7cb05e" + dependencies: + domelementtype "1" + domhandler "2.2" + domutils "1.5" + entities "1.0" + readable-stream "1.1" + +inherits@2, inherits@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +jshint@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jshint/-/jshint-2.5.2.tgz#bec223d5149e49ef6ea96dcf8b3504a27613e8be" + dependencies: + cli "0.6.x" + console-browserify "1.1.x" + exit "0.1.x" + htmlparser2 "3.7.x" + minimatch "0.x.x" + shelljs "0.3.x" + strip-json-comments "0.1.x" + underscore "1.6.x" + +lru-cache@2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" + +minimatch@0.3: + version "0.3.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +minimatch@0.x.x: + version "0.4.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.4.0.tgz#bd2c7d060d2c8c8fd7cde7f1f2ed2d5b270fdb1b" + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +object-assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" + +packet-reader@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.3.1.tgz#cd62e60af8d7fea8a705ec4ff990871c46871f27" + +pg-connection-string@0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" + +pg-copy-streams@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/pg-copy-streams/-/pg-copy-streams-0.3.0.tgz#a4fbc2a3b788d4e9da6f77ceb35422d8d7043b7f" + +pg-pool@1.*: + version "1.7.1" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-1.7.1.tgz#421105cb7469979dcc48d6fc4fe3fe4659437437" + dependencies: + generic-pool "2.4.3" + object-assign "4.1.0" + +pg-types@1.*: + version "1.12.0" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.12.0.tgz#8ad3b7b897e3fd463e62de241ad5fc640b4a66f0" + dependencies: + ap "~0.2.0" + postgres-array "~1.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.0" + postgres-interval "^1.1.0" + +pgpass@1.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" + dependencies: + split "^1.0.0" + +postgres-array@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.2.tgz#8e0b32eb03bf77a5c0a7851e0441c169a256a238" + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + +postgres-date@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.3.tgz#e2d89702efdb258ff9d9cee0fe91bd06975257a8" + +postgres-interval@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.1.0.tgz#1031e7bac34564132862adc9eb6c6d2f3aa75bb4" + dependencies: + xtend "^4.0.0" + +readable-stream@1.1: + version "1.1.13" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +semver@4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" + +shelljs@0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" + +sigmund@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + +split@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.0.tgz#c4395ce683abcd254bc28fe1dabb6e5c27dcffae" + dependencies: + through "2" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +strip-json-comments@0.1.x: + version "0.1.3" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-0.1.3.tgz#164c64e370a8a3cc00c9e01b539e569823f0ee54" + +through@2: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +underscore@1.6.x: + version "1.6.0" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8" + +xtend@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From 272858ca57d67d5680394e560b845893da16f7d1 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 9 Jun 2017 13:52:41 -0500 Subject: [PATCH 06/58] Remove lockfile because yarn in travis is blowing up the tests --- yarn.lock | 248 ------------------------------------------------------ 1 file changed, 248 deletions(-) delete mode 100644 yarn.lock diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 7a50d7e3..00000000 --- a/yarn.lock +++ /dev/null @@ -1,248 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -ap@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" - -async@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.0.tgz#ac3613b1da9bed1b47510bb4651b8931e47146c7" - -buffer-writer@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-1.0.1.tgz#22a936901e3029afcd7547eb4487ceb697a3bf08" - -cli@0.6.x: - version "0.6.6" - resolved "https://registry.yarnpkg.com/cli/-/cli-0.6.6.tgz#02ad44a380abf27adac5e6f0cdd7b043d74c53e3" - dependencies: - exit "0.1.2" - glob "~ 3.2.1" - -co@4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -console-browserify@1.1.x: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - dependencies: - date-now "^0.1.4" - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - -deprecate@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/deprecate/-/deprecate-1.0.0.tgz#661490ed2428916a6c8883d8834e5646f4e4a4a8" - -dom-serializer@0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" - dependencies: - domelementtype "~1.1.1" - entities "~1.1.1" - -domelementtype@1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" - -domelementtype@~1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - -domhandler@2.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.2.1.tgz#59df9dcd227e808b365ae73e1f6684ac3d946fc2" - dependencies: - domelementtype "1" - -domutils@1.5: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - dependencies: - dom-serializer "0" - domelementtype "1" - -entities@1.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" - -entities@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" - -exit@0.1.2, exit@0.1.x: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - -generic-pool@2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff" - -"glob@~ 3.2.1": - version "3.2.11" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" - dependencies: - inherits "2" - minimatch "0.3" - -htmlparser2@3.7.x: - version "3.7.3" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.7.3.tgz#6a64c77637c08c6f30ec2a8157a53333be7cb05e" - dependencies: - domelementtype "1" - domhandler "2.2" - domutils "1.5" - entities "1.0" - readable-stream "1.1" - -inherits@2, inherits@~2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - -jshint@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jshint/-/jshint-2.5.2.tgz#bec223d5149e49ef6ea96dcf8b3504a27613e8be" - dependencies: - cli "0.6.x" - console-browserify "1.1.x" - exit "0.1.x" - htmlparser2 "3.7.x" - minimatch "0.x.x" - shelljs "0.3.x" - strip-json-comments "0.1.x" - underscore "1.6.x" - -lru-cache@2: - version "2.7.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" - -minimatch@0.3: - version "0.3.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - -minimatch@0.x.x: - version "0.4.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.4.0.tgz#bd2c7d060d2c8c8fd7cde7f1f2ed2d5b270fdb1b" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - -object-assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" - -packet-reader@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.3.1.tgz#cd62e60af8d7fea8a705ec4ff990871c46871f27" - -pg-connection-string@0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" - -pg-copy-streams@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/pg-copy-streams/-/pg-copy-streams-0.3.0.tgz#a4fbc2a3b788d4e9da6f77ceb35422d8d7043b7f" - -pg-pool@1.*: - version "1.7.1" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-1.7.1.tgz#421105cb7469979dcc48d6fc4fe3fe4659437437" - dependencies: - generic-pool "2.4.3" - object-assign "4.1.0" - -pg-types@1.*: - version "1.12.0" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.12.0.tgz#8ad3b7b897e3fd463e62de241ad5fc640b4a66f0" - dependencies: - ap "~0.2.0" - postgres-array "~1.0.0" - postgres-bytea "~1.0.0" - postgres-date "~1.0.0" - postgres-interval "^1.1.0" - -pgpass@1.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" - dependencies: - split "^1.0.0" - -postgres-array@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.2.tgz#8e0b32eb03bf77a5c0a7851e0441c169a256a238" - -postgres-bytea@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" - -postgres-date@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.3.tgz#e2d89702efdb258ff9d9cee0fe91bd06975257a8" - -postgres-interval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.1.0.tgz#1031e7bac34564132862adc9eb6c6d2f3aa75bb4" - dependencies: - xtend "^4.0.0" - -readable-stream@1.1: - version "1.1.13" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -semver@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" - -shelljs@0.3.x: - version "0.3.0" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" - -sigmund@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - -split@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.0.tgz#c4395ce683abcd254bc28fe1dabb6e5c27dcffae" - dependencies: - through "2" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - -strip-json-comments@0.1.x: - version "0.1.3" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-0.1.3.tgz#164c64e370a8a3cc00c9e01b539e569823f0ee54" - -through@2: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - -underscore@1.6.x: - version "1.6.0" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8" - -xtend@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From bbbd6e99f9dc5755bda6168ba2157a9513d7f2d7 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 9 Jun 2017 15:15:13 -0500 Subject: [PATCH 07/58] Use built-in util.deprecate --- lib/index.js | 18 ++++++++---------- package.json | 1 - test/test-helper.js | 4 +--- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/lib/index.js b/lib/index.js index 343819cd..a2439711 100644 --- a/lib/index.js +++ b/lib/index.js @@ -13,7 +13,6 @@ var defaults = require('./defaults'); var Connection = require('./connection'); var ConnectionParameters = require('./connection-parameters'); var poolFactory = require('./pool-factory'); -var deprecate = require('deprecate'); var PG = function(clientConstructor) { EventEmitter.call(this); @@ -28,8 +27,7 @@ var PG = function(clientConstructor) { util.inherits(PG, EventEmitter); -PG.prototype.end = function() { - deprecate('pg.end() is deprecated - please construct pools directly via new pg.Pool()'); +PG.prototype.end = util.deprecate(function() { var self = this; var keys = Object.keys(this._pools); var count = keys.length; @@ -49,10 +47,10 @@ PG.prototype.end = function() { }); }); } -}; +}, +'pg.end() is deprecated - please construct pools directly via new pg.Pool()'); -PG.prototype.connect = function(config, callback) { - deprecate('pg.connect() is deprecated - please construct pools directly via new pg.Pool()'); +PG.prototype.connect = util.deprecate(function(config, callback) { if(typeof config == "function") { callback = config; config = null; @@ -78,11 +76,11 @@ PG.prototype.connect = function(config, callback) { }.bind(this)); } return pool.connect(callback); -}; +}, +'pg.connect() is deprecated - please construct pools directly via new pg.Pool()'); // cancel the query running on the given client -PG.prototype.cancel = function(config, client, query) { - deprecate('pg.cancel() is deprecated - please create your own client instances to cancel queries'); +PG.prototype.cancel = util.deprecate(function(config, client, query) { if(client.native) { return client.cancel(query); } @@ -93,7 +91,7 @@ PG.prototype.cancel = function(config, client, query) { } var cancellingClient = new this.Client(c); cancellingClient.cancel(client, query); -}; +}, 'pg.cancel() is deprecated - please create your own client instances to cancel queries'); if(typeof process.env.NODE_PG_FORCE_NATIVE != 'undefined') { module.exports = new PG(require('./native')); diff --git a/package.json b/package.json index b7fd9d0c..d52ba05c 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,6 @@ "main": "./lib", "dependencies": { "buffer-writer": "1.0.1", - "deprecate": "1.0.0", "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", "pg-pool": "1.*", diff --git a/test/test-helper.js b/test/test-helper.js index ad3e785b..f39cbfef 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,8 +1,6 @@ //make assert a global... assert = require('assert'); - -require('deprecate').silence = true; - +process.noDeprecation = true; var EventEmitter = require('events').EventEmitter; var sys = require('util'); var BufferList = require(__dirname+'/buffer-list') From bc00f90c6a2a6502774b07a2ebabfd89231f408c Mon Sep 17 00:00:00 2001 From: Amila Welihinda Date: Sun, 11 Jun 2017 12:59:33 -0700 Subject: [PATCH 08/58] Added MIT License --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..11cda4c0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Brian C + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 25a98f509999b36f5c9da2cf5e870f6ec7ab9be5 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 12 Jun 2017 09:47:39 -0500 Subject: [PATCH 09/58] Create LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 11cda4c0..a7b546d2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Brian C +Copyright (c) 2010 - 2017 Brian Carlson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 6d98b0847cf39ff327ce45c663ee4230d7b9104a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 9 Jun 2017 16:35:01 -0500 Subject: [PATCH 10/58] Actual promisification of client.query --- lib/client.js | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/client.js b/lib/client.js index 9fb2f8b1..d489ff8d 100644 --- a/lib/client.js +++ b/lib/client.js @@ -349,19 +349,37 @@ Client.prototype.copyTo = function (text) { }; Client.prototype.query = function(config, values, callback) { - //can take in strings, config object or query object - var query = (typeof config.submit == 'function') ? config : - new Query(config, values, callback); + var promise; + var isQueryable = typeof config.submit == 'function'; + var query; + // if we receive an object with a 'submit' function we delegate + // processing to the passed object - this is how pg.Query, QueryStream, and Cursor work + if (isQueryable) { + query = config; + } else { + query = new Query(config, values, callback); + if (!query.callback) { + promise = new global.Promise(function (resolve, reject) { + query.on('error', reject); + query.on('end', resolve); + }); + } + } if(this.binary && !query.binary) { query.binary = true; } + + // TODO - this is a smell if(query._result) { query._result._getTypeParser = this._types.getTypeParser.bind(this._types); } this.queryQueue.push(query); this._pulseQueryQueue(); - return query; + + // if we were passed a queryable, return it + // otherwise return callback/promise result + return isQueryable ? query : promise; }; Client.prototype.end = function(cb) { From 96b7fc38a60e289d0e6e4029e563f6e1d43640b1 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 10 Jun 2017 09:40:17 -0500 Subject: [PATCH 11/58] Fix unit tests --- test/unit/client/prepared-statement-tests.js | 7 ++++--- test/unit/client/result-metadata-tests.js | 8 +++----- test/unit/client/simple-query-tests.js | 3 ++- test/unit/client/throw-in-type-parser-tests.js | 8 ++++---- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/test/unit/client/prepared-statement-tests.js b/test/unit/client/prepared-statement-tests.js index 6e26c796..460cbf95 100644 --- a/test/unit/client/prepared-statement-tests.js +++ b/test/unit/client/prepared-statement-tests.js @@ -1,4 +1,5 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); +var Query = require('../../../lib/query') var client = helper.client(); var con = client.connection; @@ -49,10 +50,10 @@ test('bound command', function() { test('simple, unnamed bound command', function() { assert.ok(client.connection.emit('readyForQuery')); - var query = client.query({ + var query = client.query(new Query({ text: 'select * from X where name = $1', values: ['hi'] - }); + })); assert.emits(query,'end', function() { test('parse argument', function() { diff --git a/test/unit/client/result-metadata-tests.js b/test/unit/client/result-metadata-tests.js index 435af25b..5f349b57 100644 --- a/test/unit/client/result-metadata-tests.js +++ b/test/unit/client/result-metadata-tests.js @@ -6,13 +6,11 @@ var testForTag = function(tagText, callback) { var client = helper.client(); client.connection.emit('readyForQuery') - var query = client.query("whatever"); - assert.lengthIs(client.connection.queries, 1) - - assert.emits(query, 'end', function(result) { + var query = client.query("whatever", assert.calls((err, result) => { assert.ok(result != null, "should pass something to this event") callback(result) - }) + })); + assert.lengthIs(client.connection.queries, 1) client.connection.emit('commandComplete', { text: tagText diff --git a/test/unit/client/simple-query-tests.js b/test/unit/client/simple-query-tests.js index 19f05c18..df71faed 100644 --- a/test/unit/client/simple-query-tests.js +++ b/test/unit/client/simple-query-tests.js @@ -1,4 +1,5 @@ var helper = require(__dirname + "/test-helper"); +var Query = require('../../../lib/query') test('executing query', function() { @@ -64,7 +65,7 @@ test('executing query', function() { test("query event binding and flow", function() { var client = helper.client(); var con = client.connection; - var query = client.query('whatever'); + var query = client.query(new Query('whatever')); test("has no queries sent before ready", function() { assert.empty(con.queries); diff --git a/test/unit/client/throw-in-type-parser-tests.js b/test/unit/client/throw-in-type-parser-tests.js index ed371137..37a272aa 100644 --- a/test/unit/client/throw-in-type-parser-tests.js +++ b/test/unit/client/throw-in-type-parser-tests.js @@ -1,4 +1,5 @@ -var helper = require(__dirname + "/test-helper"); +var helper = require("./test-helper"); +var Query = require('../../../lib/query') var types = require('pg-types') test('handles throws in type parsers', function() { @@ -12,7 +13,7 @@ test('handles throws in type parsers', function() { var handled; var client = helper.client(); var con = client.connection; - var query = client.query('whatever'); + var query = client.query(new Query('whatever')); handled = con.emit('readyForQuery'); assert.ok(handled, "should have handled ready for query"); @@ -81,8 +82,7 @@ test('handles throws in type parsers', function() { var handled; var client = helper.client(); var con = client.connection; - var query = client.query('whatever'); - var queryPromise = query.promise(); + var queryPromise = client.query('whatever'); handled = con.emit('readyForQuery'); assert.ok(handled, "should have handled ready for query"); From 2f3d72a28ce58429e432578c0df7ec489643038d Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 10 Jun 2017 10:02:33 -0500 Subject: [PATCH 12/58] Start fixing integration tests --- script/create-test-tables.js | 9 ++---- test/integration/client/array-tests.js | 8 ++--- .../client/error-handling-tests.js | 31 +++++-------------- .../client/query-error-handling-tests.js | 8 +++-- test/integration/gh-issues/131-tests.js | 2 +- 5 files changed, 21 insertions(+), 37 deletions(-) diff --git a/script/create-test-tables.js b/script/create-test-tables.js index fa5d1b6e..6a569f2a 100644 --- a/script/create-test-tables.js +++ b/script/create-test-tables.js @@ -39,15 +39,12 @@ var con = new pg.Client({ }); con.connect(); var query = con.query("drop table if exists person"); -query.on('end', function() { - console.log("Dropped table 'person'") -}); -con.query("create table person(id serial, name varchar(10), age integer)").on('end', function(){ +con.query("create table person(id serial, name varchar(10), age integer)", (err, res) => { console.log("Created table person"); console.log("Filling it with people"); -}); +}) people.map(function(person) { - return con.query("insert into person(name, age) values('"+person.name + "', '" + person.age + "')"); + return con.query(new pg.Query("insert into person(name, age) values('"+person.name + "', '" + person.age + "')")); }).pop().on('end', function(){ console.log("Inserted 26 people"); con.end(); diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index 2525b8a2..937ea17b 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -35,7 +35,7 @@ test('parsing array results', function() { 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); + client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); test('numbers', function() { // client.connection.on('message', console.log) client.query('SELECT numbors FROM why', assert.success(function(result) { @@ -55,7 +55,7 @@ test('parsing array results', function() { assert.equal(names[2], "a b c"); })) }) - + test('empty array', function(){ client.query("SELECT '{}'::text[] as names", assert.success(function(result) { var names = result.rows[0].names; @@ -142,7 +142,7 @@ test('parsing array results', function() { assert.equal(names[2][1], 100); })) }) - + test('JS array parameter', function(){ client.query("SELECT $1::integer[] as names", [[[1,100],[2,100],[3,100]]], assert.success(function(result) { var names = result.rows[0].names; @@ -159,7 +159,7 @@ test('parsing array results', function() { pg.end(); })) }) - + })) }) diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 3fcd305b..d66fb611 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -1,23 +1,8 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); var util = require('util'); +const { pg } = helper - test('non-query error with callback', function () { - var client = new Client({ - user:'asldkfjsadlfkj' - }); - client.connect(assert.calls(function (err) { - assert(err); - })); - }); - - test('non-query error', function() { - var client = new Client({ - user:'asldkfjsadlfkj' - }); - assert.emits(client, 'error'); - client.connect(); - }); var createErorrClient = function() { var client = helper.client(); @@ -33,7 +18,7 @@ test('error handling', function() { test('within a simple query', function() { var client = createErorrClient(); - var query = client.query("select omfg from yodas_dsflsd where pixistix = 'zoiks!!!'"); + var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")); assert.emits(query, 'error', function(error) { assert.equal(error.severity, "ERROR"); @@ -52,17 +37,17 @@ test('error handling', function() { var ensureFuture = function(testClient) { test("client can issue more queries successfully", function() { - var goodQuery = testClient.query("select age from boom"); + var goodQuery = testClient.query(new pg.Query("select age from boom")); assert.emits(goodQuery, 'row', function(row) { assert.equal(row.age, 28); }); }); }; - var query = client.query({ + var query = client.query(new pg.Query({ text: "select * from bang where name = $1", values: ['0'] - }); + })); test("query emits the error", function() { assert.emits(query, 'error', function(err) { @@ -72,10 +57,10 @@ test('error handling', function() { test("when a query is binding", function() { - var query = client.query({ + var query = client.query(new pg.Query({ text: 'select * from boom where age = $1', values: ['asldkfjasdf'] - }); + })); test("query emits the error", function() { diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index 2618a49d..3eba4b11 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -1,10 +1,11 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); var util = require('util'); +const { Query } = helper.pg; test('error during query execution', function() { var client = new Client(helper.args); client.connect(assert.success(function() { - var sleepQuery = 'select pg_sleep(5)'; + var sleepQuery = new Query('select pg_sleep(5)'); var pidColName = 'procpid' var queryColName = 'current_query'; helper.versionGTE(client, '9.2.0', assert.success(function(isGreater) { @@ -27,13 +28,14 @@ test('error during query execution', function() { client2.connect(assert.success(function() { var killIdleQuery = "SELECT " + pidColName + ", (SELECT pg_terminate_backend(" + pidColName + ")) AS killed FROM pg_stat_activity WHERE " + queryColName + " = $1"; client2.query(killIdleQuery, [sleepQuery], assert.calls(function(err, res) { + console.log('\nresult', res) assert.ifError(err); assert.equal(res.rows.length, 1); client2.end(); assert.emits(client2, 'end'); })); })); - }, 100) + }, 300) })); })); }); diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index eee5086a..f733ea70 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -5,7 +5,7 @@ test('parsing array results', function() { pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])"); - client.query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')').on('error', console.log); + client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log); test('decimals', function() { client.query('SELECT decimals FROM why', assert.success(function(result) { assert.lengthIs(result.rows[0].decimals, 3); From b8c2bebcaca895d7803ebb9b86364675bd9147a2 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 10 Jun 2017 16:29:00 -0500 Subject: [PATCH 13/58] Fix more tests to use query instance --- lib/client.js | 4 + .../client/big-simple-query-tests.js | 18 +-- test/integration/client/cancel-query-tests.js | 11 +- .../client/error-handling-tests.js | 2 +- test/integration/client/no-data-tests.js | 11 +- .../integration/client/no-row-result-tests.js | 4 +- .../client/prepared-statement-tests.js | 104 +++++------------- ...error-handling-prepared-statement-tests.js | 10 +- .../client/query-error-handling-tests.js | 10 +- .../client/result-metadata-tests.js | 8 +- .../client/results-as-array-tests.js | 3 - test/integration/client/simple-query-tests.js | 33 ++---- .../integration/client/type-coercion-tests.js | 9 +- .../connection-pool/test-helper.js | 4 +- 14 files changed, 75 insertions(+), 156 deletions(-) diff --git a/lib/client.js b/lib/client.js index d489ff8d..32ea76b9 100644 --- a/lib/client.js +++ b/lib/client.js @@ -356,6 +356,10 @@ Client.prototype.query = function(config, values, callback) { // processing to the passed object - this is how pg.Query, QueryStream, and Cursor work if (isQueryable) { query = config; + // accept client.query(new Query('select *'), (err, res) => { }) call signature + if (typeof values == 'function') { + query.callback = query.callback || values; + } } else { query = new Query(config, values, callback); if (!query.callback) { diff --git a/test/integration/client/big-simple-query-tests.js b/test/integration/client/big-simple-query-tests.js index cf6cdbf7..514babe6 100644 --- a/test/integration/client/big-simple-query-tests.js +++ b/test/integration/client/big-simple-query-tests.js @@ -1,4 +1,5 @@ -var helper = require(__dirname+"/test-helper"); +var helper = require("./test-helper"); +var Query = helper.pg.Query /* Test to trigger a bug. @@ -15,7 +16,7 @@ var big_query_rows_3 = []; // Works test('big simple query 1',function() { var client = helper.client(); - client.query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1") + client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1")) .on('row', function(row) { big_query_rows_1.push(row); }) .on('error', function(error) { console.log("big simple query 1 error"); console.log(error); }); client.on('drain', client.end.bind(client)); @@ -24,7 +25,7 @@ test('big simple query 1',function() { // Works test('big simple query 2',function() { var client = helper.client(); - client.query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",['']) + client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''])) .on('row', function(row) { big_query_rows_2.push(row); }) .on('error', function(error) { console.log("big simple query 2 error"); console.log(error); }); client.on('drain', client.end.bind(client)); @@ -34,7 +35,7 @@ test('big simple query 2',function() { // If test 1 and 2 are commented out it works test('big simple query 3',function() { var client = helper.client(); - client.query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",['']) + client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''])) .on('row', function(row) { big_query_rows_3.push(row); }) .on('error', function(error) { console.log("big simple query 3 error"); console.log(error); }); client.on('drain', client.end.bind(client)); @@ -56,19 +57,12 @@ var runBigQuery = function(client) { } assert.lengthIs(result.rows, 26); }); - q.on('row', function(row) { - rows.push(row); - }) - assert.emits(q, 'end', function() { - //query ended - assert.lengthIs(rows, 26); - }) } test('many times', function() { var client = helper.client(); for(var i = 0; i < 20; i++) { - runBigQuery(client); + runBigQuery(client); } client.on('drain', function() { client.end(); diff --git a/test/integration/client/cancel-query-tests.js b/test/integration/client/cancel-query-tests.js index b6c0c7f4..0275fa89 100644 --- a/test/integration/client/cancel-query-tests.js +++ b/test/integration/client/cancel-query-tests.js @@ -1,4 +1,5 @@ -var helper = require(__dirname+"/test-helper"); +var helper = require("./test-helper"); +var Query = helper.pg.Query; //before running this test make sure you run the script create-test-tables test("cancellation of a query", function() { @@ -11,19 +12,19 @@ test("cancellation of a query", function() { var rows3 = 0; - var query1 = client.query(qry); + var query1 = client.query(new Query(qry)); query1.on('row', function(row) { throw new Error('Should not emit a row') }); - var query2 = client.query(qry); + var query2 = client.query(new Query(qry)); query2.on('row', function(row) { throw new Error('Should not emit a row') }); - var query3 = client.query(qry); + var query3 = client.query(new Query(qry)); query3.on('row', function(row) { rows3++; }); - var query4 = client.query(qry); + var query4 = client.query(new Query(qry)); query4.on('row', function(row) { throw new Error('Should not emit a row') }); diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index d66fb611..08e78b33 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -1,7 +1,7 @@ var helper = require('./test-helper'); var util = require('util'); -const { pg } = helper +var pg = helper.pg var createErorrClient = function() { diff --git a/test/integration/client/no-data-tests.js b/test/integration/client/no-data-tests.js index 341d7287..3258e6a5 100644 --- a/test/integration/client/no-data-tests.js +++ b/test/integration/client/no-data-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); test("noData message handling", function() { @@ -22,7 +22,6 @@ test("noData message handling", function() { client.query({ name: 'insert', - text: 'insert into boom(size) values($1)', values: [101] }); @@ -30,12 +29,10 @@ test("noData message handling", function() { name: 'fetch', text: 'select size from boom where size < $1', values: [101] - }); - - assert.emits(query, 'row', function(row) { - assert.strictEqual(row.size,100) + }, (err, res) => { + var row = res.rows[0] + assert.strictEqual(row.size, 100) }); client.on('drain', client.end.bind(client)); - }); diff --git a/test/integration/client/no-row-result-tests.js b/test/integration/client/no-row-result-tests.js index 5555ff6f..1929b162 100644 --- a/test/integration/client/no-row-result-tests.js +++ b/test/integration/client/no-row-result-tests.js @@ -3,6 +3,7 @@ var pg = helper.pg; var config = helper.config; test('can access results when no rows are returned', function() { + console.log('maybe fix this?', __filename) if(config.native) return false; var checkResult = function(result) { assert(result.fields, 'should have fields definition'); @@ -13,7 +14,8 @@ test('can access results when no rows are returned', function() { }; pg.connect(config, assert.success(function(client, done) { - var query = client.query('select $1::text as val limit 0', ['hi'], assert.success(function(result) { + const q = new pg.Query('select $1::text as val limit 0', ['hi']) + var query = client.query(q, assert.success(function(result) { checkResult(result); done(); })); diff --git a/test/integration/client/prepared-statement-tests.js b/test/integration/client/prepared-statement-tests.js index 478cd007..9735407a 100644 --- a/test/integration/client/prepared-statement-tests.js +++ b/test/integration/client/prepared-statement-tests.js @@ -1,48 +1,5 @@ -var helper = require(__dirname +'/test-helper'); - -test("simple, unnamed prepared statement", function(){ - var client = helper.client(); - - var query = client.query({ - text: 'select age from person where name = $1', - values: ['Brian'] - }); - - assert.emits(query, 'row', function(row) { - assert.equal(row.age, 20); - }); - - assert.emits(query, 'end', function() { - client.end(); - }); -}); - -test("use interval in prepared statement", function(){ - return; - var client = helper.client(); - - client.query('SELECT interval \'15 days 2 months 3 years 6:12:05\' as interval', assert.success(function(result) { - var interval = result.rows[0].interval; - - var query = client.query({ - text: 'select cast($1 as interval) as interval', - values: [interval] - }); - - assert.emits(query, 'row', function(row) { - assert.equal(row.interval.seconds, 5); - assert.equal(row.interval.minutes, 12); - assert.equal(row.interval.hours, 6); - assert.equal(row.interval.days, 15); - assert.equal(row.interval.months, 2); - assert.equal(row.interval.years, 3); - }); - - assert.emits(query, 'end', function() { - client.end(); - }); - })); -}); +var helper = require('./test-helper'); +var Query = helper.pg.Query; test("named prepared statement", function() { @@ -52,12 +9,12 @@ test("named prepared statement", function() { var queryName = "user by age and like name"; var parseCount = 0; - test("first named prepared statement",function() { - var query = client.query({ + test("first named prepared statement", function() { + var query = client.query(new Query({ text: 'select name from person where age <= $1 and name LIKE $2', values: [20, 'Bri%'], name: queryName - }); + })); assert.emits(query, 'row', function(row) { assert.equal(row.name, 'Brian'); @@ -68,11 +25,11 @@ test("named prepared statement", function() { }); test("second named prepared statement with same name & text", function() { - var cachedQuery = client.query({ + var cachedQuery = client.query(new Query({ text: 'select name from person where age <= $1 and name LIKE $2', name: queryName, values: [10, 'A%'] - }); + })); assert.emits(cachedQuery, 'row', function(row) { assert.equal(row.name, 'Aaron'); @@ -82,28 +39,22 @@ test("named prepared statement", function() { }); }); - test("with same name, but the query text not even there batman!", function() { - var q = client.query({ + test("with same name, but without query text", function() { + var q = client.query(new Query({ name: queryName, values: [30, '%n%'] - }); + })); - test("gets first row", function() { + assert.emits(q, 'row', function(row) { + assert.equal(row.name, "Aaron"); + + // test second row is emitted as well assert.emits(q, 'row', function(row) { - assert.equal(row.name, "Aaron"); - - test("gets second row", function() { - assert.emits(q, 'row', function(row) { - assert.equal(row.name, "Brian"); - }); - }); - + assert.equal(row.name, "Brian"); }); }); - assert.emits(q, 'end', function() { - - }); + assert.emits(q, 'end', function() { }); }); }); @@ -124,14 +75,9 @@ test("prepared statements on different clients", function() { var query = client1.query({ name: statementName, text: statement1 - }); - test('gets right data back', function() { - assert.emits(query, 'row', function(row) { - assert.equal(row.count, 26); - }); - }); - - assert.emits(query, 'end', function() { + }, (err, res) => { + assert(!err); + assert.equal(res.rows[0].count, 26); if(client2Finished) { client1.end(); client2.end(); @@ -143,11 +89,11 @@ test("prepared statements on different clients", function() { }); test('client 2 execution', function() { - var query = client2.query({ + var query = client2.query(new Query({ name: statementName, text: statement2, values: [11] - }); + })); test('gets right data', function() { assert.emits(query, 'row', function(row) { @@ -192,22 +138,22 @@ test('prepared statement', function() { }; test('with small row count', function() { - var query = client.query({ + var query = client.query(new Query({ name: 'get names', text: "SELECT name FROM zoom ORDER BY name", rows: 1 - }); + })); checkForResults(query); }) test('with large row count', function() { - var query = client.query({ + var query = client.query(new Query({ name: 'get names', text: 'SELECT name FROM zoom ORDER BY name', rows: 1000 - }) + })) checkForResults(query); }) diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index 77615ff3..5f27e5a4 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -1,4 +1,5 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); +var Query = helper.pg.Query; var util = require('util'); function killIdleQuery(targetQuery) { @@ -39,7 +40,7 @@ test('query killed during query execution of prepared statement', function() { // client should emit an error because it is unexpectedly disconnected assert.emits(client, 'error') - var query1 = client.query(queryConfig, assert.calls(function(err, result) { + var query1 = client.query(new Query(queryConfig), assert.calls(function(err, result) { assert.equal(err.message, 'terminating connection due to administrator command'); })); @@ -63,13 +64,14 @@ test('client end during query execution of prepared statement', function() { var client = new Client(helper.args); client.connect(assert.success(function() { var sleepQuery = 'select pg_sleep($1)'; - var query1 = client.query({ + var query1 = client.query(new Query({ name: 'sleep query', text: sleepQuery, values: [5] }, assert.calls(function(err, result) { assert.equal(err.message, 'Connection terminated'); - })); + }))); + query1.on('error', function(err) { assert.fail('Prepared statement should not emit error'); diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index 3eba4b11..53b59041 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -1,11 +1,12 @@ var helper = require('./test-helper'); var util = require('util'); -const { Query } = helper.pg; +var Query = helper.pg.Query; test('error during query execution', function() { var client = new Client(helper.args); client.connect(assert.success(function() { - var sleepQuery = new Query('select pg_sleep(5)'); + var queryText = 'select pg_sleep(5)' + var sleepQuery = new Query(queryText); var pidColName = 'procpid' var queryColName = 'current_query'; helper.versionGTE(client, '9.2.0', assert.success(function(isGreater) { @@ -26,9 +27,8 @@ test('error during query execution', function() { setTimeout(function() { var client2 = new Client(helper.args); client2.connect(assert.success(function() { - var killIdleQuery = "SELECT " + pidColName + ", (SELECT pg_terminate_backend(" + pidColName + ")) AS killed FROM pg_stat_activity WHERE " + queryColName + " = $1"; - client2.query(killIdleQuery, [sleepQuery], assert.calls(function(err, res) { - console.log('\nresult', res) + var killIdleQuery = `SELECT ${pidColName}, (SELECT pg_cancel_backend(${pidColName})) AS killed FROM pg_stat_activity WHERE ${queryColName} LIKE $1`; + client2.query(killIdleQuery, [queryText], assert.calls(function(err, res) { assert.ifError(err); assert.equal(res.rows.length, 1); client2.end(); diff --git a/test/integration/client/result-metadata-tests.js b/test/integration/client/result-metadata-tests.js index 01363003..221db776 100644 --- a/test/integration/client/result-metadata-tests.js +++ b/test/integration/client/result-metadata-tests.js @@ -20,16 +20,10 @@ test('should return insert metadata', function() { assert.isNull(err); if(hasRowCount) assert.equal(result.rowCount, 1); assert.equal(result.command, 'SELECT'); + done(); process.nextTick(pg.end.bind(pg)); })); })); - - assert.emits(q, 'end', function(result) { - assert.equal(result.command, "INSERT"); - if(hasRowCount) assert.equal(result.rowCount, 1); - done(); - }); - })); })); })); diff --git a/test/integration/client/results-as-array-tests.js b/test/integration/client/results-as-array-tests.js index ef11a891..1a1d8edf 100644 --- a/test/integration/client/results-as-array-tests.js +++ b/test/integration/client/results-as-array-tests.js @@ -26,8 +26,5 @@ test('returns results as array', function() { checkRow(result.rows[0]); client.end(); })); - assert.emits(query, 'row', function(row) { - checkRow(row); - }); })); }); diff --git a/test/integration/client/simple-query-tests.js b/test/integration/client/simple-query-tests.js index e7ffc04a..9453f159 100644 --- a/test/integration/client/simple-query-tests.js +++ b/test/integration/client/simple-query-tests.js @@ -1,10 +1,12 @@ -var helper = require(__dirname+"/test-helper"); +var helper = require("./test-helper"); +var Query = helper.pg.Query; + //before running this test make sure you run the script create-test-tables test("simple query interface", function() { var client = helper.client(); - var query = client.query("select name from person order by name"); + var query = client.query(new Query("select name from person order by name")); client.on('drain', client.end.bind(client)); @@ -36,34 +38,13 @@ test("simple query interface", function() { }); }); -test("simple query interface using addRow", function() { - - var client = helper.client(); - - var query = client.query("select name from person order by name"); - - client.on('drain', client.end.bind(client)); - - query.on('row', function(row, result) { - assert.ok(result); - result.addRow(row); - }); - - query.on('end', function(result) { - assert.lengthIs(result.rows, 26, "result returned wrong number of rows"); - assert.lengthIs(result.rows, result.rowCount); - assert.equal(result.rows[0].name, "Aaron"); - assert.equal(result.rows[25].name, "Zanzabar"); - }); -}); - test("prepared statements do not mutate params", function() { var client = helper.client(); var params = [1] - var query = client.query("select name from person where $1 = 1 order by name", params); + var query = client.query(new Query("select name from person where $1 = 1 order by name", params)); assert.deepEqual(params, [1]) @@ -86,7 +67,7 @@ test("multiple simple queries", function() { var client = helper.client(); client.query({ text: "create temp table bang(id serial, name varchar(5));insert into bang(name) VALUES('boom');"}) client.query("insert into bang(name) VALUES ('yes');"); - var query = client.query("select name from bang"); + var query = client.query(new Query("select name from bang")); assert.emits(query, 'row', function(row) { assert.equal(row['name'], 'boom'); assert.emits(query, 'row', function(row) { @@ -100,7 +81,7 @@ test("multiple select statements", function() { var client = helper.client(); client.query("create temp table boom(age integer); insert into boom(age) values(1); insert into boom(age) values(2); insert into boom(age) values(3)"); client.query({text: "create temp table bang(name varchar(5)); insert into bang(name) values('zoom');"}); - var result = client.query({text: "select age from boom where age < 2; select name from bang"}); + var result = client.query(new Query({text: "select age from boom where age < 2; select name from bang"})); assert.emits(result, 'row', function(row) { assert.strictEqual(row['age'], 1); assert.emits(result, 'row', function(row) { diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index d961c291..98f3148a 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -1,4 +1,5 @@ var helper = require(__dirname + '/test-helper'); +var pg = helper.pg; var sink; var testForTypeCoercion = function(type){ @@ -13,10 +14,10 @@ var testForTypeCoercion = function(type){ assert.isNull(err); })); - var query = client.query({ + var query = client.query(new pg.Query({ name: 'get type ' + type.name , text: 'select col from test_type' - }); + })); query.on('error', function(err) { console.log(err); throw err; @@ -128,11 +129,11 @@ test("timestampz round trip", function() { name: 'add date', values: ['now', now] }); - var result = client.query({ + var result = client.query(new pg.Query({ name: 'get date', text: 'select * from date_tests where name = $1', values: ['now'] - }); + })); assert.emits(result, 'row', function(row) { var date = row.tstz; diff --git a/test/integration/connection-pool/test-helper.js b/test/integration/connection-pool/test-helper.js index 199407cd..e4a3e425 100644 --- a/test/integration/connection-pool/test-helper.js +++ b/test/integration/connection-pool/test-helper.js @@ -17,8 +17,8 @@ helper.testPoolSize = function(max) { client.query("select count(*) as c from person", function(err, result) { assert.equal(result.rows[0].c, 26) }) - var query = client.query("SELECT * FROM NOW()") - query.on('end',function() { + var query = client.query("SELECT * FROM NOW()", (err) => { + assert(!err) sink.add(); done(); }) From e284cfc110da5b86930636765a243bf0fa775932 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 10 Jun 2017 16:47:33 -0500 Subject: [PATCH 14/58] Make all integration tests pass --- test/integration/domain-tests.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/integration/domain-tests.js b/test/integration/domain-tests.js index a51f13dd..c3beae52 100644 --- a/test/integration/domain-tests.js +++ b/test/integration/domain-tests.js @@ -1,6 +1,8 @@ -var helper = require('./test-helper') var async = require('async') +var helper = require('./test-helper') +var Query = helper.pg.Query + var testWithoutDomain = function(cb) { test('no domain', function() { assert(!process.domain) @@ -42,7 +44,7 @@ var testErrorWithDomain = function(cb) { }) domain.run(function() { helper.pg.connect(helper.config, assert.success(function(client, done) { - client.query('SELECT SLDKJFLSKDJF') + client.query(new Query('SELECT SLDKJFLSKDJF')) client.on('drain', done) })) }) From 2add7e3407e8fb97f16f12ba4369d5c0a1db4ff5 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 12 Jun 2017 18:32:34 -0500 Subject: [PATCH 15/58] Make almost all tests pass --- lib/native/index.js | 29 ++++++++++++------- lib/native/query.js | 28 +++++++++++------- .../integration/client/no-row-result-tests.js | 6 ++-- test/integration/gh-issues/131-tests.js | 10 +++---- 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/lib/native/index.js b/lib/native/index.js index 1e192e8b..39bdefff 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -46,6 +46,8 @@ var Client = module.exports = function(config) { this.namedQueries = {}; }; +Client.Query = NativeQuery; + util.inherits(Client, EventEmitter); //connect to the backend @@ -106,34 +108,41 @@ Client.prototype.connect = function(cb) { // optional string rowMode = 'array' for an array of results // } Client.prototype.query = function(config, values, callback) { - var query = new NativeQuery(this.native); + if (typeof config.submit == 'function') { + this._queryQueue.push(config); + this._pulseQueryQueue(); + return config; + } + + var conf = { }; //support query('text', ...) style calls if(typeof config == 'string') { - query.text = config; + conf.text = config; } //support passing everything in via a config object if(typeof config == 'object') { - query.text = config.text; - query.values = config.values; - query.name = config.name; - query.callback = config.callback; - query._arrayMode = config.rowMode == 'array'; + conf.text = config.text; + conf.values = config.values; + conf.name = config.name; + conf.callback = config.callback; + conf.rowMode = config.rowMode; } //support query({...}, function() {}) style calls //& support query(..., ['values'], ...) style calls if(typeof values == 'function') { - query.callback = values; + conf.callback = values; } else if(util.isArray(values)) { - query.values = values; + conf.values = values; } if(typeof callback == 'function') { - query.callback = callback; + conf.callback = callback; } + var query = new NativeQuery(conf); this._queryQueue.push(query); this._pulseQueryQueue(); return query; diff --git a/lib/native/query.js b/lib/native/query.js index a827af73..5d6b5881 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -11,15 +11,20 @@ var util = require('util'); var utils = require('../utils'); var NativeResult = require('./result'); -var NativeQuery = module.exports = function(native) { +var NativeQuery = module.exports = function(config, values) { EventEmitter.call(this); - this.native = native; - this.text = null; - this.values = null; - this.name = null; - this.callback = null; + if (typeof config == 'string') { + config = { + text: config, + values: values, + }; + } + this.text = config.text; + this.values = config.values; + this.name = config.name; + this.callback = config.callback; this.state = 'new'; - this._arrayMode = false; + this._arrayMode = config.rowMode == 'array'; //if the 'row' event is listened for //then emit them as they come in @@ -87,6 +92,7 @@ NativeQuery.prototype.handleError = function(err) { NativeQuery.prototype.submit = function(client) { this.state = 'running'; var self = this; + this.native = client.native; client.native.arrayMode = this._arrayMode; var after = function(err, rows) { @@ -136,10 +142,10 @@ NativeQuery.prototype.submit = function(client) { //check if the client has already executed this named query //if so...just execute it again - skip the planning phase if(client.namedQueries[this.name]) { - return this.native.execute(this.name, values, after); + return client.native.execute(this.name, values, after); } //plan the named query the first time, then execute it - return this.native.prepare(this.name, this.text, values.length, function(err) { + return client.native.prepare(this.name, this.text, values.length, function(err) { if(err) return after(err); client.namedQueries[self.name] = true; return self.native.execute(self.name, values, after); @@ -147,8 +153,8 @@ NativeQuery.prototype.submit = function(client) { } else if(this.values) { var vals = this.values.map(utils.prepareValue); - this.native.query(this.text, vals, after); + client.native.query(this.text, vals, after); } else { - this.native.query(this.text, after); + client.native.query(this.text, after); } }; diff --git a/test/integration/client/no-row-result-tests.js b/test/integration/client/no-row-result-tests.js index 1929b162..99ed0da7 100644 --- a/test/integration/client/no-row-result-tests.js +++ b/test/integration/client/no-row-result-tests.js @@ -3,8 +3,10 @@ var pg = helper.pg; var config = helper.config; test('can access results when no rows are returned', function() { - console.log('maybe fix this?', __filename) - if(config.native) return false; + if(config.native) { + console.log('maybe fix this?', __filename) + return false + } var checkResult = function(result) { assert(result.fields, 'should have fields definition'); assert.equal(result.fields.length, 1); diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index f733ea70..62bad27c 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -1,13 +1,13 @@ -var helper = require(__dirname + "/../test-helper"); +var helper = require('../test-helper'); var pg = helper.pg; -test('parsing array results', function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { +test('parsing array results', function () { + pg.connect(helper.config, assert.calls(function (err, client, done) { assert.isNull(err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])"); client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log); - test('decimals', function() { - client.query('SELECT decimals FROM why', assert.success(function(result) { + test('decimals', function () { + client.query('SELECT decimals FROM why', assert.success(function (result) { assert.lengthIs(result.rows[0].decimals, 3); assert.equal(result.rows[0].decimals[0], 0.1); assert.equal(result.rows[0].decimals[1], 0.05); From d3ec938b82f3bd999e1fc189b49931627eac401b Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 11:15:21 -0500 Subject: [PATCH 16/58] Fix remainder of error tests --- Makefile | 2 ++ lib/native/index.js | 4 ++++ lib/native/query.js | 9 ++------ ...error-handling-prepared-statement-tests.js | 21 ++++++++++++------- .../client/query-error-handling-tests.js | 12 +++++------ 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 4eddd4f1..0da68207 100644 --- a/Makefile +++ b/Makefile @@ -36,8 +36,10 @@ test-connection: test-missing-native: @echo "***Testing optional native install***" @rm -rf node_modules/pg-native + @rm -rf node_modules/libpq @node test/native/missing-native.js @rm -rf node_modules/pg-native + @rm -rf node_modules/libpq node_modules/pg-native/index.js: @npm i pg-native diff --git a/lib/native/index.js b/lib/native/index.js index 39bdefff..c76953d0 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -109,6 +109,10 @@ Client.prototype.connect = function(cb) { // } Client.prototype.query = function(config, values, callback) { if (typeof config.submit == 'function') { + // accept query(new Query(...), (err, res) => { }) style + if (typeof values == 'function') { + config.callback = values; + } this._queryQueue.push(config); this._pulseQueryQueue(); return config; diff --git a/lib/native/query.js b/lib/native/query.js index 5d6b5881..708585f4 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -11,14 +11,9 @@ var util = require('util'); var utils = require('../utils'); var NativeResult = require('./result'); -var NativeQuery = module.exports = function(config, values) { +var NativeQuery = module.exports = function(config, values, callback) { EventEmitter.call(this); - if (typeof config == 'string') { - config = { - text: config, - values: values, - }; - } + config = utils.normalizeQueryConfig(config, values, callback); this.text = config.text; this.values = config.values; this.name = config.name; diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index 5f27e5a4..e301ab68 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -64,24 +64,29 @@ test('client end during query execution of prepared statement', function() { var client = new Client(helper.args); client.connect(assert.success(function() { var sleepQuery = 'select pg_sleep($1)'; - var query1 = client.query(new Query({ + + var queryConfig = { name: 'sleep query', text: sleepQuery, - values: [5] }, - assert.calls(function(err, result) { - assert.equal(err.message, 'Connection terminated'); - }))); + values: [5], + } + + var queryInstance = new Query(queryConfig, assert.calls(function (err, result) { + assert.equal(err.message, 'Connection terminated'); + })) + + var query1 = client.query(queryInstance); - query1.on('error', function(err) { + query1.on('error', function (err) { assert.fail('Prepared statement should not emit error'); }); - query1.on('row', function(row) { + query1.on('row', function (row) { assert.fail('Prepared statement should not emit row'); }); - query1.on('end', function(err) { + query1.on('end', function (err) { assert.fail('Prepared statement when executed should not return before being killed'); }); diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index 53b59041..2e28737d 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -40,7 +40,9 @@ test('error during query execution', function() { })); }); -if(helper.config.native) return; +if (helper.config.native) { + return console.log("\nTODO: this should work on native as well") +} test('9.3 column error fields', function() { var client = new Client(helper.args); @@ -50,12 +52,10 @@ test('9.3 column error fields', function() { return client.end(); } - client.query('DROP TABLE IF EXISTS column_err_test'); - client.query('CREATE TABLE column_err_test(a int NOT NULL)'); + client.query('CREATE TEMP TABLE column_err_test(a int NOT NULL)'); client.query('INSERT INTO column_err_test(a) VALUES (NULL)', function (err) { assert.equal(err.severity, 'ERROR'); assert.equal(err.code, '23502'); - assert.equal(err.schema, 'public'); assert.equal(err.table, 'column_err_test'); assert.equal(err.column, 'a'); return client.end(); @@ -73,13 +73,11 @@ test('9.3 constraint error fields', function() { return client.end(); } - client.query('DROP TABLE IF EXISTS constraint_err_test'); - client.query('CREATE TABLE constraint_err_test(a int PRIMARY KEY)'); + client.query('CREATE TEMP TABLE constraint_err_test(a int PRIMARY KEY)'); client.query('INSERT INTO constraint_err_test(a) VALUES (1)'); client.query('INSERT INTO constraint_err_test(a) VALUES (1)', function (err) { assert.equal(err.severity, 'ERROR'); assert.equal(err.code, '23505'); - assert.equal(err.schema, 'public'); assert.equal(err.table, 'constraint_err_test'); assert.equal(err.constraint, 'constraint_err_test_pkey'); return client.end(); From 970d83aca45b04f404ec79b001c61ca5d7230cfe Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 11:20:47 -0500 Subject: [PATCH 17/58] Remove weird quasi-promise interface on JS query --- lib/query.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/query.js b/lib/query.js index 4d49dafd..b36cf6b8 100644 --- a/lib/query.js +++ b/lib/query.js @@ -40,23 +40,6 @@ var Query = function(config, values, callback) { util.inherits(Query, EventEmitter); -Query.prototype.then = function(onSuccess, onFailure) { - return this.promise().then(onSuccess, onFailure); -}; - -Query.prototype.catch = function(callback) { - return this.promise().catch(callback); -}; - -Query.prototype.promise = function() { - if (this._promise) return this._promise; - this._promise = new Promise(function(resolve, reject) { - this.once('end', resolve); - this.once('error', reject); - }.bind(this)); - return this._promise; -}; - Query.prototype.requiresPreparation = function() { //named queries must always be prepared if(this.name) { return true; } From df36bece86cecfba03d44d872d7426275f91c489 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 11:21:24 -0500 Subject: [PATCH 18/58] Restructure native file paths Make file paths more closely match the non-native files, to make auto-complete file names slightly easier. --- lib/native/client.js | 214 ++++++++++++++++++++++++++++++++++++++++++ lib/native/index.js | 215 +------------------------------------------ 2 files changed, 215 insertions(+), 214 deletions(-) create mode 100644 lib/native/client.js diff --git a/lib/native/client.js b/lib/native/client.js new file mode 100644 index 00000000..c76953d0 --- /dev/null +++ b/lib/native/client.js @@ -0,0 +1,214 @@ +/** + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) + * All rights reserved. + * + * This source code is licensed under the MIT license found in the + * README.md file in the root directory of this source tree. + */ + +var Native = require('pg-native'); +var TypeOverrides = require('../type-overrides'); +var semver = require('semver'); +var pkg = require('../../package.json'); +var assert = require('assert'); +var EventEmitter = require('events').EventEmitter; +var util = require('util'); +var ConnectionParameters = require('../connection-parameters'); + +var msg = 'Version >= ' + pkg.minNativeVersion + ' of pg-native required.'; +assert(semver.gte(Native.version, pkg.minNativeVersion), msg); + +var NativeQuery = require('./query'); + +var Client = module.exports = function(config) { + EventEmitter.call(this); + config = config || {}; + + this._types = new TypeOverrides(config.types); + + this.native = new Native({ + types: this._types + }); + + this._queryQueue = []; + this._connected = false; + + //keep these on the object for legacy reasons + //for the time being. TODO: deprecate all this jazz + var cp = this.connectionParameters = new ConnectionParameters(config); + this.user = cp.user; + this.password = cp.password; + this.database = cp.database; + this.host = cp.host; + this.port = cp.port; + + //a hash to hold named queries + this.namedQueries = {}; +}; + +Client.Query = NativeQuery; + +util.inherits(Client, EventEmitter); + +//connect to the backend +//pass an optional callback to be called once connected +//or with an error if there was a connection error +//if no callback is passed and there is a connection error +//the client will emit an error event. +Client.prototype.connect = function(cb) { + var self = this; + + var onError = function(err) { + if(cb) return cb(err); + return self.emit('error', err); + }; + + this.connectionParameters.getLibpqConnectionString(function(err, conString) { + if(err) return onError(err); + self.native.connect(conString, function(err) { + if(err) return onError(err); + + //set internal states to connected + self._connected = true; + + //handle connection errors from the native layer + self.native.on('error', function(err) { + //error will be handled by active query + if(self._activeQuery && self._activeQuery.state != 'end') { + return; + } + self.emit('error', err); + }); + + self.native.on('notification', function(msg) { + self.emit('notification', { + channel: msg.relname, + payload: msg.extra + }); + }); + + //signal we are connected now + self.emit('connect'); + self._pulseQueryQueue(true); + + //possibly call the optional callback + if(cb) cb(); + }); + }); +}; + +//send a query to the server +//this method is highly overloaded to take +//1) string query, optional array of parameters, optional function callback +//2) object query with { +// string query +// optional array values, +// optional function callback instead of as a separate parameter +// optional string name to name & cache the query plan +// optional string rowMode = 'array' for an array of results +// } +Client.prototype.query = function(config, values, callback) { + if (typeof config.submit == 'function') { + // accept query(new Query(...), (err, res) => { }) style + if (typeof values == 'function') { + config.callback = values; + } + this._queryQueue.push(config); + this._pulseQueryQueue(); + return config; + } + + var conf = { }; + + //support query('text', ...) style calls + if(typeof config == 'string') { + conf.text = config; + } + + //support passing everything in via a config object + if(typeof config == 'object') { + conf.text = config.text; + conf.values = config.values; + conf.name = config.name; + conf.callback = config.callback; + conf.rowMode = config.rowMode; + } + + //support query({...}, function() {}) style calls + //& support query(..., ['values'], ...) style calls + if(typeof values == 'function') { + conf.callback = values; + } + else if(util.isArray(values)) { + conf.values = values; + } + if(typeof callback == 'function') { + conf.callback = callback; + } + + var query = new NativeQuery(conf); + this._queryQueue.push(query); + this._pulseQueryQueue(); + return query; +}; + +//disconnect from the backend server +Client.prototype.end = function(cb) { + var self = this; + if(!this._connected) { + this.once('connect', this.end.bind(this, cb)); + } + this.native.end(function() { + //send an error to the active query + if(self._hasActiveQuery()) { + var msg = 'Connection terminated'; + self._queryQueue.length = 0; + self._activeQuery.handleError(new Error(msg)); + } + self.emit('end'); + if(cb) cb(); + }); +}; + +Client.prototype._hasActiveQuery = function() { + return this._activeQuery && this._activeQuery.state != 'error' && this._activeQuery.state != 'end'; +}; + +Client.prototype._pulseQueryQueue = function(initialConnection) { + if(!this._connected) { + return; + } + if(this._hasActiveQuery()) { + return; + } + var query = this._queryQueue.shift(); + if(!query) { + if(!initialConnection) { + this.emit('drain'); + } + return; + } + this._activeQuery = query; + query.submit(this); + var self = this; + query.once('_done', function() { + self._pulseQueryQueue(); + }); +}; + +//attempt to cancel an in-progress query +Client.prototype.cancel = function(query) { + if(this._activeQuery == query) { + this.native.cancel(function() {}); + } else if (this._queryQueue.indexOf(query) != -1) { + this._queryQueue.splice(this._queryQueue.indexOf(query), 1); + } +}; + +Client.prototype.setTypeParser = function(oid, format, parseFn) { + return this._types.setTypeParser(oid, format, parseFn); +}; + +Client.prototype.getTypeParser = function(oid, format) { + return this._types.getTypeParser(oid, format); +}; diff --git a/lib/native/index.js b/lib/native/index.js index c76953d0..a35a2733 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -1,214 +1 @@ -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ - -var Native = require('pg-native'); -var TypeOverrides = require('../type-overrides'); -var semver = require('semver'); -var pkg = require('../../package.json'); -var assert = require('assert'); -var EventEmitter = require('events').EventEmitter; -var util = require('util'); -var ConnectionParameters = require('../connection-parameters'); - -var msg = 'Version >= ' + pkg.minNativeVersion + ' of pg-native required.'; -assert(semver.gte(Native.version, pkg.minNativeVersion), msg); - -var NativeQuery = require('./query'); - -var Client = module.exports = function(config) { - EventEmitter.call(this); - config = config || {}; - - this._types = new TypeOverrides(config.types); - - this.native = new Native({ - types: this._types - }); - - this._queryQueue = []; - this._connected = false; - - //keep these on the object for legacy reasons - //for the time being. TODO: deprecate all this jazz - var cp = this.connectionParameters = new ConnectionParameters(config); - this.user = cp.user; - this.password = cp.password; - this.database = cp.database; - this.host = cp.host; - this.port = cp.port; - - //a hash to hold named queries - this.namedQueries = {}; -}; - -Client.Query = NativeQuery; - -util.inherits(Client, EventEmitter); - -//connect to the backend -//pass an optional callback to be called once connected -//or with an error if there was a connection error -//if no callback is passed and there is a connection error -//the client will emit an error event. -Client.prototype.connect = function(cb) { - var self = this; - - var onError = function(err) { - if(cb) return cb(err); - return self.emit('error', err); - }; - - this.connectionParameters.getLibpqConnectionString(function(err, conString) { - if(err) return onError(err); - self.native.connect(conString, function(err) { - if(err) return onError(err); - - //set internal states to connected - self._connected = true; - - //handle connection errors from the native layer - self.native.on('error', function(err) { - //error will be handled by active query - if(self._activeQuery && self._activeQuery.state != 'end') { - return; - } - self.emit('error', err); - }); - - self.native.on('notification', function(msg) { - self.emit('notification', { - channel: msg.relname, - payload: msg.extra - }); - }); - - //signal we are connected now - self.emit('connect'); - self._pulseQueryQueue(true); - - //possibly call the optional callback - if(cb) cb(); - }); - }); -}; - -//send a query to the server -//this method is highly overloaded to take -//1) string query, optional array of parameters, optional function callback -//2) object query with { -// string query -// optional array values, -// optional function callback instead of as a separate parameter -// optional string name to name & cache the query plan -// optional string rowMode = 'array' for an array of results -// } -Client.prototype.query = function(config, values, callback) { - if (typeof config.submit == 'function') { - // accept query(new Query(...), (err, res) => { }) style - if (typeof values == 'function') { - config.callback = values; - } - this._queryQueue.push(config); - this._pulseQueryQueue(); - return config; - } - - var conf = { }; - - //support query('text', ...) style calls - if(typeof config == 'string') { - conf.text = config; - } - - //support passing everything in via a config object - if(typeof config == 'object') { - conf.text = config.text; - conf.values = config.values; - conf.name = config.name; - conf.callback = config.callback; - conf.rowMode = config.rowMode; - } - - //support query({...}, function() {}) style calls - //& support query(..., ['values'], ...) style calls - if(typeof values == 'function') { - conf.callback = values; - } - else if(util.isArray(values)) { - conf.values = values; - } - if(typeof callback == 'function') { - conf.callback = callback; - } - - var query = new NativeQuery(conf); - this._queryQueue.push(query); - this._pulseQueryQueue(); - return query; -}; - -//disconnect from the backend server -Client.prototype.end = function(cb) { - var self = this; - if(!this._connected) { - this.once('connect', this.end.bind(this, cb)); - } - this.native.end(function() { - //send an error to the active query - if(self._hasActiveQuery()) { - var msg = 'Connection terminated'; - self._queryQueue.length = 0; - self._activeQuery.handleError(new Error(msg)); - } - self.emit('end'); - if(cb) cb(); - }); -}; - -Client.prototype._hasActiveQuery = function() { - return this._activeQuery && this._activeQuery.state != 'error' && this._activeQuery.state != 'end'; -}; - -Client.prototype._pulseQueryQueue = function(initialConnection) { - if(!this._connected) { - return; - } - if(this._hasActiveQuery()) { - return; - } - var query = this._queryQueue.shift(); - if(!query) { - if(!initialConnection) { - this.emit('drain'); - } - return; - } - this._activeQuery = query; - query.submit(this); - var self = this; - query.once('_done', function() { - self._pulseQueryQueue(); - }); -}; - -//attempt to cancel an in-progress query -Client.prototype.cancel = function(query) { - if(this._activeQuery == query) { - this.native.cancel(function() {}); - } else if (this._queryQueue.indexOf(query) != -1) { - this._queryQueue.splice(this._queryQueue.indexOf(query), 1); - } -}; - -Client.prototype.setTypeParser = function(oid, format, parseFn) { - return this._types.setTypeParser(oid, format, parseFn); -}; - -Client.prototype.getTypeParser = function(oid, format) { - return this._types.getTypeParser(oid, format); -}; +module.exports = require('./client') From 55c3b3691cc3e095aa7a4b6a8d27daddd2360f9a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 11:23:15 -0500 Subject: [PATCH 19/58] Use normalizeQueryConfig in native query --- lib/native/client.js | 30 +----------------------------- lib/native/index.js | 2 +- 2 files changed, 2 insertions(+), 30 deletions(-) diff --git a/lib/native/client.js b/lib/native/client.js index c76953d0..e7e17b08 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -118,35 +118,7 @@ Client.prototype.query = function(config, values, callback) { return config; } - var conf = { }; - - //support query('text', ...) style calls - if(typeof config == 'string') { - conf.text = config; - } - - //support passing everything in via a config object - if(typeof config == 'object') { - conf.text = config.text; - conf.values = config.values; - conf.name = config.name; - conf.callback = config.callback; - conf.rowMode = config.rowMode; - } - - //support query({...}, function() {}) style calls - //& support query(..., ['values'], ...) style calls - if(typeof values == 'function') { - conf.callback = values; - } - else if(util.isArray(values)) { - conf.values = values; - } - if(typeof callback == 'function') { - conf.callback = callback; - } - - var query = new NativeQuery(conf); + var query = new NativeQuery(config, values, callback); this._queryQueue.push(query); this._pulseQueryQueue(); return query; diff --git a/lib/native/index.js b/lib/native/index.js index a35a2733..ccf987e3 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -1 +1 @@ -module.exports = require('./client') +module.exports = require('./client'); From bc2f5504029c3c29a751736b0406f4fcda94e78c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 11:43:15 -0500 Subject: [PATCH 20/58] Remove promise-interop from native query --- lib/native/client.js | 7 ++++- lib/native/query.js | 17 ----------- test/native/error-tests.js | 28 ------------------- test/native/evented-api-tests.js | 48 ++++++++------------------------ test/native/stress-tests.js | 5 ++-- 5 files changed, 20 insertions(+), 85 deletions(-) diff --git a/lib/native/client.js b/lib/native/client.js index e7e17b08..e57a9419 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -119,9 +119,14 @@ Client.prototype.query = function(config, values, callback) { } var query = new NativeQuery(config, values, callback); + var result = query.callback ? query : new global.Promise(function(resolve, reject) { + query.on('end', resolve); + query.on('error', reject); + }); + this._queryQueue.push(query); this._pulseQueryQueue(); - return query; + return result; }; //disconnect from the backend server diff --git a/lib/native/query.js b/lib/native/query.js index 708585f4..1523e7c7 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -34,23 +34,6 @@ var NativeQuery = module.exports = function(config, values, callback) { util.inherits(NativeQuery, EventEmitter); -NativeQuery.prototype.then = function(onSuccess, onFailure) { - return this.promise().then(onSuccess, onFailure); -}; - -NativeQuery.prototype.catch = function(callback) { - return this.promise().catch(callback); -}; - -NativeQuery.prototype.promise = function() { - if (this._promise) return this._promise; - this._promise = new Promise(function(resolve, reject) { - this.once('end', resolve); - this.once('error', reject); - }.bind(this)); - return this._promise; -}; - var errorFieldMap = { 'sqlState': 'code', 'statementPosition': 'position', diff --git a/test/native/error-tests.js b/test/native/error-tests.js index 3a932705..2edf3421 100644 --- a/test/native/error-tests.js +++ b/test/native/error-tests.js @@ -1,34 +1,6 @@ var helper = require(__dirname + "/../test-helper"); var Client = require(__dirname + "/../../lib/native"); -test('query with non-text as first parameter throws error', function() { - var client = new Client(helper.config); - client.connect(); - assert.emits(client, 'connect', function() { - 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() { - 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); diff --git a/test/native/evented-api-tests.js b/test/native/evented-api-tests.js index 9bff3410..122dc47e 100644 --- a/test/native/evented-api-tests.js +++ b/test/native/evented-api-tests.js @@ -1,5 +1,6 @@ -var helper = require(__dirname + "/../test-helper"); -var Client = require(__dirname + "/../../lib/native"); +var helper = require("../test-helper"); +var Client = require("../../lib/native"); +var Query = Client.Query; var setupClient = function() { var client = new Client(helper.config); @@ -10,37 +11,10 @@ var setupClient = function() { return client; } -//test('connects', function() { - //var client = new Client(helper.config); - //client.connect(); - //test('good query', function() { - //var query = client.query("SELECT 1 as num, 'HELLO' as str"); - //assert.emits(query, 'row', function(row) { - //test('has integer data type', function() { - //assert.strictEqual(row.num, 1); - //}) - //test('has string data type', function() { - //assert.strictEqual(row.str, "HELLO") - //}) - //test('emits end AFTER row event', function() { - //assert.emits(query, 'end'); - //test('error query', function() { - //var query = client.query("LSKDJF"); - //assert.emits(query, 'error', function(err) { - //assert.ok(err != null, "Should not have emitted null error"); - //client.end(); - //}) - //}) - //}) - //}) - //}) -//}) - - test('multiple results', function() { test('queued queries', function() { var client = setupClient(); - var q = client.query("SELECT name FROM BOOM"); + var q = client.query(new Query("SELECT name FROM BOOM")); assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Aaron'); assert.emits(q, 'row', function(row) { @@ -49,7 +23,7 @@ test('multiple results', function() { }) assert.emits(q, 'end', function() { test('query with config', function() { - var q2 = client.query({text:'SELECT 1 as num'}); + var q2 = client.query(new Query({text:'SELECT 1 as num'})); assert.emits(q2, 'row', function(row) { assert.strictEqual(row.num, 1); assert.emits(q2, 'end', function() { @@ -64,7 +38,7 @@ test('multiple results', function() { test('parameterized queries', function() { test('with a single string param', function() { var client = setupClient(); - var q = client.query("SELECT * FROM boom WHERE name = $1", ['Aaron']); + var q = client.query(new Query("SELECT * FROM boom WHERE name = $1", ['Aaron'])); assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Aaron'); }) @@ -75,10 +49,10 @@ test('parameterized queries', function() { test('with object config for query', function() { var client = setupClient(); - var q = client.query({ + var q = client.query(new Query({ text: "SELECT name FROM boom WHERE name = $1", values: ['Brian'] - }); + })); assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Brian'); }) @@ -89,7 +63,7 @@ test('parameterized queries', function() { test('multiple parameters', function() { var client = setupClient(); - var q = client.query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name', ['Aaron', 'Brian']); + var q = client.query(new Query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name', ['Aaron', 'Brian'])); assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Aaron'); assert.emits(q, 'row', function(row) { @@ -100,10 +74,10 @@ test('parameterized queries', function() { }) }) }) - + test('integer parameters', function() { var client = setupClient(); - var q = client.query('SELECT * FROM boom WHERE age > $1', [27]); + var q = client.query(new Query('SELECT * FROM boom WHERE age > $1', [27])); assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Brian'); assert.equal(row.age, 28); diff --git a/test/native/stress-tests.js b/test/native/stress-tests.js index bd2bca5a..08fab97e 100644 --- a/test/native/stress-tests.js +++ b/test/native/stress-tests.js @@ -1,10 +1,11 @@ var helper = require(__dirname + "/../test-helper"); var Client = require(__dirname + "/../../lib/native"); +var Query = Client.Query; test('many rows', function() { var client = new Client(helper.config); client.connect(); - var q = client.query("SELECT * FROM person"); + var q = client.query(new Query("SELECT * FROM person")); var rows = []; q.on('row', function(row) { rows.push(row) @@ -21,7 +22,7 @@ test('many queries', function() { var count = 0; var expected = 100; for(var i = 0; i < expected; i++) { - var q = client.query("SELECT * FROM person"); + var q = client.query(new Query("SELECT * FROM person")); assert.emits(q, 'end', function() { count++; }); From 02bcc9d97af454b56106fd080146e5c8e1828586 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 12:54:07 -0500 Subject: [PATCH 21/58] Start working on promsie tests --- lib/client.js | 133 +++++++++++-------- test/integration/client/promise-api-tests.js | 105 +++++++++++++++ 2 files changed, 182 insertions(+), 56 deletions(-) create mode 100644 test/integration/client/promise-api-tests.js diff --git a/lib/client.js b/lib/client.js index 32ea76b9..3a8515a4 100644 --- a/lib/client.js +++ b/lib/client.js @@ -108,56 +108,21 @@ Client.prototype.connect = function(callback) { self.secretKey = msg.secretKey; }); + + con.on('readyForQuery', function() { + var activeQuery = self.activeQuery; + self.activeQuery = null; + self.readyForQuery = true; + self._pulseQueryQueue(); + if(activeQuery) { + activeQuery.handleReadyForQuery(con); + } + }); + //hook up query handling events to connection //after the connection initially becomes ready for queries con.once('readyForQuery', function() { - self._connecting = false; - - //delegate rowDescription to active query - con.on('rowDescription', function(msg) { - self.activeQuery.handleRowDescription(msg); - }); - - //delegate dataRow to active query - con.on('dataRow', function(msg) { - self.activeQuery.handleDataRow(msg); - }); - - //delegate portalSuspended to active query - con.on('portalSuspended', function(msg) { - self.activeQuery.handlePortalSuspended(con); - }); - - //deletagate emptyQuery to active query - con.on('emptyQuery', function(msg) { - self.activeQuery.handleEmptyQuery(con); - }); - - //delegate commandComplete to active query - con.on('commandComplete', function(msg) { - self.activeQuery.handleCommandComplete(msg, con); - }); - - //if a prepared statement has a name and properly parses - //we track that its already been executed so we don't parse - //it again on the same client - con.on('parseComplete', function(msg) { - if(self.activeQuery.name) { - con.parsedStatements[self.activeQuery.name] = true; - } - }); - - con.on('copyInResponse', function(msg) { - self.activeQuery.handleCopyInResponse(self.connection); - }); - - con.on('copyData', function (msg) { - self.activeQuery.handleCopyData(msg, self.connection); - }); - - con.on('notification', function(msg) { - self.emit('notification', msg); - }); + self._attachEventListeners(con) //process possible callback argument to Client#connect if (callback) { @@ -169,15 +134,15 @@ Client.prototype.connect = function(callback) { self.emit('connect'); }); - con.on('readyForQuery', function() { - var activeQuery = self.activeQuery; - self.activeQuery = null; - self.readyForQuery = true; - self._pulseQueryQueue(); - if(activeQuery) { - activeQuery.handleReadyForQuery(con); - } - }); + if (!callback) { + return new global.Promise(function (resolve, reject) { + con.once('connect', () => { + con.removeListener('error', reject) + resolve() + }) + con.once('error', reject) + }) + } con.on('error', function(error) { if(this.activeQuery) { @@ -234,6 +199,58 @@ Client.prototype.connect = function(callback) { }; +// once a connection is established connect listeners +Client.prototype._attachEventListeners = function(con) { + var self = this; + self._connecting = false; + + //delegate rowDescription to active query + con.on('rowDescription', function(msg) { + self.activeQuery.handleRowDescription(msg); + }); + + //delegate dataRow to active query + con.on('dataRow', function(msg) { + self.activeQuery.handleDataRow(msg); + }); + + //delegate portalSuspended to active query + con.on('portalSuspended', function(msg) { + self.activeQuery.handlePortalSuspended(con); + }); + + //deletagate emptyQuery to active query + con.on('emptyQuery', function(msg) { + self.activeQuery.handleEmptyQuery(con); + }); + + //delegate commandComplete to active query + con.on('commandComplete', function(msg) { + self.activeQuery.handleCommandComplete(msg, con); + }); + + //if a prepared statement has a name and properly parses + //we track that its already been executed so we don't parse + //it again on the same client + con.on('parseComplete', function(msg) { + if(self.activeQuery.name) { + con.parsedStatements[self.activeQuery.name] = true; + } + }); + + con.on('copyInResponse', function(msg) { + self.activeQuery.handleCopyInResponse(self.connection); + }); + + con.on('copyData', function (msg) { + self.activeQuery.handleCopyData(msg, self.connection); + }); + + con.on('notification', function(msg) { + self.emit('notification', msg); + }); +} + Client.prototype.getStartupConf = function() { var params = this.connectionParameters; @@ -391,6 +408,10 @@ Client.prototype.end = function(cb) { this.connection.end(); if (cb) { this.connection.once('end', cb); + } else { + return new global.Promise((resolve) => { + this.connection.once('end', resolve); + }); } }; diff --git a/test/integration/client/promise-api-tests.js b/test/integration/client/promise-api-tests.js new file mode 100644 index 00000000..783fb46c --- /dev/null +++ b/test/integration/client/promise-api-tests.js @@ -0,0 +1,105 @@ +const async = require('async') +const helper = require('./test-helper') +const pg = helper.pg; + +class Test { + constructor(name, cb) { + this.name = name + this.action = cb + this.timeout = 5000 + } + + run(cb) { + try { + this._run(cb) + } catch (e) { + cb(e) + } + } + + _run(cb) { + if (!this.action) { + console.log(`${this.name} skipped`) + return cb() + } + if (!this.action.length) { + const result = this.action.call(this) + if ((result || 0).then) { + result + .then(() => cb()) + .catch(err => cb(err || new Error('Unhandled promise rejection'))) + } + } else { + this.action.call(this, cb) + } + } +} + +class Suite { + constructor() { + console.log('') + this._queue = async.queue(this.run.bind(this), 1) + this._queue.drain = () => { } + } + + run(test, cb) { + const tid = setTimeout(() => { + const err = Error(`test: ${test.name} did not complete withint ${test.timeout}ms`) + cb(err) + }, test.timeout) + test.run((err) => { + clearTimeout(tid) + if (err) { + console.log(test.name + ' FAILED!', err.stack) + } else { + console.log(test.name) + } + cb(err) + }) + } + + test(name, cb) { + this._queue.push(new Test(name, cb)) + } +} + +const suite = new Suite() + +suite.test('valid connection completes promise', () => { + const client = new pg.Client() + return client.connect() + .then(() => { + return client.end() + .then(() => { }) + }) +}) + +suite.test('valid connection completes promise', () => { + const client = new pg.Client() + return client.connect() + .then(() => { + return client.end() + .then(() => { }) + }) +}) + + +suite.test('invalid connection rejects promise', (done) => { + const client = new pg.Client({ host: 'alksdjflaskdfj' }) + return client.connect() + .catch(e => { + assert(e instanceof Error) + done() + }) +}) + +suite.test('connected client does not reject promise after', (done) => { + const client = new pg.Client() + return client.connect() + .then(() => { + setTimeout(() => { + // manually kill the connection + client.connection.stream.end() + }, 50) + }) +}) From 3a7b226fe3e6a0e1400fc05df4ce33c7a8a6e86c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 16:55:56 -0500 Subject: [PATCH 22/58] WIP --- lib/client.js | 35 +-- lib/connection.js | 7 +- lib/promise.js | 12 + .../client/error-handling-tests.js | 236 +++++++----------- test/integration/client/promise-api-tests.js | 72 +----- ...error-handling-prepared-statement-tests.js | 16 +- test/suite.js | 74 ++++++ test/test-helper.js | 1 + 8 files changed, 226 insertions(+), 227 deletions(-) create mode 100644 lib/promise.js create mode 100644 test/suite.js diff --git a/lib/client.js b/lib/client.js index 3a8515a4..3104f70b 100644 --- a/lib/client.js +++ b/lib/client.js @@ -67,12 +67,12 @@ Client.prototype.connect = function(callback) { if(self.ssl) { con.requestSsl(); } else { - con.startup(self.getStartupConf()); + con.startup(self._getStartupConfiguration()); } }); con.on('sslconnect', function() { - con.startup(self.getStartupConf()); + con.startup(self._getStartupConfiguration()); }); function checkPgPass(cb) { @@ -122,7 +122,7 @@ Client.prototype.connect = function(callback) { //hook up query handling events to connection //after the connection initially becomes ready for queries con.once('readyForQuery', function() { - self._attachEventListeners(con) + self._attachEventListeners(con); //process possible callback argument to Client#connect if (callback) { @@ -134,16 +134,6 @@ Client.prototype.connect = function(callback) { self.emit('connect'); }); - if (!callback) { - return new global.Promise(function (resolve, reject) { - con.once('connect', () => { - con.removeListener('error', reject) - resolve() - }) - con.once('error', reject) - }) - } - con.on('error', function(error) { if(this.activeQuery) { var activeQuery = self.activeQuery; @@ -197,8 +187,22 @@ Client.prototype.connect = function(callback) { self.emit('notice', msg); }); + var result; + + if (!callback) { + result = new global.Promise(function (resolve, reject) { + con.once('connect', function () { + con.removeListener('error', reject) + resolve() + }) + this.once('error', reject) + }.bind(this)) + } + + return result; }; + // once a connection is established connect listeners Client.prototype._attachEventListeners = function(con) { var self = this; @@ -251,7 +255,7 @@ Client.prototype._attachEventListeners = function(con) { }); } -Client.prototype.getStartupConf = function() { +Client.prototype._getStartupConfiguration = function() { var params = this.connectionParameters; var data = { @@ -405,6 +409,9 @@ Client.prototype.query = function(config, values, callback) { Client.prototype.end = function(cb) { this._ending = true; + if (this.activeQuery) { + return this.connection.stream.end() + } this.connection.end(); if (cb) { this.connection.once('end', cb); diff --git a/lib/connection.js b/lib/connection.js index 6bda2f8b..c40639e0 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -186,7 +186,9 @@ Connection.prototype.password = function(password) { }; Connection.prototype._send = function(code, more) { - if(!this.stream.writable) { return false; } + if(!this.stream.writable) { + return false; + } if(more === true) { this.writer.addHeader(code); } else { @@ -308,11 +310,12 @@ Connection.prototype.sync = function() { this._send(0x53); }; +const END_BUFFER = new Buffer([0x58, 0x00, 0x00, 0x00, 0x04]); Connection.prototype.end = function() { //0x58 = 'X' this.writer.add(emptyBuffer); this._ending = true; - this._send(0x58); + return this.stream.end(END_BUFFER); }; Connection.prototype.close = function(msg, more) { diff --git a/lib/promise.js b/lib/promise.js new file mode 100644 index 00000000..4d308cb9 --- /dev/null +++ b/lib/promise.js @@ -0,0 +1,12 @@ +const util = require('util') +const deprecationMessage = 'Using the promise result as an event emitter is deprecated and will be removed in pg@8.0' +module.exports = function(emitter, callback) { + const promise = new global.Promise(callback) + promise.on = util.deprecate(function () { + emitter.on.apply(emitter, arguments) + }, deprecationMessage); + + promise.once = util.deprecate(function () { + emitter.once.apply(emitter, arguments) + }, deprecationMessage) +} diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 08e78b33..4a2be1ee 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -1,103 +1,111 @@ +"use strict"; + var helper = require('./test-helper'); var util = require('util'); var pg = helper.pg - var createErorrClient = function() { var client = helper.client(); client.once('error', function(err) { - //console.log('error', util.inspect(err)); assert.fail('Client shoud not throw error during query execution'); }); client.on('drain', client.end.bind(client)); return client; }; -test('error handling', function() { - test('within a simple query', function() { - var client = createErorrClient(); +const suite = new helper.Suite('error handling') - var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")); - - assert.emits(query, 'error', function(error) { - assert.equal(error.severity, "ERROR"); - }); - }); - - test('within a prepared statement', function() { - - var client = createErorrClient(); - - var q = client.query({text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);", binary: false}); - - test("when query is parsing", function() { - - //this query wont parse since there ain't no table named bang - - var ensureFuture = function(testClient) { - test("client can issue more queries successfully", function() { - var goodQuery = testClient.query(new pg.Query("select age from boom")); - assert.emits(goodQuery, 'row', function(row) { - assert.equal(row.age, 28); - }); - }); - }; - - var query = client.query(new pg.Query({ - text: "select * from bang where name = $1", - values: ['0'] - })); - - test("query emits the error", function() { - assert.emits(query, 'error', function(err) { - ensureFuture(client); - }); - }); - - test("when a query is binding", function() { - - var query = client.query(new pg.Query({ - text: 'select * from boom where age = $1', - values: ['asldkfjasdf'] - })); - - test("query emits the error", function() { - - assert.emits(query, 'error', function(err) { - test('error has right severity', function() { - assert.equal(err.severity, "ERROR"); - }) - - ensureFuture(client); - }); - }); - - //TODO how to test for errors during execution? - }); - }); - }); - - test('non-query error', function() { - var client = new Client({ - user:'asldkfjsadlfkj' - }); - assert.emits(client, 'error'); - client.connect(); - }); - - test('non-query error with callback', function() { - var client = new Client({ - user:'asldkfjsadlfkj' - }); - client.connect(assert.calls(function(error, client) { - assert.ok(error); +suite.test('query receives error on client shutdown', false, function(done) { + var client = new Client(); + client.connect(function(err) { + if (err) { + return done(err) + } + client.query('SELECT pg_sleep(5)', assert.calls(function(err, res) { + assert(err instanceof Error) + done() })); + setTimeout(() => { + client.end() + assert.emits(client, 'end'); + }, 50) }); - }); -test('non-error calls supplied callback', function() { +suite.test('within a simple query', (done) => { + var client = createErorrClient(); + + var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")); + + assert.emits(query, 'error', function(error) { + assert.equal(error.severity, "ERROR"); + done(); + }); +}); + +(function () { + var client = createErorrClient(); + + var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);", binary: false }); + + var ensureFuture = function (testClient, done) { + var goodQuery = testClient.query(new pg.Query("select age from boom")); + assert.emits(goodQuery, 'row', function (row) { + assert.equal(row.age, 28); + done(); + }); + }; + + suite.test("when query is parsing", (done) => { + + //this query wont parse since there isn't a table named bang + var query = client.query(new pg.Query({ + text: "select * from bang where name = $1", + values: ['0'] + })); + + assert.emits(query, 'error', function (err) { + ensureFuture(client, done); + }); + }); + + suite.test("when a query is binding", function (done) { + + var query = client.query(new pg.Query({ + text: 'select * from boom where age = $1', + values: ['asldkfjasdf'] + })); + + assert.emits(query, 'error', function (err) { + assert.equal(err.severity, "ERROR"); + ensureFuture(client, done); + }); + }); +})(); + +suite.test('non-query error', function(done) { + var client = new Client({ + user:'asldkfjsadlfkj' + }); + client.on('error', (err) => { + assert(err instanceof Error) + done() + }); + client.connect(); +}); + +suite.test('non-query error with callback', function(done) { + var client = new Client({ + user:'asldkfjsadlfkj' + }); + client.connect(assert.calls(function(error, client) { + assert(error instanceof Error) + done() + })); +}); + +suite.test('non-error calls supplied callback', function(done) { var client = new Client({ user: helper.args.user, password: helper.args.password, @@ -108,75 +116,23 @@ test('non-error calls supplied callback', function() { client.connect(assert.calls(function(err) { assert.ifError(err); - client.end(); + client.end(done); })) }); -test('when connecting to invalid host', function() { - //this test fails about 30% on travis and only on travis... - //I'm not sure what the cause could be - if(process.env.TRAVIS) return false; - +suite.test('when connecting to invalid host with promise', function(done) { var client = new Client({ - user: 'aslkdjfsdf', - password: '1234', - host: 'asldkfjasdf!!#1308140.com' + host: 'asdlfkjasldkfjlaskdfj' }); - - var delay = 5000; - var tid = setTimeout(function() { - var msg = "When connecting to an invalid host the error event should be emitted but it has been " + delay + " and still no error event." - assert(false, msg); - }, delay); - client.on('error', function() { - clearTimeout(tid); - }) - client.connect(); + client.connect().catch((e) => done()); }); -test('when connecting to invalid host with callback', function() { +suite.test('when connecting to an invalid host with callback', function (done) { var client = new Client({ - user: 'brian', - password: '1234', host: 'asldkfjasdf!!#1308140.com' }); client.connect(function(error, client) { - assert(error); + assert(error instanceof Error); + done(); }); }); - -test('multiple connection errors (gh#31)', function() { - return false; - test('with single client', function() { - //don't run yet...this test fails...need to think of fix - var client = new Client({ - user: 'blaksdjf', - password: 'omfsadfas', - host: helper.args.host, - port: helper.args.port, - database: helper.args.database - }); - client.connect(); - assert.emits(client, 'error', function(e) { - client.connect(); - assert.emits(client, 'error'); - }); - }); - - test('with callback method', function() { - var badConString = "postgres://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/promise-api-tests.js b/test/integration/client/promise-api-tests.js index 783fb46c..17094c9d 100644 --- a/test/integration/client/promise-api-tests.js +++ b/test/integration/client/promise-api-tests.js @@ -1,69 +1,9 @@ -const async = require('async') +'use strict'; + const helper = require('./test-helper') const pg = helper.pg; -class Test { - constructor(name, cb) { - this.name = name - this.action = cb - this.timeout = 5000 - } - - run(cb) { - try { - this._run(cb) - } catch (e) { - cb(e) - } - } - - _run(cb) { - if (!this.action) { - console.log(`${this.name} skipped`) - return cb() - } - if (!this.action.length) { - const result = this.action.call(this) - if ((result || 0).then) { - result - .then(() => cb()) - .catch(err => cb(err || new Error('Unhandled promise rejection'))) - } - } else { - this.action.call(this, cb) - } - } -} - -class Suite { - constructor() { - console.log('') - this._queue = async.queue(this.run.bind(this), 1) - this._queue.drain = () => { } - } - - run(test, cb) { - const tid = setTimeout(() => { - const err = Error(`test: ${test.name} did not complete withint ${test.timeout}ms`) - cb(err) - }, test.timeout) - test.run((err) => { - clearTimeout(tid) - if (err) { - console.log(test.name + ' FAILED!', err.stack) - } else { - console.log(test.name) - } - cb(err) - }) - } - - test(name, cb) { - this._queue.push(new Test(name, cb)) - } -} - -const suite = new Suite() +const suite = new helper.Suite() suite.test('valid connection completes promise', () => { const client = new pg.Client() @@ -93,11 +33,15 @@ suite.test('invalid connection rejects promise', (done) => { }) }) -suite.test('connected client does not reject promise after', (done) => { +suite.test('connected client does not reject promise after connection', (done) => { const client = new pg.Client() return client.connect() .then(() => { setTimeout(() => { + client.on('error', (e) => { + assert(e instanceof Error) + done() + }) // manually kill the connection client.connection.stream.end() }, 50) diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index e301ab68..a7bda9c7 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -2,7 +2,9 @@ var helper = require('./test-helper'); var Query = helper.pg.Query; var util = require('util'); -function killIdleQuery(targetQuery) { +var suite = new helper.Suite(); + +function killIdleQuery(targetQuery, cb) { var client2 = new Client(helper.args); var pidColName = 'procpid' var queryColName = 'current_query'; @@ -16,16 +18,16 @@ function killIdleQuery(targetQuery) { client2.query(killIdleQuery, [targetQuery], assert.calls(function(err, res) { assert.ifError(err); assert.equal(res.rows.length, 1); - client2.end(); + client2.end(cb); assert.emits(client2, 'end'); })); })); })); } -test('query killed during query execution of prepared statement', function() { +suite.test('query killed during query execution of prepared statement', function(done) { if(helper.args.native) { - return false; + return done(); } var client = new Client(helper.args); client.connect(assert.success(function() { @@ -56,11 +58,11 @@ test('query killed during query execution of prepared statement', function() { assert.fail('Prepared statement when executed should not return before being killed'); }); - killIdleQuery(sleepQuery); + killIdleQuery(sleepQuery, done); })); }); -test('client end during query execution of prepared statement', function() { +suite.test('client end during query execution of prepared statement', function(done) { var client = new Client(helper.args); client.connect(assert.success(function() { var sleepQuery = 'select pg_sleep($1)'; @@ -90,6 +92,6 @@ test('client end during query execution of prepared statement', function() { assert.fail('Prepared statement when executed should not return before being killed'); }); - client.end(); + client.end(done); })); }); diff --git a/test/suite.js b/test/suite.js new file mode 100644 index 00000000..37227fc9 --- /dev/null +++ b/test/suite.js @@ -0,0 +1,74 @@ +'use strict'; + +const async = require('async') + +class Test { + constructor(name, cb) { + this.name = name + this.action = cb + this.timeout = 5000 + } + + run(cb) { + try { + this._run(cb) + } catch (e) { + cb(e) + } + } + + _run(cb) { + if (!this.action) { + console.log(`${this.name} skipped`) + return cb() + } + if (!this.action.length) { + const result = this.action.call(this) + if ((result || 0).then) { + result + .then(() => cb()) + .catch(err => cb(err || new Error('Unhandled promise rejection'))) + } + } else { + this.action.call(this, cb) + } + } +} + +class Suite { + constructor(name) { + console.log('') + this._queue = async.queue(this.run.bind(this), 1) + this._queue.drain = () => { } + } + + run(test, cb) { + process.stdout.write(test.name + ' ') + if (!test.action) { + process.stdout.write('? - SKIPPED') + return cb() + } + + const tid = setTimeout(() => { + const err = Error(`test: ${test.name} did not complete withint ${test.timeout}ms`) + cb(err) + }, test.timeout) + + test.run((err) => { + clearTimeout(tid) + if (err) { + process.stdout.write(`FAILED!\n\n${err.stack}\n`) + process.exit(-1) + } else { + process.stdout.write('✔\n') + } + cb(err) + }) + } + + test(name, cb) { + this._queue.push(new Test(name, cb)) + } +} + +module.exports = Suite diff --git a/test/test-helper.js b/test/test-helper.js index f39cbfef..4cf6a455 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -240,6 +240,7 @@ var resetTimezoneOffset = function() { module.exports = { Sink: Sink, + Suite: require('./suite'), pg: require(__dirname + '/../lib/'), args: args, config: args, From 72560850d7ca0c07591acfc8421e26469d283423 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 17:02:23 -0500 Subject: [PATCH 23/58] Working on disconnect issue --- lib/client.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/client.js b/lib/client.js index 3104f70b..5800e943 100644 --- a/lib/client.js +++ b/lib/client.js @@ -409,17 +409,15 @@ Client.prototype.query = function(config, values, callback) { Client.prototype.end = function(cb) { this._ending = true; - if (this.activeQuery) { - return this.connection.stream.end() - } - this.connection.end(); if (cb) { this.connection.once('end', cb); - } else { - return new global.Promise((resolve) => { - this.connection.once('end', resolve); - }); + this.connection.end(); + return; } + return new global.Promise((resolve) => { + this.connection.end(); + this.connection.once('end', resolve); + }); }; Client.md5 = function(string) { From f41839b83a43c6bd5efbfe68484119770da3a756 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 17:09:27 -0500 Subject: [PATCH 24/58] Work on test --- ...error-handling-prepared-statement-tests.js | 69 ++++++++++--------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index a7bda9c7..a250f78b 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -4,6 +4,41 @@ var util = require('util'); var suite = new helper.Suite(); +suite.test('client end during query execution of prepared statement', function(done) { + var client = new Client(helper.args); + client.connect(assert.success(function() { + + var sleepQuery = 'select pg_sleep($1)'; + + var queryConfig = { + name: 'sleep query', + text: sleepQuery, + values: [5], + } + + var queryInstance = new Query(queryConfig, assert.calls(function (err, result) { + assert.equal(err.message, 'Connection terminated'); + })) + + var query1 = client.query(queryInstance); + + + query1.on('error', function (err) { + assert.fail('Prepared statement should not emit error'); + }); + + query1.on('row', function (row) { + assert.fail('Prepared statement should not emit row'); + }); + + query1.on('end', function (err) { + assert.fail('Prepared statement when executed should not return before being killed'); + }); + + client.end(done); + })); +}); + function killIdleQuery(targetQuery, cb) { var client2 = new Client(helper.args); var pidColName = 'procpid' @@ -61,37 +96,3 @@ suite.test('query killed during query execution of prepared statement', function killIdleQuery(sleepQuery, done); })); }); - -suite.test('client end during query execution of prepared statement', function(done) { - var client = new Client(helper.args); - client.connect(assert.success(function() { - var sleepQuery = 'select pg_sleep($1)'; - - var queryConfig = { - name: 'sleep query', - text: sleepQuery, - values: [5], - } - - var queryInstance = new Query(queryConfig, assert.calls(function (err, result) { - assert.equal(err.message, 'Connection terminated'); - })) - - var query1 = client.query(queryInstance); - - - query1.on('error', function (err) { - assert.fail('Prepared statement should not emit error'); - }); - - query1.on('row', function (row) { - assert.fail('Prepared statement should not emit row'); - }); - - query1.on('end', function (err) { - assert.fail('Prepared statement when executed should not return before being killed'); - }); - - client.end(done); - })); -}); From 3219db993ab9880bb03499a7819c85ae177b4250 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 17:49:49 -0500 Subject: [PATCH 25/58] All tests passing --- Makefile | 1 - lib/client.js | 187 ++++++++---------- lib/connection.js | 2 +- .../client/error-handling-tests.js | 95 ++++----- .../client/network-partition-tests.js | 11 +- test/suite.js | 9 +- 6 files changed, 146 insertions(+), 159 deletions(-) diff --git a/Makefile b/Makefile index 0da68207..08c1e10c 100644 --- a/Makefile +++ b/Makefile @@ -62,4 +62,3 @@ test-pool: jshint: @echo "***Starting jshint***" - @./node_modules/.bin/jshint lib diff --git a/lib/client.js b/lib/client.js index 5800e943..c1cef452 100644 --- a/lib/client.js +++ b/lib/client.js @@ -67,12 +67,12 @@ Client.prototype.connect = function(callback) { if(self.ssl) { con.requestSsl(); } else { - con.startup(self._getStartupConfiguration()); + con.startup(self.getStartupConf()); } }); con.on('sslconnect', function() { - con.startup(self._getStartupConfiguration()); + con.startup(self.getStartupConf()); }); function checkPgPass(cb) { @@ -108,21 +108,56 @@ Client.prototype.connect = function(callback) { self.secretKey = msg.secretKey; }); - - con.on('readyForQuery', function() { - var activeQuery = self.activeQuery; - self.activeQuery = null; - self.readyForQuery = true; - self._pulseQueryQueue(); - if(activeQuery) { - activeQuery.handleReadyForQuery(con); - } - }); - //hook up query handling events to connection //after the connection initially becomes ready for queries con.once('readyForQuery', function() { - self._attachEventListeners(con); + self._connecting = false; + + //delegate rowDescription to active query + con.on('rowDescription', function(msg) { + self.activeQuery.handleRowDescription(msg); + }); + + //delegate dataRow to active query + con.on('dataRow', function(msg) { + self.activeQuery.handleDataRow(msg); + }); + + //delegate portalSuspended to active query + con.on('portalSuspended', function(msg) { + self.activeQuery.handlePortalSuspended(con); + }); + + //deletagate emptyQuery to active query + con.on('emptyQuery', function(msg) { + self.activeQuery.handleEmptyQuery(con); + }); + + //delegate commandComplete to active query + con.on('commandComplete', function(msg) { + self.activeQuery.handleCommandComplete(msg, con); + }); + + //if a prepared statement has a name and properly parses + //we track that its already been executed so we don't parse + //it again on the same client + con.on('parseComplete', function(msg) { + if(self.activeQuery.name) { + con.parsedStatements[self.activeQuery.name] = true; + } + }); + + con.on('copyInResponse', function(msg) { + self.activeQuery.handleCopyInResponse(self.connection); + }); + + con.on('copyData', function (msg) { + self.activeQuery.handleCopyData(msg, self.connection); + }); + + con.on('notification', function(msg) { + self.emit('notification', msg); + }); //process possible callback argument to Client#connect if (callback) { @@ -134,6 +169,16 @@ Client.prototype.connect = function(callback) { self.emit('connect'); }); + con.on('readyForQuery', function() { + var activeQuery = self.activeQuery; + self.activeQuery = null; + self.readyForQuery = true; + self._pulseQueryQueue(); + if(activeQuery) { + activeQuery.handleReadyForQuery(con); + } + }); + con.on('error', function(error) { if(this.activeQuery) { var activeQuery = self.activeQuery; @@ -187,75 +232,19 @@ Client.prototype.connect = function(callback) { self.emit('notice', msg); }); - var result; - if (!callback) { - result = new global.Promise(function (resolve, reject) { - con.once('connect', function () { - con.removeListener('error', reject) + return new global.Promise((resolve, reject) => { + this.once('error', reject) + this.once('connect', () => { + this.removeListener('error', reject) resolve() }) - this.once('error', reject) - }.bind(this)) + }) } - return result; }; - -// once a connection is established connect listeners -Client.prototype._attachEventListeners = function(con) { - var self = this; - self._connecting = false; - - //delegate rowDescription to active query - con.on('rowDescription', function(msg) { - self.activeQuery.handleRowDescription(msg); - }); - - //delegate dataRow to active query - con.on('dataRow', function(msg) { - self.activeQuery.handleDataRow(msg); - }); - - //delegate portalSuspended to active query - con.on('portalSuspended', function(msg) { - self.activeQuery.handlePortalSuspended(con); - }); - - //deletagate emptyQuery to active query - con.on('emptyQuery', function(msg) { - self.activeQuery.handleEmptyQuery(con); - }); - - //delegate commandComplete to active query - con.on('commandComplete', function(msg) { - self.activeQuery.handleCommandComplete(msg, con); - }); - - //if a prepared statement has a name and properly parses - //we track that its already been executed so we don't parse - //it again on the same client - con.on('parseComplete', function(msg) { - if(self.activeQuery.name) { - con.parsedStatements[self.activeQuery.name] = true; - } - }); - - con.on('copyInResponse', function(msg) { - self.activeQuery.handleCopyInResponse(self.connection); - }); - - con.on('copyData', function (msg) { - self.activeQuery.handleCopyData(msg, self.connection); - }); - - con.on('notification', function(msg) { - self.emit('notification', msg); - }); -} - -Client.prototype._getStartupConfiguration = function() { +Client.prototype.getStartupConf = function() { var params = this.connectionParameters; var data = { @@ -370,54 +359,46 @@ Client.prototype.copyTo = function (text) { }; Client.prototype.query = function(config, values, callback) { - var promise; - var isQueryable = typeof config.submit == 'function'; + //can take in strings, config object or query object var query; - // if we receive an object with a 'submit' function we delegate - // processing to the passed object - this is how pg.Query, QueryStream, and Cursor work - if (isQueryable) { - query = config; - // accept client.query(new Query('select *'), (err, res) => { }) call signature + var result; + if (typeof config.submit == 'function') { + query = config + result = query if (typeof values == 'function') { - query.callback = query.callback || values; + query.callback = query.callback || values } } else { - query = new Query(config, values, callback); - if (!query.callback) { - promise = new global.Promise(function (resolve, reject) { - query.on('error', reject); - query.on('end', resolve); - }); - } + query = new Query(config, values, callback) + result = query.callback ? undefined : new global.Promise((resolve, reject) => { + query.once('end', resolve) + query.once('error', reject) + }) } + if(this.binary && !query.binary) { query.binary = true; } - - // TODO - this is a smell if(query._result) { query._result._getTypeParser = this._types.getTypeParser.bind(this._types); } this.queryQueue.push(query); this._pulseQueryQueue(); - - // if we were passed a queryable, return it - // otherwise return callback/promise result - return isQueryable ? query : promise; + return result }; Client.prototype.end = function(cb) { this._ending = true; if (cb) { + this.connection.end(); this.connection.once('end', cb); - this.connection.end(); - return; + } else { + return new global.Promise((resolve, reject) => { + this.connection.end() + this.connection.once('end', resolve) + }) } - return new global.Promise((resolve) => { - this.connection.end(); - this.connection.once('end', resolve); - }); }; Client.md5 = function(string) { diff --git a/lib/connection.js b/lib/connection.js index c40639e0..8e57ff46 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -315,7 +315,7 @@ Connection.prototype.end = function() { //0x58 = 'X' this.writer.add(emptyBuffer); this._ending = true; - return this.stream.end(END_BUFFER); + return this.stream.write(END_BUFFER); }; Connection.prototype.close = function(msg, more) { diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 4a2be1ee..9aff27fb 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -16,35 +16,7 @@ var createErorrClient = function() { const suite = new helper.Suite('error handling') -suite.test('query receives error on client shutdown', false, function(done) { - var client = new Client(); - client.connect(function(err) { - if (err) { - return done(err) - } - client.query('SELECT pg_sleep(5)', assert.calls(function(err, res) { - assert(err instanceof Error) - done() - })); - setTimeout(() => { - client.end() - assert.emits(client, 'end'); - }, 50) - }); -}); - -suite.test('within a simple query', (done) => { - var client = createErorrClient(); - - var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")); - - assert.emits(query, 'error', function(error) { - assert.equal(error.severity, "ERROR"); - done(); - }); -}); - -(function () { +;(function () { var client = createErorrClient(); var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);", binary: false }); @@ -84,17 +56,6 @@ suite.test('within a simple query', (done) => { }); })(); -suite.test('non-query error', function(done) { - var client = new Client({ - user:'asldkfjsadlfkj' - }); - client.on('error', (err) => { - assert(err instanceof Error) - done() - }); - client.connect(); -}); - suite.test('non-query error with callback', function(done) { var client = new Client({ user:'asldkfjsadlfkj' @@ -120,13 +81,6 @@ suite.test('non-error calls supplied callback', function(done) { })) }); -suite.test('when connecting to invalid host with promise', function(done) { - var client = new Client({ - host: 'asdlfkjasldkfjlaskdfj' - }); - client.connect().catch((e) => done()); -}); - suite.test('when connecting to an invalid host with callback', function (done) { var client = new Client({ host: 'asldkfjasdf!!#1308140.com' @@ -136,3 +90,50 @@ suite.test('when connecting to an invalid host with callback', function (done) { done(); }); }); + +suite.test('when connecting to invalid host with promise', function(done) { + var client = new Client({ + host: 'asdlfkjasldkfjlaskdfj' + }); + client.connect().catch((e) => done()); +}); + +suite.test('non-query error', function(done) { + var client = new Client({ + user:'asldkfjsadlfkj' + }); + client.connect() + .catch(e => { + assert(e instanceof Error) + done() + }) +}); + + +suite.test('query receives error on client shutdown', false, function(done) { + var client = new Client(); + client.connect(function(err) { + if (err) { + return done(err) + } + client.query('SELECT pg_sleep(5)', assert.calls(function(err, res) { + assert(err instanceof Error) + done() + })); + setTimeout(() => { + client.end() + assert.emits(client, 'end'); + }, 50) + }); +}); + +suite.test('within a simple query', (done) => { + var client = createErorrClient(); + + var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")); + + assert.emits(query, 'error', function(error) { + assert.equal(error.severity, "ERROR"); + done(); + }); +}); diff --git a/test/integration/client/network-partition-tests.js b/test/integration/client/network-partition-tests.js index 944df510..945a2ee8 100644 --- a/test/integration/client/network-partition-tests.js +++ b/test/integration/client/network-partition-tests.js @@ -59,6 +59,11 @@ var testServer = function (server, cb) { // connect a client to it var client = new helper.Client(options) client.connect() + .catch((err) => { + assert(err instanceof Error) + clearTimeout(timeoutId) + server.close(cb) + }) // after 50 milliseconds, drop the client setTimeout(function() { @@ -69,12 +74,6 @@ var testServer = function (server, cb) { var timeoutId = setTimeout(function () { throw new Error('Client should have emitted an error but it did not.') }, 5000) - - // return our wait token - client.on('error', function () { - clearTimeout(timeoutId) - server.close(cb) - }) }) } diff --git a/test/suite.js b/test/suite.js index 37227fc9..1de1b69c 100644 --- a/test/suite.js +++ b/test/suite.js @@ -43,7 +43,7 @@ class Suite { } run(test, cb) { - process.stdout.write(test.name + ' ') + process.stdout.write(' ' + test.name + ' ') if (!test.action) { process.stdout.write('? - SKIPPED') return cb() @@ -71,4 +71,11 @@ class Suite { } } +process.on('unhandledRejection', (e) => { + setImmediate(() => { + console.error('Uhandled promise rejection') + throw e + }) +}) + module.exports = Suite From c961c900d61258b2e6e16950dcddc4d5fefe3a52 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 18:10:18 -0500 Subject: [PATCH 26/58] Almost all tests passing --- lib/native/client.js | 22 +++++++++++ .../client/error-handling-tests.js | 38 +++++++++---------- test/integration/client/promise-api-tests.js | 3 +- ...error-handling-prepared-statement-tests.js | 6 +-- test/native/connection-tests.js | 36 ------------------ test/suite.js | 2 +- 6 files changed, 47 insertions(+), 60 deletions(-) delete mode 100644 test/native/connection-tests.js diff --git a/lib/native/client.js b/lib/native/client.js index e57a9419..639484ec 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -63,6 +63,16 @@ Client.prototype.connect = function(cb) { return self.emit('error', err); }; + var result + if (!cb) { + var resolve, reject + cb = (err) => err ? reject(err) : resolve() + result = new global.Promise(function(res, rej) { + resolve = res + reject = rej + }) + } + this.connectionParameters.getLibpqConnectionString(function(err, conString) { if(err) return onError(err); self.native.connect(conString, function(err) { @@ -95,6 +105,8 @@ Client.prototype.connect = function(cb) { if(cb) cb(); }); }); + + return result }; //send a query to the server @@ -135,6 +147,15 @@ Client.prototype.end = function(cb) { if(!this._connected) { this.once('connect', this.end.bind(this, cb)); } + var result; + if (!cb) { + var resolve, reject + cb = (err) => err ? reject(err) : resolve() + result = new global.Promise(function(res, rej) { + resolve = res + reject = rej + }) + } this.native.end(function() { //send an error to the active query if(self._hasActiveQuery()) { @@ -145,6 +166,7 @@ Client.prototype.end = function(cb) { self.emit('end'); if(cb) cb(); }); + return result }; Client.prototype._hasActiveQuery = function() { diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 9aff27fb..cc60e2c9 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -16,6 +16,24 @@ var createErorrClient = function() { const suite = new helper.Suite('error handling') +suite.test('query receives error on client shutdown', false, function(done) { + var client = new Client(); + client.connect(assert.success(function() { + const config = { + text: 'select pg_sleep(5)', + name: 'foobar' + } + client.query(new pg.Query(config), assert.calls(function(err, res) { + assert(err instanceof Error) + done() + })); + setTimeout(() => { + client.end() + assert.emits(client, 'end'); + }, 50) + })); +}); + ;(function () { var client = createErorrClient(); @@ -83,7 +101,7 @@ suite.test('non-error calls supplied callback', function(done) { suite.test('when connecting to an invalid host with callback', function (done) { var client = new Client({ - host: 'asldkfjasdf!!#1308140.com' + host: '!#%!@#%' }); client.connect(function(error, client) { assert(error instanceof Error); @@ -109,24 +127,6 @@ suite.test('non-query error', function(done) { }) }); - -suite.test('query receives error on client shutdown', false, function(done) { - var client = new Client(); - client.connect(function(err) { - if (err) { - return done(err) - } - client.query('SELECT pg_sleep(5)', assert.calls(function(err, res) { - assert(err instanceof Error) - done() - })); - setTimeout(() => { - client.end() - assert.emits(client, 'end'); - }, 50) - }); -}); - suite.test('within a simple query', (done) => { var client = createErorrClient(); diff --git a/test/integration/client/promise-api-tests.js b/test/integration/client/promise-api-tests.js index 17094c9d..ee088f94 100644 --- a/test/integration/client/promise-api-tests.js +++ b/test/integration/client/promise-api-tests.js @@ -40,10 +40,11 @@ suite.test('connected client does not reject promise after connection', (done) = setTimeout(() => { client.on('error', (e) => { assert(e instanceof Error) + client.end() done() }) // manually kill the connection - client.connection.stream.end() + client.emit('error', new Error('something bad happened...but not really')) }, 50) }) }) diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index a250f78b..7aa68f59 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -5,7 +5,7 @@ var util = require('util'); var suite = new helper.Suite(); suite.test('client end during query execution of prepared statement', function(done) { - var client = new Client(helper.args); + var client = new Client(); client.connect(assert.success(function() { var sleepQuery = 'select pg_sleep($1)'; @@ -18,11 +18,11 @@ suite.test('client end during query execution of prepared statement', function(d var queryInstance = new Query(queryConfig, assert.calls(function (err, result) { assert.equal(err.message, 'Connection terminated'); + done(); })) var query1 = client.query(queryInstance); - query1.on('error', function (err) { assert.fail('Prepared statement should not emit error'); }); @@ -35,7 +35,7 @@ suite.test('client end during query execution of prepared statement', function(d assert.fail('Prepared statement when executed should not return before being killed'); }); - client.end(done); + client.end(); })); }); diff --git a/test/native/connection-tests.js b/test/native/connection-tests.js deleted file mode 100644 index be84be6e..00000000 --- a/test/native/connection-tests.js +++ /dev/null @@ -1,36 +0,0 @@ -var helper = require(__dirname + "/../test-helper"); -var Client = require(__dirname + "/../../lib/native"); -var domain = require('domain'); - -test('connecting with wrong parameters', function() { - var con = new Client("user=asldfkj hostaddr=127.0.0.1 port=5432 dbname=asldkfj"); - assert.emits(con, 'error', function(error) { - assert.ok(error != null, "error should not be null"); - con.end(); - }); - - con.connect(); -}); - -test('connects', function() { - var con = new Client(helper.config); - con.connect(); - assert.emits(con, 'connect', function() { - test('disconnects', function() { - con.end(); - }) - }) -}) - -test('preserves domain', function() { - var dom = domain.create(); - - dom.run(function() { - var con = new Client(helper.config); - assert.ok(dom === require('domain').active, 'domain is active'); - con.connect(function() { - assert.ok(dom === require('domain').active, 'domain is still active'); - con.end(); - }); - }); -}) diff --git a/test/suite.js b/test/suite.js index 1de1b69c..7d248b36 100644 --- a/test/suite.js +++ b/test/suite.js @@ -45,7 +45,7 @@ class Suite { run(test, cb) { process.stdout.write(' ' + test.name + ' ') if (!test.action) { - process.stdout.write('? - SKIPPED') + process.stdout.write('? - SKIPPED\n') return cb() } From 2c3f55e5bdd1f6075fe168cfecdb8f375d5fef26 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 19:24:39 -0500 Subject: [PATCH 27/58] Make all tests pass --- lib/client.js | 8 ++++- .../client/error-handling-tests.js | 32 +++++++++++-------- .../client/query-as-promise-tests.js | 13 ++++---- .../client/query-error-handling-tests.js | 2 +- test/integration/gh-issues/699-tests.js | 4 ++- 5 files changed, 35 insertions(+), 24 deletions(-) diff --git a/lib/client.js b/lib/client.js index c1cef452..0b67ba31 100644 --- a/lib/client.js +++ b/lib/client.js @@ -173,10 +173,10 @@ Client.prototype.connect = function(callback) { var activeQuery = self.activeQuery; self.activeQuery = null; self.readyForQuery = true; - self._pulseQueryQueue(); if(activeQuery) { activeQuery.handleReadyForQuery(con); } + self._pulseQueryQueue(); }); con.on('error', function(error) { @@ -390,6 +390,12 @@ Client.prototype.query = function(config, values, callback) { Client.prototype.end = function(cb) { this._ending = true; + if (this.activeQuery) { + // if we have an active query we need to force a disconnect + // on the socket - otherwise a hung query could block end forever + this.connection.stream.destroy(new Error('Connection terminated by user')) + return; + } if (cb) { this.connection.end(); this.connection.once('end', cb); diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index cc60e2c9..69d43085 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -16,29 +16,26 @@ var createErorrClient = function() { const suite = new helper.Suite('error handling') -suite.test('query receives error on client shutdown', false, function(done) { +suite.test('query receives error on client shutdown', function(done) { var client = new Client(); client.connect(assert.success(function() { const config = { text: 'select pg_sleep(5)', name: 'foobar' } + let queryError; client.query(new pg.Query(config), assert.calls(function(err, res) { assert(err instanceof Error) - done() + queryError = err })); - setTimeout(() => { - client.end() - assert.emits(client, 'end'); - }, 50) + setTimeout(() => client.end(), 50) + client.once('end', () => { + assert(queryError instanceof Error) + done() + }) })); }); -;(function () { - var client = createErorrClient(); - - var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);", binary: false }); - var ensureFuture = function (testClient, done) { var goodQuery = testClient.query(new pg.Query("select age from boom")); assert.emits(goodQuery, 'row', function (row) { @@ -48,6 +45,10 @@ suite.test('query receives error on client shutdown', false, function(done) { }; suite.test("when query is parsing", (done) => { + var client = createErorrClient(); + + var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);" }); + //this query wont parse since there isn't a table named bang var query = client.query(new pg.Query({ @@ -61,6 +62,10 @@ suite.test('query receives error on client shutdown', false, function(done) { }); suite.test("when a query is binding", function (done) { + var client = createErorrClient(); + + var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);" }); + var query = client.query(new pg.Query({ text: 'select * from boom where age = $1', @@ -72,7 +77,6 @@ suite.test('query receives error on client shutdown', false, function(done) { ensureFuture(client, done); }); }); -})(); suite.test('non-query error with callback', function(done) { var client = new Client({ @@ -101,7 +105,7 @@ suite.test('non-error calls supplied callback', function(done) { suite.test('when connecting to an invalid host with callback', function (done) { var client = new Client({ - host: '!#%!@#%' + user: 'very invalid username', }); client.connect(function(error, client) { assert(error instanceof Error); @@ -111,7 +115,7 @@ suite.test('when connecting to an invalid host with callback', function (done) { suite.test('when connecting to invalid host with promise', function(done) { var client = new Client({ - host: 'asdlfkjasldkfjlaskdfj' + user: 'very invalid username' }); client.connect().catch((e) => done()); }); diff --git a/test/integration/client/query-as-promise-tests.js b/test/integration/client/query-as-promise-tests.js index ac958729..92eedcc8 100644 --- a/test/integration/client/query-as-promise-tests.js +++ b/test/integration/client/query-as-promise-tests.js @@ -16,13 +16,12 @@ pg.connect(helper.config, assert.success(function(client, done) { client.query('ALKJSDF') .catch(function(e) { assert(e instanceof Error) + client.query('SELECT 1 as num') + .then(function (result) { + assert.equal(result.rows[0].num, 1) + done() + pg.end() + }) }) }) - - client.query('SELECT 1 as num') - .then(function(result) { - assert.equal(result.rows[0].num, 1) - done() - pg.end() - }) })) diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index 2e28737d..f2dd294e 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -5,7 +5,7 @@ var Query = helper.pg.Query; test('error during query execution', function() { var client = new Client(helper.args); client.connect(assert.success(function() { - var queryText = 'select pg_sleep(5)' + var queryText = 'select pg_sleep(10)' var sleepQuery = new Query(queryText); var pidColName = 'procpid' var queryColName = 'current_query'; diff --git a/test/integration/gh-issues/699-tests.js b/test/integration/gh-issues/699-tests.js index 2918c9ae..f9cb876d 100644 --- a/test/integration/gh-issues/699-tests.js +++ b/test/integration/gh-issues/699-tests.js @@ -15,7 +15,9 @@ helper.pg.connect(helper.config, function (err, client, done) { var stream = client.query(copyFrom("COPY employee FROM STDIN")); stream.on('end', function () { done(); - helper.pg.end(); + setTimeout(() => { + helper.pg.end(); + }, 50) }); for (var i = 1; i <= 5; i++) { From 30744362360f2defeaead502b39b9f1f1bb17702 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 19:47:03 -0500 Subject: [PATCH 28/58] Tidy up a bit of testing --- 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 f2dd294e..d5ecd7bd 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -30,7 +30,7 @@ test('error during query execution', function() { var killIdleQuery = `SELECT ${pidColName}, (SELECT pg_cancel_backend(${pidColName})) AS killed FROM pg_stat_activity WHERE ${queryColName} LIKE $1`; client2.query(killIdleQuery, [queryText], assert.calls(function(err, res) { assert.ifError(err); - assert.equal(res.rows.length, 1); + assert(res.rows.length > 0); client2.end(); assert.emits(client2, 'end'); })); @@ -41,7 +41,7 @@ test('error during query execution', function() { }); if (helper.config.native) { - return console.log("\nTODO: this should work on native as well") + return } test('9.3 column error fields', function() { From d615ebee177ed57c7a7df861b1db675c9e0ebb0f Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 21:06:21 -0500 Subject: [PATCH 29/58] Start cleaning up tests --- package.json | 1 - test/integration/client/appname-tests.js | 28 +- test/integration/client/array-tests.js | 318 +++++++++--------- .../client/big-simple-query-tests.js | 26 +- test/integration/client/cancel-query-tests.js | 2 +- .../integration/client/configuration-tests.js | 69 ++-- test/integration/client/custom-types-tests.js | 31 +- test/integration/client/empty-query-tests.js | 15 +- test/integration/client/end-callback-tests.js | 6 - .../client/force-native-with-envvar-tests.js | 39 --- test/integration/client/huge-numeric-tests.js | 4 +- .../client/json-type-parsing-tests.js | 58 ++-- .../client/network-partition-tests.js | 20 +- test/integration/domain-tests.js | 91 +++-- test/integration/gh-issues/131-tests.js | 25 +- test/integration/gh-issues/507-tests.js | 3 +- test/integration/gh-issues/600-tests.js | 7 +- test/integration/gh-issues/675-tests.js | 2 +- test/integration/gh-issues/699-tests.js | 2 +- test/integration/gh-issues/787-tests.js | 4 +- test/integration/test-helper.js | 2 +- test/native/callback-api-tests.js | 13 +- test/suite.js | 16 +- test/test-helper.js | 32 +- test/unit/client/early-disconnect-tests.js | 9 +- 25 files changed, 390 insertions(+), 433 deletions(-) delete mode 100644 test/integration/client/end-callback-tests.js delete mode 100644 test/integration/client/force-native-with-envvar-tests.js diff --git a/package.json b/package.json index 5eecc421..1d8a6913 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ }, "devDependencies": { "async": "0.9.0", - "co": "4.6.0", "jshint": "2.5.2", "pg-copy-streams": "0.3.0" }, diff --git a/test/integration/client/appname-tests.js b/test/integration/client/appname-tests.js index ca074ecc..55673eff 100644 --- a/test/integration/client/appname-tests.js +++ b/test/integration/client/appname-tests.js @@ -1,7 +1,8 @@ -return; var helper = require('./test-helper'); var Client = helper.Client; +var suite = new helper.Suite(); + var conInfo = helper.config; function getConInfo(override) { @@ -26,34 +27,37 @@ function getAppName(conf, cb) { })); } -test('No default appliation_name ', function(){ +suite.test('No default appliation_name ', function(done) { var conf = getConInfo(); - getAppName(conf, function(res){ + getAppName({ }, function(res){ assert.strictEqual(res, ''); + done() }); }); -test('fallback_application_name is used', function(){ +suite.test('fallback_application_name is used', function(done) { var fbAppName = 'this is my app'; var conf = getConInfo({ 'fallback_application_name' : fbAppName }); getAppName(conf, function(res){ assert.strictEqual(res, fbAppName); + done() }); }); -test('application_name is used', function(){ +suite.test('application_name is used', function(done) { var appName = 'some wired !@#$% application_name'; var conf = getConInfo({ 'application_name' : appName }); getAppName(conf, function(res){ assert.strictEqual(res, appName); + done() }); }); -test('application_name has precedence over fallback_application_name', function(){ +suite.test('application_name has precedence over fallback_application_name', function(done) { var appName = 'some wired !@#$% application_name'; var fbAppName = 'some other strange $$test$$ appname'; var conf = getConInfo({ @@ -62,10 +66,11 @@ test('application_name has precedence over fallback_application_name', function( }); getAppName(conf, function(res){ assert.strictEqual(res, appName); + done() }); }); -test('application_name from connection string', function(){ +suite.test('application_name from connection string', function(done) { var appName = 'my app'; var conParams = require(__dirname + '/../../../lib/connection-parameters'); var conf; @@ -76,6 +81,7 @@ test('application_name from connection string', function(){ } getAppName(conf, function(res){ assert.strictEqual(res, appName); + done() }); }); @@ -83,14 +89,12 @@ test('application_name from connection string', function(){ // TODO: make the test work for native client too if (!helper.args.native) { - test('application_name is read from the env', function(){ + suite.test('application_name is read from the env', function(done) { var appName = process.env.PGAPPNAME = 'testest'; - var conf = getConInfo({ - 'just some bla' : 'to fool the pool' - }); - getAppName(conf, function(res){ + getAppName({ }, function(res){ delete process.env.PGAPPNAME; assert.strictEqual(res, appName); + done() }); }); } diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index 937ea17b..7512d55b 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -1,166 +1,176 @@ var helper = require(__dirname + "/test-helper"); var pg = helper.pg; -test('serializing arrays', function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.isNull(err); +var suite = new helper.Suite() - test('nulls', function() { - client.query('SELECT $1::text[] as array', [[null]], assert.success(function(result) { - var array = result.rows[0].array; - assert.lengthIs(array, 1); - assert.isNull(array[0]); - })); - }); +pg.connect(assert.calls(function(err, client, release) { + assert.isNull(err); - test('elements containing JSON-escaped characters', function() { - var param = '\\"\\"'; + suite.test('nulls', function(done) { + client.query('SELECT $1::text[] as array', [[null]], assert.success(function(result) { + var array = result.rows[0].array; + assert.lengthIs(array, 1); + assert.isNull(array[0]); + done() + })); + }); - for (var i = 1; i <= 0x1f; i++) { - param += String.fromCharCode(i); - } + suite.test('elements containing JSON-escaped characters', function(done) { + var param = '\\"\\"'; - client.query('SELECT $1::text[] as array', [[param]], assert.success(function(result) { - var array = result.rows[0].array; - assert.lengthIs(array, 1); - assert.equal(array[0], param); - })); + for (var i = 1; i <= 0x1f; i++) { + param += String.fromCharCode(i); + } + client.query('SELECT $1::text[] as array', [[param]], assert.success(function(result) { + var array = result.rows[0].array; + assert.lengthIs(array, 1); + assert.equal(array[0], param); + done() + })); + }); + + suite.test('cleanup', () => release()) +})); + +pg.connect(assert.calls(function (err, client, release) { + assert.isNull(err); + client.query("CREATE TEMP TABLE why(names text[], numbors integer[])"); + client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); + suite.test('numbers', function (done) { + // client.connection.on('message', console.log) + client.query('SELECT numbors FROM why', assert.success(function (result) { + assert.lengthIs(result.rows[0].numbors, 3); + assert.equal(result.rows[0].numbors[0], 1); + assert.equal(result.rows[0].numbors[1], 2); + assert.equal(result.rows[0].numbors[2], 3); + done() + })) + }) + + suite.test('parses string arrays', function (done) { + client.query('SELECT names FROM why', assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0], 'aaron'); + assert.equal(names[1], 'brian'); + assert.equal(names[2], "a b c"); + done() + })) + }) + + suite.test('empty array', function (done) { + client.query("SELECT '{}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 0); + done() + })) + }) + + suite.test('element containing comma', function (done) { + client.query("SELECT '{\"joe,bob\",jim}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 2); + assert.equal(names[0], 'joe,bob'); + assert.equal(names[1], 'jim'); + done() + })) + }) + + suite.test('bracket in quotes', function (done) { + client.query("SELECT '{\"{\",\"}\"}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 2); + assert.equal(names[0], '{'); + assert.equal(names[1], '}'); + done() + })) + }) + + suite.test('null value', function (done) { + client.query("SELECT '{joe,null,bob,\"NULL\"}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 4); + assert.equal(names[0], 'joe'); + assert.equal(names[1], null); + assert.equal(names[2], 'bob'); + assert.equal(names[3], 'NULL'); + done() + })) + }) + + suite.test('element containing quote char', function (done) { + client.query("SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0], 'joe\''); + assert.equal(names[1], 'jim'); + assert.equal(names[2], 'bob"'); + done() + })) + }) + + suite.test('nested array', function (done) { + client.query("SELECT '{{1,joe},{2,bob}}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 2); + + assert.lengthIs(names[0], 2); + assert.equal(names[0][0], '1'); + assert.equal(names[0][1], 'joe'); + + assert.lengthIs(names[1], 2); + assert.equal(names[1][0], '2'); + assert.equal(names[1][1], 'bob'); + done() + })) + }) + + suite.test('integer array', function (done) { + client.query("SELECT '{1,2,3}'::integer[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0], 1); + assert.equal(names[1], 2); + assert.equal(names[2], 3); + done() + })) + }) + + suite.test('integer nested array', function (done) { + client.query("SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0][0], 1); + assert.equal(names[0][1], 100); + + assert.equal(names[1][0], 2); + assert.equal(names[1][1], 100); + + assert.equal(names[2][0], 3); + assert.equal(names[2][1], 100); + done() + })) + }) + + suite.test('JS array parameter', function (done) { + client.query("SELECT $1::integer[] as names", [[[1, 100], [2, 100], [3, 100]]], assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0][0], 1); + assert.equal(names[0][1], 100); + + assert.equal(names[1][0], 2); + assert.equal(names[1][1], 100); + + assert.equal(names[2][0], 3); + assert.equal(names[2][1], 100); + release(); + pg.end(); done(); - }); - })); -}); + })) + }) -test('parsing array results', function() { - 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(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); - test('numbers', function() { - // client.connection.on('message', console.log) - client.query('SELECT numbors FROM why', assert.success(function(result) { - assert.lengthIs(result.rows[0].numbors, 3); - assert.equal(result.rows[0].numbors[0], 1); - assert.equal(result.rows[0].numbors[1], 2); - assert.equal(result.rows[0].numbors[2], 3); - })) - }) - - test('parses string arrays', function() { - client.query('SELECT names FROM why', assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 'aaron'); - assert.equal(names[1], 'brian'); - assert.equal(names[2], "a b c"); - })) - }) - - test('empty array', function(){ - client.query("SELECT '{}'::text[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 0); - })) - }) - - test('element containing comma', function(){ - client.query("SELECT '{\"joe,bob\",jim}'::text[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - assert.equal(names[0], 'joe,bob'); - assert.equal(names[1], 'jim'); - })) - }) - - test('bracket in quotes', function(){ - client.query("SELECT '{\"{\",\"}\"}'::text[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - assert.equal(names[0], '{'); - assert.equal(names[1], '}'); - })) - }) - - test('null value', function(){ - client.query("SELECT '{joe,null,bob,\"NULL\"}'::text[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 4); - assert.equal(names[0], 'joe'); - assert.equal(names[1], null); - assert.equal(names[2], 'bob'); - assert.equal(names[3], 'NULL'); - })) - }) - - test('element containing quote char', function(){ - client.query("SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 'joe\''); - assert.equal(names[1], 'jim'); - assert.equal(names[2], 'bob"'); - })) - }) - - test('nested array', function(){ - client.query("SELECT '{{1,joe},{2,bob}}'::text[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - - assert.lengthIs(names[0], 2); - assert.equal(names[0][0], '1'); - assert.equal(names[0][1], 'joe'); - - assert.lengthIs(names[1], 2); - assert.equal(names[1][0], '2'); - assert.equal(names[1][1], 'bob'); - - })) - }) - - test('integer array', function(){ - client.query("SELECT '{1,2,3}'::integer[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 1); - assert.equal(names[1], 2); - assert.equal(names[2], 3); - })) - }) - - test('integer nested array', function(){ - client.query("SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0][0], 1); - assert.equal(names[0][1], 100); - - assert.equal(names[1][0], 2); - assert.equal(names[1][1], 100); - - assert.equal(names[2][0], 3); - assert.equal(names[2][1], 100); - })) - }) - - test('JS array parameter', function(){ - client.query("SELECT $1::integer[] as names", [[[1,100],[2,100],[3,100]]], assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0][0], 1); - assert.equal(names[0][1], 100); - - assert.equal(names[1][0], 2); - assert.equal(names[1][1], 100); - - assert.equal(names[2][0], 3); - assert.equal(names[2][1], 100); - done(); - pg.end(); - })) - }) - - })) -}) +})) diff --git a/test/integration/client/big-simple-query-tests.js b/test/integration/client/big-simple-query-tests.js index 514babe6..0065772c 100644 --- a/test/integration/client/big-simple-query-tests.js +++ b/test/integration/client/big-simple-query-tests.js @@ -1,6 +1,8 @@ var helper = require("./test-helper"); var Query = helper.pg.Query +const suite = new helper.Suite(); + /* Test to trigger a bug. @@ -14,31 +16,40 @@ var big_query_rows_2 = []; var big_query_rows_3 = []; // Works -test('big simple query 1',function() { +suite.test('big simple query 1', function(done) { var client = helper.client(); client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1")) .on('row', function(row) { big_query_rows_1.push(row); }) .on('error', function(error) { console.log("big simple query 1 error"); console.log(error); }); - client.on('drain', client.end.bind(client)); + client.on('drain', () => { + client.end() + done() + }); }); // Works -test('big simple query 2',function() { +suite.test('big simple query 2', function(done) { var client = helper.client(); client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''])) .on('row', function(row) { big_query_rows_2.push(row); }) .on('error', function(error) { console.log("big simple query 2 error"); console.log(error); }); - client.on('drain', client.end.bind(client)); + client.on('drain', () => { + client.end() + done() + }); }); // Fails most of the time with 'invalid byte sequence for encoding "UTF8": 0xb9' or 'insufficient data left in message' // If test 1 and 2 are commented out it works -test('big simple query 3',function() { +suite.test('big simple query 3',function(done) { var client = helper.client(); client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''])) .on('row', function(row) { big_query_rows_3.push(row); }) .on('error', function(error) { console.log("big simple query 3 error"); console.log(error); }); - client.on('drain', client.end.bind(client)); + client.on('drain', () => { + client.end() + done() + }); }); process.on('exit', function() { @@ -59,7 +70,7 @@ var runBigQuery = function(client) { }); } -test('many times', function() { +suite.test('many times', function(done) { var client = helper.client(); for(var i = 0; i < 20; i++) { runBigQuery(client); @@ -67,6 +78,7 @@ test('many times', function() { client.on('drain', function() { client.end(); setTimeout(function() { + done() //let client disconnect fully }, 100) }); diff --git a/test/integration/client/cancel-query-tests.js b/test/integration/client/cancel-query-tests.js index 0275fa89..4485b328 100644 --- a/test/integration/client/cancel-query-tests.js +++ b/test/integration/client/cancel-query-tests.js @@ -2,7 +2,7 @@ var helper = require("./test-helper"); var Query = helper.pg.Query; //before running this test make sure you run the script create-test-tables -test("cancellation of a query", function() { +new helper.Suite().test("cancellation of a query", function() { var client = helper.client(); diff --git a/test/integration/client/configuration-tests.js b/test/integration/client/configuration-tests.js index e922a4e7..8cde4cea 100644 --- a/test/integration/client/configuration-tests.js +++ b/test/integration/client/configuration-tests.js @@ -1,6 +1,8 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); var pg = helper.pg; +var suite = new helper.Suite(); + //clear process.env var realEnv = {}; for(var key in process.env) { @@ -8,8 +10,8 @@ for(var key in process.env) { if(!key.indexOf('PG')) delete process.env[key]; } -test('default values', function() { - assert.same(pg.defaults,{ +suite.test('default values are used in new clients', function() { + assert.same(pg.defaults, { user: process.env.USER, database: process.env.USER, password: null, @@ -17,42 +19,37 @@ test('default values', function() { rows: 0, poolSize: 10 }) - test('are used in new clients', function() { - var client = new pg.Client(); - assert.same(client,{ - user: process.env.USER, - database: process.env.USER, - password: null, - port: 5432 - }) + + var client = new pg.Client(); + assert.same(client, { + user: process.env.USER, + database: process.env.USER, + password: null, + port: 5432 }) }) -if(!helper.args.native) { - test('modified values', function() { - pg.defaults.user = 'boom' - pg.defaults.password = 'zap' - pg.defaults.database = 'pow' - pg.defaults.port = 1234 - pg.defaults.host = 'blam' - pg.defaults.rows = 10 - pg.defaults.poolSize = 0 - test('are passed into created clients', function() { - var client = new Client(); - assert.same(client,{ - user: 'boom', - password: 'zap', - database: 'pow', - port: 1234, - host: 'blam' - }) - }) +suite.test('modified values are passed to created clients', function() { + pg.defaults.user = 'boom' + pg.defaults.password = 'zap' + pg.defaults.database = 'pow' + pg.defaults.port = 1234 + pg.defaults.host = 'blam' + + var client = new Client(); + assert.same(client,{ + user: 'boom', + password: 'zap', + database: 'pow', + port: 1234, + host: 'blam' }) -} +}) - -//restore process.env -for(var key in realEnv) { - process.env[key] = realEnv[key]; -} +suite.test('cleanup', () => { + //restore process.env + for (var key in realEnv) { + process.env[key] = realEnv[key]; + } +}) diff --git a/test/integration/client/custom-types-tests.js b/test/integration/client/custom-types-tests.js index 38479229..9305dbbd 100644 --- a/test/integration/client/custom-types-tests.js +++ b/test/integration/client/custom-types-tests.js @@ -1,18 +1,19 @@ -var helper = require(__dirname + '/test-helper'); -return console.log('TODO: get this working for non-native client'); +const helper = require('./test-helper'); +const Client = helper.pg.Client; +const suite = new helper.Suite() -helper.config.types = { - getTypeParser: function() { - return function() { - return 'okay!' - } +const client = new Client({ + types: { + getTypeParser: () => () => 'okay!' } -}; +}) -helper.pg.connect(helper.config, assert.success(function(client, done) { - client.query('SELECT NOW() as val', assert.success(function(res) { - assert.equal(res.rows[0].val, 'okay!'); - done(); - helper.pg.end(); - })); -})); +suite.test('custom type parser in client config', (done) => { + client.connect() + .then(() => { + client.query('SELECT NOW() as val', assert.success(function (res) { + assert.equal(res.rows[0].val, 'okay!'); + client.end().then(done); + })); + }) +}) diff --git a/test/integration/client/empty-query-tests.js b/test/integration/client/empty-query-tests.js index 6f0d574d..8251088a 100644 --- a/test/integration/client/empty-query-tests.js +++ b/test/integration/client/empty-query-tests.js @@ -1,17 +1,20 @@ -var helper = require(__dirname+'/test-helper'); -var client = helper.client(); +var helper = require('./test-helper'); +const suite = new helper.Suite() -test("empty query message handling", function() { +suite.test("empty query message handling", function(done) { + const client = helper.client(); assert.emits(client, 'drain', function() { - client.end(); + client.end(done); }); client.query({text: ""}); }); -test('callback supported', assert.calls(function() { +suite.test('callback supported', function(done) { + const client = helper.client(); client.query("", function(err, result) { assert.isNull(err); assert.empty(result.rows); + client.end(done) }) -})) +}) diff --git a/test/integration/client/end-callback-tests.js b/test/integration/client/end-callback-tests.js deleted file mode 100644 index 997cfb0c..00000000 --- a/test/integration/client/end-callback-tests.js +++ /dev/null @@ -1,6 +0,0 @@ -var helper = require('./test-helper') - -var client = helper.client(assert.success(function() { - client.end(assert.success(function() { - })) -})) diff --git a/test/integration/client/force-native-with-envvar-tests.js b/test/integration/client/force-native-with-envvar-tests.js deleted file mode 100644 index 0ac3098e..00000000 --- a/test/integration/client/force-native-with-envvar-tests.js +++ /dev/null @@ -1,39 +0,0 @@ -return; -/** - * helper needs to be loaded for the asserts but it alos proloads - * client which we don't want here - * - */ -var helper = require(__dirname+"/test-helper") - , path = require('path') -; - -var paths = { - 'pg' : path.join(__dirname, '..', '..', '..', 'lib', 'index.js') , - 'query_js' : path.join(__dirname, '..', '..', '..', 'lib', 'query.js') , - 'query_native' : path.join(__dirname, '..', '..', '..', 'lib', 'native', 'query.js') , -}; - -/** - * delete the modules we are concerned about from the - * module cache, so they get loaded cleanly and the env - * var can kick in ... - */ -function emptyCache(){ - Object.keys(require.cache).forEach(function(key){ - delete require.cache[key]; - }); -}; - -emptyCache(); -process.env.NODE_PG_FORCE_NATIVE = '1'; - -var pg = require( paths.pg ); -var query_native = require( paths.query_native ); -var query_js = require( paths.query_js ); - -assert.deepEqual(pg.Client.Query, query_native); -assert.notDeepEqual(pg.Client.Query, query_js); - -emptyCache(); -delete process.env.NODE_PG_FORCE_NATIVE diff --git a/test/integration/client/huge-numeric-tests.js b/test/integration/client/huge-numeric-tests.js index 8db3f296..76b2aac5 100644 --- a/test/integration/client/huge-numeric-tests.js +++ b/test/integration/client/huge-numeric-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); helper.pg.connect(helper.config, assert.success(function(client, done) { var types = require('pg-types'); @@ -18,5 +18,3 @@ helper.pg.connect(helper.config, assert.success(function(client, done) { done(); })) })); - -//custom type converter diff --git a/test/integration/client/json-type-parsing-tests.js b/test/integration/client/json-type-parsing-tests.js index 1c0759bf..1fe21ac5 100644 --- a/test/integration/client/json-type-parsing-tests.js +++ b/test/integration/client/json-type-parsing-tests.js @@ -1,38 +1,26 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); var assert = require('assert'); -//if you want binary support, pull request me! -if (helper.config.binary) { - console.log('binary mode does not support JSON right now'); - return; -} -test('can read and write json', function() { - helper.pg.connect(helper.config, function(err, client, done) { - assert.ifError(err); - helper.versionGTE(client, '9.2.0', assert.success(function(jsonSupported) { - if(!jsonSupported) { - console.log('skip json test on older versions of postgres'); - done(); - return helper.pg.end(); - } - client.query('CREATE TEMP TABLE stuff(id SERIAL PRIMARY KEY, data JSON)'); - var value ={name: 'Brian', age: 250, alive: true, now: new Date()}; - client.query('INSERT INTO stuff (data) VALUES ($1)', [value]); - client.query('SELECT * FROM stuff', assert.success(function(result) { - assert.equal(result.rows.length, 1); - assert.equal(typeof result.rows[0].data, 'object'); - var row = result.rows[0].data; - assert.strictEqual(row.name, value.name); - assert.strictEqual(row.age, value.age); - assert.strictEqual(row.alive, value.alive); - test('row should have "now" as a date', function() { - return false; - assert(row.now instanceof Date, 'row.now should be a date instance but is ' + typeof row.now); - }); - assert.equal(JSON.stringify(row.now), JSON.stringify(value.now)); - done(); - helper.pg.end(); - })); +helper.pg.connect(assert.success(function (client, done) { + helper.versionGTE(client, '9.2.0', assert.success(function (jsonSupported) { + if (!jsonSupported) { + console.log('skip json test on older versions of postgres'); + done(); + return helper.pg.end(); + } + client.query('CREATE TEMP TABLE stuff(id SERIAL PRIMARY KEY, data JSON)'); + var value = { name: 'Brian', age: 250, alive: true, now: new Date() }; + client.query('INSERT INTO stuff (data) VALUES ($1)', [value]); + client.query('SELECT * FROM stuff', assert.success(function (result) { + assert.equal(result.rows.length, 1); + assert.equal(typeof result.rows[0].data, 'object'); + var row = result.rows[0].data; + assert.strictEqual(row.name, value.name); + assert.strictEqual(row.age, value.age); + assert.strictEqual(row.alive, value.alive); + assert.equal(JSON.stringify(row.now), JSON.stringify(value.now)); + done(); + helper.pg.end(); })); - }); -}); + })); +})); diff --git a/test/integration/client/network-partition-tests.js b/test/integration/client/network-partition-tests.js index 945a2ee8..8e9d8af8 100644 --- a/test/integration/client/network-partition-tests.js +++ b/test/integration/client/network-partition-tests.js @@ -1,7 +1,6 @@ -var co = require('co') - var buffers = require('../../test-buffers') var helper = require('./test-helper') +var suite = new helper.Suite() var net = require('net') @@ -77,13 +76,12 @@ var testServer = function (server, cb) { }) } -// test being disconnected after readyForQuery -const respondingServer = new Server(buffers.readyForQuery()) -testServer(respondingServer, function () { - process.stdout.write('.') - // test being disconnected from a server that never responds - const silentServer = new Server() - testServer(silentServer, function () { - process.stdout.write('.') - }) +suite.test('readyForQuery server', (done) => { + const respondingServer = new Server(buffers.readyForQuery()) + testServer(respondingServer, done) +}) + +suite.test('silent server', (done) => { + const silentServer = new Server() + testServer(silentServer, done) }) diff --git a/test/integration/domain-tests.js b/test/integration/domain-tests.js index c3beae52..dbd71c18 100644 --- a/test/integration/domain-tests.js +++ b/test/integration/domain-tests.js @@ -2,59 +2,48 @@ var async = require('async') var helper = require('./test-helper') var Query = helper.pg.Query +var suite = new helper.Suite() -var testWithoutDomain = function(cb) { - test('no domain', function() { +suite.test('no domain', function (cb) { + assert(!process.domain) + helper.pg.connect(assert.success(function (client, done) { assert(!process.domain) - helper.pg.connect(helper.config, assert.success(function(client, done) { - assert(!process.domain) - done() - cb() + done() + cb() + })) +}) + +suite.test('with domain', function (cb) { + assert(!process.domain) + var domain = require('domain').create() + domain.run(function () { + var startingDomain = process.domain + assert(startingDomain) + helper.pg.connect(helper.config, assert.success(function (client, done) { + assert(process.domain, 'no domain exists in connect callback') + assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') + var query = client.query('SELECT NOW()', assert.success(function () { + assert(process.domain, 'no domain exists in query callback') + assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') + done(true) + process.domain.exit() + cb() + })) })) }) -} - -var testWithDomain = function(cb) { - test('with domain', function() { - assert(!process.domain) - var domain = require('domain').create() - domain.run(function() { - var startingDomain = process.domain - assert(startingDomain) - helper.pg.connect(helper.config, assert.success(function(client, done) { - assert(process.domain, 'no domain exists in connect callback') - assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') - var query = client.query('SELECT NOW()', assert.success(function() { - assert(process.domain, 'no domain exists in query callback') - assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') - done(true) - process.domain.exit() - cb() - })) - })) - }) - }) -} - -var testErrorWithDomain = function(cb) { - test('error on domain', function() { - var domain = require('domain').create() - domain.on('error', function() { - cb() - }) - domain.run(function() { - helper.pg.connect(helper.config, assert.success(function(client, done) { - client.query(new Query('SELECT SLDKJFLSKDJF')) - client.on('drain', done) - })) - }) - }) -} - -async.series([ - testWithoutDomain, - testWithDomain, - testErrorWithDomain -], function() { - helper.pg.end() }) + +suite.test('error on domain', function (cb) { + var domain = require('domain').create() + domain.on('error', function () { + cb() + }) + domain.run(function () { + helper.pg.connect(helper.config, assert.success(function (client, done) { + client.query(new Query('SELECT SLDKJFLSKDJF')) + client.on('drain', done) + })) + }) +}) + +suite.test('cleanup', () => helper.pg.end()) diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index 62bad27c..ff5c0344 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -1,20 +1,21 @@ var helper = require('../test-helper'); var pg = helper.pg; -test('parsing array results', function () { - pg.connect(helper.config, assert.calls(function (err, client, done) { +var suite = new helper.Suite() + +suite.test('parsing array decimal results', function (done) { + pg.connect(helper.config, assert.calls(function (err, client, release) { assert.isNull(err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])"); client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log); - test('decimals', function () { - client.query('SELECT decimals FROM why', assert.success(function (result) { - assert.lengthIs(result.rows[0].decimals, 3); - assert.equal(result.rows[0].decimals[0], 0.1); - assert.equal(result.rows[0].decimals[1], 0.05); - assert.equal(result.rows[0].decimals[2], 3.654); - done() - pg.end(); - })) - }) + client.query('SELECT decimals FROM why', assert.success(function (result) { + assert.lengthIs(result.rows[0].decimals, 3); + assert.equal(result.rows[0].decimals[0], 0.1); + assert.equal(result.rows[0].decimals[1], 0.05); + assert.equal(result.rows[0].decimals[2], 3.654); + release() + pg.end(); + done() + })) })) }) diff --git a/test/integration/gh-issues/507-tests.js b/test/integration/gh-issues/507-tests.js index ef75effc..097e3be1 100644 --- a/test/integration/gh-issues/507-tests.js +++ b/test/integration/gh-issues/507-tests.js @@ -1,7 +1,7 @@ var helper = require(__dirname + "/../test-helper"); var pg = helper.pg; -test('parsing array results', function() { +new helper.Suite().test('parsing array results', function(cb) { pg.connect(helper.config, assert.success(function(client, done) { client.query('CREATE TEMP TABLE test_table(bar integer, "baz\'s" integer)') client.query('INSERT INTO test_table(bar, "baz\'s") VALUES(1, 1), (2, 2)') @@ -10,6 +10,7 @@ test('parsing array results', function() { assert.equal(res.rows[1]["baz's"], 2) done() pg.end() + cb() }) })) }) diff --git a/test/integration/gh-issues/600-tests.js b/test/integration/gh-issues/600-tests.js index 0476d42d..b64f19fa 100644 --- a/test/integration/gh-issues/600-tests.js +++ b/test/integration/gh-issues/600-tests.js @@ -1,5 +1,6 @@ var async = require('async'); var helper = require('../test-helper'); +const suite = new helper.Suite() var db = helper.client(); @@ -53,13 +54,14 @@ var steps = [ insertDataBar ] -test('test if query fails', function() { +suite.test('test if query fails', function(done) { async.series(steps, assert.success(function() { db.end() + done() })) }) -test('test if prepare works but bind fails', function() { +suite.test('test if prepare works but bind fails', function(done) { var client = helper.client(); var q = { text: 'SELECT $1::int as name', @@ -71,6 +73,7 @@ test('test if prepare works but bind fails', function() { client.query(q, assert.calls(function(err, res) { assert.ifError(err); client.end(); + done() })); })); }); diff --git a/test/integration/gh-issues/675-tests.js b/test/integration/gh-issues/675-tests.js index c27d3632..f7fbf01b 100644 --- a/test/integration/gh-issues/675-tests.js +++ b/test/integration/gh-issues/675-tests.js @@ -1,7 +1,7 @@ var helper = require('../test-helper'); var assert = require('assert'); -helper.pg.connect(helper.config, function(err, client, done) { +helper.pg.connect(function(err, client, done) { if (err) throw err; var c = 'CREATE TEMP TABLE posts (body TEXT)'; diff --git a/test/integration/gh-issues/699-tests.js b/test/integration/gh-issues/699-tests.js index f9cb876d..8e92ff22 100644 --- a/test/integration/gh-issues/699-tests.js +++ b/test/integration/gh-issues/699-tests.js @@ -4,7 +4,7 @@ var copyFrom = require('pg-copy-streams').from; if(helper.args.native) return; -helper.pg.connect(helper.config, function (err, client, done) { +helper.pg.connect(function (err, client, done) { if (err) throw err; var c = 'CREATE TEMP TABLE employee (id integer, fname varchar(400), lname varchar(400))'; diff --git a/test/integration/gh-issues/787-tests.js b/test/integration/gh-issues/787-tests.js index e75c6766..df90cc54 100644 --- a/test/integration/gh-issues/787-tests.js +++ b/test/integration/gh-issues/787-tests.js @@ -1,6 +1,6 @@ -var helper = require(__dirname + '/../test-helper'); +var helper = require('../test-helper'); -helper.pg.connect(helper.config, function(err,client) { +helper.pg.connect(function(err,client) { var q = { name: 'This is a super long query name just so I can test that an error message is properly spit out to console.error without throwing an exception or anything', text: 'SELECT NOW()' diff --git a/test/integration/test-helper.js b/test/integration/test-helper.js index c6a4922d..ceed87d5 100644 --- a/test/integration/test-helper.js +++ b/test/integration/test-helper.js @@ -8,7 +8,7 @@ if(helper.args.native) { //creates a client from cli parameters helper.client = function(cb) { - var client = new Client(helper.config); + var client = new Client(); client.connect(cb); return client; }; diff --git a/test/native/callback-api-tests.js b/test/native/callback-api-tests.js index 95e9a8ff..6193ba74 100644 --- a/test/native/callback-api-tests.js +++ b/test/native/callback-api-tests.js @@ -1,8 +1,9 @@ var domain = require('domain'); -var helper = require(__dirname + "/../test-helper"); -var Client = require(__dirname + "/../../lib/native"); +var helper = require("./../test-helper"); +var Client = require("./../../lib/native"); +const suite = new helper.Suite() -test('fires callback with results', function() { +suite.test('fires callback with results', function(done) { var client = new Client(helper.config); client.connect(); client.query('SELECT 1 as num', assert.calls(function(err, result) { @@ -12,12 +13,12 @@ test('fires callback with results', function() { client.query('SELECT * FROM person WHERE name = $1', ['Brian'], assert.calls(function(err, result) { assert.isNull(err); assert.equal(result.rows[0].name, 'Brian'); - client.end(); + client.end(done); })) })); }) -test('preserves domain', function() { +suite.test('preserves domain', function(done) { var dom = domain.create(); dom.run(function() { @@ -26,7 +27,7 @@ test('preserves domain', function() { client.connect() client.query('select 1', function() { assert.ok(dom === require('domain').active, 'domain is still active'); - client.end(); + client.end(done); }); }); }) diff --git a/test/suite.js b/test/suite.js index 7d248b36..43c9e620 100644 --- a/test/suite.js +++ b/test/suite.js @@ -24,11 +24,12 @@ class Test { } if (!this.action.length) { const result = this.action.call(this) - if ((result || 0).then) { - result - .then(() => cb()) - .catch(err => cb(err || new Error('Unhandled promise rejection'))) + if (!(result || 0).then) { + return cb() } + result + .then(() => cb()) + .catch(err => cb(err || new Error('Unhandled promise rejection'))) } else { this.action.call(this, cb) } @@ -51,7 +52,7 @@ class Suite { const tid = setTimeout(() => { const err = Error(`test: ${test.name} did not complete withint ${test.timeout}ms`) - cb(err) + process.exit(-1) }, test.timeout) test.run((err) => { @@ -61,13 +62,14 @@ class Suite { process.exit(-1) } else { process.stdout.write('✔\n') + cb() } - cb(err) }) } test(name, cb) { - this._queue.push(new Test(name, cb)) + const test = new Test(name, cb) + this._queue.push(test) } } diff --git a/test/test-helper.js b/test/test-helper.js index 4cf6a455..7fab5ad6 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,13 +1,17 @@ //make assert a global... assert = require('assert'); -process.noDeprecation = true; var EventEmitter = require('events').EventEmitter; var sys = require('util'); -var BufferList = require(__dirname+'/buffer-list') -var Connection = require(__dirname + '/../lib/connection'); +process.noDeprecation = true; -Client = require(__dirname + '/../lib').Client; +var BufferList = require('./buffer-list') +const Suite = require('./suite') +const args = require('./cli'); + +var Connection = require('./../lib/connection'); + +Client = require('./../lib').Client; process.on('uncaughtException', function(d) { if ('stack' in d && 'message' in d) { @@ -16,6 +20,7 @@ process.on('uncaughtException', function(d) { } else { console.log(d); } + process.exit(-1); }); assert.same = function(actual, expected) { @@ -24,7 +29,6 @@ assert.same = function(actual, expected) { } }; - assert.emits = function(item, eventName, callback, message) { var called = false; var id = setTimeout(function() { @@ -71,13 +75,6 @@ assert.UTCDate = function(actual, year, month, day, hours, min, sec, milisecond) assert.equal(actualMili, milisecond, "expected milisecond " + milisecond + " but got " + actualMili); }; -var spit = function(actual, expected) { - console.log(""); - console.log("actual " + sys.inspect(actual)); - console.log("expect " + sys.inspect(expected)); - console.log(""); -} - assert.equalBuffers = function(actual, expected) { if(actual.length != expected.length) { spit(actual, expected) @@ -171,6 +168,12 @@ assert.isNull = function(item, message) { assert.ok(item === null, message); }; +const getMode = () => { + if (args.native) return 'native' + if (args.binary) return 'binary' + return '' +} + test = function(name, action) { test.testCount ++; test[name] = action; @@ -184,7 +187,6 @@ test = function(name, action) { //print out the filename process.stdout.write(require('path').basename(process.argv[1])); -var args = require(__dirname + '/cli'); if(args.binary) process.stdout.write(' (binary)'); if(args.native) process.stdout.write(' (native)'); @@ -240,8 +242,8 @@ var resetTimezoneOffset = function() { module.exports = { Sink: Sink, - Suite: require('./suite'), - pg: require(__dirname + '/../lib/'), + Suite: Suite, + pg: require('./../lib/'), args: args, config: args, sys: sys, diff --git a/test/unit/client/early-disconnect-tests.js b/test/unit/client/early-disconnect-tests.js index c67a783a..a4c38be9 100644 --- a/test/unit/client/early-disconnect-tests.js +++ b/test/unit/client/early-disconnect-tests.js @@ -4,20 +4,13 @@ var pg = require('../../..//lib/index.js'); /* console.log() messages show up in `make test` output. TODO: fix it. */ var server = net.createServer(function(c) { - console.log('server connected'); c.destroy(); - console.log('server socket destroyed.'); - server.close(function() { console.log('server closed'); }); + server.close(); }); server.listen(7777, function() { - console.log('server listening'); var client = new pg.Client('postgres://localhost:7777'); - console.log('client connecting'); client.connect(assert.calls(function(err) { - if (err) console.log("Error on connect: "+err); - else console.log('client connected'); assert(err); })); - }); From f12eb0a6fdb4ce6f218e73ee27d4ff8727ae3c99 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 21:24:44 -0500 Subject: [PATCH 30/58] Format more tests --- test/integration/client/no-data-tests.js | 4 +- .../integration/client/no-row-result-tests.js | 10 +-- test/integration/client/notice-tests.js | 62 +++++++++++-------- test/integration/client/parse-int-8-tests.js | 6 +- test/suite.js | 1 + 5 files changed, 47 insertions(+), 36 deletions(-) diff --git a/test/integration/client/no-data-tests.js b/test/integration/client/no-data-tests.js index 3258e6a5..28a4999a 100644 --- a/test/integration/client/no-data-tests.js +++ b/test/integration/client/no-data-tests.js @@ -1,6 +1,8 @@ var helper = require('./test-helper'); +const suite = new helper.Suite() -test("noData message handling", function() { + +suite.test("noData message handling", function() { var client = helper.client(); diff --git a/test/integration/client/no-row-result-tests.js b/test/integration/client/no-row-result-tests.js index 99ed0da7..9081e233 100644 --- a/test/integration/client/no-row-result-tests.js +++ b/test/integration/client/no-row-result-tests.js @@ -1,12 +1,8 @@ var helper = require(__dirname + '/test-helper'); var pg = helper.pg; -var config = helper.config; +const suite = new helper.Suite() -test('can access results when no rows are returned', function() { - if(config.native) { - console.log('maybe fix this?', __filename) - return false - } +suite.test('can access results when no rows are returned', function() { var checkResult = function(result) { assert(result.fields, 'should have fields definition'); assert.equal(result.fields.length, 1); @@ -15,7 +11,7 @@ test('can access results when no rows are returned', function() { pg.end(); }; - pg.connect(config, assert.success(function(client, done) { + pg.connect(assert.success(function(client, done) { const q = new pg.Query('select $1::text as val limit 0', ['hi']) var query = client.query(q, assert.success(function(result) { checkResult(result); diff --git a/test/integration/client/notice-tests.js b/test/integration/client/notice-tests.js index 764b45cd..4d6634e1 100644 --- a/test/integration/client/notice-tests.js +++ b/test/integration/client/notice-tests.js @@ -1,40 +1,27 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); +const suite = new helper.Suite() -test('emits notice message', function() { - //TODO this doesn't work on all versions of postgres - return false; +suite.test('emits notify message', function (done) { var client = helper.client(); - client.query('create temp table boom(id serial, size integer)'); - assert.emits(client, 'notice', function(notice) { - assert.ok(notice != null); - //TODO ending connection after notice generates weird errors - process.nextTick(function() { - client.end(); - }) - }); -}) - -test('emits notify message', function() { - var client = helper.client(); - client.query('LISTEN boom', assert.calls(function() { + client.query('LISTEN boom', assert.calls(function () { var otherClient = helper.client(); - otherClient.query('LISTEN boom', assert.calls(function() { - assert.emits(client, 'notification', function(msg) { + var bothEmitted = -1 + otherClient.query('LISTEN boom', assert.calls(function () { + assert.emits(client, 'notification', function (msg) { //make sure PQfreemem doesn't invalidate string pointers - setTimeout(function() { + setTimeout(function () { assert.equal(msg.channel, 'boom'); assert.ok(msg.payload == 'omg!' /*9.x*/ || msg.payload == '' /*8.x*/, "expected blank payload or correct payload but got " + msg.message) - client.end() + client.end(++bothEmitted ? done : undefined) }, 100) - }); - assert.emits(otherClient, 'notification', function(msg) { + assert.emits(otherClient, 'notification', function (msg) { assert.equal(msg.channel, 'boom'); - otherClient.end(); + otherClient.end(++bothEmitted ? done : undefined); }); - client.query("NOTIFY boom, 'omg!'", function(err, q) { - if(err) { + client.query("NOTIFY boom, 'omg!'", function (err, q) { + if (err) { //notify not supported with payload on 8.x client.query("NOTIFY boom") } @@ -43,3 +30,26 @@ test('emits notify message', function() { })); }) + + +suite.test('emits notice message', function (done) { + if (helper.args.native) { + return console.error('need to get notice message working on native') + } + //TODO this doesn't work on all versions of postgres + var client = helper.client(); + const text = ` +DO language plpgsql $$ +BEGIN + RAISE NOTICE 'hello, world!'; +END +$$; + ` + client.query(text, () => { + client.end(); + }); + assert.emits(client, 'notice', function (notice) { + assert.ok(notice != null); + done(); + }); +}) diff --git a/test/integration/client/parse-int-8-tests.js b/test/integration/client/parse-int-8-tests.js index 42228cb8..4ece9445 100644 --- a/test/integration/client/parse-int-8-tests.js +++ b/test/integration/client/parse-int-8-tests.js @@ -1,7 +1,9 @@ -var helper = require(__dirname + '/../test-helper'); +var helper = require('../test-helper'); var pg = helper.pg; -test('ability to turn on and off parser', function() { +const suite = new helper.Suite() + +suite.test('ability to turn on and off parser', function() { if(helper.args.binary) return false; pg.connect(helper.config, assert.success(function(client, done) { pg.defaults.parseInt8 = true; diff --git a/test/suite.js b/test/suite.js index 43c9e620..22d1a9cc 100644 --- a/test/suite.js +++ b/test/suite.js @@ -52,6 +52,7 @@ class Suite { const tid = setTimeout(() => { const err = Error(`test: ${test.name} did not complete withint ${test.timeout}ms`) + console.log('\n' + err.stack) process.exit(-1) }, test.timeout) From 132861f43fe38ca6e0ef8cd4ce44a8470c28b7c7 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 21:35:16 -0500 Subject: [PATCH 31/58] Test cleanup --- test/integration/client/notice-tests.js | 3 +- .../client/prepared-statement-tests.js | 91 ++++++++----------- 2 files changed, 40 insertions(+), 54 deletions(-) diff --git a/test/integration/client/notice-tests.js b/test/integration/client/notice-tests.js index 4d6634e1..eba01a80 100644 --- a/test/integration/client/notice-tests.js +++ b/test/integration/client/notice-tests.js @@ -34,7 +34,8 @@ suite.test('emits notify message', function (done) { suite.test('emits notice message', function (done) { if (helper.args.native) { - return console.error('need to get notice message working on native') + console.error('need to get notice message working on native') + return done() } //TODO this doesn't work on all versions of postgres var client = helper.client(); diff --git a/test/integration/client/prepared-statement-tests.js b/test/integration/client/prepared-statement-tests.js index 9735407a..0d037b00 100644 --- a/test/integration/client/prepared-statement-tests.js +++ b/test/integration/client/prepared-statement-tests.js @@ -1,7 +1,9 @@ var helper = require('./test-helper'); var Query = helper.pg.Query; -test("named prepared statement", function() { +var suite = new helper.Suite() + +;(function() { var client = helper.client(); client.on('drain', client.end.bind(client)); @@ -9,7 +11,7 @@ test("named prepared statement", function() { var queryName = "user by age and like name"; var parseCount = 0; - test("first named prepared statement", function() { + suite.test("first named prepared statement", function(done) { var query = client.query(new Query({ text: 'select name from person where age <= $1 and name LIKE $2', values: [20, 'Bri%'], @@ -20,11 +22,10 @@ test("named prepared statement", function() { assert.equal(row.name, 'Brian'); }); - assert.emits(query, 'end', function() { - }); + query.on('end', () => done()) }); - test("second named prepared statement with same name & text", function() { + suite.test("second named prepared statement with same name & text", function(done) { var cachedQuery = client.query(new Query({ text: 'select name from person where age <= $1 and name LIKE $2', name: queryName, @@ -35,11 +36,10 @@ test("named prepared statement", function() { assert.equal(row.name, 'Aaron'); }); - assert.emits(cachedQuery, 'end', function() { - }); + cachedQuery.on('end', () => done()) }); - test("with same name, but without query text", function() { + suite.test("with same name, but without query text", function(done) { var q = client.query(new Query({ name: queryName, values: [30, '%n%'] @@ -54,23 +54,19 @@ test("named prepared statement", function() { }); }); - assert.emits(q, 'end', function() { }); + q.on('end', () => done()) }); -}); +})(); -test("prepared statements on different clients", function() { +;(function() { var statementName = "differ"; var statement1 = "select count(*)::int4 as count from person"; var statement2 = "select count(*)::int4 as count from person where age < $1"; - var client1Finished = false; - var client2Finished = false; - var client1 = helper.client(); - var client2 = helper.client(); - test("client 1 execution", function() { + suite.test("client 1 execution", function(done) { var query = client1.query({ name: statementName, @@ -78,83 +74,72 @@ test("prepared statements on different clients", function() { }, (err, res) => { assert(!err); assert.equal(res.rows[0].count, 26); - if(client2Finished) { - client1.end(); - client2.end(); - } else { - client1Finished = true; - } + done() }); - }); - test('client 2 execution', function() { + suite.test('client 2 execution', function(done) { var query = client2.query(new Query({ name: statementName, text: statement2, values: [11] })); - test('gets right data', function() { - assert.emits(query, 'row', function(row) { - assert.equal(row.count, 1); - }); + assert.emits(query, 'row', function(row) { + assert.equal(row.count, 1); }); assert.emits(query, 'end', function() { - if(client1Finished) { - client1.end(); - client2.end(); - } else { - client2Finished = true; - } + done(); }); }); -}); + suite.test('clean up clients', () => { + return client1.end().then(() => client2.end()) + }); -test('prepared statement', function() { +})(); + +;(function() { var client = helper.client(); - client.on('drain', client.end.bind(client)); client.query('CREATE TEMP TABLE zoom(name varchar(100));'); client.query("INSERT INTO zoom (name) VALUES ('zed')"); client.query("INSERT INTO zoom (name) VALUES ('postgres')"); client.query("INSERT INTO zoom (name) VALUES ('node postgres')"); - var checkForResults = function(q) { - test('row callback fires for each result', function() { - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'node postgres'); + var checkForResults = function (q) { + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'node postgres'); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'postgres'); + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'postgres'); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'zed'); - }) - }); - }) + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'zed'); + }) + }); }) }; - test('with small row count', function() { + suite.test('with small row count', function (done) { var query = client.query(new Query({ name: 'get names', text: "SELECT name FROM zoom ORDER BY name", rows: 1 - })); + }, done)); checkForResults(query); }) - test('with large row count', function() { + suite.test('with large row count', function (done) { var query = client.query(new Query({ name: 'get names', text: 'SELECT name FROM zoom ORDER BY name', rows: 1000 - })) + }, done)) checkForResults(query); }) -}) + suite.test('cleanup', () => client.end()) +})() From e100152fb0297e69133ebf8122baf338af3eae1d Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 21:49:20 -0500 Subject: [PATCH 32/58] Remove failing travis test --- test/integration/client/notice-tests.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/integration/client/notice-tests.js b/test/integration/client/notice-tests.js index eba01a80..f226de8f 100644 --- a/test/integration/client/notice-tests.js +++ b/test/integration/client/notice-tests.js @@ -30,9 +30,8 @@ suite.test('emits notify message', function (done) { })); }) - - -suite.test('emits notice message', function (done) { +// this test fails on travis due to their config +suite.test('emits notice message', false, function (done) { if (helper.args.native) { console.error('need to get notice message working on native') return done() From a4b42ac36b29ef6d04a9b8c5bc5868bf3b2be498 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 21:55:20 -0500 Subject: [PATCH 33/58] Add co to dev deps --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 1d8a6913..5eecc421 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ }, "devDependencies": { "async": "0.9.0", + "co": "4.6.0", "jshint": "2.5.2", "pg-copy-streams": "0.3.0" }, From fc3634045bccf8765e1354d926b9c200629fa896 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Thu, 15 Jun 2017 13:22:58 -0500 Subject: [PATCH 34/58] Move attach listeners into its own function Just for readability --- lib/client.js | 144 ++++++++++++++++++++++++++------------------------ 1 file changed, 74 insertions(+), 70 deletions(-) diff --git a/lib/client.js b/lib/client.js index 0b67ba31..563adbe0 100644 --- a/lib/client.js +++ b/lib/client.js @@ -112,52 +112,8 @@ Client.prototype.connect = function(callback) { //after the connection initially becomes ready for queries con.once('readyForQuery', function() { self._connecting = false; + self._attachListeners(con); - //delegate rowDescription to active query - con.on('rowDescription', function(msg) { - self.activeQuery.handleRowDescription(msg); - }); - - //delegate dataRow to active query - con.on('dataRow', function(msg) { - self.activeQuery.handleDataRow(msg); - }); - - //delegate portalSuspended to active query - con.on('portalSuspended', function(msg) { - self.activeQuery.handlePortalSuspended(con); - }); - - //deletagate emptyQuery to active query - con.on('emptyQuery', function(msg) { - self.activeQuery.handleEmptyQuery(con); - }); - - //delegate commandComplete to active query - con.on('commandComplete', function(msg) { - self.activeQuery.handleCommandComplete(msg, con); - }); - - //if a prepared statement has a name and properly parses - //we track that its already been executed so we don't parse - //it again on the same client - con.on('parseComplete', function(msg) { - if(self.activeQuery.name) { - con.parsedStatements[self.activeQuery.name] = true; - } - }); - - con.on('copyInResponse', function(msg) { - self.activeQuery.handleCopyInResponse(self.connection); - }); - - con.on('copyData', function (msg) { - self.activeQuery.handleCopyData(msg, self.connection); - }); - - con.on('notification', function(msg) { - self.emit('notification', msg); - }); //process possible callback argument to Client#connect if (callback) { @@ -241,10 +197,58 @@ Client.prototype.connect = function(callback) { }) }) } - }; -Client.prototype.getStartupConf = function() { +Client.prototype._attachListeners = function(con) { + const self = this + //delegate rowDescription to active query + con.on('rowDescription', function (msg) { + self.activeQuery.handleRowDescription(msg); + }); + + //delegate dataRow to active query + con.on('dataRow', function (msg) { + self.activeQuery.handleDataRow(msg); + }); + + //delegate portalSuspended to active query + con.on('portalSuspended', function (msg) { + self.activeQuery.handlePortalSuspended(con); + }); + + //deletagate emptyQuery to active query + con.on('emptyQuery', function (msg) { + self.activeQuery.handleEmptyQuery(con); + }); + + //delegate commandComplete to active query + con.on('commandComplete', function (msg) { + self.activeQuery.handleCommandComplete(msg, con); + }); + + //if a prepared statement has a name and properly parses + //we track that its already been executed so we don't parse + //it again on the same client + con.on('parseComplete', function (msg) { + if (self.activeQuery.name) { + con.parsedStatements[self.activeQuery.name] = true; + } + }); + + con.on('copyInResponse', function (msg) { + self.activeQuery.handleCopyInResponse(self.connection); + }); + + con.on('copyData', function (msg) { + self.activeQuery.handleCopyData(msg, self.connection); + }); + + con.on('notification', function (msg) { + self.emit('notification', msg); + }); +} + +Client.prototype.getStartupConf = function () { var params = this.connectionParameters; var data = { @@ -263,41 +267,41 @@ Client.prototype.getStartupConf = function() { return data; }; -Client.prototype.cancel = function(client, query) { - if(client.activeQuery == query) { +Client.prototype.cancel = function (client, query) { + if (client.activeQuery == query) { var con = this.connection; - if(this.host && this.host.indexOf('/') === 0) { + if (this.host && this.host.indexOf('/') === 0) { con.connect(this.host + '/.s.PGSQL.' + this.port); } else { con.connect(this.port, this.host); } //once connection is established send cancel message - con.on('connect', function() { + con.on('connect', function () { con.cancel(client.processID, client.secretKey); }); - } else if(client.queryQueue.indexOf(query) != -1) { + } else if (client.queryQueue.indexOf(query) != -1) { client.queryQueue.splice(client.queryQueue.indexOf(query), 1); } }; -Client.prototype.setTypeParser = function(oid, format, parseFn) { +Client.prototype.setTypeParser = function (oid, format, parseFn) { return this._types.setTypeParser(oid, format, parseFn); }; -Client.prototype.getTypeParser = function(oid, format) { +Client.prototype.getTypeParser = function (oid, format) { return this._types.getTypeParser(oid, format); }; // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c -Client.prototype.escapeIdentifier = function(str) { +Client.prototype.escapeIdentifier = function (str) { var escaped = '"'; - for(var i = 0; i < str.length; i++) { + for (var i = 0; i < str.length; i++) { var c = str[i]; - if(c === '"') { + if (c === '"') { escaped += c + c; } else { escaped += c; @@ -310,14 +314,14 @@ Client.prototype.escapeIdentifier = function(str) { }; // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c -Client.prototype.escapeLiteral = function(str) { +Client.prototype.escapeLiteral = function (str) { var hasBackslash = false; var escaped = '\''; - for(var i = 0; i < str.length; i++) { + for (var i = 0; i < str.length; i++) { var c = str[i]; - if(c === '\'') { + if (c === '\'') { escaped += c + c; } else if (c === '\\') { escaped += c + c; @@ -329,21 +333,21 @@ Client.prototype.escapeLiteral = function(str) { escaped += '\''; - if(hasBackslash === true) { + if (hasBackslash === true) { escaped = ' E' + escaped; } return escaped; }; -Client.prototype._pulseQueryQueue = function() { - if(this.readyForQuery===true) { +Client.prototype._pulseQueryQueue = function () { + if (this.readyForQuery === true) { this.activeQuery = this.queryQueue.shift(); - if(this.activeQuery) { + if (this.activeQuery) { this.readyForQuery = false; this.hasExecuted = true; this.activeQuery.submit(this.connection); - } else if(this.hasExecuted) { + } else if (this.hasExecuted) { this.activeQuery = null; this.emit('drain'); } @@ -358,7 +362,7 @@ Client.prototype.copyTo = function (text) { throw new Error("For PostgreSQL COPY TO/COPY FROM support npm install pg-copy-streams"); }; -Client.prototype.query = function(config, values, callback) { +Client.prototype.query = function (config, values, callback) { //can take in strings, config object or query object var query; var result; @@ -376,10 +380,10 @@ Client.prototype.query = function(config, values, callback) { }) } - if(this.binary && !query.binary) { + if (this.binary && !query.binary) { query.binary = true; } - if(query._result) { + if (query._result) { query._result._getTypeParser = this._types.getTypeParser.bind(this._types); } @@ -388,7 +392,7 @@ Client.prototype.query = function(config, values, callback) { return result }; -Client.prototype.end = function(cb) { +Client.prototype.end = function (cb) { this._ending = true; if (this.activeQuery) { // if we have an active query we need to force a disconnect @@ -407,7 +411,7 @@ Client.prototype.end = function(cb) { } }; -Client.md5 = function(string) { +Client.md5 = function (string) { return crypto.createHash('md5').update(string, 'utf-8').digest('hex'); }; From 5f5e40f03cd89cf212a0c6a6c1d0862cfeda8a4a Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Thu, 15 Jun 2017 14:00:37 -0500 Subject: [PATCH 35/58] Add tests to support deprecated event listeners --- lib/client.js | 6 ++-- lib/query.js | 19 ++++++++++++ .../client/deprecated-listener-tests.js | 30 +++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 test/integration/client/deprecated-listener-tests.js diff --git a/lib/client.js b/lib/client.js index 563adbe0..c866f293 100644 --- a/lib/client.js +++ b/lib/client.js @@ -374,10 +374,8 @@ Client.prototype.query = function (config, values, callback) { } } else { query = new Query(config, values, callback) - result = query.callback ? undefined : new global.Promise((resolve, reject) => { - query.once('end', resolve) - query.once('error', reject) - }) + query._deprecateListeners() + result = query } if (this.binary && !query.binary) { diff --git a/lib/query.js b/lib/query.js index b36cf6b8..a98afaae 100644 --- a/lib/query.js +++ b/lib/query.js @@ -53,6 +53,25 @@ Query.prototype.requiresPreparation = function() { return this.values.length > 0; }; +Query.prototype.then = function(onSuccess, onFailure) { + return this._getPromise().then(onSuccess, onFailure); +}; + +Query.prototype.catch = function(callback) { + return this._getPromise().catch(callback); +}; + +Query.prototype._getPromise = function() { + if (this._promise) return this._promise; + this._promise = new Promise(function(resolve, reject) { + this.once('end', resolve); + this.once('error', reject); + }.bind(this)); + return this._promise; +}; + +Query.prototype._deprecateListeners = function() { +} //associates row metadata from the supplied //message with this query object diff --git a/test/integration/client/deprecated-listener-tests.js b/test/integration/client/deprecated-listener-tests.js new file mode 100644 index 00000000..0687ff64 --- /dev/null +++ b/test/integration/client/deprecated-listener-tests.js @@ -0,0 +1,30 @@ +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()) +}) From 0ce8a6c675be21bf2ec450cd15ca602c77f2644d Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 16 Jun 2017 15:56:18 -0500 Subject: [PATCH 36/58] Fix brittle unit tests --- test/unit/client/test-helper.js | 9 +- .../unit/client/throw-in-type-parser-tests.js | 155 +++++++----------- test/unit/test-helper.js | 6 +- 3 files changed, 65 insertions(+), 105 deletions(-) diff --git a/test/unit/client/test-helper.js b/test/unit/client/test-helper.js index a8294023..7c0bb31b 100644 --- a/test/unit/client/test-helper.js +++ b/test/unit/client/test-helper.js @@ -1,5 +1,6 @@ -var helper = require(__dirname+'/../test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); +var helper = require('../test-helper'); +var Connection = require('../../../lib/connection'); + var makeClient = function() { var connection = new Connection({stream: "no"}); connection.startup = function() {}; @@ -14,6 +15,6 @@ var makeClient = function() { return client; }; -module.exports = { +module.exports = Object.assign({ client: makeClient -}; +}, helper); diff --git a/test/unit/client/throw-in-type-parser-tests.js b/test/unit/client/throw-in-type-parser-tests.js index 37a272aa..2f184543 100644 --- a/test/unit/client/throw-in-type-parser-tests.js +++ b/test/unit/client/throw-in-type-parser-tests.js @@ -1,112 +1,69 @@ var helper = require("./test-helper"); -var Query = require('../../../lib/query') -var types = require('pg-types') +var Query = require("../../../lib/query"); +var types = require("pg-types"); -test('handles throws in type parsers', function() { - var typeParserError = new Error('TEST: Throw in type parsers'); +const suite = new helper.Suite(); - types.setTypeParser('special oid that will throw', function () { - throw typeParserError; +var typeParserError = new Error("TEST: Throw in type parsers"); + +types.setTypeParser("special oid that will throw", function() { + throw typeParserError; +}); + +const emitFakeEvents = con => { + setImmediate(() => { + con.emit("readyForQuery"); + + con.emit("rowDescription", { + fields: [ + { + name: "boom", + dataTypeID: "special oid that will throw" + } + ] + }); + + con.emit("dataRow", { fields: ["hi"] }); + con.emit("dataRow", { fields: ["hi"] }); + con.emit("commandComplete", { text: "INSERT 31 1" }); + con.emit("readyForQuery"); }); +}; - test('emits error', function() { - var handled; - var client = helper.client(); - var con = client.connection; - var query = client.query(new Query('whatever')); +suite.test("emits error", function(done) { + var handled; + var client = helper.client(); + var con = client.connection; + var query = client.query(new Query("whatever")); + emitFakeEvents(con) - handled = con.emit('readyForQuery'); - assert.ok(handled, "should have handled ready for query"); - - con.emit('rowDescription',{ - fields: [{ - name: 'boom', - dataTypeID: 'special oid that will throw' - }] - }); - assert.ok(handled, "should have handled row description"); - - assert.emits(query, 'error', function(err) { - assert.equal(err, typeParserError); - }); - - handled = con.emit('dataRow', { fields: ["hi"] }); - assert.ok(handled, "should have handled first data row message"); - - handled = con.emit('commandComplete', { text: 'INSERT 31 1' }); - assert.ok(handled, "should have handled command complete"); - - handled = con.emit('readyForQuery'); - assert.ok(handled, "should have handled ready for query"); + assert.emits(query, "error", function(err) { + assert.equal(err, typeParserError); + done(); }); +}); - test('calls callback with error', function() { - var handled; +suite.test("calls callback with error", function(done) { + var handled; - var callbackCalled = 0; + var callbackCalled = 0; - var client = helper.client(); - var con = client.connection; - var query = client.query('whatever', assert.calls(function (err) { - callbackCalled += 1; - - assert.equal(callbackCalled, 1); - assert.equal(err, typeParserError); - })); - - handled = con.emit('readyForQuery'); - assert.ok(handled, "should have handled ready for query"); - - handled = con.emit('rowDescription',{ - fields: [{ - name: 'boom', - dataTypeID: 'special oid that will throw' - }] - }); - assert.ok(handled, "should have handled row description"); - - handled = con.emit('dataRow', { fields: ["hi"] }); - assert.ok(handled, "should have handled first data row message"); - - handled = con.emit('dataRow', { fields: ["hi"] }); - assert.ok(handled, "should have handled second data row message"); - - con.emit('commandComplete', { text: 'INSERT 31 1' }); - assert.ok(handled, "should have handled command complete"); - - handled = con.emit('readyForQuery'); - assert.ok(handled, "should have handled ready for query"); - }); - - test('rejects promise with error', function() { - var handled; - var client = helper.client(); - var con = client.connection; - var queryPromise = client.query('whatever'); - - handled = con.emit('readyForQuery'); - assert.ok(handled, "should have handled ready for query"); - - handled = con.emit('rowDescription',{ - fields: [{ - name: 'boom', - dataTypeID: 'special oid that will throw' - }] - }); - assert.ok(handled, "should have handled row description"); - - handled = con.emit('dataRow', { fields: ["hi"] }); - assert.ok(handled, "should have handled first data row message"); - - handled = con.emit('commandComplete', { text: 'INSERT 31 1' }); - assert.ok(handled, "should have handled command complete"); - - handled = con.emit('readyForQuery'); - assert.ok(handled, "should have handled ready for query"); - - queryPromise.catch(assert.calls(function (err) { - assert.equal(err, typeParserError); - })); + var client = helper.client(); + var con = client.connection; + emitFakeEvents(con); + var query = client.query("whatever", function(err) { + assert.equal(err, typeParserError); + done(); }); }); + +suite.test("rejects promise with error", function(done) { + var client = helper.client(); + var con = client.connection; + emitFakeEvents(con); + client.query("whatever").catch(err => { + assert.equal(err, typeParserError); + done(); + }); +}); diff --git a/test/unit/test-helper.js b/test/unit/test-helper.js index 878898d8..ad6485be 100644 --- a/test/unit/test-helper.js +++ b/test/unit/test-helper.js @@ -1,6 +1,8 @@ -var helper = require(__dirname+'/../test-helper'); var EventEmitter = require('events').EventEmitter; -var Connection = require(__dirname + '/../../lib/connection'); + +var helper = require('../test-helper'); +var Connection = require('../../lib/connection'); + MemoryStream = function() { EventEmitter.call(this); this.packets = []; From 76c10005670bdaea6bd01e789060a4b4101f0419 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 16 Jun 2017 16:11:25 -0500 Subject: [PATCH 37/58] Add event-emitters back --- lib/client.js | 1 - lib/native/client.js | 7 +------ lib/native/query.js | 17 +++++++++++++++++ lib/query.js | 3 --- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/client.js b/lib/client.js index c866f293..8ca944b1 100644 --- a/lib/client.js +++ b/lib/client.js @@ -374,7 +374,6 @@ Client.prototype.query = function (config, values, callback) { } } else { query = new Query(config, values, callback) - query._deprecateListeners() result = query } diff --git a/lib/native/client.js b/lib/native/client.js index 639484ec..7950bc3d 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -131,14 +131,9 @@ Client.prototype.query = function(config, values, callback) { } var query = new NativeQuery(config, values, callback); - var result = query.callback ? query : new global.Promise(function(resolve, reject) { - query.on('end', resolve); - query.on('error', reject); - }); - this._queryQueue.push(query); this._pulseQueryQueue(); - return result; + return query; }; //disconnect from the backend server diff --git a/lib/native/query.js b/lib/native/query.js index 1523e7c7..a1f7dd42 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -67,6 +67,23 @@ NativeQuery.prototype.handleError = function(err) { self.state = 'error'; }; +NativeQuery.prototype.then = function(onSuccess, onFailure) { + return this._getPromise().then(onSuccess, onFailure); +}; + +NativeQuery.prototype.catch = function(callback) { + return this._getPromise().catch(callback); +}; + +NativeQuery.prototype._getPromise = function() { + if (this._promise) return this._promise; + this._promise = new Promise(function(resolve, reject) { + this.once('end', resolve); + this.once('error', reject); + }.bind(this)); + return this._promise; +}; + NativeQuery.prototype.submit = function(client) { this.state = 'running'; var self = this; diff --git a/lib/query.js b/lib/query.js index a98afaae..d3656748 100644 --- a/lib/query.js +++ b/lib/query.js @@ -70,9 +70,6 @@ Query.prototype._getPromise = function() { return this._promise; }; -Query.prototype._deprecateListeners = function() { -} - //associates row metadata from the supplied //message with this query object //metadata used when parsing row results From cfd9caa925b68a951ab0a0976636b3db99bf72f0 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 16 Jun 2017 16:41:31 -0500 Subject: [PATCH 38/58] Deprecate query.on & query.once --- lib/client.js | 4 +++- lib/native/client.js | 4 +++- lib/native/query.js | 4 ++-- lib/query.js | 4 ++-- lib/utils.js | 21 ++++++++++++++++++++- 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/client.js b/lib/client.js index 8ca944b1..3eee5402 100644 --- a/lib/client.js +++ b/lib/client.js @@ -362,6 +362,8 @@ 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; @@ -373,7 +375,7 @@ Client.prototype.query = function (config, values, callback) { query.callback = query.callback || values } } else { - query = new Query(config, values, callback) + query = new DeprecatedQuery(config, values, callback) result = query } diff --git a/lib/native/client.js b/lib/native/client.js index 7950bc3d..331f9206 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -109,6 +109,8 @@ Client.prototype.connect = function(cb) { return result }; +const DeprecatedQuery = require('../utils').deprecateEventEmitter(NativeQuery) + //send a query to the server //this method is highly overloaded to take //1) string query, optional array of parameters, optional function callback @@ -130,7 +132,7 @@ Client.prototype.query = function(config, values, callback) { return config; } - var query = new NativeQuery(config, values, callback); + var query = new DeprecatedQuery(config, values, callback); this._queryQueue.push(query); this._pulseQueryQueue(); return query; diff --git a/lib/native/query.js b/lib/native/query.js index a1f7dd42..4fb501f1 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -78,8 +78,8 @@ NativeQuery.prototype.catch = function(callback) { NativeQuery.prototype._getPromise = function() { if (this._promise) return this._promise; this._promise = new Promise(function(resolve, reject) { - this.once('end', resolve); - this.once('error', reject); + this._once('end', resolve); + this._once('error', reject); }.bind(this)); return this._promise; }; diff --git a/lib/query.js b/lib/query.js index d3656748..b997091c 100644 --- a/lib/query.js +++ b/lib/query.js @@ -64,8 +64,8 @@ Query.prototype.catch = function(callback) { Query.prototype._getPromise = function() { if (this._promise) return this._promise; this._promise = new Promise(function(resolve, reject) { - this.once('end', resolve); - this.once('error', reject); + this._once('end', resolve); + this._once('error', reject); }.bind(this)); return this._promise; }; diff --git a/lib/utils.js b/lib/utils.js index 82d1aefd..381775ff 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -6,6 +6,7 @@ * README.md file in the root directory of this source tree. */ +const util = require('util') var defaults = require('./defaults'); function escapeElement(elementRepresentation) { @@ -137,11 +138,29 @@ function normalizeQueryConfig (config, values, callback) { return config; } +const queryEventEmitterOverloadDeprecationMessage = ` +Using the automatically created return value from client.query as an event emitter is deprecated. +Use either the callback or promise interface. +` + +const deprecateEventEmitter = function(Emitter) { + const Result = function () { + Emitter.apply(this, arguments) + } + util.inherits(Result, Emitter) + Result.prototype._on = Result.prototype.on + Result.prototype._once = Result.prototype.once + Result.prototype.on = util.deprecate(Result.prototype.on, queryEventEmitterOverloadDeprecationMessage) + Result.prototype.once = util.deprecate(Result.prototype.once, queryEventEmitterOverloadDeprecationMessage) + return Result +} + module.exports = { prepareValue: function prepareValueWrapper (value) { //this ensures that extra arguments do not get passed into prepareValue //by accident, eg: from calling values.map(utils.prepareValue) return prepareValue(value); }, - normalizeQueryConfig: normalizeQueryConfig + normalizeQueryConfig: normalizeQueryConfig, + deprecateEventEmitter: deprecateEventEmitter, }; From 94a628a16f74c043788a7ff37c38dee60ea7e974 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 15:16:39 -0500 Subject: [PATCH 39/58] Update engine support --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5eecc421..0fee6bf4 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,6 @@ }, "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">= 4.0.0" } } From 313c41a39fa34d1902669136adbad5149c558ca0 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 12:53:12 -0500 Subject: [PATCH 40/58] Cleanup --- lib/client.js | 24 +- test/integration/client/api-tests.js | 354 ++++++++++-------- .../client/deprecated-listener-tests.js | 30 -- 3 files changed, 204 insertions(+), 204 deletions(-) delete mode 100644 test/integration/client/deprecated-listener-tests.js 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()) -}) From 1bc1758579ef7855b7e08e0bb56998d95cf33bf8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 14:20:55 -0500 Subject: [PATCH 41/58] Remove deprecated methods --- Makefile | 2 +- lib/index.js | 69 ------- lib/native/client.js | 15 +- lib/query.js | 17 -- lib/utils.js | 18 -- test/integration/client/array-tests.js | 8 +- test/integration/client/cancel-query-tests.js | 41 ---- test/integration/client/huge-numeric-tests.js | 5 +- .../client/json-type-parsing-tests.js | 5 +- .../integration/client/no-row-result-tests.js | 34 ++-- test/integration/client/parse-int-8-tests.js | 5 +- .../client/query-as-promise-tests.js | 43 +++-- .../client/query-column-names-tests.js | 15 +- .../client/result-metadata-tests.js | 9 +- test/integration/client/timezone-tests.js | 34 ++-- test/integration/client/transaction-tests.js | 92 ++++----- .../integration/client/type-coercion-tests.js | 182 +++++++++--------- .../client/type-parser-override-tests.js | 14 +- .../connection-pool-size-tests.js | 9 + .../double-connection-tests.js | 2 - .../ending-empty-pool-tests.js | 15 -- .../connection-pool/ending-pool-tests.js | 30 --- .../connection-pool/error-tests.js | 68 ++++--- .../connection-pool/idle-timeout-tests.js | 19 +- .../connection-pool/max-connection-tests.js | 2 - .../connection-pool/optional-config-tests.js | 20 -- .../single-connection-tests.js | 2 - .../single-pool-on-object-config-tests.js | 13 -- .../connection-pool/test-helper.js | 45 +++-- .../waiting-connection-tests.js | 2 - .../connection-pool/yield-support-tests.js | 21 +- test/integration/domain-tests.js | 19 +- test/integration/gh-issues/130-tests.js | 5 +- test/integration/gh-issues/131-tests.js | 6 +- test/integration/gh-issues/507-tests.js | 6 +- test/integration/gh-issues/675-tests.js | 5 +- test/integration/gh-issues/699-tests.js | 5 +- test/integration/gh-issues/787-tests.js | 3 +- test/integration/gh-issues/981-tests.js | 28 ++- test/test-helper.js | 2 - 40 files changed, 374 insertions(+), 561 deletions(-) delete mode 100644 test/integration/client/cancel-query-tests.js create mode 100644 test/integration/connection-pool/connection-pool-size-tests.js delete mode 100644 test/integration/connection-pool/double-connection-tests.js delete mode 100644 test/integration/connection-pool/ending-empty-pool-tests.js delete mode 100644 test/integration/connection-pool/ending-pool-tests.js delete mode 100644 test/integration/connection-pool/max-connection-tests.js delete mode 100644 test/integration/connection-pool/optional-config-tests.js delete mode 100644 test/integration/connection-pool/single-connection-tests.js delete mode 100644 test/integration/connection-pool/single-pool-on-object-config-tests.js delete mode 100644 test/integration/connection-pool/waiting-connection-tests.js diff --git a/Makefile b/Makefile index 08c1e10c..ad8ed3de 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ help: test: test-unit -test-all: jshint test-missing-native test-unit test-integration test-native test-binary +test-all: jshint test-missing-native test-unit test-integration test-native update-npm: diff --git a/lib/index.js b/lib/index.js index a2439711..ac3fb059 100644 --- a/lib/index.js +++ b/lib/index.js @@ -15,7 +15,6 @@ var ConnectionParameters = require('./connection-parameters'); var poolFactory = require('./pool-factory'); var PG = function(clientConstructor) { - EventEmitter.call(this); this.defaults = defaults; this.Client = clientConstructor; this.Query = this.Client.Query; @@ -25,74 +24,6 @@ var PG = function(clientConstructor) { this.types = require('pg-types'); }; -util.inherits(PG, EventEmitter); - -PG.prototype.end = util.deprecate(function() { - var self = this; - var keys = Object.keys(this._pools); - var count = keys.length; - if(count === 0) { - self.emit('end'); - } else { - keys.forEach(function(key) { - var pool = self._pools[key]; - delete self._pools[key]; - pool.pool.drain(function() { - pool.pool.destroyAllNow(function() { - count--; - if(count === 0) { - self.emit('end'); - } - }); - }); - }); - } -}, -'pg.end() is deprecated - please construct pools directly via new pg.Pool()'); - -PG.prototype.connect = util.deprecate(function(config, callback) { - if(typeof config == "function") { - callback = config; - config = null; - } - if (typeof config == 'string') { - config = new ConnectionParameters(config); - } - - config = config || {}; - - //for backwards compatibility - config.max = config.max || config.poolSize || defaults.poolSize; - config.idleTimeoutMillis = config.idleTimeoutMillis || config.poolIdleTimeout || defaults.poolIdleTimeout; - config.log = config.log || config.poolLog || defaults.poolLog; - - var poolName = JSON.stringify(config); - this._pools[poolName] = this._pools[poolName] || new this.Pool(config); - var pool = this._pools[poolName]; - if(!pool.listeners('error').length) { - //propagate errors up to pg object - pool.on('error', function(e) { - this.emit('error', e, e.client); - }.bind(this)); - } - return pool.connect(callback); -}, -'pg.connect() is deprecated - please construct pools directly via new pg.Pool()'); - -// cancel the query running on the given client -PG.prototype.cancel = util.deprecate(function(config, client, query) { - if(client.native) { - return client.cancel(query); - } - var c = config; - //allow for no config to be passed - if(typeof c === 'function') { - c = defaults; - } - var cancellingClient = new this.Client(c); - cancellingClient.cancel(client, query); -}, 'pg.cancel() is deprecated - please create your own client instances to cancel queries'); - if(typeof process.env.NODE_PG_FORCE_NATIVE != 'undefined') { module.exports = new PG(require('./native')); } else { diff --git a/lib/native/client.js b/lib/native/client.js index 331f9206..9641d399 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -109,8 +109,6 @@ Client.prototype.connect = function(cb) { return result }; -const DeprecatedQuery = require('../utils').deprecateEventEmitter(NativeQuery) - //send a query to the server //this method is highly overloaded to take //1) string query, optional array of parameters, optional function callback @@ -132,10 +130,19 @@ Client.prototype.query = function(config, values, callback) { return config; } - var query = new DeprecatedQuery(config, values, callback); + var query = new NativeQuery(config, values, callback); + var result + if (!query.callback) { + let resolve, reject; + result = new Promise((res, rej) => { + resolve = res + reject = rej + }) + query.callback = (err, res) => err ? reject(err) : resolve(res) + } this._queryQueue.push(query); this._pulseQueryQueue(); - return query; + return result; }; //disconnect from the backend server diff --git a/lib/query.js b/lib/query.js index b997091c..99b5ea8b 100644 --- a/lib/query.js +++ b/lib/query.js @@ -53,23 +53,6 @@ Query.prototype.requiresPreparation = function() { return this.values.length > 0; }; -Query.prototype.then = function(onSuccess, onFailure) { - return this._getPromise().then(onSuccess, onFailure); -}; - -Query.prototype.catch = function(callback) { - return this._getPromise().catch(callback); -}; - -Query.prototype._getPromise = function() { - if (this._promise) return this._promise; - this._promise = new Promise(function(resolve, reject) { - this._once('end', resolve); - this._once('error', reject); - }.bind(this)); - return this._promise; -}; - //associates row metadata from the supplied //message with this query object //metadata used when parsing row results diff --git a/lib/utils.js b/lib/utils.js index 381775ff..e658bbd4 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -138,23 +138,6 @@ function normalizeQueryConfig (config, values, callback) { return config; } -const queryEventEmitterOverloadDeprecationMessage = ` -Using the automatically created return value from client.query as an event emitter is deprecated. -Use either the callback or promise interface. -` - -const deprecateEventEmitter = function(Emitter) { - const Result = function () { - Emitter.apply(this, arguments) - } - util.inherits(Result, Emitter) - Result.prototype._on = Result.prototype.on - Result.prototype._once = Result.prototype.once - Result.prototype.on = util.deprecate(Result.prototype.on, queryEventEmitterOverloadDeprecationMessage) - Result.prototype.once = util.deprecate(Result.prototype.once, queryEventEmitterOverloadDeprecationMessage) - return Result -} - module.exports = { prepareValue: function prepareValueWrapper (value) { //this ensures that extra arguments do not get passed into prepareValue @@ -162,5 +145,4 @@ module.exports = { return prepareValue(value); }, normalizeQueryConfig: normalizeQueryConfig, - deprecateEventEmitter: deprecateEventEmitter, }; diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index 7512d55b..a26c7636 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -3,7 +3,8 @@ var pg = helper.pg; var suite = new helper.Suite() -pg.connect(assert.calls(function(err, client, release) { +const pool = new pg.Pool() +pool.connect(assert.calls(function(err, client, release) { assert.isNull(err); suite.test('nulls', function(done) { @@ -33,7 +34,7 @@ pg.connect(assert.calls(function(err, client, release) { suite.test('cleanup', () => release()) })); -pg.connect(assert.calls(function (err, client, release) { +pool.connect(assert.calls(function (err, client, release) { assert.isNull(err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[])"); client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); @@ -166,8 +167,7 @@ pg.connect(assert.calls(function (err, client, release) { assert.equal(names[2][0], 3); assert.equal(names[2][1], 100); release(); - pg.end(); - done(); + pool.end(done) })) }) diff --git a/test/integration/client/cancel-query-tests.js b/test/integration/client/cancel-query-tests.js deleted file mode 100644 index 4485b328..00000000 --- a/test/integration/client/cancel-query-tests.js +++ /dev/null @@ -1,41 +0,0 @@ -var helper = require("./test-helper"); -var Query = helper.pg.Query; - -//before running this test make sure you run the script create-test-tables -new helper.Suite().test("cancellation of a query", function() { - - var client = helper.client(); - - var qry = "select name from person order by name"; - - client.on('drain', client.end.bind(client)); - - var rows3 = 0; - - var query1 = client.query(new Query(qry)); - query1.on('row', function(row) { - throw new Error('Should not emit a row') - }); - var query2 = client.query(new Query(qry)); - query2.on('row', function(row) { - throw new Error('Should not emit a row') - }); - var query3 = client.query(new Query(qry)); - query3.on('row', function(row) { - rows3++; - }); - var query4 = client.query(new Query(qry)); - query4.on('row', function(row) { - throw new Error('Should not emit a row') - }); - - helper.pg.cancel(helper.config, client, query1); - helper.pg.cancel(helper.config, client, query2); - helper.pg.cancel(helper.config, client, query4); - - assert.emits(query3, 'end', function() { - test("returned right number of rows", function() { - assert.equal(rows3, 26); - }); - }); -}); diff --git a/test/integration/client/huge-numeric-tests.js b/test/integration/client/huge-numeric-tests.js index 76b2aac5..9cd90537 100644 --- a/test/integration/client/huge-numeric-tests.js +++ b/test/integration/client/huge-numeric-tests.js @@ -1,6 +1,7 @@ var helper = require('./test-helper'); +const pool = new helper.pg.Pool() -helper.pg.connect(helper.config, assert.success(function(client, done) { +pool.connect(assert.success(function(client, done) { var types = require('pg-types'); //1231 = numericOID types.setTypeParser(1700, function(){ @@ -14,7 +15,7 @@ helper.pg.connect(helper.config, assert.success(function(client, done) { client.query('INSERT INTO bignumz(id) VALUES ($1)', [bignum]); client.query('SELECT * FROM bignumz', assert.success(function(result) { assert.equal(result.rows[0].id, 'yes') - helper.pg.end(); done(); + pool.end() })) })); diff --git a/test/integration/client/json-type-parsing-tests.js b/test/integration/client/json-type-parsing-tests.js index 1fe21ac5..e3dca3a5 100644 --- a/test/integration/client/json-type-parsing-tests.js +++ b/test/integration/client/json-type-parsing-tests.js @@ -1,7 +1,8 @@ var helper = require('./test-helper'); var assert = require('assert'); -helper.pg.connect(assert.success(function (client, done) { +const pool = new helper.pg.Pool() +pool.connect(assert.success(function (client, done) { helper.versionGTE(client, '9.2.0', assert.success(function (jsonSupported) { if (!jsonSupported) { console.log('skip json test on older versions of postgres'); @@ -20,7 +21,7 @@ helper.pg.connect(assert.success(function (client, done) { assert.strictEqual(row.alive, value.alive); assert.equal(JSON.stringify(row.now), JSON.stringify(value.now)); done(); - helper.pg.end(); + pool.end() })); })); })); diff --git a/test/integration/client/no-row-result-tests.js b/test/integration/client/no-row-result-tests.js index 9081e233..cc91c647 100644 --- a/test/integration/client/no-row-result-tests.js +++ b/test/integration/client/no-row-result-tests.js @@ -1,23 +1,27 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require("./test-helper"); var pg = helper.pg; -const suite = new helper.Suite() +const suite = new helper.Suite(); +const pool = new pg.Pool(); -suite.test('can access results when no rows are returned', function() { - var checkResult = function(result) { - assert(result.fields, 'should have fields definition'); +suite.test("can access results when no rows are returned", function (done) { + var checkResult = function (result) { + assert(result.fields, "should have fields definition"); assert.equal(result.fields.length, 1); - assert.equal(result.fields[0].name, 'val'); + assert.equal(result.fields[0].name, "val"); assert.equal(result.fields[0].dataTypeID, 25); - pg.end(); }; - pg.connect(assert.success(function(client, done) { - const q = new pg.Query('select $1::text as val limit 0', ['hi']) - var query = client.query(q, assert.success(function(result) { - checkResult(result); - done(); - })); + pool.connect( + assert.success(function (client, release) { + const q = new pg.Query("select $1::text as val limit 0", ["hi"]); + var query = client.query(q, assert.success(function (result) { + checkResult(result); + release(); + pool.end(done); + }) + ); - assert.emits(query, 'end', checkResult); - })); + assert.emits(query, "end", checkResult); + }) + ); }); diff --git a/test/integration/client/parse-int-8-tests.js b/test/integration/client/parse-int-8-tests.js index 4ece9445..937b41b7 100644 --- a/test/integration/client/parse-int-8-tests.js +++ b/test/integration/client/parse-int-8-tests.js @@ -3,9 +3,10 @@ var helper = require('../test-helper'); var pg = helper.pg; const suite = new helper.Suite() +const pool = new pg.Pool(helper.config) suite.test('ability to turn on and off parser', function() { if(helper.args.binary) return false; - pg.connect(helper.config, assert.success(function(client, done) { + pool.connect(assert.success(function(client, done) { pg.defaults.parseInt8 = true; client.query('CREATE TEMP TABLE asdf(id SERIAL PRIMARY KEY)'); client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function(res) { @@ -20,7 +21,7 @@ suite.test('ability to turn on and off parser', function() { assert.strictEqual('1', res.rows[0].array[0]); assert.strictEqual('2', res.rows[0].array[1]); assert.strictEqual('3', res.rows[0].array[2]); - pg.end(); + pool.end(); })); })); })); diff --git a/test/integration/client/query-as-promise-tests.js b/test/integration/client/query-as-promise-tests.js index 92eedcc8..95bf73ce 100644 --- a/test/integration/client/query-as-promise-tests.js +++ b/test/integration/client/query-as-promise-tests.js @@ -6,22 +6,27 @@ process.on('unhandledRejection', function(e) { process.exit(1) }) -pg.connect(helper.config, assert.success(function(client, done) { - client.query('SELECT $1::text as name', ['foo']) - .then(function(result) { - assert.equal(result.rows[0].name, 'foo') - return client - }) - .then(function(client) { - client.query('ALKJSDF') - .catch(function(e) { - assert(e instanceof Error) - client.query('SELECT 1 as num') - .then(function (result) { - assert.equal(result.rows[0].num, 1) - done() - pg.end() - }) - }) - }) -})) +const pool = new pg.Pool() +const suite = new helper.Suite() + +suite.test('promise API', (cb) => { + pool.connect().then((client) => { + client.query('SELECT $1::text as name', ['foo']) + .then(function (result) { + assert.equal(result.rows[0].name, 'foo') + return client + }) + .then(function (client) { + client.query('ALKJSDF') + .catch(function (e) { + assert(e instanceof Error) + client.query('SELECT 1 as num') + .then(function (result) { + assert.equal(result.rows[0].num, 1) + client.release() + pool.end(cb) + }) + }) + }) + }) +}) diff --git a/test/integration/client/query-column-names-tests.js b/test/integration/client/query-column-names-tests.js index 811d673a..d929b508 100644 --- a/test/integration/client/query-column-names-tests.js +++ b/test/integration/client/query-column-names-tests.js @@ -1,13 +1,14 @@ var helper = require(__dirname + '/../test-helper'); var pg = helper.pg; -test('support for complex column names', function() { - pg.connect(helper.config, assert.success(function(client, done) { +new helper.Suite().test('support for complex column names', function () { + const pool = new pg.Pool() + pool.connect(assert.success(function (client, done) { client.query("CREATE TEMP TABLE t ( \"complex''column\" TEXT )"); - client.query('SELECT * FROM t', assert.success(function(res) { - done(); - assert.strictEqual(res.fields[0].name, "complex''column"); - pg.end(); + client.query('SELECT * FROM t', assert.success(function (res) { + done(); + assert.strictEqual(res.fields[0].name, "complex''column"); + pool.end(); })); })); -}); \ No newline at end of file +}); diff --git a/test/integration/client/result-metadata-tests.js b/test/integration/client/result-metadata-tests.js index 221db776..85b7e18c 100644 --- a/test/integration/client/result-metadata-tests.js +++ b/test/integration/client/result-metadata-tests.js @@ -1,8 +1,9 @@ -var helper = require(__dirname + "/test-helper"); +var helper = require("./test-helper"); var pg = helper.pg; -test('should return insert metadata', function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { +const pool = new pg.Pool() +new helper.Suite().test('should return insert metadata', function() { + pool.connect(assert.calls(function(err, client, done) { assert.isNull(err); helper.versionGTE(client, '9.0.0', assert.success(function(hasRowCount) { @@ -21,7 +22,7 @@ test('should return insert metadata', function() { if(hasRowCount) assert.equal(result.rowCount, 1); assert.equal(result.command, 'SELECT'); done(); - process.nextTick(pg.end.bind(pg)); + process.nextTick(pool.end.bind(pool)); })); })); })); diff --git a/test/integration/client/timezone-tests.js b/test/integration/client/timezone-tests.js index b355550d..29873431 100644 --- a/test/integration/client/timezone-tests.js +++ b/test/integration/client/timezone-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/../test-helper'); +var helper = require('./../test-helper'); var exec = require('child_process').exec; var oldTz = process.env.TZ; @@ -6,24 +6,28 @@ process.env.TZ = 'Europe/Berlin'; var date = new Date(); -helper.pg.connect(helper.config, function(err, client, done) { +const pool = new helper.pg.Pool() +const suite = new helper.Suite() + +pool.connect(function (err, client, done) { assert.isNull(err); - test('timestamp without time zone', function() { - client.query("SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS \"val\"", [ date ], function(err, result) { + suite.test('timestamp without time zone', function (cb) { + client.query("SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS \"val\"", [date], function (err, result) { + assert.isNull(err); + assert.equal(result.rows[0].val.getTime(), date.getTime()); + cb() + }) + }) + + suite.test('timestamp with time zone', function (cb) { + client.query("SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS \"val\"", [date], function (err, result) { assert.isNull(err); assert.equal(result.rows[0].val.getTime(), date.getTime()); - test('timestamp with time zone', function() { - client.query("SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS \"val\"", [ date ], function(err, result) { - assert.isNull(err); - assert.equal(result.rows[0].val.getTime(), date.getTime()); - - done(); - helper.pg.end(); - process.env.TZ = oldTz; - }); - }); + done(); + pool.end(cb) + process.env.TZ = oldTz; }); }); -}); \ No newline at end of file +}); diff --git a/test/integration/client/transaction-tests.js b/test/integration/client/transaction-tests.js index 85ee7e53..389a70d0 100644 --- a/test/integration/client/transaction-tests.js +++ b/test/integration/client/transaction-tests.js @@ -1,72 +1,76 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); +const suite = new helper.Suite() +const pg = helper.pg -var sink = new helper.Sink(2, function() { - helper.pg.end(); -}); +const client = new pg.Client() +client.connect(assert.success(function () { -test('a single connection transaction', function() { - helper.pg.connect(helper.config, assert.success(function(client, done) { + client.query('begin'); - client.query('begin'); + var getZed = { + text: 'SELECT * FROM person WHERE name = $1', + values: ['Zed'] + }; - var getZed = { - text: 'SELECT * FROM person WHERE name = $1', - values: ['Zed'] - }; + suite.test('name should not exist in the database', function (done) { + client.query(getZed, assert.calls(function (err, result) { + assert.isNull(err); + assert.empty(result.rows); + done() + })) + }) - test('Zed should not exist in the database', function() { - client.query(getZed, assert.calls(function(err, result) { - assert.isNull(err); - assert.empty(result.rows); - })) - }) - - client.query("INSERT INTO person(name, age) VALUES($1, $2)", ['Zed', 270], assert.calls(function(err, result) { + suite.test('can insert name', (done) => { + client.query("INSERT INTO person(name, age) VALUES($1, $2)", ['Zed', 270], assert.calls(function (err, result) { assert.isNull(err) + done() })); + }) - test('Zed should exist in the database', function() { - client.query(getZed, assert.calls(function(err, result) { - assert.isNull(err); - assert.equal(result.rows[0].name, 'Zed'); - })) - }) + suite.test('name should exist in the database', function (done) { + client.query(getZed, assert.calls(function (err, result) { + assert.isNull(err); + assert.equal(result.rows[0].name, 'Zed'); + done() + })) + }) - client.query('rollback'); + suite.test('rollback', (done) => { + client.query('rollback', done); + }) - test('Zed should not exist in the database', function() { - client.query(getZed, assert.calls(function(err, result) { - assert.isNull(err); - assert.empty(result.rows); - done(); - sink.add(); - })) - }) - })) -}) + suite.test('name should not exist in the database', function (done) { + client.query(getZed, assert.calls(function (err, result) { + assert.isNull(err); + assert.empty(result.rows); + client.end(done) + })) + }) +})) -test('gh#36', function() { - helper.pg.connect(helper.config, assert.success(function(client, done) { +suite.test('gh#36', function (cb) { + const pool = new pg.Pool() + pool.connect(assert.success(function (client, done) { client.query("BEGIN"); client.query({ name: 'X', text: "SELECT $1::INTEGER", values: [0] - }, assert.calls(function(err, result) { - if(err) throw err; + }, assert.calls(function (err, result) { + if (err) throw err; assert.equal(result.rows.length, 1); })) client.query({ name: 'X', text: "SELECT $1::INTEGER", values: [0] - }, assert.calls(function(err, result) { - if(err) throw err; + }, assert.calls(function (err, result) { + if (err) throw err; assert.equal(result.rows.length, 1); })) - client.query("COMMIT", function() { - sink.add(); + client.query("COMMIT", function () { done(); + pool.end(cb) }) })); }) diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index 98f3148a..dc50732e 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -1,29 +1,33 @@ var helper = require(__dirname + '/test-helper'); var pg = helper.pg; var sink; +const suite = new helper.Suite() -var testForTypeCoercion = function(type){ - 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) { +var testForTypeCoercion = function (type) { + const pool = new pg.Pool() + suite.test(`test type coercion ${type.name}`, (cb) => { + pool.connect(function (err, client, done) { assert.isNull(err); - test("Coerces " + type.name, function() { - type.values.forEach(function(val) { + client.query("create temp table test_type(col " + type.name + ")", assert.calls(function (err, result) { + assert.isNull(err); - var insertQuery = client.query('insert into test_type(col) VALUES($1)',[val],assert.calls(function(err, result) { + type.values.forEach(function (val) { + + var insertQuery = client.query('insert into test_type(col) VALUES($1)', [val], assert.calls(function (err, result) { assert.isNull(err); })); var query = client.query(new pg.Query({ - name: 'get type ' + type.name , + name: 'get type ' + type.name, text: 'select col from test_type' })); - query.on('error', function(err) { + + query.on('error', function (err) { console.log(err); throw err; }); - assert.emits(query, 'row', function(row) { + assert.emits(query, 'row', function (row) { var expected = val + " (" + typeof val + ")"; var returned = row.col + " (" + typeof row.col + ")"; assert.strictEqual(row.col, val, "expected " + type.name + " of " + expected + " but got " + returned); @@ -32,22 +36,23 @@ var testForTypeCoercion = function(type){ client.query('delete from test_type'); }); - client.query('drop table test_type', function() { - sink.add(); + client.query('drop table test_type', function () { done(); + pool.end(cb) }); - }) - })); + })); + }) + }) }; var types = [{ name: 'integer', values: [-2147483648, -1, 0, 1, 2147483647, null] -},{ +}, { name: 'smallint', values: [-32768, -1, 0, 1, 32767, null] -},{ +}, { name: 'bigint', values: [ '-9223372036854775808', @@ -58,16 +63,16 @@ var types = [{ '9223372036854775807', null ] -},{ +}, { name: 'varchar(5)', values: ['yo', '', 'zomg!', null] -},{ +}, { name: 'oid', values: [0, 204410, null] -},{ +}, { name: 'bool', values: [true, false, null] -},{ +}, { name: 'numeric', values: [ '-12.34', @@ -77,52 +82,42 @@ var types = [{ '3141592653589793238462643383279502.1618033988749894848204586834365638', null ] -},{ +}, { name: 'real', values: [-101.3, -1.2, 0, 1.2, 101.1, null] -},{ +}, { name: 'double precision', values: [-101.3, -1.2, 0, 1.2, 101.1, null] -},{ +}, { name: 'timestamptz', values: [null] -},{ +}, { name: 'timestamp', values: [null] -},{ +}, { name: 'timetz', - values: ['13:11:12.1234-05:30',null] -},{ + values: ['13:11:12.1234-05:30', null] +}, { name: 'time', values: ['13:12:12.321', null] }]; // 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, 'numeric': 1, 'bigint': 1}); + types = types.filter(function (type) { + return !(type.name in { 'real': 1, 'timetz': 1, 'time': 1, 'numeric': 1, 'bigint': 1 }); }); } var valueCount = 0; -types.forEach(function(type) { - valueCount += type.values.length; -}) -sink = new helper.Sink(types.length + 1, function() { - helper.pg.end(); -}) -types.forEach(function(type) { +types.forEach(function (type) { testForTypeCoercion(type) }); -test("timestampz round trip", function() { +suite.test("timestampz round trip", function (cb) { var now = new Date(); var client = helper.client(); - client.on('error', function(err) { - console.log(err); - client.end(); - }); client.query("create temp table date_tests(name varchar(10), tstz timestamptz(3))"); client.query({ text: "insert into date_tests(name, tstz)VALUES($1, $2)", @@ -135,67 +130,66 @@ test("timestampz round trip", function() { values: ['now'] })); - assert.emits(result, 'row', function(row) { + assert.emits(result, 'row', function (row) { var date = row.tstz; - assert.equal(date.getYear(),now.getYear()); + assert.equal(date.getYear(), now.getYear()); assert.equal(date.getMonth(), now.getMonth()); assert.equal(date.getDate(), now.getDate()); assert.equal(date.getHours(), now.getHours()); assert.equal(date.getMinutes(), now.getMinutes()); assert.equal(date.getSeconds(), now.getSeconds()); - test("milliseconds are equal", function() { - assert.equal(date.getMilliseconds(), now.getMilliseconds()); - }); + assert.equal(date.getMilliseconds(), now.getMilliseconds()); }); - client.on('drain', client.end.bind(client)); + client.on('drain', () => { + client.end(cb) + }); }); -if(!helper.config.binary) { - test('date range extremes', function() { - var client = helper.client(); - client.on('error', function(err) { - console.log(err); - client.end(); - }); - - // Set the server timeszone to the same as used for the test, - // otherwise (if server's timezone is ahead of GMT) in - // textParsers.js::parseDate() the timezone offest is added to the date; - // in the case of "275760-09-13 00:00:00 GMT" the timevalue overflows. - client.query('SET TIMEZONE TO GMT', assert.success(function(res){ - - // PostgreSQL supports date range of 4713 BCE to 294276 CE - // http://www.postgresql.org/docs/9.2/static/datatype-datetime.html - // ECMAScript supports date range of Apr 20 271821 BCE to Sep 13 275760 CE - // http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1 - client.query('SELECT $1::TIMESTAMPTZ as when', ["275760-09-13 00:00:00 GMT"], assert.success(function(res) { - assert.equal(res.rows[0].when.getFullYear(), 275760); - })); - - client.query('SELECT $1::TIMESTAMPTZ as when', ["4713-12-31 12:31:59 BC GMT"], assert.success(function(res) { - assert.equal(res.rows[0].when.getFullYear(), -4713); - })); - - client.query('SELECT $1::TIMESTAMPTZ as when', ["275760-09-13 00:00:00 -15:00"], assert.success(function(res) { - assert( isNaN(res.rows[0].when.getTime()) ); - })); - - client.on('drain', client.end.bind(client)); - })); - }); -} - -helper.pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.ifError(err); - client.query('select null as res;', assert.calls(function(err, res) { - assert.isNull(err); - assert.strictEqual(res.rows[0].res, null) +suite.test('selecting nulls', cb => { + const pool = new pg.Pool() + pool.connect(assert.calls(function (err, client, done) { + assert.ifError(err); + client.query('select null as res;', assert.calls(function (err, res) { + assert.isNull(err); + assert.strictEqual(res.rows[0].res, null) + })) + client.query('select 7 <> $1 as res;', [null], function (err, res) { + assert.isNull(err); + assert.strictEqual(res.rows[0].res, null); + done(); + pool.end(cb) + }) })) - client.query('select 7 <> $1 as res;',[null], function(err, res) { - assert.isNull(err); - assert.strictEqual(res.rows[0].res, null); - sink.add(); - done(); - }) -})) +}) + +suite.test('date range extremes', function (done) { + var client = helper.client(); + + // Set the server timeszone to the same as used for the test, + // otherwise (if server's timezone is ahead of GMT) in + // textParsers.js::parseDate() the timezone offest is added to the date; + // in the case of "275760-09-13 00:00:00 GMT" the timevalue overflows. + client.query('SET TIMEZONE TO GMT', assert.success(function (res) { + + // PostgreSQL supports date range of 4713 BCE to 294276 CE + // http://www.postgresql.org/docs/9.2/static/datatype-datetime.html + // ECMAScript supports date range of Apr 20 271821 BCE to Sep 13 275760 CE + // http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1 + client.query('SELECT $1::TIMESTAMPTZ as when', ["275760-09-13 00:00:00 GMT"], assert.success(function (res) { + assert.equal(res.rows[0].when.getFullYear(), 275760); + })); + + client.query('SELECT $1::TIMESTAMPTZ as when', ["4713-12-31 12:31:59 BC GMT"], assert.success(function (res) { + assert.equal(res.rows[0].when.getFullYear(), -4713); + })); + + client.query('SELECT $1::TIMESTAMPTZ as when', ["275760-09-13 00:00:00 -15:00"], assert.success(function (res) { + assert(isNaN(res.rows[0].when.getTime())); + })); + + client.on('drain', () => { + client.end(done) + }); + })); +}); diff --git a/test/integration/client/type-parser-override-tests.js b/test/integration/client/type-parser-override-tests.js index 68a5de7f..3fd52dd2 100644 --- a/test/integration/client/type-parser-override-tests.js +++ b/test/integration/client/type-parser-override-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); function testTypeParser(client, expectedResult, done) { var boolValue = true; @@ -6,13 +6,13 @@ function testTypeParser(client, expectedResult, done) { client.query('INSERT INTO parserOverrideTest(id) VALUES ($1)', [boolValue]); client.query('SELECT * FROM parserOverrideTest', assert.success(function(result) { assert.equal(result.rows[0].id, expectedResult); - helper.pg.end(); done(); })); } -helper.pg.connect(helper.config, assert.success(function(client1, done1) { - helper.pg.connect(helper.config, assert.success(function(client2, done2) { +const pool = new helper.pg.Pool(helper.config) +pool.connect(assert.success(function(client1, done1) { + pool.connect(assert.success(function(client2, done2) { var boolTypeOID = 16; client1.setTypeParser(boolTypeOID, function(){ return 'first client'; @@ -28,7 +28,9 @@ helper.pg.connect(helper.config, assert.success(function(client1, done1) { return 'second client binary'; }); - testTypeParser(client1, 'first client', done1); - testTypeParser(client2, 'second client', done2); + testTypeParser(client1, 'first client', () => { + done1() + testTypeParser(client2, 'second client', () => done2(), pool.end()); + }); })); })); diff --git a/test/integration/connection-pool/connection-pool-size-tests.js b/test/integration/connection-pool/connection-pool-size-tests.js new file mode 100644 index 00000000..998bff7e --- /dev/null +++ b/test/integration/connection-pool/connection-pool-size-tests.js @@ -0,0 +1,9 @@ +var helper = require("./test-helper") + +helper.testPoolSize(1); + +helper.testPoolSize(2); + +helper.testPoolSize(40); + +helper.testPoolSize(200); diff --git a/test/integration/connection-pool/double-connection-tests.js b/test/integration/connection-pool/double-connection-tests.js deleted file mode 100644 index 421e1f9e..00000000 --- a/test/integration/connection-pool/double-connection-tests.js +++ /dev/null @@ -1,2 +0,0 @@ -var helper = require("./test-helper") -helper.testPoolSize(2); diff --git a/test/integration/connection-pool/ending-empty-pool-tests.js b/test/integration/connection-pool/ending-empty-pool-tests.js deleted file mode 100644 index d1acc6f2..00000000 --- a/test/integration/connection-pool/ending-empty-pool-tests.js +++ /dev/null @@ -1,15 +0,0 @@ -var helper = require('./test-helper') - -var called = false; -test('disconnects', function() { - called = true; - var eventSink = new helper.Sink(1, function() {}); - helper.pg.on('end', function() { - eventSink.add(); - }); - - //this should exit the process - helper.pg.end(); -}) - - diff --git a/test/integration/connection-pool/ending-pool-tests.js b/test/integration/connection-pool/ending-pool-tests.js deleted file mode 100644 index 3a1ab46f..00000000 --- a/test/integration/connection-pool/ending-pool-tests.js +++ /dev/null @@ -1,30 +0,0 @@ -var helper = require('./test-helper') - -var called = false; - -test('disconnects', function() { - var sink = new helper.Sink(4, function() { - called = true; - var eventSink = new helper.Sink(1, function() {}); - helper.pg.on('end', function() { - eventSink.add(); - }); - - //this should exit the process, killing each connection pool - helper.pg.end(); - }); - [helper.config, helper.config, helper.config, helper.config].forEach(function(config) { - helper.pg.connect(config, function(err, client, done) { - assert.isNull(err); - client.query("SELECT * FROM NOW()", function(err, result) { - setTimeout(function() { - assert.equal(called, false, "Should not have disconnected yet") - sink.add(); - done(); - }, 0) - }) - }) - }) -}) - - diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index 59121a86..21f61531 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -1,40 +1,46 @@ -var helper = require("../test-helper"); -var pg = require("../../../lib"); +var helper = require("./test-helper"); +const pg = helper.pg //first make pool hold 2 clients pg.defaults.poolSize = 2; -//get first client -pg.connect(helper.config, assert.success(function(client, done) { - client.id = 1; - client.query('SELECT NOW()', function() { - pg.connect(helper.config, assert.success(function(client2, done2) { - client2.id = 2; - var pidColName = 'procpid'; - helper.versionGTE(client2, '9.2.0', assert.success(function(isGreater) { - var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1'; - var params = ['idle']; - if(!isGreater) { - killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE $1'; - params = ['%IDLE%'] - } +const pool = new pg.Pool() - //subscribe to the pg error event - assert.emits(pg, 'error', function(error, brokenClient) { - assert.ok(error); - assert.ok(brokenClient); - assert.equal(client.id, brokenClient.id); - }); +const suite = new helper.Suite() +suite.test('errors emitted on pool', (cb) => { + //get first client + pool.connect(assert.success(function (client, done) { + client.id = 1; + client.query('SELECT NOW()', function () { + pool.connect(assert.success(function (client2, done2) { + client2.id = 2; + var pidColName = 'procpid'; + helper.versionGTE(client2, '9.2.0', assert.success(function (isGreater) { + var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1'; + var params = ['idle']; + if (!isGreater) { + killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE $1'; + params = ['%IDLE%'] + } - //kill the connection from client - client2.query(killIdleQuery, params, assert.success(function(res) { - //check to make sure client connection actually was killed - //return client2 to the pool - done2(); - pg.end(); + pool.once('error', (err, brokenClient) => { + assert.ok(err); + assert.ok(brokenClient); + assert.equal(client.id, brokenClient.id); + cb() + }) + + //kill the connection from client + client2.query(killIdleQuery, params, assert.success(function (res) { + //check to make sure client connection actually was killed + //return client2 to the pool + done2(); + pool.end(); + })); })); })); - })); - }) -})); + }) + })); + +}) diff --git a/test/integration/connection-pool/idle-timeout-tests.js b/test/integration/connection-pool/idle-timeout-tests.js index 5a5db0ba..e8090a09 100644 --- a/test/integration/connection-pool/idle-timeout-tests.js +++ b/test/integration/connection-pool/idle-timeout-tests.js @@ -1,13 +1,12 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); -const config = Object.assign({ }, helper.config, { idleTimeoutMillis: 50 }) -test('idle timeout', function() { - helper.pg.connect(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(); - })); +new helper.Suite().test('idle timeout', function () { + const config = Object.assign({}, helper.config, { idleTimeoutMillis: 50 }) + const pool = new helper.pg.Pool(config) + pool.connect(assert.calls(function (err, client, done) { + assert.isNull(err); + client.query('SELECT NOW()'); + done(); + })); }); diff --git a/test/integration/connection-pool/max-connection-tests.js b/test/integration/connection-pool/max-connection-tests.js deleted file mode 100644 index 944d2fb2..00000000 --- a/test/integration/connection-pool/max-connection-tests.js +++ /dev/null @@ -1,2 +0,0 @@ -var helper = require("./test-helper") -helper.testPoolSize(40); diff --git a/test/integration/connection-pool/optional-config-tests.js b/test/integration/connection-pool/optional-config-tests.js deleted file mode 100644 index be7063eb..00000000 --- a/test/integration/connection-pool/optional-config-tests.js +++ /dev/null @@ -1,20 +0,0 @@ -var helper = require('./test-helper'); - -//setup defaults -helper.pg.defaults.user = helper.args.user; -helper.pg.defaults.password = helper.args.password; -helper.pg.defaults.host = helper.args.host; -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, done) { - assert.isNull(err); - client.query('SELECT NOW()'); - client.once('drain', function() { - setTimeout(function() { - helper.pg.end(); - done(); - }, 10); - }); -})); diff --git a/test/integration/connection-pool/single-connection-tests.js b/test/integration/connection-pool/single-connection-tests.js deleted file mode 100644 index 89f6f069..00000000 --- a/test/integration/connection-pool/single-connection-tests.js +++ /dev/null @@ -1,2 +0,0 @@ -var helper = require("./test-helper") -helper.testPoolSize(1); diff --git a/test/integration/connection-pool/single-pool-on-object-config-tests.js b/test/integration/connection-pool/single-pool-on-object-config-tests.js deleted file mode 100644 index 81cdf8e4..00000000 --- a/test/integration/connection-pool/single-pool-on-object-config-tests.js +++ /dev/null @@ -1,13 +0,0 @@ -var helper = require("../test-helper"); -var pg = require("../../../lib"); - -pg.connect(helper.config, assert.success(function(client, done) { - assert.equal(Object.keys(pg._pools).length, 1); - pg.connect(helper.config, assert.success(function(client2, done2) { - assert.equal(Object.keys(pg._pools).length, 1); - - done(); - done2(); - pg.end(); - })); -})); diff --git a/test/integration/connection-pool/test-helper.js b/test/integration/connection-pool/test-helper.js index e4a3e425..b66bcba5 100644 --- a/test/integration/connection-pool/test-helper.js +++ b/test/integration/connection-pool/test-helper.js @@ -1,32 +1,31 @@ -var helper = require(__dirname + "/../test-helper"); +var helper = require("./../test-helper"); -helper.testPoolSize = function(max) { - var sink = new helper.Sink(max, function() { - helper.pg.end(); - }); +const suite = new helper.Suite() - test("can pool " + max + " times", function() { - for(var i = 0; i < max; i++) { - helper.pg.poolSize = 10; - test("connection #" + i + " executes", function() { - helper.pg.connect(helper.config, function(err, client, done) { - assert.isNull(err); - client.query("select * from person", function(err, result) { - assert.lengthIs(result.rows, 26) - }) - client.query("select count(*) as c from person", function(err, result) { - assert.equal(result.rows[0].c, 26) - }) - var query = client.query("SELECT * FROM NOW()", (err) => { - assert(!err) - sink.add(); - done(); - }) +helper.testPoolSize = function (max) { + suite.test(`test ${max} queries executed on a pool rapidly`, (cb) => { + const pool = new helper.pg.Pool({ max: 10 }) + + var sink = new helper.Sink(max, function () { + pool.end(cb) + }); + + for (var i = 0; i < max; i++) { + pool.connect(function (err, client, done) { + assert.isNull(err); + client.query("SELECT * FROM NOW()") + client.query("select generate_series(0, 25)", function (err, result) { + assert.equal(result.rows.length, 26) + }) + var query = client.query("SELECT * FROM NOW()", (err) => { + assert(!err) + sink.add(); + done(); }) }) } }) } -module.exports = helper; +module.exports = Object.assign({}, helper, { suite: suite }) diff --git a/test/integration/connection-pool/waiting-connection-tests.js b/test/integration/connection-pool/waiting-connection-tests.js deleted file mode 100644 index 82572d1e..00000000 --- a/test/integration/connection-pool/waiting-connection-tests.js +++ /dev/null @@ -1,2 +0,0 @@ -var helper = require("./test-helper") -helper.testPoolSize(200); diff --git a/test/integration/connection-pool/yield-support-tests.js b/test/integration/connection-pool/yield-support-tests.js index 943ab3a2..c56d9851 100644 --- a/test/integration/connection-pool/yield-support-tests.js +++ b/test/integration/connection-pool/yield-support-tests.js @@ -1,28 +1,19 @@ var helper = require('./test-helper') var co = require('co') -var tid = setTimeout(function() { - throw new Error('Tests did not complete in time') -}, 1000) - -co(function * () { - var client = yield helper.pg.connect() +const pool = new helper.pg.Pool() +new helper.Suite().test('using coroutines works with promises', co.wrap(function* () { + var client = yield pool.connect() var res = yield client.query('SELECT $1::text as name', ['foo']) assert.equal(res.rows[0].name, 'foo') var threw = false try { yield client.query('SELECT LKDSJDSLKFJ') - } catch(e) { + } catch (e) { threw = true } assert(threw) client.release() - helper.pg.end() - clearTimeout(tid) -}) -.catch(function(e) { - setImmediate(function() { - throw e - }) -}) + yield pool.end() +})) diff --git a/test/integration/domain-tests.js b/test/integration/domain-tests.js index dbd71c18..ce87335e 100644 --- a/test/integration/domain-tests.js +++ b/test/integration/domain-tests.js @@ -4,22 +4,26 @@ var helper = require('./test-helper') var Query = helper.pg.Query var suite = new helper.Suite() +const Pool = helper.pg.Pool + suite.test('no domain', function (cb) { assert(!process.domain) - helper.pg.connect(assert.success(function (client, done) { + const pool = new Pool() + pool.connect(assert.success(function (client, done) { assert(!process.domain) done() - cb() + pool.end(cb) })) }) suite.test('with domain', function (cb) { assert(!process.domain) + const pool = new Pool() var domain = require('domain').create() domain.run(function () { var startingDomain = process.domain assert(startingDomain) - helper.pg.connect(helper.config, assert.success(function (client, done) { + pool.connect(assert.success(function (client, done) { assert(process.domain, 'no domain exists in connect callback') assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') var query = client.query('SELECT NOW()', assert.success(function () { @@ -27,7 +31,7 @@ suite.test('with domain', function (cb) { assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') done(true) process.domain.exit() - cb() + pool.end(cb) })) })) }) @@ -35,15 +39,14 @@ suite.test('with domain', function (cb) { suite.test('error on domain', function (cb) { var domain = require('domain').create() + const pool = new Pool() domain.on('error', function () { - cb() + pool.end(cb) }) domain.run(function () { - helper.pg.connect(helper.config, assert.success(function (client, done) { + pool.connect(assert.success(function (client, done) { client.query(new Query('SELECT SLDKJFLSKDJF')) client.on('drain', done) })) }) }) - -suite.test('cleanup', () => helper.pg.end()) diff --git a/test/integration/gh-issues/130-tests.js b/test/integration/gh-issues/130-tests.js index fba9d4b4..0fed550b 100644 --- a/test/integration/gh-issues/130-tests.js +++ b/test/integration/gh-issues/130-tests.js @@ -3,7 +3,8 @@ var exec = require('child_process').exec; helper.pg.defaults.poolIdleTimeout = 1000; -helper.pg.connect(helper.config, function(err,client) { +const pool = new helper.pg.Pool() +pool.connect(function(err,client) { client.query("SELECT pg_backend_pid()", function(err, result) { var pid = result.rows[0].pg_backend_pid; var psql = 'psql'; @@ -16,6 +17,6 @@ helper.pg.connect(helper.config, function(err,client) { }); }); -helper.pg.on('error', function(err, client) { +pool.on('error', function(err, client) { //swallow errors }); diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index ff5c0344..41e71b5c 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -4,7 +4,8 @@ var pg = helper.pg; var suite = new helper.Suite() suite.test('parsing array decimal results', function (done) { - pg.connect(helper.config, assert.calls(function (err, client, release) { + const pool = new pg.Pool() + pool.connect(assert.calls(function (err, client, release) { assert.isNull(err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])"); client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log); @@ -14,8 +15,7 @@ suite.test('parsing array decimal results', function (done) { assert.equal(result.rows[0].decimals[1], 0.05); assert.equal(result.rows[0].decimals[2], 3.654); release() - pg.end(); - done() + pool.end(done) })) })) }) diff --git a/test/integration/gh-issues/507-tests.js b/test/integration/gh-issues/507-tests.js index 097e3be1..57e0f769 100644 --- a/test/integration/gh-issues/507-tests.js +++ b/test/integration/gh-issues/507-tests.js @@ -2,15 +2,15 @@ var helper = require(__dirname + "/../test-helper"); var pg = helper.pg; new helper.Suite().test('parsing array results', function(cb) { - pg.connect(helper.config, assert.success(function(client, done) { + const pool = new pg.Pool() + pool.connect(assert.success(function(client, done) { client.query('CREATE TEMP TABLE test_table(bar integer, "baz\'s" integer)') client.query('INSERT INTO test_table(bar, "baz\'s") VALUES(1, 1), (2, 2)') client.query('SELECT * FROM test_table', function(err, res) { assert.equal(res.rows[0]["baz's"], 1) assert.equal(res.rows[1]["baz's"], 2) done() - pg.end() - cb() + pool.end(cb) }) })) }) diff --git a/test/integration/gh-issues/675-tests.js b/test/integration/gh-issues/675-tests.js index f7fbf01b..e1bc0a55 100644 --- a/test/integration/gh-issues/675-tests.js +++ b/test/integration/gh-issues/675-tests.js @@ -1,7 +1,8 @@ var helper = require('../test-helper'); var assert = require('assert'); -helper.pg.connect(function(err, client, done) { +const pool = new helper.pg.Pool() +pool.connect(function(err, client, done) { if (err) throw err; var c = 'CREATE TEMP TABLE posts (body TEXT)'; @@ -21,7 +22,7 @@ helper.pg.connect(function(err, client, done) { if (err) throw err; assert.equal(res.rows[0].body, '') - helper.pg.end(); + pool.end(); }); }); }); diff --git a/test/integration/gh-issues/699-tests.js b/test/integration/gh-issues/699-tests.js index 8e92ff22..6f47ffca 100644 --- a/test/integration/gh-issues/699-tests.js +++ b/test/integration/gh-issues/699-tests.js @@ -4,7 +4,8 @@ var copyFrom = require('pg-copy-streams').from; if(helper.args.native) return; -helper.pg.connect(function (err, client, done) { +const pool = new helper.pg.Pool() +pool.connect(function (err, client, done) { if (err) throw err; var c = 'CREATE TEMP TABLE employee (id integer, fname varchar(400), lname varchar(400))'; @@ -16,7 +17,7 @@ helper.pg.connect(function (err, client, done) { stream.on('end', function () { done(); setTimeout(() => { - helper.pg.end(); + pool.end() }, 50) }); diff --git a/test/integration/gh-issues/787-tests.js b/test/integration/gh-issues/787-tests.js index df90cc54..773a033d 100644 --- a/test/integration/gh-issues/787-tests.js +++ b/test/integration/gh-issues/787-tests.js @@ -1,6 +1,7 @@ var helper = require('../test-helper'); +const pool = new helper.pg.Pool() -helper.pg.connect(function(err,client) { +pool.connect(function(err,client) { var q = { name: 'This is a super long query name just so I can test that an error message is properly spit out to console.error without throwing an exception or anything', text: 'SELECT NOW()' diff --git a/test/integration/gh-issues/981-tests.js b/test/integration/gh-issues/981-tests.js index ed3c3123..4ba2f5ad 100644 --- a/test/integration/gh-issues/981-tests.js +++ b/test/integration/gh-issues/981-tests.js @@ -1,7 +1,7 @@ -var helper = require(__dirname + '/../test-helper'); +var helper = require('./../test-helper'); //native bindings are only installed for native tests -if(!helper.args.native) { +if (!helper.args.native) { return; } @@ -15,13 +15,23 @@ var NativeClient = require('../../../lib/native') assert(pg.Client === JsClient); assert(native.Client === NativeClient); -pg.connect(function(err, client, done) { - assert(client instanceof JsClient); - client.end(); +const jsPool = new pg.Pool() +const nativePool = new native.Pool() - native.connect(function(err, client, done) { +const suite = new helper.Suite() +suite.test('js pool returns js client', cb => { + jsPool.connect(function (err, client, done) { + assert(client instanceof JsClient); + done() + jsPool.end(cb) + }) + +}) + +suite.test('native pool returns native client', cb => { + nativePool.connect(function (err, client, done) { assert(client instanceof NativeClient); - client.end(); + done() + nativePool.end(cb) }); -}); - +}) diff --git a/test/test-helper.js b/test/test-helper.js index 7fab5ad6..802d19c0 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -3,8 +3,6 @@ assert = require('assert'); var EventEmitter = require('events').EventEmitter; var sys = require('util'); -process.noDeprecation = true; - var BufferList = require('./buffer-list') const Suite = require('./suite') const args = require('./cli'); From 2300445646db264fe03a6194e2e7a77887204027 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 14:30:39 -0500 Subject: [PATCH 42/58] Cleanup a bit of dead code --- lib/client.js | 10 +++------- lib/index.js | 17 ++++++++++++++++- lib/native/index.js | 2 +- lib/pool-factory.js | 17 ----------------- lib/promise.js | 12 ------------ lib/utils.js | 10 +++++++++- test/unit/client/md5-password-tests.js | 9 +++++---- 7 files changed, 34 insertions(+), 43 deletions(-) delete mode 100644 lib/pool-factory.js delete mode 100644 lib/promise.js diff --git a/lib/client.js b/lib/client.js index 22026c1f..b11a0f39 100644 --- a/lib/client.js +++ b/lib/client.js @@ -6,9 +6,9 @@ * README.md file in the root directory of this source tree. */ -var crypto = require('crypto'); var EventEmitter = require('events').EventEmitter; var util = require('util'); +var utils = require('./utils') var pgPass = require('pgpass'); var TypeOverrides = require('./type-overrides'); @@ -97,8 +97,8 @@ Client.prototype.connect = function(callback) { //password request handling con.on('authenticationMD5Password', checkPgPass(function(msg) { - var inner = Client.md5(self.password + self.user); - var outer = Client.md5(Buffer.concat([Buffer.from(inner), msg.salt])); + var inner = utils.md5(self.password + self.user); + var outer = utils.md5(Buffer.concat([Buffer.from(inner), msg.salt])); var md5password = "md5" + outer; con.password(md5password); })); @@ -406,10 +406,6 @@ Client.prototype.end = function (cb) { } }; -Client.md5 = function (string) { - return crypto.createHash('md5').update(string, 'utf-8').digest('hex'); -}; - // expose a Query constructor Client.Query = Query; diff --git a/lib/index.js b/lib/index.js index ac3fb059..d12ea45a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -12,7 +12,22 @@ var Client = require('./client'); var defaults = require('./defaults'); var Connection = require('./connection'); var ConnectionParameters = require('./connection-parameters'); -var poolFactory = require('./pool-factory'); +var Pool = require('pg-pool'); + +const poolFactory = (Client) => { + var BoundPool = function(options) { + var config = { Client: Client }; + for (var key in options) { + config[key] = options[key]; + } + Pool.call(this, config); + }; + + util.inherits(BoundPool, Pool); + + return BoundPool; +}; + var PG = function(clientConstructor) { this.defaults = defaults; diff --git a/lib/native/index.js b/lib/native/index.js index ccf987e3..a35a2733 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -1 +1 @@ -module.exports = require('./client'); +module.exports = require('./client') diff --git a/lib/pool-factory.js b/lib/pool-factory.js deleted file mode 100644 index 85f0e6a5..00000000 --- a/lib/pool-factory.js +++ /dev/null @@ -1,17 +0,0 @@ -var Client = require('./client'); -var util = require('util'); -var Pool = require('pg-pool'); - -module.exports = function(Client) { - var BoundPool = function(options) { - var config = { Client: Client }; - for (var key in options) { - config[key] = options[key]; - } - Pool.call(this, config); - }; - - util.inherits(BoundPool, Pool); - - return BoundPool; -}; diff --git a/lib/promise.js b/lib/promise.js deleted file mode 100644 index 4d308cb9..00000000 --- a/lib/promise.js +++ /dev/null @@ -1,12 +0,0 @@ -const util = require('util') -const deprecationMessage = 'Using the promise result as an event emitter is deprecated and will be removed in pg@8.0' -module.exports = function(emitter, callback) { - const promise = new global.Promise(callback) - promise.on = util.deprecate(function () { - emitter.on.apply(emitter, arguments) - }, deprecationMessage); - - promise.once = util.deprecate(function () { - emitter.once.apply(emitter, arguments) - }, deprecationMessage) -} diff --git a/lib/utils.js b/lib/utils.js index e658bbd4..7ecf4b29 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -7,7 +7,9 @@ */ const util = require('util') -var defaults = require('./defaults'); +const crypto = require('crypto'); + +const defaults = require('./defaults'); function escapeElement(elementRepresentation) { var escaped = elementRepresentation @@ -138,6 +140,11 @@ function normalizeQueryConfig (config, values, callback) { return config; } + +const md5 = function (string) { + return crypto.createHash('md5').update(string, 'utf-8').digest('hex'); +}; + module.exports = { prepareValue: function prepareValueWrapper (value) { //this ensures that extra arguments do not get passed into prepareValue @@ -145,4 +152,5 @@ module.exports = { return prepareValue(value); }, normalizeQueryConfig: normalizeQueryConfig, + md5: md5, }; diff --git a/test/unit/client/md5-password-tests.js b/test/unit/client/md5-password-tests.js index 315ef197..78c82602 100644 --- a/test/unit/client/md5-password-tests.js +++ b/test/unit/client/md5-password-tests.js @@ -1,4 +1,5 @@ -require(__dirname + '/test-helper'); +require('./test-helper'); +var utils = require('../../../lib/utils') test('md5 authentication', function() { var client = createClient(); @@ -9,8 +10,8 @@ test('md5 authentication', function() { test('responds', function() { assert.lengthIs(client.connection.stream.packets, 1); test('should have correct encrypted data', function() { - var encrypted = Client.md5(client.password + client.user); - encrypted = Client.md5(encrypted + salt.toString('binary')); + var encrypted = utils.md5(client.password + client.user); + encrypted = utils.md5(encrypted + salt.toString('binary')); var password = "md5" + encrypted //how do we want to test this? assert.equalBuffers(client.connection.stream.packets[0], new BufferList() @@ -20,5 +21,5 @@ test('md5 authentication', function() { }); test('md5 of utf-8 strings', function() { - assert.equal(Client.md5('😊'), '5deda34cd95f304948d2bc1b4a62c11e'); + assert.equal(utils.md5('😊'), '5deda34cd95f304948d2bc1b4a62c11e'); }); From ed9a33d3d14cd5ad1e432476979d36a3c4bd10f6 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 14:54:42 -0500 Subject: [PATCH 43/58] Fix test for older version of postgres --- test/integration/client/json-type-parsing-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/client/json-type-parsing-tests.js b/test/integration/client/json-type-parsing-tests.js index e3dca3a5..b3ec4074 100644 --- a/test/integration/client/json-type-parsing-tests.js +++ b/test/integration/client/json-type-parsing-tests.js @@ -7,7 +7,7 @@ pool.connect(assert.success(function (client, done) { if (!jsonSupported) { console.log('skip json test on older versions of postgres'); done(); - return helper.pg.end(); + return pool.end(); } client.query('CREATE TEMP TABLE stuff(id SERIAL PRIMARY KEY, data JSON)'); var value = { name: 'Brian', age: 250, alive: true, now: new Date() }; From 49c5976947fa8d23722bd88de20fb699c1ce669b Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 15:14:20 -0500 Subject: [PATCH 44/58] Tweak travis node versions --- .travis.yml | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index ec0b7e3d..46e3a342 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,47 +8,29 @@ env: matrix: include: - - node_js: "4" + - node_js: "lts/argon" addons: postgresql: "9.6" - - node_js: "5" - addons: - postgresql: "9.6" - - node_js: "6" + - node_js: "lts/boron" addons: postgresql: "9.1" dist: precise - - node_js: "6" + - node_js: "lts/boron" addons: postgresql: "9.2" - - node_js: "6" + - node_js: "lts/boron" addons: postgresql: "9.3" - - node_js: "6" + - node_js: "lts/boron" addons: postgresql: "9.4" - - node_js: "6" + - node_js: "lts/boron" addons: postgresql: "9.5" - - node_js: "6" + - node_js: "lts/boron" addons: postgresql: "9.6" - - node_js: "8" - addons: - postgresql: "9.1" dist: precise - - node_js: "8" - addons: - postgresql: "9.2" - - node_js: "8" - addons: - postgresql: "9.3" - - node_js: "8" - addons: - postgresql: "9.4" - - node_js: "8" - addons: - postgresql: "9.5" - node_js: "8" addons: postgresql: "9.6" From 0f1f8626cf1e681f016ae844c3e1184fac67d2aa Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 15:34:30 -0500 Subject: [PATCH 45/58] Add use strict to every file --- lib/client.js | 1 + lib/connection-parameters.js | 1 + lib/connection.js | 1 + lib/defaults.js | 1 + lib/index.js | 1 + lib/native/client.js | 1 + lib/native/index.js | 1 + lib/native/query.js | 1 + lib/native/result.js | 1 + lib/query.js | 1 + lib/result.js | 1 + lib/type-overrides.js | 1 + lib/utils.js | 1 + script/create-test-tables.js | 1 + script/dump-db-types.js | 1 + script/list-db-types.js | 1 + test/buffer-list.js | 3 ++- test/cli.js | 1 + test/integration/client/api-tests.js | 1 + test/integration/client/appname-tests.js | 1 + test/integration/client/array-tests.js | 1 + test/integration/client/big-simple-query-tests.js | 1 + test/integration/client/configuration-tests.js | 1 + test/integration/client/custom-types-tests.js | 1 + test/integration/client/empty-query-tests.js | 1 + test/integration/client/error-handling-tests.js | 1 + test/integration/client/huge-numeric-tests.js | 1 + test/integration/client/json-type-parsing-tests.js | 1 + test/integration/client/network-partition-tests.js | 1 + test/integration/client/no-data-tests.js | 1 + test/integration/client/no-row-result-tests.js | 1 + test/integration/client/notice-tests.js | 1 + test/integration/client/parse-int-8-tests.js | 1 + test/integration/client/prepared-statement-tests.js | 1 + test/integration/client/promise-api-tests.js | 1 + test/integration/client/query-as-promise-tests.js | 1 + test/integration/client/query-column-names-tests.js | 1 + .../query-error-handling-prepared-statement-tests.js | 1 + test/integration/client/query-error-handling-tests.js | 1 + test/integration/client/quick-disconnect-tests.js | 1 + test/integration/client/result-metadata-tests.js | 1 + test/integration/client/results-as-array-tests.js | 1 + .../client/row-description-on-results-tests.js | 1 + test/integration/client/simple-query-tests.js | 3 ++- test/integration/client/ssl-tests.js | 1 + test/integration/client/test-helper.js | 3 ++- test/integration/client/timezone-tests.js | 1 + test/integration/client/transaction-tests.js | 1 + test/integration/client/type-coercion-tests.js | 1 + test/integration/client/type-parser-override-tests.js | 1 + .../connection-pool/connection-pool-size-tests.js | 1 + test/integration/connection-pool/error-tests.js | 1 + test/integration/connection-pool/idle-timeout-tests.js | 1 + .../integration/connection-pool/native-instance-tests.js | 1 + test/integration/connection-pool/test-helper.js | 1 + test/integration/connection-pool/yield-support-tests.js | 1 + test/integration/connection/bound-command-tests.js | 1 + test/integration/connection/copy-tests.js | 1 + test/integration/connection/notification-tests.js | 1 + test/integration/connection/query-tests.js | 1 + test/integration/connection/test-helper.js | 1 + test/integration/domain-tests.js | 1 + test/integration/gh-issues/130-tests.js | 1 + test/integration/gh-issues/131-tests.js | 1 + test/integration/gh-issues/199-tests.js | 1 + test/integration/gh-issues/507-tests.js | 1 + test/integration/gh-issues/600-tests.js | 1 + test/integration/gh-issues/675-tests.js | 1 + test/integration/gh-issues/699-tests.js | 1 + test/integration/gh-issues/787-tests.js | 1 + test/integration/gh-issues/882-tests.js | 1 + test/integration/gh-issues/981-tests.js | 1 + test/integration/test-helper.js | 1 + test/native/callback-api-tests.js | 1 + test/native/error-tests.js | 1 + test/native/evented-api-tests.js | 1 + test/native/missing-native.js | 1 + test/native/native-vs-js-error-tests.js | 1 + test/native/stress-tests.js | 1 + test/suite.js | 1 + test/test-buffers.js | 1 + test/test-helper.js | 7 ++++--- test/unit/client/cleartext-password-tests.js | 4 +++- test/unit/client/configuration-tests.js | 1 + test/unit/client/early-disconnect-tests.js | 1 + test/unit/client/escape-tests.js | 1 + test/unit/client/md5-password-tests.js | 5 +++-- test/unit/client/notification-tests.js | 1 + test/unit/client/prepared-statement-tests.js | 1 + test/unit/client/query-queue-tests.js | 1 + test/unit/client/result-metadata-tests.js | 1 + test/unit/client/simple-query-tests.js | 1 + .../client/stream-and-query-error-interaction-tests.js | 1 + test/unit/client/test-helper.js | 1 + test/unit/client/throw-in-type-parser-tests.js | 1 + test/unit/connection-parameters/creation-tests.js | 5 +++-- .../connection-parameters/environment-variable-tests.js | 1 + test/unit/connection/error-tests.js | 1 + test/unit/connection/inbound-parser-tests.js | 1 + test/unit/connection/outbound-sending-tests.js | 1 + test/unit/connection/startup-tests.js | 1 + test/unit/connection/test-helper.js | 1 + test/unit/test-helper.js | 9 ++++++--- test/unit/utils-tests.js | 7 ++++--- 104 files changed, 124 insertions(+), 17 deletions(-) diff --git a/lib/client.js b/lib/client.js index b11a0f39..dafa5a49 100644 --- a/lib/client.js +++ b/lib/client.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index e6efa158..a675e585 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/connection.js b/lib/connection.js index 8e57ff46..18aaf6f8 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/defaults.js b/lib/defaults.js index b94d33f3..de8898ee 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/index.js b/lib/index.js index d12ea45a..ad0c7172 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/native/client.js b/lib/native/client.js index 9641d399..9614cd14 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/native/index.js b/lib/native/index.js index a35a2733..53f10c4a 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -1 +1,2 @@ +"use strict"; module.exports = require('./client') diff --git a/lib/native/query.js b/lib/native/query.js index 4fb501f1..f9dacfa1 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/native/result.js b/lib/native/result.js index 51903731..62075b65 100644 --- a/lib/native/result.js +++ b/lib/native/result.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/query.js b/lib/query.js index 99b5ea8b..e294a4f0 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/result.js b/lib/result.js index 093a73c3..21b649a9 100644 --- a/lib/result.js +++ b/lib/result.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/type-overrides.js b/lib/type-overrides.js index 90526089..53be35ef 100644 --- a/lib/type-overrides.js +++ b/lib/type-overrides.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/utils.js b/lib/utils.js index 7ecf4b29..05c6f0b4 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/script/create-test-tables.js b/script/create-test-tables.js index 6a569f2a..4881daf8 100644 --- a/script/create-test-tables.js +++ b/script/create-test-tables.js @@ -1,3 +1,4 @@ +"use strict"; var args = require(__dirname + '/../test/cli'); var pg = require(__dirname + '/../lib'); diff --git a/script/dump-db-types.js b/script/dump-db-types.js index aa23825c..cd204153 100644 --- a/script/dump-db-types.js +++ b/script/dump-db-types.js @@ -1,3 +1,4 @@ +"use strict"; var pg = require(__dirname + '/../lib'); var args = require(__dirname + '/../test/cli'); diff --git a/script/list-db-types.js b/script/list-db-types.js index 748d32f2..b2db8403 100644 --- a/script/list-db-types.js +++ b/script/list-db-types.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/../test/integration/test-helper"); var pg = helper.pg; pg.connect(helper.config, assert.success(function(client) { diff --git a/test/buffer-list.js b/test/buffer-list.js index 2b1ac73e..3ebffe9d 100644 --- a/test/buffer-list.js +++ b/test/buffer-list.js @@ -1,4 +1,5 @@ -BufferList = function() { +"use strict"; +global.BufferList = function() { this.buffers = []; }; var p = BufferList.prototype; diff --git a/test/cli.js b/test/cli.js index bec0f3fb..388b8acf 100644 --- a/test/cli.js +++ b/test/cli.js @@ -1,3 +1,4 @@ +"use strict"; var ConnectionParameters = require(__dirname + '/../lib/connection-parameters'); var config = new ConnectionParameters(process.argv[2]); diff --git a/test/integration/client/api-tests.js b/test/integration/client/api-tests.js index 5f999482..e51a363a 100644 --- a/test/integration/client/api-tests.js +++ b/test/integration/client/api-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/../test-helper"); var pg = helper.pg; diff --git a/test/integration/client/appname-tests.js b/test/integration/client/appname-tests.js index 55673eff..98c41776 100644 --- a/test/integration/client/appname-tests.js +++ b/test/integration/client/appname-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var Client = helper.Client; diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index a26c7636..e56b5e63 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/test-helper"); var pg = helper.pg; diff --git a/test/integration/client/big-simple-query-tests.js b/test/integration/client/big-simple-query-tests.js index 0065772c..7db183f4 100644 --- a/test/integration/client/big-simple-query-tests.js +++ b/test/integration/client/big-simple-query-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper"); var Query = helper.pg.Query diff --git a/test/integration/client/configuration-tests.js b/test/integration/client/configuration-tests.js index 8cde4cea..8bd065e9 100644 --- a/test/integration/client/configuration-tests.js +++ b/test/integration/client/configuration-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var pg = helper.pg; diff --git a/test/integration/client/custom-types-tests.js b/test/integration/client/custom-types-tests.js index 9305dbbd..db143356 100644 --- a/test/integration/client/custom-types-tests.js +++ b/test/integration/client/custom-types-tests.js @@ -1,3 +1,4 @@ +"use strict"; const helper = require('./test-helper'); const Client = helper.pg.Client; const suite = new helper.Suite() diff --git a/test/integration/client/empty-query-tests.js b/test/integration/client/empty-query-tests.js index 8251088a..443c37d6 100644 --- a/test/integration/client/empty-query-tests.js +++ b/test/integration/client/empty-query-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); const suite = new helper.Suite() diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 69d43085..32ee58ba 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -1,4 +1,5 @@ "use strict"; +"use strict"; var helper = require('./test-helper'); var util = require('util'); diff --git a/test/integration/client/huge-numeric-tests.js b/test/integration/client/huge-numeric-tests.js index 9cd90537..a5bdbc8a 100644 --- a/test/integration/client/huge-numeric-tests.js +++ b/test/integration/client/huge-numeric-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); const pool = new helper.pg.Pool() diff --git a/test/integration/client/json-type-parsing-tests.js b/test/integration/client/json-type-parsing-tests.js index b3ec4074..77c5469a 100644 --- a/test/integration/client/json-type-parsing-tests.js +++ b/test/integration/client/json-type-parsing-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var assert = require('assert'); diff --git a/test/integration/client/network-partition-tests.js b/test/integration/client/network-partition-tests.js index 8e9d8af8..704f7fdf 100644 --- a/test/integration/client/network-partition-tests.js +++ b/test/integration/client/network-partition-tests.js @@ -1,3 +1,4 @@ +"use strict"; var buffers = require('../../test-buffers') var helper = require('./test-helper') var suite = new helper.Suite() diff --git a/test/integration/client/no-data-tests.js b/test/integration/client/no-data-tests.js index 28a4999a..a4ab36fb 100644 --- a/test/integration/client/no-data-tests.js +++ b/test/integration/client/no-data-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); const suite = new helper.Suite() diff --git a/test/integration/client/no-row-result-tests.js b/test/integration/client/no-row-result-tests.js index cc91c647..4ff28995 100644 --- a/test/integration/client/no-row-result-tests.js +++ b/test/integration/client/no-row-result-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper"); var pg = helper.pg; const suite = new helper.Suite(); diff --git a/test/integration/client/notice-tests.js b/test/integration/client/notice-tests.js index f226de8f..9c682050 100644 --- a/test/integration/client/notice-tests.js +++ b/test/integration/client/notice-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); const suite = new helper.Suite() diff --git a/test/integration/client/parse-int-8-tests.js b/test/integration/client/parse-int-8-tests.js index 937b41b7..920f5558 100644 --- a/test/integration/client/parse-int-8-tests.js +++ b/test/integration/client/parse-int-8-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); var pg = helper.pg; diff --git a/test/integration/client/prepared-statement-tests.js b/test/integration/client/prepared-statement-tests.js index 0d037b00..9b00f9d8 100644 --- a/test/integration/client/prepared-statement-tests.js +++ b/test/integration/client/prepared-statement-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var Query = helper.pg.Query; diff --git a/test/integration/client/promise-api-tests.js b/test/integration/client/promise-api-tests.js index ee088f94..45083a1b 100644 --- a/test/integration/client/promise-api-tests.js +++ b/test/integration/client/promise-api-tests.js @@ -1,3 +1,4 @@ +"use strict"; 'use strict'; const helper = require('./test-helper') diff --git a/test/integration/client/query-as-promise-tests.js b/test/integration/client/query-as-promise-tests.js index 95bf73ce..52487a7d 100644 --- a/test/integration/client/query-as-promise-tests.js +++ b/test/integration/client/query-as-promise-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/../test-helper'); var pg = helper.pg; diff --git a/test/integration/client/query-column-names-tests.js b/test/integration/client/query-column-names-tests.js index d929b508..a670bae3 100644 --- a/test/integration/client/query-column-names-tests.js +++ b/test/integration/client/query-column-names-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/../test-helper'); var pg = helper.pg; diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index 7aa68f59..f16f96f6 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var Query = helper.pg.Query; var util = require('util'); diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index d5ecd7bd..6c1b3b7c 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var util = require('util'); var Query = helper.pg.Query; diff --git a/test/integration/client/quick-disconnect-tests.js b/test/integration/client/quick-disconnect-tests.js index a1b6bab6..76a825ac 100644 --- a/test/integration/client/quick-disconnect-tests.js +++ b/test/integration/client/quick-disconnect-tests.js @@ -1,3 +1,4 @@ +"use strict"; //test for issue #320 // var helper = require('./test-helper'); diff --git a/test/integration/client/result-metadata-tests.js b/test/integration/client/result-metadata-tests.js index 85b7e18c..bb7aeff7 100644 --- a/test/integration/client/result-metadata-tests.js +++ b/test/integration/client/result-metadata-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper"); var pg = helper.pg; diff --git a/test/integration/client/results-as-array-tests.js b/test/integration/client/results-as-array-tests.js index 1a1d8edf..45398c05 100644 --- a/test/integration/client/results-as-array-tests.js +++ b/test/integration/client/results-as-array-tests.js @@ -1,3 +1,4 @@ +"use strict"; var util = require('util'); var helper = require('./test-helper'); diff --git a/test/integration/client/row-description-on-results-tests.js b/test/integration/client/row-description-on-results-tests.js index 22c92965..3d146bd6 100644 --- a/test/integration/client/row-description-on-results-tests.js +++ b/test/integration/client/row-description-on-results-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var Client = helper.Client; diff --git a/test/integration/client/simple-query-tests.js b/test/integration/client/simple-query-tests.js index 9453f159..6ae957dc 100644 --- a/test/integration/client/simple-query-tests.js +++ b/test/integration/client/simple-query-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper"); var Query = helper.pg.Query; @@ -18,7 +19,7 @@ test("simple query interface", function() { query.once('row', function(row) { test('Can iterate through columns', function () { var columnCount = 0; - for (column in row) { + for (var column in row) { columnCount++; } if ('length' in row) { diff --git a/test/integration/client/ssl-tests.js b/test/integration/client/ssl-tests.js index 0458d6b0..7523dfd3 100644 --- a/test/integration/client/ssl-tests.js +++ b/test/integration/client/ssl-tests.js @@ -1,3 +1,4 @@ +"use strict"; var pg = require(__dirname + '/../../../lib'); var config = require(__dirname + '/test-helper').config; test('can connect with ssl', function() { diff --git a/test/integration/client/test-helper.js b/test/integration/client/test-helper.js index 24cddf61..027477a1 100644 --- a/test/integration/client/test-helper.js +++ b/test/integration/client/test-helper.js @@ -1,3 +1,4 @@ -var helper = require(__dirname+'/../test-helper'); +"use strict"; +var helper = require('./../test-helper'); module.exports = helper; diff --git a/test/integration/client/timezone-tests.js b/test/integration/client/timezone-tests.js index 29873431..c1baa798 100644 --- a/test/integration/client/timezone-tests.js +++ b/test/integration/client/timezone-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./../test-helper'); var exec = require('child_process').exec; diff --git a/test/integration/client/transaction-tests.js b/test/integration/client/transaction-tests.js index 389a70d0..c9af7eab 100644 --- a/test/integration/client/transaction-tests.js +++ b/test/integration/client/transaction-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); const suite = new helper.Suite() const pg = helper.pg diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index dc50732e..080dd9ad 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); var pg = helper.pg; var sink; diff --git a/test/integration/client/type-parser-override-tests.js b/test/integration/client/type-parser-override-tests.js index 3fd52dd2..f12e4005 100644 --- a/test/integration/client/type-parser-override-tests.js +++ b/test/integration/client/type-parser-override-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); function testTypeParser(client, expectedResult, done) { diff --git a/test/integration/connection-pool/connection-pool-size-tests.js b/test/integration/connection-pool/connection-pool-size-tests.js index 998bff7e..51051c24 100644 --- a/test/integration/connection-pool/connection-pool-size-tests.js +++ b/test/integration/connection-pool/connection-pool-size-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper") helper.testPoolSize(1); diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index 21f61531..e01d598f 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper"); const pg = helper.pg diff --git a/test/integration/connection-pool/idle-timeout-tests.js b/test/integration/connection-pool/idle-timeout-tests.js index e8090a09..0531ae80 100644 --- a/test/integration/connection-pool/idle-timeout-tests.js +++ b/test/integration/connection-pool/idle-timeout-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); diff --git a/test/integration/connection-pool/native-instance-tests.js b/test/integration/connection-pool/native-instance-tests.js index 314920c4..caaa2b67 100644 --- a/test/integration/connection-pool/native-instance-tests.js +++ b/test/integration/connection-pool/native-instance-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./../test-helper") var pg = helper.pg var native = helper.args.native diff --git a/test/integration/connection-pool/test-helper.js b/test/integration/connection-pool/test-helper.js index b66bcba5..85ecd899 100644 --- a/test/integration/connection-pool/test-helper.js +++ b/test/integration/connection-pool/test-helper.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./../test-helper"); const suite = new helper.Suite() diff --git a/test/integration/connection-pool/yield-support-tests.js b/test/integration/connection-pool/yield-support-tests.js index c56d9851..14926699 100644 --- a/test/integration/connection-pool/yield-support-tests.js +++ b/test/integration/connection-pool/yield-support-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper') var co = require('co') diff --git a/test/integration/connection/bound-command-tests.js b/test/integration/connection/bound-command-tests.js index 9d40e5bc..40da4b5a 100644 --- a/test/integration/connection/bound-command-tests.js +++ b/test/integration/connection/bound-command-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); //http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY diff --git a/test/integration/connection/copy-tests.js b/test/integration/connection/copy-tests.js index ee4a71c5..2dfbc607 100644 --- a/test/integration/connection/copy-tests.js +++ b/test/integration/connection/copy-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname+"/test-helper"); var assert = require('assert'); diff --git a/test/integration/connection/notification-tests.js b/test/integration/connection/notification-tests.js index e0cf1382..dd11904d 100644 --- a/test/integration/connection/notification-tests.js +++ b/test/integration/connection/notification-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); //http://www.postgresql.org/docs/8.3/static/libpq-notify.html test('recieves notification from same connection with no payload', function() { diff --git a/test/integration/connection/query-tests.js b/test/integration/connection/query-tests.js index f308546d..6216c55a 100644 --- a/test/integration/connection/query-tests.js +++ b/test/integration/connection/query-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname+"/test-helper"); var assert = require('assert'); diff --git a/test/integration/connection/test-helper.js b/test/integration/connection/test-helper.js index 0bc65046..d053e39a 100644 --- a/test/integration/connection/test-helper.js +++ b/test/integration/connection/test-helper.js @@ -1,3 +1,4 @@ +"use strict"; var net = require('net'); var helper = require(__dirname+'/../test-helper'); var Connection = require(__dirname + '/../../../lib/connection'); diff --git a/test/integration/domain-tests.js b/test/integration/domain-tests.js index ce87335e..5d4db53c 100644 --- a/test/integration/domain-tests.js +++ b/test/integration/domain-tests.js @@ -1,3 +1,4 @@ +"use strict"; var async = require('async') var helper = require('./test-helper') diff --git a/test/integration/gh-issues/130-tests.js b/test/integration/gh-issues/130-tests.js index 0fed550b..bc1f3b74 100644 --- a/test/integration/gh-issues/130-tests.js +++ b/test/integration/gh-issues/130-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/../test-helper'); var exec = require('child_process').exec; diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index 41e71b5c..164f94e9 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); var pg = helper.pg; diff --git a/test/integration/gh-issues/199-tests.js b/test/integration/gh-issues/199-tests.js index b60477fd..60637fb1 100644 --- a/test/integration/gh-issues/199-tests.js +++ b/test/integration/gh-issues/199-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); var client = helper.client(); diff --git a/test/integration/gh-issues/507-tests.js b/test/integration/gh-issues/507-tests.js index 57e0f769..62bec47c 100644 --- a/test/integration/gh-issues/507-tests.js +++ b/test/integration/gh-issues/507-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/../test-helper"); var pg = helper.pg; diff --git a/test/integration/gh-issues/600-tests.js b/test/integration/gh-issues/600-tests.js index b64f19fa..263e48d0 100644 --- a/test/integration/gh-issues/600-tests.js +++ b/test/integration/gh-issues/600-tests.js @@ -1,3 +1,4 @@ +"use strict"; var async = require('async'); var helper = require('../test-helper'); const suite = new helper.Suite() diff --git a/test/integration/gh-issues/675-tests.js b/test/integration/gh-issues/675-tests.js index e1bc0a55..b162b9df 100644 --- a/test/integration/gh-issues/675-tests.js +++ b/test/integration/gh-issues/675-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); var assert = require('assert'); diff --git a/test/integration/gh-issues/699-tests.js b/test/integration/gh-issues/699-tests.js index 6f47ffca..d4c9eab7 100644 --- a/test/integration/gh-issues/699-tests.js +++ b/test/integration/gh-issues/699-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); var assert = require('assert'); var copyFrom = require('pg-copy-streams').from; diff --git a/test/integration/gh-issues/787-tests.js b/test/integration/gh-issues/787-tests.js index 773a033d..83ea85f3 100644 --- a/test/integration/gh-issues/787-tests.js +++ b/test/integration/gh-issues/787-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); const pool = new helper.pg.Pool() diff --git a/test/integration/gh-issues/882-tests.js b/test/integration/gh-issues/882-tests.js index 1818b0c6..154f9e96 100644 --- a/test/integration/gh-issues/882-tests.js +++ b/test/integration/gh-issues/882-tests.js @@ -1,3 +1,4 @@ +"use strict"; //client should not hang on an empty query var helper = require('../test-helper'); var client = helper.client(); diff --git a/test/integration/gh-issues/981-tests.js b/test/integration/gh-issues/981-tests.js index 4ba2f5ad..6348d05a 100644 --- a/test/integration/gh-issues/981-tests.js +++ b/test/integration/gh-issues/981-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./../test-helper'); //native bindings are only installed for native tests diff --git a/test/integration/test-helper.js b/test/integration/test-helper.js index ceed87d5..9dba636d 100644 --- a/test/integration/test-helper.js +++ b/test/integration/test-helper.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/../test-helper'); if(helper.args.native) { diff --git a/test/native/callback-api-tests.js b/test/native/callback-api-tests.js index 6193ba74..fa57dbde 100644 --- a/test/native/callback-api-tests.js +++ b/test/native/callback-api-tests.js @@ -1,3 +1,4 @@ +"use strict"; var domain = require('domain'); var helper = require("./../test-helper"); var Client = require("./../../lib/native"); diff --git a/test/native/error-tests.js b/test/native/error-tests.js index 2edf3421..a6f87644 100644 --- a/test/native/error-tests.js +++ b/test/native/error-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/../test-helper"); var Client = require(__dirname + "/../../lib/native"); diff --git a/test/native/evented-api-tests.js b/test/native/evented-api-tests.js index 122dc47e..8a7c19b4 100644 --- a/test/native/evented-api-tests.js +++ b/test/native/evented-api-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("../test-helper"); var Client = require("../../lib/native"); var Query = Client.Query; diff --git a/test/native/missing-native.js b/test/native/missing-native.js index 775c6186..d8474287 100644 --- a/test/native/missing-native.js +++ b/test/native/missing-native.js @@ -1,3 +1,4 @@ +"use strict"; //this test assumes it has been run from the Makefile //and that node_modules/pg-native has been deleted diff --git a/test/native/native-vs-js-error-tests.js b/test/native/native-vs-js-error-tests.js index ee192ddc..59c6bb94 100644 --- a/test/native/native-vs-js-error-tests.js +++ b/test/native/native-vs-js-error-tests.js @@ -1,3 +1,4 @@ +"use strict"; var assert = require('assert') var Client = require('../../lib/client'); var NativeClient = require('../../lib/native'); diff --git a/test/native/stress-tests.js b/test/native/stress-tests.js index 08fab97e..32477cb8 100644 --- a/test/native/stress-tests.js +++ b/test/native/stress-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/../test-helper"); var Client = require(__dirname + "/../../lib/native"); var Query = Client.Query; diff --git a/test/suite.js b/test/suite.js index 22d1a9cc..da6492fb 100644 --- a/test/suite.js +++ b/test/suite.js @@ -1,3 +1,4 @@ +"use strict"; 'use strict'; const async = require('async') diff --git a/test/test-buffers.js b/test/test-buffers.js index b16a7ab6..0351559a 100644 --- a/test/test-buffers.js +++ b/test/test-buffers.js @@ -1,3 +1,4 @@ +"use strict"; require(__dirname+'/test-helper'); //http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html diff --git a/test/test-helper.js b/test/test-helper.js index 802d19c0..3bfc5177 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,5 +1,6 @@ +"use strict"; //make assert a global... -assert = require('assert'); +global.assert = require('assert'); var EventEmitter = require('events').EventEmitter; var sys = require('util'); @@ -9,7 +10,7 @@ const args = require('./cli'); var Connection = require('./../lib/connection'); -Client = require('./../lib').Client; +global.Client = require('./../lib').Client; process.on('uncaughtException', function(d) { if ('stack' in d && 'message' in d) { @@ -172,7 +173,7 @@ const getMode = () => { return '' } -test = function(name, action) { +global.test = function(name, action) { test.testCount ++; test[name] = action; var result = test[name](); diff --git a/test/unit/client/cleartext-password-tests.js b/test/unit/client/cleartext-password-tests.js index e880908b..67e7c67b 100644 --- a/test/unit/client/cleartext-password-tests.js +++ b/test/unit/client/cleartext-password-tests.js @@ -1,4 +1,6 @@ -require(__dirname+'/test-helper'); +"use strict"; + +const createClient = require('./test-helper').createClient; /* * TODO: Add _some_ comments to explain what it is we're testing, and how the diff --git a/test/unit/client/configuration-tests.js b/test/unit/client/configuration-tests.js index 5548e5fb..bf007ee7 100644 --- a/test/unit/client/configuration-tests.js +++ b/test/unit/client/configuration-tests.js @@ -1,3 +1,4 @@ +"use strict"; require(__dirname+'/test-helper'); var pguser = process.env['PGUSER'] || process.env.USER; diff --git a/test/unit/client/early-disconnect-tests.js b/test/unit/client/early-disconnect-tests.js index a4c38be9..f3884c7b 100644 --- a/test/unit/client/early-disconnect-tests.js +++ b/test/unit/client/early-disconnect-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); var net = require('net'); var pg = require('../../..//lib/index.js'); diff --git a/test/unit/client/escape-tests.js b/test/unit/client/escape-tests.js index e3f638ac..7ea640fc 100644 --- a/test/unit/client/escape-tests.js +++ b/test/unit/client/escape-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); function createClient(callback) { diff --git a/test/unit/client/md5-password-tests.js b/test/unit/client/md5-password-tests.js index 78c82602..63a0398d 100644 --- a/test/unit/client/md5-password-tests.js +++ b/test/unit/client/md5-password-tests.js @@ -1,8 +1,9 @@ -require('./test-helper'); +"use strict"; +var helper = require('./test-helper'); var utils = require('../../../lib/utils') test('md5 authentication', function() { - var client = createClient(); + var client = helper.createClient(); client.password = "!"; var salt = Buffer.from([1, 2, 3, 4]); client.connection.emit('authenticationMD5Password', {salt: salt}); diff --git a/test/unit/client/notification-tests.js b/test/unit/client/notification-tests.js index e6b0dff1..dab8f608 100644 --- a/test/unit/client/notification-tests.js +++ b/test/unit/client/notification-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/test-helper"); test('passes connection notification', function() { diff --git a/test/unit/client/prepared-statement-tests.js b/test/unit/client/prepared-statement-tests.js index 460cbf95..50327bf4 100644 --- a/test/unit/client/prepared-statement-tests.js +++ b/test/unit/client/prepared-statement-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var Query = require('../../../lib/query') diff --git a/test/unit/client/query-queue-tests.js b/test/unit/client/query-queue-tests.js index 62b38bd5..2aa3b6b0 100644 --- a/test/unit/client/query-queue-tests.js +++ b/test/unit/client/query-queue-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); var Connection = require(__dirname + '/../../../lib/connection'); diff --git a/test/unit/client/result-metadata-tests.js b/test/unit/client/result-metadata-tests.js index 5f349b57..c3f26620 100644 --- a/test/unit/client/result-metadata-tests.js +++ b/test/unit/client/result-metadata-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/test-helper") var testForTag = function(tagText, callback) { diff --git a/test/unit/client/simple-query-tests.js b/test/unit/client/simple-query-tests.js index df71faed..29ab0012 100644 --- a/test/unit/client/simple-query-tests.js +++ b/test/unit/client/simple-query-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/test-helper"); var Query = require('../../../lib/query') diff --git a/test/unit/client/stream-and-query-error-interaction-tests.js b/test/unit/client/stream-and-query-error-interaction-tests.js index a60e1f73..0815fccd 100644 --- a/test/unit/client/stream-and-query-error-interaction-tests.js +++ b/test/unit/client/stream-and-query-error-interaction-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); var Connection = require(__dirname + '/../../../lib/connection'); var Client = require(__dirname + '/../../../lib/client'); diff --git a/test/unit/client/test-helper.js b/test/unit/client/test-helper.js index 7c0bb31b..fe1765d6 100644 --- a/test/unit/client/test-helper.js +++ b/test/unit/client/test-helper.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); var Connection = require('../../../lib/connection'); diff --git a/test/unit/client/throw-in-type-parser-tests.js b/test/unit/client/throw-in-type-parser-tests.js index 2f184543..06580eb0 100644 --- a/test/unit/client/throw-in-type-parser-tests.js +++ b/test/unit/client/throw-in-type-parser-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper"); var Query = require("../../../lib/query"); var types = require("pg-types"); diff --git a/test/unit/connection-parameters/creation-tests.js b/test/unit/connection-parameters/creation-tests.js index 85c2bd03..36e17a93 100644 --- a/test/unit/connection-parameters/creation-tests.js +++ b/test/unit/connection-parameters/creation-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/../test-helper'); var assert = require('assert'); var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters'); @@ -67,12 +68,12 @@ test('ConnectionParameters initializing from config', function() { }); test('escape spaces if present', function() { - subject = new ConnectionParameters('postgres://localhost/post gres'); + var subject = new ConnectionParameters('postgres://localhost/post gres'); assert.equal(subject.database, 'post gres'); }); test('do not double escape spaces', function() { - subject = new ConnectionParameters('postgres://localhost/post%20gres'); + var subject = new ConnectionParameters('postgres://localhost/post%20gres'); assert.equal(subject.database, 'post gres'); }); diff --git a/test/unit/connection-parameters/environment-variable-tests.js b/test/unit/connection-parameters/environment-variable-tests.js index 5481915f..2f41fecd 100644 --- a/test/unit/connection-parameters/environment-variable-tests.js +++ b/test/unit/connection-parameters/environment-variable-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/../test-helper'); var assert = require('assert'); var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters'); diff --git a/test/unit/connection/error-tests.js b/test/unit/connection/error-tests.js index 98eb20a8..20952a69 100644 --- a/test/unit/connection/error-tests.js +++ b/test/unit/connection/error-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); var Connection = require(__dirname + '/../../../lib/connection'); test("connection emits stream errors", function() { diff --git a/test/unit/connection/inbound-parser-tests.js b/test/unit/connection/inbound-parser-tests.js index 2b822e44..86266b22 100644 --- a/test/unit/connection/inbound-parser-tests.js +++ b/test/unit/connection/inbound-parser-tests.js @@ -1,3 +1,4 @@ +"use strict"; require(__dirname+'/test-helper'); var Connection = require(__dirname + '/../../../lib/connection'); var buffers = require(__dirname + '/../../test-buffers'); diff --git a/test/unit/connection/outbound-sending-tests.js b/test/unit/connection/outbound-sending-tests.js index 353c073b..69642957 100644 --- a/test/unit/connection/outbound-sending-tests.js +++ b/test/unit/connection/outbound-sending-tests.js @@ -1,3 +1,4 @@ +"use strict"; require(__dirname + "/test-helper"); var Connection = require(__dirname + '/../../../lib/connection'); var stream = new MemoryStream(); diff --git a/test/unit/connection/startup-tests.js b/test/unit/connection/startup-tests.js index 622f4737..ee20d679 100644 --- a/test/unit/connection/startup-tests.js +++ b/test/unit/connection/startup-tests.js @@ -1,3 +1,4 @@ +"use strict"; require(__dirname+'/test-helper'); var Connection = require(__dirname + '/../../../lib/connection'); test('connection can take existing stream', function() { diff --git a/test/unit/connection/test-helper.js b/test/unit/connection/test-helper.js index 88cced6d..03d95a69 100644 --- a/test/unit/connection/test-helper.js +++ b/test/unit/connection/test-helper.js @@ -1 +1,2 @@ +"use strict"; require(__dirname+'/../test-helper') diff --git a/test/unit/test-helper.js b/test/unit/test-helper.js index ad6485be..1dcac733 100644 --- a/test/unit/test-helper.js +++ b/test/unit/test-helper.js @@ -1,9 +1,10 @@ +"use strict"; var EventEmitter = require('events').EventEmitter; var helper = require('../test-helper'); var Connection = require('../../lib/connection'); -MemoryStream = function() { +global.MemoryStream = function() { EventEmitter.call(this); this.packets = []; }; @@ -21,7 +22,7 @@ p.setKeepAlive = function(){}; p.writable = true; -createClient = function() { +const createClient = function() { var stream = new MemoryStream(); stream.readyState = "open"; var client = new Client({ @@ -31,4 +32,6 @@ createClient = function() { return client; }; -module.exports = helper; +module.exports = Object.assign({}, helper, { + createClient: createClient, +}); diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index 82b11715..893cf5b5 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -1,6 +1,7 @@ -var helper = require(__dirname + '/test-helper'); -var utils = require(__dirname + "/../../lib/utils"); -var defaults = require(__dirname + "/../../lib").defaults; +"use strict"; +var helper = require('./test-helper'); +var utils = require("./../../lib/utils"); +var defaults = require("./../../lib").defaults; test('ensure types is exported on root object', function() { From 729d4e9c4737b8c0cfe75719e24f7ebb879f828f Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 15:41:30 -0500 Subject: [PATCH 46/58] Tweak travis.yml --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 46e3a342..3abcf8a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,6 @@ matrix: - node_js: "lts/boron" addons: postgresql: "9.6" - dist: precise - node_js: "8" addons: postgresql: "9.6" From bd87cddc72bbf49e7a83921644df0f2fede14341 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 16:26:13 -0500 Subject: [PATCH 47/58] Fix connection / disconnection issues --- lib/client.js | 70 +++++++++---------- .../client/error-handling-tests.js | 19 ++++- .../connection-pool/error-tests.js | 5 ++ test/integration/test-helper.js | 4 +- test/unit/client/early-disconnect-tests.js | 4 +- 5 files changed, 62 insertions(+), 40 deletions(-) diff --git a/lib/client.js b/lib/client.js index dafa5a49..ae5a176d 100644 --- a/lib/client.js +++ b/lib/client.js @@ -109,12 +109,35 @@ Client.prototype.connect = function(callback) { self.secretKey = msg.secretKey; }); + const connectingErrorHandler = (err) => { + if (this._connectionError) { + return; + } + this._connectionError = true + if (callback) { + return callback(err) + } + this.emit('error', err) + } + + const connectedErrorHandler = (err) => { + if(this.activeQuery) { + var activeQuery = self.activeQuery; + this.activeQuery = null; + return activeQuery.handleError(err, con); + } + this.emit('error', err) + } + + con.on('error', connectingErrorHandler) + //hook up query handling events to connection //after the connection initially becomes ready for queries con.once('readyForQuery', function() { self._connecting = false; self._attachListeners(con); - + con.removeListener('error', connectingErrorHandler); + con.on('error', connectedErrorHandler) //process possible callback argument to Client#connect if (callback) { @@ -136,37 +159,7 @@ Client.prototype.connect = function(callback) { self._pulseQueryQueue(); }); - con.on('error', function(error) { - if(this.activeQuery) { - var activeQuery = self.activeQuery; - this.activeQuery = null; - return activeQuery.handleError(error, con); - } - - if (this._connecting) { - // set a flag indicating we've seen an error during connection - // the backend will terminate the connection and we don't want - // to throw a second error when the connection is terminated - this._connectionError = true; - } - - if(!callback) { - return this.emit('error', error); - } - - con.end(); // make sure ECONNRESET errors don't cause error events - callback(error); - callback = null; - }.bind(this)); - - con.once('end', function() { - if (callback) { - // haven't received a connection message yet! - var err = new Error('Connection terminated'); - callback(err); - callback = null; - return; - } + con.once('end', () => { if(this.activeQuery) { var disconnectError = new Error('Connection terminated'); this.activeQuery.handleError(disconnectError, con); @@ -177,12 +170,19 @@ Client.prototype.connect = function(callback) { // on this client then we have an unexpected disconnection // treat this as an error unless we've already emitted an error // during connection. - if (!this._connectionError) { - this.emit('error', new Error('Connection terminated unexpectedly')); + const error = new Error('Connection terminated unexpectedly') + if (this._connecting && !this._connectionError) { + if (callback) { + callback(error) + } else { + this.emit('error', error) + } + } else if (!this._connectionError) { + this.emit('error', error); } } this.emit('end'); - }.bind(this)); + }); con.on('notice', function(msg) { diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 32ee58ba..89c181a5 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -1,10 +1,10 @@ "use strict"; -"use strict"; var helper = require('./test-helper'); var util = require('util'); var pg = helper.pg +const Client = pg.Client var createErorrClient = function() { var client = helper.client(); @@ -84,6 +84,7 @@ suite.test('non-query error with callback', function(done) { user:'asldkfjsadlfkj' }); client.connect(assert.calls(function(error, client) { + console.log('error!', error.stack) assert(error instanceof Error) done() })); @@ -142,3 +143,19 @@ suite.test('within a simple query', (done) => { done(); }); }); + +suite.test('connected, idle client error', (done) => { + const client = new Client() + client.connect((err) => { + if (err) { + throw new Error('Should not receive error callback after connection') + } + setImmediate(() => { + (client.connection || client.native).emit('error', new Error('expected')) + }) + }) + client.on('error', (err) => { + assert.equal(err.message, 'expected') + client.end(done) + }) +}) diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index e01d598f..4098ba9d 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -8,6 +8,11 @@ pg.defaults.poolSize = 2; const pool = new pg.Pool() const suite = new helper.Suite() +suite.test('connecting to invalid port', (cb) => { + const pool = new pg.Pool({ port: 13801 }) + pool.connect().catch(e => cb()) +}) + suite.test('errors emitted on pool', (cb) => { //get first client pool.connect(assert.success(function (client, done) { diff --git a/test/integration/test-helper.js b/test/integration/test-helper.js index 9dba636d..56ea43ed 100644 --- a/test/integration/test-helper.js +++ b/test/integration/test-helper.js @@ -1,8 +1,8 @@ "use strict"; -var helper = require(__dirname + '/../test-helper'); +var helper = require('./../test-helper'); if(helper.args.native) { - Client = require(__dirname + '/../../lib/native'); + Client = require('./../../lib/native'); helper.Client = Client; helper.pg = helper.pg.native; } diff --git a/test/unit/client/early-disconnect-tests.js b/test/unit/client/early-disconnect-tests.js index f3884c7b..c8d7fbc5 100644 --- a/test/unit/client/early-disconnect-tests.js +++ b/test/unit/client/early-disconnect-tests.js @@ -1,7 +1,7 @@ "use strict"; -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); var net = require('net'); -var pg = require('../../..//lib/index.js'); +var pg = require('../../../lib/index.js'); /* console.log() messages show up in `make test` output. TODO: fix it. */ var server = net.createServer(function(c) { From da71ea58f67ef088dd80e4b22984ada8efea56b2 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 17:06:46 -0500 Subject: [PATCH 48/58] Add query validity check Passing nothing for both the query.text and query.name is unsupported but previously crashed with an impossible to catch error. --- lib/query.js | 6 ++++++ test/integration/client/error-handling-tests.js | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/query.js b/lib/query.js index e294a4f0..a8e76547 100644 --- a/lib/query.js +++ b/lib/query.js @@ -127,6 +127,12 @@ Query.prototype.handleError = function(err, connection) { }; Query.prototype.submit = function(connection) { + if (typeof this.text != 'string' && typeof this.name != 'string') { + const err = new Error('A query must have either text or a name. Supplying neither is unsupported.') + connection.emit('error', err) + connection.emit('readyForQuery') + return + } if(this.requiresPreparation()) { this.prepare(connection); } else { diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 89c181a5..c929dd7b 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -159,3 +159,16 @@ suite.test('connected, idle client error', (done) => { client.end(done) }) }) + +suite.test('cannot pass non-string values to query as text', (done) => { + const client = new Client() + client.connect() + client.query({ text: { } }, (err) => { + assert(err) + client.query({ }, (err) => { + client.on('drain', () => { + client.end(done) + }) + }) + }) +}) From a83655a396309521aed72cb02ecce87409034e83 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 17:23:58 -0500 Subject: [PATCH 49/58] Remove console.log statement --- test/integration/client/error-handling-tests.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index c929dd7b..e18cc900 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -84,7 +84,6 @@ suite.test('non-query error with callback', function(done) { user:'asldkfjsadlfkj' }); client.connect(assert.calls(function(error, client) { - console.log('error!', error.stack) assert(error instanceof Error) done() })); From 27450d07e6fb4eb0eb7a14754963c8bf9d2a3be9 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 14 Jul 2017 14:57:48 -0500 Subject: [PATCH 50/58] Throw on reconnect attempt Clients are not reusable. This changes the client to raise errors whenever you try to reconnect a client that's already been used. They're cheap to create: just instantiate a new one (or use the pool) :wink:. Closes #1352 --- lib/client.js | 10 + lib/index.js | 2 +- lib/native/client.js | 8 + package.json | 2 +- test/integration/client/api-tests.js | 20 +- test/integration/client/array-tests.js | 284 +++++++++--------- test/integration/client/empty-query-tests.js | 2 +- .../client/error-handling-tests.js | 20 ++ .../client/result-metadata-tests.js | 8 +- test/integration/client/timezone-tests.js | 6 +- test/integration/client/transaction-tests.js | 8 +- .../integration/client/type-coercion-tests.js | 10 +- .../connection-pool/idle-timeout-tests.js | 2 +- .../connection-pool/test-helper.js | 2 +- test/integration/gh-issues/131-tests.js | 2 +- test/native/callback-api-tests.js | 4 +- .../connection-parameters/creation-tests.js | 10 +- 17 files changed, 219 insertions(+), 181 deletions(-) diff --git a/lib/client.js b/lib/client.js index ae5a176d..25a9d66c 100644 --- a/lib/client.js +++ b/lib/client.js @@ -34,6 +34,7 @@ var Client = function(config) { this._types = new TypeOverrides(c.types); this._ending = false; this._connecting = false; + this._connected = false; this._connectionError = false; this.connection = c.connection || new Connection({ @@ -54,6 +55,14 @@ util.inherits(Client, EventEmitter); Client.prototype.connect = function(callback) { var self = this; var con = this.connection; + if (this._connecting || this._connected) { + const err = new Error('Client has already been connected. You cannot reuse a client.') + if (callback) { + callback(err) + return undefined + } + return Promise.reject(err) + } this._connecting = true; if(this.host && this.host.indexOf('/') === 0) { @@ -135,6 +144,7 @@ Client.prototype.connect = function(callback) { //after the connection initially becomes ready for queries con.once('readyForQuery', function() { self._connecting = false; + self._connected = true; self._attachListeners(con); con.removeListener('error', connectingErrorHandler); con.on('error', connectedErrorHandler) diff --git a/lib/index.js b/lib/index.js index ad0c7172..b74cbdeb 100644 --- a/lib/index.js +++ b/lib/index.js @@ -21,7 +21,7 @@ const poolFactory = (Client) => { for (var key in options) { config[key] = options[key]; } - Pool.call(this, config); + return new Pool(config) }; util.inherits(BoundPool, Pool); diff --git a/lib/native/client.js b/lib/native/client.js index 9614cd14..d8f20fe7 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -33,6 +33,7 @@ var Client = module.exports = function(config) { this._queryQueue = []; this._connected = false; + this._connecting = false; //keep these on the object for legacy reasons //for the time being. TODO: deprecate all this jazz @@ -74,6 +75,13 @@ Client.prototype.connect = function(cb) { }) } + if (this._connecting) { + process.nextTick(() => cb(new Error('Client has already been connected. You cannot reuse a client.'))) + return result + } + + this._connecting = true + this.connectionParameters.getLibpqConnectionString(function(err, conString) { if(err) return onError(err); self.native.connect(conString, function(err) { diff --git a/package.json b/package.json index 0fee6bf4..537570d0 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "buffer-writer": "1.0.1", "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", - "pg-pool": "1.*", + "pg-pool": "2.*", "pg-types": "1.*", "pgpass": "1.x", "semver": "4.3.2" diff --git a/test/integration/client/api-tests.js b/test/integration/client/api-tests.js index e51a363a..668c6a74 100644 --- a/test/integration/client/api-tests.js +++ b/test/integration/client/api-tests.js @@ -8,7 +8,7 @@ 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); + assert(!err); arguments[1].emit("drain"); arguments[2](); pool.end(done); @@ -52,7 +52,7 @@ suite.test("executing nested queries", function(done) { const pool = new pg.Pool(); pool.connect( assert.calls(function(err, client, release) { - assert.isNull(err); + assert(!err); client.query( "select now as now from NOW()", assert.calls(function(err, result) { @@ -91,7 +91,7 @@ suite.test("query errors are handled and do not bubble if callback is provded", const pool = new pg.Pool(); pool.connect( assert.calls(function(err, client, release) { - assert.isNull(err); + assert(!err); client.query( "SELECT OISDJF FROM LEIWLISEJLSE", assert.calls(function(err, result) { @@ -109,7 +109,7 @@ 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); + assert(!err); client.query("CREATE TEMP TABLE boom(name varchar(10))"); var callCount = 0; client.query( @@ -136,14 +136,14 @@ 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); + assert(!err); client.query( { name: "boom", text: "select NOW()" }, assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows[0].now.getYear(), new Date().getYear()); release(); pool.end(done) @@ -157,7 +157,7 @@ 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); + assert(!err); var config = { text: "select $1::text as val" }; @@ -165,7 +165,7 @@ suite.test("can provide callback and config and parameters", function(done) { config, ["hi"], assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows.length, 1); assert.equal(result.rows[0].val, "hi"); release() @@ -180,7 +180,7 @@ 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); + assert(!err); client.query( "CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)" ); @@ -191,7 +191,7 @@ suite.test("null and undefined are both inserted as NULL", function(done) { client.query( "SELECT * FROM my_nulls", assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows.length, 1); assert.isNull(result.rows[0].a); assert.isNull(result.rows[0].b); diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index e56b5e63..3185ad2c 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -5,8 +5,9 @@ var pg = helper.pg; var suite = new helper.Suite() const pool = new pg.Pool() + pool.connect(assert.calls(function(err, client, release) { - assert.isNull(err); + assert(!err); suite.test('nulls', function(done) { client.query('SELECT $1::text[] as array', [[null]], assert.success(function(result) { @@ -33,145 +34,144 @@ pool.connect(assert.calls(function(err, client, release) { }); suite.test('cleanup', () => release()) + + pool.connect(assert.calls(function (err, client, release) { + assert(!err); + client.query("CREATE TEMP TABLE why(names text[], numbors integer[])"); + client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); + suite.test('numbers', function (done) { + // client.connection.on('message', console.log) + client.query('SELECT numbors FROM why', assert.success(function (result) { + assert.lengthIs(result.rows[0].numbors, 3); + assert.equal(result.rows[0].numbors[0], 1); + assert.equal(result.rows[0].numbors[1], 2); + assert.equal(result.rows[0].numbors[2], 3); + done() + })) + }) + + suite.test('parses string arrays', function (done) { + client.query('SELECT names FROM why', assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0], 'aaron'); + assert.equal(names[1], 'brian'); + assert.equal(names[2], "a b c"); + done() + })) + }) + + suite.test('empty array', function (done) { + client.query("SELECT '{}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 0); + done() + })) + }) + + suite.test('element containing comma', function (done) { + client.query("SELECT '{\"joe,bob\",jim}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 2); + assert.equal(names[0], 'joe,bob'); + assert.equal(names[1], 'jim'); + done() + })) + }) + + suite.test('bracket in quotes', function (done) { + client.query("SELECT '{\"{\",\"}\"}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 2); + assert.equal(names[0], '{'); + assert.equal(names[1], '}'); + done() + })) + }) + + suite.test('null value', function (done) { + client.query("SELECT '{joe,null,bob,\"NULL\"}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 4); + assert.equal(names[0], 'joe'); + assert.equal(names[1], null); + assert.equal(names[2], 'bob'); + assert.equal(names[3], 'NULL'); + done() + })) + }) + + suite.test('element containing quote char', function (done) { + client.query("SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0], 'joe\''); + assert.equal(names[1], 'jim'); + assert.equal(names[2], 'bob"'); + done() + })) + }) + + suite.test('nested array', function (done) { + client.query("SELECT '{{1,joe},{2,bob}}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 2); + + assert.lengthIs(names[0], 2); + assert.equal(names[0][0], '1'); + assert.equal(names[0][1], 'joe'); + + assert.lengthIs(names[1], 2); + assert.equal(names[1][0], '2'); + assert.equal(names[1][1], 'bob'); + done() + })) + }) + + suite.test('integer array', function (done) { + client.query("SELECT '{1,2,3}'::integer[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0], 1); + assert.equal(names[1], 2); + assert.equal(names[2], 3); + done() + })) + }) + + suite.test('integer nested array', function (done) { + client.query("SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0][0], 1); + assert.equal(names[0][1], 100); + + assert.equal(names[1][0], 2); + assert.equal(names[1][1], 100); + + assert.equal(names[2][0], 3); + assert.equal(names[2][1], 100); + done() + })) + }) + + suite.test('JS array parameter', function (done) { + client.query("SELECT $1::integer[] as names", [[[1, 100], [2, 100], [3, 100]]], assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0][0], 1); + assert.equal(names[0][1], 100); + + assert.equal(names[1][0], 2); + assert.equal(names[1][1], 100); + + assert.equal(names[2][0], 3); + assert.equal(names[2][1], 100); + release(); + pool.end(() => { + done() + }) + })) + }) + })) })); - -pool.connect(assert.calls(function (err, client, release) { - assert.isNull(err); - client.query("CREATE TEMP TABLE why(names text[], numbors integer[])"); - client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); - suite.test('numbers', function (done) { - // client.connection.on('message', console.log) - client.query('SELECT numbors FROM why', assert.success(function (result) { - assert.lengthIs(result.rows[0].numbors, 3); - assert.equal(result.rows[0].numbors[0], 1); - assert.equal(result.rows[0].numbors[1], 2); - assert.equal(result.rows[0].numbors[2], 3); - done() - })) - }) - - suite.test('parses string arrays', function (done) { - client.query('SELECT names FROM why', assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 'aaron'); - assert.equal(names[1], 'brian'); - assert.equal(names[2], "a b c"); - done() - })) - }) - - suite.test('empty array', function (done) { - client.query("SELECT '{}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 0); - done() - })) - }) - - suite.test('element containing comma', function (done) { - client.query("SELECT '{\"joe,bob\",jim}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - assert.equal(names[0], 'joe,bob'); - assert.equal(names[1], 'jim'); - done() - })) - }) - - suite.test('bracket in quotes', function (done) { - client.query("SELECT '{\"{\",\"}\"}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - assert.equal(names[0], '{'); - assert.equal(names[1], '}'); - done() - })) - }) - - suite.test('null value', function (done) { - client.query("SELECT '{joe,null,bob,\"NULL\"}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 4); - assert.equal(names[0], 'joe'); - assert.equal(names[1], null); - assert.equal(names[2], 'bob'); - assert.equal(names[3], 'NULL'); - done() - })) - }) - - suite.test('element containing quote char', function (done) { - client.query("SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 'joe\''); - assert.equal(names[1], 'jim'); - assert.equal(names[2], 'bob"'); - done() - })) - }) - - suite.test('nested array', function (done) { - client.query("SELECT '{{1,joe},{2,bob}}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - - assert.lengthIs(names[0], 2); - assert.equal(names[0][0], '1'); - assert.equal(names[0][1], 'joe'); - - assert.lengthIs(names[1], 2); - assert.equal(names[1][0], '2'); - assert.equal(names[1][1], 'bob'); - done() - })) - }) - - suite.test('integer array', function (done) { - client.query("SELECT '{1,2,3}'::integer[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 1); - assert.equal(names[1], 2); - assert.equal(names[2], 3); - done() - })) - }) - - suite.test('integer nested array', function (done) { - client.query("SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0][0], 1); - assert.equal(names[0][1], 100); - - assert.equal(names[1][0], 2); - assert.equal(names[1][1], 100); - - assert.equal(names[2][0], 3); - assert.equal(names[2][1], 100); - done() - })) - }) - - suite.test('JS array parameter', function (done) { - client.query("SELECT $1::integer[] as names", [[[1, 100], [2, 100], [3, 100]]], assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0][0], 1); - assert.equal(names[0][1], 100); - - assert.equal(names[1][0], 2); - assert.equal(names[1][1], 100); - - assert.equal(names[2][0], 3); - assert.equal(names[2][1], 100); - release(); - pool.end(done) - })) - }) - -})) - - diff --git a/test/integration/client/empty-query-tests.js b/test/integration/client/empty-query-tests.js index 443c37d6..d02c142d 100644 --- a/test/integration/client/empty-query-tests.js +++ b/test/integration/client/empty-query-tests.js @@ -13,7 +13,7 @@ suite.test("empty query message handling", function(done) { suite.test('callback supported', function(done) { const client = helper.client(); client.query("", function(err, result) { - assert.isNull(err); + assert(!err); assert.empty(result.rows); client.end(done) }) diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index e18cc900..a798a659 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -17,6 +17,26 @@ var createErorrClient = function() { const suite = new helper.Suite('error handling') +suite.test('re-using connections results in error callback', (done) => { + const client = new Client() + client.connect(() => { + client.connect(err => { + assert(err instanceof Error) + client.end(done) + }) + }) +}) + +suite.test('re-using connections results in promise rejection', (done) => { + const client = new Client() + client.connect().then(() => { + client.connect().catch(err => { + assert(err instanceof Error) + client.end().then(done) + }) + }) +}) + suite.test('query receives error on client shutdown', function(done) { var client = new Client(); client.connect(assert.success(function() { diff --git a/test/integration/client/result-metadata-tests.js b/test/integration/client/result-metadata-tests.js index bb7aeff7..5b683a3a 100644 --- a/test/integration/client/result-metadata-tests.js +++ b/test/integration/client/result-metadata-tests.js @@ -5,21 +5,21 @@ var pg = helper.pg; const pool = new pg.Pool() new helper.Suite().test('should return insert metadata', function() { pool.connect(assert.calls(function(err, client, done) { - assert.isNull(err); + assert(!err); helper.versionGTE(client, '9.0.0', assert.success(function(hasRowCount) { client.query("CREATE TEMP TABLE zugzug(name varchar(10))", assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.oid, null); assert.equal(result.command, 'CREATE'); var q = client.query("INSERT INTO zugzug(name) VALUES('more work?')", assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.command, "INSERT"); assert.equal(result.rowCount, 1); client.query('SELECT * FROM zugzug', assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); if(hasRowCount) assert.equal(result.rowCount, 1); assert.equal(result.command, 'SELECT'); done(); diff --git a/test/integration/client/timezone-tests.js b/test/integration/client/timezone-tests.js index c1baa798..1f0e0698 100644 --- a/test/integration/client/timezone-tests.js +++ b/test/integration/client/timezone-tests.js @@ -11,11 +11,11 @@ const pool = new helper.pg.Pool() const suite = new helper.Suite() pool.connect(function (err, client, done) { - assert.isNull(err); + assert(!err); suite.test('timestamp without time zone', function (cb) { client.query("SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS \"val\"", [date], function (err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows[0].val.getTime(), date.getTime()); cb() }) @@ -23,7 +23,7 @@ pool.connect(function (err, client, done) { suite.test('timestamp with time zone', function (cb) { client.query("SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS \"val\"", [date], function (err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows[0].val.getTime(), date.getTime()); done(); diff --git a/test/integration/client/transaction-tests.js b/test/integration/client/transaction-tests.js index c9af7eab..4668a427 100644 --- a/test/integration/client/transaction-tests.js +++ b/test/integration/client/transaction-tests.js @@ -15,7 +15,7 @@ client.connect(assert.success(function () { suite.test('name should not exist in the database', function (done) { client.query(getZed, assert.calls(function (err, result) { - assert.isNull(err); + assert(!err); assert.empty(result.rows); done() })) @@ -23,14 +23,14 @@ client.connect(assert.success(function () { suite.test('can insert name', (done) => { client.query("INSERT INTO person(name, age) VALUES($1, $2)", ['Zed', 270], assert.calls(function (err, result) { - assert.isNull(err) + assert(!err) done() })); }) suite.test('name should exist in the database', function (done) { client.query(getZed, assert.calls(function (err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows[0].name, 'Zed'); done() })) @@ -42,7 +42,7 @@ client.connect(assert.success(function () { suite.test('name should not exist in the database', function (done) { client.query(getZed, assert.calls(function (err, result) { - assert.isNull(err); + assert(!err); assert.empty(result.rows); client.end(done) })) diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index 080dd9ad..2aaffbc4 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -8,14 +8,14 @@ var testForTypeCoercion = function (type) { const pool = new pg.Pool() suite.test(`test type coercion ${type.name}`, (cb) => { pool.connect(function (err, client, done) { - assert.isNull(err); + assert(!err); client.query("create temp table test_type(col " + type.name + ")", assert.calls(function (err, result) { - assert.isNull(err); + assert(!err); type.values.forEach(function (val) { var insertQuery = client.query('insert into test_type(col) VALUES($1)', [val], assert.calls(function (err, result) { - assert.isNull(err); + assert(!err); })); var query = client.query(new pg.Query({ @@ -152,11 +152,11 @@ suite.test('selecting nulls', cb => { pool.connect(assert.calls(function (err, client, done) { assert.ifError(err); client.query('select null as res;', assert.calls(function (err, res) { - assert.isNull(err); + assert(!err); assert.strictEqual(res.rows[0].res, null) })) client.query('select 7 <> $1 as res;', [null], function (err, res) { - assert.isNull(err); + assert(!err); assert.strictEqual(res.rows[0].res, null); done(); pool.end(cb) diff --git a/test/integration/connection-pool/idle-timeout-tests.js b/test/integration/connection-pool/idle-timeout-tests.js index 0531ae80..63956b64 100644 --- a/test/integration/connection-pool/idle-timeout-tests.js +++ b/test/integration/connection-pool/idle-timeout-tests.js @@ -6,7 +6,7 @@ new helper.Suite().test('idle timeout', function () { const config = Object.assign({}, helper.config, { idleTimeoutMillis: 50 }) const pool = new helper.pg.Pool(config) pool.connect(assert.calls(function (err, client, done) { - assert.isNull(err); + assert(!err); client.query('SELECT NOW()'); done(); })); diff --git a/test/integration/connection-pool/test-helper.js b/test/integration/connection-pool/test-helper.js index 85ecd899..2fde015e 100644 --- a/test/integration/connection-pool/test-helper.js +++ b/test/integration/connection-pool/test-helper.js @@ -13,7 +13,7 @@ helper.testPoolSize = function (max) { for (var i = 0; i < max; i++) { pool.connect(function (err, client, done) { - assert.isNull(err); + assert(!err); client.query("SELECT * FROM NOW()") client.query("select generate_series(0, 25)", function (err, result) { assert.equal(result.rows.length, 26) diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index 164f94e9..f56834e2 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -7,7 +7,7 @@ var suite = new helper.Suite() suite.test('parsing array decimal results', function (done) { const pool = new pg.Pool() pool.connect(assert.calls(function (err, client, release) { - assert.isNull(err); + assert(!err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])"); client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log); client.query('SELECT decimals FROM why', assert.success(function (result) { diff --git a/test/native/callback-api-tests.js b/test/native/callback-api-tests.js index fa57dbde..a0a77795 100644 --- a/test/native/callback-api-tests.js +++ b/test/native/callback-api-tests.js @@ -8,11 +8,11 @@ suite.test('fires callback with results', function(done) { var client = new Client(helper.config); client.connect(); client.query('SELECT 1 as num', assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows[0].num, 1); assert.strictEqual(result.rowCount, 1); client.query('SELECT * FROM person WHERE name = $1', ['Brian'], assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows[0].name, 'Brian'); client.end(done); })) diff --git a/test/unit/connection-parameters/creation-tests.js b/test/unit/connection-parameters/creation-tests.js index 36e17a93..f0268a13 100644 --- a/test/unit/connection-parameters/creation-tests.js +++ b/test/unit/connection-parameters/creation-tests.js @@ -122,7 +122,7 @@ test('libpq connection string building', function() { } var subject = new ConnectionParameters(config); subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert.isNull(err); + assert(!err); var parts = constring.split(" "); checkForPart(parts, "user='brian'"); checkForPart(parts, "password='xyz'"); @@ -141,7 +141,7 @@ test('libpq connection string building', function() { }; var subject = new ConnectionParameters(config); subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert.isNull(err); + assert(!err); var parts = constring.split(" "); checkForPart(parts, "user='brian'"); checkForPart(parts, "hostaddr='127.0.0.1'"); @@ -171,7 +171,7 @@ test('libpq connection string building', function() { }; var subject = new ConnectionParameters(config); subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert.isNull(err); + assert(!err); var parts = constring.split(" "); checkForPart(parts, "user='brian'"); checkForPart(parts, "host='/tmp/'"); @@ -187,7 +187,7 @@ test('libpq connection string building', function() { }; var subject = new ConnectionParameters(config); subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert.isNull(err); + assert(!err); var parts = constring.split(" "); checkForPart(parts, "user='not\\\\brian'"); checkForPart(parts, "password='bad\\'chars'"); @@ -200,7 +200,7 @@ test('libpq connection string building', function() { } var subject = new ConnectionParameters(config); subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert.isNull(err); + assert(!err); var parts = constring.split(" "); checkForPart(parts, "client_encoding='utf-8'"); })); From f7de9ce820715146644c076f31959b68a323cf30 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 15 Jul 2017 11:14:15 -0500 Subject: [PATCH 51/58] Non-array query values cause query to end with an error. This is a small change and is _kinda_ backwards compatible since the old behavior was to throw an error, but if someone was relying on anything with `.map` working as values it would break them, so it's in a major semver bump. --- lib/native/query.js | 7 +++- lib/query.js | 6 +++ .../client/error-handling-tests.js | 13 ++++++ test/native/error-tests.js | 41 ------------------- 4 files changed, 24 insertions(+), 43 deletions(-) delete mode 100644 test/native/error-tests.js diff --git a/lib/native/query.js b/lib/native/query.js index f9dacfa1..a35e5304 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -146,8 +146,11 @@ NativeQuery.prototype.submit = function(client) { client.namedQueries[self.name] = true; return self.native.execute(self.name, values, after); }); - } - else if(this.values) { + } else if(this.values) { + if (!Array.isArray(this.values)) { + const err = new Error('Query values must be an array') + return after(err) + } var vals = this.values.map(utils.prepareValue); client.native.query(this.text, vals, after); } else { diff --git a/lib/query.js b/lib/query.js index a8e76547..26b930fb 100644 --- a/lib/query.js +++ b/lib/query.js @@ -133,6 +133,12 @@ Query.prototype.submit = function(connection) { connection.emit('readyForQuery') return } + if (this.values && !Array.isArray(this.values)) { + const err = new Error('Query values must be an array') + connection.emit('error', err) + connection.emit('readyForQuery') + return + } if(this.requiresPreparation()) { this.prepare(connection); } else { diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index a798a659..e4d77903 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -17,6 +17,19 @@ var createErorrClient = function() { const suite = new helper.Suite('error handling') +suite.test('sending non-array argument as values causes an error callback', (done) => { + const client = new Client() + client.connect(() => { + client.query('select $1::text as name', 'foo', (err) => { + assert(err instanceof Error) + client.query('SELECT $1::text as name', ['foo'], (err, res) => { + assert.equal(res.rows[0].name, 'foo') + client.end(done) + }) + }) + }) +}) + suite.test('re-using connections results in error callback', (done) => { const client = new Client() client.connect(() => { diff --git a/test/native/error-tests.js b/test/native/error-tests.js deleted file mode 100644 index a6f87644..00000000 --- a/test/native/error-tests.js +++ /dev/null @@ -1,41 +0,0 @@ -"use strict"; -var helper = require(__dirname + "/../test-helper"); -var Client = require(__dirname + "/../../lib/native"); - - -var connect = function(callback) { - var client = new Client(helper.config); - client.connect(); - assert.emits(client, 'connect', function() { - callback(client); - }) -} - -test('parameterized query with non-array for second value', function() { - test('inline', function() { - connect(function(client) { - client.end(); - assert.emits(client, 'end', function() { - assert.throws(function() { - client.query("SELECT *", "LKSDJF") - }); - }); - }); - }); - - test('config', function() { - connect(function(client) { - client.end(); - assert.emits(client, 'end', function() { - assert.throws(function() { - client.query({ - text: "SELECT *", - values: "ALSDKFJ" - }); - }); - }); - }); - }); -}); - - From 8798e50ad3493fc1e688d41f2c7985be7ff24592 Mon Sep 17 00:00:00 2001 From: Brian C Date: Sat, 15 Jul 2017 12:05:58 -0500 Subject: [PATCH 52/58] Re-enable eslint with standard format (#1367) * Work on converting lib to standard * Finish updating lib * Finish linting lib * Format test files * Add .eslintrc with standard format * Supply full path to eslint bin * Move lint command to package.json * Add eslint as dev dependency --- .eslintrc | 6 + .jshintrc | 5 - Makefile | 9 +- lib/client.js | 416 ++++---- lib/connection-parameters.js | 171 ++-- lib/connection.js | 936 +++++++++--------- lib/defaults.js | 54 +- lib/index.js | 73 +- lib/native/client.js | 288 +++--- lib/native/index.js | 2 +- lib/native/query.js | 211 ++-- lib/native/result.js | 36 +- lib/query.js | 268 ++--- lib/result.js | 166 ++-- lib/type-overrides.js | 46 +- lib/utils.js | 178 ++-- package.json | 10 +- script/create-test-tables.js | 78 +- script/dump-db-types.js | 27 +- script/list-db-types.js | 12 +- test/buffer-list.js | 106 +- test/cli.js | 38 +- test/integration/client/api-tests.js | 290 +++--- test/integration/client/appname-tests.js | 146 ++- test/integration/client/array-tests.js | 172 ++-- .../client/big-simple-query-tests.js | 97 +- .../integration/client/configuration-tests.js | 33 +- test/integration/client/custom-types-tests.js | 12 +- test/integration/client/empty-query-tests.js | 29 +- .../client/error-handling-tests.js | 170 ++-- test/integration/client/huge-numeric-tests.js | 30 +- .../client/json-type-parsing-tests.js | 40 +- .../client/network-partition-tests.js | 10 +- test/integration/client/no-data-tests.js | 30 +- .../integration/client/no-row-result-tests.js | 38 +- test/integration/client/notice-tests.js | 46 +- test/integration/client/parse-int-8-tests.js | 50 +- .../client/prepared-statement-tests.js | 138 ++- test/integration/client/promise-api-tests.js | 7 +- .../client/query-as-promise-tests.js | 8 +- .../client/query-column-names-tests.js | 20 +- ...error-handling-prepared-statement-tests.js | 125 ++- .../client/quick-disconnect-tests.js | 12 +- .../client/result-metadata-tests.js | 54 +- .../client/results-as-array-tests.js | 46 +- .../row-description-on-results-tests.js | 66 +- test/integration/client/simple-query-tests.js | 140 ++- test/integration/client/ssl-tests.js | 26 +- test/integration/client/test-helper.js | 6 +- test/integration/client/timezone-tests.js | 36 +- test/integration/client/transaction-tests.js | 47 +- .../integration/client/type-coercion-tests.js | 131 ++- .../client/type-parser-override-tests.js | 58 +- .../connection-pool-size-tests.js | 12 +- .../connection-pool/error-tests.js | 48 +- .../connection-pool/idle-timeout-tests.js | 15 +- .../connection-pool/native-instance-tests.js | 6 +- .../connection-pool/test-helper.js | 19 +- .../connection-pool/yield-support-tests.js | 4 +- .../connection/bound-command-tests.js | 97 +- test/integration/connection/copy-tests.js | 48 +- .../connection/notification-tests.js | 30 +- test/integration/connection/query-tests.js | 48 +- test/integration/connection/test-helper.js | 74 +- test/integration/domain-tests.js | 2 +- test/integration/gh-issues/130-tests.js | 38 +- test/integration/gh-issues/131-tests.js | 20 +- test/integration/gh-issues/199-tests.js | 28 +- test/integration/gh-issues/507-tests.js | 12 +- test/integration/gh-issues/600-tests.js | 91 +- test/integration/gh-issues/675-tests.js | 42 +- test/integration/gh-issues/787-tests.js | 16 +- test/integration/gh-issues/882-tests.js | 18 +- test/integration/test-helper.js | 45 +- test/native/callback-api-tests.js | 52 +- test/native/evented-api-tests.js | 122 +-- test/native/missing-native.js | 10 +- test/native/native-vs-js-error-tests.js | 24 +- test/native/stress-tests.js | 80 +- test/suite.js | 16 +- test/test-buffers.js | 164 +-- test/test-helper.js | 300 +++--- test/unit/client/cleartext-password-tests.js | 30 +- test/unit/client/configuration-tests.js | 234 +++-- test/unit/client/early-disconnect-tests.js | 28 +- test/unit/client/escape-tests.js | 74 +- test/unit/client/md5-password-tests.js | 42 +- test/unit/client/notification-tests.js | 15 +- test/unit/client/prepared-statement-tests.js | 142 +-- test/unit/client/query-queue-tests.js | 90 +- test/unit/client/result-metadata-tests.js | 43 +- test/unit/client/simple-query-tests.js | 204 ++-- ...tream-and-query-error-interaction-tests.js | 52 +- test/unit/client/test-helper.js | 34 +- .../unit/client/throw-in-type-parser-tests.js | 101 +- .../connection-parameters/creation-tests.js | 341 ++++--- .../environment-variable-tests.js | 178 ++-- test/unit/connection/error-tests.js | 58 +- test/unit/connection/inbound-parser-tests.js | 539 +++++----- .../unit/connection/outbound-sending-tests.js | 231 +++-- test/unit/connection/startup-tests.js | 146 ++- test/unit/connection/test-helper.js | 4 +- test/unit/test-helper.js | 49 +- test/unit/utils-tests.js | 303 +++--- 104 files changed, 4788 insertions(+), 4880 deletions(-) create mode 100644 .eslintrc delete mode 100644 .jshintrc diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..6f96eccc --- /dev/null +++ b/.eslintrc @@ -0,0 +1,6 @@ +{ + "extends": "standard", + "rules": { + "no-new-func": "off" + } +} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index c6c11efc..00000000 --- a/.jshintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "trailing": true, - "indent": 2, - "evil": true -} diff --git a/Makefile b/Makefile index ad8ed3de..f710d846 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ params := $(connectionString) node-command := xargs -n 1 -I file node file $(params) .PHONY : test test-connection test-integration bench test-native \ - jshint publish test-missing-native update-npm + lint publish test-missing-native update-npm all: npm install @@ -17,7 +17,7 @@ help: test: test-unit -test-all: jshint test-missing-native test-unit test-integration test-native +test-all: lint test-missing-native test-unit test-integration test-native update-npm: @@ -60,5 +60,6 @@ test-binary: test-connection test-pool: @find test/integration/connection-pool -name "*.js" | $(node-command) binary -jshint: - @echo "***Starting jshint***" +lint: + @echo "***Starting lint***" + eslint lib diff --git a/lib/client.js b/lib/client.js index 25a9d66c..d0052604 100644 --- a/lib/client.js +++ b/lib/client.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,54 +7,54 @@ * README.md file in the root directory of this source tree. */ -var EventEmitter = require('events').EventEmitter; -var util = require('util'); +var EventEmitter = require('events').EventEmitter +var util = require('util') var utils = require('./utils') -var pgPass = require('pgpass'); -var TypeOverrides = require('./type-overrides'); +var pgPass = require('pgpass') +var TypeOverrides = require('./type-overrides') -var ConnectionParameters = require('./connection-parameters'); -var Query = require('./query'); -var defaults = require('./defaults'); -var Connection = require('./connection'); +var ConnectionParameters = require('./connection-parameters') +var Query = require('./query') +var defaults = require('./defaults') +var Connection = require('./connection') -var Client = function(config) { - EventEmitter.call(this); +var Client = function (config) { + EventEmitter.call(this) - this.connectionParameters = new ConnectionParameters(config); - this.user = this.connectionParameters.user; - this.database = this.connectionParameters.database; - this.port = this.connectionParameters.port; - this.host = this.connectionParameters.host; - this.password = this.connectionParameters.password; - this.replication = this.connectionParameters.replication; + this.connectionParameters = new ConnectionParameters(config) + this.user = this.connectionParameters.user + this.database = this.connectionParameters.database + this.port = this.connectionParameters.port + this.host = this.connectionParameters.host + this.password = this.connectionParameters.password + this.replication = this.connectionParameters.replication - var c = config || {}; + var c = config || {} - this._types = new TypeOverrides(c.types); - this._ending = false; - this._connecting = false; - this._connected = false; - this._connectionError = false; + this._types = new TypeOverrides(c.types) + this._ending = false + this._connecting = false + this._connected = false + this._connectionError = false this.connection = c.connection || new Connection({ stream: c.stream, ssl: this.connectionParameters.ssl, keepAlive: c.keepAlive || false - }); - this.queryQueue = []; - this.binary = c.binary || defaults.binary; - this.encoding = 'utf8'; - this.processID = null; - this.secretKey = null; - this.ssl = this.connectionParameters.ssl || false; -}; + }) + this.queryQueue = [] + this.binary = c.binary || defaults.binary + this.encoding = 'utf8' + this.processID = null + this.secretKey = null + this.ssl = this.connectionParameters.ssl || false +} -util.inherits(Client, EventEmitter); +util.inherits(Client, EventEmitter) -Client.prototype.connect = function(callback) { - var self = this; - var con = this.connection; +Client.prototype.connect = function (callback) { + var self = this + var con = this.connection if (this._connecting || this._connected) { const err = new Error('Client has already been connected. You cannot reuse a client.') if (callback) { @@ -63,64 +63,63 @@ Client.prototype.connect = function(callback) { } return Promise.reject(err) } - this._connecting = true; + this._connecting = true - if(this.host && this.host.indexOf('/') === 0) { - con.connect(this.host + '/.s.PGSQL.' + this.port); + if (this.host && this.host.indexOf('/') === 0) { + con.connect(this.host + '/.s.PGSQL.' + this.port) } else { - con.connect(this.port, this.host); + con.connect(this.port, this.host) } - - //once connection is established send startup message - con.on('connect', function() { - if(self.ssl) { - con.requestSsl(); + // once connection is established send startup message + con.on('connect', function () { + if (self.ssl) { + con.requestSsl() } else { - con.startup(self.getStartupConf()); + con.startup(self.getStartupConf()) } - }); + }) - con.on('sslconnect', function() { - con.startup(self.getStartupConf()); - }); + con.on('sslconnect', function () { + con.startup(self.getStartupConf()) + }) - function checkPgPass(cb) { - return function(msg) { - if (null !== self.password) { - cb(msg); + function checkPgPass (cb) { + return function (msg) { + if (self.password !== null) { + cb(msg) } else { - pgPass(self.connectionParameters, function(pass){ + pgPass(self.connectionParameters, function (pass) { if (undefined !== pass) { - self.connectionParameters.password = self.password = pass; + self.connectionParameters.password = self.password = pass } - cb(msg); - }); + cb(msg) + }) } - }; + } } - //password request handling - con.on('authenticationCleartextPassword', checkPgPass(function() { - con.password(self.password); - })); + // password request handling + con.on('authenticationCleartextPassword', checkPgPass(function () { + con.password(self.password) + })) - //password request handling - con.on('authenticationMD5Password', checkPgPass(function(msg) { - var inner = utils.md5(self.password + self.user); - var outer = utils.md5(Buffer.concat([Buffer.from(inner), msg.salt])); - var md5password = "md5" + outer; - con.password(md5password); - })); + // password request handling + con.on('authenticationMD5Password', checkPgPass(function (msg) { + var inner = utils.md5(self.password + self.user) + var outer = utils.md5(Buffer.concat([Buffer.from(inner), msg.salt])) + var md5password = 'md5' + outer + con.password(md5password) + })) - con.once('backendKeyData', function(msg) { - self.processID = msg.processID; - self.secretKey = msg.secretKey; - }); + con.once('backendKeyData', function (msg) { + self.processID = msg.processID + self.secretKey = msg.secretKey + }) const connectingErrorHandler = (err) => { if (this._connectionError) { - return; + return } this._connectionError = true if (callback) { @@ -130,50 +129,50 @@ Client.prototype.connect = function(callback) { } const connectedErrorHandler = (err) => { - if(this.activeQuery) { - var activeQuery = self.activeQuery; - this.activeQuery = null; - return activeQuery.handleError(err, con); + if (this.activeQuery) { + var activeQuery = self.activeQuery + this.activeQuery = null + return activeQuery.handleError(err, con) } this.emit('error', err) } con.on('error', connectingErrorHandler) - //hook up query handling events to connection - //after the connection initially becomes ready for queries - con.once('readyForQuery', function() { - self._connecting = false; - self._connected = true; - self._attachListeners(con); - con.removeListener('error', connectingErrorHandler); + // hook up query handling events to connection + // after the connection initially becomes ready for queries + con.once('readyForQuery', function () { + self._connecting = false + self._connected = true + self._attachListeners(con) + con.removeListener('error', connectingErrorHandler) con.on('error', connectedErrorHandler) - //process possible callback argument to Client#connect + // process possible callback argument to Client#connect if (callback) { - callback(null, self); - //remove callback for proper error handling - //after the connect event - callback = null; + callback(null, self) + // remove callback for proper error handling + // after the connect event + callback = null } - self.emit('connect'); - }); + self.emit('connect') + }) - con.on('readyForQuery', function() { - var activeQuery = self.activeQuery; - self.activeQuery = null; - self.readyForQuery = true; - if(activeQuery) { - activeQuery.handleReadyForQuery(con); + con.on('readyForQuery', function () { + var activeQuery = self.activeQuery + self.activeQuery = null + self.readyForQuery = true + if (activeQuery) { + activeQuery.handleReadyForQuery(con) } - self._pulseQueryQueue(); - }); + self._pulseQueryQueue() + }) con.once('end', () => { - if(this.activeQuery) { - var disconnectError = new Error('Connection terminated'); - this.activeQuery.handleError(disconnectError, con); - this.activeQuery = null; + if (this.activeQuery) { + var disconnectError = new Error('Connection terminated') + this.activeQuery.handleError(disconnectError, con) + this.activeQuery = null } if (!this._ending) { // if the connection is ended without us calling .end() @@ -188,16 +187,15 @@ Client.prototype.connect = function(callback) { this.emit('error', error) } } else if (!this._connectionError) { - this.emit('error', error); + this.emit('error', error) } } - this.emit('end'); - }); + this.emit('end') + }) - - con.on('notice', function(msg) { - self.emit('notice', msg); - }); + con.on('notice', function (msg) { + self.emit('notice', msg) + }) if (!callback) { return new global.Promise((resolve, reject) => { @@ -208,216 +206,214 @@ Client.prototype.connect = function(callback) { }) }) } -}; +} -Client.prototype._attachListeners = function(con) { +Client.prototype._attachListeners = function (con) { const self = this - //delegate rowDescription to active query + // delegate rowDescription to active query con.on('rowDescription', function (msg) { - self.activeQuery.handleRowDescription(msg); - }); + self.activeQuery.handleRowDescription(msg) + }) - //delegate dataRow to active query + // delegate dataRow to active query con.on('dataRow', function (msg) { - self.activeQuery.handleDataRow(msg); - }); + self.activeQuery.handleDataRow(msg) + }) - //delegate portalSuspended to active query + // delegate portalSuspended to active query con.on('portalSuspended', function (msg) { - self.activeQuery.handlePortalSuspended(con); - }); + self.activeQuery.handlePortalSuspended(con) + }) - //deletagate emptyQuery to active query + // deletagate emptyQuery to active query con.on('emptyQuery', function (msg) { - self.activeQuery.handleEmptyQuery(con); - }); + self.activeQuery.handleEmptyQuery(con) + }) - //delegate commandComplete to active query + // delegate commandComplete to active query con.on('commandComplete', function (msg) { - self.activeQuery.handleCommandComplete(msg, con); - }); + self.activeQuery.handleCommandComplete(msg, con) + }) - //if a prepared statement has a name and properly parses - //we track that its already been executed so we don't parse - //it again on the same client + // if a prepared statement has a name and properly parses + // we track that its already been executed so we don't parse + // it again on the same client con.on('parseComplete', function (msg) { if (self.activeQuery.name) { - con.parsedStatements[self.activeQuery.name] = true; + con.parsedStatements[self.activeQuery.name] = true } - }); + }) con.on('copyInResponse', function (msg) { - self.activeQuery.handleCopyInResponse(self.connection); - }); + self.activeQuery.handleCopyInResponse(self.connection) + }) con.on('copyData', function (msg) { - self.activeQuery.handleCopyData(msg, self.connection); - }); + self.activeQuery.handleCopyData(msg, self.connection) + }) con.on('notification', function (msg) { - self.emit('notification', msg); - }); + self.emit('notification', msg) + }) } Client.prototype.getStartupConf = function () { - var params = this.connectionParameters; + var params = this.connectionParameters var data = { user: params.user, database: params.database - }; + } - var appName = params.application_name || params.fallback_application_name; + var appName = params.application_name || params.fallback_application_name if (appName) { - data.application_name = appName; + data.application_name = appName } if (params.replication) { - data.replication = '' + params.replication; + data.replication = '' + params.replication } - return data; -}; + return data +} Client.prototype.cancel = function (client, query) { - if (client.activeQuery == query) { - var con = this.connection; + if (client.activeQuery === query) { + var con = this.connection if (this.host && this.host.indexOf('/') === 0) { - con.connect(this.host + '/.s.PGSQL.' + this.port); + con.connect(this.host + '/.s.PGSQL.' + this.port) } else { - con.connect(this.port, this.host); + con.connect(this.port, this.host) } - //once connection is established send cancel message + // once connection is established send cancel message con.on('connect', function () { - con.cancel(client.processID, client.secretKey); - }); - } else if (client.queryQueue.indexOf(query) != -1) { - client.queryQueue.splice(client.queryQueue.indexOf(query), 1); + con.cancel(client.processID, client.secretKey) + }) + } else if (client.queryQueue.indexOf(query) !== -1) { + client.queryQueue.splice(client.queryQueue.indexOf(query), 1) } -}; +} Client.prototype.setTypeParser = function (oid, format, parseFn) { - return this._types.setTypeParser(oid, format, parseFn); -}; + return this._types.setTypeParser(oid, format, parseFn) +} Client.prototype.getTypeParser = function (oid, format) { - return this._types.getTypeParser(oid, format); -}; + return this._types.getTypeParser(oid, format) +} // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c Client.prototype.escapeIdentifier = function (str) { - - var escaped = '"'; + var escaped = '"' for (var i = 0; i < str.length; i++) { - var c = str[i]; + var c = str[i] if (c === '"') { - escaped += c + c; + escaped += c + c } else { - escaped += c; + escaped += c } } - escaped += '"'; + escaped += '"' - return escaped; -}; + return escaped +} // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c Client.prototype.escapeLiteral = function (str) { - - var hasBackslash = false; - var escaped = '\''; + var hasBackslash = false + var escaped = '\'' for (var i = 0; i < str.length; i++) { - var c = str[i]; + var c = str[i] if (c === '\'') { - escaped += c + c; + escaped += c + c } else if (c === '\\') { - escaped += c + c; - hasBackslash = true; + escaped += c + c + hasBackslash = true } else { - escaped += c; + escaped += c } } - escaped += '\''; + escaped += '\'' if (hasBackslash === true) { - escaped = ' E' + escaped; + escaped = ' E' + escaped } - return escaped; -}; + return escaped +} Client.prototype._pulseQueryQueue = function () { if (this.readyForQuery === true) { - this.activeQuery = this.queryQueue.shift(); + this.activeQuery = this.queryQueue.shift() if (this.activeQuery) { - this.readyForQuery = false; - this.hasExecuted = true; - this.activeQuery.submit(this.connection); + this.readyForQuery = false + this.hasExecuted = true + this.activeQuery.submit(this.connection) } else if (this.hasExecuted) { - this.activeQuery = null; - this.emit('drain'); + this.activeQuery = null + this.emit('drain') } } -}; +} 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') { + // can take in strings, config object or query object + var query + var result + if (typeof config.submit === 'function') { result = query = config - if (typeof values == 'function') { + if (typeof values === 'function') { query.callback = query.callback || values } } else { query = new Query(config, values, callback) if (!query.callback) { - let resolve, reject; - result = new Promise((res, rej) => { - resolve = res - reject = rej + let resolveOut, rejectOut + result = new Promise((resolve, reject) => { + resolveOut = resolve + rejectOut = reject }) - query.callback = (err, res) => err ? reject(err) : resolve(res) + query.callback = (err, res) => err ? rejectOut(err) : resolveOut(res) } } if (this.binary && !query.binary) { - query.binary = true; + query.binary = true } if (query._result) { - query._result._getTypeParser = this._types.getTypeParser.bind(this._types); + query._result._getTypeParser = this._types.getTypeParser.bind(this._types) } - this.queryQueue.push(query); - this._pulseQueryQueue(); + this.queryQueue.push(query) + this._pulseQueryQueue() return result -}; +} Client.prototype.end = function (cb) { - this._ending = true; + this._ending = true if (this.activeQuery) { // if we have an active query we need to force a disconnect // on the socket - otherwise a hung query could block end forever this.connection.stream.destroy(new Error('Connection terminated by user')) - return; + return } if (cb) { - this.connection.end(); - this.connection.once('end', cb); + this.connection.end() + this.connection.once('end', cb) } else { return new global.Promise((resolve, reject) => { this.connection.end() this.connection.once('end', resolve) }) } -}; +} // expose a Query constructor -Client.Query = Query; +Client.Query = Query -module.exports = Client; +module.exports = Client diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index a675e585..f999d180 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,111 +7,110 @@ * README.md file in the root directory of this source tree. */ -var url = require('url'); -var dns = require('dns'); +var dns = require('dns') -var defaults = require('./defaults'); +var defaults = require('./defaults') -var val = function(key, config, envVar) { +var val = function (key, config, envVar) { if (envVar === undefined) { - envVar = process.env[ 'PG' + key.toUpperCase() ]; + envVar = process.env[ 'PG' + key.toUpperCase() ] } else if (envVar === false) { // do nothing ... use false } else { - envVar = process.env[ envVar ]; + envVar = process.env[ envVar ] } return config[key] || envVar || - defaults[key]; -}; + defaults[key] +} -//parses a connection string -var parse = require('pg-connection-string').parse; +// parses a connection string +var parse = require('pg-connection-string').parse -var useSsl = function() { - switch(process.env.PGSSLMODE) { - case "disable": - return false; - case "prefer": - case "require": - case "verify-ca": - case "verify-full": - return true; +var useSsl = function () { + switch (process.env.PGSSLMODE) { + case 'disable': + return false + case 'prefer': + case 'require': + case 'verify-ca': + case 'verify-full': + return true } - return defaults.ssl; -}; + return defaults.ssl +} -var ConnectionParameters = function(config) { - //if a string is passed, it is a raw connection string so we parse it into a config - config = typeof config == 'string' ? parse(config) : (config || {}); - //if the config has a connectionString defined, parse IT into the config we use - //this will override other default values with what is stored in connectionString - if(config.connectionString) { - config = parse(config.connectionString); +var ConnectionParameters = function (config) { + // if a string is passed, it is a raw connection string so we parse it into a config + config = typeof config === 'string' ? parse(config) : (config || {}) + // if the config has a connectionString defined, parse IT into the config we use + // this will override other default values with what is stored in connectionString + if (config.connectionString) { + config = parse(config.connectionString) } - this.user = val('user', config); - this.database = val('database', config); - this.port = parseInt(val('port', config), 10); - this.host = val('host', config); - this.password = val('password', config); - this.binary = val('binary', config); - this.ssl = typeof config.ssl === 'undefined' ? useSsl() : config.ssl; - this.client_encoding = val("client_encoding", config); - this.replication = val("replication", config); - //a domain socket begins with '/' - this.isDomainSocket = (!(this.host||'').indexOf('/')); + this.user = val('user', config) + this.database = val('database', config) + this.port = parseInt(val('port', config), 10) + this.host = val('host', config) + this.password = val('password', config) + this.binary = val('binary', config) + this.ssl = typeof config.ssl === 'undefined' ? useSsl() : config.ssl + this.client_encoding = val('client_encoding', config) + this.replication = val('replication', config) + // a domain socket begins with '/' + this.isDomainSocket = (!(this.host || '').indexOf('/')) - this.application_name = val('application_name', config, 'PGAPPNAME'); - this.fallback_application_name = val('fallback_application_name', config, false); -}; + this.application_name = val('application_name', config, 'PGAPPNAME') + this.fallback_application_name = val('fallback_application_name', config, false) +} // Convert arg to a string, surround in single quotes, and escape single quotes and backslashes -var quoteParamValue = function(value) { - return "'" + ('' + value).replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'"; -}; +var quoteParamValue = function (value) { + return "'" + ('' + value).replace(/\\/g, '\\\\').replace(/'/g, "\\'") + "'" +} -var add = function(params, config, paramName) { - var value = config[paramName]; - if(value) { - params.push(paramName + "=" + quoteParamValue(value)); +var add = function (params, config, paramName) { + var value = config[paramName] + if (value) { + params.push(paramName + '=' + quoteParamValue(value)) } -}; +} -ConnectionParameters.prototype.getLibpqConnectionString = function(cb) { - var params = []; - add(params, this, 'user'); - add(params, this, 'password'); - add(params, this, 'port'); - add(params, this, 'application_name'); - add(params, this, 'fallback_application_name'); +ConnectionParameters.prototype.getLibpqConnectionString = function (cb) { + var params = [] + add(params, this, 'user') + add(params, this, 'password') + add(params, this, 'port') + add(params, this, 'application_name') + add(params, this, 'fallback_application_name') - var ssl = typeof this.ssl === 'object' ? this.ssl : {sslmode: this.ssl}; - add(params, ssl, 'sslmode'); - add(params, ssl, 'sslca'); - add(params, ssl, 'sslkey'); - add(params, ssl, 'sslcert'); - - if(this.database) { - params.push("dbname=" + quoteParamValue(this.database)); - } - if(this.replication) { - params.push("replication=" + quoteParamValue(this.replication)); - } - if(this.host) { - params.push("host=" + quoteParamValue(this.host)); - } - if(this.isDomainSocket) { - return cb(null, params.join(' ')); - } - if(this.client_encoding) { - params.push("client_encoding=" + quoteParamValue(this.client_encoding)); - } - dns.lookup(this.host, function(err, address) { - if(err) return cb(err, null); - params.push("hostaddr=" + quoteParamValue(address)); - return cb(null, params.join(' ')); - }); -}; + var ssl = typeof this.ssl === 'object' ? this.ssl : {sslmode: this.ssl} + add(params, ssl, 'sslmode') + add(params, ssl, 'sslca') + add(params, ssl, 'sslkey') + add(params, ssl, 'sslcert') -module.exports = ConnectionParameters; + if (this.database) { + params.push('dbname=' + quoteParamValue(this.database)) + } + if (this.replication) { + params.push('replication=' + quoteParamValue(this.replication)) + } + if (this.host) { + params.push('host=' + quoteParamValue(this.host)) + } + if (this.isDomainSocket) { + return cb(null, params.join(' ')) + } + if (this.client_encoding) { + params.push('client_encoding=' + quoteParamValue(this.client_encoding)) + } + dns.lookup(this.host, function (err, address) { + if (err) return cb(err, null) + params.push('hostaddr=' + quoteParamValue(address)) + return cb(null, params.join(' ')) + }) +} + +module.exports = ConnectionParameters diff --git a/lib/connection.js b/lib/connection.js index 18aaf6f8..2f13803e 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,85 +7,84 @@ * README.md file in the root directory of this source tree. */ -var net = require('net'); -var EventEmitter = require('events').EventEmitter; -var util = require('util'); +var net = require('net') +var EventEmitter = require('events').EventEmitter +var util = require('util') -var Writer = require('buffer-writer'); -var Reader = require('packet-reader'); +var Writer = require('buffer-writer') +var Reader = require('packet-reader') -var TEXT_MODE = 0; -var BINARY_MODE = 1; -var Connection = function(config) { - EventEmitter.call(this); - config = config || {}; - this.stream = config.stream || new net.Stream(); - this._keepAlive = config.keepAlive; - this.lastBuffer = false; - this.lastOffset = 0; - this.buffer = null; - this.offset = null; - this.encoding = 'utf8'; - this.parsedStatements = {}; - this.writer = new Writer(); - this.ssl = config.ssl || false; - this._ending = false; - this._mode = TEXT_MODE; - this._emitMessage = false; +var TEXT_MODE = 0 +var BINARY_MODE = 1 +var Connection = function (config) { + EventEmitter.call(this) + config = config || {} + this.stream = config.stream || new net.Stream() + this._keepAlive = config.keepAlive + this.lastBuffer = false + this.lastOffset = 0 + this.buffer = null + this.offset = null + this.encoding = 'utf8' + this.parsedStatements = {} + this.writer = new Writer() + this.ssl = config.ssl || false + this._ending = false + this._mode = TEXT_MODE + this._emitMessage = false this._reader = new Reader({ headerSize: 1, lengthPadding: -4 - }); - var self = this; - this.on('newListener', function(eventName) { - if(eventName == 'message') { - self._emitMessage = true; + }) + var self = this + this.on('newListener', function (eventName) { + if (eventName === 'message') { + self._emitMessage = true } - }); -}; + }) +} -util.inherits(Connection, EventEmitter); +util.inherits(Connection, EventEmitter) -Connection.prototype.connect = function(port, host) { - - if(this.stream.readyState === 'closed') { - this.stream.connect(port, host); - } else if(this.stream.readyState == 'open') { - this.emit('connect'); +Connection.prototype.connect = function (port, host) { + if (this.stream.readyState === 'closed') { + this.stream.connect(port, host) + } else if (this.stream.readyState === 'open') { + this.emit('connect') } - var self = this; + var self = this - this.stream.on('connect', function() { + this.stream.on('connect', function () { if (self._keepAlive) { - self.stream.setKeepAlive(true); + self.stream.setKeepAlive(true) } - self.emit('connect'); - }); + self.emit('connect') + }) - 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; + 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); - }); + self.emit('error', error) + }) - this.stream.on('close', function() { - self.emit('end'); - }); + this.stream.on('close', function () { + self.emit('end') + }) - if(!this.ssl) { - return this.attachListeners(this.stream); + if (!this.ssl) { + return this.attachListeners(this.stream) } - this.stream.once('data', function(buffer) { - var responseCode = buffer.toString('utf8'); - if(responseCode != 'S') { - return self.emit('error', new Error('The server does not support SSL connections')); + this.stream.once('data', function (buffer) { + var responseCode = buffer.toString('utf8') + if (responseCode !== 'S') { + return self.emit('error', new Error('The server does not support SSL connections')) } - var tls = require('tls'); + var tls = require('tls') self.stream = tls.connect({ socket: self.stream, servername: host, @@ -96,562 +95,553 @@ Connection.prototype.connect = function(port, host) { passphrase: self.ssl.passphrase, cert: self.ssl.cert, NPNProtocols: self.ssl.NPNProtocols - }); - self.attachListeners(self.stream); - self.emit('sslconnect'); + }) + self.attachListeners(self.stream) + self.emit('sslconnect') - self.stream.on('error', function(error){ - self.emit('error', error); - }); - }); -}; + self.stream.on('error', function (error) { + self.emit('error', error) + }) + }) +} -Connection.prototype.attachListeners = function(stream) { - var self = this; - stream.on('data', function(buff) { - self._reader.addChunk(buff); - var packet = self._reader.read(); - while(packet) { - var msg = self.parseMessage(packet); - if(self._emitMessage) { - self.emit('message', msg); +Connection.prototype.attachListeners = function (stream) { + var self = this + stream.on('data', function (buff) { + self._reader.addChunk(buff) + var packet = self._reader.read() + while (packet) { + var msg = self.parseMessage(packet) + if (self._emitMessage) { + self.emit('message', msg) } - self.emit(msg.name, msg); - packet = self._reader.read(); + self.emit(msg.name, msg) + packet = self._reader.read() } - }); - stream.on('end', function() { - self.emit('end'); - }); -}; + }) + stream.on('end', function () { + self.emit('end') + }) +} -Connection.prototype.requestSsl = function() { +Connection.prototype.requestSsl = function () { var bodyBuffer = this.writer .addInt16(0x04D2) - .addInt16(0x162F).flush(); + .addInt16(0x162F).flush() - var length = bodyBuffer.length + 4; + var length = bodyBuffer.length + 4 var buffer = new Writer() .addInt32(length) .add(bodyBuffer) - .join(); - this.stream.write(buffer); -}; + .join() + this.stream.write(buffer) +} -Connection.prototype.startup = function(config) { +Connection.prototype.startup = function (config) { var writer = this.writer .addInt16(3) .addInt16(0) - ; - Object.keys(config).forEach(function(key){ - var val = config[key]; - writer.addCString(key).addCString(val); - }); + Object.keys(config).forEach(function (key) { + var val = config[key] + writer.addCString(key).addCString(val) + }) - writer.addCString('client_encoding').addCString("'utf-8'"); + writer.addCString('client_encoding').addCString("'utf-8'") - var bodyBuffer = writer.addCString('').flush(); - //this message is sent without a code + var bodyBuffer = writer.addCString('').flush() + // this message is sent without a code - var length = bodyBuffer.length + 4; + var length = bodyBuffer.length + 4 var buffer = new Writer() .addInt32(length) .add(bodyBuffer) - .join(); - this.stream.write(buffer); -}; + .join() + this.stream.write(buffer) +} -Connection.prototype.cancel = function(processID, secretKey) { +Connection.prototype.cancel = function (processID, secretKey) { var bodyBuffer = this.writer .addInt16(1234) .addInt16(5678) .addInt32(processID) .addInt32(secretKey) - .flush(); + .flush() - var length = bodyBuffer.length + 4; + var length = bodyBuffer.length + 4 var buffer = new Writer() .addInt32(length) .add(bodyBuffer) - .join(); - this.stream.write(buffer); -}; + .join() + this.stream.write(buffer) +} -Connection.prototype.password = function(password) { - //0x70 = 'p' - this._send(0x70, this.writer.addCString(password)); -}; +Connection.prototype.password = function (password) { + // 0x70 = 'p' + this._send(0x70, this.writer.addCString(password)) +} -Connection.prototype._send = function(code, more) { - if(!this.stream.writable) { - return false; +Connection.prototype._send = function (code, more) { + if (!this.stream.writable) { + return false } - if(more === true) { - this.writer.addHeader(code); + if (more === true) { + this.writer.addHeader(code) } else { - return this.stream.write(this.writer.flush(code)); + return this.stream.write(this.writer.flush(code)) } -}; +} -Connection.prototype.query = function(text) { - //0x51 = Q - this.stream.write(this.writer.addCString(text).flush(0x51)); -}; +Connection.prototype.query = function (text) { + // 0x51 = Q + this.stream.write(this.writer.addCString(text).flush(0x51)) +} -//send parse message -//"more" === true to buffer the message until flush() is called -Connection.prototype.parse = function(query, more) { - //expect something like this: +// send parse message +// "more" === true to buffer the message until flush() is called +Connection.prototype.parse = function (query, more) { + // expect something like this: // { name: 'queryName', // text: 'select * from blah', // types: ['int8', 'bool'] } - //normalize missing query names to allow for null - query.name = query.name || ''; + // normalize missing query names to allow for null + query.name = query.name || '' if (query.name.length > 63) { - console.error('Warning! Postgres only supports 63 characters for query names.'); - console.error('You supplied', query.name, '(', query.name.length, ')'); - console.error('This can cause conflicts and silent errors executing queries'); + console.error('Warning! Postgres only supports 63 characters for query names.') + console.error('You supplied', query.name, '(', query.name.length, ')') + console.error('This can cause conflicts and silent errors executing queries') } - //normalize null type array - query.types = query.types || []; - var len = query.types.length; + // normalize null type array + query.types = query.types || [] + var len = query.types.length var buffer = this.writer - .addCString(query.name) //name of query - .addCString(query.text) //actual query text - .addInt16(len); - for(var i = 0; i < len; i++) { - buffer.addInt32(query.types[i]); + .addCString(query.name) // name of query + .addCString(query.text) // actual query text + .addInt16(len) + for (var i = 0; i < len; i++) { + buffer.addInt32(query.types[i]) } - var code = 0x50; - this._send(code, more); -}; + var code = 0x50 + this._send(code, more) +} -//send bind message -//"more" === true to buffer the message until flush() is called -Connection.prototype.bind = function(config, more) { - //normalize config - config = config || {}; - config.portal = config.portal || ''; - config.statement = config.statement || ''; - config.binary = config.binary || false; - var values = config.values || []; - var len = values.length; - var useBinary = false; - for (var j = 0; j < len; j++) - useBinary |= values[j] instanceof Buffer; +// send bind message +// "more" === true to buffer the message until flush() is called +Connection.prototype.bind = function (config, more) { + // normalize config + config = config || {} + config.portal = config.portal || '' + config.statement = config.statement || '' + config.binary = config.binary || false + var values = config.values || [] + var len = values.length + var useBinary = false + for (var j = 0; j < len; j++) { useBinary |= values[j] instanceof Buffer } var buffer = this.writer .addCString(config.portal) - .addCString(config.statement); - if (!useBinary) - buffer.addInt16(0); - else { - buffer.addInt16(len); - for (j = 0; j < len; j++) - buffer.addInt16(values[j] instanceof Buffer); + .addCString(config.statement) + if (!useBinary) { buffer.addInt16(0) } else { + buffer.addInt16(len) + for (j = 0; j < len; j++) { buffer.addInt16(values[j] instanceof Buffer) } } - buffer.addInt16(len); - for(var i = 0; i < len; i++) { - var val = values[i]; - if(val === null || typeof val === "undefined") { - buffer.addInt32(-1); + buffer.addInt16(len) + for (var i = 0; i < len; i++) { + var val = values[i] + if (val === null || typeof val === 'undefined') { + buffer.addInt32(-1) } else if (val instanceof Buffer) { - buffer.addInt32(val.length); - buffer.add(val); + buffer.addInt32(val.length) + buffer.add(val) } else { - buffer.addInt32(Buffer.byteLength(val)); - buffer.addString(val); + buffer.addInt32(Buffer.byteLength(val)) + buffer.addString(val) } } - if(config.binary) { - buffer.addInt16(1); // format codes to use binary - buffer.addInt16(1); + if (config.binary) { + buffer.addInt16(1) // format codes to use binary + buffer.addInt16(1) + } else { + buffer.addInt16(0) // format codes to use text } - else { - buffer.addInt16(0); // format codes to use text - } - //0x42 = 'B' - this._send(0x42, more); -}; + // 0x42 = 'B' + this._send(0x42, more) +} -//send execute message -//"more" === true to buffer the message until flush() is called -Connection.prototype.execute = function(config, more) { - config = config || {}; - config.portal = config.portal || ''; - config.rows = config.rows || ''; +// send execute message +// "more" === true to buffer the message until flush() is called +Connection.prototype.execute = function (config, more) { + config = config || {} + config.portal = config.portal || '' + config.rows = config.rows || '' this.writer .addCString(config.portal) - .addInt32(config.rows); + .addInt32(config.rows) - //0x45 = 'E' - this._send(0x45, more); -}; + // 0x45 = 'E' + this._send(0x45, more) +} -var emptyBuffer = Buffer.alloc(0); +var emptyBuffer = Buffer.alloc(0) -Connection.prototype.flush = function() { - //0x48 = 'H' - this.writer.add(emptyBuffer); - this._send(0x48); -}; +Connection.prototype.flush = function () { + // 0x48 = 'H' + this.writer.add(emptyBuffer) + this._send(0x48) +} -Connection.prototype.sync = function() { - //clear out any pending data in the writer - this.writer.flush(0); +Connection.prototype.sync = function () { + // clear out any pending data in the writer + this.writer.flush(0) - this.writer.add(emptyBuffer); - this._ending = true; - this._send(0x53); -}; + this.writer.add(emptyBuffer) + this._ending = true + this._send(0x53) +} -const END_BUFFER = new Buffer([0x58, 0x00, 0x00, 0x00, 0x04]); -Connection.prototype.end = function() { - //0x58 = 'X' - this.writer.add(emptyBuffer); - this._ending = true; - return this.stream.write(END_BUFFER); -}; +const END_BUFFER = Buffer.from([0x58, 0x00, 0x00, 0x00, 0x04]) -Connection.prototype.close = function(msg, more) { - this.writer.addCString(msg.type + (msg.name || '')); - this._send(0x43, more); -}; +Connection.prototype.end = function () { + // 0x58 = 'X' + this.writer.add(emptyBuffer) + this._ending = true + return this.stream.write(END_BUFFER) +} -Connection.prototype.describe = function(msg, more) { - this.writer.addCString(msg.type + (msg.name || '')); - this._send(0x44, more); -}; +Connection.prototype.close = function (msg, more) { + this.writer.addCString(msg.type + (msg.name || '')) + this._send(0x43, more) +} + +Connection.prototype.describe = function (msg, more) { + this.writer.addCString(msg.type + (msg.name || '')) + this._send(0x44, more) +} Connection.prototype.sendCopyFromChunk = function (chunk) { - this.stream.write(this.writer.add(chunk).flush(0x64)); -}; + this.stream.write(this.writer.add(chunk).flush(0x64)) +} Connection.prototype.endCopyFrom = function () { - this.stream.write(this.writer.add(emptyBuffer).flush(0x63)); -}; + this.stream.write(this.writer.add(emptyBuffer).flush(0x63)) +} Connection.prototype.sendCopyFail = function (msg) { - //this.stream.write(this.writer.add(emptyBuffer).flush(0x66)); - this.writer.addCString(msg); - this._send(0x66); -}; + // this.stream.write(this.writer.add(emptyBuffer).flush(0x66)); + this.writer.addCString(msg) + this._send(0x66) +} -var Message = function(name, length) { - this.name = name; - this.length = length; -}; +var Message = function (name, length) { + this.name = name + this.length = length +} -Connection.prototype.parseMessage = function(buffer) { +Connection.prototype.parseMessage = function (buffer) { + this.offset = 0 + var length = buffer.length + 4 + switch (this._reader.header) { + case 0x52: // R + return this.parseR(buffer, length) - this.offset = 0; - var length = buffer.length + 4; - switch(this._reader.header) - { + case 0x53: // S + return this.parseS(buffer, length) - case 0x52: //R - return this.parseR(buffer, length); + case 0x4b: // K + return this.parseK(buffer, length) - case 0x53: //S - return this.parseS(buffer, length); + case 0x43: // C + return this.parseC(buffer, length) - case 0x4b: //K - return this.parseK(buffer, length); + case 0x5a: // Z + return this.parseZ(buffer, length) - case 0x43: //C - return this.parseC(buffer, length); + case 0x54: // T + return this.parseT(buffer, length) - case 0x5a: //Z - return this.parseZ(buffer, length); + case 0x44: // D + return this.parseD(buffer, length) - case 0x54: //T - return this.parseT(buffer, length); + case 0x45: // E + return this.parseE(buffer, length) - case 0x44: //D - return this.parseD(buffer, length); + case 0x4e: // N + return this.parseN(buffer, length) - case 0x45: //E - return this.parseE(buffer, length); + case 0x31: // 1 + return new Message('parseComplete', length) - case 0x4e: //N - return this.parseN(buffer, length); + case 0x32: // 2 + return new Message('bindComplete', length) - case 0x31: //1 - return new Message('parseComplete', length); + case 0x33: // 3 + return new Message('closeComplete', length) - case 0x32: //2 - return new Message('bindComplete', length); + case 0x41: // A + return this.parseA(buffer, length) - case 0x33: //3 - return new Message('closeComplete', length); + case 0x6e: // n + return new Message('noData', length) - case 0x41: //A - return this.parseA(buffer, length); + case 0x49: // I + return new Message('emptyQuery', length) - case 0x6e: //n - return new Message('noData', length); + case 0x73: // s + return new Message('portalSuspended', length) - case 0x49: //I - return new Message('emptyQuery', length); + case 0x47: // G + return this.parseG(buffer, length) - case 0x73: //s - return new Message('portalSuspended', length); + case 0x48: // H + return this.parseH(buffer, length) - case 0x47: //G - return this.parseG(buffer, length); + case 0x57: // W + return new Message('replicationStart', length) - case 0x48: //H - return this.parseH(buffer, length); + case 0x63: // c + return new Message('copyDone', length) - case 0x57: //W - return new Message('replicationStart', length); - - case 0x63: //c - return new Message('copyDone', length); - - case 0x64: //d - return this.parsed(buffer, length); + case 0x64: // d + return this.parsed(buffer, length) } -}; +} -Connection.prototype.parseR = function(buffer, length) { - var code = 0; - var msg = new Message('authenticationOk', length); - if(msg.length === 8) { - code = this.parseInt32(buffer); - if(code === 3) { - msg.name = 'authenticationCleartextPassword'; +Connection.prototype.parseR = function (buffer, length) { + var code = 0 + var msg = new Message('authenticationOk', length) + if (msg.length === 8) { + code = this.parseInt32(buffer) + if (code === 3) { + msg.name = 'authenticationCleartextPassword' } - return msg; + return msg } - if(msg.length === 12) { - code = this.parseInt32(buffer); - if(code === 5) { //md5 required - msg.name = 'authenticationMD5Password'; - msg.salt = Buffer.alloc(4); - buffer.copy(msg.salt, 0, this.offset, this.offset + 4); - this.offset += 4; - return msg; + if (msg.length === 12) { + code = this.parseInt32(buffer) + if (code === 5) { // md5 required + msg.name = 'authenticationMD5Password' + msg.salt = Buffer.alloc(4) + buffer.copy(msg.salt, 0, this.offset, this.offset + 4) + this.offset += 4 + return msg } } - throw new Error("Unknown authenticationOk message type" + util.inspect(msg)); -}; + throw new Error('Unknown authenticationOk message type' + util.inspect(msg)) +} -Connection.prototype.parseS = function(buffer, length) { - var msg = new Message('parameterStatus', length); - msg.parameterName = this.parseCString(buffer); - msg.parameterValue = this.parseCString(buffer); - return msg; -}; +Connection.prototype.parseS = function (buffer, length) { + var msg = new Message('parameterStatus', length) + msg.parameterName = this.parseCString(buffer) + msg.parameterValue = this.parseCString(buffer) + return msg +} -Connection.prototype.parseK = function(buffer, length) { - var msg = new Message('backendKeyData', length); - msg.processID = this.parseInt32(buffer); - msg.secretKey = this.parseInt32(buffer); - return msg; -}; +Connection.prototype.parseK = function (buffer, length) { + var msg = new Message('backendKeyData', length) + msg.processID = this.parseInt32(buffer) + msg.secretKey = this.parseInt32(buffer) + return msg +} -Connection.prototype.parseC = function(buffer, length) { - var msg = new Message('commandComplete', length); - msg.text = this.parseCString(buffer); - return msg; -}; +Connection.prototype.parseC = function (buffer, length) { + var msg = new Message('commandComplete', length) + msg.text = this.parseCString(buffer) + return msg +} -Connection.prototype.parseZ = function(buffer, length) { - var msg = new Message('readyForQuery', length); - msg.name = 'readyForQuery'; - msg.status = this.readString(buffer, 1); - return msg; -}; +Connection.prototype.parseZ = function (buffer, length) { + var msg = new Message('readyForQuery', length) + msg.name = 'readyForQuery' + msg.status = this.readString(buffer, 1) + return msg +} -var ROW_DESCRIPTION = 'rowDescription'; -Connection.prototype.parseT = function(buffer, length) { - var msg = new Message(ROW_DESCRIPTION, length); - msg.fieldCount = this.parseInt16(buffer); - var fields = []; - for(var i = 0; i < msg.fieldCount; i++){ - fields.push(this.parseField(buffer)); +var ROW_DESCRIPTION = 'rowDescription' +Connection.prototype.parseT = function (buffer, length) { + var msg = new Message(ROW_DESCRIPTION, length) + msg.fieldCount = this.parseInt16(buffer) + var fields = [] + for (var i = 0; i < msg.fieldCount; i++) { + fields.push(this.parseField(buffer)) } - msg.fields = fields; - return msg; -}; + msg.fields = fields + return msg +} -var Field = function() { - this.name = null; - this.tableID = null; - this.columnID = null; - this.dataTypeID = null; - this.dataTypeSize = null; - this.dataTypeModifier = null; - this.format = null; -}; +var Field = function () { + this.name = null + this.tableID = null + this.columnID = null + this.dataTypeID = null + this.dataTypeSize = null + this.dataTypeModifier = null + this.format = null +} -var FORMAT_TEXT = 'text'; -var FORMAT_BINARY = 'binary'; -Connection.prototype.parseField = function(buffer) { - var field = new Field(); - field.name = this.parseCString(buffer); - field.tableID = this.parseInt32(buffer); - field.columnID = this.parseInt16(buffer); - field.dataTypeID = this.parseInt32(buffer); - field.dataTypeSize = this.parseInt16(buffer); - field.dataTypeModifier = this.parseInt32(buffer); - if(this.parseInt16(buffer) === TEXT_MODE) { - this._mode = TEXT_MODE; - field.format = FORMAT_TEXT; +var FORMAT_TEXT = 'text' +var FORMAT_BINARY = 'binary' +Connection.prototype.parseField = function (buffer) { + var field = new Field() + field.name = this.parseCString(buffer) + field.tableID = this.parseInt32(buffer) + field.columnID = this.parseInt16(buffer) + field.dataTypeID = this.parseInt32(buffer) + field.dataTypeSize = this.parseInt16(buffer) + field.dataTypeModifier = this.parseInt32(buffer) + if (this.parseInt16(buffer) === TEXT_MODE) { + this._mode = TEXT_MODE + field.format = FORMAT_TEXT } else { - this._mode = BINARY_MODE; - field.format = FORMAT_BINARY; + this._mode = BINARY_MODE + field.format = FORMAT_BINARY } - return field; -}; + return field +} -var DATA_ROW = 'dataRow'; -var DataRowMessage = function(length, fieldCount) { - this.name = DATA_ROW; - this.length = length; - this.fieldCount = fieldCount; - this.fields = []; -}; +var DATA_ROW = 'dataRow' +var DataRowMessage = function (length, fieldCount) { + this.name = DATA_ROW + this.length = length + this.fieldCount = fieldCount + this.fields = [] +} - -//extremely hot-path code -Connection.prototype.parseD = function(buffer, length) { - var fieldCount = this.parseInt16(buffer); - var msg = new DataRowMessage(length, fieldCount); - for(var i = 0; i < fieldCount; i++) { - msg.fields.push(this._readValue(buffer)); +// extremely hot-path code +Connection.prototype.parseD = function (buffer, length) { + var fieldCount = this.parseInt16(buffer) + var msg = new DataRowMessage(length, fieldCount) + for (var i = 0; i < fieldCount; i++) { + msg.fields.push(this._readValue(buffer)) } - return msg; -}; + return msg +} -//extremely hot-path code -Connection.prototype._readValue = function(buffer) { - var length = this.parseInt32(buffer); - if(length === -1) return null; - if(this._mode === TEXT_MODE) { - return this.readString(buffer, length); +// extremely hot-path code +Connection.prototype._readValue = function (buffer) { + var length = this.parseInt32(buffer) + if (length === -1) return null + if (this._mode === TEXT_MODE) { + return this.readString(buffer, length) } - return this.readBytes(buffer, length); -}; + return this.readBytes(buffer, length) +} -//parses error -Connection.prototype.parseE = function(buffer, length) { - var fields = {}; - var msg, item; - var input = new Message('error', length); - var fieldType = this.readString(buffer, 1); - while(fieldType != '\0') { - fields[fieldType] = this.parseCString(buffer); - fieldType = this.readString(buffer, 1); +// parses error +Connection.prototype.parseE = function (buffer, length) { + var fields = {} + var msg, item + var input = new Message('error', length) + var fieldType = this.readString(buffer, 1) + while (fieldType !== '\0') { + fields[fieldType] = this.parseCString(buffer) + fieldType = this.readString(buffer, 1) } - if(input.name === 'error') { + if (input.name === 'error') { // the msg is an Error instance - msg = new Error(fields.M); + msg = new Error(fields.M) for (item in input) { // copy input properties to the error - if(input.hasOwnProperty(item)) { - msg[item] = input[item]; + if (input.hasOwnProperty(item)) { + msg[item] = input[item] } } } else { // the msg is an object literal - msg = input; - msg.message = fields.M; + msg = input + msg.message = fields.M } - msg.severity = fields.S; - msg.code = fields.C; - msg.detail = fields.D; - msg.hint = fields.H; - msg.position = fields.P; - msg.internalPosition = fields.p; - msg.internalQuery = fields.q; - msg.where = fields.W; - msg.schema = fields.s; - msg.table = fields.t; - msg.column = fields.c; - msg.dataType = fields.d; - msg.constraint = fields.n; - msg.file = fields.F; - msg.line = fields.L; - msg.routine = fields.R; - return msg; -}; + msg.severity = fields.S + msg.code = fields.C + msg.detail = fields.D + msg.hint = fields.H + msg.position = fields.P + msg.internalPosition = fields.p + msg.internalQuery = fields.q + msg.where = fields.W + msg.schema = fields.s + msg.table = fields.t + msg.column = fields.c + msg.dataType = fields.d + msg.constraint = fields.n + msg.file = fields.F + msg.line = fields.L + msg.routine = fields.R + return msg +} -//same thing, different name -Connection.prototype.parseN = function(buffer, length) { - var msg = this.parseE(buffer, length); - msg.name = 'notice'; - return msg; -}; +// same thing, different name +Connection.prototype.parseN = function (buffer, length) { + var msg = this.parseE(buffer, length) + msg.name = 'notice' + return msg +} -Connection.prototype.parseA = function(buffer, length) { - var msg = new Message('notification', length); - msg.processId = this.parseInt32(buffer); - msg.channel = this.parseCString(buffer); - msg.payload = this.parseCString(buffer); - return msg; -}; +Connection.prototype.parseA = function (buffer, length) { + var msg = new Message('notification', length) + msg.processId = this.parseInt32(buffer) + msg.channel = this.parseCString(buffer) + msg.payload = this.parseCString(buffer) + return msg +} Connection.prototype.parseG = function (buffer, length) { - var msg = new Message('copyInResponse', length); - return this.parseGH(buffer, msg); -}; + var msg = new Message('copyInResponse', length) + return this.parseGH(buffer, msg) +} -Connection.prototype.parseH = function(buffer, length) { - var msg = new Message('copyOutResponse', length); - return this.parseGH(buffer, msg); -}; +Connection.prototype.parseH = function (buffer, length) { + var msg = new Message('copyOutResponse', length) + return this.parseGH(buffer, msg) +} Connection.prototype.parseGH = function (buffer, msg) { - var isBinary = buffer[this.offset] !== 0; - this.offset++; - msg.binary = isBinary; - var columnCount = this.parseInt16(buffer); - msg.columnTypes = []; - for(var i = 0; i { - var BoundPool = function(options) { - var config = { Client: Client }; + var BoundPool = function (options) { + var config = { Client: Client } for (var key in options) { - config[key] = options[key]; + config[key] = options[key] } return new Pool(config) - }; + } - util.inherits(BoundPool, Pool); + util.inherits(BoundPool, Pool) - return BoundPool; -}; + return BoundPool +} +var PG = function (clientConstructor) { + this.defaults = defaults + this.Client = clientConstructor + this.Query = this.Client.Query + this.Pool = poolFactory(this.Client) + this._pools = [] + this.Connection = Connection + this.types = require('pg-types') +} -var PG = function(clientConstructor) { - this.defaults = defaults; - this.Client = clientConstructor; - this.Query = this.Client.Query; - this.Pool = poolFactory(this.Client); - this._pools = []; - this.Connection = Connection; - this.types = require('pg-types'); -}; - -if(typeof process.env.NODE_PG_FORCE_NATIVE != 'undefined') { - module.exports = new PG(require('./native')); +if (typeof process.env.NODE_PG_FORCE_NATIVE !== 'undefined') { + module.exports = new PG(require('./native')) } else { - module.exports = new PG(Client); + module.exports = new PG(Client) - //lazy require native module...the native module may not have installed - module.exports.__defineGetter__("native", function() { - delete module.exports.native; - var native = null; + // lazy require native module...the native module may not have installed + module.exports.__defineGetter__('native', function () { + delete module.exports.native + var native = null try { - native = new PG(require('./native')); + native = new PG(require('./native')) } catch (err) { if (err.code !== 'MODULE_NOT_FOUND') { - throw err; + throw err } - console.error(err.message); + console.error(err.message) } - module.exports.native = native; - return native; - }); + module.exports.native = native + return native + }) } diff --git a/lib/native/client.js b/lib/native/client.js index d8f20fe7..bed548ad 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,71 +7,71 @@ * README.md file in the root directory of this source tree. */ -var Native = require('pg-native'); -var TypeOverrides = require('../type-overrides'); -var semver = require('semver'); -var pkg = require('../../package.json'); -var assert = require('assert'); -var EventEmitter = require('events').EventEmitter; -var util = require('util'); -var ConnectionParameters = require('../connection-parameters'); +var Native = require('pg-native') +var TypeOverrides = require('../type-overrides') +var semver = require('semver') +var pkg = require('../../package.json') +var assert = require('assert') +var EventEmitter = require('events').EventEmitter +var util = require('util') +var ConnectionParameters = require('../connection-parameters') -var msg = 'Version >= ' + pkg.minNativeVersion + ' of pg-native required.'; -assert(semver.gte(Native.version, pkg.minNativeVersion), msg); +var msg = 'Version >= ' + pkg.minNativeVersion + ' of pg-native required.' +assert(semver.gte(Native.version, pkg.minNativeVersion), msg) -var NativeQuery = require('./query'); +var NativeQuery = require('./query') -var Client = module.exports = function(config) { - EventEmitter.call(this); - config = config || {}; +var Client = module.exports = function (config) { + EventEmitter.call(this) + config = config || {} - this._types = new TypeOverrides(config.types); + this._types = new TypeOverrides(config.types) this.native = new Native({ types: this._types - }); + }) - this._queryQueue = []; - this._connected = false; - this._connecting = false; + this._queryQueue = [] + this._connected = false + this._connecting = false - //keep these on the object for legacy reasons - //for the time being. TODO: deprecate all this jazz - var cp = this.connectionParameters = new ConnectionParameters(config); - this.user = cp.user; - this.password = cp.password; - this.database = cp.database; - this.host = cp.host; - this.port = cp.port; + // keep these on the object for legacy reasons + // for the time being. TODO: deprecate all this jazz + var cp = this.connectionParameters = new ConnectionParameters(config) + this.user = cp.user + this.password = cp.password + this.database = cp.database + this.host = cp.host + this.port = cp.port - //a hash to hold named queries - this.namedQueries = {}; -}; + // a hash to hold named queries + this.namedQueries = {} +} -Client.Query = NativeQuery; +Client.Query = NativeQuery -util.inherits(Client, EventEmitter); +util.inherits(Client, EventEmitter) -//connect to the backend -//pass an optional callback to be called once connected -//or with an error if there was a connection error -//if no callback is passed and there is a connection error -//the client will emit an error event. -Client.prototype.connect = function(cb) { - var self = this; +// connect to the backend +// pass an optional callback to be called once connected +// or with an error if there was a connection error +// if no callback is passed and there is a connection error +// the client will emit an error event. +Client.prototype.connect = function (cb) { + var self = this - var onError = function(err) { - if(cb) return cb(err); - return self.emit('error', err); - }; + var onError = function (err) { + if (cb) return cb(err) + return self.emit('error', err) + } var result if (!cb) { - var resolve, reject - cb = (err) => err ? reject(err) : resolve() - result = new global.Promise(function(res, rej) { - resolve = res - reject = rej + var resolveOut, rejectOut + cb = (err) => err ? rejectOut(err) : resolveOut() + result = new global.Promise(function (resolve, reject) { + resolveOut = resolve + rejectOut = reject }) } @@ -82,145 +82,145 @@ Client.prototype.connect = function(cb) { this._connecting = true - this.connectionParameters.getLibpqConnectionString(function(err, conString) { - if(err) return onError(err); - self.native.connect(conString, function(err) { - if(err) return onError(err); + this.connectionParameters.getLibpqConnectionString(function (err, conString) { + if (err) return onError(err) + self.native.connect(conString, function (err) { + if (err) return onError(err) - //set internal states to connected - self._connected = true; + // set internal states to connected + self._connected = true - //handle connection errors from the native layer - self.native.on('error', function(err) { - //error will be handled by active query - if(self._activeQuery && self._activeQuery.state != 'end') { - return; + // handle connection errors from the native layer + self.native.on('error', function (err) { + // error will be handled by active query + if (self._activeQuery && self._activeQuery.state !== 'end') { + return } - self.emit('error', err); - }); + self.emit('error', err) + }) - self.native.on('notification', function(msg) { + self.native.on('notification', function (msg) { self.emit('notification', { channel: msg.relname, payload: msg.extra - }); - }); + }) + }) - //signal we are connected now - self.emit('connect'); - self._pulseQueryQueue(true); + // signal we are connected now + self.emit('connect') + self._pulseQueryQueue(true) - //possibly call the optional callback - if(cb) cb(); - }); - }); + // possibly call the optional callback + if (cb) cb() + }) + }) return result -}; +} -//send a query to the server -//this method is highly overloaded to take -//1) string query, optional array of parameters, optional function callback -//2) object query with { +// send a query to the server +// this method is highly overloaded to take +// 1) string query, optional array of parameters, optional function callback +// 2) object query with { // string query // optional array values, // optional function callback instead of as a separate parameter // optional string name to name & cache the query plan // optional string rowMode = 'array' for an array of results // } -Client.prototype.query = function(config, values, callback) { - if (typeof config.submit == 'function') { +Client.prototype.query = function (config, values, callback) { + if (typeof config.submit === 'function') { // accept query(new Query(...), (err, res) => { }) style - if (typeof values == 'function') { - config.callback = values; + if (typeof values === 'function') { + config.callback = values } - this._queryQueue.push(config); - this._pulseQueryQueue(); - return config; + this._queryQueue.push(config) + this._pulseQueryQueue() + return config } - var query = new NativeQuery(config, values, callback); + var query = new NativeQuery(config, values, callback) var result if (!query.callback) { - let resolve, reject; - result = new Promise((res, rej) => { - resolve = res - reject = rej + let resolveOut, rejectOut + result = new Promise((resolve, reject) => { + resolveOut = resolve + rejectOut = reject }) - query.callback = (err, res) => err ? reject(err) : resolve(res) + query.callback = (err, res) => err ? rejectOut(err) : resolveOut(res) } - this._queryQueue.push(query); - this._pulseQueryQueue(); - return result; -}; + this._queryQueue.push(query) + this._pulseQueryQueue() + return result +} -//disconnect from the backend server -Client.prototype.end = function(cb) { - var self = this; - if(!this._connected) { - this.once('connect', this.end.bind(this, cb)); +// disconnect from the backend server +Client.prototype.end = function (cb) { + var self = this + if (!this._connected) { + this.once('connect', this.end.bind(this, cb)) } - var result; + var result if (!cb) { var resolve, reject cb = (err) => err ? reject(err) : resolve() - result = new global.Promise(function(res, rej) { + result = new global.Promise(function (res, rej) { resolve = res reject = rej }) } - this.native.end(function() { - //send an error to the active query - if(self._hasActiveQuery()) { - var msg = 'Connection terminated'; - self._queryQueue.length = 0; - self._activeQuery.handleError(new Error(msg)); + this.native.end(function () { + // send an error to the active query + if (self._hasActiveQuery()) { + var msg = 'Connection terminated' + self._queryQueue.length = 0 + self._activeQuery.handleError(new Error(msg)) } - self.emit('end'); - if(cb) cb(); - }); + self.emit('end') + if (cb) cb() + }) return result -}; +} -Client.prototype._hasActiveQuery = function() { - return this._activeQuery && this._activeQuery.state != 'error' && this._activeQuery.state != 'end'; -}; +Client.prototype._hasActiveQuery = function () { + return this._activeQuery && this._activeQuery.state !== 'error' && this._activeQuery.state !== 'end' +} -Client.prototype._pulseQueryQueue = function(initialConnection) { - if(!this._connected) { - return; +Client.prototype._pulseQueryQueue = function (initialConnection) { + if (!this._connected) { + return } - if(this._hasActiveQuery()) { - return; + if (this._hasActiveQuery()) { + return } - var query = this._queryQueue.shift(); - if(!query) { - if(!initialConnection) { - this.emit('drain'); + var query = this._queryQueue.shift() + if (!query) { + if (!initialConnection) { + this.emit('drain') } - return; + return } - this._activeQuery = query; - query.submit(this); - var self = this; - query.once('_done', function() { - self._pulseQueryQueue(); - }); -}; + this._activeQuery = query + query.submit(this) + var self = this + query.once('_done', function () { + self._pulseQueryQueue() + }) +} -//attempt to cancel an in-progress query -Client.prototype.cancel = function(query) { - if(this._activeQuery == query) { - this.native.cancel(function() {}); - } else if (this._queryQueue.indexOf(query) != -1) { - this._queryQueue.splice(this._queryQueue.indexOf(query), 1); +// attempt to cancel an in-progress query +Client.prototype.cancel = function (query) { + if (this._activeQuery === query) { + this.native.cancel(function () {}) + } else if (this._queryQueue.indexOf(query) !== -1) { + this._queryQueue.splice(this._queryQueue.indexOf(query), 1) } -}; +} -Client.prototype.setTypeParser = function(oid, format, parseFn) { - return this._types.setTypeParser(oid, format, parseFn); -}; +Client.prototype.setTypeParser = function (oid, format, parseFn) { + return this._types.setTypeParser(oid, format, parseFn) +} -Client.prototype.getTypeParser = function(oid, format) { - return this._types.getTypeParser(oid, format); -}; +Client.prototype.getTypeParser = function (oid, format) { + return this._types.getTypeParser(oid, format) +} diff --git a/lib/native/index.js b/lib/native/index.js index 53f10c4a..eead422a 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -1,2 +1,2 @@ -"use strict"; +'use strict' module.exports = require('./client') diff --git a/lib/native/query.js b/lib/native/query.js index a35e5304..c1a76915 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,33 +7,33 @@ * README.md file in the root directory of this source tree. */ -var EventEmitter = require('events').EventEmitter; -var util = require('util'); -var utils = require('../utils'); -var NativeResult = require('./result'); +var EventEmitter = require('events').EventEmitter +var util = require('util') +var utils = require('../utils') +var NativeResult = require('./result') -var NativeQuery = module.exports = function(config, values, callback) { - EventEmitter.call(this); - config = utils.normalizeQueryConfig(config, values, callback); - this.text = config.text; - this.values = config.values; - this.name = config.name; - this.callback = config.callback; - this.state = 'new'; - this._arrayMode = config.rowMode == 'array'; +var NativeQuery = module.exports = function (config, values, callback) { + EventEmitter.call(this) + config = utils.normalizeQueryConfig(config, values, callback) + this.text = config.text + this.values = config.values + this.name = config.name + this.callback = config.callback + this.state = 'new' + this._arrayMode = config.rowMode === 'array' - //if the 'row' event is listened for - //then emit them as they come in - //without setting singleRowMode to true - //this has almost no meaning because libpq - //reads all rows into memory befor returning any - this._emitRowEvents = false; - this.on('newListener', function(event) { - if(event === 'row') this._emitRowEvents = true; - }.bind(this)); -}; + // if the 'row' event is listened for + // then emit them as they come in + // without setting singleRowMode to true + // this has almost no meaning because libpq + // reads all rows into memory befor returning any + this._emitRowEvents = false + this.on('newListener', function (event) { + if (event === 'row') this._emitRowEvents = true + }.bind(this)) +} -util.inherits(NativeQuery, EventEmitter); +util.inherits(NativeQuery, EventEmitter) var errorFieldMap = { 'sqlState': 'code', @@ -47,113 +47,112 @@ var errorFieldMap = { 'constraintName': 'constraint', 'sourceFile': 'file', 'sourceLine': 'line', - 'sourceFunction': 'routine', -}; + 'sourceFunction': 'routine' +} -NativeQuery.prototype.handleError = function(err) { - var self = this; - //copy pq error fields into the error object - var fields = self.native.pq.resultErrorFields(); - if(fields) { - for(var key in fields) { - var normalizedFieldName = errorFieldMap[key] || key; - err[normalizedFieldName] = fields[key]; +NativeQuery.prototype.handleError = function (err) { + var self = this + // copy pq error fields into the error object + var fields = self.native.pq.resultErrorFields() + if (fields) { + for (var key in fields) { + var normalizedFieldName = errorFieldMap[key] || key + err[normalizedFieldName] = fields[key] } } - if(self.callback) { - self.callback(err); + if (self.callback) { + self.callback(err) } else { - self.emit('error', err); + self.emit('error', err) } - self.state = 'error'; -}; + self.state = 'error' +} -NativeQuery.prototype.then = function(onSuccess, onFailure) { - return this._getPromise().then(onSuccess, onFailure); -}; +NativeQuery.prototype.then = function (onSuccess, onFailure) { + return this._getPromise().then(onSuccess, onFailure) +} -NativeQuery.prototype.catch = function(callback) { - return this._getPromise().catch(callback); -}; +NativeQuery.prototype.catch = function (callback) { + return this._getPromise().catch(callback) +} -NativeQuery.prototype._getPromise = function() { - if (this._promise) return this._promise; - this._promise = new Promise(function(resolve, reject) { - this._once('end', resolve); - this._once('error', reject); - }.bind(this)); - return this._promise; -}; +NativeQuery.prototype._getPromise = function () { + if (this._promise) return this._promise + this._promise = new Promise(function (resolve, reject) { + this._once('end', resolve) + this._once('error', reject) + }.bind(this)) + return this._promise +} -NativeQuery.prototype.submit = function(client) { - this.state = 'running'; - var self = this; - this.native = client.native; - client.native.arrayMode = this._arrayMode; +NativeQuery.prototype.submit = function (client) { + this.state = 'running' + var self = this + this.native = client.native + client.native.arrayMode = this._arrayMode - var after = function(err, rows) { - client.native.arrayMode = false; - setImmediate(function() { - self.emit('_done'); - }); + var after = function (err, rows) { + client.native.arrayMode = false + setImmediate(function () { + self.emit('_done') + }) - //handle possible query error - if(err) { - return self.handleError(err); + // handle possible query error + if (err) { + return self.handleError(err) } - var result = new NativeResult(); - result.addCommandComplete(self.native.pq); - result.rows = rows; + var result = new NativeResult() + result.addCommandComplete(self.native.pq) + result.rows = rows - //emit row events for each row in the result - if(self._emitRowEvents) { - rows.forEach(function(row) { - self.emit('row', row, result); - }); + // emit row events for each row in the result + if (self._emitRowEvents) { + rows.forEach(function (row) { + self.emit('row', row, result) + }) } - - //handle successful result - self.state = 'end'; - self.emit('end', result); - if(self.callback) { - self.callback(null, result); + // handle successful result + self.state = 'end' + self.emit('end', result) + if (self.callback) { + self.callback(null, result) } - }; - - if(process.domain) { - after = process.domain.bind(after); } - //named query - if(this.name) { + if (process.domain) { + after = process.domain.bind(after) + } + + // named query + if (this.name) { if (this.name.length > 63) { - console.error('Warning! Postgres only supports 63 characters for query names.'); - console.error('You supplied', this.name, '(', this.name.length, ')'); - console.error('This can cause conflicts and silent errors executing queries'); + console.error('Warning! Postgres only supports 63 characters for query names.') + console.error('You supplied', this.name, '(', this.name.length, ')') + console.error('This can cause conflicts and silent errors executing queries') } - var values = (this.values||[]).map(utils.prepareValue); + var values = (this.values || []).map(utils.prepareValue) - //check if the client has already executed this named query - //if so...just execute it again - skip the planning phase - if(client.namedQueries[this.name]) { - return client.native.execute(this.name, values, after); + // check if the client has already executed this named query + // if so...just execute it again - skip the planning phase + if (client.namedQueries[this.name]) { + return client.native.execute(this.name, values, after) } - //plan the named query the first time, then execute it - return client.native.prepare(this.name, this.text, values.length, function(err) { - if(err) return after(err); - client.namedQueries[self.name] = true; - return self.native.execute(self.name, values, after); - }); - } else if(this.values) { + // plan the named query the first time, then execute it + return client.native.prepare(this.name, this.text, values.length, function (err) { + if (err) return after(err) + client.namedQueries[self.name] = true + return self.native.execute(self.name, values, after) + }) + } else if (this.values) { if (!Array.isArray(this.values)) { const err = new Error('Query values must be an array') return after(err) } - var vals = this.values.map(utils.prepareValue); - client.native.query(this.text, vals, after); + var vals = this.values.map(utils.prepareValue) + client.native.query(this.text, vals, after) } else { - client.native.query(this.text, after); + client.native.query(this.text, after) } -}; +} diff --git a/lib/native/result.js b/lib/native/result.js index 62075b65..ae9a97a1 100644 --- a/lib/native/result.js +++ b/lib/native/result.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,31 +7,31 @@ * README.md file in the root directory of this source tree. */ -var NativeResult = module.exports = function(pq) { - this.command = null; - this.rowCount = 0; - this.rows = null; - this.fields = null; -}; +var NativeResult = module.exports = function (pq) { + this.command = null + this.rowCount = 0 + this.rows = null + this.fields = null +} -NativeResult.prototype.addCommandComplete = function(pq) { - this.command = pq.cmdStatus().split(' ')[0]; - this.rowCount = parseInt(pq.cmdTuples(), 10); - var nfields = pq.nfields(); - if(nfields < 1) return; +NativeResult.prototype.addCommandComplete = function (pq) { + this.command = pq.cmdStatus().split(' ')[0] + this.rowCount = parseInt(pq.cmdTuples(), 10) + var nfields = pq.nfields() + if (nfields < 1) return - this.fields = []; - for(var i = 0; i < nfields; i++) { + this.fields = [] + for (var i = 0; i < nfields; i++) { this.fields.push({ name: pq.fname(i), dataTypeID: pq.ftype(i) - }); + }) } -}; +} -NativeResult.prototype.addRow = function(row) { +NativeResult.prototype.addRow = function (row) { // This is empty to ensure pg code doesn't break when switching to pg-native // pg-native loads all rows into the final result object by default. // This is because libpg loads all rows into memory before passing the result // to pg-native. -}; +} diff --git a/lib/query.js b/lib/query.js index 26b930fb..89bde080 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,127 +7,127 @@ * README.md file in the root directory of this source tree. */ -var EventEmitter = require('events').EventEmitter; -var util = require('util'); +var EventEmitter = require('events').EventEmitter +var util = require('util') -var Result = require('./result'); -var utils = require('./utils'); +var Result = require('./result') +var utils = require('./utils') -var Query = function(config, values, callback) { +var Query = function (config, values, callback) { // use of "new" optional - if(!(this instanceof Query)) { return new Query(config, values, callback); } + if (!(this instanceof Query)) { return new Query(config, values, callback) } - config = utils.normalizeQueryConfig(config, values, callback); + config = utils.normalizeQueryConfig(config, values, callback) - this.text = config.text; - this.values = config.values; - this.rows = config.rows; - this.types = config.types; - this.name = config.name; - this.binary = config.binary; - this.stream = config.stream; - //use unique portal name each time - this.portal = config.portal || ""; - this.callback = config.callback; - if(process.domain && config.callback) { - this.callback = process.domain.bind(config.callback); + this.text = config.text + this.values = config.values + this.rows = config.rows + this.types = config.types + this.name = config.name + this.binary = config.binary + this.stream = config.stream + // use unique portal name each time + this.portal = config.portal || '' + this.callback = config.callback + if (process.domain && config.callback) { + this.callback = process.domain.bind(config.callback) } - this._result = new Result(config.rowMode, config.types); - this.isPreparedStatement = false; - this._canceledDueToError = false; - this._promise = null; - EventEmitter.call(this); -}; + this._result = new Result(config.rowMode, config.types) + this.isPreparedStatement = false + this._canceledDueToError = false + this._promise = null + EventEmitter.call(this) +} -util.inherits(Query, EventEmitter); +util.inherits(Query, EventEmitter) -Query.prototype.requiresPreparation = function() { - //named queries must always be prepared - if(this.name) { return true; } - //always prepare if there are max number of rows expected per - //portal execution - if(this.rows) { return true; } - //don't prepare empty text queries - if(!this.text) { return false; } - //prepare if there are values - if(!this.values) { return false; } - return this.values.length > 0; -}; +Query.prototype.requiresPreparation = function () { + // named queries must always be prepared + if (this.name) { return true } + // always prepare if there are max number of rows expected per + // portal execution + if (this.rows) { return true } + // don't prepare empty text queries + if (!this.text) { return false } + // prepare if there are values + if (!this.values) { return false } + return this.values.length > 0 +} -//associates row metadata from the supplied -//message with this query object -//metadata used when parsing row results -Query.prototype.handleRowDescription = function(msg) { - this._result.addFields(msg.fields); - this._accumulateRows = this.callback || !this.listeners('row').length; -}; +// associates row metadata from the supplied +// message with this query object +// metadata used when parsing row results +Query.prototype.handleRowDescription = function (msg) { + this._result.addFields(msg.fields) + this._accumulateRows = this.callback || !this.listeners('row').length +} -Query.prototype.handleDataRow = function(msg) { - var row; +Query.prototype.handleDataRow = function (msg) { + var row if (this._canceledDueToError) { - return; + return } try { - row = this._result.parseRow(msg.fields); + row = this._result.parseRow(msg.fields) } catch (err) { - this._canceledDueToError = err; - return; + this._canceledDueToError = err + return } - this.emit('row', row, this._result); + this.emit('row', row, this._result) if (this._accumulateRows) { - this._result.addRow(row); + this._result.addRow(row) } -}; +} -Query.prototype.handleCommandComplete = function(msg, con) { - this._result.addCommandComplete(msg); - //need to sync after each command complete of a prepared statement - if(this.isPreparedStatement) { - con.sync(); - } -}; - -//if a named prepared statement is created with empty query text -//the backend will send an emptyQuery message but *not* a command complete message -//execution on the connection will hang until the backend receives a sync message -Query.prototype.handleEmptyQuery = function(con) { +Query.prototype.handleCommandComplete = function (msg, con) { + this._result.addCommandComplete(msg) + // need to sync after each command complete of a prepared statement if (this.isPreparedStatement) { - con.sync(); + con.sync() } -}; +} -Query.prototype.handleReadyForQuery = function(con) { - if(this._canceledDueToError) { - return this.handleError(this._canceledDueToError, con); +// if a named prepared statement is created with empty query text +// the backend will send an emptyQuery message but *not* a command complete message +// execution on the connection will hang until the backend receives a sync message +Query.prototype.handleEmptyQuery = function (con) { + if (this.isPreparedStatement) { + con.sync() } - if(this.callback) { - this.callback(null, this._result); - } - this.emit('end', this._result); -}; +} -Query.prototype.handleError = function(err, connection) { - //need to sync after error during a prepared statement - if(this.isPreparedStatement) { - connection.sync(); +Query.prototype.handleReadyForQuery = function (con) { + if (this._canceledDueToError) { + return this.handleError(this._canceledDueToError, con) } - if(this._canceledDueToError) { - err = this._canceledDueToError; - this._canceledDueToError = false; + if (this.callback) { + this.callback(null, this._result) } - //if callback supplied do not emit error event as uncaught error - //events will bubble up to node process - if(this.callback) { - return this.callback(err); - } - this.emit('error', err); -}; + this.emit('end', this._result) +} -Query.prototype.submit = function(connection) { - if (typeof this.text != 'string' && typeof this.name != 'string') { +Query.prototype.handleError = function (err, connection) { + // need to sync after error during a prepared statement + if (this.isPreparedStatement) { + connection.sync() + } + if (this._canceledDueToError) { + err = this._canceledDueToError + this._canceledDueToError = false + } + // if callback supplied do not emit error event as uncaught error + // events will bubble up to node process + if (this.callback) { + return this.callback(err) + } + this.emit('error', err) +} + +Query.prototype.submit = function (connection) { + if (typeof this.text !== 'string' && typeof this.name !== 'string') { const err = new Error('A query must have either text or a name. Supplying neither is unsupported.') connection.emit('error', err) connection.emit('readyForQuery') @@ -139,75 +139,75 @@ Query.prototype.submit = function(connection) { connection.emit('readyForQuery') return } - if(this.requiresPreparation()) { - this.prepare(connection); + if (this.requiresPreparation()) { + this.prepare(connection) } else { - connection.query(this.text); + connection.query(this.text) } -}; +} -Query.prototype.hasBeenParsed = function(connection) { - return this.name && connection.parsedStatements[this.name]; -}; +Query.prototype.hasBeenParsed = function (connection) { + return this.name && connection.parsedStatements[this.name] +} -Query.prototype.handlePortalSuspended = function(connection) { - this._getRows(connection, this.rows); -}; +Query.prototype.handlePortalSuspended = function (connection) { + this._getRows(connection, this.rows) +} -Query.prototype._getRows = function(connection, rows) { +Query.prototype._getRows = function (connection, rows) { connection.execute({ portal: this.portalName, rows: rows - }, true); - connection.flush(); -}; + }, true) + connection.flush() +} -Query.prototype.prepare = function(connection) { - var self = this; - //prepared statements need sync to be called after each command - //complete or when an error is encountered - this.isPreparedStatement = true; - //TODO refactor this poor encapsulation - if(!this.hasBeenParsed(connection)) { +Query.prototype.prepare = function (connection) { + var self = this + // prepared statements need sync to be called after each command + // complete or when an error is encountered + this.isPreparedStatement = true + // TODO refactor this poor encapsulation + if (!this.hasBeenParsed(connection)) { connection.parse({ text: self.text, name: self.name, types: self.types - }, true); + }, true) } - if(self.values) { - self.values = self.values.map(utils.prepareValue); + if (self.values) { + self.values = self.values.map(utils.prepareValue) } - //http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY + // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY connection.bind({ portal: self.portalName, statement: self.name, values: self.values, binary: self.binary - }, true); + }, true) connection.describe({ type: 'P', - name: self.portalName || "" - }, true); + name: self.portalName || '' + }, true) - this._getRows(connection, this.rows); -}; + this._getRows(connection, this.rows) +} Query.prototype.handleCopyInResponse = function (connection) { - if(this.stream) this.stream.startStreamingToConnection(connection); - else connection.sendCopyFail('No source stream defined'); -}; + if (this.stream) this.stream.startStreamingToConnection(connection) + else connection.sendCopyFail('No source stream defined') +} Query.prototype.handleCopyData = function (msg, connection) { - var chunk = msg.chunk; - if(this.stream) { - this.stream.handleChunk(chunk); + var chunk = msg.chunk + if (this.stream) { + this.stream.handleChunk(chunk) } - //if there are no stream (for example when copy to query was sent by - //query method instead of copyTo) error will be handled - //on copyOutResponse event, so silently ignore this error here -}; -module.exports = Query; + // if there are no stream (for example when copy to query was sent by + // query method instead of copyTo) error will be handled + // on copyOutResponse event, so silently ignore this error here +} +module.exports = Query diff --git a/lib/result.js b/lib/result.js index 21b649a9..da999158 100644 --- a/lib/result.js +++ b/lib/result.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,110 +7,110 @@ * README.md file in the root directory of this source tree. */ -var types = require('pg-types'); +var types = require('pg-types') -//result object returned from query -//in the 'end' event and also -//passed as second argument to provided callback -var Result = function(rowMode) { - this.command = null; - this.rowCount = null; - this.oid = null; - this.rows = []; - this.fields = []; - this._parsers = []; - this.RowCtor = null; - this.rowAsArray = rowMode == "array"; - if(this.rowAsArray) { - this.parseRow = this._parseRowAsArray; +// result object returned from query +// in the 'end' event and also +// passed as second argument to provided callback +var Result = function (rowMode) { + this.command = null + this.rowCount = null + this.oid = null + this.rows = [] + this.fields = [] + this._parsers = [] + this.RowCtor = null + this.rowAsArray = rowMode === 'array' + if (this.rowAsArray) { + this.parseRow = this._parseRowAsArray } -}; +} -var matchRegexp = /([A-Za-z]+) ?(\d+ )?(\d+)?/; +var matchRegexp = /([A-Za-z]+) ?(\d+ )?(\d+)?/ -//adds a command complete message -Result.prototype.addCommandComplete = function(msg) { - var match; - if(msg.text) { - //pure javascript - match = matchRegexp.exec(msg.text); +// adds a command complete message +Result.prototype.addCommandComplete = function (msg) { + var match + if (msg.text) { + // pure javascript + match = matchRegexp.exec(msg.text) } else { - //native bindings - match = matchRegexp.exec(msg.command); + // native bindings + match = matchRegexp.exec(msg.command) } - if(match) { - this.command = match[1]; - //match 3 will only be existing on insert commands - if(match[3]) { - //msg.value is from native bindings - this.rowCount = parseInt(match[3] || msg.value, 10); - this.oid = parseInt(match[2], 10); + if (match) { + this.command = match[1] + // match 3 will only be existing on insert commands + if (match[3]) { + // msg.value is from native bindings + this.rowCount = parseInt(match[3] || msg.value, 10) + this.oid = parseInt(match[2], 10) } else { - this.rowCount = parseInt(match[2], 10); + this.rowCount = parseInt(match[2], 10) } } -}; +} -Result.prototype._parseRowAsArray = function(rowData) { - var row = []; - for(var i = 0, len = rowData.length; i < len; i++) { - var rawValue = rowData[i]; - if(rawValue !== null) { - row.push(this._parsers[i](rawValue)); +Result.prototype._parseRowAsArray = function (rowData) { + var row = [] + for (var i = 0, len = rowData.length; i < len; i++) { + var rawValue = rowData[i] + if (rawValue !== null) { + row.push(this._parsers[i](rawValue)) } else { - row.push(null); + row.push(null) } } - return row; -}; + return row +} -//rowData is an array of text or binary values -//this turns the row into a JavaScript object -Result.prototype.parseRow = function(rowData) { - return new this.RowCtor(this._parsers, rowData); -}; +// rowData is an array of text or binary values +// this turns the row into a JavaScript object +Result.prototype.parseRow = function (rowData) { + return new this.RowCtor(this._parsers, rowData) +} -Result.prototype.addRow = function(row) { - this.rows.push(row); -}; +Result.prototype.addRow = function (row) { + this.rows.push(row) +} -var inlineParser = function(fieldName, i) { +var inlineParser = function (fieldName, i) { return "\nthis['" + - //fields containing single quotes will break - //the evaluated javascript unless they are escaped - //see https://github.com/brianc/node-postgres/issues/507 - //Addendum: However, we need to make sure to replace all - //occurences of apostrophes, not just the first one. - //See https://github.com/brianc/node-postgres/issues/934 + // fields containing single quotes will break + // the evaluated javascript unless they are escaped + // see https://github.com/brianc/node-postgres/issues/507 + // Addendum: However, we need to make sure to replace all + // occurences of apostrophes, not just the first one. + // See https://github.com/brianc/node-postgres/issues/934 fieldName.replace(/'/g, "\\'") + "'] = " + - "rowData[" + i + "] == null ? null : parsers[" + i + "](rowData[" + i + "]);"; -}; + 'rowData[' + i + '] == null ? null : parsers[' + i + '](rowData[' + i + ']);' +} -Result.prototype.addFields = function(fieldDescriptions) { - //clears field definitions - //multiple query statements in 1 action can result in multiple sets - //of rowDescriptions...eg: 'select NOW(); select 1::int;' - //you need to reset the fields - if(this.fields.length) { - this.fields = []; - this._parsers = []; +Result.prototype.addFields = function (fieldDescriptions) { + // clears field definitions + // multiple query statements in 1 action can result in multiple sets + // of rowDescriptions...eg: 'select NOW(); select 1::int;' + // you need to reset the fields + if (this.fields.length) { + this.fields = [] + this._parsers = [] } - var ctorBody = ""; - for(var i = 0; i < fieldDescriptions.length; i++) { - var desc = fieldDescriptions[i]; - this.fields.push(desc); - var parser = this._getTypeParser(desc.dataTypeID, desc.format || 'text'); - this._parsers.push(parser); - //this is some craziness to compile the row result parsing - //results in ~60% speedup on large query result sets - ctorBody += inlineParser(desc.name, i); + var ctorBody = '' + for (var i = 0; i < fieldDescriptions.length; i++) { + var desc = fieldDescriptions[i] + this.fields.push(desc) + var parser = this._getTypeParser(desc.dataTypeID, desc.format || 'text') + this._parsers.push(parser) + // this is some craziness to compile the row result parsing + // results in ~60% speedup on large query result sets + ctorBody += inlineParser(desc.name, i) } - if(!this.rowAsArray) { - this.RowCtor = Function("parsers", "rowData", ctorBody); + if (!this.rowAsArray) { + this.RowCtor = Function('parsers', 'rowData', ctorBody) } -}; +} -Result.prototype._getTypeParser = types.getTypeParser; +Result.prototype._getTypeParser = types.getTypeParser -module.exports = Result; +module.exports = Result diff --git a/lib/type-overrides.js b/lib/type-overrides.js index 53be35ef..54394406 100644 --- a/lib/type-overrides.js +++ b/lib/type-overrides.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,33 +7,33 @@ * README.md file in the root directory of this source tree. */ -var types = require('pg-types'); +var types = require('pg-types') -function TypeOverrides(userTypes) { - this._types = userTypes || types; - this.text = {}; - this.binary = {}; +function TypeOverrides (userTypes) { + this._types = userTypes || types + this.text = {} + this.binary = {} } -TypeOverrides.prototype.getOverrides = function(format) { - switch(format) { - case 'text': return this.text; - case 'binary': return this.binary; - default: return {}; +TypeOverrides.prototype.getOverrides = function (format) { + switch (format) { + case 'text': return this.text + case 'binary': return this.binary + default: return {} } -}; +} -TypeOverrides.prototype.setTypeParser = function(oid, format, parseFn) { - if(typeof format == 'function') { - parseFn = format; - format = 'text'; +TypeOverrides.prototype.setTypeParser = function (oid, format, parseFn) { + if (typeof format === 'function') { + parseFn = format + format = 'text' } - this.getOverrides(format)[oid] = parseFn; -}; + this.getOverrides(format)[oid] = parseFn +} -TypeOverrides.prototype.getTypeParser = function(oid, format) { - format = format || 'text'; - return this.getOverrides(format)[oid] || this._types.getTypeParser(oid, format); -}; +TypeOverrides.prototype.getTypeParser = function (oid, format) { + format = format || 'text' + return this.getOverrides(format)[oid] || this._types.getTypeParser(oid, format) +} -module.exports = TypeOverrides; +module.exports = TypeOverrides diff --git a/lib/utils.js b/lib/utils.js index 05c6f0b4..a83cdee9 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,151 +7,141 @@ * README.md file in the root directory of this source tree. */ -const util = require('util') -const crypto = require('crypto'); +const crypto = require('crypto') -const defaults = require('./defaults'); +const defaults = require('./defaults') -function escapeElement(elementRepresentation) { +function escapeElement (elementRepresentation) { var escaped = elementRepresentation .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"'); + .replace(/"/g, '\\"') - return '"' + escaped + '"'; + return '"' + escaped + '"' } // convert a JS array to a postgres array literal // uses comma separator so won't work for types like box that use // a different array separator. -function arrayString(val) { - var result = '{'; - for (var i = 0 ; i < val.length; i++) { - if(i > 0) { - result = result + ','; +function arrayString (val) { + var result = '{' + for (var i = 0; i < val.length; i++) { + if (i > 0) { + result = result + ',' } - if(val[i] === null || typeof val[i] === 'undefined') { - result = result + 'NULL'; - } - else if(Array.isArray(val[i])) { - result = result + arrayString(val[i]); - } - else - { - result += escapeElement(prepareValue(val[i])); - } - } - result = result + '}'; - return result; -} - -//converts values from javascript types -//to their 'raw' counterparts for use as a postgres parameter -//note: you can override this function to provide your own conversion mechanism -//for complex types, etc... -var prepareValue = function(val, seen) { - if (val instanceof Buffer) { - return val; - } - if(val instanceof Date) { - if(defaults.parseInputDatesAsUTC) { - return dateToStringUTC(val); + if (val[i] === null || typeof val[i] === 'undefined') { + result = result + 'NULL' + } else if (Array.isArray(val[i])) { + result = result + arrayString(val[i]) } else { - return dateToString(val); + result += escapeElement(prepareValue(val[i])) } } - if(Array.isArray(val)) { - return arrayString(val); - } - if(val === null || typeof val === 'undefined') { - return null; - } - if(typeof val === 'object') { - return prepareObject(val, seen); - } - return val.toString(); -}; + result = result + '}' + return result +} -function prepareObject(val, seen) { - if(val.toPostgres && typeof val.toPostgres === 'function') { - seen = seen || []; +// converts values from javascript types +// to their 'raw' counterparts for use as a postgres parameter +// note: you can override this function to provide your own conversion mechanism +// for complex types, etc... +var prepareValue = function (val, seen) { + if (val instanceof Buffer) { + return val + } + if (val instanceof Date) { + if (defaults.parseInputDatesAsUTC) { + return dateToStringUTC(val) + } else { + return dateToString(val) + } + } + if (Array.isArray(val)) { + return arrayString(val) + } + if (val === null || typeof val === 'undefined') { + return null + } + if (typeof val === 'object') { + return prepareObject(val, seen) + } + return val.toString() +} + +function prepareObject (val, seen) { + if (val.toPostgres && typeof val.toPostgres === 'function') { + seen = seen || [] if (seen.indexOf(val) !== -1) { - throw new Error('circular reference detected while preparing "' + val + '" for query'); + throw new Error('circular reference detected while preparing "' + val + '" for query') } - seen.push(val); + seen.push(val) - return prepareValue(val.toPostgres(prepareValue), seen); + return prepareValue(val.toPostgres(prepareValue), seen) } - return JSON.stringify(val); + return JSON.stringify(val) } -function pad(number, digits) { - number = "" +number; - while(number.length < digits) - number = "0" + number; - return number; +function pad (number, digits) { + number = '' + number + while (number.length < digits) { number = '0' + number } + return number } -function dateToString(date) { - - var offset = -date.getTimezoneOffset(); +function dateToString (date) { + var offset = -date.getTimezoneOffset() var ret = pad(date.getFullYear(), 4) + '-' + pad(date.getMonth() + 1, 2) + '-' + pad(date.getDate(), 2) + 'T' + pad(date.getHours(), 2) + ':' + pad(date.getMinutes(), 2) + ':' + pad(date.getSeconds(), 2) + '.' + - pad(date.getMilliseconds(), 3); + pad(date.getMilliseconds(), 3) - if(offset < 0) { - ret += "-"; - offset *= -1; - } - else - ret += "+"; + if (offset < 0) { + ret += '-' + offset *= -1 + } else { ret += '+' } - return ret + pad(Math.floor(offset/60), 2) + ":" + pad(offset%60, 2); + return ret + pad(Math.floor(offset / 60), 2) + ':' + pad(offset % 60, 2) } -function dateToStringUTC(date) { - +function dateToStringUTC (date) { var ret = pad(date.getUTCFullYear(), 4) + '-' + pad(date.getUTCMonth() + 1, 2) + '-' + pad(date.getUTCDate(), 2) + 'T' + pad(date.getUTCHours(), 2) + ':' + pad(date.getUTCMinutes(), 2) + ':' + pad(date.getUTCSeconds(), 2) + '.' + - pad(date.getUTCMilliseconds(), 3); + pad(date.getUTCMilliseconds(), 3) - return ret + "+00:00"; + return ret + '+00:00' } function normalizeQueryConfig (config, values, callback) { - //can take in strings or config objects - config = (typeof(config) == 'string') ? { text: config } : config; - if(values) { - if(typeof values === 'function') { - config.callback = values; + // can take in strings or config objects + config = (typeof (config) === 'string') ? { text: config } : config + if (values) { + if (typeof values === 'function') { + config.callback = values } else { - config.values = values; + config.values = values } } - if(callback) { - config.callback = callback; + if (callback) { + config.callback = callback } - return config; + return config } - const md5 = function (string) { - return crypto.createHash('md5').update(string, 'utf-8').digest('hex'); -}; + return crypto.createHash('md5').update(string, 'utf-8').digest('hex') +} module.exports = { prepareValue: function prepareValueWrapper (value) { - //this ensures that extra arguments do not get passed into prepareValue - //by accident, eg: from calling values.map(utils.prepareValue) - return prepareValue(value); + // this ensures that extra arguments do not get passed into prepareValue + // by accident, eg: from calling values.map(utils.prepareValue) + return prepareValue(value) }, normalizeQueryConfig: normalizeQueryConfig, - md5: md5, -}; + md5: md5 +} diff --git a/package.json b/package.json index 537570d0..07068972 100644 --- a/package.json +++ b/package.json @@ -29,13 +29,17 @@ "devDependencies": { "async": "0.9.0", "co": "4.6.0", - "jshint": "2.5.2", + "eslint": "4.2.0", + "eslint-config-standard": "10.2.1", + "eslint-plugin-import": "2.7.0", + "eslint-plugin-node": "5.1.0", + "eslint-plugin-promise": "3.5.0", + "eslint-plugin-standard": "3.0.1", "pg-copy-streams": "0.3.0" }, "minNativeVersion": "1.7.0", "scripts": { - "changelog": "npm i github-changes && ./node_modules/.bin/github-changes -o brianc -r node-postgres -d pulls -a -v", - "test": "make test-all connectionString=postgres://postgres@localhost:5432/postgres" + "test": "make test-all" }, "license": "MIT", "engines": { diff --git a/script/create-test-tables.js b/script/create-test-tables.js index 4881daf8..c887629e 100644 --- a/script/create-test-tables.js +++ b/script/create-test-tables.js @@ -1,33 +1,33 @@ -"use strict"; -var args = require(__dirname + '/../test/cli'); -var pg = require(__dirname + '/../lib'); +'use strict' +var args = require(__dirname + '/../test/cli') +var pg = require(__dirname + '/../lib') var people = [ - {name: 'Aaron', age: 10}, - {name: 'Brian', age: 20}, - {name: 'Chris', age: 30}, - {name: 'David', age: 40}, - {name: 'Elvis', age: 50}, - {name: 'Frank', age: 60}, - {name: 'Grace', age: 70}, - {name: 'Haley', age: 80}, - {name: 'Irma', age: 90}, - {name: 'Jenny', age: 100}, - {name: 'Kevin', age: 110}, - {name: 'Larry', age: 120}, + {name: 'Aaron', age: 10}, + {name: 'Brian', age: 20}, + {name: 'Chris', age: 30}, + {name: 'David', age: 40}, + {name: 'Elvis', age: 50}, + {name: 'Frank', age: 60}, + {name: 'Grace', age: 70}, + {name: 'Haley', age: 80}, + {name: 'Irma', age: 90}, + {name: 'Jenny', age: 100}, + {name: 'Kevin', age: 110}, + {name: 'Larry', age: 120}, {name: 'Michelle', age: 130}, - {name: 'Nancy', age: 140}, - {name: 'Olivia', age: 150}, - {name: 'Peter', age: 160}, - {name: 'Quinn', age: 170}, - {name: 'Ronda', age: 180}, - {name: 'Shelley', age: 190}, - {name: 'Tobias', age: 200}, - {name: 'Uma', age: 210}, - {name: 'Veena', age: 220}, - {name: 'Wanda', age: 230}, - {name: 'Xavier', age: 240}, - {name: 'Yoyo', age: 250}, + {name: 'Nancy', age: 140}, + {name: 'Olivia', age: 150}, + {name: 'Peter', age: 160}, + {name: 'Quinn', age: 170}, + {name: 'Ronda', age: 180}, + {name: 'Shelley', age: 190}, + {name: 'Tobias', age: 200}, + {name: 'Uma', age: 210}, + {name: 'Veena', age: 220}, + {name: 'Wanda', age: 230}, + {name: 'Xavier', age: 240}, + {name: 'Yoyo', age: 250}, {name: 'Zanzabar', age: 260} ] @@ -37,16 +37,16 @@ var con = new pg.Client({ user: args.user, password: args.password, database: args.database -}); -con.connect(); -var query = con.query("drop table if exists person"); -con.query("create table person(id serial, name varchar(10), age integer)", (err, res) => { - console.log("Created table person"); - console.log("Filling it with people"); }) -people.map(function(person) { - return con.query(new pg.Query("insert into person(name, age) values('"+person.name + "', '" + person.age + "')")); -}).pop().on('end', function(){ - console.log("Inserted 26 people"); - con.end(); -}); +con.connect() +var query = con.query('drop table if exists person') +con.query('create table person(id serial, name varchar(10), age integer)', (err, res) => { + console.log('Created table person') + console.log('Filling it with people') +}) +people.map(function (person) { + return con.query(new pg.Query("insert into person(name, age) values('" + person.name + "', '" + person.age + "')")) +}).pop().on('end', function () { + console.log('Inserted 26 people') + con.end() +}) diff --git a/script/dump-db-types.js b/script/dump-db-types.js index cd204153..2e55969d 100644 --- a/script/dump-db-types.js +++ b/script/dump-db-types.js @@ -1,24 +1,23 @@ -"use strict"; -var pg = require(__dirname + '/../lib'); -var args = require(__dirname + '/../test/cli'); +'use strict' +var pg = require(__dirname + '/../lib') +var args = require(__dirname + '/../test/cli') var queries = [ - "select CURRENT_TIMESTAMP", + 'select CURRENT_TIMESTAMP', "select interval '1 day' + interval '1 hour'", - "select TIMESTAMP 'today'"]; - -queries.forEach(function(query) { + "select TIMESTAMP 'today'"] +queries.forEach(function (query) { var client = new pg.Client({ user: args.user, database: args.database, password: args.password - }); - client.connect(); + }) + client.connect() client .query(query) - .on('row', function(row) { - console.log(row); - client.end(); - }); -}); + .on('row', function (row) { + console.log(row) + client.end() + }) +}) diff --git a/script/list-db-types.js b/script/list-db-types.js index b2db8403..d281bb90 100644 --- a/script/list-db-types.js +++ b/script/list-db-types.js @@ -1,7 +1,7 @@ -"use strict"; -var helper = require(__dirname + "/../test/integration/test-helper"); -var pg = helper.pg; -pg.connect(helper.config, assert.success(function(client) { - var query = client.query('select oid, typname from pg_type where typtype = \'b\' order by oid'); - query.on('row', console.log); +'use strict' +var helper = require(__dirname + '/../test/integration/test-helper') +var pg = helper.pg +pg.connect(helper.config, assert.success(function (client) { + var query = client.query('select oid, typname from pg_type where typtype = \'b\' order by oid') + query.on('row', console.log) })) diff --git a/test/buffer-list.js b/test/buffer-list.js index 3ebffe9d..527743fb 100644 --- a/test/buffer-list.js +++ b/test/buffer-list.js @@ -1,70 +1,70 @@ -"use strict"; -global.BufferList = function() { - this.buffers = []; -}; -var p = BufferList.prototype; +'use strict' +global.BufferList = function () { + this.buffers = [] +} +var p = BufferList.prototype -p.add = function(buffer, front) { - this.buffers[front ? "unshift" : "push"](buffer); - return this; -}; +p.add = function (buffer, front) { + this.buffers[front ? 'unshift' : 'push'](buffer) + return this +} -p.addInt16 = function(val, front) { - return this.add(Buffer.from([(val >>> 8),(val >>> 0)]),front); -}; +p.addInt16 = function (val, front) { + return this.add(Buffer.from([(val >>> 8), (val >>> 0)]), front) +} -p.getByteLength = function(initial) { - return this.buffers.reduce(function(previous, current){ - return previous + current.length; - },initial || 0); -}; +p.getByteLength = function (initial) { + return this.buffers.reduce(function (previous, current) { + return previous + current.length + }, initial || 0) +} -p.addInt32 = function(val, first) { +p.addInt32 = function (val, first) { return this.add(Buffer.from([ (val >>> 24 & 0xFF), (val >>> 16 & 0xFF), (val >>> 8 & 0xFF), (val >>> 0 & 0xFF) - ]),first); -}; + ]), first) +} -p.addCString = function(val, front) { - var len = Buffer.byteLength(val); - var buffer = Buffer.alloc(len+1); - buffer.write(val); - buffer[len] = 0; - return this.add(buffer, front); -}; +p.addCString = function (val, front) { + var len = Buffer.byteLength(val) + var buffer = Buffer.alloc(len + 1) + buffer.write(val) + buffer[len] = 0 + return this.add(buffer, front) +} -p.addChar = function(char, first) { - return this.add(Buffer.from(char,'utf8'), first); -}; +p.addChar = function (char, first) { + return this.add(Buffer.from(char, 'utf8'), first) +} -p.join = function(appendLength, char) { - var length = this.getByteLength(); - if(appendLength) { - this.addInt32(length+4, true); - return this.join(false, char); +p.join = function (appendLength, char) { + var length = this.getByteLength() + if (appendLength) { + this.addInt32(length + 4, true) + return this.join(false, char) } - if(char) { - this.addChar(char, true); - length++; + if (char) { + this.addChar(char, true) + length++ } - var result = Buffer.alloc(length); - var index = 0; - this.buffers.forEach(function(buffer) { - buffer.copy(result, index, 0); - index += buffer.length; - }); - return result; -}; + var result = Buffer.alloc(length) + var index = 0 + this.buffers.forEach(function (buffer) { + buffer.copy(result, index, 0) + index += buffer.length + }) + return result +} -BufferList.concat = function() { - var total = new BufferList(); - for(var i = 0; i < arguments.length; i++) { - total.add(arguments[i]); +BufferList.concat = function () { + var total = new BufferList() + for (var i = 0; i < arguments.length; i++) { + total.add(arguments[i]) } - return total.join(); -}; + return total.join() +} -module.exports = BufferList; +module.exports = BufferList diff --git a/test/cli.js b/test/cli.js index 388b8acf..2b40976c 100644 --- a/test/cli.js +++ b/test/cli.js @@ -1,25 +1,25 @@ -"use strict"; -var ConnectionParameters = require(__dirname + '/../lib/connection-parameters'); -var config = new ConnectionParameters(process.argv[2]); +'use strict' +var ConnectionParameters = require(__dirname + '/../lib/connection-parameters') +var config = new ConnectionParameters(process.argv[2]) -for(var i = 0; i < process.argv.length; i++) { - switch(process.argv[i].toLowerCase()) { - case 'native': - config.native = true; - break; - case 'binary': - config.binary = true; - break; - case 'down': - config.down = true; - break; - default: - break; +for (var i = 0; i < process.argv.length; i++) { + switch (process.argv[i].toLowerCase()) { + case 'native': + config.native = true + break + case 'binary': + config.binary = true + break + case 'down': + config.down = true + break + default: + break } } -if(process.env['PG_TEST_NATIVE']) { - config.native = true; +if (process.env['PG_TEST_NATIVE']) { + config.native = true } -module.exports = config; +module.exports = config diff --git a/test/integration/client/api-tests.js b/test/integration/client/api-tests.js index 668c6a74..22fe96b2 100644 --- a/test/integration/client/api-tests.js +++ b/test/integration/client/api-tests.js @@ -1,208 +1,208 @@ -"use strict"; -var helper = require(__dirname + "/../test-helper"); -var pg = helper.pg; +'use strict' +var helper = require(__dirname + '/../test-helper') +var pg = helper.pg -var suite = new helper.Suite(); +var suite = new helper.Suite() -suite.test("pool callback behavior", done => { - //test weird callback behavior with node-pool - const pool = new pg.Pool(); - pool.connect(function(err) { - assert(!err); - arguments[1].emit("drain"); - arguments[2](); - pool.end(done); - }); -}); +suite.test('pool callback behavior', done => { + // test weird callback behavior with node-pool + const pool = new pg.Pool() + pool.connect(function (err) { + assert(!err) + arguments[1].emit('drain') + arguments[2]() + pool.end(done) + }) +}) -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"]); +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"]); + text: 'INSERT INTO peep(name) VALUES ($1)', + values: ['brian'] + } + client.query(config) + client.query('INSERT INTO peep(name) VALUES ($1)', ['aaron']) - client.query("SELECT * FROM peep ORDER BY name", (err, res) => { - assert(!err); - assert.equal(res.rowCount, 3); + client.query('SELECT * FROM peep ORDER BY name', (err, res) => { + assert(!err) + assert.equal(res.rowCount, 3) assert.deepEqual(res.rows, [ { - name: "aaron" + name: 'aaron' }, { - name: "brian" + name: 'brian' }, { - name: "brianc" + name: 'brianc' } - ]); - done(); - }); + ]) + done() + }) client.connect(err => { - assert(!err); - client.once("drain", () => client.end()); - }); -}); + assert(!err) + client.once('drain', () => client.end()) + }) +}) -suite.test("executing nested queries", function(done) { - const pool = new pg.Pool(); +suite.test('executing nested queries', function (done) { + const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { - assert(!err); + assert.calls(function (err, client, release) { + assert(!err) client.query( - "select now as now from NOW()", - assert.calls(function(err, result) { - assert.equal(new Date().getYear(), result.rows[0].now.getYear()); + '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() { + '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); + 'select * FROM NOW()', + assert.calls(function () { + assert.ok('all queries hit') + release() + pool.end(done) }) - ); + ) }) - ); + ) }) - ); + ) }) - ); -}); + ) +}) -suite.test("raises error if cannot connect", function() { - var connectionString = "pg://sfalsdkf:asdf@localhost/ieieie"; - const pool = new pg.Pool({ connectionString: connectionString }); +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(); + assert.calls(function (err, client, done) { + assert.ok(err, 'should have raised an error') + done() }) - ); -}); + ) +}) -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(!err); +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(!err) client.query( - "SELECT OISDJF FROM LEIWLISEJLSE", - assert.calls(function(err, result) { - assert.ok(err); + '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) { +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(!err); - client.query("CREATE TEMP TABLE boom(name varchar(10))"); - var callCount = 0; + assert.calls(function (err, client, release) { + assert(!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) { + ].join(';'), + function (err, callback) { assert.equal( callCount++, 0, - "Call count should be 0. More means this callback fired more than once." - ); + '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) { +suite.test('can provide callback and config object', function (done) { const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { - assert(!err); + assert.calls(function (err, client, release) { + assert(!err) client.query( { - name: "boom", - text: "select NOW()" + name: 'boom', + text: 'select NOW()' }, - assert.calls(function(err, result) { - assert(!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(!err); - var config = { - text: "select $1::text as val" - }; - client.query( - config, - ["hi"], - assert.calls(function(err, result) { - assert(!err); - assert.equal(result.rows.length, 1); - assert.equal(result.rows[0].val, "hi"); + assert.calls(function (err, result) { + assert(!err) + assert.equal(result.rows[0].now.getYear(), new Date().getYear()) release() pool.end(done) }) - ); + ) }) - ); -}); + ) +}) -suite.test("null and undefined are both inserted as NULL", function(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(!err); + assert.calls(function (err, client, release) { + assert(!err) + var config = { + text: 'select $1::text as val' + } 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(!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); + config, + ['hi'], + assert.calls(function (err, result) { + assert(!err) + assert.equal(result.rows.length, 1) + assert.equal(result.rows[0].val, 'hi') + release() pool.end(done) - release(); }) - ); + ) }) - ); -}); + ) +}) + +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(!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(!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/appname-tests.js b/test/integration/client/appname-tests.js index 98c41776..4db5297c 100644 --- a/test/integration/client/appname-tests.js +++ b/test/integration/client/appname-tests.js @@ -1,101 +1,99 @@ -"use strict"; -var helper = require('./test-helper'); -var Client = helper.Client; +'use strict' +var helper = require('./test-helper') +var Client = helper.Client -var suite = new helper.Suite(); +var suite = new helper.Suite() -var conInfo = helper.config; +var conInfo = helper.config -function getConInfo(override) { - var newConInfo = {}; - Object.keys(conInfo).forEach(function(k){ - newConInfo[k] = conInfo[k]; - }); - Object.keys(override || {}).forEach(function(k){ - newConInfo[k] = override[k]; - }); - return newConInfo; +function getConInfo (override) { + var newConInfo = {} + Object.keys(conInfo).forEach(function (k) { + newConInfo[k] = conInfo[k] + }) + Object.keys(override || {}).forEach(function (k) { + newConInfo[k] = override[k] + }) + return newConInfo } -function getAppName(conf, cb) { - var client = new Client(conf); - client.connect(assert.success(function(){ - client.query('SHOW application_name', assert.success(function(res){ - var appName = res.rows[0].application_name; - cb(appName); - client.end(); - })); - })); +function getAppName (conf, cb) { + var client = new Client(conf) + client.connect(assert.success(function () { + client.query('SHOW application_name', assert.success(function (res) { + var appName = res.rows[0].application_name + cb(appName) + client.end() + })) + })) } -suite.test('No default appliation_name ', function(done) { - var conf = getConInfo(); - getAppName({ }, function(res){ - assert.strictEqual(res, ''); +suite.test('No default appliation_name ', function (done) { + var conf = getConInfo() + getAppName({ }, function (res) { + assert.strictEqual(res, '') done() - }); -}); + }) +}) -suite.test('fallback_application_name is used', function(done) { - var fbAppName = 'this is my app'; +suite.test('fallback_application_name is used', function (done) { + var fbAppName = 'this is my app' var conf = getConInfo({ - 'fallback_application_name' : fbAppName - }); - getAppName(conf, function(res){ - assert.strictEqual(res, fbAppName); + 'fallback_application_name': fbAppName + }) + getAppName(conf, function (res) { + assert.strictEqual(res, fbAppName) done() - }); -}); + }) +}) -suite.test('application_name is used', function(done) { - var appName = 'some wired !@#$% application_name'; +suite.test('application_name is used', function (done) { + var appName = 'some wired !@#$% application_name' var conf = getConInfo({ - 'application_name' : appName - }); - getAppName(conf, function(res){ - assert.strictEqual(res, appName); + 'application_name': appName + }) + getAppName(conf, function (res) { + assert.strictEqual(res, appName) done() - }); -}); + }) +}) -suite.test('application_name has precedence over fallback_application_name', function(done) { - var appName = 'some wired !@#$% application_name'; - var fbAppName = 'some other strange $$test$$ appname'; +suite.test('application_name has precedence over fallback_application_name', function (done) { + var appName = 'some wired !@#$% application_name' + var fbAppName = 'some other strange $$test$$ appname' var conf = getConInfo({ - 'application_name' : appName , - 'fallback_application_name' : fbAppName - }); - getAppName(conf, function(res){ - assert.strictEqual(res, appName); + 'application_name': appName, + 'fallback_application_name': fbAppName + }) + getAppName(conf, function (res) { + assert.strictEqual(res, appName) done() - }); -}); + }) +}) -suite.test('application_name from connection string', function(done) { - var appName = 'my app'; - var conParams = require(__dirname + '/../../../lib/connection-parameters'); - var conf; +suite.test('application_name from connection string', function (done) { + var appName = 'my app' + var conParams = require(__dirname + '/../../../lib/connection-parameters') + var conf if (process.argv[2]) { - conf = new conParams(process.argv[2]+'?application_name='+appName); + conf = new conParams(process.argv[2] + '?application_name=' + appName) } else { - conf = 'postgres://?application_name='+appName; + conf = 'postgres://?application_name=' + appName } - getAppName(conf, function(res){ - assert.strictEqual(res, appName); + getAppName(conf, function (res) { + assert.strictEqual(res, appName) done() - }); -}); - - + }) +}) // TODO: make the test work for native client too if (!helper.args.native) { - suite.test('application_name is read from the env', function(done) { - var appName = process.env.PGAPPNAME = 'testest'; - getAppName({ }, function(res){ - delete process.env.PGAPPNAME; - assert.strictEqual(res, appName); + suite.test('application_name is read from the env', function (done) { + var appName = process.env.PGAPPNAME = 'testest' + getAppName({ }, function (res) { + delete process.env.PGAPPNAME + assert.strictEqual(res, appName) done() - }); - }); + }) + }) } diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index 3185ad2c..84e97f19 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -1,177 +1,177 @@ -"use strict"; -var helper = require(__dirname + "/test-helper"); -var pg = helper.pg; +'use strict' +var helper = require(__dirname + '/test-helper') +var pg = helper.pg var suite = new helper.Suite() const pool = new pg.Pool() -pool.connect(assert.calls(function(err, client, release) { - assert(!err); +pool.connect(assert.calls(function (err, client, release) { + assert(!err) - suite.test('nulls', function(done) { - client.query('SELECT $1::text[] as array', [[null]], assert.success(function(result) { - var array = result.rows[0].array; - assert.lengthIs(array, 1); - assert.isNull(array[0]); + suite.test('nulls', function (done) { + client.query('SELECT $1::text[] as array', [[null]], assert.success(function (result) { + var array = result.rows[0].array + assert.lengthIs(array, 1) + assert.isNull(array[0]) done() - })); - }); + })) + }) - suite.test('elements containing JSON-escaped characters', function(done) { - var param = '\\"\\"'; + suite.test('elements containing JSON-escaped characters', function (done) { + var param = '\\"\\"' for (var i = 1; i <= 0x1f; i++) { - param += String.fromCharCode(i); + param += String.fromCharCode(i) } - client.query('SELECT $1::text[] as array', [[param]], assert.success(function(result) { - var array = result.rows[0].array; - assert.lengthIs(array, 1); - assert.equal(array[0], param); + client.query('SELECT $1::text[] as array', [[param]], assert.success(function (result) { + var array = result.rows[0].array + assert.lengthIs(array, 1) + assert.equal(array[0], param) done() - })); - }); + })) + }) suite.test('cleanup', () => release()) pool.connect(assert.calls(function (err, client, release) { - assert(!err); - client.query("CREATE TEMP TABLE why(names text[], numbors integer[])"); - client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); + assert(!err) + client.query('CREATE TEMP TABLE why(names text[], numbors integer[])') + client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log) suite.test('numbers', function (done) { // client.connection.on('message', console.log) client.query('SELECT numbors FROM why', assert.success(function (result) { - assert.lengthIs(result.rows[0].numbors, 3); - assert.equal(result.rows[0].numbors[0], 1); - assert.equal(result.rows[0].numbors[1], 2); - assert.equal(result.rows[0].numbors[2], 3); + assert.lengthIs(result.rows[0].numbors, 3) + assert.equal(result.rows[0].numbors[0], 1) + assert.equal(result.rows[0].numbors[1], 2) + assert.equal(result.rows[0].numbors[2], 3) done() })) }) suite.test('parses string arrays', function (done) { client.query('SELECT names FROM why', assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 'aaron'); - assert.equal(names[1], 'brian'); - assert.equal(names[2], "a b c"); + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0], 'aaron') + assert.equal(names[1], 'brian') + assert.equal(names[2], 'a b c') done() })) }) suite.test('empty array', function (done) { client.query("SELECT '{}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 0); + var names = result.rows[0].names + assert.lengthIs(names, 0) done() })) }) suite.test('element containing comma', function (done) { client.query("SELECT '{\"joe,bob\",jim}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - assert.equal(names[0], 'joe,bob'); - assert.equal(names[1], 'jim'); + var names = result.rows[0].names + assert.lengthIs(names, 2) + assert.equal(names[0], 'joe,bob') + assert.equal(names[1], 'jim') done() })) }) suite.test('bracket in quotes', function (done) { client.query("SELECT '{\"{\",\"}\"}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - assert.equal(names[0], '{'); - assert.equal(names[1], '}'); + var names = result.rows[0].names + assert.lengthIs(names, 2) + assert.equal(names[0], '{') + assert.equal(names[1], '}') done() })) }) suite.test('null value', function (done) { client.query("SELECT '{joe,null,bob,\"NULL\"}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 4); - assert.equal(names[0], 'joe'); - assert.equal(names[1], null); - assert.equal(names[2], 'bob'); - assert.equal(names[3], 'NULL'); + var names = result.rows[0].names + assert.lengthIs(names, 4) + assert.equal(names[0], 'joe') + assert.equal(names[1], null) + assert.equal(names[2], 'bob') + assert.equal(names[3], 'NULL') done() })) }) suite.test('element containing quote char', function (done) { client.query("SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 'joe\''); - assert.equal(names[1], 'jim'); - assert.equal(names[2], 'bob"'); + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0], 'joe\'') + assert.equal(names[1], 'jim') + assert.equal(names[2], 'bob"') done() })) }) suite.test('nested array', function (done) { client.query("SELECT '{{1,joe},{2,bob}}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); + var names = result.rows[0].names + assert.lengthIs(names, 2) - assert.lengthIs(names[0], 2); - assert.equal(names[0][0], '1'); - assert.equal(names[0][1], 'joe'); + assert.lengthIs(names[0], 2) + assert.equal(names[0][0], '1') + assert.equal(names[0][1], 'joe') - assert.lengthIs(names[1], 2); - assert.equal(names[1][0], '2'); - assert.equal(names[1][1], 'bob'); + assert.lengthIs(names[1], 2) + assert.equal(names[1][0], '2') + assert.equal(names[1][1], 'bob') done() })) }) suite.test('integer array', function (done) { client.query("SELECT '{1,2,3}'::integer[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 1); - assert.equal(names[1], 2); - assert.equal(names[2], 3); + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0], 1) + assert.equal(names[1], 2) + assert.equal(names[2], 3) done() })) }) suite.test('integer nested array', function (done) { client.query("SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0][0], 1); - assert.equal(names[0][1], 100); + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0][0], 1) + assert.equal(names[0][1], 100) - assert.equal(names[1][0], 2); - assert.equal(names[1][1], 100); + assert.equal(names[1][0], 2) + assert.equal(names[1][1], 100) - assert.equal(names[2][0], 3); - assert.equal(names[2][1], 100); + assert.equal(names[2][0], 3) + assert.equal(names[2][1], 100) done() })) }) suite.test('JS array parameter', function (done) { - client.query("SELECT $1::integer[] as names", [[[1, 100], [2, 100], [3, 100]]], assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0][0], 1); - assert.equal(names[0][1], 100); + client.query('SELECT $1::integer[] as names', [[[1, 100], [2, 100], [3, 100]]], assert.success(function (result) { + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0][0], 1) + assert.equal(names[0][1], 100) - assert.equal(names[1][0], 2); - assert.equal(names[1][1], 100); + assert.equal(names[1][0], 2) + assert.equal(names[1][1], 100) - assert.equal(names[2][0], 3); - assert.equal(names[2][1], 100); - release(); + assert.equal(names[2][0], 3) + assert.equal(names[2][1], 100) + release() pool.end(() => { done() }) })) }) })) -})); +})) diff --git a/test/integration/client/big-simple-query-tests.js b/test/integration/client/big-simple-query-tests.js index 7db183f4..5a15dca3 100644 --- a/test/integration/client/big-simple-query-tests.js +++ b/test/integration/client/big-simple-query-tests.js @@ -1,8 +1,8 @@ -"use strict"; -var helper = require("./test-helper"); +'use strict' +var helper = require('./test-helper') var Query = helper.pg.Query -const suite = new helper.Suite(); +const suite = new helper.Suite() /* Test to trigger a bug. @@ -12,75 +12,74 @@ const suite = new helper.Suite(); */ // Big query with a where clouse from supplied value -var big_query_rows_1 = []; -var big_query_rows_2 = []; -var big_query_rows_3 = []; +var big_query_rows_1 = [] +var big_query_rows_2 = [] +var big_query_rows_3 = [] // Works -suite.test('big simple query 1', function(done) { - var client = helper.client(); +suite.test('big simple query 1', function (done) { + var client = helper.client() client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1")) - .on('row', function(row) { big_query_rows_1.push(row); }) - .on('error', function(error) { console.log("big simple query 1 error"); console.log(error); }); + .on('row', function (row) { big_query_rows_1.push(row) }) + .on('error', function (error) { console.log('big simple query 1 error'); console.log(error) }) client.on('drain', () => { client.end() done() - }); -}); + }) +}) // Works -suite.test('big simple query 2', function(done) { - var client = helper.client(); - client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''])) - .on('row', function(row) { big_query_rows_2.push(row); }) - .on('error', function(error) { console.log("big simple query 2 error"); console.log(error); }); +suite.test('big simple query 2', function (done) { + var client = helper.client() + client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", [''])) + .on('row', function (row) { big_query_rows_2.push(row) }) + .on('error', function (error) { console.log('big simple query 2 error'); console.log(error) }) client.on('drain', () => { client.end() done() - }); -}); + }) +}) // Fails most of the time with 'invalid byte sequence for encoding "UTF8": 0xb9' or 'insufficient data left in message' // If test 1 and 2 are commented out it works -suite.test('big simple query 3',function(done) { - var client = helper.client(); - client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''])) - .on('row', function(row) { big_query_rows_3.push(row); }) - .on('error', function(error) { console.log("big simple query 3 error"); console.log(error); }); +suite.test('big simple query 3', function (done) { + var client = helper.client() + client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", [''])) + .on('row', function (row) { big_query_rows_3.push(row) }) + .on('error', function (error) { console.log('big simple query 3 error'); console.log(error) }) client.on('drain', () => { client.end() done() - }); -}); + }) +}) -process.on('exit', function() { - assert.equal(big_query_rows_1.length, 26,'big simple query 1 should return 26 rows'); - assert.equal(big_query_rows_2.length, 26,'big simple query 2 should return 26 rows'); - assert.equal(big_query_rows_3.length, 26,'big simple query 3 should return 26 rows'); -}); +process.on('exit', function () { + assert.equal(big_query_rows_1.length, 26, 'big simple query 1 should return 26 rows') + assert.equal(big_query_rows_2.length, 26, 'big simple query 2 should return 26 rows') + assert.equal(big_query_rows_3.length, 26, 'big simple query 3 should return 26 rows') +}) - -var runBigQuery = function(client) { - var rows = []; - var q = client.query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''], function(err, result) { - if(err != null) { - console.log(err); - throw Err; +var runBigQuery = function (client) { + var rows = [] + var q = client.query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", [''], function (err, result) { + if (err != null) { + console.log(err) + throw Err } - assert.lengthIs(result.rows, 26); - }); + assert.lengthIs(result.rows, 26) + }) } -suite.test('many times', function(done) { - var client = helper.client(); - for(var i = 0; i < 20; i++) { - runBigQuery(client); +suite.test('many times', function (done) { + var client = helper.client() + for (var i = 0; i < 20; i++) { + runBigQuery(client) } - client.on('drain', function() { - client.end(); - setTimeout(function() { + client.on('drain', function () { + client.end() + setTimeout(function () { done() - //let client disconnect fully + // let client disconnect fully }, 100) - }); + }) }) diff --git a/test/integration/client/configuration-tests.js b/test/integration/client/configuration-tests.js index 8bd065e9..9d3b7f5a 100644 --- a/test/integration/client/configuration-tests.js +++ b/test/integration/client/configuration-tests.js @@ -1,17 +1,17 @@ -"use strict"; -var helper = require('./test-helper'); -var pg = helper.pg; +'use strict' +var helper = require('./test-helper') +var pg = helper.pg -var suite = new helper.Suite(); +var suite = new helper.Suite() -//clear process.env -var realEnv = {}; -for(var key in process.env) { - realEnv[key] = process.env[key]; - if(!key.indexOf('PG')) delete process.env[key]; +// clear process.env +var realEnv = {} +for (var key in process.env) { + realEnv[key] = process.env[key] + if (!key.indexOf('PG')) delete process.env[key] } -suite.test('default values are used in new clients', function() { +suite.test('default values are used in new clients', function () { assert.same(pg.defaults, { user: process.env.USER, database: process.env.USER, @@ -21,7 +21,7 @@ suite.test('default values are used in new clients', function() { poolSize: 10 }) - var client = new pg.Client(); + var client = new pg.Client() assert.same(client, { user: process.env.USER, database: process.env.USER, @@ -30,16 +30,15 @@ suite.test('default values are used in new clients', function() { }) }) - -suite.test('modified values are passed to created clients', function() { +suite.test('modified values are passed to created clients', function () { pg.defaults.user = 'boom' pg.defaults.password = 'zap' pg.defaults.database = 'pow' pg.defaults.port = 1234 pg.defaults.host = 'blam' - var client = new Client(); - assert.same(client,{ + var client = new Client() + assert.same(client, { user: 'boom', password: 'zap', database: 'pow', @@ -49,8 +48,8 @@ suite.test('modified values are passed to created clients', function() { }) suite.test('cleanup', () => { - //restore process.env + // restore process.env for (var key in realEnv) { - process.env[key] = realEnv[key]; + process.env[key] = realEnv[key] } }) diff --git a/test/integration/client/custom-types-tests.js b/test/integration/client/custom-types-tests.js index db143356..99e04d01 100644 --- a/test/integration/client/custom-types-tests.js +++ b/test/integration/client/custom-types-tests.js @@ -1,6 +1,6 @@ -"use strict"; -const helper = require('./test-helper'); -const Client = helper.pg.Client; +'use strict' +const helper = require('./test-helper') +const Client = helper.pg.Client const suite = new helper.Suite() const client = new Client({ @@ -13,8 +13,8 @@ suite.test('custom type parser in client config', (done) => { client.connect() .then(() => { client.query('SELECT NOW() as val', assert.success(function (res) { - assert.equal(res.rows[0].val, 'okay!'); - client.end().then(done); - })); + assert.equal(res.rows[0].val, 'okay!') + client.end().then(done) + })) }) }) diff --git a/test/integration/client/empty-query-tests.js b/test/integration/client/empty-query-tests.js index d02c142d..975dc0f6 100644 --- a/test/integration/client/empty-query-tests.js +++ b/test/integration/client/empty-query-tests.js @@ -1,21 +1,20 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') const suite = new helper.Suite() -suite.test("empty query message handling", function(done) { - const client = helper.client(); - assert.emits(client, 'drain', function() { - client.end(done); - }); - client.query({text: ""}); -}); +suite.test('empty query message handling', function (done) { + const client = helper.client() + assert.emits(client, 'drain', function () { + client.end(done) + }) + client.query({text: ''}) +}) -suite.test('callback supported', function(done) { - const client = helper.client(); - client.query("", function(err, result) { - assert(!err); - assert.empty(result.rows); +suite.test('callback supported', function (done) { + const client = helper.client() + client.query('', function (err, result) { + assert(!err) + assert.empty(result.rows) client.end(done) }) }) - diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index e4d77903..55372d14 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -1,19 +1,19 @@ -"use strict"; +'use strict' -var helper = require('./test-helper'); -var util = require('util'); +var helper = require('./test-helper') +var util = require('util') var pg = helper.pg const Client = pg.Client -var createErorrClient = function() { - var client = helper.client(); - client.once('error', function(err) { - assert.fail('Client shoud not throw error during query execution'); - }); - client.on('drain', client.end.bind(client)); - return client; -}; +var createErorrClient = function () { + var client = helper.client() + client.once('error', function (err) { + assert.fail('Client shoud not throw error during query execution') + }) + client.on('drain', client.end.bind(client)) + return client +} const suite = new helper.Suite('error handling') @@ -50,131 +50,129 @@ suite.test('re-using connections results in promise rejection', (done) => { }) }) -suite.test('query receives error on client shutdown', function(done) { - var client = new Client(); - client.connect(assert.success(function() { +suite.test('query receives error on client shutdown', function (done) { + var client = new Client() + client.connect(assert.success(function () { const config = { text: 'select pg_sleep(5)', name: 'foobar' } - let queryError; - client.query(new pg.Query(config), assert.calls(function(err, res) { + let queryError + client.query(new pg.Query(config), assert.calls(function (err, res) { assert(err instanceof Error) queryError = err - })); + })) setTimeout(() => client.end(), 50) client.once('end', () => { assert(queryError instanceof Error) done() }) - })); -}); + })) +}) - var ensureFuture = function (testClient, done) { - var goodQuery = testClient.query(new pg.Query("select age from boom")); - assert.emits(goodQuery, 'row', function (row) { - assert.equal(row.age, 28); - done(); - }); - }; +var ensureFuture = function (testClient, done) { + var goodQuery = testClient.query(new pg.Query('select age from boom')) + assert.emits(goodQuery, 'row', function (row) { + assert.equal(row.age, 28) + done() + }) +} - suite.test("when query is parsing", (done) => { - var client = createErorrClient(); +suite.test('when query is parsing', (done) => { + var client = createErorrClient() - var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);" }); + var q = client.query({ text: 'CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);' }) + // this query wont parse since there isn't a table named bang + var query = client.query(new pg.Query({ + text: 'select * from bang where name = $1', + values: ['0'] + })) - //this query wont parse since there isn't a table named bang - var query = client.query(new pg.Query({ - text: "select * from bang where name = $1", - values: ['0'] - })); + assert.emits(query, 'error', function (err) { + ensureFuture(client, done) + }) +}) - assert.emits(query, 'error', function (err) { - ensureFuture(client, done); - }); - }); +suite.test('when a query is binding', function (done) { + var client = createErorrClient() - suite.test("when a query is binding", function (done) { - var client = createErorrClient(); + var q = client.query({ text: 'CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);' }) - var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);" }); + var query = client.query(new pg.Query({ + text: 'select * from boom where age = $1', + values: ['asldkfjasdf'] + })) + assert.emits(query, 'error', function (err) { + assert.equal(err.severity, 'ERROR') + ensureFuture(client, done) + }) +}) - var query = client.query(new pg.Query({ - text: 'select * from boom where age = $1', - values: ['asldkfjasdf'] - })); - - assert.emits(query, 'error', function (err) { - assert.equal(err.severity, "ERROR"); - ensureFuture(client, done); - }); - }); - -suite.test('non-query error with callback', function(done) { +suite.test('non-query error with callback', function (done) { var client = new Client({ - user:'asldkfjsadlfkj' - }); - client.connect(assert.calls(function(error, client) { + user: 'asldkfjsadlfkj' + }) + client.connect(assert.calls(function (error, client) { assert(error instanceof Error) done() - })); -}); + })) +}) -suite.test('non-error calls supplied callback', function(done) { +suite.test('non-error calls supplied callback', function (done) { var client = new Client({ user: helper.args.user, password: helper.args.password, host: helper.args.host, port: helper.args.port, database: helper.args.database - }); + }) - client.connect(assert.calls(function(err) { - assert.ifError(err); - client.end(done); + client.connect(assert.calls(function (err) { + assert.ifError(err) + client.end(done) })) -}); +}) suite.test('when connecting to an invalid host with callback', function (done) { var client = new Client({ - user: 'very invalid username', - }); - client.connect(function(error, client) { - assert(error instanceof Error); - done(); - }); -}); + user: 'very invalid username' + }) + client.connect(function (error, client) { + assert(error instanceof Error) + done() + }) +}) -suite.test('when connecting to invalid host with promise', function(done) { +suite.test('when connecting to invalid host with promise', function (done) { var client = new Client({ user: 'very invalid username' - }); - client.connect().catch((e) => done()); -}); + }) + client.connect().catch((e) => done()) +}) -suite.test('non-query error', function(done) { +suite.test('non-query error', function (done) { var client = new Client({ - user:'asldkfjsadlfkj' - }); + user: 'asldkfjsadlfkj' + }) client.connect() .catch(e => { assert(e instanceof Error) done() }) -}); +}) suite.test('within a simple query', (done) => { - var client = createErorrClient(); + var client = createErorrClient() - var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")); + var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")) - assert.emits(query, 'error', function(error) { - assert.equal(error.severity, "ERROR"); - done(); - }); -}); + assert.emits(query, 'error', function (error) { + assert.equal(error.severity, 'ERROR') + done() + }) +}) suite.test('connected, idle client error', (done) => { const client = new Client() diff --git a/test/integration/client/huge-numeric-tests.js b/test/integration/client/huge-numeric-tests.js index a5bdbc8a..111adf20 100644 --- a/test/integration/client/huge-numeric-tests.js +++ b/test/integration/client/huge-numeric-tests.js @@ -1,22 +1,22 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') const pool = new helper.pg.Pool() -pool.connect(assert.success(function(client, done) { - var types = require('pg-types'); - //1231 = numericOID - types.setTypeParser(1700, function(){ - return 'yes'; +pool.connect(assert.success(function (client, done) { + var types = require('pg-types') + // 1231 = numericOID + types.setTypeParser(1700, function () { + return 'yes' }) - types.setTypeParser(1700, 'binary', function(){ - return 'yes'; + types.setTypeParser(1700, 'binary', function () { + return 'yes' }) - var bignum = '294733346389144765940638005275322203805'; - client.query('CREATE TEMP TABLE bignumz(id numeric)'); - client.query('INSERT INTO bignumz(id) VALUES ($1)', [bignum]); - client.query('SELECT * FROM bignumz', assert.success(function(result) { + var bignum = '294733346389144765940638005275322203805' + client.query('CREATE TEMP TABLE bignumz(id numeric)') + client.query('INSERT INTO bignumz(id) VALUES ($1)', [bignum]) + client.query('SELECT * FROM bignumz', assert.success(function (result) { assert.equal(result.rows[0].id, 'yes') - done(); + done() pool.end() })) -})); +})) diff --git a/test/integration/client/json-type-parsing-tests.js b/test/integration/client/json-type-parsing-tests.js index 77c5469a..63684d96 100644 --- a/test/integration/client/json-type-parsing-tests.js +++ b/test/integration/client/json-type-parsing-tests.js @@ -1,28 +1,28 @@ -"use strict"; -var helper = require('./test-helper'); -var assert = require('assert'); +'use strict' +var helper = require('./test-helper') +var assert = require('assert') const pool = new helper.pg.Pool() pool.connect(assert.success(function (client, done) { helper.versionGTE(client, '9.2.0', assert.success(function (jsonSupported) { if (!jsonSupported) { - console.log('skip json test on older versions of postgres'); - done(); - return pool.end(); + console.log('skip json test on older versions of postgres') + done() + return pool.end() } - client.query('CREATE TEMP TABLE stuff(id SERIAL PRIMARY KEY, data JSON)'); - var value = { name: 'Brian', age: 250, alive: true, now: new Date() }; - client.query('INSERT INTO stuff (data) VALUES ($1)', [value]); + client.query('CREATE TEMP TABLE stuff(id SERIAL PRIMARY KEY, data JSON)') + var value = { name: 'Brian', age: 250, alive: true, now: new Date() } + client.query('INSERT INTO stuff (data) VALUES ($1)', [value]) client.query('SELECT * FROM stuff', assert.success(function (result) { - assert.equal(result.rows.length, 1); - assert.equal(typeof result.rows[0].data, 'object'); - var row = result.rows[0].data; - assert.strictEqual(row.name, value.name); - assert.strictEqual(row.age, value.age); - assert.strictEqual(row.alive, value.alive); - assert.equal(JSON.stringify(row.now), JSON.stringify(value.now)); - done(); + assert.equal(result.rows.length, 1) + assert.equal(typeof result.rows[0].data, 'object') + var row = result.rows[0].data + assert.strictEqual(row.name, value.name) + assert.strictEqual(row.age, value.age) + assert.strictEqual(row.alive, value.alive) + assert.equal(JSON.stringify(row.now), JSON.stringify(value.now)) + done() pool.end() - })); - })); -})); + })) + })) +})) diff --git a/test/integration/client/network-partition-tests.js b/test/integration/client/network-partition-tests.js index 704f7fdf..95eca8e7 100644 --- a/test/integration/client/network-partition-tests.js +++ b/test/integration/client/network-partition-tests.js @@ -1,11 +1,11 @@ -"use strict"; +'use strict' var buffers = require('../../test-buffers') var helper = require('./test-helper') var suite = new helper.Suite() var net = require('net') -var Server = function(response) { +var Server = function (response) { this.server = undefined this.socket = undefined this.response = response @@ -38,7 +38,7 @@ Server.prototype.start = function (cb) { var options = { host: 'localhost', - port: port, + port: port } this.server.listen(options.port, options.host, function () { cb(options) @@ -55,7 +55,7 @@ Server.prototype.close = function (cb) { var testServer = function (server, cb) { // wait for our server to start - server.start(function(options) { + server.start(function (options) { // connect a client to it var client = new helper.Client(options) client.connect() @@ -66,7 +66,7 @@ var testServer = function (server, cb) { }) // after 50 milliseconds, drop the client - setTimeout(function() { + setTimeout(function () { server.drop() }, 50) diff --git a/test/integration/client/no-data-tests.js b/test/integration/client/no-data-tests.js index a4ab36fb..46ea4566 100644 --- a/test/integration/client/no-data-tests.js +++ b/test/integration/client/no-data-tests.js @@ -1,32 +1,30 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') const suite = new helper.Suite() - -suite.test("noData message handling", function() { - - var client = helper.client(); +suite.test('noData message handling', function () { + var client = helper.client() var q = client.query({ name: 'boom', text: 'create temp table boom(id serial, size integer)' - }); + }) client.query({ name: 'insert', text: 'insert into boom(size) values($1)', values: [100] - }, function(err, result) { - if(err) { - console.log(err); - throw err; + }, function (err, result) { + if (err) { + console.log(err) + throw err } - }); + }) client.query({ name: 'insert', values: [101] - }); + }) var query = client.query({ name: 'fetch', @@ -35,7 +33,7 @@ suite.test("noData message handling", function() { }, (err, res) => { var row = res.rows[0] assert.strictEqual(row.size, 100) - }); + }) - client.on('drain', client.end.bind(client)); -}); + client.on('drain', client.end.bind(client)) +}) diff --git a/test/integration/client/no-row-result-tests.js b/test/integration/client/no-row-result-tests.js index 4ff28995..e52d113d 100644 --- a/test/integration/client/no-row-result-tests.js +++ b/test/integration/client/no-row-result-tests.js @@ -1,28 +1,28 @@ -"use strict"; -var helper = require("./test-helper"); -var pg = helper.pg; -const suite = new helper.Suite(); -const pool = new pg.Pool(); +'use strict' +var helper = require('./test-helper') +var pg = helper.pg +const suite = new helper.Suite() +const pool = new pg.Pool() -suite.test("can access results when no rows are returned", function (done) { +suite.test('can access results when no rows are returned', function (done) { var checkResult = function (result) { - assert(result.fields, "should have fields definition"); - assert.equal(result.fields.length, 1); - assert.equal(result.fields[0].name, "val"); - assert.equal(result.fields[0].dataTypeID, 25); - }; + assert(result.fields, 'should have fields definition') + assert.equal(result.fields.length, 1) + assert.equal(result.fields[0].name, 'val') + assert.equal(result.fields[0].dataTypeID, 25) + } pool.connect( assert.success(function (client, release) { - const q = new pg.Query("select $1::text as val limit 0", ["hi"]); + const q = new pg.Query('select $1::text as val limit 0', ['hi']) var query = client.query(q, assert.success(function (result) { - checkResult(result); - release(); - pool.end(done); + checkResult(result) + release() + pool.end(done) }) - ); + ) - assert.emits(query, "end", checkResult); + assert.emits(query, 'end', checkResult) }) - ); -}); + ) +}) diff --git a/test/integration/client/notice-tests.js b/test/integration/client/notice-tests.js index 9c682050..f3dc5090 100644 --- a/test/integration/client/notice-tests.js +++ b/test/integration/client/notice-tests.js @@ -1,34 +1,34 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') const suite = new helper.Suite() suite.test('emits notify message', function (done) { - var client = helper.client(); + var client = helper.client() client.query('LISTEN boom', assert.calls(function () { - var otherClient = helper.client(); + var otherClient = helper.client() var bothEmitted = -1 otherClient.query('LISTEN boom', assert.calls(function () { assert.emits(client, 'notification', function (msg) { - //make sure PQfreemem doesn't invalidate string pointers + // make sure PQfreemem doesn't invalidate string pointers setTimeout(function () { - assert.equal(msg.channel, 'boom'); - assert.ok(msg.payload == 'omg!' /*9.x*/ || msg.payload == '' /*8.x*/, "expected blank payload or correct payload but got " + msg.message) + assert.equal(msg.channel, 'boom') + assert.ok(msg.payload == 'omg!' /* 9.x */ || msg.payload == '' /* 8.x */, 'expected blank payload or correct payload but got ' + msg.message) client.end(++bothEmitted ? done : undefined) }, 100) - }); + }) assert.emits(otherClient, 'notification', function (msg) { - assert.equal(msg.channel, 'boom'); - otherClient.end(++bothEmitted ? done : undefined); - }); + assert.equal(msg.channel, 'boom') + otherClient.end(++bothEmitted ? done : undefined) + }) client.query("NOTIFY boom, 'omg!'", function (err, q) { if (err) { - //notify not supported with payload on 8.x - client.query("NOTIFY boom") + // notify not supported with payload on 8.x + client.query('NOTIFY boom') } - }); - })); - })); + }) + })) + })) }) // this test fails on travis due to their config @@ -37,8 +37,8 @@ suite.test('emits notice message', false, function (done) { console.error('need to get notice message working on native') return done() } - //TODO this doesn't work on all versions of postgres - var client = helper.client(); + // TODO this doesn't work on all versions of postgres + var client = helper.client() const text = ` DO language plpgsql $$ BEGIN @@ -47,10 +47,10 @@ END $$; ` client.query(text, () => { - client.end(); - }); + client.end() + }) assert.emits(client, 'notice', function (notice) { - assert.ok(notice != null); - done(); - }); + assert.ok(notice != null) + done() + }) }) diff --git a/test/integration/client/parse-int-8-tests.js b/test/integration/client/parse-int-8-tests.js index 920f5558..19368904 100644 --- a/test/integration/client/parse-int-8-tests.js +++ b/test/integration/client/parse-int-8-tests.js @@ -1,29 +1,29 @@ -"use strict"; +'use strict' -var helper = require('../test-helper'); -var pg = helper.pg; +var helper = require('../test-helper') +var pg = helper.pg const suite = new helper.Suite() const pool = new pg.Pool(helper.config) -suite.test('ability to turn on and off parser', function() { - if(helper.args.binary) return false; - pool.connect(assert.success(function(client, done) { - pg.defaults.parseInt8 = true; - client.query('CREATE TEMP TABLE asdf(id SERIAL PRIMARY KEY)'); - client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function(res) { - assert.strictEqual(0, res.rows[0].count); - assert.strictEqual(1, res.rows[0].array[0]); - assert.strictEqual(2, res.rows[0].array[1]); - assert.strictEqual(3, res.rows[0].array[2]); - pg.defaults.parseInt8 = false; - client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function(res) { - done(); - assert.strictEqual('0', res.rows[0].count); - assert.strictEqual('1', res.rows[0].array[0]); - assert.strictEqual('2', res.rows[0].array[1]); - assert.strictEqual('3', res.rows[0].array[2]); - pool.end(); - })); - })); - })); -}); +suite.test('ability to turn on and off parser', function () { + if (helper.args.binary) return false + pool.connect(assert.success(function (client, done) { + pg.defaults.parseInt8 = true + client.query('CREATE TEMP TABLE asdf(id SERIAL PRIMARY KEY)') + client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function (res) { + assert.strictEqual(0, res.rows[0].count) + assert.strictEqual(1, res.rows[0].array[0]) + assert.strictEqual(2, res.rows[0].array[1]) + assert.strictEqual(3, res.rows[0].array[2]) + pg.defaults.parseInt8 = false + client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function (res) { + done() + assert.strictEqual('0', res.rows[0].count) + assert.strictEqual('1', res.rows[0].array[0]) + assert.strictEqual('2', res.rows[0].array[1]) + assert.strictEqual('3', res.rows[0].array[2]) + pool.end() + })) + })) + })) +}) diff --git a/test/integration/client/prepared-statement-tests.js b/test/integration/client/prepared-statement-tests.js index 9b00f9d8..6fdf72f6 100644 --- a/test/integration/client/prepared-statement-tests.js +++ b/test/integration/client/prepared-statement-tests.js @@ -1,136 +1,132 @@ -"use strict"; -var helper = require('./test-helper'); -var Query = helper.pg.Query; +'use strict' +var helper = require('./test-helper') +var Query = helper.pg.Query var suite = new helper.Suite() -;(function() { +;(function () { + var client = helper.client() + client.on('drain', client.end.bind(client)) - var client = helper.client(); - client.on('drain', client.end.bind(client)); + var queryName = 'user by age and like name' + var parseCount = 0 - var queryName = "user by age and like name"; - var parseCount = 0; - - suite.test("first named prepared statement", function(done) { + suite.test('first named prepared statement', function (done) { var query = client.query(new Query({ text: 'select name from person where age <= $1 and name LIKE $2', values: [20, 'Bri%'], name: queryName - })); + })) - assert.emits(query, 'row', function(row) { - assert.equal(row.name, 'Brian'); - }); + assert.emits(query, 'row', function (row) { + assert.equal(row.name, 'Brian') + }) query.on('end', () => done()) - }); + }) - suite.test("second named prepared statement with same name & text", function(done) { + suite.test('second named prepared statement with same name & text', function (done) { var cachedQuery = client.query(new Query({ text: 'select name from person where age <= $1 and name LIKE $2', name: queryName, values: [10, 'A%'] - })); + })) - assert.emits(cachedQuery, 'row', function(row) { - assert.equal(row.name, 'Aaron'); - }); + assert.emits(cachedQuery, 'row', function (row) { + assert.equal(row.name, 'Aaron') + }) cachedQuery.on('end', () => done()) - }); + }) - suite.test("with same name, but without query text", function(done) { + suite.test('with same name, but without query text', function (done) { var q = client.query(new Query({ name: queryName, values: [30, '%n%'] - })); + })) - assert.emits(q, 'row', function(row) { - assert.equal(row.name, "Aaron"); + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Aaron') // test second row is emitted as well - assert.emits(q, 'row', function(row) { - assert.equal(row.name, "Brian"); - }); - }); + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Brian') + }) + }) q.on('end', () => done()) - }); -})(); + }) +})() -;(function() { - var statementName = "differ"; - var statement1 = "select count(*)::int4 as count from person"; - var statement2 = "select count(*)::int4 as count from person where age < $1"; +;(function () { + var statementName = 'differ' + var statement1 = 'select count(*)::int4 as count from person' + var statement2 = 'select count(*)::int4 as count from person where age < $1' - var client1 = helper.client(); - var client2 = helper.client(); - - suite.test("client 1 execution", function(done) { + var client1 = helper.client() + var client2 = helper.client() + suite.test('client 1 execution', function (done) { var query = client1.query({ name: statementName, text: statement1 }, (err, res) => { - assert(!err); - assert.equal(res.rows[0].count, 26); + assert(!err) + assert.equal(res.rows[0].count, 26) done() - }); - }); + }) + }) - suite.test('client 2 execution', function(done) { + suite.test('client 2 execution', function (done) { var query = client2.query(new Query({ name: statementName, text: statement2, values: [11] - })); + })) - assert.emits(query, 'row', function(row) { - assert.equal(row.count, 1); - }); + assert.emits(query, 'row', function (row) { + assert.equal(row.count, 1) + }) - assert.emits(query, 'end', function() { - done(); - }); - }); + assert.emits(query, 'end', function () { + done() + }) + }) suite.test('clean up clients', () => { return client1.end().then(() => client2.end()) - }); + }) +})() -})(); - -;(function() { - var client = helper.client(); - client.query('CREATE TEMP TABLE zoom(name varchar(100));'); - client.query("INSERT INTO zoom (name) VALUES ('zed')"); - client.query("INSERT INTO zoom (name) VALUES ('postgres')"); - client.query("INSERT INTO zoom (name) VALUES ('node postgres')"); +;(function () { + var client = helper.client() + client.query('CREATE TEMP TABLE zoom(name varchar(100));') + client.query("INSERT INTO zoom (name) VALUES ('zed')") + client.query("INSERT INTO zoom (name) VALUES ('postgres')") + client.query("INSERT INTO zoom (name) VALUES ('node postgres')") var checkForResults = function (q) { assert.emits(q, 'row', function (row) { - assert.equal(row.name, 'node postgres'); + assert.equal(row.name, 'node postgres') assert.emits(q, 'row', function (row) { - assert.equal(row.name, 'postgres'); + assert.equal(row.name, 'postgres') assert.emits(q, 'row', function (row) { - assert.equal(row.name, 'zed'); + assert.equal(row.name, 'zed') }) - }); + }) }) - }; + } suite.test('with small row count', function (done) { var query = client.query(new Query({ name: 'get names', - text: "SELECT name FROM zoom ORDER BY name", + text: 'SELECT name FROM zoom ORDER BY name', rows: 1 - }, done)); - - checkForResults(query); + }, done)) + checkForResults(query) }) suite.test('with large row count', function (done) { @@ -139,7 +135,7 @@ var suite = new helper.Suite() text: 'SELECT name FROM zoom ORDER BY name', rows: 1000 }, done)) - checkForResults(query); + checkForResults(query) }) suite.test('cleanup', () => client.end()) diff --git a/test/integration/client/promise-api-tests.js b/test/integration/client/promise-api-tests.js index 45083a1b..d0613260 100644 --- a/test/integration/client/promise-api-tests.js +++ b/test/integration/client/promise-api-tests.js @@ -1,8 +1,8 @@ -"use strict"; -'use strict'; +'use strict' +'use strict' const helper = require('./test-helper') -const pg = helper.pg; +const pg = helper.pg const suite = new helper.Suite() @@ -24,7 +24,6 @@ suite.test('valid connection completes promise', () => { }) }) - suite.test('invalid connection rejects promise', (done) => { const client = new pg.Client({ host: 'alksdjflaskdfj' }) return client.connect() diff --git a/test/integration/client/query-as-promise-tests.js b/test/integration/client/query-as-promise-tests.js index 52487a7d..625a3339 100644 --- a/test/integration/client/query-as-promise-tests.js +++ b/test/integration/client/query-as-promise-tests.js @@ -1,8 +1,8 @@ -"use strict"; -var helper = require(__dirname + '/../test-helper'); -var pg = helper.pg; +'use strict' +var helper = require(__dirname + '/../test-helper') +var pg = helper.pg -process.on('unhandledRejection', function(e) { +process.on('unhandledRejection', function (e) { console.error(e, e.stack) process.exit(1) }) diff --git a/test/integration/client/query-column-names-tests.js b/test/integration/client/query-column-names-tests.js index a670bae3..cc5a42b5 100644 --- a/test/integration/client/query-column-names-tests.js +++ b/test/integration/client/query-column-names-tests.js @@ -1,15 +1,15 @@ -"use strict"; -var helper = require(__dirname + '/../test-helper'); -var pg = helper.pg; +'use strict' +var helper = require(__dirname + '/../test-helper') +var pg = helper.pg new helper.Suite().test('support for complex column names', function () { const pool = new pg.Pool() pool.connect(assert.success(function (client, done) { - client.query("CREATE TEMP TABLE t ( \"complex''column\" TEXT )"); + client.query("CREATE TEMP TABLE t ( \"complex''column\" TEXT )") client.query('SELECT * FROM t', assert.success(function (res) { - done(); - assert.strictEqual(res.fields[0].name, "complex''column"); - pool.end(); - })); - })); -}); + done() + assert.strictEqual(res.fields[0].name, "complex''column") + pool.end() + })) + })) +}) diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index f16f96f6..a29c41a0 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -1,99 +1,98 @@ -"use strict"; -var helper = require('./test-helper'); -var Query = helper.pg.Query; -var util = require('util'); +'use strict' +var helper = require('./test-helper') +var Query = helper.pg.Query +var util = require('util') -var suite = new helper.Suite(); +var suite = new helper.Suite() -suite.test('client end during query execution of prepared statement', function(done) { - var client = new Client(); - client.connect(assert.success(function() { - - var sleepQuery = 'select pg_sleep($1)'; +suite.test('client end during query execution of prepared statement', function (done) { + var client = new Client() + client.connect(assert.success(function () { + var sleepQuery = 'select pg_sleep($1)' var queryConfig = { name: 'sleep query', text: sleepQuery, - values: [5], + values: [5] } var queryInstance = new Query(queryConfig, assert.calls(function (err, result) { - assert.equal(err.message, 'Connection terminated'); - done(); + assert.equal(err.message, 'Connection terminated') + done() })) - var query1 = client.query(queryInstance); + var query1 = client.query(queryInstance) query1.on('error', function (err) { - assert.fail('Prepared statement should not emit error'); - }); + assert.fail('Prepared statement should not emit error') + }) query1.on('row', function (row) { - assert.fail('Prepared statement should not emit row'); - }); + assert.fail('Prepared statement should not emit row') + }) query1.on('end', function (err) { - assert.fail('Prepared statement when executed should not return before being killed'); - }); + assert.fail('Prepared statement when executed should not return before being killed') + }) - client.end(); - })); -}); + client.end() + })) +}) -function killIdleQuery(targetQuery, cb) { - var client2 = new Client(helper.args); +function killIdleQuery (targetQuery, cb) { + var client2 = new Client(helper.args) var pidColName = 'procpid' - var queryColName = 'current_query'; - client2.connect(assert.success(function() { - helper.versionGTE(client2, '9.2.0', assert.success(function(isGreater) { - if(isGreater) { - pidColName = 'pid'; - queryColName = 'query'; + var queryColName = 'current_query' + client2.connect(assert.success(function () { + helper.versionGTE(client2, '9.2.0', assert.success(function (isGreater) { + if (isGreater) { + pidColName = 'pid' + queryColName = 'query' } - var killIdleQuery = "SELECT " + pidColName + ", (SELECT pg_terminate_backend(" + pidColName + ")) AS killed FROM pg_stat_activity WHERE " + queryColName + " = $1"; - client2.query(killIdleQuery, [targetQuery], assert.calls(function(err, res) { - assert.ifError(err); - assert.equal(res.rows.length, 1); - client2.end(cb); - assert.emits(client2, 'end'); - })); - })); - })); + var killIdleQuery = 'SELECT ' + pidColName + ', (SELECT pg_terminate_backend(' + pidColName + ')) AS killed FROM pg_stat_activity WHERE ' + queryColName + ' = $1' + client2.query(killIdleQuery, [targetQuery], assert.calls(function (err, res) { + assert.ifError(err) + assert.equal(res.rows.length, 1) + client2.end(cb) + assert.emits(client2, 'end') + })) + })) + })) } -suite.test('query killed during query execution of prepared statement', function(done) { - if(helper.args.native) { - return done(); +suite.test('query killed during query execution of prepared statement', function (done) { + if (helper.args.native) { + return done() } - var client = new Client(helper.args); - client.connect(assert.success(function() { - var sleepQuery = 'select pg_sleep($1)'; + var client = new Client(helper.args) + client.connect(assert.success(function () { + var sleepQuery = 'select pg_sleep($1)' const queryConfig = { name: 'sleep query', text: sleepQuery, - values: [5], - }; + values: [5] + } // client should emit an error because it is unexpectedly disconnected assert.emits(client, 'error') - var query1 = client.query(new Query(queryConfig), assert.calls(function(err, result) { - assert.equal(err.message, 'terminating connection due to administrator command'); - })); + var query1 = client.query(new Query(queryConfig), assert.calls(function (err, result) { + assert.equal(err.message, 'terminating connection due to administrator command') + })) - query1.on('error', function(err) { - assert.fail('Prepared statement should not emit error'); - }); + query1.on('error', function (err) { + assert.fail('Prepared statement should not emit error') + }) - query1.on('row', function(row) { - assert.fail('Prepared statement should not emit row'); - }); + query1.on('row', function (row) { + assert.fail('Prepared statement should not emit row') + }) - query1.on('end', function(err) { - assert.fail('Prepared statement when executed should not return before being killed'); - }); + query1.on('end', function (err) { + assert.fail('Prepared statement when executed should not return before being killed') + }) - killIdleQuery(sleepQuery, done); - })); -}); + killIdleQuery(sleepQuery, done) + })) +}) diff --git a/test/integration/client/quick-disconnect-tests.js b/test/integration/client/quick-disconnect-tests.js index 76a825ac..066411fc 100644 --- a/test/integration/client/quick-disconnect-tests.js +++ b/test/integration/client/quick-disconnect-tests.js @@ -1,8 +1,8 @@ -"use strict"; -//test for issue #320 +'use strict' +// test for issue #320 // -var helper = require('./test-helper'); +var helper = require('./test-helper') -var client = new helper.pg.Client(helper.config); -client.connect(); -client.end(); +var client = new helper.pg.Client(helper.config) +client.connect() +client.end() diff --git a/test/integration/client/result-metadata-tests.js b/test/integration/client/result-metadata-tests.js index 5b683a3a..0f2e7e76 100644 --- a/test/integration/client/result-metadata-tests.js +++ b/test/integration/client/result-metadata-tests.js @@ -1,32 +1,32 @@ -"use strict"; -var helper = require("./test-helper"); -var pg = helper.pg; +'use strict' +var helper = require('./test-helper') +var pg = helper.pg const pool = new pg.Pool() -new helper.Suite().test('should return insert metadata', function() { - pool.connect(assert.calls(function(err, client, done) { - assert(!err); +new helper.Suite().test('should return insert metadata', function () { + pool.connect(assert.calls(function (err, client, done) { + assert(!err) - helper.versionGTE(client, '9.0.0', assert.success(function(hasRowCount) { - client.query("CREATE TEMP TABLE zugzug(name varchar(10))", assert.calls(function(err, result) { - assert(!err); - assert.equal(result.oid, null); - assert.equal(result.command, 'CREATE'); + helper.versionGTE(client, '9.0.0', assert.success(function (hasRowCount) { + client.query('CREATE TEMP TABLE zugzug(name varchar(10))', assert.calls(function (err, result) { + assert(!err) + assert.equal(result.oid, null) + assert.equal(result.command, 'CREATE') - var q = client.query("INSERT INTO zugzug(name) VALUES('more work?')", assert.calls(function(err, result) { - assert(!err); - assert.equal(result.command, "INSERT"); - assert.equal(result.rowCount, 1); + var q = client.query("INSERT INTO zugzug(name) VALUES('more work?')", assert.calls(function (err, result) { + assert(!err) + assert.equal(result.command, 'INSERT') + assert.equal(result.rowCount, 1) - client.query('SELECT * FROM zugzug', assert.calls(function(err, result) { - assert(!err); - if(hasRowCount) assert.equal(result.rowCount, 1); - assert.equal(result.command, 'SELECT'); - done(); - process.nextTick(pool.end.bind(pool)); - })); - })); - })); - })); - })); -}); + client.query('SELECT * FROM zugzug', assert.calls(function (err, result) { + assert(!err) + if (hasRowCount) assert.equal(result.rowCount, 1) + assert.equal(result.command, 'SELECT') + done() + process.nextTick(pool.end.bind(pool)) + })) + })) + })) + })) + })) +}) diff --git a/test/integration/client/results-as-array-tests.js b/test/integration/client/results-as-array-tests.js index 45398c05..b6b00ef7 100644 --- a/test/integration/client/results-as-array-tests.js +++ b/test/integration/client/results-as-array-tests.js @@ -1,31 +1,31 @@ -"use strict"; -var util = require('util'); -var helper = require('./test-helper'); +'use strict' +var util = require('util') +var helper = require('./test-helper') -var Client = helper.Client; +var Client = helper.Client -var conInfo = helper.config; +var conInfo = helper.config -test('returns results as array', function() { - var client = new Client(conInfo); - var checkRow = function(row) { - assert(util.isArray(row), 'row should be an array'); - assert.equal(row.length, 4); - assert.equal(row[0].getFullYear(), new Date().getFullYear()); - assert.strictEqual(row[1], 1); - assert.strictEqual(row[2], 'hai'); - assert.strictEqual(row[3], null); +test('returns results as array', function () { + var client = new Client(conInfo) + var checkRow = function (row) { + assert(util.isArray(row), 'row should be an array') + assert.equal(row.length, 4) + assert.equal(row[0].getFullYear(), new Date().getFullYear()) + assert.strictEqual(row[1], 1) + assert.strictEqual(row[2], 'hai') + assert.strictEqual(row[3], null) } - client.connect(assert.success(function() { + client.connect(assert.success(function () { var config = { text: 'SELECT NOW(), 1::int, $1::text, null', values: ['hai'], rowMode: 'array' - }; - var query = client.query(config, assert.success(function(result) { - assert.equal(result.rows.length, 1); - checkRow(result.rows[0]); - client.end(); - })); - })); -}); + } + var query = client.query(config, assert.success(function (result) { + assert.equal(result.rows.length, 1) + checkRow(result.rows[0]) + client.end() + })) + })) +}) diff --git a/test/integration/client/row-description-on-results-tests.js b/test/integration/client/row-description-on-results-tests.js index 3d146bd6..108e5197 100644 --- a/test/integration/client/row-description-on-results-tests.js +++ b/test/integration/client/row-description-on-results-tests.js @@ -1,38 +1,38 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') -var Client = helper.Client; +var Client = helper.Client -var conInfo = helper.config; +var conInfo = helper.config -var checkResult = function(result) { - assert(result.fields); - assert.equal(result.fields.length, 3); - var fields = result.fields; - assert.equal(fields[0].name, 'now'); - assert.equal(fields[1].name, 'num'); - assert.equal(fields[2].name, 'texty'); - assert.equal(fields[0].dataTypeID, 1184); - assert.equal(fields[1].dataTypeID, 23); - assert.equal(fields[2].dataTypeID, 25); -}; +var checkResult = function (result) { + assert(result.fields) + assert.equal(result.fields.length, 3) + var fields = result.fields + assert.equal(fields[0].name, 'now') + assert.equal(fields[1].name, 'num') + assert.equal(fields[2].name, 'texty') + assert.equal(fields[0].dataTypeID, 1184) + assert.equal(fields[1].dataTypeID, 23) + assert.equal(fields[2].dataTypeID, 25) +} -test('row descriptions on result object', function() { - var client = new Client(conInfo); - client.connect(assert.success(function() { - client.query('SELECT NOW() as now, 1::int as num, $1::text as texty', ["hello"], assert.success(function(result) { - checkResult(result); - client.end(); - })); - })); -}); +test('row descriptions on result object', function () { + var client = new Client(conInfo) + client.connect(assert.success(function () { + client.query('SELECT NOW() as now, 1::int as num, $1::text as texty', ['hello'], assert.success(function (result) { + checkResult(result) + client.end() + })) + })) +}) -test('row description on no rows', function() { - var client = new Client(conInfo); - client.connect(assert.success(function() { - client.query('SELECT NOW() as now, 1::int as num, $1::text as texty LIMIT 0', ["hello"], assert.success(function(result) { - checkResult(result); - client.end(); - })); - })); -}); +test('row description on no rows', function () { + var client = new Client(conInfo) + client.connect(assert.success(function () { + client.query('SELECT NOW() as now, 1::int as num, $1::text as texty LIMIT 0', ['hello'], assert.success(function (result) { + checkResult(result) + client.end() + })) + })) +}) diff --git a/test/integration/client/simple-query-tests.js b/test/integration/client/simple-query-tests.js index 6ae957dc..e46958f2 100644 --- a/test/integration/client/simple-query-tests.js +++ b/test/integration/client/simple-query-tests.js @@ -1,93 +1,91 @@ -"use strict"; -var helper = require("./test-helper"); -var Query = helper.pg.Query; +'use strict' +var helper = require('./test-helper') +var Query = helper.pg.Query -//before running this test make sure you run the script create-test-tables -test("simple query interface", function() { +// before running this test make sure you run the script create-test-tables +test('simple query interface', function () { + var client = helper.client() - var client = helper.client(); + var query = client.query(new Query('select name from person order by name')) - var query = client.query(new Query("select name from person order by name")); + client.on('drain', client.end.bind(client)) - client.on('drain', client.end.bind(client)); - - var rows = []; - query.on('row', function(row, result) { - assert.ok(result); - rows.push(row['name']); - }); - query.once('row', function(row) { + var rows = [] + query.on('row', function (row, result) { + assert.ok(result) + rows.push(row['name']) + }) + query.once('row', function (row) { test('Can iterate through columns', function () { - var columnCount = 0; + var columnCount = 0 for (var column in row) { - columnCount++; + columnCount++ } if ('length' in row) { - assert.lengthIs(row, columnCount, 'Iterating through the columns gives a different length from calling .length.'); + assert.lengthIs(row, columnCount, 'Iterating through the columns gives a different length from calling .length.') } - }); - }); + }) + }) - assert.emits(query, 'end', function() { - test("returned right number of rows", function() { - assert.lengthIs(rows, 26); - }); - test("row ordering", function(){ - assert.equal(rows[0], "Aaron"); - assert.equal(rows[25], "Zanzabar"); - }); - }); -}); + assert.emits(query, 'end', function () { + test('returned right number of rows', function () { + assert.lengthIs(rows, 26) + }) + test('row ordering', function () { + assert.equal(rows[0], 'Aaron') + assert.equal(rows[25], 'Zanzabar') + }) + }) +}) -test("prepared statements do not mutate params", function() { - - var client = helper.client(); +test('prepared statements do not mutate params', function () { + var client = helper.client() var params = [1] - var query = client.query(new Query("select name from person where $1 = 1 order by name", params)); + var query = client.query(new Query('select name from person where $1 = 1 order by name', params)) assert.deepEqual(params, [1]) - client.on('drain', client.end.bind(client)); + client.on('drain', client.end.bind(client)) - query.on('row', function(row, result) { - assert.ok(result); - result.addRow(row); - }); + query.on('row', function (row, result) { + assert.ok(result) + result.addRow(row) + }) - query.on('end', function(result) { - assert.lengthIs(result.rows, 26, "result returned wrong number of rows"); - assert.lengthIs(result.rows, result.rowCount); - assert.equal(result.rows[0].name, "Aaron"); - assert.equal(result.rows[25].name, "Zanzabar"); - }); -}); + query.on('end', function (result) { + assert.lengthIs(result.rows, 26, 'result returned wrong number of rows') + assert.lengthIs(result.rows, result.rowCount) + assert.equal(result.rows[0].name, 'Aaron') + assert.equal(result.rows[25].name, 'Zanzabar') + }) +}) -test("multiple simple queries", function() { - var client = helper.client(); +test('multiple simple queries', function () { + var client = helper.client() client.query({ text: "create temp table bang(id serial, name varchar(5));insert into bang(name) VALUES('boom');"}) - client.query("insert into bang(name) VALUES ('yes');"); - var query = client.query(new Query("select name from bang")); - assert.emits(query, 'row', function(row) { - assert.equal(row['name'], 'boom'); - assert.emits(query, 'row', function(row) { - assert.equal(row['name'],'yes'); - }); - }); - client.on('drain', client.end.bind(client)); -}); + client.query("insert into bang(name) VALUES ('yes');") + var query = client.query(new Query('select name from bang')) + assert.emits(query, 'row', function (row) { + assert.equal(row['name'], 'boom') + assert.emits(query, 'row', function (row) { + assert.equal(row['name'], 'yes') + }) + }) + client.on('drain', client.end.bind(client)) +}) -test("multiple select statements", function() { - var client = helper.client(); - client.query("create temp table boom(age integer); insert into boom(age) values(1); insert into boom(age) values(2); insert into boom(age) values(3)"); - client.query({text: "create temp table bang(name varchar(5)); insert into bang(name) values('zoom');"}); - var result = client.query(new Query({text: "select age from boom where age < 2; select name from bang"})); - assert.emits(result, 'row', function(row) { - assert.strictEqual(row['age'], 1); - assert.emits(result, 'row', function(row) { - assert.strictEqual(row['name'], 'zoom'); - }); - }); - client.on('drain', client.end.bind(client)); -}); +test('multiple select statements', function () { + var client = helper.client() + client.query('create temp table boom(age integer); insert into boom(age) values(1); insert into boom(age) values(2); insert into boom(age) values(3)') + client.query({text: "create temp table bang(name varchar(5)); insert into bang(name) values('zoom');"}) + var result = client.query(new Query({text: 'select age from boom where age < 2; select name from bang'})) + assert.emits(result, 'row', function (row) { + assert.strictEqual(row['age'], 1) + assert.emits(result, 'row', function (row) { + assert.strictEqual(row['name'], 'zoom') + }) + }) + client.on('drain', client.end.bind(client)) +}) diff --git a/test/integration/client/ssl-tests.js b/test/integration/client/ssl-tests.js index 7523dfd3..bd864d1e 100644 --- a/test/integration/client/ssl-tests.js +++ b/test/integration/client/ssl-tests.js @@ -1,15 +1,15 @@ -"use strict"; -var pg = require(__dirname + '/../../../lib'); -var config = require(__dirname + '/test-helper').config; -test('can connect with ssl', function() { - return false; +'use strict' +var pg = require(__dirname + '/../../../lib') +var config = require(__dirname + '/test-helper').config +test('can connect with ssl', function () { + return false config.ssl = { rejectUnauthorized: false - }; - pg.connect(config, assert.success(function(client) { - return false; - client.query('SELECT NOW()', assert.success(function() { - pg.end(); - })); - })); -}); + } + pg.connect(config, assert.success(function (client) { + return false + client.query('SELECT NOW()', assert.success(function () { + pg.end() + })) + })) +}) diff --git a/test/integration/client/test-helper.js b/test/integration/client/test-helper.js index 027477a1..14f8134e 100644 --- a/test/integration/client/test-helper.js +++ b/test/integration/client/test-helper.js @@ -1,4 +1,4 @@ -"use strict"; -var helper = require('./../test-helper'); +'use strict' +var helper = require('./../test-helper') -module.exports = helper; +module.exports = helper diff --git a/test/integration/client/timezone-tests.js b/test/integration/client/timezone-tests.js index 1f0e0698..c9f6a8c8 100644 --- a/test/integration/client/timezone-tests.js +++ b/test/integration/client/timezone-tests.js @@ -1,34 +1,34 @@ -"use strict"; -var helper = require('./../test-helper'); -var exec = require('child_process').exec; +'use strict' +var helper = require('./../test-helper') +var exec = require('child_process').exec -var oldTz = process.env.TZ; -process.env.TZ = 'Europe/Berlin'; +var oldTz = process.env.TZ +process.env.TZ = 'Europe/Berlin' -var date = new Date(); +var date = new Date() const pool = new helper.pg.Pool() const suite = new helper.Suite() pool.connect(function (err, client, done) { - assert(!err); + assert(!err) suite.test('timestamp without time zone', function (cb) { - client.query("SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS \"val\"", [date], function (err, result) { - assert(!err); - assert.equal(result.rows[0].val.getTime(), date.getTime()); + client.query('SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS "val"', [date], function (err, result) { + assert(!err) + assert.equal(result.rows[0].val.getTime(), date.getTime()) cb() }) }) suite.test('timestamp with time zone', function (cb) { - client.query("SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS \"val\"", [date], function (err, result) { - assert(!err); - assert.equal(result.rows[0].val.getTime(), date.getTime()); + client.query('SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS "val"', [date], function (err, result) { + assert(!err) + assert.equal(result.rows[0].val.getTime(), date.getTime()) - done(); + done() pool.end(cb) - process.env.TZ = oldTz; - }); - }); -}); + process.env.TZ = oldTz + }) + }) +}) diff --git a/test/integration/client/transaction-tests.js b/test/integration/client/transaction-tests.js index 4668a427..560067ba 100644 --- a/test/integration/client/transaction-tests.js +++ b/test/integration/client/transaction-tests.js @@ -1,49 +1,48 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') const suite = new helper.Suite() const pg = helper.pg const client = new pg.Client() client.connect(assert.success(function () { - - client.query('begin'); + client.query('begin') var getZed = { text: 'SELECT * FROM person WHERE name = $1', values: ['Zed'] - }; + } suite.test('name should not exist in the database', function (done) { client.query(getZed, assert.calls(function (err, result) { - assert(!err); - assert.empty(result.rows); + assert(!err) + assert.empty(result.rows) done() })) }) suite.test('can insert name', (done) => { - client.query("INSERT INTO person(name, age) VALUES($1, $2)", ['Zed', 270], assert.calls(function (err, result) { + client.query('INSERT INTO person(name, age) VALUES($1, $2)', ['Zed', 270], assert.calls(function (err, result) { assert(!err) done() - })); + })) }) suite.test('name should exist in the database', function (done) { client.query(getZed, assert.calls(function (err, result) { - assert(!err); - assert.equal(result.rows[0].name, 'Zed'); + assert(!err) + assert.equal(result.rows[0].name, 'Zed') done() })) }) suite.test('rollback', (done) => { - client.query('rollback', done); + client.query('rollback', done) }) suite.test('name should not exist in the database', function (done) { client.query(getZed, assert.calls(function (err, result) { - assert(!err); - assert.empty(result.rows); + assert(!err) + assert.empty(result.rows) client.end(done) })) }) @@ -52,26 +51,26 @@ client.connect(assert.success(function () { suite.test('gh#36', function (cb) { const pool = new pg.Pool() pool.connect(assert.success(function (client, done) { - client.query("BEGIN"); + client.query('BEGIN') client.query({ name: 'X', - text: "SELECT $1::INTEGER", + text: 'SELECT $1::INTEGER', values: [0] }, assert.calls(function (err, result) { - if (err) throw err; - assert.equal(result.rows.length, 1); + if (err) throw err + assert.equal(result.rows.length, 1) })) client.query({ name: 'X', - text: "SELECT $1::INTEGER", + text: 'SELECT $1::INTEGER', values: [0] }, assert.calls(function (err, result) { - if (err) throw err; - assert.equal(result.rows.length, 1); + if (err) throw err + assert.equal(result.rows.length, 1) })) - client.query("COMMIT", function () { - done(); + client.query('COMMIT', function () { + done() pool.end(cb) }) - })); + })) }) diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index 2aaffbc4..44ac8963 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -1,51 +1,49 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); -var pg = helper.pg; -var sink; +'use strict' +var helper = require(__dirname + '/test-helper') +var pg = helper.pg +var sink const suite = new helper.Suite() var testForTypeCoercion = function (type) { const pool = new pg.Pool() suite.test(`test type coercion ${type.name}`, (cb) => { pool.connect(function (err, client, done) { - assert(!err); - client.query("create temp table test_type(col " + type.name + ")", assert.calls(function (err, result) { - assert(!err); + assert(!err) + client.query('create temp table test_type(col ' + type.name + ')', assert.calls(function (err, result) { + assert(!err) type.values.forEach(function (val) { - var insertQuery = client.query('insert into test_type(col) VALUES($1)', [val], assert.calls(function (err, result) { - assert(!err); - })); + assert(!err) + })) var query = client.query(new pg.Query({ name: 'get type ' + type.name, text: 'select col from test_type' - })); + })) query.on('error', function (err) { - console.log(err); - throw err; - }); + console.log(err) + throw err + }) assert.emits(query, 'row', function (row) { - var expected = val + " (" + typeof val + ")"; - var returned = row.col + " (" + typeof row.col + ")"; - assert.strictEqual(row.col, val, "expected " + type.name + " of " + expected + " but got " + returned); - }, "row should have been called for " + type.name + " of " + val); + var expected = val + ' (' + typeof val + ')' + var returned = row.col + ' (' + typeof row.col + ')' + assert.strictEqual(row.col, val, 'expected ' + type.name + ' of ' + expected + ' but got ' + returned) + }, 'row should have been called for ' + type.name + ' of ' + val) - client.query('delete from test_type'); - }); + client.query('delete from test_type') + }) client.query('drop table test_type', function () { - done(); + done() pool.end(cb) - }); - })); + }) + })) }) - }) -}; +} var types = [{ name: 'integer', @@ -101,96 +99,95 @@ var types = [{ }, { name: 'time', values: ['13:12:12.321', null] -}]; +}] // 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, 'numeric': 1, 'bigint': 1 }); - }); + return !(type.name in { 'real': 1, 'timetz': 1, 'time': 1, 'numeric': 1, 'bigint': 1 }) + }) } -var valueCount = 0; +var valueCount = 0 types.forEach(function (type) { testForTypeCoercion(type) -}); +}) -suite.test("timestampz round trip", function (cb) { - var now = new Date(); - var client = helper.client(); - client.query("create temp table date_tests(name varchar(10), tstz timestamptz(3))"); +suite.test('timestampz round trip', function (cb) { + var now = new Date() + var client = helper.client() + client.query('create temp table date_tests(name varchar(10), tstz timestamptz(3))') client.query({ - text: "insert into date_tests(name, tstz)VALUES($1, $2)", + text: 'insert into date_tests(name, tstz)VALUES($1, $2)', name: 'add date', values: ['now', now] - }); + }) var result = client.query(new pg.Query({ name: 'get date', text: 'select * from date_tests where name = $1', values: ['now'] - })); + })) assert.emits(result, 'row', function (row) { - var date = row.tstz; - assert.equal(date.getYear(), now.getYear()); - assert.equal(date.getMonth(), now.getMonth()); - assert.equal(date.getDate(), now.getDate()); - assert.equal(date.getHours(), now.getHours()); - assert.equal(date.getMinutes(), now.getMinutes()); - assert.equal(date.getSeconds(), now.getSeconds()); - assert.equal(date.getMilliseconds(), now.getMilliseconds()); - }); + var date = row.tstz + assert.equal(date.getYear(), now.getYear()) + assert.equal(date.getMonth(), now.getMonth()) + assert.equal(date.getDate(), now.getDate()) + assert.equal(date.getHours(), now.getHours()) + assert.equal(date.getMinutes(), now.getMinutes()) + assert.equal(date.getSeconds(), now.getSeconds()) + assert.equal(date.getMilliseconds(), now.getMilliseconds()) + }) client.on('drain', () => { client.end(cb) - }); -}); + }) +}) suite.test('selecting nulls', cb => { const pool = new pg.Pool() pool.connect(assert.calls(function (err, client, done) { - assert.ifError(err); + assert.ifError(err) client.query('select null as res;', assert.calls(function (err, res) { - assert(!err); + assert(!err) assert.strictEqual(res.rows[0].res, null) })) client.query('select 7 <> $1 as res;', [null], function (err, res) { - assert(!err); - assert.strictEqual(res.rows[0].res, null); - done(); + assert(!err) + assert.strictEqual(res.rows[0].res, null) + done() pool.end(cb) }) })) }) suite.test('date range extremes', function (done) { - var client = helper.client(); + var client = helper.client() // Set the server timeszone to the same as used for the test, // otherwise (if server's timezone is ahead of GMT) in // textParsers.js::parseDate() the timezone offest is added to the date; // in the case of "275760-09-13 00:00:00 GMT" the timevalue overflows. client.query('SET TIMEZONE TO GMT', assert.success(function (res) { - // PostgreSQL supports date range of 4713 BCE to 294276 CE // http://www.postgresql.org/docs/9.2/static/datatype-datetime.html // ECMAScript supports date range of Apr 20 271821 BCE to Sep 13 275760 CE // http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1 - client.query('SELECT $1::TIMESTAMPTZ as when', ["275760-09-13 00:00:00 GMT"], assert.success(function (res) { - assert.equal(res.rows[0].when.getFullYear(), 275760); - })); + client.query('SELECT $1::TIMESTAMPTZ as when', ['275760-09-13 00:00:00 GMT'], assert.success(function (res) { + assert.equal(res.rows[0].when.getFullYear(), 275760) + })) - client.query('SELECT $1::TIMESTAMPTZ as when', ["4713-12-31 12:31:59 BC GMT"], assert.success(function (res) { - assert.equal(res.rows[0].when.getFullYear(), -4713); - })); + client.query('SELECT $1::TIMESTAMPTZ as when', ['4713-12-31 12:31:59 BC GMT'], assert.success(function (res) { + assert.equal(res.rows[0].when.getFullYear(), -4713) + })) - client.query('SELECT $1::TIMESTAMPTZ as when', ["275760-09-13 00:00:00 -15:00"], assert.success(function (res) { - assert(isNaN(res.rows[0].when.getTime())); - })); + client.query('SELECT $1::TIMESTAMPTZ as when', ['275760-09-13 00:00:00 -15:00'], assert.success(function (res) { + assert(isNaN(res.rows[0].when.getTime())) + })) client.on('drain', () => { client.end(done) - }); - })); -}); + }) + })) +}) diff --git a/test/integration/client/type-parser-override-tests.js b/test/integration/client/type-parser-override-tests.js index f12e4005..e806a390 100644 --- a/test/integration/client/type-parser-override-tests.js +++ b/test/integration/client/type-parser-override-tests.js @@ -1,37 +1,37 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') -function testTypeParser(client, expectedResult, done) { - var boolValue = true; - client.query('CREATE TEMP TABLE parserOverrideTest(id bool)'); - client.query('INSERT INTO parserOverrideTest(id) VALUES ($1)', [boolValue]); - client.query('SELECT * FROM parserOverrideTest', assert.success(function(result) { - assert.equal(result.rows[0].id, expectedResult); - done(); - })); +function testTypeParser (client, expectedResult, done) { + var boolValue = true + client.query('CREATE TEMP TABLE parserOverrideTest(id bool)') + client.query('INSERT INTO parserOverrideTest(id) VALUES ($1)', [boolValue]) + client.query('SELECT * FROM parserOverrideTest', assert.success(function (result) { + assert.equal(result.rows[0].id, expectedResult) + done() + })) } const pool = new helper.pg.Pool(helper.config) -pool.connect(assert.success(function(client1, done1) { - pool.connect(assert.success(function(client2, done2) { - var boolTypeOID = 16; - client1.setTypeParser(boolTypeOID, function(){ - return 'first client'; - }); - client2.setTypeParser(boolTypeOID, function(){ - return 'second client'; - }); +pool.connect(assert.success(function (client1, done1) { + pool.connect(assert.success(function (client2, done2) { + var boolTypeOID = 16 + client1.setTypeParser(boolTypeOID, function () { + return 'first client' + }) + client2.setTypeParser(boolTypeOID, function () { + return 'second client' + }) - client1.setTypeParser(boolTypeOID, 'binary', function(){ - return 'first client binary'; - }); - client2.setTypeParser(boolTypeOID, 'binary', function(){ - return 'second client binary'; - }); + client1.setTypeParser(boolTypeOID, 'binary', function () { + return 'first client binary' + }) + client2.setTypeParser(boolTypeOID, 'binary', function () { + return 'second client binary' + }) testTypeParser(client1, 'first client', () => { done1() - testTypeParser(client2, 'second client', () => done2(), pool.end()); - }); - })); -})); + testTypeParser(client2, 'second client', () => done2(), pool.end()) + }) + })) +})) diff --git a/test/integration/connection-pool/connection-pool-size-tests.js b/test/integration/connection-pool/connection-pool-size-tests.js index 51051c24..da281a19 100644 --- a/test/integration/connection-pool/connection-pool-size-tests.js +++ b/test/integration/connection-pool/connection-pool-size-tests.js @@ -1,10 +1,10 @@ -"use strict"; -var helper = require("./test-helper") +'use strict' +var helper = require('./test-helper') -helper.testPoolSize(1); +helper.testPoolSize(1) -helper.testPoolSize(2); +helper.testPoolSize(2) -helper.testPoolSize(40); +helper.testPoolSize(40) -helper.testPoolSize(200); +helper.testPoolSize(200) diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index 4098ba9d..b90ab5df 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -1,9 +1,9 @@ -"use strict"; -var helper = require("./test-helper"); +'use strict' +var helper = require('./test-helper') const pg = helper.pg -//first make pool hold 2 clients -pg.defaults.poolSize = 2; +// first make pool hold 2 clients +pg.defaults.poolSize = 2 const pool = new pg.Pool() @@ -14,39 +14,37 @@ suite.test('connecting to invalid port', (cb) => { }) suite.test('errors emitted on pool', (cb) => { - //get first client + // get first client pool.connect(assert.success(function (client, done) { - client.id = 1; + client.id = 1 client.query('SELECT NOW()', function () { pool.connect(assert.success(function (client2, done2) { - client2.id = 2; - var pidColName = 'procpid'; + client2.id = 2 + var pidColName = 'procpid' helper.versionGTE(client2, '9.2.0', assert.success(function (isGreater) { - var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1'; - var params = ['idle']; + var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1' + var params = ['idle'] if (!isGreater) { - killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE $1'; + killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE $1' params = ['%IDLE%'] } pool.once('error', (err, brokenClient) => { - assert.ok(err); - assert.ok(brokenClient); - assert.equal(client.id, brokenClient.id); + assert.ok(err) + assert.ok(brokenClient) + assert.equal(client.id, brokenClient.id) cb() }) - //kill the connection from client + // kill the connection from client client2.query(killIdleQuery, params, assert.success(function (res) { - //check to make sure client connection actually was killed - //return client2 to the pool - done2(); - pool.end(); - })); - })); - })); - + // check to make sure client connection actually was killed + // return client2 to the pool + done2() + pool.end() + })) + })) + })) }) - })); - + })) }) diff --git a/test/integration/connection-pool/idle-timeout-tests.js b/test/integration/connection-pool/idle-timeout-tests.js index 63956b64..c48f712e 100644 --- a/test/integration/connection-pool/idle-timeout-tests.js +++ b/test/integration/connection-pool/idle-timeout-tests.js @@ -1,13 +1,12 @@ -"use strict"; -var helper = require('./test-helper'); - +'use strict' +var helper = require('./test-helper') new helper.Suite().test('idle timeout', function () { const config = Object.assign({}, helper.config, { idleTimeoutMillis: 50 }) const pool = new helper.pg.Pool(config) pool.connect(assert.calls(function (err, client, done) { - assert(!err); - client.query('SELECT NOW()'); - done(); - })); -}); + assert(!err) + client.query('SELECT NOW()') + done() + })) +}) diff --git a/test/integration/connection-pool/native-instance-tests.js b/test/integration/connection-pool/native-instance-tests.js index caaa2b67..5347677a 100644 --- a/test/integration/connection-pool/native-instance-tests.js +++ b/test/integration/connection-pool/native-instance-tests.js @@ -1,11 +1,11 @@ -"use strict"; -var helper = require("./../test-helper") +'use strict' +var helper = require('./../test-helper') var pg = helper.pg var native = helper.args.native var pool = new pg.Pool() -pool.connect(assert.calls(function(err, client, done) { +pool.connect(assert.calls(function (err, client, done) { if (native) { assert(client.native) } else { diff --git a/test/integration/connection-pool/test-helper.js b/test/integration/connection-pool/test-helper.js index 2fde015e..97a177a6 100644 --- a/test/integration/connection-pool/test-helper.js +++ b/test/integration/connection-pool/test-helper.js @@ -1,5 +1,5 @@ -"use strict"; -var helper = require("./../test-helper"); +'use strict' +var helper = require('./../test-helper') const suite = new helper.Suite() @@ -9,19 +9,19 @@ helper.testPoolSize = function (max) { var sink = new helper.Sink(max, function () { pool.end(cb) - }); + }) for (var i = 0; i < max; i++) { pool.connect(function (err, client, done) { - assert(!err); - client.query("SELECT * FROM NOW()") - client.query("select generate_series(0, 25)", function (err, result) { + assert(!err) + client.query('SELECT * FROM NOW()') + client.query('select generate_series(0, 25)', function (err, result) { assert.equal(result.rows.length, 26) }) - var query = client.query("SELECT * FROM NOW()", (err) => { + var query = client.query('SELECT * FROM NOW()', (err) => { assert(!err) - sink.add(); - done(); + sink.add() + done() }) }) } @@ -29,4 +29,3 @@ helper.testPoolSize = function (max) { } module.exports = Object.assign({}, helper, { suite: suite }) - diff --git a/test/integration/connection-pool/yield-support-tests.js b/test/integration/connection-pool/yield-support-tests.js index 14926699..08d89b30 100644 --- a/test/integration/connection-pool/yield-support-tests.js +++ b/test/integration/connection-pool/yield-support-tests.js @@ -1,9 +1,9 @@ -"use strict"; +'use strict' var helper = require('./test-helper') var co = require('co') const pool = new helper.pg.Pool() -new helper.Suite().test('using coroutines works with promises', co.wrap(function* () { +new helper.Suite().test('using coroutines works with promises', co.wrap(function * () { var client = yield pool.connect() var res = yield client.query('SELECT $1::text as name', ['foo']) assert.equal(res.rows[0].name, 'foo') diff --git a/test/integration/connection/bound-command-tests.js b/test/integration/connection/bound-command-tests.js index 40da4b5a..c6cf84e1 100644 --- a/test/integration/connection/bound-command-tests.js +++ b/test/integration/connection/bound-command-tests.js @@ -1,61 +1,58 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); -//http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY +'use strict' +var helper = require(__dirname + '/test-helper') +// http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY -test('flushing once', function() { - helper.connect(function(con) { +test('flushing once', function () { + helper.connect(function (con) { con.parse({ text: 'select * from ids' - }); + }) - con.bind(); - con.execute(); - con.flush(); + con.bind() + con.execute() + con.flush() - assert.emits(con, 'parseComplete'); - assert.emits(con, 'bindComplete'); - assert.emits(con, 'dataRow'); - assert.emits(con, 'commandComplete', function(){ - con.sync(); - }); - assert.emits(con, 'readyForQuery', function(){ - con.end(); - }); + assert.emits(con, 'parseComplete') + assert.emits(con, 'bindComplete') + assert.emits(con, 'dataRow') + assert.emits(con, 'commandComplete', function () { + con.sync() + }) + assert.emits(con, 'readyForQuery', function () { + con.end() + }) + }) +}) - }); -}); +test('sending many flushes', function () { + helper.connect(function (con) { + assert.emits(con, 'parseComplete', function () { + con.bind() + con.flush() + }) -test("sending many flushes", function() { - helper.connect(function(con) { + assert.emits(con, 'bindComplete', function () { + con.execute() + con.flush() + }) - assert.emits(con, 'parseComplete', function(){ - con.bind(); - con.flush(); - }); - - assert.emits(con, 'bindComplete', function(){ - con.execute(); - con.flush(); - }); - - assert.emits(con, 'dataRow', function(msg){ - assert.equal(msg.fields[0], 1); - assert.emits(con, 'dataRow', function(msg){ - assert.equal(msg.fields[0], 2); - assert.emits(con, 'commandComplete', function(){ - con.sync(); - }); - assert.emits(con, 'readyForQuery', function(){ - con.end(); - }); - }); - }); + assert.emits(con, 'dataRow', function (msg) { + assert.equal(msg.fields[0], 1) + assert.emits(con, 'dataRow', function (msg) { + assert.equal(msg.fields[0], 2) + assert.emits(con, 'commandComplete', function () { + con.sync() + }) + assert.emits(con, 'readyForQuery', function () { + con.end() + }) + }) + }) con.parse({ - text: "select * from ids order by id" - }); + text: 'select * from ids order by id' + }) - con.flush(); - - }); -}); + con.flush() + }) +}) diff --git a/test/integration/connection/copy-tests.js b/test/integration/connection/copy-tests.js index 2dfbc607..c11632c3 100644 --- a/test/integration/connection/copy-tests.js +++ b/test/integration/connection/copy-tests.js @@ -1,45 +1,45 @@ -"use strict"; -var helper = require(__dirname+"/test-helper"); -var assert = require('assert'); +'use strict' +var helper = require(__dirname + '/test-helper') +var assert = require('assert') test('COPY FROM events check', function () { - helper.connect(function (con) { - var stdinStream = con.query('COPY person FROM STDIN'); + helper.connect(function (con) { + var stdinStream = con.query('COPY person FROM STDIN') con.on('copyInResponse', function () { - con.endCopyFrom(); - }); + con.endCopyFrom() + }) assert.emits(con, 'copyInResponse', function () { - con.endCopyFrom(); + con.endCopyFrom() }, - "backend should emit copyInResponse after COPY FROM query" - ); + 'backend should emit copyInResponse after COPY FROM query' + ) assert.emits(con, 'commandComplete', function () { - con.end(); + con.end() }, - "backend should emit commandComplete after COPY FROM stream ends" + 'backend should emit commandComplete after COPY FROM stream ends' ) - }); -}); + }) +}) test('COPY TO events check', function () { helper.connect(function (con) { - var stdoutStream = con.query('COPY person TO STDOUT'); + var stdoutStream = con.query('COPY person TO STDOUT') assert.emits(con, 'copyOutResponse', function () { }, - "backend should emit copyOutResponse after COPY TO query" - ); + 'backend should emit copyOutResponse after COPY TO query' + ) assert.emits(con, 'copyData', function () { }, - "backend should emit copyData on every data row" - ); + 'backend should emit copyData on every data row' + ) assert.emits(con, 'copyDone', function () { - con.end(); + con.end() }, - "backend should emit copyDone after all data rows" - ); - }); -}); + 'backend should emit copyDone after all data rows' + ) + }) +}) diff --git a/test/integration/connection/notification-tests.js b/test/integration/connection/notification-tests.js index dd11904d..347b7ee8 100644 --- a/test/integration/connection/notification-tests.js +++ b/test/integration/connection/notification-tests.js @@ -1,16 +1,16 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); -//http://www.postgresql.org/docs/8.3/static/libpq-notify.html -test('recieves notification from same connection with no payload', function() { - helper.connect(function(con) { - con.query('LISTEN boom'); - assert.emits(con, 'readyForQuery', function() { - con.query("NOTIFY boom"); - assert.emits(con, 'notification', function(msg) { - assert.equal(msg.payload, ""); +'use strict' +var helper = require(__dirname + '/test-helper') +// http://www.postgresql.org/docs/8.3/static/libpq-notify.html +test('recieves notification from same connection with no payload', function () { + helper.connect(function (con) { + con.query('LISTEN boom') + assert.emits(con, 'readyForQuery', function () { + con.query('NOTIFY boom') + assert.emits(con, 'notification', function (msg) { + assert.equal(msg.payload, '') assert.equal(msg.channel, 'boom') - con.end(); - }); - }); - }); -}); + con.end() + }) + }) + }) +}) diff --git a/test/integration/connection/query-tests.js b/test/integration/connection/query-tests.js index 6216c55a..70c39c32 100644 --- a/test/integration/connection/query-tests.js +++ b/test/integration/connection/query-tests.js @@ -1,26 +1,26 @@ -"use strict"; -var helper = require(__dirname+"/test-helper"); -var assert = require('assert'); +'use strict' +var helper = require(__dirname + '/test-helper') +var assert = require('assert') -var rows = []; -//testing the low level 1-1 mapping api of client to postgres messages -//it's cumbersome to use the api this way -test('simple query', function() { - helper.connect(function(con) { - con.query('select * from ids'); - assert.emits(con, 'dataRow'); - con.on('dataRow', function(msg) { - rows.push(msg.fields); - }); - assert.emits(con, 'readyForQuery', function() { - con.end(); - }); - }); -}); +var rows = [] +// testing the low level 1-1 mapping api of client to postgres messages +// it's cumbersome to use the api this way +test('simple query', function () { + helper.connect(function (con) { + con.query('select * from ids') + assert.emits(con, 'dataRow') + con.on('dataRow', function (msg) { + rows.push(msg.fields) + }) + assert.emits(con, 'readyForQuery', function () { + con.end() + }) + }) +}) -process.on('exit', function() { - assert.equal(rows.length, 2); - assert.equal(rows[0].length, 1); - assert.strictEqual(String(rows[0] [0]), '1'); - assert.strictEqual(String(rows[1] [0]), '2'); -}); +process.on('exit', function () { + assert.equal(rows.length, 2) + assert.equal(rows[0].length, 1) + assert.strictEqual(String(rows[0][0]), '1') + assert.strictEqual(String(rows[1][0]), '2') +}) diff --git a/test/integration/connection/test-helper.js b/test/integration/connection/test-helper.js index d053e39a..71bcfb2e 100644 --- a/test/integration/connection/test-helper.js +++ b/test/integration/connection/test-helper.js @@ -1,43 +1,43 @@ -"use strict"; -var net = require('net'); -var helper = require(__dirname+'/../test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); -var connect = function(callback) { - var username = helper.args.user; - var database = helper.args.database; - var con = new Connection({stream: new net.Stream()}); - con.on('error', function(error){ - console.log(error); - throw new Error("Connection error"); - }); - con.connect(helper.args.port || '5432', helper.args.host || 'localhost'); - con.once('connect', function() { +'use strict' +var net = require('net') +var helper = require(__dirname + '/../test-helper') +var Connection = require(__dirname + '/../../../lib/connection') +var connect = function (callback) { + var username = helper.args.user + var database = helper.args.database + var con = new Connection({stream: new net.Stream()}) + con.on('error', function (error) { + console.log(error) + throw new Error('Connection error') + }) + con.connect(helper.args.port || '5432', helper.args.host || 'localhost') + con.once('connect', function () { con.startup({ user: username, database: database - }); - con.once('authenticationCleartextPassword', function(){ - con.password(helper.args.password); - }); - con.once('authenticationMD5Password', function(msg){ - //need js client even if native client is included - var client = require(__dirname +"/../../../lib/client"); - var inner = client.md5(helper.args.password+helper.args.user); - var outer = client.md5(inner + msg.salt.toString('binary')); - con.password("md5"+outer); - }); - con.once('readyForQuery', function() { - con.query('create temp table ids(id integer)'); - con.once('readyForQuery', function() { - con.query('insert into ids(id) values(1); insert into ids(id) values(2);'); - con.once('readyForQuery', function() { - callback(con); - }); - }); - }); - }); -}; + }) + con.once('authenticationCleartextPassword', function () { + con.password(helper.args.password) + }) + con.once('authenticationMD5Password', function (msg) { + // need js client even if native client is included + var client = require(__dirname + '/../../../lib/client') + var inner = client.md5(helper.args.password + helper.args.user) + var outer = client.md5(inner + msg.salt.toString('binary')) + con.password('md5' + outer) + }) + con.once('readyForQuery', function () { + con.query('create temp table ids(id integer)') + con.once('readyForQuery', function () { + con.query('insert into ids(id) values(1); insert into ids(id) values(2);') + con.once('readyForQuery', function () { + callback(con) + }) + }) + }) + }) +} module.exports = { connect: connect -}; +} diff --git a/test/integration/domain-tests.js b/test/integration/domain-tests.js index 5d4db53c..a02f3942 100644 --- a/test/integration/domain-tests.js +++ b/test/integration/domain-tests.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' var async = require('async') var helper = require('./test-helper') diff --git a/test/integration/gh-issues/130-tests.js b/test/integration/gh-issues/130-tests.js index bc1f3b74..b3e2a225 100644 --- a/test/integration/gh-issues/130-tests.js +++ b/test/integration/gh-issues/130-tests.js @@ -1,23 +1,23 @@ -"use strict"; -var helper = require(__dirname + '/../test-helper'); -var exec = require('child_process').exec; +'use strict' +var helper = require(__dirname + '/../test-helper') +var exec = require('child_process').exec -helper.pg.defaults.poolIdleTimeout = 1000; +helper.pg.defaults.poolIdleTimeout = 1000 const pool = new helper.pg.Pool() -pool.connect(function(err,client) { - client.query("SELECT pg_backend_pid()", function(err, result) { - var pid = result.rows[0].pg_backend_pid; - var psql = 'psql'; - if (helper.args.host) psql = psql+' -h '+helper.args.host; - if (helper.args.port) psql = psql+' -p '+helper.args.port; - if (helper.args.user) psql = psql+' -U '+helper.args.user; - exec(psql+' -c "select pg_terminate_backend('+pid+')" template1', assert.calls(function (error, stdout, stderr) { - assert.isNull(error); - })); - }); -}); +pool.connect(function (err, client) { + client.query('SELECT pg_backend_pid()', function (err, result) { + var pid = result.rows[0].pg_backend_pid + var psql = 'psql' + if (helper.args.host) psql = psql + ' -h ' + helper.args.host + if (helper.args.port) psql = psql + ' -p ' + helper.args.port + if (helper.args.user) psql = psql + ' -U ' + helper.args.user + exec(psql + ' -c "select pg_terminate_backend(' + pid + ')" template1', assert.calls(function (error, stdout, stderr) { + assert.isNull(error) + })) + }) +}) -pool.on('error', function(err, client) { - //swallow errors -}); +pool.on('error', function (err, client) { + // swallow errors +}) diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index f56834e2..87a7b241 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -1,20 +1,20 @@ -"use strict"; -var helper = require('../test-helper'); -var pg = helper.pg; +'use strict' +var helper = require('../test-helper') +var pg = helper.pg var suite = new helper.Suite() suite.test('parsing array decimal results', function (done) { const pool = new pg.Pool() pool.connect(assert.calls(function (err, client, release) { - assert(!err); - client.query("CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])"); - client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log); + assert(!err) + client.query('CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])') + client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log) client.query('SELECT decimals FROM why', assert.success(function (result) { - assert.lengthIs(result.rows[0].decimals, 3); - assert.equal(result.rows[0].decimals[0], 0.1); - assert.equal(result.rows[0].decimals[1], 0.05); - assert.equal(result.rows[0].decimals[2], 3.654); + assert.lengthIs(result.rows[0].decimals, 3) + assert.equal(result.rows[0].decimals[0], 0.1) + assert.equal(result.rows[0].decimals[1], 0.05) + assert.equal(result.rows[0].decimals[2], 3.654) release() pool.end(done) })) diff --git a/test/integration/gh-issues/199-tests.js b/test/integration/gh-issues/199-tests.js index 60637fb1..bb93d426 100644 --- a/test/integration/gh-issues/199-tests.js +++ b/test/integration/gh-issues/199-tests.js @@ -1,22 +1,22 @@ -"use strict"; -var helper = require('../test-helper'); -var client = helper.client(); +'use strict' +var helper = require('../test-helper') +var client = helper.client() -client.query('CREATE TEMP TABLE arrtest (n integer, s varchar)'); -client.query("INSERT INTO arrtest VALUES (4, 'foo'), (5, 'bar'), (6, 'baz');"); +client.query('CREATE TEMP TABLE arrtest (n integer, s varchar)') +client.query("INSERT INTO arrtest VALUES (4, 'foo'), (5, 'bar'), (6, 'baz');") var qText = "SELECT \ ARRAY[1, 2, 3] AS b,\ ARRAY['xx', 'yy', 'zz'] AS c,\ ARRAY(SELECT n FROM arrtest) AS d,\ -ARRAY(SELECT s FROM arrtest) AS e;"; +ARRAY(SELECT s FROM arrtest) AS e;" -client.query(qText, function(err, result) { - if(err) throw err; - var row = result.rows[0]; - for(var key in row) { - assert.equal(typeof row[key], 'object'); - assert.equal(row[key].length, 3); +client.query(qText, function (err, result) { + if (err) throw err + var row = result.rows[0] + for (var key in row) { + assert.equal(typeof row[key], 'object') + assert.equal(row[key].length, 3) } - client.end(); -}); + client.end() +}) diff --git a/test/integration/gh-issues/507-tests.js b/test/integration/gh-issues/507-tests.js index 62bec47c..dadc1c83 100644 --- a/test/integration/gh-issues/507-tests.js +++ b/test/integration/gh-issues/507-tests.js @@ -1,13 +1,13 @@ -"use strict"; -var helper = require(__dirname + "/../test-helper"); -var pg = helper.pg; +'use strict' +var helper = require(__dirname + '/../test-helper') +var pg = helper.pg -new helper.Suite().test('parsing array results', function(cb) { +new helper.Suite().test('parsing array results', function (cb) { const pool = new pg.Pool() - pool.connect(assert.success(function(client, done) { + pool.connect(assert.success(function (client, done) { client.query('CREATE TEMP TABLE test_table(bar integer, "baz\'s" integer)') client.query('INSERT INTO test_table(bar, "baz\'s") VALUES(1, 1), (2, 2)') - client.query('SELECT * FROM test_table', function(err, res) { + client.query('SELECT * FROM test_table', function (err, res) { assert.equal(res.rows[0]["baz's"], 1) assert.equal(res.rows[1]["baz's"], 2) done() diff --git a/test/integration/gh-issues/600-tests.js b/test/integration/gh-issues/600-tests.js index 263e48d0..ea6154e3 100644 --- a/test/integration/gh-issues/600-tests.js +++ b/test/integration/gh-issues/600-tests.js @@ -1,51 +1,51 @@ -"use strict"; -var async = require('async'); -var helper = require('../test-helper'); +'use strict' +var async = require('async') +var helper = require('../test-helper') const suite = new helper.Suite() -var db = helper.client(); +var db = helper.client() -function createTableFoo(callback){ - db.query("create temp table foo(column1 int, column2 int)", callback); +function createTableFoo (callback) { + db.query('create temp table foo(column1 int, column2 int)', callback) } -function createTableBar(callback){ - db.query("create temp table bar(column1 text, column2 text)", callback); +function createTableBar (callback) { + db.query('create temp table bar(column1 text, column2 text)', callback) } -function insertDataFoo(callback){ - db.query({ - name: 'insertFoo', - text: 'insert into foo values($1,$2)', - values:['one','two'] - }, callback ); +function insertDataFoo (callback) { + db.query({ + name: 'insertFoo', + text: 'insert into foo values($1,$2)', + values: ['one', 'two'] + }, callback) } -function insertDataBar(callback){ - db.query({ - name: 'insertBar', - text: 'insert into bar values($1,$2)', - values:['one','two'] - }, callback ); +function insertDataBar (callback) { + db.query({ + name: 'insertBar', + text: 'insert into bar values($1,$2)', + values: ['one', 'two'] + }, callback) } -function startTransaction(callback) { - db.query('BEGIN', callback); +function startTransaction (callback) { + db.query('BEGIN', callback) } -function endTransaction(callback) { - db.query('COMMIT', callback); +function endTransaction (callback) { + db.query('COMMIT', callback) } -function doTransaction(callback) { +function doTransaction (callback) { // The transaction runs startTransaction, then all queries, then endTransaction, // no matter if there has been an error in a query in the middle. - startTransaction(function() { - insertDataFoo(function() { - insertDataBar(function() { - endTransaction( callback ); - }); - }); - }); + startTransaction(function () { + insertDataFoo(function () { + insertDataBar(function () { + endTransaction(callback) + }) + }) + }) } var steps = [ @@ -55,27 +55,26 @@ var steps = [ insertDataBar ] -suite.test('test if query fails', function(done) { - async.series(steps, assert.success(function() { +suite.test('test if query fails', function (done) { + async.series(steps, assert.success(function () { db.end() done() })) }) -suite.test('test if prepare works but bind fails', function(done) { - var client = helper.client(); +suite.test('test if prepare works but bind fails', function (done) { + var client = helper.client() var q = { text: 'SELECT $1::int as name', values: ['brian'], name: 'test' - }; - client.query(q, assert.calls(function(err, res) { - q.values = [1]; - client.query(q, assert.calls(function(err, res) { - assert.ifError(err); - client.end(); + } + client.query(q, assert.calls(function (err, res) { + q.values = [1] + client.query(q, assert.calls(function (err, res) { + assert.ifError(err) + client.end() done() - })); - })); -}); - + })) + })) +}) diff --git a/test/integration/gh-issues/675-tests.js b/test/integration/gh-issues/675-tests.js index b162b9df..2e281ecc 100644 --- a/test/integration/gh-issues/675-tests.js +++ b/test/integration/gh-issues/675-tests.js @@ -1,30 +1,30 @@ -"use strict"; -var helper = require('../test-helper'); -var assert = require('assert'); +'use strict' +var helper = require('../test-helper') +var assert = require('assert') const pool = new helper.pg.Pool() -pool.connect(function(err, client, done) { - if (err) throw err; +pool.connect(function (err, client, done) { + if (err) throw err - var c = 'CREATE TEMP TABLE posts (body TEXT)'; + var c = 'CREATE TEMP TABLE posts (body TEXT)' - client.query(c, function(err) { - if (err) throw err; + client.query(c, function (err) { + if (err) throw err - c = 'INSERT INTO posts (body) VALUES ($1) RETURNING *'; + c = 'INSERT INTO posts (body) VALUES ($1) RETURNING *' - var body = Buffer.from('foo'); - client.query(c, [body], function(err) { - if (err) throw err; + var body = Buffer.from('foo') + client.query(c, [body], function (err) { + if (err) throw err - body = Buffer.from([]); - client.query(c, [body], function(err, res) { - done(); + body = Buffer.from([]) + client.query(c, [body], function (err, res) { + done() - if (err) throw err; + if (err) throw err assert.equal(res.rows[0].body, '') - pool.end(); - }); - }); - }); -}); + pool.end() + }) + }) + }) +}) diff --git a/test/integration/gh-issues/787-tests.js b/test/integration/gh-issues/787-tests.js index 83ea85f3..456c8646 100644 --- a/test/integration/gh-issues/787-tests.js +++ b/test/integration/gh-issues/787-tests.js @@ -1,13 +1,13 @@ -"use strict"; -var helper = require('../test-helper'); +'use strict' +var helper = require('../test-helper') const pool = new helper.pg.Pool() -pool.connect(function(err,client) { +pool.connect(function (err, client) { var q = { name: 'This is a super long query name just so I can test that an error message is properly spit out to console.error without throwing an exception or anything', text: 'SELECT NOW()' - }; - client.query(q, function() { - client.end(); - }); -}); + } + client.query(q, function () { + client.end() + }) +}) diff --git a/test/integration/gh-issues/882-tests.js b/test/integration/gh-issues/882-tests.js index 154f9e96..6b4a3e2e 100644 --- a/test/integration/gh-issues/882-tests.js +++ b/test/integration/gh-issues/882-tests.js @@ -1,9 +1,9 @@ -"use strict"; -//client should not hang on an empty query -var helper = require('../test-helper'); -var client = helper.client(); -client.query({ name: 'foo1', text: null}); -client.query({ name: 'foo2', text: ' ' }); -client.query({ name: 'foo3', text: '' }, function(err, res) { - client.end(); -}); +'use strict' +// client should not hang on an empty query +var helper = require('../test-helper') +var client = helper.client() +client.query({ name: 'foo1', text: null}) +client.query({ name: 'foo2', text: ' ' }) +client.query({ name: 'foo3', text: '' }, function (err, res) { + client.end() +}) diff --git a/test/integration/test-helper.js b/test/integration/test-helper.js index 56ea43ed..ca844de3 100644 --- a/test/integration/test-helper.js +++ b/test/integration/test-helper.js @@ -1,28 +1,27 @@ -"use strict"; -var helper = require('./../test-helper'); +'use strict' +var helper = require('./../test-helper') -if(helper.args.native) { - Client = require('./../../lib/native'); - helper.Client = Client; - helper.pg = helper.pg.native; +if (helper.args.native) { + Client = require('./../../lib/native') + helper.Client = Client + helper.pg = helper.pg.native } -//creates a client from cli parameters -helper.client = function(cb) { - var client = new Client(); - client.connect(cb); - return client; -}; +// creates a client from cli parameters +helper.client = function (cb) { + var client = new Client() + client.connect(cb) + return client +} -var semver = require('semver'); -helper.versionGTE = function(client, versionString, callback) { - client.query('SELECT version()', assert.calls(function(err, result) { - if(err) return callback(err); - var version = result.rows[0].version.split(' ')[1]; - return callback(null, semver.gte(version, versionString)); - })); -}; - -//export parent helper stuffs -module.exports = helper; +var semver = require('semver') +helper.versionGTE = function (client, versionString, callback) { + client.query('SELECT version()', assert.calls(function (err, result) { + if (err) return callback(err) + var version = result.rows[0].version.split(' ')[1] + return callback(null, semver.gte(version, versionString)) + })) +} +// export parent helper stuffs +module.exports = helper diff --git a/test/native/callback-api-tests.js b/test/native/callback-api-tests.js index a0a77795..a7fff118 100644 --- a/test/native/callback-api-tests.js +++ b/test/native/callback-api-tests.js @@ -1,34 +1,34 @@ -"use strict"; -var domain = require('domain'); -var helper = require("./../test-helper"); -var Client = require("./../../lib/native"); +'use strict' +var domain = require('domain') +var helper = require('./../test-helper') +var Client = require('./../../lib/native') const suite = new helper.Suite() -suite.test('fires callback with results', function(done) { - var client = new Client(helper.config); - client.connect(); - client.query('SELECT 1 as num', assert.calls(function(err, result) { - assert(!err); - assert.equal(result.rows[0].num, 1); - assert.strictEqual(result.rowCount, 1); - client.query('SELECT * FROM person WHERE name = $1', ['Brian'], assert.calls(function(err, result) { - assert(!err); - assert.equal(result.rows[0].name, 'Brian'); - client.end(done); +suite.test('fires callback with results', function (done) { + var client = new Client(helper.config) + client.connect() + client.query('SELECT 1 as num', assert.calls(function (err, result) { + assert(!err) + assert.equal(result.rows[0].num, 1) + assert.strictEqual(result.rowCount, 1) + client.query('SELECT * FROM person WHERE name = $1', ['Brian'], assert.calls(function (err, result) { + assert(!err) + assert.equal(result.rows[0].name, 'Brian') + client.end(done) })) - })); + })) }) -suite.test('preserves domain', function(done) { - var dom = domain.create(); +suite.test('preserves domain', function (done) { + var dom = domain.create() - dom.run(function() { - var client = new Client(helper.config); - assert.ok(dom === require('domain').active, 'domain is active'); + dom.run(function () { + var client = new Client(helper.config) + assert.ok(dom === require('domain').active, 'domain is active') client.connect() - client.query('select 1', function() { - assert.ok(dom === require('domain').active, 'domain is still active'); - client.end(done); - }); - }); + client.query('select 1', function () { + assert.ok(dom === require('domain').active, 'domain is still active') + client.end(done) + }) + }) }) diff --git a/test/native/evented-api-tests.js b/test/native/evented-api-tests.js index 8a7c19b4..02a00cff 100644 --- a/test/native/evented-api-tests.js +++ b/test/native/evented-api-tests.js @@ -1,34 +1,34 @@ -"use strict"; -var helper = require("../test-helper"); -var Client = require("../../lib/native"); -var Query = Client.Query; +'use strict' +var helper = require('../test-helper') +var Client = require('../../lib/native') +var Query = Client.Query -var setupClient = function() { - var client = new Client(helper.config); - client.connect(); - client.query("CREATE TEMP TABLE boom(name varchar(10), age integer)"); - client.query("INSERT INTO boom(name, age) VALUES('Aaron', 26)"); - client.query("INSERT INTO boom(name, age) VALUES('Brian', 28)"); - return client; +var setupClient = function () { + var client = new Client(helper.config) + client.connect() + client.query('CREATE TEMP TABLE boom(name varchar(10), age integer)') + client.query("INSERT INTO boom(name, age) VALUES('Aaron', 26)") + client.query("INSERT INTO boom(name, age) VALUES('Brian', 28)") + return client } -test('multiple results', function() { - test('queued queries', function() { - var client = setupClient(); - var q = client.query(new Query("SELECT name FROM BOOM")); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'Aaron'); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, "Brian"); +test('multiple results', function () { + test('queued queries', function () { + var client = setupClient() + var q = client.query(new Query('SELECT name FROM BOOM')) + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Aaron') + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Brian') }) }) - assert.emits(q, 'end', function() { - test('query with config', function() { - var q2 = client.query(new Query({text:'SELECT 1 as num'})); - assert.emits(q2, 'row', function(row) { - assert.strictEqual(row.num, 1); - assert.emits(q2, 'end', function() { - client.end(); + assert.emits(q, 'end', function () { + test('query with config', function () { + var q2 = client.query(new Query({text: 'SELECT 1 as num'})) + assert.emits(q2, 'row', function (row) { + assert.strictEqual(row.num, 1) + assert.emits(q2, 'end', function () { + client.end() }) }) }) @@ -36,55 +36,55 @@ test('multiple results', function() { }) }) -test('parameterized queries', function() { - test('with a single string param', function() { - var client = setupClient(); - var q = client.query(new Query("SELECT * FROM boom WHERE name = $1", ['Aaron'])); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'Aaron'); +test('parameterized queries', function () { + test('with a single string param', function () { + var client = setupClient() + var q = client.query(new Query('SELECT * FROM boom WHERE name = $1', ['Aaron'])) + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Aaron') + }) + assert.emits(q, 'end', function () { + client.end() }) - assert.emits(q, 'end', function() { - client.end(); - }); }) - test('with object config for query', function() { - var client = setupClient(); + test('with object config for query', function () { + var client = setupClient() var q = client.query(new Query({ - text: "SELECT name FROM boom WHERE name = $1", + text: 'SELECT name FROM boom WHERE name = $1', values: ['Brian'] - })); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'Brian'); + })) + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Brian') }) - assert.emits(q, 'end', function() { - client.end(); + assert.emits(q, 'end', function () { + client.end() }) }) - test('multiple parameters', function() { - var client = setupClient(); - var q = client.query(new Query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name', ['Aaron', 'Brian'])); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'Aaron'); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'Brian'); - assert.emits(q, 'end', function() { - client.end(); + test('multiple parameters', function () { + var client = setupClient() + var q = client.query(new Query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name', ['Aaron', 'Brian'])) + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Aaron') + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Brian') + assert.emits(q, 'end', function () { + client.end() }) }) }) }) - test('integer parameters', function() { - var client = setupClient(); - var q = client.query(new Query('SELECT * FROM boom WHERE age > $1', [27])); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'Brian'); - assert.equal(row.age, 28); - }); - assert.emits(q, 'end', function() { - client.end(); + test('integer parameters', function () { + var client = setupClient() + var q = client.query(new Query('SELECT * FROM boom WHERE age > $1', [27])) + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Brian') + assert.equal(row.age, 28) + }) + assert.emits(q, 'end', function () { + client.end() }) }) }) diff --git a/test/native/missing-native.js b/test/native/missing-native.js index d8474287..35dad3f0 100644 --- a/test/native/missing-native.js +++ b/test/native/missing-native.js @@ -1,7 +1,7 @@ -"use strict"; -//this test assumes it has been run from the Makefile -//and that node_modules/pg-native has been deleted +'use strict' +// this test assumes it has been run from the Makefile +// and that node_modules/pg-native has been deleted -var assert = require('assert'); +var assert = require('assert') -assert.equal(require('../../lib').native, null); +assert.equal(require('../../lib').native, null) diff --git a/test/native/native-vs-js-error-tests.js b/test/native/native-vs-js-error-tests.js index 59c6bb94..842e01aa 100644 --- a/test/native/native-vs-js-error-tests.js +++ b/test/native/native-vs-js-error-tests.js @@ -1,21 +1,21 @@ -"use strict"; +'use strict' var assert = require('assert') -var Client = require('../../lib/client'); -var NativeClient = require('../../lib/native'); +var Client = require('../../lib/client') +var NativeClient = require('../../lib/native') -var client = new Client(); -var nativeClient = new NativeClient(); +var client = new Client() +var nativeClient = new NativeClient() -client.connect(); +client.connect() nativeClient.connect((err) => { client.query('SELECT alsdkfj', (err) => { - client.end(); + client.end() nativeClient.query('SELECT lkdasjfasd', (nativeErr) => { - for(var key in nativeErr) { + for (var key in nativeErr) { assert.equal(err[key], nativeErr[key], `Expected err.${key} to equal nativeErr.${key}`) } - nativeClient.end(); - }); - }); -}); + nativeClient.end() + }) + }) +}) diff --git a/test/native/stress-tests.js b/test/native/stress-tests.js index 32477cb8..49904b12 100644 --- a/test/native/stress-tests.js +++ b/test/native/stress-tests.js @@ -1,51 +1,51 @@ -"use strict"; -var helper = require(__dirname + "/../test-helper"); -var Client = require(__dirname + "/../../lib/native"); -var Query = Client.Query; +'use strict' +var helper = require(__dirname + '/../test-helper') +var Client = require(__dirname + '/../../lib/native') +var Query = Client.Query -test('many rows', function() { - var client = new Client(helper.config); - client.connect(); - var q = client.query(new Query("SELECT * FROM person")); - var rows = []; - q.on('row', function(row) { +test('many rows', function () { + var client = new Client(helper.config) + client.connect() + var q = client.query(new Query('SELECT * FROM person')) + var rows = [] + q.on('row', function (row) { rows.push(row) - }); - assert.emits(q, 'end', function() { - client.end(); - assert.lengthIs(rows, 26); }) -}); + assert.emits(q, 'end', function () { + client.end() + assert.lengthIs(rows, 26) + }) +}) -test('many queries', function() { - var client = new Client(helper.config); - client.connect(); - var count = 0; - var expected = 100; - for(var i = 0; i < expected; i++) { - var q = client.query(new Query("SELECT * FROM person")); - assert.emits(q, 'end', function() { - count++; - }); +test('many queries', function () { + var client = new Client(helper.config) + client.connect() + var count = 0 + var expected = 100 + for (var i = 0; i < expected; i++) { + var q = client.query(new Query('SELECT * FROM person')) + assert.emits(q, 'end', function () { + count++ + }) } - assert.emits(client, 'drain', function() { - client.end(); - assert.equal(count, expected); - }); -}); + assert.emits(client, 'drain', function () { + client.end() + assert.equal(count, expected) + }) +}) -test('many clients', function() { - var clients = []; - for(var i = 0; i < 10; i++) { - clients.push(new Client(helper.config)); +test('many clients', function () { + var clients = [] + for (var i = 0; i < 10; i++) { + clients.push(new Client(helper.config)) } - clients.forEach(function(client) { - client.connect(); - for(var i = 0; i < 20; i++) { - client.query('SELECT * FROM person'); + clients.forEach(function (client) { + client.connect() + for (var i = 0; i < 20; i++) { + client.query('SELECT * FROM person') } - assert.emits(client, 'drain', function() { - client.end(); + assert.emits(client, 'drain', function () { + client.end() }) }) }) diff --git a/test/suite.js b/test/suite.js index da6492fb..5de9b281 100644 --- a/test/suite.js +++ b/test/suite.js @@ -1,16 +1,16 @@ -"use strict"; -'use strict'; +'use strict' +'use strict' const async = require('async') class Test { - constructor(name, cb) { + constructor (name, cb) { this.name = name this.action = cb this.timeout = 5000 } - run(cb) { + run (cb) { try { this._run(cb) } catch (e) { @@ -18,7 +18,7 @@ class Test { } } - _run(cb) { + _run (cb) { if (!this.action) { console.log(`${this.name} skipped`) return cb() @@ -38,13 +38,13 @@ class Test { } class Suite { - constructor(name) { + constructor (name) { console.log('') this._queue = async.queue(this.run.bind(this), 1) this._queue.drain = () => { } } - run(test, cb) { + run (test, cb) { process.stdout.write(' ' + test.name + ' ') if (!test.action) { process.stdout.write('? - SKIPPED\n') @@ -69,7 +69,7 @@ class Suite { }) } - test(name, cb) { + test (name, cb) { const test = new Test(name, cb) this._queue.push(test) } diff --git a/test/test-buffers.js b/test/test-buffers.js index 0351559a..9873a310 100644 --- a/test/test-buffers.js +++ b/test/test-buffers.js @@ -1,58 +1,58 @@ -"use strict"; -require(__dirname+'/test-helper'); -//http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html +'use strict' +require(__dirname + '/test-helper') +// http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html -var buffers = {}; -buffers.readyForQuery = function() { +var buffers = {} +buffers.readyForQuery = function () { return new BufferList() .add(Buffer.from('I')) - .join(true,'Z'); -}; + .join(true, 'Z') +} -buffers.authenticationOk = function() { +buffers.authenticationOk = function () { return new BufferList() .addInt32(0) - .join(true, 'R'); -}; + .join(true, 'R') +} -buffers.authenticationCleartextPassword = function() { +buffers.authenticationCleartextPassword = function () { return new BufferList() .addInt32(3) - .join(true, 'R'); -}; + .join(true, 'R') +} -buffers.authenticationMD5Password = function() { +buffers.authenticationMD5Password = function () { return new BufferList() .addInt32(5) - .add(Buffer.from([1,2,3,4])) - .join(true, 'R'); -}; + .add(Buffer.from([1, 2, 3, 4])) + .join(true, 'R') +} -buffers.parameterStatus = function(name, value) { +buffers.parameterStatus = function (name, value) { return new BufferList() .addCString(name) .addCString(value) - .join(true, 'S'); -}; + .join(true, 'S') +} -buffers.backendKeyData = function(processID, secretKey) { +buffers.backendKeyData = function (processID, secretKey) { return new BufferList() .addInt32(processID) .addInt32(secretKey) - .join(true, 'K'); -}; + .join(true, 'K') +} -buffers.commandComplete = function(string) { +buffers.commandComplete = function (string) { return new BufferList() .addCString(string) - .join(true, 'C'); -}; + .join(true, 'C') +} -buffers.rowDescription = function(fields) { - fields = fields || []; - var buf = new BufferList(); - buf.addInt16(fields.length); - fields.forEach(function(field) { +buffers.rowDescription = function (fields) { + fields = fields || [] + var buf = new BufferList() + buf.addInt16(fields.length) + fields.forEach(function (field) { buf.addCString(field.name) .addInt32(field.tableID || 0) .addInt16(field.attributeNumber || 0) @@ -60,66 +60,66 @@ buffers.rowDescription = function(fields) { .addInt16(field.dataTypeSize || 0) .addInt32(field.typeModifier || 0) .addInt16(field.formatCode || 0) - }); - return buf.join(true, 'T'); -}; - -buffers.dataRow = function(columns) { - columns = columns || []; - var buf = new BufferList(); - buf.addInt16(columns.length); - columns.forEach(function(col) { - if(col == null) { - buf.addInt32(-1); - } else { - var strBuf = Buffer.from(col, 'utf8'); - buf.addInt32(strBuf.length); - buf.add(strBuf); - } - }); - return buf.join(true, 'D'); -}; - -buffers.error = function(fields) { - return errorOrNotice(fields).join(true, 'E'); -}; - -buffers.notice = function(fields) { - return errorOrNotice(fields).join(true, 'N'); -}; - -var errorOrNotice = function(fields) { - fields = fields || []; - var buf = new BufferList(); - fields.forEach(function(field) { - buf.addChar(field.type); - buf.addCString(field.value); - }); - return buf.add(Buffer.from([0]));//terminator + }) + return buf.join(true, 'T') } -buffers.parseComplete = function() { - return new BufferList().join(true, '1'); -}; +buffers.dataRow = function (columns) { + columns = columns || [] + var buf = new BufferList() + buf.addInt16(columns.length) + columns.forEach(function (col) { + if (col == null) { + buf.addInt32(-1) + } else { + var strBuf = Buffer.from(col, 'utf8') + buf.addInt32(strBuf.length) + buf.add(strBuf) + } + }) + return buf.join(true, 'D') +} -buffers.bindComplete = function() { - return new BufferList().join(true, '2'); -}; +buffers.error = function (fields) { + return errorOrNotice(fields).join(true, 'E') +} -buffers.notification = function(id, channel, payload) { +buffers.notice = function (fields) { + return errorOrNotice(fields).join(true, 'N') +} + +var errorOrNotice = function (fields) { + fields = fields || [] + var buf = new BufferList() + fields.forEach(function (field) { + buf.addChar(field.type) + buf.addCString(field.value) + }) + return buf.add(Buffer.from([0]))// terminator +} + +buffers.parseComplete = function () { + return new BufferList().join(true, '1') +} + +buffers.bindComplete = function () { + return new BufferList().join(true, '2') +} + +buffers.notification = function (id, channel, payload) { return new BufferList() .addInt32(id) .addCString(channel) .addCString(payload) .join(true, 'A') -}; +} -buffers.emptyQuery = function() { - return new BufferList().join(true, 'I'); -}; +buffers.emptyQuery = function () { + return new BufferList().join(true, 'I') +} -buffers.portalSuspended = function() { - return new BufferList().join(true, 's'); -}; +buffers.portalSuspended = function () { + return new BufferList().join(true, 's') +} -module.exports = buffers; +module.exports = buffers diff --git a/test/test-helper.js b/test/test-helper.js index 3bfc5177..2f39be2a 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,171 +1,170 @@ -"use strict"; -//make assert a global... -global.assert = require('assert'); -var EventEmitter = require('events').EventEmitter; -var sys = require('util'); +'use strict' +// make assert a global... +global.assert = require('assert') +var EventEmitter = require('events').EventEmitter +var sys = require('util') var BufferList = require('./buffer-list') const Suite = require('./suite') -const args = require('./cli'); +const args = require('./cli') -var Connection = require('./../lib/connection'); +var Connection = require('./../lib/connection') -global.Client = require('./../lib').Client; +global.Client = require('./../lib').Client -process.on('uncaughtException', function(d) { +process.on('uncaughtException', function (d) { if ('stack' in d && 'message' in d) { - console.log("Message: " + d.message); - console.log(d.stack); + console.log('Message: ' + d.message) + console.log(d.stack) } else { - console.log(d); + console.log(d) } - process.exit(-1); -}); + process.exit(-1) +}) -assert.same = function(actual, expected) { - for(var key in expected) { - assert.equal(actual[key], expected[key]); +assert.same = function (actual, expected) { + for (var key in expected) { + assert.equal(actual[key], expected[key]) } -}; +} -assert.emits = function(item, eventName, callback, message) { - var called = false; - var id = setTimeout(function() { - test("Should have called '" + eventName + "' event", function() { +assert.emits = function (item, eventName, callback, message) { + var called = false + var id = setTimeout(function () { + test("Should have called '" + eventName + "' event", function () { assert.ok(called, message || "Expected '" + eventName + "' to be called.") - }); - },5000); + }) + }, 5000) - item.once(eventName, function() { + item.once(eventName, function () { if (eventName === 'error') { // belt and braces test to ensure all error events return an error assert.ok(arguments[0] instanceof Error, - "Expected error events to throw instances of Error but found: " + sys.inspect(arguments[0])); + 'Expected error events to throw instances of Error but found: ' + sys.inspect(arguments[0])) } - called = true; - clearTimeout(id); - assert.ok(true); - if(callback) { - callback.apply(item, arguments); + called = true + clearTimeout(id) + assert.ok(true) + if (callback) { + callback.apply(item, arguments) } - }); -}; + }) +} -assert.UTCDate = function(actual, year, month, day, hours, min, sec, milisecond) { - var actualYear = actual.getUTCFullYear(); - assert.equal(actualYear, year, "expected year " + year + " but got " + actualYear); +assert.UTCDate = function (actual, year, month, day, hours, min, sec, milisecond) { + var actualYear = actual.getUTCFullYear() + assert.equal(actualYear, year, 'expected year ' + year + ' but got ' + actualYear) - var actualMonth = actual.getUTCMonth(); - assert.equal(actualMonth, month, "expected month " + month + " but got " + actualMonth); + var actualMonth = actual.getUTCMonth() + assert.equal(actualMonth, month, 'expected month ' + month + ' but got ' + actualMonth) - var actualDate = actual.getUTCDate(); - assert.equal(actualDate, day, "expected day " + day + " but got " + actualDate); + var actualDate = actual.getUTCDate() + assert.equal(actualDate, day, 'expected day ' + day + ' but got ' + actualDate) - var actualHours = actual.getUTCHours(); - assert.equal(actualHours, hours, "expected hours " + hours + " but got " + actualHours); + var actualHours = actual.getUTCHours() + assert.equal(actualHours, hours, 'expected hours ' + hours + ' but got ' + actualHours) - var actualMin = actual.getUTCMinutes(); - assert.equal(actualMin, min, "expected min " + min + " but got " + actualMin); + var actualMin = actual.getUTCMinutes() + assert.equal(actualMin, min, 'expected min ' + min + ' but got ' + actualMin) - var actualSec = actual.getUTCSeconds(); - assert.equal(actualSec, sec, "expected sec " + sec + " but got " + actualSec); + var actualSec = actual.getUTCSeconds() + assert.equal(actualSec, sec, 'expected sec ' + sec + ' but got ' + actualSec) - var actualMili = actual.getUTCMilliseconds(); - assert.equal(actualMili, milisecond, "expected milisecond " + milisecond + " but got " + actualMili); -}; + var actualMili = actual.getUTCMilliseconds() + assert.equal(actualMili, milisecond, 'expected milisecond ' + milisecond + ' but got ' + actualMili) +} -assert.equalBuffers = function(actual, expected) { - if(actual.length != expected.length) { +assert.equalBuffers = function (actual, expected) { + if (actual.length != expected.length) { spit(actual, expected) - assert.equal(actual.length, expected.length); + assert.equal(actual.length, expected.length) } - for(var i = 0; i < actual.length; i++) { - if(actual[i] != expected[i]) { + for (var i = 0; i < actual.length; i++) { + if (actual[i] != expected[i]) { spit(actual, expected) } - assert.equal(actual[i],expected[i]); + assert.equal(actual[i], expected[i]) } -}; +} -assert.empty = function(actual) { - assert.lengthIs(actual, 0); -}; +assert.empty = function (actual) { + assert.lengthIs(actual, 0) +} -assert.success = function(callback) { - if(callback.length === 1 || callback.length === 0) { - return assert.calls(function(err, arg) { - if(err) { - console.log(err); +assert.success = function (callback) { + if (callback.length === 1 || callback.length === 0) { + return assert.calls(function (err, arg) { + if (err) { + console.log(err) } - assert(!err); - callback(arg); - }); + assert(!err) + callback(arg) + }) } else if (callback.length === 2) { - return assert.calls(function(err, arg1, arg2) { - if(err) { - console.log(err); + return assert.calls(function (err, arg1, arg2) { + if (err) { + console.log(err) } - assert(!err); - callback(arg1, arg2); - }); + assert(!err) + callback(arg1, arg2) + }) } else { - throw new Error('need to preserve arrity of wrapped function'); + throw new Error('need to preserve arrity of wrapped function') } } -assert.throws = function(offender) { +assert.throws = function (offender) { try { - offender(); + offender() } catch (e) { - assert.ok(e instanceof Error, "Expected " + offender + " to throw instances of Error"); - return; + assert.ok(e instanceof Error, 'Expected ' + offender + ' to throw instances of Error') + return } - assert.ok(false, "Expected " + offender + " to throw exception"); + assert.ok(false, 'Expected ' + offender + ' to throw exception') } -assert.lengthIs = function(actual, expectedLength) { - assert.equal(actual.length, expectedLength); -}; +assert.lengthIs = function (actual, expectedLength) { + assert.equal(actual.length, expectedLength) +} -var expect = function(callback, timeout) { - var executed = false; - timeout = timeout || parseInt(process.env.TEST_TIMEOUT) || 5000; - var id = setTimeout(function() { +var expect = function (callback, timeout) { + var executed = false + timeout = timeout || parseInt(process.env.TEST_TIMEOUT) || 5000 + var id = setTimeout(function () { assert.ok(executed, - "Expected execution of function to be fired within " + timeout - + " milliseconds " + - + " (hint: export TEST_TIMEOUT=" - + " to change timeout globally)" - + callback.toString()); + 'Expected execution of function to be fired within ' + timeout + + ' milliseconds ' + + +' (hint: export TEST_TIMEOUT=' + + ' to change timeout globally)' + + callback.toString()) }, timeout) - if(callback.length < 3) { - return function(err, queryResult) { - clearTimeout(id); + 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)); + assert.ok(err instanceof Error, 'Expected errors to be instances of Error: ' + sys.inspect(err)) } callback.apply(this, arguments) } - } else if(callback.length == 3) { - return function(err, arg1, arg2) { - clearTimeout(id); + } 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)); + 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); + throw new Error('Unsupported arrity ' + callback.length) } - } -assert.calls = expect; +assert.calls = expect -assert.isNull = function(item, message) { - message = message || "expected " + item + " to be null"; - assert.ok(item === null, message); -}; +assert.isNull = function (item, message) { + message = message || 'expected ' + item + ' to be null' + assert.ok(item === null, message) +} const getMode = () => { if (args.native) return 'native' @@ -173,70 +172,69 @@ const getMode = () => { return '' } -global.test = function(name, action) { - test.testCount ++; - test[name] = action; - var result = test[name](); - if(result === false) { - process.stdout.write('?'); - }else{ - process.stdout.write('.'); +global.test = function (name, action) { + test.testCount ++ + test[name] = action + var result = test[name]() + if (result === false) { + process.stdout.write('?') + } else { + process.stdout.write('.') } -}; +} -//print out the filename -process.stdout.write(require('path').basename(process.argv[1])); -if(args.binary) process.stdout.write(' (binary)'); -if(args.native) process.stdout.write(' (native)'); +// print out the filename +process.stdout.write(require('path').basename(process.argv[1])) +if (args.binary) process.stdout.write(' (binary)') +if (args.native) process.stdout.write(' (native)') -process.on('exit', function() { +process.on('exit', function () { console.log('') }) -process.on('uncaughtException', function(err) { - console.error("\n %s", err.stack || err.toString()) - //causes xargs to abort right away - process.exit(255); -}); +process.on('uncaughtException', function (err) { + console.error('\n %s', err.stack || err.toString()) + // causes xargs to abort right away + process.exit(255) +}) -var count = 0; +var count = 0 -var Sink = function(expected, timeout, callback) { - var defaultTimeout = 5000; - if(typeof timeout == 'function') { - callback = timeout; - timeout = defaultTimeout; +var Sink = function (expected, timeout, callback) { + var defaultTimeout = 5000 + if (typeof timeout === 'function') { + callback = timeout + timeout = defaultTimeout } - timeout = timeout || defaultTimeout; - var internalCount = 0; - var kill = function() { - assert.ok(false, "Did not reach expected " + expected + " with an idle timeout of " + timeout); + timeout = timeout || defaultTimeout + var internalCount = 0 + var kill = function () { + assert.ok(false, 'Did not reach expected ' + expected + ' with an idle timeout of ' + timeout) } - var killTimeout = setTimeout(kill, timeout); + var killTimeout = setTimeout(kill, timeout) return { - add: function(count) { - count = count || 1; - internalCount += count; + add: function (count) { + count = count || 1 + internalCount += count clearTimeout(killTimeout) - if(internalCount < expected) { + if (internalCount < expected) { killTimeout = setTimeout(kill, timeout) - } - else { - assert.equal(internalCount, expected); - callback(); + } else { + assert.equal(internalCount, expected) + callback() } } } } -var getTimezoneOffset = Date.prototype.getTimezoneOffset; +var getTimezoneOffset = Date.prototype.getTimezoneOffset -var setTimezoneOffset = function(minutesOffset) { - Date.prototype.getTimezoneOffset = function () { return minutesOffset; }; +var setTimezoneOffset = function (minutesOffset) { + Date.prototype.getTimezoneOffset = function () { return minutesOffset } } -var resetTimezoneOffset = function() { - Date.prototype.getTimezoneOffset = getTimezoneOffset; +var resetTimezoneOffset = function () { + Date.prototype.getTimezoneOffset = getTimezoneOffset } module.exports = { @@ -249,6 +247,4 @@ module.exports = { Client: Client, setTimezoneOffset: setTimezoneOffset, resetTimezoneOffset: resetTimezoneOffset -}; - - +} diff --git a/test/unit/client/cleartext-password-tests.js b/test/unit/client/cleartext-password-tests.js index 67e7c67b..cd8dbb00 100644 --- a/test/unit/client/cleartext-password-tests.js +++ b/test/unit/client/cleartext-password-tests.js @@ -1,23 +1,21 @@ -"use strict"; +'use strict' -const createClient = require('./test-helper').createClient; +const createClient = require('./test-helper').createClient /* * TODO: Add _some_ comments to explain what it is we're testing, and how the * code-being-tested works behind the scenes. */ -test('cleartext password authentication', function(){ - - var client = createClient(); - client.password = "!"; - client.connection.stream.packets = []; - client.connection.emit('authenticationCleartextPassword'); - test('responds with password', function() { - var packets = client.connection.stream.packets; - assert.lengthIs(packets, 1); - var packet = packets[0]; - assert.equalBuffers(packet, [0x70, 0, 0, 0, 6, 33, 0]); - }); - -}); +test('cleartext password authentication', function () { + var client = createClient() + client.password = '!' + client.connection.stream.packets = [] + client.connection.emit('authenticationCleartextPassword') + test('responds with password', function () { + var packets = client.connection.stream.packets + assert.lengthIs(packets, 1) + var packet = packets[0] + assert.equalBuffers(packet, [0x70, 0, 0, 0, 6, 33, 0]) + }) +}) diff --git a/test/unit/client/configuration-tests.js b/test/unit/client/configuration-tests.js index bf007ee7..9c1fadc8 100644 --- a/test/unit/client/configuration-tests.js +++ b/test/unit/client/configuration-tests.js @@ -1,171 +1,167 @@ -"use strict"; -require(__dirname+'/test-helper'); +'use strict' +require(__dirname + '/test-helper') -var pguser = process.env['PGUSER'] || process.env.USER; -var pgdatabase = process.env['PGDATABASE'] || process.env.USER; -var pgport = process.env['PGPORT'] || 5432; +var pguser = process.env['PGUSER'] || process.env.USER +var pgdatabase = process.env['PGDATABASE'] || process.env.USER +var pgport = process.env['PGPORT'] || 5432 -test('client settings', function() { +test('client settings', function () { + test('defaults', function () { + var client = new Client() + assert.equal(client.user, pguser) + assert.equal(client.database, pgdatabase) + assert.equal(client.port, pgport) + assert.equal(client.ssl, false) + }) - test('defaults', function() { - var client = new Client(); - assert.equal(client.user, pguser); - assert.equal(client.database, pgdatabase); - assert.equal(client.port, pgport); - assert.equal(client.ssl, false); - }); - - test('custom', function() { - var user = 'brian'; - var database = 'pgjstest'; - var password = 'boom'; + test('custom', function () { + var user = 'brian' + var database = 'pgjstest' + var password = 'boom' var client = new Client({ user: user, database: database, port: 321, password: password, ssl: true - }); + }) - assert.equal(client.user, user); - assert.equal(client.database, database); - assert.equal(client.port, 321); - assert.equal(client.password, password); - assert.equal(client.ssl, true); - }); + assert.equal(client.user, user) + assert.equal(client.database, database) + assert.equal(client.port, 321) + assert.equal(client.password, password) + assert.equal(client.ssl, true) + }) - test('custom ssl default on', function() { - var old = process.env.PGSSLMODE; - process.env.PGSSLMODE = "prefer"; + test('custom ssl default on', function () { + var old = process.env.PGSSLMODE + process.env.PGSSLMODE = 'prefer' - var client = new Client(); - process.env.PGSSLMODE = old; + var client = new Client() + process.env.PGSSLMODE = old - assert.equal(client.ssl, true); - }); + assert.equal(client.ssl, true) + }) - test('custom ssl force off', function() { - var old = process.env.PGSSLMODE; - process.env.PGSSLMODE = "prefer"; + test('custom ssl force off', function () { + var old = process.env.PGSSLMODE + process.env.PGSSLMODE = 'prefer' var client = new Client({ ssl: false - }); - process.env.PGSSLMODE = old; + }) + process.env.PGSSLMODE = old - assert.equal(client.ssl, false); - }); - -}); - -test('initializing from a config string', function() { + assert.equal(client.ssl, false) + }) +}) +test('initializing from a config string', function () { test('uses connectionString property', function () { var client = new Client({ connectionString: 'postgres://brian:pass@host1:333/databasename' }) - assert.equal(client.user, 'brian'); - assert.equal(client.password, "pass"); - assert.equal(client.host, "host1"); - assert.equal(client.port, 333); - assert.equal(client.database, "databasename"); + assert.equal(client.user, 'brian') + assert.equal(client.password, 'pass') + assert.equal(client.host, 'host1') + assert.equal(client.port, 333) + assert.equal(client.database, 'databasename') }) - test('uses the correct values from the config string', function() { - var client = new Client("postgres://brian:pass@host1:333/databasename") - assert.equal(client.user, 'brian'); - assert.equal(client.password, "pass"); - assert.equal(client.host, "host1"); - assert.equal(client.port, 333); - assert.equal(client.database, "databasename"); - }); + test('uses the correct values from the config string', function () { + var client = new Client('postgres://brian:pass@host1:333/databasename') + assert.equal(client.user, 'brian') + assert.equal(client.password, 'pass') + assert.equal(client.host, 'host1') + assert.equal(client.port, 333) + assert.equal(client.database, 'databasename') + }) - test('uses the correct values from the config string with space in password', function() { - var client = new Client("postgres://brian:pass word@host1:333/databasename") - assert.equal(client.user, 'brian'); - assert.equal(client.password, "pass word"); - assert.equal(client.host, "host1"); - assert.equal(client.port, 333); - assert.equal(client.database, "databasename"); - }); + test('uses the correct values from the config string with space in password', function () { + var client = new Client('postgres://brian:pass word@host1:333/databasename') + assert.equal(client.user, 'brian') + assert.equal(client.password, 'pass word') + assert.equal(client.host, 'host1') + assert.equal(client.port, 333) + assert.equal(client.database, 'databasename') + }) - test('when not including all values the defaults are used', function() { - var client = new Client("postgres://host1"); - assert.equal(client.user, process.env['PGUSER'] || process.env.USER); - assert.equal(client.password, process.env['PGPASSWORD'] || null); - assert.equal(client.host, "host1"); - assert.equal(client.port, process.env['PGPORT'] || 5432); - assert.equal(client.database, process.env['PGDATABASE'] || process.env.USER); - }); + test('when not including all values the defaults are used', function () { + var client = new Client('postgres://host1') + assert.equal(client.user, process.env['PGUSER'] || process.env.USER) + assert.equal(client.password, process.env['PGPASSWORD'] || null) + assert.equal(client.host, 'host1') + assert.equal(client.port, process.env['PGPORT'] || 5432) + assert.equal(client.database, process.env['PGDATABASE'] || process.env.USER) + }) - test('when not including all values the environment variables are used', function() { - var envUserDefined = process.env['PGUSER'] !== undefined; - var envPasswordDefined = process.env['PGPASSWORD'] !== undefined; - var envDBDefined = process.env['PGDATABASE'] !== undefined; - var envHostDefined = process.env['PGHOST'] !== undefined; - var envPortDefined = process.env['PGPORT'] !== undefined; + test('when not including all values the environment variables are used', function () { + var envUserDefined = process.env['PGUSER'] !== undefined + var envPasswordDefined = process.env['PGPASSWORD'] !== undefined + var envDBDefined = process.env['PGDATABASE'] !== undefined + var envHostDefined = process.env['PGHOST'] !== undefined + var envPortDefined = process.env['PGPORT'] !== undefined - var savedEnvUser = process.env['PGUSER']; - var savedEnvPassword = process.env['PGPASSWORD']; - var savedEnvDB = process.env['PGDATABASE']; - var savedEnvHost = process.env['PGHOST']; - var savedEnvPort = process.env['PGPORT']; + var savedEnvUser = process.env['PGUSER'] + var savedEnvPassword = process.env['PGPASSWORD'] + var savedEnvDB = process.env['PGDATABASE'] + var savedEnvHost = process.env['PGHOST'] + var savedEnvPort = process.env['PGPORT'] - process.env['PGUSER'] = 'utUser1'; - process.env['PGPASSWORD'] = 'utPass1'; - process.env['PGDATABASE'] = 'utDB1'; - process.env['PGHOST'] = 'utHost1'; - process.env['PGPORT'] = 5464; + process.env['PGUSER'] = 'utUser1' + process.env['PGPASSWORD'] = 'utPass1' + process.env['PGDATABASE'] = 'utDB1' + process.env['PGHOST'] = 'utHost1' + process.env['PGPORT'] = 5464 - var client = new Client("postgres://host1"); - assert.equal(client.user, process.env['PGUSER']); - assert.equal(client.password, process.env['PGPASSWORD']); - assert.equal(client.host, "host1"); - assert.equal(client.port, process.env['PGPORT']); - assert.equal(client.database, process.env['PGDATABASE']); + var client = new Client('postgres://host1') + assert.equal(client.user, process.env['PGUSER']) + assert.equal(client.password, process.env['PGPASSWORD']) + assert.equal(client.host, 'host1') + assert.equal(client.port, process.env['PGPORT']) + assert.equal(client.database, process.env['PGDATABASE']) if (envUserDefined) { - process.env['PGUSER'] = savedEnvUser; + process.env['PGUSER'] = savedEnvUser } else { - delete process.env['PGUSER']; + delete process.env['PGUSER'] } if (envPasswordDefined) { - process.env['PGPASSWORD'] = savedEnvPassword; + process.env['PGPASSWORD'] = savedEnvPassword } else { - delete process.env['PGPASSWORD']; + delete process.env['PGPASSWORD'] } if (envDBDefined) { - process.env['PGDATABASE'] = savedEnvDB; + process.env['PGDATABASE'] = savedEnvDB } else { - delete process.env['PGDATABASE']; + delete process.env['PGDATABASE'] } if (envHostDefined) { - process.env['PGHOST'] = savedEnvHost; + process.env['PGHOST'] = savedEnvHost } else { - delete process.env['PGHOST']; + delete process.env['PGHOST'] } if (envPortDefined) { - process.env['PGPORT'] = savedEnvPort; + process.env['PGPORT'] = savedEnvPort } else { - delete process.env['PGPORT']; + delete process.env['PGPORT'] } - }); -}); - -test('calls connect correctly on connection', function() { - var client = new Client("/tmp"); - var usedPort = ""; - var usedHost = ""; - client.connection.connect = function(port, host) { - usedPort = port; - usedHost = host; - }; - client.connect(); - assert.equal(usedPort, "/tmp/.s.PGSQL." + pgport); - assert.strictEqual(usedHost, undefined); -}); + }) +}) +test('calls connect correctly on connection', function () { + var client = new Client('/tmp') + var usedPort = '' + var usedHost = '' + client.connection.connect = function (port, host) { + usedPort = port + usedHost = host + } + client.connect() + assert.equal(usedPort, '/tmp/.s.PGSQL.' + pgport) + assert.strictEqual(usedHost, undefined) +}) diff --git a/test/unit/client/early-disconnect-tests.js b/test/unit/client/early-disconnect-tests.js index c8d7fbc5..35a587d9 100644 --- a/test/unit/client/early-disconnect-tests.js +++ b/test/unit/client/early-disconnect-tests.js @@ -1,17 +1,17 @@ -"use strict"; -var helper = require('./test-helper'); -var net = require('net'); -var pg = require('../../../lib/index.js'); +'use strict' +var helper = require('./test-helper') +var net = require('net') +var pg = require('../../../lib/index.js') /* console.log() messages show up in `make test` output. TODO: fix it. */ -var server = net.createServer(function(c) { - c.destroy(); - server.close(); -}); +var server = net.createServer(function (c) { + c.destroy() + server.close() +}) -server.listen(7777, function() { - var client = new pg.Client('postgres://localhost:7777'); - client.connect(assert.calls(function(err) { - assert(err); - })); -}); +server.listen(7777, function () { + var client = new pg.Client('postgres://localhost:7777') + client.connect(assert.calls(function (err) { + assert(err) + })) +}) diff --git a/test/unit/client/escape-tests.js b/test/unit/client/escape-tests.js index 7ea640fc..8229a3a3 100644 --- a/test/unit/client/escape-tests.js +++ b/test/unit/client/escape-tests.js @@ -1,73 +1,73 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); +'use strict' +var helper = require(__dirname + '/test-helper') -function createClient(callback) { - var client = new Client(helper.config); - client.connect(function(err) { - return callback(client); - }); +function createClient (callback) { + var client = new Client(helper.config) + client.connect(function (err) { + return callback(client) + }) } -var testLit = function(testName, input, expected) { - test(testName, function(){ - var client = new Client(helper.config); - var actual = client.escapeLiteral(input); - assert.equal(expected, actual); - }); -}; +var testLit = function (testName, input, expected) { + test(testName, function () { + var client = new Client(helper.config) + var actual = client.escapeLiteral(input) + assert.equal(expected, actual) + }) +} -var testIdent = function(testName, input, expected) { - test(testName, function(){ - var client = new Client(helper.config); - var actual = client.escapeIdentifier(input); - assert.equal(expected, actual); - }); -}; +var testIdent = function (testName, input, expected) { + test(testName, function () { + var client = new Client(helper.config) + var actual = client.escapeIdentifier(input) + assert.equal(expected, actual) + }) +} testLit('escapeLiteral: no special characters', - 'hello world', "'hello world'"); + 'hello world', "'hello world'") testLit('escapeLiteral: contains double quotes only', - 'hello " world', "'hello \" world'"); + 'hello " world', "'hello \" world'") testLit('escapeLiteral: contains single quotes only', - 'hello \' world', "'hello \'\' world'"); + 'hello \' world', "'hello \'\' world'") testLit('escapeLiteral: contains backslashes only', - 'hello \\ world', " E'hello \\\\ world'"); + 'hello \\ world', " E'hello \\\\ world'") testLit('escapeLiteral: contains single quotes and double quotes', - 'hello \' " world', "'hello '' \" world'"); + 'hello \' " world', "'hello '' \" world'") testLit('escapeLiteral: contains double quotes and backslashes', - 'hello \\ " world', " E'hello \\\\ \" world'"); + 'hello \\ " world', " E'hello \\\\ \" world'") testLit('escapeLiteral: contains single quotes and backslashes', - 'hello \\ \' world', " E'hello \\\\ '' world'"); + 'hello \\ \' world', " E'hello \\\\ '' world'") testLit('escapeLiteral: contains single quotes, double quotes, and backslashes', - 'hello \\ \' " world', " E'hello \\\\ '' \" world'"); + 'hello \\ \' " world', " E'hello \\\\ '' \" world'") testIdent('escapeIdentifier: no special characters', - 'hello world', '"hello world"'); + 'hello world', '"hello world"') testIdent('escapeIdentifier: contains double quotes only', - 'hello " world', '"hello "" world"'); + 'hello " world', '"hello "" world"') testIdent('escapeIdentifier: contains single quotes only', - 'hello \' world', '"hello \' world"'); + 'hello \' world', '"hello \' world"') testIdent('escapeIdentifier: contains backslashes only', - 'hello \\ world', '"hello \\ world"'); + 'hello \\ world', '"hello \\ world"') testIdent('escapeIdentifier: contains single quotes and double quotes', - 'hello \' " world', '"hello \' "" world"'); + 'hello \' " world', '"hello \' "" world"') testIdent('escapeIdentifier: contains double quotes and backslashes', - 'hello \\ " world', '"hello \\ "" world"'); + 'hello \\ " world', '"hello \\ "" world"') testIdent('escapeIdentifier: contains single quotes and backslashes', - 'hello \\ \' world', '"hello \\ \' world"'); + 'hello \\ \' world', '"hello \\ \' world"') testIdent('escapeIdentifier: contains single quotes, double quotes, and backslashes', - 'hello \\ \' " world', '"hello \\ \' "" world"'); + 'hello \\ \' " world', '"hello \\ \' "" world"') diff --git a/test/unit/client/md5-password-tests.js b/test/unit/client/md5-password-tests.js index 63a0398d..26e233ed 100644 --- a/test/unit/client/md5-password-tests.js +++ b/test/unit/client/md5-password-tests.js @@ -1,26 +1,26 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') var utils = require('../../../lib/utils') -test('md5 authentication', function() { - var client = helper.createClient(); - client.password = "!"; - var salt = Buffer.from([1, 2, 3, 4]); - client.connection.emit('authenticationMD5Password', {salt: salt}); +test('md5 authentication', function () { + var client = helper.createClient() + client.password = '!' + var salt = Buffer.from([1, 2, 3, 4]) + client.connection.emit('authenticationMD5Password', {salt: salt}) - test('responds', function() { - assert.lengthIs(client.connection.stream.packets, 1); - test('should have correct encrypted data', function() { - var encrypted = utils.md5(client.password + client.user); - encrypted = utils.md5(encrypted + salt.toString('binary')); - var password = "md5" + encrypted - //how do we want to test this? + test('responds', function () { + assert.lengthIs(client.connection.stream.packets, 1) + test('should have correct encrypted data', function () { + var encrypted = utils.md5(client.password + client.user) + encrypted = utils.md5(encrypted + salt.toString('binary')) + var password = 'md5' + encrypted + // how do we want to test this? assert.equalBuffers(client.connection.stream.packets[0], new BufferList() - .addCString(password).join(true,'p')); - }); - }); -}); + .addCString(password).join(true, 'p')) + }) + }) +}) -test('md5 of utf-8 strings', function() { - assert.equal(utils.md5('😊'), '5deda34cd95f304948d2bc1b4a62c11e'); -}); +test('md5 of utf-8 strings', function () { + assert.equal(utils.md5('😊'), '5deda34cd95f304948d2bc1b4a62c11e') +}) diff --git a/test/unit/client/notification-tests.js b/test/unit/client/notification-tests.js index dab8f608..5ca9df22 100644 --- a/test/unit/client/notification-tests.js +++ b/test/unit/client/notification-tests.js @@ -1,11 +1,10 @@ -"use strict"; -var helper = require(__dirname + "/test-helper"); +'use strict' +var helper = require(__dirname + '/test-helper') -test('passes connection notification', function() { - var client = helper.client(); - assert.emits(client, 'notice', function(msg) { - assert.equal(msg, "HAY!!"); +test('passes connection notification', function () { + var client = helper.client() + assert.emits(client, 'notice', function (msg) { + assert.equal(msg, 'HAY!!') }) - client.connection.emit('notice', "HAY!!"); + client.connection.emit('notice', 'HAY!!') }) - diff --git a/test/unit/client/prepared-statement-tests.js b/test/unit/client/prepared-statement-tests.js index 50327bf4..0dc9e80a 100644 --- a/test/unit/client/prepared-statement-tests.js +++ b/test/unit/client/prepared-statement-tests.js @@ -1,88 +1,88 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') var Query = require('../../../lib/query') -var client = helper.client(); -var con = client.connection; -var parseArg = null; -con.parse = function(arg) { - parseArg = arg; - process.nextTick(function() { - con.emit('parseComplete'); - }); -}; +var client = helper.client() +var con = client.connection +var parseArg = null +con.parse = function (arg) { + parseArg = arg + process.nextTick(function () { + con.emit('parseComplete') + }) +} -var bindArg = null; -con.bind = function(arg) { - bindArg = arg; - process.nextTick(function(){ - con.emit('bindComplete'); - }); -}; +var bindArg = null +con.bind = function (arg) { + bindArg = arg + process.nextTick(function () { + con.emit('bindComplete') + }) +} -var executeArg = null; -con.execute = function(arg) { - executeArg = arg; - process.nextTick(function() { - con.emit('rowData',{ fields: [] }); - con.emit('commandComplete', { text: "" }); - }); -}; +var executeArg = null +con.execute = function (arg) { + executeArg = arg + process.nextTick(function () { + con.emit('rowData', { fields: [] }) + con.emit('commandComplete', { text: '' }) + }) +} -var describeArg = null; -con.describe = function(arg) { - describeArg = arg; - process.nextTick(function() { - con.emit('rowDescription', { fields: [] }); - }); -}; +var describeArg = null +con.describe = function (arg) { + describeArg = arg + process.nextTick(function () { + con.emit('rowDescription', { fields: [] }) + }) +} -var syncCalled = false; -con.flush = function() { -}; -con.sync = function() { - syncCalled = true; - process.nextTick(function() { - con.emit('readyForQuery'); - }); -}; +var syncCalled = false +con.flush = function () { +} +con.sync = function () { + syncCalled = true + process.nextTick(function () { + con.emit('readyForQuery') + }) +} -test('bound command', function() { - test('simple, unnamed bound command', function() { - assert.ok(client.connection.emit('readyForQuery')); +test('bound command', function () { + test('simple, unnamed bound command', function () { + assert.ok(client.connection.emit('readyForQuery')) var query = client.query(new Query({ text: 'select * from X where name = $1', values: ['hi'] - })); + })) - assert.emits(query,'end', function() { - test('parse argument', function() { - assert.equal(parseArg.name, null); - assert.equal(parseArg.text, 'select * from X where name = $1'); - assert.equal(parseArg.types, null); - }); + assert.emits(query, 'end', function () { + test('parse argument', function () { + assert.equal(parseArg.name, null) + assert.equal(parseArg.text, 'select * from X where name = $1') + assert.equal(parseArg.types, null) + }) - test('bind argument', function() { - assert.equal(bindArg.statement, null); - assert.equal(bindArg.portal, null); - assert.lengthIs(bindArg.values, 1); + test('bind argument', function () { + assert.equal(bindArg.statement, null) + assert.equal(bindArg.portal, null) + assert.lengthIs(bindArg.values, 1) assert.equal(bindArg.values[0], 'hi') - }); + }) - test('describe argument', function() { - assert.equal(describeArg.type, 'P'); - assert.equal(describeArg.name, ""); - }); + test('describe argument', function () { + assert.equal(describeArg.type, 'P') + assert.equal(describeArg.name, '') + }) - test('execute argument', function() { - assert.equal(executeArg.portal, null); - assert.equal(executeArg.rows, null); - }); + test('execute argument', function () { + assert.equal(executeArg.portal, null) + assert.equal(executeArg.rows, null) + }) - test('sync called', function() { - assert.ok(syncCalled); - }); - }); - }); -}); + test('sync called', function () { + assert.ok(syncCalled) + }) + }) + }) +}) diff --git a/test/unit/client/query-queue-tests.js b/test/unit/client/query-queue-tests.js index 2aa3b6b0..62069c01 100644 --- a/test/unit/client/query-queue-tests.js +++ b/test/unit/client/query-queue-tests.js @@ -1,53 +1,53 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); +'use strict' +var helper = require(__dirname + '/test-helper') +var Connection = require(__dirname + '/../../../lib/connection') -test('drain', function() { - var con = new Connection({stream: "NO"}); - var client = new Client({connection:con}); - con.connect = function() { - con.emit('connect'); - }; - con.query = function() { - }; - client.connect(); +test('drain', function () { + var con = new Connection({stream: 'NO'}) + var client = new Client({connection: con}) + con.connect = function () { + con.emit('connect') + } + con.query = function () { + } + client.connect() - var raisedDrain = false; - client.on('drain', function() { - raisedDrain = true; - }); + var raisedDrain = false + client.on('drain', function () { + raisedDrain = true + }) - client.query("hello"); - client.query("sup"); - client.query('boom'); + client.query('hello') + client.query('sup') + client.query('boom') - test("with pending queries", function() { - test("does not emit drain", function() { - assert.equal(raisedDrain, false); - }); - }); + test('with pending queries', function () { + test('does not emit drain', function () { + assert.equal(raisedDrain, false) + }) + }) - test("after some queries executed", function() { - con.emit('readyForQuery'); - test("does not emit drain", function() { - assert.equal(raisedDrain, false); - }); - }); + test('after some queries executed', function () { + con.emit('readyForQuery') + test('does not emit drain', function () { + assert.equal(raisedDrain, false) + }) + }) - test("when all queries are sent", function() { - con.emit('readyForQuery'); - con.emit('readyForQuery'); - test("does not emit drain", function() { - assert.equal(raisedDrain, false); - }); - }); + test('when all queries are sent', function () { + con.emit('readyForQuery') + con.emit('readyForQuery') + test('does not emit drain', function () { + assert.equal(raisedDrain, false) + }) + }) - test("after last query finishes", function() { - con.emit('readyForQuery'); - test("emits drain", function() { - process.nextTick(function() { - assert.ok(raisedDrain); + test('after last query finishes', function () { + con.emit('readyForQuery') + test('emits drain', function () { + process.nextTick(function () { + assert.ok(raisedDrain) }) - }); - }); -}); + }) + }) +}) diff --git a/test/unit/client/result-metadata-tests.js b/test/unit/client/result-metadata-tests.js index c3f26620..59b83443 100644 --- a/test/unit/client/result-metadata-tests.js +++ b/test/unit/client/result-metadata-tests.js @@ -1,38 +1,37 @@ -"use strict"; -var helper = require(__dirname + "/test-helper") +'use strict' +var helper = require(__dirname + '/test-helper') -var testForTag = function(tagText, callback) { - test('includes command tag data for tag ' + tagText, function() { - - var client = helper.client(); +var testForTag = function (tagText, callback) { + test('includes command tag data for tag ' + tagText, function () { + var client = helper.client() client.connection.emit('readyForQuery') - var query = client.query("whatever", assert.calls((err, result) => { - assert.ok(result != null, "should pass something to this event") + var query = client.query('whatever', assert.calls((err, result) => { + assert.ok(result != null, 'should pass something to this event') callback(result) - })); + })) assert.lengthIs(client.connection.queries, 1) client.connection.emit('commandComplete', { text: tagText - }); + }) - client.connection.emit('readyForQuery'); + client.connection.emit('readyForQuery') }) } -var check = function(oid, rowCount, command) { - return function(result) { - if(oid != null) { - assert.equal(result.oid, oid); +var check = function (oid, rowCount, command) { + return function (result) { + if (oid != null) { + assert.equal(result.oid, oid) } - assert.equal(result.rowCount, rowCount); - assert.equal(result.command, command); + assert.equal(result.rowCount, rowCount) + assert.equal(result.command, command) } } -testForTag("INSERT 0 3", check(0, 3, "INSERT")); -testForTag("INSERT 841 1", check(841, 1, "INSERT")); -testForTag("DELETE 10", check(null, 10, "DELETE")); -testForTag("UPDATE 11", check(null, 11, "UPDATE")); -testForTag("SELECT 20", check(null, 20, "SELECT")); +testForTag('INSERT 0 3', check(0, 3, 'INSERT')) +testForTag('INSERT 841 1', check(841, 1, 'INSERT')) +testForTag('DELETE 10', check(null, 10, 'DELETE')) +testForTag('UPDATE 11', check(null, 11, 'UPDATE')) +testForTag('SELECT 20', check(null, 20, 'SELECT')) diff --git a/test/unit/client/simple-query-tests.js b/test/unit/client/simple-query-tests.js index 29ab0012..363c44db 100644 --- a/test/unit/client/simple-query-tests.js +++ b/test/unit/client/simple-query-tests.js @@ -1,129 +1,123 @@ -"use strict"; -var helper = require(__dirname + "/test-helper"); +'use strict' +var helper = require(__dirname + '/test-helper') var Query = require('../../../lib/query') -test('executing query', function() { +test('executing query', function () { + test('queing query', function () { + test('when connection is ready', function () { + var client = helper.client() + assert.empty(client.connection.queries) + client.connection.emit('readyForQuery') + client.query('yes') + assert.lengthIs(client.connection.queries, 1) + assert.equal(client.connection.queries, 'yes') + }) - test("queing query", function() { + test('when connection is not ready', function () { + var client = helper.client() - test('when connection is ready', function() { - var client = helper.client(); - assert.empty(client.connection.queries); - client.connection.emit('readyForQuery'); - client.query('yes'); - assert.lengthIs(client.connection.queries, 1); - assert.equal(client.connection.queries, 'yes'); - }); + test('query is not sent', function () { + client.query('boom') + assert.empty(client.connection.queries) + }) - test('when connection is not ready', function() { - var client = helper.client(); + test('sends query to connection once ready', function () { + assert.ok(client.connection.emit('readyForQuery')) + assert.lengthIs(client.connection.queries, 1) + assert.equal(client.connection.queries[0], 'boom') + }) + }) - test('query is not sent', function() { - client.query('boom'); - assert.empty(client.connection.queries); - }); + test('multiple in the queue', function () { + var client = helper.client() + var connection = client.connection + var queries = connection.queries + client.query('one') + client.query('two') + client.query('three') + assert.empty(queries) - test('sends query to connection once ready', function() { - assert.ok(client.connection.emit('readyForQuery')); - assert.lengthIs(client.connection.queries, 1); - assert.equal(client.connection.queries[0], "boom"); - }); + test('after one ready for query', function () { + connection.emit('readyForQuery') + assert.lengthIs(queries, 1) + assert.equal(queries[0], 'one') + }) - }); + test('after two ready for query', function () { + connection.emit('readyForQuery') + assert.lengthIs(queries, 2) + }) - test("multiple in the queue", function() { - var client = helper.client(); - var connection = client.connection; - var queries = connection.queries; - client.query('one'); - client.query('two'); - client.query('three'); - assert.empty(queries); + test('after a bunch more', function () { + connection.emit('readyForQuery') + connection.emit('readyForQuery') + connection.emit('readyForQuery') + assert.lengthIs(queries, 3) + assert.equal(queries[0], 'one') + assert.equal(queries[1], 'two') + assert.equal(queries[2], 'three') + }) + }) + }) - test("after one ready for query",function() { - connection.emit('readyForQuery'); - assert.lengthIs(queries, 1); - assert.equal(queries[0], "one"); - }); + test('query event binding and flow', function () { + var client = helper.client() + var con = client.connection + var query = client.query(new Query('whatever')) - test('after two ready for query', function() { - connection.emit('readyForQuery'); - assert.lengthIs(queries, 2); - }); + test('has no queries sent before ready', function () { + assert.empty(con.queries) + }) - test("after a bunch more", function() { - connection.emit('readyForQuery'); - connection.emit('readyForQuery'); - connection.emit('readyForQuery'); - assert.lengthIs(queries, 3); - assert.equal(queries[0], "one"); - assert.equal(queries[1], 'two'); - assert.equal(queries[2], 'three'); - }); - }); - }); + test('sends query on readyForQuery event', function () { + con.emit('readyForQuery') + assert.lengthIs(con.queries, 1) + assert.equal(con.queries[0], 'whatever') + }) - test("query event binding and flow", function() { - var client = helper.client(); - var con = client.connection; - var query = client.query(new Query('whatever')); - - test("has no queries sent before ready", function() { - assert.empty(con.queries); - }); - - test('sends query on readyForQuery event', function() { - con.emit('readyForQuery'); - assert.lengthIs(con.queries, 1); - assert.equal(con.queries[0], 'whatever'); - }); - - test('handles rowDescription message', function() { - var handled = con.emit('rowDescription',{ + test('handles rowDescription message', function () { + var handled = con.emit('rowDescription', { fields: [{ name: 'boom' }] - }); - assert.ok(handled, "should have handlded rowDescription"); - }); + }) + assert.ok(handled, 'should have handlded rowDescription') + }) - test('handles dataRow messages', function() { - assert.emits(query, 'row', function(row) { - assert.equal(row['boom'], "hi"); - }); + test('handles dataRow messages', function () { + assert.emits(query, 'row', function (row) { + assert.equal(row['boom'], 'hi') + }) - var handled = con.emit('dataRow', { fields: ["hi"] }); - assert.ok(handled, "should have handled first data row message"); + var handled = con.emit('dataRow', { fields: ['hi'] }) + assert.ok(handled, 'should have handled first data row message') - assert.emits(query, 'row', function(row) { - assert.equal(row['boom'], "bye"); - }); + assert.emits(query, 'row', function (row) { + assert.equal(row['boom'], 'bye') + }) - var handledAgain = con.emit('dataRow', { fields: ["bye"] }); - assert.ok(handledAgain, "should have handled seciond data row message"); - }); + var handledAgain = con.emit('dataRow', { fields: ['bye'] }) + assert.ok(handledAgain, 'should have handled seciond data row message') + }) - //multiple command complete messages will be sent - //when multiple queries are in a simple command - test('handles command complete messages', function() { + // multiple command complete messages will be sent + // when multiple queries are in a simple command + test('handles command complete messages', function () { con.emit('commandComplete', { text: 'INSERT 31 1' - }); - }); - - test('removes itself after another readyForQuery message', function() { - return false; - assert.emits(query, "end", function(msg) { - //TODO do we want to check the complete messages? - }); - con.emit("readyForQuery"); - //this would never actually happen - ['dataRow','rowDescription', 'commandComplete'].forEach(function(msg) { - assert.equal(con.emit(msg), false, "Should no longer be picking up '"+ msg +"' messages"); - }); - }); - - }); - -}); + }) + }) + test('removes itself after another readyForQuery message', function () { + return false + assert.emits(query, 'end', function (msg) { + // TODO do we want to check the complete messages? + }) + con.emit('readyForQuery'); + // this would never actually happen + ['dataRow', 'rowDescription', 'commandComplete'].forEach(function (msg) { + assert.equal(con.emit(msg), false, "Should no longer be picking up '" + msg + "' messages") + }) + }) + }) +}) diff --git a/test/unit/client/stream-and-query-error-interaction-tests.js b/test/unit/client/stream-and-query-error-interaction-tests.js index 0815fccd..af0e09a6 100644 --- a/test/unit/client/stream-and-query-error-interaction-tests.js +++ b/test/unit/client/stream-and-query-error-interaction-tests.js @@ -1,29 +1,29 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); -var Client = require(__dirname + '/../../../lib/client'); +'use strict' +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 +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, 'error'); - 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('close'); - }); - }); -}); + 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, 'error') + 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('close') + }) + }) +}) diff --git a/test/unit/client/test-helper.js b/test/unit/client/test-helper.js index fe1765d6..24f94df3 100644 --- a/test/unit/client/test-helper.js +++ b/test/unit/client/test-helper.js @@ -1,21 +1,21 @@ -"use strict"; -var helper = require('../test-helper'); -var Connection = require('../../../lib/connection'); +'use strict' +var helper = require('../test-helper') +var Connection = require('../../../lib/connection') -var makeClient = function() { - var connection = new Connection({stream: "no"}); - connection.startup = function() {}; - connection.connect = function() {}; - connection.query = function(text) { - this.queries.push(text); - }; - connection.queries = []; - var client = new Client({connection: connection}); - client.connect(); - client.connection.emit('connect'); - return client; -}; +var makeClient = function () { + var connection = new Connection({stream: 'no'}) + connection.startup = function () {} + connection.connect = function () {} + connection.query = function (text) { + this.queries.push(text) + } + connection.queries = [] + var client = new Client({connection: connection}) + client.connect() + client.connection.emit('connect') + return client +} module.exports = Object.assign({ client: makeClient -}, helper); +}, helper) diff --git a/test/unit/client/throw-in-type-parser-tests.js b/test/unit/client/throw-in-type-parser-tests.js index 06580eb0..24883241 100644 --- a/test/unit/client/throw-in-type-parser-tests.js +++ b/test/unit/client/throw-in-type-parser-tests.js @@ -1,70 +1,69 @@ -"use strict"; -var helper = require("./test-helper"); -var Query = require("../../../lib/query"); -var types = require("pg-types"); +'use strict' +var helper = require('./test-helper') +var Query = require('../../../lib/query') +var types = require('pg-types') -const suite = new helper.Suite(); +const suite = new helper.Suite() -var typeParserError = new Error("TEST: Throw in type parsers"); +var typeParserError = new Error('TEST: Throw in type parsers') -types.setTypeParser("special oid that will throw", function() { - throw typeParserError; -}); +types.setTypeParser('special oid that will throw', function () { + throw typeParserError +}) const emitFakeEvents = con => { setImmediate(() => { - con.emit("readyForQuery"); + con.emit('readyForQuery') - con.emit("rowDescription", { + con.emit('rowDescription', { fields: [ { - name: "boom", - dataTypeID: "special oid that will throw" + name: 'boom', + dataTypeID: 'special oid that will throw' } ] - }); + }) - con.emit("dataRow", { fields: ["hi"] }); - con.emit("dataRow", { fields: ["hi"] }); - con.emit("commandComplete", { text: "INSERT 31 1" }); - con.emit("readyForQuery"); - }); -}; + con.emit('dataRow', { fields: ['hi'] }) + con.emit('dataRow', { fields: ['hi'] }) + con.emit('commandComplete', { text: 'INSERT 31 1' }) + con.emit('readyForQuery') + }) +} -suite.test("emits error", function(done) { - var handled; - var client = helper.client(); - var con = client.connection; - var query = client.query(new Query("whatever")); +suite.test('emits error', function (done) { + var handled + var client = helper.client() + var con = client.connection + var query = client.query(new Query('whatever')) emitFakeEvents(con) - assert.emits(query, "error", function(err) { - assert.equal(err, typeParserError); - done(); - }); -}); + assert.emits(query, 'error', function (err) { + assert.equal(err, typeParserError) + done() + }) +}) -suite.test("calls callback with error", function(done) { - var handled; +suite.test('calls callback with error', function (done) { + var handled - var callbackCalled = 0; + var callbackCalled = 0 - var client = helper.client(); - var con = client.connection; - emitFakeEvents(con); - var query = client.query("whatever", function(err) { - assert.equal(err, typeParserError); - done(); - }); + var client = helper.client() + var con = client.connection + emitFakeEvents(con) + var query = client.query('whatever', function (err) { + assert.equal(err, typeParserError) + done() + }) +}) -}); - -suite.test("rejects promise with error", function(done) { - var client = helper.client(); - var con = client.connection; - emitFakeEvents(con); - client.query("whatever").catch(err => { - assert.equal(err, typeParserError); - done(); - }); -}); +suite.test('rejects promise with error', function (done) { + var client = helper.client() + var con = client.connection + emitFakeEvents(con) + client.query('whatever').catch(err => { + assert.equal(err, typeParserError) + done() + }) +}) diff --git a/test/unit/connection-parameters/creation-tests.js b/test/unit/connection-parameters/creation-tests.js index f0268a13..aa39a038 100644 --- a/test/unit/connection-parameters/creation-tests.js +++ b/test/unit/connection-parameters/creation-tests.js @@ -1,55 +1,55 @@ -"use strict"; -var helper = require(__dirname + '/../test-helper'); -var assert = require('assert'); -var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters'); -var defaults = require(__dirname + '/../../../lib').defaults; +'use strict' +var helper = require(__dirname + '/../test-helper') +var assert = require('assert') +var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters') +var defaults = require(__dirname + '/../../../lib').defaults -//clear process.env -for(var key in process.env) { - delete process.env[key]; +// clear process.env +for (var key in process.env) { + delete process.env[key] } -test('ConnectionParameters construction', function() { - assert.ok(new ConnectionParameters(), 'with null config'); - assert.ok(new ConnectionParameters({user: 'asdf'}), 'with config object'); - assert.ok(new ConnectionParameters('postgres://localhost/postgres'), 'with connection string'); -}); +test('ConnectionParameters construction', function () { + assert.ok(new ConnectionParameters(), 'with null config') + assert.ok(new ConnectionParameters({user: 'asdf'}), 'with config object') + assert.ok(new ConnectionParameters('postgres://localhost/postgres'), 'with connection string') +}) -var compare = function(actual, expected, type) { - assert.equal(actual.user, expected.user, type + ' user'); - assert.equal(actual.database, expected.database, type + ' database'); - assert.equal(actual.port, expected.port, type + ' port'); - assert.equal(actual.host, expected.host, type + ' host'); - assert.equal(actual.password, expected.password, type + ' password'); - assert.equal(actual.binary, expected.binary, type + ' binary'); -}; +var compare = function (actual, expected, type) { + assert.equal(actual.user, expected.user, type + ' user') + assert.equal(actual.database, expected.database, type + ' database') + assert.equal(actual.port, expected.port, type + ' port') + assert.equal(actual.host, expected.host, type + ' host') + assert.equal(actual.password, expected.password, type + ' password') + assert.equal(actual.binary, expected.binary, type + ' binary') +} -test('ConnectionParameters initializing from defaults', function() { - var subject = new ConnectionParameters(); - compare(subject, defaults, 'defaults'); - assert.ok(subject.isDomainSocket === false); -}); +test('ConnectionParameters initializing from defaults', function () { + var subject = new ConnectionParameters() + compare(subject, defaults, 'defaults') + assert.ok(subject.isDomainSocket === false) +}) -test('ConnectionParameters initializing from defaults with connectionString set', function() { +test('ConnectionParameters initializing from defaults with connectionString set', function () { var config = { - user : 'brians-are-the-best', - database : 'scoobysnacks', - port : 7777, - password : 'mypassword', - host : 'foo.bar.net', - binary : defaults.binary - }; + user: 'brians-are-the-best', + database: 'scoobysnacks', + port: 7777, + password: 'mypassword', + host: 'foo.bar.net', + binary: defaults.binary + } - var original_value = defaults.connectionString; + var original_value = defaults.connectionString // Just changing this here doesn't actually work because it's no longer in scope when viewed inside of // of ConnectionParameters() so we have to pass in the defaults explicitly to test it - defaults.connectionString = 'postgres://brians-are-the-best:mypassword@foo.bar.net:7777/scoobysnacks'; - var subject = new ConnectionParameters(defaults); - defaults.connectionString = original_value; - compare(subject, config, 'defaults-connectionString'); -}); + defaults.connectionString = 'postgres://brians-are-the-best:mypassword@foo.bar.net:7777/scoobysnacks' + var subject = new ConnectionParameters(defaults) + defaults.connectionString = original_value + compare(subject, config, 'defaults-connectionString') +}) -test('ConnectionParameters initializing from config', function() { +test('ConnectionParameters initializing from config', function () { var config = { user: 'brian', database: 'home', @@ -61,58 +61,58 @@ test('ConnectionParameters initializing from config', function() { ssl: { asdf: 'blah' } - }; - var subject = new ConnectionParameters(config); - compare(subject, config, 'config'); - assert.ok(subject.isDomainSocket === false); -}); + } + var subject = new ConnectionParameters(config) + compare(subject, config, 'config') + assert.ok(subject.isDomainSocket === false) +}) -test('escape spaces if present', function() { - var subject = new ConnectionParameters('postgres://localhost/post gres'); - assert.equal(subject.database, 'post gres'); -}); +test('escape spaces if present', function () { + var subject = new ConnectionParameters('postgres://localhost/post gres') + assert.equal(subject.database, 'post gres') +}) -test('do not double escape spaces', function() { - var subject = new ConnectionParameters('postgres://localhost/post%20gres'); - assert.equal(subject.database, 'post gres'); -}); +test('do not double escape spaces', function () { + var subject = new ConnectionParameters('postgres://localhost/post%20gres') + assert.equal(subject.database, 'post gres') +}) -test('initializing with unix domain socket', function() { - var subject = new ConnectionParameters('/var/run/'); - assert.ok(subject.isDomainSocket); - assert.equal(subject.host, '/var/run/'); - assert.equal(subject.database, defaults.user); -}); +test('initializing with unix domain socket', function () { + var subject = new ConnectionParameters('/var/run/') + assert.ok(subject.isDomainSocket) + assert.equal(subject.host, '/var/run/') + assert.equal(subject.database, defaults.user) +}) -test('initializing with unix domain socket and a specific database, the simple way', function() { - var subject = new ConnectionParameters('/var/run/ mydb'); - assert.ok(subject.isDomainSocket); - assert.equal(subject.host, '/var/run/'); - assert.equal(subject.database, 'mydb'); -}); +test('initializing with unix domain socket and a specific database, the simple way', function () { + var subject = new ConnectionParameters('/var/run/ mydb') + assert.ok(subject.isDomainSocket) + assert.equal(subject.host, '/var/run/') + assert.equal(subject.database, 'mydb') +}) -test('initializing with unix domain socket, the health way', function() { - var subject = new ConnectionParameters('socket:/some path/?db=my[db]&encoding=utf8'); - assert.ok(subject.isDomainSocket); - assert.equal(subject.host, '/some path/'); - assert.equal(subject.database, 'my[db]', 'must to be escaped and unescaped trough "my%5Bdb%5D"'); - assert.equal(subject.client_encoding, 'utf8'); -}); +test('initializing with unix domain socket, the health way', function () { + var subject = new ConnectionParameters('socket:/some path/?db=my[db]&encoding=utf8') + assert.ok(subject.isDomainSocket) + assert.equal(subject.host, '/some path/') + assert.equal(subject.database, 'my[db]', 'must to be escaped and unescaped trough "my%5Bdb%5D"') + assert.equal(subject.client_encoding, 'utf8') +}) -test('initializing with unix domain socket, the escaped health way', function() { - var subject = new ConnectionParameters('socket:/some%20path/?db=my%2Bdb&encoding=utf8'); - assert.ok(subject.isDomainSocket); - assert.equal(subject.host, '/some path/'); - assert.equal(subject.database, 'my+db'); - assert.equal(subject.client_encoding, 'utf8'); -}); +test('initializing with unix domain socket, the escaped health way', function () { + var subject = new ConnectionParameters('socket:/some%20path/?db=my%2Bdb&encoding=utf8') + assert.ok(subject.isDomainSocket) + assert.equal(subject.host, '/some path/') + assert.equal(subject.database, 'my+db') + assert.equal(subject.client_encoding, 'utf8') +}) -test('libpq connection string building', function() { - var checkForPart = function(array, part) { - assert.ok(array.indexOf(part) > -1, array.join(" ") + " did not contain " + part); +test('libpq connection string building', function () { + var checkForPart = function (array, part) { + assert.ok(array.indexOf(part) > -1, array.join(' ') + ' did not contain ' + part) } - test('builds simple string', function() { + test('builds simple string', function () { var config = { user: 'brian', password: 'xyz', @@ -120,132 +120,131 @@ test('libpq connection string building', function() { host: 'localhost', database: 'bam' } - var subject = new ConnectionParameters(config); - subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert(!err); - var parts = constring.split(" "); - checkForPart(parts, "user='brian'"); - checkForPart(parts, "password='xyz'"); - checkForPart(parts, "port='888'"); - checkForPart(parts, "hostaddr='127.0.0.1'"); - checkForPart(parts, "dbname='bam'"); - })); - }); + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString(assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, "password='xyz'") + checkForPart(parts, "port='888'") + checkForPart(parts, "hostaddr='127.0.0.1'") + checkForPart(parts, "dbname='bam'") + })) + }) - test('builds dns string', function() { + test('builds dns string', function () { var config = { user: 'brian', password: 'asdf', port: 5432, host: 'localhost' - }; - var subject = new ConnectionParameters(config); - subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert(!err); - var parts = constring.split(" "); - checkForPart(parts, "user='brian'"); - checkForPart(parts, "hostaddr='127.0.0.1'"); - })); - }); + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString(assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, "hostaddr='127.0.0.1'") + })) + }) - test('error when dns fails', function() { + test('error when dns fails', function () { var config = { user: 'brian', password: 'asf', port: 5432, host: 'asdlfkjasldfkksfd#!$!!!!..com' - }; - var subject = new ConnectionParameters(config); - subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert.ok(err); + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString(assert.calls(function (err, constring) { + assert.ok(err) assert.isNull(constring) - })); - }); + })) + }) - test('connecting to unix domain socket', function() { + test('connecting to unix domain socket', function () { var config = { user: 'brian', password: 'asf', port: 5432, host: '/tmp/' - }; - var subject = new ConnectionParameters(config); - subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert(!err); - var parts = constring.split(" "); - checkForPart(parts, "user='brian'"); - checkForPart(parts, "host='/tmp/'"); - })); - }); + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString(assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, "host='/tmp/'") + })) + }) - test('config contains quotes and backslashes', function() { + test('config contains quotes and backslashes', function () { var config = { user: 'not\\brian', password: 'bad\'chars', port: 5432, host: '/tmp/' - }; - var subject = new ConnectionParameters(config); - subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert(!err); - var parts = constring.split(" "); - checkForPart(parts, "user='not\\\\brian'"); - checkForPart(parts, "password='bad\\'chars'"); - })); - }); - - test("encoding can be specified by config", function() { - var config = { - client_encoding: "utf-8" } - var subject = new ConnectionParameters(config); - subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert(!err); - var parts = constring.split(" "); - checkForPart(parts, "client_encoding='utf-8'"); - })); + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString(assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='not\\\\brian'") + checkForPart(parts, "password='bad\\'chars'") + })) + }) + + test('encoding can be specified by config', function () { + var config = { + client_encoding: 'utf-8' + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString(assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "client_encoding='utf-8'") + })) }) test('password contains < and/or > characters', function () { - return false; + return false var sourceConfig = { - user:'brian', + user: 'brian', password: 'helloe', port: 5432, host: 'localhost', database: 'postgres' } - var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database; - var subject = new ConnectionParameters(connectionString); - assert.equal(subject.password, sourceConfig.password); - }); + var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database + var subject = new ConnectionParameters(connectionString) + assert.equal(subject.password, sourceConfig.password) + }) - test('username or password contains weird characters', function() { - var defaults = require('../../../lib/defaults'); - defaults.ssl = true; - var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000'; - var subject = new ConnectionParameters(strang); - assert.equal(subject.user, 'my f%irst name'); - assert.equal(subject.password, 'is&%awesome!'); - assert.equal(subject.host, 'localhost'); - assert.equal(subject.ssl, true); - }); + test('username or password contains weird characters', function () { + var defaults = require('../../../lib/defaults') + defaults.ssl = true + var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000' + var subject = new ConnectionParameters(strang) + assert.equal(subject.user, 'my f%irst name') + assert.equal(subject.password, 'is&%awesome!') + assert.equal(subject.host, 'localhost') + assert.equal(subject.ssl, true) + }) - test("url is properly encoded", function() { - var encoded = "pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl"; - var subject = new ConnectionParameters(encoded); - assert.equal(subject.user, "bi%na%%ry "); - assert.equal(subject.password, "s@f#"); - assert.equal(subject.host, 'localhost'); - assert.equal(subject.database, " u%20rl"); - }); + test('url is properly encoded', function () { + var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl' + var subject = new ConnectionParameters(encoded) + assert.equal(subject.user, 'bi%na%%ry ') + assert.equal(subject.password, 's@f#') + assert.equal(subject.host, 'localhost') + assert.equal(subject.database, ' u%20rl') + }) - test('ssl is set on client', function() { + test('ssl is set on client', function () { var Client = require('../../../lib/client') - var defaults = require('../../../lib/defaults'); - defaults.ssl = true; + var defaults = require('../../../lib/defaults') + defaults.ssl = true var c = new Client('postgres://user@password:host/database') assert(c.ssl, 'Client should have ssl enabled via defaults') }) - -}); +}) diff --git a/test/unit/connection-parameters/environment-variable-tests.js b/test/unit/connection-parameters/environment-variable-tests.js index 2f41fecd..2c5e503d 100644 --- a/test/unit/connection-parameters/environment-variable-tests.js +++ b/test/unit/connection-parameters/environment-variable-tests.js @@ -1,115 +1,113 @@ -"use strict"; -var helper = require(__dirname + '/../test-helper'); -var assert = require('assert'); -var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters'); -var defaults = require(__dirname + '/../../../lib').defaults; +'use strict' +var helper = require(__dirname + '/../test-helper') +var assert = require('assert') +var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters') +var defaults = require(__dirname + '/../../../lib').defaults -//clear process.env -var realEnv = {}; -for(var key in process.env) { - realEnv[key] = process.env[key]; - delete process.env[key]; +// clear process.env +var realEnv = {} +for (var key in process.env) { + realEnv[key] = process.env[key] + delete process.env[key] } -test('ConnectionParameters initialized from environment variables', function(t) { - process.env['PGHOST'] = 'local'; - process.env['PGUSER'] = 'bmc2'; - process.env['PGPORT'] = 7890; - process.env['PGDATABASE'] = 'allyerbase'; - process.env['PGPASSWORD'] = 'open'; +test('ConnectionParameters initialized from environment variables', function (t) { + process.env['PGHOST'] = 'local' + process.env['PGUSER'] = 'bmc2' + process.env['PGPORT'] = 7890 + process.env['PGDATABASE'] = 'allyerbase' + process.env['PGPASSWORD'] = 'open' - var subject = new ConnectionParameters(); - assert.equal(subject.host, 'local', 'env host'); - assert.equal(subject.user, 'bmc2', 'env user'); - assert.equal(subject.port, 7890, 'env port'); - assert.equal(subject.database, 'allyerbase', 'env database'); - assert.equal(subject.password, 'open', 'env password'); -}); + var subject = new ConnectionParameters() + assert.equal(subject.host, 'local', 'env host') + assert.equal(subject.user, 'bmc2', 'env user') + assert.equal(subject.port, 7890, 'env port') + assert.equal(subject.database, 'allyerbase', 'env database') + assert.equal(subject.password, 'open', 'env password') +}) -test('ConnectionParameters initialized from mix', function(t) { - delete process.env['PGPASSWORD']; - delete process.env['PGDATABASE']; +test('ConnectionParameters initialized from mix', function (t) { + delete process.env['PGPASSWORD'] + delete process.env['PGDATABASE'] var subject = new ConnectionParameters({ user: 'testing', database: 'zugzug' - }); - assert.equal(subject.host, 'local', 'env host'); - assert.equal(subject.user, 'testing', 'config user'); - assert.equal(subject.port, 7890, 'env port'); - assert.equal(subject.database, 'zugzug', 'config database'); - assert.equal(subject.password, defaults.password, 'defaults password'); -}); + }) + assert.equal(subject.host, 'local', 'env host') + assert.equal(subject.user, 'testing', 'config user') + assert.equal(subject.port, 7890, 'env port') + assert.equal(subject.database, 'zugzug', 'config database') + assert.equal(subject.password, defaults.password, 'defaults password') +}) -//clear process.env -for(var key in process.env) { - delete process.env[key]; +// clear process.env +for (var key in process.env) { + delete process.env[key] } -test('connection string parsing', function(t) { - var string = 'postgres://brian:pw@boom:381/lala'; - var subject = new ConnectionParameters(string); - assert.equal(subject.host, 'boom', 'string host'); - assert.equal(subject.user, 'brian', 'string user'); - assert.equal(subject.password, 'pw', 'string password'); - assert.equal(subject.port, 381, 'string port'); - assert.equal(subject.database, 'lala', 'string database'); -}); +test('connection string parsing', function (t) { + var string = 'postgres://brian:pw@boom:381/lala' + var subject = new ConnectionParameters(string) + assert.equal(subject.host, 'boom', 'string host') + assert.equal(subject.user, 'brian', 'string user') + assert.equal(subject.password, 'pw', 'string password') + assert.equal(subject.port, 381, 'string port') + assert.equal(subject.database, 'lala', 'string database') +}) -test('connection string parsing - ssl', function(t) { - var string = 'postgres://brian:pw@boom:381/lala?ssl=true'; - var subject = new ConnectionParameters(string); - assert.equal(subject.ssl, true, 'ssl'); +test('connection string parsing - ssl', function (t) { + var string = 'postgres://brian:pw@boom:381/lala?ssl=true' + var subject = new ConnectionParameters(string) + assert.equal(subject.ssl, true, 'ssl') - string = 'postgres://brian:pw@boom:381/lala?ssl=1'; - subject = new ConnectionParameters(string); - assert.equal(subject.ssl, true, 'ssl'); + string = 'postgres://brian:pw@boom:381/lala?ssl=1' + subject = new ConnectionParameters(string) + assert.equal(subject.ssl, true, 'ssl') - string = 'postgres://brian:pw@boom:381/lala?other&ssl=true'; - subject = new ConnectionParameters(string); - assert.equal(subject.ssl, true, 'ssl'); + string = 'postgres://brian:pw@boom:381/lala?other&ssl=true' + subject = new ConnectionParameters(string) + assert.equal(subject.ssl, true, 'ssl') - string = 'postgres://brian:pw@boom:381/lala?ssl=0'; - subject = new ConnectionParameters(string); - assert.equal(!!subject.ssl, false, 'ssl'); + string = 'postgres://brian:pw@boom:381/lala?ssl=0' + subject = new ConnectionParameters(string) + assert.equal(!!subject.ssl, false, 'ssl') - string = 'postgres://brian:pw@boom:381/lala'; - subject = new ConnectionParameters(string); - assert.equal(!!subject.ssl, false, 'ssl'); -}); + string = 'postgres://brian:pw@boom:381/lala' + subject = new ConnectionParameters(string) + assert.equal(!!subject.ssl, false, 'ssl') +}) -//clear process.env -for(var key in process.env) { - delete process.env[key]; +// clear process.env +for (var key in process.env) { + delete process.env[key] } - -test('ssl is false by default', function() { +test('ssl is false by default', function () { var subject = new ConnectionParameters() assert.equal(subject.ssl, false) }) -var testVal = function(mode, expected) { - //clear process.env - for(var key in process.env) { - delete process.env[key]; +var testVal = function (mode, expected) { + // clear process.env + for (var key in process.env) { + delete process.env[key] } - process.env.PGSSLMODE = mode; - test('ssl is ' + expected + ' when $PGSSLMODE=' + mode, function() { - var subject = new ConnectionParameters(); - assert.equal(subject.ssl, expected); - }); -}; - -testVal('', false); -testVal('disable', false); -testVal('allow', false); -testVal('prefer', true); -testVal('require', true); -testVal('verify-ca', true); -testVal('verify-full', true); - - -//restore process.env -for(var key in realEnv) { - process.env[key] = realEnv[key]; + process.env.PGSSLMODE = mode + test('ssl is ' + expected + ' when $PGSSLMODE=' + mode, function () { + var subject = new ConnectionParameters() + assert.equal(subject.ssl, expected) + }) +} + +testVal('', false) +testVal('disable', false) +testVal('allow', false) +testVal('prefer', true) +testVal('require', true) +testVal('verify-ca', true) +testVal('verify-full', true) + +// restore process.env +for (var key in realEnv) { + process.env[key] = realEnv[key] } diff --git a/test/unit/connection/error-tests.js b/test/unit/connection/error-tests.js index 20952a69..19674608 100644 --- a/test/unit/connection/error-tests.js +++ b/test/unit/connection/error-tests.js @@ -1,31 +1,31 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); -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!")); -}); +'use strict' +var helper = require(__dirname + '/test-helper') +var Connection = require(__dirname + '/../../../lib/connection') +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 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); -}); +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) +}) diff --git a/test/unit/connection/inbound-parser-tests.js b/test/unit/connection/inbound-parser-tests.js index 86266b22..0eaefcc4 100644 --- a/test/unit/connection/inbound-parser-tests.js +++ b/test/unit/connection/inbound-parser-tests.js @@ -1,29 +1,29 @@ -"use strict"; -require(__dirname+'/test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); -var buffers = require(__dirname + '/../../test-buffers'); -var PARSE = function(buffer) { - return new Parser(buffer).parse(); -}; +'use strict' +require(__dirname + '/test-helper') +var Connection = require(__dirname + '/../../../lib/connection') +var buffers = require(__dirname + '/../../test-buffers') +var PARSE = function (buffer) { + return new Parser(buffer).parse() +} -var authOkBuffer = buffers.authenticationOk(); -var paramStatusBuffer = buffers.parameterStatus('client_encoding', 'UTF8'); -var readyForQueryBuffer = buffers.readyForQuery(); -var backendKeyDataBuffer = buffers.backendKeyData(1,2); -var commandCompleteBuffer = buffers.commandComplete("SELECT 3"); -var parseCompleteBuffer = buffers.parseComplete(); -var bindCompleteBuffer = buffers.bindComplete(); -var portalSuspendedBuffer = buffers.portalSuspended(); +var authOkBuffer = buffers.authenticationOk() +var paramStatusBuffer = buffers.parameterStatus('client_encoding', 'UTF8') +var readyForQueryBuffer = buffers.readyForQuery() +var backendKeyDataBuffer = buffers.backendKeyData(1, 2) +var commandCompleteBuffer = buffers.commandComplete('SELECT 3') +var parseCompleteBuffer = buffers.parseComplete() +var bindCompleteBuffer = buffers.bindComplete() +var portalSuspendedBuffer = buffers.portalSuspended() -var addRow = function(bufferList, name, offset) { - return bufferList.addCString(name) //field name - .addInt32(offset++) //table id - .addInt16(offset++) //attribute of column number - .addInt32(offset++) //objectId of field's data type - .addInt16(offset++) //datatype size - .addInt32(offset++) //type modifier - .addInt16(0) //format code, 0 => text -}; +var addRow = function (bufferList, name, offset) { + return bufferList.addCString(name) // field name + .addInt32(offset++) // table id + .addInt16(offset++) // attribute of column number + .addInt32(offset++) // objectId of field's data type + .addInt16(offset++) // datatype size + .addInt32(offset++) // type modifier + .addInt16(0) // format code, 0 => text +} var row1 = { name: 'id', @@ -33,11 +33,11 @@ var row1 = { dataTypeSize: 4, typeModifier: 5, formatCode: 0 -}; -var oneRowDescBuff = new buffers.rowDescription([row1]); -row1.name = 'bang'; +} +var oneRowDescBuff = new buffers.rowDescription([row1]) +row1.name = 'bang' -var twoRowBuf = new buffers.rowDescription([row1,{ +var twoRowBuf = new buffers.rowDescription([row1, { name: 'whoah', tableID: 10, attributeNumber: 11, @@ -47,144 +47,142 @@ var twoRowBuf = new buffers.rowDescription([row1,{ formatCode: 0 }]) - var emptyRowFieldBuf = new BufferList() .addInt16(0) - .join(true, 'D'); + .join(true, 'D') -var emptyRowFieldBuf = buffers.dataRow(); +var emptyRowFieldBuf = buffers.dataRow() var oneFieldBuf = new BufferList() - .addInt16(1) //number of fields - .addInt32(5) //length of bytes of fields + .addInt16(1) // number of fields + .addInt32(5) // length of bytes of fields .addCString('test') - .join(true, 'D'); - -var oneFieldBuf = buffers.dataRow(['test']); + .join(true, 'D') +var oneFieldBuf = buffers.dataRow(['test']) var expectedAuthenticationOkayMessage = { name: 'authenticationOk', length: 8 -}; +} var expectedParameterStatusMessage = { name: 'parameterStatus', parameterName: 'client_encoding', parameterValue: 'UTF8', length: 25 -}; +} var expectedBackendKeyDataMessage = { name: 'backendKeyData', processID: 1, secretKey: 2 -}; +} var expectedReadyForQueryMessage = { name: 'readyForQuery', length: 5, status: 'I' -}; +} var expectedCommandCompleteMessage = { length: 13, - text: "SELECT 3" -}; + text: 'SELECT 3' +} var emptyRowDescriptionBuffer = new BufferList() - .addInt16(0) //number of fields - .join(true,'T'); + .addInt16(0) // number of fields + .join(true, 'T') var expectedEmptyRowDescriptionMessage = { name: 'rowDescription', length: 6, fieldCount: 0 -}; +} var expectedOneRowMessage = { name: 'rowDescription', length: 27, fieldCount: 1 -}; +} var expectedTwoRowMessage = { name: 'rowDescription', length: 53, fieldCount: 2 -}; +} -var testForMessage = function(buffer, expectedMessage) { - var lastMessage = {}; - test('recieves and parses ' + expectedMessage.name, function() { - var stream = new MemoryStream(); +var testForMessage = function (buffer, expectedMessage) { + var lastMessage = {} + test('recieves and parses ' + expectedMessage.name, function () { + var stream = new MemoryStream() var client = new Connection({ stream: stream - }); - client.connect(); + }) + client.connect() - client.on('message',function(msg) { - lastMessage = msg; - }); + client.on('message', function (msg) { + lastMessage = msg + }) - client.on(expectedMessage.name, function() { - client.removeAllListeners(expectedMessage.name); - }); + client.on(expectedMessage.name, function () { + client.removeAllListeners(expectedMessage.name) + }) - stream.emit('data', buffer); - assert.same(lastMessage, expectedMessage); - }); - return lastMessage; -}; + stream.emit('data', buffer) + assert.same(lastMessage, expectedMessage) + }) + return lastMessage +} -var plainPasswordBuffer = buffers.authenticationCleartextPassword(); -var md5PasswordBuffer = buffers.authenticationMD5Password(); +var plainPasswordBuffer = buffers.authenticationCleartextPassword() +var md5PasswordBuffer = buffers.authenticationMD5Password() var expectedPlainPasswordMessage = { name: 'authenticationCleartextPassword' -}; +} var expectedMD5PasswordMessage = { name: 'authenticationMD5Password' -}; +} -var notificationResponseBuffer = buffers.notification(4, 'hi', 'boom'); +var notificationResponseBuffer = buffers.notification(4, 'hi', 'boom') var expectedNotificationResponseMessage = { name: 'notification', processId: 4, channel: 'hi', payload: 'boom' -}; +} -test('Connection', function() { - testForMessage(authOkBuffer, expectedAuthenticationOkayMessage); - testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage); - var msg = testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage); - test('md5 has right salt', function() { - assert.equalBuffers(msg.salt, Buffer.from([1,2,3,4])); - }); - testForMessage(paramStatusBuffer, expectedParameterStatusMessage); - testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage); - testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage); - testForMessage(commandCompleteBuffer,expectedCommandCompleteMessage); - testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage); - test('empty row message', function() { - var message = testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage); - test('has no fields', function() { - assert.equal(message.fields.length, 0); - }); - }); +test('Connection', function () { + testForMessage(authOkBuffer, expectedAuthenticationOkayMessage) + testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage) + var msg = testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage) + test('md5 has right salt', function () { + assert.equalBuffers(msg.salt, Buffer.from([1, 2, 3, 4])) + }) + testForMessage(paramStatusBuffer, expectedParameterStatusMessage) + testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage) + testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage) + testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage) + testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage) + test('empty row message', function () { + var message = testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage) + test('has no fields', function () { + assert.equal(message.fields.length, 0) + }) + }) - test("no data message", function() { + test('no data message', function () { testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { name: 'noData' - }); - }); + }) + }) - test('one row message', function() { - var message = testForMessage(oneRowDescBuff, expectedOneRowMessage); - test('has one field', function() { - assert.equal(message.fields.length, 1); - }); - test('has correct field info', function() { + test('one row message', function () { + var message = testForMessage(oneRowDescBuff, expectedOneRowMessage) + test('has one field', function () { + assert.equal(message.fields.length, 1) + }) + test('has correct field info', function () { assert.same(message.fields[0], { name: 'id', tableID: 1, @@ -193,16 +191,16 @@ test('Connection', function() { dataTypeSize: 4, dataTypeModifier: 5, format: 'text' - }); - }); - }); + }) + }) + }) - test('two row message', function() { - var message = testForMessage(twoRowBuf, expectedTwoRowMessage); - test('has two fields', function() { - assert.equal(message.fields.length, 2); - }); - test('has correct first field', function() { + test('two row message', function () { + var message = testForMessage(twoRowBuf, expectedTwoRowMessage) + test('has two fields', function () { + assert.equal(message.fields.length, 2) + }) + test('has correct first field', function () { assert.same(message.fields[0], { name: 'bang', tableID: 1, @@ -212,8 +210,8 @@ test('Connection', function() { dataTypeModifier: 5, format: 'text' }) - }); - test('has correct second field', function() { + }) + test('has correct second field', function () { assert.same(message.fields[1], { name: 'whoah', tableID: 10, @@ -222,98 +220,95 @@ test('Connection', function() { dataTypeSize: 13, dataTypeModifier: 14, format: 'text' - }); - }); + }) + }) + }) - }); - - test('parsing rows', function() { - - test('parsing empty row', function() { + test('parsing rows', function () { + test('parsing empty row', function () { var message = testForMessage(emptyRowFieldBuf, { name: 'dataRow', fieldCount: 0 - }); - test('has 0 fields', function() { - assert.equal(message.fields.length, 0); - }); - }); + }) + test('has 0 fields', function () { + assert.equal(message.fields.length, 0) + }) + }) - test('parsing data row with fields', function() { + test('parsing data row with fields', function () { var message = testForMessage(oneFieldBuf, { name: 'dataRow', fieldCount: 1 - }); - test('has 1 field', function() { - assert.equal(message.fields.length, 1); - }); + }) + test('has 1 field', function () { + assert.equal(message.fields.length, 1) + }) - test('field is correct', function() { - assert.equal(message.fields[0],'test'); - }); - }); + test('field is correct', function () { + assert.equal(message.fields[0], 'test') + }) + }) + }) - }); - - test('notice message', function() { - //this uses the same logic as error message - var buff = buffers.notice([{type: 'C', value: 'code'}]); + test('notice message', function () { + // this uses the same logic as error message + var buff = buffers.notice([{type: 'C', value: 'code'}]) testForMessage(buff, { name: 'notice', code: 'code' - }); - }); + }) + }) - test('error messages', function() { - test('with no fields', function() { - var msg = testForMessage(buffers.error(),{ + test('error messages', function () { + test('with no fields', function () { + var msg = testForMessage(buffers.error(), { name: 'error' - }); - }); + }) + }) - test('with all the fields', function() { + test('with all the fields', function () { var buffer = buffers.error([{ type: 'S', value: 'ERROR' - },{ + }, { type: 'C', value: 'code' - },{ + }, { type: 'M', value: 'message' - },{ + }, { type: 'D', value: 'details' - },{ + }, { type: 'H', value: 'hint' - },{ + }, { type: 'P', value: '100' - },{ + }, { type: 'p', value: '101' - },{ + }, { type: 'q', value: 'query' - },{ + }, { type: 'W', value: 'where' - },{ + }, { type: 'F', value: 'file' - },{ + }, { type: 'L', value: 'line' - },{ + }, { type: 'R', value: 'routine' - },{ - type: 'Z', //ignored + }, { + type: 'Z', // ignored value: 'alsdkf' - }]); + }]) - testForMessage(buffer,{ + testForMessage(buffer, { name: 'error', severity: 'ERROR', code: 'code', @@ -327,150 +322,148 @@ test('Connection', function() { file: 'file', line: 'line', routine: 'routine' - }); - }); - }); + }) + }) + }) - test('parses parse complete command', function() { + test('parses parse complete command', function () { testForMessage(parseCompleteBuffer, { name: 'parseComplete' - }); - }); + }) + }) - test('parses bind complete command', function() { + test('parses bind complete command', function () { testForMessage(bindCompleteBuffer, { name: 'bindComplete' - }); - }); + }) + }) - test('parses portal suspended message', function() { + test('parses portal suspended message', function () { testForMessage(portalSuspendedBuffer, { name: 'portalSuspended' - }); - }); + }) + }) - test('parses replication start message', function() { + test('parses replication start message', function () { testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { name: 'replicationStart', length: 4 - }); - }); -}); + }) + }) +}) -//since the data message on a stream can randomly divide the incomming -//tcp packets anywhere, we need to make sure we can parse every single -//split on a tcp message -test('split buffer, single message parsing', function() { - var fullBuffer = buffers.dataRow([null, "bang", "zug zug", null, "!"]); - var stream = new MemoryStream(); - stream.readyState = 'open'; +// since the data message on a stream can randomly divide the incomming +// tcp packets anywhere, we need to make sure we can parse every single +// split on a tcp message +test('split buffer, single message parsing', function () { + var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']) + var stream = new MemoryStream() + stream.readyState = 'open' var client = new Connection({ stream: stream - }); - client.connect(); - var message = null; - client.on('message', function(msg) { - message = msg; - }); + }) + client.connect() + var message = null + client.on('message', function (msg) { + message = msg + }) - test('parses when full buffer comes in', function() { - stream.emit('data', fullBuffer); - assert.lengthIs(message.fields, 5); - assert.equal(message.fields[0], null); - assert.equal(message.fields[1], "bang"); - assert.equal(message.fields[2], "zug zug"); - assert.equal(message.fields[3], null); - assert.equal(message.fields[4], "!"); - }); + test('parses when full buffer comes in', function () { + stream.emit('data', fullBuffer) + assert.lengthIs(message.fields, 5) + assert.equal(message.fields[0], null) + assert.equal(message.fields[1], 'bang') + assert.equal(message.fields[2], 'zug zug') + assert.equal(message.fields[3], null) + assert.equal(message.fields[4], '!') + }) - var testMessageRecievedAfterSpiltAt = function(split) { - var firstBuffer = Buffer.alloc(fullBuffer.length-split); - var secondBuffer = Buffer.alloc(fullBuffer.length-firstBuffer.length); - fullBuffer.copy(firstBuffer, 0, 0); - fullBuffer.copy(secondBuffer, 0, firstBuffer.length); - stream.emit('data', firstBuffer); - stream.emit('data', secondBuffer); - assert.lengthIs(message.fields, 5); - assert.equal(message.fields[0], null); - assert.equal(message.fields[1], "bang"); - assert.equal(message.fields[2], "zug zug"); - assert.equal(message.fields[3], null); - assert.equal(message.fields[4], "!"); + var testMessageRecievedAfterSpiltAt = function (split) { + var firstBuffer = Buffer.alloc(fullBuffer.length - split) + var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) + fullBuffer.copy(firstBuffer, 0, 0) + fullBuffer.copy(secondBuffer, 0, firstBuffer.length) + stream.emit('data', firstBuffer) + stream.emit('data', secondBuffer) + assert.lengthIs(message.fields, 5) + assert.equal(message.fields[0], null) + assert.equal(message.fields[1], 'bang') + assert.equal(message.fields[2], 'zug zug') + assert.equal(message.fields[3], null) + assert.equal(message.fields[4], '!') + } - }; + test('parses when split in the middle', function () { + testMessageRecievedAfterSpiltAt(6) + }) - test('parses when split in the middle', function() { - testMessageRecievedAfterSpiltAt(6); - }); + test('parses when split at end', function () { + testMessageRecievedAfterSpiltAt(2) + }) - test('parses when split at end', function() { - testMessageRecievedAfterSpiltAt(2); - }); + test('parses when split at beginning', function () { + testMessageRecievedAfterSpiltAt(fullBuffer.length - 2) + testMessageRecievedAfterSpiltAt(fullBuffer.length - 1) + testMessageRecievedAfterSpiltAt(fullBuffer.length - 5) + }) +}) - test('parses when split at beginning', function() { - testMessageRecievedAfterSpiltAt(fullBuffer.length - 2); - testMessageRecievedAfterSpiltAt(fullBuffer.length - 1); - testMessageRecievedAfterSpiltAt(fullBuffer.length - 5); - }); -}); +test('split buffer, multiple message parsing', function () { + var dataRowBuffer = buffers.dataRow(['!']) + var readyForQueryBuffer = buffers.readyForQuery() + var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length) + dataRowBuffer.copy(fullBuffer, 0, 0) + readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0) -test('split buffer, multiple message parsing', function() { - var dataRowBuffer = buffers.dataRow(['!']); - var readyForQueryBuffer = buffers.readyForQuery(); - var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length); - dataRowBuffer.copy(fullBuffer, 0, 0); - readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0); - - var messages = []; - var stream = new MemoryStream(); + var messages = [] + var stream = new MemoryStream() var client = new Connection({ stream: stream - }); - client.connect(); - client.on('message', function(msg) { - messages.push(msg); - }); + }) + client.connect() + client.on('message', function (msg) { + messages.push(msg) + }) - - var verifyMessages = function() { - assert.lengthIs(messages, 2); - assert.same(messages[0],{ + var verifyMessages = function () { + assert.lengthIs(messages, 2) + assert.same(messages[0], { name: 'dataRow', fieldCount: 1 - }); - assert.equal(messages[0].fields[0],'!'); - assert.same(messages[1],{ + }) + assert.equal(messages[0].fields[0], '!') + assert.same(messages[1], { name: 'readyForQuery' - }); - messages = []; - }; - //sanity check - test('recieves both messages when packet is not split', function() { - stream.emit('data', fullBuffer); - verifyMessages(); - }); - var splitAndVerifyTwoMessages = function(split) { - var firstBuffer = Buffer.alloc(fullBuffer.length-split); - var secondBuffer = Buffer.alloc(fullBuffer.length-firstBuffer.length); - fullBuffer.copy(firstBuffer, 0, 0); - fullBuffer.copy(secondBuffer, 0, firstBuffer.length); - stream.emit('data', firstBuffer); - stream.emit('data', secondBuffer); - }; + }) + messages = [] + } + // sanity check + test('recieves both messages when packet is not split', function () { + stream.emit('data', fullBuffer) + verifyMessages() + }) + var splitAndVerifyTwoMessages = function (split) { + var firstBuffer = Buffer.alloc(fullBuffer.length - split) + var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) + fullBuffer.copy(firstBuffer, 0, 0) + fullBuffer.copy(secondBuffer, 0, firstBuffer.length) + stream.emit('data', firstBuffer) + stream.emit('data', secondBuffer) + } - test('recieves both messages when packet is split', function() { - test('in the middle', function() { - splitAndVerifyTwoMessages(11); - }); - test('at the front', function() { - splitAndVerifyTwoMessages(fullBuffer.length-1); - splitAndVerifyTwoMessages(fullBuffer.length-4); - splitAndVerifyTwoMessages(fullBuffer.length-6); - }); + test('recieves both messages when packet is split', function () { + test('in the middle', function () { + splitAndVerifyTwoMessages(11) + }) + test('at the front', function () { + splitAndVerifyTwoMessages(fullBuffer.length - 1) + splitAndVerifyTwoMessages(fullBuffer.length - 4) + splitAndVerifyTwoMessages(fullBuffer.length - 6) + }) - test('at the end', function() { - splitAndVerifyTwoMessages(8); - splitAndVerifyTwoMessages(1); - }); - }); -}); + test('at the end', function () { + splitAndVerifyTwoMessages(8) + splitAndVerifyTwoMessages(1) + }) + }) +}) diff --git a/test/unit/connection/outbound-sending-tests.js b/test/unit/connection/outbound-sending-tests.js index 69642957..e9e148c1 100644 --- a/test/unit/connection/outbound-sending-tests.js +++ b/test/unit/connection/outbound-sending-tests.js @@ -1,22 +1,22 @@ -"use strict"; -require(__dirname + "/test-helper"); -var Connection = require(__dirname + '/../../../lib/connection'); -var stream = new MemoryStream(); +'use strict' +require(__dirname + '/test-helper') +var Connection = require(__dirname + '/../../../lib/connection') +var stream = new MemoryStream() var con = new Connection({ stream: stream -}); +}) -assert.received = function(stream, buffer) { - assert.lengthIs(stream.packets, 1); - var packet = stream.packets.pop(); - assert.equalBuffers(packet, buffer); -}; +assert.received = function (stream, buffer) { + assert.lengthIs(stream.packets, 1) + var packet = stream.packets.pop() + assert.equalBuffers(packet, buffer) +} -test("sends startup message", function() { +test('sends startup message', function () { con.startup({ user: 'brian', database: 'bang' - }); + }) assert.received(stream, new BufferList() .addInt16(3) .addInt16(0) @@ -27,175 +27,174 @@ test("sends startup message", function() { .addCString('client_encoding') .addCString("'utf-8'") .addCString('').join(true)) -}); +}) -test('sends password message', function() { - con.password("!"); - assert.received(stream, new BufferList().addCString("!").join(true,'p')); -}); +test('sends password message', function () { + con.password('!') + assert.received(stream, new BufferList().addCString('!').join(true, 'p')) +}) -test('sends query message', function() { - var txt = 'select * from boom'; - con.query(txt); - assert.received(stream, new BufferList().addCString(txt).join(true,'Q')); -}); +test('sends query message', function () { + var txt = 'select * from boom' + con.query(txt) + assert.received(stream, new BufferList().addCString(txt).join(true, 'Q')) +}) -test('sends parse message', function() { - con.parse({text: '!'}); +test('sends parse message', function () { + con.parse({text: '!'}) var expected = new BufferList() - .addCString("") - .addCString("!") - .addInt16(0).join(true, 'P'); - assert.received(stream, expected); -}); + .addCString('') + .addCString('!') + .addInt16(0).join(true, 'P') + assert.received(stream, expected) +}) -test('sends parse message with named query', function() { +test('sends parse message with named query', function () { con.parse({ name: 'boom', text: 'select * from boom', types: [] - }); + }) var expected = new BufferList() - .addCString("boom") - .addCString("select * from boom") - .addInt16(0).join(true,'P'); - assert.received(stream, expected); + .addCString('boom') + .addCString('select * from boom') + .addInt16(0).join(true, 'P') + assert.received(stream, expected) - test('with multiple parameters', function() { + test('with multiple parameters', function () { con.parse({ name: 'force', text: 'select * from bang where name = $1', - types: [1, 2, 3 ,4] - }); + types: [1, 2, 3, 4] + }) var expected = new BufferList() - .addCString("force") - .addCString("select * from bang where name = $1") + .addCString('force') + .addCString('select * from bang where name = $1') .addInt16(4) .addInt32(1) .addInt32(2) .addInt32(3) - .addInt32(4).join(true,'P'); - assert.received(stream, expected); - }); -}); + .addInt32(4).join(true, 'P') + assert.received(stream, expected) + }) +}) -test('bind messages', function() { - test('with no values', function() { - con.bind(); +test('bind messages', function () { + test('with no values', function () { + con.bind() var expectedBuffer = new BufferList() - .addCString("") - .addCString("") + .addCString('') + .addCString('') .addInt16(0) .addInt16(0) .addInt16(0) - .join(true,"B"); - assert.received(stream, expectedBuffer); - }); + .join(true, 'B') + assert.received(stream, expectedBuffer) + }) - test('with named statement, portal, and values', function() { + test('with named statement, portal, and values', function () { con.bind({ portal: 'bang', statement: 'woo', values: ['1', 'hi', null, 'zing'] - }); + }) var expectedBuffer = new BufferList() - .addCString('bang') //portal name - .addCString('woo') //statement name + .addCString('bang') // portal name + .addCString('woo') // statement name .addInt16(0) .addInt16(4) .addInt32(1) - .add(Buffer.from("1")) + .add(Buffer.from('1')) .addInt32(2) - .add(Buffer.from("hi")) + .add(Buffer.from('hi')) .addInt32(-1) .addInt32(4) .add(Buffer.from('zing')) .addInt16(0) - .join(true, 'B'); - assert.received(stream, expectedBuffer); - }); -}); + .join(true, 'B') + assert.received(stream, expectedBuffer) + }) +}) -test('with named statement, portal, and buffer value', function() { +test('with named statement, portal, and buffer value', function () { con.bind({ portal: 'bang', statement: 'woo', values: ['1', 'hi', null, Buffer.from('zing', 'utf8')] - }); + }) var expectedBuffer = new BufferList() - .addCString('bang') //portal name - .addCString('woo') //statement name - .addInt16(4)//value count - .addInt16(0)//string - .addInt16(0)//string - .addInt16(0)//string - .addInt16(1)//binary + .addCString('bang') // portal name + .addCString('woo') // statement name + .addInt16(4)// value count + .addInt16(0)// string + .addInt16(0)// string + .addInt16(0)// string + .addInt16(1)// binary .addInt16(4) .addInt32(1) - .add(Buffer.from("1")) + .add(Buffer.from('1')) .addInt32(2) - .add(Buffer.from("hi")) + .add(Buffer.from('hi')) .addInt32(-1) .addInt32(4) .add(Buffer.from('zing', 'UTF-8')) .addInt16(0) - .join(true, 'B'); - assert.received(stream, expectedBuffer); -}); + .join(true, 'B') + assert.received(stream, expectedBuffer) +}) -test("sends execute message", function() { - - test("for unamed portal with no row limit", function() { - con.execute(); +test('sends execute message', function () { + test('for unamed portal with no row limit', function () { + con.execute() var expectedBuffer = new BufferList() .addCString('') .addInt32(0) - .join(true,'E'); - assert.received(stream, expectedBuffer); - }); + .join(true, 'E') + assert.received(stream, expectedBuffer) + }) - test("for named portal with row limit", function() { + test('for named portal with row limit', function () { con.execute({ portal: 'my favorite portal', rows: 100 - }); + }) var expectedBuffer = new BufferList() - .addCString("my favorite portal") + .addCString('my favorite portal') .addInt32(100) - .join(true, 'E'); - assert.received(stream, expectedBuffer); - }); -}); + .join(true, 'E') + assert.received(stream, expectedBuffer) + }) +}) -test('sends flush command', function() { - con.flush(); - var expected = new BufferList().join(true, 'H'); - assert.received(stream, expected); -}); +test('sends flush command', function () { + con.flush() + var expected = new BufferList().join(true, 'H') + assert.received(stream, expected) +}) -test('sends sync command', function() { - con.sync(); - var expected = new BufferList().join(true,'S'); - assert.received(stream, expected); -}); +test('sends sync command', function () { + con.sync() + var expected = new BufferList().join(true, 'S') + assert.received(stream, expected) +}) -test('sends end command', function() { - con.end(); - var expected = Buffer.from([0x58, 0, 0, 0, 4]); - assert.received(stream, expected); -}); +test('sends end command', function () { + con.end() + var expected = Buffer.from([0x58, 0, 0, 0, 4]) + assert.received(stream, expected) +}) -test('sends describe command',function() { - test('describe statement', function() { - con.describe({type: 'S', name: 'bang'}); +test('sends describe command', function () { + test('describe statement', function () { + con.describe({type: 'S', name: 'bang'}) var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D') - assert.received(stream, expected); - }); + assert.received(stream, expected) + }) - test("describe unnamed portal", function() { - con.describe({type: 'P'}); - var expected = new BufferList().addChar('P').addCString("").join(true, "D"); - assert.received(stream, expected); - }); -}); + test('describe unnamed portal', function () { + con.describe({type: 'P'}) + var expected = new BufferList().addChar('P').addCString('').join(true, 'D') + assert.received(stream, expected) + }) +}) diff --git a/test/unit/connection/startup-tests.js b/test/unit/connection/startup-tests.js index ee20d679..dc793e69 100644 --- a/test/unit/connection/startup-tests.js +++ b/test/unit/connection/startup-tests.js @@ -1,88 +1,84 @@ -"use strict"; -require(__dirname+'/test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); -test('connection can take existing stream', function() { - var stream = new MemoryStream(); - var con = new Connection({stream: stream}); - assert.equal(con.stream, stream); -}); +'use strict' +require(__dirname + '/test-helper') +var Connection = require(__dirname + '/../../../lib/connection') +test('connection can take existing stream', function () { + var stream = new MemoryStream() + var con = new Connection({stream: stream}) + assert.equal(con.stream, stream) +}) -test('using closed stream', function() { - var makeStream = function() { - var stream = new MemoryStream(); - stream.readyState = 'closed'; - stream.connect = function(port, host) { - this.connectCalled = true; - this.port = port; - this.host = host; +test('using closed stream', function () { + var makeStream = function () { + var stream = new MemoryStream() + stream.readyState = 'closed' + stream.connect = function (port, host) { + this.connectCalled = true + this.port = port + this.host = host } - return stream; - }; + return stream + } - var stream = makeStream(); + var stream = makeStream() - var con = new Connection({stream: stream}); + var con = new Connection({stream: stream}) - con.connect(1234, 'bang'); - - test('makes stream connect', function() { - assert.equal(stream.connectCalled, true); - }); + con.connect(1234, 'bang') - test('uses configured port', function() { - assert.equal(stream.port, 1234); - }); + test('makes stream connect', function () { + assert.equal(stream.connectCalled, true) + }) - test('uses configured host', function() { - assert.equal(stream.host, 'bang'); - }); + test('uses configured port', function () { + assert.equal(stream.port, 1234) + }) - test('after stream connects client emits connected event', function() { + test('uses configured host', function () { + assert.equal(stream.host, 'bang') + }) - var hit = false; + test('after stream connects client emits connected event', function () { + var hit = false - con.once('connect', function() { - hit = true; - }); - - assert.ok(stream.emit('connect')); - assert.ok(hit); - - }); - - test('after stream emits connected event init TCP-keepalive', function() { - - var stream = makeStream(); - var con = new Connection({ stream: stream, keepAlive: true }); - con.connect(123, 'test'); - - var res = false; - - stream.setKeepAlive = function(bit) { - res = bit; - }; - - assert.ok(stream.emit('connect')); - setTimeout(function() { - assert.equal(res, true); + con.once('connect', function () { + hit = true }) - }); -}); -test('using opened stream', function() { - var stream = new MemoryStream(); - stream.readyState = 'open'; - stream.connect = function() { - assert.ok(false, "Should not call open"); - }; - var con = new Connection({stream: stream}); - test('does not call open', function() { - var hit = false; - con.once('connect', function() { - hit = true; - }); - con.connect(); - assert.ok(hit); - }); + assert.ok(stream.emit('connect')) + assert.ok(hit) + }) -}); + test('after stream emits connected event init TCP-keepalive', function () { + var stream = makeStream() + var con = new Connection({ stream: stream, keepAlive: true }) + con.connect(123, 'test') + + var res = false + + stream.setKeepAlive = function (bit) { + res = bit + } + + assert.ok(stream.emit('connect')) + setTimeout(function () { + assert.equal(res, true) + }) + }) +}) + +test('using opened stream', function () { + var stream = new MemoryStream() + stream.readyState = 'open' + stream.connect = function () { + assert.ok(false, 'Should not call open') + } + var con = new Connection({stream: stream}) + test('does not call open', function () { + var hit = false + con.once('connect', function () { + hit = true + }) + con.connect() + assert.ok(hit) + }) +}) diff --git a/test/unit/connection/test-helper.js b/test/unit/connection/test-helper.js index 03d95a69..bcb4b25c 100644 --- a/test/unit/connection/test-helper.js +++ b/test/unit/connection/test-helper.js @@ -1,2 +1,2 @@ -"use strict"; -require(__dirname+'/../test-helper') +'use strict' +require(__dirname + '/../test-helper') diff --git a/test/unit/test-helper.js b/test/unit/test-helper.js index 1dcac733..6cd2d24e 100644 --- a/test/unit/test-helper.js +++ b/test/unit/test-helper.js @@ -1,37 +1,36 @@ -"use strict"; -var EventEmitter = require('events').EventEmitter; +'use strict' +var EventEmitter = require('events').EventEmitter -var helper = require('../test-helper'); -var Connection = require('../../lib/connection'); +var helper = require('../test-helper') +var Connection = require('../../lib/connection') -global.MemoryStream = function() { - EventEmitter.call(this); - this.packets = []; -}; +global.MemoryStream = function () { + EventEmitter.call(this) + this.packets = [] +} +helper.sys.inherits(MemoryStream, EventEmitter) -helper.sys.inherits(MemoryStream, EventEmitter); +var p = MemoryStream.prototype -var p = MemoryStream.prototype; +p.write = function (packet) { + this.packets.push(packet) +} -p.write = function(packet) { - this.packets.push(packet); -}; +p.setKeepAlive = function () {} -p.setKeepAlive = function(){}; +p.writable = true -p.writable = true; - -const createClient = function() { - var stream = new MemoryStream(); - stream.readyState = "open"; +const createClient = function () { + var stream = new MemoryStream() + stream.readyState = 'open' var client = new Client({ connection: new Connection({stream: stream}) - }); - client.connect(); - return client; -}; + }) + client.connect() + return client +} module.exports = Object.assign({}, helper, { - createClient: createClient, -}); + createClient: createClient +}) diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index 893cf5b5..8898481a 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -1,36 +1,33 @@ -"use strict"; -var helper = require('./test-helper'); -var utils = require("./../../lib/utils"); -var defaults = require("./../../lib").defaults; +'use strict' +var helper = require('./test-helper') +var utils = require('./../../lib/utils') +var defaults = require('./../../lib').defaults - -test('ensure types is exported on root object', function() { +test('ensure types is exported on root object', function () { var pg = require('../../lib') assert(pg.types) assert(pg.types.getTypeParser) assert(pg.types.setTypeParser) }) -//this tests the monkey patching -//to ensure comptability with older -//versions of node -test("EventEmitter.once", function(t) { +// this tests the monkey patching +// to ensure comptability with older +// versions of node +test('EventEmitter.once', function (t) { + // an event emitter + var stream = new MemoryStream() - //an event emitter - var stream = new MemoryStream(); + var callCount = 0 + stream.once('single', function () { + callCount++ + }) - var callCount = 0; - stream.once('single', function() { - callCount++; - }); + stream.emit('single') + stream.emit('single') + assert.equal(callCount, 1) +}) - stream.emit('single'); - stream.emit('single'); - assert.equal(callCount, 1); -}); - - -test('normalizing query configs', function() { +test('normalizing query configs', function () { var config var callback = function () {} @@ -50,147 +47,147 @@ test('normalizing query configs', function() { assert.deepEqual(config, {text: 'TEXT', values: [10], callback: callback}) }) -test('prepareValues: buffer prepared properly', function() { - var buf = Buffer.from("quack"); - var out = utils.prepareValue(buf); - assert.strictEqual(buf, out); -}); +test('prepareValues: buffer prepared properly', function () { + var buf = Buffer.from('quack') + var out = utils.prepareValue(buf) + assert.strictEqual(buf, out) +}) -test('prepareValues: date prepared properly', function() { - helper.setTimezoneOffset(-330); +test('prepareValues: date prepared properly', function () { + helper.setTimezoneOffset(-330) - var date = new Date(2014, 1, 1, 11, 11, 1, 7); - var out = utils.prepareValue(date); - assert.strictEqual(out, "2014-02-01T11:11:01.007+05:30"); + var date = new Date(2014, 1, 1, 11, 11, 1, 7) + var out = utils.prepareValue(date) + assert.strictEqual(out, '2014-02-01T11:11:01.007+05:30') - helper.resetTimezoneOffset(); -}); + helper.resetTimezoneOffset() +}) -test('prepareValues: date prepared properly as UTC', function() { - defaults.parseInputDatesAsUTC = true; +test('prepareValues: date prepared properly as UTC', function () { + defaults.parseInputDatesAsUTC = true // make a date in the local timezone that represents a specific UTC point in time - var date = new Date(Date.UTC(2014, 1, 1, 11, 11, 1, 7)); - var out = utils.prepareValue(date); - assert.strictEqual(out, "2014-02-01T11:11:01.007+00:00"); + var date = new Date(Date.UTC(2014, 1, 1, 11, 11, 1, 7)) + var out = utils.prepareValue(date) + assert.strictEqual(out, '2014-02-01T11:11:01.007+00:00') - defaults.parseInputDatesAsUTC = false; -}); + defaults.parseInputDatesAsUTC = false +}) -test('prepareValues: undefined prepared properly', function() { - var out = utils.prepareValue(void 0); - assert.strictEqual(out, null); -}); +test('prepareValues: undefined prepared properly', function () { + var out = utils.prepareValue(void 0) + assert.strictEqual(out, null) +}) -test('prepareValue: null prepared properly', function() { - var out = utils.prepareValue(null); - assert.strictEqual(out, null); -}); +test('prepareValue: null prepared properly', function () { + var out = utils.prepareValue(null) + assert.strictEqual(out, null) +}) -test('prepareValue: true prepared properly', function() { - var out = utils.prepareValue(true); - assert.strictEqual(out, 'true'); -}); +test('prepareValue: true prepared properly', function () { + var out = utils.prepareValue(true) + assert.strictEqual(out, 'true') +}) -test('prepareValue: false prepared properly', function() { - var out = utils.prepareValue(false); - assert.strictEqual(out, 'false'); -}); +test('prepareValue: false prepared properly', function () { + var out = utils.prepareValue(false) + assert.strictEqual(out, 'false') +}) test('prepareValue: number prepared properly', function () { - var out = utils.prepareValue(3.042); - assert.strictEqual(out, '3.042'); -}); - -test('prepareValue: string prepared properly', function() { - var out = utils.prepareValue('big bad wolf'); - assert.strictEqual(out, 'big bad wolf'); -}); - -test('prepareValue: simple array prepared properly', function() { - var out = utils.prepareValue([1, null, 3, undefined, [5, 6, "squ,awk"]]); - assert.strictEqual(out, '{"1",NULL,"3",NULL,{"5","6","squ,awk"}}'); -}); - -test('prepareValue: complex array prepared properly', function() { - var out = utils.prepareValue([{ x: 42 }, { y: 84 }]); - assert.strictEqual(out, '{"{\\"x\\":42}","{\\"y\\":84}"}'); -}); - -test('prepareValue: date array prepared properly', function() { - helper.setTimezoneOffset(-330); - - var date = new Date(2014, 1, 1, 11, 11, 1, 7); - var out = utils.prepareValue([date]); - assert.strictEqual(out, '{"2014-02-01T11:11:01.007+05:30"}'); - - helper.resetTimezoneOffset(); -}); - -test('prepareValue: arbitrary objects prepared properly', function() { - var out = utils.prepareValue({ x: 42 }); - assert.strictEqual(out, '{"x":42}'); -}); - -test('prepareValue: objects with simple toPostgres prepared properly', function() { - var customType = { - toPostgres: function() { - return "zomgcustom!"; - } - }; - var out = utils.prepareValue(customType); - assert.strictEqual(out, "zomgcustom!"); -}); - -test('prepareValue: objects with complex toPostgres prepared properly', function() { - var buf = Buffer.from("zomgcustom!"); - var customType = { - toPostgres: function() { - return [1, 2]; - } - }; - var out = utils.prepareValue(customType); - assert.strictEqual(out, '{"1","2"}'); -}); - -test('prepareValue: objects with toPostgres receive prepareValue', function() { - var customRange = { - lower: { toPostgres: function() { return 5; } }, - upper: { toPostgres: function() { return 10; } }, - toPostgres: function(prepare) { - return "[" + prepare(this.lower) + "," + prepare(this.upper) + "]"; - } - }; - var out = utils.prepareValue(customRange); - assert.strictEqual(out, "[5,10]"); -}); - -test('prepareValue: objects with circular toPostgres rejected', function() { - var buf = Buffer.from("zomgcustom!"); - var customType = { - toPostgres: function() { - return { toPostgres: function () { return customType; } }; - } - }; - - //can't use `assert.throws` since we need to distinguish circular reference - //errors from call stack exceeded errors - try { - utils.prepareValue(customType); - } catch (e) { - assert.ok(e.message.match(/circular/), "Expected circular reference error but got " + e); - return; - } - throw new Error("Expected prepareValue to throw exception"); -}); - -test('prepareValue: can safely be used to map an array of values including those with toPostgres functions', function() { - var customType = { - toPostgres: function() { - return "zomgcustom!"; - } - }; - var values = [1, "test", customType] - var out = values.map(utils.prepareValue) - assert.deepEqual(out, [1, "test", "zomgcustom!"]) + var out = utils.prepareValue(3.042) + assert.strictEqual(out, '3.042') +}) + +test('prepareValue: string prepared properly', function () { + var out = utils.prepareValue('big bad wolf') + assert.strictEqual(out, 'big bad wolf') +}) + +test('prepareValue: simple array prepared properly', function () { + var out = utils.prepareValue([1, null, 3, undefined, [5, 6, 'squ,awk']]) + assert.strictEqual(out, '{"1",NULL,"3",NULL,{"5","6","squ,awk"}}') +}) + +test('prepareValue: complex array prepared properly', function () { + var out = utils.prepareValue([{ x: 42 }, { y: 84 }]) + assert.strictEqual(out, '{"{\\"x\\":42}","{\\"y\\":84}"}') +}) + +test('prepareValue: date array prepared properly', function () { + helper.setTimezoneOffset(-330) + + var date = new Date(2014, 1, 1, 11, 11, 1, 7) + var out = utils.prepareValue([date]) + assert.strictEqual(out, '{"2014-02-01T11:11:01.007+05:30"}') + + helper.resetTimezoneOffset() +}) + +test('prepareValue: arbitrary objects prepared properly', function () { + var out = utils.prepareValue({ x: 42 }) + assert.strictEqual(out, '{"x":42}') +}) + +test('prepareValue: objects with simple toPostgres prepared properly', function () { + var customType = { + toPostgres: function () { + return 'zomgcustom!' + } + } + var out = utils.prepareValue(customType) + assert.strictEqual(out, 'zomgcustom!') +}) + +test('prepareValue: objects with complex toPostgres prepared properly', function () { + var buf = Buffer.from('zomgcustom!') + var customType = { + toPostgres: function () { + return [1, 2] + } + } + var out = utils.prepareValue(customType) + assert.strictEqual(out, '{"1","2"}') +}) + +test('prepareValue: objects with toPostgres receive prepareValue', function () { + var customRange = { + lower: { toPostgres: function () { return 5 } }, + upper: { toPostgres: function () { return 10 } }, + toPostgres: function (prepare) { + return '[' + prepare(this.lower) + ',' + prepare(this.upper) + ']' + } + } + var out = utils.prepareValue(customRange) + assert.strictEqual(out, '[5,10]') +}) + +test('prepareValue: objects with circular toPostgres rejected', function () { + var buf = Buffer.from('zomgcustom!') + var customType = { + toPostgres: function () { + return { toPostgres: function () { return customType } } + } + } + + // can't use `assert.throws` since we need to distinguish circular reference + // errors from call stack exceeded errors + try { + utils.prepareValue(customType) + } catch (e) { + assert.ok(e.message.match(/circular/), 'Expected circular reference error but got ' + e) + return + } + throw new Error('Expected prepareValue to throw exception') +}) + +test('prepareValue: can safely be used to map an array of values including those with toPostgres functions', function () { + var customType = { + toPostgres: function () { + return 'zomgcustom!' + } + } + var values = [1, 'test', customType] + var out = values.map(utils.prepareValue) + assert.deepEqual(out, [1, 'test', 'zomgcustom!']) }) From 28b330c88ebac2ea3ad565f8f2ce4ebe5c9a5579 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 15 Jul 2017 17:22:21 -0500 Subject: [PATCH 53/58] Add JS driver support for multiple results --- lib/query.js | 25 ++++++- .../client/multiple-results-tests.js | 69 +++++++++++++++++++ 2 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 test/integration/client/multiple-results-tests.js diff --git a/lib/query.js b/lib/query.js index 89bde080..4d483ac7 100644 --- a/lib/query.js +++ b/lib/query.js @@ -29,10 +29,14 @@ var Query = function (config, values, callback) { // use unique portal name each time this.portal = config.portal || '' this.callback = config.callback + this._rowMode = config.rowMode if (process.domain && config.callback) { this.callback = process.domain.bind(config.callback) } - this._result = new Result(config.rowMode, config.types) + this._result = new Result(this._rowMode, this.types) + + // potential for multiple results + this._results = this._result this.isPreparedStatement = false this._canceledDueToError = false this._promise = null @@ -54,10 +58,24 @@ Query.prototype.requiresPreparation = function () { return this.values.length > 0 } +Query.prototype._checkForMultirow = function () { + // if we already have a result with a command property + // then we've already executed one query in a multi-statement simple query + // turn our results into an array of results + if (this._result.command) { + if (!Array.isArray(this._results)) { + this._results = [this._result] + } + this._result = new Result(this._rowMode, this.types) + this._results.push(this._result) + } +} + // associates row metadata from the supplied // message with this query object // metadata used when parsing row results Query.prototype.handleRowDescription = function (msg) { + this._checkForMultirow() this._result.addFields(msg.fields) this._accumulateRows = this.callback || !this.listeners('row').length } @@ -83,6 +101,7 @@ Query.prototype.handleDataRow = function (msg) { } Query.prototype.handleCommandComplete = function (msg, con) { + this._checkForMultirow() this._result.addCommandComplete(msg) // need to sync after each command complete of a prepared statement if (this.isPreparedStatement) { @@ -104,9 +123,9 @@ Query.prototype.handleReadyForQuery = function (con) { return this.handleError(this._canceledDueToError, con) } if (this.callback) { - this.callback(null, this._result) + this.callback(null, this._results) } - this.emit('end', this._result) + this.emit('end', this._results) } Query.prototype.handleError = function (err, connection) { diff --git a/test/integration/client/multiple-results-tests.js b/test/integration/client/multiple-results-tests.js new file mode 100644 index 00000000..01dd9eae --- /dev/null +++ b/test/integration/client/multiple-results-tests.js @@ -0,0 +1,69 @@ +'use strict' +const assert = require('assert') +const co = require('co') + +const helper = require('./test-helper') + +const suite = new helper.Suite('multiple result sets') + +suite.test('two select results work', co.wrap(function * () { + const client = new helper.Client() + yield client.connect() + + const results = yield client.query(`SELECT 'foo'::text as name; SELECT 'bar'::text as baz`) + assert(Array.isArray(results)) + + assert.equal(results[0].fields[0].name, 'name') + assert.deepEqual(results[0].rows, [{ name: 'foo' }]) + + assert.equal(results[1].fields[0].name, 'baz') + assert.deepEqual(results[1].rows, [{ baz: 'bar' }]) + + return client.end() +})) + +suite.test('multiple selects work', co.wrap(function * () { + const client = new helper.Client() + yield client.connect() + + const text = ` + SELECT * FROM generate_series(2, 4) as foo; + SELECT * FROM generate_series(8, 10) as bar; + SELECT * FROM generate_series(20, 22) as baz; + ` + + const results = yield client.query(text) + assert(Array.isArray(results)) + + assert.equal(results[0].fields[0].name, 'foo') + assert.deepEqual(results[0].rows, [{ foo: 2 }, { foo: 3 }, { foo: 4 }]) + + assert.equal(results[1].fields[0].name, 'bar') + assert.deepEqual(results[1].rows, [{ bar: 8 }, { bar: 9 }, { bar: 10 }]) + + assert.equal(results[2].fields[0].name, 'baz') + assert.deepEqual(results[2].rows, [{ baz: 20 }, { baz: 21 }, { baz: 22 }]) + + assert.equal(results.length, 3) + + return client.end() +})) + +suite.test('mixed queries and statements', co.wrap(function * () { + const client = new helper.Client() + yield client.connect() + + const text = ` + CREATE TEMP TABLE weather(type text); + INSERT INTO weather(type) VALUES ('rain'); + SELECT * FROM weather; + ` + + const results = yield client.query(text) + assert(Array.isArray(results)) + assert.equal(results[0].command, 'CREATE') + assert.equal(results[1].command, 'INSERT') + assert.equal(results[2].command, 'SELECT') + + return client.end() +})) From ac3102eea2e4b9f31e628cdd0a68d83ec2765724 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 16 Jul 2017 14:58:54 -0500 Subject: [PATCH 54/58] Add support for pg-native multi-row result --- lib/native/query.js | 24 +++++++++++-------- .../row-description-on-results-tests.js | 2 ++ test/integration/client/simple-query-tests.js | 11 +++++---- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/lib/native/query.js b/lib/native/query.js index c1a76915..576495ac 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -91,7 +91,7 @@ NativeQuery.prototype.submit = function (client) { this.native = client.native client.native.arrayMode = this._arrayMode - var after = function (err, rows) { + var after = function (err, rows, results) { client.native.arrayMode = false setImmediate(function () { self.emit('_done') @@ -102,22 +102,26 @@ NativeQuery.prototype.submit = function (client) { return self.handleError(err) } - var result = new NativeResult() - result.addCommandComplete(self.native.pq) - result.rows = rows - // emit row events for each row in the result if (self._emitRowEvents) { - rows.forEach(function (row) { - self.emit('row', row, result) - }) + if (results.length > 1) { + rows.forEach((rowOfRows, i) => { + rowOfRows.forEach(row => { + self.emit('row', row, results[i]) + }) + }) + } else { + rows.forEach(function (row) { + self.emit('row', row, results) + }) + } } // handle successful result self.state = 'end' - self.emit('end', result) + self.emit('end', results) if (self.callback) { - self.callback(null, result) + self.callback(null, results) } } diff --git a/test/integration/client/row-description-on-results-tests.js b/test/integration/client/row-description-on-results-tests.js index 108e5197..babf6912 100644 --- a/test/integration/client/row-description-on-results-tests.js +++ b/test/integration/client/row-description-on-results-tests.js @@ -7,6 +7,8 @@ var conInfo = helper.config var checkResult = function (result) { assert(result.fields) + console.log('YOU ARE HERE') + console.log('result!!', result) assert.equal(result.fields.length, 3) var fields = result.fields assert.equal(fields[0].name, 'now') diff --git a/test/integration/client/simple-query-tests.js b/test/integration/client/simple-query-tests.js index e46958f2..d7f1916a 100644 --- a/test/integration/client/simple-query-tests.js +++ b/test/integration/client/simple-query-tests.js @@ -49,16 +49,17 @@ test('prepared statements do not mutate params', function () { client.on('drain', client.end.bind(client)) + const rows = [] query.on('row', function (row, result) { assert.ok(result) - result.addRow(row) + rows.push(row) }) query.on('end', function (result) { - assert.lengthIs(result.rows, 26, 'result returned wrong number of rows') - assert.lengthIs(result.rows, result.rowCount) - assert.equal(result.rows[0].name, 'Aaron') - assert.equal(result.rows[25].name, 'Zanzabar') + assert.lengthIs(rows, 26, 'result returned wrong number of rows') + assert.lengthIs(rows, result.rowCount) + assert.equal(rows[0].name, 'Aaron') + assert.equal(rows[25].name, 'Zanzabar') }) }) From 111e08d0d77c30f9f0b8df4319df9aac47447aa5 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 16 Jul 2017 15:59:18 -0500 Subject: [PATCH 55/58] Cleanup --- lib/native/query.js | 1 - lib/native/result.js | 37 ------------------- package.json | 2 +- .../row-description-on-results-tests.js | 2 - 4 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 lib/native/result.js diff --git a/lib/native/query.js b/lib/native/query.js index 576495ac..dbcd5604 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -10,7 +10,6 @@ var EventEmitter = require('events').EventEmitter var util = require('util') var utils = require('../utils') -var NativeResult = require('./result') var NativeQuery = module.exports = function (config, values, callback) { EventEmitter.call(this) diff --git a/lib/native/result.js b/lib/native/result.js deleted file mode 100644 index ae9a97a1..00000000 --- a/lib/native/result.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ - -var NativeResult = module.exports = function (pq) { - this.command = null - this.rowCount = 0 - this.rows = null - this.fields = null -} - -NativeResult.prototype.addCommandComplete = function (pq) { - this.command = pq.cmdStatus().split(' ')[0] - this.rowCount = parseInt(pq.cmdTuples(), 10) - var nfields = pq.nfields() - if (nfields < 1) return - - this.fields = [] - for (var i = 0; i < nfields; i++) { - this.fields.push({ - name: pq.fname(i), - dataTypeID: pq.ftype(i) - }) - } -} - -NativeResult.prototype.addRow = function (row) { - // This is empty to ensure pg code doesn't break when switching to pg-native - // pg-native loads all rows into the final result object by default. - // This is because libpg loads all rows into memory before passing the result - // to pg-native. -} diff --git a/package.json b/package.json index 07068972..7bfc3a98 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "eslint-plugin-standard": "3.0.1", "pg-copy-streams": "0.3.0" }, - "minNativeVersion": "1.7.0", + "minNativeVersion": "2.0", "scripts": { "test": "make test-all" }, diff --git a/test/integration/client/row-description-on-results-tests.js b/test/integration/client/row-description-on-results-tests.js index babf6912..108e5197 100644 --- a/test/integration/client/row-description-on-results-tests.js +++ b/test/integration/client/row-description-on-results-tests.js @@ -7,8 +7,6 @@ var conInfo = helper.config var checkResult = function (result) { assert(result.fields) - console.log('YOU ARE HERE') - console.log('result!!', result) assert.equal(result.fields.length, 3) var fields = result.fields assert.equal(fields[0].name, 'now') From f37acc4a6e227ee468bc7a07c1c5967838029a35 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 16 Jul 2017 16:02:15 -0500 Subject: [PATCH 56/58] Use valid semver in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7bfc3a98..9935b9cd 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "eslint-plugin-standard": "3.0.1", "pg-copy-streams": "0.3.0" }, - "minNativeVersion": "2.0", + "minNativeVersion": "2.0.0", "scripts": { "test": "make test-all" }, From f9390dab6b623cf305492920ffd799682b00ba08 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 16 Jul 2017 16:35:32 -0500 Subject: [PATCH 57/58] Re-implement changes from conflict --- lib/client.js | 4 ++-- lib/connection.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/client.js b/lib/client.js index d0052604..107377c7 100644 --- a/lib/client.js +++ b/lib/client.js @@ -40,11 +40,11 @@ var Client = function (config) { this.connection = c.connection || new Connection({ stream: c.stream, ssl: this.connectionParameters.ssl, - keepAlive: c.keepAlive || false + keepAlive: c.keepAlive || false, + encoding: this.connectionParameters.client_encoding || 'utf8' }) this.queryQueue = [] this.binary = c.binary || defaults.binary - this.encoding = 'utf8' this.processID = null this.secretKey = null this.ssl = this.connectionParameters.ssl || false diff --git a/lib/connection.js b/lib/connection.js index 2f13803e..0f98cb06 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -25,7 +25,7 @@ var Connection = function (config) { this.lastOffset = 0 this.buffer = null this.offset = null - this.encoding = 'utf8' + this.encoding = config.encoding || 'utf8' this.parsedStatements = {} this.writer = new Writer() this.ssl = config.ssl || false From ca4ac9983aab7844ed5f068b8900052e1cd09652 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 16 Jul 2017 16:39:22 -0500 Subject: [PATCH 58/58] Re-implement other patch --- lib/utils.js | 14 ++++++++------ test/unit/utils-tests.js | 7 +++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index a83cdee9..166cbddc 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -32,6 +32,8 @@ function arrayString (val) { result = result + 'NULL' } else if (Array.isArray(val[i])) { result = result + arrayString(val[i]) + } else if (val[i] instanceof Buffer) { + result += '\\\\x' + val[i].toString('hex') } else { result += escapeElement(prepareValue(val[i])) } @@ -106,12 +108,12 @@ function dateToString (date) { function dateToStringUTC (date) { var ret = pad(date.getUTCFullYear(), 4) + '-' + - pad(date.getUTCMonth() + 1, 2) + '-' + - pad(date.getUTCDate(), 2) + 'T' + - pad(date.getUTCHours(), 2) + ':' + - pad(date.getUTCMinutes(), 2) + ':' + - pad(date.getUTCSeconds(), 2) + '.' + - pad(date.getUTCMilliseconds(), 3) + pad(date.getUTCMonth() + 1, 2) + '-' + + pad(date.getUTCDate(), 2) + 'T' + + pad(date.getUTCHours(), 2) + ':' + + pad(date.getUTCMinutes(), 2) + ':' + + pad(date.getUTCSeconds(), 2) + '.' + + pad(date.getUTCMilliseconds(), 3) return ret + '+00:00' } diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index 8898481a..680b9fb5 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -139,6 +139,13 @@ test('prepareValue: objects with simple toPostgres prepared properly', function assert.strictEqual(out, 'zomgcustom!') }) +test('prepareValue: buffer array prepared properly', function() { + var buffer1 = Buffer.from('dead', 'hex') + var buffer2 = Buffer.from('beef', 'hex') + var out = utils.prepareValue([buffer1, buffer2]) + assert.strictEqual(out, '{\\\\xdead,\\\\xbeef}') + }) + test('prepareValue: objects with complex toPostgres prepared properly', function () { var buf = Buffer.from('zomgcustom!') var customType = {