From 3cdf3d0396f5f755ebdfc8bcef7658a06669f405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Poyraz=20K=C3=BC=C3=A7=C3=BCkarslan?= <83272398+PoyrazK@users.noreply.github.com> Date: Sun, 19 Apr 2026 20:04:06 +0300 Subject: [PATCH 1/2] test(expression): add InExpr edge case tests (duplicates, many values, NULL) --- tests/expression_tests.cpp | 65 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tests/expression_tests.cpp b/tests/expression_tests.cpp index b8b1b316..32d1cddb 100644 --- a/tests/expression_tests.cpp +++ b/tests/expression_tests.cpp @@ -569,4 +569,69 @@ TEST(ExpressionTests, ParameterExprType) { EXPECT_EQ(expr.type(), ExprType::Parameter); } +// ============= InExpr Edge Case Tests ============= + +TEST(ExpressionTests, InExprWithDuplicates) { + // Column value appears multiple times in IN list + auto column = std::make_unique(Value::make_int64(5)); + std::vector> values; + values.push_back(std::make_unique(Value::make_int64(5))); + values.push_back(std::make_unique(Value::make_int64(5))); // duplicate + values.push_back(std::make_unique(Value::make_int64(5))); // duplicate + + InExpr expr(std::move(column), std::move(values), false); + auto result = expr.evaluate(); + EXPECT_TRUE(result.as_bool()); // 5 IN (5, 5, 5) = true +} + +TEST(ExpressionTests, InExprWithManyValues) { + // IN with many values (10) + auto column = std::make_unique(Value::make_int64(7)); + std::vector> values; + for (int i = 1; i <= 10; i++) { + values.push_back(std::make_unique(Value::make_int64(i))); + } + + InExpr expr(std::move(column), std::move(values), false); + auto result = expr.evaluate(); + EXPECT_TRUE(result.as_bool()); // 7 IN (1..10) = true +} + +TEST(ExpressionTests, InExprNotWithManyValues) { + // NOT IN with many values where value is not present + auto column = std::make_unique(Value::make_int64(15)); + std::vector> values; + for (int i = 1; i <= 10; i++) { + values.push_back(std::make_unique(Value::make_int64(i))); + } + + InExpr expr(std::move(column), std::move(values), true); // NOT IN + auto result = expr.evaluate(); + EXPECT_TRUE(result.as_bool()); // 15 NOT IN (1..10) = true +} + +TEST(ExpressionTests, InExprWithNullInList) { + // IN list containing NULL - SQL semantics: 5 IN (1, NULL, 10) = false + // because 5 == NULL is NULL (not true), so NULL doesn't match + auto column = std::make_unique(Value::make_int64(5)); + std::vector> values; + values.push_back(std::make_unique(Value::make_int64(1))); + values.push_back(std::make_unique(Value::make_null())); // NULL in list + values.push_back(std::make_unique(Value::make_int64(10))); + + InExpr expr(std::move(column), std::move(values), false); + auto result = expr.evaluate(); + EXPECT_FALSE(result.as_bool()); // 5 IN (1, NULL, 10) = false (NULL doesn't match) +} + +TEST(ExpressionTests, InExprEmptyList) { + // IN with empty list + auto column = std::make_unique(Value::make_int64(5)); + std::vector> values; // empty + + InExpr expr(std::move(column), std::move(values), false); + auto result = expr.evaluate(); + EXPECT_FALSE(result.as_bool()); // 5 IN () = false +} + } // namespace From a6b3dd45661a3aa33e6105cb3a212e7b23dbd178 Mon Sep 17 00:00:00 2001 From: poyrazK <83272398+poyrazK@users.noreply.github.com> Date: Sun, 19 Apr 2026 17:05:46 +0000 Subject: [PATCH 2/2] style: automated clang-format fixes --- tests/operator_tests.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/operator_tests.cpp b/tests/operator_tests.cpp index 6f6574f7..9bc9f8ca 100644 --- a/tests/operator_tests.cpp +++ b/tests/operator_tests.cpp @@ -794,7 +794,8 @@ TEST_F(OperatorTests, HashJoinRightOuter) { // RIGHT join output: matched rows + unmatched right rows with NULLs // Matched: (2, 2) // Unmatched right: (NULL, 3), (NULL, 4) - std::vector> results; // (left_value, right_value); use INT64_MIN as sentinel for NULL + std::vector> + results; // (left_value, right_value); use INT64_MIN as sentinel for NULL Tuple tuple; while (join->next(tuple)) { int64_t left_val = tuple.get(0).is_null() ? INT64_MIN : tuple.get(0).to_int64(); @@ -880,11 +881,11 @@ TEST_F(OperatorTests, HashJoinNullKeys) { Schema left_schema = make_schema({{"id", common::ValueType::TYPE_INT64}}); std::vector left_data; left_data.push_back(make_tuple({common::Value::make_int64(1)})); // matches 1 - left_data.push_back(make_tuple({common::Value()})); // NULL - currently matches NULL + left_data.push_back(make_tuple({common::Value()})); // NULL - currently matches NULL Schema right_schema = make_schema({{"id", common::ValueType::TYPE_INT64}}); std::vector right_data; - right_data.push_back(make_tuple({common::Value()})); // NULL - currently matches + right_data.push_back(make_tuple({common::Value()})); // NULL - currently matches right_data.push_back(make_tuple({common::Value::make_int64(1)})); // matches 1 auto left_scan = make_buffer_scan("left_table", left_data, left_schema);