From e47d7e85bab148dc72d5598a6121e0cfd77edd86 Mon Sep 17 00:00:00 2001 From: Ilya Golshtein Date: Tue, 13 Oct 2026 16:38:53 +0000 Subject: [PATCH 1/2] Fix for Aliases and Lazy Materialization Signed-off-by: Ilya Golshtein --- .../Optimizations/optimizeLazyMaterialization.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Processors/QueryPlan/Optimizations/optimizeLazyMaterialization.cpp b/src/Processors/QueryPlan/Optimizations/optimizeLazyMaterialization.cpp index a2f5275fd0f1..dcb123e82ad2 100644 --- a/src/Processors/QueryPlan/Optimizations/optimizeLazyMaterialization.cpp +++ b/src/Processors/QueryPlan/Optimizations/optimizeLazyMaterialization.cpp @@ -38,6 +38,7 @@ static void removeUsedColumnNames( String filter_name = {}) { const auto & actions_outputs = actions.getOutputs(); + NameSet passthrough_inputs; for (const auto * output_node : actions_outputs) { @@ -52,6 +53,16 @@ static void removeUsedColumnNames( if (!node) continue; + /// The lazy reader maps each source column to a single output name. If an input + /// is forwarded more than once (for example, both a column and its alias), read + /// it eagerly so all outputs contain real data and do not duplicate lazy row coordinates. + if (node->type == ActionsDAG::ActionType::INPUT && !passthrough_inputs.insert(node->result_name).second) + { + const auto it = alias_index.find(node->result_name); + if (it != alias_index.end()) + lazily_read_column_name_set.erase(it->second); + } + if (node->type == ActionsDAG::ActionType::FUNCTION || node->type == ActionsDAG::ActionType::ARRAY_JOIN || (!filter_name.empty() && filter_name == output_node->result_name)) { From a2ea700de280a7542775a8cee7c4195e1cecd7c5 Mon Sep 17 00:00:00 2001 From: Ilya Golshtein Date: Tue, 13 Oct 2026 19:49:08 +0000 Subject: [PATCH 2/2] test added Signed-off-by: Ilya Golshtein --- ...317_aliases_and_lazy_materialization.reference | 10 ++++++++++ .../05317_aliases_and_lazy_materialization.sql | 15 +++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/queries/0_stateless/05317_aliases_and_lazy_materialization.reference create mode 100644 tests/queries/0_stateless/05317_aliases_and_lazy_materialization.sql diff --git a/tests/queries/0_stateless/05317_aliases_and_lazy_materialization.reference b/tests/queries/0_stateless/05317_aliases_and_lazy_materialization.reference new file mode 100644 index 000000000000..538e1e60ef5c --- /dev/null +++ b/tests/queries/0_stateless/05317_aliases_and_lazy_materialization.reference @@ -0,0 +1,10 @@ +99 99 +98 98 +97 97 +96 96 +95 95 +94 94 +93 93 +92 92 +91 91 +90 90 diff --git a/tests/queries/0_stateless/05317_aliases_and_lazy_materialization.sql b/tests/queries/0_stateless/05317_aliases_and_lazy_materialization.sql new file mode 100644 index 000000000000..178ace2a6471 --- /dev/null +++ b/tests/queries/0_stateless/05317_aliases_and_lazy_materialization.sql @@ -0,0 +1,15 @@ +-- Tags: no-random-settings + +SET query_plan_optimize_lazy_materialization = 1; +SET query_plan_max_limit_for_lazy_materialization = 10; +SET enable_analyzer = 1; + +DROP TABLE IF EXISTS t_str; +CREATE TABLE t_str (id UInt64, ts DateTime, s String, s_alias String ALIAS s) +ENGINE = MergeTree ORDER BY id; +INSERT INTO t_str SELECT number, toDateTime('2026-01-01 00:00:00') + number, toString(number) FROM numbers(100); + +-- Selecting both the source column and its alias must materialize both outputs. +SELECT s, s_alias FROM t_str ORDER BY ts DESC LIMIT 10; + +DROP TABLE t_str;