airborne12 commented on code in PR #67918:
URL: https://github.com/apache/doris/pull/67918#discussion_r4047278959


##########
be/src/storage/index/inverted/token_filter/word_delimiter_filter.h:
##########
@@ -106,20 +120,29 @@ class WordDelimiterConcatenation {
 
     void append(const char* text, int32_t offset, int32_t length) {
         _buffer.append(text, offset, length);
+        auto source_byte_offsets = _filter.slice_source_byte_offsets(offset, 
offset + length);
+        if (!_source_byte_offsets.empty() && !source_byte_offsets.empty()) {
+            _source_byte_offsets.insert(_source_byte_offsets.end(), 
source_byte_offsets.begin() + 1,

Review Comment:
   Fixed in `2558085d88f6e815ff6775ce0c341a83fa1baef2`.
   
   I reproduced this with the native ASAN BE runner: the new 
`PinyinFilterTest.TestWordDelimiterConcatenationPreservesSourceGapsAndReset` 
failed on the previous implementation because `de` started at byte 3 instead of 
4. It covers both `catenate_words` and `catenate_all`, then resets the pipeline 
with another delimiter-separated input.
   
   Concatenation now preserves independent per-rune source end offsets 
alongside source starts, and Pinyin consumes those intervals. Removed 
delimiters therefore no longer force the preceding end and following start to 
share a boundary. The mapping remains opt-in, and reset clears both arrays. The 
test now returns `liu[0,3)` and `de[4,6)` and passes on reset/reuse.
   
   The official runner passed 178 tests across the related suites; after the 
final clang-tidy corrections, all 120 tests in the three affected suites passed 
again. The two custom-analyzer SQL suites and the existing IK SQL suite also 
passed on the task-owned native ASAN cluster.
   



##########
fe/fe-core/src/main/java/org/apache/doris/analysis/InvertedIndexUtil.java:
##########
@@ -423,17 +445,18 @@ public static boolean isAnalyzerMatched(Map<String, 
String> properties, String a
                     buildAnalyzerIdentity(properties));
         }
 
+        String resolvedAnalyzer = resolveAnalyzerName(normalizedAnalyzer);
         String preferredAnalyzer = 
InvertedIndexProperties.getPreferredAnalyzer(properties);
         if (!Strings.isNullOrEmpty(preferredAnalyzer)) {
-            return normalizedAnalyzer.equalsIgnoreCase(preferredAnalyzer);
+            return 
resolvedAnalyzer.equals(resolveAnalyzerName(preferredAnalyzer));
         }
 
         String parser = 
InvertedIndexProperties.getInvertedIndexParser(properties);
         if (Strings.isNullOrEmpty(parser)) {
-            return normalizedAnalyzer.equalsIgnoreCase("default")
-                    || 
normalizedAnalyzer.equalsIgnoreCase(INVERTED_INDEX_PARSER_NONE);
+            return resolvedAnalyzer.equals("default")
+                    || resolvedAnalyzer.equals(INVERTED_INDEX_PARSER_NONE);
         }
-        return normalizedAnalyzer.equalsIgnoreCase(parser);
+        return resolvedAnalyzer.equals(parser.trim().toLowerCase(Locale.ROOT));

Review Comment:
   Fixed in `2558085d88f6e815ff6775ce0c341a83fa1baef2`.
   
   I reproduced both selection failures with native tests. 
`InvertedIndexPropertiesTest.testExplicitBuiltinIkSelectsMatchingModeAndLowercase`
 selected the first smart/lowercase-disabled index rather than the default 
max-word index, and 
`InvertedIndexIteratorTest.MatchBindsDistinctIkModesAndLowercaseStates` 
collapsed the four physical configurations into one reader key. Both tests 
failed before the fix and now pass.
   
   FE matches an explicit built-in IK request to its effective default 
configuration and serializes that selected index's existing mode, lowercase, 
and outer character-filter fields. BE builds configuration-aware selection keys 
from those fields while retaining the original provider name. The BE test uses 
real MATCH predicate/configuration parsing and iterator selection, mocking only 
the physical reader boundary. It distinguishes all four states; additional 
guards cover outer filters and encoded-key collisions with legal policy names. 
No Thrift schema or stored index format changed.
   
   The normal SQL regression now includes the discriminating Chinese probe: 
explicit built-in IK matches the `清华` term in `清华大学`, while implicit smart 
selection does not. The uppercase probe is not claimed as proof of a 
lowercase-disabled runtime fix; existing IK internal lowercasing behavior is 
unchanged.
   
   The official FE runner passed 118 tests; the related BE runner passed 178 
tests, with 120 affected tests rerun successfully after the final source 
corrections. All three selected SQL suites passed on the task-owned native ASAN 
cluster.
   



##########
fe/fe-core/src/main/java/org/apache/doris/analysis/invertedindex/AnalyzerIdentityBuilder.java:
##########
@@ -154,43 +203,71 @@ private static String resolveComponentIdentity(String 
name, IndexPolicyTypeEnum
             return "";
         }
 
-        // Check if it's a built-in component
-        if (expectedType == IndexPolicyTypeEnum.TOKENIZER
-                && IndexPolicy.BUILTIN_TOKENIZERS.contains(name)) {
-            return name;
-        }
-
-        // For custom component, get its properties
+        // Existing named policies take precedence over built-ins for upgrade 
compatibility.
         try {
             Env env = Env.getCurrentEnv();
-            if (env == null || env.getIndexPolicyMgr() == null) {
-                return name;
-            }
-
-            IndexPolicy policy = env.getIndexPolicyMgr().getPolicyByName(name);
-            if (policy == null || policy.getType() != expectedType) {
-                return name;
-            }
-            if (policy.isInvalid()) {
-                return "invalid-policy:" + policy.getId() + ":" + 
policy.getName();
+            if (env != null && env.getIndexPolicyMgr() != null) {
+                IndexPolicy policy = 
env.getIndexPolicyMgr().getPolicyByName(name);
+                if (policy != null && policy.getType() == expectedType) {
+                    if (policy.isInvalid()) {
+                        return "invalid-policy:" + policy.getId() + ":" + 
policy.getName();
+                    }
+                    Map<String, String> props = policy.getProperties();
+                    if (props != null && !props.isEmpty()) {
+                        TreeMap<String, String> sortedProps = new 
TreeMap<>(props);
+                        String type = sortedProps.get(IndexPolicy.PROP_TYPE);
+                        String normalizedType = 
normalizeBuiltinComponentName(type, expectedType);
+                        if (normalizedType != null) {
+                            if ("empty".equals(normalizedType)) {
+                                return "";
+                            }
+                            if (sortedProps.size() == 1) {
+                                return normalizedType;
+                            }
+                            sortedProps.put(IndexPolicy.PROP_TYPE, 
normalizedType);
+                        }
+                        if (expectedType == IndexPolicyTypeEnum.TOKENIZER
+                                && 
"ngram".equals(sortedProps.get(IndexPolicy.PROP_TYPE))) {
+                            // This setting only limits policy creation; it 
does not change emitted tokens.
+                            sortedProps.remove(PROP_MAX_NGRAM_DIFF);
+                        }
+                        if (expectedType == IndexPolicyTypeEnum.CHAR_FILTER
+                                && 
"char_replace".equals(sortedProps.get(IndexPolicy.PROP_TYPE))) {
+                            String replacement = 
sortedProps.getOrDefault("replacement", " ");
+                            String pattern = canonicalizeCharReplacePattern(

Review Comment:
   Fixed in `2558085d88f6e815ff6775ce0c341a83fa1baef2`.
   
   The native identity test failed before the fix: a named `A -> a` character 
filter added a distinct identity to an IK analyzer even though the tokenizer 
absorbs that transformation. The native SQL CREATE reproduction also accepted 
the duplicate instead of reporting the expected same-analyzer error.
   
   Identity construction now resolves the actual tokenizer before 
canonicalizing named character filters and passes IK's downstream lowercase 
context into that step. It walks filters backward to determine whether a 
transformation is absorbed, but preserves their original order in the completed 
identity. After a meaningful intervening filter, earlier transformations are 
not incorrectly removed. Unit coverage includes resolved tokenizer 
aliases/shadowing and ordered filters.
   
   The official FE runner passed 118 tests, including the complete identity 
test class. The SQL regression covers both CREATE and ALTER duplicate rejection 
for both `ik_smart` and `ik_max_word`; the two new analyzer suites and the 
existing IK suite all passed against the task-owned native ASAN cluster.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to