Skip to content

Commit f847937

Browse files
committed
Fix escaping for binding parameters
1 parent 9b20ddc commit f847937

File tree

4 files changed

+29
-6
lines changed

4 files changed

+29
-6
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ Changelog
6868

6969
To be released.
7070

71-
- Use the explicitly typed binding instead of an implicit one to work
72-
around the stringification issue.
71+
- Fixed a bug where binding parameters have not been properly escaped with
72+
some settings of Postgres.js.
7373

7474
### Version 0.2.1
7575

src/kv.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { KvKey, KvStore, KvStoreSetOptions } from "@fedify/fedify";
2-
import type { JSONValue, Sql } from "postgres";
2+
import type { JSONValue, Parameter, Sql } from "postgres";
3+
import { driverSerializesJson } from "./utils.ts";
34

45
/**
56
* Options for the PostgreSQL key-value store.
@@ -39,6 +40,7 @@ export class PostgresKvStore implements KvStore {
3940
readonly #sql: Sql<{}>;
4041
readonly #tableName: string;
4142
#initialized: boolean;
43+
#driverSerializesJson = false;
4244

4345
/**
4446
* Creates a new PostgreSQL key-value store.
@@ -84,7 +86,7 @@ export class PostgresKvStore implements KvStore {
8486
INSERT INTO ${this.#sql(this.#tableName)} (key, value, ttl)
8587
VALUES (
8688
${key},
87-
${this.#sql.json(value as JSONValue)},
89+
${this.#json(value)},
8890
${ttl}
8991
)
9092
ON CONFLICT (key)
@@ -116,6 +118,7 @@ export class PostgresKvStore implements KvStore {
116118
ttl interval
117119
);
118120
`;
121+
this.#driverSerializesJson = await driverSerializesJson(this.#sql);
119122
this.#initialized = true;
120123
}
121124

@@ -126,4 +129,9 @@ export class PostgresKvStore implements KvStore {
126129
async drop(): Promise<void> {
127130
await this.#sql`DROP TABLE IF EXISTS ${this.#sql(this.#tableName)};`;
128131
}
132+
133+
#json(value: unknown): Parameter {
134+
if (this.#driverSerializesJson) return this.#sql.json(value as JSONValue);
135+
return this.#sql.json(JSON.stringify(value));
136+
}
129137
}

src/mq.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import type {
33
MessageQueueEnqueueOptions,
44
MessageQueueListenOptions,
55
} from "@fedify/fedify";
6-
import type { Sql } from "postgres";
6+
import type { JSONValue, Parameter, Sql } from "postgres";
77
import postgres from "postgres";
8+
import { driverSerializesJson } from "./utils.ts";
89

910
/**
1011
* Options for the PostgreSQL message queue.
@@ -61,6 +62,7 @@ export class PostgresMessageQueue implements MessageQueue {
6162
readonly #channelName: string;
6263
readonly #pollIntervalMs: number;
6364
#initialized: boolean;
65+
#driverSerializesJson = false;
6466

6567
constructor(
6668
// deno-lint-ignore ban-types
@@ -86,7 +88,7 @@ export class PostgresMessageQueue implements MessageQueue {
8688
await this.#sql`
8789
INSERT INTO ${this.#sql(this.#tableName)} (message, delay)
8890
VALUES (
89-
${this.#sql.json(message)},
91+
${this.#json(message)},
9092
${delay.toString()}
9193
);
9294
`;
@@ -181,6 +183,7 @@ export class PostgresMessageQueue implements MessageQueue {
181183
throw e;
182184
}
183185
}
186+
this.#driverSerializesJson = await driverSerializesJson(this.#sql);
184187
this.#initialized = true;
185188
}
186189

@@ -190,6 +193,11 @@ export class PostgresMessageQueue implements MessageQueue {
190193
async drop(): Promise<void> {
191194
await this.#sql`DROP TABLE IF EXISTS ${this.#sql(this.#tableName)};`;
192195
}
196+
197+
#json(value: unknown): Parameter {
198+
if (this.#driverSerializesJson) return this.#sql.json(value as JSONValue);
199+
return this.#sql.json(JSON.stringify(value));
200+
}
193201
}
194202

195203
// cSpell: ignore typname

src/utils.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import type { Sql } from "postgres";
2+
3+
// deno-lint-ignore ban-types
4+
export async function driverSerializesJson(sql: Sql<{}>): Promise<boolean> {
5+
const result = await sql`SELECT ${sql.json('{"foo":1}')}::jsonb AS test;`;
6+
return result[0].test === '{"foo":1}';
7+
}

0 commit comments

Comments
 (0)