Fix arrayJoin() capturing in lambda

Fixes the following LOGICAL_ERROR:

    $ clickhouse-client -q 'select arrayFilter((a) -> ((a, arrayJoin([[]])) IN (Null, [Null])), [])'
    2020.08.16 00:32:01.967102 [ 1744189 ] {b40a5ebd-d710-4f03-bb18-57db67de1181} <Error> : Logical error: 'Lambda captured argument arrayJoin(array(array())) not found in required columns.'.
    clickhouse-server: ../src/Common/Exception.cpp:45: DB::Exception::Exception(const string&, int): Assertion `false' failed.

Since there are multiple input columns for arrayJoin():

    (gdb) p captured_names_
    $6 = std::vector of length 3, capacity 4 = {"arrayJoin(array(array()))", "arrayJoin(array(array()))", "__set"}

While FunctionCaptureOverloadResolver cannot handle non-unique columns.
This commit is contained in:
Azat Khuzhin 2020-08-25 21:06:21 +03:00
parent e2dd668378
commit 308e094d04
4 changed files with 28 additions and 1 deletions

View File

@ -447,6 +447,19 @@ void ScopeStack::addAction(const ExpressionAction & action)
}
}
void ScopeStack::addActionNoInput(const ExpressionAction & action)
{
size_t level = 0;
Names required = action.getNeededColumns();
for (const auto & elem : required)
level = std::max(level, getColumnLevel(elem));
Names added;
stack[level].actions->add(action, added);
stack[level].new_columns.insert(added.begin(), added.end());
}
ExpressionActionsPtr ScopeStack::popLevel()
{
ExpressionActionsPtr res = stack.back().actions;
@ -549,7 +562,7 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data &
/// It could have been possible to implement arrayJoin which keeps source column,
/// but in this case it will always be replicated (as many arrays), which is expensive.
String tmp_name = data.getUniqueName("_array_join_" + arg->getColumnName());
data.addAction(ExpressionAction::copyColumn(arg->getColumnName(), tmp_name));
data.addActionNoInput(ExpressionAction::copyColumn(arg->getColumnName(), tmp_name));
data.addAction(ExpressionAction::arrayJoin(tmp_name, result_name));
}

View File

@ -12,6 +12,7 @@ namespace DB
class Context;
class ASTFunction;
struct ExpressionAction;
class ExpressionActions;
using ExpressionActionsPtr = std::shared_ptr<ExpressionActions>;
@ -49,6 +50,8 @@ struct ScopeStack
size_t getColumnLevel(const std::string & name);
void addAction(const ExpressionAction & action);
/// For arrayJoin() to avoid double columns in the input.
void addActionNoInput(const ExpressionAction & action);
ExpressionActionsPtr popLevel();
@ -115,6 +118,10 @@ public:
{
actions_stack.addAction(action);
}
void addActionNoInput(const ExpressionAction & action)
{
actions_stack.addActionNoInput(action);
}
const Block & getSampleBlock() const
{

View File

@ -0,0 +1 @@
[]

View File

@ -0,0 +1,6 @@
SELECT arrayFilter((a) -> ((a, arrayJoin([])) IN (Null, [Null])), []);
SELECT arrayFilter((a) -> ((a, arrayJoin([[]])) IN (Null, [Null])), []);
-- simplified from the https://clickhouse-test-reports.s3.yandex.net/10373/6c4748a63e7acde2cc3283d96ffec590aae1e724/fuzzer/fuzzer.log#fail1
SELECT * FROM system.one ARRAY JOIN arrayFilter((a) -> ((a, arrayJoin([])) IN (NULL)), []) AS arr_x; -- { serverError 43; }
SELECT * FROM numbers(1) LEFT ARRAY JOIN arrayFilter((x_0, x_1) -> (arrayJoin([]) IN (NULL)), [], []) AS arr_x;