Advanced Database Development (SQL DDL)
1. Data constraints requirements: Booking Overlapping and Sitter Availability
Data requirements description
Bookings must adhere to real world time and scheduling:
- A Pet Sitter cannot have overlapping confirmed bookings - they cant be in two places at once.
- A Pet Owner cannot book the same pet twice on overlapping dates/times.
- A booking cannot be created if the
date_fromis in the past.
Implementation
Triggers
CREATE OR REPLACE FUNCTION petsitter_trg_booking_validation()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW.date_from < now() THEN
RAISE EXCEPTION 'Cannot create a booking in the past (date_from=%)', NEW.date_from;
END IF;
IF NEW.date_to <= NEW.date_from THEN
RAISE EXCEPTION 'Booking end date (%) must be after start date (%)', NEW.date_to, NEW.date_from;
END IF;
IF NEW.status = 'Confirmed' THEN
IF EXISTS (
SELECT 1 FROM bookings b
WHERE b.sitter_id = NEW.sitter_id
AND b.status = 'Confirmed'
AND b.date_from < NEW.date_to
AND b.date_to > NEW.date_from
AND (TG_OP <> 'UPDATE' OR b.booking_id <> NEW.booking_id)
) THEN
RAISE EXCEPTION 'Sitter % is already booked for these dates.', NEW.sitter_id;
END IF;
END IF;
RETURN NEW;
END;
$$;
DROP TRIGGER IF EXISTS trg_booking_validation ON bookings;
CREATE TRIGGER trg_booking_validation
BEFORE INSERT OR UPDATE ON bookings
FOR EACH ROW
EXECUTE FUNCTION petsitter_trg_booking_validation();
2. Data constraints requirements: Review/Transaction Integrity
Data requirements description
Reviews are associated with the completion of a booking:
- A review can only be inserted if the relevant booking has the status 'Completed'.
- A booking can have a maximum of ONE (1) review.
- Once a review is created, the rating cannot be edited.
Implementation
Triggers
CREATE OR REPLACE FUNCTION petsitter_trg_review_integrity()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
v_booking_status varchar;
BEGIN
-- Get booking status
SELECT status INTO v_booking_status
FROM bookings
WHERE booking_id = NEW.booking_id;
IF v_booking_status IS NULL THEN
RAISE EXCEPTION 'Booking % not found.', NEW.booking_id;
END IF;
-- Block reviews for bookings that arent completed
IF v_booking_status <> 'Completed' THEN
RAISE EXCEPTION 'Cannot leave a review for a booking that is % (Must be Completed)', v_booking_status;
END IF;
RETURN NEW;
END;
$$;
DROP TRIGGER IF EXISTS trg_review_integrity ON reviews;
CREATE TRIGGER trg_review_integrity
BEFORE INSERT ON reviews
FOR EACH ROW
EXECUTE FUNCTION petsitter_trg_review_integrity();
-- Make reviews non-updateable
CREATE OR REPLACE FUNCTION petsitter_trg_reviews_no_update()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
RAISE EXCEPTION 'Reviews are permanent. Updates are not allowed for review_id %.', OLD.review_id;
END;
$$;
DROP TRIGGER IF EXISTS trg_reviews_no_update ON reviews;
CREATE TRIGGER trg_reviews_no_update
BEFORE UPDATE ON reviews
FOR EACH ROW
EXECUTE FUNCTION petsitter_trg_reviews_no_update();
3. Data constraints requirements: Platform Analytics and Reporting
Data requirements description
The system can create reports of long term business operations:
- Monthly reports: Calculates total revenue and booking counts per sitter, per month.
- Top Rated Sitters: Calculates average ratings and total completed jobs.
Implementation
Views
CREATE OR REPLACE VIEW v_monthly_sitter_reports AS
SELECT
u.user_id AS sitter_id,
u.first_name,
u.last_name,
date_trunc('month', b.date_to) AS month,
COUNT(b.booking_id) AS total_completed_jobs,
SUM(p.amount) AS total_revenue
FROM users u
JOIN bookings b ON u.user_id = b.sitter_id
JOIN payments p ON b.booking_id = p.booking_id
WHERE b.status = 'Completed'
GROUP BY u.user_id, u.first_name, u.last_name, date_trunc('month', b.date_to)
ORDER BY month DESC, total_revenue DESC;
CREATE OR REPLACE VIEW v_top_rated_sitters AS
SELECT
u.user_id AS sitter_id,
u.first_name,
u.last_name,
COUNT(r.review_id) AS total_reviews,
ROUND(AVG(r.rating)::numeric, 2) AS average_rating
FROM users u
JOIN bookings b ON u.user_id = b.sitter_id
JOIN reviews r ON b.booking_id = r.booking_id
GROUP BY u.user_id, u.first_name, u.last_name
HAVING COUNT(r.review_id) > 0
ORDER BY average_rating DESC, total_reviews DESC;
4. Data constraints requirements: Background Jobs (Automated System Cleanup)
Data requirements description
Rules for pending bookings that must be enforced asynchronously by the database server to keep the platform clean:
- If a booking request remains 'Pending' and the
date_frompasses, it should automatically be marked as 'Expired'. - Runs automatically every hour
Implementation
Stored procedures
-- Enable pg cronjob
CREATE EXTENSION IF NOT EXISTS pg_cron;
-- Stored procedure for clean up expired bookings
CREATE OR REPLACE PROCEDURE petsitter_job_expire_pending_bookings()
LANGUAGE plpgsql
AS $$
BEGIN
UPDATE bookings
SET status = 'Expired'
WHERE status = 'Pending'
AND date_from < now();
END;
$$;
Views
CREATE OR REPLACE VIEW v_expired_pending_bookings AS SELECT * FROM bookings WHERE status = 'Expired';
Cronjob
-- Schedule the job to run every hour
SELECT cron.schedule('petsitter_expire_bookings', '0 * * * *', $$CALL petsitter_job_expire_pending_bookings();$$);
Last modified
10 hours ago
Last modified on 05/25/26 15:31:03
Note:
See TracWiki
for help on using the wiki.
