This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.2
in repository https://gitbox.apache.org/repos/asf/doris.git
commit 5cef6f05dea5d2d2f71b27f4d70b4fc77410e98f
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Mon Sep 21 10:11:27 2026 +0800
branch-4.1: [fix](varaint) Preserve variant sub-path order #67803 (#68284)
Cherry-picked from #67803
Co-authored-by: morrySnow <[email protected]>
---
.../rules/rewrite/VariantSubPathPruning.java | 20 +++---
.../rules/rewrite/PruneNestedColumnTest.java | 14 +++++
.../variant_p0/test_variant_sub_path_order.out | 11 ++++
.../variant_p0/test_variant_sub_path_order.groovy | 72 ++++++++++++++++++++++
4 files changed, 108 insertions(+), 9 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/VariantSubPathPruning.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/VariantSubPathPruning.java
index 82f71b9db29..3036a2ba4d9 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/VariantSubPathPruning.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/VariantSubPathPruning.java
@@ -331,10 +331,7 @@ public class VariantSubPathPruning implements
CustomRewriter {
} else {
pushDownExpr = constExpr;
}
- for (int sp = entry.getKey().size() - 1; sp >= 0;
sp--) {
- VarcharLiteral path = new
VarcharLiteral(entry.getKey().get(sp));
- pushDownExpr = new ElementAt(pushDownExpr, path);
- }
+ pushDownExpr = constructElementAt(pushDownExpr,
entry.getKey());
constExprs.get(j).add(new Alias(pushDownExpr));
}
@@ -609,11 +606,7 @@ public class VariantSubPathPruning implements
CustomRewriter {
Set<List<String>> subPaths = context.slotToSubPathsMap
.get((SlotReference) projection.toSlot());
for (List<String> subPath : subPaths) {
- Expression pushDownExpr = child;
- for (int i = subPath.size() - 1; i >= 0; i--) {
- VarcharLiteral path = new VarcharLiteral(subPath.get(i));
- pushDownExpr = new ElementAt(pushDownExpr, path);
- }
+ Expression pushDownExpr = constructElementAt(child, subPath);
Alias alias = new Alias(pushDownExpr);
newProjections.add(alias);
subPathToSlot.put(subPath, (SlotReference) alias.toSlot());
@@ -780,6 +773,15 @@ public class VariantSubPathPruning implements
CustomRewriter {
}
}
+ /** Build nested ElementAt expressions from a canonical root-to-leaf
sub-path. */
+ protected static Expression constructElementAt(Expression root,
List<String> subPath) {
+ Expression result = root;
+ for (String path : subPath) {
+ result = new ElementAt(result, new VarcharLiteral(path));
+ }
+ return result;
+ }
+
protected static Pair<SlotReference, List<String>>
extractSlotToSubPathPair(ElementAt elementAt) {
List<String> subPath = Lists.newArrayList();
while (true) {
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PruneNestedColumnTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PruneNestedColumnTest.java
index cd0e08327b2..71accf14247 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PruneNestedColumnTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PruneNestedColumnTest.java
@@ -1102,6 +1102,20 @@ public class PruneNestedColumnTest extends
TestWithFeService implements MemoPatt
);
}
+ @Test
+ public void testVariantSubPathConstructionOrder() {
+ SlotReference root = new SlotReference("v", VariantType.INSTANCE);
+ List<String> subPath = ImmutableList.of("a", "b", "c");
+
+ Expression expression = VariantSubPathPruning.constructElementAt(root,
subPath);
+
+ Assertions.assertInstanceOf(ElementAt.class, expression);
+ Pair<SlotReference, List<String>> extracted =
VariantSubPathPruning.extractSlotToSubPathPair(
+ (ElementAt) expression);
+ Assertions.assertEquals(root, extracted.first);
+ Assertions.assertEquals(subPath, extracted.second);
+ }
+
@Test
public void testDataTypeAccessTree() {
List<Pair<SlotReference, DataTypeAccessTree>> trees =
getDataTypeAccessTrees(
diff --git a/regression-test/data/variant_p0/test_variant_sub_path_order.out
b/regression-test/data/variant_p0/test_variant_sub_path_order.out
new file mode 100644
index 00000000000..94e3d6d4e25
--- /dev/null
+++ b/regression-test/data/variant_p0/test_variant_sub_path_order.out
@@ -0,0 +1,11 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !union_constant_sub_path --
+1 table 1
+2 constant 1
+
+-- !project_sub_path --
+1 1
+
+-- !union_constant_sub_path_with_nested_pruning --
+1 table 1
+2 constant 1
diff --git
a/regression-test/suites/variant_p0/test_variant_sub_path_order.groovy
b/regression-test/suites/variant_p0/test_variant_sub_path_order.groovy
new file mode 100644
index 00000000000..925c1f628c5
--- /dev/null
+++ b/regression-test/suites/variant_p0/test_variant_sub_path_order.groovy
@@ -0,0 +1,72 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("test_variant_sub_path_order", "p0") {
+ sql "DROP TABLE IF EXISTS variant_sub_path_order"
+ sql """
+ CREATE TABLE variant_sub_path_order (
+ id INT NOT NULL,
+ v VARIANT NULL
+ ) ENGINE = OLAP
+ DUPLICATE KEY(id)
+ DISTRIBUTED BY HASH(id) BUCKETS 1
+ PROPERTIES ("replication_num" = "1")
+ """
+ sql """
+ INSERT INTO variant_sub_path_order VALUES
+ (1, '{"a":{"b":1},"b":{"a":2}}')
+ """
+
+ sql "SET experimental_enable_prune_nested_column = false"
+
+ order_qt_union_constant_sub_path """
+ WITH u AS (
+ SELECT id, 'table' AS branch_name, v AS c
+ FROM variant_sub_path_order
+ UNION ALL
+ SELECT 2 AS id, 'constant' AS branch_name,
+ CAST('{"a":{"b":1},"b":{"a":2}}' AS VARIANT) AS c
+ )
+ SELECT id, branch_name, CAST(c['a']['b'] AS INT) AS value
+ FROM u
+ ORDER BY id
+ """
+
+ order_qt_project_sub_path """
+ SELECT id, CAST(c['a']['b'] AS INT) AS value
+ FROM (
+ SELECT id, IF(id > 0, v, CAST('{}' AS VARIANT)) AS c
+ FROM variant_sub_path_order
+ ) projected
+ ORDER BY id
+ """
+
+ sql "SET experimental_enable_prune_nested_column = true"
+
+ order_qt_union_constant_sub_path_with_nested_pruning """
+ WITH u AS (
+ SELECT id, 'table' AS branch_name, v AS c
+ FROM variant_sub_path_order
+ UNION ALL
+ SELECT 2 AS id, 'constant' AS branch_name,
+ CAST('{"a":{"b":1},"b":{"a":2}}' AS VARIANT) AS c
+ )
+ SELECT id, branch_name, CAST(c['a']['b'] AS INT) AS value
+ FROM u
+ ORDER BY id
+ """
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]