2011-11-07 01:15:37 +00:00
|
|
|
#pragma once
|
|
|
|
|
2019-12-09 13:12:54 +00:00
|
|
|
#include <Functions/IFunctionImpl.h>
|
2018-02-06 19:34:53 +00:00
|
|
|
#include <Interpreters/ExpressionActions.h>
|
|
|
|
#include <DataTypes/DataTypeFunction.h>
|
|
|
|
#include <IO/WriteBufferFromString.h>
|
|
|
|
#include <IO/Operators.h>
|
|
|
|
#include <Columns/ColumnFunction.h>
|
2018-03-29 14:04:24 +00:00
|
|
|
#include <DataTypes/DataTypesNumber.h>
|
2016-01-11 21:46:36 +00:00
|
|
|
|
2017-03-10 13:13:32 +00:00
|
|
|
namespace DB
|
2014-09-23 15:28:21 +00:00
|
|
|
{
|
2017-04-19 03:35:11 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
class ExecutableFunctionExpression : public IExecutableFunctionImpl
|
2018-02-06 19:34:53 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-12-09 14:36:47 +00:00
|
|
|
struct Signature
|
2018-02-06 19:34:53 +00:00
|
|
|
{
|
2019-12-09 14:36:47 +00:00
|
|
|
Names argument_names;
|
|
|
|
String return_name;
|
|
|
|
};
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
using SignaturePtr = std::shared_ptr<Signature>;
|
2019-10-10 14:38:08 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
ExecutableFunctionExpression(ExpressionActionsPtr expression_actions_, SignaturePtr signature_)
|
|
|
|
: expression_actions(std::move(expression_actions_))
|
|
|
|
, signature(std::move(signature_))
|
|
|
|
{}
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
String getName() const override { return "FunctionExpression"; }
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
void execute(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override
|
2018-02-06 19:34:53 +00:00
|
|
|
{
|
|
|
|
Block expr_block;
|
|
|
|
for (size_t i = 0; i < arguments.size(); ++i)
|
|
|
|
{
|
|
|
|
const auto & argument = block.getByPosition(arguments[i]);
|
2018-02-08 16:37:50 +00:00
|
|
|
/// Replace column name with value from argument_names.
|
2019-12-09 14:36:47 +00:00
|
|
|
expr_block.insert({argument.column, argument.type, signature->argument_names[i]});
|
2018-02-06 19:34:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
expression_actions->execute(expr_block);
|
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
block.getByPosition(result).column = expr_block.getByName(signature->return_name).column;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
ExpressionActionsPtr expression_actions;
|
|
|
|
SignaturePtr signature;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Executes expression. Uses for lambda functions implementation. Can't be created from factory.
|
|
|
|
class FunctionExpression : public IFunctionBaseImpl
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
using Signature = ExecutableFunctionExpression::Signature;
|
|
|
|
using SignaturePtr = ExecutableFunctionExpression::SignaturePtr;
|
|
|
|
|
|
|
|
FunctionExpression(const ExpressionActionsPtr & expression_actions_,
|
|
|
|
const DataTypes & argument_types_, const Names & argument_names_,
|
|
|
|
const DataTypePtr & return_type_, const std::string & return_name_)
|
|
|
|
: expression_actions(expression_actions_)
|
|
|
|
, signature(std::make_shared<Signature>(Signature{argument_names_, return_name_}))
|
|
|
|
, argument_types(argument_types_), return_type(return_type_)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
String getName() const override { return "FunctionExpression"; }
|
|
|
|
|
|
|
|
bool isDeterministic() const override { return true; }
|
|
|
|
bool isDeterministicInScopeOfQuery() const override { return true; }
|
|
|
|
|
|
|
|
const DataTypes & getArgumentTypes() const override { return argument_types; }
|
|
|
|
const DataTypePtr & getReturnType() const override { return return_type; }
|
|
|
|
|
|
|
|
ExecutableFunctionImplPtr prepare(const Block &, const ColumnNumbers &, size_t) const override
|
|
|
|
{
|
|
|
|
return std::make_unique<ExecutableFunctionExpression>(expression_actions, signature);
|
2018-02-06 19:34:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
ExpressionActionsPtr expression_actions;
|
2019-12-09 14:36:47 +00:00
|
|
|
SignaturePtr signature;
|
2018-02-06 19:34:53 +00:00
|
|
|
DataTypes argument_types;
|
|
|
|
DataTypePtr return_type;
|
|
|
|
};
|
|
|
|
|
2018-02-09 19:06:29 +00:00
|
|
|
/// Captures columns which are used by lambda function but not in argument list.
|
2018-02-08 16:37:50 +00:00
|
|
|
/// Returns ColumnFunction with captured columns.
|
|
|
|
/// For lambda(x, x + y) x is in lambda_arguments, y is in captured arguments, expression_actions is 'x + y'.
|
|
|
|
/// execute(y) returns ColumnFunction(FunctionExpression(x + y), y) with type Function(x) -> function_return_type.
|
2019-12-09 14:36:47 +00:00
|
|
|
class ExecutableFunctionCapture : public IExecutableFunctionImpl
|
2018-02-06 19:34:53 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-12-09 14:36:47 +00:00
|
|
|
struct Capture
|
2018-02-06 19:34:53 +00:00
|
|
|
{
|
2019-12-09 14:36:47 +00:00
|
|
|
Names captured_names;
|
|
|
|
DataTypes captured_types;
|
|
|
|
NamesAndTypesList lambda_arguments;
|
|
|
|
String return_name;
|
|
|
|
DataTypePtr return_type;
|
|
|
|
};
|
2018-02-08 16:37:50 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
using CapturePtr = std::shared_ptr<Capture>;
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
ExecutableFunctionCapture(ExpressionActionsPtr expression_actions_, CapturePtr capture_)
|
|
|
|
: expression_actions(std::move(expression_actions_)), capture(std::move(capture_)) {}
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
String getName() const override { return "FunctionCapture"; }
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
bool useDefaultImplementationForNulls() const override { return false; }
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
void execute(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
|
|
|
{
|
|
|
|
ColumnsWithTypeAndName columns;
|
|
|
|
columns.reserve(arguments.size());
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
Names names;
|
|
|
|
DataTypes types;
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
names.reserve(capture->captured_names.size() + capture->lambda_arguments.size());
|
|
|
|
names.insert(names.end(), capture->captured_names.begin(), capture->captured_names.end());
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
types.reserve(capture->captured_types.size() + capture->lambda_arguments.size());
|
|
|
|
types.insert(types.end(), capture->captured_types.begin(), capture->captured_types.end());
|
|
|
|
|
|
|
|
for (const auto & lambda_argument : capture->lambda_arguments)
|
|
|
|
{
|
|
|
|
names.push_back(lambda_argument.name);
|
|
|
|
types.push_back(lambda_argument.type);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto & argument : arguments)
|
|
|
|
columns.push_back(block.getByPosition(argument));
|
|
|
|
|
2019-12-09 14:41:55 +00:00
|
|
|
auto function = std::make_unique<FunctionExpression>(expression_actions, types, names,
|
2019-12-09 14:36:47 +00:00
|
|
|
capture->return_type, capture->return_name);
|
2019-12-09 14:41:55 +00:00
|
|
|
auto function_adaptor = std::make_shared<FunctionBaseAdaptor>(std::move(function));
|
|
|
|
block.getByPosition(result).column = ColumnFunction::create(input_rows_count, std::move(function_adaptor), columns);
|
2019-12-09 14:36:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
ExpressionActionsPtr expression_actions;
|
|
|
|
CapturePtr capture;
|
|
|
|
};
|
|
|
|
|
|
|
|
class FunctionCapture : public IFunctionBaseImpl
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
using Capture = ExecutableFunctionCapture::Capture;
|
|
|
|
using CapturePtr = ExecutableFunctionCapture::CapturePtr;
|
|
|
|
|
|
|
|
FunctionCapture(
|
|
|
|
ExpressionActionsPtr expression_actions_,
|
|
|
|
CapturePtr capture_,
|
|
|
|
DataTypePtr return_type_,
|
|
|
|
String name_)
|
|
|
|
: expression_actions(std::move(expression_actions_))
|
|
|
|
, capture(std::move(capture_))
|
|
|
|
, return_type(std::move(return_type_))
|
|
|
|
, name(std::move(name_))
|
|
|
|
{
|
2018-02-06 19:34:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
String getName() const override { return name; }
|
|
|
|
|
2019-10-10 14:38:08 +00:00
|
|
|
bool isDeterministic() const override { return true; }
|
|
|
|
bool isDeterministicInScopeOfQuery() const override { return true; }
|
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
const DataTypes & getArgumentTypes() const override { return capture->captured_types; }
|
2018-02-06 19:34:53 +00:00
|
|
|
const DataTypePtr & getReturnType() const override { return return_type; }
|
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
ExecutableFunctionImplPtr prepare(const Block &, const ColumnNumbers &, size_t) const override
|
2018-02-06 19:34:53 +00:00
|
|
|
{
|
2019-12-09 14:36:47 +00:00
|
|
|
return std::make_unique<ExecutableFunctionCapture>(expression_actions, capture);
|
2018-02-06 19:34:53 +00:00
|
|
|
}
|
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
private:
|
|
|
|
ExpressionActionsPtr expression_actions;
|
|
|
|
CapturePtr capture;
|
|
|
|
DataTypePtr return_type;
|
|
|
|
String name;
|
|
|
|
};
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
class FunctionCaptureOverloadResolver : public IFunctionOverloadResolverImpl
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
using Capture = ExecutableFunctionCapture::Capture;
|
|
|
|
using CapturePtr = ExecutableFunctionCapture::CapturePtr;
|
|
|
|
|
|
|
|
FunctionCaptureOverloadResolver(
|
|
|
|
ExpressionActionsPtr expression_actions_,
|
|
|
|
const Names & captured_names_,
|
|
|
|
const NamesAndTypesList & lambda_arguments_,
|
|
|
|
const DataTypePtr & function_return_type_,
|
|
|
|
const String & expression_return_name_)
|
|
|
|
: expression_actions(std::move(expression_actions_))
|
|
|
|
{
|
|
|
|
std::unordered_map<std::string, DataTypePtr> arguments_map;
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
const auto & all_arguments = expression_actions->getRequiredColumnsWithTypes();
|
|
|
|
for (const auto & arg : all_arguments)
|
|
|
|
arguments_map[arg.name] = arg.type;
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
DataTypes captured_types;
|
|
|
|
captured_types.reserve(captured_names_.size());
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
for (const auto & captured_name : captured_names_)
|
2018-02-06 19:34:53 +00:00
|
|
|
{
|
2019-12-09 14:36:47 +00:00
|
|
|
auto it = arguments_map.find(captured_name);
|
|
|
|
if (it == arguments_map.end())
|
|
|
|
throw Exception("Lambda captured argument " + captured_name + " not found in required columns.",
|
|
|
|
ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
captured_types.push_back(it->second);
|
|
|
|
arguments_map.erase(it);
|
2018-02-06 19:34:53 +00:00
|
|
|
}
|
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
DataTypes argument_types;
|
|
|
|
argument_types.reserve(lambda_arguments_.size());
|
|
|
|
for (const auto & lambda_argument : lambda_arguments_)
|
|
|
|
argument_types.push_back(lambda_argument.type);
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
return_type = std::make_shared<DataTypeFunction>(argument_types, function_return_type_);
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
name = "Capture[" + toString(captured_types) + "](" + toString(argument_types) + ") -> "
|
|
|
|
+ function_return_type_->getName();
|
|
|
|
|
|
|
|
capture = std::make_shared<Capture>(Capture{
|
|
|
|
.captured_names = captured_names_,
|
|
|
|
.captured_types = std::move(captured_types),
|
|
|
|
.lambda_arguments = lambda_arguments_,
|
|
|
|
.return_name = expression_return_name_,
|
|
|
|
.return_type = function_return_type_,
|
|
|
|
});
|
|
|
|
}
|
2018-02-06 19:34:53 +00:00
|
|
|
|
2019-12-09 14:36:47 +00:00
|
|
|
String getName() const override { return name; }
|
2018-02-06 19:34:53 +00:00
|
|
|
bool useDefaultImplementationForNulls() const override { return false; }
|
2019-12-09 14:36:47 +00:00
|
|
|
DataTypePtr getReturnType(const ColumnsWithTypeAndName &) const override { return return_type; }
|
|
|
|
size_t getNumberOfArguments() const override { return capture->captured_types.size(); }
|
|
|
|
|
|
|
|
FunctionBaseImplPtr build(const ColumnsWithTypeAndName &, const DataTypePtr &) const override
|
2018-02-06 19:34:53 +00:00
|
|
|
{
|
2019-12-09 14:36:47 +00:00
|
|
|
return std::make_unique<FunctionCapture>(expression_actions, capture, return_type, name);
|
2018-02-06 19:34:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2019-12-09 14:36:47 +00:00
|
|
|
ExpressionActionsPtr expression_actions;
|
|
|
|
CapturePtr capture;
|
|
|
|
DataTypePtr return_type;
|
|
|
|
String name;
|
|
|
|
|
|
|
|
static String toString(const DataTypes & data_types)
|
2018-02-06 19:34:53 +00:00
|
|
|
{
|
|
|
|
std::string result;
|
|
|
|
{
|
|
|
|
WriteBufferFromString buffer(result);
|
|
|
|
bool first = true;
|
|
|
|
for (const auto & type : data_types)
|
|
|
|
{
|
|
|
|
if (!first)
|
|
|
|
buffer << ", ";
|
|
|
|
|
|
|
|
first = false;
|
|
|
|
buffer << type->getName();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-11-07 01:15:37 +00:00
|
|
|
}
|