| 1 | #include "FileDictionarySource.h" |
| 2 | #include <DataStreams/OwningBlockInputStream.h> |
| 3 | #include <IO/ReadBufferFromFile.h> |
| 4 | #include <Interpreters/Context.h> |
| 5 | #include <Poco/File.h> |
| 6 | #include "DictionarySourceFactory.h" |
| 7 | #include "DictionaryStructure.h" |
| 8 | #include "registerDictionaries.h" |
| 9 | |
| 10 | namespace DB |
| 11 | { |
| 12 | static const UInt64 max_block_size = 8192; |
| 13 | |
| 14 | namespace ErrorCodes |
| 15 | { |
| 16 | extern const int PATH_ACCESS_DENIED; |
| 17 | } |
| 18 | |
| 19 | |
| 20 | FileDictionarySource::FileDictionarySource( |
| 21 | const std::string & filepath_, const std::string & format_, |
| 22 | Block & sample_block_, const Context & context_, bool check_config) |
| 23 | : filepath{filepath_} |
| 24 | , format{format_} |
| 25 | , sample_block{sample_block_} |
| 26 | , context(context_) |
| 27 | { |
| 28 | if (check_config) |
| 29 | { |
| 30 | const String user_files_path = context.getUserFilesPath(); |
| 31 | if (!startsWith(filepath, user_files_path)) |
| 32 | throw Exception("File path " + filepath + " is not inside " + user_files_path, ErrorCodes::PATH_ACCESS_DENIED); |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | |
| 37 | FileDictionarySource::FileDictionarySource(const FileDictionarySource & other) |
| 38 | : filepath{other.filepath} |
| 39 | , format{other.format} |
| 40 | , sample_block{other.sample_block} |
| 41 | , context(other.context) |
| 42 | , last_modification{other.last_modification} |
| 43 | { |
| 44 | } |
| 45 | |
| 46 | |
| 47 | BlockInputStreamPtr FileDictionarySource::loadAll() |
| 48 | { |
| 49 | auto in_ptr = std::make_unique<ReadBufferFromFile>(filepath); |
| 50 | auto stream = context.getInputFormat(format, *in_ptr, sample_block, max_block_size); |
| 51 | last_modification = getLastModification(); |
| 52 | |
| 53 | return std::make_shared<OwningBlockInputStream<ReadBuffer>>(stream, std::move(in_ptr)); |
| 54 | } |
| 55 | |
| 56 | |
| 57 | std::string FileDictionarySource::toString() const |
| 58 | { |
| 59 | return "File: " + filepath + ' ' + format; |
| 60 | } |
| 61 | |
| 62 | |
| 63 | Poco::Timestamp FileDictionarySource::getLastModification() const |
| 64 | { |
| 65 | return Poco::File{filepath}.getLastModified(); |
| 66 | } |
| 67 | |
| 68 | void registerDictionarySourceFile(DictionarySourceFactory & factory) |
| 69 | { |
| 70 | auto createTableSource = [=](const DictionaryStructure & dict_struct, |
| 71 | const Poco::Util::AbstractConfiguration & config, |
| 72 | const std::string & config_prefix, |
| 73 | Block & sample_block, |
| 74 | const Context & context, |
| 75 | bool check_config) -> DictionarySourcePtr |
| 76 | { |
| 77 | if (dict_struct.has_expressions) |
| 78 | throw Exception{"Dictionary source of type `file` does not support attribute expressions" , ErrorCodes::LOGICAL_ERROR}; |
| 79 | |
| 80 | const auto filepath = config.getString(config_prefix + ".file.path" ); |
| 81 | const auto format = config.getString(config_prefix + ".file.format" ); |
| 82 | |
| 83 | return std::make_unique<FileDictionarySource>(filepath, format, sample_block, context, check_config); |
| 84 | }; |
| 85 | |
| 86 | factory.registerSource("file" , createTableSource); |
| 87 | } |
| 88 | |
| 89 | } |
| 90 | |