2017-05-31 11:46:22 +00:00
|
|
|
#include <Common/escapeForFileName.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Columns/ColumnString.h>
|
|
|
|
#include <DataTypes/DataTypeString.h>
|
|
|
|
#include <DataTypes/DataTypesNumber.h>
|
|
|
|
#include <DataTypes/DataTypeDateTime.h>
|
|
|
|
#include <DataTypes/DataTypeDate.h>
|
|
|
|
#include <DataStreams/OneBlockInputStream.h>
|
|
|
|
#include <Storages/System/StorageSystemParts.h>
|
|
|
|
#include <Storages/StorageMergeTree.h>
|
|
|
|
#include <Storages/StorageReplicatedMergeTree.h>
|
|
|
|
#include <Common/VirtualColumnUtils.h>
|
|
|
|
#include <Databases/IDatabase.h>
|
2014-07-29 14:05:15 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
|
2015-01-21 03:56:28 +00:00
|
|
|
StorageSystemParts::StorageSystemParts(const std::string & name_)
|
2017-04-01 07:20:54 +00:00
|
|
|
: name(name_),
|
|
|
|
columns
|
|
|
|
{
|
2017-04-28 14:20:31 +00:00
|
|
|
{"partition", std::make_shared<DataTypeString>()},
|
|
|
|
{"name", std::make_shared<DataTypeString>()},
|
|
|
|
{"active", std::make_shared<DataTypeUInt8>()},
|
|
|
|
{"marks", std::make_shared<DataTypeUInt64>()},
|
2017-05-30 14:03:41 +00:00
|
|
|
{"marks_size", std::make_shared<DataTypeUInt64>()},
|
2017-04-28 14:20:31 +00:00
|
|
|
{"rows", std::make_shared<DataTypeUInt64>()},
|
|
|
|
{"bytes", std::make_shared<DataTypeUInt64>()},
|
|
|
|
{"modification_time", std::make_shared<DataTypeDateTime>()},
|
|
|
|
{"remove_time", std::make_shared<DataTypeDateTime>()},
|
2017-04-01 07:20:54 +00:00
|
|
|
{"refcount", std::make_shared<DataTypeUInt32>()},
|
|
|
|
{"min_date", std::make_shared<DataTypeDate>()},
|
|
|
|
{"max_date", std::make_shared<DataTypeDate>()},
|
|
|
|
{"min_block_number", std::make_shared<DataTypeInt64>()},
|
|
|
|
{"max_block_number", std::make_shared<DataTypeInt64>()},
|
2017-04-28 14:20:31 +00:00
|
|
|
{"level", std::make_shared<DataTypeUInt32>()},
|
2017-04-01 07:20:54 +00:00
|
|
|
{"primary_key_bytes_in_memory", std::make_shared<DataTypeUInt64>()},
|
|
|
|
{"primary_key_bytes_in_memory_allocated", std::make_shared<DataTypeUInt64>()},
|
|
|
|
|
2017-04-28 14:20:31 +00:00
|
|
|
{"database", std::make_shared<DataTypeString>()},
|
|
|
|
{"table", std::make_shared<DataTypeString>()},
|
|
|
|
{"engine", std::make_shared<DataTypeString>()},
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2014-07-29 14:05:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BlockInputStreams StorageSystemParts::read(
|
2017-04-01 07:20:54 +00:00
|
|
|
const Names & column_names,
|
2017-07-15 03:48:36 +00:00
|
|
|
const SelectQueryInfo & query_info,
|
2017-04-01 07:20:54 +00:00
|
|
|
const Context & context,
|
|
|
|
QueryProcessingStage::Enum & processed_stage,
|
|
|
|
const size_t max_block_size,
|
2017-06-02 15:54:39 +00:00
|
|
|
const unsigned num_streams)
|
2014-07-29 14:05:15 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
check(column_names);
|
|
|
|
processed_stage = QueryProcessingStage::FetchColumns;
|
|
|
|
|
|
|
|
/// Will apply WHERE to subset of columns and then add more columns.
|
|
|
|
/// This is kind of complicated, but we use WHERE to do less work.
|
|
|
|
|
|
|
|
Block block_to_filter;
|
|
|
|
|
|
|
|
std::map<std::pair<String, String>, StoragePtr> storages;
|
|
|
|
|
|
|
|
{
|
|
|
|
Databases databases = context.getDatabases();
|
|
|
|
|
|
|
|
/// Add column 'database'.
|
|
|
|
ColumnPtr database_column = std::make_shared<ColumnString>();
|
|
|
|
for (const auto & database : databases)
|
|
|
|
database_column->insert(database.first);
|
|
|
|
block_to_filter.insert(ColumnWithTypeAndName(database_column, std::make_shared<DataTypeString>(), "database"));
|
|
|
|
|
|
|
|
/// Filter block_to_filter with column 'database'.
|
2017-07-15 03:48:36 +00:00
|
|
|
VirtualColumnUtils::filterBlockWithQuery(query_info.query, block_to_filter, context);
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
if (!block_to_filter.rows())
|
|
|
|
return BlockInputStreams();
|
|
|
|
|
2017-05-24 21:38:56 +00:00
|
|
|
/// Add columns 'table', 'engine', 'active'
|
2017-04-01 07:20:54 +00:00
|
|
|
database_column = block_to_filter.getByName("database").column;
|
|
|
|
size_t rows = database_column->size();
|
|
|
|
|
|
|
|
IColumn::Offsets_t offsets(rows);
|
|
|
|
ColumnPtr table_column = std::make_shared<ColumnString>();
|
|
|
|
ColumnPtr engine_column = std::make_shared<ColumnString>();
|
|
|
|
ColumnPtr active_column = std::make_shared<ColumnUInt8>();
|
|
|
|
|
|
|
|
for (size_t i = 0; i < rows; ++i)
|
|
|
|
{
|
|
|
|
String database_name = (*database_column)[i].get<String>();
|
|
|
|
const DatabasePtr database = databases.at(database_name);
|
|
|
|
|
|
|
|
offsets[i] = i ? offsets[i - 1] : 0;
|
2017-09-11 12:39:01 +00:00
|
|
|
for (auto iterator = database->getIterator(context); iterator->isValid(); iterator->next())
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
String table_name = iterator->name();
|
|
|
|
StoragePtr storage = iterator->table();
|
|
|
|
String engine_name = storage->getName();
|
|
|
|
|
|
|
|
if (!dynamic_cast<StorageMergeTree *>(&*storage) &&
|
|
|
|
!dynamic_cast<StorageReplicatedMergeTree *>(&*storage))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
storages[std::make_pair(database_name, iterator->name())] = storage;
|
|
|
|
|
2017-05-24 21:38:56 +00:00
|
|
|
/// Add all combinations of flag 'active'.
|
|
|
|
for (UInt64 active : {0, 1})
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-05-24 21:38:56 +00:00
|
|
|
table_column->insert(table_name);
|
|
|
|
engine_column->insert(engine_name);
|
|
|
|
active_column->insert(active);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
2017-05-24 21:38:56 +00:00
|
|
|
offsets[i] += 2;
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < block_to_filter.columns(); ++i)
|
|
|
|
{
|
|
|
|
ColumnPtr & column = block_to_filter.safeGetByPosition(i).column;
|
|
|
|
column = column->replicate(offsets);
|
|
|
|
}
|
|
|
|
|
|
|
|
block_to_filter.insert(ColumnWithTypeAndName(table_column, std::make_shared<DataTypeString>(), "table"));
|
|
|
|
block_to_filter.insert(ColumnWithTypeAndName(engine_column, std::make_shared<DataTypeString>(), "engine"));
|
|
|
|
block_to_filter.insert(ColumnWithTypeAndName(active_column, std::make_shared<DataTypeUInt8>(), "active"));
|
|
|
|
}
|
|
|
|
|
2017-05-24 21:38:56 +00:00
|
|
|
/// Filter block_to_filter with columns 'database', 'table', 'engine', 'active'.
|
2017-07-15 03:48:36 +00:00
|
|
|
VirtualColumnUtils::filterBlockWithQuery(query_info.query, block_to_filter, context);
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
/// If all was filtered out.
|
|
|
|
if (!block_to_filter.rows())
|
|
|
|
return {};
|
|
|
|
|
|
|
|
ColumnPtr filtered_database_column = block_to_filter.getByName("database").column;
|
|
|
|
ColumnPtr filtered_table_column = block_to_filter.getByName("table").column;
|
|
|
|
ColumnPtr filtered_active_column = block_to_filter.getByName("active").column;
|
|
|
|
|
|
|
|
/// Finally, create the result.
|
|
|
|
|
|
|
|
Block block = getSampleBlock();
|
|
|
|
|
|
|
|
for (size_t i = 0; i < filtered_database_column->size();)
|
|
|
|
{
|
|
|
|
String database = (*filtered_database_column)[i].get<String>();
|
|
|
|
String table = (*filtered_table_column)[i].get<String>();
|
|
|
|
|
2017-05-24 21:38:56 +00:00
|
|
|
/// What 'active' value we need.
|
|
|
|
bool need[2]{}; /// [active]
|
2017-04-01 07:20:54 +00:00
|
|
|
for (; i < filtered_database_column->size() &&
|
|
|
|
(*filtered_database_column)[i].get<String>() == database &&
|
|
|
|
(*filtered_table_column)[i].get<String>() == table; ++i)
|
|
|
|
{
|
|
|
|
bool active = !!(*filtered_active_column)[i].get<UInt64>();
|
2017-05-24 21:38:56 +00:00
|
|
|
need[active] = true;
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
StoragePtr storage = storages.at(std::make_pair(database, table));
|
|
|
|
TableStructureReadLockPtr table_lock;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2017-09-01 15:05:23 +00:00
|
|
|
table_lock = storage->lockStructure(false, __PRETTY_FUNCTION__); /// For table not to be dropped.
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
catch (const Exception & e)
|
|
|
|
{
|
|
|
|
/** There are case when IStorage::drop was called,
|
|
|
|
* but we still own the object.
|
|
|
|
* Then table will throw exception at attempt to lock it.
|
|
|
|
* Just skip the table.
|
|
|
|
*/
|
|
|
|
if (e.code() == ErrorCodes::TABLE_IS_DROPPED)
|
|
|
|
continue;
|
|
|
|
else
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
|
|
|
|
String engine = storage->getName();
|
|
|
|
|
2017-05-24 21:38:56 +00:00
|
|
|
MergeTreeData * data = nullptr;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
if (StorageMergeTree * merge_tree = dynamic_cast<StorageMergeTree *>(&*storage))
|
|
|
|
{
|
2017-05-24 21:38:56 +00:00
|
|
|
data = &merge_tree->getData();
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
else if (StorageReplicatedMergeTree * replicated_merge_tree = dynamic_cast<StorageReplicatedMergeTree *>(&*storage))
|
|
|
|
{
|
2017-05-24 21:38:56 +00:00
|
|
|
data = &replicated_merge_tree->getData();
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
2017-05-24 21:38:56 +00:00
|
|
|
MergeTreeData::DataParts active_parts = data->getDataParts();
|
|
|
|
MergeTreeData::DataParts all_parts;
|
|
|
|
if (need[0])
|
|
|
|
all_parts = data->getAllDataParts();
|
|
|
|
else
|
|
|
|
all_parts = active_parts;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-05-24 21:38:56 +00:00
|
|
|
/// Finally, we'll go through the list of parts.
|
|
|
|
for (const MergeTreeData::DataPartPtr & part : all_parts)
|
|
|
|
{
|
|
|
|
size_t i = 0;
|
2017-09-05 12:12:55 +00:00
|
|
|
{
|
|
|
|
WriteBufferFromOwnString out;
|
|
|
|
part->partition.serializeTextQuoted(*data, out);
|
|
|
|
block.getByPosition(i++).column->insert(out.str());
|
|
|
|
}
|
2017-05-24 21:38:56 +00:00
|
|
|
block.getByPosition(i++).column->insert(part->name);
|
|
|
|
block.getByPosition(i++).column->insert(static_cast<UInt64>(active_parts.count(part)));
|
2017-09-01 17:21:03 +00:00
|
|
|
block.getByPosition(i++).column->insert(static_cast<UInt64>(part->size));
|
2017-05-31 11:46:22 +00:00
|
|
|
|
|
|
|
size_t marks_size = 0;
|
|
|
|
for (const NameAndTypePair & it : part->columns)
|
|
|
|
{
|
|
|
|
String name = escapeForFileName(it.name);
|
|
|
|
auto checksum = part->checksums.files.find(name + ".mrk");
|
|
|
|
if (checksum != part->checksums.files.end())
|
|
|
|
marks_size += checksum->second.file_size;
|
|
|
|
}
|
2017-09-01 17:21:03 +00:00
|
|
|
block.getByPosition(i++).column->insert(static_cast<UInt64>(marks_size));
|
2017-05-31 11:46:22 +00:00
|
|
|
|
2017-09-01 17:21:03 +00:00
|
|
|
block.getByPosition(i++).column->insert(static_cast<UInt64>(part->getExactSizeRows()));
|
|
|
|
block.getByPosition(i++).column->insert(static_cast<UInt64>(part->size_in_bytes));
|
|
|
|
block.getByPosition(i++).column->insert(static_cast<UInt64>(part->modification_time));
|
|
|
|
block.getByPosition(i++).column->insert(static_cast<UInt64>(part->remove_time));
|
2017-05-24 21:38:56 +00:00
|
|
|
|
|
|
|
/// For convenience, in returned refcount, don't add references that was due to local variables in this method: all_parts, active_parts.
|
2017-09-01 17:21:03 +00:00
|
|
|
block.getByPosition(i++).column->insert(static_cast<UInt64>(part.use_count() - (active_parts.count(part) ? 2 : 1)));
|
2017-05-24 21:38:56 +00:00
|
|
|
|
2017-08-21 15:35:29 +00:00
|
|
|
block.getByPosition(i++).column->insert(static_cast<UInt64>(part->getMinDate()));
|
|
|
|
block.getByPosition(i++).column->insert(static_cast<UInt64>(part->getMaxDate()));
|
2017-08-14 18:16:11 +00:00
|
|
|
block.getByPosition(i++).column->insert(part->info.min_block);
|
|
|
|
block.getByPosition(i++).column->insert(part->info.max_block);
|
|
|
|
block.getByPosition(i++).column->insert(static_cast<UInt64>(part->info.level));
|
2017-09-01 17:21:03 +00:00
|
|
|
block.getByPosition(i++).column->insert(static_cast<UInt64>(part->getIndexSizeInBytes()));
|
|
|
|
block.getByPosition(i++).column->insert(static_cast<UInt64>(part->getIndexSizeInAllocatedBytes()));
|
2017-05-24 21:38:56 +00:00
|
|
|
|
|
|
|
block.getByPosition(i++).column->insert(database);
|
|
|
|
block.getByPosition(i++).column->insert(table);
|
|
|
|
block.getByPosition(i++).column->insert(engine);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return BlockInputStreams(1, std::make_shared<OneBlockInputStream>(block));
|
2014-07-29 14:05:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|