2012-05-17 19:15:53 +00:00
|
|
|
#pragma once
|
|
|
|
|
2017-11-20 04:15:43 +00:00
|
|
|
#include <optional>
|
2017-04-17 16:16:04 +00:00
|
|
|
|
2015-09-29 19:19:54 +00:00
|
|
|
#include <common/logger_useful.h>
|
2012-10-16 18:12:29 +00:00
|
|
|
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <DataStreams/IProfilingBlockInputStream.h>
|
|
|
|
#include <Common/Throttler.h>
|
|
|
|
#include <Interpreters/Context.h>
|
|
|
|
#include <Client/ConnectionPool.h>
|
|
|
|
#include <Client/MultiplexedConnections.h>
|
|
|
|
#include <Interpreters/Cluster.h>
|
2016-10-10 08:44:52 +00:00
|
|
|
|
2012-05-17 19:15:53 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2017-02-10 20:13:43 +00:00
|
|
|
/** This class allowes one to launch queries on remote replicas of one shard and get results
|
2012-05-17 19:15:53 +00:00
|
|
|
*/
|
|
|
|
class RemoteBlockInputStream : public IProfilingBlockInputStream
|
|
|
|
{
|
2014-04-07 00:09:19 +00:00
|
|
|
public:
|
2017-07-31 15:03:22 +00:00
|
|
|
/// Takes already set connection.
|
|
|
|
/// If `settings` is nullptr, settings will be taken from context.
|
2017-07-28 19:34:25 +00:00
|
|
|
RemoteBlockInputStream(
|
|
|
|
Connection & connection,
|
|
|
|
const String & query_, const Context & context_, const Settings * settings = nullptr,
|
|
|
|
const ThrottlerPtr & throttler = nullptr, const Tables & external_tables_ = Tables(),
|
|
|
|
QueryProcessingStage::Enum stage_ = QueryProcessingStage::Complete);
|
|
|
|
|
|
|
|
/// Accepts several connections already taken from pool.
|
|
|
|
/// If `settings` is nullptr, settings will be taken from context.
|
|
|
|
RemoteBlockInputStream(
|
|
|
|
std::vector<IConnectionPool::Entry> && connections,
|
|
|
|
const String & query_, const Context & context_, const Settings * settings = nullptr,
|
|
|
|
const ThrottlerPtr & throttler = nullptr, const Tables & external_tables_ = Tables(),
|
|
|
|
QueryProcessingStage::Enum stage_ = QueryProcessingStage::Complete);
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-07-31 15:03:22 +00:00
|
|
|
/// Takes a pool and gets one or several connections from it.
|
|
|
|
/// If `settings` is nullptr, settings will be taken from context.
|
2017-07-28 19:34:25 +00:00
|
|
|
RemoteBlockInputStream(
|
|
|
|
const ConnectionPoolWithFailoverPtr & pool,
|
|
|
|
const String & query_, const Context & context_, const Settings * settings = nullptr,
|
|
|
|
const ThrottlerPtr & throttler = nullptr, const Tables & external_tables_ = Tables(),
|
|
|
|
QueryProcessingStage::Enum stage_ = QueryProcessingStage::Complete);
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
~RemoteBlockInputStream() override;
|
|
|
|
|
|
|
|
/// Specify how we allocate connections on a shard.
|
2017-04-17 16:16:04 +00:00
|
|
|
void setPoolMode(PoolMode pool_mode_) { pool_mode = pool_mode_; }
|
|
|
|
|
|
|
|
void setMainTable(QualifiedTableName main_table_) { main_table = std::move(main_table_); }
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
/// Besides blocks themself, get blocks' extra info
|
|
|
|
void appendExtraInfo();
|
|
|
|
|
|
|
|
/// Sends query (initiates calculation) before read()
|
|
|
|
void readPrefix() override;
|
|
|
|
|
|
|
|
/** Prevent default progress notification because progress' callback is
|
|
|
|
called by its own
|
|
|
|
*/
|
2017-12-01 18:36:55 +00:00
|
|
|
void progress(const Progress & /*value*/) override {}
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
void cancel() override;
|
|
|
|
|
|
|
|
String getName() const override { return "Remote"; }
|
|
|
|
|
|
|
|
String getID() const override
|
|
|
|
{
|
|
|
|
std::stringstream res;
|
|
|
|
res << this;
|
|
|
|
return res.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockExtraInfo getBlockExtraInfo() const override
|
|
|
|
{
|
|
|
|
return multiplexed_connections->getBlockExtraInfo();
|
|
|
|
}
|
2015-10-12 14:53:16 +00:00
|
|
|
|
2012-10-20 02:10:47 +00:00
|
|
|
protected:
|
2017-04-01 07:20:54 +00:00
|
|
|
/// Send all temporary tables to remote servers
|
|
|
|
void sendExternalTables();
|
2014-03-13 15:00:06 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
Block readImpl() override;
|
2015-09-05 01:22:09 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void readSuffixImpl() override;
|
2013-09-13 20:33:09 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
/// Returns true if query was sent
|
|
|
|
bool isQueryPending() const;
|
2015-02-08 21:34:43 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
/// Returns true if exception was thrown
|
|
|
|
bool hasThrownException() const;
|
2015-02-06 12:33:15 +00:00
|
|
|
|
2015-02-21 13:59:15 +00:00
|
|
|
private:
|
2017-04-01 07:20:54 +00:00
|
|
|
void sendQuery();
|
2015-07-30 23:41:02 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
/// If wasn't sent yet, send request to cancell all connections to replicas
|
|
|
|
void tryCancel(const char * reason);
|
2015-07-30 23:41:02 +00:00
|
|
|
|
2012-05-17 19:15:53 +00:00
|
|
|
private:
|
2017-07-28 19:34:25 +00:00
|
|
|
std::function<std::unique_ptr<MultiplexedConnections>()> create_multiplexed_connections;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
std::unique_ptr<MultiplexedConnections> multiplexed_connections;
|
|
|
|
|
|
|
|
const String query;
|
2017-07-28 19:34:25 +00:00
|
|
|
Context context;
|
2017-04-01 07:20:54 +00:00
|
|
|
/// Temporary tables needed to be sent to remote servers
|
|
|
|
Tables external_tables;
|
|
|
|
QueryProcessingStage::Enum stage;
|
|
|
|
|
2017-08-18 19:30:39 +00:00
|
|
|
/// Streams for reading from temporary tables and following sending of data
|
2017-04-01 07:20:54 +00:00
|
|
|
/// to remote servers for GLOBAL-subqueries
|
|
|
|
std::vector<ExternalTablesData> external_tables_data;
|
|
|
|
std::mutex external_tables_mutex;
|
|
|
|
|
|
|
|
/// Connections to replicas are established, but no queries are sent yet
|
|
|
|
std::atomic<bool> established { false };
|
|
|
|
|
|
|
|
/// Query is sent (used before getting first block)
|
|
|
|
std::atomic<bool> sent_query { false };
|
|
|
|
|
|
|
|
/** All data from all replicas are received, before EndOfStream packet.
|
|
|
|
* To prevent desynchronization, if not all data is read before object
|
|
|
|
* destruction, it's required to send cancel query request to replicas and
|
|
|
|
* read all packets before EndOfStream
|
|
|
|
*/
|
|
|
|
std::atomic<bool> finished { false };
|
|
|
|
|
|
|
|
/** Cancel query request was sent to all replicas beacuse data is not needed anymore
|
|
|
|
* This behaviour may occur when:
|
|
|
|
* - data size is already satisfactory (when using LIMIT, for example)
|
|
|
|
* - an exception was thrown from client side
|
|
|
|
*/
|
|
|
|
std::atomic<bool> was_cancelled { false };
|
|
|
|
|
|
|
|
/** An exception from replica was received. No need in receiving more packets or
|
|
|
|
* requesting to cancel query execution
|
|
|
|
*/
|
|
|
|
std::atomic<bool> got_exception_from_replica { false };
|
|
|
|
|
|
|
|
/** Unkown packet was received from replica. No need in receiving more packets or
|
|
|
|
* requesting to cancel query execution
|
|
|
|
*/
|
|
|
|
std::atomic<bool> got_unknown_packet_from_replica { false };
|
|
|
|
|
|
|
|
bool append_extra_info = false;
|
|
|
|
PoolMode pool_mode = PoolMode::GET_MANY;
|
2017-11-20 04:15:43 +00:00
|
|
|
std::optional<QualifiedTableName> main_table;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
Logger * log = &Logger::get("RemoteBlockInputStream");
|
2012-05-17 19:15:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|