Goondex/internal/db/schema.go
Stu Leak 16fb407a3c v0.1.0-dev4: Add web frontend with UI component library
- Implement full web interface with Go html/template server
- Add GX component library (buttons, dialogs, tables, forms, etc.)
- Create scene/performer/studio/movie detail and listing pages
- Add Adult Empire scraper for additional metadata sources
- Implement movie support with database schema
- Add import and sync services for data management
- Include comprehensive API and frontend documentation
- Add custom color scheme and responsive layout

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 10:47:30 -05:00

261 lines
8.0 KiB
Go

package db
const schema = `
-- Enable foreign keys
PRAGMA foreign_keys = ON;
-- Performers table
CREATE TABLE IF NOT EXISTS performers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
aliases TEXT,
-- Physical attributes
gender TEXT,
birthday TEXT,
astrology TEXT,
birthplace TEXT,
ethnicity TEXT,
nationality TEXT,
country TEXT,
eye_color TEXT,
hair_color TEXT,
height INTEGER,
weight INTEGER,
measurements TEXT,
cup_size TEXT,
tattoo_description TEXT,
piercing_description TEXT,
boob_job TEXT,
-- Career information
career TEXT,
career_start_year INTEGER,
career_end_year INTEGER,
date_of_death TEXT,
active INTEGER DEFAULT 1,
-- Media
image_path TEXT,
image_url TEXT,
poster_url TEXT,
bio TEXT,
-- Source tracking
source TEXT,
source_id TEXT,
source_numeric_id INTEGER,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
-- Prevent duplicates from same source
UNIQUE(source, source_id)
);
-- Studios table
CREATE TABLE IF NOT EXISTS studios (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
parent_id INTEGER,
image_path TEXT,
image_url TEXT,
description TEXT,
source TEXT,
source_id TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (parent_id) REFERENCES studios(id) ON DELETE SET NULL
);
-- Tag Categories table (hierarchical)
CREATE TABLE IF NOT EXISTS tag_categories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
parent_id INTEGER,
description TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (parent_id) REFERENCES tag_categories(id) ON DELETE CASCADE
);
-- Tags table (enhanced with categories)
CREATE TABLE IF NOT EXISTS tags (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
category_id INTEGER NOT NULL,
aliases TEXT,
description TEXT,
source TEXT,
source_id TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE(category_id, name),
FOREIGN KEY (category_id) REFERENCES tag_categories(id) ON DELETE CASCADE
);
-- Scenes table
CREATE TABLE IF NOT EXISTS scenes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
code TEXT,
date TEXT,
studio_id INTEGER,
description TEXT,
image_path TEXT,
image_url TEXT,
director TEXT,
url TEXT,
source TEXT,
source_id TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (studio_id) REFERENCES studios(id) ON DELETE SET NULL
);
-- Movies table (full-length DVDs/releases)
CREATE TABLE IF NOT EXISTS movies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
date TEXT,
studio_id INTEGER,
description TEXT,
director TEXT,
duration INTEGER,
image_path TEXT,
image_url TEXT,
back_image_url TEXT,
url TEXT,
source TEXT,
source_id TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (studio_id) REFERENCES studios(id) ON DELETE SET NULL
);
-- Movie-Scene many-to-many junction table (scenes belong to movies)
CREATE TABLE IF NOT EXISTS movie_scenes (
movie_id INTEGER NOT NULL,
scene_id INTEGER NOT NULL,
scene_number INTEGER,
PRIMARY KEY (movie_id, scene_id),
FOREIGN KEY (movie_id) REFERENCES movies(id) ON DELETE CASCADE,
FOREIGN KEY (scene_id) REFERENCES scenes(id) ON DELETE CASCADE
);
-- Movie-Performer many-to-many junction table
CREATE TABLE IF NOT EXISTS movie_performers (
movie_id INTEGER NOT NULL,
performer_id INTEGER NOT NULL,
PRIMARY KEY (movie_id, performer_id),
FOREIGN KEY (movie_id) REFERENCES movies(id) ON DELETE CASCADE,
FOREIGN KEY (performer_id) REFERENCES performers(id) ON DELETE CASCADE
);
-- Movie-Tag many-to-many junction table
CREATE TABLE IF NOT EXISTS movie_tags (
movie_id INTEGER NOT NULL,
tag_id INTEGER NOT NULL,
PRIMARY KEY (movie_id, tag_id),
FOREIGN KEY (movie_id) REFERENCES movies(id) ON DELETE CASCADE,
FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE
);
-- Scene-Performer many-to-many junction table
CREATE TABLE IF NOT EXISTS scene_performers (
scene_id INTEGER NOT NULL,
performer_id INTEGER NOT NULL,
PRIMARY KEY (scene_id, performer_id),
FOREIGN KEY (scene_id) REFERENCES scenes(id) ON DELETE CASCADE,
FOREIGN KEY (performer_id) REFERENCES performers(id) ON DELETE CASCADE
);
-- Scene-Tag many-to-many junction table (enhanced with ML support)
CREATE TABLE IF NOT EXISTS scene_tags (
scene_id INTEGER NOT NULL,
tag_id INTEGER NOT NULL,
confidence REAL DEFAULT 1.0,
source TEXT NOT NULL DEFAULT 'user',
verified INTEGER DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
PRIMARY KEY (scene_id, tag_id),
FOREIGN KEY (scene_id) REFERENCES scenes(id) ON DELETE CASCADE,
FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE
);
-- Scene Images table (for ML training and PornPics integration)
CREATE TABLE IF NOT EXISTS scene_images (
id INTEGER PRIMARY KEY AUTOINCREMENT,
scene_id INTEGER NOT NULL,
image_url TEXT NOT NULL,
image_path TEXT,
source TEXT,
source_id TEXT,
width INTEGER,
height INTEGER,
file_size INTEGER,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (scene_id) REFERENCES scenes(id) ON DELETE CASCADE
);
-- ML Predictions table (track model versions and predictions)
CREATE TABLE IF NOT EXISTS ml_predictions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
scene_id INTEGER,
image_id INTEGER,
model_version TEXT NOT NULL,
predictions TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (scene_id) REFERENCES scenes(id) ON DELETE CASCADE,
FOREIGN KEY (image_id) REFERENCES scene_images(id) ON DELETE CASCADE
);
-- Indexes for common queries (v0.1.0)
CREATE INDEX IF NOT EXISTS idx_performers_name ON performers(name);
CREATE INDEX IF NOT EXISTS idx_studios_name ON studios(name);
CREATE INDEX IF NOT EXISTS idx_scenes_title ON scenes(title);
CREATE INDEX IF NOT EXISTS idx_scenes_code ON scenes(code);
CREATE INDEX IF NOT EXISTS idx_scenes_date ON scenes(date);
CREATE INDEX IF NOT EXISTS idx_movies_title ON movies(title);
CREATE INDEX IF NOT EXISTS idx_movies_date ON movies(date);
CREATE INDEX IF NOT EXISTS idx_movie_scenes_movie ON movie_scenes(movie_id);
CREATE INDEX IF NOT EXISTS idx_movie_scenes_scene ON movie_scenes(scene_id);
-- Tag search indexes (v0.2.0 - ML ready)
CREATE INDEX IF NOT EXISTS idx_tag_categories_name ON tag_categories(name);
CREATE INDEX IF NOT EXISTS idx_tag_categories_parent ON tag_categories(parent_id);
CREATE INDEX IF NOT EXISTS idx_tags_name ON tags(name);
CREATE INDEX IF NOT EXISTS idx_tags_category ON tags(category_id);
-- Scene tag filtering indexes (critical for complex queries)
CREATE INDEX IF NOT EXISTS idx_scene_tags_tag ON scene_tags(tag_id);
CREATE INDEX IF NOT EXISTS idx_scene_tags_scene ON scene_tags(scene_id);
CREATE INDEX IF NOT EXISTS idx_scene_tags_confidence ON scene_tags(confidence);
CREATE INDEX IF NOT EXISTS idx_scene_tags_verified ON scene_tags(verified);
CREATE INDEX IF NOT EXISTS idx_scene_tags_source ON scene_tags(source);
-- Image processing indexes
CREATE INDEX IF NOT EXISTS idx_scene_images_scene ON scene_images(scene_id);
CREATE INDEX IF NOT EXISTS idx_scene_images_source ON scene_images(source, source_id);
-- ML prediction indexes
CREATE INDEX IF NOT EXISTS idx_ml_predictions_scene ON ml_predictions(scene_id);
CREATE INDEX IF NOT EXISTS idx_ml_predictions_image ON ml_predictions(image_id);
CREATE INDEX IF NOT EXISTS idx_ml_predictions_model ON ml_predictions(model_version);
-- Sync metadata table (track last sync times)
CREATE TABLE IF NOT EXISTS sync_metadata (
id INTEGER PRIMARY KEY AUTOINCREMENT,
entity_type TEXT NOT NULL UNIQUE,
last_sync_at TEXT NOT NULL,
records_updated INTEGER DEFAULT 0,
records_failed INTEGER DEFAULT 0,
status TEXT NOT NULL DEFAULT 'completed',
error_message TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_sync_metadata_entity ON sync_metadata(entity_type);
CREATE INDEX IF NOT EXISTS idx_sync_metadata_last_sync ON sync_metadata(last_sync_at);
`