Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/target/
/out/
.env
/data/
*.dump
.DS_Store
.idea/

# Local pmat / pv tooling state
/.pmat/
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 25 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.PHONY: help up down pagila psql demo capstone verify test coverage fmt lint clean nuke
.PHONY: help up down pagila psql demo capstone verify test coverage fmt lint clean nuke \
demo-1-fundamentals demo-2-joins demo-3-pagila demo-4-rust demo-all

DC := docker compose
PSQL := $(DC) exec -T postgres psql -U postgres -d pagila
Expand All @@ -13,6 +14,14 @@ help:
@echo " make demo — run the SQL example walkthrough"
@echo " make capstone — build and run the Rust postgres-reports binary"
@echo " make verify — assert all headline counts (CI smoke test)"
@echo ""
@echo " Standalone demos (one script per concept):"
@echo " make demo-1-fundamentals — sql/01-fundamentals/*.sql"
@echo " make demo-2-joins — sql/02-joins/*.sql"
@echo " make demo-3-pagila — sql/pagila-analytics/*.sql"
@echo " make demo-4-rust — Rust capstone binary, 3 contract-enforced reports"
@echo " make demo-all — run every demo in sequence"
@echo ""
@echo " make test — cargo test for the Rust crate"
@echo " make coverage — cargo llvm-cov (100% line gate)"
@echo " make fmt lint — cargo fmt && cargo clippy"
Expand Down Expand Up @@ -48,6 +57,21 @@ capstone: pagila
verify: pagila
@bash scripts/verify.sh

demo-1-fundamentals: pagila
@bash scripts/demo-1-fundamentals.sh

demo-2-joins: pagila
@bash scripts/demo-2-joins.sh

demo-3-pagila: pagila
@bash scripts/demo-3-pagila.sh

demo-4-rust: pagila
@bash scripts/demo-4-rust.sh

demo-all: pagila
@bash scripts/demo-all.sh

test: pagila
@DATABASE_URL=postgres://postgres:postgres@localhost:5432/pagila cargo test --release

Expand Down
32 changes: 32 additions & 0 deletions scripts/demo-1-fundamentals.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
# demo-1-fundamentals.sh — first commands you run after `psql -d pagila`.
#
# Walks through the five SQL files in sql/01-fundamentals/:
# 01-connect.sql psql conventions, schema introspection
# 02-show-tables.sql listing tables, describing a table
# 03-select-limit.sql safe exploratory SELECT against a 16k-row table
# 04-modify.sql INSERT / UPDATE / DELETE inside a transaction
# 05-export.sql \copy a query result to a CSV file
#
# Usage:
# scripts/demo-1-fundamentals.sh
#
set -euo pipefail
cd "$(dirname "$0")/.."

bar() { printf '\n\033[1;36m=== %s ===\033[0m\n\n' "$*"; }

# bring up postgres + load Pagila if not already done
if ! docker compose ps postgres 2>/dev/null | grep -q "Up"; then
bar "starting postgres + loading Pagila (one-time)"
make pagila >/dev/null
fi

PSQL=(docker compose exec -T postgres psql -U postgres -d pagila)

for f in sql/01-fundamentals/*.sql; do
bar "$(basename "$f")"
"${PSQL[@]}" -f - < "$f"
done

bar "fundamentals demo complete"
28 changes: 28 additions & 0 deletions scripts/demo-2-joins.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash
# demo-2-joins.sh — the three join patterns every Pagila query uses.
#
# 01-traversal.sql customer → rental → inventory → film (the Sakila spine)
# 02-inner-vs-left.sql what changes when you flip INNER ↔ LEFT
# 03-explain-analyze.sql reading a query plan against real row counts
#
# Usage:
# scripts/demo-2-joins.sh
#
set -euo pipefail
cd "$(dirname "$0")/.."

bar() { printf '\n\033[1;36m=== %s ===\033[0m\n\n' "$*"; }

if ! docker compose ps postgres 2>/dev/null | grep -q "Up"; then
bar "starting postgres + loading Pagila (one-time)"
make pagila >/dev/null
fi

PSQL=(docker compose exec -T postgres psql -U postgres -d pagila)

for f in sql/02-joins/*.sql; do
bar "$(basename "$f")"
"${PSQL[@]}" -f - < "$f"
done

bar "joins demo complete"
32 changes: 32 additions & 0 deletions scripts/demo-3-pagila.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
# demo-3-pagila.sh — three Pagila analytics queries as raw SQL.
#
# Each query is the same one the Rust capstone runs (see scripts/demo-4-rust.sh).
# This demo shows them in pure SQL so you can see exactly what the binary
# wraps with runtime contracts.
#
# top-customers.sql customer × rental → 10 by rental count
# top-films.sql film × inventory × rental → 10 by rental count
# top-actors.sql actor × film_actor → 10 by distinct films
#
# Usage:
# scripts/demo-3-pagila.sh
#
set -euo pipefail
cd "$(dirname "$0")/.."

bar() { printf '\n\033[1;36m=== %s ===\033[0m\n\n' "$*"; }

if ! docker compose ps postgres 2>/dev/null | grep -q "Up"; then
bar "starting postgres + loading Pagila (one-time)"
make pagila >/dev/null
fi

PSQL=(docker compose exec -T postgres psql -U postgres -d pagila)

for q in top-customers top-films top-actors; do
bar "pagila-analytics/${q}.sql"
"${PSQL[@]}" -f - < "sql/pagila-analytics/${q}.sql"
done

bar "pagila analytics complete (run scripts/demo-4-rust.sh for the contract-enforced version)"
50 changes: 50 additions & 0 deletions scripts/demo-4-rust.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# demo-4-rust.sh — Rust capstone: postgres-reports binary, three reports.
#
# Same SQL as scripts/demo-3-pagila.sh, but wrapped by a Rust binary that
# uses an async sqlx::PgPool and enforces named runtime contracts on every
# result before printing JSON. If the database disagrees with the schema's
# invariants, the process aborts loudly instead of shipping corrupt JSON.
#
# Contracts proved per call:
# row_count == limit
# top row count >= 1
# ORDER BY DESC monotonic
# per-report id > 0, text field non-empty
#
# Output: pretty-printed JSON to stdout AND to out/ as files.
#
# Usage:
# scripts/demo-4-rust.sh # default --limit 10
# scripts/demo-4-rust.sh 5 # --limit 5
#
set -euo pipefail
cd "$(dirname "$0")/.."

LIMIT="${1:-10}"
OUT_DIR="out"

bar() { printf '\n\033[1;36m=== %s ===\033[0m\n\n' "$*"; }

if ! docker compose ps postgres 2>/dev/null | grep -q "Up"; then
bar "starting postgres + loading Pagila (one-time)"
make pagila >/dev/null
fi

bar "building postgres-reports (release)"
cargo build --release --bin postgres-reports

mkdir -p "$OUT_DIR"

export DATABASE_URL="${DATABASE_URL:-postgres://postgres:postgres@localhost:5432/pagila}"

for r in customers films actors; do
bar "postgres-reports --report ${r} --limit ${LIMIT}"
cargo run --release --quiet --bin postgres-reports -- \
--report "$r" --limit "$LIMIT" --out "${OUT_DIR}/${r}.json"
echo
echo "wrote ${OUT_DIR}/${r}.json"
done

bar "capstone complete — JSON written to ${OUT_DIR}/"
ls -lh "$OUT_DIR"/*.json
29 changes: 29 additions & 0 deletions scripts/demo-all.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# demo-all.sh — run every demo in sequence.
#
# 1. SQL fundamentals (scripts/demo-1-fundamentals.sh)
# 2. Joins (scripts/demo-2-joins.sh)
# 3. Pagila analytics SQL (scripts/demo-3-pagila.sh)
# 4. Rust capstone (scripts/demo-4-rust.sh)
#
# Usage:
# scripts/demo-all.sh
#
set -euo pipefail
cd "$(dirname "$0")/.."

bar() { printf '\n\033[1;33m################ %s ################\033[0m\n' "$*"; }

bar "DEMO 1/4 — SQL fundamentals"
scripts/demo-1-fundamentals.sh

bar "DEMO 2/4 — Joins"
scripts/demo-2-joins.sh

bar "DEMO 3/4 — Pagila analytics"
scripts/demo-3-pagila.sh

bar "DEMO 4/4 — Rust capstone"
scripts/demo-4-rust.sh

bar "ALL DEMOS COMPLETE"
4 changes: 4 additions & 0 deletions sql/pagila-analytics/top-actors.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
-- Pagila top-N actors by distinct film count.
-- Joins actor to the film_actor bridge table to count how many distinct
-- films each actor appeared in. The Rust binary `postgres-reports
-- --report actors` runs the same query and enforces runtime contracts.
SELECT a.actor_id, a.first_name, a.last_name,
COUNT(DISTINCT fa.film_id) AS film_count
FROM actor a
Expand Down
5 changes: 5 additions & 0 deletions sql/pagila-analytics/top-customers.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
-- Pagila top-N customers by rental count.
-- Joins customer to rental and ranks customers by the number of rentals
-- they appear in. The Rust binary `postgres-reports --report customers`
-- executes the same query and asserts runtime contracts on the result
-- (see crates/postgres-reports/src/lib.rs).
SELECT c.customer_id,
c.first_name || ' ' || c.last_name AS name,
COUNT(r.rental_id) AS rental_count,
Expand Down
4 changes: 4 additions & 0 deletions sql/pagila-analytics/top-films.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
-- Pagila top-N films by rental count.
-- Walks film -> inventory -> rental to count how many times each film
-- was rented. The Rust binary `postgres-reports --report films` runs
-- the same query and enforces runtime contracts on the result.
SELECT f.film_id, f.title, COUNT(r.rental_id) AS rental_count
FROM film f
LEFT JOIN inventory i ON i.film_id = f.film_id
Expand Down
Loading