Skip to content
Merged
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
62 changes: 61 additions & 1 deletion benchmarks/runners/certify/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1198,11 +1198,12 @@ fn sanitized_query_evidence(value: &serde_json::Value) -> bool {
&& sanitized_operator_rss(object.get("operator_rss"))
}

const QUERY_HOP_KEYS: [&str; 25] = [
const QUERY_HOP_KEYS: [&str; 26] = [
"ordinal",
"input_batches",
"input_rows",
"candidates_generated",
"adjacency_rows_examined",
"rows_emitted",
"projected_chunks",
"projected_rows",
Expand Down Expand Up @@ -1862,6 +1863,65 @@ mod tests {
assert!(parse_receipts(&encoded, true).is_err());
}

#[test]
fn query_receipts_preserve_typed_adjacency_probe_evidence() {
let query = serde_json::json!({
"contract": "graphforge-result-sink/2",
"destination": "/private/query.arrow",
"format": "ArrowIpc", "rows": 2, "batches": 1, "bytes": 64,
"complete": true, "result_sha256": "a".repeat(64), "scalar_u64": null,
"query_evidence": {
"contract": "graphforge-query-evidence/1",
"hops": [{
"ordinal": 0, "input_batches": 0, "input_rows": 0,
"candidates_generated": 2, "adjacency_rows_examined": 3,
"rows_emitted": 2, "projected_chunks": 1, "projected_rows": 2,
"projected_columns": 1, "edge_projected_columns": 0,
"node_projected_columns": 0, "edge_reader_calls": 0,
"edge_rows_returned": 0, "edge_logical_rows_scanned": 0,
"edge_full_reads": 0, "node_reader_calls": 0,
"node_rows_returned": 0, "node_logical_rows_scanned": 0,
"node_full_reads": 0, "identity_reader_calls": 1,
"identity_logical_bytes": 64, "identity_ranges_selected": 1,
"identity_peak_buffer_bytes": 64, "identity_per_record_seeks": 0,
"identity_revalidation_calls": 1, "identity_revalidation_bytes": 0
}],
"sorts": [],
"operator_rss": [{
"ordinal": 0, "operator": "ordered_one_hop",
"before_bytes": 100, "peak_bytes": 120, "after_bytes": 110
}],
"max_in_flight_reads": 0, "memory_reserved_before": 0,
"memory_reserved_after": 0, "returned_batch_bytes": 32,
"execution_batch_rows": 8192, "peak_rss_bytes": 120,
"rss_after_release_bytes": 110
}
});
let accepted = parse_receipts(&serde_json::to_vec(&query).unwrap(), true).unwrap();
assert_eq!(accepted[0]["query_evidence"], query["query_evidence"]);
assert!(accepted[0].get("destination").is_none());
for bad_value in [
serde_json::json!(-1),
serde_json::json!("3"),
serde_json::Value::Null,
] {
let mut invalid = query.clone();
invalid["query_evidence"]["hops"][0]["adjacency_rows_examined"] = bad_value;
assert!(parse_receipts(&serde_json::to_vec(&invalid).unwrap(), true).is_err());
}
for field in ["adjacency_rows_examined", "identity_reader_calls"] {
let mut invalid = query.clone();
invalid["query_evidence"]["hops"][0]
.as_object_mut()
.unwrap()
.remove(field);
assert!(parse_receipts(&serde_json::to_vec(&invalid).unwrap(), true).is_err());
}
let mut invalid = query;
invalid["query_evidence"]["hops"][0]["project_path"] = serde_json::json!("/private");
assert!(parse_receipts(&serde_json::to_vec(&invalid).unwrap(), true).is_err());
}

#[test]
fn storage_receipts_are_closed_and_preserve_only_semantic_attribution() {
let totals = serde_json::json!({
Expand Down
3 changes: 3 additions & 0 deletions crates/graphforge-api/src/query_evidence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ pub struct QueryHopEvidence {
pub input_rows: u64,
/// Adjacency candidates examined before projection.
pub candidates_generated: u64,
/// Adjacency degree probes, including empty destinations, in ordered shortcuts.
pub adjacency_rows_examined: u64,
/// Rows emitted by the hop.
pub rows_emitted: u64,
/// Chunks served by destination-only projection.
Expand Down Expand Up @@ -261,6 +263,7 @@ impl From<graphforge_exec::demand::DemandSnapshot> for QueryExecutionEvidence {
input_batches: hop.input_batches,
input_rows: hop.input_rows,
candidates_generated: hop.candidates_generated,
adjacency_rows_examined: hop.adjacency_rows_examined,
rows_emitted: hop.rows_emitted,
projected_chunks: hop.projected_chunks,
projected_rows: hop.projected_rows,
Expand Down
Loading