lila/packages/db/drizzle/0011_nice_spyke.sql
lila 963bff4eb8 feat: migrate production schema from OMW to Kaikki flat vocabulary model
- Replace terms/translations/term_glosses/term_examples with vocabulary_entries
  and entry_translations
- Remove decks, topics and related tables (deferred)
- Add cefr_level and difficulty to entry_translations for game query filtering
- Update termModel.ts for new schema — getDistractors now takes sourceLanguage
- Update gameService.ts and multiplayerGameService.ts for entryId rename
- Update all test fixtures from termId to entryId
- Generate and apply migration 0011
2026-05-05 17:39:25 +02:00

46 lines
No EOL
2.9 KiB
SQL

CREATE TABLE "entry_translations" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"entry_id" uuid NOT NULL,
"target_language_code" varchar(10) NOT NULL,
"translation" text NOT NULL,
"sense_hint" text,
"cefr_level" varchar(2),
"difficulty" varchar(20),
"source" varchar(50) DEFAULT 'kaikki' NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "unique_translation" UNIQUE("entry_id","target_language_code","translation"),
CONSTRAINT "target_language_code_check" CHECK ("entry_translations"."target_language_code" IN ('en', 'it', 'de', 'fr', 'es')),
CONSTRAINT "cefr_check" CHECK ("entry_translations"."cefr_level" IS NULL OR "entry_translations"."cefr_level" IN ('A1', 'A2', 'B1', 'B2', 'C1', 'C2')),
CONSTRAINT "difficulty_check" CHECK ("entry_translations"."difficulty" IS NULL OR "entry_translations"."difficulty" IN ('easy', 'intermediate', 'hard'))
);
--> statement-breakpoint
CREATE TABLE "vocabulary_entries" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"headword" text NOT NULL,
"language_code" varchar(10) NOT NULL,
"pos" varchar(20) NOT NULL,
"sense_index" smallint DEFAULT 0 NOT NULL,
"gloss" text,
"examples" text[] DEFAULT '{}' NOT NULL,
"cefr_level" varchar(2),
"difficulty" varchar(20),
"source" varchar(50) DEFAULT 'kaikki' NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "unique_entry" UNIQUE("headword","language_code","pos","sense_index"),
CONSTRAINT "language_code_check" CHECK ("vocabulary_entries"."language_code" IN ('en', 'it', 'de', 'fr', 'es')),
CONSTRAINT "pos_check" CHECK ("vocabulary_entries"."pos" IN ('noun', 'verb', 'adjective', 'adverb')),
CONSTRAINT "cefr_check" CHECK ("vocabulary_entries"."cefr_level" IS NULL OR "vocabulary_entries"."cefr_level" IN ('A1', 'A2', 'B1', 'B2', 'C1', 'C2')),
CONSTRAINT "difficulty_check" CHECK ("vocabulary_entries"."difficulty" IS NULL OR "vocabulary_entries"."difficulty" IN ('easy', 'intermediate', 'hard'))
);
--> statement-breakpoint
DROP TABLE "deck_terms" CASCADE;--> statement-breakpoint
DROP TABLE "decks" CASCADE;--> statement-breakpoint
DROP TABLE "term_examples" CASCADE;--> statement-breakpoint
DROP TABLE "term_glosses" CASCADE;--> statement-breakpoint
DROP TABLE "term_topics" CASCADE;--> statement-breakpoint
DROP TABLE "terms" CASCADE;--> statement-breakpoint
DROP TABLE "topics" CASCADE;--> statement-breakpoint
DROP TABLE "translations" CASCADE;--> statement-breakpoint
ALTER TABLE "entry_translations" ADD CONSTRAINT "entry_translations_entry_id_vocabulary_entries_id_fk" FOREIGN KEY ("entry_id") REFERENCES "public"."vocabulary_entries"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "idx_translations_target_lang" ON "entry_translations" USING btree ("target_language_code","difficulty","entry_id");--> statement-breakpoint
CREATE INDEX "idx_entries_lang_pos" ON "vocabulary_entries" USING btree ("language_code","pos","difficulty");