forked from ClickHouse/ClickHouse
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reapply "Merge pull request ClickHouse#61564 from liuneng1994/optimiz…
…e_in_single_value" This reverts commit b2e764f.
- Loading branch information
1 parent
8910820
commit 1210e8d
Showing
12 changed files
with
391 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#include <Analyzer/ColumnNode.h> | ||
#include <Analyzer/ConstantNode.h> | ||
#include <Analyzer/FunctionNode.h> | ||
#include <Analyzer/InDepthQueryTreeVisitor.h> | ||
#include <Analyzer/Passes/ConvertInToEqualPass.h> | ||
#include <Functions/equals.h> | ||
#include <Functions/notEquals.h> | ||
|
||
namespace DB | ||
{ | ||
|
||
class ConvertInToEqualPassVisitor : public InDepthQueryTreeVisitorWithContext<ConvertInToEqualPassVisitor> | ||
{ | ||
public: | ||
using Base = InDepthQueryTreeVisitorWithContext<ConvertInToEqualPassVisitor>; | ||
using Base::Base; | ||
|
||
void enterImpl(QueryTreeNodePtr & node) | ||
{ | ||
static const std::unordered_map<String, String> MAPPING = { | ||
{"in", "equals"}, | ||
{"notIn", "notEquals"} | ||
}; | ||
auto * func_node = node->as<FunctionNode>(); | ||
if (!func_node | ||
|| !MAPPING.contains(func_node->getFunctionName()) | ||
|| func_node->getArguments().getNodes().size() != 2) | ||
return ; | ||
auto args = func_node->getArguments().getNodes(); | ||
auto * column_node = args[0]->as<ColumnNode>(); | ||
auto * constant_node = args[1]->as<ConstantNode>(); | ||
if (!column_node || !constant_node) | ||
return ; | ||
// IN multiple values is not supported | ||
if (constant_node->getValue().getType() == Field::Types::Which::Tuple | ||
|| constant_node->getValue().getType() == Field::Types::Which::Array) | ||
return ; | ||
// x IN null not equivalent to x = null | ||
if (constant_node->getValue().isNull()) | ||
return ; | ||
auto result_func_name = MAPPING.at(func_node->getFunctionName()); | ||
auto equal = std::make_shared<FunctionNode>(result_func_name); | ||
auto new_const = std::make_shared<ConstantNode>(constant_node->getValue(), removeNullable(constant_node->getResultType())); | ||
new_const->getSourceExpression() = constant_node->getSourceExpression(); | ||
QueryTreeNodes arguments{column_node->clone(), new_const}; | ||
equal->getArguments().getNodes() = std::move(arguments); | ||
FunctionOverloadResolverPtr resolver; | ||
bool decimal_check_overflow = getContext()->getSettingsRef().decimal_check_overflow; | ||
if (result_func_name == "equals") | ||
{ | ||
resolver = createInternalFunctionEqualOverloadResolver(decimal_check_overflow); | ||
} | ||
else | ||
{ | ||
resolver = createInternalFunctionNotEqualOverloadResolver(decimal_check_overflow); | ||
} | ||
try | ||
{ | ||
equal->resolveAsFunction(resolver); | ||
} | ||
catch (...) | ||
{ | ||
// When function resolver fails, we should not replace the function node | ||
return; | ||
} | ||
node = equal; | ||
} | ||
}; | ||
|
||
void ConvertInToEqualPass::run(QueryTreeNodePtr & query_tree_node, ContextPtr context) | ||
{ | ||
ConvertInToEqualPassVisitor visitor(std::move(context)); | ||
visitor.visit(query_tree_node); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#pragma once | ||
|
||
#include <Analyzer/IQueryTreePass.h> | ||
|
||
namespace DB | ||
{ | ||
/** Optimize `in` to `equals` if possible. | ||
* 1. convert in single value to equal | ||
* Example: SELECT * from test where x IN (1); | ||
* Result: SELECT * from test where x = 1; | ||
* | ||
* 2. convert not in single value to notEqual | ||
* Example: SELECT * from test where x NOT IN (1); | ||
* Result: SELECT * from test where x != 1; | ||
* | ||
* If value is null or tuple, do not convert. | ||
*/ | ||
class ConvertInToEqualPass final : public IQueryTreePass | ||
{ | ||
public: | ||
String getName() override { return "ConvertInToEqualPass"; } | ||
|
||
String getDescription() override { return "Convert in to equal"; } | ||
|
||
void run(QueryTreeNodePtr & query_tree_node, ContextPtr context) override; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#pragma once | ||
#include <memory> | ||
|
||
namespace DB | ||
{ | ||
|
||
class IFunctionOverloadResolver; | ||
using FunctionOverloadResolverPtr = std::shared_ptr<IFunctionOverloadResolver>; | ||
|
||
FunctionOverloadResolverPtr createInternalFunctionEqualOverloadResolver(bool decimal_check_overflow); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#pragma once | ||
#include <memory> | ||
|
||
namespace DB | ||
{ | ||
|
||
class IFunctionOverloadResolver; | ||
using FunctionOverloadResolverPtr = std::shared_ptr<IFunctionOverloadResolver>; | ||
|
||
FunctionOverloadResolverPtr createInternalFunctionNotEqualOverloadResolver(bool decimal_check_overflow); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<test> | ||
<settings> | ||
<max_insert_threads>8</max_insert_threads> | ||
<max_threads>1</max_threads> | ||
</settings> | ||
|
||
<create_query> | ||
CREATE TABLE t_nullable | ||
( | ||
key_string1 Nullable(String), | ||
key_string2 Nullable(String), | ||
key_string3 Nullable(String), | ||
key_int64_1 Nullable(Int64), | ||
key_int64_2 Nullable(Int64), | ||
key_int64_3 Nullable(Int64), | ||
key_int64_4 Nullable(Int64), | ||
key_int64_5 Nullable(Int64), | ||
m1 Int64, | ||
m2 Int64 | ||
) | ||
ENGINE = Memory | ||
</create_query> | ||
<fill_query>insert into t_nullable select ['aaaaaa','bbaaaa','ccaaaa','ddaaaa'][number % 101 + 1], ['aa','bb','cc','dd'][number % 100 + 1], ['aa','bb','cc','dd'][number % 102 + 1], number%10+1, number%10+2, number%10+3, number%10+4,number%10+5, number%6000+1, number%5000+2 from numbers_mt(30000000)</fill_query> | ||
<query>select * from t_nullable where key_string1 in ('aaaaaa') format Null SETTINGS allow_experimental_analyzer=1</query> | ||
<query>select * from t_nullable where key_string2 in ('3') format Null SETTINGS allow_experimental_analyzer=1</query> | ||
<drop_query>drop table if exists t_nullable</drop_query> | ||
|
||
</test> |
Oops, something went wrong.