ClickHouse/src/Interpreters/UserDefinedSQLFunctionFactory.cpp

164 lines
4.9 KiB
C++
Raw Normal View History

#include "UserDefinedSQLFunctionFactory.h"
2021-10-27 15:49:18 +00:00
#include <Common/quoteString.h>
#include <Functions/FunctionFactory.h>
#include <AggregateFunctions/AggregateFunctionFactory.h>
2021-10-27 15:49:18 +00:00
#include <Interpreters/UserDefinedSQLObjectsLoader.h>
#include <Interpreters/UserDefinedExecutableFunctionFactory.h>
#include <Interpreters/Context.h>
namespace DB
{
namespace ErrorCodes
{
extern const int FUNCTION_ALREADY_EXISTS;
extern const int UNKNOWN_FUNCTION;
2021-10-27 15:49:18 +00:00
extern const int CANNOT_DROP_FUNCTION;
}
UserDefinedSQLFunctionFactory & UserDefinedSQLFunctionFactory::instance()
{
static UserDefinedSQLFunctionFactory result;
return result;
}
2021-10-27 15:49:18 +00:00
void UserDefinedSQLFunctionFactory::registerFunction(ContextPtr context, const String & function_name, ASTPtr create_function_query, bool replace, bool if_not_exists, bool persist)
{
if (FunctionFactory::instance().hasNameOrAlias(function_name))
2021-10-27 15:49:18 +00:00
{
if (if_not_exists)
return;
throw Exception(ErrorCodes::FUNCTION_ALREADY_EXISTS, "The function '{}' already exists", function_name);
2021-10-27 15:49:18 +00:00
}
if (AggregateFunctionFactory::instance().hasNameOrAlias(function_name))
2021-10-27 15:49:18 +00:00
{
if (if_not_exists)
return;
throw Exception(ErrorCodes::FUNCTION_ALREADY_EXISTS, "The aggregate function '{}' already exists", function_name);
2021-10-27 15:49:18 +00:00
}
if (UserDefinedExecutableFunctionFactory::instance().has(function_name, context))
{
if (if_not_exists)
return;
throw Exception(ErrorCodes::FUNCTION_ALREADY_EXISTS, "User defined executable function '{}' already exists", function_name);
2021-10-27 15:49:18 +00:00
}
Guard UDF container with a lock Fixes TSAN report [1]: WARNING: ThreadSanitizer: data race (pid=436) Write of size 8 at 0x7b040076e450 by thread T240: ... 3 DB::UserDefinedFunctionFactory::registerFunction() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionFactory.cpp:30:56 (clickhouse+0x1500727f) 4 DB::InterpreterCreateFunctionQuery::execute() obj-x86_64-linux-gnu/../src/Interpreters/InterpreterCreateFunctionQuery.cpp:37:44 (clickhouse+0x14b1224a) 5 DB::executeQueryImpl() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:573:32 (clickhouse+0x15039241) 6 DB::executeQuery() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:934:30 (clickhouse+0x150376fa) 7 DB::TCPHandler::runImpl() obj-x86_64-linux-gnu/../src/Server/TCPHandler.cpp:291:24 (clickhouse+0x15a7af2a) Previous read of size 8 at 0x7b040076e450 by thread T1370: ... 2 DB::UserDefinedFunctionFactory::tryGet() const obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionFactory.cpp:65:45 (clickhouse+0x150078a4) 3 DB::UserDefinedFunctionsMatcher::tryToReplaceFunction() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionsVisitor.cpp:39:73 (clickhouse+0x15007cd0) 4 DB::UserDefinedFunctionsMatcher::visit() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionsVisitor.cpp:27:19 (clickhouse+0x15007ba8) 5 DB::InDepthNodeVisitor<>::visit() obj-x86_64-linux-gnu/../src/Interpreters/InDepthNodeVisitor.h:34:13 (clickhouse+0x14fbcba4) .. 24 DB::executeQueryImpl() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:543:28 (clickhouse+0x15038f3b) [1]: https://clickhouse-test-reports.s3.yandex.net/0/df1fe27791f82c2a917390faa30716effbd32b8f/stress_test_(thread).html#fail1
2021-08-26 21:39:11 +00:00
std::lock_guard lock(mutex);
auto [it, inserted] = function_name_to_create_query.emplace(function_name, create_function_query);
if (!inserted)
{
2021-10-27 15:49:18 +00:00
if (if_not_exists)
return;
if (replace)
2021-10-27 15:49:18 +00:00
it->second = create_function_query;
else
throw Exception(ErrorCodes::FUNCTION_ALREADY_EXISTS,
"The function name '{}' is not unique",
function_name);
}
2021-10-27 15:49:18 +00:00
if (persist)
{
try
{
UserDefinedSQLObjectsLoader::instance().storeObject(context, UserDefinedSQLObjectType::Function, function_name, *create_function_query, replace);
}
catch (Exception & exception)
{
function_name_to_create_query.erase(it);
exception.addMessage(fmt::format("while storing user defined function {} on disk", backQuote(function_name)));
throw;
}
}
}
2021-10-27 15:49:18 +00:00
void UserDefinedSQLFunctionFactory::unregisterFunction(ContextPtr context, const String & function_name, bool if_exists)
{
if (FunctionFactory::instance().hasNameOrAlias(function_name) ||
AggregateFunctionFactory::instance().hasNameOrAlias(function_name))
2021-10-27 15:49:18 +00:00
throw Exception(ErrorCodes::CANNOT_DROP_FUNCTION, "Cannot drop system function '{}'", function_name);
if (UserDefinedExecutableFunctionFactory::instance().has(function_name, context))
throw Exception(ErrorCodes::CANNOT_DROP_FUNCTION, "Cannot drop user defined executable function '{}'", function_name);
Guard UDF container with a lock Fixes TSAN report [1]: WARNING: ThreadSanitizer: data race (pid=436) Write of size 8 at 0x7b040076e450 by thread T240: ... 3 DB::UserDefinedFunctionFactory::registerFunction() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionFactory.cpp:30:56 (clickhouse+0x1500727f) 4 DB::InterpreterCreateFunctionQuery::execute() obj-x86_64-linux-gnu/../src/Interpreters/InterpreterCreateFunctionQuery.cpp:37:44 (clickhouse+0x14b1224a) 5 DB::executeQueryImpl() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:573:32 (clickhouse+0x15039241) 6 DB::executeQuery() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:934:30 (clickhouse+0x150376fa) 7 DB::TCPHandler::runImpl() obj-x86_64-linux-gnu/../src/Server/TCPHandler.cpp:291:24 (clickhouse+0x15a7af2a) Previous read of size 8 at 0x7b040076e450 by thread T1370: ... 2 DB::UserDefinedFunctionFactory::tryGet() const obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionFactory.cpp:65:45 (clickhouse+0x150078a4) 3 DB::UserDefinedFunctionsMatcher::tryToReplaceFunction() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionsVisitor.cpp:39:73 (clickhouse+0x15007cd0) 4 DB::UserDefinedFunctionsMatcher::visit() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionsVisitor.cpp:27:19 (clickhouse+0x15007ba8) 5 DB::InDepthNodeVisitor<>::visit() obj-x86_64-linux-gnu/../src/Interpreters/InDepthNodeVisitor.h:34:13 (clickhouse+0x14fbcba4) .. 24 DB::executeQueryImpl() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:543:28 (clickhouse+0x15038f3b) [1]: https://clickhouse-test-reports.s3.yandex.net/0/df1fe27791f82c2a917390faa30716effbd32b8f/stress_test_(thread).html#fail1
2021-08-26 21:39:11 +00:00
std::lock_guard lock(mutex);
auto it = function_name_to_create_query.find(function_name);
if (it == function_name_to_create_query.end())
2021-10-27 15:49:18 +00:00
{
if (if_exists)
return;
throw Exception(ErrorCodes::UNKNOWN_FUNCTION,
"The function name '{}' is not registered",
function_name);
2021-10-27 15:49:18 +00:00
}
try
{
UserDefinedSQLObjectsLoader::instance().removeObject(context, UserDefinedSQLObjectType::Function, function_name);
}
catch (Exception & exception)
{
exception.addMessage(fmt::format("while removing user defined function {} from disk", backQuote(function_name)));
throw;
}
2021-08-23 14:31:58 +00:00
function_name_to_create_query.erase(it);
}
ASTPtr UserDefinedSQLFunctionFactory::get(const String & function_name) const
{
Guard UDF container with a lock Fixes TSAN report [1]: WARNING: ThreadSanitizer: data race (pid=436) Write of size 8 at 0x7b040076e450 by thread T240: ... 3 DB::UserDefinedFunctionFactory::registerFunction() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionFactory.cpp:30:56 (clickhouse+0x1500727f) 4 DB::InterpreterCreateFunctionQuery::execute() obj-x86_64-linux-gnu/../src/Interpreters/InterpreterCreateFunctionQuery.cpp:37:44 (clickhouse+0x14b1224a) 5 DB::executeQueryImpl() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:573:32 (clickhouse+0x15039241) 6 DB::executeQuery() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:934:30 (clickhouse+0x150376fa) 7 DB::TCPHandler::runImpl() obj-x86_64-linux-gnu/../src/Server/TCPHandler.cpp:291:24 (clickhouse+0x15a7af2a) Previous read of size 8 at 0x7b040076e450 by thread T1370: ... 2 DB::UserDefinedFunctionFactory::tryGet() const obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionFactory.cpp:65:45 (clickhouse+0x150078a4) 3 DB::UserDefinedFunctionsMatcher::tryToReplaceFunction() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionsVisitor.cpp:39:73 (clickhouse+0x15007cd0) 4 DB::UserDefinedFunctionsMatcher::visit() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionsVisitor.cpp:27:19 (clickhouse+0x15007ba8) 5 DB::InDepthNodeVisitor<>::visit() obj-x86_64-linux-gnu/../src/Interpreters/InDepthNodeVisitor.h:34:13 (clickhouse+0x14fbcba4) .. 24 DB::executeQueryImpl() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:543:28 (clickhouse+0x15038f3b) [1]: https://clickhouse-test-reports.s3.yandex.net/0/df1fe27791f82c2a917390faa30716effbd32b8f/stress_test_(thread).html#fail1
2021-08-26 21:39:11 +00:00
std::lock_guard lock(mutex);
auto it = function_name_to_create_query.find(function_name);
if (it == function_name_to_create_query.end())
throw Exception(ErrorCodes::UNKNOWN_FUNCTION,
"The function name '{}' is not registered",
function_name);
return it->second;
}
ASTPtr UserDefinedSQLFunctionFactory::tryGet(const std::string & function_name) const
{
Guard UDF container with a lock Fixes TSAN report [1]: WARNING: ThreadSanitizer: data race (pid=436) Write of size 8 at 0x7b040076e450 by thread T240: ... 3 DB::UserDefinedFunctionFactory::registerFunction() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionFactory.cpp:30:56 (clickhouse+0x1500727f) 4 DB::InterpreterCreateFunctionQuery::execute() obj-x86_64-linux-gnu/../src/Interpreters/InterpreterCreateFunctionQuery.cpp:37:44 (clickhouse+0x14b1224a) 5 DB::executeQueryImpl() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:573:32 (clickhouse+0x15039241) 6 DB::executeQuery() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:934:30 (clickhouse+0x150376fa) 7 DB::TCPHandler::runImpl() obj-x86_64-linux-gnu/../src/Server/TCPHandler.cpp:291:24 (clickhouse+0x15a7af2a) Previous read of size 8 at 0x7b040076e450 by thread T1370: ... 2 DB::UserDefinedFunctionFactory::tryGet() const obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionFactory.cpp:65:45 (clickhouse+0x150078a4) 3 DB::UserDefinedFunctionsMatcher::tryToReplaceFunction() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionsVisitor.cpp:39:73 (clickhouse+0x15007cd0) 4 DB::UserDefinedFunctionsMatcher::visit() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionsVisitor.cpp:27:19 (clickhouse+0x15007ba8) 5 DB::InDepthNodeVisitor<>::visit() obj-x86_64-linux-gnu/../src/Interpreters/InDepthNodeVisitor.h:34:13 (clickhouse+0x14fbcba4) .. 24 DB::executeQueryImpl() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:543:28 (clickhouse+0x15038f3b) [1]: https://clickhouse-test-reports.s3.yandex.net/0/df1fe27791f82c2a917390faa30716effbd32b8f/stress_test_(thread).html#fail1
2021-08-26 21:39:11 +00:00
std::lock_guard lock(mutex);
auto it = function_name_to_create_query.find(function_name);
if (it == function_name_to_create_query.end())
return nullptr;
return it->second;
}
bool UserDefinedSQLFunctionFactory::has(const String & function_name) const
{
return tryGet(function_name) != nullptr;
}
std::vector<std::string> UserDefinedSQLFunctionFactory::getAllRegisteredNames() const
{
std::vector<std::string> registered_names;
Guard UDF container with a lock Fixes TSAN report [1]: WARNING: ThreadSanitizer: data race (pid=436) Write of size 8 at 0x7b040076e450 by thread T240: ... 3 DB::UserDefinedFunctionFactory::registerFunction() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionFactory.cpp:30:56 (clickhouse+0x1500727f) 4 DB::InterpreterCreateFunctionQuery::execute() obj-x86_64-linux-gnu/../src/Interpreters/InterpreterCreateFunctionQuery.cpp:37:44 (clickhouse+0x14b1224a) 5 DB::executeQueryImpl() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:573:32 (clickhouse+0x15039241) 6 DB::executeQuery() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:934:30 (clickhouse+0x150376fa) 7 DB::TCPHandler::runImpl() obj-x86_64-linux-gnu/../src/Server/TCPHandler.cpp:291:24 (clickhouse+0x15a7af2a) Previous read of size 8 at 0x7b040076e450 by thread T1370: ... 2 DB::UserDefinedFunctionFactory::tryGet() const obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionFactory.cpp:65:45 (clickhouse+0x150078a4) 3 DB::UserDefinedFunctionsMatcher::tryToReplaceFunction() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionsVisitor.cpp:39:73 (clickhouse+0x15007cd0) 4 DB::UserDefinedFunctionsMatcher::visit() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionsVisitor.cpp:27:19 (clickhouse+0x15007ba8) 5 DB::InDepthNodeVisitor<>::visit() obj-x86_64-linux-gnu/../src/Interpreters/InDepthNodeVisitor.h:34:13 (clickhouse+0x14fbcba4) .. 24 DB::executeQueryImpl() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:543:28 (clickhouse+0x15038f3b) [1]: https://clickhouse-test-reports.s3.yandex.net/0/df1fe27791f82c2a917390faa30716effbd32b8f/stress_test_(thread).html#fail1
2021-08-26 21:39:11 +00:00
std::lock_guard lock(mutex);
2021-09-01 07:38:46 +00:00
registered_names.reserve(function_name_to_create_query.size());
Guard UDF container with a lock Fixes TSAN report [1]: WARNING: ThreadSanitizer: data race (pid=436) Write of size 8 at 0x7b040076e450 by thread T240: ... 3 DB::UserDefinedFunctionFactory::registerFunction() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionFactory.cpp:30:56 (clickhouse+0x1500727f) 4 DB::InterpreterCreateFunctionQuery::execute() obj-x86_64-linux-gnu/../src/Interpreters/InterpreterCreateFunctionQuery.cpp:37:44 (clickhouse+0x14b1224a) 5 DB::executeQueryImpl() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:573:32 (clickhouse+0x15039241) 6 DB::executeQuery() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:934:30 (clickhouse+0x150376fa) 7 DB::TCPHandler::runImpl() obj-x86_64-linux-gnu/../src/Server/TCPHandler.cpp:291:24 (clickhouse+0x15a7af2a) Previous read of size 8 at 0x7b040076e450 by thread T1370: ... 2 DB::UserDefinedFunctionFactory::tryGet() const obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionFactory.cpp:65:45 (clickhouse+0x150078a4) 3 DB::UserDefinedFunctionsMatcher::tryToReplaceFunction() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionsVisitor.cpp:39:73 (clickhouse+0x15007cd0) 4 DB::UserDefinedFunctionsMatcher::visit() obj-x86_64-linux-gnu/../src/Interpreters/UserDefinedFunctionsVisitor.cpp:27:19 (clickhouse+0x15007ba8) 5 DB::InDepthNodeVisitor<>::visit() obj-x86_64-linux-gnu/../src/Interpreters/InDepthNodeVisitor.h:34:13 (clickhouse+0x14fbcba4) .. 24 DB::executeQueryImpl() obj-x86_64-linux-gnu/../src/Interpreters/executeQuery.cpp:543:28 (clickhouse+0x15038f3b) [1]: https://clickhouse-test-reports.s3.yandex.net/0/df1fe27791f82c2a917390faa30716effbd32b8f/stress_test_(thread).html#fail1
2021-08-26 21:39:11 +00:00
for (const auto & [name, _] : function_name_to_create_query)
registered_names.emplace_back(name);
return registered_names;
}
}