import { BaseSchema } from '@adonisjs/lucid/schema' /** * Smaller indexes (LOG.md 2026-09-28 (17)). 99.5% of releases have no files * yet (most never will), and search only looks at releases with files; most * binaries have no size, fingerprint, file or parent. Indexing only the rows * that queries can match saves GBs and work on every insert. Built * concurrently, so ingest keeps running. */ const INDEXES: [table: string, name: string, definition: string][] = [ ['releases', 'releases_name_trgm', `USING gin (name gin_trgm_ops) WHERE file_count > 0`], ['releases', 'releases_contents_trgm', `USING gin ((contents::text) gin_trgm_ops) WHERE file_count > 0`], ['releases', 'releases_posted_at_idx', `(posted_at DESC NULLS LAST) WHERE file_count > 0`], ['releases', 'releases_size_index', `(size) WHERE file_count > 0`], ['releases', 'releases_file_count_index', `(file_count) WHERE file_count > 0`], ['releases', 'releases_complete_idx', `(complete) WHERE file_count > 0`], ['releases', 'releases_category_idx', `(category) WHERE file_count > 0`], ['binaries', 'binaries_md5_16k_index', `(md5_16k) WHERE md5_16k IS NOT NULL`], ['binaries', 'binaries_size_index', `(size) WHERE size IS NOT NULL`], ['binaries', 'binaries_file_id_idx', `(file_id) WHERE file_id IS NOT NULL`], ['binaries', 'binaries_parent_binary_id_index', `(parent_binary_id) WHERE parent_binary_id IS NOT NULL`], ] export default class extends BaseSchema { static disableTransactions = true async up() { for (const [table, name, definition] of INDEXES) { // Build the partial index under a temporary name, then swap it in. await this.db.rawQuery(`DROP INDEX CONCURRENTLY IF EXISTS ${name}_partial`) await this.db.rawQuery(`CREATE INDEX CONCURRENTLY ${name}_partial ON ${table} ${definition}`) await this.db.rawQuery(`DROP INDEX CONCURRENTLY IF EXISTS ${name}`) await this.db.rawQuery(`ALTER INDEX ${name}_partial RENAME TO ${name}`) } } async down() { for (const [table, name, definition] of INDEXES) { const full = definition.replace(/ WHERE .*$/, '') await this.db.rawQuery(`DROP INDEX CONCURRENTLY IF EXISTS ${name}`) await this.db.rawQuery(`CREATE INDEX CONCURRENTLY ${name} ON ${table} ${full}`) } } }