From 943b71e4ff61d0a4da58f7feb89df30187232bc8 Mon Sep 17 00:00:00 2001 From: vdimir Date: Mon, 30 Aug 2021 14:05:47 +0300 Subject: [PATCH] Fix non joined rows from nullable column --- src/Interpreters/join_common.cpp | 39 ++++++++++++++++--- .../00445_join_nullable_keys.reference | 10 +++++ .../0_stateless/00445_join_nullable_keys.sql | 10 +++++ ...1142_join_lc_and_nullable_in_key.reference | 5 +++ .../01142_join_lc_and_nullable_in_key.sql | 9 +++++ 5 files changed, 68 insertions(+), 5 deletions(-) diff --git a/src/Interpreters/join_common.cpp b/src/Interpreters/join_common.cpp index 9890a130c33..e97c4ab2f57 100644 --- a/src/Interpreters/join_common.cpp +++ b/src/Interpreters/join_common.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include @@ -30,12 +29,42 @@ namespace ErrorCodes namespace { +void insertFromNullableOrDefault(MutableColumnPtr & dst, const ColumnNullable * nullable_col) +{ + + const auto & nested = nullable_col->getNestedColumn(); + const auto & nullmap = nullable_col->getNullMapColumn().getData(); + if (auto * lc = typeid_cast(dst.get()); lc && !nested.lowCardinality()) + { + for (size_t i = 0; i < nullable_col->size(); ++i) + { + if (nullmap[i]) + lc->insertDefault(); + else + lc->insertRangeFromFullColumn(nested, i, 1); + } + } + else + { + for (size_t i = 0; i < nullable_col->size(); ++i) + { + if (nullmap[i]) + dst->insertDefault(); + else + dst->insertFrom(nested, i); + } + } +} + ColumnPtr changeLowCardinality(const ColumnPtr & column, const ColumnPtr & dst_sample) { if (dst_sample->lowCardinality()) { MutableColumnPtr lc = dst_sample->cloneEmpty(); - typeid_cast(*lc).insertRangeFromFullColumn(*column, 0, column->size()); + if (const auto * nullable_col = typeid_cast(column.get())) + insertFromNullableOrDefault(lc, nullable_col); + else + typeid_cast(*lc).insertRangeFromFullColumn(*column, 0, column->size()); return lc; } @@ -190,9 +219,9 @@ void removeColumnNullability(ColumnWithTypeAndName & column) if (column.column && column.column->isNullable()) { - const auto * nullable_column = checkAndGetColumn(*column.column); - ColumnPtr nested_column = nullable_column->getNestedColumnPtr(); - MutableColumnPtr mutable_column = IColumn::mutate(std::move(nested_column)); + const auto * nullable_col = checkAndGetColumn(*column.column); + MutableColumnPtr mutable_column = nullable_col->getNestedColumn().cloneEmpty(); + insertFromNullableOrDefault(mutable_column, nullable_col); column.column = std::move(mutable_column); } } diff --git a/tests/queries/0_stateless/00445_join_nullable_keys.reference b/tests/queries/0_stateless/00445_join_nullable_keys.reference index f7675766dc9..afc8003910c 100644 --- a/tests/queries/0_stateless/00445_join_nullable_keys.reference +++ b/tests/queries/0_stateless/00445_join_nullable_keys.reference @@ -22,3 +22,13 @@ 13 13 14 14 \N 8 +0 0 +0 2 +0 4 +0 6 +0 8 +1 1 +3 3 +5 5 +7 7 +9 9 diff --git a/tests/queries/0_stateless/00445_join_nullable_keys.sql b/tests/queries/0_stateless/00445_join_nullable_keys.sql index 2b8f2ca5f44..a0453356e98 100644 --- a/tests/queries/0_stateless/00445_join_nullable_keys.sql +++ b/tests/queries/0_stateless/00445_join_nullable_keys.sql @@ -30,3 +30,13 @@ ANY RIGHT JOIN ( SELECT nullIf(number, 8) AS k, toString(number) AS b FROM system.numbers LIMIT 5, 10 ) js2 USING (k) ORDER BY k; + +SELECT k, b +FROM +( + SELECT number + 1 AS k FROM numbers(10) +) js1 +RIGHT JOIN +( + SELECT nullIf(number, if(number % 2 == 0, number, 0)) AS k, number AS b FROM numbers(10) +) js2 USING (k) ORDER BY k, b; diff --git a/tests/queries/0_stateless/01142_join_lc_and_nullable_in_key.reference b/tests/queries/0_stateless/01142_join_lc_and_nullable_in_key.reference index c6bdcb773b2..01efbb7c64b 100644 --- a/tests/queries/0_stateless/01142_join_lc_and_nullable_in_key.reference +++ b/tests/queries/0_stateless/01142_join_lc_and_nullable_in_key.reference @@ -13,6 +13,8 @@ 0 \N Nullable(String) 1 l \N Nullable(String) - +0 +- 1 l \N Nullable(String) 2 \N \N Nullable(String) 1 l \N Nullable(String) @@ -27,3 +29,6 @@ \N \N \N Nullable(String) 1 l \N Nullable(String) \N \N \N Nullable(String) +- +\N \N +- diff --git a/tests/queries/0_stateless/01142_join_lc_and_nullable_in_key.sql b/tests/queries/0_stateless/01142_join_lc_and_nullable_in_key.sql index edaf2870e89..38b72837174 100644 --- a/tests/queries/0_stateless/01142_join_lc_and_nullable_in_key.sql +++ b/tests/queries/0_stateless/01142_join_lc_and_nullable_in_key.sql @@ -27,6 +27,10 @@ SELECT x, lc, materialize(r.lc) y, toTypeName(y) FROM t AS l FULL JOIN nr AS r U SELECT '-'; +SELECT x, lc FROM t AS l RIGHT JOIN nr AS r USING (lc); + +SELECT '-'; + SET join_use_nulls = 1; SELECT x, lc, r.lc, toTypeName(r.lc) FROM t AS l LEFT JOIN nr AS r USING (x) ORDER BY x; @@ -45,6 +49,11 @@ SELECT x, lc, materialize(r.lc) y, toTypeName(y) FROM t AS l LEFT JOIN nr AS r U SELECT x, lc, materialize(r.lc) y, toTypeName(y) FROM t AS l RIGHT JOIN nr AS r USING (lc) ORDER BY x; SELECT x, lc, materialize(r.lc) y, toTypeName(y) FROM t AS l FULL JOIN nr AS r USING (lc) ORDER BY x; +SELECT '-'; + +SELECT x, lc FROM t AS l RIGHT JOIN nr AS r USING (lc); + +SELECT '-'; DROP TABLE t; DROP TABLE nr;