Skip to content

Commit e6a878c

Browse files
Rich-Harrisbrianc
authored andcommitted
compare prepared statement text with previous to prevent incorrect queries (#1814)
* compare prepared statement text with previous to prevent incorrect queries - fixes #1813 * make suggested changes to error message
1 parent 4c6c0e9 commit e6a878c

File tree

4 files changed

+21
-2
lines changed

4 files changed

+21
-2
lines changed

lib/client.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ Client.prototype._attachListeners = function (con) {
276276
// it again on the same client
277277
con.on('parseComplete', function (msg) {
278278
if (self.activeQuery.name) {
279-
con.parsedStatements[self.activeQuery.name] = true
279+
con.parsedStatements[self.activeQuery.name] = self.activeQuery.text
280280
}
281281
})
282282

lib/native/query.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,16 @@ NativeQuery.prototype.submit = function (client) {
139139
// check if the client has already executed this named query
140140
// if so...just execute it again - skip the planning phase
141141
if (client.namedQueries[this.name]) {
142+
if (this.text && client.namedQueries[this.name] !== this.text) {
143+
const err = new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`)
144+
return after(err)
145+
}
142146
return client.native.execute(this.name, values, after)
143147
}
144148
// plan the named query the first time, then execute it
145149
return client.native.prepare(this.name, this.text, values.length, function (err) {
146150
if (err) return after(err)
147-
client.namedQueries[self.name] = true
151+
client.namedQueries[self.name] = self.text
148152
return self.native.execute(self.name, values, after)
149153
})
150154
} else if (this.values) {

lib/query.js

+4
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ Query.prototype.submit = function (connection) {
148148
if (typeof this.text !== 'string' && typeof this.name !== 'string') {
149149
return new Error('A query must have either text or a name. Supplying neither is unsupported.')
150150
}
151+
const previous = connection.parsedStatements[this.name]
152+
if (this.text && previous && this.text !== previous) {
153+
return new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`)
154+
}
151155
if (this.values && !Array.isArray(this.values)) {
152156
return new Error('Query values must be an array')
153157
}

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

+11
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@ var suite = new helper.Suite()
5656

5757
q.on('end', () => done())
5858
})
59+
60+
suite.test('with same name, but with different text', function (done) {
61+
client.query(new Query({
62+
text: 'select name from person where age >= $1 and name LIKE $2',
63+
name: queryName,
64+
values: [30, '%n%']
65+
}), assert.calls(err => {
66+
assert.equal(err.message, `Prepared statements must be unique - '${queryName}' was used for a different statement`)
67+
done()
68+
}))
69+
})
5970
})()
6071

6172
;(function () {

0 commit comments

Comments
 (0)