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