-- ============================================ -- SUNDOL Database Schema - Oracle 23ai -- ============================================ -- USERS CREATE TABLE users ( id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY, email VARCHAR2(320) NOT NULL UNIQUE, display_name VARCHAR2(255), avatar_url VARCHAR2(1000), google_sub VARCHAR2(255) UNIQUE, refresh_token VARCHAR2(1000), created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL, updated_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL ); -- KNOWLEDGE_ITEMS CREATE TABLE knowledge_items ( id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY, user_id RAW(16) NOT NULL REFERENCES users(id), type VARCHAR2(20) NOT NULL, title VARCHAR2(500), source_url VARCHAR2(2000), raw_text CLOB, status VARCHAR2(20) DEFAULT 'PENDING' NOT NULL, created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL, updated_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL ); CREATE INDEX idx_ki_user_id ON knowledge_items(user_id); CREATE INDEX idx_ki_status ON knowledge_items(status); -- KNOWLEDGE_CHUNKS CREATE TABLE knowledge_chunks ( id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY, knowledge_item_id RAW(16) NOT NULL REFERENCES knowledge_items(id) ON DELETE CASCADE, chunk_index NUMBER(10) NOT NULL, content CLOB NOT NULL, embedding VECTOR(1024, FLOAT32), token_count NUMBER(10), created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL ); CREATE INDEX idx_kc_item_id ON knowledge_chunks(knowledge_item_id); -- VECTOR index for semantic search CREATE VECTOR INDEX idx_kc_embedding ON knowledge_chunks(embedding) ORGANIZATION NEIGHBOR PARTITIONS DISTANCE COSINE WITH TARGET ACCURACY 95; -- TAGS CREATE TABLE tags ( id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY, user_id RAW(16) NOT NULL REFERENCES users(id), name VARCHAR2(100) NOT NULL, color VARCHAR2(7) DEFAULT '#3b82f6', created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL ); CREATE UNIQUE INDEX idx_tags_user_name ON tags(user_id, name); -- KNOWLEDGE_ITEM_TAGS (many-to-many) CREATE TABLE knowledge_item_tags ( knowledge_item_id RAW(16) NOT NULL REFERENCES knowledge_items(id) ON DELETE CASCADE, tag_id RAW(16) NOT NULL REFERENCES tags(id) ON DELETE CASCADE, PRIMARY KEY (knowledge_item_id, tag_id) ); -- CHAT_SESSIONS CREATE TABLE chat_sessions ( id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY, user_id RAW(16) NOT NULL REFERENCES users(id), title VARCHAR2(500) DEFAULT 'New Chat', created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL, updated_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL ); CREATE INDEX idx_cs_user_id ON chat_sessions(user_id); -- CHAT_MESSAGES CREATE TABLE chat_messages ( id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY, session_id RAW(16) NOT NULL REFERENCES chat_sessions(id) ON DELETE CASCADE, role VARCHAR2(20) NOT NULL, content CLOB NOT NULL, source_chunks CLOB, tokens_used NUMBER(10), created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL ); CREATE INDEX idx_cm_session_id ON chat_messages(session_id); -- TODOS CREATE TABLE todos ( id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY, user_id RAW(16) NOT NULL REFERENCES users(id), parent_id RAW(16) REFERENCES todos(id) ON DELETE CASCADE, title VARCHAR2(500) NOT NULL, description CLOB, status VARCHAR2(20) DEFAULT 'PENDING' NOT NULL, priority VARCHAR2(10) DEFAULT 'MEDIUM' NOT NULL, due_date DATE, created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL, updated_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL ); CREATE INDEX idx_todos_user_id ON todos(user_id); CREATE INDEX idx_todos_parent_id ON todos(parent_id); -- HABITS CREATE TABLE habits ( id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY, user_id RAW(16) NOT NULL REFERENCES users(id), name VARCHAR2(200) NOT NULL, description VARCHAR2(1000), habit_type VARCHAR2(10) DEFAULT 'BUILD' NOT NULL, target_days VARCHAR2(50) DEFAULT 'DAILY', color VARCHAR2(7) DEFAULT '#22c55e', streak_current NUMBER(10) DEFAULT 0, streak_best NUMBER(10) DEFAULT 0, is_active NUMBER(1) DEFAULT 1, created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL, updated_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL ); CREATE INDEX idx_habits_user_id ON habits(user_id); -- HABIT_LOGS CREATE TABLE habit_logs ( id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY, habit_id RAW(16) NOT NULL REFERENCES habits(id) ON DELETE CASCADE, log_date DATE NOT NULL, checked_in NUMBER(1) DEFAULT 1, note VARCHAR2(500), created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL ); CREATE UNIQUE INDEX idx_hl_habit_date ON habit_logs(habit_id, log_date); -- STUDY_CARDS CREATE TABLE study_cards ( id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY, user_id RAW(16) NOT NULL REFERENCES users(id), knowledge_item_id RAW(16) REFERENCES knowledge_items(id) ON DELETE SET NULL, front CLOB NOT NULL, back CLOB NOT NULL, ease_factor NUMBER(4,2) DEFAULT 2.50, interval_days NUMBER(10) DEFAULT 0, repetitions NUMBER(10) DEFAULT 0, next_review_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL, created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL, updated_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL ); CREATE INDEX idx_sc_user_review ON study_cards(user_id, next_review_at);