Skip to content

Commit

Permalink
[Fix](Variant) fix element_at should return nullable if result type i…
Browse files Browse the repository at this point in the history
…s nullable
  • Loading branch information
eldenmoon committed Aug 21, 2024
1 parent afa5684 commit 9187270
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 2 deletions.
24 changes: 22 additions & 2 deletions be/src/vec/functions/function_variant_element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class FunctionVariantElement : public IFunction {
// Get function name.
String get_name() const override { return name; }

bool use_default_implementation_for_nulls() const override { return true; }
bool use_default_implementation_for_nulls() const override { return false; }

size_t get_number_of_arguments() const override { return 2; }

Expand All @@ -77,10 +77,27 @@ class FunctionVariantElement : public IFunction {
return make_nullable(std::make_shared<DataTypeObject>());
}

// wrap variant column with nullable
// 1. if variant is null root(empty or nothing as root), then nullable map is all null
// 2. if variant is scalar variant, then use the root's nullable map
// 3. if variant is hierarchical variant, then create a nullable map with all none null
ColumnPtr wrap_variant_nullable(ColumnPtr col) const {
const auto& var = assert_cast<const ColumnObject&>(*col);
if (var.is_null_root()) {
return make_nullable(col, true);
}
if (var.is_scalar_variant() && var.get_root()->is_nullable()) {
const auto* nullable = assert_cast<const ColumnNullable*>(var.get_root().get());
return ColumnNullable::create(
col, nullable->get_null_map_column_ptr()->clone_resized(col->size()));
}
return make_nullable(col);
}

Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
size_t result, size_t input_rows_count) const override {
const auto* variant_col = check_and_get_column<ColumnObject>(
block.get_by_position(arguments[0]).column.get());
remove_nullable(block.get_by_position(arguments[0]).column).get());
if (!variant_col) {
return Status::RuntimeError(
fmt::format("unsupported types for function {}({}, {})", get_name(),
Expand All @@ -95,6 +112,9 @@ class FunctionVariantElement : public IFunction {
auto index_column = block.get_by_position(arguments[1]).column;
ColumnPtr result_column;
RETURN_IF_ERROR(get_element_column(*variant_col, index_column, &result_column));
if (block.get_by_position(result).type->is_nullable()) {
result_column = wrap_variant_nullable(result_column);
}
block.replace_by_position(result, result_column);
return Status::OK();
}
Expand Down
4 changes: 4 additions & 0 deletions regression-test/data/variant_p0/element_function.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- This file is automatically generated. You should know what you did if you want to edit this
-- !sql --
1

32 changes: 32 additions & 0 deletions regression-test/suites/variant_p0/element_function.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

suite("regression_test_variant_element_at", "p0") {
sql """
CREATE TABLE IF NOT EXISTS element_fn_test(
k bigint,
v variant,
v1 variant not null,
)
UNIQUE KEY(`k`)
DISTRIBUTED BY HASH(k) BUCKETS 4
properties("replication_num" = "1");
"""

sql """insert into element_fn_test values (1, '{"arr1" : [1, 2, 3]}', '{"arr2" : [4, 5, 6]}')"""
qt_sql """select array_first((x,y) -> (x - y) < 0, cast(v['arr1'] as array<int>), cast(v1['arr2'] as array<int>)) from element_fn_test"""
}

0 comments on commit 9187270

Please sign in to comment.