Files
relational-database-systems/lab10.sql
T
2025-11-28 16:27:38 -08:00

148 lines
3.6 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
SET search_path TO lab5;
-- TASK 1 Enforce Section Capacity
-- 1. Trigger function: ensure no course offering exceeds capacity
CREATE OR REPLACE FUNCTION check_offering_capacity()
RETURNS TRIGGER AS $$
DECLARE
v_capacity INTEGER;
v_current INTEGER;
BEGIN
SELECT off_capacity
INTO v_capacity
FROM course_offering
WHERE off_id = NEW.off_id;
SELECT COUNT(*)
INTO v_current
FROM enrollment
WHERE off_id = NEW.off_id
AND enr_status = 'Active';
IF v_current >= v_capacity THEN
RAISE EXCEPTION
'Cannot enroll student %. Section % is full (capacity=%).',
NEW.stu_num, NEW.off_id, v_capacity;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 2. Trigger
CREATE OR REPLACE TRIGGER trg_check_capacity
BEFORE INSERT ON enrollment
FOR EACH ROW
EXECUTE FUNCTION check_offering_capacity();
-- TASK 2 Enrollment Audit Logging
CREATE TABLE IF NOT EXISTS enrollment_audit (
audit_id SERIAL PRIMARY KEY,
enr_id_stu VARCHAR(20),
enr_id_off INTEGER,
action_type VARCHAR(10),
old_status VARCHAR(8),
new_status VARCHAR(8),
action_ts TIMESTAMP DEFAULT NOW(),
action_user TEXT DEFAULT current_user
);
CREATE OR REPLACE FUNCTION audit_enrollment_changes()
RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'INSERT' THEN
INSERT INTO enrollment_audit(
enr_id_stu,
enr_id_off,
action_type,
new_status
)
VALUES (
NEW.stu_num,
NEW.off_id,
'INSERT',
NEW.enr_status
);
ELSIF TG_OP = 'UPDATE' THEN
INSERT INTO enrollment_audit(
enr_id_stu,
enr_id_off,
action_type,
old_status,
new_status
)
VALUES (
NEW.stu_num,
NEW.off_id,
'UPDATE',
OLD.enr_status,
NEW.enr_status
);
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE TRIGGER trg_enrollment_audit
AFTER INSERT OR UPDATE ON enrollment
FOR EACH ROW
EXECUTE FUNCTION audit_enrollment_changes();
-- TASK 3 Validate Enrollment Status
ALTER TABLE enrollment DROP CONSTRAINT IF EXISTS enr_status_ck;
ALTER TABLE enrollment
ADD CONSTRAINT enr_status_ck
CHECK (enr_status IN ('Active', 'Dropped', 'Completed', 'Failed'));
CREATE OR REPLACE FUNCTION validate_enrollment_status()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.enr_status NOT IN ('Active','Dropped','Completed','Failed') THEN
RAISE EXCEPTION 'Invalid enrollment status: %', NEW.enr_status;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE TRIGGER trg_validate_status
BEFORE INSERT OR UPDATE OF enr_status ON enrollment
FOR EACH ROW
EXECUTE FUNCTION validate_enrollment_status();
-- TESTS
INSERT INTO enrollment VALUES ('S100', 1, 'Active');
INSERT INTO enrollment VALUES ('S101', 1, 'Active');
INSERT INTO enrollment VALUES ('S102', 1, 'Active');
INSERT INTO enrollment VALUES ('S200', 2, 'Active');
UPDATE enrollment SET enr_status = 'Dropped'
WHERE stu_num = 'S200' AND off_id = 2;
UPDATE enrollment
SET enr_status = 'Potato'
WHERE stu_num = 'S200' AND off_id = 2;
-- OUTPUT
-- SELECT * FROM enrollment;
-- SELECT * FROM enrollment_audit;
-- REFLECTION
-- Storing business rules directly inside the database ensures that
-- data remains correct and consistent no matter what application
-- or user interacts with it. Trigger-based validation centralizes
-- logic so errors are prevented at the source instead of being caught
-- later in the application.