From 1f978022c589ebfb14c767e746eaa7d27824bcc7 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Wed, 8 Jul 2020 01:10:23 +0300 Subject: [PATCH 1/2] Implement getLeastSuperType for LowCardinality #8212 --- src/DataTypes/getLeastSupertype.cpp | 34 +++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/DataTypes/getLeastSupertype.cpp b/src/DataTypes/getLeastSupertype.cpp index 9c3ca679467..4e332f0d158 100644 --- a/src/DataTypes/getLeastSupertype.cpp +++ b/src/DataTypes/getLeastSupertype.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -186,6 +187,39 @@ DataTypePtr getLeastSupertype(const DataTypes & types) } } + /// For LowCardinality + { + bool have_low_cardinality = false; + bool have_not_low_cardinality = false; + + DataTypes nested_types; + nested_types.reserve(types.size()); + + for (const auto & type : types) + { + if (const DataTypeLowCardinality * type_low_cardinality = typeid_cast(type.get())) + { + have_low_cardinality = true; + nested_types.emplace_back(type_low_cardinality->getDictionaryType()); + } + else + { + have_not_low_cardinality = true; + nested_types.emplace_back(type); + } + } + + /// All LowCardinality gives LowCardinality. + /// LowCardinality with high cardinality gives high cardinality. + if (have_low_cardinality) + { + if (have_not_low_cardinality) + return getLeastSupertype(nested_types); + else + return std::make_shared(getLeastSupertype(nested_types)); + } + } + /// Non-recursive rules std::unordered_set type_ids; From 60c1ffc892271d342343e05e0b4cb8c593b3a501 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Wed, 8 Jul 2020 01:26:43 +0300 Subject: [PATCH 2/2] Implement supertype for LowCardinality --- src/DataTypes/getLeastSupertype.cpp | 54 +++++++------- .../01377_supertype_low_cardinality.reference | 71 +++++++++++++++++++ .../01377_supertype_low_cardinality.sql | 71 +++++++++++++++++++ 3 files changed, 169 insertions(+), 27 deletions(-) create mode 100644 tests/queries/0_stateless/01377_supertype_low_cardinality.reference create mode 100644 tests/queries/0_stateless/01377_supertype_low_cardinality.sql diff --git a/src/DataTypes/getLeastSupertype.cpp b/src/DataTypes/getLeastSupertype.cpp index 4e332f0d158..9cd3e09758e 100644 --- a/src/DataTypes/getLeastSupertype.cpp +++ b/src/DataTypes/getLeastSupertype.cpp @@ -161,33 +161,7 @@ DataTypePtr getLeastSupertype(const DataTypes & types) } } - /// For Nullable - { - bool have_nullable = false; - - DataTypes nested_types; - nested_types.reserve(types.size()); - - for (const auto & type : types) - { - if (const DataTypeNullable * type_nullable = typeid_cast(type.get())) - { - have_nullable = true; - - if (!type_nullable->onlyNull()) - nested_types.emplace_back(type_nullable->getNestedType()); - } - else - nested_types.emplace_back(type); - } - - if (have_nullable) - { - return std::make_shared(getLeastSupertype(nested_types)); - } - } - - /// For LowCardinality + /// For LowCardinality. This is above Nullable, because LowCardinality can contain Nullable but cannot be inside Nullable. { bool have_low_cardinality = false; bool have_not_low_cardinality = false; @@ -220,6 +194,32 @@ DataTypePtr getLeastSupertype(const DataTypes & types) } } + /// For Nullable + { + bool have_nullable = false; + + DataTypes nested_types; + nested_types.reserve(types.size()); + + for (const auto & type : types) + { + if (const DataTypeNullable * type_nullable = typeid_cast(type.get())) + { + have_nullable = true; + + if (!type_nullable->onlyNull()) + nested_types.emplace_back(type_nullable->getNestedType()); + } + else + nested_types.emplace_back(type); + } + + if (have_nullable) + { + return std::make_shared(getLeastSupertype(nested_types)); + } + } + /// Non-recursive rules std::unordered_set type_ids; diff --git a/tests/queries/0_stateless/01377_supertype_low_cardinality.reference b/tests/queries/0_stateless/01377_supertype_low_cardinality.reference new file mode 100644 index 00000000000..89c8606dd33 --- /dev/null +++ b/tests/queries/0_stateless/01377_supertype_low_cardinality.reference @@ -0,0 +1,71 @@ +hello +hello +String +String +--- +--- +hello +hello +hello +hello +--- +hello +hello +- +hello +hello +- +hello +hello +- +hello +hello +- +hello +hello +- +hello +hello +- +hello +hello +- +hello +hello +- +hello +hello +- +hello +hello +- +hello +hello +- +hello +hello +--- +hello +hello +hello +- +hello +hello +hello +- +hello +hello +hello +- +hello +hello +hello +--- +hello +hello +hello +hello +--- +['abc','def'] +['abc','def'] +['abc','def'] diff --git a/tests/queries/0_stateless/01377_supertype_low_cardinality.sql b/tests/queries/0_stateless/01377_supertype_low_cardinality.sql new file mode 100644 index 00000000000..9e7ed1f98b2 --- /dev/null +++ b/tests/queries/0_stateless/01377_supertype_low_cardinality.sql @@ -0,0 +1,71 @@ +SELECT 'hello' UNION ALL SELECT toLowCardinality('hello'); +SELECT toTypeName(x) FROM (SELECT 'hello' AS x UNION ALL SELECT toLowCardinality('hello')); + +SELECT '---'; + +create temporary table t1(a String); +create temporary table t2(a LowCardinality(String)); +select a from t1 union all select a from t2; + +SELECT '---'; + +CREATE TEMPORARY TABLE a (x String); +CREATE TEMPORARY TABLE b (x LowCardinality(String)); +CREATE TEMPORARY TABLE c (x Nullable(String)); +CREATE TEMPORARY TABLE d (x LowCardinality(Nullable(String))); + +INSERT INTO a VALUES ('hello'); +INSERT INTO b VALUES ('hello'); +INSERT INTO c VALUES ('hello'); +INSERT INTO d VALUES ('hello'); + +SELECT x FROM a; +SELECT x FROM b; +SELECT x FROM c; +SELECT x FROM d; + +SELECT '---'; + +SELECT x FROM a UNION ALL SELECT x FROM b; +SELECT '-'; +SELECT x FROM a UNION ALL SELECT x FROM c; +SELECT '-'; +SELECT x FROM a UNION ALL SELECT x FROM d; +SELECT '-'; +SELECT x FROM b UNION ALL SELECT x FROM a; +SELECT '-'; +SELECT x FROM b UNION ALL SELECT x FROM c; +SELECT '-'; +SELECT x FROM b UNION ALL SELECT x FROM d; +SELECT '-'; +SELECT x FROM c UNION ALL SELECT x FROM a; +SELECT '-'; +SELECT x FROM c UNION ALL SELECT x FROM b; +SELECT '-'; +SELECT x FROM c UNION ALL SELECT x FROM d; +SELECT '-'; +SELECT x FROM d UNION ALL SELECT x FROM a; +SELECT '-'; +SELECT x FROM d UNION ALL SELECT x FROM c; +SELECT '-'; +SELECT x FROM d UNION ALL SELECT x FROM b; + +SELECT '---'; + +SELECT x FROM b UNION ALL SELECT x FROM c UNION ALL SELECT x FROM d; +SELECT '-'; +SELECT x FROM a UNION ALL SELECT x FROM c UNION ALL SELECT x FROM d; +SELECT '-'; +SELECT x FROM a UNION ALL SELECT x FROM b UNION ALL SELECT x FROM d; +SELECT '-'; +SELECT x FROM a UNION ALL SELECT x FROM b UNION ALL SELECT x FROM c; + +SELECT '---'; + +SELECT x FROM a UNION ALL SELECT x FROM b UNION ALL SELECT x FROM c UNION ALL SELECT x FROM d; + +SELECT '---'; + +SELECT [CAST('abc' AS LowCardinality(String)), CAST('def' AS Nullable(String))]; +SELECT [CAST('abc' AS LowCardinality(String)), CAST('def' AS FixedString(3))]; +SELECT [CAST('abc' AS LowCardinality(String)), CAST('def' AS LowCardinality(FixedString(3)))];