mod common;
use common::pgwire_harness::TestServer;
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn strict_bitemporal_audit_query_preserves_user_columns() {
let srv = TestServer::start().await;
srv.exec(
"CREATE COLLECTION bt_audit (id STRING PRIMARY KEY, value STRING) \
WITH (engine='document_strict', bitemporal=true)",
)
.await
.expect("create strict bitemporal collection");
srv.exec("INSERT INTO bt_audit (id, value) VALUES ('r1', 'hello')")
.await
.expect("insert row");
srv.exec("UPDATE bt_audit SET value = 'world' WHERE id = 'r1'")
.await
.expect("update row to create a second system-time version");
let rows = srv
.query_named_rows("SELECT * FROM bt_audit AS OF SYSTEM TIME NULL")
.await
.expect("select audit-log (all versions) from strict bitemporal collection");
assert_eq!(
rows.len(),
2,
"expected both system-time versions of the row, got: {rows:?}"
);
for row in &rows {
assert_eq!(
row.get("id").map(String::as_str),
Some("r1"),
"user column 'id' must be present and correct in every audit-log row, got: {row:?}"
);
assert!(
row.contains_key("value"),
"user column 'value' must be present in every audit-log row, got: {row:?}"
);
for ts in ["_ts_system", "_ts_valid_from", "_ts_valid_until"] {
assert!(
row.contains_key(ts),
"synthetic temporal column '{ts}' must be present, got: {row:?}"
);
}
assert_eq!(
row.get("_ts_valid_from").map(String::as_str),
Some(i64::MIN.to_string().as_str()),
"_ts_valid_from must surface the raw i64::MIN unbounded sentinel, got: {row:?}"
);
assert_eq!(
row.get("_ts_valid_until").map(String::as_str),
Some(i64::MAX.to_string().as_str()),
"_ts_valid_until must surface the raw i64::MAX unbounded sentinel, got: {row:?}"
);
for reserved in ["__system_from_ms", "__valid_from_ms", "__valid_until_ms"] {
assert!(
!row.contains_key(reserved),
"reserved temporal column '{reserved}' must not leak into audit-log output, got keys: {:?}",
row.keys().collect::<Vec<_>>()
);
}
}
let values: std::collections::HashSet<&str> = rows
.iter()
.filter_map(|r| r.get("value").map(String::as_str))
.collect();
assert!(
values.contains("hello") && values.contains("world"),
"expected both versions' 'value' payloads to survive decode, got: {values:?}"
);
}