You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by yi...@apache.org on 2026/05/29 03:24:59 UTC

(doris) branch branch-4.1 updated: branch-4.1 [fix](match) Allow MATCH on aliased variant subcolumns (#63811)

This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new d959ea0ae44 branch-4.1 [fix](match) Allow MATCH on aliased variant subcolumns (#63811)
d959ea0ae44 is described below

commit d959ea0ae44d0edbe68c79dba08735614edf3447
Author: lihangyu <li...@selectdb.com>
AuthorDate: Fri May 29 11:24:52 2026 +0800

    branch-4.1 [fix](match) Allow MATCH on aliased variant subcolumns (#63811)
    
    cherry-pick #63772
---
 .../rules/rewrite/CheckMatchExpression.java        |  7 ++--
 .../rules/rewrite/CheckMatchExpressionTest.java    | 45 ++++++++++++++++++++++
 .../rules/rewrite/VariantPruningLogicTest.java     | 29 ++++++++++++++
 3 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/CheckMatchExpression.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/CheckMatchExpression.java
index feaad409995..8f0ad8706f3 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/CheckMatchExpression.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/CheckMatchExpression.java
@@ -20,6 +20,7 @@ package org.apache.doris.nereids.rules.rewrite;
 import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
+import org.apache.doris.nereids.trees.expressions.Alias;
 import org.apache.doris.nereids.trees.expressions.Cast;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.Match;
@@ -49,7 +50,7 @@ public class CheckMatchExpression extends OneRewriteRuleFactory {
         for (Expression expr : expressions) {
             if (expr instanceof Match) {
                 Match matchExpression = (Match) expr;
-                SlotReference slotReference = getSlotFromSlotOrCastChain(matchExpression.left());
+                SlotReference slotReference = getSlotFromSlotCastOrAliasChain(matchExpression.left());
                 if (slotReference == null
                         || !(matchExpression.right() instanceof Literal)) {
                     throw new AnalysisException(String.format("Only support match left operand is SlotRef,"
@@ -65,9 +66,9 @@ public class CheckMatchExpression extends OneRewriteRuleFactory {
         return filter;
     }
 
-    private SlotReference getSlotFromSlotOrCastChain(Expression expression) {
+    private SlotReference getSlotFromSlotCastOrAliasChain(Expression expression) {
         Expression current = expression;
-        while (current instanceof Cast) {
+        while (current instanceof Cast || current instanceof Alias) {
             current = current.child(0);
         }
         return current instanceof SlotReference ? (SlotReference) current : null;
diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/CheckMatchExpressionTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/CheckMatchExpressionTest.java
index fbaa2d97a12..a127ed0e7c5 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/CheckMatchExpressionTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/CheckMatchExpressionTest.java
@@ -18,10 +18,13 @@
 package org.apache.doris.nereids.rules.rewrite;
 
 import org.apache.doris.nereids.exceptions.AnalysisException;
+import org.apache.doris.nereids.trees.expressions.Add;
+import org.apache.doris.nereids.trees.expressions.Alias;
 import org.apache.doris.nereids.trees.expressions.Cast;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.MatchAny;
 import org.apache.doris.nereids.trees.expressions.SlotReference;
+import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.StringLiteral;
 import org.apache.doris.nereids.trees.plans.logical.LogicalFilter;
 import org.apache.doris.nereids.trees.plans.logical.LogicalOlapScan;
@@ -79,6 +82,48 @@ class CheckMatchExpressionTest {
         Assertions.assertDoesNotThrow(() -> invokeCheck(match));
     }
 
+    @Test
+    void testAllowsAliasOnVariantSubcolumnMatch() {
+        SlotReference variantSubcolumnSlot = new SlotReference("response", VariantType.INSTANCE, true, Arrays.asList())
+                .withSubPath(Arrays.asList("trace_id"));
+        MatchAny match = new MatchAny(new Alias(variantSubcolumnSlot, "response.trace_id"),
+                new StringLiteral("doris"));
+
+        Assertions.assertDoesNotThrow(() -> invokeCheck(match));
+    }
+
+    @Test
+    void testAllowsCastOnAliasVariantSubcolumnMatch() {
+        SlotReference variantSubcolumnSlot = new SlotReference("response", VariantType.INSTANCE, true, Arrays.asList())
+                .withSubPath(Arrays.asList("trace_id"));
+        MatchAny match = new MatchAny(new Cast(new Alias(variantSubcolumnSlot, "response.trace_id"),
+                StringType.INSTANCE), new StringLiteral("doris"));
+
+        Assertions.assertDoesNotThrow(() -> invokeCheck(match));
+    }
+
+    @Test
+    void testAllowsAliasAndCastChainOnVariantSubcolumnMatch() {
+        SlotReference variantSubcolumnSlot = new SlotReference("response", VariantType.INSTANCE, true, Arrays.asList())
+                .withSubPath(Arrays.asList("trace_id"));
+        Expression left = new Cast(new Alias(new Cast(variantSubcolumnSlot, StringType.INSTANCE),
+                "response.trace_id"), StringType.INSTANCE);
+        MatchAny match = new MatchAny(left, new StringLiteral("doris"));
+
+        Assertions.assertDoesNotThrow(() -> invokeCheck(match));
+    }
+
+    @Test
+    void testRejectsAliasOnExpressionMatch() {
+        Expression aliasOnExpression = new Alias(new Add(new IntegerLiteral(1), new IntegerLiteral(2)),
+                "response.trace_id");
+        MatchAny match = new MatchAny(aliasOnExpression, new StringLiteral("doris"));
+
+        AnalysisException exception = Assertions.assertThrows(AnalysisException.class, () -> invokeCheck(match));
+        Assertions.assertTrue(exception.getMessage().contains("Only support match left operand is SlotRef"),
+                exception.getMessage());
+    }
+
     private void invokeCheck(Expression expression) throws Throwable {
         LogicalOlapScan scan = PlanConstructor.newLogicalOlapScan(0, "t1", 0);
         LogicalFilter<LogicalOlapScan> filter = new LogicalFilter<>(ImmutableSet.of(expression), scan);
diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/VariantPruningLogicTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/VariantPruningLogicTest.java
index cba05d26a93..6a23519e069 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/VariantPruningLogicTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/VariantPruningLogicTest.java
@@ -17,7 +17,10 @@
 
 package org.apache.doris.nereids.rules.rewrite;
 
+import org.apache.doris.analysis.Expr;
+import org.apache.doris.analysis.MatchPredicate;
 import org.apache.doris.analysis.SlotDescriptor;
+import org.apache.doris.analysis.SlotRef;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.common.Pair;
 import org.apache.doris.nereids.NereidsPlanner;
@@ -240,4 +243,30 @@ public class VariantPruningLogicTest extends TestWithFeService {
         accessPath.data_access_path = new TDataAccessPath(ImmutableList.copyOf(path));
         return accessPath;
     }
+
+    @Test
+    public void testMatchOnDotVariantSubColumnUsesSlotRefInScanPredicate() throws Exception {
+        String sql = "select id from variant_tbl "
+                + "where cast(v.trace_id as string) match_phrase_prefix 'abc'";
+        List<OlapScanNode> olapScanNodes = collectOlapScanNodes(sql);
+        Assertions.assertEquals(1, olapScanNodes.size());
+
+        List<MatchPredicate> matchPredicates = new ArrayList<>();
+        Expr.collectList(olapScanNodes.get(0).getConjuncts(), MatchPredicate.class, matchPredicates);
+        Assertions.assertEquals(1, matchPredicates.size());
+
+        Expr leftWithoutCast = matchPredicates.get(0).getChildWithoutCast(0);
+        Assertions.assertInstanceOf(SlotRef.class, leftWithoutCast, matchPredicates.get(0).toString());
+        SlotRef leftSlot = (SlotRef) leftWithoutCast;
+        Assertions.assertEquals(ImmutableList.of("trace_id"), leftSlot.getDesc().getSubColLables());
+    }
+
+    private List<OlapScanNode> collectOlapScanNodes(String sql) throws Exception {
+        NereidsPlanner planner = (NereidsPlanner) executeNereidsSql(sql).planner();
+        List<OlapScanNode> olapScanNodes = new ArrayList<>();
+        for (PlanFragment fragment : planner.getFragments()) {
+            olapScanNodes.addAll(fragment.getPlanRoot().collectInCurrentFragment(OlapScanNode.class::isInstance));
+        }
+        return olapScanNodes;
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org