2018-03-06 20:18:34 +00:00
|
|
|
#include <Storages/ColumnsDescription.h>
|
2020-03-24 17:05:38 +00:00
|
|
|
|
2018-11-06 13:26:43 +00:00
|
|
|
#include <Parsers/ASTLiteral.h>
|
2018-11-16 12:01:52 +00:00
|
|
|
#include <Parsers/ExpressionElementParsers.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Parsers/ExpressionListParsers.h>
|
2019-02-27 16:41:51 +00:00
|
|
|
#include <Parsers/ParserCreateQuery.h>
|
2017-07-12 02:40:28 +00:00
|
|
|
#include <Parsers/parseQuery.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Parsers/queryToString.h>
|
2020-03-03 09:05:17 +00:00
|
|
|
#include <Parsers/ASTSubquery.h>
|
|
|
|
#include <Parsers/ASTSelectQuery.h>
|
2020-03-03 12:51:41 +00:00
|
|
|
#include <Parsers/ASTSelectWithUnionQuery.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <IO/WriteBuffer.h>
|
|
|
|
#include <IO/WriteHelpers.h>
|
|
|
|
#include <IO/ReadBuffer.h>
|
|
|
|
#include <IO/ReadHelpers.h>
|
|
|
|
#include <IO/WriteBufferFromString.h>
|
|
|
|
#include <IO/ReadBufferFromString.h>
|
|
|
|
#include <DataTypes/DataTypeFactory.h>
|
2019-03-14 15:20:51 +00:00
|
|
|
#include <DataTypes/NestedUtils.h>
|
|
|
|
#include <DataTypes/DataTypeArray.h>
|
|
|
|
#include <DataTypes/DataTypeTuple.h>
|
2020-11-05 13:24:31 +00:00
|
|
|
#include <DataTypes/DataTypeNested.h>
|
2018-03-06 20:18:34 +00:00
|
|
|
#include <Common/Exception.h>
|
2018-12-04 20:03:04 +00:00
|
|
|
#include <Interpreters/Context.h>
|
|
|
|
#include <Storages/IStorage.h>
|
2018-11-06 13:26:43 +00:00
|
|
|
#include <Common/typeid_cast.h>
|
2020-04-15 20:28:05 +00:00
|
|
|
#include <Core/Defines.h>
|
2018-10-11 02:57:48 +00:00
|
|
|
#include <Compression/CompressionFactory.h>
|
2020-03-03 09:05:17 +00:00
|
|
|
#include <Interpreters/ExpressionAnalyzer.h>
|
2020-07-22 17:13:05 +00:00
|
|
|
#include <Interpreters/TreeRewriter.h>
|
2020-03-03 09:05:17 +00:00
|
|
|
#include <Interpreters/ExpressionActions.h>
|
2021-09-22 15:44:01 +00:00
|
|
|
#include <Interpreters/FunctionNameNormalizer.h>
|
2015-04-11 03:10:23 +00:00
|
|
|
|
2020-04-15 20:28:05 +00:00
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2016-01-11 21:46:36 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
2018-03-06 20:18:34 +00:00
|
|
|
extern const int NO_SUCH_COLUMN_IN_TABLE;
|
2019-03-14 15:20:51 +00:00
|
|
|
extern const int ILLEGAL_COLUMN;
|
2017-04-01 07:20:54 +00:00
|
|
|
extern const int CANNOT_PARSE_TEXT;
|
2020-03-03 09:05:17 +00:00
|
|
|
extern const int THERE_IS_NO_DEFAULT_VALUE;
|
2020-03-31 16:18:18 +00:00
|
|
|
extern const int LOGICAL_ERROR;
|
2016-01-11 21:46:36 +00:00
|
|
|
}
|
|
|
|
|
2020-04-27 13:55:30 +00:00
|
|
|
ColumnDescription::ColumnDescription(String name_, DataTypePtr type_)
|
|
|
|
: name(std::move(name_)), type(std::move(type_))
|
2019-05-21 11:24:32 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
bool ColumnDescription::operator==(const ColumnDescription & other) const
|
|
|
|
{
|
2020-08-26 08:45:13 +00:00
|
|
|
auto ast_to_str = [](const ASTPtr & ast) { return ast ? queryToString(ast) : String{}; };
|
2015-04-11 03:10:23 +00:00
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
return name == other.name
|
|
|
|
&& type->equals(*other.type)
|
|
|
|
&& default_desc == other.default_desc
|
|
|
|
&& comment == other.comment
|
2020-08-26 08:45:13 +00:00
|
|
|
&& ast_to_str(codec) == ast_to_str(other.codec)
|
|
|
|
&& ast_to_str(ttl) == ast_to_str(other.ttl);
|
2019-03-14 15:20:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ColumnDescription::writeText(WriteBuffer & buf) const
|
2018-03-06 20:18:34 +00:00
|
|
|
{
|
2021-01-23 01:11:18 +00:00
|
|
|
/// NOTE: Serialization format is insane.
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
writeBackQuotedString(name, buf);
|
|
|
|
writeChar(' ', buf);
|
2020-11-19 17:16:45 +00:00
|
|
|
writeEscapedString(type->getName(), buf);
|
2019-03-14 15:20:51 +00:00
|
|
|
|
|
|
|
if (default_desc.expression)
|
|
|
|
{
|
|
|
|
writeChar('\t', buf);
|
|
|
|
DB::writeText(DB::toString(default_desc.kind), buf);
|
|
|
|
writeChar('\t', buf);
|
2020-11-19 17:16:45 +00:00
|
|
|
writeEscapedString(queryToString(default_desc.expression), buf);
|
2019-03-14 15:20:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!comment.empty())
|
|
|
|
{
|
|
|
|
writeChar('\t', buf);
|
|
|
|
DB::writeText("COMMENT ", buf);
|
2020-11-19 17:16:45 +00:00
|
|
|
writeEscapedString(queryToString(ASTLiteral(Field(comment))), buf);
|
2019-03-14 15:20:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (codec)
|
|
|
|
{
|
|
|
|
writeChar('\t', buf);
|
2020-11-19 17:16:45 +00:00
|
|
|
writeEscapedString(queryToString(codec), buf);
|
2019-03-14 15:20:51 +00:00
|
|
|
}
|
|
|
|
|
2019-04-15 09:30:45 +00:00
|
|
|
if (ttl)
|
|
|
|
{
|
|
|
|
writeChar('\t', buf);
|
|
|
|
DB::writeText("TTL ", buf);
|
2020-11-19 17:16:45 +00:00
|
|
|
writeEscapedString(queryToString(ttl), buf);
|
2019-04-15 09:30:45 +00:00
|
|
|
}
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
writeChar('\n', buf);
|
2018-03-06 20:18:34 +00:00
|
|
|
}
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
void ColumnDescription::readText(ReadBuffer & buf)
|
|
|
|
{
|
2021-01-23 01:11:18 +00:00
|
|
|
readBackQuotedString(name, buf);
|
|
|
|
assertChar(' ', buf);
|
|
|
|
|
|
|
|
String type_string;
|
|
|
|
readEscapedString(type_string, buf);
|
|
|
|
type = DataTypeFactory::instance().get(type_string);
|
|
|
|
|
|
|
|
if (checkChar('\t', buf))
|
2019-03-14 15:20:51 +00:00
|
|
|
{
|
2021-01-23 01:11:18 +00:00
|
|
|
String modifiers;
|
|
|
|
readEscapedStringUntilEOL(modifiers, buf);
|
2018-03-06 20:18:34 +00:00
|
|
|
|
2021-01-23 01:11:18 +00:00
|
|
|
ParserColumnDeclaration column_parser(/* require type */ true);
|
|
|
|
ASTPtr ast = parseQuery(column_parser, "x T " + modifiers, "column parser", 0, DBMS_DEFAULT_MAX_PARSER_DEPTH);
|
|
|
|
|
2022-03-02 17:22:12 +00:00
|
|
|
if (auto * col_ast = ast->as<ASTColumnDeclaration>())
|
2019-03-14 15:20:51 +00:00
|
|
|
{
|
2021-01-23 01:11:18 +00:00
|
|
|
if (col_ast->default_expression)
|
|
|
|
{
|
|
|
|
default_desc.kind = columnDefaultKindFromString(col_ast->default_specifier);
|
2022-04-04 20:41:42 +00:00
|
|
|
default_desc.expression = std::move(col_ast->default_expression);
|
2021-01-23 01:11:18 +00:00
|
|
|
}
|
2019-03-14 15:20:51 +00:00
|
|
|
|
2021-01-23 01:11:18 +00:00
|
|
|
if (col_ast->comment)
|
|
|
|
comment = col_ast->comment->as<ASTLiteral &>().value.get<String>();
|
2019-03-14 15:20:51 +00:00
|
|
|
|
2021-01-23 01:11:18 +00:00
|
|
|
if (col_ast->codec)
|
2021-05-06 11:57:22 +00:00
|
|
|
codec = CompressionCodecFactory::instance().validateCodecAndGetPreprocessedAST(col_ast->codec, type, false, true);
|
2019-04-15 09:30:45 +00:00
|
|
|
|
2021-01-23 01:11:18 +00:00
|
|
|
if (col_ast->ttl)
|
|
|
|
ttl = col_ast->ttl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw Exception("Cannot parse column description", ErrorCodes::CANNOT_PARSE_TEXT);
|
2019-03-14 15:20:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-04-27 13:55:30 +00:00
|
|
|
ColumnsDescription::ColumnsDescription(NamesAndTypesList ordinary)
|
2018-03-10 17:03:57 +00:00
|
|
|
{
|
2019-03-14 15:20:51 +00:00
|
|
|
for (auto & elem : ordinary)
|
2020-04-27 13:55:30 +00:00
|
|
|
add(ColumnDescription(std::move(elem.name), std::move(elem.type)));
|
2018-03-10 17:03:57 +00:00
|
|
|
}
|
|
|
|
|
2021-06-28 11:42:21 +00:00
|
|
|
ColumnsDescription::ColumnsDescription(NamesAndTypesList ordinary, NamesAndAliases aliases)
|
|
|
|
{
|
|
|
|
for (auto & elem : ordinary)
|
|
|
|
add(ColumnDescription(std::move(elem.name), std::move(elem.type)));
|
|
|
|
|
|
|
|
for (auto & alias : aliases)
|
|
|
|
{
|
|
|
|
ColumnDescription description(std::move(alias.name), std::move(alias.type));
|
|
|
|
description.default_desc.kind = ColumnDefaultKind::Alias;
|
|
|
|
|
|
|
|
const char * alias_expression_pos = alias.expression.data();
|
|
|
|
const char * alias_expression_end = alias_expression_pos + alias.expression.size();
|
|
|
|
ParserExpression expression_parser;
|
|
|
|
description.default_desc.expression = parseQuery(expression_parser, alias_expression_pos, alias_expression_end, "expression", 0, DBMS_DEFAULT_MAX_PARSER_DEPTH);
|
|
|
|
|
|
|
|
add(std::move(description));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-10 17:03:57 +00:00
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
/// We are trying to find first column from end with name `column_name` or with a name beginning with `column_name` and ".".
|
|
|
|
/// For example "fruits.bananas"
|
|
|
|
/// names are considered the same if they completely match or `name_without_dot` matches the part of the name to the point
|
2021-07-15 03:12:37 +00:00
|
|
|
static auto getNameRange(const ColumnsDescription::ColumnsContainer & columns, const String & name_without_dot)
|
2018-03-06 20:18:34 +00:00
|
|
|
{
|
2019-03-14 15:20:51 +00:00
|
|
|
String name_with_dot = name_without_dot + ".";
|
|
|
|
|
2022-06-21 12:32:12 +00:00
|
|
|
/// First we need to check if we have column with name name_without_dot
|
|
|
|
/// and if not - check if we have names that start with name_with_dot
|
2022-06-10 08:58:00 +00:00
|
|
|
for (auto it = columns.begin(); it != columns.end(); ++it)
|
2019-03-14 15:20:51 +00:00
|
|
|
{
|
2022-06-10 08:58:00 +00:00
|
|
|
if (it->name == name_without_dot)
|
|
|
|
return std::make_pair(it, std::next(it));
|
2019-03-14 15:20:51 +00:00
|
|
|
}
|
|
|
|
|
2022-06-10 08:58:00 +00:00
|
|
|
auto begin = std::find_if(columns.begin(), columns.end(), [&](const auto & column){ return startsWith(column.name, name_with_dot); });
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
if (begin == columns.end())
|
|
|
|
return std::make_pair(begin, begin);
|
|
|
|
|
|
|
|
auto end = std::next(begin);
|
|
|
|
for (; end != columns.end(); ++end)
|
|
|
|
{
|
|
|
|
if (!startsWith(end->name, name_with_dot))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::make_pair(begin, end);
|
2018-03-06 20:18:34 +00:00
|
|
|
}
|
|
|
|
|
2022-05-20 17:48:24 +00:00
|
|
|
void ColumnsDescription::add(ColumnDescription column, const String & after_column, bool first, bool add_subcolumns)
|
2019-03-14 15:20:51 +00:00
|
|
|
{
|
|
|
|
if (has(column.name))
|
|
|
|
throw Exception("Cannot add column " + column.name + ": column with this name already exists",
|
|
|
|
ErrorCodes::ILLEGAL_COLUMN);
|
|
|
|
|
2021-09-22 15:44:01 +00:00
|
|
|
/// Normalize ASTs to be compatible with InterpreterCreateQuery.
|
|
|
|
if (column.default_desc.expression)
|
2021-09-24 11:08:33 +00:00
|
|
|
FunctionNameNormalizer::visit(column.default_desc.expression.get());
|
2021-09-22 15:44:01 +00:00
|
|
|
if (column.ttl)
|
2021-09-24 11:08:33 +00:00
|
|
|
FunctionNameNormalizer::visit(column.ttl.get());
|
2021-09-22 15:44:01 +00:00
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
auto insert_it = columns.cend();
|
2018-03-06 20:18:34 +00:00
|
|
|
|
2020-07-01 14:58:52 +00:00
|
|
|
if (first)
|
|
|
|
insert_it = columns.cbegin();
|
|
|
|
else if (!after_column.empty())
|
2019-03-14 15:20:51 +00:00
|
|
|
{
|
|
|
|
auto range = getNameRange(columns, after_column);
|
|
|
|
if (range.first == range.second)
|
|
|
|
throw Exception("Wrong column name. Cannot find column " + after_column + " to insert after",
|
|
|
|
ErrorCodes::NO_SUCH_COLUMN_IN_TABLE);
|
|
|
|
|
|
|
|
insert_it = range.second;
|
|
|
|
}
|
|
|
|
|
2022-05-20 17:48:24 +00:00
|
|
|
if (add_subcolumns)
|
|
|
|
addSubcolumns(column.name, column.type);
|
2019-05-01 21:43:05 +00:00
|
|
|
columns.get<0>().insert(insert_it, std::move(column));
|
2019-03-14 15:20:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ColumnsDescription::remove(const String & column_name)
|
2018-03-06 20:18:34 +00:00
|
|
|
{
|
2019-03-14 15:20:51 +00:00
|
|
|
auto range = getNameRange(columns, column_name);
|
|
|
|
if (range.first == range.second)
|
2022-04-01 13:12:54 +00:00
|
|
|
{
|
|
|
|
String exception_message = fmt::format("There is no column {} in table", column_name);
|
|
|
|
appendHintsMessage(exception_message, column_name);
|
|
|
|
throw Exception(exception_message, ErrorCodes::NO_SUCH_COLUMN_IN_TABLE);
|
|
|
|
}
|
2019-03-14 15:20:51 +00:00
|
|
|
|
|
|
|
for (auto list_it = range.first; list_it != range.second;)
|
2020-10-27 11:27:14 +00:00
|
|
|
{
|
2021-07-15 03:12:37 +00:00
|
|
|
removeSubcolumns(list_it->name);
|
2019-05-01 21:43:05 +00:00
|
|
|
list_it = columns.get<0>().erase(list_it);
|
2020-10-27 11:27:14 +00:00
|
|
|
}
|
2018-03-06 20:18:34 +00:00
|
|
|
}
|
|
|
|
|
2020-03-24 17:05:38 +00:00
|
|
|
void ColumnsDescription::rename(const String & column_from, const String & column_to)
|
|
|
|
{
|
2020-03-25 18:44:08 +00:00
|
|
|
auto it = columns.get<1>().find(column_from);
|
|
|
|
if (it == columns.get<1>().end())
|
2022-03-30 12:54:33 +00:00
|
|
|
{
|
2022-04-01 13:12:54 +00:00
|
|
|
String exception_message = fmt::format("Cannot find column {} in ColumnsDescription", column_from);
|
|
|
|
appendHintsMessage(exception_message, column_from);
|
|
|
|
throw Exception(exception_message, ErrorCodes::LOGICAL_ERROR);
|
2022-03-30 12:54:33 +00:00
|
|
|
}
|
2020-03-24 17:05:38 +00:00
|
|
|
|
2020-03-25 18:44:08 +00:00
|
|
|
columns.get<1>().modify_key(it, [&column_to] (String & old_name)
|
2020-03-24 17:05:38 +00:00
|
|
|
{
|
2020-03-25 18:44:08 +00:00
|
|
|
old_name = column_to;
|
|
|
|
});
|
2020-03-24 17:05:38 +00:00
|
|
|
}
|
|
|
|
|
2020-07-01 14:58:52 +00:00
|
|
|
void ColumnsDescription::modifyColumnOrder(const String & column_name, const String & after_column, bool first)
|
|
|
|
{
|
|
|
|
const auto & reorder_column = [&](auto get_new_pos)
|
|
|
|
{
|
|
|
|
auto column_range = getNameRange(columns, column_name);
|
|
|
|
|
|
|
|
if (column_range.first == column_range.second)
|
|
|
|
throw Exception("There is no column " + column_name + " in table.", ErrorCodes::NO_SUCH_COLUMN_IN_TABLE);
|
|
|
|
|
|
|
|
std::vector<ColumnDescription> moving_columns;
|
|
|
|
for (auto list_it = column_range.first; list_it != column_range.second;)
|
|
|
|
{
|
|
|
|
moving_columns.emplace_back(*list_it);
|
|
|
|
list_it = columns.get<0>().erase(list_it);
|
|
|
|
}
|
|
|
|
|
|
|
|
columns.get<0>().insert(get_new_pos(), moving_columns.begin(), moving_columns.end());
|
|
|
|
};
|
|
|
|
|
|
|
|
if (first)
|
|
|
|
reorder_column([&]() { return columns.cbegin(); });
|
|
|
|
else if (!after_column.empty() && column_name != after_column)
|
|
|
|
{
|
|
|
|
/// Checked first
|
|
|
|
auto range = getNameRange(columns, after_column);
|
|
|
|
if (range.first == range.second)
|
|
|
|
throw Exception("Wrong column name. Cannot find column " + after_column + " to insert after",
|
|
|
|
ErrorCodes::NO_SUCH_COLUMN_IN_TABLE);
|
|
|
|
|
|
|
|
reorder_column([&]() { return getNameRange(columns, after_column).second; });
|
|
|
|
}
|
|
|
|
}
|
2018-03-06 20:18:34 +00:00
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
void ColumnsDescription::flattenNested()
|
2018-03-06 20:18:34 +00:00
|
|
|
{
|
2019-03-16 15:07:08 +00:00
|
|
|
for (auto it = columns.begin(); it != columns.end();)
|
2019-03-14 15:20:51 +00:00
|
|
|
{
|
2019-03-16 15:07:08 +00:00
|
|
|
const auto * type_arr = typeid_cast<const DataTypeArray *>(it->type.get());
|
|
|
|
if (!type_arr)
|
|
|
|
{
|
|
|
|
++it;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto * type_tuple = typeid_cast<const DataTypeTuple *>(type_arr->getNestedType().get());
|
|
|
|
if (!type_tuple)
|
|
|
|
{
|
|
|
|
++it;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-01-27 20:26:39 +00:00
|
|
|
if (!type_tuple->haveExplicitNames())
|
|
|
|
{
|
|
|
|
++it;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-03-02 17:22:12 +00:00
|
|
|
ColumnDescription column = *it;
|
2021-07-15 03:12:37 +00:00
|
|
|
removeSubcolumns(column.name);
|
2019-05-01 21:43:05 +00:00
|
|
|
it = columns.get<0>().erase(it);
|
2019-03-16 15:07:08 +00:00
|
|
|
|
|
|
|
const DataTypes & elements = type_tuple->getElements();
|
|
|
|
const Strings & names = type_tuple->getElementNames();
|
|
|
|
size_t tuple_size = elements.size();
|
|
|
|
|
|
|
|
for (size_t i = 0; i < tuple_size; ++i)
|
2019-03-14 15:20:51 +00:00
|
|
|
{
|
2019-03-16 15:07:08 +00:00
|
|
|
auto nested_column = column;
|
|
|
|
/// TODO: what to do with default expressions?
|
|
|
|
nested_column.name = Nested::concatenateName(column.name, names[i]);
|
|
|
|
nested_column.type = std::make_shared<DataTypeArray>(elements[i]);
|
|
|
|
|
2020-10-29 14:14:23 +00:00
|
|
|
addSubcolumns(nested_column.name, nested_column.type);
|
2019-05-01 21:43:05 +00:00
|
|
|
columns.get<0>().insert(it, std::move(nested_column));
|
2019-03-14 15:20:51 +00:00
|
|
|
}
|
|
|
|
}
|
2018-03-06 20:18:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
NamesAndTypesList ColumnsDescription::getOrdinary() const
|
2019-02-27 16:41:51 +00:00
|
|
|
{
|
2019-03-14 15:20:51 +00:00
|
|
|
NamesAndTypesList ret;
|
|
|
|
for (const auto & col : columns)
|
2020-04-27 13:55:30 +00:00
|
|
|
if (col.default_desc.kind == ColumnDefaultKind::Default)
|
2019-03-14 15:20:51 +00:00
|
|
|
ret.emplace_back(col.name, col.type);
|
|
|
|
return ret;
|
|
|
|
}
|
2019-02-27 16:41:51 +00:00
|
|
|
|
2022-02-07 23:21:10 +00:00
|
|
|
NamesAndTypesList ColumnsDescription::getInsertable() const
|
|
|
|
{
|
|
|
|
NamesAndTypesList ret;
|
|
|
|
for (const auto & col : columns)
|
|
|
|
if (col.default_desc.kind == ColumnDefaultKind::Default || col.default_desc.kind == ColumnDefaultKind::Ephemeral)
|
|
|
|
ret.emplace_back(col.name, col.type);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
NamesAndTypesList ColumnsDescription::getMaterialized() const
|
|
|
|
{
|
|
|
|
NamesAndTypesList ret;
|
|
|
|
for (const auto & col : columns)
|
|
|
|
if (col.default_desc.kind == ColumnDefaultKind::Materialized)
|
|
|
|
ret.emplace_back(col.name, col.type);
|
|
|
|
return ret;
|
|
|
|
}
|
2019-02-27 16:41:51 +00:00
|
|
|
|
2019-05-23 11:15:18 +00:00
|
|
|
NamesAndTypesList ColumnsDescription::getAliases() const
|
2019-03-14 15:20:51 +00:00
|
|
|
{
|
|
|
|
NamesAndTypesList ret;
|
|
|
|
for (const auto & col : columns)
|
2019-05-23 11:15:18 +00:00
|
|
|
if (col.default_desc.kind == ColumnDefaultKind::Alias)
|
2019-03-14 15:20:51 +00:00
|
|
|
ret.emplace_back(col.name, col.type);
|
|
|
|
return ret;
|
2019-02-27 16:41:51 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 23:21:10 +00:00
|
|
|
NamesAndTypesList ColumnsDescription::getEphemeral() const
|
|
|
|
{
|
|
|
|
NamesAndTypesList ret;
|
|
|
|
for (const auto & col : columns)
|
|
|
|
if (col.default_desc.kind == ColumnDefaultKind::Ephemeral)
|
|
|
|
ret.emplace_back(col.name, col.type);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
NamesAndTypesList ColumnsDescription::getAll() const
|
2015-04-11 03:10:23 +00:00
|
|
|
{
|
2019-03-14 15:20:51 +00:00
|
|
|
NamesAndTypesList ret;
|
|
|
|
for (const auto & col : columns)
|
|
|
|
ret.emplace_back(col.name, col.type);
|
|
|
|
return ret;
|
|
|
|
}
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2021-07-23 16:30:18 +00:00
|
|
|
NamesAndTypesList ColumnsDescription::getSubcolumns(const String & name_in_storage) const
|
2021-05-04 23:02:54 +00:00
|
|
|
{
|
2021-07-23 16:30:18 +00:00
|
|
|
auto range = subcolumns.get<1>().equal_range(name_in_storage);
|
|
|
|
return NamesAndTypesList(range.first, range.second);
|
|
|
|
}
|
|
|
|
|
2022-03-31 10:24:05 +00:00
|
|
|
NamesAndTypesList ColumnsDescription::getNested(const String & column_name) const
|
|
|
|
{
|
|
|
|
auto range = getNameRange(columns, column_name);
|
|
|
|
NamesAndTypesList nested;
|
|
|
|
for (auto & it = range.first; it != range.second; ++it)
|
|
|
|
nested.emplace_back(it->name, it->type);
|
|
|
|
return nested;
|
|
|
|
}
|
|
|
|
|
2021-07-23 16:30:18 +00:00
|
|
|
void ColumnsDescription::addSubcolumnsToList(NamesAndTypesList & source_list) const
|
|
|
|
{
|
|
|
|
NamesAndTypesList subcolumns_list;
|
2021-05-04 23:02:54 +00:00
|
|
|
for (const auto & col : source_list)
|
|
|
|
{
|
2021-07-23 16:30:18 +00:00
|
|
|
auto range = subcolumns.get<1>().equal_range(col.name);
|
|
|
|
if (range.first != range.second)
|
|
|
|
subcolumns_list.insert(subcolumns_list.end(), range.first, range.second);
|
2021-05-04 23:02:54 +00:00
|
|
|
}
|
|
|
|
|
2021-07-23 16:30:18 +00:00
|
|
|
source_list.splice(source_list.end(), std::move(subcolumns_list));
|
2021-05-04 23:02:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NamesAndTypesList ColumnsDescription::get(const GetColumnsOptions & options) const
|
|
|
|
{
|
|
|
|
NamesAndTypesList res;
|
|
|
|
switch (options.kind)
|
|
|
|
{
|
|
|
|
case GetColumnsOptions::All:
|
|
|
|
res = getAll();
|
|
|
|
break;
|
|
|
|
case GetColumnsOptions::AllPhysical:
|
|
|
|
res = getAllPhysical();
|
|
|
|
break;
|
|
|
|
case GetColumnsOptions::Ordinary:
|
|
|
|
res = getOrdinary();
|
|
|
|
break;
|
|
|
|
case GetColumnsOptions::Materialized:
|
|
|
|
res = getMaterialized();
|
|
|
|
break;
|
|
|
|
case GetColumnsOptions::Aliases:
|
|
|
|
res = getAliases();
|
|
|
|
break;
|
2022-02-25 10:41:30 +00:00
|
|
|
case GetColumnsOptions::Ephemeral:
|
|
|
|
res = getEphemeral();
|
|
|
|
break;
|
2021-05-04 23:02:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (options.with_subcolumns)
|
2021-07-23 16:30:18 +00:00
|
|
|
addSubcolumnsToList(res);
|
2021-05-04 23:02:54 +00:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
bool ColumnsDescription::has(const String & column_name) const
|
|
|
|
{
|
2021-01-21 12:34:11 +00:00
|
|
|
return columns.get<1>().find(column_name) != columns.get<1>().end();
|
2019-03-14 15:20:51 +00:00
|
|
|
}
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
bool ColumnsDescription::hasNested(const String & column_name) const
|
|
|
|
{
|
|
|
|
auto range = getNameRange(columns, column_name);
|
|
|
|
return range.first != range.second && range.first->name.length() > column_name.length();
|
|
|
|
}
|
2018-10-14 15:30:06 +00:00
|
|
|
|
2021-01-21 12:34:11 +00:00
|
|
|
bool ColumnsDescription::hasSubcolumn(const String & column_name) const
|
|
|
|
{
|
2021-07-15 03:12:37 +00:00
|
|
|
return subcolumns.get<0>().count(column_name);
|
2021-01-21 12:34:11 +00:00
|
|
|
}
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
const ColumnDescription & ColumnsDescription::get(const String & column_name) const
|
|
|
|
{
|
2019-05-01 21:43:05 +00:00
|
|
|
auto it = columns.get<1>().find(column_name);
|
|
|
|
if (it == columns.get<1>().end())
|
2019-03-14 15:20:51 +00:00
|
|
|
throw Exception("There is no column " + column_name + " in table.",
|
|
|
|
ErrorCodes::NO_SUCH_COLUMN_IN_TABLE);
|
2018-12-25 10:04:38 +00:00
|
|
|
|
2019-05-01 21:43:05 +00:00
|
|
|
return *it;
|
2019-03-14 15:20:51 +00:00
|
|
|
}
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2021-07-20 15:20:21 +00:00
|
|
|
static GetColumnsOptions::Kind defaultKindToGetKind(ColumnDefaultKind kind)
|
2021-07-15 03:12:37 +00:00
|
|
|
{
|
|
|
|
switch (kind)
|
|
|
|
{
|
|
|
|
case ColumnDefaultKind::Default:
|
2021-07-20 15:20:21 +00:00
|
|
|
return GetColumnsOptions::Ordinary;
|
2021-07-15 03:12:37 +00:00
|
|
|
case ColumnDefaultKind::Materialized:
|
2021-07-20 15:20:21 +00:00
|
|
|
return GetColumnsOptions::Materialized;
|
2021-07-15 03:12:37 +00:00
|
|
|
case ColumnDefaultKind::Alias:
|
2021-07-20 15:20:21 +00:00
|
|
|
return GetColumnsOptions::Aliases;
|
2022-02-07 23:21:10 +00:00
|
|
|
case ColumnDefaultKind::Ephemeral:
|
2022-02-25 10:41:30 +00:00
|
|
|
return GetColumnsOptions::Ephemeral;
|
2021-07-15 03:12:37 +00:00
|
|
|
}
|
2021-07-15 15:31:21 +00:00
|
|
|
__builtin_unreachable();
|
2021-07-15 03:12:37 +00:00
|
|
|
}
|
|
|
|
|
2021-07-20 15:20:21 +00:00
|
|
|
NamesAndTypesList ColumnsDescription::getByNames(const GetColumnsOptions & options, const Names & names) const
|
2021-07-15 03:12:37 +00:00
|
|
|
{
|
|
|
|
NamesAndTypesList res;
|
|
|
|
for (const auto & name : names)
|
|
|
|
{
|
|
|
|
if (auto it = columns.get<1>().find(name); it != columns.get<1>().end())
|
|
|
|
{
|
2021-07-20 15:20:21 +00:00
|
|
|
auto kind = defaultKindToGetKind(it->default_desc.kind);
|
|
|
|
if (options.kind & kind)
|
2021-07-15 03:12:37 +00:00
|
|
|
{
|
|
|
|
res.emplace_back(name, it->type);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2021-07-20 15:20:21 +00:00
|
|
|
else if (options.with_subcolumns)
|
2021-07-15 03:12:37 +00:00
|
|
|
{
|
|
|
|
auto jt = subcolumns.get<0>().find(name);
|
|
|
|
if (jt != subcolumns.get<0>().end())
|
|
|
|
{
|
|
|
|
res.push_back(*jt);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throw Exception(ErrorCodes::NO_SUCH_COLUMN_IN_TABLE, "There is no column {} in table", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
|
|
|
|
NamesAndTypesList ColumnsDescription::getAllPhysical() const
|
|
|
|
{
|
|
|
|
NamesAndTypesList ret;
|
|
|
|
for (const auto & col : columns)
|
2022-02-13 17:42:59 +00:00
|
|
|
if (col.default_desc.kind != ColumnDefaultKind::Alias && col.default_desc.kind != ColumnDefaultKind::Ephemeral)
|
2019-03-14 15:20:51 +00:00
|
|
|
ret.emplace_back(col.name, col.type);
|
|
|
|
return ret;
|
2015-04-11 03:10:23 +00:00
|
|
|
}
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
Names ColumnsDescription::getNamesOfPhysical() const
|
2018-11-16 12:01:52 +00:00
|
|
|
{
|
2019-03-14 15:20:51 +00:00
|
|
|
Names ret;
|
|
|
|
for (const auto & col : columns)
|
2022-02-13 17:42:59 +00:00
|
|
|
if (col.default_desc.kind != ColumnDefaultKind::Alias && col.default_desc.kind != ColumnDefaultKind::Ephemeral)
|
2019-03-14 15:20:51 +00:00
|
|
|
ret.emplace_back(col.name);
|
|
|
|
return ret;
|
|
|
|
}
|
2018-11-16 12:01:52 +00:00
|
|
|
|
2021-07-21 14:45:19 +00:00
|
|
|
std::optional<NameAndTypePair> ColumnsDescription::tryGetColumn(const GetColumnsOptions & options, const String & column_name) const
|
|
|
|
{
|
2022-05-18 12:36:13 +00:00
|
|
|
auto it = columns.get<1>().find(column_name);
|
|
|
|
if (it != columns.get<1>().end() && (defaultKindToGetKind(it->default_desc.kind) & options.kind))
|
|
|
|
return NameAndTypePair(it->name, it->type);
|
|
|
|
|
|
|
|
if (options.with_subcolumns)
|
|
|
|
{
|
|
|
|
auto jt = subcolumns.get<0>().find(column_name);
|
|
|
|
if (jt != subcolumns.get<0>().end())
|
|
|
|
return *jt;
|
|
|
|
}
|
2021-07-21 14:45:19 +00:00
|
|
|
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2021-07-23 16:30:18 +00:00
|
|
|
NameAndTypePair ColumnsDescription::getColumn(const GetColumnsOptions & options, const String & column_name) const
|
2019-03-14 15:20:51 +00:00
|
|
|
{
|
2021-07-23 16:30:18 +00:00
|
|
|
auto column = tryGetColumn(options, column_name);
|
|
|
|
if (!column)
|
|
|
|
throw Exception(ErrorCodes::NO_SUCH_COLUMN_IN_TABLE,
|
|
|
|
"There is no column {} in table.", column_name);
|
2021-07-15 03:12:37 +00:00
|
|
|
|
2021-07-23 16:30:18 +00:00
|
|
|
return *column;
|
|
|
|
}
|
2021-07-15 17:36:48 +00:00
|
|
|
|
2021-07-23 16:30:18 +00:00
|
|
|
std::optional<NameAndTypePair> ColumnsDescription::tryGetColumnOrSubcolumn(GetColumnsOptions::Kind kind, const String & column_name) const
|
|
|
|
{
|
|
|
|
return tryGetColumn(GetColumnsOptions(kind).withSubcolumns(), column_name);
|
2019-03-14 15:20:51 +00:00
|
|
|
}
|
2018-11-16 12:01:52 +00:00
|
|
|
|
2022-05-16 14:19:44 +00:00
|
|
|
std::optional<const ColumnDescription> ColumnsDescription::tryGetColumnDescription(const GetColumnsOptions & options, const String & column_name) const
|
|
|
|
{
|
|
|
|
auto it = columns.get<1>().find(column_name);
|
|
|
|
if (it != columns.get<1>().end() && (defaultKindToGetKind(it->default_desc.kind) & options.kind))
|
|
|
|
return *it;
|
|
|
|
|
|
|
|
if (options.with_subcolumns)
|
|
|
|
{
|
|
|
|
auto jt = subcolumns.get<0>().find(column_name);
|
|
|
|
if (jt != subcolumns.get<0>().end())
|
|
|
|
return ColumnDescription{jt->name, jt->type};
|
|
|
|
}
|
|
|
|
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<const ColumnDescription> ColumnsDescription::tryGetColumnOrSubcolumnDescription(GetColumnsOptions::Kind kind, const String & column_name) const
|
|
|
|
{
|
|
|
|
return tryGetColumnDescription(GetColumnsOptions(kind).withSubcolumns(), column_name);
|
|
|
|
}
|
|
|
|
|
2021-07-20 15:20:21 +00:00
|
|
|
NameAndTypePair ColumnsDescription::getColumnOrSubcolumn(GetColumnsOptions::Kind kind, const String & column_name) const
|
2020-09-14 11:22:17 +00:00
|
|
|
{
|
2021-07-20 15:20:21 +00:00
|
|
|
auto column = tryGetColumnOrSubcolumn(kind, column_name);
|
2021-07-15 03:12:37 +00:00
|
|
|
if (!column)
|
|
|
|
throw Exception(ErrorCodes::NO_SUCH_COLUMN_IN_TABLE,
|
2021-07-15 17:36:48 +00:00
|
|
|
"There is no column or subcolumn {} in table.", column_name);
|
2021-07-15 03:12:37 +00:00
|
|
|
|
|
|
|
return *column;
|
|
|
|
}
|
|
|
|
|
2021-07-15 17:36:48 +00:00
|
|
|
std::optional<NameAndTypePair> ColumnsDescription::tryGetPhysical(const String & column_name) const
|
2019-03-14 15:20:51 +00:00
|
|
|
{
|
2021-07-23 16:30:18 +00:00
|
|
|
return tryGetColumn(GetColumnsOptions::AllPhysical, column_name);
|
2019-03-14 15:20:51 +00:00
|
|
|
}
|
2018-11-16 12:01:52 +00:00
|
|
|
|
2021-07-15 17:36:48 +00:00
|
|
|
NameAndTypePair ColumnsDescription::getPhysical(const String & column_name) const
|
2020-09-14 11:22:17 +00:00
|
|
|
{
|
2021-07-15 17:36:48 +00:00
|
|
|
auto column = tryGetPhysical(column_name);
|
2021-07-15 03:12:37 +00:00
|
|
|
if (!column)
|
|
|
|
throw Exception(ErrorCodes::NO_SUCH_COLUMN_IN_TABLE,
|
2021-07-15 17:36:48 +00:00
|
|
|
"There is no physical column {} in table.", column_name);
|
2020-09-14 11:22:17 +00:00
|
|
|
|
2021-07-15 03:12:37 +00:00
|
|
|
return *column;
|
2020-09-14 11:22:17 +00:00
|
|
|
}
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
bool ColumnsDescription::hasPhysical(const String & column_name) const
|
|
|
|
{
|
2019-05-01 21:43:05 +00:00
|
|
|
auto it = columns.get<1>().find(column_name);
|
2022-02-13 17:42:59 +00:00
|
|
|
return it != columns.get<1>().end() &&
|
|
|
|
it->default_desc.kind != ColumnDefaultKind::Alias && it->default_desc.kind != ColumnDefaultKind::Ephemeral;
|
2019-03-14 15:20:51 +00:00
|
|
|
}
|
2018-11-16 12:01:52 +00:00
|
|
|
|
2021-07-20 15:20:21 +00:00
|
|
|
bool ColumnsDescription::hasColumnOrSubcolumn(GetColumnsOptions::Kind kind, const String & column_name) const
|
2020-09-18 14:51:54 +00:00
|
|
|
{
|
2021-07-15 17:36:48 +00:00
|
|
|
auto it = columns.get<1>().find(column_name);
|
|
|
|
return (it != columns.get<1>().end()
|
2021-07-20 15:20:21 +00:00
|
|
|
&& (defaultKindToGetKind(it->default_desc.kind) & kind))
|
2021-07-15 17:36:48 +00:00
|
|
|
|| hasSubcolumn(column_name);
|
2020-09-18 14:51:54 +00:00
|
|
|
}
|
2018-12-25 11:33:54 +00:00
|
|
|
|
2022-03-31 09:50:13 +00:00
|
|
|
bool ColumnsDescription::hasColumnOrNested(GetColumnsOptions::Kind kind, const String & column_name) const
|
|
|
|
{
|
|
|
|
auto range = getNameRange(columns, column_name);
|
|
|
|
return range.first != range.second &&
|
|
|
|
defaultKindToGetKind(range.first->default_desc.kind) & kind;
|
|
|
|
}
|
|
|
|
|
2020-10-02 12:38:50 +00:00
|
|
|
bool ColumnsDescription::hasDefaults() const
|
|
|
|
{
|
|
|
|
for (const auto & column : columns)
|
|
|
|
if (column.default_desc.expression)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
ColumnDefaults ColumnsDescription::getDefaults() const
|
|
|
|
{
|
|
|
|
ColumnDefaults ret;
|
|
|
|
for (const auto & column : columns)
|
|
|
|
if (column.default_desc.expression)
|
|
|
|
ret.emplace(column.name, column.default_desc);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ColumnsDescription::hasDefault(const String & column_name) const
|
|
|
|
{
|
2019-05-01 21:43:05 +00:00
|
|
|
auto it = columns.get<1>().find(column_name);
|
|
|
|
return it != columns.get<1>().end() && it->default_desc.expression;
|
2018-11-16 12:01:52 +00:00
|
|
|
}
|
2015-04-11 03:10:23 +00:00
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
std::optional<ColumnDefault> ColumnsDescription::getDefault(const String & column_name) const
|
|
|
|
{
|
2019-05-01 21:43:05 +00:00
|
|
|
auto it = columns.get<1>().find(column_name);
|
|
|
|
if (it != columns.get<1>().end() && it->default_desc.expression)
|
|
|
|
return it->default_desc;
|
2019-03-14 15:20:51 +00:00
|
|
|
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-28 09:07:20 +00:00
|
|
|
bool ColumnsDescription::hasCompressionCodec(const String & column_name) const
|
|
|
|
{
|
|
|
|
const auto it = columns.get<1>().find(column_name);
|
|
|
|
|
2020-08-28 10:47:29 +00:00
|
|
|
return it != columns.get<1>().end() && it->codec != nullptr;
|
2020-08-28 09:07:20 +00:00
|
|
|
}
|
|
|
|
|
2018-12-21 12:17:30 +00:00
|
|
|
CompressionCodecPtr ColumnsDescription::getCodecOrDefault(const String & column_name, CompressionCodecPtr default_codec) const
|
2018-10-11 02:57:48 +00:00
|
|
|
{
|
2019-05-01 21:43:05 +00:00
|
|
|
const auto it = columns.get<1>().find(column_name);
|
2018-10-11 02:57:48 +00:00
|
|
|
|
2019-05-01 21:43:05 +00:00
|
|
|
if (it == columns.get<1>().end() || !it->codec)
|
2018-12-21 12:17:30 +00:00
|
|
|
return default_codec;
|
2018-10-11 02:57:48 +00:00
|
|
|
|
2020-08-26 08:45:13 +00:00
|
|
|
return CompressionCodecFactory::instance().get(it->codec, it->type, default_codec);
|
2018-10-11 02:57:48 +00:00
|
|
|
}
|
|
|
|
|
2019-01-21 14:00:06 +00:00
|
|
|
CompressionCodecPtr ColumnsDescription::getCodecOrDefault(const String & column_name) const
|
|
|
|
{
|
|
|
|
return getCodecOrDefault(column_name, CompressionCodecFactory::instance().getDefaultCodec());
|
|
|
|
}
|
|
|
|
|
2020-09-21 11:24:10 +00:00
|
|
|
ASTPtr ColumnsDescription::getCodecDescOrDefault(const String & column_name, CompressionCodecPtr default_codec) const
|
2020-09-21 07:18:23 +00:00
|
|
|
{
|
|
|
|
const auto it = columns.get<1>().find(column_name);
|
|
|
|
|
|
|
|
if (it == columns.get<1>().end() || !it->codec)
|
|
|
|
return default_codec->getFullCodecDesc();
|
|
|
|
|
|
|
|
return it->codec;
|
|
|
|
}
|
|
|
|
|
2019-04-15 09:30:45 +00:00
|
|
|
ColumnsDescription::ColumnTTLs ColumnsDescription::getColumnTTLs() const
|
|
|
|
{
|
|
|
|
ColumnTTLs ret;
|
|
|
|
for (const auto & column : columns)
|
|
|
|
if (column.ttl)
|
|
|
|
ret.emplace(column.name, column.ttl);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-02-28 06:12:17 +00:00
|
|
|
void ColumnsDescription::resetColumnTTLs()
|
|
|
|
{
|
|
|
|
std::vector<ColumnDescription> old_columns;
|
|
|
|
old_columns.reserve(columns.size());
|
|
|
|
for (const auto & col : columns)
|
|
|
|
old_columns.emplace_back(col);
|
|
|
|
|
|
|
|
columns.clear();
|
|
|
|
|
|
|
|
for (auto & col : old_columns)
|
|
|
|
{
|
|
|
|
col.ttl.reset();
|
|
|
|
add(col);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-14 15:20:51 +00:00
|
|
|
|
|
|
|
String ColumnsDescription::toString() const
|
|
|
|
{
|
|
|
|
WriteBufferFromOwnString buf;
|
|
|
|
|
|
|
|
writeCString("columns format version: 1\n", buf);
|
|
|
|
DB::writeText(columns.size(), buf);
|
|
|
|
writeCString(" columns:\n", buf);
|
|
|
|
|
|
|
|
for (const ColumnDescription & column : columns)
|
|
|
|
column.writeText(buf);
|
|
|
|
|
|
|
|
return buf.str();
|
|
|
|
}
|
|
|
|
|
2018-03-06 20:18:34 +00:00
|
|
|
ColumnsDescription ColumnsDescription::parse(const String & str)
|
2015-04-11 03:10:23 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
ReadBufferFromString buf{str};
|
|
|
|
|
|
|
|
assertString("columns format version: 1\n", buf);
|
|
|
|
size_t count{};
|
|
|
|
readText(count, buf);
|
|
|
|
assertString(" columns:\n", buf);
|
|
|
|
|
2018-03-06 20:18:34 +00:00
|
|
|
ColumnsDescription result;
|
2017-04-01 07:20:54 +00:00
|
|
|
for (size_t i = 0; i < count; ++i)
|
|
|
|
{
|
2019-03-14 15:20:51 +00:00
|
|
|
ColumnDescription column;
|
|
|
|
column.readText(buf);
|
2019-02-27 16:41:51 +00:00
|
|
|
buf.ignore(1); /// ignore new line
|
2020-09-18 17:37:08 +00:00
|
|
|
result.add(column);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
assertEOF(buf);
|
|
|
|
return result;
|
2015-04-11 03:10:23 +00:00
|
|
|
}
|
|
|
|
|
2021-01-12 23:20:32 +00:00
|
|
|
void ColumnsDescription::addSubcolumns(const String & name_in_storage, const DataTypePtr & type_in_storage)
|
2020-09-18 17:37:08 +00:00
|
|
|
{
|
2022-02-15 23:14:09 +00:00
|
|
|
IDataType::forEachSubcolumn([&](const auto &, const auto & subname, const auto & subdata)
|
2020-09-18 17:37:08 +00:00
|
|
|
{
|
2022-02-15 23:14:09 +00:00
|
|
|
auto subcolumn = NameAndTypePair(name_in_storage, subname, type_in_storage, subdata.type);
|
2020-09-18 17:37:08 +00:00
|
|
|
|
|
|
|
if (has(subcolumn.name))
|
|
|
|
throw Exception(ErrorCodes::ILLEGAL_COLUMN,
|
|
|
|
"Cannot add subcolumn {}: column with this name already exists", subcolumn.name);
|
|
|
|
|
2021-07-15 03:12:37 +00:00
|
|
|
subcolumns.get<0>().insert(std::move(subcolumn));
|
2022-02-15 23:14:09 +00:00
|
|
|
}, {type_in_storage->getDefaultSerialization(), type_in_storage, nullptr, nullptr});
|
2020-09-18 17:37:08 +00:00
|
|
|
}
|
2020-03-03 09:05:17 +00:00
|
|
|
|
2021-07-15 03:12:37 +00:00
|
|
|
void ColumnsDescription::removeSubcolumns(const String & name_in_storage)
|
2020-10-27 11:27:14 +00:00
|
|
|
{
|
2021-07-15 03:12:37 +00:00
|
|
|
auto range = subcolumns.get<1>().equal_range(name_in_storage);
|
|
|
|
if (range.first != range.second)
|
|
|
|
subcolumns.get<1>().erase(range.first, range.second);
|
2020-10-27 11:27:14 +00:00
|
|
|
}
|
|
|
|
|
2022-03-30 12:54:33 +00:00
|
|
|
std::vector<String> ColumnsDescription::getAllRegisteredNames() const
|
|
|
|
{
|
|
|
|
std::vector<String> names;
|
|
|
|
names.reserve(columns.size());
|
|
|
|
for (const auto & column : columns)
|
|
|
|
{
|
|
|
|
if (column.name.find('.') == std::string::npos)
|
|
|
|
names.push_back(column.name);
|
|
|
|
}
|
|
|
|
return names;
|
|
|
|
}
|
|
|
|
|
2021-04-10 23:33:54 +00:00
|
|
|
Block validateColumnsDefaultsAndGetSampleBlock(ASTPtr default_expr_list, const NamesAndTypesList & all_columns, ContextPtr context)
|
2020-03-03 09:05:17 +00:00
|
|
|
{
|
|
|
|
for (const auto & child : default_expr_list->children)
|
2020-03-03 12:51:41 +00:00
|
|
|
if (child->as<ASTSelectQuery>() || child->as<ASTSelectWithUnionQuery>() || child->as<ASTSubquery>())
|
2020-03-03 09:05:17 +00:00
|
|
|
throw Exception("Select query is not allowed in columns DEFAULT expression", ErrorCodes::THERE_IS_NO_DEFAULT_VALUE);
|
|
|
|
|
2020-03-03 10:02:43 +00:00
|
|
|
try
|
|
|
|
{
|
2021-06-08 09:54:00 +00:00
|
|
|
auto syntax_analyzer_result = TreeRewriter(context).analyze(default_expr_list, all_columns, {}, {}, false, /* allow_self_aliases = */ false);
|
2020-03-03 10:02:43 +00:00
|
|
|
const auto actions = ExpressionAnalyzer(default_expr_list, syntax_analyzer_result, context).getActions(true);
|
2020-04-22 06:22:14 +00:00
|
|
|
for (const auto & action : actions->getActions())
|
2020-11-10 14:54:59 +00:00
|
|
|
if (action.node->type == ActionsDAG::ActionType::ARRAY_JOIN)
|
2020-09-08 10:40:53 +00:00
|
|
|
throw Exception("Unsupported default value that requires ARRAY JOIN action", ErrorCodes::THERE_IS_NO_DEFAULT_VALUE);
|
2020-03-03 09:05:17 +00:00
|
|
|
|
2020-03-03 10:02:43 +00:00
|
|
|
return actions->getSampleBlock();
|
|
|
|
}
|
|
|
|
catch (Exception & ex)
|
|
|
|
{
|
|
|
|
ex.addMessage("default expression and column type are incompatible.");
|
|
|
|
throw;
|
|
|
|
}
|
2020-03-03 09:05:17 +00:00
|
|
|
}
|
2020-03-03 10:02:43 +00:00
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
}
|