2018-06-07 13:28:39 +00:00
|
|
|
#include <Storages/System/StorageSystemMutations.h>
|
|
|
|
#include <DataTypes/DataTypeString.h>
|
|
|
|
#include <DataTypes/DataTypesNumber.h>
|
|
|
|
#include <DataTypes/DataTypeDateTime.h>
|
|
|
|
#include <DataTypes/DataTypeArray.h>
|
|
|
|
#include <DataStreams/OneBlockInputStream.h>
|
2019-05-03 02:00:57 +00:00
|
|
|
#include <Storages/MergeTree/MergeTreeData.h>
|
|
|
|
#include <Storages/MergeTree/MergeTreeMutationStatus.h>
|
2018-06-07 13:28:39 +00:00
|
|
|
#include <Storages/VirtualColumnUtils.h>
|
2020-03-07 17:37:38 +00:00
|
|
|
#include <Access/ContextAccess.h>
|
2018-06-07 13:28:39 +00:00
|
|
|
#include <Databases/IDatabase.h>
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2018-07-24 14:28:56 +00:00
|
|
|
|
|
|
|
NamesAndTypesList StorageSystemMutations::getNamesAndTypes()
|
2018-06-07 13:28:39 +00:00
|
|
|
{
|
2018-07-24 14:28:56 +00:00
|
|
|
return {
|
2018-11-26 00:56:50 +00:00
|
|
|
{ "database", std::make_shared<DataTypeString>() },
|
|
|
|
{ "table", std::make_shared<DataTypeString>() },
|
|
|
|
{ "mutation_id", std::make_shared<DataTypeString>() },
|
|
|
|
{ "command", std::make_shared<DataTypeString>() },
|
|
|
|
{ "create_time", std::make_shared<DataTypeDateTime>() },
|
|
|
|
{ "block_numbers.partition_id", std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>()) },
|
|
|
|
{ "block_numbers.number", std::make_shared<DataTypeArray>(std::make_shared<DataTypeInt64>()) },
|
2019-12-12 16:24:03 +00:00
|
|
|
{ "parts_to_do_names", std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>()) },
|
2018-11-26 00:56:50 +00:00
|
|
|
{ "parts_to_do", std::make_shared<DataTypeInt64>() },
|
|
|
|
{ "is_done", std::make_shared<DataTypeUInt8>() },
|
2019-01-10 17:06:27 +00:00
|
|
|
{ "latest_failed_part", std::make_shared<DataTypeString>() },
|
|
|
|
{ "latest_fail_time", std::make_shared<DataTypeDateTime>() },
|
|
|
|
{ "latest_fail_reason", std::make_shared<DataTypeString>() },
|
2018-07-24 14:28:56 +00:00
|
|
|
};
|
2018-06-07 13:28:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-24 14:28:56 +00:00
|
|
|
void StorageSystemMutations::fillData(MutableColumns & res_columns, const Context & context, const SelectQueryInfo & query_info) const
|
2018-06-07 13:28:39 +00:00
|
|
|
{
|
2020-03-07 17:37:38 +00:00
|
|
|
const auto access = context.getAccess();
|
|
|
|
const bool check_access_for_databases = !access->isGranted(AccessType::SHOW_TABLES);
|
2020-01-24 16:20:36 +00:00
|
|
|
|
2018-07-06 19:04:54 +00:00
|
|
|
/// Collect a set of *MergeTree tables.
|
|
|
|
std::map<String, std::map<String, StoragePtr>> merge_tree_tables;
|
2020-02-10 13:10:17 +00:00
|
|
|
for (const auto & db : DatabaseCatalog::instance().getDatabases())
|
2019-10-01 12:44:17 +00:00
|
|
|
{
|
|
|
|
/// Lazy database can not contain MergeTree tables
|
|
|
|
if (db.second->getEngineName() == "Lazy")
|
|
|
|
continue;
|
2020-01-24 16:20:36 +00:00
|
|
|
|
2020-03-07 17:37:38 +00:00
|
|
|
const bool check_access_for_tables = check_access_for_databases && !access->isGranted(AccessType::SHOW_TABLES, db.first);
|
2020-01-24 16:20:36 +00:00
|
|
|
|
|
|
|
for (auto iterator = db.second->getTablesIterator(context); iterator->isValid(); iterator->next())
|
|
|
|
{
|
|
|
|
if (!dynamic_cast<const MergeTreeData *>(iterator->table().get()))
|
|
|
|
continue;
|
|
|
|
|
2020-03-07 17:37:38 +00:00
|
|
|
if (check_access_for_tables && !access->isGranted(AccessType::SHOW_TABLES, db.first, iterator->name()))
|
2020-01-24 16:20:36 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
merge_tree_tables[db.first][iterator->name()] = iterator->table();
|
|
|
|
}
|
2019-10-01 12:44:17 +00:00
|
|
|
}
|
2018-06-07 13:28:39 +00:00
|
|
|
|
|
|
|
MutableColumnPtr col_database_mut = ColumnString::create();
|
|
|
|
MutableColumnPtr col_table_mut = ColumnString::create();
|
|
|
|
|
2018-07-06 19:04:54 +00:00
|
|
|
for (auto & db : merge_tree_tables)
|
2018-06-07 13:28:39 +00:00
|
|
|
{
|
|
|
|
for (auto & table : db.second)
|
|
|
|
{
|
|
|
|
col_database_mut->insert(db.first);
|
|
|
|
col_table_mut->insert(table.first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ColumnPtr col_database = std::move(col_database_mut);
|
|
|
|
ColumnPtr col_table = std::move(col_table_mut);
|
|
|
|
|
|
|
|
/// Determine what tables are needed by the conditions in the query.
|
|
|
|
{
|
|
|
|
Block filtered_block
|
|
|
|
{
|
|
|
|
{ col_database, std::make_shared<DataTypeString>(), "database" },
|
|
|
|
{ col_table, std::make_shared<DataTypeString>(), "table" },
|
|
|
|
};
|
|
|
|
|
|
|
|
VirtualColumnUtils::filterBlockWithQuery(query_info.query, filtered_block, context);
|
|
|
|
|
|
|
|
if (!filtered_block.rows())
|
2018-07-24 14:28:56 +00:00
|
|
|
return;
|
2018-06-07 13:28:39 +00:00
|
|
|
|
|
|
|
col_database = filtered_block.getByName("database").column;
|
|
|
|
col_table = filtered_block.getByName("table").column;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i_storage = 0; i_storage < col_database->size(); ++i_storage)
|
|
|
|
{
|
|
|
|
auto database = (*col_database)[i_storage].safeGet<String>();
|
|
|
|
auto table = (*col_table)[i_storage].safeGet<String>();
|
|
|
|
|
2018-07-06 19:04:54 +00:00
|
|
|
std::vector<MergeTreeMutationStatus> statuses;
|
|
|
|
{
|
|
|
|
const IStorage * storage = merge_tree_tables[database][table].get();
|
2019-05-03 02:00:57 +00:00
|
|
|
if (const auto * merge_tree = dynamic_cast<const MergeTreeData *>(storage))
|
2018-07-06 19:04:54 +00:00
|
|
|
statuses = merge_tree->getMutationsStatus();
|
|
|
|
}
|
2018-06-07 13:28:39 +00:00
|
|
|
|
2018-07-06 19:04:54 +00:00
|
|
|
for (const MergeTreeMutationStatus & status : statuses)
|
2018-06-07 13:28:39 +00:00
|
|
|
{
|
|
|
|
Array block_partition_ids;
|
|
|
|
block_partition_ids.reserve(status.block_numbers.size());
|
|
|
|
Array block_numbers;
|
|
|
|
block_numbers.reserve(status.block_numbers.size());
|
|
|
|
for (const auto & pair : status.block_numbers)
|
|
|
|
{
|
|
|
|
block_partition_ids.emplace_back(pair.first);
|
|
|
|
block_numbers.emplace_back(pair.second);
|
|
|
|
}
|
2019-12-12 16:24:03 +00:00
|
|
|
Array parts_to_do_names;
|
|
|
|
parts_to_do_names.reserve(status.parts_to_do_names.size());
|
|
|
|
for (const String & part_name : status.parts_to_do_names)
|
|
|
|
parts_to_do_names.emplace_back(part_name);
|
2018-06-07 13:28:39 +00:00
|
|
|
|
|
|
|
size_t col_num = 0;
|
|
|
|
res_columns[col_num++]->insert(database);
|
|
|
|
res_columns[col_num++]->insert(table);
|
|
|
|
|
|
|
|
res_columns[col_num++]->insert(status.id);
|
|
|
|
res_columns[col_num++]->insert(status.command);
|
|
|
|
res_columns[col_num++]->insert(UInt64(status.create_time));
|
|
|
|
res_columns[col_num++]->insert(block_partition_ids);
|
|
|
|
res_columns[col_num++]->insert(block_numbers);
|
2019-12-12 16:24:03 +00:00
|
|
|
res_columns[col_num++]->insert(parts_to_do_names);
|
|
|
|
res_columns[col_num++]->insert(parts_to_do_names.size());
|
2018-10-22 08:54:54 +00:00
|
|
|
res_columns[col_num++]->insert(status.is_done);
|
2019-01-10 17:06:27 +00:00
|
|
|
res_columns[col_num++]->insert(status.latest_failed_part);
|
|
|
|
res_columns[col_num++]->insert(UInt64(status.latest_fail_time));
|
|
|
|
res_columns[col_num++]->insert(status.latest_fail_reason);
|
2018-06-07 13:28:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|