ClickHouse/src/Storages/NamedCollectionsHelpers.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

147 lines
4.7 KiB
C++
Raw Normal View History

#include "NamedCollectionsHelpers.h"
2023-06-06 12:46:34 +00:00
#include <Access/ContextAccess.h>
#include <Common/NamedCollections/NamedCollections.h>
#include <Interpreters/evaluateConstantExpression.h>
#include <Storages/checkAndGetLiteralArgument.h>
#include <Parsers/ASTIdentifier.h>
#include <Parsers/ASTFunction.h>
namespace DB
{
2022-12-22 11:15:34 +00:00
namespace ErrorCodes
{
extern const int BAD_ARGUMENTS;
}
namespace
{
2023-06-06 12:46:34 +00:00
std::optional<std::string> getCollectionName(ASTs asts)
{
if (asts.empty())
2023-06-06 12:46:34 +00:00
return std::nullopt;
const auto * identifier = asts[0]->as<ASTIdentifier>();
if (!identifier)
2023-06-06 12:46:34 +00:00
return std::nullopt;
2023-06-06 12:46:34 +00:00
return identifier->name();
}
2023-03-05 11:50:29 +00:00
std::optional<std::pair<std::string, std::variant<Field, ASTPtr>>> getKeyValueFromAST(ASTPtr ast, bool fallback_to_ast_value, ContextPtr context)
{
const auto * function = ast->as<ASTFunction>();
if (!function || function->name != "equals")
return std::nullopt;
const auto * function_args_expr = assert_cast<const ASTExpressionList *>(function->arguments.get());
const auto & function_args = function_args_expr->children;
if (function_args.size() != 2)
return std::nullopt;
2023-03-01 12:37:05 +00:00
auto literal_key = evaluateConstantExpressionOrIdentifierAsLiteral(function_args[0], context);
auto key = checkAndGetLiteralArgument<String>(literal_key, "key");
2023-03-01 12:37:05 +00:00
ASTPtr literal_value;
try
{
2023-03-05 11:50:29 +00:00
if (key == "database" || key == "db")
literal_value = evaluateConstantExpressionForDatabaseName(function_args[1], context);
else
literal_value = evaluateConstantExpressionOrIdentifierAsLiteral(function_args[1], context);
2023-03-01 12:37:05 +00:00
}
catch (...)
{
2023-03-02 18:04:33 +00:00
if (fallback_to_ast_value)
return std::pair{key, function_args[1]};
throw;
2023-03-01 12:37:05 +00:00
}
2023-03-01 12:37:05 +00:00
auto value = literal_value->as<ASTLiteral>()->value;
2023-03-17 12:56:02 +00:00
return std::pair{key, Field(value)};
}
}
2023-03-02 18:04:33 +00:00
MutableNamedCollectionPtr tryGetNamedCollectionWithOverrides(
2023-03-05 11:50:29 +00:00
ASTs asts, ContextPtr context, bool throw_unknown_collection, std::vector<std::pair<std::string, ASTPtr>> * complex_args)
{
if (asts.empty())
return nullptr;
2023-02-20 14:29:09 +00:00
NamedCollectionUtils::loadIfNot();
2023-06-06 12:46:34 +00:00
auto collection_name = getCollectionName(asts);
if (!collection_name.has_value())
return nullptr;
2023-06-15 10:35:13 +00:00
context->checkAccess(AccessType::NAMED_COLLECTION, *collection_name);
2023-06-13 10:40:53 +00:00
2023-06-06 12:46:34 +00:00
NamedCollectionPtr collection;
if (throw_unknown_collection)
collection = NamedCollectionFactory::instance().get(*collection_name);
else
collection = NamedCollectionFactory::instance().tryGet(*collection_name);
if (!collection)
return nullptr;
auto collection_copy = collection->duplicate();
2023-02-20 20:37:38 +00:00
if (asts.size() == 1)
return collection_copy;
2023-01-04 14:29:06 +00:00
for (auto * it = std::next(asts.begin()); it != asts.end(); ++it)
{
2023-03-17 12:56:02 +00:00
auto value_override = getKeyValueFromAST(*it, /* fallback_to_ast_value */complex_args != nullptr, context);
2023-03-01 12:37:05 +00:00
2022-12-22 11:15:34 +00:00
if (!value_override && !(*it)->as<ASTFunction>())
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Expected key-value argument or function");
if (!value_override)
continue;
2023-03-01 12:37:05 +00:00
if (const ASTPtr * value = std::get_if<ASTPtr>(&value_override->second))
{
2023-03-02 18:04:33 +00:00
complex_args->emplace_back(value_override->first, *value);
2023-03-01 12:37:05 +00:00
continue;
}
const auto & [key, value] = *value_override;
2023-03-01 12:37:05 +00:00
collection_copy->setOrUpdate<String>(key, toString(std::get<Field>(value_override->second)));
}
return collection_copy;
}
2023-03-02 18:04:33 +00:00
MutableNamedCollectionPtr tryGetNamedCollectionWithOverrides(
2023-06-06 12:46:34 +00:00
const Poco::Util::AbstractConfiguration & config, const std::string & config_prefix, ContextPtr context)
2023-02-20 20:37:38 +00:00
{
auto collection_name = config.getString(config_prefix + ".name", "");
if (collection_name.empty())
return nullptr;
2023-06-15 10:35:13 +00:00
context->checkAccess(AccessType::NAMED_COLLECTION, collection_name);
2023-06-06 12:46:34 +00:00
2023-02-20 20:37:38 +00:00
const auto & collection = NamedCollectionFactory::instance().get(collection_name);
auto collection_copy = collection->duplicate();
Poco::Util::AbstractConfiguration::Keys keys;
config.keys(config_prefix, keys);
for (const auto & key : keys)
collection_copy->setOrUpdate<String>(key, config.getString(config_prefix + '.' + key));
return collection_copy;
}
HTTPHeaderEntries getHeadersFromNamedCollection(const NamedCollection & collection)
{
HTTPHeaderEntries headers;
auto keys = collection.getKeys(0, "headers");
for (const auto & key : keys)
headers.emplace_back(collection.get<String>(key + ".name"), collection.get<String>(key + ".value"));
return headers;
}
}