Skip to content

[fix](policy) Enforce row policies on MOW time travel - #67783

Merged
morrySnow merged 5 commits into
apache:masterfrom
morrySnow:fix/mow-time-travel-row-policy
Sep 17, 2026
Merged

morrySnow merged 5 commits into
apache:masterfrom
morrySnow:fix/mow-time-travel-row-policy

Conversation

@morrySnow

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

A row policy can be bypassed by a merge-on-write time-travel query. The rewrite replaces the original relation with a subquery alias over a union of the base-table scan and the row-binlog scan. The policy marker left above that composite plan is then removed because policy analysis only recognizes relation-shaped children, so neither union branch receives the row filter.

This can be reproduced by creating a merge-on-write table with historical row binlog enabled, updating and deleting rows after a captured commit TSO, assigning restrictive and permissive row policies to a non-privileged user, and querying the captured version as that user. Rows rejected by the policy are returned from both the base branch and the before-image branch.

What is changed?

  • Put an independent policy-check node directly above both scans produced by the merge-on-write time-travel rewrite, before branch-specific filters and projections are added.
  • Resolve authorization and materialized-view refresh policy ownership through every OlapTableWrapper layer to the original table. Policy expressions and data masks are still bound against each wrapper scan's own output slots.
  • Add unit coverage for a renamed wrapper and recursively nested wrappers.
  • Add an end-to-end regression that proves both the base branch and the row-binlog branch enforce the combined row policies.

Tests

  • CheckRowPolicyTest: 10 tests passed.
  • test_mow_time_travel_row_policy: passed.
  • test_time_travel_mow: passed.
  • FE build with Checkstyle: passed.

@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?

@morrySnow

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 92.86% (13/14) 🎉
Increment coverage report
Complete coverage report

@morrySnow
morrySnow marked this pull request as draft September 11, 2026 05:29
@morrySnow
morrySnow force-pushed the fix/mow-time-travel-row-policy branch from 9f36362 to 0aedb2b Compare September 11, 2026 06:41
@morrySnow

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17590	3101	3094	3094
q2	2089	245	218	218
q3	10288	971	520	520
q4	4673	248	200	200
q5	7688	578	376	376
q6	139	114	94	94
q7	545	494	386	386
q8	9242	885	879	879
q9	3466	2398	2393	2393
q10	6498	862	724	724
q11	399	207	178	178
q12	630	257	205	205
q13	18127	1530	1153	1153
q14	161	153	141	141
q15	q16	453	395	368	368
q17	1376	876	830	830
q18	3029	2270	2234	2234
q19	1297	883	683	683
q20	378	283	198	198
q21	5624	1626	1828	1626
q22	326	275	232	232
Total cold run time: 94018 ms
Total hot run time: 16732 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3458	3363	3408	3363
q2	501	387	371	371
q3	2237	2266	2214	2214
q4	1187	1168	894	894
q5	2165	2139	2092	2092
q6	168	118	90	90
q7	1002	876	895	876
q8	1595	1394	1427	1394
q9	3084	3075	3060	3060
q10	1876	1802	1627	1627
q11	355	274	250	250
q12	458	426	342	342
q13	1476	1525	1178	1178
q14	182	193	170	170
q15	q16	405	389	360	360
q17	3549	3238	3286	3238
q18	4805	4370	4728	4370
q19	857	878	897	878
q20	994	974	826	826
q21	3896	3148	3216	3148
q22	401	338	323	323
Total cold run time: 34651 ms
Total hot run time: 31064 ms

@hello-stephen

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

query5	4286	409	324	324
query6	399	136	129	129
query7	4966	414	243	243
query8	295	138	121	121
query9	8694	2871	2861	2861
query10	399	219	193	193
query11	5409	1044	930	930
query12	114	72	68	68
query13	1194	435	351	351
query14	6086	2175	2070	2070
query14_1	1975	1971	1950	1950
query15	183	119	109	109
query16	907	338	365	338
query17	797	446	373	373
query18	2333	329	235	235
query19	164	140	108	108
query20	77	71	73	71
query21	203	100	88	88
query22	5525	5293	5257	5257
query23	6648	6236	5956	5956
query23_1	6113	6253	5917	5917
query24	7283	1127	752	752
query24_1	744	773	798	773
query25	434	304	261	261
query26	1226	238	136	136
query27	2778	421	258	258
query28	4678	1491	1480	1480
query29	940	469	355	355
query30	252	159	131	131
query31	831	401	330	330
query32	131	78	78	78
query33	463	225	186	186
query34	995	841	479	479
query35	405	401	349	349
query36	572	542	539	539
query37	122	82	72	72
query38	1045	835	819	819
query39	495	476	483	476
query39_1	447	450	478	450
query40	198	94	77	77
query41	53	52	51	51
query42	74	68	71	68
query43	240	240	210	210
query44	974	536	540	536
query45	105	104	109	104
query46	734	828	514	514
query47	754	746	696	696
query48	299	290	215	215
query49	526	241	193	193
query50	769	268	203	203
query51	8046	7830	8077	7830
query52	77	66	64	64
query53	196	209	154	154
query54	231	167	148	148
query55	89	60	64	60
query56	190	154	173	154
query57	696	696	675	675
query58	194	170	161	161
query59	1234	1211	1114	1114
query60	223	183	172	172
query61	140	107	110	107
query62	346	208	192	192
query63	171	147	145	145
query64	2697	718	612	612
query65	1642	1651	1573	1573
query66	1846	256	224	224
query67	9844	9720	9366	9366
query68	3019	1183	759	759
query69	342	227	198	198
query70	673	617	614	614
query71	258	178	169	169
query72	2278	1633	1511	1511
query73	640	623	333	333
query74	1982	1221	1159	1159
query75	1175	1108	955	955
query76	2366	710	537	537
query77	257	247	199	199
query78	4091	3730	3332	3332
query79	2332	787	562	562
query80	1604	317	265	265
query81	487	156	136	136
query82	866	130	94	94
query83	276	205	186	186
query84	307	106	84	84
query85	776	340	281	281
query86	390	179	174	174
query87	1018	966	893	893
query88	2797	2104	2090	2090
query89	287	195	172	172
query90	1967	129	117	117
query91	124	114	94	94
query92	74	70	62	62
query93	1476	1053	725	725
query94	642	250	222	222
query95	515	262	296	262
query96	790	535	259	259
query97	1032	1074	966	966
query98	135	135	130	130
query99	419	340	307	307
Total cold run time: 178024 ms
Total hot run time: 81249 ms

@hello-stephen

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

query1	0.01	0.00	0.01
query2	0.07	0.04	0.03
query3	0.25	0.12	0.11
query4	1.60	0.11	0.10
query5	0.18	0.16	0.15
query6	1.26	0.67	0.69
query7	0.03	0.01	0.00
query8	0.05	0.03	0.03
query9	0.29	0.22	0.21
query10	0.34	0.34	0.34
query11	0.17	0.11	0.11
query12	0.14	0.13	0.12
query13	0.31	0.30	0.31
query14	0.44	0.44	0.44
query15	0.36	0.36	0.36
query16	0.20	0.21	0.22
query17	0.62	0.69	0.67
query18	0.18	0.16	0.16
query19	1.17	1.18	1.18
query20	0.02	0.01	0.01
query21	15.46	0.17	0.12
query22	5.06	0.04	0.04
query23	16.20	0.26	0.10
query24	2.98	0.33	0.25
query25	0.11	0.03	0.03
query26	0.78	0.16	0.12
query27	0.04	0.03	0.02
query28	3.63	0.55	0.29
query29	12.43	3.18	2.60
query30	0.24	0.11	0.12
query31	2.75	0.37	0.17
query32	3.54	0.31	0.23
query33	1.44	1.46	1.55
query34	15.38	2.14	1.77
query35	1.73	1.73	1.73
query36	0.47	0.28	0.28
query37	0.06	0.04	0.04
query38	0.05	0.03	0.03
query39	0.03	0.03	0.02
query40	0.11	0.07	0.07
query41	0.08	0.03	0.02
query42	0.04	0.02	0.02
query43	0.03	0.03	0.03
Total cold run time: 90.33 s
Total hot run time: 14.75 s

@morrySnow
morrySnow marked this pull request as ready for review September 12, 2026 08:18
@morrySnow

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

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.

Requesting changes because the new MOW time-travel policy placement leaves two authorization failures.

Critical checkpoint conclusions:

  • Goal/correctness/security: native row filters are exercised on both reconstructed branches, but ordinary plugin data masks can be eliminated and expose raw historical values. The two branches also resolve live policy state independently, so a policy transition can produce a mixed result whose SQL-cache proof records only the later policy. Both affect an in-scope restricted SQL user.
  • Scope/parallel paths: recursive OlapTableWrapper unwrapping is correct for current wrapper schemas. DUP time travel, direct @incr, ordinary scans, MV refresh, no-policy, and root/admin paths were traced without another distinct defect.
  • Concurrency/lifecycle/configuration/compatibility: the policy-DDL/plugin-refresh interleaving is covered by the inline cache finding. No separate lifecycle, configuration, persistence/edit-log, FE-BE protocol, storage-format, or rolling-upgrade issue is introduced.
  • Tests: the new regression covers native restrictive/permissive row filters across base and binlog branches, but it has no data-mask case and does not follow the required generated-oracle/post-test-state rules. The author reports unit, regression, and checkstyle results; this review is static-only and did not independently run builds or tests, as required by the review environment.
  • Performance/observability: duplicate provider work shares the mixed-policy root cause and remedy; no separate performance or observability blocker was substantiated.

No additional user review focus was provided. The review converged after two rounds, with all round-two reviewers returning NO_NEW_VALUABLE_FINDINGS beyond the three inline comments.

Comment thread regression-test/suites/time_travel_p0/test_mow_time_travel_row_policy.groovy Outdated
### What problem does this PR solve?

Issue Number: N/A

Related PR: apache#67783

Problem Summary: MOW time-travel branch projections captured raw scan slots before row policies and data masks were expanded. Later project merging could bypass the mask in either the base-scan or row-binlog branch. The regression also asserted results inline and deleted its state instead of using the repository oracle and cleanup contract. Build visible branch outputs as unbound slots so they bind to post-policy outputs, cover both branches, and use a generated regression oracle while retaining the final test state.

### Release note

MOW time-travel queries now preserve data masking in both union branches.

### Check List (For Author)

- Test:
    - Unit Test: CheckRowPolicyTest (11 tests)
    - Regression test: test_mow_time_travel_row_policy
    - FE build with Checkstyle
- Behavior changed: Yes (masked values remain masked for MOW time-travel queries)
- Does this need documentation: No
@morrySnow

Copy link
Copy Markdown
Contributor Author

run buildall

@morrySnow

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

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.

Requesting changes for one remaining MOW time-travel data-mask ordering defect.

Critical checkpoint conclusions:

  • Goal/data correctness/security: the change now enforces native row policies on both reconstruction sources and preserves ordinary movable visible-column masks, but it does not safely handle every supported data mask because reconstruction filters can remain above the mask project. This affects an in-scope restricted SQL user.
  • Scope/clarity and parallel paths: the five-file change is focused. Recursive wrapper unwrapping, MV-refresh identity, union output order/types and qualifiers, and ordinary, DUP, direct @incr, partition/tablet/index, hint, and sample paths were traced without another distinct defect.
  • Concurrency/lifecycle/configuration: no new threads, locks, special static lifecycle, or production configuration are introduced. The mixed live-policy/SQL-cache snapshot race remains unresolved in existing discussion 4002131610 and is not reposted.
  • Compatibility/persistence/writes/FE-BE variables: there is no storage-format, protocol, symbol, EditLog, transaction/write, rolling-upgrade, or new FE-BE variable change.
  • Conditions/error behavior: the inline finding covers both observable failure modes from the same marker-placement root cause; no other conditional or silent-error path was substantiated.
  • Tests/results: the ordered regression correctly proves row-policy enforcement on both branches, and the unit test proves movable visible-mask retention, but neither covers a non-movable mask or an exact hidden-control-column mask. Exact-head FE UT evidence showed two failures in unrelated unchanged OSS-HDFS and Iceberg tests. This review was static-only; no build or test was independently run, as required by the review environment.
  • Performance/observability/memory/nullability: duplicate provider work belongs to the already-fenced cache-snapshot issue. No separate performance or observability blocker was found; this FE-only change introduces no BE memory or nullable handling.

No additional user review focus was supplied. The review converged after two rounds; both normal Round 2 reviewers and the separate risk reviewer returned NO_NEW_VALUABLE_FINDINGS beyond the one inline comment.

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17559	3022	3007	3007
q2	2093	253	215	215
q3	10249	855	495	495
q4	4669	251	199	199
q5	7677	603	387	387
q6	135	114	93	93
q7	530	525	381	381
q8	9224	932	871	871
q9	3443	2431	2391	2391
q10	6490	839	710	710
q11	395	192	181	181
q12	609	258	198	198
q13	18135	1588	1154	1154
q14	164	156	137	137
q15	q16	437	399	371	371
q17	1387	889	823	823
q18	3095	2239	2232	2232
q19	1244	872	795	795
q20	377	278	196	196
q21	5593	1585	1825	1585
q22	323	267	227	227
Total cold run time: 93828 ms
Total hot run time: 16648 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3394	3313	3281	3281
q2	508	396	377	377
q3	2218	2281	2179	2179
q4	1177	1157	891	891
q5	2163	2137	2094	2094
q6	170	117	85	85
q7	1102	897	894	894
q8	1579	1383	1392	1383
q9	3135	3091	3075	3075
q10	1890	1787	1611	1611
q11	352	269	249	249
q12	457	430	338	338
q13	1485	1531	1155	1155
q14	174	171	166	166
q15	q16	390	395	355	355
q17	3587	3325	3255	3255
q18	4852	4385	4740	4385
q19	874	806	925	806
q20	1013	970	843	843
q21	3836	3093	3269	3093
q22	392	383	323	323
Total cold run time: 34748 ms
Total hot run time: 30838 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 82140 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 6afc961fdaa3e1f64213133eac520e608b4c8c4a, data reload: false

query5	4239	424	344	344
query6	387	144	129	129
query7	4920	428	237	237
query8	288	131	137	131
query9	8695	2996	2984	2984
query10	394	220	178	178
query11	5392	1041	924	924
query12	124	72	69	69
query13	1197	440	326	326
query14	6049	2205	2096	2096
query14_1	1980	1931	1937	1931
query15	173	119	107	107
query16	900	303	344	303
query17	772	438	342	342
query18	2318	312	237	237
query19	157	127	102	102
query20	70	68	72	68
query21	194	108	86	86
query22	5350	5352	5190	5190
query23	6659	6268	5942	5942
query23_1	6324	6068	6173	6068
query24	7318	1081	744	744
query24_1	781	786	793	786
query25	411	275	235	235
query26	1207	237	126	126
query27	2782	414	247	247
query28	4703	1557	1580	1557
query29	933	441	363	363
query30	244	159	132	132
query31	819	400	331	331
query32	126	82	76	76
query33	468	221	191	191
query34	992	818	490	490
query35	408	400	364	364
query36	575	597	557	557
query37	127	84	75	75
query38	1005	847	840	840
query39	500	502	453	453
query39_1	473	511	474	474
query40	202	94	80	80
query41	58	56	56	56
query42	75	73	74	73
query43	240	243	213	213
query44	1001	545	554	545
query45	115	108	102	102
query46	795	827	540	540
query47	767	759	715	715
query48	294	328	225	225
query49	560	252	200	200
query50	722	267	200	200
query51	8092	8057	8044	8044
query52	71	68	68	68
query53	191	202	153	153
query54	214	174	158	158
query55	84	74	60	60
query56	207	192	179	179
query57	804	706	643	643
query58	185	161	155	155
query59	1207	1230	1155	1155
query60	238	178	165	165
query61	124	105	110	105
query62	346	205	180	180
query63	168	135	138	135
query64	2696	683	621	621
query65	1694	1602	1579	1579
query66	1809	259	209	209
query67	9758	9669	9627	9627
query68	2783	1157	782	782
query69	328	230	204	204
query70	666	648	614	614
query71	255	179	172	172
query72	2290	1654	1482	1482
query73	656	586	337	337
query74	1566	1224	1136	1136
query75	1175	1106	960	960
query76	2282	690	507	507
query77	250	266	221	221
query78	3871	3648	3216	3216
query79	2837	858	609	609
query80	1551	340	270	270
query81	494	158	132	132
query82	612	120	97	97
query83	276	215	225	215
query84	294	114	89	89
query85	802	352	285	285
query86	394	177	172	172
query87	1010	962	888	888
query88	2875	2151	2128	2128
query89	283	199	179	179
query90	1943	130	130	130
query91	131	119	97	97
query92	80	62	70	62
query93	1561	1146	686	686
query94	635	244	236	236
query95	520	240	230	230
query96	820	570	278	278
query97	1068	1075	1054	1054
query98	173	148	137	137
query99	418	347	317	317
Total cold run time: 177489 ms
Total hot run time: 82140 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.08	0.03	0.04
query3	0.24	0.10	0.11
query4	1.60	0.11	0.11
query5	0.17	0.17	0.16
query6	1.25	0.69	0.68
query7	0.03	0.00	0.00
query8	0.04	0.04	0.03
query9	0.29	0.21	0.20
query10	0.33	0.33	0.34
query11	0.16	0.11	0.12
query12	0.14	0.12	0.12
query13	0.31	0.31	0.31
query14	0.45	0.45	0.44
query15	0.36	0.34	0.35
query16	0.22	0.23	0.22
query17	0.71	0.70	0.72
query18	0.19	0.16	0.16
query19	1.20	1.12	1.11
query20	0.02	0.01	0.01
query21	15.44	0.15	0.12
query22	5.07	0.04	0.05
query23	16.19	0.25	0.10
query24	3.00	0.33	0.24
query25	0.11	0.03	0.02
query26	0.76	0.17	0.12
query27	0.04	0.03	0.04
query28	3.61	0.59	0.28
query29	12.40	3.15	2.53
query30	0.26	0.12	0.11
query31	2.76	0.36	0.17
query32	3.54	0.32	0.24
query33	1.52	1.57	1.60
query34	15.37	2.20	1.78
query35	1.74	1.75	1.72
query36	0.45	0.28	0.28
query37	0.06	0.04	0.04
query38	0.04	0.03	0.03
query39	0.03	0.03	0.02
query40	0.11	0.08	0.07
query41	0.08	0.02	0.03
query42	0.03	0.02	0.03
query43	0.03	0.03	0.02
Total cold run time: 90.44 s
Total hot run time: 14.74 s

### What problem does this PR solve?\n\nIssue Number: N/A\n\nRelated PR: apache#67783\n\nProblem Summary: MOW time-travel reconstruction predicates were built above LogicalCheckPolicy. Expanding a non-movable data mask therefore evaluated the mask before commit-TSO, delete-sign, and binlog-operation filters, and masks on hidden control columns could also replace the ExprIds referenced by those parent filters. Wrap each complete reconstruction filter chain in LogicalCheckPolicy and let CheckPolicy absorb every filter in the chain below the mask project. The unit test covers a non-movable assert_true mask and masks the hidden reconstruction columns as well.\n\n### Release note\n\nMOW time-travel reconstruction filters now run before row-policy data masks.\n\n### Check List (For Author)\n\n- Test:\n    - Unit Test: CheckRowPolicyTest (11 tests)\n    - FE build with Checkstyle\n- Behavior changed: Yes (time-travel-only reconstruction predicates execute below policy masks)\n- Does this need documentation: No
@morrySnow

Copy link
Copy Markdown
Contributor Author

run buildall

@morrySnow

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

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.

Requesting changes for three exact-head correctness failures in MOW time travel.

Critical checkpoint conclusions:

  • Goal/data correctness/security: the change enforces ordinary visible-column row policies and preserves masks on both reconstructed branches, but it does not fully accomplish the goal. A valid error-raising row policy can execute on rows outside the historical image; an accepted origin-hidden-column policy cannot bind on the row-binlog branch; and a legal dotted column name is corrupted by the new projection alias. The first two fail closed rather than bypassing RBAC. The still-present mixed-policy/cache-proof leak is already hard-fenced by discussion 4002131610 and is not reposted.
  • Scope/clarity/parallel paths/conditions: the six-file change is focused. Both MOW branches, ordinary unique-key filtering, DUP time travel, direct @incr, views/export, MV refresh, aliases, partitions/tablets, and the widened filter loop were traced. No fourth distinct defect was found.
  • Concurrency/lifecycle/configuration: no new threads, locks, production configuration, special static initialization, or resource lifecycle are introduced. The only mutable policy interleaving is the existing duplicate-fenced discussion above.
  • Compatibility/persistence/writes/FE-BE variables: there is no function-symbol, storage-format, EditLog, transaction/write, FE-BE protocol/variable, or rolling-upgrade change.
  • Tests/results: the generated .out matches its two labeled ordered queries, and the unit/regression additions cover the ordinary visible-policy and mask-placement happy paths. They do not cover an error-raising row policy, an origin-only hidden policy slot, or a dotted primitive column. The author reports the exact-head CheckRowPolicyTest at 11/11; this review was static-only and did not independently run builds or tests, as required by the review environment.
  • Error handling/data correctness: the three inline comments identify deterministic analysis/execution failures with concrete plan and value cases. No ignored status, silent fallback, or additional MoW version-boundary defect was found.
  • Observability/performance/memory/nullability: no new logging or metrics are needed for this planner-only change. Duplicate provider work shares the already-fenced snapshot issue; no separate performance concern was substantiated. This FE-only diff adds no BE memory or nullable handling.
  • Other issues: no additional user review focus was provided. After two full rounds, both normal round-two reviewers and the separate risk reviewer returned NO_NEW_VALUABLE_FINDINGS beyond the three inline comments and existing duplicates.

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 14.63% (18/123) 🎉
Increment coverage report
Complete coverage report

@morrySnow

Copy link
Copy Markdown
Contributor Author

run buildall

@morrySnow

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

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.

Requesting changes at exact head cbb2b9f20230984421a63f51513fa3996f9a11a4.

No new inline comment is added in this pass: the remaining substantiated issues are already covered by existing inline threads, which are hard duplicate fences:

Checkpoint conclusions:

  • Goal and evidence: the ordinary visible-column path now applies row filters/data masks to both MOW historical branches, keeps reconstruction filters below mask projects, preserves raw dotted names, and has focused FE plan-shape plus ordered regression coverage. The three unresolved cases above prevent a complete correctness/security conclusion.
  • Scope and parallel paths: the production change is focused. I traced both union branches, DUP time travel, direct @incr, wrapper/MV-refresh identity, set-operation binding, partition/tablet propagation, and qualified/unqualified output binding. No additional unfenced issue was found.
  • Concurrency: planner nodes add no locks or shared lifecycle state, but authorization state can change between the two independent branch lookups; that is the first blocking existing thread above.
  • Lifecycle, configuration, compatibility, and persistence: there is no new production configuration, long-lived owner, edit-log/persistence path, transaction/write path, FE-BE field, wire/storage format, or rolling-upgrade requirement.
  • Tests and results: the checked-in .out matches the ordered queries and covers a base-branch row, a reconstructed before-image row, and qualified/unqualified dotted columns. The FE structural test covers both mask projects and all three reconstruction-control slots. I did not run builds or tests because this review environment explicitly prohibits them; this conclusion is static-only. The missing race, hidden-column, and error-policy negatives correspond to the existing blocking threads.
  • Performance and observability: no distinct hot-path regression or new observability requirement was substantiated. The extra policy-source call/latency shares the same cause and fix as the single-snapshot blocking thread.
  • Security: restricted authenticated SQL users are in scope under the Doris threat model. The unresolved policy-snapshot path can produce a mixed-policy plan, so this review cannot approve the access-control change yet.

There was no additional user-provided focus. One complete review round (two full reviews plus a separate risk-focused scan) converged with no new valuable findings after duplicate fencing and main-agent verification.

@morrySnow

Copy link
Copy Markdown
Contributor Author

run buildall

@morrySnow

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

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.

Requesting changes at exact head 40f0315961e35d8e5b3d180730560ba6439b9f77.

No new inline comment is added in this pass: the remaining substantiated issues are already covered by existing inline threads, which are hard duplicate fences:

Checkpoint conclusions:

  • Goal, correctness, and security: ordinary visible-column row filters and data masks now apply to both MOW historical branches; reconstruction filters are below mask projects; and the latest follow-up correctly preserves raw dotted names plus branch qualifiers. The three unresolved cases above still prevent approval. Restricted authenticated SQL users are in scope under the Doris threat model, and the mixed-policy SQL-cache path can violate the RBAC property by serving rows planned without the retained policy proof.
  • Scope, clarity, and parallel paths: the production change is focused. Both MOW branches, DUP time travel, direct @incr, wrapper/MV-refresh identity, aggregates and filter chains, connector predicates, streams/snapshots, partitions/tablets, union alignment, aliases, and qualified/unqualified binding were traced. No additional unfenced defect was found.
  • Concurrency and lifecycle: no new threads, locks, static initialization, or resource lifetime are introduced. The mutable policy-provider interleaving between the two sequential branch lookups is the first existing blocker above.
  • Configuration, compatibility, persistence, and writes: there is no new production configuration, function symbol, FE-BE field, wire/storage format, EditLog/transaction path, data-write path, or rolling-upgrade requirement.
  • Conditions and error handling: the widened filter peel is valid for the reachable wrapper/aggregate shapes, but it does not create an execution barrier between reconstruction and row-policy evaluation; that remains the second existing blocker.
  • Tests and results: the generated ordered oracle covers one base-branch row, one reconstructed before-image row, and qualified/unqualified dotted columns; FE tests cover wrapper ownership, mask retention, reconstruction-control slots, and branch qualifiers. Missing cache-mutation, error-policy, and omitted-origin-column negatives correspond to the three existing blockers. This review is static-only: builds and tests were not run because the review environment prohibits them.
  • Performance and observability: no distinct hot-path or observability issue was substantiated. The duplicate policy-source call and latency share the same cause and fix as the single-snapshot blocker.

No additional user review focus was provided. One complete review round converged: both normal full-review agents and the separate risk-focused agent returned NO_NEW_VALUABLE_FINDINGS, and the main-agent final sweep resolved every candidate as an existing duplicate or an evidence-backed dismissal.

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 100.00% (21/21) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17562	3054	3028	3028
q2	2118	246	221	221
q3	10249	911	537	537
q4	4672	249	213	213
q5	7669	548	386	386
q6	138	121	96	96
q7	621	493	385	385
q8	9236	935	877	877
q9	3495	2383	2410	2383
q10	6496	847	712	712
q11	391	193	180	180
q12	613	259	202	202
q13	18123	1536	1166	1166
q14	160	150	136	136
q15	q16	429	401	369	369
q17	1356	938	894	894
q18	3112	2230	2231	2230
q19	1274	874	803	803
q20	380	291	210	210
q21	5628	1562	1822	1562
q22	322	271	233	233
Total cold run time: 94044 ms
Total hot run time: 16823 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3442	3368	3356	3356
q2	502	386	368	368
q3	2234	2313	2258	2258
q4	1204	1181	905	905
q5	2166	2116	2083	2083
q6	168	120	89	89
q7	1020	929	858	858
q8	1594	1395	1384	1384
q9	3141	3095	3087	3087
q10	1871	1785	1612	1612
q11	348	271	249	249
q12	453	431	340	340
q13	1504	1534	1154	1154
q14	174	159	153	153
q15	q16	397	394	356	356
q17	3583	3319	3257	3257
q18	4799	4376	4698	4376
q19	859	916	896	896
q20	1029	949	823	823
q21	3889	3168	3194	3168
q22	397	336	314	314
Total cold run time: 34774 ms
Total hot run time: 31086 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 82208 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 40f0315961e35d8e5b3d180730560ba6439b9f77, data reload: false

query5	4230	417	332	332
query6	386	136	146	136
query7	4938	400	237	237
query8	286	122	132	122
query9	8692	2886	2879	2879
query10	405	213	187	187
query11	5381	1046	906	906
query12	127	69	70	69
query13	1196	438	325	325
query14	6153	2212	2095	2095
query14_1	2013	1958	1977	1958
query15	174	122	111	111
query16	903	370	356	356
query17	802	452	358	358
query18	2347	332	238	238
query19	179	135	107	107
query20	71	71	70	70
query21	198	102	88	88
query22	5362	5343	5407	5343
query23	6871	6294	6139	6139
query23_1	6210	6041	6093	6041
query24	7259	1083	768	768
query24_1	786	776	770	770
query25	419	305	234	234
query26	1231	236	123	123
query27	2792	426	252	252
query28	4675	1495	1487	1487
query29	905	413	335	335
query30	256	158	130	130
query31	812	397	330	330
query32	126	72	72	72
query33	448	212	171	171
query34	984	817	477	477
query35	402	385	349	349
query36	556	565	503	503
query37	119	78	72	72
query38	1001	851	794	794
query39	495	473	473	473
query39_1	466	462	495	462
query40	197	89	81	81
query41	54	53	53	53
query42	78	69	71	69
query43	240	241	208	208
query44	993	519	525	519
query45	108	107	96	96
query46	777	851	533	533
query47	762	776	708	708
query48	307	299	222	222
query49	551	236	189	189
query50	750	261	201	201
query51	8213	8117	8181	8117
query52	66	78	56	56
query53	184	198	149	149
query54	220	152	147	147
query55	69	59	56	56
query56	180	173	148	148
query57	805	665	668	665
query58	204	162	159	159
query59	1220	1237	1124	1124
query60	225	179	165	165
query61	129	109	107	107
query62	347	198	180	180
query63	171	139	143	139
query64	2662	673	565	565
query65	1586	1661	1600	1600
query66	1899	269	205	205
query67	10212	9871	9678	9678
query68	3004	1233	710	710
query69	348	233	203	203
query70	689	624	625	624
query71	265	181	172	172
query72	2265	1805	1594	1594
query73	664	613	331	331
query74	2051	1227	1160	1160
query75	1184	1094	980	980
query76	2378	725	521	521
query77	261	263	211	211
query78	3841	3670	3335	3335
query79	1816	885	567	567
query80	1213	329	291	291
query81	498	161	134	134
query82	630	133	107	107
query83	334	224	185	185
query84	296	113	84	84
query85	787	337	271	271
query86	389	182	166	166
query87	1032	962	896	896
query88	2793	2127	2112	2112
query89	294	197	175	175
query90	1967	128	129	128
query91	132	119	96	96
query92	81	73	64	64
query93	1358	1074	725	725
query94	637	271	211	211
query95	535	335	223	223
query96	791	571	288	288
query97	1034	1056	1021	1021
query98	139	143	132	132
query99	423	341	317	317
Total cold run time: 177424 ms
Total hot run time: 82208 ms

@hello-stephen

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

query1	0.00	0.01	0.00
query2	0.08	0.04	0.04
query3	0.26	0.11	0.11
query4	1.61	0.11	0.10
query5	0.17	0.16	0.16
query6	1.16	0.72	0.69
query7	0.03	0.01	0.00
query8	0.04	0.02	0.03
query9	0.29	0.21	0.22
query10	0.35	0.34	0.35
query11	0.16	0.12	0.11
query12	0.15	0.12	0.12
query13	0.31	0.32	0.30
query14	0.46	0.45	0.44
query15	0.37	0.35	0.34
query16	0.21	0.23	0.23
query17	0.67	0.69	0.65
query18	0.19	0.17	0.17
query19	1.17	1.17	1.15
query20	0.02	0.01	0.01
query21	15.45	0.15	0.11
query22	5.07	0.04	0.05
query23	16.17	0.26	0.10
query24	3.08	0.34	0.26
query25	0.12	0.05	0.03
query26	0.75	0.16	0.13
query27	0.04	0.04	0.02
query28	3.66	0.59	0.26
query29	12.44	3.19	2.58
query30	0.25	0.12	0.13
query31	2.85	0.38	0.17
query32	3.51	0.31	0.23
query33	1.50	1.52	1.53
query34	15.39	2.16	1.75
query35	1.78	1.76	1.73
query36	0.46	0.31	0.29
query37	0.06	0.03	0.04
query38	0.04	0.03	0.03
query39	0.04	0.02	0.03
query40	0.12	0.08	0.07
query41	0.07	0.02	0.03
query42	0.04	0.02	0.02
query43	0.04	0.03	0.03
Total cold run time: 90.63 s
Total hot run time: 14.75 s

@yujun777 yujun777 left a comment

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.

LGTM

@morrySnow
morrySnow merged commit e545b13 into apache:master Sep 17, 2026
38 of 39 checks passed
@morrySnow
morrySnow deleted the fix/mow-time-travel-row-policy branch September 17, 2026 02:51
@github-actions github-actions Bot added the approved Indicates a PR has been approved by one committer. label Sep 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

PR approved by at least one committer and no changes requested.

morningman added a commit that referenced this pull request Sep 18, 2026
…on PRs from master in merge order (#67783 #68034 #68033 #68057 #68094 #68087) (#68151)

Cherry-picked from #67783, #68034, #68033, #68057, #68094, #68087

Batch pick of every merged PR carrying the `incremental-computation`
label that `branch-incremental-computation` does not have yet (no
`incremental-computation-picked` label), in the order they landed on
master (`git log --first-parent`). One commit per PR, each created with
`git cherry-pick -x` so the message ends with `(cherry picked from
commit <master sha>)`. Follows the same convention as #67830, #68017 and
#68073.

| # | Master commit | PR | Title |
|---|---|---|---|
| 1 | e545b13 | #67783 | [fix](policy) Enforce row policies on MOW
time travel |
| 2 | f7a0842 | #68034 | [fix](binlog) Fix missing DELETE events in
row binlog |
| 3 | e85575e | #68033 | [fix](binlog) Preserve row binlog
compaction policy |
| 4 | 21160d7 | #68057 | [fix](binlog) Decouple row binlog
compaction from CCR binlog config |
| 5 | 04aa5a1 | #68094 | [fix](binlog) Persist row binlog config
updates in cloud mode |
| 6 | da8feed | #68087 | [fix](binlog) Report streams with missing
base tables as stale |

Not included on purpose:
- The 20 labelled PRs that already carry
`incremental-computation-picked` (#62606 in the fork point, #67508 via
#67712, the nine of #67830, the six of #68017, the two of #68073, and
#68050 whose content this branch got directly through #68012).
- #68012 carries the label but is a PR against this branch itself
(merged as `6f7c87fa892`); nothing to pick.
- #67820 is still open on master; this branch already carries its
content via #67861.

### Prerequisite check

For every pick I listed the master commits between the fork point
(`efedf10c7e3`) and the pick that touch the same files and are not on
this branch, and checked whether the pick's behavior depends on them.

- **#67783** declares no related PR. It builds on the MOW time-travel
rewrite (`BindRelation.buildMowTimeTravelUnion`, #67480) which is
already here. Two unlabelled master commits overlap: #66770
(authorization plugin SPI: reworks the data-mask / row-filter API of
`LogicalCheckPolicy` and its test) and #67811 (removes the
`isPlayNereidsDump()` check in `CheckPolicy`). Neither is a functional
prerequisite: the fix consists of `getPolicyTable()` unwrapping
`OlapTableWrapper`, `CheckPolicy` collecting the whole filter chain
below the policy mask, and `BindRelation` putting a `LogicalCheckPolicy`
above each union branch — none of that uses the #66770 API. Not picked;
adapted instead (see below).
- **#68034**, **#68033**, **#68087** (#68087 relates to #67173, which is
before the fork point): no unpicked master commit touches any of their
files; the picks applied cleanly and are byte-identical to master.
- **#68057**: only `be/test/cloud/cloud_compaction_test.cpp` overlaps
with the unrelated #67972 (refresh tablet meta of continuously ingested
tablets); auto-merged, the pick only adds new `TEST_F` blocks. Main-code
hunks are byte-identical to master.
- **#68094**: overlaps with #68090 / #67972 / #66598
(`cloud_tablet.cpp`), #67295 / #67618 / #68090 (`base_tablet.{h,cpp}`),
#66598 / #67637 (`meta_service.cpp`), #66598 (`cloud.proto`,
`cloud_tablet_test.cpp`) and #67761 / #66598 / #67637
(`meta_service_test.cpp`). All auto-merged. The fix —
`BaseTablet::binlog_config()` under the meta lock,
`BinlogConfig::operator==`, `CloudTablet::sync_meta()` refreshing the
binlog config, `update_tablet` in the meta service accepting
`binlog_config`, and `CloudSchemaChangeHandler` routing ROW-binlog
property updates through it — does not use anything those commits add.
Its hunks are byte-identical to master except one trailing context line
in `sync_meta()` (`last_sync_tablet_meta_time_s` comes from #67972).

Only #67783 needed adaptation, recorded in its commit message:
- `LogicalCheckPolicy.java`: the conflicting context was master's
`parsePolicyExpression()` helper (#66770), which does not exist here;
the new `getPolicyTable()` is inserted in the same place without it.
- `CheckRowPolicyTest.java`: the data-mask mock is written against this
branch's per-column `AccessControllerManager.evalDataMaskPolicy(...,
column) -> Optional<DataMaskPolicy>` instead of master's
`evalDataMaskPolicies(..., Set<String>) -> Map<String, DataMaskSpec>`.
The masks are the same (concat for the random-distribution table; the
non-movable `k2` mask plus identity masks for the hidden reconstruction
columns of the MOW table). The master-only `Or` import (#66770) is not
carried; `Collections` / `Locale` imports were added because they arrive
with #66770 on master.

### Drift check against master

Each pick's `+`/`-` lines are identical to the master commit's, except
for the #67783 adaptation above. After the six picks, the touched files
still differ from master at `da8feed859d` in: `cloud_tablet.cpp`,
`base_tablet.{h,cpp}`, `cloud_compaction_test.cpp`,
`cloud_tablet_test.cpp`, `meta_service.cpp`, `meta_service_test.cpp`,
`cloud.proto`, `CheckPolicy.java`, `LogicalCheckPolicy.java`,
`CheckRowPolicyTest.java`. Replaying the nine unpicked master commits
listed above (#67637, #67618, #66770, #66598, #67972, #67811, #67761,
#67295, #68090) in a temporary index and removing this branch's own
#67861 (`GetTsoRecoveryTransactions` in `cloud.proto` /
`meta_service_test.cpp`) brings every file to zero diff against master,
except the two `LogicalCheckPolicy.java` / `CheckRowPolicyTest.java`
hunks of #66770 that overlap the adaptation. Nothing else is left over.

### Verification

- FE: `run-fe-ut.sh --run` on this branch (regenerates thrift/protobuf,
compiles fe-core main + test) with the test classes touched by the picks
plus `DeleteFromCommandTest` from #68034's checklist: 5 classes, 58
tests, 0 failures, 0 errors, BUILD SUCCESS — `CheckRowPolicyTest` 9 (the
three tests #67783 adds included), `ExplainTableStreamPlanTest` 24,
`CloudSchemaChangeHandlerTest` 18 (the tests of #68033 and #68094
included), `DropTableStreamTest` 5, `DeleteFromCommandTest` 2.
- FE checkstyle on fe-core: 0 violations.
- BE: `-fsyntax-only` with the flags of the Release build
(`compile_commands.json`, regenerated `gen_cpp` headers incl. the new
`TabletMetaInfoPB.binlog_config`) passes for `cloud/cloud_tablet.cpp`,
`cloud/cloud_storage_engine.cpp`, `storage/olap_server.cpp`,
`storage/tablet/tablet.cpp`, `storage/tablet/base_tablet.cpp`, and with
`-DBE_TEST -fno-access-control` for
`test/cloud/cloud_compaction_test.cpp`,
`test/cloud/cloud_tablet_test.cpp`,
`test/storage/compaction/compaction_task_test.cpp`,
`test/storage/tablet/tablet_test.cpp`.
- Meta service: the two-line `update_tablet` hunk of #68094 only uses
the generated `TabletMetaInfoPB::has_binlog_config()/binlog_config()`
and `TabletMetaCloudPB::mutable_binlog_config()` accessors, all present
in the regenerated headers.
- The two new groovy suites
(`row_binlog_p0/test_row_binlog_mow_light_delete`,
`time_travel_p0/test_mow_time_travel_row_policy`) parse cleanly (groovy
parser check).

---------

Co-authored-by: morrySnow <zhangwenxin@selectdb.com>
Co-authored-by: Luwei <814383175@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by one committer. incremental-computation incremental-computation-picked

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants