From aaecc233b23291745eea18bd9ce1e53b019c30dc Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Fri, 10 Mar 2023 20:14:35 +0000 Subject: [PATCH] Disable logical expression optimizer for expression with aliases. Never use it with optimize_min_equality_disjunction_chain_length=0 --- src/Interpreters/LogicalExpressionsOptimizer.cpp | 9 ++++++--- .../25340_logical_optimizer_alias_bug.reference | 1 + .../0_stateless/25340_logical_optimizer_alias_bug.sql | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 tests/queries/0_stateless/25340_logical_optimizer_alias_bug.reference create mode 100644 tests/queries/0_stateless/25340_logical_optimizer_alias_bug.sql diff --git a/src/Interpreters/LogicalExpressionsOptimizer.cpp b/src/Interpreters/LogicalExpressionsOptimizer.cpp index 02594269f08..df0623ffe0b 100644 --- a/src/Interpreters/LogicalExpressionsOptimizer.cpp +++ b/src/Interpreters/LogicalExpressionsOptimizer.cpp @@ -119,7 +119,7 @@ void LogicalExpressionsOptimizer::collectDisjunctiveEqualityChains() bool found_chain = false; auto * function = to_node->as(); - if (function && function->name == "or" && function->children.size() == 1) + if (function && function->alias.empty() && function->name == "or" && function->children.size() == 1) { const auto * expression_list = function->children[0]->as(); if (expression_list) @@ -128,14 +128,14 @@ void LogicalExpressionsOptimizer::collectDisjunctiveEqualityChains() for (const auto & child : expression_list->children) { auto * equals = child->as(); - if (equals && equals->name == "equals" && equals->children.size() == 1) + if (equals && equals->alias.empty() && equals->name == "equals" && equals->children.size() == 1) { const auto * equals_expression_list = equals->children[0]->as(); if (equals_expression_list && equals_expression_list->children.size() == 2) { /// Equality expr = xN. const auto * literal = equals_expression_list->children[1]->as(); - if (literal) + if (literal && literal->alias.empty()) { auto expr_lhs = equals_expression_list->children[0]->getTreeHash(); OrWithExpression or_with_expression{function, expr_lhs, function->tryGetAlias()}; @@ -230,6 +230,9 @@ bool LogicalExpressionsOptimizer::mayOptimizeDisjunctiveEqualityChain(const Disj const auto & equalities = chain.second; const auto & equality_functions = equalities.functions; + if (settings.optimize_min_equality_disjunction_chain_length == 0) + return false; + /// For LowCardinality column, the dict is usually smaller and the index is relatively large. /// In most cases, merging OR-chain as IN is better than converting each LowCardinality into full column individually. /// For non-LowCardinality, we need to eliminate too short chains. diff --git a/tests/queries/0_stateless/25340_logical_optimizer_alias_bug.reference b/tests/queries/0_stateless/25340_logical_optimizer_alias_bug.reference new file mode 100644 index 00000000000..573541ac970 --- /dev/null +++ b/tests/queries/0_stateless/25340_logical_optimizer_alias_bug.reference @@ -0,0 +1 @@ +0 diff --git a/tests/queries/0_stateless/25340_logical_optimizer_alias_bug.sql b/tests/queries/0_stateless/25340_logical_optimizer_alias_bug.sql new file mode 100644 index 00000000000..5b13eea5e4b --- /dev/null +++ b/tests/queries/0_stateless/25340_logical_optimizer_alias_bug.sql @@ -0,0 +1,2 @@ +create table test_local (id UInt32, path LowCardinality(String)) engine = MergeTree order by id; +WITH ((position(path, '/a') > 0) AND (NOT (position(path, 'a') > 0))) OR (path = '/b') OR (path = '/b/') as alias1 SELECT max(alias1) FROM remote('127.0.0.{1,2}', currentDatabase(), test_local) WHERE (id = 299386662);