Skip to main content

Module filter_compiled

Module filter_compiled 

Source
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:

  1. one HashMap (or BTreeMap) lookup per predicate per row;
  2. one closure indirection per lookup;
  3. 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::Null at a slot position → equivalent to “column not found” in the legacy path: IsNull returns true, every other predicate returns false
  • And / Or are short-circuited per the postfix arity
  • Not flips 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:

  1. Pre-typed values. Filter predicates 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 a CompiledFilter is built.

  2. No implicit casts at eval time. Because types are resolved at plan time, evaluator::evaluate’s implicit-cast step (which consults schema::coercion_spine) adds zero value at row-eval time for ops in FilterOp: Eq, Ne, Lt, Le, Gt, Ge, IsNull, IsNotNull, Between, In, NotIn, Like, NotLike, Contains, StartsWith, EndsWith. The hand-rolled partial_compare_values path is type-safe for these ops given precondition 1.

  3. Parity test guards against drift. compiled_matches_legacy_for_random_filters exercises 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§

CompiledFilter
A filter that has been compiled against a fixed column schema.

Enums§

CompileError
Error returned by CompiledFilter::compile when the filter references a column that is not in the provided schema.
CompiledOp
Single instruction in a CompiledFilter op stream.