Expand description
Compiled filter interpreter — flat opcode evaluation.
Mirrors PostgreSQL’s ExprState::steps / ExecInterpExpr
(src/backend/executor/execExprInterp.c). The legacy walker in
super::filter::Filter::evaluate recurses through the AST per row
and consults a &dyn Fn(&str) -> Option<Value> closure for every
predicate’s column lookup. That pays:
- one HashMap (or BTreeMap) lookup per predicate per row;
- one closure indirection per lookup;
- one stack frame per AST node per row.
CompiledFilter does the column resolution once at plan time,
flattens the AST into a linear Vec<CompiledOp>, and evaluates
each row with a tight loop over the ops against a &[Value] slot
indexed by the column index resolved at compile time. The hot loop
does no allocation, no string lookup, and no closure call.
§Wiring
Compile once per query plan with CompiledFilter::compile,
providing a column-name → slot-index map (the schema). On every
row, build a &[Value] slot in schema order and call
CompiledFilter::evaluate. The compiled filter is Send + Sync
and can be cached on the plan node.
§Semantics
Identical to the legacy walker, byte for byte:
- column missing from the schema at compile time →
CompileError Value::Nullat a slot position → equivalent to “column not found” in the legacy path:IsNullreturnstrue, every other predicate returnsfalseAnd/Orare short-circuited per the postfix arityNotflips the top of the stack
A fuzz test (compiled_matches_legacy_for_random_filters) exercises
1 000 random filter + row pairs to guard against drift.
§Evaluator bypass contract
CompiledFilter::evaluate dispatches every predicate through
Predicate::evaluate rather than routing through
query::evaluator::evaluate. This bypass is intentional for the hot
path and is valid under the following preconditions:
-
Pre-typed values.
Filterpredicates are constructed from values whose types have already been resolved by the query planner (or a typed DSL caller). The planner guarantees that the column type and predicate-value type are compatible before aCompiledFilteris built. -
No implicit casts at eval time. Because types are resolved at plan time,
evaluator::evaluate’s implicit-cast step (which consultsschema::coercion_spine) adds zero value at row-eval time for ops inFilterOp:Eq,Ne,Lt,Le,Gt,Ge,IsNull,IsNotNull,Between,In,NotIn,Like,NotLike,Contains,StartsWith,EndsWith. The hand-rolledpartial_compare_valuespath is type-safe for these ops given precondition 1. -
Parity test guards against drift.
compiled_matches_legacy_for_random_filtersexercises 1 000 random filter+row pairs comparing compiled output to the legacy walker. Any semantic deviation from the accepted behavior surfaces there.
When a future slice migrates Filter construction to emit Expr
trees (so the planner can enforce type contracts through the type
system rather than by convention), the bypass should be removed and
the ops above routed through evaluator::evaluate.
Structs§
- Compiled
Filter - A filter that has been compiled against a fixed column schema.
Enums§
- Compile
Error - Error returned by
CompiledFilter::compilewhen the filter references a column that is not in the provided schema. - Compiled
Op - Single instruction in a
CompiledFilterop stream.