41 lines
1.6 KiB
Bash
Executable File
41 lines
1.6 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
repo=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
|
|
output=$(mktemp)
|
|
cleanup() { rm -f "$output"; }
|
|
trap cleanup EXIT INT TERM
|
|
|
|
docker compose exec -T db psql -X -U rf4 -d rf4_spotter \
|
|
< "$repo/deploy/query-plan-gate.sql" > "$output"
|
|
|
|
grep -Eq '100000[[:space:]]*\|[[:space:]]*90000[[:space:]]*\|[[:space:]]*20000[[:space:]]*\|[[:space:]]*5000' "$output"
|
|
|
|
for plan in activity_72h records_count records_page spot_detail public_spot_pages; do
|
|
grep -F "PLAN $plan" "$output" >/dev/null
|
|
done
|
|
|
|
# Public query budget from docs/query-performance.md. Five EXPLAIN statements
|
|
# must finish below it on the local alpha-sized fixture.
|
|
awk '
|
|
/Execution Time:/ { count += 1; if (($3 + 0) > 250) { print "Query plan exceeded 250 ms: " $0 > "/dev/stderr"; failed = 1 } }
|
|
END { if (count != 5 || failed) exit 1 }
|
|
' "$output"
|
|
|
|
# Selective paths must use an index. public_spot_pages may legitimately scan
|
|
# many approved rows while producing the distinct sitemap set.
|
|
awk '
|
|
/PLAN activity_72h/ { section = "activity"; next }
|
|
/PLAN records_count/ { section = "records_count"; next }
|
|
/PLAN records_page/ { section = "records_page"; next }
|
|
/PLAN spot_detail/ { section = "spot_detail"; next }
|
|
/PLAN public_spot_pages/ { section = "public_spot_pages"; next }
|
|
section == "activity" && /Index Scan/ { activity = 1 }
|
|
section == "records_page" && /Index Scan/ { records = 1 }
|
|
section == "spot_detail" && /Index Scan/ { spot = 1 }
|
|
END { if (!activity || !records || !spot) exit 1 }
|
|
' "$output"
|
|
|
|
grep 'Execution Time:' "$output"
|
|
echo "Query-plan gate passed: 100000 temporary reports, indexed selective paths, all plans under 250 ms"
|