From eb21afa2aaccd7e80efae72fdf3eb63ed9032f27 Mon Sep 17 00:00:00 2001 From: daidai Date: Thu, 16 Jul 2026 17:27:40 +0800 Subject: [PATCH] [fix](topn) Resolve topn lazy materialization column indexes for aliases Issue Number: None Related PR: None Problem Summary: TopN lazy materialization resolved deferred column indexes with output slot names. Queries that renamed Hive columns therefore produced -1 indexes, and external row-id fetch could fill those columns with NULL when positional reading was used. Resolve the index from the already traced original base column so the descriptor and index share one column identity. Add a focused planner unit test and a Hive ORC Explain regression for the alias path. Fix incorrect NULL values from aliased external-table columns when TopN lazy materialization is used. --- .../physical/PhysicalLazyMaterialize.java | 2 +- .../postprocess/TopnLazyMaterializeTest.java | 25 +++++++++++++++++++ .../hive/test_hive_topn_lazy_mat.groovy | 9 +++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalLazyMaterialize.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalLazyMaterialize.java index e3be64e577c617..2eb9bc0a07d030 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalLazyMaterialize.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalLazyMaterialize.java @@ -180,7 +180,7 @@ public PhysicalLazyMaterialize(CHILD_TYPE child, } outputBuilder.add(outputSlot); lazyColumnForRel.add(originalColumn); - lazyBaseColumnIdxForRel.add(relationTable.getBaseColumnIdxByName(lazySlot.getName())); + lazyBaseColumnIdxForRel.add(relationTable.getBaseColumnIdxByName(originalColumn.getName())); lazySlotLocationForRel.add(loc); loc++; } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/TopnLazyMaterializeTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/TopnLazyMaterializeTest.java index cb5045ad76dd8c..ee0942c30716d9 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/TopnLazyMaterializeTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/TopnLazyMaterializeTest.java @@ -24,6 +24,8 @@ import org.apache.doris.nereids.glue.translator.PhysicalPlanTranslator; import org.apache.doris.nereids.glue.translator.PlanTranslatorContext; import org.apache.doris.nereids.processor.post.PlanPostProcessors; +import org.apache.doris.nereids.trees.plans.Plan; +import org.apache.doris.nereids.trees.plans.physical.PhysicalLazyMaterialize; import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan; import org.apache.doris.nereids.util.PlanChecker; import org.apache.doris.planner.MaterializationNode; @@ -117,6 +119,29 @@ public void testNestedColumnAccessPathInLazyMaterialize() throws Exception { ColumnAccessPath.data(ImmutableList.of("user_profile", "professional", "skills")))); } + @Test + public void testLazyBaseColumnIndexUsesOriginalColumnNameForAlias() throws Exception { + this.createTable("create table lazy_materialize_alias_tbl(" + + "sort_col int, lazy_col int) " + + "duplicate key(sort_col) distributed by hash(sort_col) buckets 1 " + + "properties('replication_num' = '1')"); + String sql = "select lazy_col as lazy_alias from lazy_materialize_alias_tbl " + + "order by sort_col limit 1"; + + PlanChecker checker = PlanChecker.from(connectContext) + .analyze(sql) + .rewrite() + .implement(); + PhysicalPlan plan = checker.getPhysicalPlan(); + plan = new PlanPostProcessors(checker.getCascadesContext()).process(plan); + + List> materializeNodes = plan.collectToList( + node -> node instanceof PhysicalLazyMaterialize); + Assertions.assertEquals(1, materializeNodes.size(), plan.treeString()); + Assertions.assertEquals(ImmutableList.of(ImmutableList.of(1)), + materializeNodes.get(0).getLazyBaseColumnIndices()); + } + @Test public void testLightSchemaChangeFalse() throws Exception { this.createTable("create table tm_lsc_false (k int, v int) duplicate key(k) " diff --git a/regression-test/suites/external_table_p0/hive/test_hive_topn_lazy_mat.groovy b/regression-test/suites/external_table_p0/hive/test_hive_topn_lazy_mat.groovy index ce0890fbccc1f6..2ef76dc8bd080d 100644 --- a/regression-test/suites/external_table_p0/hive/test_hive_topn_lazy_mat.groovy +++ b/regression-test/suites/external_table_p0/hive/test_hive_topn_lazy_mat.groovy @@ -223,6 +223,15 @@ suite("test_hive_topn_lazy_mat", "p0,external") { contains("row_ids: [__DORIS_GLOBAL_ROWID_COL__orc_topn_lazy_mat_table]") } + // Output aliases must not be used to resolve physical Hive column indices. + explain { + sql "select name as lazy_alias from orc_topn_lazy_mat_table order by id limit 10;" + contains("VMaterializeNode") + contains("column_descs_lists[[`name` text NULL]]") + contains("column_idxs_lists: [[1]]") + contains("row_ids: [__DORIS_GLOBAL_ROWID_COL__orc_topn_lazy_mat_table]") + } + explain { sql """ select a.name,length(a.name),a.value,b.*,a.* from parquet_topn_lazy_mat_table as a join orc_topn_lazy_mat_table as b on a.id = b.id order by a.name limit 10 """