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

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17654	4258	4144	4144
q2	2029	314	204	204
q3	10300	1459	900	900
q4	4688	477	343	343
q5	7490	856	573	573
q6	189	176	140	140
q7	767	827	627	627
q8	9338	1605	1574	1574
q9	5627	4418	4422	4418
q10	6734	1795	1542	1542
q11	496	352	329	329
q12	721	542	435	435
q13	18080	3412	2769	2769
q14	276	271	246	246
q15	q16	791	787	712	712
q17	1001	913	895	895
q18	6969	5749	5756	5749
q19	1298	1240	1035	1035
q20	774	647	540	540
q21	5913	2684	2484	2484
q22	440	361	302	302
Total cold run time: 101575 ms
Total hot run time: 29961 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4443	4349	4352	4349
q2	297	321	216	216
q3	4597	4905	4437	4437
q4	2057	2159	1364	1364
q5	4447	4299	4508	4299
q6	229	173	129	129
q7	1744	2101	1801	1801
q8	2541	2146	2163	2146
q9	8096	8031	7847	7847
q10	4761	4698	4256	4256
q11	596	409	400	400
q12	785	787	533	533
q13	3308	3505	2975	2975
q14	295	321	285	285
q15	q16	713	748	668	668
q17	1336	1339	1324	1324
q18	7918	7246	7283	7246
q19	1135	1141	1121	1121
q20	2216	2203	1952	1952
q21	5228	4555	4393	4393
q22	512	458	402	402
Total cold run time: 57254 ms
Total hot run time: 52143 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 180801 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 0e4329c7c3c6cdd1b979e498be0640b9cd022149, data reload: false

query5	4340	651	502	502
query6	458	233	212	212
query7	4886	584	337	337
query8	342	203	178	178
query9	8795	4114	4057	4057
query10	478	358	299	299
query11	5933	2334	2163	2163
query12	162	107	102	102
query13	1283	625	440	440
query14	6309	5299	4959	4959
query14_1	4276	4278	4276	4276
query15	228	206	182	182
query16	1016	468	442	442
query17	1136	743	604	604
query18	2524	487	358	358
query19	214	191	159	159
query20	114	113	108	108
query21	231	159	137	137
query22	13642	13526	13314	13314
query23	17458	16606	16260	16260
query23_1	16283	16354	16374	16354
query24	7538	1764	1310	1310
query24_1	1297	1319	1325	1319
query25	566	470	402	402
query26	1346	353	211	211
query27	2550	610	393	393
query28	4447	2037	2009	2009
query29	1082	624	514	514
query30	336	269	234	234
query31	1128	1095	980	980
query32	112	108	59	59
query33	505	303	241	241
query34	1195	1135	674	674
query35	759	771	657	657
query36	1398	1413	1230	1230
query37	156	107	92	92
query38	1880	1688	1641	1641
query39	926	927	884	884
query39_1	866	870	883	870
query40	242	159	140	140
query41	65	64	63	63
query42	101	94	89	89
query43	319	317	297	297
query44	1425	794	783	783
query45	194	192	178	178
query46	1075	1166	708	708
query47	2417	2305	2195	2195
query48	420	393	309	309
query49	581	427	308	308
query50	1070	416	328	328
query51	10728	10681	10869	10681
query52	83	88	75	75
query53	262	286	205	205
query54	274	230	227	227
query55	73	70	64	64
query56	286	291	277	277
query57	1416	1406	1313	1313
query58	297	235	249	235
query59	1573	1650	1429	1429
query60	316	266	240	240
query61	145	150	150	150
query62	694	661	586	586
query63	259	205	210	205
query64	2842	1039	840	840
query65	4900	4786	4749	4749
query66	1848	500	385	385
query67	29540	29327	29210	29210
query68	3154	1632	954	954
query69	404	312	264	264
query70	1079	996	983	983
query71	338	312	306	306
query72	3052	2734	2425	2425
query73	829	844	444	444
query74	5090	4913	4796	4796
query75	2594	2575	2223	2223
query76	2331	1185	782	782
query77	368	389	287	287
query78	12326	12322	11837	11837
query79	1451	1129	720	720
query80	756	534	460	460
query81	488	329	272	272
query82	581	157	120	120
query83	359	320	292	292
query84	276	162	134	134
query85	947	601	497	497
query86	407	303	289	289
query87	1862	1833	1749	1749
query88	3741	2794	2813	2794
query89	456	397	364	364
query90	1923	204	197	197
query91	209	187	154	154
query92	63	59	57	57
query93	1616	1510	980	980
query94	610	352	310	310
query95	786	512	569	512
query96	1070	766	346	346
query97	2742	2692	2540	2540
query98	215	205	199	199
query99	1150	1167	1045	1045
Total cold run time: 265255 ms
Total hot run time: 180801 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.10	0.05	0.05
query3	0.25	0.13	0.14
query4	1.63	0.14	0.14
query5	0.24	0.22	0.22
query6	1.25	1.09	1.08
query7	0.03	0.01	0.00
query8	0.05	0.04	0.04
query9	0.38	0.32	0.31
query10	0.59	0.54	0.54
query11	0.20	0.15	0.15
query12	0.18	0.14	0.14
query13	0.48	0.48	0.47
query14	1.02	1.00	1.00
query15	0.61	0.61	0.60
query16	0.31	0.31	0.32
query17	1.07	1.09	1.12
query18	0.23	0.20	0.22
query19	2.03	1.99	1.90
query20	0.01	0.01	0.01
query21	15.42	0.22	0.13
query22	4.76	0.05	0.05
query23	16.13	0.32	0.12
query24	2.98	0.44	0.32
query25	0.12	0.05	0.04
query26	0.73	0.20	0.16
query27	0.05	0.04	0.03
query28	3.53	0.85	0.52
query29	12.50	3.99	3.20
query30	0.28	0.16	0.15
query31	2.77	0.61	0.33
query32	3.22	0.60	0.49
query33	3.15	3.18	3.27
query34	15.66	4.28	3.51
query35	3.48	3.51	3.53
query36	0.55	0.45	0.42
query37	0.08	0.06	0.06
query38	0.05	0.04	0.04
query39	0.04	0.03	0.03
query40	0.18	0.16	0.16
query41	0.09	0.04	0.03
query42	0.03	0.04	0.03
query43	0.04	0.04	0.04
Total cold run time: 96.51 s
Total hot run time: 24.94 s

ImmutableSet.of(LogicalCTEAnchor.class),
() -> {
List<RewriteJob> rewriteJobs = Lists.newArrayListWithExpectedSize(300);
if (Config.enable_table_stream) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe move config check inside rule?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rule already matches only LogicalOlapTableStreamScan. If such a node exists, it should always be normalized regardless of Config.enable_table_stream. The config controls whether stream tables can be created, but it is not a condition for this normalization rule, so the config check is not needed here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, a rewrite rule first performs pattern matching and only executes its rewrite function after the pattern matches. If no LogicalOlapTableStreamScan exists, this rule is not matched by any plan node and its rewrite logic is never executed.

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

3 participants