Backport #62999 to 24.3: Fix optimize_rewrite_aggregate_function_with_if implicit cast

This commit is contained in:
robot-clickhouse 2024-04-30 03:10:30 +00:00
parent f46ef3bf05
commit 6284bbb1aa
5 changed files with 251 additions and 77 deletions

View File

@ -10,9 +10,10 @@
#include <Interpreters/Context.h> #include <Interpreters/Context.h>
#include <Analyzer/InDepthQueryTreeVisitor.h>
#include <Analyzer/ConstantNode.h> #include <Analyzer/ConstantNode.h>
#include <Analyzer/FunctionNode.h> #include <Analyzer/FunctionNode.h>
#include <Analyzer/InDepthQueryTreeVisitor.h>
#include <Analyzer/Utils.h>
namespace DB namespace DB
{ {
@ -52,17 +53,24 @@ public:
const auto & second_const_value = second_const_node->getValue(); const auto & second_const_value = second_const_node->getValue();
if (second_const_value.isNull() if (second_const_value.isNull()
|| (lower_name == "sum" && isInt64OrUInt64FieldType(second_const_value.getType()) && second_const_value.get<UInt64>() == 0 || (lower_name == "sum" && isInt64OrUInt64FieldType(second_const_value.getType()) && second_const_value.get<UInt64>() == 0
&& !function_node->getResultType()->isNullable())) && !if_node->getResultType()->isNullable()))
{ {
/// avg(if(cond, a, null)) -> avgIf(a, cond) /// avg(if(cond, a, null)) -> avgIf(a::ResultTypeIf, cond)
/// avg(if(cond, nullable_a, null)) -> avgIfOrNull(a, cond) /// avg(if(cond, nullable_a, null)) -> avgIf(nullable_a, cond)
/// sum(if(cond, a, 0)) -> sumIf(a, cond) /// sum(if(cond, a, 0)) -> sumIf(a, cond)
/// sum(if(cond, nullable_a, 0)) **is not** equivalent to sumIfOrNull(cond, nullable_a) as /// sum(if(cond, nullable_a, 0)) **is not** equivalent to sumIfOrNull(cond, nullable_a) as
/// it changes the output when no rows pass the condition (from 0 to NULL) /// it changes the output when no rows pass the condition (from 0 to NULL)
function_arguments_nodes.resize(2);
function_arguments_nodes[0] = std::move(if_arguments_nodes[1]); QueryTreeNodes new_arguments{2};
function_arguments_nodes[1] = std::move(if_arguments_nodes[0]);
/// We need to preserve the output type from if()
if (if_arguments_nodes[1]->getResultType()->getName() != if_node->getResultType()->getName())
new_arguments[0] = createCastFunction(std::move(if_arguments_nodes[1]), if_node->getResultType(), getContext());
else
new_arguments[0] = std::move(if_arguments_nodes[1]);
new_arguments[1] = std::move(if_arguments_nodes[0]);
function_arguments_nodes = std::move(new_arguments);
resolveAsAggregateFunctionWithIf( resolveAsAggregateFunctionWithIf(
*function_node, {function_arguments_nodes[0]->getResultType(), function_arguments_nodes[1]->getResultType()}); *function_node, {function_arguments_nodes[0]->getResultType(), function_arguments_nodes[1]->getResultType()});
} }
@ -72,21 +80,27 @@ public:
const auto & first_const_value = first_const_node->getValue(); const auto & first_const_value = first_const_node->getValue();
if (first_const_value.isNull() if (first_const_value.isNull()
|| (lower_name == "sum" && isInt64OrUInt64FieldType(first_const_value.getType()) && first_const_value.get<UInt64>() == 0 || (lower_name == "sum" && isInt64OrUInt64FieldType(first_const_value.getType()) && first_const_value.get<UInt64>() == 0
&& !function_node->getResultType()->isNullable())) && !if_node->getResultType()->isNullable()))
{ {
/// avg(if(cond, null, a) -> avgIfOrNullable(a, !cond)) /// avg(if(cond, null, a) -> avgIf(a::ResultTypeIf, !cond))
/// sum(if(cond, 0, a) -> sumIf(a, !cond)) /// sum(if(cond, 0, a) -> sumIf(a, !cond))
/// sum(if(cond, 0, nullable_a) **is not** sumIf(a, !cond)) -> Same as above /// sum(if(cond, 0, nullable_a) **is not** sumIf(a, !cond)) -> Same as above
QueryTreeNodes new_arguments{2};
if (if_arguments_nodes[2]->getResultType()->getName() != if_node->getResultType()->getName())
new_arguments[0] = createCastFunction(std::move(if_arguments_nodes[2]), if_node->getResultType(), getContext());
else
new_arguments[0] = std::move(if_arguments_nodes[2]);
auto not_function = std::make_shared<FunctionNode>("not"); auto not_function = std::make_shared<FunctionNode>("not");
auto & not_function_arguments = not_function->getArguments().getNodes(); auto & not_function_arguments = not_function->getArguments().getNodes();
not_function_arguments.push_back(std::move(if_arguments_nodes[0])); not_function_arguments.push_back(std::move(if_arguments_nodes[0]));
not_function->resolveAsFunction( not_function->resolveAsFunction(
FunctionFactory::instance().get("not", getContext())->build(not_function->getArgumentColumns())); FunctionFactory::instance().get("not", getContext())->build(not_function->getArgumentColumns()));
new_arguments[1] = std::move(not_function);
function_arguments_nodes.resize(2); function_arguments_nodes = std::move(new_arguments);
function_arguments_nodes[0] = std::move(if_arguments_nodes[2]);
function_arguments_nodes[1] = std::move(not_function);
resolveAsAggregateFunctionWithIf( resolveAsAggregateFunctionWithIf(
*function_node, {function_arguments_nodes[0]->getResultType(), function_arguments_nodes[1]->getResultType()}); *function_node, {function_arguments_nodes[0]->getResultType(), function_arguments_nodes[1]->getResultType()});
} }
@ -98,13 +112,9 @@ private:
{ {
auto result_type = function_node.getResultType(); auto result_type = function_node.getResultType();
std::string suffix = "If";
if (result_type->isNullable())
suffix = "OrNullIf";
AggregateFunctionProperties properties; AggregateFunctionProperties properties;
auto aggregate_function = AggregateFunctionFactory::instance().get( auto aggregate_function = AggregateFunctionFactory::instance().get(
function_node.getFunctionName() + suffix, function_node.getFunctionName() + "If",
function_node.getNullsAction(), function_node.getNullsAction(),
argument_types, argument_types,
function_node.getAggregateFunction()->getParameters(), function_node.getAggregateFunction()->getParameters(),

View File

@ -1,3 +1,7 @@
-- { echoOn }
set optimize_rewrite_aggregate_function_with_if = false;
EXPLAIN QUERY TREE run_passes = 1 select sum(if(number % 2, number, 0)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
sum(if(modulo(number, 2), number, 0)) UInt64 sum(if(modulo(number, 2), number, 0)) UInt64
@ -21,6 +25,7 @@ QUERY id: 0
ARGUMENTS ARGUMENTS
LIST id: 12, nodes: 1 LIST id: 12, nodes: 1
CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select sum(if(number % 2, 0, number)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
sum(if(modulo(number, 2), 0, number)) UInt64 sum(if(modulo(number, 2), 0, number)) UInt64
@ -44,6 +49,7 @@ QUERY id: 0
ARGUMENTS ARGUMENTS
LIST id: 12, nodes: 1 LIST id: 12, nodes: 1
CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select sum(if(number % 2, number, null)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
sum(if(modulo(number, 2), number, NULL)) Nullable(UInt64) sum(if(modulo(number, 2), number, NULL)) Nullable(UInt64)
@ -67,6 +73,7 @@ QUERY id: 0
ARGUMENTS ARGUMENTS
LIST id: 12, nodes: 1 LIST id: 12, nodes: 1
CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select sum(if(number % 2, null, number)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
sum(if(modulo(number, 2), NULL, number)) Nullable(UInt64) sum(if(modulo(number, 2), NULL, number)) Nullable(UInt64)
@ -90,6 +97,7 @@ QUERY id: 0
ARGUMENTS ARGUMENTS
LIST id: 12, nodes: 1 LIST id: 12, nodes: 1
CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select avg(if(number % 2, number, null)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
avg(if(modulo(number, 2), number, NULL)) Nullable(Float64) avg(if(modulo(number, 2), number, NULL)) Nullable(Float64)
@ -113,6 +121,7 @@ QUERY id: 0
ARGUMENTS ARGUMENTS
LIST id: 12, nodes: 1 LIST id: 12, nodes: 1
CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select avg(if(number % 2, null, number)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
avg(if(modulo(number, 2), NULL, number)) Nullable(Float64) avg(if(modulo(number, 2), NULL, number)) Nullable(Float64)
@ -136,6 +145,7 @@ QUERY id: 0
ARGUMENTS ARGUMENTS
LIST id: 12, nodes: 1 LIST id: 12, nodes: 1
CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select quantiles(0.5, 0.9, 0.99)(if(number % 2, number, null)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
quantiles(0.5, 0.9, 0.99)(if(modulo(number, 2), number, NULL)) Array(Float64) quantiles(0.5, 0.9, 0.99)(if(modulo(number, 2), number, NULL)) Array(Float64)
@ -164,6 +174,7 @@ QUERY id: 0
ARGUMENTS ARGUMENTS
LIST id: 16, nodes: 1 LIST id: 16, nodes: 1
CONSTANT id: 17, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 17, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select quantiles(0.5, 0.9, 0.99)(if(number % 2, null, number)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
quantiles(0.5, 0.9, 0.99)(if(modulo(number, 2), NULL, number)) Array(Float64) quantiles(0.5, 0.9, 0.99)(if(modulo(number, 2), NULL, number)) Array(Float64)
@ -192,6 +203,8 @@ QUERY id: 0
ARGUMENTS ARGUMENTS
LIST id: 16, nodes: 1 LIST id: 16, nodes: 1
CONSTANT id: 17, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 17, constant_value: UInt64_100, constant_value_type: UInt8
set optimize_rewrite_aggregate_function_with_if = true;
EXPLAIN QUERY TREE run_passes = 1 select sum(if(number % 2, number, 0)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
sum(if(modulo(number, 2), number, 0)) UInt64 sum(if(modulo(number, 2), number, 0)) UInt64
@ -211,6 +224,7 @@ QUERY id: 0
ARGUMENTS ARGUMENTS
LIST id: 9, nodes: 1 LIST id: 9, nodes: 1
CONSTANT id: 10, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 10, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select sum(if(number % 2, 0, number)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
sum(if(modulo(number, 2), 0, number)) UInt64 sum(if(modulo(number, 2), 0, number)) UInt64
@ -233,88 +247,109 @@ QUERY id: 0
ARGUMENTS ARGUMENTS
LIST id: 11, nodes: 1 LIST id: 11, nodes: 1
CONSTANT id: 12, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 12, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select sum(if(number % 2, number, null)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
sum(if(modulo(number, 2), number, NULL)) Nullable(UInt64) sum(if(modulo(number, 2), number, NULL)) Nullable(UInt64)
PROJECTION PROJECTION
LIST id: 1, nodes: 1 LIST id: 1, nodes: 1
FUNCTION id: 2, function_name: sumOrNullIf, function_type: aggregate, result_type: Nullable(UInt64) FUNCTION id: 2, function_name: sumIf, function_type: aggregate, result_type: Nullable(UInt64)
ARGUMENTS ARGUMENTS
LIST id: 3, nodes: 2 LIST id: 3, nodes: 2
COLUMN id: 4, column_name: number, result_type: UInt64, source_id: 5 FUNCTION id: 4, function_name: _CAST, function_type: ordinary, result_type: Nullable(UInt64)
FUNCTION id: 6, function_name: modulo, function_type: ordinary, result_type: UInt8
ARGUMENTS ARGUMENTS
LIST id: 7, nodes: 2 LIST id: 5, nodes: 2
COLUMN id: 4, column_name: number, result_type: UInt64, source_id: 5 COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 8, constant_value: UInt64_2, constant_value_type: UInt8 CONSTANT id: 8, constant_value: \'Nullable(UInt64)\', constant_value_type: String
FUNCTION id: 9, function_name: modulo, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 10, nodes: 2
COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 11, constant_value: UInt64_2, constant_value_type: UInt8
JOIN TREE JOIN TREE
TABLE_FUNCTION id: 5, alias: __table1, table_function_name: numbers TABLE_FUNCTION id: 7, alias: __table1, table_function_name: numbers
ARGUMENTS ARGUMENTS
LIST id: 9, nodes: 1 LIST id: 12, nodes: 1
CONSTANT id: 10, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select sum(if(number % 2, null, number)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
sum(if(modulo(number, 2), NULL, number)) Nullable(UInt64) sum(if(modulo(number, 2), NULL, number)) Nullable(UInt64)
PROJECTION PROJECTION
LIST id: 1, nodes: 1 LIST id: 1, nodes: 1
FUNCTION id: 2, function_name: sumOrNullIf, function_type: aggregate, result_type: Nullable(UInt64) FUNCTION id: 2, function_name: sumIf, function_type: aggregate, result_type: Nullable(UInt64)
ARGUMENTS ARGUMENTS
LIST id: 3, nodes: 2 LIST id: 3, nodes: 2
COLUMN id: 4, column_name: number, result_type: UInt64, source_id: 5 FUNCTION id: 4, function_name: _CAST, function_type: ordinary, result_type: Nullable(UInt64)
FUNCTION id: 6, function_name: not, function_type: ordinary, result_type: UInt8
ARGUMENTS ARGUMENTS
LIST id: 7, nodes: 1 LIST id: 5, nodes: 2
FUNCTION id: 8, function_name: modulo, function_type: ordinary, result_type: UInt8 COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 8, constant_value: \'Nullable(UInt64)\', constant_value_type: String
FUNCTION id: 9, function_name: not, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 10, nodes: 1
FUNCTION id: 11, function_name: modulo, function_type: ordinary, result_type: UInt8
ARGUMENTS ARGUMENTS
LIST id: 9, nodes: 2 LIST id: 12, nodes: 2
COLUMN id: 4, column_name: number, result_type: UInt64, source_id: 5 COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 10, constant_value: UInt64_2, constant_value_type: UInt8 CONSTANT id: 13, constant_value: UInt64_2, constant_value_type: UInt8
JOIN TREE JOIN TREE
TABLE_FUNCTION id: 5, alias: __table1, table_function_name: numbers TABLE_FUNCTION id: 7, alias: __table1, table_function_name: numbers
ARGUMENTS ARGUMENTS
LIST id: 11, nodes: 1 LIST id: 14, nodes: 1
CONSTANT id: 12, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 15, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select avg(if(number % 2, number, null)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
avg(if(modulo(number, 2), number, NULL)) Nullable(Float64) avg(if(modulo(number, 2), number, NULL)) Nullable(Float64)
PROJECTION PROJECTION
LIST id: 1, nodes: 1 LIST id: 1, nodes: 1
FUNCTION id: 2, function_name: avgOrNullIf, function_type: aggregate, result_type: Nullable(Float64) FUNCTION id: 2, function_name: avgIf, function_type: aggregate, result_type: Nullable(Float64)
ARGUMENTS ARGUMENTS
LIST id: 3, nodes: 2 LIST id: 3, nodes: 2
COLUMN id: 4, column_name: number, result_type: UInt64, source_id: 5 FUNCTION id: 4, function_name: _CAST, function_type: ordinary, result_type: Nullable(UInt64)
FUNCTION id: 6, function_name: modulo, function_type: ordinary, result_type: UInt8
ARGUMENTS ARGUMENTS
LIST id: 7, nodes: 2 LIST id: 5, nodes: 2
COLUMN id: 4, column_name: number, result_type: UInt64, source_id: 5 COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 8, constant_value: UInt64_2, constant_value_type: UInt8 CONSTANT id: 8, constant_value: \'Nullable(UInt64)\', constant_value_type: String
FUNCTION id: 9, function_name: modulo, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 10, nodes: 2
COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 11, constant_value: UInt64_2, constant_value_type: UInt8
JOIN TREE JOIN TREE
TABLE_FUNCTION id: 5, alias: __table1, table_function_name: numbers TABLE_FUNCTION id: 7, alias: __table1, table_function_name: numbers
ARGUMENTS ARGUMENTS
LIST id: 9, nodes: 1 LIST id: 12, nodes: 1
CONSTANT id: 10, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 13, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select avg(if(number % 2, null, number)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
avg(if(modulo(number, 2), NULL, number)) Nullable(Float64) avg(if(modulo(number, 2), NULL, number)) Nullable(Float64)
PROJECTION PROJECTION
LIST id: 1, nodes: 1 LIST id: 1, nodes: 1
FUNCTION id: 2, function_name: avgOrNullIf, function_type: aggregate, result_type: Nullable(Float64) FUNCTION id: 2, function_name: avgIf, function_type: aggregate, result_type: Nullable(Float64)
ARGUMENTS ARGUMENTS
LIST id: 3, nodes: 2 LIST id: 3, nodes: 2
COLUMN id: 4, column_name: number, result_type: UInt64, source_id: 5 FUNCTION id: 4, function_name: _CAST, function_type: ordinary, result_type: Nullable(UInt64)
FUNCTION id: 6, function_name: not, function_type: ordinary, result_type: UInt8
ARGUMENTS ARGUMENTS
LIST id: 7, nodes: 1 LIST id: 5, nodes: 2
FUNCTION id: 8, function_name: modulo, function_type: ordinary, result_type: UInt8 COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 8, constant_value: \'Nullable(UInt64)\', constant_value_type: String
FUNCTION id: 9, function_name: not, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 10, nodes: 1
FUNCTION id: 11, function_name: modulo, function_type: ordinary, result_type: UInt8
ARGUMENTS ARGUMENTS
LIST id: 9, nodes: 2 LIST id: 12, nodes: 2
COLUMN id: 4, column_name: number, result_type: UInt64, source_id: 5 COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 10, constant_value: UInt64_2, constant_value_type: UInt8 CONSTANT id: 13, constant_value: UInt64_2, constant_value_type: UInt8
JOIN TREE JOIN TREE
TABLE_FUNCTION id: 5, alias: __table1, table_function_name: numbers TABLE_FUNCTION id: 7, alias: __table1, table_function_name: numbers
ARGUMENTS ARGUMENTS
LIST id: 11, nodes: 1 LIST id: 14, nodes: 1
CONSTANT id: 12, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 15, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select quantiles(0.5, 0.9, 0.99)(if(number % 2, number, null)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
quantiles(0.5, 0.9, 0.99)(if(modulo(number, 2), number, NULL)) Array(Float64) quantiles(0.5, 0.9, 0.99)(if(modulo(number, 2), number, NULL)) Array(Float64)
@ -328,17 +363,22 @@ QUERY id: 0
CONSTANT id: 6, constant_value: Float64_0.99, constant_value_type: Float64 CONSTANT id: 6, constant_value: Float64_0.99, constant_value_type: Float64
ARGUMENTS ARGUMENTS
LIST id: 7, nodes: 2 LIST id: 7, nodes: 2
COLUMN id: 8, column_name: number, result_type: UInt64, source_id: 9 FUNCTION id: 8, function_name: _CAST, function_type: ordinary, result_type: Nullable(UInt64)
FUNCTION id: 10, function_name: modulo, function_type: ordinary, result_type: UInt8
ARGUMENTS ARGUMENTS
LIST id: 11, nodes: 2 LIST id: 9, nodes: 2
COLUMN id: 8, column_name: number, result_type: UInt64, source_id: 9 COLUMN id: 10, column_name: number, result_type: UInt64, source_id: 11
CONSTANT id: 12, constant_value: UInt64_2, constant_value_type: UInt8 CONSTANT id: 12, constant_value: \'Nullable(UInt64)\', constant_value_type: String
FUNCTION id: 13, function_name: modulo, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 14, nodes: 2
COLUMN id: 10, column_name: number, result_type: UInt64, source_id: 11
CONSTANT id: 15, constant_value: UInt64_2, constant_value_type: UInt8
JOIN TREE JOIN TREE
TABLE_FUNCTION id: 9, alias: __table1, table_function_name: numbers TABLE_FUNCTION id: 11, alias: __table1, table_function_name: numbers
ARGUMENTS ARGUMENTS
LIST id: 13, nodes: 1 LIST id: 16, nodes: 1
CONSTANT id: 14, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 17, constant_value: UInt64_100, constant_value_type: UInt8
EXPLAIN QUERY TREE run_passes = 1 select quantiles(0.5, 0.9, 0.99)(if(number % 2, null, number)) from numbers(100);
QUERY id: 0 QUERY id: 0
PROJECTION COLUMNS PROJECTION COLUMNS
quantiles(0.5, 0.9, 0.99)(if(modulo(number, 2), NULL, number)) Array(Float64) quantiles(0.5, 0.9, 0.99)(if(modulo(number, 2), NULL, number)) Array(Float64)
@ -352,17 +392,21 @@ QUERY id: 0
CONSTANT id: 6, constant_value: Float64_0.99, constant_value_type: Float64 CONSTANT id: 6, constant_value: Float64_0.99, constant_value_type: Float64
ARGUMENTS ARGUMENTS
LIST id: 7, nodes: 2 LIST id: 7, nodes: 2
COLUMN id: 8, column_name: number, result_type: UInt64, source_id: 9 FUNCTION id: 8, function_name: _CAST, function_type: ordinary, result_type: Nullable(UInt64)
FUNCTION id: 10, function_name: not, function_type: ordinary, result_type: UInt8
ARGUMENTS ARGUMENTS
LIST id: 11, nodes: 1 LIST id: 9, nodes: 2
FUNCTION id: 12, function_name: modulo, function_type: ordinary, result_type: UInt8 COLUMN id: 10, column_name: number, result_type: UInt64, source_id: 11
CONSTANT id: 12, constant_value: \'Nullable(UInt64)\', constant_value_type: String
FUNCTION id: 13, function_name: not, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 14, nodes: 1
FUNCTION id: 15, function_name: modulo, function_type: ordinary, result_type: UInt8
ARGUMENTS ARGUMENTS
LIST id: 13, nodes: 2 LIST id: 16, nodes: 2
COLUMN id: 8, column_name: number, result_type: UInt64, source_id: 9 COLUMN id: 10, column_name: number, result_type: UInt64, source_id: 11
CONSTANT id: 14, constant_value: UInt64_2, constant_value_type: UInt8 CONSTANT id: 17, constant_value: UInt64_2, constant_value_type: UInt8
JOIN TREE JOIN TREE
TABLE_FUNCTION id: 9, alias: __table1, table_function_name: numbers TABLE_FUNCTION id: 11, alias: __table1, table_function_name: numbers
ARGUMENTS ARGUMENTS
LIST id: 15, nodes: 1 LIST id: 18, nodes: 1
CONSTANT id: 16, constant_value: UInt64_100, constant_value_type: UInt8 CONSTANT id: 19, constant_value: UInt64_100, constant_value_type: UInt8

View File

@ -1,4 +1,5 @@
set allow_experimental_analyzer = true; set allow_experimental_analyzer = true;
-- { echoOn }
set optimize_rewrite_aggregate_function_with_if = false; set optimize_rewrite_aggregate_function_with_if = false;
EXPLAIN QUERY TREE run_passes = 1 select sum(if(number % 2, number, 0)) from numbers(100); EXPLAIN QUERY TREE run_passes = 1 select sum(if(number % 2, number, 0)) from numbers(100);

View File

@ -0,0 +1,111 @@
-- { echoOn }
SELECT concat(1, sum(if(0, toUInt128(concat('%', toLowCardinality(toNullable(1)), toUInt256(1))), materialize(0))));
10
SELECT any(if((number % 10) = 5, number, CAST(NULL, 'Nullable(Int128)'))) AS a, toTypeName(a) FROM numbers(100) AS a;
5 Nullable(Int128)
EXPLAIN QUERY TREE SELECT any(if((number % 10) = 5, number, CAST(NULL, 'Nullable(Int128)'))) AS a, toTypeName(a) FROM numbers(100);
QUERY id: 0
PROJECTION COLUMNS
a Nullable(Int128)
toTypeName(a) String
PROJECTION
LIST id: 1, nodes: 2
FUNCTION id: 2, function_name: anyIf, function_type: aggregate, result_type: Nullable(Int128)
ARGUMENTS
LIST id: 3, nodes: 2
FUNCTION id: 4, function_name: _CAST, function_type: ordinary, result_type: Nullable(Int128)
ARGUMENTS
LIST id: 5, nodes: 2
COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 8, constant_value: \'Nullable(Int128)\', constant_value_type: String
FUNCTION id: 9, function_name: equals, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 10, nodes: 2
FUNCTION id: 11, function_name: modulo, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 12, nodes: 2
COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 13, constant_value: UInt64_10, constant_value_type: UInt8
CONSTANT id: 14, constant_value: UInt64_5, constant_value_type: UInt8
FUNCTION id: 15, function_name: toTypeName, function_type: ordinary, result_type: String
ARGUMENTS
LIST id: 16, nodes: 1
FUNCTION id: 2, function_name: anyIf, function_type: aggregate, result_type: Nullable(Int128)
ARGUMENTS
LIST id: 3, nodes: 2
FUNCTION id: 4, function_name: _CAST, function_type: ordinary, result_type: Nullable(Int128)
ARGUMENTS
LIST id: 5, nodes: 2
COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 8, constant_value: \'Nullable(Int128)\', constant_value_type: String
FUNCTION id: 9, function_name: equals, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 10, nodes: 2
FUNCTION id: 11, function_name: modulo, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 12, nodes: 2
COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 13, constant_value: UInt64_10, constant_value_type: UInt8
CONSTANT id: 14, constant_value: UInt64_5, constant_value_type: UInt8
JOIN TREE
TABLE_FUNCTION id: 7, alias: __table1, table_function_name: numbers
ARGUMENTS
LIST id: 17, nodes: 1
CONSTANT id: 18, constant_value: UInt64_100, constant_value_type: UInt8
SELECT any(if((number % 10) = 5, CAST(NULL, 'Nullable(Int128)'), number)) AS a, toTypeName(a) FROM numbers(100) AS a;
0 Nullable(Int128)
EXPLAIN QUERY TREE SELECT any(if((number % 10) = 5, CAST(NULL, 'Nullable(Int128)'), number)) AS a, toTypeName(a) FROM numbers(100);
QUERY id: 0
PROJECTION COLUMNS
a Nullable(Int128)
toTypeName(a) String
PROJECTION
LIST id: 1, nodes: 2
FUNCTION id: 2, function_name: anyIf, function_type: aggregate, result_type: Nullable(Int128)
ARGUMENTS
LIST id: 3, nodes: 2
FUNCTION id: 4, function_name: _CAST, function_type: ordinary, result_type: Nullable(Int128)
ARGUMENTS
LIST id: 5, nodes: 2
COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 8, constant_value: \'Nullable(Int128)\', constant_value_type: String
FUNCTION id: 9, function_name: not, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 10, nodes: 1
FUNCTION id: 11, function_name: equals, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 12, nodes: 2
FUNCTION id: 13, function_name: modulo, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 14, nodes: 2
COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 15, constant_value: UInt64_10, constant_value_type: UInt8
CONSTANT id: 16, constant_value: UInt64_5, constant_value_type: UInt8
FUNCTION id: 17, function_name: toTypeName, function_type: ordinary, result_type: String
ARGUMENTS
LIST id: 18, nodes: 1
FUNCTION id: 2, function_name: anyIf, function_type: aggregate, result_type: Nullable(Int128)
ARGUMENTS
LIST id: 3, nodes: 2
FUNCTION id: 4, function_name: _CAST, function_type: ordinary, result_type: Nullable(Int128)
ARGUMENTS
LIST id: 5, nodes: 2
COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 8, constant_value: \'Nullable(Int128)\', constant_value_type: String
FUNCTION id: 9, function_name: not, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 10, nodes: 1
FUNCTION id: 11, function_name: equals, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 12, nodes: 2
FUNCTION id: 13, function_name: modulo, function_type: ordinary, result_type: UInt8
ARGUMENTS
LIST id: 14, nodes: 2
COLUMN id: 6, column_name: number, result_type: UInt64, source_id: 7
CONSTANT id: 15, constant_value: UInt64_10, constant_value_type: UInt8
CONSTANT id: 16, constant_value: UInt64_5, constant_value_type: UInt8
JOIN TREE
TABLE_FUNCTION id: 7, alias: __table1, table_function_name: numbers
ARGUMENTS
LIST id: 19, nodes: 1
CONSTANT id: 20, constant_value: UInt64_100, constant_value_type: UInt8

View File

@ -0,0 +1,8 @@
SET allow_experimental_analyzer = 1;
-- { echoOn }
SELECT concat(1, sum(if(0, toUInt128(concat('%', toLowCardinality(toNullable(1)), toUInt256(1))), materialize(0))));
SELECT any(if((number % 10) = 5, number, CAST(NULL, 'Nullable(Int128)'))) AS a, toTypeName(a) FROM numbers(100) AS a;
EXPLAIN QUERY TREE SELECT any(if((number % 10) = 5, number, CAST(NULL, 'Nullable(Int128)'))) AS a, toTypeName(a) FROM numbers(100);
SELECT any(if((number % 10) = 5, CAST(NULL, 'Nullable(Int128)'), number)) AS a, toTypeName(a) FROM numbers(100) AS a;
EXPLAIN QUERY TREE SELECT any(if((number % 10) = 5, CAST(NULL, 'Nullable(Int128)'), number)) AS a, toTypeName(a) FROM numbers(100);