mod common;
use common::pgwire_harness::TestServer;
async fn assert_point_and_scan_agree_absent(server: &TestServer, table: &str, id: &str) {
let point = server
.query_text(&format!("SELECT id FROM {table} WHERE id = '{id}'"))
.await
.unwrap();
assert!(
point.is_empty(),
"PK point-lookup must not see the deleted row '{id}', got {point:?}"
);
let scan = server
.query_rows(&format!("SELECT id FROM {table}"))
.await
.unwrap();
assert!(
scan.iter().all(|row| row[0] != id),
"full scan must not see the deleted row '{id}', got {scan:?}"
);
let count = server
.query_text(&format!("SELECT COUNT(*) FROM {table}"))
.await
.unwrap();
assert_eq!(
count,
vec![scan.len().to_string()],
"COUNT(*) must agree with the scan row count"
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn committed_tx_delete_agrees_between_point_lookup_and_scan() {
let server = TestServer::start().await;
server
.exec("CREATE COLLECTION pk_scan (id TEXT PRIMARY KEY, val INT) WITH (engine='document_strict')")
.await
.unwrap();
server
.exec("INSERT INTO pk_scan (id, val) VALUES ('x', 1)")
.await
.unwrap();
server
.exec("INSERT INTO pk_scan (id, val) VALUES ('keep', 2)")
.await
.unwrap();
server.exec("BEGIN").await.unwrap();
server
.exec("DELETE FROM pk_scan WHERE id = 'x'")
.await
.unwrap();
server.exec("COMMIT").await.unwrap();
assert_point_and_scan_agree_absent(&server, "pk_scan", "x").await;
let point_keep = server
.query_text("SELECT id FROM pk_scan WHERE id = 'keep'")
.await
.unwrap();
assert_eq!(
point_keep.len(),
1,
"untouched row must still be visible via point-lookup, got {point_keep:?}"
);
let scan_keep = server.query_rows("SELECT id FROM pk_scan").await.unwrap();
assert_eq!(
scan_keep.len(),
1,
"scan must show exactly the one remaining row, got {scan_keep:?}"
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn equality_operand_order_agrees_on_primary_key() {
let server = TestServer::start().await;
server
.exec("CREATE COLLECTION pk_order (id TEXT PRIMARY KEY, val INT) WITH (engine='document_strict')")
.await
.unwrap();
server
.exec("INSERT INTO pk_order (id, val) VALUES ('smoke_32ea5f88', 1)")
.await
.unwrap();
let column_first = server
.query_text("SELECT id FROM pk_order WHERE id = 'smoke_32ea5f88'")
.await
.unwrap();
let literal_first = server
.query_text("SELECT id FROM pk_order WHERE 'smoke_32ea5f88' = id")
.await
.unwrap();
assert_eq!(
column_first,
vec!["smoke_32ea5f88".to_string()],
"column-first `id = 'x'` must match the committed row via the point-lookup path"
);
assert_eq!(
literal_first, column_first,
"literal-first `'x' = id` must return the identical row set as `id = 'x'`; \
operand order must not route the same predicate to a physical operator that disagrees"
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn equality_operand_order_agrees_when_absent() {
let server = TestServer::start().await;
server
.exec("CREATE COLLECTION pk_order_absent (id TEXT PRIMARY KEY, val INT) WITH (engine='document_strict')")
.await
.unwrap();
server
.exec("INSERT INTO pk_order_absent (id, val) VALUES ('present', 1)")
.await
.unwrap();
let column_first = server
.query_text("SELECT id FROM pk_order_absent WHERE id = 'absent'")
.await
.unwrap();
let literal_first = server
.query_text("SELECT id FROM pk_order_absent WHERE 'absent' = id")
.await
.unwrap();
assert!(
column_first.is_empty(),
"column-first `id = 'absent'` must not match any row, got {column_first:?}"
);
assert_eq!(
literal_first, column_first,
"literal-first `'absent' = id` must also return empty for an absent key"
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn point_lookup_scan_and_count_agree_after_restart() {
let server = TestServer::start().await;
server
.exec("CREATE COLLECTION pk_restart (id TEXT PRIMARY KEY, val INT) WITH (engine='document_strict')")
.await
.unwrap();
for i in 0..7u32 {
server
.exec(&format!(
"INSERT INTO pk_restart (id, val) VALUES ('row_{i}', {i})"
))
.await
.unwrap();
}
let (server, dir) = server.take_dir();
server.graceful_shutdown().await;
let (server, _dir) = TestServer::open_on_path(dir).await;
let scan = server
.query_rows("SELECT id FROM pk_restart")
.await
.unwrap();
assert_eq!(
scan.len(),
7,
"all 7 rows must survive the restart, got {scan:?}"
);
for row in &scan {
let id = &row[0];
let point = server
.query_text(&format!("SELECT id FROM pk_restart WHERE id = '{id}'"))
.await
.unwrap();
assert_eq!(
point,
vec![id.clone()],
"scanned row '{id}' must be reachable by primary-key point-lookup after restart"
);
}
let count = server
.query_text("SELECT COUNT(*) FROM pk_restart")
.await
.unwrap();
assert_eq!(
count,
vec![scan.len().to_string()],
"COUNT(*) must equal the scanned row count after restart, got {count:?}"
);
}