2019-01-23 19:28:13 +00:00
|
|
|
#include <Formats/FormatSchemaInfo.h>
|
|
|
|
#include <Interpreters/Context.h>
|
|
|
|
#include <Common/Exception.h>
|
2021-05-16 18:36:55 +00:00
|
|
|
#include <filesystem>
|
2019-01-23 19:28:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int BAD_ARGUMENTS;
|
|
|
|
}
|
|
|
|
|
2021-05-16 18:36:55 +00:00
|
|
|
namespace fs = std::filesystem;
|
2019-03-29 14:37:08 +00:00
|
|
|
|
|
|
|
namespace
|
2019-01-23 19:28:13 +00:00
|
|
|
{
|
2019-03-29 14:37:08 +00:00
|
|
|
String getFormatSchemaDefaultFileExtension(const String & format)
|
2019-01-23 19:28:13 +00:00
|
|
|
{
|
2019-03-29 14:37:08 +00:00
|
|
|
if (format == "Protobuf")
|
|
|
|
return "proto";
|
|
|
|
else if (format == "CapnProto")
|
|
|
|
return "capnp";
|
|
|
|
else
|
|
|
|
return "";
|
2019-01-23 19:28:13 +00:00
|
|
|
}
|
2019-03-29 14:37:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-12-25 19:17:41 +00:00
|
|
|
FormatSchemaInfo::FormatSchemaInfo(const String & format_schema, const String & format, bool require_message, bool is_server, const std::string & format_schema_path)
|
2019-03-29 14:37:08 +00:00
|
|
|
{
|
|
|
|
if (format_schema.empty())
|
|
|
|
throw Exception(
|
2019-09-24 14:25:22 +00:00
|
|
|
"The format " + format + " requires a schema. The corresponding setting should be set", ErrorCodes::BAD_ARGUMENTS);
|
2019-03-29 14:37:08 +00:00
|
|
|
|
|
|
|
String default_file_extension = getFormatSchemaDefaultFileExtension(format);
|
2019-01-23 19:28:13 +00:00
|
|
|
|
2021-05-16 18:36:55 +00:00
|
|
|
fs::path path;
|
2019-09-24 14:25:22 +00:00
|
|
|
if (require_message)
|
2019-01-23 19:28:13 +00:00
|
|
|
{
|
2019-09-24 14:25:22 +00:00
|
|
|
size_t colon_pos = format_schema.find(':');
|
2021-05-16 18:36:55 +00:00
|
|
|
if ((colon_pos == String::npos) || (colon_pos == 0) || (colon_pos == format_schema.length() - 1))
|
2019-09-24 14:25:22 +00:00
|
|
|
{
|
|
|
|
throw Exception(
|
|
|
|
"Format schema requires the 'format_schema' setting to have the 'schema_file:message_name' format"
|
|
|
|
+ (default_file_extension.empty() ? "" : ", e.g. 'schema." + default_file_extension + ":Message'") +
|
2021-05-16 18:36:55 +00:00
|
|
|
". Got '" + format_schema + "'", ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
path = fs::path(format_schema.substr(0, colon_pos));
|
|
|
|
String filename = path.has_filename() ? path.filename() : path.parent_path().filename();
|
|
|
|
if (filename.empty())
|
|
|
|
throw Exception(
|
|
|
|
"Format schema requires the 'format_schema' setting to have the 'schema_file:message_name' format"
|
|
|
|
+ (default_file_extension.empty() ? "" : ", e.g. 'schema." + default_file_extension + ":Message'") +
|
|
|
|
". Got '" + format_schema + "'", ErrorCodes::BAD_ARGUMENTS);
|
2019-09-24 14:25:22 +00:00
|
|
|
}
|
|
|
|
message_name = format_schema.substr(colon_pos + 1);
|
|
|
|
}
|
|
|
|
else
|
2021-05-16 18:36:55 +00:00
|
|
|
{
|
|
|
|
path = fs::path(format_schema);
|
|
|
|
if (!path.has_filename())
|
|
|
|
path = path.parent_path() / "";
|
|
|
|
}
|
2019-01-27 09:15:32 +00:00
|
|
|
|
2019-12-25 19:17:41 +00:00
|
|
|
auto default_schema_directory = [&format_schema_path]()
|
2019-01-23 19:28:13 +00:00
|
|
|
{
|
2021-05-23 07:56:13 +00:00
|
|
|
static const String str = fs::canonical(format_schema_path) / "";
|
2019-01-27 09:15:32 +00:00
|
|
|
return str;
|
|
|
|
};
|
2019-01-23 19:28:13 +00:00
|
|
|
|
2021-05-16 18:36:55 +00:00
|
|
|
if (!path.has_extension() && !default_file_extension.empty())
|
|
|
|
path = path.parent_path() / (path.stem().string() + '.' + default_file_extension);
|
2019-01-27 09:15:32 +00:00
|
|
|
|
2021-05-16 18:36:55 +00:00
|
|
|
if (path.is_absolute())
|
2019-01-27 09:15:32 +00:00
|
|
|
{
|
2019-12-25 19:17:41 +00:00
|
|
|
if (is_server)
|
2021-05-16 18:36:55 +00:00
|
|
|
throw Exception("Absolute path in the 'format_schema' setting is prohibited: " + path.string(), ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
schema_path = path.filename();
|
|
|
|
schema_directory = path.parent_path() / "";
|
2019-01-27 09:15:32 +00:00
|
|
|
}
|
2021-05-28 18:17:16 +00:00
|
|
|
else if (!fs::weakly_canonical(path).string().starts_with(fs::weakly_canonical(default_schema_directory()).string()))
|
2019-01-27 09:15:32 +00:00
|
|
|
{
|
2019-12-25 19:17:41 +00:00
|
|
|
if (is_server)
|
2019-01-23 19:28:13 +00:00
|
|
|
throw Exception(
|
2021-05-16 18:36:55 +00:00
|
|
|
"Path in the 'format_schema' setting shouldn't go outside the 'format_schema_path' directory: " + path.string(),
|
2019-01-23 19:28:13 +00:00
|
|
|
ErrorCodes::BAD_ARGUMENTS);
|
2021-05-28 18:17:16 +00:00
|
|
|
fs::path default_schema_directory_path(default_schema_directory());
|
2021-05-17 06:48:02 +00:00
|
|
|
if (default_schema_directory_path.is_absolute())
|
|
|
|
path = default_schema_directory_path;
|
|
|
|
else
|
|
|
|
path /= default_schema_directory_path;
|
2021-05-16 18:36:55 +00:00
|
|
|
schema_path = path.filename();
|
|
|
|
schema_directory = path.parent_path() / "";
|
2019-01-27 09:15:32 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-05-16 18:36:55 +00:00
|
|
|
schema_path = path;
|
2019-01-27 09:15:32 +00:00
|
|
|
schema_directory = default_schema_directory();
|
2019-01-23 19:28:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|