From fe47c041d5d5840bb4620c913b423b8fc3dae970 Mon Sep 17 00:00:00 2001 From: Daniel Durante Date: Thu, 2 Jan 2020 19:43:53 -0500 Subject: [PATCH] Pg: Adds a boolean value for PoolClient.release's support for truthy and error values (#41040) * Formats code * Adds boolean value for Pool.release's support for truthy and error values --- types/pg/index.d.ts | 95 +++++++++++----- types/pg/pg-tests.ts | 255 +++++++++++++++++++++++-------------------- 2 files changed, 203 insertions(+), 147 deletions(-) diff --git a/types/pg/index.d.ts b/types/pg/index.d.ts index 255165a1df..db132d570a 100644 --- a/types/pg/index.d.ts +++ b/types/pg/index.d.ts @@ -6,9 +6,9 @@ /// -import events = require("events"); -import stream = require("stream"); -import pgTypes = require("pg-types"); +import events = require('events'); +import stream = require('stream'); +import pgTypes = require('pg-types'); import { ConnectionOptions } from "tls"; @@ -81,7 +81,7 @@ export interface QueryResultBase { } export interface QueryResultRow { - [column: string]: any; + [column: string]: any; } export interface QueryResult extends QueryResultBase { @@ -112,7 +112,7 @@ export interface BindConfig { portal?: string; statement?: string; binary?: string; - values?: Array<(Buffer | null | undefined | string)>; + values?: Array; } export interface ExecuteConfig { @@ -167,16 +167,34 @@ export class Pool extends events.EventEmitter { query(queryStream: T): T; // tslint:disable:no-unnecessary-generics - query(queryConfig: QueryArrayConfig, values?: I): Promise>; - query(queryConfig: QueryConfig): Promise>; - query(queryTextOrConfig: string | QueryConfig, values?: I): Promise>; - query(queryConfig: QueryArrayConfig, callback: (err: Error, result: QueryArrayResult) => void): void; - query(queryTextOrConfig: string | QueryConfig, callback: (err: Error, result: QueryResult) => void): void; - query(queryText: string, values: I, callback: (err: Error, result: QueryResult) => void): void; + query( + queryConfig: QueryArrayConfig, + values?: I, + ): Promise>; + query( + queryConfig: QueryConfig, + ): Promise>; + query( + queryTextOrConfig: string | QueryConfig, + values?: I, + ): Promise>; + query( + queryConfig: QueryArrayConfig, + callback: (err: Error, result: QueryArrayResult) => void, + ): void; + query( + queryTextOrConfig: string | QueryConfig, + callback: (err: Error, result: QueryResult) => void, + ): void; + query( + queryText: string, + values: I, + callback: (err: Error, result: QueryResult) => void, + ): void; // tslint:enable:no-unnecessary-generics - on(event: "error", listener: (err: Error, client: PoolClient) => void): this; - on(event: "connect" | "acquire" | "remove", listener: (client: PoolClient) => void): this; + on(event: 'error', listener: (err: Error, client: PoolClient) => void): this; + on(event: 'connect' | 'acquire' | 'remove', listener: (client: PoolClient) => void): this; } export class ClientBase extends events.EventEmitter { @@ -187,12 +205,30 @@ export class ClientBase extends events.EventEmitter { query(queryStream: T): T; // tslint:disable:no-unnecessary-generics - query(queryConfig: QueryArrayConfig, values?: I): Promise>; - query(queryConfig: QueryConfig): Promise>; - query(queryTextOrConfig: string | QueryConfig, values?: I): Promise>; - query(queryConfig: QueryArrayConfig, callback: (err: Error, result: QueryArrayResult) => void): void; - query(queryTextOrConfig: string | QueryConfig, callback: (err: Error, result: QueryResult) => void): void; - query(queryText: string, values: any[], callback: (err: Error, result: QueryResult) => void): void; + query( + queryConfig: QueryArrayConfig, + values?: I, + ): Promise>; + query( + queryConfig: QueryConfig, + ): Promise>; + query( + queryTextOrConfig: string | QueryConfig, + values?: I, + ): Promise>; + query( + queryConfig: QueryArrayConfig, + callback: (err: Error, result: QueryArrayResult) => void, + ): void; + query( + queryTextOrConfig: string | QueryConfig, + callback: (err: Error, result: QueryResult) => void, + ): void; + query( + queryText: string, + values: any[], + callback: (err: Error, result: QueryResult) => void, + ): void; // tslint:enable:no-unnecessary-generics copyFrom(queryText: string): stream.Writable; @@ -204,11 +240,11 @@ export class ClientBase extends events.EventEmitter { escapeIdentifier(str: string): string; escapeLiteral(str: string): string; - on(event: "drain", listener: () => void): this; - on(event: "error" | "notice", listener: (err: Error) => void): this; - on(event: "notification", listener: (message: Notification) => void): this; + on(event: 'drain', listener: () => void): this; + on(event: 'error' | 'notice', listener: (err: Error) => void): this; + on(event: 'notification', listener: (message: Notification) => void): this; // tslint:disable-next-line unified-signatures - on(event: "end", listener: () => void): this; + on(event: 'end', listener: () => void): this; } export class Client extends ClientBase { @@ -219,19 +255,20 @@ export class Client extends ClientBase { } export interface PoolClient extends ClientBase { - release(err?: Error): void; + release(err?: Error | boolean): void; } -export class Query extends events.EventEmitter implements Submittable { +export class Query extends events.EventEmitter + implements Submittable { constructor(queryTextOrConfig?: string | QueryConfig, values?: I); submit: (connection: Connection) => void; - on(event: "row", listener: (row: R, result?: ResultBuilder) => void): this; - on(event: "error", listener: (err: Error) => void): this; - on(event: "end", listener: (result: ResultBuilder) => void): this; + on(event: 'row', listener: (row: R, result?: ResultBuilder) => void): this; + on(event: 'error', listener: (err: Error) => void): this; + on(event: 'end', listener: (result: ResultBuilder) => void): this; } export class Events extends events.EventEmitter { - on(event: "error", listener: (err: Error, client: Client) => void): this; + on(event: 'error', listener: (err: Error, client: Client) => void): this; } export const types: typeof pgTypes; diff --git a/types/pg/pg-tests.ts b/types/pg/pg-tests.ts index 673f4105e4..26332a803e 100644 --- a/types/pg/pg-tests.ts +++ b/types/pg/pg-tests.ts @@ -1,128 +1,135 @@ -import { types, Client, QueryArrayConfig, Pool } from "pg"; +import { types, Client, QueryArrayConfig, Pool } from 'pg'; // https://github.com/brianc/node-pg-types // tslint:disable-next-line no-unnecessary-callback-wrapper types.setTypeParser(20, val => Number(val)); const client = new Client({ - host: 'my.database-server.com', - port: 5334, - user: 'database-user', - password: 'secretpassword!!', - keepAlive: true, + host: 'my.database-server.com', + port: 5334, + user: 'database-user', + password: 'secretpassword!!', + keepAlive: true, }); client.connect(err => { if (err) { - console.error("Could not connect to postgres", err); + console.error('Could not connect to postgres', err); return; } client.query("SELECT NOW() AS 'theTime'", (err, result) => { if (err) { - console.error("Error running query", err); + console.error('Error running query', err); return; } console.log(result.rowCount); - console.log(result.rows[0]["theTime"]); + console.log(result.rows[0]['theTime']); client.end(); return null; }); return null; }); -client.on('end', () => console.log("Client was disconnected.")); +client.on('end', () => console.log('Client was disconnected.')); -client.connect() - .then(() => console.log('connected')) - .catch(e => console.error('connection error', e.stack)); +client + .connect() + .then(() => console.log('connected')) + .catch(e => console.error('connection error', e.stack)); client.query('SELECT NOW()', (err, res) => { - if (err) throw err; - console.log(res); - client.end(); + if (err) throw err; + console.log(res); + client.end(); }); client.query('SELECT $1::text as name', ['brianc'], (err, res) => { - if (err) throw err; - console.log(res); - client.end(); + if (err) throw err; + console.log(res); + client.end(); }); interface Person { - name: string; + name: string; } client.query('SELECT $1::text as name', ['brianc'], (err, res) => { - if (err) throw err; - console.log(res.rows[0].name); - client.end(); + if (err) throw err; + console.log(res.rows[0].name); + client.end(); }); const query = { - name: 'get-name', - text: 'SELECT $1::text', - values: ['brianc'] + name: 'get-name', + text: 'SELECT $1::text', + values: ['brianc'], }; client.query(query, (err, res) => { - if (err) { - console.error(err.stack); - } else { - console.log(res.rows); - console.log(res.fields.map(f => f.name)); - } + if (err) { + console.error(err.stack); + } else { + console.log(res.rows); + console.log(res.fields.map(f => f.name)); + } }); -client.query(query) - .then(res => { - console.log(res.rows); - console.log(res.fields.map(f => f.name)); - }) - .catch(e => { - console.error(e.stack); - }); -client.query(query, ['brianc']) - .then(res => { - console.log(res.rows); - console.log(res.fields.map(f => f.name)); - }) - .catch(e => { - console.error(e.stack); - }); +client + .query(query) + .then(res => { + console.log(res.rows); + console.log(res.fields.map(f => f.name)); + }) + .catch(e => { + console.error(e.stack); + }); +client + .query(query, ['brianc']) + .then(res => { + console.log(res.rows); + console.log(res.fields.map(f => f.name)); + }) + .catch(e => { + console.error(e.stack); + }); const queryArrMode: QueryArrayConfig = { - name: 'get-name-array', - text: 'SELECT $1::text', - values: ['brianc'], - rowMode: 'array' + name: 'get-name-array', + text: 'SELECT $1::text', + values: ['brianc'], + rowMode: 'array', }; client.query(queryArrMode, (err, res) => { - if (err) { - console.error(err.stack); - } else { - console.log(res.rows); - console.log(res.fields.map(f => f.name)); - } + if (err) { + console.error(err.stack); + } else { + console.log(res.rows); + console.log(res.fields.map(f => f.name)); + } }); -client.query(queryArrMode) - .then(res => { - console.log(res.rows); - console.log(res.fields.map(f => f.name)); - }) - .catch(e => { - console.error(e.stack); - }); -client.query({ - text: 'select 1', - rowMode: 'array', -}).then(res => console.log(res.fields[0])); +client + .query(queryArrMode) + .then(res => { + console.log(res.rows); + console.log(res.fields.map(f => f.name)); + }) + .catch(e => { + console.error(e.stack); + }); +client + .query({ + text: 'select 1', + rowMode: 'array', + }) + .then(res => console.log(res.fields[0])); -client.end((err) => { - console.log('client has disconnected'); - if (err) { - console.log('error during disconnection', err.stack); - } +client.end(err => { + console.log('client has disconnected'); + if (err) { + console.log('error during disconnection', err.stack); + } }); -client.end() - .then(() => console.log('client has disconnected')) - .catch(err => console.error('error during disconnection', err.stack)); +client + .end() + .then(() => console.log('client has disconnected')) + .catch(err => console.error('error during disconnection', err.stack)); // pg.Pool // https://node-postgres.com/api/pool @@ -131,74 +138,86 @@ client.end() const poolParameterlessCtor = new Pool(); const poolOne = new Pool({ - connectionString: 'postgresql://dbuser:secretpassword@database.server.com:3211/mydb' + connectionString: 'postgresql://dbuser:secretpassword@database.server.com:3211/mydb', }); const pool = new Pool({ - host: 'localhost', - port: 5432, - user: 'database-user', - database: 'my_db', - max: 20, - idleTimeoutMillis: 30000, - connectionTimeoutMillis: 2000, - keepAlive: false, - log: (...args) => { - console.log.apply(console, args); - }, + host: 'localhost', + port: 5432, + user: 'database-user', + database: 'my_db', + max: 20, + idleTimeoutMillis: 30000, + connectionTimeoutMillis: 2000, + keepAlive: false, + log: (...args) => { + console.log.apply(console, args); + }, }); console.log(pool.totalCount); pool.connect((err, client, done) => { - if (err) { - console.error('error fetching client from pool', err); - return; - } - client.query('SELECT $1::int AS number', ['1'], (err, result) => { - done(); - if (err) { - console.error('error running query', err); - return; + console.error('error fetching client from pool', err); + return; } - console.log(result.rows[0].number); - }); + client.query('SELECT $1::int AS number', ['1'], (err, result) => { + done(); + + if (err) { + console.error('error running query', err); + return; + } + console.log(result.rows[0].number); + }); }); pool.connect().then(client => { - client.query({ text: 'SELECT $1::int AS number', values: ['1'], rowMode: 'array' }).then(result => { - console.log(result.rowCount, result.rows[0][0], result.fields[0].name); - }).then(() => client.release(), e => client.release(e)); + client + .query({ text: 'SELECT $1::int AS number', values: ['1'], rowMode: 'array' }) + .then(result => { + console.log(result.rowCount, result.rows[0][0], result.fields[0].name); + }) + .then( + () => client.release(), + e => client.release(e), + ); }); pool.on('error', (err, client) => { - console.error('idle client error', err.message, err.stack); + console.error('idle client error', err.message, err.stack); }); +(async () => { + const client = await pool.connect(); + await client.query('SELECT 1'); + client.release(true); +})(); + pool.query('SELECT $1::text as name', ['brianc'], (err, result) => { - if (err) { - console.error('Error executing query', err.stack); - return; - } - console.log(result.rows[0].name); + if (err) { + console.error('Error executing query', err.stack); + return; + } + console.log(result.rows[0].name); }); pool.query('SELECT $1::text as name', ['brianc']) - .then((res) => console.log(res.rows[0].name)) - .catch(err => console.error('Error executing query', err.stack)); + .then(res => console.log(res.rows[0].name)) + .catch(err => console.error('Error executing query', err.stack)); pool.query({ text: 'SELECT $1::text as name' }, ['brianc']) - .then((res) => console.log(res.rows[0].name)) - .catch(err => console.error('Error executing query', err.stack)); + .then(res => console.log(res.rows[0].name)) + .catch(err => console.error('Error executing query', err.stack)); pool.end(() => { - console.log('pool has ended'); + console.log('pool has ended'); }); pool.end().then(() => console.log('pool has ended')); (async () => { - const client = await pool.connect(); - await client.query('SELECT NOW()'); - client.release(); + const client = await pool.connect(); + await client.query('SELECT NOW()'); + client.release(); })(); // client constructor tests