Mold the things to work with Postgres

This commit is contained in:
Alex Gleason 2024-04-19 20:52:42 -05:00
parent b87a59c521
commit 9ccf6bbea0
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
14 changed files with 32 additions and 50 deletions

View File

@ -15,7 +15,9 @@
"@/": "./src/", "@/": "./src/",
"@nostrify/nostrify": "jsr:@nostrify/nostrify@^0.9.7", "@nostrify/nostrify": "jsr:@nostrify/nostrify@^0.9.7",
"~/fixtures/": "./fixtures/", "~/fixtures/": "./fixtures/",
"kysely": "npm:kysely@^0.26.3" "kysely": "npm:kysely@^0.26.3",
"pg": "npm:pg@^8.11.5",
"pg-pool": "npm:pg-pool@^3.6.2"
}, },
"lint": { "lint": {
"include": ["src/", "scripts/"], "include": ["src/", "scripts/"],

View File

@ -56,7 +56,7 @@ interface UnattachedMediaRow {
pubkey: string; pubkey: string;
url: string; url: string;
data: string; data: string;
uploaded_at: Date; uploaded_at: number;
} }
interface PubkeyDomainRow { interface PubkeyDomainRow {

View File

@ -21,6 +21,9 @@ export class DittoSQLite {
await Promise.all([ await Promise.all([
sql`PRAGMA synchronous = normal`.execute(this.db), sql`PRAGMA synchronous = normal`.execute(this.db),
sql`PRAGMA temp_store = memory`.execute(this.db), sql`PRAGMA temp_store = memory`.execute(this.db),
sql`PRAGMA foreign_keys = ON`.execute(this.db),
sql`PRAGMA auto_vacuum = FULL`.execute(this.db),
sql`PRAGMA journal_mode = WAL`.execute(this.db),
sql.raw(`PRAGMA mmap_size = ${Conf.sqlite.mmapSize}`).execute(this.db), sql.raw(`PRAGMA mmap_size = ${Conf.sqlite.mmapSize}`).execute(this.db),
]); ]);
} }

View File

@ -1,4 +1,4 @@
import { Kysely, sql } from '@/deps.ts'; import { Kysely } from '@/deps.ts';
export async function up(db: Kysely<any>): Promise<void> { export async function up(db: Kysely<any>): Promise<void> {
await db.schema await db.schema
@ -21,13 +21,6 @@ export async function up(db: Kysely<any>): Promise<void> {
.addColumn('event_id', 'text', (col) => col.notNull()) .addColumn('event_id', 'text', (col) => col.notNull())
.execute(); .execute();
await db.schema
.createTable('users')
.addColumn('pubkey', 'text', (col) => col.primaryKey())
.addColumn('username', 'text', (col) => col.notNull().unique())
.addColumn('inserted_at', 'datetime', (col) => col.notNull().defaultTo(sql`CURRENT_TIMESTAMP`))
.execute();
await db.schema await db.schema
.createIndex('idx_events_kind') .createIndex('idx_events_kind')
.on('events') .on('events')

View File

@ -1,9 +1,12 @@
import { Conf } from '@/config.ts';
import { Kysely, sql } from '@/deps.ts'; import { Kysely, sql } from '@/deps.ts';
export async function up(db: Kysely<any>): Promise<void> { export async function up(db: Kysely<any>): Promise<void> {
await sql`CREATE VIRTUAL TABLE events_fts USING fts5(id, content)`.execute(db); if (Conf.databaseUrl.protocol === 'sqlite:') {
await sql`CREATE VIRTUAL TABLE events_fts USING fts5(id, content)`.execute(db);
}
} }
export async function down(db: Kysely<any>): Promise<void> { export async function down(db: Kysely<any>): Promise<void> {
await db.schema.dropTable('events_fts').execute(); await db.schema.dropTable('events_fts').ifExists().execute();
} }

View File

@ -1,10 +1,6 @@
import { Kysely } from '@/deps.ts'; import { Kysely } from '@/deps.ts';
export async function up(db: Kysely<any>): Promise<void> { export async function up(_db: Kysely<any>): Promise<void> {
await db.schema
.alterTable('users')
.addColumn('admin', 'boolean', (col) => col.defaultTo(false))
.execute();
} }
export async function down(db: Kysely<any>): Promise<void> { export async function down(db: Kysely<any>): Promise<void> {

View File

@ -1,17 +1,6 @@
import { Kysely } from '@/deps.ts'; import { Kysely } from '@/deps.ts';
export async function up(db: Kysely<any>): Promise<void> { export async function up(_db: Kysely<any>): Promise<void> {
await db.schema
.createIndex('idx_users_pubkey')
.on('users')
.column('pubkey')
.execute();
await db.schema
.createIndex('idx_users_username')
.on('users')
.column('username')
.execute();
} }
export async function down(db: Kysely<any>): Promise<void> { export async function down(db: Kysely<any>): Promise<void> {

View File

@ -1,12 +1,7 @@
import { Kysely, sql } from '@/deps.ts'; import { Kysely } from '@/deps.ts';
export async function up(db: Kysely<any>): Promise<void> { export async function up(_db: Kysely<any>): Promise<void> {
await sql`PRAGMA foreign_keys = ON`.execute(db);
await sql`PRAGMA auto_vacuum = FULL`.execute(db);
await sql`VACUUM`.execute(db);
} }
export async function down(db: Kysely<any>): Promise<void> { export async function down(_db: Kysely<any>): Promise<void> {
await sql`PRAGMA foreign_keys = OFF`.execute(db);
await sql`PRAGMA auto_vacuum = NONE`.execute(db);
} }

View File

@ -1,4 +1,4 @@
import { Kysely, sql } from '@/deps.ts'; import { Kysely } from '@/deps.ts';
export async function up(db: Kysely<any>): Promise<void> { export async function up(db: Kysely<any>): Promise<void> {
await db.schema await db.schema
@ -7,7 +7,7 @@ export async function up(db: Kysely<any>): Promise<void> {
.addColumn('pubkey', 'text', (c) => c.notNull()) .addColumn('pubkey', 'text', (c) => c.notNull())
.addColumn('url', 'text', (c) => c.notNull()) .addColumn('url', 'text', (c) => c.notNull())
.addColumn('data', 'text', (c) => c.notNull()) .addColumn('data', 'text', (c) => c.notNull())
.addColumn('uploaded_at', 'datetime', (c) => c.notNull().defaultTo(sql`CURRENT_TIMESTAMP`)) .addColumn('uploaded_at', 'bigint', (c) => c.notNull())
.execute(); .execute();
await db.schema await db.schema

View File

@ -1,9 +1,7 @@
import { Kysely, sql } from '@/deps.ts'; import { Kysely } from '@/deps.ts';
export async function up(db: Kysely<any>): Promise<void> { export async function up(_db: Kysely<any>): Promise<void> {
await sql`PRAGMA journal_mode = WAL`.execute(db);
} }
export async function down(db: Kysely<any>): Promise<void> { export async function down(_db: Kysely<any>): Promise<void> {
await sql`PRAGMA journal_mode = DELETE`.execute(db);
} }

View File

@ -1,7 +1,7 @@
import { Kysely } from '@/deps.ts'; import { Kysely } from '@/deps.ts';
export async function up(db: Kysely<any>): Promise<void> { export async function up(db: Kysely<any>): Promise<void> {
await db.schema.dropTable('users').execute(); await db.schema.dropTable('users').ifExists().execute();
} }
export async function down(_db: Kysely<any>): Promise<void> { export async function down(_db: Kysely<any>): Promise<void> {

View File

@ -7,14 +7,14 @@ interface UnattachedMedia {
pubkey: string; pubkey: string;
url: string; url: string;
data: MediaData; data: MediaData;
uploaded_at: Date; uploaded_at: number;
} }
/** Add unattached media into the database. */ /** Add unattached media into the database. */
async function insertUnattachedMedia(media: Omit<UnattachedMedia, 'id' | 'uploaded_at'>) { async function insertUnattachedMedia(media: Omit<UnattachedMedia, 'id' | 'uploaded_at'>) {
const result = { const result = {
id: uuid62.v4(), id: uuid62.v4(),
uploaded_at: new Date(), uploaded_at: Date.now(),
...media, ...media,
}; };
@ -41,7 +41,7 @@ function selectUnattachedMediaQuery() {
function getUnattachedMedia(until: Date) { function getUnattachedMedia(until: Date) {
return selectUnattachedMediaQuery() return selectUnattachedMediaQuery()
.leftJoin('tags', 'unattached_media.url', 'tags.value') .leftJoin('tags', 'unattached_media.url', 'tags.value')
.where('uploaded_at', '<', until) .where('uploaded_at', '<', until.getTime())
.execute(); .execute();
} }

View File

@ -60,6 +60,7 @@ type EventQuery = SelectQueryBuilder<DittoTables, 'events', {
class EventsDB implements NStore { class EventsDB implements NStore {
#db: Kysely<DittoTables>; #db: Kysely<DittoTables>;
#debug = Debug('ditto:db:events'); #debug = Debug('ditto:db:events');
private protocol = Conf.databaseUrl.protocol;
constructor(db: Kysely<DittoTables>) { constructor(db: Kysely<DittoTables>) {
this.#db = db; this.#db = db;
@ -82,8 +83,10 @@ class EventsDB implements NStore {
.execute(); .execute();
} }
const protocol = this.protocol;
/** Add search data to the FTS table. */ /** Add search data to the FTS table. */
async function indexSearch() { async function indexSearch() {
if (protocol !== 'sqlite:') return;
const searchContent = buildSearchContent(event); const searchContent = buildSearchContent(event);
if (!searchContent) return; if (!searchContent) return;
await trx.insertInto('events_fts') await trx.insertInto('events_fts')
@ -194,7 +197,7 @@ class EventsDB implements NStore {
} }
} }
if (filter.search) { if (filter.search && this.protocol === 'sqlite:') {
query = query query = query
.innerJoin('events_fts', 'events_fts.id', 'events.id') .innerJoin('events_fts', 'events_fts.id', 'events.id')
.where('events_fts.content', 'match', JSON.stringify(filter.search)); .where('events_fts.content', 'match', JSON.stringify(filter.search));

View File

@ -28,7 +28,7 @@ export const TrendsWorker = {
CREATE TABLE IF NOT EXISTS tag_usages ( CREATE TABLE IF NOT EXISTS tag_usages (
tag TEXT NOT NULL COLLATE NOCASE, tag TEXT NOT NULL COLLATE NOCASE,
pubkey8 TEXT NOT NULL, pubkey8 TEXT NOT NULL,
inserted_at DATETIME NOT NULL inserted_at INTEGER NOT NULL
); );
CREATE INDEX IF NOT EXISTS idx_time_tag ON tag_usages(inserted_at, tag); CREATE INDEX IF NOT EXISTS idx_time_tag ON tag_usages(inserted_at, tag);