Skip to content

Commit dd3ce61

Browse files
committed
Fixes based on postgres maintainer advice
1 parent d31486f commit dd3ce61

File tree

2 files changed

+20
-18
lines changed

2 files changed

+20
-18
lines changed

packages/pg/lib/query.js

+10-18
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,22 @@ class Query extends EventEmitter {
103103
// need to sync after each command complete of a prepared statement
104104
// if we were using a row count which results in multiple calls to _getRows
105105
if (this.rows) {
106-
this.maybeSync(connection)
106+
connection.sync()
107107
}
108108
}
109109

110110
// if a named prepared statement is created with empty query text
111111
// the backend will send an emptyQuery message but *not* a command complete message
112-
// execution on the connection will hang until the backend receives a sync message
112+
// since we pipeline sync immediately after execute we don't need to do anything here
113+
// unless we have rows specified, in which case we did not pipeline the intial sync call
113114
handleEmptyQuery(connection) {
114-
// this.maybeSync(connection)
115+
if (this.rows) {
116+
connection.sync()
117+
}
115118
}
116119

117120
handleError(err, connection) {
118121
// need to sync after error during a prepared statement
119-
// this.maybeSync(connection)
120122
if (this._canceledDueToError) {
121123
err = this._canceledDueToError
122124
this._canceledDueToError = false
@@ -139,19 +141,6 @@ class Query extends EventEmitter {
139141
this.emit('end', this._results)
140142
}
141143

142-
// In postgres 9.x & 10.x the backend sends both a CommandComplete and ErrorResponse
143-
// to the same query when it times out due to a statement_timeout on rare, random occasions. If we send sync twice we will receive
144-
// to ReadyForQuery messages . I hink this might be a race condition in some versions of postgres, but I'm not sure...
145-
// the docs here: https://www.postgresql.org/docs/9.6/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY
146-
// say "Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages:
147-
// CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended."
148-
maybeSync(connection) {
149-
if (this.isPreparedStatement) {
150-
this._hasSentSync = true
151-
connection.sync()
152-
}
153-
}
154-
155144
submit(connection) {
156145
if (typeof this.text !== 'string' && typeof this.name !== 'string') {
157146
return new Error('A query must have either text or a name. Supplying neither is unsupported.')
@@ -184,9 +173,12 @@ class Query extends EventEmitter {
184173
portal: this.portal,
185174
rows: rows,
186175
})
176+
// if we're not reading pages of rows send the sync command
177+
// to indicate the pipeline is finished
187178
if (!rows) {
188-
this.maybeSync(connection)
179+
connection.sync()
189180
} else {
181+
// otherwise flush the call out to read more rows
190182
connection.flush()
191183
}
192184
}

packages/pg/test/integration/client/prepared-statement-tests.js

+10
Original file line numberDiff line numberDiff line change
@@ -174,5 +174,15 @@ var suite = new helper.Suite()
174174
checkForResults(query)
175175
})
176176

177+
suite.testAsync('with no data response and rows', async function () {
178+
const result = await client.query({
179+
name: 'some insert',
180+
text: '',
181+
values: [],
182+
rows: 1,
183+
})
184+
assert.equal(result.rows.length, 0)
185+
})
186+
177187
suite.test('cleanup', () => client.end())
178188
})()

0 commit comments

Comments
 (0)