mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 07:31:57 +00:00
dbms: development [#METR-10498]
Signed-off-by: Pavel Kartavyy <kartavyy@yandex-team.ru>
This commit is contained in:
parent
a737895eb4
commit
bdeee5386b
@ -101,6 +101,10 @@ public:
|
||||
|
||||
/// Все новые временные таблицы, полученные при выполнении подзапросов GLOBAL IN.
|
||||
Tables external_tables;
|
||||
|
||||
/// создает Set, заданные явно
|
||||
void makeExplicitSets();
|
||||
|
||||
private:
|
||||
typedef std::set<String> NamesSet;
|
||||
|
||||
@ -313,6 +317,9 @@ private:
|
||||
void assertSelect();
|
||||
void assertAggregation();
|
||||
void assertArrayJoin();
|
||||
|
||||
void makeExplicitSet(ASTFunction * node, const Block & sample_block);
|
||||
void makeExplicitSetsRecursively(ASTPtr & node, const Block & sample_block);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <DB/Columns/ColumnArray.h>
|
||||
|
||||
#include <DB/Storages/MergeTree/BoolMask.h>
|
||||
#include <DB/Storages/MergeTree/PKCondition.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <DB/Parsers/ASTSelectQuery.h>
|
||||
#include <DB/Parsers/ASTFunction.h>
|
||||
#include <DB/Parsers/ASTLiteral.h>
|
||||
#include <DB/Columns/ColumnSet.h>
|
||||
#include <DB/Storages/MergeTree/BoolMask.h>
|
||||
|
||||
|
||||
@ -347,7 +346,7 @@ private:
|
||||
Range range;
|
||||
size_t key_column;
|
||||
/// Для FUNCTION_IN_SET
|
||||
SetPtr set;
|
||||
ASTPtr in_function;
|
||||
};
|
||||
|
||||
typedef std::vector<RPNElement> RPN;
|
||||
|
@ -498,6 +498,26 @@ void ExpressionAnalyzer::normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_as
|
||||
finished_asts[initial_ast] = ast;
|
||||
}
|
||||
|
||||
void ExpressionAnalyzer::makeExplicitSets()
|
||||
{
|
||||
makeExplicitSetsRecursively(ast, storage->getSampleBlock());
|
||||
}
|
||||
|
||||
void ExpressionAnalyzer::makeExplicitSetsRecursively(ASTPtr & node, const Block & sample_block)
|
||||
{
|
||||
for (auto & child : node->children)
|
||||
makeExplicitSetsRecursively(child, sample_block);
|
||||
|
||||
ASTFunction * func = dynamic_cast<ASTFunction *>(node.get());
|
||||
if (func && func->kind == ASTFunction::FUNCTION && (func->name == "in" || func->name == "notIn"))
|
||||
{
|
||||
IAST & args = *func->arguments;
|
||||
ASTPtr & arg = args.children[1];
|
||||
|
||||
if (!dynamic_cast<ASTSet *>(&*arg) && !dynamic_cast<ASTSubquery *>(&*arg))
|
||||
makeExplicitSet(func, sample_block);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionAnalyzer::findGlobalFunctions(ASTPtr & ast, std::vector<ASTPtr> & global_nodes)
|
||||
{
|
||||
@ -679,7 +699,15 @@ void ExpressionAnalyzer::makeSet(ASTFunction * node, const Block & sample_block)
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Случай явного перечисления значений.
|
||||
makeExplicitSet(node, sample_block);
|
||||
}
|
||||
}
|
||||
|
||||
/// Случай явного перечисления значений.
|
||||
void ExpressionAnalyzer::makeExplicitSet(ASTFunction * node, const Block & sample_block)
|
||||
{
|
||||
IAST & args = *node->arguments;
|
||||
ASTPtr & arg = args.children[1];
|
||||
|
||||
DataTypes set_element_types;
|
||||
ASTPtr & left_arg = args.children[0];
|
||||
@ -741,7 +769,6 @@ void ExpressionAnalyzer::makeSet(ASTFunction * node, const Block & sample_block)
|
||||
ast_set->set = new Set(settings.limits);
|
||||
ast_set->set->createFromAST(set_element_types, elements_ast);
|
||||
arg = ast_set_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -501,6 +501,7 @@ QueryProcessingStage::Enum InterpreterSelectQuery::executeFetchColumns(BlockInpu
|
||||
|
||||
QueryProcessingStage::Enum from_stage = QueryProcessingStage::FetchColumns;
|
||||
|
||||
query_analyzer->makeExplicitSets();
|
||||
/// Инициализируем изначальные потоки данных, на которые накладываются преобразования запроса. Таблица или подзапрос?
|
||||
if (!interpreter_subquery)
|
||||
{
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <DB/Interpreters/ExpressionAnalyzer.h>
|
||||
#include <DB/Columns/ColumnSet.h>
|
||||
#include <DB/Columns/ColumnTuple.h>
|
||||
#include <DB/Parsers/ASTSet.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -139,15 +140,11 @@ bool PKCondition::atomFromAST(ASTPtr & node, Block & block_with_constants, RPNEl
|
||||
inverted = true;
|
||||
column = pk_columns[args[1]->getColumnName()];
|
||||
}
|
||||
/// для In, notIn
|
||||
else if (pk_columns.count(args[0]->getColumnName()) && dynamic_cast<DB::ColumnSet *>(args[1].get()))
|
||||
else if (pk_columns.count(args[0]->getColumnName()) && dynamic_cast<ASTSet *>(args[1].get()))
|
||||
{
|
||||
/// для in не бывает inverted
|
||||
inverted = false;
|
||||
/// не поддерживаем Primary Key, если аргумент функции in tuple
|
||||
if (dynamic_cast<DB::ColumnTuple*>(args[0].get()))
|
||||
return false;
|
||||
column = pk_columns[args[0]->getColumnName()];
|
||||
dynamic_cast<ASTSet *>(args[1].get())->set->createOrderedSet();
|
||||
}
|
||||
else
|
||||
return false;
|
||||
@ -188,8 +185,7 @@ bool PKCondition::atomFromAST(ASTPtr & node, Block & block_with_constants, RPNEl
|
||||
else if (func->name == "in" || func->name == "notIn")
|
||||
{
|
||||
out.function = func->name == "in" ? RPNElement::FUNCTION_IN_SET : RPNElement::FUNCTION_NOT_IN_SET;
|
||||
out.set = (dynamic_cast<DB::ColumnSet *>(args[1].get())->getData());
|
||||
out.set->createOrderedSet();
|
||||
out.in_function = node;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
@ -282,11 +278,21 @@ bool PKCondition::mayBeTrueInRange(const Field * left_pk, const Field * right_pk
|
||||
}
|
||||
else if (element.function == RPNElement::FUNCTION_IN_SET || element.function == RPNElement::FUNCTION_NOT_IN_SET)
|
||||
{
|
||||
const Range & key_range = key_ranges[element.key_column];
|
||||
ASTFunction * in_func = dynamic_cast<ASTFunction *>(element.in_function.get());
|
||||
ASTs & args = dynamic_cast<ASTExpressionList &>(*in_func->arguments).children;
|
||||
ASTSet * ast_set = dynamic_cast<ASTSet *>(args[1].get());
|
||||
if (in_func && ast_set)
|
||||
{
|
||||
const Range & key_range = key_ranges[element.key_column];
|
||||
|
||||
rpn_stack.push_back(element.set->mayBeTrueInRange(key_range.left, key_range.right));
|
||||
if (element.function == RPNElement::FUNCTION_NOT_IN_SET)
|
||||
rpn_stack.back() = !rpn_stack.back();
|
||||
rpn_stack.push_back(ast_set->set->mayBeTrueInRange(key_range.left, key_range.right));
|
||||
if (element.function == RPNElement::FUNCTION_NOT_IN_SET)
|
||||
rpn_stack.back() = !rpn_stack.back();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw DB::Exception("Set for IN is not created yet!");
|
||||
}
|
||||
}
|
||||
else if (element.function == RPNElement::FUNCTION_NOT)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user