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
13 changes: 8 additions & 5 deletions crates/ourios-querier/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ use datafusion::dataframe::DataFrame;
use datafusion::functions::expr_fn::{coalesce, get_field, regexp_like, starts_with};
use datafusion::functions_aggregate::expr_fn::{avg, max, min, sum};
use datafusion::functions_nested::expr_fn::array_element;
use datafusion::logical_expr::{Expr, cast, is_not_true, is_true, not, try_cast};
use datafusion::logical_expr::{Expr, cast, is_not_true, not, try_cast};
use datafusion::prelude::{col, lit};

use ourios_core::alias::AliasMap;
Expand Down Expand Up @@ -1019,9 +1019,12 @@ fn body_equality(

let physical_eq =
physical_present.then(|| string_kind.clone().and(col(columns::BODY).eq(body_lit())));
// `IS TRUE` mirrors the `!=` totalisation: an unknowable row never
// matches equality. The arm is further gated to NULL physical bodies:
// when a body is retained the stored bytes are the truth (an
// No `IS TRUE` here, deliberately: under a filter NULL and false are
// equivalent (both drop the row), so equality is already total — and
// wrapping the arm would defeat the row-group pruning the template
// ids exist to enable (the `!=` branch, where NULL genuinely differs
// from false, uses `IS NOT TRUE`). The arm is gated to NULL physical
// bodies: when a body is retained the stored bytes are the truth (an
// overflow-spilled param's truncated stored value could otherwise
// false-match a crafted literal — `reconstruct` refuses exactly that
// case), and for non-lossy retention §3.3 makes the physical arm
Expand All @@ -1034,7 +1037,7 @@ fn body_equality(
} else {
lit(true)
})
.and(is_true(arm))
.and(arm)
});
match (physical_eq, template_eq) {
(Some(p), Some(t)) => PredExpr::Filter(p.or(t)),
Expand Down
67 changes: 67 additions & 0 deletions crates/ourios-querier/tests/it/rfc0044_body_equality.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,73 @@ async fn rfc0044_overflow_spill_cannot_false_match_a_crafted_literal() {
assert_eq!(truth.rows, 1, "the retained body is the truth");
}

/// Scenario RFC0044.7 — pruning still engages: two hour-partitioned
/// files, the matched template only in the first. The second file's row
/// group is skippable by both arms (its `template_id` statistics exclude
/// every candidate and its body column is all-NULL), so the scan touches
/// only the matching file — and the result is still complete.
/// See `docs/rfcs/0044-template-aware-body-equality.md` §5.
#[tokio::test]
async fn rfc0044_7_pruning_engages_across_partitions() {
const HOUR: u64 = 3_600_000_000_000;
let bucket = tempfile::TempDir::new().expect("temp");
write_audit(
bucket.path(),
&[
created("t", 1, "claude_code.api_request", TS0),
created("t", 9, "claude_code.tool_result", TS0 + 1),
],
);
write_all(
bucket.path(),
&[
mined("t", 1, TS0 + 10, &[], &["", ""]),
// A different template a partition-hour later: its own file.
mined("t", 9, TS0 + HOUR + 10, &[], &["", ""]),
],
);
let result = run(bucket.path(), r#"body == "claude_code.api_request""#).await;
assert_eq!(result.rows, 1, "the matching record returns, completely");
assert!(
result.stats.row_groups_pruned >= 1,
"the non-candidate partition is pruned: {:?}",
result.stats,
);
}

/// Scenario RFC0044.8 (full) — a literal matching no template and no
/// retained body returns empty with every row group pruned: correct
/// empties stay cheap.
Comment thread
jensholdgaard marked this conversation as resolved.
/// See `docs/rfcs/0044-template-aware-body-equality.md` §5.
#[tokio::test]
async fn rfc0044_8_correct_empties_prune_everything() {
const HOUR: u64 = 3_600_000_000_000;
let bucket = tempfile::TempDir::new().expect("temp");
write_audit(
bucket.path(),
&[created("t", 1, "claude_code.api_request", TS0)],
);
write_all(
bucket.path(),
&[
mined("t", 1, TS0 + 10, &[], &["", ""]),
mined("t", 1, TS0 + HOUR + 10, &[], &["", ""]),
],
);
let result = run(bucket.path(), r#"body == "claude_code.no_such_event""#).await;
assert_eq!(result.rows, 0);
assert_eq!(
result.stats.row_groups_scanned, 0,
"an unmatched literal must not scan anything: {:?}",
result.stats,
);
assert_eq!(
result.stats.row_groups_pruned, 2,
"both partitions' row groups are pruned, not elided: {:?}",
result.stats,
);
}

/// The empty-set half of RFC0044.8 — a literal matching no template and
/// no retained body returns empty (the full pruning assertion lands with
/// the partitioned fixtures in a later slice).
Expand Down