| 1 | #include <Formats/FormatSchemaInfo.h> |
| 2 | #include <Poco/Path.h> |
| 3 | #include <Interpreters/Context.h> |
| 4 | #include <Common/Exception.h> |
| 5 | |
| 6 | |
| 7 | namespace DB |
| 8 | { |
| 9 | namespace ErrorCodes |
| 10 | { |
| 11 | extern const int BAD_ARGUMENTS; |
| 12 | } |
| 13 | |
| 14 | |
| 15 | namespace |
| 16 | { |
| 17 | String getFormatSchemaDefaultFileExtension(const String & format) |
| 18 | { |
| 19 | if (format == "Protobuf" ) |
| 20 | return "proto" ; |
| 21 | else if (format == "CapnProto" ) |
| 22 | return "capnp" ; |
| 23 | else |
| 24 | return "" ; |
| 25 | } |
| 26 | } |
| 27 | |
| 28 | |
| 29 | FormatSchemaInfo::FormatSchemaInfo(const String & format_schema, const String & format, bool require_message, bool is_server, const std::string & format_schema_path) |
| 30 | { |
| 31 | if (format_schema.empty()) |
| 32 | throw Exception( |
| 33 | "The format " + format + " requires a schema. The corresponding setting should be set" , ErrorCodes::BAD_ARGUMENTS); |
| 34 | |
| 35 | String default_file_extension = getFormatSchemaDefaultFileExtension(format); |
| 36 | |
| 37 | Poco::Path path; |
| 38 | if (require_message) |
| 39 | { |
| 40 | size_t colon_pos = format_schema.find(':'); |
| 41 | if ((colon_pos == String::npos) || (colon_pos == 0) || (colon_pos == format_schema.length() - 1) |
| 42 | || path.assign(format_schema.substr(0, colon_pos)).makeFile().getFileName().empty()) |
| 43 | { |
| 44 | throw Exception( |
| 45 | "Format schema requires the 'format_schema' setting to have the 'schema_file:message_name' format" |
| 46 | + (default_file_extension.empty() ? "" : ", e.g. 'schema." + default_file_extension + ":Message'" ) + |
| 47 | ". Got '" + format_schema |
| 48 | + "'" , |
| 49 | ErrorCodes::BAD_ARGUMENTS); |
| 50 | } |
| 51 | |
| 52 | message_name = format_schema.substr(colon_pos + 1); |
| 53 | } |
| 54 | else |
| 55 | path.assign(format_schema).makeFile().getFileName(); |
| 56 | |
| 57 | auto default_schema_directory = [&format_schema_path]() |
| 58 | { |
| 59 | static const String str = Poco::Path(format_schema_path).makeAbsolute().makeDirectory().toString(); |
| 60 | return str; |
| 61 | }; |
| 62 | |
| 63 | if (path.getExtension().empty() && !default_file_extension.empty()) |
| 64 | path.setExtension(default_file_extension); |
| 65 | |
| 66 | if (path.isAbsolute()) |
| 67 | { |
| 68 | if (is_server) |
| 69 | throw Exception("Absolute path in the 'format_schema' setting is prohibited: " + path.toString(), ErrorCodes::BAD_ARGUMENTS); |
| 70 | schema_path = path.getFileName(); |
| 71 | schema_directory = path.makeParent().toString(); |
| 72 | } |
| 73 | else if (path.depth() >= 1 && path.directory(0) == ".." ) |
| 74 | { |
| 75 | if (is_server) |
| 76 | throw Exception( |
| 77 | "Path in the 'format_schema' setting shouldn't go outside the 'format_schema_path' directory: " + path.toString(), |
| 78 | ErrorCodes::BAD_ARGUMENTS); |
| 79 | path = Poco::Path(default_schema_directory()).resolve(path).toString(); |
| 80 | schema_path = path.getFileName(); |
| 81 | schema_directory = path.makeParent().toString(); |
| 82 | } |
| 83 | else |
| 84 | { |
| 85 | schema_path = path.toString(); |
| 86 | schema_directory = default_schema_directory(); |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | } |
| 91 | |