Skip to content

expr: recover pushdown for day-only interval predicates#36706

Draft
antiguru wants to merge 1 commit into
claude/github-issue-9656-4DVQcfrom
claude/github-issue-9656-followup-pushdown
Draft

expr: recover pushdown for day-only interval predicates#36706
antiguru wants to merge 1 commit into
claude/github-issue-9656-4DVQcfrom
claude/github-issue-9656-followup-pushdown

Conversation

@antiguru
Copy link
Copy Markdown
Member

Stacked on top of #36702.

Motivation

The parent PR (#36702) fixes the persist filter-pushdown audit panic by marking add/sub_timestamp{,_tz}_interval as non-monotone in both arguments. That's the right correctness answer (calendar-month arithmetic with day-clamping breaks monotonicity for month-bearing intervals), but it's too conservative for the common case of literal day-only intervals — predicates like t_col - INTERVAL '1' day < literal were a motivating use case for filter pushdown and lose their pushdown= line in EXPLAIN.

Description

Extends SpecialBinary with a second handler variant:

enum SpecialBinaryHandler {
    Override(...),            // existing: replace the spec computation entirely
    DynamicMonotone(...),     // new: compute monotonicity flags from the input specs
}

The DynamicMonotone handler for Add/SubTimestamp{,Tz}Interval inspects the right argument's ResultSpec and returns (true, true) if it is a single-value interval with months == 0, else (false, false). The standard flat_map machinery then either narrows precisely or falls back to anything(). Since the static is_monotone annotation isn't consulted when a SpecialBinary is present, the parent PR's (false, false) annotation is still in effect for any code path that bypasses the special handler — so soundness is preserved.

For Trace (which can't see actual values), the SpecialBinary::pushdownable is set to (true, false). This makes t_col +/- INTERVAL_lit Trace-pushdownable regardless of whether the interval has months; at runtime, ColumnSpecs either narrows or hands back anything() based on the dynamic check, so we may attempt pushdown for a month-bearing literal but the predicate will be sound (it just won't narrow anything for that case).

Also restores the pushdown= lines in test/sqllogictest/filter-pushdown.slt that the parent PR had to drop.

Verification

  • New regression test interpret::tests::test_timestamp_plus_interval_dynamic_monotone covers three scenarios:
    1. t_col - INTERVAL '1' day < lit over a range that includes both matching and non-matching values → interpreter admits both True and False (tight narrowing).
    2. Same predicate over a range entirely after the literal → interpreter rules out True (impossible matches eliminated).
    3. t_col - INTERVAL '1' month < lit (month-bearing) → interpreter admits both outcomes (conservative fallback; soundness preserved).
  • cargo test -p mz-expr --lib — all 52 tests pass.
  • test/sqllogictest/filter-pushdown.slt updated to reflect that pushdown= is restored for t - INTERVAL '1' day predicates.

Known limitations

The recovery only kicks in when the interval is a constant with statically-zero months. Day-only column-valued intervals don't currently get pushdown — that's a smaller win to leave for later.


Generated by Claude Code

@antiguru antiguru force-pushed the claude/github-issue-9656-4DVQc branch from 51e86ed to fa54894 Compare May 24, 2026 11:18
@antiguru antiguru force-pushed the claude/github-issue-9656-followup-pushdown branch from 8650bc0 to 939e4e2 Compare May 24, 2026 11:18
@antiguru antiguru force-pushed the claude/github-issue-9656-4DVQc branch from fa54894 to eb53ce5 Compare May 24, 2026 12:15
The previous commits in this stack marked add/sub_timestamp_interval
(and the tz variants) as non-monotone in both arguments to preserve
correctness in the presence of calendar-month / day-clamping
arithmetic. But that conservative annotation costs pushdown for
common temporal-filter predicates like 't_col - INTERVAL ''1'' day <
literal', which were a motivating use case for filter pushdown in
the first place.

Recovers that pushdown by extending SpecialBinary with a
DynamicMonotone handler: when the interval argument is a literal with
months == 0, the operation reduces to adding a fixed number of
microseconds, which is monotone in both arguments. In that case the
interpreter computes a tight output range; in all other cases it
falls back to anything(), preserving the soundness fix.

The SpecialBinary's pushdownable hint is set to (true, false) so the
Trace pass routes 't_col +/- INTERVAL_lit' predicates through
pushdown regardless of months — at runtime the dynamic check decides
whether to narrow.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants