Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/iceberg/expression/predicate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -267,13 +267,18 @@ Result<std::shared_ptr<Expression>> UnboundPredicateImpl<B>::BindUnaryOperation(
if (!bound_term->MayProduceNull()) {
return Expressions::AlwaysFalse();
}
// TODO(gangwu): deal with UnknownType
if (bound_term->type()->type_id() == TypeId::kUnknown) {
return Expressions::AlwaysTrue();
Comment thread
ggyuchive marked this conversation as resolved.
}
return BoundUnaryPredicate::Make(Expression::Operation::kIsNull,
std::move(bound_term));
case Expression::Operation::kNotNull:
if (!bound_term->MayProduceNull()) {
return Expressions::AlwaysTrue();
}
if (bound_term->type()->type_id() == TypeId::kUnknown) {
return Expressions::AlwaysFalse();
}
return BoundUnaryPredicate::Make(Expression::Operation::kNotNull,
std::move(bound_term));
case Expression::Operation::kIsNan:
Expand Down
21 changes: 20 additions & 1 deletion src/iceberg/test/predicate_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class PredicateTest : public ::testing::Test {
SchemaField::MakeRequired(3, "age", int32()),
SchemaField::MakeOptional(4, "salary", float64()),
SchemaField::MakeRequired(5, "active", boolean()),
SchemaField::MakeRequired(6, "age2", int32())},
SchemaField::MakeRequired(6, "age2", int32()),
SchemaField::MakeOptional(7, "always_null", unknown())},
/*schema_id=*/0);
}

Expand Down Expand Up @@ -365,6 +366,24 @@ TEST_F(PredicateTest, UnboundPredicateBindUnary) {
EXPECT_EQ(bound_is_null->op(), Expression::Operation::kFalse);
}

TEST_F(PredicateTest, UnboundPredicateBindUnaryWithUnknownType) {
// Test IS NULL on unknown type field - should return AlwaysTrue
auto is_null_unknown = Expressions::IsNull("always_null"); // always_null is unknown
auto bound_is_null_result = is_null_unknown->Bind(*schema_, /*case_sensitive=*/true);
ASSERT_THAT(bound_is_null_result, IsOk());

auto bound_is_null = bound_is_null_result.value();
EXPECT_EQ(bound_is_null->op(), Expression::Operation::kTrue);

// Test NOT NULL on unknown type field - should return AlwaysFalse
auto not_null_unknown = Expressions::NotNull("always_null");
auto bound_not_null_result = not_null_unknown->Bind(*schema_, /*case_sensitive=*/true);
ASSERT_THAT(bound_not_null_result, IsOk());

auto bound_not_null = bound_not_null_result.value();
EXPECT_EQ(bound_not_null->op(), Expression::Operation::kFalse);
}

TEST_F(PredicateTest, UnboundPredicateBindLiteral) {
auto equal_pred = Expressions::Equal("age", Literal::Int(25));
auto bound_result = equal_pred->Bind(*schema_, /*case_sensitive=*/true);
Expand Down
Loading