Files
OHTU-German-learning-website/gradesa/data/schema.sql
T

495 lines
17 KiB
PL/PgSQL

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
);
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_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.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 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);
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;