mod common;
use postgres::Client;
fn explain_json(conn_str: &str, sql: &str) -> String {
let mut client = Client::connect(conn_str, postgres::NoTls)
.expect("postgres::Client must connect for EXPLAIN");
let rows = client
.query(&format!("EXPLAIN (FORMAT JSON) {sql}"), &[])
.expect("EXPLAIN must succeed");
rows.first()
.expect("EXPLAIN must return at least one row")
.get::<_, String>(0)
}
fn assert_index_scan(plan_json: &str, context: &str) {
let lower = plan_json.to_ascii_lowercase();
assert!(
!lower.contains("\"seq scan\""),
"{context}: EXPLAIN must not show a Seq Scan; got plan:\n{plan_json}"
);
assert!(
lower.contains("\"index scan\"") || lower.contains("\"index only scan\""),
"{context}: EXPLAIN must show an Index Scan or Index Only Scan on idx_claims_subject_line; \
got plan:\n{plan_json}"
);
assert!(
plan_json.contains("idx_claims_subject_line"),
"{context}: EXPLAIN must reference idx_claims_subject_line; got plan:\n{plan_json}"
);
}
fn run_explain_assertions(conn_str: &str) {
let plan_no_cutoff = explain_json(
conn_str,
"SELECT DISTINCT predicate FROM claims WHERE agent_id = 'test-agent' AND subject = 'alice'",
);
assert_index_scan(&plan_no_cutoff, "list_predicates_for_subject (no cutoff)");
let plan_with_cutoff = explain_json(
conn_str,
"SELECT DISTINCT predicate FROM claims \
WHERE agent_id = 'test-agent' AND subject = 'alice' AND tx_time <= '2030-01-01T00:00:00+00:00'",
);
assert!(
!plan_with_cutoff.to_ascii_lowercase().contains("\"seq scan\""),
"list_predicates_for_subject (with cutoff): EXPLAIN must not show a Seq Scan; \
got plan:\n{plan_with_cutoff}"
);
assert!(
plan_with_cutoff.contains("idx_claims_subject_line"),
"list_predicates_for_subject (with cutoff): EXPLAIN must reference idx_claims_subject_line; \
got plan:\n{plan_with_cutoff}"
);
}
#[test]
fn postgres_list_predicates_uses_index_pg16() {
common::with_pg_and_conn("16", |_store, conn_str| {
run_explain_assertions(&conn_str);
});
}
#[test]
fn postgres_list_predicates_uses_index_pg18() {
common::with_pg_and_conn("18", |_store, conn_str| {
run_explain_assertions(&conn_str);
});
}