Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 82 additions & 91 deletions schema/schema.sql
Original file line number Diff line number Diff line change
@@ -1,120 +1,111 @@
CREATE TABLE public.employee (
emp_no SERIAL NOT NULL,
birth_date DATE NOT NULL,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
gender TEXT NOT NULL CHECK (gender IN('M', 'F')) NOT NULL,
hire_date DATE NOT NULL,
PRIMARY KEY (emp_no)
COMMENT ON SCHEMA "public" IS 'standard public schema';

CREATE TABLE "public"."audit" (
"id" serial,
"operation" text NOT NULL,
"query" text,
"user_name" text NOT NULL,
"changed_at" timestamp(6) with time zone DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "audit_pkey" PRIMARY KEY (id)
);

CREATE INDEX idx_employee_hire_date ON public.employee (hire_date);
CREATE INDEX "idx_audit_changed_at" ON ONLY "public"."audit" (changed_at);

CREATE INDEX "idx_audit_operation" ON ONLY "public"."audit" (operation);

CREATE INDEX "idx_audit_username" ON ONLY "public"."audit" (user_name);

CREATE TABLE "public"."department" (
"dept_no" text NOT NULL,
"dept_name" text NOT NULL,
CONSTRAINT "department_pkey" PRIMARY KEY (dept_no),
CONSTRAINT "department_dept_name_key" UNIQUE (dept_name)
);

CREATE TABLE public.department (
dept_no TEXT NOT NULL,
dept_name TEXT NOT NULL,
PRIMARY KEY (dept_no),
UNIQUE (dept_name)
CREATE TABLE "public"."dept_emp" (
"emp_no" integer NOT NULL,
"dept_no" text NOT NULL,
"from_date" date NOT NULL,
"to_date" date NOT NULL,
CONSTRAINT "dept_emp_pkey" PRIMARY KEY (emp_no, dept_no),
CONSTRAINT "dept_emp_dept_no_fkey" FOREIGN KEY ("dept_no") REFERENCES "public"."department" ("dept_no") ON DELETE CASCADE,
CONSTRAINT "dept_emp_emp_no_fkey" FOREIGN KEY ("emp_no") REFERENCES "public"."employee" ("emp_no") ON DELETE CASCADE
);

CREATE TABLE public.dept_manager (
emp_no INT NOT NULL,
dept_no TEXT NOT NULL,
from_date DATE NOT NULL,
to_date DATE NOT NULL,
FOREIGN KEY (emp_no) REFERENCES employee (emp_no) ON DELETE CASCADE,
FOREIGN KEY (dept_no) REFERENCES department (dept_no) ON DELETE CASCADE,
PRIMARY KEY (emp_no, dept_no)
CREATE TABLE "public"."dept_manager" (
"emp_no" integer NOT NULL,
"dept_no" text NOT NULL,
"from_date" date NOT NULL,
"to_date" date NOT NULL,
CONSTRAINT "dept_manager_pkey" PRIMARY KEY (emp_no, dept_no),
CONSTRAINT "dept_manager_dept_no_fkey" FOREIGN KEY ("dept_no") REFERENCES "public"."department" ("dept_no") ON DELETE CASCADE,
CONSTRAINT "dept_manager_emp_no_fkey" FOREIGN KEY ("emp_no") REFERENCES "public"."employee" ("emp_no") ON DELETE CASCADE
);

CREATE TABLE public.dept_emp (
emp_no INT NOT NULL,
dept_no TEXT NOT NULL,
from_date DATE NOT NULL,
to_date DATE NOT NULL,
FOREIGN KEY (emp_no) REFERENCES employee (emp_no) ON DELETE CASCADE,
FOREIGN KEY (dept_no) REFERENCES department (dept_no) ON DELETE CASCADE,
PRIMARY KEY (emp_no, dept_no)
CREATE TABLE "public"."employee" (
"emp_no" serial,
"birth_date" date NOT NULL,
"first_name" text NOT NULL,
"last_name" text NOT NULL,
"gender" text NOT NULL,
"hire_date" date NOT NULL,
CONSTRAINT "employee_pkey" PRIMARY KEY (emp_no),
CONSTRAINT "employee_gender_check" CHECK (gender = ANY (ARRAY['M'::text, 'F'::text]))
);

CREATE TABLE public.title (
emp_no INT NOT NULL,
title TEXT NOT NULL,
from_date DATE NOT NULL,
to_date DATE,
FOREIGN KEY (emp_no) REFERENCES employee (emp_no) ON DELETE CASCADE,
PRIMARY KEY (emp_no, title, from_date)
);
CREATE INDEX "idx_employee_hire_date" ON ONLY "public"."employee" (hire_date);

CREATE TABLE public.salary (
emp_no INT NOT NULL,
amount INT NOT NULL,
from_date DATE NOT NULL,
to_date DATE NOT NULL,
FOREIGN KEY (emp_no) REFERENCES employee (emp_no) ON DELETE CASCADE,
PRIMARY KEY (emp_no, from_date)
CREATE TABLE "public"."salary" (
"emp_no" integer NOT NULL,
"amount" integer NOT NULL,
"from_date" date NOT NULL,
"to_date" date NOT NULL,
CONSTRAINT "salary_pkey" PRIMARY KEY (emp_no, from_date),
CONSTRAINT "salary_emp_no_fkey" FOREIGN KEY ("emp_no") REFERENCES "public"."employee" ("emp_no") ON DELETE CASCADE
);

CREATE INDEX idx_salary_amount ON public.salary (amount);
CREATE INDEX "idx_salary_amount" ON ONLY "public"."salary" (amount);

CREATE TABLE public.audit (
id SERIAL PRIMARY KEY,
operation TEXT NOT NULL,
query TEXT,
user_name TEXT NOT NULL,
changed_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
CREATE TABLE "public"."title" (
"emp_no" integer NOT NULL,
"title" text NOT NULL,
"from_date" date NOT NULL,
"to_date" date,
CONSTRAINT "title_pkey" PRIMARY KEY (emp_no, title, from_date),
CONSTRAINT "title_emp_no_fkey" FOREIGN KEY ("emp_no") REFERENCES "public"."employee" ("emp_no") ON DELETE CASCADE
);

CREATE INDEX idx_audit_operation ON public.audit (operation);
CREATE INDEX idx_audit_username ON public.audit (user_name);
CREATE INDEX idx_audit_changed_at ON public.audit (changed_at);
CREATE VIEW "public"."current_dept_emp" AS SELECT l.emp_no,
d.dept_no,
l.from_date,
l.to_date
FROM (public.dept_emp d
JOIN public.dept_emp_latest_date l ON (((d.emp_no = l.emp_no) AND (d.from_date = l.from_date) AND (l.to_date = d.to_date))));

CREATE OR REPLACE FUNCTION public.log_dml_operations() RETURNS TRIGGER AS $$
CREATE VIEW "public"."dept_emp_latest_date" AS SELECT emp_no,
max(from_date) AS from_date,
max(to_date) AS to_date
FROM public.dept_emp
GROUP BY emp_no;

CREATE OR REPLACE FUNCTION public.log_dml_operations()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
IF (TG_OP = 'INSERT') THEN
INSERT INTO public.audit (operation, query, user_name)
INSERT INTO audit (operation, query, user_name)
VALUES ('INSERT', current_query(), current_user);
RETURN NEW;
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO public.audit (operation, query, user_name)
INSERT INTO audit (operation, query, user_name)
VALUES ('UPDATE', current_query(), current_user);
RETURN NEW;
ELSIF (TG_OP = 'DELETE') THEN
INSERT INTO public.audit (operation, query, user_name)
INSERT INTO audit (operation, query, user_name)
VALUES ('DELETE', current_query(), current_user);
RETURN OLD;
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;

-- only log update and delete, otherwise, it will cause too much change.
CREATE TRIGGER salary_log_trigger
AFTER UPDATE OR DELETE ON public.salary
FOR EACH ROW
EXECUTE FUNCTION public.log_dml_operations();

CREATE OR REPLACE VIEW public.dept_emp_latest_date AS
SELECT
emp_no,
MAX(
from_date) AS from_date,
MAX(
to_date) AS to_date
FROM
public.dept_emp
GROUP BY
emp_no;

-- shows only the current department for each employee
CREATE OR REPLACE VIEW public.current_dept_emp AS
SELECT
l.emp_no,
dept_no,
l.from_date,
l.to_date
FROM
public.dept_emp d
INNER JOIN public.dept_emp_latest_date l ON d.emp_no = l.emp_no
AND d.from_date = l.from_date
AND l.to_date = d.to_date;
$function$;