Skip to content

Commit 1d29c01

Browse files
authored
fix(postgres): don't name the one-off create-table prepared statement (#196) (#366)
_query() named every prepared statement `${prefix}:${q.name}`. The create-table query passes no name, so it was registered as the named statement `${prefix}:undefined`. Only set the statement name when one is provided; named queries (upsert/get/delete/clear-expired) are unchanged. Co-authored-by: Ruby-Leung <261113120+Ruby-Leung@users.noreply.github.com>
1 parent e58ee32 commit 1d29c01

2 files changed

Lines changed: 38 additions & 1 deletion

File tree

lib/RateLimiterPostgres.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,13 @@ class RateLimiterPostgres extends RateLimiterStoreAbstract {
262262

263263
_query(q) {
264264
const prefix = this.tableName.toLowerCase();
265-
const queryObj = { name: `${prefix}:${q.name}`, text: q.text, values: q.values };
265+
const queryObj = { text: q.text, values: q.values };
266+
// Only name the prepared statement when a name is provided. The one-off
267+
// create-table query passes no name, and naming it `${prefix}:undefined`
268+
// pollutes the prepared-statement cache (see #196).
269+
if (q.name) {
270+
queryObj.name = `${prefix}:${q.name}`;
271+
}
266272
return new Promise((resolve, reject) => {
267273
this._getConnection()
268274
.then((conn) => {

test/RateLimiterPostgres.test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,37 @@ describe('RateLimiterPostgres with fixed window', function RateLimiterPostgresTe
6060
});
6161
});
6262

63+
it('runs the create-table query without a named prepared statement (#196)', (done) => {
64+
// The create-table query carries no `name` and runs once, so it must not be
65+
// sent as a named prepared statement (previously the name became
66+
// `<prefix>:undefined`). Named queries must still keep their name.
67+
const rateLimiter = new RateLimiterPostgres({
68+
storeClient: pgClient, storeType: 'client', points: 2, duration: 5,
69+
}, () => {
70+
try {
71+
const createTableQuery = pgClientStub.getCall(0).args[0];
72+
expect(createTableQuery.text).to.match(/CREATE TABLE/i);
73+
expect('name' in createTableQuery).to.equal(false);
74+
} catch (err) {
75+
done(err);
76+
return;
77+
}
78+
79+
pgClientStub.restore();
80+
pgClientStub = sinon.stub(pgClient, 'query').resolves({
81+
rows: [{ points: 1, expire: 5000 }],
82+
});
83+
rateLimiter.consume('test196')
84+
.then(() => {
85+
const namedQuery = pgClientStub.getCall(0).args[0];
86+
expect(namedQuery.name).to.be.a('string');
87+
expect(namedQuery.name).to.match(/rlflx-upsert$/);
88+
done();
89+
})
90+
.catch(done);
91+
});
92+
});
93+
6394
it('consume 1 point', (done) => {
6495
const testKey = 'consume1';
6596

0 commit comments

Comments
 (0)