mirror of
https://github.com/OHTU-German-learning-website/OHTU-German-learning-website.git
synced 2026-10-12 19:13:51 +03:00
770 lines
28 KiB
PL/PgSQL
770 lines
28 KiB
PL/PgSQL
CREATE OR REPLACE FUNCTION public.check_dnd_match_pair_exercise_integrity()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $function$
|
|
DECLARE
|
|
left_exercise_id BIGINT;
|
|
right_exercise_id BIGINT;
|
|
BEGIN
|
|
SELECT dnd_match_exercise_id INTO left_exercise_id
|
|
FROM dnd_match_pairs WHERE id = NEW.left_pair_id;
|
|
|
|
SELECT dnd_match_exercise_id INTO right_exercise_id
|
|
FROM dnd_match_pairs WHERE id = NEW.selected_right_pair_id;
|
|
|
|
IF left_exercise_id IS DISTINCT FROM NEW.dnd_match_exercise_id
|
|
OR right_exercise_id IS DISTINCT FROM NEW.dnd_match_exercise_id THEN
|
|
RAISE EXCEPTION
|
|
'dnd_match_user_answers: left_pair_id and selected_right_pair_id must belong to dnd_match_exercise_id %',
|
|
NEW.dnd_match_exercise_id;
|
|
END IF;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$function$
|
|
;
|
|
|
|
CREATE OR REPLACE FUNCTION public.insert_into_exercises()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $function$
|
|
DECLARE
|
|
new_exercise_id BIGINT;
|
|
BEGIN
|
|
-- Insert a new row into the exercises table
|
|
INSERT INTO exercises (created_at, updated_at, category)
|
|
VALUES (NOW(), NOW(), 'click')
|
|
RETURNING id INTO new_exercise_id;
|
|
|
|
-- Link the new exercise to the click_exercises entry
|
|
INSERT INTO click_to_exercises (click_id, exercise_id, created_at, updated_at)
|
|
VALUES (NEW.id, new_exercise_id, NOW(), NOW());
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$function$
|
|
;
|
|
|
|
CREATE OR REPLACE FUNCTION public.updated_at()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $function$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$function$
|
|
;
|
|
|
|
CREATE TABLE public.anchors (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
anchor_id text UNIQUE NOT NULL
|
|
);
|
|
|
|
CREATE TABLE public.click_answers (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
user_id bigint NOT NULL,
|
|
click_exercise_id bigint NOT NULL,
|
|
answer text[] NOT NULL,
|
|
target_words text[] NOT NULL,
|
|
is_correct boolean NOT NULL GENERATED ALWAYS AS ((answer = target_words)) STORED
|
|
);
|
|
|
|
ALTER TABLE public.click_answers
|
|
ADD CONSTRAINT click_answers_unique
|
|
UNIQUE (user_id, click_exercise_id);
|
|
|
|
CREATE TABLE public.click_exercises (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
title text NOT NULL,
|
|
category text NOT NULL,
|
|
target_words text[] NOT NULL,
|
|
all_words text[] NOT NULL,
|
|
source_html text
|
|
);
|
|
|
|
ALTER TABLE public.click_exercises
|
|
ADD CONSTRAINT click_exercises_all_words_target_words_key
|
|
UNIQUE (all_words, target_words);
|
|
|
|
ALTER TABLE public.click_exercises
|
|
ADD CONSTRAINT click_exercises_id_target_words_key
|
|
UNIQUE (id, target_words);
|
|
|
|
CREATE TRIGGER after_click_exercises_insert AFTER INSERT ON public.click_exercises FOR EACH ROW EXECUTE FUNCTION insert_into_exercises();
|
|
|
|
ALTER TABLE public.click_answers
|
|
ADD CONSTRAINT click_answers_click_exercise_id_fkey
|
|
FOREIGN KEY (click_exercise_id) REFERENCES click_exercises(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.click_answers
|
|
ADD CONSTRAINT click_answers_click_exercise_id_target_words_fkey
|
|
FOREIGN KEY (click_exercise_id, target_words) REFERENCES click_exercises(id, target_words) ON UPDATE CASCADE ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.users (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
email text UNIQUE NOT NULL,
|
|
password_hash text NOT NULL,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
salt text NOT NULL,
|
|
username text NOT NULL DEFAULT ''::text,
|
|
is_admin boolean DEFAULT false,
|
|
is_superadmin boolean NOT NULL DEFAULT false
|
|
);
|
|
|
|
ALTER TABLE public.click_answers
|
|
ADD CONSTRAINT click_answers_user_id_fkey
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.click_to_exercises (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
click_id bigint,
|
|
exercise_id bigint
|
|
);
|
|
|
|
ALTER TABLE public.click_to_exercises
|
|
ADD CONSTRAINT click_to_exercises_click_id_fkey
|
|
FOREIGN KEY (click_id) REFERENCES click_exercises(id);
|
|
|
|
CREATE TABLE public.exercises (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
category text,
|
|
created_by bigint
|
|
);
|
|
|
|
ALTER TABLE public.click_to_exercises
|
|
ADD CONSTRAINT click_to_exercises_exercise_id_fkey
|
|
FOREIGN KEY (exercise_id) REFERENCES exercises(id);
|
|
|
|
CREATE TABLE public.dnd_categories (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
category text NOT NULL,
|
|
color text NOT NULL
|
|
);
|
|
|
|
ALTER TABLE public.dnd_categories
|
|
ADD CONSTRAINT unique_category_color
|
|
UNIQUE (category, color);
|
|
|
|
CREATE TABLE public.dnd_exercises (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
created_by bigint NOT NULL,
|
|
exercise_id bigint NOT NULL,
|
|
title text NOT NULL
|
|
);
|
|
|
|
ALTER TABLE public.dnd_exercises
|
|
ADD CONSTRAINT dnd_exercises_created_by_fkey
|
|
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.dnd_exercises
|
|
ADD CONSTRAINT dnd_exercises_exercise_id_fkey
|
|
FOREIGN KEY (exercise_id) REFERENCES exercises(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.dnd_match_exercises (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
exercise_id bigint UNIQUE NOT NULL,
|
|
created_by bigint NOT NULL,
|
|
title text NOT NULL,
|
|
description text NOT NULL
|
|
);
|
|
|
|
ALTER TABLE public.dnd_match_exercises
|
|
ADD CONSTRAINT dnd_match_exercises_created_by_fkey
|
|
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.dnd_match_exercises
|
|
ADD CONSTRAINT dnd_match_exercises_exercise_id_fkey
|
|
FOREIGN KEY (exercise_id) REFERENCES exercises(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.dnd_match_pairs (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
dnd_match_exercise_id bigint NOT NULL,
|
|
left_item text NOT NULL,
|
|
right_item text NOT NULL,
|
|
pair_order integer NOT NULL
|
|
);
|
|
|
|
CREATE INDEX dnd_match_pairs_exercise_order_idx ON public.dnd_match_pairs USING btree (dnd_match_exercise_id, pair_order);
|
|
|
|
ALTER TABLE public.dnd_match_pairs
|
|
ADD CONSTRAINT dnd_match_pairs_dnd_match_exercise_id_pair_order_key
|
|
UNIQUE (dnd_match_exercise_id, pair_order);
|
|
|
|
ALTER TABLE public.dnd_match_pairs
|
|
ADD CONSTRAINT dnd_match_pairs_dnd_match_exercise_id_right_item_key
|
|
UNIQUE (dnd_match_exercise_id, right_item);
|
|
|
|
ALTER TABLE public.dnd_match_pairs
|
|
ADD CONSTRAINT dnd_match_pairs_dnd_match_exercise_id_fkey
|
|
FOREIGN KEY (dnd_match_exercise_id) REFERENCES dnd_match_exercises(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.dnd_match_user_answers (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
user_id bigint NOT NULL,
|
|
dnd_match_exercise_id bigint NOT NULL,
|
|
left_pair_id bigint NOT NULL,
|
|
selected_right_pair_id bigint NOT NULL,
|
|
is_correct boolean NOT NULL DEFAULT false
|
|
);
|
|
|
|
CREATE INDEX dnd_match_user_answers_exercise_idx ON public.dnd_match_user_answers USING btree (dnd_match_exercise_id);
|
|
|
|
CREATE INDEX dnd_match_user_answers_user_exercise_idx ON public.dnd_match_user_answers USING btree (user_id, dnd_match_exercise_id);
|
|
|
|
ALTER TABLE public.dnd_match_user_answers
|
|
ADD CONSTRAINT dnd_match_user_answers_user_id_dnd_match_exercise_id_left_p_key
|
|
UNIQUE (user_id, dnd_match_exercise_id, left_pair_id);
|
|
|
|
CREATE TRIGGER check_pair_exercise_integrity BEFORE INSERT OR UPDATE ON public.dnd_match_user_answers FOR EACH ROW EXECUTE FUNCTION check_dnd_match_pair_exercise_integrity();
|
|
|
|
ALTER TABLE public.dnd_match_user_answers
|
|
ADD CONSTRAINT dnd_match_user_answers_dnd_match_exercise_id_fkey
|
|
FOREIGN KEY (dnd_match_exercise_id) REFERENCES dnd_match_exercises(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.dnd_match_user_answers
|
|
ADD CONSTRAINT dnd_match_user_answers_left_pair_id_fkey
|
|
FOREIGN KEY (left_pair_id) REFERENCES dnd_match_pairs(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.dnd_match_user_answers
|
|
ADD CONSTRAINT dnd_match_user_answers_selected_right_pair_id_fkey
|
|
FOREIGN KEY (selected_right_pair_id) REFERENCES dnd_match_pairs(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.dnd_match_user_answers
|
|
ADD CONSTRAINT dnd_match_user_answers_user_id_fkey
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.dnd_user_answer (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
user_id bigint NOT NULL,
|
|
word_id bigint NOT NULL,
|
|
category_id bigint,
|
|
is_correct boolean NOT NULL
|
|
);
|
|
|
|
ALTER TABLE public.dnd_user_answer
|
|
ADD CONSTRAINT dnd_user_answer_category_id_fkey
|
|
FOREIGN KEY (category_id) REFERENCES dnd_categories(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.dnd_user_answer
|
|
ADD CONSTRAINT dnd_user_answer_user_id_fkey
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.draggable_words (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
word text UNIQUE NOT NULL
|
|
);
|
|
|
|
ALTER TABLE public.dnd_user_answer
|
|
ADD CONSTRAINT dnd_user_answer_word_id_fkey
|
|
FOREIGN KEY (word_id) REFERENCES draggable_words(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.exercise_anchors (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
exercise_id bigint NOT NULL,
|
|
anchor_id bigint NOT NULL,
|
|
position integer NOT NULL DEFAULT 0,
|
|
difficulty text NOT NULL DEFAULT 'medium'::text,
|
|
title text
|
|
);
|
|
|
|
CREATE INDEX exercise_anchors_anchor_id_idx ON public.exercise_anchors USING btree (anchor_id);
|
|
|
|
CREATE INDEX exercise_anchors_exercise_id_idx ON public.exercise_anchors USING btree (exercise_id);
|
|
|
|
ALTER TABLE public.exercise_anchors
|
|
ADD CONSTRAINT exercise_anchors_difficulty_check
|
|
CHECK ((difficulty = ANY (ARRAY['easy'::text, 'medium'::text, 'hard'::text])));
|
|
|
|
ALTER TABLE public.exercise_anchors
|
|
ADD CONSTRAINT exercise_anchors_exercise_id_anchor_id_key
|
|
UNIQUE (exercise_id, anchor_id);
|
|
|
|
ALTER TABLE public.exercise_anchors
|
|
ADD CONSTRAINT exercise_anchors_anchor_id_fkey
|
|
FOREIGN KEY (anchor_id) REFERENCES anchors(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.exercise_anchors
|
|
ADD CONSTRAINT exercise_anchors_exercise_id_fkey
|
|
FOREIGN KEY (exercise_id) REFERENCES exercises(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.exercises
|
|
ADD CONSTRAINT exercises_created_by_fkey
|
|
FOREIGN KEY (created_by) REFERENCES users(id);
|
|
|
|
CREATE TABLE public.exercises_to_grammar_items (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
grammar_item_id bigint,
|
|
exercise_id bigint
|
|
);
|
|
|
|
ALTER TABLE public.exercises_to_grammar_items
|
|
ADD CONSTRAINT exercises_to_grammar_items_exercise_id_fkey
|
|
FOREIGN KEY (exercise_id) REFERENCES exercises(id);
|
|
|
|
CREATE TABLE public.grammar_items (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
grammar_item text UNIQUE NOT NULL
|
|
);
|
|
|
|
ALTER TABLE public.exercises_to_grammar_items
|
|
ADD CONSTRAINT exercises_to_grammar_items_grammar_item_id_fkey
|
|
FOREIGN KEY (grammar_item_id) REFERENCES grammar_items(id);
|
|
|
|
CREATE SEQUENCE public.feedbacks_id_seq;
|
|
|
|
CREATE TABLE public.feedbacks (
|
|
id integer PRIMARY KEY NOT NULL DEFAULT nextval('feedbacks_id_seq'::regclass),
|
|
email character varying(255) NOT NULL,
|
|
message text NOT NULL,
|
|
user_id integer NOT NULL,
|
|
timestamp timestamp with time zone DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
ALTER SEQUENCE public.feedbacks_id_seq OWNED BY public.feedbacks.id;
|
|
|
|
CREATE TABLE public.fill_gap_answers (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
fill_gap_gap_id bigint NOT NULL,
|
|
answer text NOT NULL,
|
|
is_correct boolean NOT NULL DEFAULT false,
|
|
feedback text NOT NULL
|
|
);
|
|
|
|
CREATE TABLE public.fill_gap_gaps (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
fill_gap_exercise_id bigint NOT NULL,
|
|
token_index integer NOT NULL,
|
|
token_text text NOT NULL,
|
|
gap_order integer NOT NULL
|
|
);
|
|
|
|
ALTER TABLE public.fill_gap_gaps
|
|
ADD CONSTRAINT fill_gap_gaps_fill_gap_exercise_id_token_index_key
|
|
UNIQUE (fill_gap_exercise_id, token_index);
|
|
|
|
ALTER TABLE public.fill_gap_answers
|
|
ADD CONSTRAINT fill_gap_answers_fill_gap_gap_id_fkey
|
|
FOREIGN KEY (fill_gap_gap_id) REFERENCES fill_gap_gaps(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.fill_gap_exercises (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
exercise_id bigint UNIQUE NOT NULL,
|
|
title text NOT NULL,
|
|
source_text text NOT NULL,
|
|
source_html text NOT NULL DEFAULT ''::text
|
|
);
|
|
|
|
ALTER TABLE public.fill_gap_exercises
|
|
ADD CONSTRAINT fill_gap_exercises_exercise_id_fkey
|
|
FOREIGN KEY (exercise_id) REFERENCES exercises(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.fill_gap_gaps
|
|
ADD CONSTRAINT fill_gap_gaps_fill_gap_exercise_id_fkey
|
|
FOREIGN KEY (fill_gap_exercise_id) REFERENCES fill_gap_exercises(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.fill_gap_user_answers (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
user_id bigint NOT NULL,
|
|
fill_gap_gap_id bigint NOT NULL,
|
|
answer text NOT NULL,
|
|
is_correct boolean NOT NULL DEFAULT false,
|
|
feedback text
|
|
);
|
|
|
|
ALTER TABLE public.fill_gap_user_answers
|
|
ADD CONSTRAINT fill_gap_user_answers_user_id_fill_gap_gap_id_key
|
|
UNIQUE (user_id, fill_gap_gap_id);
|
|
|
|
ALTER TABLE public.fill_gap_user_answers
|
|
ADD CONSTRAINT fill_gap_user_answers_fill_gap_gap_id_fkey
|
|
FOREIGN KEY (fill_gap_gap_id) REFERENCES fill_gap_gaps(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.fill_gap_user_answers
|
|
ADD CONSTRAINT fill_gap_user_answers_user_id_fkey
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.jumbled_sentence_sentences (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
jumbled_exercise_id bigint NOT NULL,
|
|
sentence text NOT NULL,
|
|
alternates text[] DEFAULT ARRAY[]::text[],
|
|
correct_feedback text,
|
|
alternate_feedbacks text[] NOT NULL DEFAULT ARRAY[]::text[],
|
|
incorrect_feedbacks text[] NOT NULL DEFAULT ARRAY[]::text[],
|
|
incorrect_alternates text[] NOT NULL DEFAULT ARRAY[]::text[]
|
|
);
|
|
|
|
CREATE TABLE public.jumbled_sentence_exercises (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
exercise_id bigint UNIQUE NOT NULL,
|
|
created_by bigint NOT NULL,
|
|
title text NOT NULL
|
|
);
|
|
|
|
ALTER TABLE public.jumbled_sentence_sentences
|
|
ADD CONSTRAINT fk_jumbled_exercise
|
|
FOREIGN KEY (jumbled_exercise_id) REFERENCES jumbled_sentence_exercises(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.form_parts (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
form_id bigint NOT NULL,
|
|
title_en text,
|
|
title_de text,
|
|
step_label text NOT NULL,
|
|
advice_en text,
|
|
advice_de text,
|
|
advice_threshold numeric(5,2) DEFAULT 3
|
|
);
|
|
|
|
ALTER TABLE public.form_parts
|
|
ADD CONSTRAINT check_step_label
|
|
CHECK ((step_label ~ '^[A-Za-z0-9]$'::text));
|
|
|
|
ALTER TABLE public.form_parts
|
|
ADD CONSTRAINT unique_step_label
|
|
UNIQUE (form_id, step_label);
|
|
|
|
CREATE TABLE public.forms (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
public_id text UNIQUE NOT NULL,
|
|
title_en text,
|
|
title_de text,
|
|
description_en text,
|
|
description_de text
|
|
);
|
|
|
|
ALTER TABLE public.form_parts
|
|
ADD CONSTRAINT form_parts_form_id_fkey
|
|
FOREIGN KEY (form_id) REFERENCES forms(id) ON DELETE RESTRICT;
|
|
|
|
CREATE TABLE public.free_form_answers (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
free_form_exercise_id bigint NOT NULL,
|
|
answer text NOT NULL,
|
|
is_correct boolean DEFAULT false,
|
|
feedback text,
|
|
free_form_question_id bigint
|
|
);
|
|
|
|
CREATE INDEX free_form_answers_free_form_exercise_id_idx ON public.free_form_answers USING btree (free_form_exercise_id);
|
|
|
|
CREATE TABLE public.free_form_exercises (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
exercise_id bigint NOT NULL,
|
|
question text,
|
|
title text NOT NULL
|
|
);
|
|
|
|
ALTER TABLE public.free_form_answers
|
|
ADD CONSTRAINT free_form_answers_free_form_exercise_id_fkey
|
|
FOREIGN KEY (free_form_exercise_id) REFERENCES free_form_exercises(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.free_form_questions (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
free_form_exercise_id bigint NOT NULL,
|
|
question text NOT NULL,
|
|
question_order integer NOT NULL DEFAULT 1
|
|
);
|
|
|
|
ALTER TABLE public.free_form_answers
|
|
ADD CONSTRAINT free_form_answers_free_form_question_id_fkey
|
|
FOREIGN KEY (free_form_question_id) REFERENCES free_form_questions(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.free_form_exercises
|
|
ADD CONSTRAINT free_form_exercises_exercise_id_fkey
|
|
FOREIGN KEY (exercise_id) REFERENCES exercises(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.free_form_questions
|
|
ADD CONSTRAINT free_form_questions_free_form_exercise_id_fkey
|
|
FOREIGN KEY (free_form_exercise_id) REFERENCES free_form_exercises(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.free_form_user_answers (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
answer text NOT NULL,
|
|
free_form_exercise_id bigint NOT NULL,
|
|
is_correct boolean DEFAULT false,
|
|
user_id bigint NOT NULL,
|
|
free_form_question_id bigint
|
|
);
|
|
|
|
ALTER TABLE public.free_form_user_answers
|
|
ADD CONSTRAINT free_form_user_answers_free_form_exercise_id_user_id_key
|
|
UNIQUE (free_form_exercise_id, user_id);
|
|
|
|
ALTER TABLE public.free_form_user_answers
|
|
ADD CONSTRAINT free_form_user_answers_free_form_exercise_id_fkey
|
|
FOREIGN KEY (free_form_exercise_id) REFERENCES free_form_exercises(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.free_form_user_answers
|
|
ADD CONSTRAINT free_form_user_answers_free_form_question_id_fkey
|
|
FOREIGN KEY (free_form_question_id) REFERENCES free_form_questions(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.free_form_user_answers
|
|
ADD CONSTRAINT free_form_user_answers_user_id_fkey
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.glossary_entries (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
word text NOT NULL,
|
|
word_definition text NOT NULL
|
|
);
|
|
|
|
CREATE TRIGGER update_glossary_entries_updated_at BEFORE UPDATE ON public.glossary_entries FOR EACH ROW EXECUTE FUNCTION updated_at();
|
|
|
|
CREATE SEQUENCE public.grammar_topics_id_seq;
|
|
|
|
CREATE TABLE public.grammar_topics (
|
|
id integer PRIMARY KEY NOT NULL DEFAULT nextval('grammar_topics_id_seq'::regclass),
|
|
name text NOT NULL,
|
|
sort_order integer
|
|
);
|
|
|
|
ALTER SEQUENCE public.grammar_topics_id_seq OWNED BY public.grammar_topics.id;
|
|
|
|
CREATE TABLE public.html_pages (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
title text,
|
|
content text,
|
|
page_order integer,
|
|
slug text,
|
|
page_group text,
|
|
grammar_topic_id integer,
|
|
description text
|
|
);
|
|
|
|
ALTER TABLE public.html_pages
|
|
ADD CONSTRAINT html_pages_grammar_topic_id_fkey
|
|
FOREIGN KEY (grammar_topic_id) REFERENCES grammar_topics(id);
|
|
|
|
ALTER TABLE public.jumbled_sentence_exercises
|
|
ADD CONSTRAINT jumbled_sentence_exercises_created_by_fkey
|
|
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.jumbled_sentence_exercises
|
|
ADD CONSTRAINT jumbled_sentence_exercises_exercise_id_fkey
|
|
FOREIGN KEY (exercise_id) REFERENCES exercises(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.memory_game_exercises (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
exercise_id bigint UNIQUE NOT NULL,
|
|
created_by bigint NOT NULL,
|
|
title text NOT NULL,
|
|
description text NOT NULL
|
|
);
|
|
|
|
ALTER TABLE public.memory_game_exercises
|
|
ADD CONSTRAINT memory_game_exercises_created_by_fkey
|
|
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.memory_game_exercises
|
|
ADD CONSTRAINT memory_game_exercises_exercise_id_fkey
|
|
FOREIGN KEY (exercise_id) REFERENCES exercises(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.memory_game_pairs (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
memory_game_exercise_id bigint NOT NULL,
|
|
left_item text NOT NULL,
|
|
right_item text NOT NULL,
|
|
pair_order integer NOT NULL
|
|
);
|
|
|
|
CREATE INDEX memory_game_pairs_exercise_order_idx ON public.memory_game_pairs USING btree (memory_game_exercise_id, pair_order);
|
|
|
|
ALTER TABLE public.memory_game_pairs
|
|
ADD CONSTRAINT memory_game_pairs_memory_game_exercise_id_pair_order_key
|
|
UNIQUE (memory_game_exercise_id, pair_order);
|
|
|
|
ALTER TABLE public.memory_game_pairs
|
|
ADD CONSTRAINT memory_game_pairs_memory_game_exercise_id_right_item_key
|
|
UNIQUE (memory_game_exercise_id, right_item);
|
|
|
|
ALTER TABLE public.memory_game_pairs
|
|
ADD CONSTRAINT memory_game_pairs_memory_game_exercise_id_fkey
|
|
FOREIGN KEY (memory_game_exercise_id) REFERENCES memory_game_exercises(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.memory_game_user_answers (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
user_id bigint NOT NULL,
|
|
memory_game_exercise_id bigint NOT NULL,
|
|
attempts jsonb NOT NULL,
|
|
score integer NOT NULL,
|
|
completed boolean NOT NULL DEFAULT false
|
|
);
|
|
|
|
CREATE INDEX memory_game_user_answers_user_exercise_idx ON public.memory_game_user_answers USING btree (user_id, memory_game_exercise_id);
|
|
|
|
ALTER TABLE public.memory_game_user_answers
|
|
ADD CONSTRAINT memory_game_user_answers_user_id_memory_game_exercise_id_key
|
|
UNIQUE (user_id, memory_game_exercise_id);
|
|
|
|
ALTER TABLE public.memory_game_user_answers
|
|
ADD CONSTRAINT memory_game_user_answers_memory_game_exercise_id_fkey
|
|
FOREIGN KEY (memory_game_exercise_id) REFERENCES memory_game_exercises(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.memory_game_user_answers
|
|
ADD CONSTRAINT memory_game_user_answers_user_id_fkey
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.multichoice_content (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
multichoice_exercise_id bigint NOT NULL,
|
|
content_type text NOT NULL,
|
|
content_value text NOT NULL,
|
|
content_order integer NOT NULL,
|
|
correct_answer text,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE public.multichoice_exercises (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
exercise_id bigint NOT NULL,
|
|
title text NOT NULL,
|
|
exercise_description text,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now()
|
|
);
|
|
|
|
ALTER TABLE public.multichoice_content
|
|
ADD CONSTRAINT multichoice_content_multichoice_exercise_id_fkey
|
|
FOREIGN KEY (multichoice_exercise_id) REFERENCES multichoice_exercises(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.multichoice_exercises
|
|
ADD CONSTRAINT multichoice_exercises_exercise_id_fkey
|
|
FOREIGN KEY (exercise_id) REFERENCES exercises(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.multichoice_options (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
multichoice_content_id bigint NOT NULL,
|
|
option_value text NOT NULL,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now()
|
|
);
|
|
|
|
ALTER TABLE public.multichoice_options
|
|
ADD CONSTRAINT multichoice_options_multichoice_content_id_fkey
|
|
FOREIGN KEY (multichoice_content_id) REFERENCES multichoice_content(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.part_questions (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
form_part_id bigint NOT NULL,
|
|
title_en text,
|
|
title_de text
|
|
);
|
|
|
|
ALTER TABLE public.part_questions
|
|
ADD CONSTRAINT part_questions_form_part_id_fkey
|
|
FOREIGN KEY (form_part_id) REFERENCES form_parts(id) ON DELETE RESTRICT;
|
|
|
|
CREATE TABLE public.pgmigrate_migrations (
|
|
id text PRIMARY KEY NOT NULL,
|
|
checksum text NOT NULL,
|
|
execution_time_in_millis bigint NOT NULL,
|
|
applied_at timestamp with time zone NOT NULL
|
|
);
|
|
|
|
CREATE TABLE public.user_question_answers (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
answer integer NOT NULL,
|
|
user_id bigint,
|
|
part_question_id bigint NOT NULL,
|
|
answerer_id text NOT NULL
|
|
);
|
|
|
|
ALTER TABLE public.user_question_answers
|
|
ADD CONSTRAINT user_question_answers_user_id_part_question_id_key
|
|
UNIQUE (user_id, part_question_id);
|
|
|
|
ALTER TABLE public.user_question_answers
|
|
ADD CONSTRAINT user_question_answers_part_question_id_fkey
|
|
FOREIGN KEY (part_question_id) REFERENCES part_questions(id) ON DELETE RESTRICT;
|
|
|
|
ALTER TABLE public.user_question_answers
|
|
ADD CONSTRAINT user_question_answers_user_id_fkey
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
|
|
|
CREATE TABLE public.word_category_mappings (
|
|
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
|
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
updated_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
word_id bigint NOT NULL,
|
|
category_id bigint NOT NULL,
|
|
exercise_id bigint NOT NULL
|
|
);
|
|
|
|
CREATE TRIGGER updated_at BEFORE UPDATE ON public.word_category_mappings FOR EACH ROW EXECUTE FUNCTION updated_at();
|
|
|
|
ALTER TABLE public.word_category_mappings
|
|
ADD CONSTRAINT word_category_mappings_category_id_fkey
|
|
FOREIGN KEY (category_id) REFERENCES dnd_categories(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.word_category_mappings
|
|
ADD CONSTRAINT word_category_mappings_exercise_id_fkey
|
|
FOREIGN KEY (exercise_id) REFERENCES dnd_exercises(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE public.word_category_mappings
|
|
ADD CONSTRAINT word_category_mappings_word_id_fkey
|
|
FOREIGN KEY (word_id) REFERENCES draggable_words(id) ON DELETE CASCADE;
|