| /* | |
| * 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 <memory> | |
| #include <string_view> | |
| #include <vector> | |
| #include "arrow/array/array_base.h" | |
| #include "arrow/util/bit_util.h" | |
| namespace arrow { | |
| class StructArray; | |
| } // namespace arrow | |
| namespace paimon { | |
| class MemoryPool; | |
| /// Pre-cached column metadata for fast access without virtual function calls or checked_cast. | |
| struct CachedColumnMeta { | |
| /// Null bitmap pointer. nullptr means no nulls (all valid). | |
| const uint8_t* null_bitmap = nullptr; | |
| /// Arrow array offset (for sliced arrays). | |
| int64_t array_offset = 0; | |
| /// For fixed-width types: raw pointer to values buffer (buffer[1]). | |
| /// For variable-length types (STRING/BINARY): raw pointer to data buffer (buffer[2]). | |
| const uint8_t* values_data = nullptr; | |
| /// For variable-length types (STRING/BINARY): raw pointer to offsets buffer (buffer[1]). | |
| const int32_t* offsets = nullptr; | |
| /// Fast null check: directly reads validity bitmap bit. | |
| inline bool IsNull(int64_t row_id) const { | |
| return null_bitmap != nullptr && | |
| !arrow::bit_util::GetBit(null_bitmap, array_offset + row_id); | |
| } | |
| /// Fast fixed-width value access (INT8/INT16/INT32/INT64/FLOAT/DOUBLE/DATE32/TIMESTAMP). | |
| template <typename T> | |
| inline T GetFixed(int64_t row_id) const { | |
| return reinterpret_cast<const T*>(values_data)[array_offset + row_id]; | |
| } | |
| /// Fast boolean value access (bit-packed in values buffer). | |
| inline bool GetBool(int64_t row_id) const { | |
| return arrow::bit_util::GetBit(values_data, array_offset + row_id); | |
| } | |
| /// Fast string_view access for non-dictionary STRING/BINARY columns. | |
| inline std::string_view GetVarLenView(int64_t row_id) const { | |
| int64_t idx = array_offset + row_id; | |
| int32_t start = offsets[idx]; | |
| int32_t length = offsets[idx + 1] - start; | |
| return {reinterpret_cast<const char*>(values_data) + start, static_cast<size_t>(length)}; | |
| } | |
| }; | |
| struct ColumnarBatchContext { | |
| ColumnarBatchContext(const arrow::ArrayVector& array_vec_in, | |
| const std::shared_ptr<MemoryPool>& pool_in) | |
| : pool(pool_in), array_vec(array_vec_in) { | |
| BuildCachedMeta(); | |
| } | |
| std::shared_ptr<MemoryPool> pool; | |
| arrow::ArrayVector array_vec; | |
| /// Pre-cached metadata per column for fast access. | |
| std::vector<CachedColumnMeta> cached_meta; | |
| private: | |
| void BuildCachedMeta() { | |
| cached_meta.resize(array_vec.size()); | |
| for (size_t i = 0; i < array_vec.size(); i++) { | |
| const auto* array = array_vec[i].get(); | |
| auto& meta = cached_meta[i]; | |
| meta.array_offset = array->offset(); | |
| // Cache null bitmap | |
| if (array->null_count() != 0) { | |
| meta.null_bitmap = array->null_bitmap_data(); | |
| } | |
| // Cache data pointers based on type | |
| const auto& array_data = array->data(); | |
| switch (array->type_id()) { | |
| case arrow::Type::BOOL: | |
| case arrow::Type::INT8: | |
| case arrow::Type::INT16: | |
| case arrow::Type::INT32: | |
| case arrow::Type::DATE32: | |
| case arrow::Type::INT64: | |
| case arrow::Type::FLOAT: | |
| case arrow::Type::DOUBLE: { | |
| // Fixed-width: values in buffer[1] | |
| if (array_data->buffers.size() > 1 && array_data->buffers[1]) { | |
| meta.values_data = array_data->buffers[1]->data(); | |
| } | |
| break; | |
| } | |
| case arrow::Type::STRING: | |
| case arrow::Type::BINARY: { | |
| // Variable-length: offsets in buffer[1], data in buffer[2] | |
| if (array_data->buffers.size() > 2) { | |
| if (array_data->buffers[1]) { | |
| meta.offsets = | |
| reinterpret_cast<const int32_t*>(array_data->buffers[1]->data()); | |
| } | |
| if (array_data->buffers[2]) { | |
| meta.values_data = array_data->buffers[2]->data(); | |
| } | |
| } | |
| break; | |
| } | |
| default: | |
| // TIMESTAMP, DECIMAL, DICTIONARY, LIST, MAP, STRUCT — not cached, use array_vec | |
| // fallback | |
| break; | |
| } | |
| } | |
| } | |
| }; | |
| } // namespace paimon |