Convert IN operators to = ANY() operators on Postgres

This commit is contained in:
Alex Gleason 2024-07-31 12:52:03 -05:00
parent 7860dd2a0c
commit d73370cc68
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
5 changed files with 52 additions and 7 deletions

View file

@ -50,7 +50,7 @@
"hono-rate-limiter": "npm:hono-rate-limiter@^0.3.0",
"iso-639-1": "npm:iso-639-1@2.1.15",
"isomorphic-dompurify": "npm:isomorphic-dompurify@^2.11.0",
"kysely": "npm:kysely@^0.27.3",
"kysely": "npm:kysely@^0.27.4",
"postgres": "https://raw.githubusercontent.com/xyzshantaram/postgres.js/8a9bbce88b3f6425ecaacd99a80372338b157a53/deno/mod.js",
"kysely-postgres-js": "npm:kysely-postgres-js@2.0.0",
"light-bolt11-decoder": "npm:light-bolt11-decoder",

7
deno.lock generated
View file

@ -53,6 +53,7 @@
"npm:kysely@0.27.3": "npm:kysely@0.27.3",
"npm:kysely@^0.27.2": "npm:kysely@0.27.3",
"npm:kysely@^0.27.3": "npm:kysely@0.27.3",
"npm:kysely@^0.27.4": "npm:kysely@0.27.4",
"npm:light-bolt11-decoder": "npm:light-bolt11-decoder@3.1.1",
"npm:linkify-plugin-hashtag@^4.1.1": "npm:linkify-plugin-hashtag@4.1.3_linkifyjs@4.1.3",
"npm:linkify-string@^4.1.1": "npm:linkify-string@4.1.3_linkifyjs@4.1.3",
@ -710,6 +711,10 @@
"integrity": "sha512-lG03Ru+XyOJFsjH3OMY6R/9U38IjDPfnOfDgO3ynhbDr+Dz8fak+X6L62vqu3iybQnj+lG84OttBuU9KY3L9kA==",
"dependencies": {}
},
"kysely@0.27.4": {
"integrity": "sha512-dyNKv2KRvYOQPLCAOCjjQuCk4YFd33BvGdf/o5bC7FiW+BB6snA81Zt+2wT9QDFzKqxKa5rrOmvlK/anehCcgA==",
"dependencies": {}
},
"light-bolt11-decoder@3.1.1": {
"integrity": "sha512-sLg/KCwYkgsHWkefWd6KqpCHrLFWWaXTOX3cf6yD2hAzL0SLpX+lFcaFK2spkjbgzG6hhijKfORDc9WoUHwX0A==",
"dependencies": {
@ -1799,7 +1804,7 @@
"npm:iso-639-1@2.1.15",
"npm:isomorphic-dompurify@^2.11.0",
"npm:kysely-postgres-js@2.0.0",
"npm:kysely@^0.27.3",
"npm:kysely@^0.27.4",
"npm:light-bolt11-decoder",
"npm:linkify-plugin-hashtag@^4.1.1",
"npm:linkify-string@^4.1.1",

View file

@ -1,5 +1,15 @@
import { Kysely } from 'kysely';
import { PostgresJSDialect, PostgresJSDialectConfig } from 'kysely-postgres-js';
import {
BinaryOperationNode,
FunctionNode,
Kysely,
OperatorNode,
PostgresAdapter,
PostgresIntrospector,
PostgresQueryCompiler,
PrimitiveValueListNode,
ValueNode,
} from 'kysely';
import { PostgresJSDialectConfig, PostgresJSDriver } from 'kysely-postgres-js';
import postgres from 'postgres';
import { Conf } from '@/config.ts';
@ -18,9 +28,22 @@ export class DittoPostgres {
if (!this.db) {
this.db = new Kysely({
dialect: new PostgresJSDialect({
postgres: this.postgres as unknown as PostgresJSDialectConfig['postgres'],
}),
dialect: {
createAdapter() {
return new PostgresAdapter();
},
createDriver() {
return new PostgresJSDriver({
postgres: DittoPostgres.postgres as unknown as PostgresJSDialectConfig['postgres'],
});
},
createIntrospector(db) {
return new PostgresIntrospector(db);
},
createQueryCompiler() {
return new DittoPostgresQueryCompiler();
},
},
log: KyselyLogger,
});
}
@ -36,3 +59,18 @@ export class DittoPostgres {
return this.postgres?.connections.idle ?? 0;
}
}
/** Converts `in` queries to `any` to improve prepared statements on Postgres. */
class DittoPostgresQueryCompiler extends PostgresQueryCompiler {
protected override visitBinaryOperation(node: BinaryOperationNode): void {
if (
OperatorNode.is(node.operator) && node.operator.operator === 'in' && PrimitiveValueListNode.is(node.rightOperand)
) {
this.visitNode(node.leftOperand);
this.append(' = ');
this.visitNode(FunctionNode.create('any', [ValueNode.create(node.rightOperand.values)]));
} else {
super.visitBinaryOperation(node);
}
}
}

View file

@ -15,6 +15,7 @@ export class DittoSQLite {
await sqliteWorker.open(this.path);
this.db = new Kysely<DittoTables>({
// @ts-ignore Kysely version mismatch.
dialect: new PolySqliteDialect({
database: sqliteWorker,
}),

View file

@ -43,6 +43,7 @@ class EventsDB implements NStore {
};
constructor(private kysely: Kysely<DittoTables>) {
// @ts-ignore Kysely version mismatch.
this.store = new NDatabase(kysely, {
fts: Conf.db.dialect,
timeoutStrategy: Conf.db.dialect === 'postgres' ? 'setStatementTimeout' : undefined,