Skip to content

Field Pruning

prune_fields removes or projects field-based constraints from an expression tree. Useful when a stored filter contains constraints on fields that are unavailable or irrelevant in a particular execution context.

from therismos import F, prune_fields, FieldSelection, PruneMode

age = F("age", int)
status = F("status")
dept = F("department")

expr = (age > 18) & (status == "active") & (dept == "engineering")

Prune Mode (default)

Removes listed fields — remaining constraints are kept:

result = prune_fields(expr, frozenset({"age"}))
# result: AllExpr(status == "active", dept == "engineering")

RESTRICT vs RELAX

These modes control what happens when all constraints are pruned from a sub-expression:

only_age = age > 18

# RESTRICT (default): no constraint left → exclude records
result = prune_fields(only_age, frozenset({"age"}))
# result: FALSE

# RELAX: no constraint left → include records
result = prune_fields(only_age, frozenset({"age"}), mode=PruneMode.RELAX)
# result: TRUE

Keep Mode

Keep only listed fields, prune everything else:

result = prune_fields(expr, frozenset({"status"}), selection=FieldSelection.KEEP)
# result: status == "active"

Polarity-Aware Substitution Under NOT

The substitution correctly flips semantics when a pruned leaf appears inside a NOT:

expr = ~(age > 18) & (status == "active")

# RESTRICT: age is pruned to FALSE at positive polarity
# NOT(FALSE) → TRUE → TRUE & (status == "active") → status == "active"
result = prune_fields(expr, frozenset({"age"}))
# result: status == "active"