Skip to content

[fix](fe) Fix stream scan normalization and snapshot/reset pruning#65468

Open
yujun777 wants to merge 7 commits into
apache:masterfrom
yujun777:fix-cte-stream-normalize
Open

[fix](fe) Fix stream scan normalization and snapshot/reset pruning#65468
yujun777 wants to merge 7 commits into
apache:masterfrom
yujun777:fix-cte-stream-normalize

Conversation

@yujun777

@yujun777 yujun777 commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close #65469

Related PR:

Problem Summary: This PR fixes two FE issues in the stream scan path.

First, when a stream scan appears inside a CTE, NormalizeOlapTableStreamScan may not be applied on the reused CTE branch, so the stream virtual columns are not lowered consistently and later rewrite steps see the wrong scan shape.

Second, PruneEmptyPartition uses selectNonEmptyPartitionIds before stream scan normalization. For stream@snapshot and stream@reset, the old stream-wrapper pruning logic still used incremental stream visibility semantics, so a stream with no new delta could be pruned as empty even though snapshot/reset should still read snapshot data.

This change keeps stream read mode as explicit logical scan state, threads that mode through LogicalCatalogRelation into partition pruning, preserves stream scan helper predicates on the logical node, and lets snapshot/reset pruning follow the base table path while incremental reads still use stream delta visibility. It also keeps stream scan normalization behavior consistent when the scan is referenced through a CTE.

Release note

None

Check List (For Author)

  • Test: Unit Test
    • ./run-fe-ut.sh --run org.apache.doris.nereids.trees.plans.ExplainTableStreamPlanTest
  • Behavior changed: Yes (stream scans under CTE are normalized consistently, and stream@snapshot / stream@reset are no longer pruned by incremental stream visibility)
  • Does this need documentation: No

yujun777 added 3 commits July 10, 2026 18:36
…and normalize after CTE inline

Two fixes for LogicalOlapTableStreamScan handling in Nereids planner:

1. Override withVirtualColumns to return LogicalOlapTableStreamScan
   instead of LogicalOlapScan, preventing type downgrade during
   LogicalPlanDeepCopier.deepCopy used by CTEInline.

2. Move NormalizeOlapTableStreamScan execution to after CTE inline
   so StreamScans exposed by CTE expansion get normalized. Previously
   it ran inside notTraverseChildrenOf(CTEAnchor) which blocked
   traversal into CTE producers.

This fixes CTE+stream hidden column queries and IVM incremental
refresh failures caused by un-normalized stream scans.
Issue Number: close apache#65339

Related PR:

Problem Summary: Normalize stream scan rules were executed in a late CTE-related rewrite topic, which could be skipped in trees with CTE-related traversal constraints, causing delta/rewrite paths to miss synthetic change_type/version project aliases and fail when buildDmlFactorExpr accessed hidden stream columns. This moves  into the early table/physical optimization topic after partition pruning and removes the separate late topic from , and updates regression baseline for  to the fixed incremental result behavior.

None

- Test: Regression test / Unit Test / Manual test / No need to test (with reason)
    - test_ivm_basic_mtmv (baseline .out updated)
- Behavior changed: Yes (CTE stream-scan normalization now runs in the proper rewrite phase)
- Does this need documentation: No
@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@yujun777 yujun777 changed the title [fix](binlog) normalize cte stream scan before operative column derive [fix](binlog) fix stream scan normalization under cte Jul 10, 2026
@yujun777

Copy link
Copy Markdown
Contributor Author

run buildall

@yujun777 yujun777 changed the title [fix](binlog) fix stream scan normalization under cte [fix](stream) fix stream scan normalization under cte Jul 10, 2026
@yujun777

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 29280 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 44b0ee46ffa45649efeda3d1c3d432a88330d382, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17648	4176	4099	4099
q2	2083	318	201	201
q3	10349	1417	822	822
q4	4697	484	336	336
q5	7542	870	562	562
q6	186	182	134	134
q7	759	830	614	614
q8	9892	1702	1583	1583
q9	6224	4408	4409	4408
q10	6873	1787	1515	1515
q11	512	338	300	300
q12	769	560	426	426
q13	18146	3826	2701	2701
q14	272	263	240	240
q15	q16	796	789	706	706
q17	1032	946	1161	946
q18	6795	5758	5410	5410
q19	1291	1284	1108	1108
q20	726	675	525	525
q21	5832	2603	2341	2341
q22	421	357	303	303
Total cold run time: 102845 ms
Total hot run time: 29280 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4495	4384	4513	4384
q2	320	334	218	218
q3	4625	4955	4382	4382
q4	2068	2152	1380	1380
q5	4594	4468	4579	4468
q6	247	185	126	126
q7	2320	1873	1618	1618
q8	2685	2183	2166	2166
q9	7955	7931	8029	7931
q10	4806	4704	4291	4291
q11	711	400	376	376
q12	793	824	557	557
q13	3228	3626	2994	2994
q14	315	297	291	291
q15	q16	722	738	644	644
q17	1357	1382	1375	1375
q18	8142	7186	6730	6730
q19	1115	1050	1067	1050
q20	2207	2219	1926	1926
q21	5323	4565	4342	4342
q22	514	464	407	407
Total cold run time: 58542 ms
Total hot run time: 51656 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 180182 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 44b0ee46ffa45649efeda3d1c3d432a88330d382, data reload: false

query5	4360	629	512	512
query6	485	228	219	219
query7	4863	622	333	333
query8	359	190	177	177
query9	8794	4124	4107	4107
query10	475	386	325	325
query11	5961	2348	2132	2132
query12	164	104	104	104
query13	1274	590	440	440
query14	6241	5373	4956	4956
query14_1	4303	4274	4335	4274
query15	219	217	182	182
query16	1051	495	453	453
query17	1150	750	609	609
query18	2617	488	356	356
query19	226	212	155	155
query20	114	113	109	109
query21	228	163	134	134
query22	13616	13672	13518	13518
query23	17447	16607	16167	16167
query23_1	16199	16361	16246	16246
query24	7477	1744	1301	1301
query24_1	1320	1338	1316	1316
query25	580	491	403	403
query26	1329	357	216	216
query27	2599	607	369	369
query28	4473	2033	2020	2020
query29	1092	643	506	506
query30	337	265	228	228
query31	1137	1096	984	984
query32	122	70	63	63
query33	544	334	268	268
query34	1187	1149	657	657
query35	778	791	678	678
query36	1413	1361	1226	1226
query37	166	124	105	105
query38	1893	1689	1682	1682
query39	942	914	887	887
query39_1	887	877	868	868
query40	250	167	146	146
query41	73	71	70	70
query42	134	100	94	94
query43	330	336	287	287
query44	1470	793	762	762
query45	190	184	182	182
query46	1104	1232	764	764
query47	2512	2276	2209	2209
query48	410	411	305	305
query49	591	424	316	316
query50	1019	421	350	350
query51	10872	10813	10830	10813
query52	92	88	75	75
query53	250	286	199	199
query54	282	234	235	234
query55	74	71	66	66
query56	292	284	299	284
query57	1442	1420	1310	1310
query58	303	271	232	232
query59	1584	1617	1377	1377
query60	304	270	256	256
query61	157	145	151	145
query62	691	636	593	593
query63	242	203	209	203
query64	2831	1025	840	840
query65	4900	4789	4754	4754
query66	1799	506	392	392
query67	29329	29393	29308	29308
query68	3048	1514	952	952
query69	421	300	268	268
query70	1052	965	953	953
query71	351	325	309	309
query72	3057	2663	2402	2402
query73	869	754	446	446
query74	5124	4948	4781	4781
query75	2619	2575	2238	2238
query76	2331	1175	762	762
query77	350	380	287	287
query78	12437	12245	11652	11652
query79	1489	1189	767	767
query80	1284	540	453	453
query81	532	339	286	286
query82	612	159	127	127
query83	368	325	287	287
query84	294	161	129	129
query85	968	599	483	483
query86	455	292	278	278
query87	1821	1818	1744	1744
query88	3713	2821	2786	2786
query89	526	405	367	367
query90	1900	207	200	200
query91	204	192	161	161
query92	65	63	58	58
query93	1696	1541	1035	1035
query94	753	369	317	317
query95	787	479	581	479
query96	1031	782	361	361
query97	2692	2691	2543	2543
query98	211	205	198	198
query99	1137	1175	1036	1036
Total cold run time: 266504 ms
Total hot run time: 180182 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 25.04 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 44b0ee46ffa45649efeda3d1c3d432a88330d382, data reload: false

query1	0.01	0.01	0.01
query2	0.10	0.05	0.05
query3	0.26	0.14	0.13
query4	1.61	0.14	0.14
query5	0.23	0.25	0.25
query6	1.24	1.09	1.04
query7	0.04	0.01	0.01
query8	0.06	0.04	0.04
query9	0.39	0.31	0.31
query10	0.54	0.55	0.54
query11	0.19	0.14	0.14
query12	0.19	0.14	0.14
query13	0.46	0.46	0.48
query14	1.00	1.00	1.00
query15	0.64	0.59	0.58
query16	0.30	0.32	0.32
query17	1.09	1.08	1.11
query18	0.22	0.21	0.21
query19	2.01	1.97	1.96
query20	0.01	0.02	0.01
query21	15.43	0.22	0.13
query22	4.85	0.06	0.05
query23	16.10	0.31	0.12
query24	3.04	0.41	0.32
query25	0.12	0.05	0.04
query26	0.80	0.20	0.14
query27	0.06	0.04	0.03
query28	3.58	0.93	0.56
query29	12.51	4.14	3.30
query30	0.28	0.15	0.15
query31	2.77	0.61	0.30
query32	3.23	0.60	0.48
query33	3.14	3.26	3.17
query34	15.61	4.19	3.50
query35	3.52	3.53	3.54
query36	0.56	0.42	0.42
query37	0.09	0.07	0.07
query38	0.05	0.04	0.04
query39	0.04	0.03	0.03
query40	0.18	0.17	0.15
query41	0.08	0.03	0.02
query42	0.04	0.03	0.03
query43	0.05	0.04	0.04
Total cold run time: 96.72 s
Total hot run time: 25.04 s

yujun777 added a commit to yujun777/doris that referenced this pull request Jul 10, 2026
### What problem does this PR solve?

Issue Number: close apache#65469

Related PR: apache#65468

Problem Summary: Several IVM aggregate regression cases used `REFRESH ... COMPLETE` before validating later incremental behavior. COMPLETE refresh does not advance the stream consumption offset, so the following `REFRESH ... INCREMENTAL` could re-consume historical changes and produce results that no longer matched the intended test point. This change updates the affected aggregate suites to establish the baseline with an initial incremental refresh, keeps the later COMPLETE refreshes that compare against snapshot ground truth, and regenerates the `.out` files so the expected results match the corrected stream-offset behavior.

### Release note

None

### Check List (For Author)

- Test: Regression test
    - `./run-regression-test.sh --run -d mtmv_p0 -s test_ivm_agg_2,test_ivm_agg_3,test_ivm_agg_4,test_ivm_agg_6 -forceGenOut --no-parallel`
- Behavior changed: Yes (the affected regression cases now validate incremental results after establishing stream offsets with incremental refresh)
- Does this need documentation: No
yujun777 added a commit to yujun777/doris that referenced this pull request Jul 10, 2026
### What problem does this PR solve?

Issue Number: close apache#65469

Related PR: apache#65468

Problem Summary: Several IVM aggregate regression cases used `REFRESH ... COMPLETE` before validating later incremental behavior. COMPLETE refresh does not advance the stream consumption offset, so the following `REFRESH ... INCREMENTAL` could re-consume historical changes and produce results that no longer matched the intended test point. This change updates the affected aggregate suites to establish the baseline with an initial incremental refresh, keeps the later COMPLETE refreshes that compare against snapshot ground truth, and regenerates the `.out` files so the expected results match the corrected stream-offset behavior.

### Release note

None

### Check List (For Author)

- Test: Regression test
    - `./run-regression-test.sh --run -d mtmv_p0 -s test_ivm_agg_2,test_ivm_agg_3,test_ivm_agg_4,test_ivm_agg_6 -forceGenOut --no-parallel`
- Behavior changed: Yes (the affected regression cases now validate incremental results after establishing stream offsets with incremental refresh)
- Does this need documentation: No
### What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary: Add a regression case for min_delta stream queries that project the stream change type column through a CTE and reuse that CTE twice in a self-join. The case verifies the output through an auto-generated .out file and keeps the existing stream regression coverage intact.

### Release note

None

### Check List (For Author)

- Test: Regression test

    - ./run-regression-test.sh --run -d table_stream_p0 -s test_min_delta_stream

- Behavior changed: No

- Does this need documentation: No
@yujun777

Copy link
Copy Markdown
Contributor Author

run buildall

### What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary: Stream scan planning had split state for snapshot and reset, while partition pruning still depended on table-specific non-empty checks that did not receive stream read semantics. This made the stream planning path harder to reason about and caused snapshot/reset handling to diverge from incremental reads. This change replaces the dual boolean state on logical stream scan with a single StreamReadMode enum, threads the optional read mode through LogicalCatalogRelation into selectNonEmptyPartitionIds, and lets the stream wrapper choose incremental pruning from stream.hasData while delegating snapshot/reset pruning to the base table path. The result keeps the read-mode semantics continuous from binding through rewrite and pruning, while preserving the convenience isSnapshot/isReset/isIncremental helpers on the scan node.

### Release note

None

### Check List (For Author)

- Test: Unit Test
    - ./run-fe-ut.sh --run org.apache.doris.nereids.trees.plans.ExplainTableStreamPlanTest
- Behavior changed: Yes (stream scan snapshot/reset partition pruning now follows explicit read-mode plumbing instead of split boolean flags)
- Does this need documentation: No
@yujun777 yujun777 changed the title [fix](stream) fix stream scan normalization under cte [fix](fe) Fix stream scan normalization and snapshot/reset pruning Jul 11, 2026
@yujun777

Copy link
Copy Markdown
Contributor Author

run buildall

### What problem does this PR solve?

Issue Number: None

Related PR: apache#65468

Problem Summary: This follow-up keeps the stream scan helper implementation order aligned with the surrounding builder methods by moving  after  in . The change is code organization only and does not alter semantics.

### Release note

None

### Check List (For Author)

- Test: No need to test (with reason)
    - Method order only, no logic change
- Behavior changed: No
- Does this need documentation: No
@yujun777

Copy link
Copy Markdown
Contributor Author

run buildall

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.

[Bug] Stream scan under CTE may skip NormalizeOlapTableStreamScan

2 participants