Mold the things to work with Postgres
This commit is contained in:
parent
b87a59c521
commit
9ccf6bbea0
|
@ -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/"],
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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')
|
||||||
|
|
|
@ -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> {
|
||||||
|
if (Conf.databaseUrl.protocol === 'sqlite:') {
|
||||||
await sql`CREATE VIRTUAL TABLE events_fts USING fts5(id, content)`.execute(db);
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue