mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 11:29:46 +00:00
76 lines
2.1 KiB
TypeScript
76 lines
2.1 KiB
TypeScript
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';
|
|
import { DittoTables } from '@/db/DittoTables.ts';
|
|
import { KyselyLogger } from '@/db/KyselyLogger.ts';
|
|
|
|
export class DittoPostgres {
|
|
static db: Kysely<DittoTables> | undefined;
|
|
static postgres?: postgres.Sql;
|
|
|
|
// deno-lint-ignore require-await
|
|
static async getInstance(): Promise<Kysely<DittoTables>> {
|
|
if (!this.postgres) {
|
|
this.postgres = postgres(Conf.databaseUrl, { max: Conf.pg.poolSize });
|
|
}
|
|
|
|
if (!this.db) {
|
|
this.db = new Kysely({
|
|
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,
|
|
});
|
|
}
|
|
|
|
return this.db;
|
|
}
|
|
|
|
static get poolSize() {
|
|
return this.postgres?.connections.open ?? 0;
|
|
}
|
|
|
|
static get availableConnections(): number {
|
|
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);
|
|
}
|
|
}
|
|
}
|