| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| */ | |
| #pragma once | |
| #include <cstdint> | |
| #include <map> | |
| #include <memory> | |
| #include <string> | |
| #include <vector> | |
| #include "paimon/result.h" | |
| #include "paimon/visibility.h" | |
| struct ArrowArray; | |
| namespace paimon { | |
| /// `RecordBatch` encapsulates a batch of data with the same schema, supporting different types such | |
| /// as `INSERT`, `UPDATE_BEFORE`, `UPDATE_AFTER`, and `DELETE`. It is typically used in streaming | |
| /// write or batch processing scenarios, with underlying data stored in the Apache Arrow format. | |
| /// @note Do not use this class directly, use `RecordBatchBuilder` to build a `RecordBatch` which | |
| /// has input validation. | |
| class PAIMON_EXPORT RecordBatch { | |
| public: | |
| enum class PAIMON_EXPORT RowKind : int8_t { | |
| INSERT = 0, | |
| UPDATE_BEFORE = 1, | |
| UPDATE_AFTER = 2, | |
| DELETE = 3, | |
| }; | |
| /// @note 1. Data cannot be reused, as it will be released after Write. 2. If a partition | |
| /// field's value is null, it should be represented as "__DEFAULT_PARTITION__"(or a user-defined | |
| /// default value) in the partition map. However, in the Arrow array, partition column values | |
| /// MUST NOT be set to "__DEFAULT_PARTITION__" (or a user-defined default value). Instead, they | |
| /// should be properly set as actual nulls. If used, it may lead to behavioral inconsistencies | |
| /// between C++ Paimon and Java Paimon. | |
| RecordBatch(const std::map<std::string, std::string>& partition, int32_t bucket, | |
| const std::vector<RowKind>& row_kinds, ArrowArray* data); | |
| ~RecordBatch(); | |
| RecordBatch(RecordBatch&&); | |
| RecordBatch& operator=(RecordBatch&&); | |
| RecordBatch(const RecordBatch&) = delete; | |
| RecordBatch& operator=(const RecordBatch&) = delete; | |
| const std::map<std::string, std::string>& GetPartition() const { | |
| return partition_; | |
| } | |
| int32_t GetBucket() const { | |
| return bucket_; | |
| } | |
| ArrowArray* GetData() const { | |
| return data_; | |
| } | |
| const std::vector<RecordBatch::RowKind>& GetRowKind() const { | |
| return row_kinds_; | |
| } | |
| void SetBucket(int32_t bucket) { | |
| bucket_ = bucket; | |
| } | |
| bool HasSpecifiedBucket() const; | |
| private: | |
| std::map<std::string, std::string> partition_; | |
| int32_t bucket_; | |
| std::vector<RecordBatch::RowKind> row_kinds_; | |
| ::ArrowArray* data_; | |
| }; | |
| /// Builder for constructing `RecordBatch` instances. | |
| /// | |
| /// This class provides a convenient way to build `RecordBatch` objects by setting | |
| /// various properties such as data, row kinds, partition information, and bucket id. | |
| class PAIMON_EXPORT RecordBatchBuilder { | |
| public: | |
| /// Constructs a `RecordBatchBuilder` with Arrow data | |
| /// | |
| /// @note The `data` must conform to table schema: | |
| /// - Each array in `data` corresponds to a field in table schema. | |
| /// - If a field in table schema is marked as non-nullable (`nullable = false`), | |
| /// the corresponding array in `data` must have zero null entries. | |
| /// | |
| /// @note Consistency between `data` and table schema will be validated during the write | |
| /// process. | |
| /// | |
| /// @param data ArrowArray struct containing the columnar data (via C Data Interface) | |
| explicit RecordBatchBuilder(::ArrowArray* data); | |
| ~RecordBatchBuilder(); | |
| /// Move new Arrow data into the builder, replacing existing data. | |
| /// @param data New Arrow array data. | |
| RecordBatchBuilder& MoveData(::ArrowArray* data); | |
| /// Set the row kinds for each record in the batch. | |
| /// @param row_kinds A vector of row kinds, including INSERT, UPDATE_BEFORE, UPDATE_AFTER and | |
| /// DELETE. If not set, default value is `INSERT`. | |
| /// @note `row_kinds` must have the same length as the number of records in the data. | |
| RecordBatchBuilder& SetRowKinds(const std::vector<RecordBatch::RowKind>& row_kinds); | |
| /// Set the partition information for this record batch. | |
| /// @param data Map of partition column names to their string values. | |
| RecordBatchBuilder& SetPartition(const std::map<std::string, std::string>& data); | |
| /// Set the bucket id for this record batch. If not set, default value is `-2147483648` | |
| /// (i.e., `HasSpecifiedBucket()` returns false), and the bucket will be auto-resolved | |
| /// at write time based on the table's bucket option: | |
| /// | |
| /// - **Unaware-bucket mode** (table option `bucket = -1`, append-only table without | |
| /// primary keys): the bucket will be auto-filled with `UNAWARE_BUCKET (0)`. If the | |
| /// caller does specify a bucket, it MUST be `UNAWARE_BUCKET (0)`, otherwise the | |
| /// write fails. | |
| /// - **Postpone-bucket mode** (table option `bucket = -2`, primary-key table whose | |
| /// bucket assignment is deferred): the bucket will be auto-filled with | |
| /// `POSTPONE_BUCKET (-2)`. If the caller does specify a bucket, it MUST be | |
| /// `POSTPONE_BUCKET (-2)`, otherwise the write fails. | |
| /// - **Fixed-bucket mode** (table option `bucket > 0`): the caller MUST explicitly | |
| /// call `SetBucket()` with a value in `[0, bucket)`; not calling `SetBucket()` | |
| /// (or passing an out-of-range value) will cause the write to fail. | |
| /// | |
| /// @param bucket The bucket id for data distribution. | |
| RecordBatchBuilder& SetBucket(int32_t bucket); | |
| /// Build and return the final `RecordBatch` instance. | |
| /// | |
| /// This method validates the configuration and creates `RecordBatch` with all | |
| /// the specified properties. | |
| Result<std::unique_ptr<RecordBatch>> Finish(); | |
| class Impl; | |
| private: | |
| std::unique_ptr<Impl> impl_; | |
| }; | |
| } // namespace paimon |