Spaces:
Running
Running
-- AI Language Tutor Database Schema | |
-- Table for storing extracted metadata from user queries | |
CREATE TABLE IF NOT EXISTS metadata_extractions ( | |
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))), | |
user_id INTEGER, | |
query TEXT NOT NULL, | |
native_language TEXT, | |
target_language TEXT, | |
proficiency TEXT CHECK(proficiency IN ('beginner', 'intermediate', 'advanced')), | |
title TEXT, | |
description TEXT, | |
metadata_json TEXT NOT NULL, -- Full JSON response | |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
); | |
-- Index for user queries | |
CREATE INDEX IF NOT EXISTS idx_metadata_user_id ON metadata_extractions(user_id); | |
CREATE INDEX IF NOT EXISTS idx_metadata_languages ON metadata_extractions(native_language, target_language); | |
-- Table for storing generated curricula | |
CREATE TABLE IF NOT EXISTS curricula ( | |
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))), | |
metadata_extraction_id TEXT NOT NULL, | |
user_id INTEGER, | |
lesson_topic TEXT, | |
curriculum_json TEXT NOT NULL, -- Full curriculum JSON with 25 lessons | |
is_content_generated INTEGER DEFAULT 0, -- Boolean: has all content been generated? | |
content_generation_status TEXT DEFAULT 'pending' CHECK(content_generation_status IN ('pending', 'generating', 'completed', 'failed')), | |
content_generation_error TEXT, -- Store error message if generation fails | |
content_generation_started_at TIMESTAMP, | |
content_generation_completed_at TIMESTAMP, | |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
FOREIGN KEY (metadata_extraction_id) REFERENCES metadata_extractions(id) ON DELETE CASCADE | |
); | |
-- Index for curriculum lookups | |
CREATE INDEX IF NOT EXISTS idx_curricula_metadata_id ON curricula(metadata_extraction_id); | |
CREATE INDEX IF NOT EXISTS idx_curricula_user_id ON curricula(user_id); | |
-- Table for storing all types of learning content | |
CREATE TABLE IF NOT EXISTS learning_content ( | |
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))), | |
curriculum_id TEXT NOT NULL, | |
content_type TEXT NOT NULL CHECK(content_type IN ('flashcards', 'exercises', 'simulation')), | |
lesson_index INTEGER NOT NULL CHECK(lesson_index >= 0 AND lesson_index < 25), | |
lesson_topic TEXT, | |
content_json TEXT NOT NULL, -- The actual generated content | |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
FOREIGN KEY (curriculum_id) REFERENCES curricula(id) ON DELETE CASCADE | |
); | |
-- Index for content lookups | |
CREATE INDEX IF NOT EXISTS idx_content_curriculum_id ON learning_content(curriculum_id); | |
CREATE INDEX IF NOT EXISTS idx_content_type ON learning_content(content_type); | |
CREATE INDEX IF NOT EXISTS idx_content_lesson ON learning_content(curriculum_id, lesson_index); | |
-- View for easy access to user's learning journeys | |
CREATE VIEW IF NOT EXISTS user_learning_journeys AS | |
SELECT | |
m.id as metadata_id, | |
m.user_id, | |
m.query, | |
m.native_language, | |
m.target_language, | |
m.proficiency, | |
m.title, | |
m.description, | |
c.id as curriculum_id, | |
c.lesson_topic, | |
c.is_content_generated, | |
c.content_generation_status, | |
c.content_generation_error, | |
c.content_generation_started_at, | |
c.content_generation_completed_at, | |
m.created_at | |
FROM metadata_extractions m | |
LEFT JOIN curricula c ON m.id = c.metadata_extraction_id | |
ORDER BY m.created_at DESC; | |
-- View for content availability per curriculum | |
CREATE VIEW IF NOT EXISTS curriculum_content_status AS | |
SELECT | |
c.id as curriculum_id, | |
c.user_id, | |
c.lesson_topic, | |
c.content_generation_status, | |
c.content_generation_error, | |
c.content_generation_started_at, | |
c.content_generation_completed_at, | |
COUNT(DISTINCT lc.lesson_index) as lessons_with_content, | |
COUNT(DISTINCT CASE WHEN lc.content_type = 'flashcards' THEN lc.lesson_index END) as lessons_with_flashcards, | |
COUNT(DISTINCT CASE WHEN lc.content_type = 'exercises' THEN lc.lesson_index END) as lessons_with_exercises, | |
COUNT(DISTINCT CASE WHEN lc.content_type = 'simulation' THEN lc.lesson_index END) as lessons_with_simulations, | |
c.created_at | |
FROM curricula c | |
LEFT JOIN learning_content lc ON c.id = lc.curriculum_id | |
GROUP BY c.id; | |
-- Generic cache for API responses to reduce redundant AI calls | |
CREATE TABLE IF NOT EXISTS api_cache ( | |
cache_key TEXT NOT NULL, | |
category TEXT NOT NULL, | |
content_json TEXT NOT NULL, | |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
PRIMARY KEY (cache_key, category) | |
) WITHOUT ROWID; | |
-- Index for faster cache lookups | |
CREATE INDEX IF NOT EXISTS idx_api_cache_key_category ON api_cache(cache_key, category); |