diff --git a/src/Storages/System/IStorageSystemOneBlock.h b/src/Storages/System/IStorageSystemOneBlock.h index 36e92d5a1f4..fdc966130ad 100644 --- a/src/Storages/System/IStorageSystemOneBlock.h +++ b/src/Storages/System/IStorageSystemOneBlock.h @@ -12,7 +12,16 @@ namespace DB class Context; -/** Base class for system tables whose all columns have String type. +/** IStorageSystemOneBlock is base class for system tables whose all columns can be synchronously fetched. + * + * Client class need to provide static method static NamesAndTypesList getNamesAndTypes() that will return list of column names and + * their types. IStorageSystemOneBlock during read will create result columns in same order as result of getNamesAndTypes + * and pass it with fillData method. + * + * Client also must override fillData and fill result columns. + * + * If subclass want to support virtual columns, it should override getVirtuals method of IStorage interface. + * IStorageSystemOneBlock will add virtuals columns at the end of result columns of fillData method. */ template class IStorageSystemOneBlock : public IStorage @@ -41,9 +50,10 @@ public: size_t /*max_block_size*/, unsigned /*num_streams*/) override { - metadata_snapshot->check(column_names, getVirtuals(), getStorageID()); + auto virtuals_names_and_types = getVirtuals(); + metadata_snapshot->check(column_names, virtuals_names_and_types, getStorageID()); - Block sample_block = metadata_snapshot->getSampleBlock(); + Block sample_block = metadata_snapshot->getSampleBlockWithVirtuals(virtuals_names_and_types); MutableColumns res_columns = sample_block.cloneEmptyColumns(); fillData(res_columns, context, query_info); diff --git a/src/Storages/System/StorageSystemDictionaries.cpp b/src/Storages/System/StorageSystemDictionaries.cpp index a362e6a44e3..c76dba9df58 100644 --- a/src/Storages/System/StorageSystemDictionaries.cpp +++ b/src/Storages/System/StorageSystemDictionaries.cpp @@ -50,6 +50,13 @@ NamesAndTypesList StorageSystemDictionaries::getNamesAndTypes() }; } +NamesAndTypesList StorageSystemDictionaries::getVirtuals() const +{ + return { + {"key", std::make_shared()} + }; +} + void StorageSystemDictionaries::fillData(MutableColumns & res_columns, ContextPtr context, const SelectQueryInfo & /*query_info*/) const { const auto access = context->getAccess(); @@ -128,6 +135,9 @@ void StorageSystemDictionaries::fillData(MutableColumns & res_columns, ContextPt else res_columns[i++]->insertDefault(); + /// Start fill virtual columns + + res_columns[i++]->insert(dictionary_structure.getKeyDescription()); } } diff --git a/src/Storages/System/StorageSystemDictionaries.h b/src/Storages/System/StorageSystemDictionaries.h index 63b33adaaff..aa65a946127 100644 --- a/src/Storages/System/StorageSystemDictionaries.h +++ b/src/Storages/System/StorageSystemDictionaries.h @@ -18,6 +18,8 @@ public: static NamesAndTypesList getNamesAndTypes(); + NamesAndTypesList getVirtuals() const override; + protected: using IStorageSystemOneBlock::IStorageSystemOneBlock; diff --git a/tests/queries/0_stateless/01838_system_dictionaries_virtual_key_column.reference b/tests/queries/0_stateless/01838_system_dictionaries_virtual_key_column.reference new file mode 100644 index 00000000000..f0543d9221e --- /dev/null +++ b/tests/queries/0_stateless/01838_system_dictionaries_virtual_key_column.reference @@ -0,0 +1,4 @@ +simple key +example_simple_key_dictionary UInt64 +complex key +example_complex_key_dictionary (UInt64, String) diff --git a/tests/queries/0_stateless/01838_system_dictionaries_virtual_key_column.sql b/tests/queries/0_stateless/01838_system_dictionaries_virtual_key_column.sql new file mode 100644 index 00000000000..97d96f643cf --- /dev/null +++ b/tests/queries/0_stateless/01838_system_dictionaries_virtual_key_column.sql @@ -0,0 +1,26 @@ +DROP DICTIONARY IF EXISTS example_simple_key_dictionary; +CREATE DICTIONARY example_simple_key_dictionary ( + id UInt64, + value UInt64 +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE '' DATABASE currentDatabase())) +LAYOUT(DIRECT()); + +SELECT 'simple key'; + +SELECT name, key FROM system.dictionaries WHERE name='example_simple_key_dictionary' AND database=currentDatabase(); + +DROP DICTIONARY IF EXISTS example_complex_key_dictionary; +CREATE DICTIONARY example_complex_key_dictionary ( + id UInt64, + id_key String, + value UInt64 +) +PRIMARY KEY id, id_key +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE '' DATABASE currentDatabase())) +LAYOUT(COMPLEX_KEY_DIRECT()); + +SELECT 'complex key'; + +SELECT name, key FROM system.dictionaries WHERE name='example_complex_key_dictionary' AND database=currentDatabase();