node-postgres icon indicating copy to clipboard operation
node-postgres copied to clipboard

Improve support for multiple results

Open ViktorQvarfordt opened this issue 1 year ago • 0 comments

The return type from pool.query (or client.query) is QueryResult, which is incorrect when multiple statements are executed. In that case the type is QueryResult[].

Example showing the problem:

import pg from 'pg'

// docker run --rm -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres:15-alpine
const pool = new pg.Pool({ connectionString: 'postgresql://postgres:postgres@localhost:5432/postgres' })

const results = await pool.query(`
  SELECT 1;
  SELECT 2;
`)

console.log(results[1].rows) // TS ERROR: 'QueryResult<any>' cannot be indexed. It is not an array.

But the code runs as expected.

I think this pattern of making the object an array or an object is not so good. The correct type right now is QueryResult | QueryResult[] which is difficult to work with since one would need to check if (Array.isArray(result)) each type to do type narrowing.

I suggest that we make the following (mostly) backwards compatible change: Change the return type of query to QueryResult & QueryResult[]. It may look strange but it is fully doable in both javascript and typescript; an array that also has object properties.

Proof of concept code:

type SingleQueryResult = { rows: string[] }

type QueryResult = SingleQueryResult & SingleQueryResult[]

const mockResult0 = { rows: ['result-0-row-0'] }
const mockResult1 = { rows: ['result-1-row-0'] }
const mockResult: QueryResult = Object.assign([mockResult0, mockResult1], mockResult0)

const resultDefault = mockResult
const result1 = mockResult[1]
console.log(resultDefault.rows[0] === 'result-0-row-0' && result1?.rows[0] === 'result-1-row-0') // true

ViktorQvarfordt avatar Jan 05 '24 10:01 ViktorQvarfordt