1#include <Formats/FormatSchemaInfo.h>
2#include <Poco/Path.h>
3#include <Interpreters/Context.h>
4#include <Common/Exception.h>
5
6
7namespace DB
8{
9namespace ErrorCodes
10{
11 extern const int BAD_ARGUMENTS;
12}
13
14
15namespace
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
29FormatSchemaInfo::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