PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]); $pdo->exec('PRAGMA journal_mode = WAL'); $pdo->exec('PRAGMA busy_timeout = 5000'); $pdo->exec('PRAGMA foreign_keys = ON'); self::migrate($pdo); return $pdo; } private static function migrate(PDO $pdo): void { $pdo->exec(<<<'SQL' CREATE TABLE IF NOT EXISTS items ( id TEXT PRIMARY KEY, source TEXT NOT NULL, feed_label TEXT, feed_url TEXT NOT NULL, title TEXT NOT NULL, link TEXT NOT NULL, author TEXT, published_at TEXT, description TEXT, thumbnail TEXT, fetched_at TEXT NOT NULL ) SQL); $pdo->exec('CREATE INDEX IF NOT EXISTS idx_items_published ON items (published_at DESC)'); $pdo->exec('CREATE INDEX IF NOT EXISTS idx_items_source ON items (source, published_at DESC)'); $pdo->exec(<<<'SQL' CREATE TABLE IF NOT EXISTS feeds ( url TEXT PRIMARY KEY, source TEXT NOT NULL, label TEXT, last_attempt_at TEXT, last_success_at TEXT, last_error TEXT, origin TEXT NOT NULL DEFAULT 'config', enabled INTEGER NOT NULL DEFAULT 1 ) SQL); // SQLite has no "ADD COLUMN IF NOT EXISTS": migrate pre-existing tables. self::addColumn($pdo, 'feeds', 'origin', "ALTER TABLE feeds ADD COLUMN origin TEXT NOT NULL DEFAULT 'config'"); self::addColumn($pdo, 'feeds', 'enabled', 'ALTER TABLE feeds ADD COLUMN enabled INTEGER NOT NULL DEFAULT 1'); } private static function addColumn(PDO $pdo, string $table, string $column, string $sql): void { $existing = []; foreach ($pdo->query(sprintf('PRAGMA table_info(%s)', $table)) as $row) { $existing[strtolower((string) $row['name'])] = true; } if (!isset($existing[strtolower($column)])) { $pdo->exec($sql); } } }