mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 16:42:05 +00:00
added hash of itiator address
This commit is contained in:
parent
2549468c14
commit
4e4b383214
@ -114,7 +114,7 @@ RemoteQueryExecutor::~RemoteQueryExecutor()
|
|||||||
/** If we receive a block with slightly different column types, or with excessive columns,
|
/** If we receive a block with slightly different column types, or with excessive columns,
|
||||||
* we will adapt it to expected structure.
|
* we will adapt it to expected structure.
|
||||||
*/
|
*/
|
||||||
[[maybe_unused]] static Block adaptBlockStructure(const Block & block, const Block & header)
|
static Block adaptBlockStructure(const Block & block, const Block & header)
|
||||||
{
|
{
|
||||||
/// Special case when reader doesn't care about result structure. Deprecated and used only in Benchmark, PerformanceTest.
|
/// Special case when reader doesn't care about result structure. Deprecated and used only in Benchmark, PerformanceTest.
|
||||||
if (!header)
|
if (!header)
|
||||||
@ -123,9 +123,6 @@ RemoteQueryExecutor::~RemoteQueryExecutor()
|
|||||||
Block res;
|
Block res;
|
||||||
res.info = block.info;
|
res.info = block.info;
|
||||||
|
|
||||||
std::cout << "block " << block.dumpStructure() << std::endl;
|
|
||||||
std::cout << "header " << header.dumpStructure() << std::endl;
|
|
||||||
|
|
||||||
for (const auto & elem : header)
|
for (const auto & elem : header)
|
||||||
{
|
{
|
||||||
ColumnPtr column;
|
ColumnPtr column;
|
||||||
@ -156,17 +153,7 @@ RemoteQueryExecutor::~RemoteQueryExecutor()
|
|||||||
column = elem.column->cloneResized(block.rows());
|
column = elem.column->cloneResized(block.rows());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
// if (!block.has(elem.name))
|
|
||||||
// {
|
|
||||||
// column = elem.type->createColumn();
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// column = castColumn(block.getByName(elem.name), elem.type);
|
|
||||||
// }
|
|
||||||
column = castColumn(block.getByName(elem.name), elem.type);
|
column = castColumn(block.getByName(elem.name), elem.type);
|
||||||
}
|
|
||||||
|
|
||||||
res.insert({column, elem.type, elem.name});
|
res.insert({column, elem.type, elem.name});
|
||||||
}
|
}
|
||||||
@ -327,12 +314,7 @@ std::optional<Block> RemoteQueryExecutor::processPacket(Packet packet)
|
|||||||
case Protocol::Server::Data:
|
case Protocol::Server::Data:
|
||||||
/// If the block is not empty and is not a header block
|
/// If the block is not empty and is not a header block
|
||||||
if (packet.block && (packet.block.rows() > 0))
|
if (packet.block && (packet.block.rows() > 0))
|
||||||
{
|
return adaptBlockStructure(packet.block, header);
|
||||||
// return packet.block;
|
|
||||||
Block anime = adaptBlockStructure(packet.block, header);
|
|
||||||
std::cout << "RemoteQueryExecutor " << anime.dumpStructure() << std::endl;
|
|
||||||
return anime;
|
|
||||||
}
|
|
||||||
break; /// If the block is empty - we will receive other packets before EndOfStream.
|
break; /// If the block is empty - we will receive other packets before EndOfStream.
|
||||||
|
|
||||||
case Protocol::Server::Exception:
|
case Protocol::Server::Exception:
|
||||||
|
@ -399,7 +399,6 @@ namespace S3
|
|||||||
else
|
else
|
||||||
throw Exception("Bucket or key name are invalid in S3 URI: " + uri.toString(), ErrorCodes::BAD_ARGUMENTS);
|
throw Exception("Bucket or key name are invalid in S3 URI: " + uri.toString(), ErrorCodes::BAD_ARGUMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -138,6 +138,17 @@ String Cluster::Address::toString() const
|
|||||||
return toString(host_name, port);
|
return toString(host_name, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String Cluster::Address::getHash() const
|
||||||
|
{
|
||||||
|
SipHash hash;
|
||||||
|
hash.update(host_name);
|
||||||
|
hash.update(std::to_string(port));
|
||||||
|
hash.update(user);
|
||||||
|
hash.update(password);
|
||||||
|
return std::to_string(hash.get64());
|
||||||
|
}
|
||||||
|
|
||||||
String Cluster::Address::toString(const String & host_name, UInt16 port)
|
String Cluster::Address::toString(const String & host_name, UInt16 port)
|
||||||
{
|
{
|
||||||
return escapeForFileName(host_name) + ':' + DB::toString(port);
|
return escapeForFileName(host_name) + ':' + DB::toString(port);
|
||||||
|
@ -122,6 +122,9 @@ public:
|
|||||||
|
|
||||||
/// Returns 'escaped_host_name:port'
|
/// Returns 'escaped_host_name:port'
|
||||||
String toString() const;
|
String toString() const;
|
||||||
|
|
||||||
|
/// Returns hash of all fields
|
||||||
|
String getHash() const;
|
||||||
|
|
||||||
/// Returns 'host_name:port'
|
/// Returns 'host_name:port'
|
||||||
String readableString() const;
|
String readableString() const;
|
||||||
|
@ -26,9 +26,9 @@ struct DatabaseAndTableWithAlias
|
|||||||
UUID uuid = UUIDHelpers::Nil;
|
UUID uuid = UUIDHelpers::Nil;
|
||||||
|
|
||||||
DatabaseAndTableWithAlias() = default;
|
DatabaseAndTableWithAlias() = default;
|
||||||
DatabaseAndTableWithAlias(const ASTPtr & identifier_node, const String & current_database = "");
|
explicit DatabaseAndTableWithAlias(const ASTPtr & identifier_node, const String & current_database = "");
|
||||||
DatabaseAndTableWithAlias(const ASTIdentifier & identifier, const String & current_database = "");
|
explicit DatabaseAndTableWithAlias(const ASTIdentifier & identifier, const String & current_database = "");
|
||||||
DatabaseAndTableWithAlias(const ASTTableExpression & table_expression, const String & current_database = "");
|
explicit DatabaseAndTableWithAlias(const ASTTableExpression & table_expression, const String & current_database = "");
|
||||||
|
|
||||||
/// "alias." or "table." if alias is empty
|
/// "alias." or "table." if alias is empty
|
||||||
String getQualifiedNamePrefix(bool with_dot = true) const;
|
String getQualifiedNamePrefix(bool with_dot = true) const;
|
||||||
@ -80,7 +80,7 @@ private:
|
|||||||
void addAdditionalColumns(NamesAndTypesList & target, const NamesAndTypesList & addition)
|
void addAdditionalColumns(NamesAndTypesList & target, const NamesAndTypesList & addition)
|
||||||
{
|
{
|
||||||
target.insert(target.end(), addition.begin(), addition.end());
|
target.insert(target.end(), addition.begin(), addition.end());
|
||||||
for (auto & col : addition)
|
for (const auto & col : addition)
|
||||||
names.insert(col.name);
|
names.insert(col.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ public:
|
|||||||
bool second_with_brackets;
|
bool second_with_brackets;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ASTPair(bool second_with_brackets_)
|
explicit ASTPair(bool second_with_brackets_)
|
||||||
: second_with_brackets(second_with_brackets_)
|
: second_with_brackets(second_with_brackets_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ public:
|
|||||||
/// Has brackets around arguments
|
/// Has brackets around arguments
|
||||||
bool has_brackets;
|
bool has_brackets;
|
||||||
|
|
||||||
ASTFunctionWithKeyValueArguments(bool has_brackets_ = true)
|
explicit ASTFunctionWithKeyValueArguments(bool has_brackets_ = true)
|
||||||
: has_brackets(has_brackets_)
|
: has_brackets(has_brackets_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ protected:
|
|||||||
class ParserIdentifier : public IParserBase
|
class ParserIdentifier : public IParserBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ParserIdentifier(bool allow_query_parameter_ = false) : allow_query_parameter(allow_query_parameter_) {}
|
explicit ParserIdentifier(bool allow_query_parameter_ = false) : allow_query_parameter(allow_query_parameter_) {}
|
||||||
protected:
|
protected:
|
||||||
const char * getName() const override { return "identifier"; }
|
const char * getName() const override { return "identifier"; }
|
||||||
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
@ -59,7 +59,7 @@ protected:
|
|||||||
class ParserCompoundIdentifier : public IParserBase
|
class ParserCompoundIdentifier : public IParserBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ParserCompoundIdentifier(bool table_name_with_optional_uuid_ = false, bool allow_query_parameter_ = false)
|
explicit ParserCompoundIdentifier(bool table_name_with_optional_uuid_ = false, bool allow_query_parameter_ = false)
|
||||||
: table_name_with_optional_uuid(table_name_with_optional_uuid_), allow_query_parameter(allow_query_parameter_)
|
: table_name_with_optional_uuid(table_name_with_optional_uuid_), allow_query_parameter(allow_query_parameter_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ public:
|
|||||||
using ColumnTransformers = MultiEnum<ColumnTransformer, UInt8>;
|
using ColumnTransformers = MultiEnum<ColumnTransformer, UInt8>;
|
||||||
static constexpr auto AllTransformers = ColumnTransformers{ColumnTransformer::APPLY, ColumnTransformer::EXCEPT, ColumnTransformer::REPLACE};
|
static constexpr auto AllTransformers = ColumnTransformers{ColumnTransformer::APPLY, ColumnTransformer::EXCEPT, ColumnTransformer::REPLACE};
|
||||||
|
|
||||||
ParserColumnsTransformers(ColumnTransformers allowed_transformers_ = AllTransformers, bool is_strict_ = false)
|
explicit ParserColumnsTransformers(ColumnTransformers allowed_transformers_ = AllTransformers, bool is_strict_ = false)
|
||||||
: allowed_transformers(allowed_transformers_)
|
: allowed_transformers(allowed_transformers_)
|
||||||
, is_strict(is_strict_)
|
, is_strict(is_strict_)
|
||||||
{}
|
{}
|
||||||
@ -103,7 +103,7 @@ class ParserAsterisk : public IParserBase
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ColumnTransformers = ParserColumnsTransformers::ColumnTransformers;
|
using ColumnTransformers = ParserColumnsTransformers::ColumnTransformers;
|
||||||
ParserAsterisk(ColumnTransformers allowed_transformers_ = ParserColumnsTransformers::AllTransformers)
|
explicit ParserAsterisk(ColumnTransformers allowed_transformers_ = ParserColumnsTransformers::AllTransformers)
|
||||||
: allowed_transformers(allowed_transformers_)
|
: allowed_transformers(allowed_transformers_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ class ParserColumnsMatcher : public IParserBase
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ColumnTransformers = ParserColumnsTransformers::ColumnTransformers;
|
using ColumnTransformers = ParserColumnsTransformers::ColumnTransformers;
|
||||||
ParserColumnsMatcher(ColumnTransformers allowed_transformers_ = ParserColumnsTransformers::AllTransformers)
|
explicit ParserColumnsMatcher(ColumnTransformers allowed_transformers_ = ParserColumnsTransformers::AllTransformers)
|
||||||
: allowed_transformers(allowed_transformers_)
|
: allowed_transformers(allowed_transformers_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ protected:
|
|||||||
class ParserFunction : public IParserBase
|
class ParserFunction : public IParserBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ParserFunction(bool allow_function_parameters_ = true, bool is_table_function_ = false)
|
explicit ParserFunction(bool allow_function_parameters_ = true, bool is_table_function_ = false)
|
||||||
: allow_function_parameters(allow_function_parameters_), is_table_function(is_table_function_)
|
: allow_function_parameters(allow_function_parameters_), is_table_function(is_table_function_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,12 @@
|
|||||||
#include <Storages/SelectQueryInfo.h>
|
#include <Storages/SelectQueryInfo.h>
|
||||||
#include <Storages/StorageS3.h>
|
#include <Storages/StorageS3.h>
|
||||||
#include <Parsers/queryToString.h>
|
#include <Parsers/queryToString.h>
|
||||||
|
#include <Parsers/ASTTablesInSelectQuery.h>
|
||||||
|
|
||||||
#include <Interpreters/getHeaderForProcessingStage.h>
|
#include <Interpreters/getHeaderForProcessingStage.h>
|
||||||
#include <Interpreters/SelectQueryOptions.h>
|
#include <Interpreters/SelectQueryOptions.h>
|
||||||
#include <Interpreters/InterpreterSelectQuery.h>
|
#include <Interpreters/InterpreterSelectQuery.h>
|
||||||
|
#include <Interpreters/getTableExpressions.h>
|
||||||
|
|
||||||
#include <Poco/Logger.h>
|
#include <Poco/Logger.h>
|
||||||
#include <Poco/Net/TCPServerConnection.h>
|
#include <Poco/Net/TCPServerConnection.h>
|
||||||
@ -61,6 +63,19 @@ namespace ErrorCodes
|
|||||||
extern const int LOGICAL_ERROR;
|
extern const int LOGICAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StorageS3SourceBuilder
|
||||||
|
{
|
||||||
|
bool need_path;
|
||||||
|
bool need_file;
|
||||||
|
String format;
|
||||||
|
String name;
|
||||||
|
Block sample_block;
|
||||||
|
const Context & context;
|
||||||
|
const ColumnsDescription & columns;
|
||||||
|
UInt64 max_block_size;
|
||||||
|
String compression_method;
|
||||||
|
};
|
||||||
|
|
||||||
class StorageS3SequentialSource : public SourceWithProgress
|
class StorageS3SequentialSource : public SourceWithProgress
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -77,37 +92,23 @@ public:
|
|||||||
|
|
||||||
StorageS3SequentialSource(
|
StorageS3SequentialSource(
|
||||||
String initial_query_id_,
|
String initial_query_id_,
|
||||||
bool need_path_,
|
Cluster::Address initiator,
|
||||||
bool need_file_,
|
const ClientAuthentificationBuilder & client_auth_builder_,
|
||||||
const String & format_,
|
const StorageS3SourceBuilder & s3_builder_)
|
||||||
String name_,
|
: SourceWithProgress(getHeader(s3_builder_.sample_block, s3_builder_.need_path, s3_builder_.need_file))
|
||||||
const Block & sample_block_,
|
|
||||||
const Context & context_,
|
|
||||||
const ColumnsDescription & columns_,
|
|
||||||
UInt64 max_block_size_,
|
|
||||||
const CompressionMethod compression_method_,
|
|
||||||
StorageS3::ClientAuthentificaiton & client_auth_)
|
|
||||||
: SourceWithProgress(getHeader(sample_block_, need_path_, need_file_))
|
|
||||||
, need_path(need_path_)
|
|
||||||
, need_file(need_file_)
|
|
||||||
, format(format_)
|
|
||||||
, name(name_)
|
|
||||||
, sample_block(sample_block_)
|
|
||||||
, context(context_)
|
|
||||||
, columns(columns_)
|
|
||||||
, max_block_size(max_block_size_)
|
|
||||||
, compression_method(compression_method_)
|
|
||||||
, client_auth(client_auth_)
|
|
||||||
, initial_query_id(initial_query_id_)
|
, initial_query_id(initial_query_id_)
|
||||||
|
, s3_source_builder(s3_builder_)
|
||||||
|
, cli_builder(client_auth_builder_)
|
||||||
{
|
{
|
||||||
initiator_connection = std::make_shared<Connection>(
|
connections = std::make_shared<ConnectionPool>(
|
||||||
/*host*/"127.0.0.1",
|
/*max_connections*/3,
|
||||||
/*port*/9000,
|
/*host*/initiator.host_name,
|
||||||
/*default_database=*/context.getGlobalContext().getCurrentDatabase(),
|
/*port*/initiator.port,
|
||||||
/*user=*/context.getClientInfo().initial_user,
|
/*default_database=*/s3_builder_.context.getGlobalContext().getCurrentDatabase(),
|
||||||
/*password=*/"",
|
/*user=*/s3_builder_.context.getClientInfo().initial_user,
|
||||||
/*cluster=*/"",
|
/*password=*/initiator.password,
|
||||||
/*cluster_secret=*/""
|
/*cluster=*/initiator.cluster,
|
||||||
|
/*cluster_secret=*/initiator.cluster_secret
|
||||||
);
|
);
|
||||||
|
|
||||||
createOrUpdateInnerSource();
|
createOrUpdateInnerSource();
|
||||||
@ -115,7 +116,7 @@ public:
|
|||||||
|
|
||||||
String getName() const override
|
String getName() const override
|
||||||
{
|
{
|
||||||
return name;
|
return "StorageS3SequentialSource";
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk generate() override
|
Chunk generate() override
|
||||||
@ -131,7 +132,6 @@ public:
|
|||||||
else
|
else
|
||||||
chunk = inner->generate();
|
chunk = inner->generate();
|
||||||
}
|
}
|
||||||
std::cout << "generate() " << chunk.dumpStructure() << std::endl;
|
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,9 +141,9 @@ private:
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
initiator_connection->connect(timeouts);
|
auto connection = connections->get(timeouts);
|
||||||
initiator_connection->sendNextTaskRequest(initial_query_id);
|
connection->sendNextTaskRequest(initial_query_id);
|
||||||
auto packet = initiator_connection->receivePacket();
|
auto packet = connection->receivePacket();
|
||||||
assert(packet.type = Protocol::Server::NextTaskReply);
|
assert(packet.type = Protocol::Server::NextTaskReply);
|
||||||
LOG_TRACE(&Poco::Logger::get("StorageS3SequentialSource"), "Got new task {}", packet.next_task);
|
LOG_TRACE(&Poco::Logger::get("StorageS3SequentialSource"), "Got new task {}", packet.next_task);
|
||||||
return packet.next_task;
|
return packet.next_task;
|
||||||
@ -155,28 +155,32 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool createOrUpdateInnerSource()
|
bool createOrUpdateInnerSource()
|
||||||
{
|
{
|
||||||
auto next_string = askAboutNextKey();
|
auto next_string = askAboutNextKey();
|
||||||
std::cout << "createOrUpdateInnerSource " << next_string << std::endl;
|
|
||||||
if (next_string.empty())
|
if (next_string.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto next_uri = S3::URI(Poco::URI(next_string));
|
auto next_uri = S3::URI(Poco::URI(next_string));
|
||||||
|
|
||||||
assert(next_uri.bucket == client_auth.uri.bucket);
|
auto client_auth = StorageS3::ClientAuthentificaiton{
|
||||||
|
next_uri,
|
||||||
|
cli_builder.access_key_id,
|
||||||
|
cli_builder.secret_access_key,
|
||||||
|
cli_builder.max_connections,
|
||||||
|
{}, {}};
|
||||||
|
StorageS3::updateClientAndAuthSettings(s3_source_builder.context, client_auth);
|
||||||
|
|
||||||
inner = std::make_unique<StorageS3Source>(
|
inner = std::make_unique<StorageS3Source>(
|
||||||
need_path,
|
s3_source_builder.need_path,
|
||||||
need_file,
|
s3_source_builder.need_file,
|
||||||
format,
|
s3_source_builder.format,
|
||||||
name,
|
s3_source_builder.name,
|
||||||
sample_block,
|
s3_source_builder.sample_block,
|
||||||
context,
|
s3_source_builder.context,
|
||||||
columns,
|
s3_source_builder.columns,
|
||||||
max_block_size,
|
s3_source_builder.max_block_size,
|
||||||
compression_method,
|
chooseCompressionMethod(client_auth.uri.key, s3_source_builder.compression_method),
|
||||||
client_auth.client,
|
client_auth.client,
|
||||||
client_auth.uri.bucket,
|
client_auth.uri.bucket,
|
||||||
next_uri.key
|
next_uri.key
|
||||||
@ -184,30 +188,24 @@ private:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool need_path;
|
/// This is used to ask about next task
|
||||||
bool need_file;
|
String initial_query_id;
|
||||||
String format;
|
|
||||||
String name;
|
StorageS3SourceBuilder s3_source_builder;
|
||||||
Block sample_block;
|
ClientAuthentificationBuilder cli_builder;
|
||||||
const Context & context;
|
|
||||||
const ColumnsDescription & columns;
|
|
||||||
UInt64 max_block_size;
|
|
||||||
const CompressionMethod compression_method;
|
|
||||||
|
|
||||||
std::unique_ptr<StorageS3Source> inner;
|
std::unique_ptr<StorageS3Source> inner;
|
||||||
StorageS3::ClientAuthentificaiton client_auth;
|
|
||||||
|
|
||||||
/// One second just in case
|
/// One second just in case
|
||||||
ConnectionTimeouts timeouts{{1, 0}, {1, 0}, {1, 0}};
|
ConnectionTimeouts timeouts{{1, 0}, {1, 0}, {1, 0}};
|
||||||
std::shared_ptr<Connection> initiator_connection;
|
std::shared_ptr<ConnectionPool> connections;
|
||||||
/// This is used to ask about next task
|
|
||||||
String initial_query_id;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
StorageS3Distributed::StorageS3Distributed(
|
StorageS3Distributed::StorageS3Distributed(
|
||||||
const S3::URI & uri_,
|
IAST::Hash tree_hash_,
|
||||||
|
const String & address_hash_or_filename_,
|
||||||
const String & access_key_id_,
|
const String & access_key_id_,
|
||||||
const String & secret_access_key_,
|
const String & secret_access_key_,
|
||||||
const StorageID & table_id_,
|
const StorageID & table_id_,
|
||||||
@ -219,17 +217,18 @@ StorageS3Distributed::StorageS3Distributed(
|
|||||||
const Context & context_,
|
const Context & context_,
|
||||||
const String & compression_method_)
|
const String & compression_method_)
|
||||||
: IStorage(table_id_)
|
: IStorage(table_id_)
|
||||||
|
, tree_hash(tree_hash_)
|
||||||
|
, address_hash_or_filename(address_hash_or_filename_)
|
||||||
, cluster_name(cluster_name_)
|
, cluster_name(cluster_name_)
|
||||||
, cluster(context_.getCluster(cluster_name)->getClusterWithReplicasAsShards(context_.getSettings()))
|
, cluster(context_.getCluster(cluster_name)->getClusterWithReplicasAsShards(context_.getSettings()))
|
||||||
, client_auth{uri_, access_key_id_, secret_access_key_, max_connections_, {}, {}}
|
|
||||||
, format_name(format_name_)
|
, format_name(format_name_)
|
||||||
, compression_method(compression_method_)
|
, compression_method(compression_method_)
|
||||||
|
, cli_builder{access_key_id_, secret_access_key_, max_connections_}
|
||||||
{
|
{
|
||||||
StorageInMemoryMetadata storage_metadata;
|
StorageInMemoryMetadata storage_metadata;
|
||||||
storage_metadata.setColumns(columns_);
|
storage_metadata.setColumns(columns_);
|
||||||
storage_metadata.setConstraints(constraints_);
|
storage_metadata.setConstraints(constraints_);
|
||||||
setInMemoryMetadata(storage_metadata);
|
setInMemoryMetadata(storage_metadata);
|
||||||
StorageS3::updateClientAndAuthSettings(context_, client_auth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -246,7 +245,16 @@ Pipe StorageS3Distributed::read(
|
|||||||
/// Secondary query, need to read from S3
|
/// Secondary query, need to read from S3
|
||||||
if (context.getCurrentQueryId() != context.getInitialQueryId())
|
if (context.getCurrentQueryId() != context.getInitialQueryId())
|
||||||
{
|
{
|
||||||
StorageS3::updateClientAndAuthSettings(context, client_auth);
|
/// Find initiator in cluster
|
||||||
|
Cluster::Address initiator;
|
||||||
|
for (const auto & replicas : cluster->getShardsAddresses())
|
||||||
|
for (const auto & node : replicas)
|
||||||
|
if (node.getHash() == address_hash_or_filename)
|
||||||
|
{
|
||||||
|
initiator = node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool need_path_column = false;
|
bool need_path_column = false;
|
||||||
bool need_file_column = false;
|
bool need_file_column = false;
|
||||||
@ -258,13 +266,8 @@ Pipe StorageS3Distributed::read(
|
|||||||
need_file_column = true;
|
need_file_column = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << need_file_column << std::boolalpha << need_file_column << std::endl;
|
StorageS3SourceBuilder s3builder
|
||||||
std::cout << need_path_column << std::boolalpha << need_path_column << std::endl;
|
{
|
||||||
|
|
||||||
std::cout << "metadata_snapshot->getSampleBlock().dumpStructure() " << metadata_snapshot->getSampleBlock().dumpStructure() << std::endl;
|
|
||||||
|
|
||||||
return Pipe(std::make_shared<StorageS3SequentialSource>(
|
|
||||||
context.getInitialQueryId(),
|
|
||||||
need_path_column,
|
need_path_column,
|
||||||
need_file_column,
|
need_file_column,
|
||||||
format_name,
|
format_name,
|
||||||
@ -273,24 +276,65 @@ Pipe StorageS3Distributed::read(
|
|||||||
context,
|
context,
|
||||||
metadata_snapshot->getColumns(),
|
metadata_snapshot->getColumns(),
|
||||||
max_block_size,
|
max_block_size,
|
||||||
chooseCompressionMethod(client_auth.uri.key, compression_method),
|
compression_method
|
||||||
client_auth
|
};
|
||||||
|
|
||||||
|
return Pipe(std::make_shared<StorageS3SequentialSource>(
|
||||||
|
context.getInitialQueryId(),
|
||||||
|
/*initiator*/initiator,
|
||||||
|
cli_builder,
|
||||||
|
s3builder
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Pipes pipes;
|
/// This part of code executes on initiator
|
||||||
connections.reserve(cluster->getShardCount());
|
|
||||||
|
|
||||||
std::cout << "StorageS3Distributed::read" << std::endl;
|
String hash_of_address;
|
||||||
std::cout << "QueryProcessingStage " << processed_stage << std::endl;
|
for (const auto & replicas : cluster->getShardsAddresses())
|
||||||
|
for (const auto & node : replicas)
|
||||||
|
if (node.is_local && node.port == context.getTCPPort())
|
||||||
|
{
|
||||||
|
hash_of_address = node.getHash();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FIXME: better exception
|
||||||
|
if (hash_of_address.empty())
|
||||||
|
throw Exception(fmt::format("Could not find outself in cluster {}", ""), ErrorCodes::LOGICAL_ERROR);
|
||||||
|
|
||||||
|
auto remote_query_ast = query_info.query->clone();
|
||||||
|
auto table_expressions_from_whole_query = getTableExpressions(remote_query_ast->as<ASTSelectQuery &>());
|
||||||
|
|
||||||
|
String remote_query;
|
||||||
|
for (const auto & table_expression : table_expressions_from_whole_query)
|
||||||
|
{
|
||||||
|
const auto & table_function_ast = table_expression->table_function;
|
||||||
|
if (table_function_ast->getTreeHash() == tree_hash)
|
||||||
|
{
|
||||||
|
std::cout << table_function_ast->dumpTree() << std::endl;
|
||||||
|
auto & arguments = table_function_ast->children.at(0)->children;
|
||||||
|
auto & bucket = arguments[1]->as<ASTLiteral &>().value.safeGet<String>();
|
||||||
|
/// We rewrite query, and insert a port to connect as a first parameter
|
||||||
|
/// So, we write hash_of_address here as buckey name to find initiator node
|
||||||
|
/// in cluster from config on remote replica
|
||||||
|
bucket = hash_of_address;
|
||||||
|
remote_query = queryToString(remote_query_ast);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remote_query.empty())
|
||||||
|
throw Exception("No table function", ErrorCodes::LOGICAL_ERROR);
|
||||||
|
|
||||||
Block header =
|
Block header =
|
||||||
InterpreterSelectQuery(query_info.query, context, SelectQueryOptions(processed_stage).analyze()).getSampleBlock();
|
InterpreterSelectQuery(remote_query_ast, context, SelectQueryOptions(processed_stage).analyze()).getSampleBlock();
|
||||||
|
|
||||||
const Scalars & scalars = context.hasQueryContext() ? context.getQueryContext().getScalars() : Scalars{};
|
const Scalars & scalars = context.hasQueryContext() ? context.getQueryContext().getScalars() : Scalars{};
|
||||||
|
|
||||||
|
Pipes pipes;
|
||||||
|
connections.reserve(cluster->getShardCount());
|
||||||
|
|
||||||
for (const auto & replicas : cluster->getShardsAddresses()) {
|
for (const auto & replicas : cluster->getShardsAddresses()) {
|
||||||
/// There will be only one replica, because we consider each replica as a shard
|
/// There will be only one replica, because we consider each replica as a shard
|
||||||
for (const auto & node : replicas)
|
for (const auto & node : replicas)
|
||||||
@ -306,13 +350,13 @@ Pipe StorageS3Distributed::read(
|
|||||||
));
|
));
|
||||||
auto stream = std::make_shared<RemoteBlockInputStream>(
|
auto stream = std::make_shared<RemoteBlockInputStream>(
|
||||||
/*connection=*/*connections.back(),
|
/*connection=*/*connections.back(),
|
||||||
/*query=*/queryToString(query_info.query),
|
/*query=*/remote_query,
|
||||||
/*header=*/header,
|
/*header=*/header,
|
||||||
/*context=*/context,
|
/*context=*/context,
|
||||||
nullptr,
|
nullptr,
|
||||||
scalars,
|
scalars,
|
||||||
Tables(),
|
Tables(),
|
||||||
QueryProcessingStage::FetchColumns
|
processed_stage
|
||||||
);
|
);
|
||||||
pipes.emplace_back(std::make_shared<SourceFromInputStream>(std::move(stream)));
|
pipes.emplace_back(std::make_shared<SourceFromInputStream>(std::move(stream)));
|
||||||
}
|
}
|
||||||
@ -322,11 +366,5 @@ Pipe StorageS3Distributed::read(
|
|||||||
metadata_snapshot->check(column_names, getVirtuals(), getStorageID());
|
metadata_snapshot->check(column_names, getVirtuals(), getStorageID());
|
||||||
return Pipe::unitePipes(std::move(pipes));
|
return Pipe::unitePipes(std::move(pipes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,12 @@ namespace ErrorCodes
|
|||||||
|
|
||||||
class Context;
|
class Context;
|
||||||
|
|
||||||
|
struct ClientAuthentificationBuilder
|
||||||
|
{
|
||||||
|
String access_key_id;
|
||||||
|
String secret_access_key;
|
||||||
|
UInt64 max_connections;
|
||||||
|
};
|
||||||
|
|
||||||
class StorageS3Distributed : public ext::shared_ptr_helper<StorageS3Distributed>, public IStorage
|
class StorageS3Distributed : public ext::shared_ptr_helper<StorageS3Distributed>, public IStorage
|
||||||
{
|
{
|
||||||
@ -39,7 +45,8 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
StorageS3Distributed(
|
StorageS3Distributed(
|
||||||
const S3::URI & uri_,
|
IAST::Hash tree_hash_,
|
||||||
|
const String & address_hash_or_filename_,
|
||||||
const String & access_key_id_,
|
const String & access_key_id_,
|
||||||
const String & secret_access_key_,
|
const String & secret_access_key_,
|
||||||
const StorageID & table_id_,
|
const StorageID & table_id_,
|
||||||
@ -49,21 +56,19 @@ protected:
|
|||||||
const ColumnsDescription & columns_,
|
const ColumnsDescription & columns_,
|
||||||
const ConstraintsDescription & constraints_,
|
const ConstraintsDescription & constraints_,
|
||||||
const Context & context_,
|
const Context & context_,
|
||||||
const String & compression_method_ = "");
|
const String & compression_method_);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Connections from initiator to other nodes
|
/// Connections from initiator to other nodes
|
||||||
std::vector<std::shared_ptr<Connection>> connections;
|
std::vector<std::shared_ptr<Connection>> connections;
|
||||||
|
IAST::Hash tree_hash;
|
||||||
|
String address_hash_or_filename;
|
||||||
std::string cluster_name;
|
std::string cluster_name;
|
||||||
ClusterPtr cluster;
|
ClusterPtr cluster;
|
||||||
|
|
||||||
/// This will be used on non-initiator nodes.
|
|
||||||
std::optional<Cluster::Address> initiator;
|
|
||||||
std::shared_ptr<Connection> initiator_connection;
|
|
||||||
StorageS3::ClientAuthentificaiton client_auth;
|
|
||||||
|
|
||||||
String format_name;
|
String format_name;
|
||||||
String compression_method;
|
String compression_method;
|
||||||
|
ClientAuthentificationBuilder cli_builder;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <Common/config.h>
|
#include <Common/config.h>
|
||||||
#include "DataStreams/RemoteBlockInputStream.h"
|
#include "DataStreams/RemoteBlockInputStream.h"
|
||||||
|
#include "Parsers/ASTExpressionList.h"
|
||||||
#include "Parsers/ASTFunction.h"
|
#include "Parsers/ASTFunction.h"
|
||||||
#include "Parsers/IAST_fwd.h"
|
#include "Parsers/IAST_fwd.h"
|
||||||
#include "Processors/Sources/SourceFromInputStream.h"
|
#include "Processors/Sources/SourceFromInputStream.h"
|
||||||
@ -49,7 +50,7 @@ void TableFunctionS3Distributed::parseArguments(const ASTPtr & ast_function, con
|
|||||||
arg = evaluateConstantExpressionOrIdentifierAsLiteral(arg, context);
|
arg = evaluateConstantExpressionOrIdentifierAsLiteral(arg, context);
|
||||||
|
|
||||||
cluster_name = args[0]->as<ASTLiteral &>().value.safeGet<String>();
|
cluster_name = args[0]->as<ASTLiteral &>().value.safeGet<String>();
|
||||||
filename = args[1]->as<ASTLiteral &>().value.safeGet<String>();
|
filename_or_initiator_hash = args[1]->as<ASTLiteral &>().value.safeGet<String>();
|
||||||
|
|
||||||
if (args.size() < 5)
|
if (args.size() < 5)
|
||||||
{
|
{
|
||||||
@ -78,38 +79,38 @@ StoragePtr TableFunctionS3Distributed::executeImpl(
|
|||||||
const ASTPtr & ast_function, const Context & context,
|
const ASTPtr & ast_function, const Context & context,
|
||||||
const std::string & table_name, ColumnsDescription /*cached_columns*/) const
|
const std::string & table_name, ColumnsDescription /*cached_columns*/) const
|
||||||
{
|
{
|
||||||
Poco::URI uri (filename);
|
|
||||||
S3::URI s3_uri (uri);
|
|
||||||
// UInt64 min_upload_part_size = context.getSettingsRef().s3_min_upload_part_size;
|
|
||||||
// UInt64 max_single_part_upload_size = context.getSettingsRef().s3_max_single_part_upload_size;
|
|
||||||
UInt64 max_connections = context.getSettingsRef().s3_max_connections;
|
UInt64 max_connections = context.getSettingsRef().s3_max_connections;
|
||||||
|
|
||||||
StorageS3::ClientAuthentificaiton client_auth{s3_uri, access_key_id, secret_access_key, max_connections, {}, {}};
|
/// Initiator specific logic
|
||||||
StorageS3::updateClientAndAuthSettings(context, client_auth);
|
while (context.getInitialQueryId() == context.getCurrentQueryId())
|
||||||
|
|
||||||
auto lists = StorageS3::listFilesWithRegexpMatching(*client_auth.client, client_auth.uri);
|
|
||||||
Strings tasks;
|
|
||||||
tasks.reserve(lists.size());
|
|
||||||
|
|
||||||
for (auto & value : lists)
|
|
||||||
{
|
{
|
||||||
tasks.emplace_back(client_auth.uri.endpoint + '/' + client_auth.uri.bucket + '/' + value);
|
auto poco_uri = Poco::URI{filename_or_initiator_hash};
|
||||||
std::cout << tasks.back() << std::endl;
|
|
||||||
|
/// This is needed, because secondary query on local replica has the same query-id
|
||||||
|
if (poco_uri.getHost().empty() || poco_uri.getPort() == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
S3::URI s3_uri(poco_uri);
|
||||||
|
StorageS3::ClientAuthentificaiton client_auth{s3_uri, access_key_id, secret_access_key, max_connections, {}, {}};
|
||||||
|
StorageS3::updateClientAndAuthSettings(context, client_auth);
|
||||||
|
|
||||||
|
auto lists = StorageS3::listFilesWithRegexpMatching(*client_auth.client, client_auth.uri);
|
||||||
|
Strings tasks;
|
||||||
|
tasks.reserve(lists.size());
|
||||||
|
|
||||||
|
for (auto & value : lists)
|
||||||
|
tasks.emplace_back(client_auth.uri.endpoint + '/' + client_auth.uri.bucket + '/' + value);
|
||||||
|
|
||||||
|
/// Register resolver, which will give other nodes a task to execute
|
||||||
|
TaskSupervisor::instance().registerNextTaskResolver(
|
||||||
|
std::make_unique<S3NextTaskResolver>(context.getCurrentQueryId(), std::move(tasks)));
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "query_id " << context.getCurrentQueryId() << std::endl;
|
|
||||||
|
|
||||||
std::cout << ast_function->dumpTree() << std::endl;
|
|
||||||
auto * func = ast_function->as<ASTFunction>();
|
|
||||||
|
|
||||||
std::cout << func->arguments->dumpTree() << std::endl;
|
|
||||||
|
|
||||||
/// Register resolver, which will give other nodes a task to execute
|
|
||||||
TaskSupervisor::instance().registerNextTaskResolver(
|
|
||||||
std::make_unique<S3NextTaskResolver>(context.getCurrentQueryId(), std::move(tasks)));
|
|
||||||
|
|
||||||
StoragePtr storage = StorageS3Distributed::create(
|
StoragePtr storage = StorageS3Distributed::create(
|
||||||
s3_uri,
|
ast_function->getTreeHash(),
|
||||||
|
filename_or_initiator_hash,
|
||||||
access_key_id,
|
access_key_id,
|
||||||
secret_access_key,
|
secret_access_key,
|
||||||
StorageID(getDatabaseName(), table_name),
|
StorageID(getDatabaseName(), table_name),
|
||||||
|
@ -37,7 +37,7 @@ protected:
|
|||||||
void parseArguments(const ASTPtr & ast_function, const Context & context) override;
|
void parseArguments(const ASTPtr & ast_function, const Context & context) override;
|
||||||
|
|
||||||
String cluster_name;
|
String cluster_name;
|
||||||
String filename;
|
String filename_or_initiator_hash;
|
||||||
String format;
|
String format;
|
||||||
String structure;
|
String structure;
|
||||||
String access_key_id;
|
String access_key_id;
|
||||||
|
Loading…
Reference in New Issue
Block a user