DROP TABLE IF EXISTS Historia; DROP TABLE IF EXISTS Instytucje; DROP TABLE IF EXISTS Eksponaty; DROP TABLE IF EXISTS Artysta; DROP TABLE IF EXISTS Galeria; CREATE TABLE Galeria ( id_galerii VARCHAR(3) PRIMARY KEY, nazwa VARCHAR(50) NOT NULL, miasto VARCHAR(50) NOT NULL ); CREATE TABLE Artysta ( id_artysty VARCHAR(3) PRIMARY KEY, imie VARCHAR(50) NOT NULL, nazwisko VARCHAR(50) NOT NULL, rok_urodzenia INT NOT NULL, rok_smierci INT, CONSTRAINT chk_artysta_dates CHECK (rok_smierci IS NULL OR rok_urodzenia < rok_smierci) ); CREATE TABLE Eksponaty ( id_eksponatu VARCHAR(3) PRIMARY KEY, tytul VARCHAR(50) NOT NULL, typ VARCHAR(50) NOT NULL, wysokosc DECIMAL(10,2) NOT NULL, szerokosc DECIMAL(10,2) NOT NULL, waga DECIMAL(10,2) NOT NULL, id_artysty VARCHAR(3) REFERENCES Artysta (id_artysty), czy_cenny BOOLEAN NOT NULL ); CREATE TABLE Instytucje ( id_instytucji VARCHAR(3) PRIMARY KEY, nazwa VARCHAR(50) NOT NULL, miasto VARCHAR(50) NOT NULL ); CREATE TABLE Historia ( id_historii SERIAL PRIMARY KEY, id_galerii VARCHAR(3) REFERENCES Galeria(id_galerii), id_eksponatu VARCHAR(3) NOT NULL REFERENCES Eksponaty(id_eksponatu), status VARCHAR(15) NOT NULL CHECK (status IN ('magazyn', 'galeria', 'wypozyczony')), data_rozpoczecia DATE NOT NULL, data_zakonczenia DATE, id_instytucji VARCHAR(3) REFERENCES Instytucje(id_instytucji), id_sali VARCHAR(3), CONSTRAINT chk_data_wypozyczenia CHECK (data_zakonczenia IS NULL OR data_rozpoczecia < data_zakonczenia) ); ----------------------- CREATE OR REPLACE FUNCTION zamknij_poprzedni_pobyt() RETURNS TRIGGER AS $$ BEGIN UPDATE Historia SET data_zakonczenia = NEW.data_rozpoczecia WHERE id_eksponatu = NEW.id_eksponatu AND data_zakonczenia IS NULL AND id_historii <> NEW.id_historii; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER tg_zamknij_poprzedni_pobyt BEFORE INSERT OR UPDATE ON Historia FOR EACH ROW EXECUTE PROCEDURE zamknij_poprzedni_pobyt(); ----------------------- CREATE OR REPLACE FUNCTION minimum_jeden_w_muzeum() RETURNS TRIGGER AS $$ DECLARE liczba_eksp_w_muzeum INT; artysta_id VARCHAR(3); BEGIN IF (NEW.status = 'wypozyczony') THEN SELECT e.id_artysty INTO artysta_id FROM Eksponaty e WHERE e.id_eksponatu = NEW.id_eksponatu; SELECT COUNT(*) INTO liczba_eksp_w_muzeum FROM Historia h JOIN Eksponaty e ON e.id_eksponatu = h.id_eksponatu WHERE e.id_artysty = artysta_id AND h.status IN ('magazyn', 'galeria') AND (h.data_zakonczenia IS NULL OR h.data_zakonczenia >= CURRENT_DATE) AND h.id_historii <> NEW.id_historii; IF liczba_eksp_w_muzeum = 0 THEN RAISE EXCEPTION 'Nie mozna wypozyczyc eksponatu - artysta % nie bedzie mial zadnego dziela w muzeum', artysta_id; END IF; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER tg_minimum_jeden_w_muzeum BEFORE INSERT OR UPDATE ON Historia FOR EACH ROW EXECUTE PROCEDURE minimum_jeden_w_muzeum(); ----------------------------- CREATE OR REPLACE FUNCTION sprawdz_czas_wypozyczenia() RETURNS TRIGGER AS $$ DECLARE czas_wypozyczenia INT; biezacy_rok INT := EXTRACT(YEAR FROM CURRENT_DATE); BEGIN IF (NEW.status = 'wypozyczony') THEN SELECT COALESCE(SUM(GREATEST(0,(LEAST(COALESCE(data_zakonczenia, CURRENT_DATE), make_date(biezacy_rok, 12, 31))- GREATEST(data_rozpoczecia, make_date(biezacy_rok, 1, 1)) + 1))), 0) INTO czas_wypozyczenia FROM Historia WHERE id_eksponatu = NEW.id_eksponatu AND status = 'wypozyczony' AND data_rozpoczecia <= make_date(biezacy_rok, 12, 31) AND (data_zakonczenia IS NULL OR data_zakonczenia >= make_date(biezacy_rok, 1, 1)); IF czas_wypozyczenia > 30 THEN RAISE EXCEPTION 'Nie mozna wypozyczyc eksponatu, ktory byl w tym roku poza muzeum ponad 30 dni'; END IF; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER tg_sprawdz_czas_wypozyczenia BEFORE INSERT OR UPDATE ON Historia FOR EACH ROW EXECUTE PROCEDURE sprawdz_czas_wypozyczenia(); ------------------------ CREATE OR REPLACE FUNCTION czy_eksponat_juz_wypozyczony() RETURNS TRIGGER AS $$ DECLARE nie_zwr INT; BEGIN IF NEW.status = 'wypozyczony' THEN SELECT COUNT(*) INTO nie_zwr FROM Historia WHERE id_eksponatu = NEW.id_eksponatu AND status = 'wypozyczony' AND data_zakonczenia IS NULL; IF nie_zwr > 0 THEN RAISE EXCEPTION 'Eksponat jest już wypożyczony i nie można go wypożyczyć ponownie!'; END IF; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER tg_czy_eksponat_juz_wypozyczony BEFORE INSERT OR UPDATE ON Historia FOR EACH ROW EXECUTE PROCEDURE czy_eksponat_juz_wypozyczony(); ------------------------ CREATE OR REPLACE FUNCTION zakaz_nakladania_statusu() RETURNS TRIGGER AS $$ DECLARE licznik INT; BEGIN SELECT COUNT(*) INTO licznik FROM Historia WHERE id_eksponatu = NEW.id_eksponatu AND status IN ('magazyn', 'galeria', 'wypozyczony') AND ( COALESCE(NEW.data_zakonczenia, '9999-12-31'::date) >= data_rozpoczecia AND COALESCE(data_zakonczenia, '9999-12-31'::date) >= NEW.data_rozpoczecia) AND (TG_OP = 'INSERT' OR id_historii <> NEW.id_historii); IF licznik > 0 THEN RAISE EXCEPTION 'Eksponat % ma już status w okresie, który koliduje z nowym wpisem.', NEW.id_eksponatu; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER tg_zakaz_nakladania_statusu BEFORE INSERT OR UPDATE ON Historia FOR EACH ROW EXECUTE PROCEDURE zakaz_nakladania_statusu();