[Test](function) not unpack when else column is const null in IF function (#22419)
This commit is contained in:
@ -157,11 +157,13 @@ public:
|
||||
}
|
||||
|
||||
DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
|
||||
DataTypePtr type = nullptr;
|
||||
get_least_supertype(DataTypes {arguments[1], arguments[2]}, &type);
|
||||
DCHECK_NE(type, nullptr) << " arguments[1]: " << arguments[1]->get_name()
|
||||
<< " arguments[2]: " << arguments[2]->get_name();
|
||||
return type;
|
||||
// if return type is custom, one of nullable return type will be nullable
|
||||
bool nullable = arguments[1]->is_nullable() || arguments[2]->is_nullable();
|
||||
if (nullable) {
|
||||
return make_nullable(arguments[1]);
|
||||
} else {
|
||||
return arguments[1];
|
||||
}
|
||||
}
|
||||
|
||||
static ColumnPtr materialize_column_if_const(const ColumnPtr& column) {
|
||||
@ -293,7 +295,9 @@ public:
|
||||
bool then_is_null = arg_then.column->only_null();
|
||||
bool else_is_null = arg_else.column->only_null();
|
||||
|
||||
if (!then_is_null && !else_is_null) return false;
|
||||
if (!then_is_null && !else_is_null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (then_is_null && else_is_null) {
|
||||
block.get_by_position(result).column =
|
||||
@ -309,24 +313,24 @@ public:
|
||||
/// If then is NULL, we create Nullable column with null mask OR-ed with condition.
|
||||
if (then_is_null) {
|
||||
if (cond_col) {
|
||||
if (is_column_nullable(*arg_else.column)) {
|
||||
if (is_column_nullable(*arg_else.column)) { // if(cond, null, nullable)
|
||||
auto arg_else_column = arg_else.column;
|
||||
auto result_column = (*std::move(arg_else_column)).mutate();
|
||||
assert_cast<ColumnNullable&>(*result_column)
|
||||
.apply_null_map(assert_cast<const ColumnUInt8&>(*arg_cond.column));
|
||||
block.replace_by_position(result, std::move(result_column));
|
||||
} else {
|
||||
} else { // if(cond, null, not_nullable)
|
||||
block.replace_by_position(
|
||||
result,
|
||||
ColumnNullable::create(materialize_column_if_const(arg_else.column),
|
||||
arg_cond.column));
|
||||
}
|
||||
} else if (cond_const_col) {
|
||||
if (cond_const_col->get_value<UInt8>()) {
|
||||
if (cond_const_col->get_value<UInt8>()) { // if(true, null, else)
|
||||
block.get_by_position(result).column =
|
||||
block.get_by_position(result).type->create_column()->clone_resized(
|
||||
input_rows_count);
|
||||
} else {
|
||||
} else { // if(false, null, else)
|
||||
block.get_by_position(result).column =
|
||||
make_nullable_column_if_not(arg_else.column);
|
||||
}
|
||||
@ -353,24 +357,24 @@ public:
|
||||
negated_null_map_data[i] = !null_map_data[i];
|
||||
}
|
||||
|
||||
if (is_column_nullable(*arg_then.column)) {
|
||||
if (is_column_nullable(*arg_then.column)) { // if(cond, nullable, NULL)
|
||||
auto arg_then_column = arg_then.column;
|
||||
auto result_column = (*std::move(arg_then_column)).mutate();
|
||||
assert_cast<ColumnNullable&>(*result_column)
|
||||
.apply_negated_null_map(
|
||||
assert_cast<const ColumnUInt8&>(*arg_cond.column));
|
||||
block.replace_by_position(result, std::move(result_column));
|
||||
} else {
|
||||
} else { // if(cond, not_nullable, NULL)
|
||||
block.replace_by_position(
|
||||
result,
|
||||
ColumnNullable::create(materialize_column_if_const(arg_then.column),
|
||||
std::move(negated_null_map)));
|
||||
}
|
||||
} else if (cond_const_col) {
|
||||
if (cond_const_col->get_value<UInt8>()) {
|
||||
if (cond_const_col->get_value<UInt8>()) { // if(true, then, NULL)
|
||||
block.get_by_position(result).column =
|
||||
make_nullable_column_if_not(arg_then.column);
|
||||
} else {
|
||||
} else { // if(false, then, NULL)
|
||||
block.get_by_position(result).column =
|
||||
block.get_by_position(result).type->create_column()->clone_resized(
|
||||
input_rows_count);
|
||||
@ -395,7 +399,9 @@ public:
|
||||
auto* then_is_nullable = check_and_get_column<ColumnNullable>(*arg_then.column);
|
||||
auto* else_is_nullable = check_and_get_column<ColumnNullable>(*arg_else.column);
|
||||
|
||||
if (!then_is_nullable && !else_is_nullable) return false;
|
||||
if (!then_is_nullable && !else_is_nullable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Calculate null mask of result and nested column separately.
|
||||
*/
|
||||
@ -439,6 +445,7 @@ public:
|
||||
}
|
||||
|
||||
bool execute_for_null_condition(FunctionContext* context, Block& block,
|
||||
const ColumnNumbers& arguments,
|
||||
const ColumnWithTypeAndName& arg_cond,
|
||||
const ColumnWithTypeAndName& arg_then,
|
||||
const ColumnWithTypeAndName& arg_else, size_t result) {
|
||||
@ -459,19 +466,13 @@ public:
|
||||
((ColumnVector<UInt8>&)(nullable->get_nested_column())).get_data().data();
|
||||
auto rows = nullable->size();
|
||||
for (size_t i = 0; i < rows; i++) {
|
||||
nested_bool_data[i] = null_map[i] ? false : nested_bool_data[i];
|
||||
nested_bool_data[i] = null_map[i] ? 0 : nested_bool_data[i];
|
||||
}
|
||||
auto column_size = block.columns();
|
||||
block.insert({nullable->get_nested_column_ptr(), remove_nullable(arg_cond.type),
|
||||
arg_cond.name});
|
||||
|
||||
Block temporary_block {{nullable->get_nested_column_ptr(),
|
||||
remove_nullable(arg_cond.type), arg_cond.name},
|
||||
arg_then,
|
||||
arg_else,
|
||||
block.get_by_position(result)};
|
||||
|
||||
execute_impl(context, temporary_block, {0, 1, 2}, 3, rows);
|
||||
|
||||
block.get_by_position(result).column =
|
||||
std::move(temporary_block.get_by_position(3).column);
|
||||
execute_impl(context, block, {column_size, arguments[1], arguments[2]}, result, rows);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -493,21 +494,9 @@ public:
|
||||
cond_column.column = materialize_column_if_const(cond_column.column);
|
||||
const ColumnWithTypeAndName& arg_cond = block.get_by_position(arguments[0]);
|
||||
|
||||
if (auto* then_is_const = check_and_get_column<ColumnConst>(*arg_then.column)) {
|
||||
if (check_and_get_column<ColumnNullable>(then_is_const->get_data_column())) {
|
||||
ColumnWithTypeAndName& then_column = block.get_by_position(arguments[1]);
|
||||
then_column.column = materialize_column_if_const(then_column.column);
|
||||
}
|
||||
}
|
||||
if (auto* else_is_const = check_and_get_column<ColumnConst>(*arg_else.column)) {
|
||||
if (check_and_get_column<ColumnNullable>(else_is_const->get_data_column())) {
|
||||
ColumnWithTypeAndName& else_column = block.get_by_position(arguments[2]);
|
||||
else_column.column = materialize_column_if_const(else_column.column);
|
||||
}
|
||||
}
|
||||
|
||||
Status ret = Status::OK();
|
||||
if (execute_for_null_condition(context, block, arg_cond, arg_then, arg_else, result) ||
|
||||
if (execute_for_null_condition(context, block, arguments, arg_cond, arg_then, arg_else,
|
||||
result) ||
|
||||
execute_for_null_then_else(context, block, arg_cond, arg_then, arg_else, result,
|
||||
input_rows_count, ret) ||
|
||||
execute_for_nullable_then_else(context, block, arg_cond, arg_then, arg_else, result,
|
||||
|
||||
Reference in New Issue
Block a user