Skip to content

Instantly share code, notes, and snippets.

@blambeau
Last active March 19, 2026 20:05
Show Gist options
  • Select an option

  • Save blambeau/18c711c38bc6a425e3b0dfad3233b946 to your computer and use it in GitHub Desktop.

Select an option

Save blambeau/18c711c38bc6a425e3b0dfad3233b946 to your computer and use it in GitHub Desktop.
⏺ Here's a Tutorial D/Rel design for tracking book loans with a max 5 books per client constraint:
// Base relvars
VAR Client REAL RELATION {client_id INT, name CHAR} KEY {client_id};
VAR Book REAL RELATION {book_id INT, title CHAR} KEY {book_id};
VAR Loan REAL RELATION {client_id INT, book_id INT, loan_date DATE}
KEY {book_id} // A book can only be loaned to one client at a time
;
// Foreign key constraints
CONSTRAINT Loan_Client_FK
Loan {client_id} ⊆ Client {client_id};
CONSTRAINT Loan_Book_FK
Loan {book_id} ⊆ Book {book_id};
// Max 5 books per client constraint
CONSTRAINT Max5BooksPerClient
IS_EMPTY(
(SUMMARIZE Loan BY {client_id} ADD (COUNT() AS loan_count))
WHERE loan_count > 5
);
CREATE TABLE clients (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL
);
CREATE TABLE borrowings (
id SERIAL PRIMARY KEY,
client_id INT NOT NULL REFERENCES clients(id),
book_id INT NOT NULL REFERENCES books(id),
borrowed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
returned_at TIMESTAMP,
UNIQUE(book_id, returned_at) -- prevent double-borrowing active books
);
CREATE OR REPLACE FUNCTION active_borrow_count(p_client_id INT)
RETURNS INT AS $$
SELECT COUNT(*)::INT FROM borrowings
WHERE client_id = p_client_id AND returned_at IS NULL;
$$ LANGUAGE sql STABLE;
ALTER TABLE borrowings
ADD CONSTRAINT max_5_books
CHECK (active_borrow_count(client_id) < 5);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment