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 | |