41d4465905
Adds backend/src/db/migrations-runner.js: - Tracks applied migrations in _migrations table - Applies .sql files from src/db/migrations/ in alphabetical order - Each file runs in a transaction — fail-fast, no partial state - `migrate:bootstrap` marks 000_baseline.sql as applied on existing DBs 000_baseline.sql — full schema snapshot from prod DB (168 objects, 2026-05-06). Removed stale PostgreSQL migration files (001_init.sql, 002_constraints.sql) that used SERIAL/EXTENSION syntax incompatible with SQLite. npm scripts: migrate → migrations-runner.js (versioned) migrate:bootstrap → mark baseline applied (run once per env) migrate:legacy → legacy migrate.js (kept for reference) On prod DB after `migrate:bootstrap`: "Nothing to apply — schema is up to date". Legacy migrate.js still in place; tests still use it via setup.js (unchanged). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1018 lines
39 KiB
SQL
1018 lines
39 KiB
SQL
CREATE TABLE achievements (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
slug TEXT UNIQUE NOT NULL,
|
|
title TEXT NOT NULL,
|
|
icon TEXT NOT NULL DEFAULT '🏆',
|
|
category TEXT NOT NULL DEFAULT 'general',
|
|
description TEXT
|
|
);
|
|
|
|
CREATE TABLE admin_audit_log (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
admin_id INTEGER NOT NULL REFERENCES users(id),
|
|
action TEXT NOT NULL,
|
|
target TEXT,
|
|
detail TEXT,
|
|
ip TEXT,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE announcements (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
class_id INTEGER NOT NULL REFERENCES classes(id) ON DELETE CASCADE,
|
|
author_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
text TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE app_settings (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT NOT NULL DEFAULT ''
|
|
);
|
|
|
|
CREATE TABLE "assignment_sessions" (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
assignment_id INTEGER NOT NULL REFERENCES assignments(id) ON DELETE CASCADE,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
session_id INTEGER REFERENCES test_sessions(id) ON DELETE SET NULL,
|
|
attempt_num INTEGER NOT NULL DEFAULT 1,
|
|
first_seen_at TEXT
|
|
);
|
|
|
|
CREATE TABLE assignment_templates (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
created_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
label TEXT NOT NULL,
|
|
subject_slug TEXT NOT NULL,
|
|
mode TEXT NOT NULL DEFAULT 'exam',
|
|
count INTEGER NOT NULL DEFAULT 25,
|
|
topic_id INTEGER REFERENCES topics(id) ON DELETE SET NULL,
|
|
test_id INTEGER REFERENCES tests(id) ON DELETE SET NULL,
|
|
file_id INTEGER REFERENCES files(id) ON DELETE SET NULL,
|
|
is_homework INTEGER NOT NULL DEFAULT 0,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE "assignments" (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
class_id INTEGER REFERENCES classes(id) ON DELETE CASCADE,
|
|
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
|
|
title TEXT NOT NULL,
|
|
subject_slug TEXT NOT NULL,
|
|
mode TEXT NOT NULL DEFAULT 'exam',
|
|
count INTEGER NOT NULL DEFAULT 25,
|
|
topic_id INTEGER REFERENCES topics(id) ON DELETE SET NULL,
|
|
deadline TEXT,
|
|
created_by INTEGER NOT NULL REFERENCES users(id),
|
|
test_id INTEGER REFERENCES tests(id) ON DELETE SET NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
, file_id INTEGER REFERENCES files(id) ON DELETE SET NULL, is_homework INTEGER NOT NULL DEFAULT 0, max_attempts INTEGER NOT NULL DEFAULT 0);
|
|
|
|
CREATE TABLE avatar_requests (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
filename TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
reviewer_id INTEGER REFERENCES users(id),
|
|
reject_msg TEXT,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
reviewed_at TEXT
|
|
);
|
|
|
|
CREATE TABLE bio_challenges (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
title TEXT NOT NULL,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
type TEXT NOT NULL DEFAULT 'build',
|
|
target_formula TEXT NOT NULL DEFAULT '',
|
|
hint TEXT DEFAULT NULL,
|
|
xp_reward INTEGER NOT NULL DEFAULT 50,
|
|
difficulty INTEGER NOT NULL DEFAULT 1,
|
|
topic_tag TEXT DEFAULT NULL,
|
|
order_n INTEGER NOT NULL DEFAULT 0
|
|
, data_json TEXT DEFAULT NULL);
|
|
|
|
CREATE TABLE bio_elements (
|
|
symbol TEXT PRIMARY KEY,
|
|
name_ru TEXT NOT NULL,
|
|
valency_max INTEGER NOT NULL DEFAULT 1,
|
|
valency_opts TEXT NOT NULL DEFAULT '[1]',
|
|
color TEXT NOT NULL DEFAULT '#888888',
|
|
radius INTEGER NOT NULL DEFAULT 20,
|
|
mass REAL NOT NULL DEFAULT 1.0
|
|
);
|
|
|
|
CREATE TABLE bio_molecules (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
formula TEXT NOT NULL,
|
|
name_ru TEXT NOT NULL,
|
|
name_lat TEXT NOT NULL DEFAULT '',
|
|
category TEXT NOT NULL DEFAULT 'inorganic',
|
|
difficulty INTEGER NOT NULL DEFAULT 1,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
atoms_json TEXT NOT NULL DEFAULT '[]',
|
|
bonds_json TEXT NOT NULL DEFAULT '[]',
|
|
is_library INTEGER NOT NULL DEFAULT 1,
|
|
topic_tags TEXT NOT NULL DEFAULT '[]',
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE bio_reactions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
equation TEXT NOT NULL,
|
|
name_ru TEXT NOT NULL,
|
|
type TEXT NOT NULL DEFAULT 'synthesis',
|
|
description TEXT NOT NULL DEFAULT '',
|
|
reactant_ids TEXT NOT NULL DEFAULT '[]',
|
|
product_ids TEXT NOT NULL DEFAULT '[]',
|
|
conditions TEXT DEFAULT NULL,
|
|
energy_kj REAL DEFAULT NULL,
|
|
topic_tags TEXT NOT NULL DEFAULT '[]'
|
|
);
|
|
|
|
CREATE TABLE bio_user_challenges (
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
challenge_id INTEGER NOT NULL REFERENCES bio_challenges(id) ON DELETE CASCADE,
|
|
completed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
PRIMARY KEY (user_id, challenge_id)
|
|
);
|
|
|
|
CREATE TABLE bio_user_molecules (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
molecule_id INTEGER REFERENCES bio_molecules(id),
|
|
name TEXT DEFAULT NULL,
|
|
formula TEXT NOT NULL,
|
|
atoms_json TEXT NOT NULL,
|
|
bonds_json TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE bookmarks (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
entity_type TEXT NOT NULL CHECK (entity_type IN ('lesson','course','file','question')),
|
|
entity_id INTEGER NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
UNIQUE (user_id, entity_type, entity_id)
|
|
);
|
|
|
|
CREATE TABLE challenges (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
week TEXT NOT NULL,
|
|
title TEXT NOT NULL,
|
|
description TEXT,
|
|
type TEXT NOT NULL DEFAULT 'tests',
|
|
target INTEGER NOT NULL DEFAULT 3,
|
|
progress INTEGER NOT NULL DEFAULT 0,
|
|
xp_reward INTEGER NOT NULL DEFAULT 100,
|
|
subject_slug TEXT,
|
|
topic_id INTEGER,
|
|
completed INTEGER NOT NULL DEFAULT 0,
|
|
claimed INTEGER NOT NULL DEFAULT 0,
|
|
UNIQUE(user_id, week, title)
|
|
);
|
|
|
|
CREATE TABLE class_courses (
|
|
class_id INTEGER NOT NULL REFERENCES classes(id) ON DELETE CASCADE,
|
|
course_id INTEGER NOT NULL REFERENCES courses(id) ON DELETE CASCADE,
|
|
deadline TEXT,
|
|
assigned_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
assigned_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
PRIMARY KEY (class_id, course_id)
|
|
);
|
|
|
|
CREATE TABLE class_members (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
class_id INTEGER NOT NULL REFERENCES classes(id) ON DELETE CASCADE,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
joined_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
UNIQUE (class_id, user_id)
|
|
);
|
|
|
|
CREATE TABLE classes (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL,
|
|
description TEXT,
|
|
teacher_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
invite_code TEXT UNIQUE NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
, features TEXT, cover_emoji TEXT NOT NULL DEFAULT '');
|
|
|
|
CREATE TABLE classroom_attendance (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
session_id INTEGER NOT NULL REFERENCES classroom_sessions(id) ON DELETE CASCADE,
|
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
joined_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
left_at TEXT,
|
|
UNIQUE(session_id, user_id)
|
|
);
|
|
|
|
CREATE TABLE classroom_chat (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
session_id INTEGER NOT NULL REFERENCES classroom_sessions(id) ON DELETE CASCADE,
|
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
message TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
, pinned INTEGER NOT NULL DEFAULT 0, attachment_url TEXT, attachment_type TEXT);
|
|
|
|
CREATE TABLE classroom_chat_reactions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
chat_id INTEGER NOT NULL REFERENCES classroom_chat(id) ON DELETE CASCADE,
|
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
reaction TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
UNIQUE(chat_id, user_id, reaction)
|
|
);
|
|
|
|
CREATE TABLE classroom_draw_permissions (
|
|
session_id INTEGER NOT NULL REFERENCES classroom_sessions(id) ON DELETE CASCADE,
|
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
PRIMARY KEY (session_id, user_id)
|
|
);
|
|
|
|
CREATE TABLE classroom_hands (
|
|
session_id INTEGER NOT NULL REFERENCES classroom_sessions(id) ON DELETE CASCADE,
|
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
PRIMARY KEY (session_id, user_id)
|
|
);
|
|
|
|
CREATE TABLE classroom_invites (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
session_id INTEGER NOT NULL REFERENCES classroom_sessions(id) ON DELETE CASCADE,
|
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
UNIQUE(session_id, user_id)
|
|
);
|
|
|
|
CREATE TABLE classroom_notes (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
session_id INTEGER NOT NULL REFERENCES classroom_sessions(id) ON DELETE CASCADE,
|
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
content TEXT NOT NULL DEFAULT '',
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
UNIQUE(session_id, user_id)
|
|
);
|
|
|
|
CREATE TABLE classroom_pages (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
session_id INTEGER NOT NULL REFERENCES classroom_sessions(id) ON DELETE CASCADE,
|
|
page_num INTEGER NOT NULL DEFAULT 1,
|
|
bg_color TEXT NOT NULL DEFAULT '#ffffff', template TEXT NOT NULL DEFAULT 'blank', name TEXT,
|
|
UNIQUE(session_id, page_num)
|
|
);
|
|
|
|
CREATE TABLE classroom_sessions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
class_id INTEGER REFERENCES classes(id) ON DELETE CASCADE,
|
|
teacher_id INTEGER NOT NULL REFERENCES users(id),
|
|
title TEXT NOT NULL DEFAULT '',
|
|
status TEXT NOT NULL DEFAULT 'active',
|
|
current_page INTEGER NOT NULL DEFAULT 1,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
ended_at TEXT
|
|
, board_theme TEXT NOT NULL DEFAULT 'chalkboard');
|
|
|
|
CREATE TABLE classroom_strokes (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
session_id INTEGER NOT NULL REFERENCES classroom_sessions(id) ON DELETE CASCADE,
|
|
page_num INTEGER NOT NULL DEFAULT 1,
|
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
tool TEXT NOT NULL DEFAULT 'pencil',
|
|
data TEXT NOT NULL,
|
|
seq INTEGER NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE classroom_templates (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
teacher_id INTEGER NOT NULL REFERENCES users(id),
|
|
title TEXT NOT NULL,
|
|
description TEXT DEFAULT '',
|
|
pages_data TEXT NOT NULL DEFAULT '[]',
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE course_sections (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
course_id INTEGER NOT NULL REFERENCES courses(id) ON DELETE CASCADE,
|
|
title TEXT NOT NULL,
|
|
order_index INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE course_templates (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
title TEXT NOT NULL,
|
|
description TEXT,
|
|
category TEXT NOT NULL DEFAULT 'general',
|
|
subject_slug TEXT,
|
|
structure TEXT NOT NULL DEFAULT '{}',
|
|
is_public INTEGER NOT NULL DEFAULT 0,
|
|
created_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE courses (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
subject_slug TEXT NOT NULL,
|
|
title TEXT NOT NULL,
|
|
description TEXT,
|
|
cover_emoji TEXT NOT NULL DEFAULT '📚',
|
|
order_index INTEGER NOT NULL DEFAULT 0,
|
|
is_published INTEGER NOT NULL DEFAULT 0,
|
|
created_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE daily_goals (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
date TEXT NOT NULL,
|
|
tests_target INTEGER NOT NULL DEFAULT 3,
|
|
tests_done INTEGER NOT NULL DEFAULT 0,
|
|
xp_target INTEGER NOT NULL DEFAULT 200,
|
|
xp_earned INTEGER NOT NULL DEFAULT 0,
|
|
UNIQUE (user_id, date)
|
|
);
|
|
|
|
CREATE TABLE error_log (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
level TEXT NOT NULL DEFAULT 'error',
|
|
message TEXT NOT NULL,
|
|
stack TEXT,
|
|
route TEXT,
|
|
method TEXT,
|
|
user_id INTEGER,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE file_access (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,
|
|
type TEXT NOT NULL CHECK (type IN ('class', 'user')),
|
|
target_id INTEGER NOT NULL,
|
|
UNIQUE (file_id, type, target_id)
|
|
);
|
|
|
|
CREATE TABLE files (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
title TEXT NOT NULL,
|
|
description TEXT,
|
|
original_name TEXT NOT NULL,
|
|
stored_name TEXT NOT NULL UNIQUE,
|
|
mimetype TEXT,
|
|
size INTEGER,
|
|
subject_slug TEXT,
|
|
is_public INTEGER NOT NULL DEFAULT 1,
|
|
uploaded_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
, folder_id INTEGER);
|
|
|
|
CREATE TABLE flashcard_cards (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
deck_id INTEGER NOT NULL REFERENCES flashcard_decks(id) ON DELETE CASCADE,
|
|
front TEXT NOT NULL DEFAULT '',
|
|
back TEXT NOT NULL DEFAULT '',
|
|
order_idx INTEGER NOT NULL DEFAULT 0,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE flashcard_decks (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
title TEXT NOT NULL,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
color TEXT NOT NULL DEFAULT '#9B5DE5',
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE flashcard_reviews (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
card_id INTEGER NOT NULL REFERENCES flashcard_cards(id) ON DELETE CASCADE,
|
|
ease_factor REAL NOT NULL DEFAULT 2.5,
|
|
interval_days INTEGER NOT NULL DEFAULT 1,
|
|
repetitions INTEGER NOT NULL DEFAULT 0,
|
|
due_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
last_reviewed TEXT,
|
|
UNIQUE(user_id, card_id)
|
|
);
|
|
|
|
CREATE TABLE folder_access (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
folder_id INTEGER NOT NULL REFERENCES folders(id) ON DELETE CASCADE,
|
|
type TEXT NOT NULL CHECK (type IN ('class', 'user')),
|
|
target_id INTEGER NOT NULL,
|
|
UNIQUE (folder_id, type, target_id)
|
|
);
|
|
|
|
CREATE TABLE folders (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL,
|
|
created_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE geometry_submissions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
task_id INTEGER NOT NULL REFERENCES geometry_tasks(id) ON DELETE CASCADE,
|
|
student_id INTEGER NOT NULL REFERENCES users(id),
|
|
state_json TEXT NOT NULL DEFAULT '{}',
|
|
score REAL DEFAULT NULL,
|
|
feedback TEXT DEFAULT '',
|
|
submitted_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
UNIQUE(task_id, student_id)
|
|
);
|
|
|
|
CREATE TABLE geometry_tasks (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
teacher_id INTEGER NOT NULL REFERENCES users(id),
|
|
class_id INTEGER REFERENCES classes(id) ON DELETE SET NULL,
|
|
title TEXT NOT NULL DEFAULT 'Без названия',
|
|
description TEXT DEFAULT '',
|
|
state_json TEXT NOT NULL DEFAULT '{}',
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE "lesson_blocks" (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
lesson_id INTEGER NOT NULL REFERENCES lessons(id) ON DELETE CASCADE,
|
|
type TEXT NOT NULL DEFAULT 'text'
|
|
CHECK (type IN ('heading','text','formula','image','quiz','sim',
|
|
'table','code','divider','callout','video','flashcard',
|
|
'matching','fill-blank','ordering',
|
|
'accordion','timeline','diagram','geogebra','audio','columns','alert')),
|
|
order_index INTEGER NOT NULL DEFAULT 0,
|
|
data TEXT NOT NULL DEFAULT '{}'
|
|
);
|
|
|
|
CREATE TABLE lesson_comments (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
lesson_id INTEGER NOT NULL REFERENCES lessons(id) ON DELETE CASCADE,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
parent_id INTEGER REFERENCES lesson_comments(id) ON DELETE CASCADE,
|
|
text TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE lesson_notes (
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
lesson_id INTEGER NOT NULL REFERENCES lessons(id) ON DELETE CASCADE,
|
|
text TEXT NOT NULL DEFAULT '',
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
PRIMARY KEY (user_id, lesson_id)
|
|
);
|
|
|
|
CREATE TABLE lesson_progress (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
lesson_id INTEGER NOT NULL REFERENCES lessons(id) ON DELETE CASCADE,
|
|
completed INTEGER NOT NULL DEFAULT 0,
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
UNIQUE (user_id, lesson_id)
|
|
);
|
|
|
|
CREATE TABLE lesson_templates (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
title TEXT NOT NULL,
|
|
category TEXT NOT NULL DEFAULT 'general',
|
|
subject_slug TEXT,
|
|
blocks TEXT NOT NULL DEFAULT '[]',
|
|
is_public INTEGER NOT NULL DEFAULT 0,
|
|
created_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE lessons (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
course_id INTEGER NOT NULL REFERENCES courses(id) ON DELETE CASCADE,
|
|
title TEXT NOT NULL,
|
|
order_index INTEGER NOT NULL DEFAULT 0,
|
|
is_published INTEGER NOT NULL DEFAULT 0,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
, section_id INTEGER REFERENCES course_sections(id) ON DELETE SET NULL, read_time INTEGER NOT NULL DEFAULT 0);
|
|
|
|
CREATE TABLE "live_answers" (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
live_session_id INTEGER NOT NULL REFERENCES live_sessions(id) ON DELETE CASCADE,
|
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
question_id INTEGER REFERENCES questions(id) ON DELETE SET NULL,
|
|
option_id INTEGER REFERENCES options(id),
|
|
answer_text TEXT,
|
|
is_correct INTEGER,
|
|
answered_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
UNIQUE(live_session_id, user_id, question_id)
|
|
);
|
|
|
|
CREATE TABLE live_sessions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
class_id INTEGER NOT NULL REFERENCES classes(id) ON DELETE CASCADE,
|
|
teacher_id INTEGER NOT NULL REFERENCES users(id),
|
|
question_id INTEGER REFERENCES questions(id),
|
|
status TEXT NOT NULL DEFAULT 'waiting',
|
|
show_results INTEGER NOT NULL DEFAULT 0,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
ended_at TEXT
|
|
);
|
|
|
|
CREATE TABLE notifications (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
type TEXT NOT NULL DEFAULT 'info',
|
|
message TEXT NOT NULL,
|
|
link TEXT,
|
|
is_read INTEGER NOT NULL DEFAULT 0,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE options (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
question_id INTEGER NOT NULL REFERENCES questions(id) ON DELETE CASCADE,
|
|
text TEXT NOT NULL,
|
|
is_correct INTEGER NOT NULL DEFAULT 0,
|
|
order_index INTEGER NOT NULL DEFAULT 0
|
|
, match_pair TEXT);
|
|
|
|
CREATE TABLE parent_links (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
student_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
token TEXT UNIQUE NOT NULL,
|
|
label TEXT NOT NULL DEFAULT '',
|
|
is_active INTEGER NOT NULL DEFAULT 1,
|
|
last_used TEXT,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
expires_at TEXT
|
|
);
|
|
|
|
CREATE TABLE parent_notifications (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
parent_link_id INTEGER NOT NULL REFERENCES parent_links(id) ON DELETE CASCADE,
|
|
type TEXT NOT NULL DEFAULT 'info',
|
|
message TEXT NOT NULL,
|
|
is_read INTEGER NOT NULL DEFAULT 0,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE questions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
subject_id INTEGER NOT NULL REFERENCES subjects(id) ON DELETE CASCADE,
|
|
topic_id INTEGER REFERENCES topics(id) ON DELETE SET NULL,
|
|
text TEXT NOT NULL,
|
|
difficulty INTEGER NOT NULL DEFAULT 1 CHECK (difficulty BETWEEN 1 AND 3),
|
|
year INTEGER,
|
|
explanation TEXT,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
, type TEXT NOT NULL DEFAULT 'single', correct_text TEXT, image TEXT, source_type TEXT NOT NULL DEFAULT 'базовый');
|
|
|
|
CREATE TABLE rb_food_web (
|
|
predator_id INTEGER NOT NULL REFERENCES rb_species(id) ON DELETE CASCADE,
|
|
prey_id INTEGER NOT NULL REFERENCES rb_species(id) ON DELETE CASCADE,
|
|
strength REAL NOT NULL DEFAULT 0.5,
|
|
PRIMARY KEY (predator_id, prey_id)
|
|
);
|
|
|
|
CREATE TABLE rb_groups (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name_ru TEXT NOT NULL,
|
|
name_lat TEXT NOT NULL DEFAULT '',
|
|
icon TEXT NOT NULL DEFAULT '🌿',
|
|
color TEXT NOT NULL DEFAULT '#16a34a'
|
|
);
|
|
|
|
CREATE TABLE rb_habitats (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL,
|
|
type TEXT NOT NULL DEFAULT 'forest',
|
|
description TEXT NOT NULL DEFAULT '',
|
|
sound_file TEXT NOT NULL DEFAULT ''
|
|
);
|
|
|
|
CREATE TABLE rb_population_data (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
species_id INTEGER NOT NULL REFERENCES rb_species(id) ON DELETE CASCADE,
|
|
year INTEGER NOT NULL,
|
|
count_estimate INTEGER NOT NULL DEFAULT 0,
|
|
source TEXT NOT NULL DEFAULT ''
|
|
);
|
|
|
|
CREATE TABLE rb_quests (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
title TEXT NOT NULL,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
species_ids TEXT NOT NULL DEFAULT '[]',
|
|
xp_reward INTEGER NOT NULL DEFAULT 150,
|
|
badge_slug TEXT NOT NULL DEFAULT ''
|
|
);
|
|
|
|
CREATE TABLE rb_sightings (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
species_id INTEGER NOT NULL REFERENCES rb_species(id) ON DELETE CASCADE,
|
|
region_code TEXT NOT NULL DEFAULT '',
|
|
description TEXT NOT NULL DEFAULT '',
|
|
photo_url TEXT NOT NULL DEFAULT '',
|
|
confirmed_by_teacher INTEGER NOT NULL DEFAULT 0,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE rb_species (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
group_id INTEGER NOT NULL REFERENCES rb_groups(id),
|
|
habitat_id INTEGER REFERENCES rb_habitats(id),
|
|
name_ru TEXT NOT NULL,
|
|
name_be TEXT NOT NULL DEFAULT '',
|
|
name_lat TEXT NOT NULL DEFAULT '',
|
|
category TEXT NOT NULL DEFAULT 'VU'
|
|
CHECK (category IN ('CR','EN','VU','NT','LC')),
|
|
by_category TEXT NOT NULL DEFAULT 'III',
|
|
description TEXT NOT NULL DEFAULT '',
|
|
interesting_fact TEXT NOT NULL DEFAULT '',
|
|
threats TEXT NOT NULL DEFAULT '[]',
|
|
conservation TEXT NOT NULL DEFAULT '',
|
|
where_to_see TEXT NOT NULL DEFAULT '',
|
|
photo_url TEXT NOT NULL DEFAULT '',
|
|
model_type TEXT NOT NULL DEFAULT 'silhouette'
|
|
CHECK (model_type IN ('procedural','silhouette','none')),
|
|
population_trend TEXT NOT NULL DEFAULT '[]',
|
|
biomass_kg REAL NOT NULL DEFAULT 0,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
, season_active TEXT NOT NULL DEFAULT '', name_be_short TEXT NOT NULL DEFAULT '');
|
|
|
|
CREATE TABLE rb_species_regions (
|
|
species_id INTEGER NOT NULL REFERENCES rb_species(id) ON DELETE CASCADE,
|
|
region_code TEXT NOT NULL
|
|
CHECK (region_code IN ('brest','vitebsk','gomel','grodno','minsk','mogilev')),
|
|
PRIMARY KEY (species_id, region_code)
|
|
);
|
|
|
|
CREATE TABLE rb_user_collection (
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
species_id INTEGER NOT NULL REFERENCES rb_species(id) ON DELETE CASCADE,
|
|
unlock_method TEXT NOT NULL DEFAULT 'explore',
|
|
notes TEXT NOT NULL DEFAULT '',
|
|
unlocked_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
PRIMARY KEY (user_id, species_id)
|
|
);
|
|
|
|
CREATE TABLE rb_user_quests (
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
quest_id INTEGER NOT NULL REFERENCES rb_quests(id) ON DELETE CASCADE,
|
|
status TEXT NOT NULL DEFAULT 'active'
|
|
CHECK (status IN ('active','completed')),
|
|
progress TEXT NOT NULL DEFAULT '{}',
|
|
completed_at TEXT,
|
|
PRIMARY KEY (user_id, quest_id)
|
|
);
|
|
|
|
CREATE TABLE "role_permissions" (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
role TEXT NOT NULL CHECK (role IN ('teacher', 'student', 'free_student')),
|
|
permission TEXT NOT NULL,
|
|
enabled INTEGER NOT NULL DEFAULT 0,
|
|
UNIQUE (role, permission)
|
|
);
|
|
|
|
CREATE TABLE session_questions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
session_id INTEGER NOT NULL REFERENCES test_sessions(id) ON DELETE CASCADE,
|
|
question_id INTEGER NOT NULL REFERENCES questions(id),
|
|
order_index INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE TABLE shop_items (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL,
|
|
description TEXT,
|
|
type TEXT NOT NULL DEFAULT 'frame'
|
|
CHECK (type IN ('frame','theme','title','effect')),
|
|
category TEXT NOT NULL DEFAULT 'cosmetic',
|
|
price INTEGER NOT NULL DEFAULT 100,
|
|
data TEXT NOT NULL DEFAULT '{}',
|
|
icon TEXT NOT NULL DEFAULT 'star',
|
|
is_active INTEGER NOT NULL DEFAULT 1,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE subjects (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
slug TEXT UNIQUE NOT NULL,
|
|
name TEXT NOT NULL,
|
|
icon TEXT
|
|
, default_mode TEXT NOT NULL DEFAULT 'exam', default_count INTEGER NOT NULL DEFAULT 25, default_test_id INTEGER REFERENCES tests(id) ON DELETE SET NULL);
|
|
|
|
CREATE TABLE submission_log (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
submission_id INTEGER NOT NULL,
|
|
class_id INTEGER,
|
|
assignment_id INTEGER,
|
|
student_id INTEGER NOT NULL,
|
|
student_name TEXT,
|
|
original_name TEXT,
|
|
status TEXT,
|
|
grade INTEGER,
|
|
teacher_note TEXT,
|
|
submitted_at TEXT,
|
|
action TEXT NOT NULL DEFAULT 'deleted',
|
|
deleted_by INTEGER NOT NULL,
|
|
deleted_by_role TEXT,
|
|
deleted_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE "submissions" (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
class_id INTEGER NOT NULL REFERENCES classes(id) ON DELETE CASCADE,
|
|
assignment_id INTEGER REFERENCES assignments(id) ON DELETE SET NULL,
|
|
student_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
original_name TEXT NOT NULL,
|
|
stored_name TEXT NOT NULL UNIQUE,
|
|
mimetype TEXT,
|
|
size INTEGER,
|
|
message TEXT,
|
|
status TEXT NOT NULL DEFAULT 'new' CHECK (status IN ('new','reviewed','revision','resubmitted','accepted')),
|
|
teacher_note TEXT,
|
|
grade INTEGER,
|
|
reviewed_at TEXT,
|
|
submitted_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE test_questions (
|
|
test_id INTEGER NOT NULL REFERENCES tests(id) ON DELETE CASCADE,
|
|
question_id INTEGER NOT NULL REFERENCES questions(id) ON DELETE CASCADE,
|
|
order_index INTEGER NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (test_id, question_id)
|
|
);
|
|
|
|
CREATE TABLE test_sessions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
subject_id INTEGER REFERENCES subjects(id) ON DELETE SET NULL,
|
|
mode TEXT NOT NULL DEFAULT 'exam'
|
|
CHECK (mode IN ('exam', 'practice', 'topic', 'random')),
|
|
total INTEGER NOT NULL,
|
|
score INTEGER,
|
|
status TEXT NOT NULL DEFAULT 'in_progress'
|
|
CHECK (status IN ('in_progress', 'completed', 'abandoned')),
|
|
started_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
finished_at TEXT
|
|
);
|
|
|
|
CREATE TABLE tests (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
title TEXT NOT NULL,
|
|
subject_slug TEXT NOT NULL,
|
|
description TEXT,
|
|
created_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
, show_answers INTEGER NOT NULL DEFAULT 1, time_limit INTEGER);
|
|
|
|
CREATE TABLE topics (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
subject_id INTEGER NOT NULL REFERENCES subjects(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
order_index INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE user_achievements (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
achievement_id INTEGER NOT NULL REFERENCES achievements(id) ON DELETE CASCADE,
|
|
unlocked_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
UNIQUE (user_id, achievement_id)
|
|
);
|
|
|
|
CREATE TABLE user_answers (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
session_id INTEGER NOT NULL REFERENCES test_sessions(id) ON DELETE CASCADE,
|
|
question_id INTEGER NOT NULL REFERENCES questions(id),
|
|
chosen_option_id INTEGER REFERENCES options(id),
|
|
is_correct INTEGER,
|
|
time_spent_sec INTEGER,
|
|
answered_at TEXT NOT NULL DEFAULT (datetime('now')), answer_text TEXT,
|
|
UNIQUE (session_id, question_id)
|
|
);
|
|
|
|
CREATE TABLE user_permissions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
permission TEXT NOT NULL,
|
|
enabled INTEGER NOT NULL DEFAULT 0,
|
|
UNIQUE (user_id, permission)
|
|
);
|
|
|
|
CREATE TABLE user_preferences (
|
|
user_id INTEGER PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
|
data TEXT NOT NULL DEFAULT '{}',
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE user_purchases (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
item_id INTEGER NOT NULL REFERENCES shop_items(id) ON DELETE CASCADE,
|
|
purchased_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
UNIQUE(user_id, item_id)
|
|
);
|
|
|
|
CREATE TABLE "users" (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
email TEXT UNIQUE NOT NULL,
|
|
password_hash TEXT NOT NULL,
|
|
name TEXT NOT NULL,
|
|
role TEXT NOT NULL DEFAULT 'student'
|
|
CHECK (role IN ('student','teacher','admin','free_student')),
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
last_login TEXT,
|
|
xp INTEGER NOT NULL DEFAULT 0,
|
|
level INTEGER NOT NULL DEFAULT 1,
|
|
streak_current INTEGER NOT NULL DEFAULT 0,
|
|
streak_best INTEGER NOT NULL DEFAULT 0,
|
|
streak_date TEXT,
|
|
goal_tier TEXT DEFAULT 'medium',
|
|
avatar_frame TEXT DEFAULT 'default',
|
|
coins INTEGER NOT NULL DEFAULT 0,
|
|
active_title TEXT DEFAULT NULL,
|
|
active_theme TEXT DEFAULT NULL,
|
|
active_effect TEXT DEFAULT NULL,
|
|
token_version INTEGER NOT NULL DEFAULT 0,
|
|
lab_experiments INTEGER NOT NULL DEFAULT 0,
|
|
lab_reactions INTEGER NOT NULL DEFAULT 0,
|
|
is_banned INTEGER NOT NULL DEFAULT 0
|
|
, pet_name TEXT, pet_color TEXT DEFAULT 'purple', pet_last_petted TEXT, pet_petting_streak INT DEFAULT 0, pet_last_star TEXT, pet_bg TEXT DEFAULT 'default', pet_bg_owned TEXT DEFAULT '[]', pet_last_fed TEXT, avatar_url TEXT DEFAULT NULL);
|
|
|
|
CREATE TABLE xp_log (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
amount INTEGER NOT NULL,
|
|
reason TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE INDEX idx_announcements_class ON announcements(class_id);
|
|
|
|
CREATE INDEX idx_answers_session ON user_answers(session_id);
|
|
|
|
CREATE INDEX idx_answers_sq ON user_answers(session_id, question_id);
|
|
|
|
CREATE INDEX idx_assign_sess_assign ON assignment_sessions(assignment_id);
|
|
|
|
CREATE INDEX idx_assign_sess_user ON assignment_sessions(user_id);
|
|
|
|
CREATE INDEX idx_assignments_class ON assignments(class_id);
|
|
|
|
CREATE INDEX idx_assignments_deadline ON assignments(deadline);
|
|
|
|
CREATE INDEX idx_assignments_user ON assignments(user_id);
|
|
|
|
CREATE INDEX idx_audit_log_admin ON admin_audit_log(admin_id);
|
|
|
|
CREATE INDEX idx_audit_log_date ON admin_audit_log(created_at DESC);
|
|
|
|
CREATE INDEX idx_avatar_req_status ON avatar_requests(status);
|
|
|
|
CREATE INDEX idx_avatar_req_user ON avatar_requests(user_id);
|
|
|
|
CREATE INDEX idx_bio_mol_cat ON bio_molecules(category);
|
|
|
|
CREATE INDEX idx_bio_mol_formula ON bio_molecules(formula);
|
|
|
|
CREATE INDEX idx_bio_user_chal ON bio_user_challenges(user_id);
|
|
|
|
CREATE INDEX idx_bio_user_mol ON bio_user_molecules(user_id);
|
|
|
|
CREATE INDEX idx_blocks_lesson ON lesson_blocks(lesson_id);
|
|
|
|
CREATE INDEX idx_bookmarks_user ON bookmarks(user_id);
|
|
|
|
CREATE INDEX idx_cc_class ON class_courses(class_id);
|
|
|
|
CREATE INDEX idx_cc_course ON class_courses(course_id);
|
|
|
|
CREATE INDEX idx_challenges_user_week ON challenges(user_id, week);
|
|
|
|
CREATE INDEX idx_class_members_class ON class_members(class_id);
|
|
|
|
CREATE INDEX idx_class_members_user ON class_members(user_id);
|
|
|
|
CREATE INDEX idx_courses_creator ON courses(created_by);
|
|
|
|
CREATE INDEX idx_courses_subject ON courses(subject_slug);
|
|
|
|
CREATE INDEX idx_cr_chat ON classroom_chat(session_id);
|
|
|
|
CREATE INDEX idx_cr_reactions ON classroom_chat_reactions(chat_id);
|
|
|
|
CREATE INDEX idx_cr_sessions_class ON classroom_sessions(class_id, status);
|
|
|
|
CREATE INDEX idx_cr_strokes ON classroom_strokes(session_id, page_num, seq);
|
|
|
|
CREATE INDEX idx_ctpl_creator ON course_templates(created_by);
|
|
|
|
CREATE INDEX idx_ctpl_public ON course_templates(is_public);
|
|
|
|
CREATE INDEX idx_daily_goals_user ON daily_goals(user_id, date);
|
|
|
|
CREATE INDEX idx_error_log_date ON error_log(created_at DESC);
|
|
|
|
CREATE INDEX idx_file_access_file ON file_access(file_id);
|
|
|
|
CREATE INDEX idx_files_subject ON files(subject_slug);
|
|
|
|
CREATE INDEX idx_files_uploader ON files(uploaded_by);
|
|
|
|
CREATE INDEX idx_folder_access_folder ON folder_access(folder_id);
|
|
|
|
CREATE INDEX idx_geo_subs_student ON geometry_submissions(student_id);
|
|
|
|
CREATE INDEX idx_geo_subs_task ON geometry_submissions(task_id);
|
|
|
|
CREATE INDEX idx_geo_tasks_teacher ON geometry_tasks(teacher_id);
|
|
|
|
CREATE INDEX idx_lcomments_lesson ON lesson_comments(lesson_id);
|
|
|
|
CREATE INDEX idx_lcomments_parent ON lesson_comments(parent_id);
|
|
|
|
CREATE INDEX idx_lcomments_user ON lesson_comments(user_id);
|
|
|
|
CREATE INDEX idx_lessons_course ON lessons(course_id);
|
|
|
|
CREATE INDEX idx_live_answers_question ON live_answers(live_session_id, question_id);
|
|
|
|
CREATE INDEX idx_live_answers_session ON live_answers(live_session_id);
|
|
|
|
CREATE INDEX idx_live_sessions_class ON live_sessions(class_id, status);
|
|
|
|
CREATE INDEX idx_lprogress_lesson ON lesson_progress(lesson_id);
|
|
|
|
CREATE INDEX idx_lprogress_user ON lesson_progress(user_id);
|
|
|
|
CREATE INDEX idx_ltpl_creator ON lesson_templates(created_by);
|
|
|
|
CREATE INDEX idx_ltpl_public ON lesson_templates(is_public);
|
|
|
|
CREATE INDEX idx_notes_lesson ON lesson_notes(lesson_id);
|
|
|
|
CREATE INDEX idx_notes_user ON lesson_notes(user_id);
|
|
|
|
CREATE INDEX idx_notifications_user ON notifications(user_id, is_read);
|
|
|
|
CREATE INDEX idx_parent_links_student ON parent_links(student_id);
|
|
|
|
CREATE INDEX idx_parent_links_token ON parent_links(token);
|
|
|
|
CREATE INDEX idx_parent_notif_link ON parent_notifications(parent_link_id, is_read);
|
|
|
|
CREATE INDEX idx_parent_notif_link_date ON parent_notifications(parent_link_id, created_at DESC);
|
|
|
|
CREATE INDEX idx_purchases_user ON user_purchases(user_id);
|
|
|
|
CREATE INDEX idx_questions_source ON questions(source_type);
|
|
|
|
CREATE INDEX idx_questions_subject ON questions(subject_id);
|
|
|
|
CREATE INDEX idx_questions_topic ON questions(topic_id);
|
|
|
|
CREATE INDEX idx_rb_collection_user ON rb_user_collection(user_id);
|
|
|
|
CREATE INDEX idx_rb_popdata_species ON rb_population_data(species_id);
|
|
|
|
CREATE INDEX idx_rb_sightings_user ON rb_sightings(user_id);
|
|
|
|
CREATE INDEX idx_rb_species_category ON rb_species(category);
|
|
|
|
CREATE INDEX idx_rb_species_group ON rb_species(group_id);
|
|
|
|
CREATE INDEX idx_sections_course ON course_sections(course_id);
|
|
|
|
CREATE INDEX idx_sessions_user ON test_sessions(user_id);
|
|
|
|
CREATE INDEX idx_sessions_user_status ON test_sessions(user_id, status);
|
|
|
|
CREATE INDEX idx_sessions_user_status_date ON test_sessions(user_id, status, started_at DESC);
|
|
|
|
CREATE INDEX idx_sq_session ON session_questions(session_id);
|
|
|
|
CREATE INDEX idx_submissions_assignment ON submissions(assignment_id);
|
|
|
|
CREATE INDEX idx_submissions_class ON submissions(class_id);
|
|
|
|
CREATE INDEX idx_submissions_student ON submissions(student_id);
|
|
|
|
CREATE INDEX idx_test_sessions_status ON test_sessions(status);
|
|
|
|
CREATE INDEX idx_test_sessions_user_status ON test_sessions(user_id, status);
|
|
|
|
CREATE UNIQUE INDEX idx_topics_uniq ON topics(subject_id, name);
|
|
|
|
CREATE INDEX idx_tpl_creator ON assignment_templates(created_by);
|
|
|
|
CREATE INDEX idx_user_achievements_user ON user_achievements(user_id);
|
|
|
|
CREATE INDEX idx_user_permissions_user ON user_permissions(user_id);
|
|
|
|
CREATE INDEX idx_xp_log_date ON xp_log(created_at);
|
|
|
|
CREATE INDEX idx_xp_log_user ON xp_log(user_id);
|
|
|
|
CREATE INDEX idx_xp_log_user_created ON xp_log(user_id, created_at);
|