jacktengg opened a new pull request, #68093:
URL: https://github.com/apache/doris/pull/68093

   
   ### What problem does this PR solve?
   
   Problem Summary:
   `window_funnel(..., 'increase', ...)` returned a lower level than expected 
when an intermediate condition matched more than once, because the INCREASE 
path of the V2 implementation (`WindowFunnelStateV2::_get_increase`) kept only 
a single state per level and overwrote it unconditionally with the later event. 
The overwriting event is not always able to extend the chain (the timestamps 
have to increase strictly), while the overwritten one still was, so the 
remaining events could no longer be attached to the chain.
   
   Reproduction:
   ```sql
   SELECT window_funnel(10, 'increase', ts, e = 'A', e = 'B', e = 'C') AS inc
   FROM (
       SELECT CAST('2026-01-01 00:00:00' AS DATETIMEV2(6)) AS ts, 'A' AS e
       UNION ALL SELECT CAST('2026-01-01 00:00:01' AS DATETIMEV2(6)), 'B'
       UNION ALL SELECT CAST('2026-01-01 00:00:02' AS DATETIMEV2(6)), 'B'
       UNION ALL SELECT CAST('2026-01-01 00:00:02' AS DATETIMEV2(6)), 'C'
   ) t;
   ```
   Before the fix this returned 2, because `B@2` overwrote `B@1` and the 
strict-increase check then rejected `C@2` (`2 < 2` is false). The valid chain 
is `A@0 -> B@1 -> C@2`.
   
   Root cause:
   For every level the algorithm stored exactly one `(first_ts, last_ts, 
list_idx)` state and replaced it whenever a later event extended the same 
level. Two different states of one level are not interchangeable: the earlier 
one is the only one that can still satisfy the strict increase for an event 
with the same timestamp, while the later one is required to extend an event 
that lies after it. Both have to be kept until one of them is provably 
dominated.
   
   Fix:
   The INCREASE scan now keeps, per level, the most permissive partial chain 
instead of the last one:
   - when several states of a level are reachable, the state with the latest 
chain start is retained, because it expires last in the time-window check and 
every event that can be attached to another state can be attached to it as well;
   - a state is dropped once a state of a higher level has a last timestamp 
that is not greater, because that state can extend every event the lower one 
can extend and already reaches a higher level;
   - each event extends the most permissive eligible state of the previous 
level.
   
   With the fix the statement above returns 3. The default, deduplication and 
fixed modes are untouched, and the new rule was cross-checked against 
`window_funnel_v1` semantics.
   
   ### Release note
   
   Fix `window_funnel` with the `increase` mode returning a too small number of 
levels when an intermediate condition occurs more than once.
   
   ### Check List (For Author)
   
   - Test: Unit Test / Regression test
       - New unit test 
`VWindowFunnelV2Test.testIncreaseModeExtendableIntermediateLevelKept` covering 
`A@0, B@1, B@2, C@2`; all 36 `*WindowFunnel*` unit tests pass.
       - New regression blocks in 
`regression-test/suites/query_p0/aggregate/window_funnel_v2.groovy`; the `.out` 
file was generated with `-forceGenOut` and the suite passed afterwards. The 
final re-run of the suite was blocked by a worktree port re-allocation in the 
test host, the recorded output is unchanged by the follow-up refactoring of the 
fix.
       - The new algorithm was additionally validated against an exhaustive 
search over chain lengths on 80k randomized inputs (conditions 2..6, rows up to 
10, several window sizes).
   - Behavior changed: Yes (see above)
   - Does this need documentation: No
   
   ### What problem does this PR solve?
   
   Issue Number: close #xxx
   
   Related PR: #xxx
   
   Problem Summary:
   
   ### Release note
   
   None
   
   ### Check List (For Author)
   
   - Test <!-- At least one of them must be included. -->
       - [ ] Regression test
       - [ ] Unit Test
       - [ ] Manual test (add detailed scripts or steps below)
       - [ ] No need to test or manual test. Explain why:
           - [ ] This is a refactor/code format and no logic has been changed.
           - [ ] Previous test can cover this change.
           - [ ] No code files have been changed.
           - [ ] Other reason <!-- Add your reason?  -->
   
   - Behavior changed:
       - [ ] No.
       - [ ] Yes. <!-- Explain the behavior change -->
   
   - Does this need documentation?
       - [ ] No.
       - [ ] Yes. <!-- Add document PR link here. eg: 
https://github.com/apache/doris-website/pull/1214 -->
   
   ### Check List (For Reviewer who merge this PR)
   
   - [ ] Confirm the release note
   - [ ] Confirm test cases
   - [ ] Confirm document
   - [ ] Add branch pick label <!-- Add branch pick label that this PR should 
merge into -->
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to