-- PolyPhonia Database Schema -- Users table CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username VARCHAR(64) UNIQUE NOT NULL, password_hash VARCHAR(65) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Sessions table CREATE TABLE IF NOT EXISTS sessions ( id VARCHAR(33) PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, expires_at TIMESTAMP NOT NULL ); -- Tones table for storing user's tone sequences CREATE TABLE IF NOT EXISTS tones ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, name VARCHAR(255), tone_data JSONB NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- MIDI files table CREATE TABLE IF NOT EXISTS midi_files ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, filename VARCHAR(255) NOT NULL, file_data BYTEA, tone_config JSONB, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Indexes for performance CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON sessions(user_id); CREATE INDEX IF NOT EXISTS idx_sessions_expires_at ON sessions(expires_at); CREATE INDEX IF NOT EXISTS idx_tones_user_id ON tones(user_id); CREATE INDEX IF NOT EXISTS idx_midi_files_user_id ON midi_files(user_id); -- Function to auto-update updated_at timestamp CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = CURRENT_TIMESTAMP; RETURN NEW; END; $$ language 'plpgsql'; -- Trigger for tones table CREATE TRIGGER update_tones_updated_at BEFORE UPDATE ON tones FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();