Skip to content

Commit f8c3ad2

Browse files
committed
feat(commit): align functionality with java paimon commit
1 parent f24a61b commit f8c3ad2

77 files changed

Lines changed: 6706 additions & 974 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

include/paimon/commit_context.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class PAIMON_EXPORT CommitContext {
3737
public:
3838
CommitContext(const std::string& root_path, const std::string& commit_user,
3939
bool ignore_empty_commit, bool use_rest_catalog_commit,
40-
const std::shared_ptr<MemoryPool>& memory_pool,
40+
bool append_commit_check_conflict, const std::shared_ptr<MemoryPool>& memory_pool,
4141
const std::shared_ptr<Executor>& executor,
4242
const std::shared_ptr<FileSystem>& specific_file_system,
4343
const std::map<std::string, std::string>& options);
@@ -59,6 +59,10 @@ class PAIMON_EXPORT CommitContext {
5959
return use_rest_catalog_commit_;
6060
}
6161

62+
bool AppendCommitCheckConflict() const {
63+
return append_commit_check_conflict_;
64+
}
65+
6266
std::shared_ptr<MemoryPool> GetMemoryPool() const {
6367
return memory_pool_;
6468
}
@@ -80,6 +84,7 @@ class PAIMON_EXPORT CommitContext {
8084
std::string commit_user_;
8185
bool ignore_empty_commit_;
8286
bool use_rest_catalog_commit_;
87+
bool append_commit_check_conflict_;
8388
std::shared_ptr<MemoryPool> memory_pool_;
8489
std::shared_ptr<Executor> executor_;
8590
std::shared_ptr<FileSystem> specific_file_system_;
@@ -125,6 +130,11 @@ class PAIMON_EXPORT CommitContextBuilder {
125130
/// @return Reference to this builder for method chaining.
126131
CommitContextBuilder& UseRESTCatalogCommit(bool use_rest_catalog_commit);
127132

133+
/// Sets whether append commits should perform conflict checking (default is false).
134+
/// @param append_commit_check_conflict True to enable append conflict checks.
135+
/// @return Reference to this builder for method chaining.
136+
CommitContextBuilder& AppendCommitCheckConflict(bool append_commit_check_conflict);
137+
128138
/// Sets the memory pool to be used for memory allocation during commit operations.
129139
/// @param memory_pool Shared pointer to the memory pool instance.
130140
/// @return Reference to this builder for method chaining.

include/paimon/defs.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,16 @@ struct PAIMON_EXPORT Options {
235235
/// "commit.max-retries" - Maximum number of retries when commit failed. Default value is 10.
236236
static const char COMMIT_MAX_RETRIES[];
237237

238+
/// "commit.min-retry-wait" - Min retry wait time when commit failed. Default value is 10ms.
239+
static const char COMMIT_MIN_RETRY_WAIT[];
240+
241+
/// "commit.max-retry-wait" - Max retry wait time when commit failed. Default value is 10s.
242+
static const char COMMIT_MAX_RETRY_WAIT[];
243+
244+
/// "commit.discard-duplicate-files" - Whether to discard duplicate files in commit.
245+
/// Default value is "false".
246+
static const char COMMIT_DISCARD_DUPLICATE_FILES[];
247+
238248
/// "compaction.max-size-amplification-percent" - The size amplification is defined as the
239249
/// amount (in percentage) of additional storage needed to store a single byte of data in the
240250
/// merge tree for changelog mode table. Default value is 200.
@@ -270,6 +280,15 @@ struct PAIMON_EXPORT Options {
270280
/// level 0 files in candidates. Default value is false.
271281
static const char COMPACTION_FORCE_UP_LEVEL_0[];
272282

283+
/// "overwrite-upgrade" - Whether to try upgrading the data files after overwriting a
284+
/// primary key table. Default value is true.
285+
static const char OVERWRITE_UPGRADE[];
286+
287+
/// "dynamic-partition-overwrite" - Whether only overwrite dynamic partition when
288+
/// overwriting a partitioned table with dynamic partition columns. Works only when
289+
/// the table has partition keys. Default value is true.
290+
static const char DYNAMIC_PARTITION_OVERWRITE[];
291+
273292
/// "lookup-compact.max-interval" - The max interval for a gentle mode lookup compaction to be
274293
/// triggered. For every interval, a forced lookup compaction will be performed to flush L0
275294
/// files to higher level. This option is only valid when lookup-compact mode is gentle. No
@@ -453,6 +472,12 @@ struct PAIMON_EXPORT Options {
453472
/// "write-only" - If set to "true", compactions and snapshot expiration will be skipped. This
454473
/// option is used along with dedicated compact jobs. Default value is "false".
455474
static const char WRITE_ONLY[];
475+
/// "bucket-append-ordered" - Whether append writes in fixed bucket mode are ordered. This
476+
/// option is used by commit conflict checks. Default value is "false".
477+
static const char BUCKET_APPEND_ORDERED[];
478+
/// "write.sequence-number-init-mode" - Specify how to initialize the next sequence number for
479+
/// primary key table writers. Values can be: "scan", "snapshot". Default value is "scan".
480+
static const char WRITE_SEQUENCE_NUMBER_INIT_MODE[];
456481
/// "compaction.min.file-num" - For file set [f_0,...,f_N], the minimum file number to trigger a
457482
/// compaction for append-only table. Default value is 5.
458483
static const char COMPACTION_MIN_FILE_NUM[];

include/paimon/file_store_commit.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class PAIMON_EXPORT FileStoreCommit {
8383

8484
/// Overwrite from manifest committable and partition.
8585
///
86-
/// @param partitions A single partition maps each partition key to a partition value. Depending
86+
/// @param partition A single partition maps each partition key to a partition value. Depending
8787
/// on the user-defined statement, the partition might not include all partition keys. Also
8888
/// note that this partition does not necessarily equal to the partitions of the newly added
8989
/// key-values. This is just the partition to be cleaned up.
@@ -92,22 +92,22 @@ class PAIMON_EXPORT FileStoreCommit {
9292
/// @param watermark An optional event-time watermark used to indicate the progress of data
9393
/// processing. Default is std::nullopt.
9494
/// @return Result of the operation.
95-
virtual Status Overwrite(const std::vector<std::map<std::string, std::string>>& partitions,
95+
virtual Status Overwrite(const std::map<std::string, std::string>& partition,
9696
const std::vector<std::shared_ptr<CommitMessage>>& commit_messages,
9797
int64_t commit_identifier,
9898
std::optional<int64_t> watermark = std::nullopt) = 0;
9999

100100
/// This is a temporary interface for internal use. It will be removed in a future version.
101101
/// Please do not rely on it for long-term use.
102102
///
103-
/// @param partitions Description of the partitions.
103+
/// @param partition Description of the partition.
104104
/// @param commit_messages Description of the commit messages.
105105
/// @param commit_identifier Unique identifier.
106106
/// @param watermark An optional event-time watermark used to indicate the progress of data
107107
/// processing. Default is std::nullopt.
108108
/// @return Result of the operation.
109109
virtual Result<int32_t> FilterAndOverwrite(
110-
const std::vector<std::map<std::string, std::string>>& partitions,
110+
const std::map<std::string, std::string>& partition,
111111
const std::vector<std::shared_ptr<CommitMessage>>& commit_messages,
112112
int64_t commit_identifier, std::optional<int64_t> watermark = std::nullopt) = 0;
113113

@@ -135,6 +135,17 @@ class PAIMON_EXPORT FileStoreCommit {
135135
virtual Status DropPartition(const std::vector<std::map<std::string, std::string>>& partitions,
136136
int64_t commit_identifier) = 0;
137137

138+
/// Configure row-id conflict checking from a specific snapshot id.
139+
///
140+
/// If set to a snapshot id, commit conflict detection will additionally validate row-id
141+
/// conflicts against snapshots after that id. Passing std::nullopt disables this behavior.
142+
///
143+
/// @param row_id_check_from_snapshot Snapshot id to start row-id conflict checks from, or
144+
/// std::nullopt to disable.
145+
/// @return Current commit object for chaining.
146+
virtual FileStoreCommit& RowIdCheckConflict(
147+
std::optional<int64_t> row_id_check_from_snapshot) = 0;
148+
138149
/// Retrieve metrics related to commit operations.
139150
///
140151
/// @return A shared pointer to a `Metrics` object containing commit metrics.

src/paimon/CMakeLists.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,17 @@ set(PAIMON_CORE_SRCS
288288
core/operation/abstract_split_read.cpp
289289
core/operation/append_only_file_store_scan.cpp
290290
core/operation/append_only_file_store_write.cpp
291+
core/operation/metrics/commit_metrics.cpp
292+
core/operation/commit/conflict_detection.cpp
293+
core/operation/commit/commit_scanner.cpp
294+
core/operation/commit/commit_changes_provider.cpp
295+
core/operation/commit/compacted_changelog_path_resolver.cpp
296+
core/operation/commit/overwrite_changes_provider.cpp
297+
core/operation/commit/row_id_column_conflict_checker.cpp
298+
core/operation/commit/manifest_entry_changes.cpp
299+
core/operation/commit/row_tracking_commit_utils.cpp
300+
core/operation/commit/sequence_snapshot_properties.cpp
301+
core/operation/commit/retry_waiter.cpp
291302
core/operation/commit_context.cpp
292303
core/operation/expire_snapshots.cpp
293304
core/operation/file_store_commit.cpp
@@ -320,6 +331,7 @@ set(PAIMON_CORE_SRCS
320331
core/stats/simple_stats.cpp
321332
core/stats/simple_stats_evolution.cpp
322333
core/table/table.cpp
334+
core/table/bucket_mode.cpp
323335
core/table/sink/commit_message.cpp
324336
core/table/sink/commit_message_impl.cpp
325337
core/table/sink/commit_message_serializer.cpp
@@ -696,13 +708,24 @@ if(PAIMON_BUILD_TESTS)
696708
core/mergetree/spill_reader_writer_test.cpp
697709
core/migrate/file_meta_utils_test.cpp
698710
core/operation/metrics/compaction_metrics_test.cpp
711+
core/operation/metrics/commit_stats_test.cpp
699712
core/operation/data_evolution_file_store_scan_test.cpp
700713
core/operation/data_evolution_split_read_test.cpp
714+
core/operation/commit/compacted_changelog_path_resolver_test.cpp
715+
core/operation/commit/commit_changes_provider_test.cpp
716+
core/operation/commit/commit_scanner_test.cpp
717+
core/operation/commit/conflict_detection_test.cpp
718+
core/operation/commit/manifest_entry_changes_test.cpp
719+
core/operation/commit/overwrite_changes_provider_test.cpp
720+
core/operation/commit/row_id_column_conflict_checker_test.cpp
721+
core/operation/commit/row_tracking_commit_utils_test.cpp
722+
core/operation/commit/retry_waiter_test.cpp
701723
core/operation/key_value_file_store_write_test.cpp
702724
core/operation/internal_read_context_test.cpp
703725
core/operation/abstract_split_read_test.cpp
704726
core/operation/append_only_file_store_write_test.cpp
705727
core/operation/commit_metrics_test.cpp
728+
core/operation/commit_context_test.cpp
706729
core/operation/expire_snapshots_test.cpp
707730
core/operation/file_store_commit_impl_test.cpp
708731
core/operation/file_store_commit_test.cpp
@@ -731,6 +754,7 @@ if(PAIMON_BUILD_TESTS)
731754
core/stats/simple_stats_collector_test.cpp
732755
core/stats/simple_stats_test.cpp
733756
core/table/table_test.cpp
757+
core/table/bucket_mode_test.cpp
734758
core/table/sink/commit_message_test.cpp
735759
core/table/sink/commit_message_impl_test.cpp
736760
core/table/source/fallback_data_split_test.cpp

src/paimon/common/data/binary_row.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,19 @@ struct hash<std::tuple<paimon::BinaryRow, int32_t, std::string>> {
156156
}
157157
};
158158

159+
/// for std::unordered_map<std::tuple<paimon::BinaryRow, int32_t, int32_t>, ...>
160+
template <>
161+
struct hash<std::tuple<paimon::BinaryRow, int32_t, int32_t>> {
162+
size_t operator()(
163+
const std::tuple<paimon::BinaryRow, int32_t, int32_t>& partition_bucket_level) const {
164+
const auto& [partition, bucket, level] = partition_bucket_level;
165+
size_t hash = paimon::MurmurHashUtils::HashUnsafeBytes(
166+
reinterpret_cast<const void*>(&bucket), 0, sizeof(bucket), partition.HashCode());
167+
return paimon::MurmurHashUtils::HashUnsafeBytes(reinterpret_cast<const void*>(&level), 0,
168+
sizeof(level), hash);
169+
}
170+
};
171+
159172
template <>
160173
struct hash<paimon::BinaryRow> {
161174
size_t operator()(const paimon::BinaryRow& row) const {

src/paimon/common/defs.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ const char Options::SNAPSHOT_CLEAN_EMPTY_DIRECTORIES[] = "snapshot.clean-empty-d
6565
const char Options::COMMIT_FORCE_COMPACT[] = "commit.force-compact";
6666
const char Options::COMMIT_TIMEOUT[] = "commit.timeout";
6767
const char Options::COMMIT_MAX_RETRIES[] = "commit.max-retries";
68+
const char Options::COMMIT_MIN_RETRY_WAIT[] = "commit.min-retry-wait";
69+
const char Options::COMMIT_MAX_RETRY_WAIT[] = "commit.max-retry-wait";
70+
const char Options::COMMIT_DISCARD_DUPLICATE_FILES[] = "commit.discard-duplicate-files";
6871
const char Options::SEQUENCE_FIELD[] = "sequence.field";
6972
const char Options::SEQUENCE_FIELD_SORT_ORDER[] = "sequence.field.sort-order";
7073
const char Options::MERGE_ENGINE[] = "merge-engine";
@@ -114,6 +117,8 @@ const char Options::SCAN_TIMESTAMP_MILLIS[] = "scan.timestamp-millis";
114117
const char Options::SCAN_TIMESTAMP[] = "scan.timestamp";
115118
const char Options::SCAN_TAG_NAME[] = "scan.tag-name";
116119
const char Options::WRITE_ONLY[] = "write-only";
120+
const char Options::BUCKET_APPEND_ORDERED[] = "bucket-append-ordered";
121+
const char Options::WRITE_SEQUENCE_NUMBER_INIT_MODE[] = "write.sequence-number-init-mode";
117122
const char Options::COMPACTION_MIN_FILE_NUM[] = "compaction.min.file-num";
118123
const char Options::COMPACTION_FORCE_REWRITE_ALL_FILES[] = "compaction.force-rewrite-all-files";
119124
const char Options::COMPACTION_OPTIMIZATION_INTERVAL[] = "compaction.optimization-interval";
@@ -138,6 +143,8 @@ const char Options::NUM_SORTED_RUNS_COMPACTION_TRIGGER[] = "num-sorted-run.compa
138143
const char Options::NUM_SORTED_RUNS_STOP_TRIGGER[] = "num-sorted-run.stop-trigger";
139144
const char Options::NUM_LEVELS[] = "num-levels";
140145
const char Options::COMPACTION_FORCE_UP_LEVEL_0[] = "compaction.force-up-level-0";
146+
const char Options::OVERWRITE_UPGRADE[] = "overwrite-upgrade";
147+
const char Options::DYNAMIC_PARTITION_OVERWRITE[] = "dynamic-partition-overwrite";
141148
const char Options::LOOKUP_WAIT[] = "lookup-wait";
142149
const char Options::LOOKUP_COMPACT[] = "lookup-compact";
143150
const char Options::LOOKUP_COMPACT_MAX_INTERVAL[] = "lookup-compact.max-interval";

src/paimon/common/table/special_fields.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "arrow/type_fwd.h"
2424
#include "paimon/common/types/data_field.h"
25+
#include "paimon/common/utils/string_utils.h"
2526
#include "paimon/utils/special_field_ids.h"
2627

2728
namespace paimon {
@@ -63,6 +64,15 @@ struct SpecialFields {
6364
return data_field;
6465
}
6566

67+
static bool IsSystemField(const std::string& field_name) {
68+
if (StringUtils::StartsWith(field_name, KEY_FIELD_PREFIX)) {
69+
return true;
70+
}
71+
return field_name == SequenceNumber().Name() || field_name == ValueKind().Name() ||
72+
field_name == RowKind().Name() || field_name == RowId().Name() ||
73+
field_name == IndexScore().Name();
74+
}
75+
6676
static bool IsSpecialFieldName(const std::string& field_name) {
6777
if (field_name == SequenceNumber().Name() || field_name == ValueKind().Name() ||
6878
field_name == RowKind().Name() || field_name == RowId().Name() ||

src/paimon/core/catalog/commit_table_request_test.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ TEST(CommitTableRequestTest, TestSimple) {
3737
/*changelog_manifest_list_size=*/std::nullopt, /*index_manifest=*/std::nullopt,
3838
/*commit_user=*/"commit_user_1", /*commit_identifier=*/9223372036854775807,
3939
/*commit_kind=*/Snapshot::CommitKind::Append(), /*time_millis=*/1758097357597,
40-
/*log_offsets=*/std::map<int32_t, int64_t>(), /*total_record_count=*/5,
40+
/*total_record_count=*/5,
4141
/*delta_record_count=*/5, /*changelog_record_count=*/0, /*watermark=*/std::nullopt,
4242
/*statistics=*/std::nullopt, /*properties=*/std::nullopt, /*next_row_id=*/0);
4343
std::vector<PartitionStatistics> partition_statistics = {
@@ -61,7 +61,6 @@ TEST(CommitTableRequestTest, TestSimple) {
6161
"commitIdentifier": 9223372036854775807,
6262
"commitKind": "APPEND",
6363
"timeMillis": 1758097357597,
64-
"logOffsets": {},
6564
"totalRecordCount": 5,
6665
"deltaRecordCount": 5,
6766
"changelogRecordCount": 0,

src/paimon/core/catalog/renaming_snapshot_commit_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ TEST(RenamingSnapshotCommitTest, TestSimple) {
4646
/*changelog_manifest_list_size=*/std::nullopt, /*index_manifest=*/std::nullopt,
4747
/*commit_user=*/"commit_user_1", /*commit_identifier=*/9223372036854775807,
4848
/*commit_kind=*/Snapshot::CommitKind::Append(), /*time_millis=*/1758097357597,
49-
/*log_offsets=*/std::map<int32_t, int64_t>(), /*total_record_count=*/5,
49+
/*total_record_count=*/5,
5050
/*delta_record_count=*/5, /*changelog_record_count=*/0, /*watermark=*/std::nullopt,
5151
/*statistics=*/std::nullopt, /*properties=*/std::nullopt, /*next_row_id=*/0);
5252
ASSERT_OK_AND_ASSIGN(bool success, commit->Commit(snapshot, /*statistics=*/{}));

0 commit comments

Comments
 (0)