Skip to content

[fix](point query) Enforce fixed key predicates in prepared point queries - #67885

Open
morrySnow wants to merge 1 commit into
apache:masterfrom
morrySnow:fix/enforce-prepared-point-policy-key-constraints
Open

[fix](point query) Enforce fixed key predicates in prepared point queries#67885
morrySnow wants to merge 1 commit into
apache:masterfrom
morrySnow:fix/enforce-prepared-point-policy-key-constraints

Conversation

@morrySnow

Copy link
Copy Markdown
Contributor

Problem

Server-side prepared point queries could reuse a cached scan plan after a row policy added a fixed equality on the same key column as a placeholder. A later parameter binding could replace the policy literal in the cached conjunct, both bypassing the fixed restriction and contaminating subsequent executions of the same prepared handle.

Root cause

The direct point-query path rediscovered key values from translated scan conjuncts and updated every cached binary predicate sharing a column name. That representation lost the provenance between caller-controlled placeholders and fixed statement or policy literals, and made shared plan state mutable across executions.

Reproduction

Create a unique-key merge-on-write table with a composite key and a restrictive row policy such as tenant_id = 1. Prepare a query with tenant_id = ? AND item_id = ?, then execute the same handle with tenant values 1, 2, and 1 again (and with NULL). The conflicting binding must return no rows, while the repeated matching binding must still work without changing the cached plan. A lossy predicate such as CAST(tenant_id AS CHAR(1)) = '1' must remain on the normal planning path.

Fix

  • Freeze placeholder-to-key bindings and fixed equality literals into an immutable point-query key template when the short-circuit context is created.
  • Bind a new SQL-typed key tuple for each execution and distinguish lookup, provably empty, and safe fallback outcomes.
  • Return an empty row batch before tablet pruning or backend RPC when a placeholder is NULL or conflicts with a fixed key literal.
  • Build pruning filters from execution-owned values without rewriting cached conjuncts.
  • Fall back to the normal planner for inexact type coercions and any fixed predicate that cannot prove an exact physical key, including casts and non-key residuals.

Tests

  • ./run-fe-ut.sh --run "org.apache.doris.nereids.trees.plans.commands.ExecuteCommandTest,org.apache.doris.qe.PointQueryExecutorTest,org.apache.doris.qe.ShortCircuitQueryContextTest"
  • ./build.sh --fe (through the sandbox FE update flow)
  • ./run-regression-test.sh --conf regression-test/conf/regression-conf.groovy.custom --run -f regression-test/suites/prepared_stmt_p0/prepared_point_query_row_policy.groovy

@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

@morrySnow morrySnow changed the title Fix prepared point queries with fixed key predicates [fix](nereids) Enforce fixed key predicates in prepared point queries Sep 11, 2026
@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 67.49% (164/243) 🎉
Increment coverage report
Complete coverage report

### What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary: Server-side prepared point queries could reuse a cached scan plan after a restrictive row policy added a fixed equality on the same key column as a placeholder. The direct path rediscovered key values from mutable translated conjuncts and rewrote every predicate sharing that column name, so a later binding could overwrite the policy literal and contaminate subsequent executions. Freeze placeholder bindings and exact fixed literals into an immutable key template, derive a typed tuple per execution, return a schema-correct empty batch before pruning or backend RPC for NULL or conflicting bindings, and fall back to normal planning for inexact coercions or unprovable predicates.

### Release note

Prepared point queries now preserve fixed row-policy key constraints across repeated server-side executions and safely fall back when a predicate cannot be represented as an exact physical lookup key.

### Check List (For Author)

- Test:
    - Unit Test: ExecuteCommandTest, ShortCircuitQueryContextTest, and PointQueryExecutorTest (21 tests).
    - Regression test: prepared_point_query_row_policy.
    - Build/checkstyle: DISABLE_BUILD_UI=ON ./build.sh --fe.
- Behavior changed: Yes. Prepared point queries now return an empty result before tablet lookup when a bound key conflicts with an exact fixed predicate or is NULL; unprovable predicates use normal planning.
- Does this need documentation: No.
@morrySnow
morrySnow force-pushed the fix/enforce-prepared-point-policy-key-constraints branch from 371563b to a77b540 Compare September 11, 2026 20:44
@morrySnow

Copy link
Copy Markdown
Contributor Author

run buildall

@morrySnow morrySnow changed the title [fix](nereids) Enforce fixed key predicates in prepared point queries [fix](point query) Enforce fixed key predicates in prepared point queries Sep 12, 2026
@morrySnow
morrySnow marked this pull request as draft September 12, 2026 03:06
@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17579	3134	3105	3105
q2	2093	242	218	218
q3	10238	904	512	512
q4	4673	261	202	202
q5	7668	577	391	391
q6	139	115	96	96
q7	526	511	380	380
q8	9237	914	929	914
q9	3417	2376	2381	2376
q10	6502	830	726	726
q11	392	191	181	181
q12	612	263	201	201
q13	18115	1504	1140	1140
q14	153	147	138	138
q15	q16	429	398	371	371
q17	1269	869	793	793
q18	3122	2262	2245	2245
q19	1268	895	780	780
q20	371	284	198	198
q21	5656	1760	1901	1760
q22	323	270	227	227
Total cold run time: 93782 ms
Total hot run time: 16954 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3464	3383	3386	3383
q2	498	392	399	392
q3	2248	2293	2257	2257
q4	1193	1173	889	889
q5	2199	2122	2082	2082
q6	167	120	87	87
q7	1054	925	887	887
q8	1609	1406	1416	1406
q9	3134	3102	3097	3097
q10	1856	1806	1625	1625
q11	353	270	251	251
q12	450	421	339	339
q13	1456	1513	1144	1144
q14	171	162	187	162
q15	q16	395	394	361	361
q17	3614	3368	3270	3270
q18	4767	4430	4657	4430
q19	850	918	869	869
q20	1007	1003	837	837
q21	3824	3225	3203	3203
q22	393	360	332	332
Total cold run time: 34702 ms
Total hot run time: 31303 ms

@hello-stephen

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

query5	4241	399	342	342
query6	380	143	121	121
query7	4953	400	223	223
query8	289	123	114	114
query9	8691	2887	2898	2887
query10	398	214	184	184
query11	5388	1054	913	913
query12	121	73	69	69
query13	1191	462	326	326
query14	6108	2208	2078	2078
query14_1	1957	1942	1952	1942
query15	170	117	117	117
query16	906	386	360	360
query17	795	449	354	354
query18	2328	332	234	234
query19	168	136	113	113
query20	77	70	74	70
query21	201	101	88	88
query22	5443	5281	5312	5281
query23	6636	6212	6058	6058
query23_1	5958	5939	6024	5939
query24	7310	1120	753	753
query24_1	763	754	751	751
query25	419	299	264	264
query26	1226	239	132	132
query27	2782	421	237	237
query28	4717	1511	1503	1503
query29	922	440	346	346
query30	254	156	133	133
query31	833	397	330	330
query32	129	80	75	75
query33	460	222	183	183
query34	1000	824	487	487
query35	403	405	357	357
query36	561	583	558	558
query37	124	84	80	80
query38	1010	849	811	811
query39	496	481	482	481
query39_1	476	468	454	454
query40	207	95	78	78
query41	61	56	56	56
query42	75	72	100	72
query43	240	242	208	208
query44	972	527	533	527
query45	113	99	101	99
query46	755	856	525	525
query47	765	765	707	707
query48	318	307	226	226
query49	532	251	195	195
query50	755	254	193	193
query51	8125	8066	8114	8066
query52	65	65	56	56
query53	195	193	145	145
query54	227	161	194	161
query55	75	57	53	53
query56	185	157	152	152
query57	667	651	654	651
query58	248	161	149	149
query59	1201	1213	1116	1116
query60	242	177	162	162
query61	115	122	108	108
query62	345	213	178	178
query63	175	157	139	139
query64	2746	687	606	606
query65	1655	1619	1612	1612
query66	1798	262	206	206
query67	10082	9911	10888	9911
query68	2985	1211	675	675
query69	360	224	194	194
query70	676	618	589	589
query71	258	175	157	157
query72	2273	1690	1494	1494
query73	633	581	352	352
query74	2005	1211	1119	1119
query75	1174	1100	954	954
query76	2381	708	522	522
query77	252	265	201	201
query78	3905	3611	3172	3172
query79	2830	783	550	550
query80	1615	314	266	266
query81	524	152	137	137
query82	640	125	92	92
query83	288	202	189	189
query84	305	109	91	91
query85	808	332	277	277
query86	493	182	163	163
query87	1008	968	886	886
query88	3054	2108	2074	2074
query89	279	193	169	169
query90	2185	129	120	120
query91	128	122	102	102
query92	99	66	69	66
query93	2280	1059	739	739
query94	646	239	222	222
query95	507	241	293	241
query96	781	557	272	272
query97	1045	1064	1050	1050
query98	175	146	136	136
query99	427	349	311	311
Total cold run time: 179619 ms
Total hot run time: 81829 ms

@hello-stephen

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

query1	0.00	0.01	0.00
query2	0.08	0.04	0.04
query3	0.24	0.11	0.09
query4	1.60	0.10	0.10
query5	0.18	0.16	0.15
query6	1.23	0.73	0.69
query7	0.04	0.01	0.01
query8	0.06	0.03	0.03
query9	0.29	0.21	0.22
query10	0.35	0.36	0.34
query11	0.16	0.12	0.11
query12	0.15	0.12	0.12
query13	0.32	0.30	0.30
query14	0.45	0.45	0.46
query15	0.36	0.37	0.36
query16	0.21	0.23	0.21
query17	0.69	0.69	0.73
query18	0.19	0.16	0.17
query19	1.16	1.14	1.10
query20	0.02	0.01	0.01
query21	15.45	0.16	0.11
query22	5.11	0.04	0.04
query23	16.16	0.27	0.10
query24	2.97	0.30	0.27
query25	0.10	0.04	0.03
query26	0.82	0.16	0.11
query27	0.03	0.03	0.02
query28	3.65	0.56	0.29
query29	12.43	3.23	2.57
query30	0.26	0.11	0.11
query31	2.77	0.37	0.17
query32	3.52	0.32	0.23
query33	1.38	1.39	1.41
query34	15.39	2.16	1.80
query35	1.77	1.72	1.70
query36	0.45	0.29	0.28
query37	0.06	0.04	0.04
query38	0.04	0.04	0.02
query39	0.03	0.02	0.02
query40	0.12	0.07	0.07
query41	0.08	0.02	0.02
query42	0.03	0.03	0.02
query43	0.03	0.02	0.03
Total cold run time: 90.43 s
Total hot run time: 14.6 s

hello-stephen pushed a commit that referenced this pull request Sep 12, 2026
…67897)

Since today every `Doris_DorisCloudRegression_VaultP0` run dies in the
`run` step before executing a single test, e.g.
#67883 (TeamCity build 39010) and
#67881 / #67882 / #67885 / #67886 / #67892 / #67893:

```
doris-external--minio Pulling
doris-external--minio Error
Error response from daemon: pull access denied for minio/minio, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
ERROR: start minio docker twice failed
```

MinIO stopped publishing container images in October 2025 (the project
is a source-only distribution now, see minio/minio#21647) and the
`minio/minio` and `minio/mc` repositories have since been removed from
Docker Hub altogether
(`https://hub.docker.com/v2/repositories/minio/minio/` answers 404, same
for `minio/mc`). The few VaultP0 runs that still pass do so only on
agents that have the image cached locally (their logs have no `Pulling`
line). The iceberg, hudi and polaris third-party fixtures,
`test_file_cache_warmup_read_metrics_docker` (which runs a `docker run
minio/minio` itself), the all-in-one `cloud.yml` and the datalake
samples reference the same images and are one cache eviction away from
the same failure.

`quay.io/minio/minio` and `quay.io/minio/mc` still serve every tag we
use -- `RELEASE.2024-11-07T00-52-20Z`, `RELEASE.2025-01-20T14-49-07Z`,
mc `RELEASE.2025-01-17T23-25-50Z`, the two 2022 tags of the samples and
`latest` -- and MinIO keeps pushing hotfix tags there (latest one dated
2026-04). `docker manifest inspect` resolves all of them (amd64 / arm64
/ ppc64le). So every reference gets the `quay.io/` prefix and the tags
stay exactly as they were: same builds, different registry. The CI
agents already pull from quay.io for the OceanBase fixture.

A longer-term option is to mirror these three tags into the project's
own `doristhirdpartydocker` namespace, which already hosts hive /
zookeeper / kafka / trinodb; that needs someone with push access to that
Docker Hub organization and can follow separately.
@morrySnow
morrySnow marked this pull request as ready for review September 12, 2026 11:22
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