From eabeb3076f1eb0cad8c995398ad276ed22453611 Mon Sep 17 00:00:00 2001 From: Maksim Kita Date: Wed, 9 Jun 2021 20:21:32 +0300 Subject: [PATCH] Added tests --- src/Dictionaries/CacheDictionaryStorage.h | 188 ++++++++++-------- src/Dictionaries/HashedDictionary.cpp | 15 +- src/Dictionaries/IPAddressDictionary.cpp | 30 ++- src/Dictionaries/IPAddressDictionary.h | 4 +- src/Dictionaries/PolygonDictionary.cpp | 134 +++++++------ src/Dictionaries/PolygonDictionary.h | 6 +- src/Dictionaries/RangeHashedDictionary.cpp | 23 ++- src/Dictionaries/RangeHashedDictionary.h | 2 +- .../ParserDictionaryAttributeDeclaration.cpp | 5 +- .../01805_dictionary_array_type.reference | 2 - .../01805_dictionary_array_type.sql | 55 ----- .../01902_dictionary_array_type.reference | 28 +++ .../01902_dictionary_array_type.sql | 164 +++++++++++++++ ..._ssd_cache_dictionary_array_type.reference | 4 + .../01903_ssd_cache_dictionary_array_type.sh | 35 ++++ 15 files changed, 478 insertions(+), 217 deletions(-) delete mode 100644 tests/queries/0_stateless/01805_dictionary_array_type.reference delete mode 100644 tests/queries/0_stateless/01805_dictionary_array_type.sql create mode 100644 tests/queries/0_stateless/01902_dictionary_array_type.reference create mode 100644 tests/queries/0_stateless/01902_dictionary_array_type.sql create mode 100644 tests/queries/0_stateless/01903_ssd_cache_dictionary_array_type.reference create mode 100755 tests/queries/0_stateless/01903_ssd_cache_dictionary_array_type.sh diff --git a/src/Dictionaries/CacheDictionaryStorage.h b/src/Dictionaries/CacheDictionaryStorage.h index d93dfea2f91..79bfef8e349 100644 --- a/src/Dictionaries/CacheDictionaryStorage.h +++ b/src/Dictionaries/CacheDictionaryStorage.h @@ -226,23 +226,17 @@ private: auto & attribute = attributes[attribute_index]; const auto & default_value_provider = fetch_request.defaultValueProviderAtIndex(attribute_index); - size_t fetched_keys_size = fetched_keys.size(); auto & fetched_column = *result.fetched_columns[attribute_index]; - fetched_column.reserve(fetched_keys_size); + fetched_column.reserve(fetched_columns_index); if (unlikely(attribute.is_complex_type)) { - auto & container = std::get>(attribute.attribute_container); - - for (size_t fetched_key_index = 0; fetched_key_index < fetched_columns_index; ++fetched_key_index) - { - auto fetched_key = fetched_keys[fetched_key_index]; - - if (unlikely(fetched_key.is_default)) - fetched_column.insert(default_value_provider.getDefaultValue(fetched_key_index)); - else - fetched_column.insert(container[fetched_key.element_index]); - } + getItemsForFetchedKeys( + attribute, + fetched_columns_index, + fetched_keys, + [&](Field & value) { fetched_column.insert(value); }, + default_value_provider); } else { @@ -250,46 +244,40 @@ private: { using Type = std::decay_t; using AttributeType = typename Type::AttributeType; + using ColumnProvider = DictionaryAttributeColumnProvider; + using ColumnType = typename ColumnProvider::ColumnType; using ValueType = DictionaryValueType; - using ColumnType = - std::conditional_t, ColumnString, - std::conditional_t, ColumnDecimal, - ColumnVector>>; - auto & container = std::get>(attribute.attribute_container); ColumnType & column_typed = static_cast(fetched_column); - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) { - for (size_t fetched_key_index = 0; fetched_key_index < fetched_columns_index; ++fetched_key_index) - { - auto fetched_key = fetched_keys[fetched_key_index]; - - if (unlikely(fetched_key.is_default)) - column_typed.insert(default_value_provider.getDefaultValue(fetched_key_index)); - else - { - auto item = container[fetched_key.element_index]; - column_typed.insertData(item.data, item.size); - } - } + getItemsForFetchedKeys( + attribute, + fetched_columns_index, + fetched_keys, + [&](Array & value) { fetched_column.insert(value); }, + default_value_provider); + } + else if constexpr (std::is_same_v) + { + getItemsForFetchedKeys( + attribute, + fetched_columns_index, + fetched_keys, + [&](StringRef value) { fetched_column.insertData(value.data, value.size); }, + default_value_provider); } else { auto & data = column_typed.getData(); - for (size_t fetched_key_index = 0; fetched_key_index < fetched_columns_index; ++fetched_key_index) - { - auto fetched_key = fetched_keys[fetched_key_index]; - - if (unlikely(fetched_key.is_default)) - column_typed.insert(default_value_provider.getDefaultValue(fetched_key_index)); - else - { - auto item = container[fetched_key.element_index]; - data.push_back(item); - } - } + getItemsForFetchedKeys( + attribute, + fetched_columns_index, + fetched_keys, + [&](auto value) { data.push_back(value); }, + default_value_provider); } }; @@ -506,7 +494,7 @@ private: if (unlikely(attribute.is_complex_type)) { - auto & container = std::get>(attribute.attribute_container); + auto & container = std::get>(attribute.attribute_container); std::forward(func)(container); } else @@ -517,7 +505,7 @@ private: using AttributeType = typename Type::AttributeType; using ValueType = DictionaryValueType; - auto & container = std::get>(attribute.attribute_container); + auto & container = std::get>(attribute.attribute_container); std::forward(func)(container); }; @@ -541,6 +529,81 @@ private: return updated_value; } + template + static constexpr bool is_nullable_or_array_type = std::is_same_v || std::is_same_v; + + template + using ContainerType = std::conditional_t, std::vector, PaddedPODArray>; + + struct Attribute + { + AttributeUnderlyingType type; + bool is_complex_type; + + std::variant< + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType, + ContainerType> attribute_container; + }; + + template + void getItemsForFetchedKeys( + Attribute & attribute, + size_t fetched_keys_size, + PaddedPODArray & fetched_keys, + ValueSetter && value_setter, + const DefaultValueProvider & default_value_provider) + { + auto & container = std::get>(attribute.attribute_container); + + for (size_t fetched_key_index = 0; fetched_key_index < fetched_keys_size; ++fetched_key_index) + { + auto fetched_key = fetched_keys[fetched_key_index]; + + if (unlikely(fetched_key.is_default)) + { + auto default_value = default_value_provider.getDefaultValue(fetched_key_index); + + if constexpr (std::is_same_v) + { + value_setter(default_value); + } + else if constexpr (std::is_same_v) + { + auto & value = default_value.get(); + value_setter(value); + } + else + { + value_setter(default_value.get()); + } + } + else + { + value_setter(container[fetched_key.element_index]); + } + } + } + void setup(const DictionaryStructure & dictionary_structure) { /// For each dictionary attribute create storage attribute @@ -563,9 +626,9 @@ private: last_attribute.type = attribute_type; if (dictionary_attribute.is_nullable) - last_attribute.attribute_container = std::vector(); + last_attribute.attribute_container = ContainerType(); else - last_attribute.attribute_container = PaddedPODArray(); + last_attribute.attribute_container = ContainerType(); }; callOnDictionaryAttributeType(attribute_type, type_call); @@ -582,37 +645,6 @@ private: time_t deadline; }; - struct Attribute - { - AttributeUnderlyingType type; - bool is_complex_type; - - std::variant< - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - PaddedPODArray, - /// TODO: FIX - PaddedPODArray, - std::vector> attribute_container; - }; - CacheDictionaryStorageConfiguration configuration; pcg64 rnd_engine; diff --git a/src/Dictionaries/HashedDictionary.cpp b/src/Dictionaries/HashedDictionary.cpp index 0de28f18006..9e41f552b08 100644 --- a/src/Dictionaries/HashedDictionary.cpp +++ b/src/Dictionaries/HashedDictionary.cpp @@ -96,7 +96,20 @@ ColumnPtr HashedDictionary::getColumn( auto column = ColumnProvider::getColumn(dictionary_attribute, size); - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) + { + auto * out = column.get(); + + getItemsImpl( + attribute, + extractor, + [&](const size_t, const Array & value) { out->insert(value); }, + [&](const size_t) + { + }, + default_value_extractor); + } + else if constexpr (std::is_same_v) { auto * out = column.get(); diff --git a/src/Dictionaries/IPAddressDictionary.cpp b/src/Dictionaries/IPAddressDictionary.cpp index 6526517c83c..22266461538 100644 --- a/src/Dictionaries/IPAddressDictionary.cpp +++ b/src/Dictionaries/IPAddressDictionary.cpp @@ -238,11 +238,21 @@ ColumnPtr IPAddressDictionary::getColumn( auto column = ColumnProvider::getColumn(dictionary_attribute, size); - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) { auto * out = column.get(); - getItemsImpl( + getItemsImpl( + attribute, + key_columns, + [&](const size_t, const Array & value) { out->insert(value); }, + default_value_extractor); + } + else if constexpr (std::is_same_v) + { + auto * out = column.get(); + + getItemsImpl( attribute, key_columns, [&](const size_t, const StringRef value) { out->insertData(value.data, value.size); }, @@ -252,7 +262,7 @@ ColumnPtr IPAddressDictionary::getColumn( { auto & out = column->getData(); - getItemsImpl( + getItemsImpl( attribute, key_columns, [&](const size_t row, const auto value) { return out[row] = value; }, @@ -591,7 +601,7 @@ const uint8_t * IPAddressDictionary::getIPv6FromOffset(const IPAddressDictionary return reinterpret_cast(&ipv6_col[i * IPV6_BINARY_LENGTH]); } -template +template void IPAddressDictionary::getItemsByTwoKeyColumnsImpl( const Attribute & attribute, const Columns & key_columns, @@ -630,7 +640,7 @@ void IPAddressDictionary::getItemsByTwoKeyColumnsImpl( (*ipv4_col)[*found_it] == addr && mask_column[*found_it] == mask)) { - set_value(i, static_cast(vec[row_idx[*found_it]])); + set_value(i, vec[row_idx[*found_it]]); } else set_value(i, default_value_extractor[i]); @@ -666,13 +676,13 @@ void IPAddressDictionary::getItemsByTwoKeyColumnsImpl( if (likely(found_it != range.end() && memequal16(getIPv6FromOffset(*ipv6_col, *found_it), target.addr) && mask_column[*found_it] == mask)) - set_value(i, static_cast(vec[row_idx[*found_it]])); + set_value(i, vec[row_idx[*found_it]]); else set_value(i, default_value_extractor[i]); } } -template +template void IPAddressDictionary::getItemsImpl( const Attribute & attribute, const Columns & key_columns, @@ -685,7 +695,7 @@ void IPAddressDictionary::getItemsImpl( // special case for getBlockInputStream if (unlikely(key_columns.size() == 2)) { - getItemsByTwoKeyColumnsImpl( + getItemsByTwoKeyColumnsImpl( attribute, key_columns, std::forward(set_value), default_value_extractor); query_count.fetch_add(rows, std::memory_order_relaxed); return; @@ -705,7 +715,7 @@ void IPAddressDictionary::getItemsImpl( auto found = tryLookupIPv4(addrv4, addrv6_buf); if (found != ipNotFound()) { - set_value(i, static_cast(vec[*found])); + set_value(i, vec[*found]); ++keys_found; } else @@ -723,7 +733,7 @@ void IPAddressDictionary::getItemsImpl( auto found = tryLookupIPv6(reinterpret_cast(addr.data)); if (found != ipNotFound()) { - set_value(i, static_cast(vec[*found])); + set_value(i, vec[*found]); ++keys_found; } else diff --git a/src/Dictionaries/IPAddressDictionary.h b/src/Dictionaries/IPAddressDictionary.h index cacf9bd3118..075742da11a 100644 --- a/src/Dictionaries/IPAddressDictionary.h +++ b/src/Dictionaries/IPAddressDictionary.h @@ -159,14 +159,14 @@ private: static Attribute createAttributeWithType(const AttributeUnderlyingType type, const Field & null_value); - template + template void getItemsByTwoKeyColumnsImpl( const Attribute & attribute, const Columns & key_columns, ValueSetter && set_value, DefaultValueExtractor & default_value_extractor) const; - template + template void getItemsImpl( const Attribute & attribute, const Columns & key_columns, diff --git a/src/Dictionaries/PolygonDictionary.cpp b/src/Dictionaries/PolygonDictionary.cpp index f58e578ea1c..17e7605d136 100644 --- a/src/Dictionaries/PolygonDictionary.cpp +++ b/src/Dictionaries/PolygonDictionary.cpp @@ -60,28 +60,13 @@ ColumnPtr IPolygonDictionary::getColumn( auto result = attribute_values_column->cloneEmpty(); result->reserve(requested_key_points.size()); - Field row_value_to_insert; - size_t polygon_index = 0; - - size_t keys_found = 0; - if (unlikely(attribute.is_nullable)) { - for (size_t requested_key_index = 0; requested_key_index < requested_key_points.size(); ++requested_key_index) - { - const auto found = find(requested_key_points[requested_key_index], polygon_index); - - if (found) - { - size_t attribute_values_index = polygon_index_to_attribute_value_index[polygon_index]; - attribute_values_column->get(attribute_values_index, row_value_to_insert); - ++keys_found; - } - else - row_value_to_insert = default_value_provider.getDefaultValue(requested_key_index); - - result->insert(row_value_to_insert); - } + getItemsImpl( + requested_key_points, + [&](size_t row) { return (*attribute_values_column)[row]; }, + [&](Field & value) { result->insert(value); }, + default_value_provider); } else { @@ -90,10 +75,8 @@ ColumnPtr IPolygonDictionary::getColumn( using Type = std::decay_t; using AttributeType = typename Type::AttributeType; using ValueType = DictionaryValueType; - using ColumnType = std::conditional_t< - std::is_same_v, - ColumnString, - std::conditional_t, ColumnDecimal, ColumnVector>>; + using ColumnProvider = DictionaryAttributeColumnProvider; + using ColumnType = typename ColumnProvider::ColumnType; const auto attribute_values_column_typed = typeid_cast(attribute_values_column.get()); if (!attribute_values_column_typed) @@ -101,54 +84,38 @@ ColumnPtr IPolygonDictionary::getColumn( ColumnType & result_column_typed = static_cast(*result); - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) { - for (size_t requested_key_index = 0; requested_key_index < requested_key_points.size(); ++requested_key_index) - { - const auto found = find(requested_key_points[requested_key_index], polygon_index); - - if (found) - { - size_t attribute_values_index = polygon_index_to_attribute_value_index[polygon_index]; - auto data_to_insert = attribute_values_column->getDataAt(attribute_values_index); - result_column_typed.insertData(data_to_insert.data, data_to_insert.size); - ++keys_found; - } - else - result_column_typed.insert(default_value_provider.getDefaultValue(requested_key_index)); - } + getItemsImpl( + requested_key_points, + [&](size_t row) { return (*attribute_values_column)[row].get(); }, + [&](Array & value) { result_column_typed.insert(value); }, + default_value_provider); + } + else if constexpr (std::is_same_v) + { + getItemsImpl( + requested_key_points, + [&](size_t row) { return attribute_values_column->getDataAt(row); }, + [&](StringRef value) { result_column_typed.insertData(value.data, value.size); }, + default_value_provider); } else { auto & attribute_data = attribute_values_column_typed->getData(); auto & result_data = result_column_typed.getData(); - for (size_t requested_key_index = 0; requested_key_index < requested_key_points.size(); ++requested_key_index) - { - const auto found = find(requested_key_points[requested_key_index], polygon_index); - - if (found) - { - size_t attribute_values_index = polygon_index_to_attribute_value_index[polygon_index]; - auto & item = attribute_data[attribute_values_index]; - result_data.emplace_back(item); - ++keys_found; - } - else - { - row_value_to_insert = default_value_provider.getDefaultValue(requested_key_index); - result_data.emplace_back(row_value_to_insert.template get>()); - } - } + getItemsImpl( + requested_key_points, + [&](size_t row) { return attribute_data[row]; }, + [&](auto value) { result_data.emplace_back(value); }, + default_value_provider); } }; callOnDictionaryAttributeType(attribute.underlying_type, type_call); } - query_count.fetch_add(requested_key_points.size(), std::memory_order_relaxed); - found_count.fetch_add(keys_found, std::memory_order_relaxed); - return result; } @@ -308,6 +275,55 @@ ColumnUInt8::Ptr IPolygonDictionary::hasKeys(const Columns & key_columns, const return result; } +template +void IPolygonDictionary::getItemsImpl( + const std::vector & requested_key_points, + ValueGetter && get_value, + ValueSetter && set_value, + DefaultValueExtractor & default_value_extractor) const +{ + size_t polygon_index = 0; + size_t keys_found = 0; + + for (size_t requested_key_index = 0; requested_key_index < requested_key_points.size(); ++requested_key_index) + { + const auto found = find(requested_key_points[requested_key_index], polygon_index); + + if (found) + { + size_t attribute_values_index = polygon_index_to_attribute_value_index[polygon_index]; + auto value = get_value(attribute_values_index); + set_value(value); + ++keys_found; + } + else + { + Field default_value = default_value_extractor.getDefaultValue(requested_key_index); + + if constexpr (std::is_same_v) + { + set_value(default_value); + } + else if constexpr (std::is_same_v) + { + set_value(default_value.get()); + } + else if constexpr (std::is_same_v) + { + auto default_value_string = default_value.get(); + set_value(default_value_string); + } + else + { + set_value(default_value.get>()); + } + } + } + + query_count.fetch_add(requested_key_points.size(), std::memory_order_relaxed); + found_count.fetch_add(keys_found, std::memory_order_relaxed); +} + namespace { diff --git a/src/Dictionaries/PolygonDictionary.h b/src/Dictionaries/PolygonDictionary.h index 997b9ed71d8..14492df6469 100644 --- a/src/Dictionaries/PolygonDictionary.h +++ b/src/Dictionaries/PolygonDictionary.h @@ -139,10 +139,10 @@ private: size_t getAttributeIndex(const std::string & attribute_name) const; /** Helper function for retrieving the value of an attribute by key. */ - template + template void getItemsImpl( - size_t attribute_ind, - const Columns & key_columns, + const std::vector & requested_key_points, + ValueGetter && get_value, ValueSetter && set_value, DefaultValueExtractor & default_value_extractor) const; diff --git a/src/Dictionaries/RangeHashedDictionary.cpp b/src/Dictionaries/RangeHashedDictionary.cpp index b771bca068f..28014594117 100644 --- a/src/Dictionaries/RangeHashedDictionary.cpp +++ b/src/Dictionaries/RangeHashedDictionary.cpp @@ -131,11 +131,24 @@ ColumnPtr RangeHashedDictionary::getColumn( auto column = ColumnProvider::getColumn(dictionary_attribute, keys_size); - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) { auto * out = column.get(); - getItemsImpl( + getItemsImpl( + attribute, + modified_key_columns, + [&](const size_t, const Array & value, bool) + { + out->insert(value); + }, + default_value_extractor); + } + else if constexpr (std::is_same_v) + { + auto * out = column.get(); + + getItemsImpl( attribute, modified_key_columns, [&](const size_t row, const StringRef value, bool is_null) @@ -151,7 +164,7 @@ ColumnPtr RangeHashedDictionary::getColumn( { auto & out = column->getData(); - getItemsImpl( + getItemsImpl( attribute, modified_key_columns, [&](const size_t row, const auto value, bool is_null) @@ -385,7 +398,7 @@ RangeHashedDictionary::createAttribute(const DictionaryAttribute& attribute, con return attr; } -template +template void RangeHashedDictionary::getItemsImpl( const Attribute & attribute, const Columns & key_columns, @@ -423,7 +436,7 @@ void RangeHashedDictionary::getItemsImpl( auto & value = val_it->value; if (value) - set_value(row, static_cast(*value), false); // NOLINT + set_value(row, *value, false); else set_value(row, default_value_extractor[row], true); } diff --git a/src/Dictionaries/RangeHashedDictionary.h b/src/Dictionaries/RangeHashedDictionary.h index a6d6343cd3f..50888873c3c 100644 --- a/src/Dictionaries/RangeHashedDictionary.h +++ b/src/Dictionaries/RangeHashedDictionary.h @@ -170,7 +170,7 @@ private: static Attribute createAttribute(const DictionaryAttribute& attribute, const Field & null_value); - template + template void getItemsImpl( const Attribute & attribute, const Columns & key_columns, diff --git a/src/Parsers/ParserDictionaryAttributeDeclaration.cpp b/src/Parsers/ParserDictionaryAttributeDeclaration.cpp index 9cd1cebe4e0..2099618588e 100644 --- a/src/Parsers/ParserDictionaryAttributeDeclaration.cpp +++ b/src/Parsers/ParserDictionaryAttributeDeclaration.cpp @@ -17,6 +17,7 @@ bool ParserDictionaryAttributeDeclaration::parseImpl(Pos & pos, ASTPtr & node, E ParserKeyword s_injective{"INJECTIVE"}; ParserKeyword s_is_object_id{"IS_OBJECT_ID"}; ParserLiteral default_parser; + ParserArrayOfLiterals array_literals_parser; ParserTernaryOperatorExpression expression_parser; /// mandatory attribute name @@ -40,8 +41,10 @@ bool ParserDictionaryAttributeDeclaration::parseImpl(Pos & pos, ASTPtr & node, E { if (!default_value && s_default.ignore(pos, expected)) { - if (!default_parser.parse(pos, default_value, expected)) + if (!default_parser.parse(pos, default_value, expected) && + !array_literals_parser.parse(pos, default_value, expected)) return false; + continue; } diff --git a/tests/queries/0_stateless/01805_dictionary_array_type.reference b/tests/queries/0_stateless/01805_dictionary_array_type.reference deleted file mode 100644 index fc2a6af66ef..00000000000 --- a/tests/queries/0_stateless/01805_dictionary_array_type.reference +++ /dev/null @@ -1,2 +0,0 @@ -Flat dictionary -[0,1,2] diff --git a/tests/queries/0_stateless/01805_dictionary_array_type.sql b/tests/queries/0_stateless/01805_dictionary_array_type.sql deleted file mode 100644 index 606c2df49fa..00000000000 --- a/tests/queries/0_stateless/01805_dictionary_array_type.sql +++ /dev/null @@ -1,55 +0,0 @@ -DROP TABLE IF EXISTS dictionary_array_source_table; -CREATE TABLE dictionary_array_source_table -( - id UInt64, - array_value Array(Int) DEFAULT [0, 1, 3] -) ENGINE=TinyLog; - -INSERT INTO dictionary_array_source_table VALUES (0, [0, 1, 2]); - -DROP DICTIONARY IF EXISTS flat_dictionary; -CREATE DICTIONARY flat_dictionary -( - id UInt64, - array_value Array(Int) -) -PRIMARY KEY id -SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() TABLE 'dictionary_array_source_table')) -LIFETIME(MIN 1 MAX 1000) -LAYOUT(FLAT()); - -SELECT 'Flat dictionary'; -SELECT dictGet('flat_dictionary', 'array_value', toUInt64(0)); -DROP DICTIONARY flat_dictionary; - --- DROP DICTIONARY IF EXISTS hashed_dictionary; --- CREATE DICTIONARY hashed_dictionary --- ( --- id UInt64, --- array_value Array(Int) --- ) --- PRIMARY KEY id --- SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() TABLE 'dictionary_array_source_table')) --- LIFETIME(MIN 1 MAX 1000) --- LAYOUT(HASHED()); - --- SELECT 'Hashed dictionary'; --- SELECT dictGet('hashed_dictionary', 'array_value', toUInt64(1)); --- DROP DICTIONARY hashed_dictionary; - --- DROP DICTIONARY IF EXISTS cache_dictionary; --- CREATE DICTIONARY cache_dictionary --- ( --- id UInt64, --- array_value Array(Int) --- ) --- PRIMARY KEY id --- SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() TABLE 'dictionary_array_source_table')) --- LIFETIME(MIN 1 MAX 1000) --- LAYOUT(CACHE(SIZE_IN_CELLS 10)); - --- SELECT 'Cache dictionary'; --- SELECT dictGet('cache_dictionary', 'array_value', toUInt64(1)); --- DROP DICTIONARY cache_dictionary; - -DROP TABLE dictionary_array_source_table; \ No newline at end of file diff --git a/tests/queries/0_stateless/01902_dictionary_array_type.reference b/tests/queries/0_stateless/01902_dictionary_array_type.reference new file mode 100644 index 00000000000..b7f0ff968c6 --- /dev/null +++ b/tests/queries/0_stateless/01902_dictionary_array_type.reference @@ -0,0 +1,28 @@ +Flat dictionary +[0,1,2] +[1,2,3] +[2,3,4] +Hashed dictionary +[0,1,2] +[1,2,3] +[2,3,4] +Cache dictionary +[0,1,2] +[1,2,3] +[2,3,4] +Direct dictionary +[0,1,2] +[1,2,3] +[2,3,4] +IPTrie dictionary +[0,1,2] +[1,2,3] +[2,3,4] +Polygon dictionary +[0,1,2] +[1,2,3] +[2,3,4] +Range dictionary +[0,1,2] +[1,2,3] +[2,3,4] diff --git a/tests/queries/0_stateless/01902_dictionary_array_type.sql b/tests/queries/0_stateless/01902_dictionary_array_type.sql new file mode 100644 index 00000000000..fcd41c77819 --- /dev/null +++ b/tests/queries/0_stateless/01902_dictionary_array_type.sql @@ -0,0 +1,164 @@ +DROP TABLE IF EXISTS dictionary_array_source_table; +CREATE TABLE dictionary_array_source_table +( + id UInt64, + array_value Array(Int64) +) ENGINE=TinyLog; + +INSERT INTO dictionary_array_source_table VALUES (0, [0, 1, 2]); + +DROP DICTIONARY IF EXISTS flat_dictionary; +CREATE DICTIONARY flat_dictionary +( + id UInt64, + array_value Array(Int64) DEFAULT [1,2,3] +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() TABLE 'dictionary_array_source_table')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(FLAT()); + +SELECT 'Flat dictionary'; +SELECT dictGet('flat_dictionary', 'array_value', toUInt64(0)); +SELECT dictGet('flat_dictionary', 'array_value', toUInt64(1)); +SELECT dictGetOrDefault('flat_dictionary', 'array_value', toUInt64(1), [2,3,4]); +DROP DICTIONARY flat_dictionary; + +DROP DICTIONARY IF EXISTS hashed_dictionary; +CREATE DICTIONARY hashed_dictionary +( + id UInt64, + array_value Array(Int64) DEFAULT [1,2,3] +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() TABLE 'dictionary_array_source_table')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(HASHED()); + +SELECT 'Hashed dictionary'; +SELECT dictGet('hashed_dictionary', 'array_value', toUInt64(0)); +SELECT dictGet('hashed_dictionary', 'array_value', toUInt64(1)); +SELECT dictGetOrDefault('hashed_dictionary', 'array_value', toUInt64(1), [2,3,4]); +DROP DICTIONARY hashed_dictionary; + +DROP DICTIONARY IF EXISTS cache_dictionary; +CREATE DICTIONARY cache_dictionary +( + id UInt64, + array_value Array(Int64) DEFAULT [1,2,3] +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() TABLE 'dictionary_array_source_table')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(CACHE(SIZE_IN_CELLS 10)); + +SELECT 'Cache dictionary'; +SELECT dictGet('cache_dictionary', 'array_value', toUInt64(0)); +SELECT dictGet('cache_dictionary', 'array_value', toUInt64(1)); +SELECT dictGetOrDefault('cache_dictionary', 'array_value', toUInt64(1), [2,3,4]); +DROP DICTIONARY cache_dictionary; + +DROP DICTIONARY IF EXISTS direct_dictionary; +CREATE DICTIONARY direct_dictionary +( + id UInt64, + array_value Array(Int64) DEFAULT [1,2,3] +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() TABLE 'dictionary_array_source_table')) +LAYOUT(DIRECT()); + +SELECT 'Direct dictionary'; +SELECT dictGet('direct_dictionary', 'array_value', toUInt64(0)); +SELECT dictGet('direct_dictionary', 'array_value', toUInt64(1)); +SELECT dictGetOrDefault('direct_dictionary', 'array_value', toUInt64(1), [2,3,4]); +DROP DICTIONARY direct_dictionary; + +DROP TABLE IF EXISTS ip_trie_dictionary_array_source_table; +CREATE TABLE ip_trie_dictionary_array_source_table +( + prefix String, + array_value Array(Int64) +) ENGINE = TinyLog; + +DROP TABLE dictionary_array_source_table; + +DROP DICTIONARY IF EXISTS ip_trie_dictionary; +CREATE DICTIONARY ip_trie_dictionary +( + prefix String, + array_value Array(Int64) DEFAULT [1,2,3] +) +PRIMARY KEY prefix +SOURCE(CLICKHOUSE(HOST 'localhost' port tcpPort() TABLE 'ip_trie_dictionary_array_source_table')) +LIFETIME(MIN 10 MAX 1000) +LAYOUT(IP_TRIE()); + +INSERT INTO ip_trie_dictionary_array_source_table VALUES ('127.0.0.0', [0, 1, 2]); + +SELECT 'IPTrie dictionary'; +SELECT dictGet('ip_trie_dictionary', 'array_value', tuple(IPv4StringToNum('127.0.0.0'))); +SELECT dictGet('ip_trie_dictionary', 'array_value', tuple(IPv4StringToNum('128.0.0.0'))); +SELECT dictGetOrDefault('ip_trie_dictionary', 'array_value', tuple(IPv4StringToNum('128.0.0.0')), [2,3,4]); + +DROP DICTIONARY ip_trie_dictionary; +DROP TABLE ip_trie_dictionary_array_source_table; + +DROP TABLE IF EXISTS polygon_dictionary_array_source_table; +CREATE TABLE polygon_dictionary_array_source_table +( + key Array(Array(Array(Tuple(Float64, Float64)))), + array_value Array(Int64) +) ENGINE = TinyLog; + +INSERT INTO polygon_dictionary_array_source_table VALUES ([[[(0, 0), (0, 1), (1, 1), (1, 0)]]], [0, 1, 2]); + +DROP DICTIONARY IF EXISTS polygon_dictionary; +CREATE DICTIONARY polygon_dictionary +( + key Array(Array(Array(Tuple(Float64, Float64)))), + array_value Array(Int64) DEFAULT [1,2,3] +) +PRIMARY KEY key +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() TABLE 'polygon_dictionary_array_source_table')) +LIFETIME(MIN 0 MAX 1000) +LAYOUT(POLYGON()); + +SELECT 'Polygon dictionary'; +SELECT dictGet('polygon_dictionary', 'array_value', tuple(0.5, 0.5)); +SELECT dictGet('polygon_dictionary', 'array_value', tuple(1.5, 1.5)); +SELECT dictGetOrDefault('polygon_dictionary', 'array_value', tuple(1.5, 1.5), [2, 3, 4]); + +DROP DICTIONARY polygon_dictionary; +DROP TABLE polygon_dictionary_array_source_table; + +CREATE TABLE range_dictionary_array_source_table +( + key UInt64, + start_date Date, + end_date Date, + array_value Array(Int64) +) +ENGINE = TinyLog; + +INSERT INTO range_dictionary_array_source_table VALUES(1, toDate('2019-05-05'), toDate('2019-05-20'), [0, 1, 2]); +CREATE DICTIONARY range_dictionary +( + key UInt64, + start_date Date, + end_date Date, + array_value Array(Int64) DEFAULT [1,2,3] +) +PRIMARY KEY key +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() TABLE 'range_dictionary_array_source_table')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(RANGE_HASHED()) +RANGE(MIN start_date MAX end_date); + +SELECT 'Range dictionary'; +SELECT dictGet('range_dictionary', 'array_value', toUInt64(1), toDate('2019-05-15')); +SELECT dictGet('range_dictionary', 'array_value', toUInt64(1), toDate('2019-05-21')); +SELECT dictGetOrDefault('range_dictionary', 'array_value', toUInt64(1), toDate('2019-05-21'), [2, 3, 4]); + +DROP DICTIONARY range_dictionary; +DROP TABLE range_dictionary_array_source_table; diff --git a/tests/queries/0_stateless/01903_ssd_cache_dictionary_array_type.reference b/tests/queries/0_stateless/01903_ssd_cache_dictionary_array_type.reference new file mode 100644 index 00000000000..90850428694 --- /dev/null +++ b/tests/queries/0_stateless/01903_ssd_cache_dictionary_array_type.reference @@ -0,0 +1,4 @@ +SSDCache dictionary +[0,1,2] +[1,2,3] +[2,3,4] diff --git a/tests/queries/0_stateless/01903_ssd_cache_dictionary_array_type.sh b/tests/queries/0_stateless/01903_ssd_cache_dictionary_array_type.sh new file mode 100755 index 00000000000..70aa4623320 --- /dev/null +++ b/tests/queries/0_stateless/01903_ssd_cache_dictionary_array_type.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +USER_FILES_PATH=$(clickhouse-client --query "select _path,_file from file('nonexist.txt', 'CSV', 'val1 char')" 2>&1 | grep Exception | awk '{gsub("/nonexist.txt","",$9); print $9}') + +$CLICKHOUSE_CLIENT -n --query=" + DROP TABLE IF EXISTS dictionary_array_source_table; + CREATE TABLE dictionary_array_source_table + ( + id UInt64, + array_value Array(Int64) + ) ENGINE=TinyLog; + + INSERT INTO dictionary_array_source_table VALUES (0, [0, 1, 2]); + + DROP DICTIONARY IF EXISTS ssd_cache_dictionary; + CREATE DICTIONARY ssd_cache_dictionary + ( + id UInt64, + array_value Array(Int64) DEFAULT [1,2,3] + ) + PRIMARY KEY id + SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() TABLE 'dictionary_array_source_table')) + LIFETIME(MIN 1 MAX 1000) + LAYOUT(SSD_CACHE(BLOCK_SIZE 4096 FILE_SIZE 8192 PATH '$USER_FILES_PATH/0d')); + + SELECT 'SSDCache dictionary'; + SELECT dictGet('ssd_cache_dictionary', 'array_value', toUInt64(0)); + SELECT dictGet('ssd_cache_dictionary', 'array_value', toUInt64(1)); + SELECT dictGetOrDefault('ssd_cache_dictionary', 'array_value', toUInt64(1), [2,3,4]); + DROP DICTIONARY ssd_cache_dictionary; + DROP TABLE dictionary_array_source_table;"