mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-28 10:31:57 +00:00
Merge pull request #10237 from ClickHouse/akz/mutations-to-correctly-handle-lambdas
ALTER UPDATE/DELETE on Replicated* storages: Fixed "Unknown function lambda." error
This commit is contained in:
commit
b8be585595
@ -36,34 +36,46 @@ namespace ErrorCodes
|
||||
|
||||
namespace
|
||||
{
|
||||
struct FirstNonDeterministicFuncData
|
||||
/// Helps to detect situations, where non-deterministic functions may be used in mutations of Replicated*MergeTree.
|
||||
class FirstNonDeterministicFuncMatcher
|
||||
{
|
||||
using TypeToVisit = ASTFunction;
|
||||
|
||||
explicit FirstNonDeterministicFuncData(const Context & context_)
|
||||
: context{context_}
|
||||
{}
|
||||
|
||||
const Context & context;
|
||||
std::optional<String> nondeterministic_function_name;
|
||||
|
||||
void visit(ASTFunction & function, ASTPtr &)
|
||||
public:
|
||||
struct Data
|
||||
{
|
||||
if (nondeterministic_function_name)
|
||||
const Context & context;
|
||||
std::optional<String> nondeterministic_function_name;
|
||||
};
|
||||
|
||||
public:
|
||||
static bool needChildVisit(const ASTPtr & /*node*/, const ASTPtr & child)
|
||||
{
|
||||
return child != nullptr;
|
||||
}
|
||||
|
||||
static void visit(const ASTPtr & node, Data & data)
|
||||
{
|
||||
if (data.nondeterministic_function_name)
|
||||
return;
|
||||
|
||||
const auto func = FunctionFactory::instance().get(function.name, context);
|
||||
if (!func->isDeterministic())
|
||||
nondeterministic_function_name = func->getName();
|
||||
if (const auto * function = typeid_cast<const ASTFunction *>(node.get()))
|
||||
{
|
||||
/// Property of being deterministic for lambda expression is completely determined
|
||||
/// by the contents of its definition, so we just proceed to it.
|
||||
if (function->name != "lambda")
|
||||
{
|
||||
const auto func = FunctionFactory::instance().get(function->name, data.context);
|
||||
if (!func->isDeterministic())
|
||||
data.nondeterministic_function_name = func->getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using FirstNonDeterministicFuncFinder =
|
||||
InDepthNodeVisitor<OneTypeMatcher<FirstNonDeterministicFuncData>, true>;
|
||||
using FirstNonDeterministicFuncFinder = InDepthNodeVisitor<FirstNonDeterministicFuncMatcher, true>;
|
||||
|
||||
std::optional<String> findFirstNonDeterministicFuncName(const MutationCommand & command, const Context & context)
|
||||
{
|
||||
FirstNonDeterministicFuncData finder_data(context);
|
||||
FirstNonDeterministicFuncMatcher::Data finder_data{context, std::nullopt};
|
||||
|
||||
switch (command.type)
|
||||
{
|
||||
|
@ -5,3 +5,5 @@ OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
|
@ -43,6 +43,12 @@ ${CLICKHOUSE_CLIENT} --query "ALTER TABLE $R1 DELETE WHERE ignore(rand())" 2>&1
|
||||
${CLICKHOUSE_CLIENT} --query "ALTER TABLE $R1 UPDATE y = y + rand() % 1 WHERE not ignore()" 2>&1 \
|
||||
| fgrep -q "must use only deterministic functions" && echo 'OK' || echo 'FAIL'
|
||||
|
||||
${CLICKHOUSE_CLIENT} --query "ALTER TABLE $R1 UPDATE y = x + arrayCount(x -> (x + y) % 2, range(y)) WHERE not ignore()" 2>&1 > /dev/null \
|
||||
&& echo 'OK' || echo 'FAIL'
|
||||
|
||||
${CLICKHOUSE_CLIENT} --query "ALTER TABLE $R1 UPDATE y = x + arrayCount(x -> (rand() + x) % 2, range(y)) WHERE not ignore()" 2>&1 \
|
||||
| fgrep -q "must use only deterministic functions" && echo 'OK' || echo 'FAIL'
|
||||
|
||||
|
||||
# For regular tables we do not enforce deterministic functions
|
||||
${CLICKHOUSE_CLIENT} --query "ALTER TABLE $T1 DELETE WHERE rand() = 0" 2>&1 > /dev/null \
|
||||
|
Loading…
Reference in New Issue
Block a user