Do not optimize GROUP BY functions that shadow their arguments

This commit is contained in:
Anton Kozlov 2022-07-11 15:13:36 +00:00
parent 356786f0c6
commit 0e44e34e69
4 changed files with 68 additions and 0 deletions

View File

@ -0,0 +1,43 @@
#pragma once
#include <DataTypes/Serializations/ISerialization.h>
#include <Interpreters/InDepthNodeVisitor.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTIdentifier.h>
namespace DB
{
/// Checks from bottom to top if a function's alias shadows the name
/// of one of it's arguments
class FunctionMaskingArgumentCheckMatcher
{
public:
struct Data
{
const String& alias;
bool is_rejected = false;
void reject() { is_rejected = true; }
};
static void visit(const ASTPtr & ast, Data & data)
{
if (data.is_rejected)
return;
if (const auto & identifier = ast->as<ASTIdentifier>())
visit(*identifier, data);
}
static void visit(const ASTIdentifier & ast, Data & data)
{
if (ast.getAliasOrColumnName() == data.alias)
data.reject();
}
static bool needChildVisit(const ASTPtr &, const ASTPtr &) { return true; }
};
using FunctionMaskingArgumentCheckVisitor = ConstInDepthNodeVisitor<FunctionMaskingArgumentCheckMatcher, false>;
}

View File

@ -13,6 +13,7 @@
#include <Interpreters/AggregateFunctionOfGroupByKeysVisitor.h>
#include <Interpreters/RewriteAnyFunctionVisitor.h>
#include <Interpreters/RemoveInjectiveFunctionsVisitor.h>
#include <Interpreters/FunctionMaskingArgumentCheckVisitor.h>
#include <Interpreters/RedundantFunctionsInOrderByVisitor.h>
#include <Interpreters/RewriteCountVariantsVisitor.h>
#include <Interpreters/MonotonicityCheckVisitor.h>
@ -153,6 +154,19 @@ void optimizeGroupBy(ASTSelectQuery * select_query, ContextPtr context)
continue;
}
}
/// don't optimise functions that shadow any of it's arguments:
/// https://github.com/ClickHouse/ClickHouse/issues/37032
else if (!function->alias.empty())
{
FunctionMaskingArgumentCheckVisitor::Data data{.alias=function->alias};
FunctionMaskingArgumentCheckVisitor(data).visit(function->arguments);
if (data.is_rejected)
{
++i;
continue;
}
}
/// copy shared pointer to args in order to ensure lifetime
auto args_ast = function->arguments;

View File

@ -0,0 +1,6 @@
0
1
4
0
1
2

View File

@ -0,0 +1,5 @@
SET prefer_localhost_replica=0;
SELECT toString(dummy) as dummy FROM remote('127.{1,1}', 'system.one') GROUP BY dummy;
SELECT toString(dummy+1) as dummy FROM remote('127.{1,1}', 'system.one') GROUP BY dummy;
SELECT toString((toInt8(dummy)+2) * (toInt8(dummy)+2)) as dummy FROM remote('127.{1,1}', system.one) GROUP BY dummy;
SELECT round(number % 3) AS number FROM remote('127.{1,1}', numbers(20)) GROUP BY number ORDER BY number ASC;