diff --git a/be/src/exprs/vexpr.cpp b/be/src/exprs/vexpr.cpp index 557d04a4e1f522..e49bb037865582 100644 --- a/be/src/exprs/vexpr.cpp +++ b/be/src/exprs/vexpr.cpp @@ -1074,16 +1074,10 @@ Status VExpr::execute_column(VExprContext* context, const Block* block, const Se if (!check_and_get_column(result_column.get())) { auto result_type = execute_type(block); if (result_type != nullptr) { - Status st = result_type->check_column(*result_column); - if (!st.ok()) { - // Nullable(T) may legitimately produce a non-nullable T column when all rows are - // non-null (use_default_implementation_for_nulls optimization). Allow this. - const auto* nullable_type = - check_and_get_data_type(result_type.get()); - if (nullable_type && !check_and_get_column(result_column.get())) { - st = nullable_type->get_nested_type()->check_column(*result_column); - } + if (result_type->is_nullable() && !result_column->is_nullable()) { + result_column = make_nullable(result_column, false); } + Status st = result_type->check_column(*result_column); if (!st.ok()) { return Status::InternalError( "Expr {} return column type mismatch: declared={}, actual={}", expr_name(), diff --git a/be/test/exprs/vexpr_test.cpp b/be/test/exprs/vexpr_test.cpp index 10bdfb815d7d57..6138fc89ea3489 100644 --- a/be/test/exprs/vexpr_test.cpp +++ b/be/test/exprs/vexpr_test.cpp @@ -893,11 +893,10 @@ TEST(VExprExecuteColumnTest, TypeMismatchFails) { EXPECT_FALSE(st.ok()); } -TEST(VExprExecuteColumnTest, NullableTypeWithNonNullableColumnPasses) { +TEST(VExprExecuteColumnTest, NullableTypeWithNonNullableColumnIsWrapped) { using namespace doris; FakeVExpr expr; - // Declared type is Nullable(Int32) but result is Int32 (non-nullable). - // This mirrors the use_default_implementation_for_nulls optimization and must pass. + // Declared type is Nullable(Int32), so the result must carry a nullable column wrapper. expr.set_data_type(std::make_shared(std::make_shared())); auto col = ColumnInt32::create(); @@ -907,6 +906,7 @@ TEST(VExprExecuteColumnTest, NullableTypeWithNonNullableColumnPasses) { ColumnPtr result; auto st = expr.execute_column(nullptr, nullptr, nullptr, 1, result); EXPECT_TRUE(st.ok()); + EXPECT_TRUE(result->is_nullable()); } TEST(VExprExecuteColumnTest, ColumnNothingPassesTypeCheck) {