2020-02-19 15:01:08 +00:00
|
|
|
#include "Internals.h"
|
|
|
|
|
2020-02-20 09:06:00 +00:00
|
|
|
namespace DB
|
2020-02-19 20:50:27 +00:00
|
|
|
{
|
2020-02-19 15:01:08 +00:00
|
|
|
|
2020-02-19 15:59:47 +00:00
|
|
|
ConfigurationPtr getConfigurationFromXMLString(const std::string & xml_data)
|
|
|
|
{
|
2020-02-19 15:01:08 +00:00
|
|
|
std::stringstream ss(xml_data);
|
|
|
|
Poco::XML::InputSource input_source{ss};
|
|
|
|
return {new Poco::Util::XMLConfiguration{&input_source}};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-19 15:59:47 +00:00
|
|
|
String getQuotedTable(const String & database, const String & table)
|
|
|
|
{
|
|
|
|
if (database.empty())
|
2020-02-19 15:01:08 +00:00
|
|
|
return backQuoteIfNeed(table);
|
|
|
|
|
|
|
|
return backQuoteIfNeed(database) + "." + backQuoteIfNeed(table);
|
|
|
|
}
|
|
|
|
|
2020-02-19 15:59:47 +00:00
|
|
|
String getQuotedTable(const DatabaseAndTableName & db_and_table)
|
|
|
|
{
|
2020-02-19 15:01:08 +00:00
|
|
|
return getQuotedTable(db_and_table.first, db_and_table.second);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Creates AST representing 'ENGINE = Distributed(cluster, db, table, [sharding_key])
|
|
|
|
std::shared_ptr<ASTStorage> createASTStorageDistributed(
|
2020-02-19 15:45:49 +00:00
|
|
|
const String & cluster_name, const String & database, const String & table,
|
2020-02-19 15:59:47 +00:00
|
|
|
const ASTPtr & sharding_key_ast)
|
|
|
|
{
|
2020-02-19 15:01:08 +00:00
|
|
|
auto args = std::make_shared<ASTExpressionList>();
|
|
|
|
args->children.emplace_back(std::make_shared<ASTLiteral>(cluster_name));
|
|
|
|
args->children.emplace_back(std::make_shared<ASTIdentifier>(database));
|
|
|
|
args->children.emplace_back(std::make_shared<ASTIdentifier>(table));
|
|
|
|
if (sharding_key_ast)
|
|
|
|
args->children.emplace_back(sharding_key_ast);
|
|
|
|
|
|
|
|
auto engine = std::make_shared<ASTFunction>();
|
|
|
|
engine->name = "Distributed";
|
|
|
|
engine->arguments = args;
|
|
|
|
|
|
|
|
auto storage = std::make_shared<ASTStorage>();
|
|
|
|
storage->set(storage->engine, engine);
|
|
|
|
|
|
|
|
return storage;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-19 15:59:47 +00:00
|
|
|
BlockInputStreamPtr squashStreamIntoOneBlock(const BlockInputStreamPtr & stream)
|
|
|
|
{
|
2020-02-19 15:01:08 +00:00
|
|
|
return std::make_shared<SquashingBlockInputStream>(
|
|
|
|
stream,
|
|
|
|
std::numeric_limits<size_t>::max(),
|
|
|
|
std::numeric_limits<size_t>::max());
|
|
|
|
}
|
|
|
|
|
2020-02-19 15:59:47 +00:00
|
|
|
Block getBlockWithAllStreamData(const BlockInputStreamPtr & stream)
|
|
|
|
{
|
2020-02-19 15:01:08 +00:00
|
|
|
return squashStreamIntoOneBlock(stream)->read();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-19 15:59:47 +00:00
|
|
|
bool isExtendedDefinitionStorage(const ASTPtr & storage_ast)
|
|
|
|
{
|
2020-02-19 15:45:49 +00:00
|
|
|
const auto & storage = storage_ast->as<ASTStorage &>();
|
2020-02-19 15:01:08 +00:00
|
|
|
return storage.partition_by || storage.order_by || storage.sample_by;
|
|
|
|
}
|
|
|
|
|
2020-02-19 15:59:47 +00:00
|
|
|
ASTPtr extractPartitionKey(const ASTPtr & storage_ast)
|
|
|
|
{
|
2020-02-19 15:01:08 +00:00
|
|
|
String storage_str = queryToString(storage_ast);
|
|
|
|
|
2020-02-19 15:45:49 +00:00
|
|
|
const auto & storage = storage_ast->as<ASTStorage &>();
|
|
|
|
const auto & engine = storage.engine->as<ASTFunction &>();
|
2020-02-19 15:01:08 +00:00
|
|
|
|
2020-02-19 15:59:47 +00:00
|
|
|
if (!endsWith(engine.name, "MergeTree"))
|
|
|
|
{
|
2020-02-19 15:01:08 +00:00
|
|
|
throw Exception(
|
|
|
|
"Unsupported engine was specified in " + storage_str + ", only *MergeTree engines are supported",
|
|
|
|
ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
}
|
|
|
|
|
2020-02-19 15:59:47 +00:00
|
|
|
if (isExtendedDefinitionStorage(storage_ast))
|
|
|
|
{
|
2020-02-19 15:01:08 +00:00
|
|
|
if (storage.partition_by)
|
|
|
|
return storage.partition_by->clone();
|
|
|
|
|
2020-02-19 15:45:49 +00:00
|
|
|
static const char * all = "all";
|
2020-02-19 15:01:08 +00:00
|
|
|
return std::make_shared<ASTLiteral>(Field(all, strlen(all)));
|
2020-02-19 15:59:47 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-02-19 15:01:08 +00:00
|
|
|
bool is_replicated = startsWith(engine.name, "Replicated");
|
|
|
|
size_t min_args = is_replicated ? 3 : 1;
|
|
|
|
|
|
|
|
if (!engine.arguments)
|
|
|
|
throw Exception("Expected arguments in " + storage_str, ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
|
|
|
ASTPtr arguments_ast = engine.arguments->clone();
|
2020-02-19 15:45:49 +00:00
|
|
|
ASTs & arguments = arguments_ast->children;
|
2020-02-19 15:01:08 +00:00
|
|
|
|
|
|
|
if (arguments.size() < min_args)
|
|
|
|
throw Exception("Expected at least " + toString(min_args) + " arguments in " + storage_str,
|
|
|
|
ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
2020-02-19 15:45:49 +00:00
|
|
|
ASTPtr & month_arg = is_replicated ? arguments[2] : arguments[1];
|
2020-02-19 15:01:08 +00:00
|
|
|
return makeASTFunction("toYYYYMM", month_arg->clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-19 15:59:47 +00:00
|
|
|
ShardPriority getReplicasPriority(const Cluster::Addresses & replicas, const std::string & local_hostname, UInt8 random)
|
|
|
|
{
|
2020-02-19 15:01:08 +00:00
|
|
|
ShardPriority res;
|
|
|
|
|
|
|
|
if (replicas.empty())
|
|
|
|
return res;
|
|
|
|
|
|
|
|
res.is_remote = 1;
|
|
|
|
for (auto & replica : replicas)
|
|
|
|
{
|
|
|
|
if (isLocalAddress(DNSResolver::instance().resolveHost(replica.host_name)))
|
|
|
|
{
|
|
|
|
res.is_remote = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res.hostname_difference = std::numeric_limits<size_t>::max();
|
|
|
|
for (auto & replica : replicas)
|
|
|
|
{
|
|
|
|
size_t difference = getHostNameDifference(local_hostname, replica.host_name);
|
|
|
|
res.hostname_difference = std::min(difference, res.hostname_difference);
|
|
|
|
}
|
|
|
|
|
|
|
|
res.random = random;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|