From 4c573b36fe3eb67a9a7d0ebabeaa149f09fa9d8e Mon Sep 17 00:00:00 2001 From: Amos Bird Date: Tue, 15 Jun 2021 16:34:53 +0800 Subject: [PATCH] Fix joinGetOrNull with not-nullable columns --- src/Interpreters/HashJoin.cpp | 54 +++++++++++++------ src/Interpreters/HashJoin.h | 3 +- .../01240_join_get_or_null.reference | 5 ++ .../0_stateless/01240_join_get_or_null.sql | 11 ++++ 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/Interpreters/HashJoin.cpp b/src/Interpreters/HashJoin.cpp index 09c4c538347..6ec021ea290 100644 --- a/src/Interpreters/HashJoin.cpp +++ b/src/Interpreters/HashJoin.cpp @@ -680,7 +680,6 @@ namespace class AddedColumns { public: - struct TypeAndName { DataTypePtr type; @@ -688,24 +687,26 @@ public: String qualified_name; TypeAndName(DataTypePtr type_, const String & name_, const String & qualified_name_) - : type(type_) - , name(name_) - , qualified_name(qualified_name_) - {} + : type(type_), name(name_), qualified_name(qualified_name_) + { + } }; - AddedColumns(const Block & block_with_columns_to_add, - const Block & block, - const Block & saved_block_sample, - const HashJoin & join, - const ColumnRawPtrs & key_columns_, - const Sizes & key_sizes_, - bool is_asof_join) + AddedColumns( + const Block & block_with_columns_to_add, + const Block & block, + const Block & saved_block_sample, + const HashJoin & join, + const ColumnRawPtrs & key_columns_, + const Sizes & key_sizes_, + bool is_asof_join, + bool is_join_get_) : key_columns(key_columns_) , key_sizes(key_sizes_) , rows_to_add(block.rows()) , asof_type(join.getAsofType()) , asof_inequality(join.getAsofInequality()) + , is_join_get(is_join_get_) { size_t num_columns_to_add = block_with_columns_to_add.columns(); if (is_asof_join) @@ -749,8 +750,25 @@ public: if constexpr (has_defaults) applyLazyDefaults(); - for (size_t j = 0, size = right_indexes.size(); j < size; ++j) - columns[j]->insertFrom(*block.getByPosition(right_indexes[j]).column, row_num); + if (is_join_get) + { + /// If it's joinGetOrNull, we need to wrap not-nullable columns in StorageJoin. + for (size_t j = 0, size = right_indexes.size(); j < size; ++j) + { + const auto & column = *block.getByPosition(right_indexes[j]).column; + if (auto * nullable_col = typeid_cast(columns[j].get()); nullable_col && !column.isNullable()) + nullable_col->insertFromNotNullable(column, row_num); + else + columns[j]->insertFrom(column, row_num); + } + } + else + { + for (size_t j = 0, size = right_indexes.size(); j < size; ++j) + { + columns[j]->insertFrom(*block.getByPosition(right_indexes[j]).column, row_num); + } + } } void appendDefaultRow() @@ -787,6 +805,7 @@ private: std::optional asof_type; ASOF::Inequality asof_inequality; const IColumn * left_asof_key = nullptr; + bool is_join_get; void addColumn(const ColumnWithTypeAndName & src_column, const std::string & qualified_name) { @@ -1021,7 +1040,8 @@ void HashJoin::joinBlockImpl( Block & block, const Names & key_names_left, const Block & block_with_columns_to_add, - const Maps & maps_) const + const Maps & maps_, + bool is_join_get) const { constexpr bool is_any_join = STRICTNESS == ASTTableJoin::Strictness::Any; constexpr bool is_all_join = STRICTNESS == ASTTableJoin::Strictness::All; @@ -1065,7 +1085,7 @@ void HashJoin::joinBlockImpl( * For ASOF, the last column is used as the ASOF column */ - AddedColumns added_columns(block_with_columns_to_add, block, savedBlockSample(), *this, left_key_columns, key_sizes, is_asof_join); + AddedColumns added_columns(block_with_columns_to_add, block, savedBlockSample(), *this, left_key_columns, key_sizes, is_asof_join, is_join_get); bool has_required_right_keys = (required_right_keys.columns() != 0); added_columns.need_filter = need_filter || has_required_right_keys; @@ -1274,7 +1294,7 @@ ColumnWithTypeAndName HashJoin::joinGet(const Block & block, const Block & block static_assert(!MapGetter::flagged, "joinGet are not protected from hash table changes between block processing"); joinBlockImpl( - keys, key_names_right, block_with_columns_to_add, std::get(data->maps)); + keys, key_names_right, block_with_columns_to_add, std::get(data->maps), /* is_join_get */ true); return keys.getByPosition(keys.columns() - 1); } diff --git a/src/Interpreters/HashJoin.h b/src/Interpreters/HashJoin.h index 5ec8ed92f10..84c447d875e 100644 --- a/src/Interpreters/HashJoin.h +++ b/src/Interpreters/HashJoin.h @@ -400,7 +400,8 @@ private: Block & block, const Names & key_names_left, const Block & block_with_columns_to_add, - const Maps & maps) const; + const Maps & maps, + bool is_join_get = false) const; void joinBlockImplCross(Block & block, ExtraBlockPtr & not_processed) const; diff --git a/tests/queries/0_stateless/01240_join_get_or_null.reference b/tests/queries/0_stateless/01240_join_get_or_null.reference index 96e34d5a44c..322d026bea8 100644 --- a/tests/queries/0_stateless/01240_join_get_or_null.reference +++ b/tests/queries/0_stateless/01240_join_get_or_null.reference @@ -1,2 +1,7 @@ \N \N +1396-01-12 +1396-01-13 +\N +\N +\N diff --git a/tests/queries/0_stateless/01240_join_get_or_null.sql b/tests/queries/0_stateless/01240_join_get_or_null.sql index 48fd8228b55..b230cc7bb8d 100644 --- a/tests/queries/0_stateless/01240_join_get_or_null.sql +++ b/tests/queries/0_stateless/01240_join_get_or_null.sql @@ -11,3 +11,14 @@ DROP TABLE join_test; CREATE TABLE join_test (id UInt16, num Array(UInt16)) engine = Join(ANY, LEFT, id); SELECT joinGetOrNull('join_test', 'num', 500); -- { serverError 43 } DROP TABLE join_test; + +drop table if exists test; +create table test (x Date, y String) engine Join(ANY, LEFT, x); +insert into test values ('2017-04-01', '1396-01-12') ,('2017-04-02', '1396-01-13'); + +WITH + A as (SELECT rowNumberInAllBlocks() R, addDays(toDate('2017-04-01'), R) TVV from numbers(5)), + B as (SELECT rowNumberInAllBlocks() R, toDateTime(NULL) TVV from numbers(1)) +SELECT + joinGetOrNull('test', 'y', toDate(A.TVV) ) TV1 +from A LEFT JOIN B USING (R) order by TV1;