diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index 77a410626..ff27662e6 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -44,7 +44,7 @@ The simplest possible way to connect, query, and disconnect is with async/await: ```js import { Client } from 'pg' -const client = await new Client().connect(); +const client = await new Client().connect() const res = await client.query('SELECT $1::text as message', ['Hello world!']) console.log(res.rows[0].message) // Hello world! @@ -55,10 +55,9 @@ await client.end() For the sake of simplicity, these docs will assume that the methods are successful. In real life use, make sure to properly handle errors thrown in the methods. A `try/catch` block is a great way to do so: -```ts +```js import { Client } from 'pg' -const client = new Client() -await client.connect() +const client = await new Client().connect() try { const res = await client.query('SELECT $1::text as message', ['Hello world!']) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index df430f881..b0214e3dc 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -407,23 +407,47 @@ class Client extends EventEmitter { } _handleRowDescription(msg) { + const activeQuery = this._getActiveQuery() + if (activeQuery == null) { + const error = new Error('Received unexpected rowDescription message from backend.') + this._handleErrorEvent(error) + return + } // delegate rowDescription to active query - this._getActiveQuery().handleRowDescription(msg) + activeQuery.handleRowDescription(msg) } _handleDataRow(msg) { + const activeQuery = this._getActiveQuery() + if (activeQuery == null) { + const error = new Error('Received unexpected dataRow message from backend.') + this._handleErrorEvent(error) + return + } // delegate dataRow to active query - this._getActiveQuery().handleDataRow(msg) + activeQuery.handleDataRow(msg) } _handlePortalSuspended(msg) { + const activeQuery = this._getActiveQuery() + if (activeQuery == null) { + const error = new Error('Received unexpected portalSuspended message from backend.') + this._handleErrorEvent(error) + return + } // delegate portalSuspended to active query - this._getActiveQuery().handlePortalSuspended(this.connection) + activeQuery.handlePortalSuspended(this.connection) } _handleEmptyQuery(msg) { + const activeQuery = this._getActiveQuery() + if (activeQuery == null) { + const error = new Error('Received unexpected emptyQuery message from backend.') + this._handleErrorEvent(error) + return + } // delegate emptyQuery to active query - this._getActiveQuery().handleEmptyQuery(this.connection) + activeQuery.handleEmptyQuery(this.connection) } _handleCommandComplete(msg) { @@ -453,11 +477,23 @@ class Client extends EventEmitter { } _handleCopyInResponse(msg) { - this._getActiveQuery().handleCopyInResponse(this.connection) + const activeQuery = this._getActiveQuery() + if (activeQuery == null) { + const error = new Error('Received unexpected copyInResponse message from backend.') + this._handleErrorEvent(error) + return + } + activeQuery.handleCopyInResponse(this.connection) } _handleCopyData(msg) { - this._getActiveQuery().handleCopyData(msg, this.connection) + const activeQuery = this._getActiveQuery() + if (activeQuery == null) { + const error = new Error('Received unexpected copyData message from backend.') + this._handleErrorEvent(error) + return + } + activeQuery.handleCopyData(msg, this.connection) } _handleNotification(msg) { diff --git a/packages/pg/test/integration/gh-issues/3174-tests.js b/packages/pg/test/integration/gh-issues/3174-tests.js index 9949c8071..462cb825e 100644 --- a/packages/pg/test/integration/gh-issues/3174-tests.js +++ b/packages/pg/test/integration/gh-issues/3174-tests.js @@ -165,4 +165,10 @@ const testErrorBuffer = (bufferName, errorBuffer) => { if (!helper.args.native) { testErrorBuffer('parseComplete', buffers.parseComplete()) testErrorBuffer('commandComplete', buffers.commandComplete('f')) + testErrorBuffer('rowDescription', buffers.rowDescription()) + testErrorBuffer('dataRow', buffers.dataRow()) + testErrorBuffer('portalSuspended', buffers.portalSuspended()) + testErrorBuffer('emptyQuery', buffers.emptyQuery()) + testErrorBuffer('copyIn', buffers.copyIn(0)) + testErrorBuffer('copyData', buffers.copyData(Buffer.from([1, 2, 3]))) } diff --git a/packages/pg/test/test-buffers.js b/packages/pg/test/test-buffers.js index 576d22f7e..8beee33ec 100644 --- a/packages/pg/test/test-buffers.js +++ b/packages/pg/test/test-buffers.js @@ -118,4 +118,20 @@ buffers.portalSuspended = function () { return new BufferList().join(true, 's') } +buffers.copyIn = function (cols) { + const list = new BufferList() + // text mode + .add(Buffer.from([0])) + // column count + .addInt16(cols) + for (let i = 0; i < cols; i++) { + list.addInt16(i) + } + return list.join(true, 'G') +} + +buffers.copyData = function (bytes) { + return new BufferList().add(bytes).join(true, 'd') +} + module.exports = buffers