2017-04-01 09:19:00 +00:00
|
|
|
#include <Storages/System/StorageSystemColumns.h>
|
|
|
|
#include <Storages/MergeTree/MergeTreeData.h>
|
|
|
|
#include <Storages/StorageMergeTree.h>
|
|
|
|
#include <Storages/StorageReplicatedMergeTree.h>
|
|
|
|
#include <Columns/ColumnsNumber.h>
|
|
|
|
#include <Columns/ColumnString.h>
|
|
|
|
#include <DataTypes/DataTypeString.h>
|
|
|
|
#include <DataTypes/DataTypesNumber.h>
|
|
|
|
#include <DataStreams/OneBlockInputStream.h>
|
2017-11-20 05:22:54 +00:00
|
|
|
#include <Storages/VirtualColumnUtils.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Parsers/queryToString.h>
|
|
|
|
#include <Databases/IDatabase.h>
|
2016-03-19 01:18:49 +00:00
|
|
|
|
2015-04-24 12:26:23 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2018-07-24 18:46:23 +00:00
|
|
|
NamesAndTypesList StorageSystemColumns::getNamesAndTypes()
|
|
|
|
{
|
2018-07-24 14:28:56 +00:00
|
|
|
return {
|
2017-04-01 07:20:54 +00:00
|
|
|
{ "database", std::make_shared<DataTypeString>() },
|
|
|
|
{ "table", std::make_shared<DataTypeString>() },
|
|
|
|
{ "name", std::make_shared<DataTypeString>() },
|
|
|
|
{ "type", std::make_shared<DataTypeString>() },
|
2017-05-24 19:54:25 +00:00
|
|
|
{ "default_kind", std::make_shared<DataTypeString>() },
|
2017-04-01 07:20:54 +00:00
|
|
|
{ "default_expression", std::make_shared<DataTypeString>() },
|
2017-05-24 19:54:25 +00:00
|
|
|
{ "data_compressed_bytes", std::make_shared<DataTypeUInt64>() },
|
2017-04-01 07:20:54 +00:00
|
|
|
{ "data_uncompressed_bytes", std::make_shared<DataTypeUInt64>() },
|
|
|
|
{ "marks_bytes", std::make_shared<DataTypeUInt64>() },
|
2018-07-24 14:28:56 +00:00
|
|
|
};
|
2015-04-24 12:26:23 +00:00
|
|
|
}
|
|
|
|
|
2018-07-24 14:28:56 +00:00
|
|
|
void StorageSystemColumns::fillData(MutableColumns & res_columns, const Context & context, const SelectQueryInfo & query_info) const
|
2015-04-24 12:26:23 +00:00
|
|
|
{
|
2017-12-16 00:49:03 +00:00
|
|
|
Block block_to_filter;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
std::map<std::pair<std::string, std::string>, StoragePtr> storages;
|
|
|
|
|
|
|
|
{
|
|
|
|
Databases databases = context.getDatabases();
|
|
|
|
|
|
|
|
/// Add `database` column.
|
2017-12-16 00:49:03 +00:00
|
|
|
MutableColumnPtr database_column_mut = ColumnString::create();
|
2017-04-01 07:20:54 +00:00
|
|
|
for (const auto & database : databases)
|
2018-08-13 09:11:58 +00:00
|
|
|
{
|
2018-08-14 02:18:57 +00:00
|
|
|
if (context.hasDatabaseAccessRights(database.first))
|
2018-08-13 09:11:58 +00:00
|
|
|
database_column_mut->insert(database.first);
|
|
|
|
}
|
|
|
|
|
2017-12-16 00:49:03 +00:00
|
|
|
block_to_filter.insert(ColumnWithTypeAndName(std::move(database_column_mut), std::make_shared<DataTypeString>(), "database"));
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
/// Filter block with `database` column.
|
2017-12-16 00:49:03 +00:00
|
|
|
VirtualColumnUtils::filterBlockWithQuery(query_info.query, block_to_filter, context);
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-12-16 00:49:03 +00:00
|
|
|
if (!block_to_filter.rows())
|
2018-07-24 14:28:56 +00:00
|
|
|
return;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-12-16 00:49:03 +00:00
|
|
|
ColumnPtr database_column = block_to_filter.getByName("database").column;
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t rows = database_column->size();
|
|
|
|
|
|
|
|
/// Add `table` column.
|
2017-12-16 00:49:03 +00:00
|
|
|
MutableColumnPtr table_column_mut = ColumnString::create();
|
2017-12-15 21:32:25 +00:00
|
|
|
IColumn::Offsets offsets(rows);
|
2017-04-01 07:20:54 +00:00
|
|
|
for (size_t i = 0; i < rows; ++i)
|
|
|
|
{
|
|
|
|
const std::string database_name = (*database_column)[i].get<std::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
|
|
|
{
|
|
|
|
const String & table_name = iterator->name();
|
|
|
|
storages.emplace(std::piecewise_construct,
|
|
|
|
std::forward_as_tuple(database_name, table_name),
|
|
|
|
std::forward_as_tuple(iterator->table()));
|
2017-12-16 00:49:03 +00:00
|
|
|
table_column_mut->insert(table_name);
|
2017-04-01 07:20:54 +00:00
|
|
|
offsets[i] += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-16 00:49:03 +00:00
|
|
|
for (size_t i = 0; i < block_to_filter.columns(); ++i)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-12-16 00:49:03 +00:00
|
|
|
ColumnPtr & column = block_to_filter.safeGetByPosition(i).column;
|
2017-04-01 07:20:54 +00:00
|
|
|
column = column->replicate(offsets);
|
|
|
|
}
|
|
|
|
|
2017-12-16 00:49:03 +00:00
|
|
|
block_to_filter.insert(ColumnWithTypeAndName(std::move(table_column_mut), std::make_shared<DataTypeString>(), "table"));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Filter block with `database` and `table` columns.
|
2017-12-16 00:49:03 +00:00
|
|
|
VirtualColumnUtils::filterBlockWithQuery(query_info.query, block_to_filter, context);
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-12-16 00:49:03 +00:00
|
|
|
if (!block_to_filter.rows())
|
2018-07-24 14:28:56 +00:00
|
|
|
return;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-12-16 00:49:03 +00:00
|
|
|
ColumnPtr filtered_database_column = block_to_filter.getByName("database").column;
|
|
|
|
ColumnPtr filtered_table_column = block_to_filter.getByName("table").column;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
/// We compose the result.
|
|
|
|
size_t rows = filtered_database_column->size();
|
2018-08-10 04:02:56 +00:00
|
|
|
for (size_t row_no = 0; row_no < rows; ++row_no)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2018-08-10 04:02:56 +00:00
|
|
|
const std::string database_name = (*filtered_database_column)[row_no].get<std::string>();
|
|
|
|
const std::string table_name = (*filtered_table_column)[row_no].get<std::string>();
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-12-25 21:57:29 +00:00
|
|
|
NamesAndTypesList columns;
|
2017-04-01 07:20:54 +00:00
|
|
|
ColumnDefaults column_defaults;
|
2018-03-26 14:18:04 +00:00
|
|
|
MergeTreeData::ColumnSizeByName column_sizes;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
StoragePtr storage = storages.at(std::make_pair(database_name, table_name));
|
|
|
|
TableStructureReadLockPtr table_lock;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2017-09-01 15:05:23 +00:00
|
|
|
table_lock = storage->lockStructure(false, __PRETTY_FUNCTION__);
|
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;
|
|
|
|
}
|
|
|
|
|
2018-03-13 14:18:11 +00:00
|
|
|
columns = storage->getColumns().getAll();
|
|
|
|
column_defaults = storage->getColumns().defaults;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
/** Info about sizes of columns for tables of MergeTree family.
|
|
|
|
* NOTE: It is possible to add getter for this info to IStorage interface.
|
|
|
|
*/
|
2018-08-10 04:02:56 +00:00
|
|
|
if (auto storage_concrete_plain = dynamic_cast<StorageMergeTree *>(storage.get()))
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2018-08-10 04:02:56 +00:00
|
|
|
column_sizes = storage_concrete_plain->getData().getColumnSizes();
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2018-08-10 04:02:56 +00:00
|
|
|
else if (auto storage_concrete_replicated = dynamic_cast<StorageReplicatedMergeTree *>(storage.get()))
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2018-08-10 04:02:56 +00:00
|
|
|
column_sizes = storage_concrete_replicated->getData().getColumnSizes();
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto & column : columns)
|
|
|
|
{
|
2017-12-16 00:49:03 +00:00
|
|
|
size_t i = 0;
|
|
|
|
|
|
|
|
res_columns[i++]->insert(database_name);
|
|
|
|
res_columns[i++]->insert(table_name);
|
|
|
|
res_columns[i++]->insert(column.name);
|
|
|
|
res_columns[i++]->insert(column.type->getName());
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
const auto it = column_defaults.find(column.name);
|
|
|
|
if (it == std::end(column_defaults))
|
|
|
|
{
|
2017-12-16 00:49:03 +00:00
|
|
|
res_columns[i++]->insertDefault();
|
|
|
|
res_columns[i++]->insertDefault();
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-03-12 13:47:01 +00:00
|
|
|
res_columns[i++]->insert(toString(it->second.kind));
|
2017-12-16 00:49:03 +00:00
|
|
|
res_columns[i++]->insert(queryToString(it->second.expression));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
const auto it = column_sizes.find(column.name);
|
|
|
|
if (it == std::end(column_sizes))
|
|
|
|
{
|
2017-12-16 00:49:03 +00:00
|
|
|
res_columns[i++]->insertDefault();
|
|
|
|
res_columns[i++]->insertDefault();
|
|
|
|
res_columns[i++]->insertDefault();
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-12-16 00:49:03 +00:00
|
|
|
res_columns[i++]->insert(static_cast<UInt64>(it->second.data_compressed));
|
|
|
|
res_columns[i++]->insert(static_cast<UInt64>(it->second.data_uncompressed));
|
|
|
|
res_columns[i++]->insert(static_cast<UInt64>(it->second.marks));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-24 12:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|