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]

Reply via email to