diff --git a/.eslintrc b/.eslintrc index e4ff2e0f..57948b71 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,14 +1,15 @@ { "plugins": [ - "node" + "prettier" ], + "parser": "@typescript-eslint/parser", "extends": [ - "standard", - "eslint:recommended", - "plugin:node/recommended" + "plugin:prettier/recommended", + "prettier/@typescript-eslint" ], "ignorePatterns": [ - "**/*.ts" + "node_modules", + "packages/pg-protocol/dist/**/*" ], "parserOptions": { "ecmaVersion": 2017, @@ -18,17 +19,5 @@ "node": true, "es6": true, "mocha": true - }, - "rules": { - "space-before-function-paren": "off", - "node/no-unsupported-features/es-syntax": "off", - "node/no-unpublished-require": [ - "error", - { - "allowModules": [ - "pg" - ] - } - ] } } diff --git a/package.json b/package.json index 16018077..dd32e85b 100644 --- a/package.json +++ b/package.json @@ -10,13 +10,28 @@ "packages/*" ], "scripts": { - "test": "yarn lerna exec yarn test", + "test": "yarn lint && yarn lerna exec yarn test", "build": "yarn lerna exec --scope pg-protocol yarn build", "pretest": "yarn build", - "lint": "yarn lerna exec --parallel yarn lint" + "lint": "!([[ -e node_modules/.bin/prettier ]]) || eslint '*/**/*.{js,ts,tsx}'" }, "devDependencies": { + "@typescript-eslint/eslint-plugin": "^2.27.0", + "@typescript-eslint/parser": "^2.27.0", + "eslint": "^6.8.0", + "eslint-config-prettier": "^6.10.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^3.1.2", "lerna": "^3.19.0" }, - "dependencies": {} + "optionalDependencies": { + "prettier": "2.0.4" + }, + "prettier": { + "semi": false, + "printWidth": 120, + "arrowParens": "always", + "trailingComma": "es5", + "singleQuote": true + } } diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index 727fe908..9d672dbf 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -44,7 +44,7 @@ Cursor.prototype.submit = function (connection) { con.parse( { - text: this.text + text: this.text, }, true ) @@ -52,7 +52,7 @@ Cursor.prototype.submit = function (connection) { con.bind( { portal: this._portal, - values: this.values + values: this.values, }, true ) @@ -60,7 +60,7 @@ Cursor.prototype.submit = function (connection) { con.describe( { type: 'P', - name: this._portal // AWS Redshift requires a portal name + name: this._portal, // AWS Redshift requires a portal name }, true ) @@ -165,7 +165,7 @@ Cursor.prototype._getRows = function (rows, cb) { this._rows = [] const msg = { portal: this._portal, - rows: rows + rows: rows, } this.connection.execute(msg, true) this.connection.flush() diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index dc5e02e1..3ce12975 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -7,8 +7,7 @@ "test": "test" }, "scripts": { - "test": "mocha && eslint .", - "lint": "eslint ." + "test": "mocha" }, "repository": { "type": "git", @@ -17,17 +16,7 @@ "author": "Brian M. Carlson", "license": "MIT", "devDependencies": { - "eslint": "^6.5.1", - "eslint-config-prettier": "^6.4.0", - "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^8.0.2", - "prettier": "^1.18.2" - }, - "prettier": { - "semi": false, - "printWidth": 120, - "trailingComma": "none", - "singleQuote": true + "pg": "^8.0.2" } } diff --git a/packages/pg-cursor/test/error-handling.js b/packages/pg-cursor/test/error-handling.js index 43d34581..f6edef6d 100644 --- a/packages/pg-cursor/test/error-handling.js +++ b/packages/pg-cursor/test/error-handling.js @@ -5,14 +5,14 @@ const pg = require('pg') const text = 'SELECT generate_series as num FROM generate_series(0, 4)' -describe('error handling', function() { - it('can continue after error', function(done) { +describe('error handling', function () { + it('can continue after error', function (done) { const client = new pg.Client() client.connect() const cursor = client.query(new Cursor('asdfdffsdf')) - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(err) - client.query('SELECT NOW()', function(err) { + client.query('SELECT NOW()', function (err) { assert.ifError(err) client.end() done() @@ -22,16 +22,16 @@ describe('error handling', function() { }) describe('read callback does not fire sync', () => { - it('does not fire error callback sync', done => { + it('does not fire error callback sync', (done) => { const client = new pg.Client() client.connect() const cursor = client.query(new Cursor('asdfdffsdf')) let after = false - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(err, 'error should be returned') assert.strictEqual(after, true, 'should not call read sync') after = false - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(err, 'error should be returned') assert.strictEqual(after, true, 'should not call read sync') client.end() @@ -42,18 +42,18 @@ describe('read callback does not fire sync', () => { after = true }) - it('does not fire result sync after finished', done => { + it('does not fire result sync after finished', (done) => { const client = new pg.Client() client.connect() const cursor = client.query(new Cursor('SELECT NOW()')) let after = false - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(!err) assert.strictEqual(after, true, 'should not call read sync') - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(!err) after = false - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(!err) assert.strictEqual(after, true, 'should not call read sync') client.end() @@ -66,16 +66,16 @@ describe('read callback does not fire sync', () => { }) }) -describe('proper cleanup', function() { - it('can issue multiple cursors on one client', function(done) { +describe('proper cleanup', function () { + it('can issue multiple cursors on one client', function (done) { const client = new pg.Client() client.connect() const cursor1 = client.query(new Cursor(text)) - cursor1.read(8, function(err, rows) { + cursor1.read(8, function (err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 5) const cursor2 = client.query(new Cursor(text)) - cursor2.read(8, function(err, rows) { + cursor2.read(8, function (err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 5) client.end() diff --git a/packages/pg-cursor/test/index.js b/packages/pg-cursor/test/index.js index fe210096..24d3cfd7 100644 --- a/packages/pg-cursor/test/index.js +++ b/packages/pg-cursor/test/index.js @@ -4,58 +4,58 @@ const pg = require('pg') const text = 'SELECT generate_series as num FROM generate_series(0, 5)' -describe('cursor', function() { - beforeEach(function(done) { +describe('cursor', function () { + beforeEach(function (done) { const client = (this.client = new pg.Client()) client.connect(done) - this.pgCursor = function(text, values) { + this.pgCursor = function (text, values) { return client.query(new Cursor(text, values || [])) } }) - afterEach(function() { + afterEach(function () { this.client.end() }) - it('fetch 6 when asking for 10', function(done) { + it('fetch 6 when asking for 10', function (done) { const cursor = this.pgCursor(text) - cursor.read(10, function(err, res) { + cursor.read(10, function (err, res) { assert.ifError(err) assert.strictEqual(res.length, 6) done() }) }) - it('end before reading to end', function(done) { + it('end before reading to end', function (done) { const cursor = this.pgCursor(text) - cursor.read(3, function(err, res) { + cursor.read(3, function (err, res) { assert.ifError(err) assert.strictEqual(res.length, 3) done() }) }) - it('callback with error', function(done) { + it('callback with error', function (done) { const cursor = this.pgCursor('select asdfasdf') - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(err) done() }) }) - it('read a partial chunk of data', function(done) { + it('read a partial chunk of data', function (done) { const cursor = this.pgCursor(text) - cursor.read(2, function(err, res) { + cursor.read(2, function (err, res) { assert.ifError(err) assert.strictEqual(res.length, 2) - cursor.read(3, function(err, res) { + cursor.read(3, function (err, res) { assert(!err) assert.strictEqual(res.length, 3) - cursor.read(1, function(err, res) { + cursor.read(1, function (err, res) { assert(!err) assert.strictEqual(res.length, 1) - cursor.read(1, function(err, res) { + cursor.read(1, function (err, res) { assert(!err) assert.ifError(err) assert.strictEqual(res.length, 0) @@ -66,14 +66,14 @@ describe('cursor', function() { }) }) - it('read return length 0 past the end', function(done) { + it('read return length 0 past the end', function (done) { const cursor = this.pgCursor(text) - cursor.read(2, function(err) { + cursor.read(2, function (err) { assert(!err) - cursor.read(100, function(err, res) { + cursor.read(100, function (err, res) { assert(!err) assert.strictEqual(res.length, 4) - cursor.read(100, function(err, res) { + cursor.read(100, function (err, res) { assert(!err) assert.strictEqual(res.length, 0) done() @@ -82,14 +82,14 @@ describe('cursor', function() { }) }) - it('read huge result', function(done) { + it('read huge result', function (done) { this.timeout(10000) const text = 'SELECT generate_series as num FROM generate_series(0, 100000)' const values = [] const cursor = this.pgCursor(text, values) let count = 0 - const read = function() { - cursor.read(100, function(err, rows) { + const read = function () { + cursor.read(100, function (err, rows) { if (err) return done(err) if (!rows.length) { assert.strictEqual(count, 100001) @@ -105,14 +105,14 @@ describe('cursor', function() { read() }) - it('normalizes parameter values', function(done) { + it('normalizes parameter values', function (done) { const text = 'SELECT $1::json me' const values = [{ name: 'brian' }] const cursor = this.pgCursor(text, values) - cursor.read(1, function(err, rows) { + cursor.read(1, function (err, rows) { if (err) return done(err) assert.strictEqual(rows[0].me.name, 'brian') - cursor.read(1, function(err, rows) { + cursor.read(1, function (err, rows) { assert(!err) assert.strictEqual(rows.length, 0) done() @@ -120,34 +120,34 @@ describe('cursor', function() { }) }) - it('returns result along with rows', function(done) { + it('returns result along with rows', function (done) { const cursor = this.pgCursor(text) - cursor.read(1, function(err, rows, result) { + cursor.read(1, function (err, rows, result) { assert.ifError(err) assert.strictEqual(rows.length, 1) assert.strictEqual(rows, result.rows) assert.deepStrictEqual( - result.fields.map(f => f.name), + result.fields.map((f) => f.name), ['num'] ) done() }) }) - it('emits row events', function(done) { + it('emits row events', function (done) { const cursor = this.pgCursor(text) cursor.read(10) cursor.on('row', (row, result) => result.addRow(row)) - cursor.on('end', result => { + cursor.on('end', (result) => { assert.strictEqual(result.rows.length, 6) done() }) }) - it('emits row events when cursor is closed manually', function(done) { + it('emits row events when cursor is closed manually', function (done) { const cursor = this.pgCursor(text) cursor.on('row', (row, result) => result.addRow(row)) - cursor.on('end', result => { + cursor.on('end', (result) => { assert.strictEqual(result.rows.length, 3) done() }) @@ -155,21 +155,21 @@ describe('cursor', function() { cursor.read(3, () => cursor.close()) }) - it('emits error events', function(done) { + it('emits error events', function (done) { const cursor = this.pgCursor('select asdfasdf') - cursor.on('error', function(err) { + cursor.on('error', function (err) { assert(err) done() }) }) - it('returns rowCount on insert', function(done) { + it('returns rowCount on insert', function (done) { const pgCursor = this.pgCursor this.client .query('CREATE TEMPORARY TABLE pg_cursor_test (foo VARCHAR(1), bar VARCHAR(1))') - .then(function() { + .then(function () { const cursor = pgCursor('insert into pg_cursor_test values($1, $2)', ['a', 'b']) - cursor.read(1, function(err, rows, result) { + cursor.read(1, function (err, rows, result) { assert.ifError(err) assert.strictEqual(rows.length, 0) assert.strictEqual(result.rowCount, 1) diff --git a/packages/pg-cursor/test/no-data-handling.js b/packages/pg-cursor/test/no-data-handling.js index 75565874..9c860b9c 100644 --- a/packages/pg-cursor/test/no-data-handling.js +++ b/packages/pg-cursor/test/no-data-handling.js @@ -2,30 +2,30 @@ const assert = require('assert') const pg = require('pg') const Cursor = require('../') -describe('queries with no data', function() { - beforeEach(function(done) { +describe('queries with no data', function () { + beforeEach(function (done) { const client = (this.client = new pg.Client()) client.connect(done) }) - afterEach(function() { + afterEach(function () { this.client.end() }) - it('handles queries that return no data', function(done) { + it('handles queries that return no data', function (done) { const cursor = new Cursor('CREATE TEMPORARY TABLE whatwhat (thing int)') this.client.query(cursor) - cursor.read(100, function(err, rows) { + cursor.read(100, function (err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 0) done() }) }) - it('handles empty query', function(done) { + it('handles empty query', function (done) { let cursor = new Cursor('-- this is a comment') cursor = this.client.query(cursor) - cursor.read(100, function(err, rows) { + cursor.read(100, function (err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 0) done() diff --git a/packages/pg-cursor/test/pool.js b/packages/pg-cursor/test/pool.js index 9af79276..9d8ca772 100644 --- a/packages/pg-cursor/test/pool.js +++ b/packages/pg-cursor/test/pool.js @@ -5,7 +5,7 @@ const pg = require('pg') const text = 'SELECT generate_series as num FROM generate_series(0, 50)' -function poolQueryPromise (pool, readRowCount) { +function poolQueryPromise(pool, readRowCount) { return new Promise((resolve, reject) => { pool.connect((err, client, done) => { if (err) { @@ -13,12 +13,12 @@ function poolQueryPromise (pool, readRowCount) { return reject(err) } const cursor = client.query(new Cursor(text)) - cursor.read(readRowCount, err => { + cursor.read(readRowCount, (err) => { if (err) { done(err) return reject(err) } - cursor.close(err => { + cursor.close((err) => { if (err) { done(err) return reject(err) @@ -43,7 +43,7 @@ describe('pool', function () { it('closes cursor early, single pool query', function (done) { poolQueryPromise(this.pool, 25) .then(() => done()) - .catch(err => { + .catch((err) => { assert.ifError(err) done() }) @@ -56,7 +56,7 @@ describe('pool', function () { } Promise.all(promises) .then(() => done()) - .catch(err => { + .catch((err) => { assert.ifError(err) done() }) @@ -65,7 +65,7 @@ describe('pool', function () { it('closes exhausted cursor, single pool query', function (done) { poolQueryPromise(this.pool, 100) .then(() => done()) - .catch(err => { + .catch((err) => { assert.ifError(err) done() }) @@ -78,7 +78,7 @@ describe('pool', function () { } Promise.all(promises) .then(() => done()) - .catch(err => { + .catch((err) => { assert.ifError(err) done() }) @@ -90,7 +90,7 @@ describe('pool', function () { const cursor = new Cursor(text) const client = await pool.connect() client.query(cursor) - await new Promise(resolve => { + await new Promise((resolve) => { cursor.read(25, function (err) { assert.ifError(err) cursor.close(function (err) { diff --git a/packages/pg-cursor/test/query-config.js b/packages/pg-cursor/test/query-config.js index 42692b90..855af305 100644 --- a/packages/pg-cursor/test/query-config.js +++ b/packages/pg-cursor/test/query-config.js @@ -4,7 +4,7 @@ const Cursor = require('../') const pg = require('pg') describe('query config passed to result', () => { - it('passes rowMode to result', done => { + it('passes rowMode to result', (done) => { const client = new pg.Client() client.connect() const text = 'SELECT generate_series as num FROM generate_series(0, 5)' @@ -17,12 +17,12 @@ describe('query config passed to result', () => { }) }) - it('passes types to result', done => { + it('passes types to result', (done) => { const client = new pg.Client() client.connect() const text = 'SELECT generate_series as num FROM generate_series(0, 2)' const types = { - getTypeParser: () => () => 'foo' + getTypeParser: () => () => 'foo', } const cursor = client.query(new Cursor(text, null, { types })) cursor.read(10, (err, rows) => { diff --git a/packages/pg-cursor/test/transactions.js b/packages/pg-cursor/test/transactions.js index a0ee5e6f..37ca7db6 100644 --- a/packages/pg-cursor/test/transactions.js +++ b/packages/pg-cursor/test/transactions.js @@ -23,7 +23,7 @@ describe('transactions', () => { await client.query('begin') await client.query('CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)') const cursor = client.query(new Cursor('SELECT * FROM foobar')) - await new Promise(resolve => cursor.close(resolve)) + await new Promise((resolve) => cursor.close(resolve)) await client.query('ALTER TABLE foobar ADD COLUMN name TEXT') await client.end() }) @@ -35,7 +35,7 @@ describe('transactions', () => { // create a cursor that has no data response const createText = 'CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)' const cursor = client.query(new Cursor(createText)) - const err = await new Promise(resolve => cursor.read(100, resolve)) + const err = await new Promise((resolve) => cursor.read(100, resolve)) assert.ifError(err) await client.query('ALTER TABLE foobar ADD COLUMN name TEXT') await client.end() diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 32a4736d..27875c1f 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -1,18 +1,16 @@ 'use strict' const EventEmitter = require('events').EventEmitter -const NOOP = function () { } +const NOOP = function () {} const removeWhere = (list, predicate) => { const i = list.findIndex(predicate) - return i === -1 - ? undefined - : list.splice(i, 1)[0] + return i === -1 ? undefined : list.splice(i, 1)[0] } class IdleItem { - constructor (client, idleListener, timeoutId) { + constructor(client, idleListener, timeoutId) { this.client = client this.idleListener = idleListener this.timeoutId = timeoutId @@ -20,16 +18,16 @@ class IdleItem { } class PendingItem { - constructor (callback) { + constructor(callback) { this.callback = callback } } -function throwOnDoubleRelease () { +function throwOnDoubleRelease() { throw new Error('Release called on client which has already been released to the pool.') } -function promisify (Promise, callback) { +function promisify(Promise, callback) { if (callback) { return { callback: callback, result: undefined } } @@ -45,8 +43,8 @@ function promisify (Promise, callback) { return { callback: cb, result: result } } -function makeIdleListener (pool, client) { - return function idleListener (err) { +function makeIdleListener(pool, client) { + return function idleListener(err) { err.client = client client.removeListener('error', idleListener) @@ -61,7 +59,7 @@ function makeIdleListener (pool, client) { } class Pool extends EventEmitter { - constructor (options, Client) { + constructor(options, Client) { super() this.options = Object.assign({}, options) @@ -72,13 +70,13 @@ class Pool extends EventEmitter { configurable: true, enumerable: false, writable: true, - value: options.password + value: options.password, }) } this.options.max = this.options.max || this.options.poolSize || 10 this.options.maxUses = this.options.maxUses || Infinity - this.log = this.options.log || function () { } + this.log = this.options.log || function () {} this.Client = this.options.Client || Client || require('pg').Client this.Promise = this.options.Promise || global.Promise @@ -94,11 +92,11 @@ class Pool extends EventEmitter { this.ended = false } - _isFull () { + _isFull() { return this._clients.length >= this.options.max } - _pulseQueue () { + _pulseQueue() { this.log('pulse queue') if (this.ended) { this.log('pulse queue ended') @@ -107,7 +105,7 @@ class Pool extends EventEmitter { if (this.ending) { this.log('pulse queue on ending') if (this._idle.length) { - this._idle.slice().map(item => { + this._idle.slice().map((item) => { this._remove(item.client) }) } @@ -141,22 +139,19 @@ class Pool extends EventEmitter { throw new Error('unexpected condition') } - _remove (client) { - const removed = removeWhere( - this._idle, - item => item.client === client - ) + _remove(client) { + const removed = removeWhere(this._idle, (item) => item.client === client) if (removed !== undefined) { clearTimeout(removed.timeoutId) } - this._clients = this._clients.filter(c => c !== client) + this._clients = this._clients.filter((c) => c !== client) client.end() this.emit('remove', client) } - connect (cb) { + connect(cb) { if (this.ending) { const err = new Error('Cannot use a pool after calling end on the pool') return cb ? cb(err) : this.Promise.reject(err) @@ -202,7 +197,7 @@ class Pool extends EventEmitter { return result } - newClient (pendingItem) { + newClient(pendingItem) { const client = new this.Client(this.options) this._clients.push(client) const idleListener = makeIdleListener(this, client) @@ -230,7 +225,7 @@ class Pool extends EventEmitter { if (err) { this.log('client failed to connect', err) // remove the dead client from our list of clients - this._clients = this._clients.filter(c => c !== client) + this._clients = this._clients.filter((c) => c !== client) if (timeoutHit) { err.message = 'Connection terminated due to connection timeout' } @@ -250,7 +245,7 @@ class Pool extends EventEmitter { } // acquire a client for a pending work item - _acquireClient (client, pendingItem, idleListener, isNew) { + _acquireClient(client, pendingItem, idleListener, isNew) { if (isNew) { this.emit('connect', client) } @@ -294,7 +289,7 @@ class Pool extends EventEmitter { // release a client back to the poll, include an error // to remove it from the pool - _release (client, idleListener, err) { + _release(client, idleListener, err) { client.on('error', idleListener) client._poolUseCount = (client._poolUseCount || 0) + 1 @@ -322,7 +317,7 @@ class Pool extends EventEmitter { this._pulseQueue() } - query (text, values, cb) { + query(text, values, cb) { // guard clause against passing a function as the first parameter if (typeof text === 'function') { const response = promisify(this.Promise, text) @@ -375,7 +370,7 @@ class Pool extends EventEmitter { return response.result } - end (cb) { + end(cb) { this.log('ending') if (this.ending) { const err = new Error('Called end on pool more than once') @@ -388,15 +383,15 @@ class Pool extends EventEmitter { return promised.result } - get waitingCount () { + get waitingCount() { return this._pendingQueue.length } - get idleCount () { + get idleCount() { return this._idle.length } - get totalCount () { + get totalCount() { return this._clients.length } } diff --git a/packages/pg-pool/test/bring-your-own-promise.js b/packages/pg-pool/test/bring-your-own-promise.js index f7fe3bde..e905ccc0 100644 --- a/packages/pg-pool/test/bring-your-own-promise.js +++ b/packages/pg-pool/test/bring-your-own-promise.js @@ -8,29 +8,35 @@ const BluebirdPromise = require('bluebird') const Pool = require('../') -const checkType = promise => { +const checkType = (promise) => { expect(promise).to.be.a(BluebirdPromise) - return promise.catch(e => undefined) + return promise.catch((e) => undefined) } describe('Bring your own promise', function () { - it('uses supplied promise for operations', co.wrap(function * () { - const pool = new Pool({ Promise: BluebirdPromise }) - const client1 = yield checkType(pool.connect()) - client1.release() - yield checkType(pool.query('SELECT NOW()')) - const client2 = yield checkType(pool.connect()) - // TODO - make sure pg supports BYOP as well - client2.release() - yield checkType(pool.end()) - })) + it( + 'uses supplied promise for operations', + co.wrap(function* () { + const pool = new Pool({ Promise: BluebirdPromise }) + const client1 = yield checkType(pool.connect()) + client1.release() + yield checkType(pool.query('SELECT NOW()')) + const client2 = yield checkType(pool.connect()) + // TODO - make sure pg supports BYOP as well + client2.release() + yield checkType(pool.end()) + }) + ) - it('uses promises in errors', co.wrap(function * () { - const pool = new Pool({ Promise: BluebirdPromise, port: 48484 }) - yield checkType(pool.connect()) - yield checkType(pool.end()) - yield checkType(pool.connect()) - yield checkType(pool.query()) - yield checkType(pool.end()) - })) + it( + 'uses promises in errors', + co.wrap(function* () { + const pool = new Pool({ Promise: BluebirdPromise, port: 48484 }) + yield checkType(pool.connect()) + yield checkType(pool.end()) + yield checkType(pool.connect()) + yield checkType(pool.query()) + yield checkType(pool.end()) + }) + ) }) diff --git a/packages/pg-pool/test/connection-strings.js b/packages/pg-pool/test/connection-strings.js index 7013f28d..de45830d 100644 --- a/packages/pg-pool/test/connection-strings.js +++ b/packages/pg-pool/test/connection-strings.js @@ -15,10 +15,10 @@ describe('Connection strings', function () { connect: function (cb) { cb(new Error('testing')) }, - on: function () { } + on: function () {}, } }, - connectionString: connectionString + connectionString: connectionString, }) pool.connect(function (err, client) { @@ -27,4 +27,3 @@ describe('Connection strings', function () { }) }) }) - diff --git a/packages/pg-pool/test/connection-timeout.js b/packages/pg-pool/test/connection-timeout.js index 97078520..05e8931d 100644 --- a/packages/pg-pool/test/connection-timeout.js +++ b/packages/pg-pool/test/connection-timeout.js @@ -43,7 +43,7 @@ describe('connection timeout', () => { it('should reject promise with an error if timeout is passed', (done) => { const pool = new Pool({ connectionTimeoutMillis: 10, port: this.port, host: 'localhost' }) - pool.connect().catch(err => { + pool.connect().catch((err) => { expect(err).to.be.an(Error) expect(err.message).to.contain('timeout') expect(pool.idleCount).to.equal(0) @@ -51,18 +51,23 @@ describe('connection timeout', () => { }) }) - it('should handle multiple timeouts', co.wrap(function* () { - const errors = [] - const pool = new Pool({ connectionTimeoutMillis: 1, port: this.port, host: 'localhost' }) - for (var i = 0; i < 15; i++) { - try { - yield pool.connect() - } catch (e) { - errors.push(e) - } - } - expect(errors).to.have.length(15) - }.bind(this))) + it( + 'should handle multiple timeouts', + co.wrap( + function* () { + const errors = [] + const pool = new Pool({ connectionTimeoutMillis: 1, port: this.port, host: 'localhost' }) + for (var i = 0; i < 15; i++) { + try { + yield pool.connect() + } catch (e) { + errors.push(e) + } + } + expect(errors).to.have.length(15) + }.bind(this) + ) + ) it('should timeout on checkout of used connection', (done) => { const pool = new Pool({ connectionTimeoutMillis: 100, max: 1 }) @@ -153,7 +158,7 @@ describe('connection timeout', () => { const pool = new Pool({ Client: Client, connectionTimeoutMillis: 1000, - max: 1 + max: 1, }) pool.connect((err, client, release) => { @@ -199,7 +204,7 @@ describe('connection timeout', () => { const pool = new Pool({ Client: Client, connectionTimeoutMillis: 1000, - max: 1 + max: 1, }) // Direct connect diff --git a/packages/pg-pool/test/ending.js b/packages/pg-pool/test/ending.js index 1956b13f..e1839b46 100644 --- a/packages/pg-pool/test/ending.js +++ b/packages/pg-pool/test/ending.js @@ -17,18 +17,24 @@ describe('pool ending', () => { return new Pool().end() }) - it('ends with clients', co.wrap(function * () { - const pool = new Pool() - const res = yield pool.query('SELECT $1::text as name', ['brianc']) - expect(res.rows[0].name).to.equal('brianc') - return pool.end() - })) + it( + 'ends with clients', + co.wrap(function* () { + const pool = new Pool() + const res = yield pool.query('SELECT $1::text as name', ['brianc']) + expect(res.rows[0].name).to.equal('brianc') + return pool.end() + }) + ) - it('allows client to finish', co.wrap(function * () { - const pool = new Pool() - const query = pool.query('SELECT $1::text as name', ['brianc']) - yield pool.end() - const res = yield query - expect(res.rows[0].name).to.equal('brianc') - })) + it( + 'allows client to finish', + co.wrap(function* () { + const pool = new Pool() + const query = pool.query('SELECT $1::text as name', ['brianc']) + yield pool.end() + const res = yield query + expect(res.rows[0].name).to.equal('brianc') + }) + ) }) diff --git a/packages/pg-pool/test/error-handling.js b/packages/pg-pool/test/error-handling.js index 90de4ec4..fea1d114 100644 --- a/packages/pg-pool/test/error-handling.js +++ b/packages/pg-pool/test/error-handling.js @@ -16,12 +16,15 @@ describe('pool error handling', function () { function runErrorQuery() { shouldGet++ return new Promise(function (resolve, reject) { - pool.query("SELECT 'asd'+1 ").then(function (res) { - reject(res) // this should always error - }).catch(function (err) { - errors++ - resolve(err) - }) + pool + .query("SELECT 'asd'+1 ") + .then(function (res) { + reject(res) // this should always error + }) + .catch(function (err) { + errors++ + resolve(err) + }) }) } const ps = [] @@ -35,14 +38,17 @@ describe('pool error handling', function () { }) describe('calling release more than once', () => { - it('should throw each time', co.wrap(function* () { - const pool = new Pool() - const client = yield pool.connect() - client.release() - expect(() => client.release()).to.throwError() - expect(() => client.release()).to.throwError() - return yield pool.end() - })) + it( + 'should throw each time', + co.wrap(function* () { + const pool = new Pool() + const client = yield pool.connect() + client.release() + expect(() => client.release()).to.throwError() + expect(() => client.release()).to.throwError() + return yield pool.end() + }) + ) it('should throw each time with callbacks', function (done) { const pool = new Pool() @@ -75,17 +81,16 @@ describe('pool error handling', function () { it('rejects all additional promises', (done) => { const pool = new Pool() const promises = [] - pool.end() - .then(() => { - const squash = promise => promise.catch(e => 'okay!') - promises.push(squash(pool.connect())) - promises.push(squash(pool.query('SELECT NOW()'))) - promises.push(squash(pool.end())) - Promise.all(promises).then(res => { - expect(res).to.eql(['okay!', 'okay!', 'okay!']) - done() - }) + pool.end().then(() => { + const squash = (promise) => promise.catch((e) => 'okay!') + promises.push(squash(pool.connect())) + promises.push(squash(pool.query('SELECT NOW()'))) + promises.push(squash(pool.end())) + Promise.all(promises).then((res) => { + expect(res).to.eql(['okay!', 'okay!', 'okay!']) + done() }) + }) }) it('returns an error on all additional callbacks', (done) => { @@ -106,68 +111,74 @@ describe('pool error handling', function () { }) describe('error from idle client', () => { - it('removes client from pool', co.wrap(function* () { - const pool = new Pool() - const client = yield pool.connect() - expect(pool.totalCount).to.equal(1) - expect(pool.waitingCount).to.equal(0) - expect(pool.idleCount).to.equal(0) - client.release() - yield new Promise((resolve, reject) => { - process.nextTick(() => { - let poolError - pool.once('error', (err) => { - poolError = err + it( + 'removes client from pool', + co.wrap(function* () { + const pool = new Pool() + const client = yield pool.connect() + expect(pool.totalCount).to.equal(1) + expect(pool.waitingCount).to.equal(0) + expect(pool.idleCount).to.equal(0) + client.release() + yield new Promise((resolve, reject) => { + process.nextTick(() => { + let poolError + pool.once('error', (err) => { + poolError = err + }) + + let clientError + client.once('error', (err) => { + clientError = err + }) + + client.emit('error', new Error('expected')) + + expect(clientError.message).to.equal('expected') + expect(poolError.message).to.equal('expected') + expect(pool.idleCount).to.equal(0) + expect(pool.totalCount).to.equal(0) + pool.end().then(resolve, reject) }) - - let clientError - client.once('error', (err) => { - clientError = err - }) - - client.emit('error', new Error('expected')) - - expect(clientError.message).to.equal('expected') - expect(poolError.message).to.equal('expected') - expect(pool.idleCount).to.equal(0) - expect(pool.totalCount).to.equal(0) - pool.end().then(resolve, reject) }) }) - })) + ) }) describe('error from in-use client', () => { - it('keeps the client in the pool', co.wrap(function* () { - const pool = new Pool() - const client = yield pool.connect() - expect(pool.totalCount).to.equal(1) - expect(pool.waitingCount).to.equal(0) - expect(pool.idleCount).to.equal(0) + it( + 'keeps the client in the pool', + co.wrap(function* () { + const pool = new Pool() + const client = yield pool.connect() + expect(pool.totalCount).to.equal(1) + expect(pool.waitingCount).to.equal(0) + expect(pool.idleCount).to.equal(0) - yield new Promise((resolve, reject) => { - process.nextTick(() => { - let poolError - pool.once('error', (err) => { - poolError = err + yield new Promise((resolve, reject) => { + process.nextTick(() => { + let poolError + pool.once('error', (err) => { + poolError = err + }) + + let clientError + client.once('error', (err) => { + clientError = err + }) + + client.emit('error', new Error('expected')) + + expect(clientError.message).to.equal('expected') + expect(poolError).not.to.be.ok() + expect(pool.idleCount).to.equal(0) + expect(pool.totalCount).to.equal(1) + client.release() + pool.end().then(resolve, reject) }) - - let clientError - client.once('error', (err) => { - clientError = err - }) - - client.emit('error', new Error('expected')) - - expect(clientError.message).to.equal('expected') - expect(poolError).not.to.be.ok() - expect(pool.idleCount).to.equal(0) - expect(pool.totalCount).to.equal(1) - client.release() - pool.end().then(resolve, reject) }) }) - })) + ) }) describe('passing a function to pool.query', () => { @@ -182,30 +193,35 @@ describe('pool error handling', function () { }) describe('pool with lots of errors', () => { - it('continues to work and provide new clients', co.wrap(function* () { - const pool = new Pool({ max: 1 }) - const errors = [] - for (var i = 0; i < 20; i++) { - try { - yield pool.query('invalid sql') - } catch (err) { - errors.push(err) + it( + 'continues to work and provide new clients', + co.wrap(function* () { + const pool = new Pool({ max: 1 }) + const errors = [] + for (var i = 0; i < 20; i++) { + try { + yield pool.query('invalid sql') + } catch (err) { + errors.push(err) + } } - } - expect(errors).to.have.length(20) - expect(pool.idleCount).to.equal(0) - expect(pool.query).to.be.a(Function) - const res = yield pool.query('SELECT $1::text as name', ['brianc']) - expect(res.rows).to.have.length(1) - expect(res.rows[0].name).to.equal('brianc') - return pool.end() - })) + expect(errors).to.have.length(20) + expect(pool.idleCount).to.equal(0) + expect(pool.query).to.be.a(Function) + const res = yield pool.query('SELECT $1::text as name', ['brianc']) + expect(res.rows).to.have.length(1) + expect(res.rows[0].name).to.equal('brianc') + return pool.end() + }) + ) }) it('should continue with queued items after a connection failure', (done) => { - const closeServer = net.createServer((socket) => { - socket.destroy() - }).unref() + const closeServer = net + .createServer((socket) => { + socket.destroy() + }) + .unref() closeServer.listen(() => { const pool = new Pool({ max: 1, port: closeServer.address().port, host: 'localhost' }) diff --git a/packages/pg-pool/test/events.js b/packages/pg-pool/test/events.js index a2da4810..61979247 100644 --- a/packages/pg-pool/test/events.js +++ b/packages/pg-pool/test/events.js @@ -31,13 +31,13 @@ describe('events', function () { process.nextTick(() => { cb(new Error('bad news')) }) - } - }) + }, + }), }) pool.on('connect', function () { throw new Error('should never get here') }) - return pool.connect().catch(e => expect(e.message).to.equal('bad news')) + return pool.connect().catch((e) => expect(e.message).to.equal('bad news')) }) it('emits acquire every time a client is acquired', function (done) { @@ -77,7 +77,7 @@ describe('events', function () { }) }) -function mockClient (methods) { +function mockClient(methods) { return function () { const client = new EventEmitter() Object.assign(client, methods) diff --git a/packages/pg-pool/test/idle-timeout.js b/packages/pg-pool/test/idle-timeout.js index a24ab7b0..fd9fba4a 100644 --- a/packages/pg-pool/test/idle-timeout.js +++ b/packages/pg-pool/test/idle-timeout.js @@ -7,7 +7,7 @@ const it = require('mocha').it const Pool = require('../') -const wait = time => new Promise((resolve) => setTimeout(resolve, time)) +const wait = (time) => new Promise((resolve) => setTimeout(resolve, time)) describe('idle timeout', () => { it('should timeout and remove the client', (done) => { @@ -20,60 +20,68 @@ describe('idle timeout', () => { }) }) - it('times out and removes clients when others are also removed', co.wrap(function * () { - const pool = new Pool({ idleTimeoutMillis: 10 }) - const clientA = yield pool.connect() - const clientB = yield pool.connect() - clientA.release() - clientB.release(new Error()) + it( + 'times out and removes clients when others are also removed', + co.wrap(function* () { + const pool = new Pool({ idleTimeoutMillis: 10 }) + const clientA = yield pool.connect() + const clientB = yield pool.connect() + clientA.release() + clientB.release(new Error()) - const removal = new Promise((resolve) => { - pool.on('remove', () => { + const removal = new Promise((resolve) => { + pool.on('remove', () => { + expect(pool.idleCount).to.equal(0) + expect(pool.totalCount).to.equal(0) + resolve() + }) + }) + + const timeout = wait(100).then(() => Promise.reject(new Error('Idle timeout failed to occur'))) + + try { + yield Promise.race([removal, timeout]) + } finally { + pool.end() + } + }) + ) + + it( + 'can remove idle clients and recreate them', + co.wrap(function* () { + const pool = new Pool({ idleTimeoutMillis: 1 }) + const results = [] + for (var i = 0; i < 20; i++) { + let query = pool.query('SELECT NOW()') + expect(pool.idleCount).to.equal(0) + expect(pool.totalCount).to.equal(1) + results.push(yield query) + yield wait(2) expect(pool.idleCount).to.equal(0) expect(pool.totalCount).to.equal(0) - resolve() - }) + } + expect(results).to.have.length(20) }) + ) - const timeout = wait(100).then(() => - Promise.reject(new Error('Idle timeout failed to occur'))) - - try { - yield Promise.race([removal, timeout]) - } finally { - pool.end() - } - })) - - it('can remove idle clients and recreate them', co.wrap(function * () { - const pool = new Pool({ idleTimeoutMillis: 1 }) - const results = [] - for (var i = 0; i < 20; i++) { - let query = pool.query('SELECT NOW()') - expect(pool.idleCount).to.equal(0) - expect(pool.totalCount).to.equal(1) - results.push(yield query) - yield wait(2) - expect(pool.idleCount).to.equal(0) - expect(pool.totalCount).to.equal(0) - } - expect(results).to.have.length(20) - })) - - it('does not time out clients which are used', co.wrap(function * () { - const pool = new Pool({ idleTimeoutMillis: 1 }) - const results = [] - for (var i = 0; i < 20; i++) { - let client = yield pool.connect() - expect(pool.totalCount).to.equal(1) - expect(pool.idleCount).to.equal(0) - yield wait(10) - results.push(yield client.query('SELECT NOW()')) - client.release() - expect(pool.idleCount).to.equal(1) - expect(pool.totalCount).to.equal(1) - } - expect(results).to.have.length(20) - return pool.end() - })) + it( + 'does not time out clients which are used', + co.wrap(function* () { + const pool = new Pool({ idleTimeoutMillis: 1 }) + const results = [] + for (var i = 0; i < 20; i++) { + let client = yield pool.connect() + expect(pool.totalCount).to.equal(1) + expect(pool.idleCount).to.equal(0) + yield wait(10) + results.push(yield client.query('SELECT NOW()')) + client.release() + expect(pool.idleCount).to.equal(1) + expect(pool.totalCount).to.equal(1) + } + expect(results).to.have.length(20) + return pool.end() + }) + ) }) diff --git a/packages/pg-pool/test/index.js b/packages/pg-pool/test/index.js index 010d99c5..57a68e01 100644 --- a/packages/pg-pool/test/index.js +++ b/packages/pg-pool/test/index.js @@ -167,13 +167,11 @@ describe('pool', function () { it('executes a query directly', () => { const pool = new Pool() - return pool - .query('SELECT $1::text as name', ['hi']) - .then(res => { - expect(res.rows).to.have.length(1) - expect(res.rows[0].name).to.equal('hi') - return pool.end() - }) + return pool.query('SELECT $1::text as name', ['hi']).then((res) => { + expect(res.rows).to.have.length(1) + expect(res.rows[0].name).to.equal('hi') + return pool.end() + }) }) it('properly pools clients', function () { @@ -210,10 +208,9 @@ describe('pool', function () { const errors = [] const promises = _.times(30, () => { - return pool.query('SELECT asldkfjasldkf') - .catch(function (e) { - errors.push(e) - }) + return pool.query('SELECT asldkfjasldkf').catch(function (e) { + errors.push(e) + }) }) return Promise.all(promises).then(() => { expect(errors).to.have.length(30) diff --git a/packages/pg-pool/test/max-uses.js b/packages/pg-pool/test/max-uses.js index 2abede31..c94ddec6 100644 --- a/packages/pg-pool/test/max-uses.js +++ b/packages/pg-pool/test/max-uses.js @@ -8,78 +8,91 @@ const it = require('mocha').it const Pool = require('../') describe('maxUses', () => { - it('can create a single client and use it once', co.wrap(function * () { - const pool = new Pool({ maxUses: 2 }) - expect(pool.waitingCount).to.equal(0) - const client = yield pool.connect() - const res = yield client.query('SELECT $1::text as name', ['hi']) - expect(res.rows[0].name).to.equal('hi') - client.release() - pool.end() - })) + it( + 'can create a single client and use it once', + co.wrap(function* () { + const pool = new Pool({ maxUses: 2 }) + expect(pool.waitingCount).to.equal(0) + const client = yield pool.connect() + const res = yield client.query('SELECT $1::text as name', ['hi']) + expect(res.rows[0].name).to.equal('hi') + client.release() + pool.end() + }) + ) - it('getting a connection a second time returns the same connection and releasing it also closes it', co.wrap(function * () { - const pool = new Pool({ maxUses: 2 }) - expect(pool.waitingCount).to.equal(0) - const client = yield pool.connect() - client.release() - const client2 = yield pool.connect() - expect(client).to.equal(client2) - expect(client2._ending).to.equal(false) - client2.release() - expect(client2._ending).to.equal(true) - return yield pool.end() - })) + it( + 'getting a connection a second time returns the same connection and releasing it also closes it', + co.wrap(function* () { + const pool = new Pool({ maxUses: 2 }) + expect(pool.waitingCount).to.equal(0) + const client = yield pool.connect() + client.release() + const client2 = yield pool.connect() + expect(client).to.equal(client2) + expect(client2._ending).to.equal(false) + client2.release() + expect(client2._ending).to.equal(true) + return yield pool.end() + }) + ) - it('getting a connection a third time returns a new connection', co.wrap(function * () { - const pool = new Pool({ maxUses: 2 }) - expect(pool.waitingCount).to.equal(0) - const client = yield pool.connect() - client.release() - const client2 = yield pool.connect() - expect(client).to.equal(client2) - client2.release() - const client3 = yield pool.connect() - expect(client3).not.to.equal(client2) - client3.release() - return yield pool.end() - })) + it( + 'getting a connection a third time returns a new connection', + co.wrap(function* () { + const pool = new Pool({ maxUses: 2 }) + expect(pool.waitingCount).to.equal(0) + const client = yield pool.connect() + client.release() + const client2 = yield pool.connect() + expect(client).to.equal(client2) + client2.release() + const client3 = yield pool.connect() + expect(client3).not.to.equal(client2) + client3.release() + return yield pool.end() + }) + ) - it('getting a connection from a pending request gets a fresh client when the released candidate is expended', co.wrap(function * () { - const pool = new Pool({ max: 1, maxUses: 2 }) - expect(pool.waitingCount).to.equal(0) - const client1 = yield pool.connect() - pool.connect() - .then(client2 => { + it( + 'getting a connection from a pending request gets a fresh client when the released candidate is expended', + co.wrap(function* () { + const pool = new Pool({ max: 1, maxUses: 2 }) + expect(pool.waitingCount).to.equal(0) + const client1 = yield pool.connect() + pool.connect().then((client2) => { expect(client2).to.equal(client1) expect(pool.waitingCount).to.equal(1) // Releasing the client this time should also expend it since maxUses is 2, causing client3 to be a fresh client client2.release() }) - const client3Promise = pool.connect() - .then(client3 => { + const client3Promise = pool.connect().then((client3) => { // client3 should be a fresh client since client2's release caused the first client to be expended expect(pool.waitingCount).to.equal(0) expect(client3).not.to.equal(client1) return client3.release() }) - // There should be two pending requests since we have 3 connect requests but a max size of 1 - expect(pool.waitingCount).to.equal(2) - // Releasing the client should not yet expend it since maxUses is 2 - client1.release() - yield client3Promise - return yield pool.end() - })) + // There should be two pending requests since we have 3 connect requests but a max size of 1 + expect(pool.waitingCount).to.equal(2) + // Releasing the client should not yet expend it since maxUses is 2 + client1.release() + yield client3Promise + return yield pool.end() + }) + ) - it('logs when removing an expended client', co.wrap(function * () { - const messages = [] - const log = function (msg) { - messages.push(msg) - } - const pool = new Pool({ maxUses: 1, log }) - const client = yield pool.connect() - client.release() - expect(messages).to.contain('remove expended client') - return yield pool.end() - })) + it( + 'logs when removing an expended client', + co.wrap(function* () { + const messages = [] + const log = function (msg) { + messages.push(msg) + } + const pool = new Pool({ maxUses: 1, log }) + const client = yield pool.connect() + client.release() + expect(messages).to.contain('remove expended client') + return yield pool.end() + }) + ) }) diff --git a/packages/pg-pool/test/setup.js b/packages/pg-pool/test/setup.js index cf75b7a6..811e956d 100644 --- a/packages/pg-pool/test/setup.js +++ b/packages/pg-pool/test/setup.js @@ -1,5 +1,5 @@ -const crash = reason => { - process.on(reason, err => { +const crash = (reason) => { + process.on(reason, (err) => { console.error(reason, err.stack) process.exit(-1) }) diff --git a/packages/pg-pool/test/sizing.js b/packages/pg-pool/test/sizing.js index b310b3d3..e7863ba0 100644 --- a/packages/pg-pool/test/sizing.js +++ b/packages/pg-pool/test/sizing.js @@ -8,43 +8,51 @@ const it = require('mocha').it const Pool = require('../') describe('pool size of 1', () => { - it('can create a single client and use it once', co.wrap(function * () { - const pool = new Pool({ max: 1 }) - expect(pool.waitingCount).to.equal(0) - const client = yield pool.connect() - const res = yield client.query('SELECT $1::text as name', ['hi']) - expect(res.rows[0].name).to.equal('hi') - client.release() - pool.end() - })) + it( + 'can create a single client and use it once', + co.wrap(function* () { + const pool = new Pool({ max: 1 }) + expect(pool.waitingCount).to.equal(0) + const client = yield pool.connect() + const res = yield client.query('SELECT $1::text as name', ['hi']) + expect(res.rows[0].name).to.equal('hi') + client.release() + pool.end() + }) + ) - it('can create a single client and use it multiple times', co.wrap(function * () { - const pool = new Pool({ max: 1 }) - expect(pool.waitingCount).to.equal(0) - const client = yield pool.connect() - const wait = pool.connect() - expect(pool.waitingCount).to.equal(1) - client.release() - const client2 = yield wait - expect(client).to.equal(client2) - client2.release() - return yield pool.end() - })) + it( + 'can create a single client and use it multiple times', + co.wrap(function* () { + const pool = new Pool({ max: 1 }) + expect(pool.waitingCount).to.equal(0) + const client = yield pool.connect() + const wait = pool.connect() + expect(pool.waitingCount).to.equal(1) + client.release() + const client2 = yield wait + expect(client).to.equal(client2) + client2.release() + return yield pool.end() + }) + ) - it('can only send 1 query at a time', co.wrap(function * () { - const pool = new Pool({ max: 1 }) + it( + 'can only send 1 query at a time', + co.wrap(function* () { + const pool = new Pool({ max: 1 }) - // the query text column name changed in PostgreSQL 9.2 - const versionResult = yield pool.query('SHOW server_version_num') - const version = parseInt(versionResult.rows[0].server_version_num, 10) - const queryColumn = version < 90200 ? 'current_query' : 'query' + // the query text column name changed in PostgreSQL 9.2 + const versionResult = yield pool.query('SHOW server_version_num') + const version = parseInt(versionResult.rows[0].server_version_num, 10) + const queryColumn = version < 90200 ? 'current_query' : 'query' - const queryText = 'SELECT COUNT(*) as counts FROM pg_stat_activity WHERE ' + queryColumn + ' = $1' - const queries = _.times(20, () => - pool.query(queryText, [queryText])) - const results = yield Promise.all(queries) - const counts = results.map(res => parseInt(res.rows[0].counts, 10)) - expect(counts).to.eql(_.times(20, i => 1)) - return yield pool.end() - })) + const queryText = 'SELECT COUNT(*) as counts FROM pg_stat_activity WHERE ' + queryColumn + ' = $1' + const queries = _.times(20, () => pool.query(queryText, [queryText])) + const results = yield Promise.all(queries) + const counts = results.map((res) => parseInt(res.rows[0].counts, 10)) + expect(counts).to.eql(_.times(20, (i) => 1)) + return yield pool.end() + }) + ) }) diff --git a/packages/pg-pool/test/verify.js b/packages/pg-pool/test/verify.js index 667dea9f..e7ae1dd8 100644 --- a/packages/pg-pool/test/verify.js +++ b/packages/pg-pool/test/verify.js @@ -12,7 +12,7 @@ describe('verify', () => { verify: (client, cb) => { client.release() cb(new Error('nope')) - } + }, }) pool.connect((err, client) => { diff --git a/packages/pg-protocol/src/b.ts b/packages/pg-protocol/src/b.ts index dbf9f52e..028b7639 100644 --- a/packages/pg-protocol/src/b.ts +++ b/packages/pg-protocol/src/b.ts @@ -1,4 +1,4 @@ -// file for microbenchmarking +// file for microbenchmarking import { Writer } from './buffer-writer' import { serialize } from './index' @@ -15,10 +15,10 @@ const buffer = Buffer.from([33, 33, 33, 33, 33, 33, 33, 0]) const run = () => { if (count > LOOPS) { console.log(Date.now() - start) - return; + return } count++ - for(let i = 0; i < LOOPS; i++) { + for (let i = 0; i < LOOPS; i++) { reader.setBuffer(0, buffer) reader.cstring() } diff --git a/packages/pg-protocol/src/buffer-reader.ts b/packages/pg-protocol/src/buffer-reader.ts index cb7d4e3b..2305e130 100644 --- a/packages/pg-protocol/src/buffer-reader.ts +++ b/packages/pg-protocol/src/buffer-reader.ts @@ -1,54 +1,53 @@ -const emptyBuffer = Buffer.allocUnsafe(0); +const emptyBuffer = Buffer.allocUnsafe(0) export class BufferReader { - private buffer: Buffer = emptyBuffer; + private buffer: Buffer = emptyBuffer // TODO(bmc): support non-utf8 encoding? - private encoding: string = 'utf-8'; + private encoding: string = 'utf-8' - constructor(private offset: number = 0) { - } + constructor(private offset: number = 0) {} public setBuffer(offset: number, buffer: Buffer): void { - this.offset = offset; - this.buffer = buffer; + this.offset = offset + this.buffer = buffer } public int16(): number { - const result = this.buffer.readInt16BE(this.offset); - this.offset += 2; - return result; + const result = this.buffer.readInt16BE(this.offset) + this.offset += 2 + return result } public byte(): number { - const result = this.buffer[this.offset]; - this.offset++; - return result; + const result = this.buffer[this.offset] + this.offset++ + return result } public int32(): number { - const result = this.buffer.readInt32BE(this.offset); - this.offset += 4; - return result; + const result = this.buffer.readInt32BE(this.offset) + this.offset += 4 + return result } public string(length: number): string { - const result = this.buffer.toString(this.encoding, this.offset, this.offset + length); - this.offset += length; - return result; + const result = this.buffer.toString(this.encoding, this.offset, this.offset + length) + this.offset += length + return result } public cstring(): string { - const start = this.offset; + const start = this.offset let end = start - while(this.buffer[end++] !== 0) { }; - this.offset = end; - return this.buffer.toString(this.encoding, start, end - 1); + while (this.buffer[end++] !== 0) {} + this.offset = end + return this.buffer.toString(this.encoding, start, end - 1) } public bytes(length: number): Buffer { - const result = this.buffer.slice(this.offset, this.offset + length); - this.offset += length; - return result; + const result = this.buffer.slice(this.offset, this.offset + length) + this.offset += length + return result } } diff --git a/packages/pg-protocol/src/buffer-writer.ts b/packages/pg-protocol/src/buffer-writer.ts index 2299070d..3a8d80b3 100644 --- a/packages/pg-protocol/src/buffer-writer.ts +++ b/packages/pg-protocol/src/buffer-writer.ts @@ -1,87 +1,85 @@ //binary data writer tuned for encoding binary specific to the postgres binary protocol export class Writer { - private buffer: Buffer; - private offset: number = 5; - private headerPosition: number = 0; + private buffer: Buffer + private offset: number = 5 + private headerPosition: number = 0 constructor(private size = 256) { this.buffer = Buffer.alloc(size) } private ensure(size: number): void { - var remaining = this.buffer.length - this.offset; + var remaining = this.buffer.length - this.offset if (remaining < size) { - var oldBuffer = this.buffer; + var oldBuffer = this.buffer // exponential growth factor of around ~ 1.5 // https://stackoverflow.com/questions/2269063/buffer-growth-strategy - var newSize = oldBuffer.length + (oldBuffer.length >> 1) + size; - this.buffer = Buffer.alloc(newSize); - oldBuffer.copy(this.buffer); + var newSize = oldBuffer.length + (oldBuffer.length >> 1) + size + this.buffer = Buffer.alloc(newSize) + oldBuffer.copy(this.buffer) } } public addInt32(num: number): Writer { - this.ensure(4); - this.buffer[this.offset++] = (num >>> 24 & 0xFF); - this.buffer[this.offset++] = (num >>> 16 & 0xFF); - this.buffer[this.offset++] = (num >>> 8 & 0xFF); - this.buffer[this.offset++] = (num >>> 0 & 0xFF); - return this; + this.ensure(4) + this.buffer[this.offset++] = (num >>> 24) & 0xff + this.buffer[this.offset++] = (num >>> 16) & 0xff + this.buffer[this.offset++] = (num >>> 8) & 0xff + this.buffer[this.offset++] = (num >>> 0) & 0xff + return this } public addInt16(num: number): Writer { - this.ensure(2); - this.buffer[this.offset++] = (num >>> 8 & 0xFF); - this.buffer[this.offset++] = (num >>> 0 & 0xFF); - return this; + this.ensure(2) + this.buffer[this.offset++] = (num >>> 8) & 0xff + this.buffer[this.offset++] = (num >>> 0) & 0xff + return this } - public addCString(string: string): Writer { if (!string) { - this.ensure(1); + this.ensure(1) } else { - var len = Buffer.byteLength(string); - this.ensure(len + 1); // +1 for null terminator + var len = Buffer.byteLength(string) + this.ensure(len + 1) // +1 for null terminator this.buffer.write(string, this.offset, 'utf-8') - this.offset += len; + this.offset += len } - this.buffer[this.offset++] = 0; // null terminator - return this; + this.buffer[this.offset++] = 0 // null terminator + return this } - public addString(string: string = ""): Writer { - var len = Buffer.byteLength(string); - this.ensure(len); - this.buffer.write(string, this.offset); - this.offset += len; - return this; + public addString(string: string = ''): Writer { + var len = Buffer.byteLength(string) + this.ensure(len) + this.buffer.write(string, this.offset) + this.offset += len + return this } public add(otherBuffer: Buffer): Writer { - this.ensure(otherBuffer.length); - otherBuffer.copy(this.buffer, this.offset); - this.offset += otherBuffer.length; - return this; + this.ensure(otherBuffer.length) + otherBuffer.copy(this.buffer, this.offset) + this.offset += otherBuffer.length + return this } private join(code?: number): Buffer { if (code) { - this.buffer[this.headerPosition] = code; + this.buffer[this.headerPosition] = code //length is everything in this packet minus the code const length = this.offset - (this.headerPosition + 1) this.buffer.writeInt32BE(length, this.headerPosition + 1) } - return this.buffer.slice(code ? 0 : 5, this.offset); + return this.buffer.slice(code ? 0 : 5, this.offset) } public flush(code?: number): Buffer { - var result = this.join(code); - this.offset = 5; - this.headerPosition = 0; + var result = this.join(code) + this.offset = 5 + this.headerPosition = 0 this.buffer = Buffer.allocUnsafe(this.size) - return result; + return result } } - diff --git a/packages/pg-protocol/src/inbound-parser.test.ts b/packages/pg-protocol/src/inbound-parser.test.ts index 461ab262..8a8785a5 100644 --- a/packages/pg-protocol/src/inbound-parser.test.ts +++ b/packages/pg-protocol/src/inbound-parser.test.ts @@ -15,7 +15,8 @@ var bindCompleteBuffer = buffers.bindComplete() var portalSuspendedBuffer = buffers.portalSuspended() var addRow = function (bufferList: BufferList, name: string, offset: number) { - return bufferList.addCString(name) // field name + return bufferList + .addCString(name) // field name .addInt32(offset++) // table id .addInt16(offset++) // attribute of column number .addInt32(offset++) // objectId of field's data type @@ -31,24 +32,25 @@ var row1 = { dataTypeID: 3, dataTypeSize: 4, typeModifier: 5, - formatCode: 0 + formatCode: 0, } var oneRowDescBuff = buffers.rowDescription([row1]) row1.name = 'bang' -var twoRowBuf = buffers.rowDescription([row1, { - name: 'whoah', - tableID: 10, - attributeNumber: 11, - dataTypeID: 12, - dataTypeSize: 13, - typeModifier: 14, - formatCode: 0 -}]) +var twoRowBuf = buffers.rowDescription([ + row1, + { + name: 'whoah', + tableID: 10, + attributeNumber: 11, + dataTypeID: 12, + dataTypeSize: 13, + typeModifier: 14, + formatCode: 0, + }, +]) -var emptyRowFieldBuf = new BufferList() - .addInt16(0) - .join(true, 'D') +var emptyRowFieldBuf = new BufferList().addInt16(0).join(true, 'D') var emptyRowFieldBuf = buffers.dataRow([]) @@ -62,32 +64,32 @@ var oneFieldBuf = buffers.dataRow(['test']) var expectedAuthenticationOkayMessage = { name: 'authenticationOk', - length: 8 + length: 8, } var expectedParameterStatusMessage = { name: 'parameterStatus', parameterName: 'client_encoding', parameterValue: 'UTF8', - length: 25 + length: 25, } var expectedBackendKeyDataMessage = { name: 'backendKeyData', processID: 1, - secretKey: 2 + secretKey: 2, } var expectedReadyForQueryMessage = { name: 'readyForQuery', length: 5, - status: 'I' + status: 'I', } var expectedCommandCompleteMessage = { name: 'commandComplete', length: 13, - text: 'SELECT 3' + text: 'SELECT 3', } var emptyRowDescriptionBuffer = new BufferList() .addInt16(0) // number of fields @@ -103,45 +105,49 @@ var expectedOneRowMessage = { name: 'rowDescription', length: 27, fieldCount: 1, - fields: [{ - name: 'id', - tableID: 1, - columnID: 2, - dataTypeID: 3, - dataTypeSize: 4, - dataTypeModifier: 5, - format: 'text' - }] + fields: [ + { + name: 'id', + tableID: 1, + columnID: 2, + dataTypeID: 3, + dataTypeSize: 4, + dataTypeModifier: 5, + format: 'text', + }, + ], } var expectedTwoRowMessage = { name: 'rowDescription', length: 53, fieldCount: 2, - fields: [{ - name: 'bang', - tableID: 1, - columnID: 2, - dataTypeID: 3, - dataTypeSize: 4, - dataTypeModifier: 5, - format: 'text' - }, - { - name: 'whoah', - tableID: 10, - columnID: 11, - dataTypeID: 12, - dataTypeSize: 13, - dataTypeModifier: 14, - format: 'text' - }] + fields: [ + { + name: 'bang', + tableID: 1, + columnID: 2, + dataTypeID: 3, + dataTypeSize: 4, + dataTypeModifier: 5, + format: 'text', + }, + { + name: 'whoah', + tableID: 10, + columnID: 11, + dataTypeID: 12, + dataTypeSize: 13, + dataTypeModifier: 14, + format: 'text', + }, + ], } var testForMessage = function (buffer: Buffer, expectedMessage: any) { it('recieves and parses ' + expectedMessage.name, async () => { const messages = await parseBuffers([buffer]) - const [lastMessage] = messages; + const [lastMessage] = messages for (const key in expectedMessage) { assert.deepEqual((lastMessage as any)[key], expectedMessage[key]) @@ -156,17 +162,17 @@ var SASLContinueBuffer = buffers.authenticationSASLContinue() var SASLFinalBuffer = buffers.authenticationSASLFinal() var expectedPlainPasswordMessage = { - name: 'authenticationCleartextPassword' + name: 'authenticationCleartextPassword', } var expectedMD5PasswordMessage = { name: 'authenticationMD5Password', - salt: Buffer.from([1, 2, 3, 4]) + salt: Buffer.from([1, 2, 3, 4]), } var expectedSASLMessage = { name: 'authenticationSASL', - mechanisms: ['SCRAM-SHA-256'] + mechanisms: ['SCRAM-SHA-256'], } var expectedSASLContinueMessage = { @@ -184,15 +190,13 @@ var expectedNotificationResponseMessage = { name: 'notification', processId: 4, channel: 'hi', - payload: 'boom' + payload: 'boom', } - - const parseBuffers = async (buffers: Buffer[]): Promise => { - const stream = new PassThrough(); + const stream = new PassThrough() for (const buffer of buffers) { - stream.write(buffer); + stream.write(buffer) } stream.end() const msgs: BackendMessage[] = [] @@ -219,7 +223,7 @@ describe('PgPacketStream', function () { }) testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { - name: 'noData' + name: 'noData', }) describe('rowDescription messages', function () { @@ -232,7 +236,7 @@ describe('PgPacketStream', function () { describe('parsing empty row', function () { testForMessage(emptyRowFieldBuf, { name: 'dataRow', - fieldCount: 0 + fieldCount: 0, }) }) @@ -240,7 +244,7 @@ describe('PgPacketStream', function () { testForMessage(oneFieldBuf, { name: 'dataRow', fieldCount: 1, - fields: ['test'] + fields: ['test'], }) }) }) @@ -250,55 +254,69 @@ describe('PgPacketStream', function () { var buff = buffers.notice([{ type: 'C', value: 'code' }]) testForMessage(buff, { name: 'notice', - code: 'code' + code: 'code', }) }) testForMessage(buffers.error([]), { - name: 'error' + name: 'error', }) describe('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 - value: 'alsdkf' - }]) + 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 + value: 'alsdkf', + }, + ]) testForMessage(buffer, { name: 'error', @@ -313,36 +331,36 @@ describe('PgPacketStream', function () { where: 'where', file: 'file', line: 'line', - routine: 'routine' + routine: 'routine', }) }) testForMessage(parseCompleteBuffer, { - name: 'parseComplete' + name: 'parseComplete', }) testForMessage(bindCompleteBuffer, { - name: 'bindComplete' + name: 'bindComplete', }) testForMessage(bindCompleteBuffer, { - name: 'bindComplete' + name: 'bindComplete', }) testForMessage(buffers.closeComplete(), { - name: 'closeComplete' + name: 'closeComplete', }) describe('parses portal suspended message', function () { testForMessage(portalSuspendedBuffer, { - name: 'portalSuspended' + name: 'portalSuspended', }) }) describe('parses replication start message', function () { testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { name: 'replicationStart', - length: 4 + length: 4, }) }) @@ -351,28 +369,28 @@ describe('PgPacketStream', function () { name: 'copyInResponse', length: 7, binary: false, - columnTypes: [] + columnTypes: [], }) testForMessage(buffers.copyIn(2), { name: 'copyInResponse', length: 11, binary: false, - columnTypes: [0, 1] + columnTypes: [0, 1], }) testForMessage(buffers.copyOut(0), { name: 'copyOutResponse', length: 7, binary: false, - columnTypes: [] + columnTypes: [], }) testForMessage(buffers.copyOut(3), { name: 'copyOutResponse', length: 13, binary: false, - columnTypes: [0, 1, 2] + columnTypes: [0, 1, 2], }) testForMessage(buffers.copyDone(), { @@ -383,11 +401,10 @@ describe('PgPacketStream', function () { testForMessage(buffers.copyData(Buffer.from([5, 6, 7])), { name: 'copyData', length: 7, - chunk: Buffer.from([5, 6, 7]) + chunk: Buffer.from([5, 6, 7]), }) }) - // 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 @@ -395,7 +412,7 @@ describe('PgPacketStream', function () { var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']) it('parses when full buffer comes in', async function () { - const messages = await parseBuffers([fullBuffer]); + const messages = await parseBuffers([fullBuffer]) const message = messages[0] as any assert.equal(message.fields.length, 5) assert.equal(message.fields[0], null) @@ -410,7 +427,7 @@ describe('PgPacketStream', function () { var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) fullBuffer.copy(firstBuffer, 0, 0) fullBuffer.copy(secondBuffer, 0, firstBuffer.length) - const messages = await parseBuffers([fullBuffer]); + const messages = await parseBuffers([fullBuffer]) const message = messages[0] as any assert.equal(message.fields.length, 5) assert.equal(message.fields[0], null) @@ -448,13 +465,13 @@ describe('PgPacketStream', function () { name: 'dataRow', fieldCount: 1, length: 11, - fields: ['!'] + fields: ['!'], }) assert.equal(messages[0].fields[0], '!') assert.deepEqual(messages[1], { name: 'readyForQuery', length: 5, - status: 'I' + status: 'I', }) } // sanity check @@ -480,17 +497,13 @@ describe('PgPacketStream', function () { return Promise.all([ splitAndVerifyTwoMessages(fullBuffer.length - 1), splitAndVerifyTwoMessages(fullBuffer.length - 4), - splitAndVerifyTwoMessages(fullBuffer.length - 6) + splitAndVerifyTwoMessages(fullBuffer.length - 6), ]) }) it('at the end', function () { - return Promise.all([ - splitAndVerifyTwoMessages(8), - splitAndVerifyTwoMessages(1) - ]) + return Promise.all([splitAndVerifyTwoMessages(8), splitAndVerifyTwoMessages(1)]) }) }) }) - }) diff --git a/packages/pg-protocol/src/index.ts b/packages/pg-protocol/src/index.ts index f4ade017..486f79c8 100644 --- a/packages/pg-protocol/src/index.ts +++ b/packages/pg-protocol/src/index.ts @@ -1,5 +1,5 @@ -import { BackendMessage } from './messages'; -import { serialize } from './serializer'; +import { BackendMessage } from './messages' +import { serialize } from './serializer' import { Parser, MessageCallback } from './parser' export function parse(stream: NodeJS.ReadableStream, callback: MessageCallback): Promise { @@ -8,4 +8,4 @@ export function parse(stream: NodeJS.ReadableStream, callback: MessageCallback): return new Promise((resolve) => stream.on('end', () => resolve())) } -export { serialize }; +export { serialize } diff --git a/packages/pg-protocol/src/messages.ts b/packages/pg-protocol/src/messages.ts index 222a2490..03c2f61e 100644 --- a/packages/pg-protocol/src/messages.ts +++ b/packages/pg-protocol/src/messages.ts @@ -1,4 +1,4 @@ -export type Mode = 'text' | 'binary'; +export type Mode = 'text' | 'binary' export const enum MessageName { parseComplete = 'parseComplete', @@ -30,14 +30,14 @@ export const enum MessageName { } export interface BackendMessage { - name: MessageName; - length: number; + name: MessageName + length: number } export const parseComplete: BackendMessage = { name: MessageName.parseComplete, length: 5, -}; +} export const bindComplete: BackendMessage = { name: MessageName.bindComplete, @@ -51,7 +51,7 @@ export const closeComplete: BackendMessage = { export const noData: BackendMessage = { name: MessageName.noData, - length: 5 + length: 5, } export const portalSuspended: BackendMessage = { @@ -75,136 +75,148 @@ export const copyDone: BackendMessage = { } interface NoticeOrError { - message: string | undefined; - severity: string | undefined; - code: string | undefined; - detail: string | undefined; - hint: string | undefined; - position: string | undefined; - internalPosition: string | undefined; - internalQuery: string | undefined; - where: string | undefined; - schema: string | undefined; - table: string | undefined; - column: string | undefined; - dataType: string | undefined; - constraint: string | undefined; - file: string | undefined; - line: string | undefined; - routine: string | undefined; + message: string | undefined + severity: string | undefined + code: string | undefined + detail: string | undefined + hint: string | undefined + position: string | undefined + internalPosition: string | undefined + internalQuery: string | undefined + where: string | undefined + schema: string | undefined + table: string | undefined + column: string | undefined + dataType: string | undefined + constraint: string | undefined + file: string | undefined + line: string | undefined + routine: string | undefined } export class DatabaseError extends Error implements NoticeOrError { - public severity: string | undefined; - public code: string | undefined; - public detail: string | undefined; - public hint: string | undefined; - public position: string | undefined; - public internalPosition: string | undefined; - public internalQuery: string | undefined; - public where: string | undefined; - public schema: string | undefined; - public table: string | undefined; - public column: string | undefined; - public dataType: string | undefined; - public constraint: string | undefined; - public file: string | undefined; - public line: string | undefined; - public routine: string | undefined; + public severity: string | undefined + public code: string | undefined + public detail: string | undefined + public hint: string | undefined + public position: string | undefined + public internalPosition: string | undefined + public internalQuery: string | undefined + public where: string | undefined + public schema: string | undefined + public table: string | undefined + public column: string | undefined + public dataType: string | undefined + public constraint: string | undefined + public file: string | undefined + public line: string | undefined + public routine: string | undefined constructor(message: string, public readonly length: number, public readonly name: MessageName) { super(message) } } export class CopyDataMessage { - public readonly name = MessageName.copyData; - constructor(public readonly length: number, public readonly chunk: Buffer) { - - } + public readonly name = MessageName.copyData + constructor(public readonly length: number, public readonly chunk: Buffer) {} } export class CopyResponse { - public readonly columnTypes: number[]; - constructor(public readonly length: number, public readonly name: MessageName, public readonly binary: boolean, columnCount: number) { - this.columnTypes = new Array(columnCount); + public readonly columnTypes: number[] + constructor( + public readonly length: number, + public readonly name: MessageName, + public readonly binary: boolean, + columnCount: number + ) { + this.columnTypes = new Array(columnCount) } } export class Field { - constructor(public readonly name: string, public readonly tableID: number, public readonly columnID: number, public readonly dataTypeID: number, public readonly dataTypeSize: number, public readonly dataTypeModifier: number, public readonly format: Mode) { - } + constructor( + public readonly name: string, + public readonly tableID: number, + public readonly columnID: number, + public readonly dataTypeID: number, + public readonly dataTypeSize: number, + public readonly dataTypeModifier: number, + public readonly format: Mode + ) {} } export class RowDescriptionMessage { - public readonly name: MessageName = MessageName.rowDescription; - public readonly fields: Field[]; + public readonly name: MessageName = MessageName.rowDescription + public readonly fields: Field[] constructor(public readonly length: number, public readonly fieldCount: number) { this.fields = new Array(this.fieldCount) } } export class ParameterStatusMessage { - public readonly name: MessageName = MessageName.parameterStatus; - constructor(public readonly length: number, public readonly parameterName: string, public readonly parameterValue: string) { - - } + public readonly name: MessageName = MessageName.parameterStatus + constructor( + public readonly length: number, + public readonly parameterName: string, + public readonly parameterValue: string + ) {} } export class AuthenticationMD5Password implements BackendMessage { - public readonly name: MessageName = MessageName.authenticationMD5Password; - constructor(public readonly length: number, public readonly salt: Buffer) { - } + public readonly name: MessageName = MessageName.authenticationMD5Password + constructor(public readonly length: number, public readonly salt: Buffer) {} } export class BackendKeyDataMessage { - public readonly name: MessageName = MessageName.backendKeyData; - constructor(public readonly length: number, public readonly processID: number, public readonly secretKey: number) { - } + public readonly name: MessageName = MessageName.backendKeyData + constructor(public readonly length: number, public readonly processID: number, public readonly secretKey: number) {} } export class NotificationResponseMessage { - public readonly name: MessageName = MessageName.notification; - constructor(public readonly length: number, public readonly processId: number, public readonly channel: string, public readonly payload: string) { - } + public readonly name: MessageName = MessageName.notification + constructor( + public readonly length: number, + public readonly processId: number, + public readonly channel: string, + public readonly payload: string + ) {} } export class ReadyForQueryMessage { - public readonly name: MessageName = MessageName.readyForQuery; - constructor(public readonly length: number, public readonly status: string) { - } + public readonly name: MessageName = MessageName.readyForQuery + constructor(public readonly length: number, public readonly status: string) {} } export class CommandCompleteMessage { public readonly name: MessageName = MessageName.commandComplete - constructor(public readonly length: number, public readonly text: string) { - } + constructor(public readonly length: number, public readonly text: string) {} } export class DataRowMessage { - public readonly fieldCount: number; + public readonly fieldCount: number public readonly name: MessageName = MessageName.dataRow constructor(public length: number, public fields: any[]) { - this.fieldCount = fields.length; + this.fieldCount = fields.length } } export class NoticeMessage implements BackendMessage, NoticeOrError { constructor(public readonly length: number, public readonly message: string | undefined) {} - public readonly name = MessageName.notice; - public severity: string | undefined; - public code: string | undefined; - public detail: string | undefined; - public hint: string | undefined; - public position: string | undefined; - public internalPosition: string | undefined; - public internalQuery: string | undefined; - public where: string | undefined; - public schema: string | undefined; - public table: string | undefined; - public column: string | undefined; - public dataType: string | undefined; - public constraint: string | undefined; - public file: string | undefined; - public line: string | undefined; - public routine: string | undefined; + public readonly name = MessageName.notice + public severity: string | undefined + public code: string | undefined + public detail: string | undefined + public hint: string | undefined + public position: string | undefined + public internalPosition: string | undefined + public internalQuery: string | undefined + public where: string | undefined + public schema: string | undefined + public table: string | undefined + public column: string | undefined + public dataType: string | undefined + public constraint: string | undefined + public file: string | undefined + public line: string | undefined + public routine: string | undefined } diff --git a/packages/pg-protocol/src/outbound-serializer.test.ts b/packages/pg-protocol/src/outbound-serializer.test.ts index 110b932c..4d2457e1 100644 --- a/packages/pg-protocol/src/outbound-serializer.test.ts +++ b/packages/pg-protocol/src/outbound-serializer.test.ts @@ -6,18 +6,22 @@ describe('serializer', () => { it('builds startup message', function () { const actual = serialize.startup({ user: 'brian', - database: 'bang' + database: 'bang', }) - assert.deepEqual(actual, new BufferList() - .addInt16(3) - .addInt16(0) - .addCString('user') - .addCString('brian') - .addCString('database') - .addCString('bang') - .addCString('client_encoding') - .addCString("'utf-8'") - .addCString('').join(true)) + assert.deepEqual( + actual, + new BufferList() + .addInt16(3) + .addInt16(0) + .addCString('user') + .addCString('brian') + .addCString('database') + .addCString('bang') + .addCString('client_encoding') + .addCString("'utf-8'") + .addCString('') + .join(true) + ) }) it('builds password message', function () { @@ -28,7 +32,7 @@ describe('serializer', () => { it('builds request ssl message', function () { const actual = serialize.requestSsl() const expected = new BufferList().addInt32(80877103).join(true) - assert.deepEqual(actual, expected); + assert.deepEqual(actual, expected) }) it('builds SASLInitialResponseMessage message', function () { @@ -36,28 +40,21 @@ describe('serializer', () => { assert.deepEqual(actual, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p')) }) - it('builds SCRAMClientFinalMessage message', function () { const actual = serialize.sendSCRAMClientFinalMessage('data') assert.deepEqual(actual, new BufferList().addString('data').join(true, 'p')) }) - it('builds query message', function () { var txt = 'select * from boom' const actual = serialize.query(txt) assert.deepEqual(actual, new BufferList().addCString(txt).join(true, 'Q')) }) - describe('parse message', () => { - it('builds parse message', function () { const actual = serialize.parse({ text: '!' }) - var expected = new BufferList() - .addCString('') - .addCString('!') - .addInt16(0).join(true, 'P') + var expected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P') assert.deepEqual(actual, expected) }) @@ -65,12 +62,9 @@ describe('serializer', () => { const actual = serialize.parse({ name: 'boom', text: 'select * from boom', - types: [] + types: [], }) - var expected = new BufferList() - .addCString('boom') - .addCString('select * from boom') - .addInt16(0).join(true, 'P') + var expected = new BufferList().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P') assert.deepEqual(actual, expected) }) @@ -78,7 +72,7 @@ describe('serializer', () => { const actual = serialize.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') @@ -87,13 +81,12 @@ describe('serializer', () => { .addInt32(1) .addInt32(2) .addInt32(3) - .addInt32(4).join(true, 'P') + .addInt32(4) + .join(true, 'P') assert.deepEqual(actual, expected) }) - }) - describe('bind messages', function () { it('with no values', function () { const actual = serialize.bind() @@ -112,10 +105,10 @@ describe('serializer', () => { const actual = serialize.bind({ portal: 'bang', statement: 'woo', - values: ['1', 'hi', null, 'zing'] + values: ['1', 'hi', null, 'zing'], }) var expectedBuffer = new BufferList() - .addCString('bang') // portal name + .addCString('bang') // portal name .addCString('woo') // statement name .addInt16(0) .addInt16(4) @@ -136,16 +129,16 @@ describe('serializer', () => { const actual = serialize.bind({ portal: 'bang', statement: 'woo', - values: ['1', 'hi', null, Buffer.from('zing', 'utf8')] + values: ['1', 'hi', null, Buffer.from('zing', 'utf8')], }) var expectedBuffer = new BufferList() - .addCString('bang') // portal name + .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) // value count + .addInt16(0) // string + .addInt16(0) // string + .addInt16(0) // string + .addInt16(1) // binary .addInt16(4) .addInt32(1) .add(Buffer.from('1')) @@ -162,22 +155,16 @@ describe('serializer', () => { describe('builds execute message', function () { it('for unamed portal with no row limit', function () { const actual = serialize.execute() - var expectedBuffer = new BufferList() - .addCString('') - .addInt32(0) - .join(true, 'E') + var expectedBuffer = new BufferList().addCString('').addInt32(0).join(true, 'E') assert.deepEqual(actual, expectedBuffer) }) it('for named portal with row limit', function () { const actual = serialize.execute({ portal: 'my favorite portal', - rows: 100 + rows: 100, }) - var expectedBuffer = new BufferList() - .addCString('my favorite portal') - .addInt32(100) - .join(true, 'E') + var expectedBuffer = new BufferList().addCString('my favorite portal').addInt32(100).join(true, 'E') assert.deepEqual(actual, expectedBuffer) }) }) @@ -231,7 +218,7 @@ describe('serializer', () => { describe('copy messages', function () { it('builds copyFromChunk', () => { const actual = serialize.copyData(Buffer.from([1, 2, 3])) - const expected = new BufferList().add(Buffer.from([1, 2,3 ])).join(true, 'd') + const expected = new BufferList().add(Buffer.from([1, 2, 3])).join(true, 'd') assert.deepEqual(actual, expected) }) diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 14573e62..1531f3c0 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -1,22 +1,47 @@ -import { TransformOptions } from 'stream'; -import { Mode, bindComplete, parseComplete, closeComplete, noData, portalSuspended, copyDone, replicationStart, emptyQuery, ReadyForQueryMessage, CommandCompleteMessage, CopyDataMessage, CopyResponse, NotificationResponseMessage, RowDescriptionMessage, Field, DataRowMessage, ParameterStatusMessage, BackendKeyDataMessage, DatabaseError, BackendMessage, MessageName, AuthenticationMD5Password, NoticeMessage } from './messages'; -import { BufferReader } from './buffer-reader'; +import { TransformOptions } from 'stream' +import { + Mode, + bindComplete, + parseComplete, + closeComplete, + noData, + portalSuspended, + copyDone, + replicationStart, + emptyQuery, + ReadyForQueryMessage, + CommandCompleteMessage, + CopyDataMessage, + CopyResponse, + NotificationResponseMessage, + RowDescriptionMessage, + Field, + DataRowMessage, + ParameterStatusMessage, + BackendKeyDataMessage, + DatabaseError, + BackendMessage, + MessageName, + AuthenticationMD5Password, + NoticeMessage, +} from './messages' +import { BufferReader } from './buffer-reader' import assert from 'assert' // every message is prefixed with a single bye -const CODE_LENGTH = 1; +const CODE_LENGTH = 1 // every message has an int32 length which includes itself but does // NOT include the code in the length -const LEN_LENGTH = 4; +const LEN_LENGTH = 4 -const HEADER_LENGTH = CODE_LENGTH + LEN_LENGTH; +const HEADER_LENGTH = CODE_LENGTH + LEN_LENGTH export type Packet = { - code: number; - packet: Buffer; + code: number + packet: Buffer } -const emptyBuffer = Buffer.allocUnsafe(0); +const emptyBuffer = Buffer.allocUnsafe(0) type StreamOptions = TransformOptions & { mode: Mode @@ -46,118 +71,117 @@ const enum MessageCodes { CopyData = 0x64, // d } -export type MessageCallback = (msg: BackendMessage) => void; +export type MessageCallback = (msg: BackendMessage) => void export class Parser { - private remainingBuffer: Buffer = emptyBuffer; - private reader = new BufferReader(); - private mode: Mode; + private remainingBuffer: Buffer = emptyBuffer + private reader = new BufferReader() + private mode: Mode constructor(opts?: StreamOptions) { if (opts?.mode === 'binary') { throw new Error('Binary mode not supported yet') } - this.mode = opts?.mode || 'text'; + this.mode = opts?.mode || 'text' } public parse(buffer: Buffer, callback: MessageCallback) { - let combinedBuffer = buffer; + let combinedBuffer = buffer if (this.remainingBuffer.byteLength) { - combinedBuffer = Buffer.allocUnsafe(this.remainingBuffer.byteLength + buffer.byteLength); + combinedBuffer = Buffer.allocUnsafe(this.remainingBuffer.byteLength + buffer.byteLength) this.remainingBuffer.copy(combinedBuffer) buffer.copy(combinedBuffer, this.remainingBuffer.byteLength) } - let offset = 0; - while ((offset + HEADER_LENGTH) <= combinedBuffer.byteLength) { + let offset = 0 + while (offset + HEADER_LENGTH <= combinedBuffer.byteLength) { // code is 1 byte long - it identifies the message type - const code = combinedBuffer[offset]; + const code = combinedBuffer[offset] // length is 1 Uint32BE - it is the length of the message EXCLUDING the code - const length = combinedBuffer.readUInt32BE(offset + CODE_LENGTH); + const length = combinedBuffer.readUInt32BE(offset + CODE_LENGTH) - const fullMessageLength = CODE_LENGTH + length; + const fullMessageLength = CODE_LENGTH + length if (fullMessageLength + offset <= combinedBuffer.byteLength) { - const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer); + const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer) callback(message) - offset += fullMessageLength; + offset += fullMessageLength } else { - break; + break } } if (offset === combinedBuffer.byteLength) { - this.remainingBuffer = emptyBuffer; + this.remainingBuffer = emptyBuffer } else { this.remainingBuffer = combinedBuffer.slice(offset) } - } private handlePacket(offset: number, code: number, length: number, bytes: Buffer): BackendMessage { switch (code) { case MessageCodes.BindComplete: - return bindComplete; + return bindComplete case MessageCodes.ParseComplete: - return parseComplete; + return parseComplete case MessageCodes.CloseComplete: - return closeComplete; + return closeComplete case MessageCodes.NoData: - return noData; + return noData case MessageCodes.PortalSuspended: - return portalSuspended; + return portalSuspended case MessageCodes.CopyDone: - return copyDone; + return copyDone case MessageCodes.ReplicationStart: - return replicationStart; + return replicationStart case MessageCodes.EmptyQuery: - return emptyQuery; + return emptyQuery case MessageCodes.DataRow: - return this.parseDataRowMessage(offset, length, bytes); + return this.parseDataRowMessage(offset, length, bytes) case MessageCodes.CommandComplete: - return this.parseCommandCompleteMessage(offset, length, bytes); + return this.parseCommandCompleteMessage(offset, length, bytes) case MessageCodes.ReadyForQuery: - return this.parseReadyForQueryMessage(offset, length, bytes); + return this.parseReadyForQueryMessage(offset, length, bytes) case MessageCodes.NotificationResponse: - return this.parseNotificationMessage(offset, length, bytes); + return this.parseNotificationMessage(offset, length, bytes) case MessageCodes.AuthenticationResponse: - return this.parseAuthenticationResponse(offset, length, bytes); + return this.parseAuthenticationResponse(offset, length, bytes) case MessageCodes.ParameterStatus: - return this.parseParameterStatusMessage(offset, length, bytes); + return this.parseParameterStatusMessage(offset, length, bytes) case MessageCodes.BackendKeyData: - return this.parseBackendKeyData(offset, length, bytes); + return this.parseBackendKeyData(offset, length, bytes) case MessageCodes.ErrorMessage: - return this.parseErrorMessage(offset, length, bytes, MessageName.error); + return this.parseErrorMessage(offset, length, bytes, MessageName.error) case MessageCodes.NoticeMessage: - return this.parseErrorMessage(offset, length, bytes, MessageName.notice); + return this.parseErrorMessage(offset, length, bytes, MessageName.notice) case MessageCodes.RowDescriptionMessage: - return this.parseRowDescriptionMessage(offset, length, bytes); + return this.parseRowDescriptionMessage(offset, length, bytes) case MessageCodes.CopyIn: - return this.parseCopyInMessage(offset, length, bytes); + return this.parseCopyInMessage(offset, length, bytes) case MessageCodes.CopyOut: - return this.parseCopyOutMessage(offset, length, bytes); + return this.parseCopyOutMessage(offset, length, bytes) case MessageCodes.CopyData: - return this.parseCopyData(offset, length, bytes); + return this.parseCopyData(offset, length, bytes) default: assert.fail(`unknown message code: ${code.toString(16)}`) } } private parseReadyForQueryMessage(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); - const status = this.reader.string(1); + this.reader.setBuffer(offset, bytes) + const status = this.reader.string(1) return new ReadyForQueryMessage(length, status) } private parseCommandCompleteMessage(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); - const text = this.reader.cstring(); - return new CommandCompleteMessage(length, text); + this.reader.setBuffer(offset, bytes) + const text = this.reader.cstring() + return new CommandCompleteMessage(length, text) } private parseCopyData(offset: number, length: number, bytes: Buffer) { - const chunk = bytes.slice(offset, offset + (length - 4)); - return new CopyDataMessage(length, chunk); + const chunk = bytes.slice(offset, offset + (length - 4)) + return new CopyDataMessage(length, chunk) } private parseCopyInMessage(offset: number, length: number, bytes: Buffer) { @@ -169,32 +193,32 @@ export class Parser { } private parseCopyMessage(offset: number, length: number, bytes: Buffer, messageName: MessageName) { - this.reader.setBuffer(offset, bytes); - const isBinary = this.reader.byte() !== 0; + this.reader.setBuffer(offset, bytes) + const isBinary = this.reader.byte() !== 0 const columnCount = this.reader.int16() - const message = new CopyResponse(length, messageName, isBinary, columnCount); + const message = new CopyResponse(length, messageName, isBinary, columnCount) for (let i = 0; i < columnCount; i++) { - message.columnTypes[i] = this.reader.int16(); + message.columnTypes[i] = this.reader.int16() } - return message; + return message } private parseNotificationMessage(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); - const processId = this.reader.int32(); - const channel = this.reader.cstring(); - const payload = this.reader.cstring(); - return new NotificationResponseMessage(length, processId, channel, payload); + this.reader.setBuffer(offset, bytes) + const processId = this.reader.int32() + const channel = this.reader.cstring() + const payload = this.reader.cstring() + return new NotificationResponseMessage(length, processId, channel, payload) } private parseRowDescriptionMessage(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); + this.reader.setBuffer(offset, bytes) const fieldCount = this.reader.int16() - const message = new RowDescriptionMessage(length, fieldCount); + const message = new RowDescriptionMessage(length, fieldCount) for (let i = 0; i < fieldCount; i++) { message.fields[i] = this.parseField() } - return message; + return message } private parseField(): Field { @@ -204,49 +228,48 @@ export class Parser { const dataTypeID = this.reader.int32() const dataTypeSize = this.reader.int16() const dataTypeModifier = this.reader.int32() - const mode = this.reader.int16() === 0 ? 'text' : 'binary'; + const mode = this.reader.int16() === 0 ? 'text' : 'binary' return new Field(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, mode) } private parseDataRowMessage(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); - const fieldCount = this.reader.int16(); - const fields: any[] = new Array(fieldCount); + this.reader.setBuffer(offset, bytes) + const fieldCount = this.reader.int16() + const fields: any[] = new Array(fieldCount) for (let i = 0; i < fieldCount; i++) { - const len = this.reader.int32(); + const len = this.reader.int32() // a -1 for length means the value of the field is null fields[i] = len === -1 ? null : this.reader.string(len) } - return new DataRowMessage(length, fields); + return new DataRowMessage(length, fields) } private parseParameterStatusMessage(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); - const name = this.reader.cstring(); + this.reader.setBuffer(offset, bytes) + const name = this.reader.cstring() const value = this.reader.cstring() return new ParameterStatusMessage(length, name, value) } private parseBackendKeyData(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); + this.reader.setBuffer(offset, bytes) const processID = this.reader.int32() const secretKey = this.reader.int32() return new BackendKeyDataMessage(length, processID, secretKey) } - public parseAuthenticationResponse(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); + this.reader.setBuffer(offset, bytes) const code = this.reader.int32() // TODO(bmc): maybe better types here const message: BackendMessage & any = { name: MessageName.authenticationOk, length, - }; + } switch (code) { case 0: // AuthenticationOk - break; + break case 3: // AuthenticationCleartextPassword if (message.length === 8) { message.name = MessageName.authenticationCleartextPassword @@ -255,14 +278,14 @@ export class Parser { case 5: // AuthenticationMD5Password if (message.length === 12) { message.name = MessageName.authenticationMD5Password - const salt = this.reader.bytes(4); - return new AuthenticationMD5Password(length, salt); + const salt = this.reader.bytes(4) + return new AuthenticationMD5Password(length, salt) } break case 10: // AuthenticationSASL message.name = MessageName.authenticationSASL message.mechanisms = [] - let mechanism: string; + let mechanism: string do { mechanism = this.reader.cstring() @@ -270,23 +293,23 @@ export class Parser { message.mechanisms.push(mechanism) } } while (mechanism) - break; + break case 11: // AuthenticationSASLContinue message.name = MessageName.authenticationSASLContinue message.data = this.reader.string(length - 4) - break; + break case 12: // AuthenticationSASLFinal message.name = MessageName.authenticationSASLFinal message.data = this.reader.string(length - 4) - break; + break default: throw new Error('Unknown authenticationOk message type ' + code) } - return message; + return message } private parseErrorMessage(offset: number, length: number, bytes: Buffer, name: MessageName) { - this.reader.setBuffer(offset, bytes); + this.reader.setBuffer(offset, bytes) const fields: Record = {} let fieldType = this.reader.string(1) while (fieldType !== '\0') { @@ -296,7 +319,10 @@ export class Parser { const messageValue = fields.M - const message = name === MessageName.notice ? new NoticeMessage(length, messageValue) : new DatabaseError(messageValue, length, name) + const message = + name === MessageName.notice + ? new NoticeMessage(length, messageValue) + : new DatabaseError(messageValue, length, name) message.severity = fields.S message.code = fields.C @@ -314,6 +340,6 @@ export class Parser { message.file = fields.F message.line = fields.L message.routine = fields.R - return message; + return message } } diff --git a/packages/pg-protocol/src/serializer.ts b/packages/pg-protocol/src/serializer.ts index 71ac3c87..00e43fff 100644 --- a/packages/pg-protocol/src/serializer.ts +++ b/packages/pg-protocol/src/serializer.ts @@ -13,7 +13,7 @@ const enum code { describe = 0x44, copyFromChunk = 0x64, copyDone = 0x63, - copyFail = 0x66 + copyFail = 0x66, } const writer = new Writer() @@ -32,15 +32,12 @@ const startup = (opts: Record): Buffer => { var length = bodyBuffer.length + 4 - return new Writer() - .addInt32(length) - .add(bodyBuffer) - .flush() + return new Writer().addInt32(length).add(bodyBuffer).flush() } const requestSsl = (): Buffer => { const response = Buffer.allocUnsafe(8) - response.writeInt32BE(8, 0); + response.writeInt32BE(8, 0) response.writeInt32BE(80877103, 4) return response } @@ -51,10 +48,7 @@ const password = (password: string): Buffer => { const sendSASLInitialResponseMessage = function (mechanism: string, initialResponse: string): Buffer { // 0x70 = 'p' - writer - .addCString(mechanism) - .addInt32(Buffer.byteLength(initialResponse)) - .addString(initialResponse) + writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse) return writer.flush(code.startup) } @@ -68,9 +62,9 @@ const query = (text: string): Buffer => { } type ParseOpts = { - name?: string; - types?: number[]; - text: string; + name?: string + types?: number[] + text: string } const emptyArray: any[] = [] @@ -108,10 +102,10 @@ const parse = (query: ParseOpts): Buffer => { } type BindOpts = { - portal?: string; - binary?: boolean; - statement?: string; - values?: any[]; + portal?: string + binary?: boolean + statement?: string + values?: any[] } const bind = (config: BindOpts = {}): Buffer => { @@ -128,9 +122,7 @@ const bind = (config: BindOpts = {}): Buffer => { useBinary = useBinary || values[j] instanceof Buffer } - var buffer = writer - .addCString(portal) - .addCString(statement) + var buffer = writer.addCString(portal).addCString(statement) if (!useBinary) { buffer.addInt16(0) } else { @@ -163,16 +155,16 @@ const bind = (config: BindOpts = {}): Buffer => { } type ExecOpts = { - portal?: string; - rows?: number; + portal?: string + rows?: number } const emptyExecute = Buffer.from([code.execute, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00]) const execute = (config?: ExecOpts): Buffer => { // this is the happy path for most queries - if (!config || !config.portal && !config.rows) { - return emptyExecute; + if (!config || (!config.portal && !config.rows)) { + return emptyExecute } const portal = config.portal || '' @@ -185,9 +177,9 @@ const execute = (config?: ExecOpts): Buffer => { buff[0] = code.execute buff.writeInt32BE(len, 1) buff.write(portal, 5, 'utf-8') - buff[portalLength + 5] = 0; // null terminate portal cString + buff[portalLength + 5] = 0 // null terminate portal cString buff.writeUInt32BE(rows, buff.length - 4) - return buff; + return buff } const cancel = (processID: number, secretKey: number): Buffer => { @@ -197,12 +189,12 @@ const cancel = (processID: number, secretKey: number): Buffer => { buffer.writeInt16BE(5678, 6) buffer.writeInt32BE(processID, 8) buffer.writeInt32BE(secretKey, 12) - return buffer; + return buffer } type PortalOpts = { - type: 'S' | 'P', - name?: string; + type: 'S' | 'P' + name?: string } const cstringMessage = (code: code, string: string): Buffer => { @@ -221,11 +213,11 @@ const emptyDescribePortal = writer.addCString('P').flush(code.describe) const emptyDescribeStatement = writer.addCString('S').flush(code.describe) const describe = (msg: PortalOpts): Buffer => { - return msg.name ? - cstringMessage(code.describe,`${msg.type}${msg.name || ''}`) : - msg.type === 'P' ? - emptyDescribePortal : - emptyDescribeStatement; + return msg.name + ? cstringMessage(code.describe, `${msg.type}${msg.name || ''}`) + : msg.type === 'P' + ? emptyDescribePortal + : emptyDescribeStatement } const close = (msg: PortalOpts): Buffer => { @@ -238,7 +230,7 @@ const copyData = (chunk: Buffer): Buffer => { } const copyFail = (message: string): Buffer => { - return cstringMessage(code.copyFail, message); + return cstringMessage(code.copyFail, message) } const codeOnlyBuffer = (code: code): Buffer => Buffer.from([code, 0x00, 0x00, 0x00, 0x04]) @@ -266,7 +258,7 @@ const serialize = { copyData, copyDone: () => copyDoneBuffer, copyFail, - cancel + cancel, } export { serialize } diff --git a/packages/pg-protocol/src/testing/buffer-list.ts b/packages/pg-protocol/src/testing/buffer-list.ts index 51812bce..15ac785c 100644 --- a/packages/pg-protocol/src/testing/buffer-list.ts +++ b/packages/pg-protocol/src/testing/buffer-list.ts @@ -1,7 +1,5 @@ export default class BufferList { - constructor(public buffers: Buffer[] = []) { - - } + constructor(public buffers: Buffer[] = []) {} public add(buffer: Buffer, front?: boolean) { this.buffers[front ? 'unshift' : 'push'](buffer) @@ -9,7 +7,7 @@ export default class BufferList { } public addInt16(val: number, front?: boolean) { - return this.add(Buffer.from([(val >>> 8), (val >>> 0)]), front) + return this.add(Buffer.from([val >>> 8, val >>> 0]), front) } public getByteLength(initial?: number) { @@ -19,12 +17,10 @@ export default class BufferList { } public addInt32(val: number, first?: boolean) { - return this.add(Buffer.from([ - (val >>> 24 & 0xFF), - (val >>> 16 & 0xFF), - (val >>> 8 & 0xFF), - (val >>> 0 & 0xFF) - ]), first) + return this.add( + Buffer.from([(val >>> 24) & 0xff, (val >>> 16) & 0xff, (val >>> 8) & 0xff, (val >>> 0) & 0xff]), + first + ) } public addCString(val: string, front?: boolean) { diff --git a/packages/pg-protocol/src/testing/test-buffers.ts b/packages/pg-protocol/src/testing/test-buffers.ts index 0594eaad..19ba16cc 100644 --- a/packages/pg-protocol/src/testing/test-buffers.ts +++ b/packages/pg-protocol/src/testing/test-buffers.ts @@ -3,21 +3,15 @@ import BufferList from './buffer-list' const buffers = { readyForQuery: function () { - return new BufferList() - .add(Buffer.from('I')) - .join(true, 'Z') + return new BufferList().add(Buffer.from('I')).join(true, 'Z') }, authenticationOk: function () { - return new BufferList() - .addInt32(0) - .join(true, 'R') + return new BufferList().addInt32(0).join(true, 'R') }, authenticationCleartextPassword: function () { - return new BufferList() - .addInt32(3) - .join(true, 'R') + return new BufferList().addInt32(3).join(true, 'R') }, authenticationMD5Password: function () { @@ -28,45 +22,27 @@ const buffers = { }, authenticationSASL: function () { - return new BufferList() - .addInt32(10) - .addCString('SCRAM-SHA-256') - .addCString('') - .join(true, 'R') + return new BufferList().addInt32(10).addCString('SCRAM-SHA-256').addCString('').join(true, 'R') }, authenticationSASLContinue: function () { - return new BufferList() - .addInt32(11) - .addString('data') - .join(true, 'R') + return new BufferList().addInt32(11).addString('data').join(true, 'R') }, authenticationSASLFinal: function () { - return new BufferList() - .addInt32(12) - .addString('data') - .join(true, 'R') + return new BufferList().addInt32(12).addString('data').join(true, 'R') }, parameterStatus: function (name: string, value: string) { - return new BufferList() - .addCString(name) - .addCString(value) - .join(true, 'S') + return new BufferList().addCString(name).addCString(value).join(true, 'S') }, backendKeyData: function (processID: number, secretKey: number) { - return new BufferList() - .addInt32(processID) - .addInt32(secretKey) - .join(true, 'K') + return new BufferList().addInt32(processID).addInt32(secretKey).join(true, 'K') }, commandComplete: function (string: string) { - return new BufferList() - .addCString(string) - .join(true, 'C') + return new BufferList().addCString(string).join(true, 'C') }, rowDescription: function (fields: any[]) { @@ -74,7 +50,8 @@ const buffers = { var buf = new BufferList() buf.addInt16(fields.length) fields.forEach(function (field) { - buf.addCString(field.name) + buf + .addCString(field.name) .addInt32(field.tableID || 0) .addInt16(field.attributeNumber || 0) .addInt32(field.dataTypeID || 0) @@ -116,7 +93,7 @@ const buffers = { buf.addChar(field.type) buf.addCString(field.value) }) - return buf.add(Buffer.from([0]))// terminator + return buf.add(Buffer.from([0])) // terminator }, parseComplete: function () { @@ -128,11 +105,7 @@ const buffers = { }, notification: function (id: number, channel: string, payload: string) { - return new BufferList() - .addInt32(id) - .addCString(channel) - .addCString(payload) - .join(true, 'A') + return new BufferList().addInt32(id).addCString(channel).addCString(payload).join(true, 'A') }, emptyQuery: function () { @@ -152,9 +125,9 @@ const buffers = { // text mode .addByte(0) // column count - .addInt16(cols); + .addInt16(cols) for (let i = 0; i < cols; i++) { - list.addInt16(i); + list.addInt16(i) } return list.join(true, 'G') }, @@ -164,20 +137,20 @@ const buffers = { // text mode .addByte(0) // column count - .addInt16(cols); + .addInt16(cols) for (let i = 0; i < cols; i++) { - list.addInt16(i); + list.addInt16(i) } return list.join(true, 'H') }, copyData: function (bytes: Buffer) { - return new BufferList().add(bytes).join(true, 'd'); + return new BufferList().add(bytes).join(true, 'd') }, copyDone: function () { return new BufferList().join(true, 'c') - } + }, } export default buffers diff --git a/packages/pg-query-stream/index.js b/packages/pg-query-stream/index.js index 20c56b38..914a7e32 100644 --- a/packages/pg-query-stream/index.js +++ b/packages/pg-query-stream/index.js @@ -3,7 +3,7 @@ const Cursor = require('pg-cursor') class PgQueryStream extends Readable { constructor(text, values, config = {}) { - const { batchSize, highWaterMark = 100 } = config; + const { batchSize, highWaterMark = 100 } = config // https://nodejs.org/api/stream.html#stream_new_stream_readable_options super({ objectMode: true, emitClose: true, autoDestroy: true, highWaterMark: batchSize || highWaterMark }) this.cursor = new Cursor(text, values, config) diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 7f8f2f80..05a3f970 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -4,8 +4,7 @@ "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { - "test": "mocha", - "lint": "eslint ." + "test": "mocha" }, "repository": { "type": "git", diff --git a/packages/pg-query-stream/test/close.js b/packages/pg-query-stream/test/close.js index d7e44b67..4a95464a 100644 --- a/packages/pg-query-stream/test/close.js +++ b/packages/pg-query-stream/test/close.js @@ -5,84 +5,87 @@ var QueryStream = require('../') var helper = require('./helper') if (process.version.startsWith('v8.')) { - return console.error('warning! node versions less than 10lts no longer supported & stream closing semantics may not behave properly'); -} - -helper('close', function (client) { - it('emits close', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], { batchSize: 2, highWaterMark: 2 }) - var query = client.query(stream) - query.pipe(concat(function () { })) - query.on('close', done) - }) -}) - -helper('early close', function (client) { - it('can be closed early', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [20000], { batchSize: 2, highWaterMark: 2 }) - var query = client.query(stream) - var readCount = 0 - query.on('readable', function () { - readCount++ - query.read() - }) - query.once('readable', function () { - query.destroy() - }) - query.on('close', function () { - assert(readCount < 10, 'should not have read more than 10 rows') - done() + console.error('warning! node less than 10lts stream closing semantics may not behave properly') +} else { + helper('close', function (client) { + it('emits close', function (done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], { batchSize: 2, highWaterMark: 2 }) + var query = client.query(stream) + query.pipe(concat(function () {})) + query.on('close', done) }) }) - it('can destroy stream while reading', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') - client.query(stream) - stream.on('data', () => done(new Error('stream should not have returned rows'))) - setTimeout(() => { + helper('early close', function (client) { + it('can be closed early', function (done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [20000], { + batchSize: 2, + highWaterMark: 2, + }) + var query = client.query(stream) + var readCount = 0 + query.on('readable', function () { + readCount++ + query.read() + }) + query.once('readable', function () { + query.destroy() + }) + query.on('close', function () { + assert(readCount < 10, 'should not have read more than 10 rows') + done() + }) + }) + + it('can destroy stream while reading', function (done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') + client.query(stream) + stream.on('data', () => done(new Error('stream should not have returned rows'))) + setTimeout(() => { + stream.destroy() + stream.on('close', done) + }, 100) + }) + + it('emits an error when calling destroy with an error', function (done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') + client.query(stream) + stream.on('data', () => done(new Error('stream should not have returned rows'))) + setTimeout(() => { + stream.destroy(new Error('intentional error')) + stream.on('error', (err) => { + // make sure there's an error + assert(err) + assert.strictEqual(err.message, 'intentional error') + done() + }) + }, 100) + }) + + it('can destroy stream while reading an error', function (done) { + var stream = new QueryStream('SELECT * from pg_sleep(1), basdfasdf;') + client.query(stream) + stream.on('data', () => done(new Error('stream should not have returned rows'))) + stream.once('error', () => { + stream.destroy() + // wait a bit to let any other errors shake through + setTimeout(done, 100) + }) + }) + + it('does not crash when destroying the stream immediately after calling read', function (done) { + var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') + client.query(stream) + stream.on('data', () => done(new Error('stream should not have returned rows'))) stream.destroy() stream.on('close', done) - }, 100) - }) + }) - it('emits an error when calling destroy with an error', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') - client.query(stream) - stream.on('data', () => done(new Error('stream should not have returned rows'))) - setTimeout(() => { - stream.destroy(new Error('intentional error')) - stream.on('error', (err) => { - // make sure there's an error - assert(err); - assert.strictEqual(err.message, 'intentional error'); - done(); - }) - }, 100) - }) - - it('can destroy stream while reading an error', function (done) { - var stream = new QueryStream('SELECT * from pg_sleep(1), basdfasdf;') - client.query(stream) - stream.on('data', () => done(new Error('stream should not have returned rows'))) - stream.once('error', () => { + it('does not crash when destroying the stream before its submitted', function (done) { + var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') + stream.on('data', () => done(new Error('stream should not have returned rows'))) stream.destroy() - // wait a bit to let any other errors shake through - setTimeout(done, 100) + stream.on('close', done) }) }) - - it('does not crash when destroying the stream immediately after calling read', function (done) { - var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') - client.query(stream) - stream.on('data', () => done(new Error('stream should not have returned rows'))) - stream.destroy() - stream.on('close', done) - }) - - it('does not crash when destroying the stream before its submitted', function (done) { - var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') - stream.on('data', () => done(new Error('stream should not have returned rows'))) - stream.destroy() - stream.on('close', done) - }) -}) +} diff --git a/packages/pg-query-stream/test/concat.js b/packages/pg-query-stream/test/concat.js index 78a633be..6ce17a28 100644 --- a/packages/pg-query-stream/test/concat.js +++ b/packages/pg-query-stream/test/concat.js @@ -9,14 +9,20 @@ helper('concat', function (client) { it('concats correctly', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) - query.pipe(through(function (row) { - this.push(row.num) - })).pipe(concat(function (result) { - var total = result.reduce(function (prev, cur) { - return prev + cur - }) - assert.equal(total, 20100) - })) + query + .pipe( + through(function (row) { + this.push(row.num) + }) + ) + .pipe( + concat(function (result) { + var total = result.reduce(function (prev, cur) { + return prev + cur + }) + assert.equal(total, 20100) + }) + ) stream.on('end', done) }) }) diff --git a/packages/pg-query-stream/test/config.js b/packages/pg-query-stream/test/config.js index 1634f617..061fb115 100644 --- a/packages/pg-query-stream/test/config.js +++ b/packages/pg-query-stream/test/config.js @@ -5,14 +5,14 @@ describe('stream config options', () => { // this is mostly for backwards compatability. it('sets readable.highWaterMark based on batch size', () => { var stream = new QueryStream('SELECT NOW()', [], { - batchSize: 88 + batchSize: 88, }) assert.equal(stream._readableState.highWaterMark, 88) }) it('sets readable.highWaterMark based on highWaterMark config', () => { var stream = new QueryStream('SELECT NOW()', [], { - highWaterMark: 88 + highWaterMark: 88, }) assert.equal(stream._readableState.highWaterMark, 88) diff --git a/packages/pg-query-stream/test/empty-query.js b/packages/pg-query-stream/test/empty-query.js index 75603174..25f7d695 100644 --- a/packages/pg-query-stream/test/empty-query.js +++ b/packages/pg-query-stream/test/empty-query.js @@ -3,18 +3,20 @@ const helper = require('./helper') const QueryStream = require('../') helper('empty-query', function (client) { - it('handles empty query', function(done) { + it('handles empty query', function (done) { const stream = new QueryStream('-- this is a comment', []) const query = client.query(stream) - query.on('end', function () { - // nothing should happen for empty query - done(); - }).on('data', function () { - // noop to kick off reading - }) + query + .on('end', function () { + // nothing should happen for empty query + done() + }) + .on('data', function () { + // noop to kick off reading + }) }) it('continues to function after stream', function (done) { client.query('SELECT NOW()', done) }) -}) \ No newline at end of file +}) diff --git a/packages/pg-query-stream/test/error.js b/packages/pg-query-stream/test/error.js index 1e6030d5..0b732923 100644 --- a/packages/pg-query-stream/test/error.js +++ b/packages/pg-query-stream/test/error.js @@ -7,13 +7,15 @@ helper('error', function (client) { it('receives error on stream', function (done) { var stream = new QueryStream('SELECT * FROM asdf num', []) var query = client.query(stream) - query.on('error', function (err) { - assert(err) - assert.equal(err.code, '42P01') - done() - }).on('data', function () { - // noop to kick of reading - }) + query + .on('error', function (err) { + assert(err) + assert.equal(err.code, '42P01') + done() + }) + .on('data', function () { + // noop to kick of reading + }) }) it('continues to function after stream', function (done) { diff --git a/packages/pg-query-stream/test/instant.js b/packages/pg-query-stream/test/instant.js index 49ab0b07..0939753b 100644 --- a/packages/pg-query-stream/test/instant.js +++ b/packages/pg-query-stream/test/instant.js @@ -7,9 +7,11 @@ require('./helper')('instant', function (client) { it('instant', function (done) { var query = new QueryStream('SELECT pg_sleep(1)', []) var stream = client.query(query) - stream.pipe(concat(function (res) { - assert.equal(res.length, 1) - done() - })) + stream.pipe( + concat(function (res) { + assert.equal(res.length, 1) + done() + }) + ) }) }) diff --git a/packages/pg-query-stream/test/passing-options.js b/packages/pg-query-stream/test/passing-options.js index e2ddd185..858767de 100644 --- a/packages/pg-query-stream/test/passing-options.js +++ b/packages/pg-query-stream/test/passing-options.js @@ -2,12 +2,12 @@ var assert = require('assert') var helper = require('./helper') var QueryStream = require('../') -helper('passing options', function(client) { - it('passes row mode array', function(done) { +helper('passing options', function (client) { + it('passes row mode array', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { rowMode: 'array' }) var query = client.query(stream) var result = [] - query.on('data', datum => { + query.on('data', (datum) => { result.push(datum) }) query.on('end', () => { @@ -17,14 +17,14 @@ helper('passing options', function(client) { }) }) - it('passes custom types', function(done) { + it('passes custom types', function (done) { const types = { - getTypeParser: () => string => string, + getTypeParser: () => (string) => string, } var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { types }) var query = client.query(stream) var result = [] - query.on('data', datum => { + query.on('data', (datum) => { result.push(datum) }) query.on('end', () => { diff --git a/packages/pg-query-stream/test/pauses.js b/packages/pg-query-stream/test/pauses.js index 8d9beb02..3da9a0b0 100644 --- a/packages/pg-query-stream/test/pauses.js +++ b/packages/pg-query-stream/test/pauses.js @@ -7,12 +7,17 @@ var QueryStream = require('../') require('./helper')('pauses', function (client) { it('pauses', function (done) { this.timeout(5000) - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], {batchSize: 2, highWaterMark: 2}) + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], { batchSize: 2, highWaterMark: 2 }) var query = client.query(stream) var pauser = tester.createPauseStream(0.1, 100) - query.pipe(JSONStream.stringify()).pipe(pauser).pipe(concat(function (json) { - JSON.parse(json) - done() - })) + query + .pipe(JSONStream.stringify()) + .pipe(pauser) + .pipe( + concat(function (json) { + JSON.parse(json) + done() + }) + ) }) }) diff --git a/packages/pg-query-stream/test/slow-reader.js b/packages/pg-query-stream/test/slow-reader.js index 4c0070a3..3978f300 100644 --- a/packages/pg-query-stream/test/slow-reader.js +++ b/packages/pg-query-stream/test/slow-reader.js @@ -14,13 +14,18 @@ mapper._transform = function (obj, enc, cb) { helper('slow reader', function (client) { it('works', function (done) { this.timeout(50000) - var stream = new QueryStream('SELECT * FROM generate_series(0, 201) num', [], { highWaterMark: 100, batchSize: 50 }) + var stream = new QueryStream('SELECT * FROM generate_series(0, 201) num', [], { + highWaterMark: 100, + batchSize: 50, + }) stream.on('end', function () { // console.log('stream end') }) client.query(stream) - stream.pipe(mapper).pipe(concat(function (res) { - done() - })) + stream.pipe(mapper).pipe( + concat(function (res) { + done() + }) + ) }) }) diff --git a/packages/pg-query-stream/test/stream-tester-timestamp.js b/packages/pg-query-stream/test/stream-tester-timestamp.js index 7a31b4ec..ce989cc3 100644 --- a/packages/pg-query-stream/test/stream-tester-timestamp.js +++ b/packages/pg-query-stream/test/stream-tester-timestamp.js @@ -4,15 +4,14 @@ var assert = require('assert') require('./helper')('stream tester timestamp', function (client) { it('should not warn about max listeners', function (done) { - var sql = 'SELECT * FROM generate_series(\'1983-12-30 00:00\'::timestamp, \'2013-12-30 00:00\', \'1 years\')' + var sql = "SELECT * FROM generate_series('1983-12-30 00:00'::timestamp, '2013-12-30 00:00', '1 years')" var stream = new QueryStream(sql, []) var ended = false var query = client.query(stream) - query.on('end', function () { ended = true }) - spec(query) - .readable() - .pausable({ strict: true }) - .validateOnExit() + query.on('end', function () { + ended = true + }) + spec(query).readable().pausable({ strict: true }).validateOnExit() var checkListeners = function () { assert(stream.listeners('end').length < 10) if (!ended) { diff --git a/packages/pg-query-stream/test/stream-tester.js b/packages/pg-query-stream/test/stream-tester.js index 82656581..f5ab2e37 100644 --- a/packages/pg-query-stream/test/stream-tester.js +++ b/packages/pg-query-stream/test/stream-tester.js @@ -6,10 +6,7 @@ require('./helper')('stream tester', function (client) { it('passes stream spec', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) - spec(query) - .readable() - .pausable({strict: true}) - .validateOnExit() + spec(query).readable().pausable({ strict: true }).validateOnExit() stream.on('end', done) }) }) diff --git a/packages/pg/Makefile b/packages/pg/Makefile index a5b0bc1d..e05edbf4 100644 --- a/packages/pg/Makefile +++ b/packages/pg/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 \ - lint publish test-missing-native update-npm + publish test-missing-native update-npm all: npm install @@ -17,7 +17,7 @@ help: test: test-unit -test-all: lint test-missing-native test-unit test-integration test-native +test-all: test-missing-native test-unit test-integration test-native update-npm: @@ -59,7 +59,3 @@ test-binary: test-connection test-pool: @find test/integration/connection-pool -name "*.js" | $(node-command) binary - -lint: - @echo "***Starting lint***" - node_modules/.bin/eslint lib diff --git a/packages/pg/bench.js b/packages/pg/bench.js index 4fde9170..80c07dc1 100644 --- a/packages/pg/bench.js +++ b/packages/pg/bench.js @@ -1,69 +1,69 @@ -const pg = require("./lib"); +const pg = require('./lib') const pool = new pg.Pool() const params = { text: - "select typname, typnamespace, typowner, typlen, typbyval, typcategory, typispreferred, typisdefined, typdelim, typrelid, typelem, typarray from pg_type where typtypmod = $1 and typisdefined = $2", - values: [-1, true] -}; + 'select typname, typnamespace, typowner, typlen, typbyval, typcategory, typispreferred, typisdefined, typdelim, typrelid, typelem, typarray from pg_type where typtypmod = $1 and typisdefined = $2', + values: [-1, true], +} const insert = { text: 'INSERT INTO foobar(name, age) VALUES ($1, $2)', - values: ['brian', 100] + values: ['brian', 100], } const seq = { - text: 'SELECT * FROM generate_series(1, 1000)' + text: 'SELECT * FROM generate_series(1, 1000)', } const exec = async (client, q) => { const result = await client.query({ text: q.text, values: q.values, - rowMode: "array" - }); -}; + rowMode: 'array', + }) +} const bench = async (client, q, time) => { - let start = Date.now(); - let count = 0; + let start = Date.now() + let count = 0 while (true) { - await exec(client, q); - count++; + await exec(client, q) + count++ if (Date.now() - start > time) { - return count; + return count } } -}; +} const run = async () => { - const client = new pg.Client(); - await client.connect(); + const client = new pg.Client() + await client.connect() await client.query('CREATE TEMP TABLE foobar(name TEXT, age NUMERIC)') - await bench(client, params, 1000); - console.log("warmup done"); - const seconds = 5; + await bench(client, params, 1000) + console.log('warmup done') + const seconds = 5 - let queries = await bench(client, params, seconds * 1000); + let queries = await bench(client, params, seconds * 1000) console.log('') - console.log("little queries:", queries); - console.log("qps", queries / seconds); - console.log("on my laptop best so far seen 733 qps") + console.log('little queries:', queries) + console.log('qps', queries / seconds) + console.log('on my laptop best so far seen 733 qps') console.log('') - queries = await bench(client, seq, seconds * 1000); - console.log("sequence queries:", queries); - console.log("qps", queries / seconds); - console.log("on my laptop best so far seen 1309 qps") + queries = await bench(client, seq, seconds * 1000) + console.log('sequence queries:', queries) + console.log('qps', queries / seconds) + console.log('on my laptop best so far seen 1309 qps') console.log('') - queries = await bench(client, insert, seconds * 1000); - console.log("insert queries:", queries); - console.log("qps", queries / seconds); - console.log("on my laptop best so far seen 5799 qps") + queries = await bench(client, insert, seconds * 1000) + console.log('insert queries:', queries) + console.log('qps', queries / seconds) + console.log('on my laptop best so far seen 5799 qps') console.log() - await client.end(); - await client.end(); -}; + await client.end() + await client.end() +} -run().catch(e => console.error(e) || process.exit(-1)); +run().catch((e) => console.error(e) || process.exit(-1)) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index ac7ab4c2..04124f8a 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -37,7 +37,7 @@ var Client = function (config) { configurable: true, enumerable: false, writable: true, - value: this.connectionParameters.password + value: this.connectionParameters.password, }) this.replication = this.connectionParameters.replication @@ -52,13 +52,15 @@ var Client = function (config) { this._connectionError = false this._queryable = true - this.connection = c.connection || new Connection({ - stream: c.stream, - ssl: this.connectionParameters.ssl, - keepAlive: c.keepAlive || false, - keepAliveInitialDelayMillis: c.keepAliveInitialDelayMillis || 0, - encoding: this.connectionParameters.client_encoding || 'utf8' - }) + this.connection = + c.connection || + new Connection({ + stream: c.stream, + ssl: this.connectionParameters.ssl, + keepAlive: c.keepAlive || false, + keepAliveInitialDelayMillis: c.keepAliveInitialDelayMillis || 0, + encoding: this.connectionParameters.client_encoding || 'utf8', + }) this.queryQueue = [] this.binary = c.binary || defaults.binary this.processID = null @@ -127,9 +129,10 @@ Client.prototype._connect = function (callback) { function checkPgPass(cb) { return function (msg) { if (typeof self.password === 'function') { - self._Promise.resolve() + self._Promise + .resolve() .then(() => self.password()) - .then(pass => { + .then((pass) => { if (pass !== undefined) { if (typeof pass !== 'string') { con.emit('error', new TypeError('Password must be a string')) @@ -140,7 +143,8 @@ Client.prototype._connect = function (callback) { self.connectionParameters.password = self.password = null } cb(msg) - }).catch(err => { + }) + .catch((err) => { con.emit('error', err) }) } else if (self.password !== null) { @@ -157,22 +161,31 @@ Client.prototype._connect = function (callback) { } // password request handling - con.on('authenticationCleartextPassword', checkPgPass(function () { - con.password(self.password) - })) + con.on( + 'authenticationCleartextPassword', + checkPgPass(function () { + con.password(self.password) + }) + ) // password request handling - con.on('authenticationMD5Password', checkPgPass(function (msg) { - con.password(utils.postgresMd5PasswordHash(self.user, self.password, msg.salt)) - })) + con.on( + 'authenticationMD5Password', + checkPgPass(function (msg) { + con.password(utils.postgresMd5PasswordHash(self.user, self.password, msg.salt)) + }) + ) // password request handling (SASL) var saslSession - con.on('authenticationSASL', checkPgPass(function (msg) { - saslSession = sasl.startSession(msg.mechanisms) + con.on( + 'authenticationSASL', + checkPgPass(function (msg) { + saslSession = sasl.startSession(msg.mechanisms) - con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response) - })) + con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response) + }) + ) // password request handling (SASL) con.on('authenticationSASLContinue', function (msg) { @@ -259,9 +272,7 @@ Client.prototype._connect = function (callback) { }) con.once('end', () => { - const error = this._ending - ? new Error('Connection terminated') - : new Error('Connection terminated unexpectedly') + const error = this._ending ? new Error('Connection terminated') : new Error('Connection terminated unexpectedly') clearTimeout(connectionTimeoutHandle) this._errorAllQueries(error) @@ -367,7 +378,7 @@ Client.prototype.getStartupConf = function () { var data = { user: params.user, - database: params.database + database: params.database, } var appName = params.application_name || params.fallback_application_name @@ -422,11 +433,11 @@ 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) { var hasBackslash = false - var escaped = '\'' + var escaped = "'" 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 @@ -436,7 +447,7 @@ Client.prototype.escapeLiteral = function (str) { } } - escaped += '\'' + escaped += "'" if (hasBackslash === true) { escaped = ' E' + escaped @@ -488,7 +499,7 @@ Client.prototype.query = function (config, values, callback) { query = new Query(config, values, callback) if (!query.callback) { result = new this._Promise((resolve, reject) => { - query.callback = (err, res) => err ? reject(err) : resolve(res) + query.callback = (err, res) => (err ? reject(err) : resolve(res)) }) } } @@ -507,7 +518,7 @@ Client.prototype.query = function (config, values, callback) { // we already returned an error, // just do nothing if query completes - query.callback = () => { } + query.callback = () => {} // Remove from queue var index = this.queryQueue.indexOf(query) diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index 71ef63ba..acc5c0e8 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -80,14 +80,18 @@ Connection.prototype.connect = function (port, host) { case 'N': // Server does not support SSL connections self.stream.end() return self.emit('error', new Error('The server does not support SSL connections')) - default: // Any other response byte, including 'E' (ErrorResponse) indicating a server error + default: + // Any other response byte, including 'E' (ErrorResponse) indicating a server error self.stream.end() return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') - const options = Object.assign({ - socket: self.stream - }, self.ssl) + const options = Object.assign( + { + socket: self.stream, + }, + self.ssl + ) if (net.isIP(host) === 0) { options.servername = host } diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index cd6d3b8a..b34e0df5 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -22,9 +22,7 @@ var val = function (key, config, envVar) { envVar = process.env[envVar] } - return config[key] || - envVar || - defaults[key] + return config[key] || envVar || defaults[key] } var useSsl = function () { @@ -66,7 +64,7 @@ var ConnectionParameters = function (config) { configurable: true, enumerable: false, writable: true, - value: val('password', config) + value: val('password', config), }) this.binary = val('binary', config) @@ -74,7 +72,7 @@ var ConnectionParameters = function (config) { this.client_encoding = val('client_encoding', config) this.replication = val('replication', config) // a domain socket begins with '/' - this.isDomainSocket = (!(this.host || '').indexOf('/')) + this.isDomainSocket = !(this.host || '').indexOf('/') this.application_name = val('application_name', config, 'PGAPPNAME') this.fallback_application_name = val('fallback_application_name', config, false) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index b7fde90a..243872c9 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -35,7 +35,7 @@ var Connection = function (config) { this._emitMessage = false this._reader = new Reader({ headerSize: 1, - lengthPadding: -4 + lengthPadding: -4, }) var self = this this.on('newListener', function (eventName) { @@ -88,14 +88,18 @@ Connection.prototype.connect = function (port, host) { case 'N': // Server does not support SSL connections self.stream.end() return self.emit('error', new Error('The server does not support SSL connections')) - default: // Any other response byte, including 'E' (ErrorResponse) indicating a server error + default: + // Any other response byte, including 'E' (ErrorResponse) indicating a server error self.stream.end() return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') - const options = Object.assign({ - socket: self.stream - }, self.ssl) + const options = Object.assign( + { + socket: self.stream, + }, + self.ssl + ) if (net.isIP(host) === 0) { options.servername = host } @@ -127,23 +131,16 @@ Connection.prototype.attachListeners = function (stream) { } Connection.prototype.requestSsl = function () { - var bodyBuffer = this.writer - .addInt16(0x04D2) - .addInt16(0x162F).flush() + var bodyBuffer = this.writer.addInt16(0x04d2).addInt16(0x162f).flush() var length = bodyBuffer.length + 4 - var buffer = new Writer() - .addInt32(length) - .add(bodyBuffer) - .join() + var buffer = new Writer().addInt32(length).add(bodyBuffer).join() this.stream.write(buffer) } Connection.prototype.startup = function (config) { - var writer = this.writer - .addInt16(3) - .addInt16(0) + var writer = this.writer.addInt16(3).addInt16(0) Object.keys(config).forEach(function (key) { var val = config[key] @@ -157,27 +154,16 @@ Connection.prototype.startup = function (config) { var length = bodyBuffer.length + 4 - var buffer = new Writer() - .addInt32(length) - .add(bodyBuffer) - .join() + var buffer = new Writer().addInt32(length).add(bodyBuffer).join() this.stream.write(buffer) } Connection.prototype.cancel = function (processID, secretKey) { - var bodyBuffer = this.writer - .addInt16(1234) - .addInt16(5678) - .addInt32(processID) - .addInt32(secretKey) - .flush() + var bodyBuffer = this.writer.addInt16(1234).addInt16(5678).addInt32(processID).addInt32(secretKey).flush() var length = bodyBuffer.length + 4 - var buffer = new Writer() - .addInt32(length) - .add(bodyBuffer) - .join() + var buffer = new Writer().addInt32(length).add(bodyBuffer).join() this.stream.write(buffer) } @@ -188,18 +174,14 @@ Connection.prototype.password = function (password) { Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) { // 0x70 = 'p' - this.writer - .addCString(mechanism) - .addInt32(Buffer.byteLength(initialResponse)) - .addString(initialResponse) + this.writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse) this._send(0x70) } Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) { // 0x70 = 'p' - this.writer - .addString(additionalData) + this.writer.addString(additionalData) this._send(0x70) } @@ -263,13 +245,17 @@ Connection.prototype.bind = function (config, more) { 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 { + 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) } + for (j = 0; j < len; j++) { + buffer.addInt16(values[j] instanceof Buffer) + } } buffer.addInt16(len) for (var i = 0; i < len; i++) { @@ -301,9 +287,7 @@ Connection.prototype.execute = function (config, more) { config = config || {} config.portal = config.portal || '' config.rows = config.rows || '' - this.writer - .addCString(config.portal) - .addInt32(config.rows) + this.writer.addCString(config.portal).addInt32(config.rows) // 0x45 = 'E' this._send(0x45, more) diff --git a/packages/pg/lib/defaults.js b/packages/pg/lib/defaults.js index eb58550d..39421668 100644 --- a/packages/pg/lib/defaults.js +++ b/packages/pg/lib/defaults.js @@ -70,7 +70,7 @@ module.exports = { keepalives: 1, - keepalives_idle: 0 + keepalives_idle: 0, } var pgTypes = require('pg-types') diff --git a/packages/pg/lib/index.js b/packages/pg/lib/index.js index c73064cf..975175cd 100644 --- a/packages/pg/lib/index.js +++ b/packages/pg/lib/index.js @@ -14,7 +14,7 @@ var Pool = require('pg-pool') const poolFactory = (Client) => { return class BoundPool extends Pool { - constructor (options) { + constructor(options) { super(options, Client) } } @@ -54,10 +54,10 @@ if (typeof process.env.NODE_PG_FORCE_NATIVE !== 'undefined') { // overwrite module.exports.native so that getter is never called again Object.defineProperty(module.exports, 'native', { - value: native + value: native, }) return native - } + }, }) } diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index 165147f9..f4554615 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -22,7 +22,7 @@ assert(semver.gte(Native.version, pkg.minNativeVersion), msg) var NativeQuery = require('./query') -var Client = module.exports = function (config) { +var Client = (module.exports = function (config) { EventEmitter.call(this) config = config || {} @@ -30,7 +30,7 @@ var Client = module.exports = function (config) { this._types = new TypeOverrides(config.types) this.native = new Native({ - types: this._types + types: this._types, }) this._queryQueue = [] @@ -41,7 +41,7 @@ var Client = module.exports = function (config) { // keep these on the object for legacy reasons // for the time being. TODO: deprecate all this jazz - var cp = this.connectionParameters = new ConnectionParameters(config) + var cp = (this.connectionParameters = new ConnectionParameters(config)) this.user = cp.user // "hiding" the password so it doesn't show up in stack traces @@ -50,7 +50,7 @@ var Client = module.exports = function (config) { configurable: true, enumerable: false, writable: true, - value: cp.password + value: cp.password, }) this.database = cp.database this.host = cp.host @@ -58,7 +58,7 @@ var Client = module.exports = function (config) { // a hash to hold named queries this.namedQueries = {} -} +}) Client.Query = NativeQuery @@ -115,7 +115,7 @@ Client.prototype._connect = function (cb) { self.native.on('notification', function (msg) { self.emit('notification', { channel: msg.relname, - payload: msg.extra + payload: msg.extra, }) }) @@ -180,7 +180,7 @@ Client.prototype.query = function (config, values, callback) { resolveOut = resolve rejectOut = reject }) - query.callback = (err, res) => err ? rejectOut(err) : resolveOut(res) + query.callback = (err, res) => (err ? rejectOut(err) : resolveOut(res)) } } @@ -248,7 +248,7 @@ Client.prototype.end = function (cb) { var result if (!cb) { result = new this._Promise(function (resolve, reject) { - cb = (err) => err ? reject(err) : resolve() + cb = (err) => (err ? reject(err) : resolve()) }) } this.native.end(function () { diff --git a/packages/pg/lib/native/query.js b/packages/pg/lib/native/query.js index 0c83e27e..de443489 100644 --- a/packages/pg/lib/native/query.js +++ b/packages/pg/lib/native/query.js @@ -11,7 +11,7 @@ var EventEmitter = require('events').EventEmitter var util = require('util') var utils = require('../utils') -var NativeQuery = module.exports = function (config, values, callback) { +var NativeQuery = (module.exports = function (config, values, callback) { EventEmitter.call(this) config = utils.normalizeQueryConfig(config, values, callback) this.text = config.text @@ -27,27 +27,30 @@ var NativeQuery = module.exports = function (config, values, callback) { // 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)) -} + this.on( + 'newListener', + function (event) { + if (event === 'row') this._emitRowEvents = true + }.bind(this) + ) +}) util.inherits(NativeQuery, EventEmitter) var errorFieldMap = { /* eslint-disable quote-props */ - 'sqlState': 'code', - 'statementPosition': 'position', - 'messagePrimary': 'message', - 'context': 'where', - 'schemaName': 'schema', - 'tableName': 'table', - 'columnName': 'column', - 'dataTypeName': 'dataType', - 'constraintName': 'constraint', - 'sourceFile': 'file', - 'sourceLine': 'line', - 'sourceFunction': 'routine' + 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) { @@ -77,10 +80,12 @@ 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) - }.bind(this)) + this._promise = new Promise( + function (resolve, reject) { + this._once('end', resolve) + this._once('error', reject) + }.bind(this) + ) return this._promise } @@ -105,7 +110,7 @@ NativeQuery.prototype.submit = function (client) { if (self._emitRowEvents) { if (results.length > 1) { rows.forEach((rowOfRows, i) => { - rowOfRows.forEach(row => { + rowOfRows.forEach((row) => { self.emit('row', row, results[i]) }) }) diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 4fcfe391..2392b710 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -42,14 +42,22 @@ class Query extends EventEmitter { requiresPreparation() { // named queries must always be prepared - if (this.name) { return true } + if (this.name) { + return true + } // always prepare if there are max number of rows expected per // portal execution - if (this.rows) { return true } + if (this.rows) { + return true + } // don't prepare empty text queries - if (!this.text) { return false } + if (!this.text) { + return false + } // prepare if there are values - if (!this.values) { return false } + if (!this.values) { + return false + } return this.values.length > 0 } @@ -168,10 +176,13 @@ class Query extends EventEmitter { } _getRows(connection, rows) { - connection.execute({ - portal: this.portal, - rows: rows - }, true) + connection.execute( + { + portal: this.portal, + rows: rows, + }, + true + ) connection.flush() } @@ -181,11 +192,14 @@ class Query extends EventEmitter { this.isPreparedStatement = true // TODO refactor this poor encapsulation if (!this.hasBeenParsed(connection)) { - connection.parse({ - text: this.text, - name: this.name, - types: this.types - }, true) + connection.parse( + { + text: this.text, + name: this.name, + types: this.types, + }, + true + ) } if (this.values) { @@ -198,17 +212,23 @@ class Query extends EventEmitter { } // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY - connection.bind({ - portal: this.portal, - statement: this.name, - values: this.values, - binary: this.binary - }, true) + connection.bind( + { + portal: this.portal, + statement: this.name, + values: this.values, + binary: this.binary, + }, + true + ) - connection.describe({ - type: 'P', - name: this.portal || '' - }, true) + connection.describe( + { + type: 'P', + name: this.portal || '', + }, + true + ) this._getRows(connection, this.rows) } diff --git a/packages/pg/lib/sasl.js b/packages/pg/lib/sasl.js index 39c24bb3..22abf5c4 100644 --- a/packages/pg/lib/sasl.js +++ b/packages/pg/lib/sasl.js @@ -1,7 +1,7 @@ 'use strict' const crypto = require('crypto') -function startSession (mechanisms) { +function startSession(mechanisms) { if (mechanisms.indexOf('SCRAM-SHA-256') === -1) { throw new Error('SASL: Only mechanism SCRAM-SHA-256 is currently supported') } @@ -12,11 +12,11 @@ function startSession (mechanisms) { mechanism: 'SCRAM-SHA-256', clientNonce, response: 'n,,n=*,r=' + clientNonce, - message: 'SASLInitialResponse' + message: 'SASLInitialResponse', } } -function continueSession (session, password, serverData) { +function continueSession(session, password, serverData) { if (session.message !== 'SASLInitialResponse') { throw new Error('SASL: Last message was not SASLInitialResponse') } @@ -53,42 +53,46 @@ function continueSession (session, password, serverData) { session.response = clientFinalMessageWithoutProof + ',p=' + clientProof } -function finalizeSession (session, serverData) { +function finalizeSession(session, serverData) { if (session.message !== 'SASLResponse') { throw new Error('SASL: Last message was not SASLResponse') } var serverSignature - String(serverData).split(',').forEach(function (part) { - switch (part[0]) { - case 'v': - serverSignature = part.substr(2) - break - } - }) + String(serverData) + .split(',') + .forEach(function (part) { + switch (part[0]) { + case 'v': + serverSignature = part.substr(2) + break + } + }) if (serverSignature !== session.serverSignature) { throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature does not match') } } -function extractVariablesFromFirstServerMessage (data) { +function extractVariablesFromFirstServerMessage(data) { var nonce, salt, iteration - String(data).split(',').forEach(function (part) { - switch (part[0]) { - case 'r': - nonce = part.substr(2) - break - case 's': - salt = part.substr(2) - break - case 'i': - iteration = parseInt(part.substr(2), 10) - break - } - }) + String(data) + .split(',') + .forEach(function (part) { + switch (part[0]) { + case 'r': + nonce = part.substr(2) + break + case 's': + salt = part.substr(2) + break + case 'i': + iteration = parseInt(part.substr(2), 10) + break + } + }) if (!nonce) { throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing') @@ -105,11 +109,11 @@ function extractVariablesFromFirstServerMessage (data) { return { nonce, salt, - iteration + iteration, } } -function xorBuffers (a, b) { +function xorBuffers(a, b) { if (!Buffer.isBuffer(a)) a = Buffer.from(a) if (!Buffer.isBuffer(b)) b = Buffer.from(b) var res = [] @@ -125,11 +129,11 @@ function xorBuffers (a, b) { return Buffer.from(res) } -function createHMAC (key, msg) { +function createHMAC(key, msg) { return crypto.createHmac('sha256', key).update(msg).digest() } -function Hi (password, saltBytes, iterations) { +function Hi(password, saltBytes, iterations) { var ui1 = createHMAC(password, Buffer.concat([saltBytes, Buffer.from([0, 0, 0, 1])])) var ui = ui1 for (var i = 0; i < iterations - 1; i++) { @@ -143,5 +147,5 @@ function Hi (password, saltBytes, iterations) { module.exports = { startSession, continueSession, - finalizeSession + finalizeSession, } diff --git a/packages/pg/lib/type-overrides.js b/packages/pg/lib/type-overrides.js index 54394406..63bfc83e 100644 --- a/packages/pg/lib/type-overrides.js +++ b/packages/pg/lib/type-overrides.js @@ -9,7 +9,7 @@ var types = require('pg-types') -function TypeOverrides (userTypes) { +function TypeOverrides(userTypes) { this._types = userTypes || types this.text = {} this.binary = {} @@ -17,9 +17,12 @@ function TypeOverrides (userTypes) { TypeOverrides.prototype.getOverrides = function (format) { switch (format) { - case 'text': return this.text - case 'binary': return this.binary - default: return {} + case 'text': + return this.text + case 'binary': + return this.binary + default: + return {} } } diff --git a/packages/pg/lib/utils.js b/packages/pg/lib/utils.js index 879949f0..f6da81f4 100644 --- a/packages/pg/lib/utils.js +++ b/packages/pg/lib/utils.js @@ -11,10 +11,8 @@ const crypto = require('crypto') const defaults = require('./defaults') -function escapeElement (elementRepresentation) { - var escaped = elementRepresentation - .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"') +function escapeElement(elementRepresentation) { + var escaped = elementRepresentation.replace(/\\/g, '\\\\').replace(/"/g, '\\"') return '"' + escaped + '"' } @@ -22,7 +20,7 @@ function escapeElement (elementRepresentation) { // 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) { +function arrayString(val) { var result = '{' for (var i = 0; i < val.length; i++) { if (i > 0) { @@ -76,7 +74,7 @@ var prepareValue = function (val, seen) { return val.toString() } -function prepareObject (val, seen) { +function prepareObject(val, seen) { if (val && typeof val.toPostgres === 'function') { seen = seen || [] if (seen.indexOf(val) !== -1) { @@ -89,48 +87,66 @@ function prepareObject (val, seen) { return JSON.stringify(val) } -function pad (number, digits) { +function pad(number, digits) { number = '' + number - while (number.length < digits) { number = '0' + number } + while (number.length < digits) { + number = '0' + number + } return number } -function dateToString (date) { +function dateToString(date) { var offset = -date.getTimezoneOffset() var year = date.getFullYear() var isBCYear = year < 1 if (isBCYear) year = Math.abs(year) + 1 // negative years are 1 off their BC representation - var ret = pad(year, 4) + '-' + - pad(date.getMonth() + 1, 2) + '-' + - pad(date.getDate(), 2) + 'T' + - pad(date.getHours(), 2) + ':' + - pad(date.getMinutes(), 2) + ':' + - pad(date.getSeconds(), 2) + '.' + + var ret = + pad(year, 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) if (offset < 0) { ret += '-' offset *= -1 - } else { ret += '+' } + } else { + ret += '+' + } ret += pad(Math.floor(offset / 60), 2) + ':' + pad(offset % 60, 2) if (isBCYear) ret += ' BC' return ret } -function dateToStringUTC (date) { +function dateToStringUTC(date) { var year = date.getUTCFullYear() var isBCYear = year < 1 if (isBCYear) year = Math.abs(year) + 1 // negative years are 1 off their BC representation - var ret = pad(year, 4) + '-' + - pad(date.getUTCMonth() + 1, 2) + '-' + - pad(date.getUTCDate(), 2) + 'T' + - pad(date.getUTCHours(), 2) + ':' + - pad(date.getUTCMinutes(), 2) + ':' + - pad(date.getUTCSeconds(), 2) + '.' + + var ret = + pad(year, 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) ret += '+00:00' @@ -138,9 +154,9 @@ function dateToStringUTC (date) { return ret } -function normalizeQueryConfig (config, values, callback) { +function normalizeQueryConfig(config, values, callback) { // can take in strings or config objects - config = (typeof (config) === 'string') ? { text: config } : config + config = typeof config === 'string' ? { text: config } : config if (values) { if (typeof values === 'function') { config.callback = values @@ -166,12 +182,12 @@ const postgresMd5PasswordHash = function (user, password, salt) { } module.exports = { - prepareValue: function prepareValueWrapper (value) { + 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, postgresMd5PasswordHash, - md5 + md5, } diff --git a/packages/pg/package.json b/packages/pg/package.json index 91e78d33..5386ec2e 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -32,18 +32,11 @@ "async": "0.9.0", "bluebird": "3.5.2", "co": "4.6.0", - "eslint": "^6.0.1", - "eslint-config-standard": "^13.0.1", - "eslint-plugin-import": "^2.18.1", - "eslint-plugin-node": "^9.1.0", - "eslint-plugin-promise": "^4.2.1", - "eslint-plugin-standard": "^4.0.0", "pg-copy-streams": "0.3.0" }, "minNativeVersion": "2.0.0", "scripts": { - "test": "make test-all", - "lint": "make lint" + "test": "make test-all" }, "files": [ "lib", diff --git a/packages/pg/script/create-test-tables.js b/packages/pg/script/create-test-tables.js index e2110313..6db5fea7 100644 --- a/packages/pg/script/create-test-tables.js +++ b/packages/pg/script/create-test-tables.js @@ -3,32 +3,32 @@ 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: '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: 'Zanzabar', age: 260} + { 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: 'Zanzabar', age: 260 }, ] var con = new pg.Client({ @@ -36,7 +36,7 @@ var con = new pg.Client({ port: args.port, user: args.user, password: args.password, - database: args.database + database: args.database, }) con.connect((err) => { @@ -45,8 +45,7 @@ con.connect((err) => { } con.query( - 'DROP TABLE IF EXISTS person;' - + ' CREATE TABLE person (id serial, name varchar(10), age integer)', + 'DROP TABLE IF EXISTS person;' + ' CREATE TABLE person (id serial, name varchar(10), age integer)', (err) => { if (err) { throw err @@ -56,10 +55,8 @@ con.connect((err) => { console.log('Filling it with people') con.query( - 'INSERT INTO person (name, age) VALUES' - + people - .map((person) => ` ('${person.name}', ${person.age})`) - .join(','), + 'INSERT INTO person (name, age) VALUES' + + people.map((person) => ` ('${person.name}', ${person.age})`).join(','), (err, result) => { if (err) { throw err @@ -67,6 +64,8 @@ con.connect((err) => { console.log(`Inserted ${result.rowCount} people`) con.end() - }) - }) + } + ) + } + ) }) diff --git a/packages/pg/script/dump-db-types.js b/packages/pg/script/dump-db-types.js index 2e55969d..08fe4dc9 100644 --- a/packages/pg/script/dump-db-types.js +++ b/packages/pg/script/dump-db-types.js @@ -2,22 +2,17 @@ var pg = require(__dirname + '/../lib') var args = require(__dirname + '/../test/cli') -var queries = [ - 'select CURRENT_TIMESTAMP', - "select interval '1 day' + interval '1 hour'", - "select TIMESTAMP 'today'"] +var queries = ['select CURRENT_TIMESTAMP', "select interval '1 day' + interval '1 hour'", "select TIMESTAMP 'today'"] queries.forEach(function (query) { var client = new pg.Client({ user: args.user, database: args.database, - password: args.password + password: args.password, }) client.connect() - client - .query(query) - .on('row', function (row) { - console.log(row) - client.end() - }) + client.query(query).on('row', function (row) { + console.log(row) + client.end() + }) }) diff --git a/packages/pg/script/list-db-types.js b/packages/pg/script/list-db-types.js index d281bb90..c3e75c1a 100644 --- a/packages/pg/script/list-db-types.js +++ b/packages/pg/script/list-db-types.js @@ -1,7 +1,10 @@ '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) -})) +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/packages/pg/test/buffer-list.js b/packages/pg/test/buffer-list.js index e0a9007b..aea529c1 100644 --- a/packages/pg/test/buffer-list.js +++ b/packages/pg/test/buffer-list.js @@ -10,7 +10,7 @@ p.add = function (buffer, front) { } p.addInt16 = function (val, front) { - return this.add(Buffer.from([(val >>> 8), (val >>> 0)]), front) + return this.add(Buffer.from([val >>> 8, val >>> 0]), front) } p.getByteLength = function (initial) { @@ -20,12 +20,10 @@ p.getByteLength = function (initial) { } p.addInt32 = function (val, first) { - return this.add(Buffer.from([ - (val >>> 24 & 0xFF), - (val >>> 16 & 0xFF), - (val >>> 8 & 0xFF), - (val >>> 0 & 0xFF) - ]), first) + return this.add( + Buffer.from([(val >>> 24) & 0xff, (val >>> 16) & 0xff, (val >>> 8) & 0xff, (val >>> 0) & 0xff]), + first + ) } p.addCString = function (val, front) { diff --git a/packages/pg/test/integration/client/api-tests.js b/packages/pg/test/integration/client/api-tests.js index dab92350..a957c32a 100644 --- a/packages/pg/test/integration/client/api-tests.js +++ b/packages/pg/test/integration/client/api-tests.js @@ -9,13 +9,15 @@ suite.test('null and undefined are both inserted as NULL', function (done) { 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('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) { @@ -36,7 +38,7 @@ suite.test('null and undefined are both inserted as NULL', function (done) { ) }) -suite.test('pool callback behavior', done => { +suite.test('pool callback behavior', (done) => { // test weird callback behavior with node-pool const pool = new pg.Pool() pool.connect(function (err) { @@ -50,51 +52,63 @@ suite.test('pool callback behavior', done => { suite.test('query timeout', (cb) => { const pool = new pg.Pool({ query_timeout: 1000 }) pool.connect().then((client) => { - client.query('SELECT pg_sleep(2)', assert.calls(function (err, result) { - assert(err) - assert(err.message === 'Query read timeout') - client.release() - pool.end(cb) - })) + client.query( + 'SELECT pg_sleep(2)', + assert.calls(function (err, result) { + assert(err) + assert(err.message === 'Query read timeout') + client.release() + pool.end(cb) + }) + ) }) }) suite.test('query recover from timeout', (cb) => { const pool = new pg.Pool({ query_timeout: 1000 }) pool.connect().then((client) => { - client.query('SELECT pg_sleep(20)', assert.calls(function (err, result) { - assert(err) - assert(err.message === 'Query read timeout') - client.release(err) - pool.connect().then((client) => { - client.query('SELECT 1', assert.calls(function (err, result) { - assert(!err) - client.release(err) - pool.end(cb) - })) + client.query( + 'SELECT pg_sleep(20)', + assert.calls(function (err, result) { + assert(err) + assert(err.message === 'Query read timeout') + client.release(err) + pool.connect().then((client) => { + client.query( + 'SELECT 1', + assert.calls(function (err, result) { + assert(!err) + client.release(err) + pool.end(cb) + }) + ) + }) }) - })) + ) }) }) suite.test('query no timeout', (cb) => { const pool = new pg.Pool({ query_timeout: 10000 }) pool.connect().then((client) => { - client.query('SELECT pg_sleep(1)', assert.calls(function (err, result) { - assert(!err) - client.release() - pool.end(cb) - })) + client.query( + 'SELECT pg_sleep(1)', + assert.calls(function (err, result) { + assert(!err) + client.release() + pool.end(cb) + }) + ) }) }) -suite.test('callback API', 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']) const config = { text: 'INSERT INTO peep(name) VALUES ($1)', - values: ['brian'] + values: ['brian'], } client.query(config) client.query('INSERT INTO peep(name) VALUES ($1)', ['aaron']) @@ -104,18 +118,18 @@ suite.test('callback API', done => { assert.equal(res.rowCount, 3) assert.deepEqual(res.rows, [ { - name: 'aaron' + name: 'aaron', }, { - name: 'brian' + name: 'brian', }, { - name: 'brianc' - } + name: 'brianc', + }, ]) done() }) - client.connect(err => { + client.connect((err) => { assert(!err) client.once('drain', () => client.end()) }) @@ -175,8 +189,7 @@ suite.test('query errors are handled and do not bubble if callback is provided', ) }) ) -} -) +}) suite.test('callback is fired once and only once', function (done) { const pool = new pg.Pool() @@ -189,14 +202,10 @@ suite.test('callback is fired once and only once', function (done) { [ "INSERT INTO boom(name) VALUES('hai')", "INSERT INTO boom(name) VALUES('boom')", - "INSERT INTO boom(name) VALUES('zoom')" + "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.' - ) + assert.equal(callCount++, 0, 'Call count should be 0. More means this callback fired more than once.') release() pool.end(done) } @@ -213,7 +222,7 @@ suite.test('can provide callback and config object', function (done) { client.query( { name: 'boom', - text: 'select NOW()' + text: 'select NOW()', }, assert.calls(function (err, result) { assert(!err) @@ -232,7 +241,7 @@ suite.test('can provide callback and config and parameters', function (done) { assert.calls(function (err, client, release) { assert(!err) var config = { - text: 'select $1::text as val' + text: 'select $1::text as val', } client.query( config, diff --git a/packages/pg/test/integration/client/appname-tests.js b/packages/pg/test/integration/client/appname-tests.js index e5883908..dd8de6b3 100644 --- a/packages/pg/test/integration/client/appname-tests.js +++ b/packages/pg/test/integration/client/appname-tests.js @@ -6,24 +6,29 @@ var suite = new helper.Suite() var conInfo = helper.config -function getConInfo (override) { - return Object.assign({}, conInfo, override ) +function getConInfo(override) { + return Object.assign({}, conInfo, override) } -function getAppName (conf, cb) { +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() - })) - })) + 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) { + getAppName({}, function (res) { assert.strictEqual(res, '') done() }) @@ -32,7 +37,7 @@ suite.test('No default appliation_name ', function (done) { suite.test('fallback_application_name is used', function (done) { var fbAppName = 'this is my app' var conf = getConInfo({ - 'fallback_application_name': fbAppName + fallback_application_name: fbAppName, }) getAppName(conf, function (res) { assert.strictEqual(res, fbAppName) @@ -43,7 +48,7 @@ suite.test('fallback_application_name is used', function (done) { suite.test('application_name is used', function (done) { var appName = 'some wired !@#$% application_name' var conf = getConInfo({ - 'application_name': appName + application_name: appName, }) getAppName(conf, function (res) { assert.strictEqual(res, appName) @@ -55,8 +60,8 @@ suite.test('application_name has precedence over fallback_application_name', fun var appName = 'some wired !@#$% application_name' var fbAppName = 'some other strange $$test$$ appname' var conf = getConInfo({ - 'application_name': appName, - 'fallback_application_name': fbAppName + application_name: appName, + fallback_application_name: fbAppName, }) getAppName(conf, function (res) { assert.strictEqual(res, appName) @@ -82,8 +87,8 @@ suite.test('application_name from connection string', function (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) { + var appName = (process.env.PGAPPNAME = 'testest') + getAppName({}, function (res) { delete process.env.PGAPPNAME assert.strictEqual(res, appName) done() diff --git a/packages/pg/test/integration/client/array-tests.js b/packages/pg/test/integration/client/array-tests.js index 84e97f19..f5e62b03 100644 --- a/packages/pg/test/integration/client/array-tests.js +++ b/packages/pg/test/integration/client/array-tests.js @@ -6,172 +6,226 @@ var suite = new helper.Suite() const pool = new pg.Pool() -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]) - done() - })) - }) - - suite.test('elements containing JSON-escaped characters', function (done) { - var 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()) - - pool.connect(assert.calls(function (err, client, 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(() => { + 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 = '\\"\\"' + + 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()) + + 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() + }) + }) + ) + }) + }) + ) + }) +) diff --git a/packages/pg/test/integration/client/big-simple-query-tests.js b/packages/pg/test/integration/client/big-simple-query-tests.js index 5a15dca3..b0dc252f 100644 --- a/packages/pg/test/integration/client/big-simple-query-tests.js +++ b/packages/pg/test/integration/client/big-simple-query-tests.js @@ -19,9 +19,19 @@ var big_query_rows_3 = [] // Works 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 + .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() done() @@ -31,9 +41,20 @@ suite.test('big simple query 1', function (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) }) + 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() @@ -44,9 +65,20 @@ suite.test('big simple query 2', function (done) { // 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) }) + 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() @@ -61,13 +93,17 @@ process.on('exit', function () { 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 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) { diff --git a/packages/pg/test/integration/client/configuration-tests.js b/packages/pg/test/integration/client/configuration-tests.js index a6756dde..0737a79c 100644 --- a/packages/pg/test/integration/client/configuration-tests.js +++ b/packages/pg/test/integration/client/configuration-tests.js @@ -25,7 +25,7 @@ suite.test('default values are used in new clients', function () { ssl: false, application_name: undefined, fallback_application_name: undefined, - parseInputDatesAsUTC: false + parseInputDatesAsUTC: false, }) var client = new pg.Client() @@ -33,7 +33,7 @@ suite.test('default values are used in new clients', function () { user: process.env.USER, database: process.env.USER, password: null, - port: 5432 + port: 5432, }) }) @@ -50,7 +50,7 @@ suite.test('modified values are passed to created clients', function () { password: 'zap', database: 'pow', port: 1234, - host: 'blam' + host: 'blam', }) }) diff --git a/packages/pg/test/integration/client/connection-timeout-tests.js b/packages/pg/test/integration/client/connection-timeout-tests.js index 35e41885..843fa95b 100644 --- a/packages/pg/test/integration/client/connection-timeout-tests.js +++ b/packages/pg/test/integration/client/connection-timeout-tests.js @@ -10,26 +10,26 @@ const options = { port: 54321, connectionTimeoutMillis: 2000, user: 'not', - database: 'existing' + database: 'existing', } const serverWithConnectionTimeout = (timeout, callback) => { const sockets = new Set() - const server = net.createServer(socket => { + const server = net.createServer((socket) => { sockets.add(socket) socket.once('end', () => sockets.delete(socket)) - socket.on('data', data => { + socket.on('data', (data) => { // deny request for SSL if (data.length === 8) { socket.write(Buffer.from('N', 'utf8')) - // consider all authentication requests as good + // consider all authentication requests as good } else if (!data[0]) { socket.write(buffers.authenticationOk()) // send ReadyForQuery `timeout` ms after authentication setTimeout(() => socket.write(buffers.readyForQuery()), timeout).unref() - // respond with our canned response + // respond with our canned response } else { socket.write(buffers.readyForQuery()) } @@ -37,7 +37,7 @@ const serverWithConnectionTimeout = (timeout, callback) => { }) let closing = false - const closeServer = done => { + const closeServer = (done) => { if (closing) return closing = true @@ -50,32 +50,34 @@ const serverWithConnectionTimeout = (timeout, callback) => { server.listen(options.port, options.host, () => callback(closeServer)) } -suite.test('successful connection', done => { - serverWithConnectionTimeout(0, closeServer => { +suite.test('successful connection', (done) => { + serverWithConnectionTimeout(0, (closeServer) => { const timeoutId = setTimeout(() => { throw new Error('Client should have connected successfully but it did not.') }, 3000) const client = new helper.Client(options) - client.connect() + client + .connect() .then(() => client.end()) .then(() => closeServer(done)) - .catch(err => closeServer(() => done(err))) + .catch((err) => closeServer(() => done(err))) .then(() => clearTimeout(timeoutId)) }) }) -suite.test('expired connection timeout', done => { - serverWithConnectionTimeout(options.connectionTimeoutMillis * 2, closeServer => { +suite.test('expired connection timeout', (done) => { + serverWithConnectionTimeout(options.connectionTimeoutMillis * 2, (closeServer) => { const timeoutId = setTimeout(() => { throw new Error('Client should have emitted an error but it did not.') }, 3000) const client = new helper.Client(options) - client.connect() + client + .connect() .then(() => client.end()) .then(() => closeServer(() => done(new Error('Connection timeout should have expired but it did not.')))) - .catch(err => { + .catch((err) => { assert(err instanceof Error) assert(/timeout expired\s*/.test(err.message)) closeServer(done) diff --git a/packages/pg/test/integration/client/custom-types-tests.js b/packages/pg/test/integration/client/custom-types-tests.js index 2b50fef0..d1dd2eec 100644 --- a/packages/pg/test/integration/client/custom-types-tests.js +++ b/packages/pg/test/integration/client/custom-types-tests.js @@ -4,19 +4,21 @@ const Client = helper.pg.Client const suite = new helper.Suite() const customTypes = { - getTypeParser: () => () => 'okay!' + getTypeParser: () => () => 'okay!', } suite.test('custom type parser in client config', (done) => { const client = new Client({ types: customTypes }) - client.connect() - .then(() => { - client.query('SELECT NOW() as val', assert.success(function (res) { + client.connect().then(() => { + client.query( + 'SELECT NOW() as val', + assert.success(function (res) { assert.equal(res.rows[0].val, 'okay!') client.end().then(done) - })) - }) + }) + ) + }) }) // Custom type-parsers per query are not supported in native @@ -24,15 +26,17 @@ if (!helper.args.native) { suite.test('custom type parser in query', (done) => { const client = new Client() - client.connect() - .then(() => { - client.query({ + client.connect().then(() => { + client.query( + { text: 'SELECT NOW() as val', - types: customTypes - }, assert.success(function (res) { + types: customTypes, + }, + assert.success(function (res) { assert.equal(res.rows[0].val, 'okay!') client.end().then(done) - })) - }) + }) + ) + }) }) } diff --git a/packages/pg/test/integration/client/empty-query-tests.js b/packages/pg/test/integration/client/empty-query-tests.js index 975dc0f6..d887885c 100644 --- a/packages/pg/test/integration/client/empty-query-tests.js +++ b/packages/pg/test/integration/client/empty-query-tests.js @@ -7,7 +7,7 @@ suite.test('empty query message handling', function (done) { assert.emits(client, 'drain', function () { client.end(done) }) - client.query({text: ''}) + client.query({ text: '' }) }) suite.test('callback supported', function (done) { diff --git a/packages/pg/test/integration/client/error-handling-tests.js b/packages/pg/test/integration/client/error-handling-tests.js index 97b0ce83..93959e02 100644 --- a/packages/pg/test/integration/client/error-handling-tests.js +++ b/packages/pg/test/integration/client/error-handling-tests.js @@ -33,7 +33,7 @@ suite.test('sending non-array argument as values causes an error callback', (don suite.test('re-using connections results in error callback', (done) => { const client = new Client() client.connect(() => { - client.connect(err => { + client.connect((err) => { assert(err instanceof Error) client.end(done) }) @@ -43,7 +43,7 @@ suite.test('re-using connections results in error callback', (done) => { suite.test('re-using connections results in promise rejection', (done) => { const client = new Client() client.connect().then(() => { - client.connect().catch(err => { + client.connect().catch((err) => { assert(err instanceof Error) client.end().then(done) }) @@ -53,33 +53,43 @@ suite.test('re-using connections results in promise rejection', (done) => { suite.test('using a client after closing it results in error', (done) => { const client = new Client() client.connect(() => { - client.end(assert.calls(() => { - client.query('SELECT 1', assert.calls((err) => { - assert.equal(err.message, 'Client was closed and is not queryable') - done() - })) - })) + client.end( + assert.calls(() => { + client.query( + 'SELECT 1', + assert.calls((err) => { + assert.equal(err.message, 'Client was closed and is not queryable') + 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) - queryError = err - })) - setTimeout(() => client.end(), 50) - client.once('end', () => { - assert(queryError instanceof Error) - done() + 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) + queryError = err + }) + ) + setTimeout(() => client.end(), 50) + client.once('end', () => { + assert(queryError instanceof Error) + done() + }) }) - })) + ) }) var ensureFuture = function (testClient, done) { @@ -95,11 +105,13 @@ suite.test('when query is parsing', (done) => { 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) @@ -111,10 +123,12 @@ suite.test('when a query is binding', function (done) { 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'] - })) + 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') @@ -124,12 +138,14 @@ suite.test('when a query is binding', function (done) { suite.test('non-query error with callback', function (done) { var client = new Client({ - user: 'asldkfjsadlfkj' + user: 'asldkfjsadlfkj', }) - client.connect(assert.calls(function (error, client) { - assert(error instanceof Error) - done() - })) + client.connect( + assert.calls(function (error, client) { + assert(error instanceof Error) + done() + }) + ) }) suite.test('non-error calls supplied callback', function (done) { @@ -138,18 +154,20 @@ suite.test('non-error calls supplied callback', function (done) { password: helper.args.password, host: helper.args.host, port: helper.args.port, - database: helper.args.database + 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' + user: 'very invalid username', }) client.on('error', () => { assert.fail('unexpected error event when connecting') @@ -162,7 +180,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({ - user: 'very invalid username' + user: 'very invalid username', }) client.on('error', () => { assert.fail('unexpected error event when connecting') @@ -172,13 +190,12 @@ suite.test('when connecting to invalid host with promise', 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() }) - client.connect() - .catch(e => { - assert(e instanceof Error) - done() - }) }) suite.test('within a simple query', (done) => { @@ -199,7 +216,7 @@ suite.test('connected, idle client error', (done) => { throw new Error('Should not receive error callback after connection') } setImmediate(() => { - (client.connection || client.native).emit('error', new Error('expected')) + ;(client.connection || client.native).emit('error', new Error('expected')) }) }) client.on('error', (err) => { @@ -211,9 +228,9 @@ suite.test('connected, idle client error', (done) => { suite.test('cannot pass non-string values to query as text', (done) => { const client = new Client() client.connect() - client.query({ text: { } }, (err) => { + client.query({ text: {} }, (err) => { assert(err) - client.query({ }, (err) => { + client.query({}, (err) => { client.on('drain', () => { client.end(done) }) diff --git a/packages/pg/test/integration/client/huge-numeric-tests.js b/packages/pg/test/integration/client/huge-numeric-tests.js index 111adf20..bdbfac26 100644 --- a/packages/pg/test/integration/client/huge-numeric-tests.js +++ b/packages/pg/test/integration/client/huge-numeric-tests.js @@ -2,21 +2,26 @@ 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' + }) + 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() + pool.end() + }) + ) }) - 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) { - assert.equal(result.rows[0].id, 'yes') - done() - pool.end() - })) -})) +) diff --git a/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js index 18162f54..f970faaf 100644 --- a/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js +++ b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js @@ -6,38 +6,54 @@ var suite = new helper.Suite() var conInfo = helper.config -function getConInfo (override) { - return Object.assign({}, conInfo, override ) +function getConInfo(override) { + return Object.assign({}, conInfo, override) } function testClientVersion(cb) { var client = new Client({}) - client.connect(assert.success(function () { - helper.versionGTE(client, 100000, assert.success(function(isGreater) { - return client.end(assert.success(function () { - if (!isGreater) { - console.log('skip idle_in_transaction_session_timeout at client-level is only available in v10 and above'); - return; - } - cb(); - })) - })) - })) + client.connect( + assert.success(function () { + helper.versionGTE( + client, + 100000, + assert.success(function (isGreater) { + return client.end( + assert.success(function () { + if (!isGreater) { + console.log( + 'skip idle_in_transaction_session_timeout at client-level is only available in v10 and above' + ) + return + } + cb() + }) + ) + }) + ) + }) + ) } -function getIdleTransactionSessionTimeout (conf, cb) { +function getIdleTransactionSessionTimeout(conf, cb) { var client = new Client(conf) - client.connect(assert.success(function () { - client.query('SHOW idle_in_transaction_session_timeout', assert.success(function (res) { - var timeout = res.rows[0].idle_in_transaction_session_timeout - cb(timeout) - client.end() - })) - })) + client.connect( + assert.success(function () { + client.query( + 'SHOW idle_in_transaction_session_timeout', + assert.success(function (res) { + var timeout = res.rows[0].idle_in_transaction_session_timeout + cb(timeout) + client.end() + }) + ) + }) + ) } -if (!helper.args.native) { // idle_in_transaction_session_timeout is not supported with the native client - testClientVersion(function(){ +if (!helper.args.native) { + // idle_in_transaction_session_timeout is not supported with the native client + testClientVersion(function () { suite.test('No default idle_in_transaction_session_timeout ', function (done) { getConInfo() getIdleTransactionSessionTimeout({}, function (res) { @@ -48,7 +64,7 @@ if (!helper.args.native) { // idle_in_transaction_session_timeout is not support suite.test('idle_in_transaction_session_timeout integer is used', function (done) { var conf = getConInfo({ - 'idle_in_transaction_session_timeout': 3000 + idle_in_transaction_session_timeout: 3000, }) getIdleTransactionSessionTimeout(conf, function (res) { assert.strictEqual(res, '3s') @@ -58,7 +74,7 @@ if (!helper.args.native) { // idle_in_transaction_session_timeout is not support suite.test('idle_in_transaction_session_timeout float is used', function (done) { var conf = getConInfo({ - 'idle_in_transaction_session_timeout': 3000.7 + idle_in_transaction_session_timeout: 3000.7, }) getIdleTransactionSessionTimeout(conf, function (res) { assert.strictEqual(res, '3s') @@ -68,7 +84,7 @@ if (!helper.args.native) { // idle_in_transaction_session_timeout is not support suite.test('idle_in_transaction_session_timeout string is used', function (done) { var conf = getConInfo({ - 'idle_in_transaction_session_timeout': '3000' + idle_in_transaction_session_timeout: '3000', }) getIdleTransactionSessionTimeout(conf, function (res) { assert.strictEqual(res, '3s') diff --git a/packages/pg/test/integration/client/json-type-parsing-tests.js b/packages/pg/test/integration/client/json-type-parsing-tests.js index 58cbc3f3..ba769602 100644 --- a/packages/pg/test/integration/client/json-type-parsing-tests.js +++ b/packages/pg/test/integration/client/json-type-parsing-tests.js @@ -3,26 +3,35 @@ 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, 90200, assert.success(function (jsonSupported) { - if (!jsonSupported) { - 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('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() - pool.end() - })) - })) -})) +pool.connect( + assert.success(function (client, done) { + helper.versionGTE( + client, + 90200, + assert.success(function (jsonSupported) { + if (!jsonSupported) { + 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( + '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() + pool.end() + }) + ) + }) + ) + }) +) diff --git a/packages/pg/test/integration/client/multiple-results-tests.js b/packages/pg/test/integration/client/multiple-results-tests.js index 01dd9eae..addca9b6 100644 --- a/packages/pg/test/integration/client/multiple-results-tests.js +++ b/packages/pg/test/integration/client/multiple-results-tests.js @@ -6,64 +6,73 @@ 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() +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)) + 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[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' }]) + assert.equal(results[1].fields[0].name, 'baz') + assert.deepEqual(results[1].rows, [{ baz: 'bar' }]) - return client.end() -})) + return client.end() + }) +) -suite.test('multiple selects work', co.wrap(function * () { - const client = new helper.Client() - yield client.connect() +suite.test( + 'multiple selects work', + co.wrap(function* () { + const client = new helper.Client() + yield client.connect() - const text = ` + 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)) + 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[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[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[2].fields[0].name, 'baz') + assert.deepEqual(results[2].rows, [{ baz: 20 }, { baz: 21 }, { baz: 22 }]) - assert.equal(results.length, 3) + assert.equal(results.length, 3) - return client.end() -})) + return client.end() + }) +) -suite.test('mixed queries and statements', co.wrap(function * () { - const client = new helper.Client() - yield client.connect() +suite.test( + 'mixed queries and statements', + co.wrap(function* () { + const client = new helper.Client() + yield client.connect() - const text = ` + 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') + 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() -})) + return client.end() + }) +) diff --git a/packages/pg/test/integration/client/network-partition-tests.js b/packages/pg/test/integration/client/network-partition-tests.js index 8eaf5d0d..99339640 100644 --- a/packages/pg/test/integration/client/network-partition-tests.js +++ b/packages/pg/test/integration/client/network-partition-tests.js @@ -16,29 +16,34 @@ Server.prototype.start = function (cb) { // it responds with our specified response immediatley after receiving every buffer // this is sufficient into convincing the client its connectet to a valid backend // if we respond with a readyForQuery message - this.server = net.createServer(function (socket) { - this.socket = socket - if (this.response) { - this.socket.on('data', function (data) { - // deny request for SSL - if (data.length == 8) { - this.socket.write(Buffer.from('N', 'utf8')) - // consider all authentication requests as good - } else if (!data[0]) { - this.socket.write(buffers.authenticationOk()) - // respond with our canned response - } else { - this.socket.write(this.response) - } - }.bind(this)) - } - }.bind(this)) + this.server = net.createServer( + function (socket) { + this.socket = socket + if (this.response) { + this.socket.on( + 'data', + function (data) { + // deny request for SSL + if (data.length == 8) { + this.socket.write(Buffer.from('N', 'utf8')) + // consider all authentication requests as good + } else if (!data[0]) { + this.socket.write(buffers.authenticationOk()) + // respond with our canned response + } else { + this.socket.write(this.response) + } + }.bind(this) + ) + } + }.bind(this) + ) var port = 54321 var options = { host: 'localhost', - port: port + port: port, } this.server.listen(options.port, options.host, function () { cb(options) @@ -58,12 +63,11 @@ var testServer = function (server, cb) { server.start(function (options) { // connect a client to it var client = new helper.Client(options) - client.connect() - .catch((err) => { - assert(err instanceof Error) - clearTimeout(timeoutId) - server.close(cb) - }) + client.connect().catch((err) => { + assert(err instanceof Error) + clearTimeout(timeoutId) + server.close(cb) + }) server.server.on('connection', () => { // after 50 milliseconds, drop the client diff --git a/packages/pg/test/integration/client/no-data-tests.js b/packages/pg/test/integration/client/no-data-tests.js index 46ea4566..ad0f22be 100644 --- a/packages/pg/test/integration/client/no-data-tests.js +++ b/packages/pg/test/integration/client/no-data-tests.js @@ -7,33 +7,39 @@ suite.test('noData message handling', function () { var q = client.query({ name: 'boom', - text: 'create temp table boom(id serial, size integer)' + 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 + client.query( + { + name: 'insert', + text: 'insert into boom(size) values($1)', + values: [100], + }, + function (err, result) { + if (err) { + console.log(err) + throw err + } } - }) + ) client.query({ name: 'insert', - values: [101] + values: [101], }) - var query = client.query({ - name: 'fetch', - text: 'select size from boom where size < $1', - values: [101] - }, (err, res) => { - var row = res.rows[0] - assert.strictEqual(row.size, 100) - }) + var query = client.query( + { + name: 'fetch', + text: 'select size from boom where size < $1', + values: [101], + }, + (err, res) => { + var row = res.rows[0] + assert.strictEqual(row.size, 100) + } + ) client.on('drain', client.end.bind(client)) }) diff --git a/packages/pg/test/integration/client/no-row-result-tests.js b/packages/pg/test/integration/client/no-row-result-tests.js index e52d113d..6e8f52cf 100644 --- a/packages/pg/test/integration/client/no-row-result-tests.js +++ b/packages/pg/test/integration/client/no-row-result-tests.js @@ -15,11 +15,13 @@ suite.test('can access results when no rows are returned', function (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) - }) + var query = client.query( + q, + assert.success(function (result) { + checkResult(result) + release() + pool.end(done) + }) ) assert.emits(query, 'end', checkResult) diff --git a/packages/pg/test/integration/client/notice-tests.js b/packages/pg/test/integration/client/notice-tests.js index a6fc8a56..b5d4f3d5 100644 --- a/packages/pg/test/integration/client/notice-tests.js +++ b/packages/pg/test/integration/client/notice-tests.js @@ -5,31 +5,40 @@ const suite = new helper.Suite() suite.test('emits notify message', function (done) { const client = helper.client() - client.query('LISTEN boom', assert.calls(function () { - const otherClient = helper.client() - let 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 () { - 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) - }) + client.query( + 'LISTEN boom', + assert.calls(function () { + const otherClient = helper.client() + let 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 () { + 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) + }) - client.query("NOTIFY boom, 'omg!'", function (err, q) { - if (err) { - // notify not supported with payload on 8.x - client.query('NOTIFY boom') - } - }) - })) - })) + client.query("NOTIFY boom, 'omg!'", function (err, q) { + if (err) { + // notify not supported with payload on 8.x + client.query('NOTIFY boom') + } + }) + }) + ) + }) + ) }) // this test fails on travis due to their config diff --git a/packages/pg/test/integration/client/parse-int-8-tests.js b/packages/pg/test/integration/client/parse-int-8-tests.js index 19368904..9f251de6 100644 --- a/packages/pg/test/integration/client/parse-int-8-tests.js +++ b/packages/pg/test/integration/client/parse-int-8-tests.js @@ -7,23 +7,31 @@ 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() - })) - })) - })) + 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/packages/pg/test/integration/client/prepared-statement-tests.js b/packages/pg/test/integration/client/prepared-statement-tests.js index 76654eaa..48d12f89 100644 --- a/packages/pg/test/integration/client/prepared-statement-tests.js +++ b/packages/pg/test/integration/client/prepared-statement-tests.js @@ -12,11 +12,13 @@ var suite = new helper.Suite() var parseCount = 0 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 - })) + 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') @@ -26,11 +28,13 @@ var suite = new helper.Suite() }) 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%'] - })) + 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') @@ -40,10 +44,12 @@ var suite = new helper.Suite() }) suite.test('with same name, but without query text', function (done) { - var q = client.query(new Query({ - name: queryName, - values: [30, '%n%'] - })) + var q = client.query( + new Query({ + name: queryName, + values: [30, '%n%'], + }) + ) assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Aaron') @@ -58,17 +64,22 @@ var suite = new helper.Suite() }) suite.test('with same name, but with different text', function (done) { - client.query(new Query({ - text: 'select name from person where age >= $1 and name LIKE $2', - name: queryName, - values: [30, '%n%'] - }), assert.calls(err => { - assert.equal(err.message, `Prepared statements must be unique - '${queryName}' was used for a different statement`) - done() - })) + client.query( + new Query({ + text: 'select name from person where age >= $1 and name LIKE $2', + name: queryName, + values: [30, '%n%'], + }), + assert.calls((err) => { + assert.equal( + err.message, + `Prepared statements must be unique - '${queryName}' was used for a different statement` + ) + done() + }) + ) }) })() - ;(function () { var statementName = 'differ' var statement1 = 'select count(*)::int4 as count from person' @@ -78,22 +89,27 @@ var suite = new helper.Suite() 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) - done() - }) + var query = client1.query( + { + name: statementName, + text: statement1, + }, + (err, res) => { + assert(!err) + assert.equal(res.rows[0].count, 26) + done() + } + ) }) suite.test('client 2 execution', function (done) { - var query = client2.query(new Query({ - name: statementName, - text: statement2, - values: [11] - })) + var query = client2.query( + new Query({ + name: statementName, + text: statement2, + values: [11], + }) + ) assert.emits(query, 'row', function (row) { assert.equal(row.count, 1) @@ -108,7 +124,6 @@ var suite = new helper.Suite() return client1.end().then(() => client2.end()) }) })() - ;(function () { var client = helper.client() client.query('CREATE TEMP TABLE zoom(name varchar(100));') @@ -131,21 +146,31 @@ var suite = new helper.Suite() } 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 COLLATE "C"', - rows: 1 - }, done)) + var query = client.query( + new Query( + { + name: 'get names', + text: 'SELECT name FROM zoom ORDER BY name COLLATE "C"', + rows: 1, + }, + done + ) + ) checkForResults(query) }) 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 COLLATE "C"', - rows: 1000 - }, done)) + var query = client.query( + new Query( + { + name: 'get names', + text: 'SELECT name FROM zoom ORDER BY name COLLATE "C"', + rows: 1000, + }, + done + ) + ) checkForResults(query) }) diff --git a/packages/pg/test/integration/client/promise-api-tests.js b/packages/pg/test/integration/client/promise-api-tests.js index 80337c4a..1d6e504f 100644 --- a/packages/pg/test/integration/client/promise-api-tests.js +++ b/packages/pg/test/integration/client/promise-api-tests.js @@ -7,43 +7,37 @@ const suite = new helper.Suite() suite.test('valid connection completes promise', () => { const client = new pg.Client() - return client.connect() - .then(() => { - return client.end() - .then(() => { }) - }) + 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(() => { }) - }) + 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() - }) + return client.connect().catch((e) => { + assert(e instanceof Error) + 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) - client.end() - done() - }) - // manually kill the connection - client.emit('error', new Error('something bad happened...but not really')) - }, 50) - }) + return client.connect().then(() => { + setTimeout(() => { + client.on('error', (e) => { + assert(e instanceof Error) + client.end() + done() + }) + // manually kill the connection + client.emit('error', new Error('something bad happened...but not really')) + }, 50) + }) }) diff --git a/packages/pg/test/integration/client/query-as-promise-tests.js b/packages/pg/test/integration/client/query-as-promise-tests.js index 803b8909..46365c6c 100644 --- a/packages/pg/test/integration/client/query-as-promise-tests.js +++ b/packages/pg/test/integration/client/query-as-promise-tests.js @@ -13,22 +13,21 @@ const suite = new helper.Suite() suite.test('promise API', (cb) => { const pool = new pg.Pool() pool.connect().then((client) => { - client.query('SELECT $1::text as name', ['foo']) + 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) - }) + 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) }) + }) }) }) }) @@ -52,4 +51,4 @@ suite.test('promise API with configurable promise type', (cb) => { throw error }) }) -}); +}) diff --git a/packages/pg/test/integration/client/query-column-names-tests.js b/packages/pg/test/integration/client/query-column-names-tests.js index cc5a42b5..6b32881e 100644 --- a/packages/pg/test/integration/client/query-column-names-tests.js +++ b/packages/pg/test/integration/client/query-column-names-tests.js @@ -4,12 +4,17 @@ 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('SELECT * FROM t', assert.success(function (res) { - done() - assert.strictEqual(res.fields[0].name, "complex''column") - pool.end() - })) - })) + 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") + pool.end() + }) + ) + }) + ) }) diff --git a/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js b/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js index 9ba7567e..adef58d1 100644 --- a/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -7,57 +7,79 @@ 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)' + client.connect( + assert.success(function () { + var sleepQuery = 'select pg_sleep($1)' - var queryConfig = { - name: 'sleep query', - text: sleepQuery, - values: [5] - } + 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') - done() - })) + var queryInstance = new Query( + queryConfig, + assert.calls(function (err, result) { + 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') + 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() }) - - 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() - })) + ) }) -function killIdleQuery (targetQuery, cb) { +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, 90200, 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') - })) - })) - })) + client2.connect( + assert.success(function () { + helper.versionGTE( + client2, + 90200, + 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') + }) + ) + }) + ) + }) + ) } suite.test('query killed during query execution of prepared statement', function (done) { @@ -65,34 +87,39 @@ suite.test('query killed during query execution of prepared statement', function return done() } var client = new Client(helper.args) - client.connect(assert.success(function () { - var sleepQuery = 'select pg_sleep($1)' + client.connect( + assert.success(function () { + var sleepQuery = 'select pg_sleep($1)' - const queryConfig = { - name: 'sleep query', - text: sleepQuery, - values: [5] - } + const queryConfig = { + name: 'sleep query', + text: sleepQuery, + values: [5], + } - // client should emit an error because it is unexpectedly disconnected - assert.emits(client, 'error') + // 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('end', function (err) { + assert.fail('Prepared statement when executed should not return before being killed') + }) + + killIdleQuery(sleepQuery, done) }) - - 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') - }) - - killIdleQuery(sleepQuery, done) - })) + ) }) diff --git a/packages/pg/test/integration/client/query-error-handling-tests.js b/packages/pg/test/integration/client/query-error-handling-tests.js index 67ac5d69..34eab8f6 100644 --- a/packages/pg/test/integration/client/query-error-handling-tests.js +++ b/packages/pg/test/integration/client/query-error-handling-tests.js @@ -1,88 +1,115 @@ -"use strict"; -var helper = require('./test-helper'); -var util = require('util'); -var Query = helper.pg.Query; +'use strict' +var helper = require('./test-helper') +var util = require('util') +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(10)' - var sleepQuery = new Query(queryText); - var pidColName = 'procpid' - var queryColName = 'current_query'; - helper.versionGTE(client, 90200, assert.success(function(isGreater) { - if(isGreater) { - pidColName = 'pid'; - queryColName = 'query'; - } - var query1 = client.query(sleepQuery, assert.calls(function(err, result) { - assert(err); - client.end(); - })); - //ensure query1 does not emit an 'end' event - //because it was killed and received an error - //https://github.com/brianc/node-postgres/issues/547 - query1.on('end', function() { - assert.fail('Query with an error should not emit "end" event') - }) - setTimeout(function() { - var client2 = new Client(helper.args); - client2.connect(assert.success(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(res.rows.length > 0); - client2.end(); - assert.emits(client2, 'end'); - })); - })); - }, 300) - })); - })); -}); +test('error during query execution', function () { + var client = new Client(helper.args) + client.connect( + assert.success(function () { + var queryText = 'select pg_sleep(10)' + var sleepQuery = new Query(queryText) + var pidColName = 'procpid' + var queryColName = 'current_query' + helper.versionGTE( + client, + 90200, + assert.success(function (isGreater) { + if (isGreater) { + pidColName = 'pid' + queryColName = 'query' + } + var query1 = client.query( + sleepQuery, + assert.calls(function (err, result) { + assert(err) + client.end() + }) + ) + //ensure query1 does not emit an 'end' event + //because it was killed and received an error + //https://github.com/brianc/node-postgres/issues/547 + query1.on('end', function () { + assert.fail('Query with an error should not emit "end" event') + }) + setTimeout(function () { + var client2 = new Client(helper.args) + client2.connect( + assert.success(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(res.rows.length > 0) + client2.end() + assert.emits(client2, 'end') + }) + ) + }) + ) + }, 300) + }) + ) + }) + ) +}) if (helper.config.native) { return } -test('9.3 column error fields', function() { - var client = new Client(helper.args); - client.connect(assert.success(function() { - helper.versionGTE(client, 90300, assert.success(function(isGreater) { - if(!isGreater) { - return client.end(); - } +test('9.3 column error fields', function () { + var client = new Client(helper.args) + client.connect( + assert.success(function () { + helper.versionGTE( + client, + 90300, + assert.success(function (isGreater) { + if (!isGreater) { + return client.end() + } - 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.table, 'column_err_test'); - assert.equal(err.column, 'a'); - return client.end(); - }); - })); - })); -}); + 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.table, 'column_err_test') + assert.equal(err.column, 'a') + return client.end() + }) + }) + ) + }) + ) +}) -test('9.3 constraint error fields', function() { - var client = new Client(helper.args); - client.connect(assert.success(function() { - helper.versionGTE(client, 90300, assert.success(function(isGreater) { - if(!isGreater) { - console.log('skip 9.3 error field on older versions of postgres'); - return client.end(); - } +test('9.3 constraint error fields', function () { + var client = new Client(helper.args) + client.connect( + assert.success(function () { + helper.versionGTE( + client, + 90300, + assert.success(function (isGreater) { + if (!isGreater) { + console.log('skip 9.3 error field on older versions of postgres') + return client.end() + } - 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.table, 'constraint_err_test'); - assert.equal(err.constraint, 'constraint_err_test_pkey'); - return client.end(); - }); - })); - })); -}); + 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.table, 'constraint_err_test') + assert.equal(err.constraint, 'constraint_err_test_pkey') + return client.end() + }) + }) + ) + }) + ) +}) diff --git a/packages/pg/test/integration/client/result-metadata-tests.js b/packages/pg/test/integration/client/result-metadata-tests.js index 074a1598..66d9ac4a 100644 --- a/packages/pg/test/integration/client/result-metadata-tests.js +++ b/packages/pg/test/integration/client/result-metadata-tests.js @@ -4,29 +4,44 @@ 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) + pool.connect( + assert.calls(function (err, client, done) { + assert(!err) - helper.versionGTE(client, 90000, 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, + 90000, + 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/packages/pg/test/integration/client/results-as-array-tests.js b/packages/pg/test/integration/client/results-as-array-tests.js index b6b00ef7..5ebb2a9d 100644 --- a/packages/pg/test/integration/client/results-as-array-tests.js +++ b/packages/pg/test/integration/client/results-as-array-tests.js @@ -16,16 +16,21 @@ test('returns results as array', function () { assert.strictEqual(row[2], 'hai') assert.strictEqual(row[3], null) } - 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() - })) - })) + 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() + }) + ) + }) + ) }) diff --git a/packages/pg/test/integration/client/row-description-on-results-tests.js b/packages/pg/test/integration/client/row-description-on-results-tests.js index 108e5197..688b96e6 100644 --- a/packages/pg/test/integration/client/row-description-on-results-tests.js +++ b/packages/pg/test/integration/client/row-description-on-results-tests.js @@ -19,20 +19,32 @@ var checkResult = function (result) { 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() - })) - })) + 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() - })) - })) + 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/packages/pg/test/integration/client/simple-query-tests.js b/packages/pg/test/integration/client/simple-query-tests.js index 0c4575c5..d22d7474 100644 --- a/packages/pg/test/integration/client/simple-query-tests.js +++ b/packages/pg/test/integration/client/simple-query-tests.js @@ -22,7 +22,11 @@ test('simple query interface', function () { 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.' + ) } }) }) @@ -65,7 +69,7 @@ test('prepared statements do not mutate params', function () { 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({ 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) { @@ -79,9 +83,11 @@ test('multiple simple queries', function () { 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'})) + 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) { diff --git a/packages/pg/test/integration/client/ssl-tests.js b/packages/pg/test/integration/client/ssl-tests.js index bd864d1e..1d3c5015 100644 --- a/packages/pg/test/integration/client/ssl-tests.js +++ b/packages/pg/test/integration/client/ssl-tests.js @@ -4,12 +4,18 @@ var config = require(__dirname + '/test-helper').config test('can connect with ssl', function () { return false config.ssl = { - rejectUnauthorized: false + 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/packages/pg/test/integration/client/statement_timeout-tests.js b/packages/pg/test/integration/client/statement_timeout-tests.js index 393e82a1..e0898cce 100644 --- a/packages/pg/test/integration/client/statement_timeout-tests.js +++ b/packages/pg/test/integration/client/statement_timeout-tests.js @@ -6,22 +6,28 @@ var suite = new helper.Suite() var conInfo = helper.config -function getConInfo (override) { - return Object.assign({}, conInfo, override ) +function getConInfo(override) { + return Object.assign({}, conInfo, override) } -function getStatementTimeout (conf, cb) { +function getStatementTimeout(conf, cb) { var client = new Client(conf) - client.connect(assert.success(function () { - client.query('SHOW statement_timeout', assert.success(function (res) { - var statementTimeout = res.rows[0].statement_timeout - cb(statementTimeout) - client.end() - })) - })) + client.connect( + assert.success(function () { + client.query( + 'SHOW statement_timeout', + assert.success(function (res) { + var statementTimeout = res.rows[0].statement_timeout + cb(statementTimeout) + client.end() + }) + ) + }) + ) } -if (!helper.args.native) { // statement_timeout is not supported with the native client +if (!helper.args.native) { + // statement_timeout is not supported with the native client suite.test('No default statement_timeout ', function (done) { getConInfo() getStatementTimeout({}, function (res) { @@ -32,7 +38,7 @@ if (!helper.args.native) { // statement_timeout is not supported with the native suite.test('statement_timeout integer is used', function (done) { var conf = getConInfo({ - 'statement_timeout': 3000 + statement_timeout: 3000, }) getStatementTimeout(conf, function (res) { assert.strictEqual(res, '3s') @@ -42,7 +48,7 @@ if (!helper.args.native) { // statement_timeout is not supported with the native suite.test('statement_timeout float is used', function (done) { var conf = getConInfo({ - 'statement_timeout': 3000.7 + statement_timeout: 3000.7, }) getStatementTimeout(conf, function (res) { assert.strictEqual(res, '3s') @@ -52,7 +58,7 @@ if (!helper.args.native) { // statement_timeout is not supported with the native suite.test('statement_timeout string is used', function (done) { var conf = getConInfo({ - 'statement_timeout': '3000' + statement_timeout: '3000', }) getStatementTimeout(conf, function (res) { assert.strictEqual(res, '3s') @@ -62,16 +68,17 @@ if (!helper.args.native) { // statement_timeout is not supported with the native suite.test('statement_timeout actually cancels long running queries', function (done) { var conf = getConInfo({ - 'statement_timeout': '10' // 10ms to keep tests running fast + statement_timeout: '10', // 10ms to keep tests running fast }) var client = new Client(conf) - client.connect(assert.success(function () { - client.query('SELECT pg_sleep( 1 )', function ( error ) { - client.end() - assert.strictEqual( error.code, '57014' ) // query_cancelled - done() + client.connect( + assert.success(function () { + client.query('SELECT pg_sleep( 1 )', function (error) { + client.end() + assert.strictEqual(error.code, '57014') // query_cancelled + done() + }) }) - })) + ) }) - } diff --git a/packages/pg/test/integration/client/transaction-tests.js b/packages/pg/test/integration/client/transaction-tests.js index 560067ba..18f8ff09 100644 --- a/packages/pg/test/integration/client/transaction-tests.js +++ b/packages/pg/test/integration/client/transaction-tests.js @@ -4,73 +4,96 @@ const suite = new helper.Suite() const pg = helper.pg const client = new pg.Client() -client.connect(assert.success(function () { - client.query('begin') +client.connect( + assert.success(function () { + 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(!err) - assert.empty(result.rows) - 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) + done() + }) + ) + }) + + suite.test('can insert name', (done) => { + 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') + done() + }) + ) + }) + + suite.test('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) + client.end(done) + }) + ) + }) }) - - suite.test('can insert name', (done) => { - 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') - done() - })) - }) - - suite.test('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) - client.end(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.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.equal(result.rows.length, 1) - })) - client.query('COMMIT', function () { - done() - pool.end(cb) + 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.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.equal(result.rows.length, 1) + }) + ) + client.query('COMMIT', function () { + done() + pool.end(cb) + }) }) - })) + ) }) diff --git a/packages/pg/test/integration/client/type-coercion-tests.js b/packages/pg/test/integration/client/type-coercion-tests.js index d0d740e4..96f57b08 100644 --- a/packages/pg/test/integration/client/type-coercion-tests.js +++ b/packages/pg/test/integration/client/type-coercion-tests.js @@ -9,102 +9,130 @@ var testForTypeCoercion = function (type) { 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) + 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) - })) + type.values.forEach(function (val) { + var insertQuery = client.query( + 'insert into test_type(col) VALUES($1)', + [val], + assert.calls(function (err, result) { + assert(!err) + }) + ) - var query = client.query(new pg.Query({ - name: 'get type ' + type.name, - text: 'select col from test_type' - })) + 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 + query.on('error', function (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 + ) + + client.query('delete from test_type') }) - 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) - - client.query('delete from test_type') + client.query('drop table test_type', function () { + done() + pool.end(cb) + }) }) - - 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', - '-9007199254740992', - '0', - '9007199254740992', - '72057594037928030', - '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', - '0', - '12.34', - '-3141592653589793238462643383279502.1618033988749894848204586834365638', - '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] -}, { - name: 'time', - values: ['13:12:12.321', null] -}] +var types = [ + { + name: 'integer', + values: [-2147483648, -1, 0, 1, 2147483647, null], + }, + { + name: 'smallint', + values: [-32768, -1, 0, 1, 32767, null], + }, + { + name: 'bigint', + values: [ + '-9223372036854775808', + '-9007199254740992', + '0', + '9007199254740992', + '72057594037928030', + '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', + '0', + '12.34', + '-3141592653589793238462643383279502.1618033988749894848204586834365638', + '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], + }, + { + 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 }) }) } @@ -121,13 +149,15 @@ suite.test('timestampz round trip', function (cb) { client.query({ text: 'insert into date_tests(name, tstz)VALUES($1, $2)', name: 'add date', - values: ['now', now] + values: ['now', now], }) - var result = client.query(new pg.Query({ - name: 'get date', - text: 'select * from date_tests where name = $1', - values: ['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 @@ -145,21 +175,26 @@ suite.test('timestampz round trip', function (cb) { }) }) -suite.test('selecting nulls', cb => { +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(!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() - pool.end(cb) + pool.connect( + assert.calls(function (err, client, done) { + assert.ifError(err) + client.query( + 'select null as res;', + assert.calls(function (err, res) { + 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() + pool.end(cb) + }) }) - })) + ) }) suite.test('date range extremes', function (done) { @@ -169,25 +204,40 @@ suite.test('date range extremes', function (done) { // 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( + '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(), -4712) - })) + 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(), -4712) + }) + ) - 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) + client.on('drain', () => { + client.end(done) + }) }) - })) + ) }) diff --git a/packages/pg/test/integration/client/type-parser-override-tests.js b/packages/pg/test/integration/client/type-parser-override-tests.js index e806a390..42c3dafb 100644 --- a/packages/pg/test/integration/client/type-parser-override-tests.js +++ b/packages/pg/test/integration/client/type-parser-override-tests.js @@ -1,37 +1,44 @@ 'use strict' var helper = require('./test-helper') -function testTypeParser (client, 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() - })) + 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(client1, 'first client', () => { + done1() + testTypeParser(client2, 'second client', () => done2(), pool.end()) + }) + }) + ) + }) +) diff --git a/packages/pg/test/integration/connection-pool/error-tests.js b/packages/pg/test/integration/connection-pool/error-tests.js index 9fe76043..f3f9cdca 100644 --- a/packages/pg/test/integration/connection-pool/error-tests.js +++ b/packages/pg/test/integration/connection-pool/error-tests.js @@ -6,99 +6,135 @@ const native = helper.args.native const suite = new helper.Suite() suite.test('connecting to invalid port', (cb) => { const pool = new pg.Pool({ port: 13801 }) - pool.connect().catch(e => cb()) + pool.connect().catch((e) => cb()) }) suite.test('errors emitted on checked-out clients', (cb) => { // make pool hold 2 clients const pool = new pg.Pool({ max: 2 }) // get first client - pool.connect(assert.success(function (client, done) { - client.query('SELECT NOW()', function () { - pool.connect(assert.success(function (client2, done2) { - var pidColName = 'procpid' - helper.versionGTE(client2, 90200, 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%'] - } + pool.connect( + assert.success(function (client, done) { + client.query('SELECT NOW()', function () { + pool.connect( + assert.success(function (client2, done2) { + var pidColName = 'procpid' + helper.versionGTE( + client2, + 90200, + 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%'] + } - client.once('error', (err) => { - client.on('error', (err) => {}) - done(err) - cb() + client.once('error', (err) => { + client.on('error', (err) => {}) + done(err) + 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() + }) + ) + }) + ) }) - - // 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() - })) - })) - })) + ) + }) }) - })) + ) }) suite.test('connection-level errors cause queued queries to fail', (cb) => { const pool = new pg.Pool() - pool.connect(assert.success((client, done) => { - client.query('SELECT pg_terminate_backend(pg_backend_pid())', assert.calls((err) => { - if (helper.args.native) { - assert.ok(err) - } else { - assert.equal(err.code, '57P01') - } - })) + pool.connect( + assert.success((client, done) => { + client.query( + 'SELECT pg_terminate_backend(pg_backend_pid())', + assert.calls((err) => { + if (helper.args.native) { + assert.ok(err) + } else { + assert.equal(err.code, '57P01') + } + }) + ) - client.once('error', assert.calls((err) => { - client.on('error', (err) => {}) - })) + client.once( + 'error', + assert.calls((err) => { + client.on('error', (err) => {}) + }) + ) - client.query('SELECT 1', assert.calls((err) => { - if (helper.args.native) { - assert.equal(err.message, 'terminating connection due to administrator command') - } else { - assert.equal(err.message, 'Connection terminated unexpectedly') - } + client.query( + 'SELECT 1', + assert.calls((err) => { + if (helper.args.native) { + assert.equal(err.message, 'terminating connection due to administrator command') + } else { + assert.equal(err.message, 'Connection terminated unexpectedly') + } - done(err) - pool.end() - cb() - })) - })) + done(err) + pool.end() + cb() + }) + ) + }) + ) }) suite.test('connection-level errors cause future queries to fail', (cb) => { const pool = new pg.Pool() - pool.connect(assert.success((client, done) => { - client.query('SELECT pg_terminate_backend(pg_backend_pid())', assert.calls((err) => { - if (helper.args.native) { - assert.ok(err) - } else { - assert.equal(err.code, '57P01') - } - })) + pool.connect( + assert.success((client, done) => { + client.query( + 'SELECT pg_terminate_backend(pg_backend_pid())', + assert.calls((err) => { + if (helper.args.native) { + assert.ok(err) + } else { + assert.equal(err.code, '57P01') + } + }) + ) - client.once('error', assert.calls((err) => { - client.on('error', (err) => {}) - client.query('SELECT 1', assert.calls((err) => { - if (helper.args.native) { - assert.equal(err.message, 'terminating connection due to administrator command') - } else { - assert.equal(err.message, 'Client has encountered a connection error and is not queryable') - } + client.once( + 'error', + assert.calls((err) => { + client.on('error', (err) => {}) + client.query( + 'SELECT 1', + assert.calls((err) => { + if (helper.args.native) { + assert.equal(err.message, 'terminating connection due to administrator command') + } else { + assert.equal(err.message, 'Client has encountered a connection error and is not queryable') + } - done(err) - pool.end() - cb() - })) - })) - })) + done(err) + pool.end() + cb() + }) + ) + }) + ) + }) + ) }) suite.test('handles socket error during pool.query and destroys it immediately', (cb) => { diff --git a/packages/pg/test/integration/connection-pool/idle-timeout-tests.js b/packages/pg/test/integration/connection-pool/idle-timeout-tests.js index c48f712e..f36b6938 100644 --- a/packages/pg/test/integration/connection-pool/idle-timeout-tests.js +++ b/packages/pg/test/integration/connection-pool/idle-timeout-tests.js @@ -4,9 +4,11 @@ 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() - })) + pool.connect( + assert.calls(function (err, client, done) { + assert(!err) + client.query('SELECT NOW()') + done() + }) + ) }) diff --git a/packages/pg/test/integration/connection-pool/native-instance-tests.js b/packages/pg/test/integration/connection-pool/native-instance-tests.js index 5347677a..a981503e 100644 --- a/packages/pg/test/integration/connection-pool/native-instance-tests.js +++ b/packages/pg/test/integration/connection-pool/native-instance-tests.js @@ -5,12 +5,14 @@ var native = helper.args.native var pool = new pg.Pool() -pool.connect(assert.calls(function (err, client, done) { - if (native) { - assert(client.native) - } else { - assert(!client.native) - } - done() - pool.end() -})) +pool.connect( + assert.calls(function (err, client, done) { + if (native) { + assert(client.native) + } else { + assert(!client.native) + } + done() + pool.end() + }) +) diff --git a/packages/pg/test/integration/connection-pool/yield-support-tests.js b/packages/pg/test/integration/connection-pool/yield-support-tests.js index 08d89b30..00508f5d 100644 --- a/packages/pg/test/integration/connection-pool/yield-support-tests.js +++ b/packages/pg/test/integration/connection-pool/yield-support-tests.js @@ -3,18 +3,21 @@ 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 * () { - var client = yield pool.connect() - var res = yield client.query('SELECT $1::text as name', ['foo']) - assert.equal(res.rows[0].name, 'foo') +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) { - threw = true - } - assert(threw) - client.release() - yield pool.end() -})) + var threw = false + try { + yield client.query('SELECT LKDSJDSLKFJ') + } catch (e) { + threw = true + } + assert(threw) + client.release() + yield pool.end() + }) +) diff --git a/packages/pg/test/integration/connection/bound-command-tests.js b/packages/pg/test/integration/connection/bound-command-tests.js index c6cf84e1..a707bc4b 100644 --- a/packages/pg/test/integration/connection/bound-command-tests.js +++ b/packages/pg/test/integration/connection/bound-command-tests.js @@ -5,7 +5,7 @@ var helper = require(__dirname + '/test-helper') test('flushing once', function () { helper.connect(function (con) { con.parse({ - text: 'select * from ids' + text: 'select * from ids', }) con.bind() @@ -50,7 +50,7 @@ test('sending many flushes', function () { }) con.parse({ - text: 'select * from ids order by id' + text: 'select * from ids order by id', }) con.flush() diff --git a/packages/pg/test/integration/connection/copy-tests.js b/packages/pg/test/integration/connection/copy-tests.js index c11632c3..1b7d06ed 100644 --- a/packages/pg/test/integration/connection/copy-tests.js +++ b/packages/pg/test/integration/connection/copy-tests.js @@ -8,13 +8,17 @@ test('COPY FROM events check', function () { con.on('copyInResponse', function () { con.endCopyFrom() }) - assert.emits(con, 'copyInResponse', + assert.emits( + con, + 'copyInResponse', function () { con.endCopyFrom() }, 'backend should emit copyInResponse after COPY FROM query' ) - assert.emits(con, 'commandComplete', + assert.emits( + con, + 'commandComplete', function () { con.end() }, @@ -25,17 +29,11 @@ test('COPY FROM events check', function () { test('COPY TO events check', function () { helper.connect(function (con) { var stdoutStream = con.query('COPY person TO STDOUT') - assert.emits(con, 'copyOutResponse', - function () { - }, - 'backend should emit copyOutResponse after COPY TO query' - ) - assert.emits(con, 'copyData', - function () { - }, - 'backend should emit copyData on every data row' - ) - assert.emits(con, 'copyDone', + assert.emits(con, 'copyOutResponse', function () {}, 'backend should emit copyOutResponse after COPY TO query') + assert.emits(con, 'copyData', function () {}, 'backend should emit copyData on every data row') + assert.emits( + con, + 'copyDone', function () { con.end() }, diff --git a/packages/pg/test/integration/connection/dynamic-password-tests.js b/packages/pg/test/integration/connection/dynamic-password-tests.js index 20b50953..3ab39d0b 100644 --- a/packages/pg/test/integration/connection/dynamic-password-tests.js +++ b/packages/pg/test/integration/connection/dynamic-password-tests.js @@ -3,116 +3,117 @@ const assert = require('assert') const helper = require('./../test-helper') const suite = new helper.Suite() const pg = require('../../../lib/index') -const Client = pg.Client; +const Client = pg.Client const password = process.env.PGPASSWORD || null -const sleep = millis => new Promise(resolve => setTimeout(resolve, millis)) +const sleep = (millis) => new Promise((resolve) => setTimeout(resolve, millis)) if (!password) { - // skip these tests; no password will be requested - return + // skip these tests; no password will be requested + return } suite.testAsync('Get password from a sync function', () => { - let wasCalled = false - function getPassword() { - wasCalled = true - return password - } - const client = new Client({ - password: getPassword, - }) - return client.connect() - .then(() => { - assert.ok(wasCalled, 'Our password function should have been called') - return client.end() - }) + let wasCalled = false + function getPassword() { + wasCalled = true + return password + } + const client = new Client({ + password: getPassword, + }) + return client.connect().then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + return client.end() + }) }) suite.testAsync('Throw error from a sync function', () => { - let wasCalled = false - const myError = new Error('Oops!') - function getPassword() { - wasCalled = true - throw myError - } - const client = new Client({ - password: getPassword, + let wasCalled = false + const myError = new Error('Oops!') + function getPassword() { + wasCalled = true + throw myError + } + const client = new Client({ + password: getPassword, + }) + let wasThrown = false + return client + .connect() + .catch((err) => { + assert.equal(err, myError, 'Our sync error should have been thrown') + wasThrown = true + }) + .then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + assert.ok(wasThrown, 'Our error should have been thrown') + return client.end() }) - let wasThrown = false - return client.connect() - .catch(err => { - assert.equal(err, myError, 'Our sync error should have been thrown') - wasThrown = true - }) - .then(() => { - assert.ok(wasCalled, 'Our password function should have been called') - assert.ok(wasThrown, 'Our error should have been thrown') - return client.end() - }) }) suite.testAsync('Get password from a function asynchronously', () => { - let wasCalled = false - function getPassword() { - wasCalled = true - return sleep(100).then(() => password) - } - const client = new Client({ - password: getPassword, - }) - return client.connect() - .then(() => { - assert.ok(wasCalled, 'Our password function should have been called') - return client.end() - }) + let wasCalled = false + function getPassword() { + wasCalled = true + return sleep(100).then(() => password) + } + const client = new Client({ + password: getPassword, + }) + return client.connect().then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + return client.end() + }) }) suite.testAsync('Throw error from an async function', () => { - let wasCalled = false - const myError = new Error('Oops!') - function getPassword() { - wasCalled = true - return sleep(100).then(() => { - throw myError - }) - } - const client = new Client({ - password: getPassword, + let wasCalled = false + const myError = new Error('Oops!') + function getPassword() { + wasCalled = true + return sleep(100).then(() => { + throw myError + }) + } + const client = new Client({ + password: getPassword, + }) + let wasThrown = false + return client + .connect() + .catch((err) => { + assert.equal(err, myError, 'Our async error should have been thrown') + wasThrown = true + }) + .then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + assert.ok(wasThrown, 'Our error should have been thrown') + return client.end() }) - let wasThrown = false - return client.connect() - .catch(err => { - assert.equal(err, myError, 'Our async error should have been thrown') - wasThrown = true - }) - .then(() => { - assert.ok(wasCalled, 'Our password function should have been called') - assert.ok(wasThrown, 'Our error should have been thrown') - return client.end() - }) }) suite.testAsync('Password function must return a string', () => { - let wasCalled = false - function getPassword() { - wasCalled = true - // Return a password that is not a string - return 12345 - } - const client = new Client({ - password: getPassword, + let wasCalled = false + function getPassword() { + wasCalled = true + // Return a password that is not a string + return 12345 + } + const client = new Client({ + password: getPassword, + }) + let wasThrown = false + return client + .connect() + .catch((err) => { + assert.ok(err instanceof TypeError, 'A TypeError should have been thrown') + assert.equal(err.message, 'Password must be a string') + wasThrown = true + }) + .then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + assert.ok(wasThrown, 'Our error should have been thrown') + return client.end() }) - let wasThrown = false - return client.connect() - .catch(err => { - assert.ok(err instanceof TypeError, 'A TypeError should have been thrown') - assert.equal(err.message, 'Password must be a string') - wasThrown = true - }) - .then(() => { - assert.ok(wasCalled, 'Our password function should have been called') - assert.ok(wasThrown, 'Our error should have been thrown') - return client.end() - }) }) diff --git a/packages/pg/test/integration/connection/test-helper.js b/packages/pg/test/integration/connection/test-helper.js index 99661a46..ca978af4 100644 --- a/packages/pg/test/integration/connection/test-helper.js +++ b/packages/pg/test/integration/connection/test-helper.js @@ -6,7 +6,7 @@ var utils = require(__dirname + '/../../../lib/utils') var connect = function (callback) { var username = helper.args.user var database = helper.args.database - var con = new Connection({stream: new net.Stream()}) + var con = new Connection({ stream: new net.Stream() }) con.on('error', function (error) { console.log(error) throw new Error('Connection error') @@ -15,13 +15,13 @@ var connect = function (callback) { con.once('connect', function () { con.startup({ user: username, - database: database + database: database, }) con.once('authenticationCleartextPassword', function () { con.password(helper.args.password) }) con.once('authenticationMD5Password', function (msg) { - con.password(utils.postgresMd5PasswordHash(helper.args.user, helper.args.password, msg.salt)); + con.password(utils.postgresMd5PasswordHash(helper.args.user, helper.args.password, msg.salt)) }) con.once('readyForQuery', function () { con.query('create temp table ids(id integer)') @@ -36,5 +36,5 @@ var connect = function (callback) { } module.exports = { - connect: connect + connect: connect, } diff --git a/packages/pg/test/integration/domain-tests.js b/packages/pg/test/integration/domain-tests.js index a02f3942..ce46eb8a 100644 --- a/packages/pg/test/integration/domain-tests.js +++ b/packages/pg/test/integration/domain-tests.js @@ -10,11 +10,13 @@ const Pool = helper.pg.Pool suite.test('no domain', function (cb) { assert(!process.domain) const pool = new Pool() - pool.connect(assert.success(function (client, done) { - assert(!process.domain) - done() - pool.end(cb) - })) + pool.connect( + assert.success(function (client, done) { + assert(!process.domain) + done() + pool.end(cb) + }) + ) }) suite.test('with domain', function (cb) { @@ -24,17 +26,22 @@ suite.test('with domain', function (cb) { domain.run(function () { var startingDomain = process.domain assert(startingDomain) - 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 () { - assert(process.domain, 'no domain exists in query callback') + 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') - done(true) - process.domain.exit() - pool.end(cb) - })) - })) + 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() + pool.end(cb) + }) + ) + }) + ) }) }) @@ -45,9 +52,11 @@ suite.test('error on domain', function (cb) { pool.end(cb) }) domain.run(function () { - pool.connect(assert.success(function (client, done) { - client.query(new Query('SELECT SLDKJFLSKDJF')) - client.on('drain', done) - })) + pool.connect( + assert.success(function (client, done) { + client.query(new Query('SELECT SLDKJFLSKDJF')) + client.on('drain', done) + }) + ) }) }) diff --git a/packages/pg/test/integration/gh-issues/130-tests.js b/packages/pg/test/integration/gh-issues/130-tests.js index db3aeacd..8b097b99 100644 --- a/packages/pg/test/integration/gh-issues/130-tests.js +++ b/packages/pg/test/integration/gh-issues/130-tests.js @@ -18,8 +18,11 @@ pool.connect(function (err, client, done) { 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.ifError(error) - })) + exec( + psql + ' -c "select pg_terminate_backend(' + pid + ')" template1', + assert.calls(function (error, stdout, stderr) { + assert.ifError(error) + }) + ) }) }) diff --git a/packages/pg/test/integration/gh-issues/131-tests.js b/packages/pg/test/integration/gh-issues/131-tests.js index 87a7b241..5838067f 100644 --- a/packages/pg/test/integration/gh-issues/131-tests.js +++ b/packages/pg/test/integration/gh-issues/131-tests.js @@ -6,17 +6,28 @@ 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) - 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() - pool.end(done) - })) - })) + 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) + 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() + pool.end(done) + }) + ) + }) + ) }) diff --git a/packages/pg/test/integration/gh-issues/1382-tests.js b/packages/pg/test/integration/gh-issues/1382-tests.js index 3cbc31cf..e80924c6 100644 --- a/packages/pg/test/integration/gh-issues/1382-tests.js +++ b/packages/pg/test/integration/gh-issues/1382-tests.js @@ -1,4 +1,4 @@ -"use strict" +'use strict' var helper = require('./../test-helper') const suite = new helper.Suite() diff --git a/packages/pg/test/integration/gh-issues/1542-tests.js b/packages/pg/test/integration/gh-issues/1542-tests.js index 4d30d602..f65aa3fb 100644 --- a/packages/pg/test/integration/gh-issues/1542-tests.js +++ b/packages/pg/test/integration/gh-issues/1542-tests.js @@ -1,15 +1,12 @@ - -"use strict" +'use strict' const helper = require('./../test-helper') const assert = require('assert') const suite = new helper.Suite() suite.testAsync('BoundPool can be subclassed', async () => { - const Pool = helper.pg.Pool; - class SubPool extends Pool { - - } + const Pool = helper.pg.Pool + class SubPool extends Pool {} const subPool = new SubPool() const client = await subPool.connect() client.release() @@ -18,7 +15,7 @@ suite.testAsync('BoundPool can be subclassed', async () => { }) suite.test('calling pg.Pool without new throws', () => { - const Pool = helper.pg.Pool; + const Pool = helper.pg.Pool assert.throws(() => { const pool = Pool() }) diff --git a/packages/pg/test/integration/gh-issues/1854-tests.js b/packages/pg/test/integration/gh-issues/1854-tests.js index 8dbe37ab..92ac6ec3 100644 --- a/packages/pg/test/integration/gh-issues/1854-tests.js +++ b/packages/pg/test/integration/gh-issues/1854-tests.js @@ -1,4 +1,4 @@ -"use strict" +'use strict' var helper = require('./../test-helper') const suite = new helper.Suite() @@ -10,17 +10,17 @@ suite.test('Parameter serialization errors should not cause query to hang', (don } const client = new helper.pg.Client() const expectedErr = new Error('Serialization error') - client.connect() + client + .connect() .then(() => { const obj = { toPostgres: function () { throw expectedErr - } + }, } - return client.query('SELECT $1::text', [obj]) - .then(() => { - throw new Error('Expected a serialization error to be thrown but no error was thrown') - }) + return client.query('SELECT $1::text', [obj]).then(() => { + throw new Error('Expected a serialization error to be thrown but no error was thrown') + }) }) .catch((err) => { client.end(() => {}) diff --git a/packages/pg/test/integration/gh-issues/199-tests.js b/packages/pg/test/integration/gh-issues/199-tests.js index bb93d426..2710020c 100644 --- a/packages/pg/test/integration/gh-issues/199-tests.js +++ b/packages/pg/test/integration/gh-issues/199-tests.js @@ -5,7 +5,8 @@ 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');") -var qText = "SELECT \ +var qText = + "SELECT \ ARRAY[1, 2, 3] AS b,\ ARRAY['xx', 'yy', 'zz'] AS c,\ ARRAY(SELECT n FROM arrtest) AS d,\ diff --git a/packages/pg/test/integration/gh-issues/1992-tests.js b/packages/pg/test/integration/gh-issues/1992-tests.js index 1832f5f8..abb2167a 100644 --- a/packages/pg/test/integration/gh-issues/1992-tests.js +++ b/packages/pg/test/integration/gh-issues/1992-tests.js @@ -1,5 +1,4 @@ - -"use strict" +'use strict' const helper = require('./../test-helper') const assert = require('assert') diff --git a/packages/pg/test/integration/gh-issues/2056-tests.js b/packages/pg/test/integration/gh-issues/2056-tests.js index e025a1ad..2a12678b 100644 --- a/packages/pg/test/integration/gh-issues/2056-tests.js +++ b/packages/pg/test/integration/gh-issues/2056-tests.js @@ -1,11 +1,9 @@ - -"use strict" +'use strict' var helper = require('./../test-helper') var assert = require('assert') const suite = new helper.Suite() - suite.test('All queries should return a result array', (done) => { const client = new helper.pg.Client() client.connect() @@ -13,8 +11,8 @@ suite.test('All queries should return a result array', (done) => { promises.push(client.query('CREATE TEMP TABLE foo(bar TEXT)')) promises.push(client.query('INSERT INTO foo(bar) VALUES($1)', ['qux'])) promises.push(client.query('SELECT * FROM foo WHERE bar = $1', ['foo'])) - Promise.all(promises).then(results => { - results.forEach(res => { + Promise.all(promises).then((results) => { + results.forEach((res) => { assert(Array.isArray(res.fields)) assert(Array.isArray(res.rows)) }) diff --git a/packages/pg/test/integration/gh-issues/2064-tests.js b/packages/pg/test/integration/gh-issues/2064-tests.js index 64c150bd..6118ca2f 100644 --- a/packages/pg/test/integration/gh-issues/2064-tests.js +++ b/packages/pg/test/integration/gh-issues/2064-tests.js @@ -1,5 +1,4 @@ - -"use strict" +'use strict' const helper = require('./../test-helper') const assert = require('assert') const util = require('util') @@ -11,22 +10,22 @@ const password = 'FAIL THIS TEST' suite.test('Password should not exist in toString() output', () => { const pool = new helper.pg.Pool({ password }) const client = new helper.pg.Client({ password }) - assert(pool.toString().indexOf(password) === -1); - assert(client.toString().indexOf(password) === -1); + assert(pool.toString().indexOf(password) === -1) + assert(client.toString().indexOf(password) === -1) }) suite.test('Password should not exist in util.inspect output', () => { const pool = new helper.pg.Pool({ password }) const client = new helper.pg.Client({ password }) - const depth = 20; - assert(util.inspect(pool, { depth }).indexOf(password) === -1); - assert(util.inspect(client, { depth }).indexOf(password) === -1); + const depth = 20 + assert(util.inspect(pool, { depth }).indexOf(password) === -1) + assert(util.inspect(client, { depth }).indexOf(password) === -1) }) suite.test('Password should not exist in json.stringfy output', () => { const pool = new helper.pg.Pool({ password }) const client = new helper.pg.Client({ password }) - const depth = 20; - assert(JSON.stringify(pool).indexOf(password) === -1); - assert(JSON.stringify(client).indexOf(password) === -1); + const depth = 20 + assert(JSON.stringify(pool).indexOf(password) === -1) + assert(JSON.stringify(client).indexOf(password) === -1) }) diff --git a/packages/pg/test/integration/gh-issues/2079-tests.js b/packages/pg/test/integration/gh-issues/2079-tests.js index bec8e481..be248579 100644 --- a/packages/pg/test/integration/gh-issues/2079-tests.js +++ b/packages/pg/test/integration/gh-issues/2079-tests.js @@ -1,5 +1,4 @@ - -"use strict" +'use strict' var helper = require('./../test-helper') var assert = require('assert') @@ -7,7 +6,7 @@ const suite = new helper.Suite() // makes a backend server that responds with a non 'S' ssl response buffer let makeTerminatingBackend = (byte) => { - const { createServer } = require('net') + const { createServer } = require('net') const server = createServer((socket) => { // attach a listener so the socket can drain @@ -42,7 +41,6 @@ suite.test('SSL connection error allows event loop to exit', (done) => { }) }) - suite.test('Non "S" response code allows event loop to exit', (done) => { const port = makeTerminatingBackend('X') const client = new helper.pg.Client({ ssl: 'require', port }) @@ -53,4 +51,3 @@ suite.test('Non "S" response code allows event loop to exit', (done) => { done() }) }) - diff --git a/packages/pg/test/integration/gh-issues/2085-tests.js b/packages/pg/test/integration/gh-issues/2085-tests.js index 8ccdca15..23fd71d0 100644 --- a/packages/pg/test/integration/gh-issues/2085-tests.js +++ b/packages/pg/test/integration/gh-issues/2085-tests.js @@ -1,15 +1,15 @@ - - -"use strict" +'use strict' var helper = require('./../test-helper') var assert = require('assert') const suite = new helper.Suite() suite.testAsync('it should connect over ssl', async () => { - const ssl = helper.args.native ? 'require' : { - rejectUnauthorized: false - } + const ssl = helper.args.native + ? 'require' + : { + rejectUnauthorized: false, + } const client = new helper.pg.Client({ ssl }) await client.connect() const { rows } = await client.query('SELECT NOW()') @@ -18,12 +18,12 @@ suite.testAsync('it should connect over ssl', async () => { }) suite.testAsync('it should fail with self-signed cert error w/o rejectUnauthorized being passed', async () => { - const ssl = helper.args.native ? 'verify-ca' : { } + const ssl = helper.args.native ? 'verify-ca' : {} const client = new helper.pg.Client({ ssl }) try { await client.connect() } catch (e) { - return; + return } throw new Error('this test should have thrown an error due to self-signed cert') }) diff --git a/packages/pg/test/integration/gh-issues/2108-tests.js b/packages/pg/test/integration/gh-issues/2108-tests.js index 9832dae3..cbf2caab 100644 --- a/packages/pg/test/integration/gh-issues/2108-tests.js +++ b/packages/pg/test/integration/gh-issues/2108-tests.js @@ -1,4 +1,4 @@ -"use strict" +'use strict' var helper = require('./../test-helper') const suite = new helper.Suite() diff --git a/packages/pg/test/integration/gh-issues/507-tests.js b/packages/pg/test/integration/gh-issues/507-tests.js index dadc1c83..9c340919 100644 --- a/packages/pg/test/integration/gh-issues/507-tests.js +++ b/packages/pg/test/integration/gh-issues/507-tests.js @@ -4,14 +4,16 @@ var pg = helper.pg new helper.Suite().test('parsing array results', function (cb) { 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() - pool.end(cb) + 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() + pool.end(cb) + }) }) - })) + ) }) diff --git a/packages/pg/test/integration/gh-issues/600-tests.js b/packages/pg/test/integration/gh-issues/600-tests.js index ea6154e3..af679ee8 100644 --- a/packages/pg/test/integration/gh-issues/600-tests.js +++ b/packages/pg/test/integration/gh-issues/600-tests.js @@ -5,40 +5,46 @@ const suite = new helper.Suite() var db = helper.client() -function createTableFoo (callback) { +function createTableFoo(callback) { db.query('create temp table foo(column1 int, column2 int)', callback) } -function createTableBar (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) { +function startTransaction(callback) { db.query('BEGIN', callback) } -function endTransaction (callback) { +function endTransaction(callback) { db.query('COMMIT', 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. +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 () { @@ -48,18 +54,16 @@ function doTransaction (callback) { }) } -var steps = [ - createTableFoo, - createTableBar, - doTransaction, - insertDataBar -] +var steps = [createTableFoo, createTableBar, doTransaction, insertDataBar] suite.test('test if query fails', function (done) { - async.series(steps, assert.success(function () { - db.end() - done() - })) + async.series( + steps, + assert.success(function () { + db.end() + done() + }) + ) }) suite.test('test if prepare works but bind fails', function (done) { @@ -67,14 +71,20 @@ suite.test('test if prepare works but bind fails', function (done) { var q = { text: 'SELECT $1::int as name', values: ['brian'], - name: 'test' + 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() - done() - })) - })) + 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/packages/pg/test/integration/gh-issues/699-tests.js b/packages/pg/test/integration/gh-issues/699-tests.js index d4c9eab7..c9be63bf 100644 --- a/packages/pg/test/integration/gh-issues/699-tests.js +++ b/packages/pg/test/integration/gh-issues/699-tests.js @@ -1,31 +1,31 @@ -"use strict"; -var helper = require('../test-helper'); -var assert = require('assert'); -var copyFrom = require('pg-copy-streams').from; +'use strict' +var helper = require('../test-helper') +var assert = require('assert') +var copyFrom = require('pg-copy-streams').from -if(helper.args.native) return; +if (helper.args.native) return const pool = new helper.pg.Pool() pool.connect(function (err, client, done) { - if (err) throw err; + if (err) throw err - var c = 'CREATE TEMP TABLE employee (id integer, fname varchar(400), lname varchar(400))'; + var c = 'CREATE TEMP TABLE employee (id integer, fname varchar(400), lname varchar(400))' client.query(c, function (err) { - if (err) throw err; + if (err) throw err - var stream = client.query(copyFrom("COPY employee FROM STDIN")); + var stream = client.query(copyFrom('COPY employee FROM STDIN')) stream.on('end', function () { - done(); + done() setTimeout(() => { pool.end() }, 50) - }); + }) for (var i = 1; i <= 5; i++) { - var line = ['1\ttest', i, '\tuser', i, '\n']; - stream.write(line.join('')); + var line = ['1\ttest', i, '\tuser', i, '\n'] + stream.write(line.join('')) } - stream.end(); - }); -}); + stream.end() + }) +}) diff --git a/packages/pg/test/integration/gh-issues/787-tests.js b/packages/pg/test/integration/gh-issues/787-tests.js index 456c8646..9a3198f5 100644 --- a/packages/pg/test/integration/gh-issues/787-tests.js +++ b/packages/pg/test/integration/gh-issues/787-tests.js @@ -4,8 +4,9 @@ const pool = new helper.pg.Pool() 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()' + 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() diff --git a/packages/pg/test/integration/gh-issues/882-tests.js b/packages/pg/test/integration/gh-issues/882-tests.js index 6b4a3e2e..4a8ef647 100644 --- a/packages/pg/test/integration/gh-issues/882-tests.js +++ b/packages/pg/test/integration/gh-issues/882-tests.js @@ -2,7 +2,7 @@ // 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: 'foo1', text: null }) client.query({ name: 'foo2', text: ' ' }) client.query({ name: 'foo3', text: '' }, function (err, res) { client.end() diff --git a/packages/pg/test/integration/gh-issues/981-tests.js b/packages/pg/test/integration/gh-issues/981-tests.js index 6348d05a..998adea3 100644 --- a/packages/pg/test/integration/gh-issues/981-tests.js +++ b/packages/pg/test/integration/gh-issues/981-tests.js @@ -1,9 +1,9 @@ -"use strict"; -var helper = require('./../test-helper'); +'use strict' +var helper = require('./../test-helper') //native bindings are only installed for native tests if (!helper.args.native) { - return; + return } var assert = require('assert') @@ -13,26 +13,25 @@ var native = require('../../../lib').native var JsClient = require('../../../lib/client') var NativeClient = require('../../../lib/native') -assert(pg.Client === JsClient); -assert(native.Client === NativeClient); +assert(pg.Client === JsClient) +assert(native.Client === NativeClient) const jsPool = new pg.Pool() const nativePool = new native.Pool() const suite = new helper.Suite() -suite.test('js pool returns js client', cb => { +suite.test('js pool returns js client', (cb) => { jsPool.connect(function (err, client, done) { - assert(client instanceof JsClient); + assert(client instanceof JsClient) done() jsPool.end(cb) }) - }) -suite.test('native pool returns native client', cb => { +suite.test('native pool returns native client', (cb) => { nativePool.connect(function (err, client, done) { - assert(client instanceof NativeClient); + assert(client instanceof NativeClient) done() nativePool.end(cb) - }); + }) }) diff --git a/packages/pg/test/integration/test-helper.js b/packages/pg/test/integration/test-helper.js index fb9ac6da..9b8b58c6 100644 --- a/packages/pg/test/integration/test-helper.js +++ b/packages/pg/test/integration/test-helper.js @@ -15,11 +15,14 @@ helper.client = function (cb) { } helper.versionGTE = function (client, testVersion, callback) { - client.query('SHOW server_version_num', assert.calls(function (err, result) { - if (err) return callback(err) - var version = parseInt(result.rows[0].server_version_num, 10) - return callback(null, version >= testVersion) - })) + client.query( + 'SHOW server_version_num', + assert.calls(function (err, result) { + if (err) return callback(err) + var version = parseInt(result.rows[0].server_version_num, 10) + return callback(null, version >= testVersion) + }) + ) } // export parent helper stuffs diff --git a/packages/pg/test/native/callback-api-tests.js b/packages/pg/test/native/callback-api-tests.js index a7fff118..80fdcdf5 100644 --- a/packages/pg/test/native/callback-api-tests.js +++ b/packages/pg/test/native/callback-api-tests.js @@ -7,16 +7,23 @@ 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) { + client.query( + 'SELECT 1 as num', + assert.calls(function (err, result) { assert(!err) - assert.equal(result.rows[0].name, 'Brian') - client.end(done) - })) - })) + 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) { diff --git a/packages/pg/test/native/evented-api-tests.js b/packages/pg/test/native/evented-api-tests.js index 4fac0415..ba0496ef 100644 --- a/packages/pg/test/native/evented-api-tests.js +++ b/packages/pg/test/native/evented-api-tests.js @@ -24,7 +24,7 @@ test('multiple results', function () { }) assert.emits(q, 'end', function () { test('query with config', function () { - var q2 = client.query(new 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 () { @@ -50,10 +50,12 @@ test('parameterized queries', function () { test('with object config for query', function () { var client = setupClient() - var q = client.query(new Query({ - text: 'SELECT name FROM boom WHERE name = $1', - values: ['Brian'] - })) + 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') }) @@ -64,7 +66,9 @@ test('parameterized queries', function () { 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 COLLATE "C"', ['Aaron', 'Brian'])) + var q = client.query( + new Query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name COLLATE "C"', ['Aaron', 'Brian']) + ) assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Aaron') assert.emits(q, 'row', function (row) { diff --git a/packages/pg/test/suite.js b/packages/pg/test/suite.js index 4161ddc0..7d19edbb 100644 --- a/packages/pg/test/suite.js +++ b/packages/pg/test/suite.js @@ -3,13 +3,13 @@ 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) { @@ -17,7 +17,7 @@ class Test { } } - _run (cb) { + _run(cb) { if (!this.action) { console.log(`${this.name} skipped`) return cb() @@ -27,9 +27,7 @@ class Test { if (!(result || 0).then) { return cb() } - result - .then(() => cb()) - .catch(err => cb(err || new Error('Unhandled promise rejection'))) + result.then(() => cb()).catch((err) => cb(err || new Error('Unhandled promise rejection'))) } else { this.action.call(this, cb) } @@ -37,13 +35,13 @@ class Test { } class Suite { - constructor (name) { + constructor(name) { console.log('') this._queue = async.queue(this.run.bind(this), 1) - this._queue.drain = () => { } + this._queue.drain = () => {} } - run (test, cb) { + run(test, cb) { process.stdout.write(' ' + test.name + ' ') if (!test.action) { process.stdout.write('? - SKIPPED\n') @@ -68,7 +66,7 @@ class Suite { }) } - test (name, cb) { + test(name, cb) { const test = new Test(name, cb) this._queue.push(test) } @@ -78,8 +76,8 @@ class Suite { * successfully then the test will pass. If the Promise rejects with an * error then the test will be considered failed. */ - testAsync (name, action) { - const test = new Test(name, cb => { + testAsync(name, action) { + const test = new Test(name, (cb) => { Promise.resolve() .then(action) .then(() => cb(null), cb) diff --git a/packages/pg/test/test-buffers.js b/packages/pg/test/test-buffers.js index 60a54949..9fdd889d 100644 --- a/packages/pg/test/test-buffers.js +++ b/packages/pg/test/test-buffers.js @@ -4,21 +4,15 @@ require(__dirname + '/test-helper') var buffers = {} buffers.readyForQuery = function () { - return new BufferList() - .add(Buffer.from('I')) - .join(true, 'Z') + return new BufferList().add(Buffer.from('I')).join(true, 'Z') } buffers.authenticationOk = function () { - return new BufferList() - .addInt32(0) - .join(true, 'R') + return new BufferList().addInt32(0).join(true, 'R') } buffers.authenticationCleartextPassword = function () { - return new BufferList() - .addInt32(3) - .join(true, 'R') + return new BufferList().addInt32(3).join(true, 'R') } buffers.authenticationMD5Password = function () { @@ -29,45 +23,27 @@ buffers.authenticationMD5Password = function () { } buffers.authenticationSASL = function () { - return new BufferList() - .addInt32(10) - .addCString('SCRAM-SHA-256') - .addCString('') - .join(true, 'R') + return new BufferList().addInt32(10).addCString('SCRAM-SHA-256').addCString('').join(true, 'R') } buffers.authenticationSASLContinue = function () { - return new BufferList() - .addInt32(11) - .addString('data') - .join(true, 'R') + return new BufferList().addInt32(11).addString('data').join(true, 'R') } buffers.authenticationSASLFinal = function () { - return new BufferList() - .addInt32(12) - .addString('data') - .join(true, 'R') + return new BufferList().addInt32(12).addString('data').join(true, 'R') } buffers.parameterStatus = function (name, value) { - return new BufferList() - .addCString(name) - .addCString(value) - .join(true, 'S') + return new BufferList().addCString(name).addCString(value).join(true, 'S') } buffers.backendKeyData = function (processID, secretKey) { - return new BufferList() - .addInt32(processID) - .addInt32(secretKey) - .join(true, 'K') + return new BufferList().addInt32(processID).addInt32(secretKey).join(true, 'K') } buffers.commandComplete = function (string) { - return new BufferList() - .addCString(string) - .join(true, 'C') + return new BufferList().addCString(string).join(true, 'C') } buffers.rowDescription = function (fields) { @@ -75,7 +51,8 @@ buffers.rowDescription = function (fields) { var buf = new BufferList() buf.addInt16(fields.length) fields.forEach(function (field) { - buf.addCString(field.name) + buf + .addCString(field.name) .addInt32(field.tableID || 0) .addInt16(field.attributeNumber || 0) .addInt32(field.dataTypeID || 0) @@ -117,7 +94,7 @@ var errorOrNotice = function (fields) { buf.addChar(field.type) buf.addCString(field.value) }) - return buf.add(Buffer.from([0]))// terminator + return buf.add(Buffer.from([0])) // terminator } buffers.parseComplete = function () { @@ -129,11 +106,7 @@ buffers.bindComplete = function () { } buffers.notification = function (id, channel, payload) { - return new BufferList() - .addInt32(id) - .addCString(channel) - .addCString(payload) - .join(true, 'A') + return new BufferList().addInt32(id).addCString(channel).addCString(payload).join(true, 'A') } buffers.emptyQuery = function () { diff --git a/packages/pg/test/test-helper.js b/packages/pg/test/test-helper.js index 4c14b857..8159e387 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -39,8 +39,10 @@ assert.emits = function (item, eventName, callback, message) { 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])) + assert.ok( + arguments[0] instanceof Error, + 'Expected error events to throw instances of Error but found: ' + sys.inspect(arguments[0]) + ) } called = true clearTimeout(id) @@ -131,12 +133,15 @@ 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()) + assert.ok( + executed, + '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) { @@ -173,7 +178,7 @@ const getMode = () => { } global.test = function (name, action) { - test.testCount ++ + test.testCount++ test[name] = action var result = test[name]() if (result === false) { @@ -223,14 +228,16 @@ var Sink = function (expected, timeout, callback) { assert.equal(internalCount, expected) callback() } - } + }, } } var getTimezoneOffset = Date.prototype.getTimezoneOffset var setTimezoneOffset = function (minutesOffset) { - Date.prototype.getTimezoneOffset = function () { return minutesOffset } + Date.prototype.getTimezoneOffset = function () { + return minutesOffset + } } var resetTimezoneOffset = function () { @@ -246,5 +253,5 @@ module.exports = { sys: sys, Client: Client, setTimezoneOffset: setTimezoneOffset, - resetTimezoneOffset: resetTimezoneOffset + resetTimezoneOffset: resetTimezoneOffset, } diff --git a/packages/pg/test/unit/client/configuration-tests.js b/packages/pg/test/unit/client/configuration-tests.js index 9c1fadc8..e6cbc0dc 100644 --- a/packages/pg/test/unit/client/configuration-tests.js +++ b/packages/pg/test/unit/client/configuration-tests.js @@ -23,7 +23,7 @@ test('client settings', function () { database: database, port: 321, password: password, - ssl: true + ssl: true, }) assert.equal(client.user, user) @@ -48,7 +48,7 @@ test('client settings', function () { process.env.PGSSLMODE = 'prefer' var client = new Client({ - ssl: false + ssl: false, }) process.env.PGSSLMODE = old @@ -59,7 +59,7 @@ 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' + connectionString: 'postgres://brian:pass@host1:333/databasename', }) assert.equal(client.user, 'brian') assert.equal(client.password, 'pass') diff --git a/packages/pg/test/unit/client/early-disconnect-tests.js b/packages/pg/test/unit/client/early-disconnect-tests.js index 35a587d9..49448284 100644 --- a/packages/pg/test/unit/client/early-disconnect-tests.js +++ b/packages/pg/test/unit/client/early-disconnect-tests.js @@ -11,7 +11,9 @@ var server = net.createServer(function (c) { server.listen(7777, function () { var client = new pg.Client('postgres://localhost:7777') - client.connect(assert.calls(function (err) { - assert(err) - })) + client.connect( + assert.calls(function (err) { + assert(err) + }) + ) }) diff --git a/packages/pg/test/unit/client/escape-tests.js b/packages/pg/test/unit/client/escape-tests.js index 8229a3a3..7f96a832 100644 --- a/packages/pg/test/unit/client/escape-tests.js +++ b/packages/pg/test/unit/client/escape-tests.js @@ -1,7 +1,7 @@ 'use strict' var helper = require(__dirname + '/test-helper') -function createClient (callback) { +function createClient(callback) { var client = new Client(helper.config) client.connect(function (err) { return callback(client) @@ -24,50 +24,42 @@ var testIdent = function (testName, input, expected) { }) } -testLit('escapeLiteral: no special characters', - 'hello world', "'hello world'") +testLit('escapeLiteral: no special characters', 'hello world', "'hello world'") -testLit('escapeLiteral: contains double quotes only', - 'hello " world', "'hello \" world'") +testLit('escapeLiteral: contains double quotes only', 'hello " world', "'hello \" world'") -testLit('escapeLiteral: contains single quotes only', - 'hello \' world', "'hello \'\' world'") +testLit('escapeLiteral: contains single quotes only', "hello ' world", "'hello '' world'") -testLit('escapeLiteral: contains backslashes only', - 'hello \\ world', " E'hello \\\\ world'") +testLit('escapeLiteral: contains backslashes only', 'hello \\ world', " E'hello \\\\ world'") -testLit('escapeLiteral: contains single quotes and double quotes', - 'hello \' " world', "'hello '' \" world'") +testLit('escapeLiteral: contains single quotes and double quotes', 'hello \' " world', "'hello '' \" world'") -testLit('escapeLiteral: contains double quotes and backslashes', - 'hello \\ " world', " E'hello \\\\ \" world'") +testLit('escapeLiteral: contains double quotes and backslashes', 'hello \\ " world', " E'hello \\\\ \" world'") -testLit('escapeLiteral: contains single quotes and backslashes', - 'hello \\ \' world', " E'hello \\\\ '' world'") +testLit('escapeLiteral: contains single quotes and backslashes', "hello \\ ' world", " E'hello \\\\ '' world'") -testLit('escapeLiteral: contains single quotes, double quotes, and backslashes', - 'hello \\ \' " world', " E'hello \\\\ '' \" world'") +testLit( + 'escapeLiteral: contains single quotes, double quotes, and backslashes', + 'hello \\ \' " world', + " E'hello \\\\ '' \" world'" +) -testIdent('escapeIdentifier: no special characters', - 'hello world', '"hello world"') +testIdent('escapeIdentifier: no special characters', 'hello world', '"hello world"') -testIdent('escapeIdentifier: contains double quotes only', - 'hello " world', '"hello "" world"') +testIdent('escapeIdentifier: contains double quotes only', 'hello " world', '"hello "" world"') -testIdent('escapeIdentifier: contains single quotes only', - 'hello \' world', '"hello \' world"') +testIdent('escapeIdentifier: contains single quotes only', "hello ' world", '"hello \' world"') -testIdent('escapeIdentifier: contains backslashes only', - 'hello \\ world', '"hello \\ world"') +testIdent('escapeIdentifier: contains backslashes only', 'hello \\ world', '"hello \\ world"') -testIdent('escapeIdentifier: contains single quotes and double quotes', - 'hello \' " world', '"hello \' "" world"') +testIdent('escapeIdentifier: contains single quotes and double quotes', 'hello \' " world', '"hello \' "" world"') -testIdent('escapeIdentifier: contains double quotes and backslashes', - 'hello \\ " world', '"hello \\ "" world"') +testIdent('escapeIdentifier: contains double quotes and backslashes', 'hello \\ " world', '"hello \\ "" world"') -testIdent('escapeIdentifier: contains single quotes and backslashes', - 'hello \\ \' world', '"hello \\ \' world"') +testIdent('escapeIdentifier: contains single quotes and backslashes', "hello \\ ' world", '"hello \\ \' world"') -testIdent('escapeIdentifier: contains single quotes, double quotes, and backslashes', - 'hello \\ \' " world', '"hello \\ \' "" world"') +testIdent( + 'escapeIdentifier: contains single quotes, double quotes, and backslashes', + 'hello \\ \' " world', + '"hello \\ \' "" world"' +) diff --git a/packages/pg/test/unit/client/md5-password-tests.js b/packages/pg/test/unit/client/md5-password-tests.js index 85b357ae..a55e955b 100644 --- a/packages/pg/test/unit/client/md5-password-tests.js +++ b/packages/pg/test/unit/client/md5-password-tests.js @@ -6,15 +6,14 @@ test('md5 authentication', function () { var client = helper.createClient() client.password = '!' var salt = Buffer.from([1, 2, 3, 4]) - client.connection.emit('authenticationMD5Password', {salt: salt}) + client.connection.emit('authenticationMD5Password', { salt: salt }) test('responds', function () { assert.lengthIs(client.connection.stream.packets, 1) test('should have correct encrypted data', function () { var password = utils.postgresMd5PasswordHash(client.user, client.password, salt) // how do we want to test this? - assert.equalBuffers(client.connection.stream.packets[0], new BufferList() - .addCString(password).join(true, 'p')) + assert.equalBuffers(client.connection.stream.packets[0], new BufferList().addCString(password).join(true, 'p')) }) }) }) diff --git a/packages/pg/test/unit/client/prepared-statement-tests.js b/packages/pg/test/unit/client/prepared-statement-tests.js index 08db8860..2499808f 100644 --- a/packages/pg/test/unit/client/prepared-statement-tests.js +++ b/packages/pg/test/unit/client/prepared-statement-tests.js @@ -38,8 +38,7 @@ con.describe = function (arg) { } var syncCalled = false -con.flush = function () { -} +con.flush = function () {} con.sync = function () { syncCalled = true process.nextTick(function () { @@ -51,10 +50,12 @@ 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'] - })) + var query = client.query( + new Query({ + text: 'select * from X where name = $1', + values: ['hi'], + }) + ) assert.emits(query, 'end', function () { test('parse argument', function () { @@ -122,8 +123,7 @@ portalCon.describe = function (arg) { }) } -portalCon.flush = function () { -} +portalCon.flush = function () {} portalCon.sync = function () { process.nextTick(function () { portalCon.emit('readyForQuery') @@ -133,11 +133,13 @@ portalCon.sync = function () { test('prepared statement with explicit portal', function () { assert.ok(portalClient.connection.emit('readyForQuery')) - var query = portalClient.query(new Query({ - text: 'select * from X where name = $1', - portal: 'myportal', - values: ['hi'] - })) + var query = portalClient.query( + new Query({ + text: 'select * from X where name = $1', + portal: 'myportal', + values: ['hi'], + }) + ) assert.emits(query, 'end', function () { test('bind argument', function () { diff --git a/packages/pg/test/unit/client/query-queue-tests.js b/packages/pg/test/unit/client/query-queue-tests.js index 62069c01..9364ce82 100644 --- a/packages/pg/test/unit/client/query-queue-tests.js +++ b/packages/pg/test/unit/client/query-queue-tests.js @@ -3,13 +3,12 @@ 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}) + var con = new Connection({ stream: 'NO' }) + var client = new Client({ connection: con }) con.connect = function () { con.emit('connect') } - con.query = function () { - } + con.query = function () {} client.connect() var raisedDrain = false diff --git a/packages/pg/test/unit/client/result-metadata-tests.js b/packages/pg/test/unit/client/result-metadata-tests.js index 276892e9..f3e00594 100644 --- a/packages/pg/test/unit/client/result-metadata-tests.js +++ b/packages/pg/test/unit/client/result-metadata-tests.js @@ -6,14 +6,17 @@ var testForTag = function (tagText, callback) { 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') - callback(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 + text: tagText, }) client.connection.emit('readyForQuery') diff --git a/packages/pg/test/unit/client/sasl-scram-tests.js b/packages/pg/test/unit/client/sasl-scram-tests.js index 9987c6cf..f60c8c4c 100644 --- a/packages/pg/test/unit/client/sasl-scram-tests.js +++ b/packages/pg/test/unit/client/sasl-scram-tests.js @@ -1,18 +1,19 @@ 'use strict' -require('./test-helper'); +require('./test-helper') var sasl = require('../../../lib/sasl') test('sasl/scram', function () { - test('startSession', function () { - test('fails when mechanisms does not include SCRAM-SHA-256', function () { - assert.throws(function () { - sasl.startSession([]) - }, { - message: 'SASL: Only mechanism SCRAM-SHA-256 is currently supported', - }) + assert.throws( + function () { + sasl.startSession([]) + }, + { + message: 'SASL: Only mechanism SCRAM-SHA-256 is currently supported', + } + ) }) test('returns expected session data', function () { @@ -31,65 +32,90 @@ test('sasl/scram', function () { assert(session1.clientNonce != session2.clientNonce) }) - }) test('continueSession', function () { - test('fails when last session message was not SASLInitialResponse', function () { - assert.throws(function () { - sasl.continueSession({}) - }, { - message: 'SASL: Last message was not SASLInitialResponse', - }) + assert.throws( + function () { + sasl.continueSession({}) + }, + { + message: 'SASL: Last message was not SASLInitialResponse', + } + ) }) test('fails when nonce is missing in server message', function () { - assert.throws(function () { - sasl.continueSession({ - message: 'SASLInitialResponse', - }, "s=1,i=1") - }, { - message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing', - }) + assert.throws( + function () { + sasl.continueSession( + { + message: 'SASLInitialResponse', + }, + 's=1,i=1' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing', + } + ) }) test('fails when salt is missing in server message', function () { - assert.throws(function () { - sasl.continueSession({ - message: 'SASLInitialResponse', - }, "r=1,i=1") - }, { - message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: salt missing', - }) + assert.throws( + function () { + sasl.continueSession( + { + message: 'SASLInitialResponse', + }, + 'r=1,i=1' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: salt missing', + } + ) }) test('fails when iteration is missing in server message', function () { - assert.throws(function () { - sasl.continueSession({ - message: 'SASLInitialResponse', - }, "r=1,s=1") - }, { - message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing', - }) + assert.throws( + function () { + sasl.continueSession( + { + message: 'SASLInitialResponse', + }, + 'r=1,s=1' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing', + } + ) }) test('fails when server nonce does not start with client nonce', function () { - assert.throws(function () { - sasl.continueSession({ - message: 'SASLInitialResponse', - clientNonce: '2', - }, 'r=1,s=1,i=1') - }, { - message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not start with client nonce', - }) + assert.throws( + function () { + sasl.continueSession( + { + message: 'SASLInitialResponse', + clientNonce: '2', + }, + 'r=1,s=1,i=1' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not start with client nonce', + } + ) }) test('sets expected session data', function () { const session = { message: 'SASLInitialResponse', clientNonce: 'a', - }; + } sasl.continueSession(session, 'password', 'r=ab,s=x,i=1') @@ -98,38 +124,45 @@ test('sasl/scram', function () { assert.equal(session.response, 'c=biws,r=ab,p=KAEPBUTjjofB0IM5UWcZApK1dSzFE0o5vnbWjBbvFHA=') }) - }) test('continueSession', function () { - test('fails when last session message was not SASLResponse', function () { - assert.throws(function () { - sasl.finalizeSession({}) - }, { - message: 'SASL: Last message was not SASLResponse', - }) + assert.throws( + function () { + sasl.finalizeSession({}) + }, + { + message: 'SASL: Last message was not SASLResponse', + } + ) }) test('fails when server signature does not match', function () { - assert.throws(function () { - sasl.finalizeSession({ - message: 'SASLResponse', - serverSignature: '3', - }, "v=4") - }, { - message: 'SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature does not match', - }) + assert.throws( + function () { + sasl.finalizeSession( + { + message: 'SASLResponse', + serverSignature: '3', + }, + 'v=4' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature does not match', + } + ) }) test('does not fail when eveything is ok', function () { - sasl.finalizeSession({ - message: 'SASLResponse', - serverSignature: '5', - }, "v=5") + sasl.finalizeSession( + { + message: 'SASLResponse', + serverSignature: '5', + }, + 'v=5' + ) }) - }) - }) - diff --git a/packages/pg/test/unit/client/set-keepalives-tests.js b/packages/pg/test/unit/client/set-keepalives-tests.js index 55ff04f3..3fef0c05 100644 --- a/packages/pg/test/unit/client/set-keepalives-tests.js +++ b/packages/pg/test/unit/client/set-keepalives-tests.js @@ -5,8 +5,8 @@ const helper = require('./test-helper') const suite = new helper.Suite() -suite.test('setting keep alive', done => { - const server = net.createServer(c => { +suite.test('setting keep alive', (done) => { + const server = net.createServer((c) => { c.destroy() server.close() }) @@ -24,7 +24,7 @@ suite.test('setting keep alive', done => { port: 7777, keepAlive: true, keepAliveInitialDelayMillis: 10000, - stream + stream, }) client.connect().catch(() => {}) diff --git a/packages/pg/test/unit/client/simple-query-tests.js b/packages/pg/test/unit/client/simple-query-tests.js index 3d1deef4..b0d5b867 100644 --- a/packages/pg/test/unit/client/simple-query-tests.js +++ b/packages/pg/test/unit/client/simple-query-tests.js @@ -77,9 +77,11 @@ test('executing query', function () { test('handles rowDescription message', function () { var handled = con.emit('rowDescription', { - fields: [{ - name: 'boom' - }] + fields: [ + { + name: 'boom', + }, + ], }) assert.ok(handled, 'should have handlded rowDescription') }) @@ -104,7 +106,7 @@ test('executing query', function () { // when multiple queries are in a simple command test('handles command complete messages', function () { con.emit('commandComplete', { - text: 'INSERT 31 1' + text: 'INSERT 31 1', }) }) @@ -113,9 +115,9 @@ test('executing query', function () { assert.emits(query, 'end', function (msg) { // TODO do we want to check the complete messages? }) - con.emit('readyForQuery'); + con.emit('readyForQuery') // this would never actually happen - ['dataRow', 'rowDescription', 'commandComplete'].forEach(function (msg) { + ;['dataRow', 'rowDescription', 'commandComplete'].forEach(function (msg) { assert.equal(con.emit(msg), false, "Should no longer be picking up '" + msg + "' messages") }) }) @@ -128,7 +130,11 @@ test('executing query', function () { try { client.query(null, undefined) } catch (error) { - assert.equal(error.message, 'Client was passed a null or undefined query', 'Should have thrown an Error for null queries') + assert.equal( + error.message, + 'Client was passed a null or undefined query', + 'Should have thrown an Error for null queries' + ) } }) @@ -136,7 +142,11 @@ test('executing query', function () { try { client.query() } catch (error) { - assert.equal(error.message, 'Client was passed a null or undefined query', 'Should have thrown an Error for null queries') + assert.equal( + error.message, + 'Client was passed a null or undefined query', + 'Should have thrown an Error for null queries' + ) } }) }) diff --git a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js index af0e09a6..9b0a3560 100644 --- a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js +++ b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js @@ -9,12 +9,17 @@ test('emits end when not in query', 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) - })) - })) + 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') diff --git a/packages/pg/test/unit/client/test-helper.js b/packages/pg/test/unit/client/test-helper.js index 24f94df3..8d185903 100644 --- a/packages/pg/test/unit/client/test-helper.js +++ b/packages/pg/test/unit/client/test-helper.js @@ -3,19 +3,22 @@ var helper = require('../test-helper') var Connection = require('../../../lib/connection') var makeClient = function () { - var connection = new Connection({stream: 'no'}) + 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}) + var client = new Client({ connection: connection }) client.connect() client.connection.emit('connect') return client } -module.exports = Object.assign({ - client: makeClient -}, helper) +module.exports = Object.assign( + { + client: makeClient, + }, + helper +) diff --git a/packages/pg/test/unit/client/throw-in-type-parser-tests.js b/packages/pg/test/unit/client/throw-in-type-parser-tests.js index 24883241..8f71fdc0 100644 --- a/packages/pg/test/unit/client/throw-in-type-parser-tests.js +++ b/packages/pg/test/unit/client/throw-in-type-parser-tests.js @@ -11,7 +11,7 @@ types.setTypeParser('special oid that will throw', function () { throw typeParserError }) -const emitFakeEvents = con => { +const emitFakeEvents = (con) => { setImmediate(() => { con.emit('readyForQuery') @@ -19,9 +19,9 @@ const emitFakeEvents = con => { fields: [ { name: 'boom', - dataTypeID: 'special oid that will throw' - } - ] + dataTypeID: 'special oid that will throw', + }, + ], }) con.emit('dataRow', { fields: ['hi'] }) @@ -62,7 +62,7 @@ suite.test('rejects promise with error', function (done) { var client = helper.client() var con = client.connection emitFakeEvents(con) - client.query('whatever').catch(err => { + client.query('whatever').catch((err) => { assert.equal(err, typeParserError) done() }) diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index fdb4e662..820b320a 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -11,15 +11,12 @@ for (var key in process.env) { test('ConnectionParameters construction', function () { assert.ok(new ConnectionParameters(), 'with null config') - assert.ok(new ConnectionParameters({user: 'asdf'}), 'with config object') + 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) { - const expectedDatabase = - expected.database === undefined - ? expected.user - : expected.database + const expectedDatabase = expected.database === undefined ? expected.user : expected.database assert.equal(actual.user, expected.user, type + ' user') assert.equal(actual.database, expectedDatabase, type + ' database') @@ -28,7 +25,11 @@ var compare = function (actual, expected, type) { assert.equal(actual.password, expected.password, type + ' password') assert.equal(actual.binary, expected.binary, type + ' binary') assert.equal(actual.statement_timeout, expected.statement_timeout, type + ' statement_timeout') - assert.equal(actual.idle_in_transaction_session_timeout, expected.idle_in_transaction_session_timeout, type + ' idle_in_transaction_session_timeout') + assert.equal( + actual.idle_in_transaction_session_timeout, + expected.idle_in_transaction_session_timeout, + type + ' idle_in_transaction_session_timeout' + ) } test('ConnectionParameters initializing from defaults', function () { @@ -68,37 +69,37 @@ test('ConnectionParameters initializing from config', function () { encoding: 'utf8', host: 'yo', ssl: { - asdf: 'blah' + asdf: 'blah', }, statement_timeout: 15000, - idle_in_transaction_session_timeout: 15000 + idle_in_transaction_session_timeout: 15000, } var subject = new ConnectionParameters(config) compare(subject, config, 'config') assert.ok(subject.isDomainSocket === false) }) -test('ConnectionParameters initializing from config and config.connectionString', function() { +test('ConnectionParameters initializing from config and config.connectionString', function () { var subject1 = new ConnectionParameters({ - connectionString: 'postgres://test@host/db' + connectionString: 'postgres://test@host/db', }) var subject2 = new ConnectionParameters({ - connectionString: 'postgres://test@host/db?ssl=1' + connectionString: 'postgres://test@host/db?ssl=1', }) var subject3 = new ConnectionParameters({ connectionString: 'postgres://test@host/db', - ssl: true + ssl: true, }) var subject4 = new ConnectionParameters({ connectionString: 'postgres://test@host/db?ssl=1', - ssl: false + ssl: false, }) assert.equal(subject1.ssl, false) assert.equal(subject2.ssl, true) assert.equal(subject3.ssl, true) assert.equal(subject4.ssl, true) -}); +}) test('escape spaces if present', function () { var subject = new ConnectionParameters('postgres://localhost/post gres') @@ -151,18 +152,20 @@ test('libpq connection string building', function () { password: 'xyz', port: 888, host: 'localhost', - database: 'bam' + 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'") - })) + 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 () { @@ -170,15 +173,17 @@ test('libpq connection string building', function () { user: 'brian', password: 'asdf', port: 5432, - host: 'localhost' + 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'") - })) + 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 () { @@ -186,13 +191,15 @@ test('libpq connection string building', function () { user: 'brian', password: 'asf', port: 5432, - host: 'asdlfkjasldfkksfd#!$!!!!..com' + host: 'asdlfkjasldfkksfd#!$!!!!..com', } var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString(assert.calls(function (err, constring) { - assert.ok(err) - assert.isNull(constring) - })) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert.ok(err) + assert.isNull(constring) + }) + ) }) test('connecting to unix domain socket', function () { @@ -200,43 +207,49 @@ test('libpq connection string building', function () { user: 'brian', password: 'asf', port: 5432, - host: '/tmp/' + 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/'") - })) + 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 () { var config = { user: 'not\\brian', - password: 'bad\'chars', + password: "bad'chars", port: 5432, - host: '/tmp/' + 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'") - })) + 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' + 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'") - })) + 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 () { @@ -246,9 +259,19 @@ test('libpq connection string building', function () { password: 'helloe', port: 5432, host: 'localhost', - database: 'postgres' + database: 'postgres', } - var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database + var connectionString = + 'postgres://' + + sourceConfig.user + + ':' + + sourceConfig.password + + '@' + + sourceConfig.host + + ':' + + sourceConfig.port + + '/' + + sourceConfig.database var subject = new ConnectionParameters(connectionString) assert.equal(subject.password, sourceConfig.password) }) @@ -293,19 +316,22 @@ test('libpq connection string building', function () { sslca: '/path/ca.pem', sslkey: '/path/cert.key', sslcert: '/path/cert.crt', - sslrootcert: '/path/root.crt' - } + sslrootcert: '/path/root.crt', + }, } var Client = require('../../../lib/client') var defaults = require('../../../lib/defaults') defaults.ssl = true var c = new ConnectionParameters(sourceConfig) - c.getLibpqConnectionString(assert.calls(function (err, pgCString) { - assert(!err) - assert.equal( - pgCString.indexOf('sslrootcert=\'/path/root.crt\'') !== -1, true, - 'libpqConnectionString should contain sslrootcert' - ) - })) + c.getLibpqConnectionString( + assert.calls(function (err, pgCString) { + assert(!err) + assert.equal( + pgCString.indexOf("sslrootcert='/path/root.crt'") !== -1, + true, + 'libpqConnectionString should contain sslrootcert' + ) + }) + ) }) }) diff --git a/packages/pg/test/unit/connection-parameters/environment-variable-tests.js b/packages/pg/test/unit/connection-parameters/environment-variable-tests.js index 2c5e503d..45d481e3 100644 --- a/packages/pg/test/unit/connection-parameters/environment-variable-tests.js +++ b/packages/pg/test/unit/connection-parameters/environment-variable-tests.js @@ -31,7 +31,7 @@ test('ConnectionParameters initialized from mix', function (t) { delete process.env['PGDATABASE'] var subject = new ConnectionParameters({ user: 'testing', - database: 'zugzug' + database: 'zugzug', }) assert.equal(subject.host, 'local', 'env host') assert.equal(subject.user, 'testing', 'config user') diff --git a/packages/pg/test/unit/connection/error-tests.js b/packages/pg/test/unit/connection/error-tests.js index f72e9ff0..5075c770 100644 --- a/packages/pg/test/unit/connection/error-tests.js +++ b/packages/pg/test/unit/connection/error-tests.js @@ -6,7 +6,7 @@ var net = require('net') const suite = new helper.Suite() suite.test('connection emits stream errors', function (done) { - var con = new Connection({stream: new MemoryStream()}) + var con = new Connection({ stream: new MemoryStream() }) assert.emits(con, 'error', function (err) { assert.equal(err.message, 'OMG!') done() @@ -16,7 +16,7 @@ suite.test('connection emits stream errors', function (done) { }) suite.test('connection emits ECONNRESET errors during normal operation', function (done) { - var con = new Connection({stream: new MemoryStream()}) + var con = new Connection({ stream: new MemoryStream() }) con.connect() assert.emits(con, 'error', function (err) { assert.equal(err.code, 'ECONNRESET') @@ -28,7 +28,7 @@ suite.test('connection emits ECONNRESET errors during normal operation', functio }) suite.test('connection does not emit ECONNRESET errors during disconnect', function (done) { - var con = new Connection({stream: new MemoryStream()}) + var con = new Connection({ stream: new MemoryStream() }) con.connect() var e = new Error('Connection Reset') e.code = 'ECONNRESET' @@ -42,20 +42,20 @@ var SSLNegotiationPacketTests = [ testName: 'connection does not emit ECONNRESET errors during disconnect also when using SSL', errorMessage: null, response: 'S', - responseType: 'sslconnect' + responseType: 'sslconnect', }, { testName: 'connection emits an error when SSL is not supported', errorMessage: 'The server does not support SSL connections', response: 'N', - responseType: 'error' + responseType: 'error', }, { testName: 'connection emits an error when postmaster responds to SSL negotiation packet', errorMessage: 'There was an error establishing an SSL connection', response: 'E', - responseType: 'error' - } + responseType: 'error', + }, ] for (var i = 0; i < SSLNegotiationPacketTests.length; i++) { @@ -71,7 +71,7 @@ for (var i = 0; i < SSLNegotiationPacketTests.length; i++) { }) server.listen(7778, function () { - var con = new Connection({ssl: true}) + var con = new Connection({ ssl: true }) con.connect(7778, 'localhost') assert.emits(con, tc.responseType, function (err) { if (tc.errorMessage !== null || err) { diff --git a/packages/pg/test/unit/connection/inbound-parser-tests.js b/packages/pg/test/unit/connection/inbound-parser-tests.js index 7bb9a432..5f92cdc5 100644 --- a/packages/pg/test/unit/connection/inbound-parser-tests.js +++ b/packages/pg/test/unit/connection/inbound-parser-tests.js @@ -16,7 +16,8 @@ var bindCompleteBuffer = buffers.bindComplete() var portalSuspendedBuffer = buffers.portalSuspended() var addRow = function (bufferList, name, offset) { - return bufferList.addCString(name) // field name + return bufferList + .addCString(name) // field name .addInt32(offset++) // table id .addInt16(offset++) // attribute of column number .addInt32(offset++) // objectId of field's data type @@ -32,24 +33,25 @@ var row1 = { dataTypeID: 3, dataTypeSize: 4, typeModifier: 5, - formatCode: 0 + formatCode: 0, } var oneRowDescBuff = new buffers.rowDescription([row1]) row1.name = 'bang' -var twoRowBuf = new buffers.rowDescription([row1, { - name: 'whoah', - tableID: 10, - attributeNumber: 11, - dataTypeID: 12, - dataTypeSize: 13, - typeModifier: 14, - formatCode: 0 -}]) +var twoRowBuf = new buffers.rowDescription([ + row1, + { + name: 'whoah', + tableID: 10, + attributeNumber: 11, + dataTypeID: 12, + dataTypeSize: 13, + typeModifier: 14, + formatCode: 0, + }, +]) -var emptyRowFieldBuf = new BufferList() - .addInt16(0) - .join(true, 'D') +var emptyRowFieldBuf = new BufferList().addInt16(0).join(true, 'D') var emptyRowFieldBuf = buffers.dataRow() @@ -63,31 +65,31 @@ var oneFieldBuf = buffers.dataRow(['test']) var expectedAuthenticationOkayMessage = { name: 'authenticationOk', - length: 8 + length: 8, } var expectedParameterStatusMessage = { name: 'parameterStatus', parameterName: 'client_encoding', parameterValue: 'UTF8', - length: 25 + length: 25, } var expectedBackendKeyDataMessage = { name: 'backendKeyData', processID: 1, - secretKey: 2 + secretKey: 2, } var expectedReadyForQueryMessage = { name: 'readyForQuery', length: 5, - status: 'I' + status: 'I', } var expectedCommandCompleteMessage = { length: 13, - text: 'SELECT 3' + text: 'SELECT 3', } var emptyRowDescriptionBuffer = new BufferList() .addInt16(0) // number of fields @@ -96,18 +98,18 @@ var emptyRowDescriptionBuffer = new BufferList() var expectedEmptyRowDescriptionMessage = { name: 'rowDescription', length: 6, - fieldCount: 0 + fieldCount: 0, } var expectedOneRowMessage = { name: 'rowDescription', length: 27, - fieldCount: 1 + fieldCount: 1, } var expectedTwoRowMessage = { name: 'rowDescription', length: 53, - fieldCount: 2 + fieldCount: 2, } var testForMessage = function (buffer, expectedMessage) { @@ -115,7 +117,7 @@ var testForMessage = function (buffer, expectedMessage) { test('recieves and parses ' + expectedMessage.name, function () { var stream = new MemoryStream() var client = new Connection({ - stream: stream + stream: stream, }) client.connect() @@ -140,11 +142,11 @@ var SASLContinueBuffer = buffers.authenticationSASLContinue() var SASLFinalBuffer = buffers.authenticationSASLFinal() var expectedPlainPasswordMessage = { - name: 'authenticationCleartextPassword' + name: 'authenticationCleartextPassword', } var expectedMD5PasswordMessage = { - name: 'authenticationMD5Password' + name: 'authenticationMD5Password', } var expectedSASLMessage = { @@ -166,7 +168,7 @@ var expectedNotificationResponseMessage = { name: 'notification', processId: 4, channel: 'hi', - payload: 'boom' + payload: 'boom', } test('Connection', function () { @@ -198,7 +200,7 @@ test('Connection', function () { test('no data message', function () { testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { - name: 'noData' + name: 'noData', }) }) @@ -215,7 +217,7 @@ test('Connection', function () { dataTypeID: 3, dataTypeSize: 4, dataTypeModifier: 5, - format: 'text' + format: 'text', }) }) }) @@ -233,7 +235,7 @@ test('Connection', function () { dataTypeID: 3, dataTypeSize: 4, dataTypeModifier: 5, - format: 'text' + format: 'text', }) }) test('has correct second field', function () { @@ -244,7 +246,7 @@ test('Connection', function () { dataTypeID: 12, dataTypeSize: 13, dataTypeModifier: 14, - format: 'text' + format: 'text', }) }) }) @@ -253,7 +255,7 @@ test('Connection', function () { test('parsing empty row', function () { var message = testForMessage(emptyRowFieldBuf, { name: 'dataRow', - fieldCount: 0 + fieldCount: 0, }) test('has 0 fields', function () { assert.equal(message.fields.length, 0) @@ -263,7 +265,7 @@ test('Connection', function () { test('parsing data row with fields', function () { var message = testForMessage(oneFieldBuf, { name: 'dataRow', - fieldCount: 1 + fieldCount: 1, }) test('has 1 field', function () { assert.equal(message.fields.length, 1) @@ -277,61 +279,75 @@ test('Connection', function () { test('notice message', function () { // this uses the same logic as error message - var buff = buffers.notice([{type: 'C', value: 'code'}]) + var buff = buffers.notice([{ type: 'C', value: 'code' }]) testForMessage(buff, { name: 'notice', - code: 'code' + code: 'code', }) }) test('error messages', function () { test('with no fields', function () { var msg = testForMessage(buffers.error(), { - name: 'error' + name: 'error', }) }) 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 - value: 'alsdkf' - }]) + 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 + value: 'alsdkf', + }, + ]) testForMessage(buffer, { name: 'error', @@ -346,33 +362,33 @@ test('Connection', function () { where: 'where', file: 'file', line: 'line', - routine: 'routine' + routine: 'routine', }) }) }) test('parses parse complete command', function () { testForMessage(parseCompleteBuffer, { - name: 'parseComplete' + name: 'parseComplete', }) }) test('parses bind complete command', function () { testForMessage(bindCompleteBuffer, { - name: 'bindComplete' + name: 'bindComplete', }) }) test('parses portal suspended message', function () { testForMessage(portalSuspendedBuffer, { - name: 'portalSuspended' + name: 'portalSuspended', }) }) test('parses replication start message', function () { testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { name: 'replicationStart', - length: 4 + length: 4, }) }) }) @@ -385,7 +401,7 @@ test('split buffer, single message parsing', function () { var stream = new MemoryStream() stream.readyState = 'open' var client = new Connection({ - stream: stream + stream: stream, }) client.connect() var message = null @@ -443,7 +459,7 @@ test('split buffer, multiple message parsing', function () { var messages = [] var stream = new MemoryStream() var client = new Connection({ - stream: stream + stream: stream, }) client.connect() client.on('message', function (msg) { @@ -454,11 +470,11 @@ test('split buffer, multiple message parsing', function () { assert.lengthIs(messages, 2) assert.same(messages[0], { name: 'dataRow', - fieldCount: 1 + fieldCount: 1, }) assert.equal(messages[0].fields[0], '!') assert.same(messages[1], { - name: 'readyForQuery' + name: 'readyForQuery', }) messages = [] } diff --git a/packages/pg/test/unit/connection/outbound-sending-tests.js b/packages/pg/test/unit/connection/outbound-sending-tests.js index 6c36401f..b40af000 100644 --- a/packages/pg/test/unit/connection/outbound-sending-tests.js +++ b/packages/pg/test/unit/connection/outbound-sending-tests.js @@ -3,7 +3,7 @@ require(__dirname + '/test-helper') var Connection = require(__dirname + '/../../../lib/connection') var stream = new MemoryStream() var con = new Connection({ - stream: stream + stream: stream, }) assert.received = function (stream, buffer) { @@ -15,18 +15,22 @@ assert.received = function (stream, buffer) { test('sends startup message', function () { con.startup({ user: 'brian', - database: 'bang' + database: 'bang', }) - assert.received(stream, new BufferList() - .addInt16(3) - .addInt16(0) - .addCString('user') - .addCString('brian') - .addCString('database') - .addCString('bang') - .addCString('client_encoding') - .addCString("'utf-8'") - .addCString('').join(true)) + assert.received( + stream, + new BufferList() + .addInt16(3) + .addInt16(0) + .addCString('user') + .addCString('brian') + .addCString('database') + .addCString('bang') + .addCString('client_encoding') + .addCString("'utf-8'") + .addCString('') + .join(true) + ) }) test('sends password message', function () { @@ -51,11 +55,8 @@ test('sends query message', function () { }) test('sends parse message', function () { - con.parse({text: '!'}) - var expected = new BufferList() - .addCString('') - .addCString('!') - .addInt16(0).join(true, 'P') + con.parse({ text: '!' }) + var expected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P') assert.received(stream, expected) }) @@ -63,19 +64,16 @@ test('sends parse message with named query', function () { con.parse({ name: 'boom', text: 'select * from boom', - types: [] + types: [], }) - var expected = new BufferList() - .addCString('boom') - .addCString('select * from boom') - .addInt16(0).join(true, 'P') + var expected = new BufferList().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P') assert.received(stream, expected) 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') @@ -84,7 +82,8 @@ test('sends parse message with named query', function () { .addInt32(1) .addInt32(2) .addInt32(3) - .addInt32(4).join(true, 'P') + .addInt32(4) + .join(true, 'P') assert.received(stream, expected) }) }) @@ -107,10 +106,10 @@ test('bind messages', function () { con.bind({ portal: 'bang', statement: 'woo', - values: ['1', 'hi', null, 'zing'] + values: ['1', 'hi', null, 'zing'], }) var expectedBuffer = new BufferList() - .addCString('bang') // portal name + .addCString('bang') // portal name .addCString('woo') // statement name .addInt16(0) .addInt16(4) @@ -131,16 +130,16 @@ test('with named statement, portal, and buffer value', function () { con.bind({ portal: 'bang', statement: 'woo', - values: ['1', 'hi', null, Buffer.from('zing', 'utf8')] + values: ['1', 'hi', null, Buffer.from('zing', 'utf8')], }) var expectedBuffer = new BufferList() - .addCString('bang') // portal name + .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) // value count + .addInt16(0) // string + .addInt16(0) // string + .addInt16(0) // string + .addInt16(1) // binary .addInt16(4) .addInt32(1) .add(Buffer.from('1')) @@ -157,22 +156,16 @@ test('with named statement, portal, and buffer value', function () { 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') + var expectedBuffer = new BufferList().addCString('').addInt32(0).join(true, 'E') assert.received(stream, expectedBuffer) }) test('for named portal with row limit', function () { con.execute({ portal: 'my favorite portal', - rows: 100 + rows: 100, }) - var expectedBuffer = new BufferList() - .addCString('my favorite portal') - .addInt32(100) - .join(true, 'E') + var expectedBuffer = new BufferList().addCString('my favorite portal').addInt32(100).join(true, 'E') assert.received(stream, expectedBuffer) }) }) @@ -198,13 +191,13 @@ test('sends end command', function () { test('sends describe command', function () { test('describe statement', function () { - con.describe({type: 'S', name: 'bang'}) + con.describe({ type: 'S', name: 'bang' }) var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D') assert.received(stream, expected) }) test('describe unnamed portal', function () { - con.describe({type: 'P'}) + con.describe({ type: 'P' }) var expected = new BufferList().addChar('P').addCString('').join(true, 'D') assert.received(stream, expected) }) diff --git a/packages/pg/test/unit/connection/startup-tests.js b/packages/pg/test/unit/connection/startup-tests.js index dc793e69..09a710c7 100644 --- a/packages/pg/test/unit/connection/startup-tests.js +++ b/packages/pg/test/unit/connection/startup-tests.js @@ -3,7 +3,7 @@ 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}) + var con = new Connection({ stream: stream }) assert.equal(con.stream, stream) }) @@ -21,7 +21,7 @@ test('using closed stream', function () { var stream = makeStream() - var con = new Connection({stream: stream}) + var con = new Connection({ stream: stream }) con.connect(1234, 'bang') @@ -72,7 +72,7 @@ test('using opened stream', function () { stream.connect = function () { assert.ok(false, 'Should not call open') } - var con = new Connection({stream: stream}) + var con = new Connection({ stream: stream }) test('does not call open', function () { var hit = false con.once('connect', function () { diff --git a/packages/pg/test/unit/test-helper.js b/packages/pg/test/unit/test-helper.js index 04b73f37..5793251b 100644 --- a/packages/pg/test/unit/test-helper.js +++ b/packages/pg/test/unit/test-helper.js @@ -15,29 +15,29 @@ var p = MemoryStream.prototype p.write = function (packet, cb) { this.packets.push(packet) - if(cb){ - cb(); + if (cb) { + cb() } } -p.end = function() { - p.closed = true; +p.end = function () { + p.closed = true } p.setKeepAlive = function () {} -p.closed = false; +p.closed = false p.writable = true const createClient = function () { var stream = new MemoryStream() stream.readyState = 'open' var client = new Client({ - connection: new Connection({stream: stream}) + connection: new Connection({ stream: stream }), }) client.connect() return client } module.exports = Object.assign({}, helper, { - createClient: createClient + createClient: createClient, }) diff --git a/packages/pg/test/unit/utils-tests.js b/packages/pg/test/unit/utils-tests.js index 4308f7a1..3d087ad0 100644 --- a/packages/pg/test/unit/utils-tests.js +++ b/packages/pg/test/unit/utils-tests.js @@ -29,7 +29,7 @@ test('EventEmitter.once', function (t) { test('normalizing query configs', function () { var config - var callback = function () { } + var callback = function () {} config = utils.normalizeQueryConfig({ text: 'TEXT' }) assert.same(config, { text: 'TEXT' }) @@ -162,7 +162,7 @@ test('prepareValue: objects with simple toPostgres prepared properly', function var customType = { toPostgres: function () { return 'zomgcustom!' - } + }, } var out = utils.prepareValue(customType) assert.strictEqual(out, 'zomgcustom!') @@ -180,7 +180,7 @@ test('prepareValue: objects with complex toPostgres prepared properly', function var customType = { toPostgres: function () { return [1, 2] - } + }, } var out = utils.prepareValue(customType) assert.strictEqual(out, '{"1","2"}') @@ -188,11 +188,19 @@ test('prepareValue: objects with complex toPostgres prepared properly', function test('prepareValue: objects with toPostgres receive prepareValue', function () { var customRange = { - lower: { toPostgres: function () { return 5 } }, - upper: { toPostgres: function () { return 10 } }, + 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]') @@ -202,8 +210,12 @@ test('prepareValue: objects with circular toPostgres rejected', function () { var buf = Buffer.from('zomgcustom!') var customType = { toPostgres: function () { - return { toPostgres: function () { return customType } } - } + return { + toPostgres: function () { + return customType + }, + } + }, } // can't use `assert.throws` since we need to distinguish circular reference @@ -221,7 +233,7 @@ test('prepareValue: can safely be used to map an array of values including those var customType = { toPostgres: function () { return 'zomgcustom!' - } + }, } var values = [1, 'test', customType] var out = values.map(utils.prepareValue) diff --git a/yarn.lock b/yarn.lock index 43c90a76..f309fe97 100644 --- a/yarn.lock +++ b/yarn.lock @@ -836,6 +836,11 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.7.tgz#1c8c25cbf6e59ffa7d6b9652c78e547d9a41692d" integrity sha512-luq8meHGYwvky0O7u0eQZdA7B4Wd9owUCqvbw2m3XCrCU8mplYOujMBbvyS547AxJkC+pGnd0Cm15eNxEUNU8g== +"@types/eslint-visitor-keys@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" + integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" @@ -850,6 +855,11 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/json-schema@^7.0.3": + version "7.0.4" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" + integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -865,6 +875,49 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.21.tgz#aa44a6363291c7037111c47e4661ad210aded23f" integrity sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA== +"@typescript-eslint/eslint-plugin@^2.27.0": + version "2.27.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.27.0.tgz#e479cdc4c9cf46f96b4c287755733311b0d0ba4b" + integrity sha512-/my+vVHRN7zYgcp0n4z5A6HAK7bvKGBiswaM5zIlOQczsxj/aiD7RcgD+dvVFuwFaGh5+kM7XA6Q6PN0bvb1tw== + dependencies: + "@typescript-eslint/experimental-utils" "2.27.0" + functional-red-black-tree "^1.0.1" + regexpp "^3.0.0" + tsutils "^3.17.1" + +"@typescript-eslint/experimental-utils@2.27.0": + version "2.27.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.27.0.tgz#801a952c10b58e486c9a0b36cf21e2aab1e9e01a" + integrity sha512-vOsYzjwJlY6E0NJRXPTeCGqjv5OHgRU1kzxHKWJVPjDYGbPgLudBXjIlc+OD1hDBZ4l1DLbOc5VjofKahsu9Jw== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.27.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/parser@^2.27.0": + version "2.27.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.27.0.tgz#d91664335b2c46584294e42eb4ff35838c427287" + integrity sha512-HFUXZY+EdwrJXZo31DW4IS1ujQW3krzlRjBrFRrJcMDh0zCu107/nRfhk/uBasO8m0NVDbBF5WZKcIUMRO7vPg== + dependencies: + "@types/eslint-visitor-keys" "^1.0.0" + "@typescript-eslint/experimental-utils" "2.27.0" + "@typescript-eslint/typescript-estree" "2.27.0" + eslint-visitor-keys "^1.1.0" + +"@typescript-eslint/typescript-estree@2.27.0": + version "2.27.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.27.0.tgz#a288e54605412da8b81f1660b56c8b2e42966ce8" + integrity sha512-t2miCCJIb/FU8yArjAvxllxbTiyNqaXJag7UOpB5DVoM3+xnjeOngtqlJkLRnMtzaRcJhe3CIR9RmL40omubhg== + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^6.3.0" + tsutils "^3.17.1" + "@zkochan/cmd-shim@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz#2ab8ed81f5bb5452a85f25758eb9b8681982fd2e" @@ -1772,7 +1825,7 @@ debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: dependencies: ms "2.0.0" -debug@^4.0.1: +debug@^4.0.1, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -2036,10 +2089,10 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -eslint-config-prettier@^6.4.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.7.0.tgz#9a876952e12df2b284adbd3440994bf1f39dfbb9" - integrity sha512-FamQVKM3jjUVwhG4hEMnbtsq7xOIDm+SY5iBPfR8gKsJoAB2IQnNF+bk1+8Fy44Nq7PPJaLvkRxILYdJWoguKQ== +eslint-config-prettier@^6.10.1: + version "6.10.1" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.10.1.tgz#129ef9ec575d5ddc0e269667bf09defcd898642a" + integrity sha512-svTy6zh1ecQojvpbJSgH3aei/Rt7C6i090l5f2WQ4aB05lYHeZIR1qL4wZyyILTbtmnbHP5Yn8MrsOJMGa8RkQ== dependencies: get-stdin "^6.0.0" @@ -2072,6 +2125,14 @@ eslint-plugin-es@^1.4.1: eslint-utils "^1.4.2" regexpp "^2.0.1" +eslint-plugin-es@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz#98cb1bc8ab0aa807977855e11ad9d1c9422d014b" + integrity sha512-6/Jb/J/ZvSebydwbBJO1R9E5ky7YeElfK56Veh7e4QGFHCXoIXGH9HhVz+ibJLM3XJ1XjP+T7rKBLUa/Y7eIng== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + eslint-plugin-import@^2.18.1: version "2.19.1" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.19.1.tgz#5654e10b7839d064dd0d46cd1b88ec2133a11448" @@ -2090,6 +2151,18 @@ eslint-plugin-import@^2.18.1: read-pkg-up "^2.0.0" resolve "^1.12.0" +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + eslint-plugin-node@^9.1.0: version "9.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-9.2.0.tgz#b1911f111002d366c5954a6d96d3cd5bf2a3036a" @@ -2102,7 +2175,7 @@ eslint-plugin-node@^9.1.0: resolve "^1.10.1" semver "^6.1.0" -eslint-plugin-prettier@^3.1.1: +eslint-plugin-prettier@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" integrity sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA== @@ -2139,12 +2212,19 @@ eslint-utils@^1.4.2, eslint-utils@^1.4.3: dependencies: eslint-visitor-keys "^1.1.0" +eslint-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" + integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA== + dependencies: + eslint-visitor-keys "^1.1.0" + eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== -eslint@^6.0.1, eslint@^6.5.1: +eslint@^6.0.1: version "6.7.2" resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.2.tgz#c17707ca4ad7b2d8af986a33feba71e18a9fecd1" integrity sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng== @@ -2187,6 +2267,49 @@ eslint@^6.0.1, eslint@^6.5.1: text-table "^0.2.0" v8-compile-cache "^2.0.3" +eslint@^6.8.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" + integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.10.0" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^5.0.0" + eslint-utils "^1.4.3" + eslint-visitor-keys "^1.1.0" + espree "^6.1.2" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^7.0.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.14" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.3" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + espree@^6.1.2: version "6.1.2" resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" @@ -2684,7 +2807,7 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: +glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -4509,10 +4632,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^1.18.2: - version "1.19.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" - integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== +prettier@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.4.tgz#2d1bae173e355996ee355ec9830a7a1ee05457ef" + integrity sha512-SVJIQ51spzFDvh4fIbCLvciiDMCrRhlN3mbZvv/+ycjvmF5E73bKdGfU8QDLNmjYJf+lsGnDBC4UUnvTe5OO0w== process-nextick-args@~2.0.0: version "2.0.1" @@ -4763,6 +4886,11 @@ regexpp@^2.0.1: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== +regexpp@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + render@0.1: version "0.1.4" resolved "https://registry.yarnpkg.com/render/-/render-0.1.4.tgz#cfb33a34e26068591d418469e23d8cc5ce1ceff5" @@ -4945,7 +5073,7 @@ semver@4.3.2: resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= -semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -5554,11 +5682,23 @@ ts-node@^8.5.4: source-map-support "^0.5.6" yn "^3.0.0" +tslib@^1.8.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" + integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== + tslib@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tsutils@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" + integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== + dependencies: + tslib "^1.8.1" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"