2020-05-21 19:07:18 +00:00
|
|
|
#include <Storages/StorageInMemoryMetadata.h>
|
|
|
|
|
2021-08-15 10:32:56 +00:00
|
|
|
#include <Common/HashTable/HashMap.h>
|
|
|
|
#include <Common/HashTable/HashSet.h>
|
2020-06-16 14:25:08 +00:00
|
|
|
#include <Common/quoteString.h>
|
2020-09-14 11:22:17 +00:00
|
|
|
#include <Common/StringUtils/StringUtils.h>
|
2020-06-17 14:32:25 +00:00
|
|
|
#include <Core/ColumnWithTypeAndName.h>
|
2021-08-23 13:08:23 +00:00
|
|
|
#include <DataTypes/DataTypeEnum.h>
|
2020-09-14 11:22:17 +00:00
|
|
|
#include <IO/ReadBufferFromString.h>
|
|
|
|
#include <IO/ReadHelpers.h>
|
2020-11-10 18:22:26 +00:00
|
|
|
#include <IO/Operators.h>
|
2020-06-17 14:32:25 +00:00
|
|
|
|
2020-06-16 14:25:08 +00:00
|
|
|
|
2020-02-14 13:17:50 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
2020-06-16 14:25:08 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int COLUMN_QUERIED_MORE_THAN_ONCE;
|
|
|
|
extern const int DUPLICATE_COLUMN;
|
|
|
|
extern const int EMPTY_LIST_OF_COLUMNS_QUERIED;
|
|
|
|
extern const int NO_SUCH_COLUMN_IN_TABLE;
|
|
|
|
extern const int NOT_FOUND_COLUMN_IN_BLOCK;
|
|
|
|
extern const int TYPE_MISMATCH;
|
2020-06-19 12:05:29 +00:00
|
|
|
extern const int EMPTY_LIST_OF_COLUMNS_PASSED;
|
2020-06-16 14:25:08 +00:00
|
|
|
}
|
|
|
|
|
2020-06-08 14:18:38 +00:00
|
|
|
StorageInMemoryMetadata::StorageInMemoryMetadata(const StorageInMemoryMetadata & other)
|
|
|
|
: columns(other.columns)
|
|
|
|
, secondary_indices(other.secondary_indices)
|
|
|
|
, constraints(other.constraints)
|
2021-04-26 16:06:18 +00:00
|
|
|
, projections(other.projections.clone())
|
2020-06-08 14:18:38 +00:00
|
|
|
, partition_key(other.partition_key)
|
|
|
|
, primary_key(other.primary_key)
|
|
|
|
, sorting_key(other.sorting_key)
|
|
|
|
, sampling_key(other.sampling_key)
|
|
|
|
, column_ttls_by_name(other.column_ttls_by_name)
|
|
|
|
, table_ttl(other.table_ttl)
|
|
|
|
, settings_changes(other.settings_changes ? other.settings_changes->clone() : nullptr)
|
|
|
|
, select(other.select)
|
2021-04-23 12:18:23 +00:00
|
|
|
, comment(other.comment)
|
2020-06-08 14:18:38 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
StorageInMemoryMetadata & StorageInMemoryMetadata::operator=(const StorageInMemoryMetadata & other)
|
|
|
|
{
|
2020-06-09 17:42:04 +00:00
|
|
|
if (&other == this)
|
|
|
|
return *this;
|
|
|
|
|
2020-06-08 14:18:38 +00:00
|
|
|
columns = other.columns;
|
|
|
|
secondary_indices = other.secondary_indices;
|
|
|
|
constraints = other.constraints;
|
2021-04-26 16:06:18 +00:00
|
|
|
projections = other.projections.clone();
|
2020-06-08 14:18:38 +00:00
|
|
|
partition_key = other.partition_key;
|
|
|
|
primary_key = other.primary_key;
|
|
|
|
sorting_key = other.sorting_key;
|
|
|
|
sampling_key = other.sampling_key;
|
|
|
|
column_ttls_by_name = other.column_ttls_by_name;
|
|
|
|
table_ttl = other.table_ttl;
|
|
|
|
if (other.settings_changes)
|
|
|
|
settings_changes = other.settings_changes->clone();
|
|
|
|
else
|
|
|
|
settings_changes.reset();
|
|
|
|
select = other.select;
|
2021-04-23 12:18:23 +00:00
|
|
|
comment = other.comment;
|
2020-06-08 14:18:38 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2021-04-23 12:18:23 +00:00
|
|
|
void StorageInMemoryMetadata::setComment(const String & comment_)
|
|
|
|
{
|
|
|
|
comment = comment_;
|
|
|
|
}
|
2020-06-12 09:37:52 +00:00
|
|
|
|
2020-06-15 16:55:33 +00:00
|
|
|
void StorageInMemoryMetadata::setColumns(ColumnsDescription columns_)
|
|
|
|
{
|
2020-06-19 12:05:29 +00:00
|
|
|
if (columns_.getAllPhysical().empty())
|
|
|
|
throw Exception("Empty list of columns passed", ErrorCodes::EMPTY_LIST_OF_COLUMNS_PASSED);
|
2020-06-15 16:55:33 +00:00
|
|
|
columns = std::move(columns_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StorageInMemoryMetadata::setSecondaryIndices(IndicesDescription secondary_indices_)
|
|
|
|
{
|
|
|
|
secondary_indices = std::move(secondary_indices_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StorageInMemoryMetadata::setConstraints(ConstraintsDescription constraints_)
|
|
|
|
{
|
|
|
|
constraints = std::move(constraints_);
|
|
|
|
}
|
|
|
|
|
2021-02-10 14:12:49 +00:00
|
|
|
void StorageInMemoryMetadata::setProjections(ProjectionsDescription projections_)
|
|
|
|
{
|
|
|
|
projections = std::move(projections_);
|
|
|
|
}
|
|
|
|
|
2020-06-15 17:50:53 +00:00
|
|
|
void StorageInMemoryMetadata::setTableTTLs(const TTLTableDescription & table_ttl_)
|
|
|
|
{
|
|
|
|
table_ttl = table_ttl_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StorageInMemoryMetadata::setColumnTTLs(const TTLColumnsDescription & column_ttls_by_name_)
|
|
|
|
{
|
|
|
|
column_ttls_by_name = column_ttls_by_name_;
|
|
|
|
}
|
|
|
|
|
2020-06-15 18:08:05 +00:00
|
|
|
void StorageInMemoryMetadata::setSettingsChanges(const ASTPtr & settings_changes_)
|
|
|
|
{
|
|
|
|
if (settings_changes_)
|
|
|
|
settings_changes = settings_changes_;
|
|
|
|
else
|
|
|
|
settings_changes = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StorageInMemoryMetadata::setSelectQuery(const SelectQueryDescription & select_)
|
|
|
|
{
|
|
|
|
select = select_;
|
|
|
|
}
|
|
|
|
|
2020-06-16 12:03:27 +00:00
|
|
|
const ColumnsDescription & StorageInMemoryMetadata::getColumns() const
|
|
|
|
{
|
|
|
|
return columns;
|
|
|
|
}
|
|
|
|
|
|
|
|
const IndicesDescription & StorageInMemoryMetadata::getSecondaryIndices() const
|
|
|
|
{
|
|
|
|
return secondary_indices;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::hasSecondaryIndices() const
|
|
|
|
{
|
|
|
|
return !secondary_indices.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
const ConstraintsDescription & StorageInMemoryMetadata::getConstraints() const
|
|
|
|
{
|
|
|
|
return constraints;
|
|
|
|
}
|
|
|
|
|
2021-02-10 14:12:49 +00:00
|
|
|
const ProjectionsDescription & StorageInMemoryMetadata::getProjections() const
|
|
|
|
{
|
|
|
|
return projections;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::hasProjections() const
|
|
|
|
{
|
|
|
|
return !projections.empty();
|
|
|
|
}
|
|
|
|
|
2020-06-16 12:03:27 +00:00
|
|
|
TTLTableDescription StorageInMemoryMetadata::getTableTTLs() const
|
|
|
|
{
|
|
|
|
return table_ttl;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::hasAnyTableTTL() const
|
|
|
|
{
|
2021-01-13 14:04:27 +00:00
|
|
|
return hasAnyMoveTTL() || hasRowsTTL() || hasAnyRecompressionTTL() || hasAnyGroupByTTL() || hasAnyRowsWhereTTL();
|
2020-06-16 12:03:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TTLColumnsDescription StorageInMemoryMetadata::getColumnTTLs() const
|
|
|
|
{
|
|
|
|
return column_ttls_by_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::hasAnyColumnTTL() const
|
|
|
|
{
|
|
|
|
return !column_ttls_by_name.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
TTLDescription StorageInMemoryMetadata::getRowsTTL() const
|
|
|
|
{
|
|
|
|
return table_ttl.rows_ttl;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::hasRowsTTL() const
|
|
|
|
{
|
|
|
|
return table_ttl.rows_ttl.expression != nullptr;
|
|
|
|
}
|
|
|
|
|
2021-01-13 14:04:27 +00:00
|
|
|
TTLDescriptions StorageInMemoryMetadata::getRowsWhereTTLs() const
|
2021-01-11 23:07:21 +00:00
|
|
|
{
|
|
|
|
return table_ttl.rows_where_ttl;
|
|
|
|
}
|
|
|
|
|
2021-01-13 14:04:27 +00:00
|
|
|
bool StorageInMemoryMetadata::hasAnyRowsWhereTTL() const
|
2021-01-11 23:07:21 +00:00
|
|
|
{
|
|
|
|
return !table_ttl.rows_where_ttl.empty();
|
|
|
|
}
|
|
|
|
|
2020-06-16 12:03:27 +00:00
|
|
|
TTLDescriptions StorageInMemoryMetadata::getMoveTTLs() const
|
|
|
|
{
|
|
|
|
return table_ttl.move_ttl;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::hasAnyMoveTTL() const
|
|
|
|
{
|
|
|
|
return !table_ttl.move_ttl.empty();
|
|
|
|
}
|
|
|
|
|
2020-08-31 12:12:51 +00:00
|
|
|
TTLDescriptions StorageInMemoryMetadata::getRecompressionTTLs() const
|
|
|
|
{
|
|
|
|
return table_ttl.recompression_ttl;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::hasAnyRecompressionTTL() const
|
|
|
|
{
|
|
|
|
return !table_ttl.recompression_ttl.empty();
|
|
|
|
}
|
|
|
|
|
2020-12-25 14:52:46 +00:00
|
|
|
TTLDescriptions StorageInMemoryMetadata::getGroupByTTLs() const
|
|
|
|
{
|
|
|
|
return table_ttl.group_by_ttl;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::hasAnyGroupByTTL() const
|
|
|
|
{
|
|
|
|
return !table_ttl.group_by_ttl.empty();
|
|
|
|
}
|
|
|
|
|
2020-06-16 12:03:27 +00:00
|
|
|
ColumnDependencies StorageInMemoryMetadata::getColumnDependencies(const NameSet & updated_columns) const
|
|
|
|
{
|
|
|
|
if (updated_columns.empty())
|
|
|
|
return {};
|
|
|
|
|
|
|
|
ColumnDependencies res;
|
|
|
|
|
|
|
|
NameSet indices_columns;
|
2021-02-10 14:12:49 +00:00
|
|
|
NameSet projections_columns;
|
2020-06-16 12:03:27 +00:00
|
|
|
NameSet required_ttl_columns;
|
|
|
|
NameSet updated_ttl_columns;
|
|
|
|
|
|
|
|
auto add_dependent_columns = [&updated_columns](const auto & expression, auto & to_set)
|
|
|
|
{
|
2021-06-28 17:02:22 +00:00
|
|
|
auto required_columns = expression->getRequiredColumns();
|
|
|
|
for (const auto & dependency : required_columns)
|
2020-06-16 12:03:27 +00:00
|
|
|
{
|
|
|
|
if (updated_columns.count(dependency))
|
|
|
|
{
|
2021-06-28 17:02:22 +00:00
|
|
|
to_set.insert(required_columns.begin(), required_columns.end());
|
2020-06-16 12:03:27 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
for (const auto & index : getSecondaryIndices())
|
|
|
|
add_dependent_columns(index.expression, indices_columns);
|
|
|
|
|
2021-02-10 14:12:49 +00:00
|
|
|
for (const auto & projection : getProjections())
|
|
|
|
add_dependent_columns(&projection, projections_columns);
|
|
|
|
|
2020-06-16 12:03:27 +00:00
|
|
|
if (hasRowsTTL())
|
|
|
|
{
|
|
|
|
auto rows_expression = getRowsTTL().expression;
|
|
|
|
if (add_dependent_columns(rows_expression, required_ttl_columns))
|
|
|
|
{
|
|
|
|
/// Filter all columns, if rows TTL expression have to be recalculated.
|
|
|
|
for (const auto & column : getColumns().getAllPhysical())
|
|
|
|
updated_ttl_columns.insert(column.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-01 10:49:53 +00:00
|
|
|
for (const auto & entry : getRecompressionTTLs())
|
|
|
|
add_dependent_columns(entry.expression, required_ttl_columns);
|
|
|
|
|
2020-06-16 12:03:27 +00:00
|
|
|
for (const auto & [name, entry] : getColumnTTLs())
|
|
|
|
{
|
|
|
|
if (add_dependent_columns(entry.expression, required_ttl_columns))
|
|
|
|
updated_ttl_columns.insert(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto & entry : getMoveTTLs())
|
|
|
|
add_dependent_columns(entry.expression, required_ttl_columns);
|
|
|
|
|
|
|
|
for (const auto & column : indices_columns)
|
|
|
|
res.emplace(column, ColumnDependency::SKIP_INDEX);
|
2021-02-10 14:12:49 +00:00
|
|
|
for (const auto & column : projections_columns)
|
|
|
|
res.emplace(column, ColumnDependency::PROJECTION);
|
2020-06-16 12:03:27 +00:00
|
|
|
for (const auto & column : required_ttl_columns)
|
|
|
|
res.emplace(column, ColumnDependency::TTL_EXPRESSION);
|
|
|
|
for (const auto & column : updated_ttl_columns)
|
|
|
|
res.emplace(column, ColumnDependency::TTL_TARGET);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-06-16 12:48:10 +00:00
|
|
|
Block StorageInMemoryMetadata::getSampleBlockNonMaterialized() const
|
|
|
|
{
|
|
|
|
Block res;
|
|
|
|
|
|
|
|
for (const auto & column : getColumns().getOrdinary())
|
|
|
|
res.insert({column.type->createColumn(), column.type, column.name});
|
2020-06-16 12:03:27 +00:00
|
|
|
|
2020-06-16 12:48:10 +00:00
|
|
|
return res;
|
|
|
|
}
|
2020-06-16 12:58:05 +00:00
|
|
|
|
|
|
|
Block StorageInMemoryMetadata::getSampleBlockWithVirtuals(const NamesAndTypesList & virtuals) const
|
|
|
|
{
|
|
|
|
auto res = getSampleBlock();
|
|
|
|
|
|
|
|
/// Virtual columns must be appended after ordinary, because user can
|
|
|
|
/// override them.
|
|
|
|
for (const auto & column : virtuals)
|
|
|
|
res.insert({column.type->createColumn(), column.type, column.name});
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
Block StorageInMemoryMetadata::getSampleBlock() const
|
|
|
|
{
|
|
|
|
Block res;
|
|
|
|
|
|
|
|
for (const auto & column : getColumns().getAllPhysical())
|
|
|
|
res.insert({column.type->createColumn(), column.type, column.name});
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
2020-06-16 14:25:08 +00:00
|
|
|
|
2020-06-19 17:17:13 +00:00
|
|
|
Block StorageInMemoryMetadata::getSampleBlockForColumns(
|
|
|
|
const Names & column_names, const NamesAndTypesList & virtuals, const StorageID & storage_id) const
|
2020-06-16 14:25:08 +00:00
|
|
|
{
|
|
|
|
Block res;
|
|
|
|
|
2021-08-15 10:32:56 +00:00
|
|
|
HashMapWithSavedHash<StringRef, const DataTypePtr *, StringRefHash> virtuals_map;
|
2020-06-16 14:25:08 +00:00
|
|
|
|
|
|
|
/// Virtual columns must be appended after ordinary, because user can
|
|
|
|
/// override them.
|
|
|
|
for (const auto & column : virtuals)
|
2021-08-04 10:06:01 +00:00
|
|
|
virtuals_map[column.name] = &column.type;
|
2020-06-16 14:25:08 +00:00
|
|
|
|
|
|
|
for (const auto & name : column_names)
|
|
|
|
{
|
2021-07-15 17:36:48 +00:00
|
|
|
auto column = getColumns().tryGetColumnOrSubcolumn(ColumnsDescription::All, name);
|
|
|
|
if (column)
|
|
|
|
{
|
|
|
|
res.insert({column->type->createColumn(), column->type, column->name});
|
|
|
|
}
|
2021-08-15 10:32:56 +00:00
|
|
|
else if (auto * it = virtuals_map.find(name); it != virtuals_map.end())
|
2021-07-15 03:12:37 +00:00
|
|
|
{
|
2021-08-15 10:32:56 +00:00
|
|
|
const auto & type = *it->getMapped();
|
2021-07-15 03:12:37 +00:00
|
|
|
res.insert({type->createColumn(), type, name});
|
|
|
|
}
|
2020-06-16 14:25:08 +00:00
|
|
|
else
|
|
|
|
throw Exception(
|
2021-03-30 17:57:21 +00:00
|
|
|
"Column " + backQuote(name) + " not found in table " + (storage_id.empty() ? "" : storage_id.getNameForLogs()),
|
2020-06-16 14:25:08 +00:00
|
|
|
ErrorCodes::NOT_FOUND_COLUMN_IN_BLOCK);
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
2020-06-16 16:55:04 +00:00
|
|
|
|
2020-06-17 10:34:23 +00:00
|
|
|
const KeyDescription & StorageInMemoryMetadata::getPartitionKey() const
|
|
|
|
{
|
|
|
|
return partition_key;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::isPartitionKeyDefined() const
|
|
|
|
{
|
|
|
|
return partition_key.definition_ast != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::hasPartitionKey() const
|
|
|
|
{
|
|
|
|
return !partition_key.column_names.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
Names StorageInMemoryMetadata::getColumnsRequiredForPartitionKey() const
|
|
|
|
{
|
|
|
|
if (hasPartitionKey())
|
|
|
|
return partition_key.expression->getRequiredColumns();
|
|
|
|
return {};
|
|
|
|
}
|
2020-06-17 11:05:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
const KeyDescription & StorageInMemoryMetadata::getSortingKey() const
|
|
|
|
{
|
|
|
|
return sorting_key;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::isSortingKeyDefined() const
|
|
|
|
{
|
|
|
|
return sorting_key.definition_ast != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::hasSortingKey() const
|
|
|
|
{
|
|
|
|
return !sorting_key.column_names.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
Names StorageInMemoryMetadata::getColumnsRequiredForSortingKey() const
|
|
|
|
{
|
|
|
|
if (hasSortingKey())
|
|
|
|
return sorting_key.expression->getRequiredColumns();
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
Names StorageInMemoryMetadata::getSortingKeyColumns() const
|
|
|
|
{
|
|
|
|
if (hasSortingKey())
|
|
|
|
return sorting_key.column_names;
|
|
|
|
return {};
|
|
|
|
}
|
2020-06-17 12:07:09 +00:00
|
|
|
|
|
|
|
const KeyDescription & StorageInMemoryMetadata::getSamplingKey() const
|
|
|
|
{
|
|
|
|
return sampling_key;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::isSamplingKeyDefined() const
|
|
|
|
{
|
|
|
|
return sampling_key.definition_ast != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::hasSamplingKey() const
|
|
|
|
{
|
|
|
|
return !sampling_key.column_names.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
Names StorageInMemoryMetadata::getColumnsRequiredForSampling() const
|
|
|
|
{
|
|
|
|
if (hasSamplingKey())
|
|
|
|
return sampling_key.expression->getRequiredColumns();
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2020-06-17 12:39:20 +00:00
|
|
|
const KeyDescription & StorageInMemoryMetadata::getPrimaryKey() const
|
|
|
|
{
|
|
|
|
return primary_key;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::isPrimaryKeyDefined() const
|
|
|
|
{
|
|
|
|
return primary_key.definition_ast != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::hasPrimaryKey() const
|
|
|
|
{
|
|
|
|
return !primary_key.column_names.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
Names StorageInMemoryMetadata::getColumnsRequiredForPrimaryKey() const
|
|
|
|
{
|
|
|
|
if (hasPrimaryKey())
|
|
|
|
return primary_key.expression->getRequiredColumns();
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
Names StorageInMemoryMetadata::getPrimaryKeyColumns() const
|
|
|
|
{
|
|
|
|
if (!primary_key.column_names.empty())
|
|
|
|
return primary_key.column_names;
|
|
|
|
return {};
|
|
|
|
}
|
2020-06-17 13:46:01 +00:00
|
|
|
|
|
|
|
ASTPtr StorageInMemoryMetadata::getSettingsChanges() const
|
|
|
|
{
|
|
|
|
if (settings_changes)
|
|
|
|
return settings_changes->clone();
|
|
|
|
return nullptr;
|
|
|
|
}
|
2020-06-17 14:06:22 +00:00
|
|
|
const SelectQueryDescription & StorageInMemoryMetadata::getSelectQuery() const
|
|
|
|
{
|
|
|
|
return select;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StorageInMemoryMetadata::hasSelectQuery() const
|
|
|
|
{
|
|
|
|
return select.select_query != nullptr;
|
|
|
|
}
|
2020-06-17 13:46:01 +00:00
|
|
|
|
2020-06-17 14:32:25 +00:00
|
|
|
namespace
|
|
|
|
{
|
2021-08-15 10:32:56 +00:00
|
|
|
using NamesAndTypesMap = HashMapWithSavedHash<StringRef, const IDataType *, StringRefHash>;
|
|
|
|
using UniqueStrings = HashSetWithSavedHash<StringRef, StringRefHash>;
|
2020-06-17 14:32:25 +00:00
|
|
|
|
|
|
|
String listOfColumns(const NamesAndTypesList & available_columns)
|
|
|
|
{
|
2020-11-10 18:22:26 +00:00
|
|
|
WriteBufferFromOwnString ss;
|
2020-06-17 14:32:25 +00:00
|
|
|
for (auto it = available_columns.begin(); it != available_columns.end(); ++it)
|
|
|
|
{
|
|
|
|
if (it != available_columns.begin())
|
|
|
|
ss << ", ";
|
|
|
|
ss << it->name;
|
|
|
|
}
|
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
NamesAndTypesMap getColumnsMap(const NamesAndTypesList & columns)
|
|
|
|
{
|
|
|
|
NamesAndTypesMap res;
|
|
|
|
|
|
|
|
for (const auto & column : columns)
|
|
|
|
res.insert({column.name, column.type.get()});
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
2021-08-23 13:08:23 +00:00
|
|
|
|
|
|
|
bool isEnumSubset(const IDataType* lhs, const DataTypePtr& rhs)
|
|
|
|
{
|
|
|
|
const WhichDataType & which = WhichDataType{lhs};
|
|
|
|
if (!which.isEnum())
|
|
|
|
return false;
|
|
|
|
IDataTypeEnum const* enum_type = dynamic_cast<IDataTypeEnum const*>(lhs);
|
2021-08-23 14:55:21 +00:00
|
|
|
if (!enum_type->contains(*rhs))
|
|
|
|
return false;
|
|
|
|
return enum_type->getMaximumSizeOfValueInMemory() == rhs->getMaximumSizeOfValueInMemory();
|
2021-08-23 13:08:23 +00:00
|
|
|
}
|
2020-06-17 14:32:25 +00:00
|
|
|
}
|
|
|
|
|
2020-06-19 17:17:13 +00:00
|
|
|
void StorageInMemoryMetadata::check(const Names & column_names, const NamesAndTypesList & virtuals, const StorageID & storage_id) const
|
2020-06-17 14:32:25 +00:00
|
|
|
{
|
|
|
|
if (column_names.empty())
|
2021-07-15 17:36:48 +00:00
|
|
|
{
|
|
|
|
auto list_of_columns = listOfColumns(getColumns().getAllPhysicalWithSubcolumns());
|
|
|
|
throw Exception(ErrorCodes::EMPTY_LIST_OF_COLUMNS_QUERIED,
|
|
|
|
"Empty list of columns queried. There are columns: {}", list_of_columns);
|
|
|
|
}
|
2020-06-17 14:32:25 +00:00
|
|
|
|
2021-07-15 17:36:48 +00:00
|
|
|
const auto virtuals_map = getColumnsMap(virtuals);
|
2021-08-15 10:32:56 +00:00
|
|
|
UniqueStrings unique_names;
|
2021-07-15 17:36:48 +00:00
|
|
|
|
2020-06-17 14:32:25 +00:00
|
|
|
for (const auto & name : column_names)
|
|
|
|
{
|
2021-08-15 10:32:56 +00:00
|
|
|
bool has_column = getColumns().hasColumnOrSubcolumn(ColumnsDescription::AllPhysical, name)
|
|
|
|
|| virtuals_map.find(name) != nullptr;
|
2021-07-15 17:36:48 +00:00
|
|
|
|
|
|
|
if (!has_column)
|
|
|
|
{
|
|
|
|
auto list_of_columns = listOfColumns(getColumns().getAllPhysicalWithSubcolumns());
|
|
|
|
throw Exception(ErrorCodes::NO_SUCH_COLUMN_IN_TABLE,
|
|
|
|
"There is no column with name {} in table {}. There are columns: {}",
|
|
|
|
backQuote(name), storage_id.getNameForLogs(), list_of_columns);
|
|
|
|
}
|
2020-06-17 14:32:25 +00:00
|
|
|
|
|
|
|
if (unique_names.end() != unique_names.find(name))
|
2021-07-15 17:36:48 +00:00
|
|
|
throw Exception(ErrorCodes::COLUMN_QUERIED_MORE_THAN_ONCE, "Column {} queried more than once", name);
|
|
|
|
|
2020-06-17 14:32:25 +00:00
|
|
|
unique_names.insert(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StorageInMemoryMetadata::check(const NamesAndTypesList & provided_columns) const
|
|
|
|
{
|
|
|
|
const NamesAndTypesList & available_columns = getColumns().getAllPhysical();
|
|
|
|
const auto columns_map = getColumnsMap(available_columns);
|
|
|
|
|
2021-08-15 10:32:56 +00:00
|
|
|
UniqueStrings unique_names;
|
|
|
|
|
2020-06-17 14:32:25 +00:00
|
|
|
for (const NameAndTypePair & column : provided_columns)
|
|
|
|
{
|
2021-08-15 10:32:56 +00:00
|
|
|
const auto * it = columns_map.find(column.name);
|
2020-06-17 14:32:25 +00:00
|
|
|
if (columns_map.end() == it)
|
|
|
|
throw Exception(
|
2021-08-15 10:32:56 +00:00
|
|
|
ErrorCodes::NO_SUCH_COLUMN_IN_TABLE,
|
|
|
|
"There is no column with name {}. There are columns: {}",
|
|
|
|
column.name,
|
|
|
|
listOfColumns(available_columns));
|
2020-06-17 14:32:25 +00:00
|
|
|
|
2021-08-23 13:08:23 +00:00
|
|
|
auto const mappedType = it->getMapped();
|
|
|
|
if (!column.type->equals(*mappedType) && !isEnumSubset(mappedType, column.type))
|
2020-06-17 14:32:25 +00:00
|
|
|
throw Exception(
|
2021-08-15 10:32:56 +00:00
|
|
|
ErrorCodes::TYPE_MISMATCH,
|
|
|
|
"Type mismatch for column {}. Column has type {}, got type {}",
|
|
|
|
column.name,
|
2021-08-23 13:08:23 +00:00
|
|
|
mappedType->getName(),
|
2021-08-15 10:32:56 +00:00
|
|
|
column.type->getName());
|
2020-06-17 14:32:25 +00:00
|
|
|
|
|
|
|
if (unique_names.end() != unique_names.find(column.name))
|
2021-08-15 10:32:56 +00:00
|
|
|
throw Exception(ErrorCodes::COLUMN_QUERIED_MORE_THAN_ONCE,
|
|
|
|
"Column {} queried more than once",
|
|
|
|
column.name);
|
|
|
|
|
2020-06-17 14:32:25 +00:00
|
|
|
unique_names.insert(column.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StorageInMemoryMetadata::check(const NamesAndTypesList & provided_columns, const Names & column_names) const
|
|
|
|
{
|
|
|
|
const NamesAndTypesList & available_columns = getColumns().getAllPhysical();
|
|
|
|
const auto available_columns_map = getColumnsMap(available_columns);
|
|
|
|
const auto & provided_columns_map = getColumnsMap(provided_columns);
|
|
|
|
|
|
|
|
if (column_names.empty())
|
|
|
|
throw Exception(
|
|
|
|
"Empty list of columns queried. There are columns: " + listOfColumns(available_columns),
|
|
|
|
ErrorCodes::EMPTY_LIST_OF_COLUMNS_QUERIED);
|
|
|
|
|
2021-08-15 10:32:56 +00:00
|
|
|
UniqueStrings unique_names;
|
|
|
|
|
2020-06-17 14:32:25 +00:00
|
|
|
for (const String & name : column_names)
|
|
|
|
{
|
2021-08-15 10:32:56 +00:00
|
|
|
const auto * it = provided_columns_map.find(name);
|
2020-06-17 14:32:25 +00:00
|
|
|
if (provided_columns_map.end() == it)
|
|
|
|
continue;
|
|
|
|
|
2021-08-15 10:32:56 +00:00
|
|
|
const auto * jt = available_columns_map.find(name);
|
2020-06-17 14:32:25 +00:00
|
|
|
if (available_columns_map.end() == jt)
|
|
|
|
throw Exception(
|
2021-08-15 10:32:56 +00:00
|
|
|
ErrorCodes::NO_SUCH_COLUMN_IN_TABLE,
|
|
|
|
"There is no column with name {}. There are columns: {}",
|
|
|
|
name,
|
|
|
|
listOfColumns(available_columns));
|
2020-06-17 14:32:25 +00:00
|
|
|
|
2021-08-15 10:32:56 +00:00
|
|
|
const auto & provided_column_type = *it->getMapped();
|
|
|
|
const auto & available_column_type = *jt->getMapped();
|
|
|
|
|
|
|
|
if (!provided_column_type.equals(available_column_type))
|
2020-06-17 14:32:25 +00:00
|
|
|
throw Exception(
|
2021-08-15 10:32:56 +00:00
|
|
|
ErrorCodes::TYPE_MISMATCH,
|
|
|
|
"Type mismatch for column {}. Column has type {}, got type {}",
|
|
|
|
name,
|
|
|
|
provided_column_type.getName(),
|
|
|
|
available_column_type.getName());
|
2020-06-17 14:32:25 +00:00
|
|
|
|
|
|
|
if (unique_names.end() != unique_names.find(name))
|
2021-08-15 10:32:56 +00:00
|
|
|
throw Exception(ErrorCodes::COLUMN_QUERIED_MORE_THAN_ONCE,
|
|
|
|
"Column {} queried more than once",
|
|
|
|
name);
|
|
|
|
|
2020-06-17 14:32:25 +00:00
|
|
|
unique_names.insert(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StorageInMemoryMetadata::check(const Block & block, bool need_all) const
|
|
|
|
{
|
|
|
|
const NamesAndTypesList & available_columns = getColumns().getAllPhysical();
|
|
|
|
const auto columns_map = getColumnsMap(available_columns);
|
|
|
|
|
|
|
|
NameSet names_in_block;
|
|
|
|
|
|
|
|
block.checkNumberOfRows();
|
|
|
|
|
|
|
|
for (const auto & column : block)
|
|
|
|
{
|
|
|
|
if (names_in_block.count(column.name))
|
|
|
|
throw Exception("Duplicate column " + column.name + " in block", ErrorCodes::DUPLICATE_COLUMN);
|
|
|
|
|
|
|
|
names_in_block.insert(column.name);
|
|
|
|
|
2021-08-15 10:32:56 +00:00
|
|
|
const auto * it = columns_map.find(column.name);
|
2020-06-17 14:32:25 +00:00
|
|
|
if (columns_map.end() == it)
|
|
|
|
throw Exception(
|
2021-08-15 10:32:56 +00:00
|
|
|
ErrorCodes::NO_SUCH_COLUMN_IN_TABLE,
|
|
|
|
"There is no column with name {}. There are columns: {}",
|
|
|
|
column.name,
|
|
|
|
listOfColumns(available_columns));
|
2020-06-17 14:32:25 +00:00
|
|
|
|
2021-08-15 10:32:56 +00:00
|
|
|
if (!column.type->equals(*it->getMapped()))
|
2020-06-17 14:32:25 +00:00
|
|
|
throw Exception(
|
2021-08-15 10:32:56 +00:00
|
|
|
ErrorCodes::TYPE_MISMATCH,
|
|
|
|
"Type mismatch for column {}. Column has type {}, got type {}",
|
|
|
|
column.name,
|
|
|
|
it->getMapped()->getName(),
|
|
|
|
column.type->getName());
|
2020-06-17 14:32:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (need_all && names_in_block.size() < columns_map.size())
|
|
|
|
{
|
|
|
|
for (const auto & available_column : available_columns)
|
|
|
|
{
|
|
|
|
if (!names_in_block.count(available_column.name))
|
|
|
|
throw Exception("Expected column " + available_column.name, ErrorCodes::NOT_FOUND_COLUMN_IN_BLOCK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-30 21:25:37 +00:00
|
|
|
}
|