2018-11-28 11:37:12 +00:00
|
|
|
#include "LibraryDictionarySource.h"
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2018-12-10 15:25:45 +00:00
|
|
|
#include <DataStreams/OneBlockInputStream.h>
|
2017-09-05 01:08:26 +00:00
|
|
|
#include <Interpreters/Context.h>
|
|
|
|
#include <common/logger_useful.h>
|
2021-05-24 21:27:24 +00:00
|
|
|
#include <Common/filesystemHelpers.h>
|
2021-03-05 09:38:00 +00:00
|
|
|
#include <IO/WriteBufferFromString.h>
|
2021-03-10 18:02:43 +00:00
|
|
|
#include <IO/WriteHelpers.h>
|
2021-04-30 20:35:44 +00:00
|
|
|
#include <filesystem>
|
2021-05-24 21:27:24 +00:00
|
|
|
|
|
|
|
#include <Dictionaries/DictionarySourceFactory.h>
|
|
|
|
#include <Dictionaries/DictionarySourceHelpers.h>
|
|
|
|
#include <Dictionaries/DictionaryStructure.h>
|
|
|
|
#include <Dictionaries/registerDictionaries.h>
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2021-04-30 20:35:44 +00:00
|
|
|
namespace fs = std::filesystem;
|
2017-12-09 06:32:22 +00:00
|
|
|
|
2017-09-05 01:08:26 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2017-09-05 01:08:26 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int FILE_DOESNT_EXIST;
|
2018-02-16 17:12:22 +00:00
|
|
|
extern const int EXTERNAL_LIBRARY_ERROR;
|
2019-12-10 17:27:29 +00:00
|
|
|
extern const int PATH_ACCESS_DENIED;
|
2017-09-05 01:08:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-12-10 15:25:45 +00:00
|
|
|
LibraryDictionarySource::LibraryDictionarySource(
|
|
|
|
const DictionaryStructure & dict_struct_,
|
2017-09-05 01:08:26 +00:00
|
|
|
const Poco::Util::AbstractConfiguration & config,
|
2019-08-03 11:02:40 +00:00
|
|
|
const std::string & config_prefix_,
|
2019-12-10 17:27:29 +00:00
|
|
|
Block & sample_block_,
|
2021-06-01 12:20:52 +00:00
|
|
|
ContextPtr context_,
|
2021-05-24 21:27:24 +00:00
|
|
|
bool created_from_ddl)
|
2020-05-30 21:57:37 +00:00
|
|
|
: log(&Poco::Logger::get("LibraryDictionarySource"))
|
2018-02-14 15:03:48 +00:00
|
|
|
, dict_struct{dict_struct_}
|
2019-08-03 11:02:40 +00:00
|
|
|
, config_prefix{config_prefix_}
|
2018-02-14 15:03:48 +00:00
|
|
|
, path{config.getString(config_prefix + ".path", "")}
|
2021-03-22 14:39:17 +00:00
|
|
|
, dictionary_id(getDictID())
|
2019-08-03 11:02:40 +00:00
|
|
|
, sample_block{sample_block_}
|
2021-04-10 23:33:54 +00:00
|
|
|
, context(Context::createCopy(context_))
|
2017-09-05 01:08:26 +00:00
|
|
|
{
|
2021-08-02 07:18:51 +00:00
|
|
|
if (fs::path(path).is_relative())
|
|
|
|
path = fs::canonical(path);
|
|
|
|
|
2021-05-26 21:17:27 +00:00
|
|
|
if (created_from_ddl && !pathStartsWith(path, context->getDictionariesLibPath()))
|
|
|
|
throw Exception(ErrorCodes::PATH_ACCESS_DENIED, "File path {} is not inside {}", path, context->getDictionariesLibPath());
|
2019-12-10 17:27:29 +00:00
|
|
|
|
2021-04-30 20:35:44 +00:00
|
|
|
if (!fs::exists(path))
|
|
|
|
throw Exception(ErrorCodes::FILE_DOESNT_EXIST, "LibraryDictionarySource: Can't load library {}: file doesn't exist", path);
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2021-03-24 08:41:42 +00:00
|
|
|
description.init(sample_block);
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2021-07-30 14:20:57 +00:00
|
|
|
LibraryBridgeHelper::LibraryInitData library_data
|
|
|
|
{
|
|
|
|
.library_path = path,
|
|
|
|
.library_settings = getLibrarySettingsString(config, config_prefix + ".settings"),
|
|
|
|
.dict_attributes = getDictAttributesString()
|
|
|
|
};
|
2021-08-01 09:56:48 +00:00
|
|
|
|
2021-07-30 14:20:57 +00:00
|
|
|
bridge_helper = std::make_shared<LibraryBridgeHelper>(context, description.sample_block, dictionary_id, library_data);
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2021-08-02 07:18:51 +00:00
|
|
|
if (!bridge_helper->initLibrary())
|
2021-03-07 19:53:10 +00:00
|
|
|
throw Exception(ErrorCodes::EXTERNAL_LIBRARY_ERROR, "Failed to create shared library from path: {}", path);
|
2017-09-05 01:08:26 +00:00
|
|
|
}
|
|
|
|
|
2021-03-05 09:38:00 +00:00
|
|
|
|
|
|
|
LibraryDictionarySource::~LibraryDictionarySource()
|
|
|
|
{
|
2021-07-30 14:20:57 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
bridge_helper->removeLibrary();
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
tryLogCurrentException("LibraryDictionarySource");
|
|
|
|
}
|
|
|
|
|
2021-03-05 09:38:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-09-05 01:08:26 +00:00
|
|
|
LibraryDictionarySource::LibraryDictionarySource(const LibraryDictionarySource & other)
|
2020-05-30 21:57:37 +00:00
|
|
|
: log(&Poco::Logger::get("LibraryDictionarySource"))
|
2018-02-14 15:03:48 +00:00
|
|
|
, dict_struct{other.dict_struct}
|
|
|
|
, config_prefix{other.config_prefix}
|
|
|
|
, path{other.path}
|
2021-03-22 14:39:17 +00:00
|
|
|
, dictionary_id{getDictID()}
|
2018-02-14 15:03:48 +00:00
|
|
|
, sample_block{other.sample_block}
|
2021-03-05 09:38:00 +00:00
|
|
|
, context(other.context)
|
2018-02-14 15:03:48 +00:00
|
|
|
, description{other.description}
|
2018-02-26 16:57:14 +00:00
|
|
|
{
|
2021-07-30 14:20:57 +00:00
|
|
|
bridge_helper = std::make_shared<LibraryBridgeHelper>(context, description.sample_block, dictionary_id, other.bridge_helper->getLibraryData());
|
2021-08-02 07:18:51 +00:00
|
|
|
if (!bridge_helper->cloneLibrary(other.dictionary_id))
|
2021-08-01 09:56:48 +00:00
|
|
|
throw Exception(ErrorCodes::EXTERNAL_LIBRARY_ERROR, "Failed to clone library");
|
2017-09-05 01:08:26 +00:00
|
|
|
}
|
|
|
|
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2021-03-07 15:23:20 +00:00
|
|
|
bool LibraryDictionarySource::isModified() const
|
2021-03-05 09:38:00 +00:00
|
|
|
{
|
2021-03-07 15:23:20 +00:00
|
|
|
return bridge_helper->isModified();
|
2021-03-05 09:38:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-07 15:23:20 +00:00
|
|
|
bool LibraryDictionarySource::supportsSelectiveLoad() const
|
2017-09-05 01:08:26 +00:00
|
|
|
{
|
2021-03-07 15:23:20 +00:00
|
|
|
return bridge_helper->supportsSelectiveLoad();
|
2017-09-05 01:08:26 +00:00
|
|
|
}
|
|
|
|
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2021-08-05 18:08:52 +00:00
|
|
|
Pipe LibraryDictionarySource::loadAll()
|
2017-09-05 01:08:26 +00:00
|
|
|
{
|
2021-03-07 15:23:20 +00:00
|
|
|
LOG_TRACE(log, "loadAll {}", toString());
|
2021-03-24 09:23:29 +00:00
|
|
|
return bridge_helper->loadAll();
|
2017-09-05 01:08:26 +00:00
|
|
|
}
|
|
|
|
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2021-08-05 18:08:52 +00:00
|
|
|
Pipe LibraryDictionarySource::loadIds(const std::vector<UInt64> & ids)
|
2017-09-05 01:08:26 +00:00
|
|
|
{
|
2021-03-07 15:23:20 +00:00
|
|
|
LOG_TRACE(log, "loadIds {} size = {}", toString(), ids.size());
|
2021-08-01 09:56:48 +00:00
|
|
|
return bridge_helper->loadIds(ids);
|
2017-09-05 01:08:26 +00:00
|
|
|
}
|
|
|
|
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2021-08-05 18:08:52 +00:00
|
|
|
Pipe LibraryDictionarySource::loadKeys(const Columns & key_columns, const std::vector<std::size_t> & requested_rows)
|
2017-09-05 01:08:26 +00:00
|
|
|
{
|
2021-03-07 15:23:20 +00:00
|
|
|
LOG_TRACE(log, "loadKeys {} size = {}", toString(), requested_rows.size());
|
2021-03-10 13:10:05 +00:00
|
|
|
auto block = blockForKeys(dict_struct, key_columns, requested_rows);
|
2021-03-24 08:41:42 +00:00
|
|
|
return bridge_helper->loadKeys(block);
|
2017-09-05 01:08:26 +00:00
|
|
|
}
|
|
|
|
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2017-09-05 01:08:26 +00:00
|
|
|
DictionarySourcePtr LibraryDictionarySource::clone() const
|
|
|
|
{
|
|
|
|
return std::make_unique<LibraryDictionarySource>(*this);
|
|
|
|
}
|
|
|
|
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2017-09-05 01:08:26 +00:00
|
|
|
std::string LibraryDictionarySource::toString() const
|
|
|
|
{
|
|
|
|
return path;
|
|
|
|
}
|
2018-11-28 11:37:12 +00:00
|
|
|
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2021-03-05 15:37:43 +00:00
|
|
|
String LibraryDictionarySource::getLibrarySettingsString(const Poco::Util::AbstractConfiguration & config, const std::string & config_root)
|
|
|
|
{
|
|
|
|
Poco::Util::AbstractConfiguration::Keys config_keys;
|
|
|
|
config.keys(config_root, config_keys);
|
2021-03-24 07:53:15 +00:00
|
|
|
WriteBufferFromOwnString out;
|
|
|
|
std::vector<std::string> settings;
|
2021-03-05 15:37:43 +00:00
|
|
|
|
|
|
|
for (const auto & key : config_keys)
|
|
|
|
{
|
|
|
|
std::string key_name = key;
|
|
|
|
auto bracket_pos = key.find('[');
|
|
|
|
|
|
|
|
if (bracket_pos != std::string::npos && bracket_pos > 0)
|
|
|
|
key_name = key.substr(0, bracket_pos);
|
|
|
|
|
2021-03-24 07:53:15 +00:00
|
|
|
settings.push_back(key_name);
|
|
|
|
settings.push_back(config.getString(config_root + "." + key));
|
2021-03-05 15:37:43 +00:00
|
|
|
}
|
|
|
|
|
2021-03-24 07:53:15 +00:00
|
|
|
writeVectorBinary(settings, out);
|
|
|
|
return out.str();
|
2021-03-05 15:37:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-24 19:32:31 +00:00
|
|
|
String LibraryDictionarySource::getDictAttributesString()
|
|
|
|
{
|
|
|
|
std::vector<String> attributes_names(dict_struct.attributes.size());
|
|
|
|
for (size_t i = 0; i < dict_struct.attributes.size(); ++i)
|
|
|
|
attributes_names[i] = dict_struct.attributes[i].name;
|
|
|
|
WriteBufferFromOwnString out;
|
|
|
|
writeVectorBinary(attributes_names, out);
|
|
|
|
return out.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-28 11:37:12 +00:00
|
|
|
void registerDictionarySourceLibrary(DictionarySourceFactory & factory)
|
|
|
|
{
|
2020-03-23 02:12:31 +00:00
|
|
|
auto create_table_source = [=](const DictionaryStructure & dict_struct,
|
2018-11-28 11:37:12 +00:00
|
|
|
const Poco::Util::AbstractConfiguration & config,
|
|
|
|
const std::string & config_prefix,
|
|
|
|
Block & sample_block,
|
2021-06-01 12:20:52 +00:00
|
|
|
ContextPtr context,
|
2020-08-15 03:10:57 +00:00
|
|
|
const std::string & /* default_database */,
|
2021-05-24 21:27:24 +00:00
|
|
|
bool created_from_ddl) -> DictionarySourcePtr
|
2019-01-29 19:05:32 +00:00
|
|
|
{
|
2021-05-24 21:27:24 +00:00
|
|
|
return std::make_unique<LibraryDictionarySource>(dict_struct, config, config_prefix + ".library", sample_block, context, created_from_ddl);
|
2018-11-28 11:37:12 +00:00
|
|
|
};
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2020-03-23 02:12:31 +00:00
|
|
|
factory.registerSource("library", create_table_source);
|
2018-11-28 11:37:12 +00:00
|
|
|
}
|
|
|
|
|
2021-03-05 09:38:00 +00:00
|
|
|
|
2021-08-06 08:41:45 +00:00
|
|
|
}
|