diff --git a/src/Dictionaries/DirectDictionary.cpp b/src/Dictionaries/DirectDictionary.cpp index 603581373ef..437519c72cd 100644 --- a/src/Dictionaries/DirectDictionary.cpp +++ b/src/Dictionaries/DirectDictionary.cpp @@ -310,7 +310,8 @@ void DirectDictionary::createAttributes() for (const auto & attribute : dict_struct.attributes) { attribute_index_by_name.emplace(attribute.name, attributes.size()); - attributes.push_back(createAttributeWithType(attribute.underlying_type, attribute.null_value)); + attribute_name_by_index.emplace(attributes.size(), attribute.name); + attributes.push_back(createAttributeWithType(attribute.underlying_type, attribute.null_value, attribute.name)); if (attribute.hierarchical) { @@ -351,9 +352,9 @@ void DirectDictionary::createAttributeImpl(Attribute & attribute, const } -DirectDictionary::Attribute DirectDictionary::createAttributeWithType(const AttributeUnderlyingType type, const Field & null_value) +DirectDictionary::Attribute DirectDictionary::createAttributeWithType(const AttributeUnderlyingType type, const Field & null_value, const std::string & attr_name) { - Attribute attr{type, {}, {}}; + Attribute attr{type, {}, {}, attr_name}; switch (type) { @@ -411,7 +412,7 @@ DirectDictionary::Attribute DirectDictionary::createAttributeWithType(const Attr template void DirectDictionary::getItemsImpl( - const Attribute &, const PaddedPODArray & ids, ValueSetter && set_value, DefaultGetter && get_default) const + const Attribute & attribute, const PaddedPODArray & ids, ValueSetter && set_value, DefaultGetter && get_default) const { const auto rows = ext::size(ids); @@ -431,10 +432,9 @@ void DirectDictionary::getItemsImpl( const auto key = id_column[row_idx].get(); for (const auto row : ext::range(0, rows)) { - if (key == ids[row]) { + if (key == ids[row] && attribute.name == attribute_name_by_index.at(attribute_idx)) { is_found[row] = true; set_value(row, static_cast(attribute_column[row_idx].get())); - // break; } } } @@ -453,7 +453,7 @@ void DirectDictionary::getItemsImpl( template void DirectDictionary::getItemsStringImpl( - const Attribute &, const PaddedPODArray & ids, ValueSetter && set_value, DefaultGetter && get_default) const + const Attribute & attribute, const PaddedPODArray & ids, ValueSetter && set_value, DefaultGetter && get_default) const { const auto rows = ext::size(ids); @@ -472,14 +472,13 @@ void DirectDictionary::getItemsStringImpl( for (const auto row_idx : ext::range(0, id_column.size())) { const auto key = id_column[row_idx].get(); for (const auto row : ext::range(0, rows)) { - if (key == ids[row]) { + if (key == ids[row] && attribute.name == attribute_name_by_index.at(attribute_idx)) { is_found[row] = true; const String from_source = attribute_column[row_idx].get(); const auto * string_in_arena = temp_arena->insert(from_source.data(), from_source.size()); const auto reference = StringRef{string_in_arena, from_source.size()}; set_value(row, reference); - break; } } } @@ -526,7 +525,6 @@ void DirectDictionary::has(const Attribute &, const PaddedPODArray & ids, P for (const auto row : ext::range(0, rows)) { if (key == ids[row]) { out[row] = 1; - // break; } } } diff --git a/src/Dictionaries/DirectDictionary.h b/src/Dictionaries/DirectDictionary.h index c531038f4bc..22b6d733c30 100644 --- a/src/Dictionaries/DirectDictionary.h +++ b/src/Dictionaries/DirectDictionary.h @@ -168,6 +168,7 @@ private: StringRef> null_values; std::unique_ptr string_arena; + std::string name; }; void createAttributes(); @@ -180,7 +181,7 @@ private: template void createAttributeImpl(Attribute & attribute, const Field & null_value); - Attribute createAttributeWithType(const AttributeUnderlyingType type, const Field & null_value); + Attribute createAttributeWithType(const AttributeUnderlyingType type, const Field & null_value, const std::string & name); template void getItemsStringImpl( @@ -218,6 +219,7 @@ private: const DictionaryLifetime dict_lifetime; std::map attribute_index_by_name; + std::map attribute_name_by_index; std::vector attributes; const Attribute * hierarchical_attribute = nullptr; diff --git a/tests/queries/0_stateless/01268_dictionary_direct_layout.reference b/tests/queries/0_stateless/01268_dictionary_direct_layout.reference new file mode 100644 index 00000000000..b2957e751c7 --- /dev/null +++ b/tests/queries/0_stateless/01268_dictionary_direct_layout.reference @@ -0,0 +1,7 @@ +INITIALIZING DICTIONARY +[3,2,1] +1 +0 +1 +0 +END \ No newline at end of file diff --git a/tests/queries/0_stateless/01268_dictionary_direct_layout.sql b/tests/queries/0_stateless/01268_dictionary_direct_layout.sql new file mode 100644 index 00000000000..9e4169bcb0d --- /dev/null +++ b/tests/queries/0_stateless/01268_dictionary_direct_layout.sql @@ -0,0 +1,82 @@ +DROP DATABASE IF EXISTS database_for_dict; + +CREATE DATABASE database_for_dict Engine = Ordinary; + +DROP TABLE IF EXISTS database_for_dict.table_for_dict1; + +DROP TABLE IF EXISTS database_for_dict.table_for_dict2; + +CREATE TABLE database_for_dict.table_for_dict1 +( + key_column UInt64, + second_column UInt64, + third_column String +) +ENGINE = MergeTree() +ORDER BY key_column; + +INSERT INTO database_for_dict.table_for_dict1 VALUES (100500, 10000000, 'Hello world'); + +CREATE TABLE database_for_dict.table_for_dict2 +( + region_id UInt64, + parent_region UInt64, + region_name String +) +ENGINE = MergeTree() +ORDER BY region_id; + +INSERT INTO database_for_dict.table_for_dict2 VALUES (1, 0, 'Russia'); +INSERT INTO database_for_dict.table_for_dict2 VALUES (2, 1, 'Moscow'); +INSERT INTO database_for_dict.table_for_dict2 VALUES (3, 2, 'Center'); +INSERT INTO database_for_dict.table_for_dict2 VALUES (4, 0, 'Great Britain'); +INSERT INTO database_for_dict.table_for_dict2 VALUES (5, 4, 'London'); + +DROP DATABASE IF EXISTS ordinary_db; + +CREATE DATABASE ordinary_db ENGINE = Ordinary; + +DROP DICTIONARY IF EXISTS ordinary_db.dict1; + +CREATE DICTIONARY ordinary_db.dict1 +( + key_column UInt64 DEFAULT 0, + second_column UInt64 DEFAULT 1, + third_column String DEFAULT 'qqq' +) +PRIMARY KEY key_column +SOURCE(CLICKHOUSE(HOST 'localhost' PORT 9000 USER 'default' TABLE 'table_for_dict1' PASSWORD '' DB 'database_for_dict')) +LIFETIME(MIN 600 MAX 600) +LAYOUT(DIRECT()) SETTINGS(max_result_bytes=1); + +CREATE DICTIONARY ordinary_db.dict2 +( + region_id UInt64 DEFAULT 0, + parent_region UInt64 DEFAULT 0 HIERARCHICAL, + region_name String DEFAULT '' +) +PRIMARY KEY region_id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT 9000 USER 'default' TABLE 'table_for_dict2' PASSWORD '' DB 'database_for_dict')) +LIFETIME(MIN 600 MAX 600) +LAYOUT(DIRECT()); + +SELECT 'INITIALIZING DICTIONARY'; + +SELECT dictGetHierarchy('ordinary_db.dict2', toUInt64(3)); +SELECT dictHas('ordinary_db.dict2', toUInt64(3)); +SELECT dictHas('ordinary_db.dict2', toUInt64(45)); +SELECT dictIsIn('ordinary_db.dict2', toUInt64(3), toUInt64(1)); +SELECT dictIsIn('ordinary_db.dict2', toUInt64(1), toUInt64(3)); +SELECT dictGetUInt64('ordinary_db.dict1', 'second_column', toUInt64(100500)); -- { serverError 396 } + +SELECT 'END'; + +DROP DICTIONARY IF EXISTS ordinary_db.dict1; +DROP DICTIONARY IF EXISTS ordinary_db.dict2; + +DROP DATABASE IF EXISTS ordinary_db; + +DROP TABLE IF EXISTS database_for_dict.table_for_dict1; +DROP TABLE IF EXISTS database_for_dict.table_for_dict2; + +DROP DATABASE IF EXISTS database_for_dict;