| | 1 | = Phase P9 — Data Consistency and Integrity (Wedding Planner) = |
| | 2 | |
| | 3 | == Overview == |
| | 4 | This section explains how data consistency and integrity are ensured in the Wedding Planner database system. |
| | 5 | The goal is to prevent invalid, duplicate, or contradictory data by enforcing constraints, foreign keys, cascade rules, and transactional consistency at the database level (PostgreSQL). |
| | 6 | |
| | 7 | The described mechanisms are directly applied to real use cases such as venue booking, wedding ownership, and user-related data. |
| | 8 | |
| | 9 | == Data Integrity Concepts == |
| | 10 | Data integrity in relational databases is achieved by enforcing rules that guarantee correctness throughout the lifecycle of the data. |
| | 11 | In the Wedding Planner system, integrity is ensured through: |
| | 12 | |
| | 13 | Entity integrity (primary keys) |
| | 14 | |
| | 15 | Referential integrity (foreign keys) |
| | 16 | |
| | 17 | Domain integrity (CHECK, NOT NULL, UNIQUE) |
| | 18 | |
| | 19 | Transactional integrity (ACID properties) |
| | 20 | |
| | 21 | == Referential Integrity and Constraints == |
| | 22 | |
| | 23 | Referential integrity ensures that relationships between tables remain valid. |
| | 24 | For example, a wedding cannot exist without a valid user, and a venue booking cannot exist without a valid wedding and venue. |
| | 25 | |
| | 26 | === Core Tables and Constraints === |
| | 27 | |
| | 28 | || Table || Purpose || |
| | 29 | || user || Stores registered users || |
| | 30 | || wedding || Stores wedding events created by users || |
| | 31 | || venue || Stores available venues || |
| | 32 | || venue_booking || Connects weddings with venues and time slots || |
| | 33 | |
| | 34 | === SQL Implementation === |
| | 35 | |
| | 36 | {{{ |
| | 37 | #!sql |
| | 38 | CREATE TABLE "user" ( |
| | 39 | user_id SERIAL PRIMARY KEY, |
| | 40 | first_name VARCHAR(50) NOT NULL, |
| | 41 | last_name VARCHAR(50) NOT NULL, |
| | 42 | email VARCHAR(120) UNIQUE NOT NULL |
| | 43 | ); |
| | 44 | |
| | 45 | CREATE TABLE wedding ( |
| | 46 | wedding_id SERIAL PRIMARY KEY, |
| | 47 | wedding_date DATE NOT NULL, |
| | 48 | budget NUMERIC(12,2), |
| | 49 | user_id INTEGER NOT NULL, |
| | 50 | CONSTRAINT fk_wedding_user |
| | 51 | FOREIGN KEY (user_id) |
| | 52 | REFERENCES "user"(user_id) |
| | 53 | ON DELETE CASCADE |
| | 54 | ); |
| | 55 | |
| | 56 | CREATE TABLE venue ( |
| | 57 | venue_id SERIAL PRIMARY KEY, |
| | 58 | name VARCHAR(120) NOT NULL, |
| | 59 | capacity INTEGER NOT NULL CHECK (capacity > 0) |
| | 60 | ); |
| | 61 | |
| | 62 | CREATE TABLE venue_booking ( |
| | 63 | booking_id SERIAL PRIMARY KEY, |
| | 64 | venue_id INTEGER NOT NULL, |
| | 65 | wedding_id INTEGER NOT NULL, |
| | 66 | booking_date DATE NOT NULL, |
| | 67 | start_time TIME NOT NULL, |
| | 68 | end_time TIME NOT NULL, |
| | 69 | CONSTRAINT fk_booking_venue |
| | 70 | FOREIGN KEY (venue_id) |
| | 71 | REFERENCES venue(venue_id) |
| | 72 | ON DELETE CASCADE, |
| | 73 | CONSTRAINT fk_booking_wedding |
| | 74 | FOREIGN KEY (wedding_id) |
| | 75 | REFERENCES wedding(wedding_id) |
| | 76 | ON DELETE CASCADE, |
| | 77 | CONSTRAINT chk_time_valid |
| | 78 | CHECK (end_time > start_time) |
| | 79 | ); |
| | 80 | }}} |
| | 81 | This design prevents orphan records and ensures that deleting a wedding or user automatically removes dependent bookings. |
| | 82 | |
| | 83 | == Preventing Double Booking Using Transactions == |
| | 84 | |
| | 85 | One of the most critical integrity problems in the Wedding Planner system is preventing multiple weddings from booking the same venue at overlapping times. |
| | 86 | |
| | 87 | This problem cannot be solved reliably without transactions. |
| | 88 | |
| | 89 | === Transaction-Based Solution === |
| | 90 | |
| | 91 | {{{ |
| | 92 | #!sql |
| | 93 | |
| | 94 | BEGIN; |
| | 95 | |
| | 96 | SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; |
| | 97 | |
| | 98 | SELECT 1 |
| | 99 | FROM venue_booking |
| | 100 | WHERE venue_id = 1 |
| | 101 | AND booking_date = '2026-06-20' |
| | 102 | AND NOT (end_time <= '16:00' OR start_time >= '18:00') |
| | 103 | FOR UPDATE; |
| | 104 | |
| | 105 | INSERT INTO venue_booking ( |
| | 106 | venue_id, wedding_id, booking_date, start_time, end_time |
| | 107 | ) |
| | 108 | VALUES ( |
| | 109 | 1, 1, '2026-06-20', '16:00', '18:00' |
| | 110 | ); |
| | 111 | |
| | 112 | COMMIT; |
| | 113 | |
| | 114 | |
| | 115 | }}} |
| | 116 | |
| | 117 | The transaction guarantees that: |
| | 118 | |
| | 119 | Availability is checked and reserved atomically |
| | 120 | |
| | 121 | Concurrent booking attempts cannot create overlaps |
| | 122 | |
| | 123 | Conflicting transactions are rolled back safely |
| | 124 | |
| | 125 | == Database-Level Overlap Protection (PostgreSQL) == |
| | 126 | |
| | 127 | PostgreSQL allows enforcing scheduling rules declaratively using exclusion constraints. |
| | 128 | |
| | 129 | === Exclusion Constraint for Venues === |
| | 130 | |
| | 131 | {{{ |
| | 132 | #!sql |
| | 133 | |
| | 134 | CREATE EXTENSION IF NOT EXISTS btree_gist; |
| | 135 | |
| | 136 | ALTER TABLE venue_booking |
| | 137 | ADD COLUMN booking_range tsrange |
| | 138 | GENERATED ALWAYS AS ( |
| | 139 | tsrange( |
| | 140 | booking_date + start_time, |
| | 141 | booking_date + end_time |
| | 142 | ) |
| | 143 | ) STORED; |
| | 144 | |
| | 145 | ALTER TABLE venue_booking |
| | 146 | ADD CONSTRAINT venue_no_overlap |
| | 147 | EXCLUDE USING gist ( |
| | 148 | venue_id WITH =, |
| | 149 | booking_range WITH && |
| | 150 | ); |
| | 151 | |
| | 152 | |
| | 153 | }}} |
| | 154 | |
| | 155 | This constraint guarantees at the database level that a venue cannot be booked twice for overlapping time intervals, regardless of application logic. |
| | 156 | |
| | 157 | == Cascade Rules and Design Decisions == |
| | 158 | |
| | 159 | Different cascade strategies are used depending on business logic. |
| | 160 | |
| | 161 | || Rule || Usage in Wedding Planner || |
| | 162 | || ON DELETE CASCADE || Deleting a wedding removes all related bookings automatically || |
| | 163 | || ON DELETE RESTRICT || Prevents deleting users with active weddings || |
| | 164 | || ON DELETE SET NULL || Keeps historical records if service providers are removed || |
| | 165 | |
| | 166 | These decisions ensure both data correctness and auditability. |
| | 167 | |
| | 168 | == Best Practices Applied == |
| | 169 | |
| | 170 | Integrity rules are enforced at the database level |
| | 171 | |
| | 172 | Application logic complements, but does not replace, constraints |
| | 173 | |
| | 174 | Transactions are used for multi-step operations |
| | 175 | |
| | 176 | Scheduling conflicts are handled atomically |
| | 177 | |
| | 178 | Referential actions reflect real business semantics |
| | 179 | |
| | 180 | == Conclusion == |
| | 181 | By combining relational constraints, foreign keys, cascade rules, and transactional control, the Wedding Planner database ensures strong consistency and integrity. |
| | 182 | The system prevents invalid states such as orphan records, overlapping bookings, and partial updates, while remaining scalable and safe for concurrent usage. |
| | 183 | |
| | 184 | This approach aligns with real-world production database standards and fully supports the functional requirements of the Wedding Planner project. |