From 1b4518fe69c63036b92ceab5c0fac8a7e279baee Mon Sep 17 00:00:00 2001 From: alxndrsn Date: Tue, 14 May 2024 08:07:04 +0000 Subject: [PATCH 1/5] maybe? --- docs/pages/apis/client.mdx | 4 ++++ packages/pg/lib/native/query.js | 3 +++ packages/pg/lib/query.js | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/docs/pages/apis/client.mdx b/docs/pages/apis/client.mdx index 8175448e2..24100ac31 100644 --- a/docs/pages/apis/client.mdx +++ b/docs/pages/apis/client.mdx @@ -75,6 +75,10 @@ type QueryConfig { // custom type parsers just for this query result types?: Types; + + // force extended query usage - prevents multiple statements in a + // single query + forcePreparation?: boolean; } ``` diff --git a/packages/pg/lib/native/query.js b/packages/pg/lib/native/query.js index d06db43ca..364ffab99 100644 --- a/packages/pg/lib/native/query.js +++ b/packages/pg/lib/native/query.js @@ -10,6 +10,7 @@ var NativeQuery = (module.exports = function (config, values, callback) { this.text = config.text this.values = config.values this.name = config.name + this.forcePreparation = config.forcePreparation this.callback = config.callback this.state = 'new' this._arrayMode = config.rowMode === 'array' @@ -159,6 +160,8 @@ NativeQuery.prototype.submit = function (client) { } var vals = this.values.map(utils.prepareValue) client.native.query(this.text, vals, after) + } else if (this.forcePreparation) { + client.native.query(this.text, [], after) } else { client.native.query(this.text, after) } diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index fac4d86e3..fbc8b9322 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -16,6 +16,7 @@ class Query extends EventEmitter { this.rows = config.rows this.types = config.types this.name = config.name + this.forcePreparation = config.forcePreparation this.binary = config.binary // use unique portal name each time this.portal = config.portal || '' @@ -32,6 +33,11 @@ class Query extends EventEmitter { } requiresPreparation() { + // preparation has been requested + if (this.forcePreparation) { + return true + } + // named queries must always be prepared if (this.name) { return true From 7706ccb05a1e83859d35e85d98fae2d6d2247911 Mon Sep 17 00:00:00 2001 From: alxndrsn Date: Thu, 16 May 2024 08:14:43 +0000 Subject: [PATCH 2/5] Add test; use string for queryMode --- docs/pages/apis/client.mdx | 5 ++-- packages/pg/lib/native/query.js | 4 +-- packages/pg/lib/query.js | 5 ++-- .../client/multiple-results-tests.js | 25 +++++++++++++++++++ 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/docs/pages/apis/client.mdx b/docs/pages/apis/client.mdx index 24100ac31..648136139 100644 --- a/docs/pages/apis/client.mdx +++ b/docs/pages/apis/client.mdx @@ -76,9 +76,8 @@ type QueryConfig { // custom type parsers just for this query result types?: Types; - // force extended query usage - prevents multiple statements in a - // single query - forcePreparation?: boolean; + // TODO: document + queryMode?: string; } ``` diff --git a/packages/pg/lib/native/query.js b/packages/pg/lib/native/query.js index 364ffab99..932ab8746 100644 --- a/packages/pg/lib/native/query.js +++ b/packages/pg/lib/native/query.js @@ -10,7 +10,7 @@ var NativeQuery = (module.exports = function (config, values, callback) { this.text = config.text this.values = config.values this.name = config.name - this.forcePreparation = config.forcePreparation + this.queryMode = config.forcePreparation this.callback = config.callback this.state = 'new' this._arrayMode = config.rowMode === 'array' @@ -160,7 +160,7 @@ NativeQuery.prototype.submit = function (client) { } var vals = this.values.map(utils.prepareValue) client.native.query(this.text, vals, after) - } else if (this.forcePreparation) { + } else if (this.queryMode === 'extended') { client.native.query(this.text, [], after) } else { client.native.query(this.text, after) diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index fbc8b9322..0925960e6 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -16,7 +16,7 @@ class Query extends EventEmitter { this.rows = config.rows this.types = config.types this.name = config.name - this.forcePreparation = config.forcePreparation + this.queryMode = config.queryMode this.binary = config.binary // use unique portal name each time this.portal = config.portal || '' @@ -33,8 +33,7 @@ class Query extends EventEmitter { } requiresPreparation() { - // preparation has been requested - if (this.forcePreparation) { + if (this.queryMode === 'extended') { return true } diff --git a/packages/pg/test/integration/client/multiple-results-tests.js b/packages/pg/test/integration/client/multiple-results-tests.js index addca9b68..5ea5f76da 100644 --- a/packages/pg/test/integration/client/multiple-results-tests.js +++ b/packages/pg/test/integration/client/multiple-results-tests.js @@ -25,6 +25,31 @@ suite.test( }) ) +suite.test( + 'throws if queryMode set to "extended"', + co.wrap(function* () { + const client = new helper.Client() + yield client.connect() + + // TODO should be text or sql? + try { + const results = yield client.query({ + text: `SELECT 'foo'::text as name; SELECT 'bar'::text as baz`, + queryMode: 'extended', + }) + assert.fail('Should have thrown'); + } catch(err) { + if(err instanceof assert.AssertionError) throw err; + + assert.equal(err.severity, 'ERROR'); + assert.equal(err.code, '42601'); + assert.equal(err.message, 'cannot insert multiple commands into a prepared statement'); + } + + return client.end() + }) +) + suite.test( 'multiple selects work', co.wrap(function* () { From ce5ba84a18620045670f7c0ee51db51f32e89bf4 Mon Sep 17 00:00:00 2001 From: alxndrsn Date: Thu, 16 May 2024 11:31:50 +0000 Subject: [PATCH 3/5] lint --- .../integration/client/multiple-results-tests.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pg/test/integration/client/multiple-results-tests.js b/packages/pg/test/integration/client/multiple-results-tests.js index 5ea5f76da..c27295103 100644 --- a/packages/pg/test/integration/client/multiple-results-tests.js +++ b/packages/pg/test/integration/client/multiple-results-tests.js @@ -37,13 +37,13 @@ suite.test( text: `SELECT 'foo'::text as name; SELECT 'bar'::text as baz`, queryMode: 'extended', }) - assert.fail('Should have thrown'); - } catch(err) { - if(err instanceof assert.AssertionError) throw err; + assert.fail('Should have thrown') + } catch (err) { + if (err instanceof assert.AssertionError) throw err - assert.equal(err.severity, 'ERROR'); - assert.equal(err.code, '42601'); - assert.equal(err.message, 'cannot insert multiple commands into a prepared statement'); + assert.equal(err.severity, 'ERROR') + assert.equal(err.code, '42601') + assert.equal(err.message, 'cannot insert multiple commands into a prepared statement') } return client.end() From dd81d1c914443980818e39896d20f329669bc59b Mon Sep 17 00:00:00 2001 From: alxndrsn Date: Thu, 16 May 2024 11:38:04 +0000 Subject: [PATCH 4/5] native: fix passing queryMode from config --- packages/pg/lib/native/query.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg/lib/native/query.js b/packages/pg/lib/native/query.js index 932ab8746..0cfed1fda 100644 --- a/packages/pg/lib/native/query.js +++ b/packages/pg/lib/native/query.js @@ -10,7 +10,7 @@ var NativeQuery = (module.exports = function (config, values, callback) { this.text = config.text this.values = config.values this.name = config.name - this.queryMode = config.forcePreparation + this.queryMode = config.queryMode this.callback = config.callback this.state = 'new' this._arrayMode = config.rowMode === 'array' From 377edeab506884f5c69fc255714fedb4bf5999db Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Tue, 4 Jun 2024 11:04:55 -0500 Subject: [PATCH 5/5] Allow pg-native to prepare queries with zero params --- packages/pg-native/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg-native/index.js b/packages/pg-native/index.js index 87980197c..a3c3f070b 100644 --- a/packages/pg-native/index.js +++ b/packages/pg-native/index.js @@ -57,7 +57,7 @@ Client.prototype.query = function (text, values, cb) { cb = values } - if (Array.isArray(values) && values.length > 0) { + if (Array.isArray(values)) { queryFn = function () { return self.pq.sendQueryParams(text, values) }