|
18 | 18 |
|
19 | 19 | #include <cstdint> |
20 | 20 | #include <map> |
| 21 | +#include <memory> |
| 22 | +#include <optional> |
21 | 23 | #include <utility> |
22 | 24 |
|
23 | 25 | #include "arrow/type.h" |
24 | 26 | #include "gtest/gtest.h" |
25 | 27 | #include "paimon/common/types/data_field.h" |
| 28 | +#include "paimon/common/types/row_kind.h" |
26 | 29 | #include "paimon/common/utils/fields_comparator.h" |
27 | 30 | #include "paimon/core/core_options.h" |
| 31 | +#include "paimon/core/key_value.h" |
| 32 | +#include "paimon/core/mergetree/compact/merge_function.h" |
28 | 33 | #include "paimon/defs.h" |
| 34 | +#include "paimon/memory/memory_pool.h" |
29 | 35 | #include "paimon/status.h" |
| 36 | +#include "paimon/testing/utils/binary_row_generator.h" |
| 37 | +#include "paimon/testing/utils/key_value_checker.h" |
30 | 38 | #include "paimon/testing/utils/testharness.h" |
31 | 39 |
|
32 | 40 | namespace paimon::test { |
@@ -54,4 +62,52 @@ TEST(PrimaryKeyTableUtilsTest, TestCreateSequenceFieldsComparator) { |
54 | 62 | } |
55 | 63 | } |
56 | 64 |
|
| 65 | +TEST(PrimaryKeyTableUtilsTest, TestCreateFirstRowMergeFunctionWithIgnoreDelete) { |
| 66 | + auto pool = GetDefaultPool(); |
| 67 | + auto value_schema = arrow::schema({arrow::field("v0", arrow::int32())}); |
| 68 | + |
| 69 | + // ignore-delete can also be configured through the merge-engine-specific |
| 70 | + // first-row.ignore-delete key, which must reach FirstRowMergeFunction the same way. |
| 71 | + for (const char* ignore_delete_key : |
| 72 | + {Options::IGNORE_DELETE, Options::FALLBACK_FIRST_ROW_IGNORE_DELETE}) { |
| 73 | + ASSERT_OK_AND_ASSIGN(CoreOptions core_options, |
| 74 | + CoreOptions::FromMap({{Options::MERGE_ENGINE, "first-row"}, |
| 75 | + {ignore_delete_key, "true"}})); |
| 76 | + ASSERT_OK_AND_ASSIGN( |
| 77 | + std::unique_ptr<MergeFunction> merge_function, |
| 78 | + PrimaryKeyTableUtils::CreateMergeFunction(value_schema, {"k0"}, core_options)); |
| 79 | + merge_function->Reset(); |
| 80 | + |
| 81 | + KeyValue insert_kv(RowKind::Insert(), /*sequence_number=*/0, /*level=*/0, /*key=*/ |
| 82 | + BinaryRowGenerator::GenerateRowPtr({10}, pool.get()), |
| 83 | + /*value=*/BinaryRowGenerator::GenerateRowPtr({100}, pool.get())); |
| 84 | + KeyValue delete_kv(RowKind::Delete(), /*sequence_number=*/1, /*level=*/0, /*key=*/ |
| 85 | + BinaryRowGenerator::GenerateRowPtr({10}, pool.get()), |
| 86 | + /*value=*/BinaryRowGenerator::GenerateRowPtr({200}, pool.get())); |
| 87 | + ASSERT_OK(merge_function->Add(std::move(insert_kv))); |
| 88 | + ASSERT_OK(merge_function->Add(std::move(delete_kv))); |
| 89 | + |
| 90 | + ASSERT_OK_AND_ASSIGN(std::optional<KeyValue> result_kv, merge_function->GetResult()); |
| 91 | + ASSERT_TRUE(result_kv.has_value()); |
| 92 | + KeyValue expected(RowKind::Insert(), /*sequence_number=*/0, /*level=*/0, /*key=*/ |
| 93 | + BinaryRowGenerator::GenerateRowPtr({10}, pool.get()), |
| 94 | + /*value=*/BinaryRowGenerator::GenerateRowPtr({100}, pool.get())); |
| 95 | + KeyValueChecker::CheckResult(expected, result_kv.value(), /*key_arity=*/1, |
| 96 | + /*value_arity=*/1); |
| 97 | + } |
| 98 | + |
| 99 | + // Without the option, the first-row merge engine still rejects retract records. |
| 100 | + ASSERT_OK_AND_ASSIGN(CoreOptions core_options, |
| 101 | + CoreOptions::FromMap({{Options::MERGE_ENGINE, "first-row"}})); |
| 102 | + ASSERT_OK_AND_ASSIGN( |
| 103 | + std::unique_ptr<MergeFunction> merge_function, |
| 104 | + PrimaryKeyTableUtils::CreateMergeFunction(value_schema, {"k0"}, core_options)); |
| 105 | + merge_function->Reset(); |
| 106 | + KeyValue delete_kv(RowKind::Delete(), /*sequence_number=*/0, /*level=*/0, /*key=*/ |
| 107 | + BinaryRowGenerator::GenerateRowPtr({10}, pool.get()), |
| 108 | + /*value=*/BinaryRowGenerator::GenerateRowPtr({100}, pool.get())); |
| 109 | + ASSERT_NOK_WITH_MSG(merge_function->Add(std::move(delete_kv)), |
| 110 | + "First row merge engine can not accept DELETE/UPDATE_BEFORE records"); |
| 111 | +} |
| 112 | + |
57 | 113 | } // namespace paimon::test |
0 commit comments