Files
STCourses/packages/db/migrations/0001_init.sql
T

69 lines
3.0 KiB
SQL

-- Portable SQL: TEXT ids and ISO-8601 timestamps, INTEGER booleans, TEXT JSON.
CREATE TABLE user_roles (
user_id TEXT NOT NULL, role TEXT NOT NULL,
PRIMARY KEY (user_id, role)
);
CREATE TABLE groups (id TEXT PRIMARY KEY, name TEXT NOT NULL UNIQUE);
CREATE TABLE group_members (
group_id TEXT NOT NULL, user_id TEXT NOT NULL,
PRIMARY KEY (group_id, user_id)
);
CREATE TABLE course_authors (
course_id TEXT NOT NULL, user_id TEXT NOT NULL,
PRIMARY KEY (course_id, user_id)
);
CREATE TABLE course_acl (
course_id TEXT NOT NULL,
principal_type TEXT NOT NULL CHECK (principal_type IN ('user', 'group')),
principal_id TEXT NOT NULL,
PRIMARY KEY (course_id, principal_type, principal_id)
);
CREATE TABLE progress (
user_id TEXT NOT NULL, course_id TEXT NOT NULL, lesson_id TEXT NOT NULL,
state TEXT NOT NULL CHECK (state IN ('not-started', 'in-progress', 'done')),
position_seconds DOUBLE PRECISION,
updated_at TEXT NOT NULL,
PRIMARY KEY (user_id, course_id, lesson_id)
);
CREATE TABLE notes (
id TEXT PRIMARY KEY, user_id TEXT NOT NULL, course_id TEXT NOT NULL, lesson_id TEXT NOT NULL,
anchor_kind TEXT NOT NULL CHECK (anchor_kind IN ('none', 'video', 'slide')),
anchor_value TEXT, deck_id TEXT,
body TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL
);
CREATE INDEX notes_by_lesson ON notes (user_id, course_id, lesson_id);
CREATE TABLE exercise_attempts (
user_id TEXT NOT NULL, course_id TEXT NOT NULL, lesson_id TEXT NOT NULL, track TEXT NOT NULL,
code TEXT NOT NULL, result_json TEXT, passed INTEGER NOT NULL, updated_at TEXT NOT NULL,
PRIMARY KEY (user_id, course_id, lesson_id, track)
);
CREATE TABLE user_api_keys (
user_id TEXT NOT NULL, provider TEXT NOT NULL, ciphertext TEXT NOT NULL, created_at TEXT NOT NULL,
PRIMARY KEY (user_id, provider)
);
CREATE TABLE ai_settings (
scope TEXT NOT NULL CHECK (scope IN ('server', 'user')),
owner_id TEXT NOT NULL, -- '' for server scope
mentor_off INTEGER NOT NULL, config_json TEXT NOT NULL, updated_at TEXT NOT NULL,
PRIMARY KEY (scope, owner_id)
);
CREATE TABLE ai_conversations (
id TEXT PRIMARY KEY, user_id TEXT NOT NULL, course_id TEXT NOT NULL, title TEXT, created_at TEXT NOT NULL
);
CREATE TABLE ai_messages (
id TEXT PRIMARY KEY, conversation_id TEXT NOT NULL, role TEXT NOT NULL, content TEXT NOT NULL, created_at TEXT NOT NULL
);
CREATE INDEX ai_messages_by_conversation ON ai_messages (conversation_id);
CREATE TABLE library_settings (key TEXT PRIMARY KEY, value TEXT NOT NULL);
CREATE TABLE collections (id TEXT PRIMARY KEY, title TEXT NOT NULL, sort INTEGER NOT NULL);
CREATE TABLE collection_courses (
collection_id TEXT NOT NULL, course_id TEXT NOT NULL, sort INTEGER NOT NULL,
PRIMARY KEY (collection_id, course_id)
);
CREATE TABLE jobs (
id TEXT PRIMARY KEY, kind TEXT NOT NULL, status TEXT NOT NULL, progress DOUBLE PRECISION NOT NULL,
message TEXT, payload_json TEXT NOT NULL, result_json TEXT, error TEXT,
created_at TEXT NOT NULL, updated_at TEXT NOT NULL
);
CREATE INDEX jobs_by_status ON jobs (status);