Files
biblical-guide.com/scripts/old/clone_vector_table.ts
Andrei 95070e5369 Add comprehensive page management system to admin dashboard
Features added:
- Database schema for pages and media files with content types (Rich Text, HTML, Markdown)
- Admin API routes for full page CRUD operations
- Image upload functionality with file management
- Rich text editor using TinyMCE with image insertion
- Admin interface for creating/editing pages with SEO options
- Dynamic navigation and footer integration
- Public page display routes with proper SEO metadata
- Support for featured images and content excerpts

Admin features:
- Create/edit/delete pages with rich content editor
- Upload and manage images through media library
- Configure pages to appear in navigation or footer
- Set page status (Draft, Published, Archived)
- SEO title and description management
- Real-time preview of content changes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-24 07:26:25 +00:00

75 lines
2.8 KiB
TypeScript

import 'dotenv/config'
import { Pool } from 'pg'
async function main() {
const pool = new Pool({ connectionString: process.env.DATABASE_URL })
const schema = (process.env.VECTOR_SCHEMA || 'ai_bible').replace(/[^a-zA-Z0-9_]/g, '')
const source = `${schema}.bv_ro_fidela`
const target = `${schema}.bv_ro_cornilescu`
const client = await pool.connect()
try {
console.log('Cloning vector table from', source, 'to', target)
await client.query('BEGIN')
await client.query(`CREATE EXTENSION IF NOT EXISTS vector;`)
await client.query(`CREATE SCHEMA IF NOT EXISTS "${schema}";`)
// Create target table if not exists with same structure
await client.query(`
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.tables
WHERE table_schema = '${schema}' AND table_name = 'bv_ro_cornilescu') THEN
EXECUTE format('CREATE TABLE %I.%I (LIKE %I.%I INCLUDING ALL)', '${schema}', 'bv_ro_cornilescu', '${schema}', 'bv_ro_fidela');
END IF;
END$$;`)
// Insert rows if target empty
const cnt = await client.query(`SELECT count(*)::int AS c FROM ${target}`)
if ((cnt.rows?.[0]?.c ?? 0) === 0) {
console.log('Copying rows...')
await client.query(`
INSERT INTO ${target} (testament, book, chapter, verse, text_raw, text_norm, tsv, embedding, created_at, updated_at)
SELECT testament, book, chapter, verse, text_raw, text_norm, tsv, embedding, created_at, updated_at
FROM ${source}
ON CONFLICT DO NOTHING
`)
} else {
console.log('Target already has rows, skipping copy')
}
// Create indexes if not exist
await client.query(`
CREATE UNIQUE INDEX IF NOT EXISTS ux_ref_bv_ro_cornilescu ON ${target} (book, chapter, verse);
CREATE INDEX IF NOT EXISTS idx_tsv_bv_ro_cornilescu ON ${target} USING GIN (tsv);
CREATE INDEX IF NOT EXISTS idx_book_ch_bv_ro_cornilescu ON ${target} (book, chapter);
CREATE INDEX IF NOT EXISTS idx_testament_bv_ro_cornilescu ON ${target} (testament);
`)
await client.query('COMMIT')
console.log('Rows copied and indexes created. Running post-copy maintenance...')
// Run maintenance commands outside of transaction
await client.query(`VACUUM ANALYZE ${target};`)
try {
await client.query(`
CREATE INDEX IF NOT EXISTS idx_vec_ivfflat_bv_ro_cornilescu
ON ${target} USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
`)
} catch (e) {
console.warn('IVFFLAT index creation hit memory limits; skipping for now. You can create it later with higher maintenance_work_mem.')
}
console.log('Clone completed.')
} catch (e) {
await client.query('ROLLBACK')
console.error('Clone error:', e)
process.exit(1)
} finally {
client.release()
await pool.end()
}
}
main()