You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by en...@apache.org on 2026/04/17 03:44:56 UTC

(doris) branch master updated: [fix](fe) Fix view columns losing colUniqueId in lazy materialization (#62533)

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

englefly pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 742c046ac17 [fix](fe) Fix view columns losing colUniqueId in lazy materialization (#62533)
742c046ac17 is described below

commit 742c046ac17acd5d0ad6b3f096c2db432a62a450
Author: minghong <zh...@selectdb.com>
AuthorDate: Fri Apr 17 11:44:48 2026 +0800

    [fix](fe) Fix view columns losing colUniqueId in lazy materialization (#62533)
    
    ### What problem does this PR solve?
    
    When querying columns through a view with TopN + lazy materialization,
    SlotReference.withOneLevelTableAndColumnAndQualifier() incorrectly
    replaced
    originalColumn with the view's Column object (which has uniqueId=-1).
    This caused colUniqueId=-1 in the physical plan, making BE unable to
    find
    the column during the two-phase read (lazy materialize) fetch, resulting
    in
    "returned block with row count 0 not match request row id count" error.
    
    The fix preserves the original base table Column (which carries the
    correct
        uniqueId) instead of overwriting it with the view's Column.
---
 .../doris/nereids/trees/expressions/Alias.java     |  2 +-
 .../nereids/trees/expressions/SlotReference.java   |  2 +-
 .../nereids/trees/expressions/ExpressionTest.java  | 17 +++++
 .../query_p0/topn_lazy/lazy_materialize_view.out   | 13 ++++
 .../suites/mysql_compatibility_p0/metadata.groovy  |  4 +-
 .../topn_lazy/lazy_materialize_view.groovy         | 84 ++++++++++++++++++++++
 6 files changed, 118 insertions(+), 4 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Alias.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Alias.java
index cc0ed1d2447..edb416014a6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Alias.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Alias.java
@@ -99,7 +99,7 @@ public class Alias extends NamedExpression implements UnaryExpression {
                 slotReference != null ? ((SlotReference) child()).getOriginalTable().orElse(null) : null,
                 slotReference != null ? slotReference.getOriginalColumn().orElse(null) : null,
                 slotReference != null ? ((SlotReference) child()).getOneLevelTable().orElse(null) : null,
-                slotReference != null ? slotReference.getOriginalColumn().orElse(null) : null,
+                slotReference != null ? slotReference.getOneLevelColumn().orElse(null) : null,
                 slotReference != null ? slotReference.getSubPath() : ImmutableList.of(), Optional.empty()
         );
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java
index cd8488318ce..77df137e97c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java
@@ -340,7 +340,7 @@ public class SlotReference extends Slot {
     @Override
     public Slot withOneLevelTableAndColumnAndQualifier(TableIf oneLevelTable, Column column, List<String> qualifier) {
         return new SlotReference(exprId, name, dataType, nullable, qualifier,
-                originalTable, column, oneLevelTable, column,
+                originalTable, originalColumn, oneLevelTable, column,
                 subPath, indexInSqlString);
     }
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/ExpressionTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/ExpressionTest.java
index cb43efb0b31..43ba8a637a1 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/ExpressionTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/ExpressionTest.java
@@ -17,6 +17,8 @@
 
 package org.apache.doris.nereids.trees.expressions;
 
+import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.PrimitiveType;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.CurrentDate;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.DaysAdd;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.UnixTimestamp;
@@ -26,6 +28,7 @@ import org.apache.doris.nereids.trees.expressions.literal.StringLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral;
 import org.apache.doris.nereids.types.IntegerType;
 
+import com.google.common.collect.ImmutableList;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -66,4 +69,18 @@ public class ExpressionTest {
                 new UnixTimestamp(), new IntegerLiteral(2)).containsNondeterministic());
 
     }
+
+    @Test
+    public void testAliasToSlotKeepsOneLevelColumn() {
+        SlotReference slotReference = new SlotReference(new ExprId(1), "k1", IntegerType.INSTANCE, true,
+                ImmutableList.of("test", "view_metadata"), null, new Column("k1", PrimitiveType.INT),
+                null, new Column("vk1", PrimitiveType.INT));
+
+        SlotReference aliasSlot = (SlotReference) new Alias(slotReference, "c2").toSlot();
+
+        Assertions.assertTrue(aliasSlot.getOriginalColumn().isPresent());
+        Assertions.assertTrue(aliasSlot.getOneLevelColumn().isPresent());
+        Assertions.assertEquals("k1", aliasSlot.getOriginalColumn().get().getName());
+        Assertions.assertEquals("vk1", aliasSlot.getOneLevelColumn().get().getName());
+    }
 }
diff --git a/regression-test/data/query_p0/topn_lazy/lazy_materialize_view.out b/regression-test/data/query_p0/topn_lazy/lazy_materialize_view.out
new file mode 100644
index 00000000000..90b9d05460f
--- /dev/null
+++ b/regression-test/data/query_p0/topn_lazy/lazy_materialize_view.out
@@ -0,0 +1,13 @@
+-- This file is automatically generated. You should know what you did if you want to edit this
+-- !view_lazy --
+aaa
+bbb
+
+-- !chain_view_lazy --
+aaa
+bbb
+
+-- !view_lazy_filter --
+bbb	200
+ccc	300
+
diff --git a/regression-test/suites/mysql_compatibility_p0/metadata.groovy b/regression-test/suites/mysql_compatibility_p0/metadata.groovy
index f6b303dbfd6..284347a6b97 100644
--- a/regression-test/suites/mysql_compatibility_p0/metadata.groovy
+++ b/regression-test/suites/mysql_compatibility_p0/metadata.groovy
@@ -63,8 +63,8 @@ suite ("metadata") {
     println viewMeta
 
     assertEquals("c1", viewMeta.getColumnName(1))
-    assertEquals("vk1", viewMeta.getColumnName(2))
-    assertEquals("vk1", viewMeta.getColumnName(3))
+    assertEquals("vk1", viewMeta.getColumnName(2),"viewMeta.getColumnName(2)")
+    assertEquals("vk1", viewMeta.getColumnName(3), "viewMeta.getColumnName(3)")
     assertEquals("k2", viewMeta.getColumnName(4))
     assertEquals("k2", viewMeta.getColumnName(5))
     assertEquals("c4", viewMeta.getColumnName(6))
diff --git a/regression-test/suites/query_p0/topn_lazy/lazy_materialize_view.groovy b/regression-test/suites/query_p0/topn_lazy/lazy_materialize_view.groovy
new file mode 100644
index 00000000000..8e58ddaa7cb
--- /dev/null
+++ b/regression-test/suites/query_p0/topn_lazy/lazy_materialize_view.groovy
@@ -0,0 +1,84 @@
+// 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("lazy_materialize_view") {
+    sql """
+        set enable_two_phase_read_opt = true;
+        set topn_opt_limit_threshold = 1000;
+        set topn_lazy_materialization_threshold = -1;
+    """
+
+    sql "drop table if exists lazy_mat_view_t"
+    sql """
+        CREATE TABLE lazy_mat_view_t (
+            k1 INT NOT NULL,
+            k2 INT NOT NULL,
+            v1 VARCHAR(100) NULL,
+            v2 INT NULL
+        )
+        DUPLICATE KEY(k1)
+        DISTRIBUTED BY HASH(k1) BUCKETS 1
+        PROPERTIES (
+            "replication_num" = "1"
+        );
+    """
+
+    sql """
+        insert into lazy_mat_view_t values
+        (1, 10, 'aaa', 100),
+        (2, 20, 'bbb', 200),
+        (3, 30, 'ccc', 300);
+    """
+
+    sql "sync"
+
+    sql "drop view if exists lazy_mat_view_v1"
+    sql "CREATE VIEW lazy_mat_view_v1 AS SELECT * FROM lazy_mat_view_t"
+
+    sql "drop view if exists lazy_mat_view_v2"
+    sql "CREATE VIEW lazy_mat_view_v2 AS SELECT * FROM lazy_mat_view_v1"
+
+    // lazy materialization through a single-level view
+    explain {
+        sql "select v1 from lazy_mat_view_v1 order by k1 limit 2"
+        contains "OPT TWO PHASE"
+    }
+
+    order_qt_view_lazy """
+        select v1 from lazy_mat_view_v1 order by k1 limit 2
+    """
+
+    // lazy materialization through a chained view (v2 -> v1 -> t)
+    explain {
+        sql "select v1 from lazy_mat_view_v2 order by k1 limit 2"
+        contains "OPT TWO PHASE"
+    }
+
+    order_qt_chain_view_lazy """
+        select v1 from lazy_mat_view_v2 order by k1 limit 2
+    """
+
+    // lazy materialization through view with filter
+    explain {
+        sql "select v1, v2 from lazy_mat_view_v1 where k2 > 10 order by k1 limit 2"
+        contains "OPT TWO PHASE"
+    }
+
+    order_qt_view_lazy_filter """
+        select v1, v2 from lazy_mat_view_v1 where k2 > 10 order by k1 limit 2
+    """
+}


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