Skip to content

[fix](like) Fix LIKE matching values with extra characters at the end - #68133

Merged
yiguolei merged 1 commit into
apache:masterfrom
csun5285:fix-DORIS-28979-like-tail-anchor
Sep 18, 2026
Merged

yiguolei merged 1 commit into
apache:masterfrom
csun5285:fix-DORIS-28979-like-tail-anchor

Conversation

@csun5285

@csun5285 csun5285 commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

  1. LIKE 'a_b' is converted to ^a.b\z, not ^a.b$. Hyperscan follows PCRE, where $ also matches right before a newline that ends the value, so ^a.b$ wrongly matched 'acb\n'. \z is the end of the value in both Hyperscan and RE2.

  2. LIKE 'a_b%' is converted to ^a.b, not ^a.b.*\z. A trailing % matches anything, and so does appending nothing. The anchored form would force .* to consume the value to its end, and .* only matches valid UTF-8, so RE2 would not match 'acb\xff' while Hyperscan still would.

  3. LIKE 'a_*' is converted to ^a.\*\z, not ^a.\*. The tail anchor used to be skipped whenever the produced regex ended with *, a check meant to detect the .* expanded from a trailing %. An escaped literal * ends the regex with the same character, so the pattern lost its anchor entirely and 'ab*xyz' matched. The decision now comes from the position in the pattern instead of from the produced string.

Issue Number: close #xxx

Related PR: #xxx

Problem Summary:

Release note

None

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
    • No need to test or manual test. Explain why:
      • This is a refactor/code format and no logic has been changed.
      • Previous test can cover this change.
      • No code files have been changed.
      • Other reason
  • Behavior changed:

    • No.
    • Yes.
  • Does this need documentation?

    • No.
    • Yes.

Check List (For Reviewer who merge this PR)

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

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

@csun5285

Copy link
Copy Markdown
Contributor Author

/review

@csun5285

Copy link
Copy Markdown
Contributor Author

run buildall

@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. The exact-end \z conversion and the newline/literal-star cases are sound for valid UTF-8, but the new byte-semantics guarantee and a supported escape form remain incomplete.

Critical checkpoint conclusions:

  • Goal: The patch fixes whole-value anchoring for newline tails and avoids forcing a terminal % to traverse the remaining value, but it does not yet provide consistent invalid-byte behavior for every % position.
  • Scope/focus: The production delta is small and focused. No additional user review focus was provided.
  • Concurrency: No new concurrency is introduced; LIKE function state remains thread-local and pushed-predicate clones own separate Hyperscan scratch state.
  • Lifecycle/static initialization: No new special lifecycle, cross-TU static initialization, or ownership cycle is introduced.
  • Configuration: No configuration item is added or changed.
  • Compatibility: No function symbol, storage format, wire protocol, or rolling-upgrade contract changes.
  • Parallel paths: I traced constant Hyperscan, nonconstant RE2, scalar/vector, cloned scan pushdown, NOT LIKE, dictionary/plain-column, and JSON-search paths. The invalid-byte engine split and explicit-backslash escape gap are called out inline; no separate clone or negation defect was found.
  • Special conditions: Empty patterns, leading/interior/trailing and repeated %, _, newline, literal regex metacharacters, and default/custom escapes were checked. The terminal branch is correct for valid UTF-8, subject to the two completeness gaps inline.
  • Tests: The unit test covers constant/nonconstant argument combinations, and the regression suite covers direct evaluation, pushdown, clone reconstruction, and NOT LIKE. The invalid-byte row relies on an undefined Hyperscan contract, while interior-invalid-byte and explicit-backslash-escape cases are missing. This was a static-only review; the task contract prohibited builds or test execution.
  • Expected results: All 74 added result lines are deterministic and consistent with the inserted rows.
  • Observability: No new observability surface is needed for this local matcher change.
  • Transactions/persistence/data writes: Not applicable; no metadata, EditLog, transaction, or storage write path changes.
  • FE/BE variable propagation: Not applicable; no new cross-layer variable is introduced.
  • Performance: Removing the terminal .* avoids unnecessary suffix traversal; no additional CPU or memory regression was found.
  • Other issues: No other correctness, null-handling, error-propagation, compatibility, or performance issue remained after the second converged review round.

// A pattern open at the tail must not make the engines walk the rest of the value:
// `.*` only matches valid UTF-8, so anchoring it with `\z` would make RE2 reject a
// value whose tail is not valid UTF-8 while Hyperscan still accepts it.
{{std::string("acb\xff", 4), std::string("a_b%")}, uint8_t(1)},

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.

[P2] Avoid asserting undefined Hyperscan UTF-8 behavior

check_function_all_arg_comb includes constant-pattern runs, and a_b% bypasses the LIKE fast paths because of _. That makes construct_like_const_state compile ^a.b with HS_FLAG_UTF8 and pass this four-byte acb\xff buffer to hs_scan. Hyperscan's API explicitly says that scanning invalid UTF-8 with this flag has undefined results, so this expected 1 can vary across engine versions or architectures and cannot prove Hyperscan/RE2 equivalence. Please route invalid input through a matcher with defined byte semantics (or otherwise keep it out of the UTF-8 Hyperscan path) before asserting this result.

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.

已删除

// a trailing `%` matches anything, and so does appending nothing
return;
}
re_pattern->append(".*");

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.

[P2] Handle invalid bytes for interior percent wildcards too

The new invalid-input case establishes that SQL % must be able to absorb bytes that are not valid UTF-8, but this change makes only the terminal wildcard byte-safe. For example, a%b still becomes ^a.*b\z; the nonconstant path runs that through UTF-8 RE2, where . matches a code point and cannot traverse the 0xff in bytes [0x61, 0xff, 0x62], so it returns false. The constant-pattern Hyperscan path is undefined for the same invalid input, creating an additional path split. Although the interior case predates this hunk, it leaves the byte-semantics contract introduced here incomplete. Please give every % defined byte-safe semantics (or validate/route invalid input consistently), and cover constant, nonconstant, pushdown, and NOT LIKE forms with an invalid byte between required literals. RE2 syntax reference

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.

已删除

}

if (c == '%') {
if (i + 1 == pattern.size()) {

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.

[P2] Preserve wildcard parity with an explicit backslash escape

This leaves a supported trailing-wildcard form outside the fix. With a one-byte backslash as the explicit escape, pattern bytes [0x5c, 0x5c, 0x25] mean a literal backslash followed by wildcard %, but replace_pattern_by_escape first collapses the pair to [0x5c, 0x25]. Downstream fast-path recognition can then classify % as a literal, and the regex fallback likewise consumes it as escaped, so the pattern no longer has an open literal-backslash prefix. The normalization bug predates this branch, but both constant and nonconstant three-argument LIKE paths remain incorrect. Please preserve the original default-backslash representation (or otherwise retain escape parity), and add coverage showing that a literal-backslash prefix followed by % remains open.

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.

这个别的pr 修

@csun5285
csun5285 force-pushed the fix-DORIS-28979-like-tail-anchor branch from 88cd134 to 93c7f5d Compare September 17, 2026 10:40
@csun5285

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. The \z exact-end anchor fixes terminal-newline and literal-* matching for valid UTF-8, but applying it after a genuine trailing % introduces a distinct full-tail performance regression. The added NOT LIKE row also does not cover the specialized opposite column-predicate path its surrounding pushdown comment implies.

Critical checkpoint conclusions:

  • Goal: Whole-value matching for closed LIKE patterns is corrected, including empty values, terminal newlines, literal regex metacharacters, and escaped %. A genuine terminal wildcard should remain open; M-1 identifies the resulting performance regression.
  • Scope/focus: The production change is small and focused. No additional user review focus was provided.
  • Concurrency: No new concurrency is introduced. Function state remains thread-local, and each pushed predicate owns separate cloned Hyperscan scratch state.
  • Lifecycle/static initialization: No new special lifecycle, ownership cycle, or cross-TU static initialization is introduced.
  • Configuration: No configuration item is added or changed.
  • Compatibility: No function symbol, storage format, wire protocol, or rolling-upgrade contract changes.
  • Parallel paths: Constant Hyperscan, nonconstant/fallback RE2, scalar/vector fast paths, cloned storage pushdown, generic NOT LIKE expression pushdown, and json_search reuse were traced. M-1 affects regex paths with a real trailing %; M-2 records that the NOT LIKE query misses LikeColumnPredicate(opposite=true).
  • Special conditions: Empty patterns, leading/interior/trailing and repeated %, _, embedded/terminal newlines, literal *, escaped %, default/custom escapes, and valid UTF-8 multibyte characters were checked. Existing invalid-byte and explicit-backslash concerns are already covered by prior inline threads and were not duplicated.
  • Tests: The BE matrix covers constant/nonconstant argument combinations, and the regression suite covers direct execution plus positive specialized pushdown. Checked-in outputs are deterministic and consistent with the fixture. The NOT LIKE row is generic expression coverage rather than specialized predicate-clone coverage. CI skipped the build/test job for this head, and the review contract prohibited local builds or test execution, so this conclusion is static-only.
  • Observability: No new observability surface is needed for this local matcher change.
  • Transactions/persistence/data writes: Not applicable; no metadata, EditLog, transaction, or storage write path changes.
  • FE/BE variable propagation: Not applicable; no new cross-layer variable is introduced.
  • Performance: M-1 changes successful regex-path trailing-wildcard matches from prefix-bounded callback termination to a full-value scan.
  • Other issues: M-2 is a P3 test-description/coverage gap. No other distinct correctness, null-handling, error-propagation, compatibility, or performance issue remained after two converged review rounds.

re_pattern->append("$");
}
// `\z` is the end of the value in both Hyperscan and RE2
re_pattern->append("\\z");

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.

[P2] Keep a genuine trailing wildcard open

Appending \z unconditionally makes a regex-requiring pattern such as a_b% compile as ^a.b.*\z. Doris's Hyperscan callback stops scanning at the first reported match, so the previous open-tail form can finish after the required prefix, while the new end anchor cannot report until it has traversed the entire value. On a long valid string beginning with axb, this turns a prefix-bounded match into an O(value length) scan; the scalar fallback and cloned pushdown state receive the same unnecessary constraint. Hyperscan documents that callbacks expose match end offsets and may halt a partially completed scan. Please omit the tail anchor when the final LIKE token is an unescaped % (while retaining \z for literal * and escaped %) and update the shape coverage accordingly.

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.

a_b% compile as ^a.b

qt_pushdown_literal_star """
select id from test_like_whole_string_match where s like 'a_*' order by id
"""
qt_pushdown_not_literal_star """

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.

[P3] Do not present this as specialized NOT LIKE pushdown coverage

Nereids sends this as CompoundPredicate(NOT, LIKE(...)). _normalize_predicate checks the NOT node's direct children first; child zero is the LIKE function rather than the slot, so it returns before _normalize_function_filters can build LikeColumnPredicate(opposite=true) and clone the matcher state. On this DUP_KEYS table the whole expression may still use generic expression pushdown, so the result is valid NOT LIKE behavior coverage, but it does not cover the specialized path implied by the surrounding comment. Please rename or move this case accordingly. If specialized NOT LIKE pushdown is enabled later, add focused path tests together with nullable handling—the current opposite predicate retains NULL rows and cannot safely replace the residual expression by itself.

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.

已修改

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 63.51% (29570/46562)
Line Coverage 48.24% (307978/638482)
Region Coverage 43.86% (248664/566987)
Branch Coverage 45.39% (115536/254554)

LIKE has to match the whole value, but both engines that evaluate the
converted pattern search for a match anywhere in the value, so the
pattern carries the anchors itself. The tail anchor was `$`, which
Hyperscan reads the PCRE way: it also matches right before a newline
that ends the value. A value of 'acb' followed by a line feed therefore
matched LIKE 'a_b', and a filter on such a column returned extra rows.
RE2, used when Hyperscan cannot compile the pattern, treats `$` as the
end of the value, so the two engines disagreed on the same pattern.
Use `\z`, which is the end of the value in both.

The tail anchor was also dropped whenever the produced regex ended with
'*'. That check is meant to detect the `.*` expanded from a trailing
`%`, but an escaped literal `*` ends the regex with the same character,
so LIKE 'a_*' lost its anchor and matched 'ab*xyz'. Decide it from the
pattern instead: a `%` in the last position returns right away, which
leaves the regex unanchored and skips the redundant `.*`, while every
other pattern gets the anchor. Keeping the tail open also matters for
RE2: anchoring a trailing `%` as `^a.b.*\z` makes `.*` run to the end
of the value, which costs 1.9ms on a 1MB value against 55ns unanchored.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@csun5285
csun5285 force-pushed the fix-DORIS-28979-like-tail-anchor branch from 93c7f5d to ad1cd80 Compare September 17, 2026 13:37
@csun5285

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.

Automated review conclusion: no new valuable findings on ad1cd80f4e369cc95d77e941908fbfc16f6820d6.

Critical checkpoint conclusions:

  • Goal and proof: the change replaces Hyperscan's newline-permissive $ tail with exact end-of-value \z, leaves a genuine terminal % open, and still anchors a literal trailing * or escaped %. The unit matrix, direct shape assertions, and ordered regression expectations cover the changed outcomes across constant, nonconstant, shortcut, and positive pushdown paths.
  • Scope and clarity: the implementation is focused on one converter plus its BE unit and regression coverage. No unrelated source changes are present.
  • Error handling, memory, concurrency, and lifecycle: no new ignored Status, tracked allocation, thread, lock, or global/static lifecycle is introduced. Function state remains thread-local, and LikeColumnPredicate rebuilds each matcher with independent Hyperscan scratch before concurrent scan use.
  • Configuration and compatibility: no configuration, FE/BE protocol, persisted metadata, storage format, function symbol, or rolling-upgrade behavior changes. Both Hyperscan and RE2 support \z; the same converter and dot-newline semantics are used by constant Hyperscan, row-varying RE2, and cloned pushdown state.
  • Parallel paths and special conditions: escape processing runs before the terminal-% return, so default escape parity and non-backslash custom escapes retain the intended literal/wildcard distinction. Fast paths agree with the regex path. The known explicit-backslash custom-escape normalization concern remains covered by the existing inline thread and is not duplicated here.
  • Test coverage and results: check_function_all_arg_comb exercises constant and nonconstant argument forms, the shape test checks emitted regexes, and the DUP_KEYS positive filters reach LikeColumnPredicate cloning. Regression queries are ordered and the .out rows are internally correct. The corrected NOT LIKE case accurately states that it remains generic rather than specialized pushdown.
  • Observability, transactions, data writes, and cross-process variables: not applicable to this local expression-matching correction; no new logging or metrics are needed.
  • Performance and other risks: omitting .*\z for a real trailing % preserves prefix-bounded termination and avoids a whole-value scan. No additional hot-path copy or allocation was introduced. A bounded escape/token review found no distinct issue beyond the existing duplicate-fenced threads.

Verification status: static-only. The review contract prohibited builds and tests. Current GitHub checks show formatting/license-style success but do not provide functional-test proof for this head, so the added test results were reviewed rather than executed here.

User focus: no additional user-provided focus was supplied; the complete four-file diff was reviewed.

Opinion: no new blocking issue or inline comment is warranted beyond the existing review context.

@csun5285

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17623	3916	4008	3916
q2	2278	349	336	336
q3	10043	1385	806	806
q4	4680	483	345	345
q5	7663	843	545	545
q6	178	181	142	142
q7	751	781	592	592
q8	9299	1651	1516	1516
q9	5419	4217	4201	4201
q10	6799	1631	1379	1379
q11	439	270	246	246
q12	641	419	303	303
q13	18088	2643	2002	2002
q14	259	255	232	232
q15	q16	736	719	672	672
q17	1806	1161	973	973
q18	6410	5592	5562	5562
q19	1207	1289	984	984
q20	490	404	264	264
q21	5354	3105	2690	2690
q22	466	368	314	314
Total cold run time: 100629 ms
Total hot run time: 28020 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4695	4930	4625	4625
q2	826	600	607	600
q3	4946	5193	4716	4716
q4	2272	2362	1470	1470
q5	4617	4400	4528	4400
q6	233	180	140	140
q7	1825	1722	1502	1502
q8	2432	2195	2073	2073
q9	7397	7337	7272	7272
q10	4280	4306	3883	3883
q11	550	387	342	342
q12	706	713	506	506
q13	2272	2642	1999	1999
q14	271	269	253	253
q15	q16	677	688	614	614
q17	7383	6730	6660	6660
q18	12496	11005	11833	11005
q19	1090	1043	1028	1028
q20	2214	2192	1905	1905
q21	5472	4593	4656	4593
q22	512	474	394	394
Total cold run time: 67166 ms
Total hot run time: 59980 ms

@hello-stephen

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

query5	4324	601	466	466
query6	440	185	161	161
query7	4834	527	286	286
query8	312	169	164	164
query9	8799	4020	3983	3983
query10	455	331	267	267
query11	5877	2159	2056	2056
query12	155	99	101	99
query13	1261	590	412	412
query14	6560	4547	4263	4263
query14_1	4019	3981	3971	3971
query15	201	204	174	174
query16	987	457	402	402
query17	919	694	552	552
query18	2440	462	353	353
query19	200	199	144	144
query20	108	103	102	102
query21	224	136	120	120
query22	13096	13102	12843	12843
query23	15299	14598	13941	13941
query23_1	14063	14089	13950	13950
query24	7480	1683	1221	1221
query24_1	1229	1216	1219	1216
query25	569	470	375	375
query26	1251	302	168	168
query27	2715	546	330	330
query28	4587	1939	1974	1939
query29	1082	614	485	485
query30	321	240	203	203
query31	884	819	639	639
query32	146	102	94	94
query33	530	327	247	247
query34	1237	1065	631	631
query35	722	753	644	644
query36	835	793	702	702
query37	153	101	87	87
query38	1827	1774	1676	1676
query39	706	679	656	656
query39_1	662	665	654	654
query40	221	121	105	105
query41	73	70	69	69
query42	94	91	93	91
query43	342	349	306	306
query44	1326	705	699	699
query45	193	182	174	174
query46	1070	1181	707	707
query47	1471	1515	1409	1409
query48	392	394	300	300
query49	619	413	322	322
query50	960	353	239	239
query51	10508	10407	10367	10367
query52	83	82	72	72
query53	247	249	189	189
query54	244	198	184	184
query55	81	75	68	68
query56	225	218	233	218
query57	1478	1458	1374	1374
query58	250	217	214	214
query59	1979	2044	1796	1796
query60	270	240	224	224
query61	151	141	150	141
query62	392	322	262	262
query63	223	173	172	172
query64	2906	1019	851	851
query65	3997	3954	3940	3940
query66	1811	422	295	295
query67	22695	20112	19751	19751
query68	3594	1468	900	900
query69	414	307	262	262
query70	936	877	866	866
query71	297	227	212	212
query72	3005	2503	2173	2173
query73	820	793	427	427
query74	4637	4460	4297	4297
query75	2277	2270	1926	1926
query76	2395	1127	692	692
query77	361	393	288	288
query78	9192	9104	8551	8551
query79	1328	1165	722	722
query80	589	452	369	369
query81	481	279	235	235
query82	630	165	128	128
query83	359	277	249	249
query84	314	142	117	117
query85	824	465	374	374
query86	328	248	218	218
query87	1995	1954	1835	1835
query88	3666	2720	2704	2704
query89	350	282	247	247
query90	1907	186	186	186
query91	172	158	125	125
query92	105	82	94	82
query93	1505	1408	822	822
query94	504	300	305	300
query95	653	466	337	337
query96	1044	801	340	340
query97	2445	2442	2315	2315
query98	198	187	190	187
query99	739	718	609	609
Total cold run time: 243992 ms
Total hot run time: 153248 ms

@hello-stephen

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

query1	0.01	0.01	0.00
query2	0.10	0.05	0.05
query3	0.26	0.14	0.13
query4	1.60	0.14	0.14
query5	0.24	0.21	0.22
query6	1.22	0.95	0.89
query7	0.04	0.01	0.00
query8	0.05	0.04	0.04
query9	0.38	0.33	0.34
query10	0.55	0.57	0.56
query11	0.20	0.15	0.14
query12	0.18	0.16	0.15
query13	0.47	0.48	0.46
query14	0.94	0.95	0.95
query15	0.62	0.58	0.58
query16	0.33	0.33	0.31
query17	1.10	1.12	1.09
query18	0.22	0.20	0.20
query19	1.98	1.90	1.87
query20	0.02	0.01	0.01
query21	15.57	0.21	0.13
query22	4.92	0.05	0.05
query23	16.14	0.31	0.12
query24	2.93	0.43	0.33
query25	0.13	0.05	0.05
query26	0.71	0.20	0.14
query27	0.04	0.03	0.03
query28	3.54	0.75	0.36
query29	12.53	4.11	3.22
query30	0.29	0.15	0.16
query31	2.78	0.57	0.31
query32	3.22	0.59	0.50
query33	3.26	3.22	3.28
query34	15.53	3.95	3.27
query35	3.20	3.23	3.20
query36	0.55	0.44	0.41
query37	0.08	0.06	0.07
query38	0.05	0.04	0.04
query39	0.04	0.03	0.03
query40	0.19	0.15	0.15
query41	0.09	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.03	0.04
Total cold run time: 96.38 s
Total hot run time: 23.97 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 63.53% (29585/46565)
Line Coverage 48.29% (308367/638516)
Region Coverage 43.90% (248914/567013)
Branch Coverage 45.44% (115676/254582)

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 100% (0/0) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.30% (34405/45093)
Line Coverage 61.21% (386400/631244)
Region Coverage 57.53% (324904/564740)
Branch Coverage 58.38% (148177/253793)

@yiguolei
yiguolei merged commit d24fafc into apache:master Sep 18, 2026
46 checks passed
github-actions Bot pushed a commit that referenced this pull request Sep 18, 2026
…#68133)

### What problem does this PR solve?

1. `LIKE 'a_b'` is converted to `^a.b\z`, not `^a.b$`. Hyperscan follows
PCRE, where `$` also matches right before a newline that ends the value,
so `^a.b$` wrongly matched 'acb\n'. `\z` is the end of the value in both
Hyperscan and RE2.

2. `LIKE 'a_b%'` is converted to `^a.b`, not `^a.b.*\z`. A trailing `%`
matches anything, and so does appending nothing. The anchored form would
force `.*` to consume the value to its end, and `.*` only matches valid
UTF-8, so RE2 would not match 'acb\xff' while Hyperscan still would.

3. `LIKE 'a_*'` is converted to `^a.\*\z`, not `^a.\*`. The tail anchor
used to be skipped whenever the produced regex ended with `*`, a check
meant to detect the `.*` expanded from a trailing `%`. An escaped
literal `*` ends the regex with the same character, so the pattern lost
its anchor entirely and `'ab*xyz'` matched. The decision now comes from
the position in the pattern instead of from the produced string.


Issue Number: close #xxx

Related PR: #xxx

Problem Summary:

### Release note

None

### Check List (For Author)

- Test <!-- At least one of them must be included. -->
    - [x] Regression test
    - [x] Unit Test
    - [ ] Manual test (add detailed scripts or steps below)
    - [ ] No need to test or manual test. Explain why:
- [ ] This is a refactor/code format and no logic has been changed.
        - [ ] Previous test can cover this change.
        - [ ] No code files have been changed.
        - [ ] Other reason <!-- Add your reason?  -->

- Behavior changed:
    - [ ] No.
    - [ ] Yes. <!-- Explain the behavior change -->

- Does this need documentation?
    - [ ] No.
- [ ] Yes. <!-- Add document PR link here. eg:
apache/doris-website#1214 -->

### Check List (For Reviewer who merge this PR)

- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label <!-- Add branch pick label that this PR
should merge into -->

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
yiguolei pushed a commit that referenced this pull request Sep 19, 2026
…s at the end #68133 (#68159)

Cherry-picked from #68133

Co-authored-by: Chenyang Sun <sunchenyang@selectdb.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants