diesel-guard 0.10.0

Linter for dangerous Postgres migration patterns in Diesel and SQLx. Prevents downtime caused by unsafe schema changes.
Documentation
# Adding an EXCLUDE Constraint

**Check Name**: `AddExcludeConstraintCheck`

**Lock Type**: SHARE ROW EXCLUSIVE

## Bad

Adding an exclusion constraint scans the entire table to validate existing rows while holding a SHARE ROW EXCLUSIVE lock for the full duration. Unlike `CHECK` or `FOREIGN KEY` constraints, there is no `NOT VALID` escape hatch — exclusion constraints must be validated immediately.

```sql
ALTER TABLE meeting_rooms
    ADD CONSTRAINT no_double_booking
    EXCLUDE USING gist (room_id WITH =, during WITH &&);
```

## Good

There is no non-blocking path for adding an exclusion constraint to an existing populated table. Options:

- **Add during a low-traffic window** and accept the full-table scan cost.
- **Define the constraint at table creation time** to avoid scanning existing rows:

```sql
CREATE TABLE meeting_rooms (
    id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    room_id INT NOT NULL,
    during TSTZRANGE NOT NULL,
    CONSTRAINT no_double_booking EXCLUDE USING gist (room_id WITH =, during WITH &&)
);
```

- **Use application-level enforcement** if the table is too large to lock safely during the migration.

## Escape Hatch

If you have reviewed this operation and confirmed it is safe (e.g., the table is empty or traffic is negligible), wrap it in a safety-assured block:

```sql
-- safety-assured:start
ALTER TABLE meeting_rooms
    ADD CONSTRAINT no_double_booking
    EXCLUDE USING gist (room_id WITH =, during WITH &&);
-- safety-assured:end
```