2026-06-12 11:58:47 +00:00
|
|
|
# database/connection.py
|
|
|
|
|
import sqlite3
|
2026-06-16 05:06:08 +00:00
|
|
|
import os
|
2026-06-12 11:58:47 +00:00
|
|
|
|
|
|
|
|
def get_connection():
|
2026-06-16 05:06:08 +00:00
|
|
|
# Force the path to be absolute relative to the project folder
|
|
|
|
|
db_path = os.path.abspath("spanish_trainer.db")
|
|
|
|
|
return sqlite3.connect(db_path)
|
2026-06-12 11:58:47 +00:00
|
|
|
|
|
|
|
|
def init_db():
|
2026-06-16 05:06:08 +00:00
|
|
|
print("🛠️ Constructing relational database schema...")
|
2026-06-12 11:58:47 +00:00
|
|
|
conn = get_connection()
|
2026-06-14 09:56:43 +00:00
|
|
|
cursor = conn.cursor()
|
|
|
|
|
|
2026-06-16 05:06:08 +00:00
|
|
|
# Enable foreign keys explicitly for this connection instance
|
|
|
|
|
cursor.execute("PRAGMA foreign_keys = ON;")
|
|
|
|
|
|
|
|
|
|
# 1. Phrases Table (Holds individual localized text strings)
|
2026-06-14 09:56:43 +00:00
|
|
|
cursor.execute("""
|
|
|
|
|
CREATE TABLE IF NOT EXISTS phrases (
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
text TEXT NOT NULL,
|
|
|
|
|
language TEXT NOT NULL,
|
|
|
|
|
textbook TEXT,
|
|
|
|
|
unit INTEGER,
|
|
|
|
|
source_context TEXT,
|
|
|
|
|
word_type TEXT,
|
|
|
|
|
grammar_note TEXT,
|
|
|
|
|
voice_gender TEXT DEFAULT 'female',
|
|
|
|
|
base_speed REAL DEFAULT 1.0,
|
|
|
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
2026-06-16 05:06:08 +00:00
|
|
|
);
|
2026-06-14 09:56:43 +00:00
|
|
|
""")
|
|
|
|
|
|
2026-06-16 05:06:08 +00:00
|
|
|
# 2. Translations Table (The relational tie binding English and Spanish IDs together)
|
2026-06-14 09:56:43 +00:00
|
|
|
cursor.execute("""
|
|
|
|
|
CREATE TABLE IF NOT EXISTS translations (
|
2026-06-16 05:06:08 +00:00
|
|
|
translation_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
2026-06-14 09:56:43 +00:00
|
|
|
source_phrase_id INTEGER,
|
|
|
|
|
target_phrase_id INTEGER,
|
2026-06-16 05:06:08 +00:00
|
|
|
deck_name TEXT DEFAULT 'General',
|
2026-06-14 09:56:43 +00:00
|
|
|
FOREIGN KEY (source_phrase_id) REFERENCES phrases(id) ON DELETE CASCADE,
|
|
|
|
|
FOREIGN KEY (target_phrase_id) REFERENCES phrases(id) ON DELETE CASCADE
|
2026-06-16 05:06:08 +00:00
|
|
|
);
|
2026-06-14 09:56:43 +00:00
|
|
|
""")
|
2026-06-16 05:06:08 +00:00
|
|
|
|
|
|
|
|
# 3. Audio Tracks Table (Links phrase items to local disk storage clips)
|
2026-06-14 09:56:43 +00:00
|
|
|
cursor.execute("""
|
|
|
|
|
CREATE TABLE IF NOT EXISTS audio_tracks (
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
phrase_id INTEGER,
|
|
|
|
|
file_path TEXT NOT NULL,
|
|
|
|
|
FOREIGN KEY (phrase_id) REFERENCES phrases(id) ON DELETE CASCADE
|
2026-06-16 05:06:08 +00:00
|
|
|
);
|
2026-06-14 09:56:43 +00:00
|
|
|
""")
|
|
|
|
|
|
2026-06-16 05:06:08 +00:00
|
|
|
# CRITICAL: Force SQLite to physically commit the table architectures to disk
|
2026-06-14 09:56:43 +00:00
|
|
|
conn.commit()
|
2026-06-16 05:06:08 +00:00
|
|
|
|
|
|
|
|
# Verification Sweep: Double-check that tables actually exist before we hand over control
|
|
|
|
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
|
|
|
|
|
tables = [row[0] for row in cursor.fetchall()]
|
2026-06-14 09:56:43 +00:00
|
|
|
conn.close()
|
2026-06-16 05:06:08 +00:00
|
|
|
|
|
|
|
|
print(f"✅ Database tables physically confirmed on disk: {tables}")
|