Merge branch 'in-any' into 'main'

Convert IN operators to = ANY() operators on Postgres

See merge request soapbox-pub/ditto!439
This commit is contained in:
Alex Gleason 2024-07-31 20:08:09 +00:00
commit b47c53038f
4 changed files with 54 additions and 11 deletions

View file

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

12
deno.lock generated
View file

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

View file

@ -1,5 +1,15 @@
import { Kysely } from 'kysely'; import {
import { PostgresJSDialect, PostgresJSDialectConfig } from 'kysely-postgres-js'; BinaryOperationNode,
FunctionNode,
Kysely,
OperatorNode,
PostgresAdapter,
PostgresIntrospector,
PostgresQueryCompiler,
PrimitiveValueListNode,
ValueNode,
} from 'kysely';
import { PostgresJSDialectConfig, PostgresJSDriver } from 'kysely-postgres-js';
import postgres from 'postgres'; import postgres from 'postgres';
import { Conf } from '@/config.ts'; import { Conf } from '@/config.ts';
@ -18,9 +28,22 @@ export class DittoPostgres {
if (!this.db) { if (!this.db) {
this.db = new Kysely({ this.db = new Kysely({
dialect: new PostgresJSDialect({ dialect: {
postgres: this.postgres as unknown as PostgresJSDialectConfig['postgres'], 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, log: KyselyLogger,
}); });
} }
@ -36,3 +59,18 @@ export class DittoPostgres {
return this.postgres?.connections.idle ?? 0; 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

@ -6,8 +6,8 @@ import { DenoSqlite3Dialect } from '@soapbox/kysely-deno-sqlite';
import { finalizeEvent, generateSecretKey } from 'nostr-tools'; import { finalizeEvent, generateSecretKey } from 'nostr-tools';
import { NDatabase, NostrEvent } from '@nostrify/nostrify'; import { NDatabase, NostrEvent } from '@nostrify/nostrify';
import { FileMigrationProvider, Kysely, Migrator } from 'kysely'; import { FileMigrationProvider, Kysely, Migrator } from 'kysely';
import postgres from 'postgres';
import { PostgresJSDialect, PostgresJSDialectConfig } from 'kysely-postgres-js'; import { PostgresJSDialect, PostgresJSDialectConfig } from 'kysely-postgres-js';
import postgres from 'postgres';
import { DittoDB } from '@/db/DittoDB.ts'; import { DittoDB } from '@/db/DittoDB.ts';
import { DittoTables } from '@/db/DittoTables.ts'; import { DittoTables } from '@/db/DittoTables.ts';
@ -113,6 +113,7 @@ export const createTestDB = async (databaseUrl?: string) => {
}); });
} else { } else {
kysely = new Kysely({ kysely = new Kysely({
// @ts-ignore Kysely version mismatch.
dialect: new PostgresJSDialect({ dialect: new PostgresJSDialect({
postgres: postgres(Conf.databaseUrl, { postgres: postgres(Conf.databaseUrl, {
max: Conf.pg.poolSize, max: Conf.pg.poolSize,