Skip to content

[fix](parser) Reject unquoted suffixes attached to quoted table names - #69541

Open
Gabriel39 wants to merge 1 commit into
apache:masterfrom
Gabriel39:fix/quoted-system-table-suffix
Open

Gabriel39 wants to merge 1 commit into
apache:masterfrom
Gabriel39:fix/quoted-system-table-suffix

Conversation

@Gabriel39

@Gabriel39 Gabriel39 commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

SELECT * FROM `t`$snapshots currently parses $snapshots as an implicit table alias and silently returns rows from t. The same issue affects qualified names such as `catalog`.`db`.`t`$snapshots.

Reject an unquoted dollar-prefixed suffix immediately adjacent to a quoted table name during parsing. The error explains how to quote the complete table name or separate an intended alias. Supported forms such as t$snapshots, `t$snapshots`, and `t` AS $snapshots remain valid, as do aliases separated by whitespace or comments.

Add parser coverage for qualified names, escaped backticks, non-ASCII names, explicit and separated aliases, and parsing without building a tree. Add a p0 regression suite with six syntax-error checks that require no external catalog.

Release note

Queries that attach an unquoted dollar suffix directly to a quoted table name now fail explicitly instead of silently scanning the base table. Quote the entire system table name, for example `t$snapshots`.

Check List (For Author)

  • Test
    • Unit Test: reproduced the failure before the fix; all 255 fe-sql-parser tests pass after the fix.
    • Manual test: all six SQL statements in the new regression suite produce the expected diagnostic with the standalone parser CLI; Groovy syntax validation passes.
    • Regression test: test_quoted_table_suffix passed on a locally built FE/BE cluster; all six syntax-error checks passed.
    • FE Checkstyle: zero violations in the parent and parser modules.
  • Behavior changed:
    • Yes. Ambiguous adjacent suffixes produce a parse error; explicit and separated dollar-prefixed aliases retain their existing behavior.
  • Does this need documentation?
    • No.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

### What problem does this PR solve?

Problem Summary: SELECT * FROM `t`$snapshots treats $snapshots as an
implicit alias and silently reads the base table. Reject a dollar-prefixed
unquoted suffix immediately adjacent to a quoted table name, with guidance
to quote the complete name or separate an intended alias. Preserve valid
system-table identifiers and explicit, whitespace-separated, or
comment-separated aliases.

### Release note

Queries that attach an unquoted dollar suffix directly to a quoted table
name now fail explicitly instead of silently scanning the base table.

### Check List (For Author)

- Test: All 255 standalone parser unit tests and FE Checkstyle passed;
  verified the six added regression SQL statements with the parser CLI.
  Cluster execution of the new regression suite is pending.
- Behavior changed: Yes, reject ambiguous adjacent suffixes.
- 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?

@Gabriel39

Copy link
Copy Markdown
Contributor Author

run buildall

@Gabriel39

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.

Reviewed PR #69541 at a3ef8d4012ab64f358413c56fb359c946f744f27. No new actionable findings. All three changed files and their parser-to-FE control flow were reviewed; no existing inline threads or additional user focus points were supplied.

Critical checkpoint Conclusion
Goal and proof The grammar rejects an adjacent unquoted dollar suffix after a quoted query table before a base-table plan is built. Added negative and positive parser tests and six diagnostic-specific regression checks address the intended behavior.
Scope and reuse One shared grammar helper/action and focused tests; no unrelated changes or duplicate FE implementation.
Concurrency and locking No shared state, threads, or locks added; tokens belong to each parse invocation.
Lifecycle and initialization No new ownership, resource lifetime, or static initialization dependency.
Configuration No settings added.
Compatibility The intentional SQL rejection is documented in the release note. Full system-table names and explicit, quoted, or separated aliases remain valid. No storage or function-symbol change.
Thrift/protobuf No protocol definitions changed.
Parallel paths FE and standalone parsing share the guard. Nested queries, joins, CTEs, view/create/insert queries, and DML source relations reach it. Separate DML-target, WARM UP, and administrative alias rules retain their pre-existing behavior, outside this focused query-read fix.
Special conditions and errors Original token types and source offsets distinguish adjacency from intentional aliases, including comments and lean tokenization. Empty aliases and parsing without a tree remain safe; FE preserves the parse diagnostic.
Test coverage Qualified and escaped names, non-ASCII names, suffix variants, no-tree parsing, valid identifiers, and whitespace/comment/AS aliases are covered. Regression checks require the new error text, excluding unrelated lookup failures.
Expected results Identifier expectations agree with grammar normalization. Exception-only regression checks need no ordering or .out file; no result files changed.
Observability The exception identifies the suffix location, SQL, and corrective syntax; no added metrics are needed for this local parse rejection.
Transactions and persistence No journal, version-visibility, or failover behavior changed.
Data writes and atomicity No write implementation changed; the new rejection occurs during parsing before execution.
FE/BE propagation No cross-process variables or serialization added.
Performance and memory A small token predicate per table relation adds no repeated SQL scan or retained state on successful parsing. Full diagnostic text is extracted only on failure.
Other issues The additional recheck found no further substantiated defect or unresolved code question.

Risk checks confirmed that identifier normalization replaces tree children without changing the raw tokens used by the guard. ANTLR records rule start/stop tokens independently of tree construction (ANTLR 4.13.1 parser source). Optional relation modifiers cannot consume an attached dollar alias or create false adjacency.

Coverage limits: static review only, as required. No builds, parser generation, unit tests, regression cluster tests, or runtime validation were performed; the author's reported test results were not independently reproduced.

Review converged after 2 round(s).

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17620	5288	5052	5052
q2	2175	302	256	256
q3	10223	1372	816	816
q4	4680	463	344	344
q5	7449	808	531	531
q6	181	180	152	152
q7	747	804	603	603
q8	9255	1349	1008	1008
q9	5483	4211	4227	4211
q10	6823	1301	1048	1048
q11	427	243	221	221
q12	638	394	277	277
q13	18171	3581	3011	3011
q14	279	273	249	249
q15	q16	726	718	657	657
q17	1216	750	571	571
q18	7010	6166	6105	6105
q19	1124	947	607	607
q20	408	339	218	218
q21	5157	2543	2411	2411
q22	379	321	283	283
Total cold run time: 100171 ms
Total hot run time: 28631 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5969	5931	6120	5931
q2	719	598	577	577
q3	5573	5807	5324	5324
q4	2018	2144	1586	1586
q5	5822	5761	5662	5662
q6	234	192	144	144
q7	2255	2048	1825	1825
q8	2956	2648	2627	2627
q9	7941	7800	7521	7521
q10	3611	3569	3117	3117
q11	580	413	379	379
q12	668	652	501	501
q13	3230	3603	3015	3015
q14	289	286	270	270
q15	q16	648	685	613	613
q17	7712	7051	6857	6857
q18	13014	12280	12822	12280
q19	889	771	766	766
q20	2146	2131	1914	1914
q21	5570	4571	4632	4571
q22	547	478	410	410
Total cold run time: 72391 ms
Total hot run time: 65890 ms

@hello-stephen

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

query5	4323	578	436	436
query6	430	217	200	200
query7	4811	436	222	222
query8	327	159	152	152
query9	8763	3053	3062	3053
query10	465	316	252	252
query11	6025	3838	3557	3557
query12	150	94	88	88
query13	1259	441	328	328
query14	6132	3943	3685	3685
query14_1	3448	3390	3409	3390
query15	209	199	184	184
query16	939	438	405	405
query17	867	655	530	530
query18	2427	427	309	309
query19	217	176	131	131
query20	86	82	83	82
query21	212	129	106	106
query22	12993	13016	12780	12780
query23	13448	12857	12463	12463
query23_1	12593	12550	12728	12550
query24	7378	807	453	453
query24_1	487	466	456	456
query25	537	429	359	359
query26	1250	251	139	139
query27	2771	440	272	272
query28	4627	1920	1927	1920
query29	1542	596	456	456
query30	308	225	186	186
query31	1025	932	822	822
query32	183	95	94	94
query33	549	307	235	235
query34	911	839	487	487
query35	735	781	638	638
query36	818	798	731	731
query37	130	101	91	91
query38	1759	1723	1652	1652
query39	796	791	736	736
query39_1	738	728	757	728
query40	226	118	94	94
query41	71	67	66	66
query42	89	86	81	81
query43	343	369	311	311
query44	1284	710	670	670
query45	178	190	157	157
query46	818	960	543	543
query47	3049	2742	2848	2742
query48	308	322	211	211
query49	596	388	287	287
query50	661	268	201	201
query51	10243	10364	10430	10364
query52	75	78	75	75
query53	183	201	154	154
query54	234	187	193	187
query55	80	71	63	63
query56	268	217	198	198
query57	1671	1623	1543	1543
query58	287	256	251	251
query59	2093	2192	1914	1914
query60	282	241	228	228
query61	146	143	149	143
query62	388	322	283	283
query63	190	153	157	153
query64	2733	950	724	724
query65	3314	3265	3274	3265
query66	1775	420	295	295
query67	20122	19965	19992	19965
query68	3035	980	597	597
query69	376	277	248	248
query70	848	771	734	734
query71	294	234	195	195
query72	2770	2620	2303	2303
query73	509	514	292	292
query74	4631	4497	4333	4333
query75	2326	2273	1925	1925
query76	2295	1001	582	582
query77	348	382	268	268
query78	9820	9814	9230	9230
query79	981	901	527	527
query80	738	436	332	332
query81	589	324	281	281
query82	827	137	102	102
query83	292	197	184	184
query84	310	115	105	105
query85	954	424	361	361
query86	368	239	232	232
query87	2017	1971	1823	1823
query88	3713	2685	2666	2666
query89	336	301	239	239
query90	1713	176	177	176
query91	163	156	133	133
query92	106	91	92	91
query93	1067	1024	569	569
query94	529	316	279	279
query95	566	336	311	311
query96	677	500	238	238
query97	2431	2418	2307	2307
query98	167	148	144	144
query99	787	752	633	633
Total cold run time: 234734 ms
Total hot run time: 150333 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.10	0.04	0.05
query3	0.26	0.09	0.09
query4	1.61	0.10	0.10
query5	0.23	0.24	0.24
query6	1.17	0.67	0.67
query7	0.04	0.01	0.01
query8	0.06	0.03	0.03
query9	0.40	0.35	0.36
query10	0.57	0.55	0.59
query11	0.20	0.15	0.15
query12	0.18	0.15	0.15
query13	0.49	0.50	0.50
query14	1.03	1.01	1.01
query15	0.64	0.60	0.62
query16	0.34	0.36	0.31
query17	1.12	1.12	1.16
query18	0.21	0.19	0.19
query19	2.07	1.96	2.03
query20	0.02	0.02	0.01
query21	15.50	0.18	0.13
query22	4.95	0.06	0.05
query23	16.26	0.32	0.12
query24	3.12	0.54	0.43
query25	0.12	0.07	0.05
query26	0.82	0.20	0.14
query27	0.06	0.03	0.06
query28	3.49	0.80	0.37
query29	12.51	4.16	3.24
query30	0.28	0.13	0.10
query31	2.77	0.56	0.32
query32	3.22	0.60	0.50
query33	3.23	3.27	3.31
query34	15.37	4.00	3.42
query35	3.36	3.34	3.36
query36	0.55	0.43	0.42
query37	0.10	0.07	0.06
query38	0.06	0.04	0.04
query39	0.04	0.03	0.03
query40	0.17	0.16	0.14
query41	0.08	0.04	0.02
query42	0.04	0.02	0.02
query43	0.04	0.03	0.04
Total cold run time: 96.89 s
Total hot run time: 24.36 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 100% (0/0) 🎉
Increment coverage report
Complete coverage report

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