2019-02-16 10:11:49 +00:00
|
|
|
#include "CassandraDictionarySource.h"
|
|
|
|
#include "DictionarySourceFactory.h"
|
|
|
|
#include "DictionaryStructure.h"
|
2020-05-26 19:21:18 +00:00
|
|
|
#include "ExternalQueryBuilder.h"
|
|
|
|
#include <common/logger_useful.h>
|
2019-02-16 10:11:49 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int SUPPORT_IS_DISABLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void registerDictionarySourceCassandra(DictionarySourceFactory & factory)
|
|
|
|
{
|
2020-05-22 14:19:33 +00:00
|
|
|
auto create_table_source = [=](const DictionaryStructure & dict_struct,
|
2019-02-16 10:11:49 +00:00
|
|
|
const Poco::Util::AbstractConfiguration & config,
|
|
|
|
const std::string & config_prefix,
|
|
|
|
Block & sample_block,
|
2020-05-19 17:48:28 +00:00
|
|
|
const Context & /* context */,
|
|
|
|
bool /*check_config*/) -> DictionarySourcePtr {
|
2019-02-16 10:11:49 +00:00
|
|
|
#if USE_CASSANDRA
|
2019-05-29 23:01:25 +00:00
|
|
|
return std::make_unique<CassandraDictionarySource>(dict_struct, config, config_prefix + ".cassandra", sample_block);
|
2019-02-16 10:11:49 +00:00
|
|
|
#else
|
|
|
|
(void)dict_struct;
|
|
|
|
(void)config;
|
|
|
|
(void)config_prefix;
|
|
|
|
(void)sample_block;
|
|
|
|
throw Exception{"Dictionary source of type `cassandra` is disabled because library was built without cassandra support.",
|
|
|
|
ErrorCodes::SUPPORT_IS_DISABLED};
|
|
|
|
#endif
|
|
|
|
};
|
2020-05-22 14:19:33 +00:00
|
|
|
factory.registerSource("cassandra", create_table_source);
|
2019-02-16 10:11:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#if USE_CASSANDRA
|
|
|
|
|
|
|
|
# include <cassandra.h>
|
2019-05-22 21:09:29 +00:00
|
|
|
# include <IO/WriteHelpers.h>
|
|
|
|
# include "CassandraBlockInputStream.h"
|
2019-02-16 10:11:49 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
2019-05-29 23:01:25 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
2019-02-16 10:11:49 +00:00
|
|
|
extern const int UNSUPPORTED_METHOD;
|
|
|
|
extern const int WRONG_PASSWORD;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const size_t max_block_size = 8192;
|
|
|
|
|
|
|
|
CassandraDictionarySource::CassandraDictionarySource(
|
2020-05-19 17:48:28 +00:00
|
|
|
const DB::DictionaryStructure & dict_struct_,
|
2020-05-26 19:21:18 +00:00
|
|
|
const String & host_,
|
2020-05-19 17:48:28 +00:00
|
|
|
UInt16 port_,
|
2020-05-26 19:21:18 +00:00
|
|
|
const String & user_,
|
|
|
|
const String & password_,
|
|
|
|
//const std::string & method_,
|
|
|
|
const String & db_,
|
|
|
|
const String & table_,
|
2020-05-19 17:48:28 +00:00
|
|
|
const DB::Block & sample_block_)
|
2020-05-26 19:21:18 +00:00
|
|
|
: log(&Logger::get("CassandraDictionarySource"))
|
|
|
|
, dict_struct(dict_struct_)
|
2020-05-19 17:48:28 +00:00
|
|
|
, host(host_)
|
|
|
|
, port(port_)
|
|
|
|
, user(user_)
|
|
|
|
, password(password_)
|
2020-05-26 19:21:18 +00:00
|
|
|
//, method(method_)
|
2020-05-19 17:48:28 +00:00
|
|
|
, db(db_)
|
2020-05-26 19:21:18 +00:00
|
|
|
, table(table_)
|
2020-05-19 17:48:28 +00:00
|
|
|
, sample_block(sample_block_)
|
2020-05-26 19:21:18 +00:00
|
|
|
, cluster(cass_cluster_new()) //FIXME will not be freed in case of exception
|
2020-05-19 17:48:28 +00:00
|
|
|
, session(cass_session_new())
|
2019-02-16 10:11:49 +00:00
|
|
|
{
|
2020-05-26 19:21:18 +00:00
|
|
|
cassandraCheck(cass_cluster_set_contact_points(cluster, host.c_str()));
|
|
|
|
if (port)
|
|
|
|
cassandraCheck(cass_cluster_set_port(cluster, port));
|
|
|
|
cass_cluster_set_credentials(cluster, user.c_str(), password.c_str());
|
|
|
|
cassandraWaitAndCheck(cass_session_connect_keyspace(session, cluster, db.c_str()));
|
2019-02-16 10:11:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CassandraDictionarySource::CassandraDictionarySource(
|
2020-05-19 17:48:28 +00:00
|
|
|
const DB::DictionaryStructure & dict_struct_,
|
|
|
|
const Poco::Util::AbstractConfiguration & config,
|
|
|
|
const std::string & config_prefix,
|
|
|
|
DB::Block & sample_block_)
|
2019-02-16 10:11:49 +00:00
|
|
|
: CassandraDictionarySource(
|
2020-05-19 17:48:28 +00:00
|
|
|
dict_struct_,
|
2019-02-16 10:11:49 +00:00
|
|
|
config.getString(config_prefix + ".host"),
|
2020-05-26 19:21:18 +00:00
|
|
|
config.getUInt(config_prefix + ".port", 0),
|
2019-02-16 10:11:49 +00:00
|
|
|
config.getString(config_prefix + ".user", ""),
|
|
|
|
config.getString(config_prefix + ".password", ""),
|
2020-05-26 19:21:18 +00:00
|
|
|
//config.getString(config_prefix + ".method", ""),
|
|
|
|
config.getString(config_prefix + ".keyspace", ""),
|
|
|
|
config.getString(config_prefix + ".column_family"),
|
2020-05-19 17:48:28 +00:00
|
|
|
sample_block_)
|
2019-02-16 10:11:49 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CassandraDictionarySource::CassandraDictionarySource(const CassandraDictionarySource & other)
|
|
|
|
: CassandraDictionarySource{other.dict_struct,
|
|
|
|
other.host,
|
|
|
|
other.port,
|
|
|
|
other.user,
|
|
|
|
other.password,
|
2020-05-26 19:21:18 +00:00
|
|
|
//other.method,
|
2019-02-16 10:11:49 +00:00
|
|
|
other.db,
|
2020-05-26 19:21:18 +00:00
|
|
|
other.table,
|
2019-02-16 10:11:49 +00:00
|
|
|
other.sample_block}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CassandraDictionarySource::~CassandraDictionarySource() {
|
|
|
|
cass_session_free(session);
|
|
|
|
cass_cluster_free(cluster);
|
|
|
|
}
|
|
|
|
|
2020-05-26 19:21:18 +00:00
|
|
|
//std::string CassandraDictionarySource::toConnectionString(const std::string &host, const UInt16 port) {
|
|
|
|
// return host + (port != 0 ? ":" + std::to_string(port) : "");
|
|
|
|
//}
|
2019-02-16 10:11:49 +00:00
|
|
|
|
2020-05-26 19:21:18 +00:00
|
|
|
BlockInputStreamPtr CassandraDictionarySource::loadAll()
|
|
|
|
{
|
|
|
|
ExternalQueryBuilder builder{dict_struct, db, table, "", IdentifierQuotingStyle::DoubleQuotes};
|
|
|
|
String query = builder.composeLoadAllQuery();
|
|
|
|
query.pop_back();
|
|
|
|
query += " ALLOW FILTERING;";
|
|
|
|
LOG_INFO(log, "Loading all using query: " << query);
|
|
|
|
return std::make_shared<CassandraBlockInputStream>(session, query, sample_block, max_block_size);
|
2019-05-22 21:09:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string CassandraDictionarySource::toString() const {
|
|
|
|
return "Cassandra: " + /*db + '.' + collection + ',' + (user.empty() ? " " : " " + user + '@') + */ host + ':' + DB::toString(port);
|
|
|
|
}
|
2019-02-16 10:11:49 +00:00
|
|
|
|
2020-05-26 19:21:18 +00:00
|
|
|
BlockInputStreamPtr CassandraDictionarySource::loadIds(const std::vector<UInt64> & ids)
|
|
|
|
{
|
|
|
|
ExternalQueryBuilder builder{dict_struct, db, table, "", IdentifierQuotingStyle::DoubleQuotes};
|
|
|
|
String query = builder.composeLoadIdsQuery(ids);
|
|
|
|
query.pop_back();
|
|
|
|
query += " ALLOW FILTERING;";
|
|
|
|
LOG_INFO(log, "Loading ids using query: " << query);
|
|
|
|
return std::make_shared<CassandraBlockInputStream>(session, query, sample_block, max_block_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockInputStreamPtr CassandraDictionarySource::loadKeys(const Columns & key_columns, const std::vector<size_t> & requested_rows)
|
|
|
|
{
|
|
|
|
//FIXME split conditions on partition key and clustering key
|
|
|
|
ExternalQueryBuilder builder{dict_struct, db, table, "", IdentifierQuotingStyle::DoubleQuotes};
|
|
|
|
String query = builder.composeLoadKeysQuery(key_columns, requested_rows, ExternalQueryBuilder::IN_WITH_TUPLES);
|
|
|
|
query.pop_back();
|
|
|
|
query += " ALLOW FILTERING;";
|
|
|
|
LOG_INFO(log, "Loading keys using query: " << query);
|
|
|
|
return std::make_shared<CassandraBlockInputStream>(session, query, sample_block, max_block_size);
|
|
|
|
}
|
|
|
|
|
2019-02-16 10:11:49 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|