2018-10-12 15:41:28 +00:00
|
|
|
#pragma once
|
|
|
|
|
2019-01-18 16:30:35 +00:00
|
|
|
#include <Parsers/IAST.h>
|
|
|
|
#include <Interpreters/PreparedSets.h>
|
2018-10-18 15:03:14 +00:00
|
|
|
#include <Interpreters/ExpressionActions.h>
|
2019-01-30 12:01:00 +00:00
|
|
|
#include <Interpreters/SubqueryForSet.h>
|
2019-08-15 13:54:59 +00:00
|
|
|
#include <Interpreters/InDepthNodeVisitor.h>
|
2018-10-18 15:03:14 +00:00
|
|
|
|
2018-10-12 15:41:28 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
class Context;
|
|
|
|
class ASTFunction;
|
|
|
|
|
2019-01-22 12:33:56 +00:00
|
|
|
/// The case of an explicit enumeration of values.
|
|
|
|
SetPtr makeExplicitSet(
|
|
|
|
const ASTFunction * node, const Block & sample_block, bool create_ordered_set,
|
|
|
|
const Context & context, const SizeLimits & limits, PreparedSets & prepared_sets);
|
2018-10-12 15:41:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
/** For ActionsVisitor
|
|
|
|
* A stack of ExpressionActions corresponding to nested lambda expressions.
|
|
|
|
* The new action should be added to the highest possible level.
|
|
|
|
* For example, in the expression "select arrayMap(x -> x + column1 * column2, array1)"
|
|
|
|
* calculation of the product must be done outside the lambda expression (it does not depend on x),
|
|
|
|
* and the calculation of the sum is inside (depends on x).
|
|
|
|
*/
|
|
|
|
struct ScopeStack
|
|
|
|
{
|
|
|
|
struct Level
|
|
|
|
{
|
|
|
|
ExpressionActionsPtr actions;
|
|
|
|
NameSet new_columns;
|
|
|
|
};
|
|
|
|
|
|
|
|
using Levels = std::vector<Level>;
|
|
|
|
|
|
|
|
Levels stack;
|
|
|
|
|
|
|
|
const Context & context;
|
|
|
|
|
|
|
|
ScopeStack(const ExpressionActionsPtr & actions, const Context & context_);
|
|
|
|
|
|
|
|
void pushLevel(const NamesAndTypesList & input_columns);
|
|
|
|
|
|
|
|
size_t getColumnLevel(const std::string & name);
|
|
|
|
|
|
|
|
void addAction(const ExpressionAction & action);
|
|
|
|
|
|
|
|
ExpressionActionsPtr popLevel();
|
|
|
|
|
|
|
|
const Block & getSampleBlock() const;
|
|
|
|
};
|
|
|
|
|
2019-08-15 13:54:59 +00:00
|
|
|
class ASTIdentifier;
|
|
|
|
class ASTFunction;
|
|
|
|
class ASTLiteral;
|
2018-10-12 15:41:28 +00:00
|
|
|
|
2018-10-16 12:34:20 +00:00
|
|
|
/// Collect ExpressionAction from AST. Returns PreparedSets and SubqueriesForSets too.
|
2019-08-15 13:54:59 +00:00
|
|
|
class ActionsMatcher
|
2018-10-12 15:41:28 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-08-15 13:54:59 +00:00
|
|
|
using Visitor = ConstInDepthNodeVisitor<ActionsMatcher, true>;
|
2018-10-16 12:34:20 +00:00
|
|
|
|
2019-08-15 13:54:59 +00:00
|
|
|
struct Data
|
2019-08-14 16:53:30 +00:00
|
|
|
{
|
2019-08-15 13:54:59 +00:00
|
|
|
const Context & context;
|
|
|
|
SizeLimits set_size_limit;
|
|
|
|
size_t subquery_depth;
|
|
|
|
const NamesAndTypesList & source_columns;
|
|
|
|
PreparedSets & prepared_sets;
|
|
|
|
SubqueriesForSets & subqueries_for_sets;
|
|
|
|
bool no_subqueries;
|
|
|
|
bool only_consts;
|
|
|
|
bool no_storage_or_local;
|
|
|
|
size_t visit_depth;
|
|
|
|
ScopeStack actions_stack;
|
|
|
|
|
|
|
|
Data(const Context & context_, SizeLimits set_size_limit_, size_t subquery_depth_,
|
|
|
|
const NamesAndTypesList & source_columns_, const ExpressionActionsPtr & actions,
|
|
|
|
PreparedSets & prepared_sets_, SubqueriesForSets & subqueries_for_sets_,
|
|
|
|
bool no_subqueries_, bool only_consts_, bool no_storage_or_local_)
|
|
|
|
: context(context_),
|
|
|
|
set_size_limit(set_size_limit_),
|
|
|
|
subquery_depth(subquery_depth_),
|
|
|
|
source_columns(source_columns_),
|
|
|
|
prepared_sets(prepared_sets_),
|
|
|
|
subqueries_for_sets(subqueries_for_sets_),
|
|
|
|
no_subqueries(no_subqueries_),
|
|
|
|
only_consts(only_consts_),
|
|
|
|
no_storage_or_local(no_storage_or_local_),
|
|
|
|
visit_depth(0),
|
|
|
|
actions_stack(actions, context)
|
|
|
|
{}
|
|
|
|
|
|
|
|
void updateActions(ExpressionActionsPtr & actions)
|
|
|
|
{
|
|
|
|
actions = actions_stack.popLevel();
|
|
|
|
}
|
|
|
|
|
2019-08-15 14:22:33 +00:00
|
|
|
void addAction(const ExpressionAction & action)
|
|
|
|
{
|
|
|
|
actions_stack.addAction(action);
|
|
|
|
}
|
|
|
|
|
|
|
|
const Block & getSampleBlock() const
|
|
|
|
{
|
|
|
|
return actions_stack.getSampleBlock();
|
|
|
|
}
|
|
|
|
|
2019-08-15 13:54:59 +00:00
|
|
|
/// Does result of the calculation already exists in the block.
|
|
|
|
bool hasColumn(const String & columnName) const
|
|
|
|
{
|
|
|
|
return actions_stack.getSampleBlock().has(columnName);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void visit(const ASTPtr & ast, Data & data);
|
|
|
|
static bool needChildVisit(const ASTPtr & node, const ASTPtr & child);
|
2018-10-12 15:41:28 +00:00
|
|
|
|
|
|
|
private:
|
2019-08-15 13:54:59 +00:00
|
|
|
|
|
|
|
static void visit(const ASTIdentifier & identifier, const ASTPtr & ast, Data & data);
|
|
|
|
static void visit(const ASTFunction & node, const ASTPtr & ast, Data & data);
|
|
|
|
static void visit(const ASTLiteral & literal, const ASTPtr & ast, Data & data);
|
|
|
|
|
|
|
|
static SetPtr makeSet(const ASTFunction & node, Data & data);
|
2018-10-12 15:41:28 +00:00
|
|
|
};
|
|
|
|
|
2019-08-15 13:54:59 +00:00
|
|
|
using ActionsVisitor = ActionsMatcher::Visitor;
|
|
|
|
|
2018-10-12 15:41:28 +00:00
|
|
|
}
|