mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 07:31:57 +00:00
Merge pull request #28530 from kitaisreal/dict-get-default-implementation-for-nulls
Function dictGet default implementation for nulls
This commit is contained in:
commit
f076cc69b4
@ -321,21 +321,32 @@ public:
|
||||
|
||||
Strings attribute_names = getAttributeNamesFromColumn(arguments[1].column, arguments[1].type);
|
||||
|
||||
DataTypes types;
|
||||
|
||||
auto dictionary_structure = helper.getDictionaryStructure(dictionary_name);
|
||||
|
||||
DataTypes attribute_types;
|
||||
attribute_types.reserve(attribute_names.size());
|
||||
for (auto & attribute_name : attribute_names)
|
||||
{
|
||||
/// We're extracting the return type from the dictionary's config, without loading the dictionary.
|
||||
auto attribute = dictionary_structure.getAttribute(attribute_name);
|
||||
types.emplace_back(attribute.type);
|
||||
const auto & attribute = dictionary_structure.getAttribute(attribute_name);
|
||||
attribute_types.emplace_back(attribute.type);
|
||||
}
|
||||
|
||||
if (types.size() > 1)
|
||||
return std::make_shared<DataTypeTuple>(types, attribute_names);
|
||||
bool key_is_nullable = arguments[2].type->isNullable();
|
||||
if (attribute_types.size() > 1)
|
||||
{
|
||||
if (key_is_nullable)
|
||||
throw Exception(ErrorCodes::UNSUPPORTED_METHOD, "Function {} support nullable key only for single dictionary attribute", getName());
|
||||
|
||||
return std::make_shared<DataTypeTuple>(attribute_types, attribute_names);
|
||||
}
|
||||
else
|
||||
return types.front();
|
||||
{
|
||||
if (key_is_nullable)
|
||||
return makeNullable(attribute_types.front());
|
||||
else
|
||||
return attribute_types.front();
|
||||
}
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
@ -418,15 +429,26 @@ public:
|
||||
default_cols = tuple_column->getColumnsCopy();
|
||||
}
|
||||
else
|
||||
{
|
||||
default_cols.emplace_back(result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < attribute_names.size(); ++i)
|
||||
default_cols.emplace_back(nullptr);
|
||||
}
|
||||
|
||||
const auto & key_col_with_type = arguments[2];
|
||||
auto key_col_with_type = arguments[2];
|
||||
|
||||
bool key_is_only_null = key_col_with_type.type->onlyNull();
|
||||
if (key_is_only_null)
|
||||
return result_type->createColumnConstWithDefaultValue(input_rows_count);
|
||||
|
||||
bool key_is_nullable = key_col_with_type.type->isNullable();
|
||||
if (key_is_nullable)
|
||||
key_col_with_type = columnGetNested(key_col_with_type);
|
||||
|
||||
auto key_column = key_col_with_type.column;
|
||||
|
||||
Columns key_columns;
|
||||
@ -482,7 +504,26 @@ public:
|
||||
key_types.emplace_back(range_col_type);
|
||||
}
|
||||
|
||||
return executeDictionaryRequest(dictionary, attribute_names, key_columns, key_types, result_type, default_cols);
|
||||
DataTypePtr attribute_type = result_type;
|
||||
if (key_is_nullable)
|
||||
{
|
||||
DataTypes attribute_types;
|
||||
attribute_types.reserve(attribute_names.size());
|
||||
for (auto & attribute_name : attribute_names)
|
||||
{
|
||||
const auto & attribute = dictionary->getStructure().getAttribute(attribute_name);
|
||||
attribute_types.emplace_back(attribute.type);
|
||||
}
|
||||
|
||||
attribute_type = attribute_types.front();
|
||||
}
|
||||
|
||||
auto result_column = executeDictionaryRequest(dictionary, attribute_names, key_columns, key_types, attribute_type, default_cols);
|
||||
|
||||
if (key_is_nullable)
|
||||
result_column = wrapInNullable(result_column, {arguments[2]}, result_type, input_rows_count);
|
||||
|
||||
return result_column;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -511,12 +552,14 @@ private:
|
||||
result = ColumnTuple::create(std::move(result_columns));
|
||||
}
|
||||
else
|
||||
{
|
||||
result = dictionary->getColumn(
|
||||
attribute_names[0],
|
||||
result_type,
|
||||
key_columns,
|
||||
key_types,
|
||||
default_cols.front());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -526,7 +569,9 @@ private:
|
||||
Strings attribute_names;
|
||||
|
||||
if (const auto * name_col = checkAndGetColumnConst<ColumnString>(column.get()))
|
||||
{
|
||||
attribute_names.emplace_back(name_col->getValue<String>());
|
||||
}
|
||||
else if (const auto * tuple_col_const = checkAndGetColumnConst<ColumnTuple>(column.get()))
|
||||
{
|
||||
const ColumnTuple & tuple_col = assert_cast<const ColumnTuple &>(tuple_col_const->getDataColumn());
|
||||
@ -551,10 +596,12 @@ private:
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Illegal type {} of second argument of function {}, expected a const string or const tuple of const strings.",
|
||||
type->getName(),
|
||||
getName());
|
||||
}
|
||||
|
||||
return attribute_names;
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
Non nullable value only null key
|
||||
\N
|
||||
Non nullable value nullable key
|
||||
Test
|
||||
\N
|
||||
|
||||
Nullable value only null key
|
||||
\N
|
||||
Nullable value nullable key
|
||||
Test
|
||||
\N
|
||||
\N
|
||||
\N
|
29
tests/queries/0_stateless/2014_dict_get_nullable_key.sql
Normal file
29
tests/queries/0_stateless/2014_dict_get_nullable_key.sql
Normal file
@ -0,0 +1,29 @@
|
||||
DROP TABLE IF EXISTS dictionary_non_nullable_source_table;
|
||||
CREATE TABLE dictionary_non_nullable_source_table (id UInt64, value String) ENGINE=TinyLog;
|
||||
INSERT INTO dictionary_non_nullable_source_table VALUES (0, 'Test');
|
||||
|
||||
DROP DICTIONARY IF EXISTS test_dictionary_non_nullable;
|
||||
CREATE DICTIONARY test_dictionary_non_nullable (id UInt64, value String) PRIMARY KEY id LAYOUT(DIRECT()) SOURCE(CLICKHOUSE(TABLE 'dictionary_non_nullable_source_table'));
|
||||
|
||||
SELECT 'Non nullable value only null key ';
|
||||
SELECT dictGet('test_dictionary_non_nullable', 'value', NULL);
|
||||
SELECT 'Non nullable value nullable key';
|
||||
SELECT dictGet('test_dictionary_non_nullable', 'value', arrayJoin([toUInt64(0), NULL, 1]));
|
||||
|
||||
DROP DICTIONARY test_dictionary_non_nullable;
|
||||
DROP TABLE dictionary_non_nullable_source_table;
|
||||
|
||||
DROP TABLE IF EXISTS dictionary_nullable_source_table;
|
||||
CREATE TABLE dictionary_nullable_source_table (id UInt64, value Nullable(String)) ENGINE=TinyLog;
|
||||
INSERT INTO dictionary_nullable_source_table VALUES (0, 'Test'), (1, NULL);
|
||||
|
||||
DROP DICTIONARY IF EXISTS test_dictionary_nullable;
|
||||
CREATE DICTIONARY test_dictionary_nullable (id UInt64, value Nullable(String)) PRIMARY KEY id LAYOUT(DIRECT()) SOURCE(CLICKHOUSE(TABLE 'dictionary_nullable_source_table'));
|
||||
|
||||
SELECT 'Nullable value only null key ';
|
||||
SELECT dictGet('test_dictionary_nullable', 'value', NULL);
|
||||
SELECT 'Nullable value nullable key';
|
||||
SELECT dictGet('test_dictionary_nullable', 'value', arrayJoin([toUInt64(0), NULL, 1, 2]));
|
||||
|
||||
DROP DICTIONARY test_dictionary_nullable;
|
||||
DROP TABLE dictionary_nullable_source_table;
|
Loading…
Reference in New Issue
Block a user