blob: dfede21d635c80e259dc563c296e4cc17241e97b [file]
/*
* 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 <iostream>
#include "arrow/api.h"
#include "arrow/status.h"
#include "fury/row/type.h"
#include "fury/util/bit_util.h"
#include "fury/util/buffer.h"
#include "fury/util/status.h"
namespace fury {
class ArrayData;
class MapData;
class Row;
class Getter {
public:
virtual ~Getter() = default;
virtual std::shared_ptr<Buffer> buffer() const = 0;
virtual int base_offset() const = 0;
virtual int size_bytes() const = 0;
virtual bool IsNullAt(int i) const = 0;
virtual int GetOffset(int i) const = 0;
int8_t GetInt8(int i) const {
return buffer()->GetByteAs<int8_t>(GetOffset(i));
}
int8_t GetUInt8(int i) const {
return buffer()->GetByteAs<uint8_t>(GetOffset(i));
}
bool GetBoolean(int i) const {
return buffer()->GetByteAs<uint8_t>(GetOffset(i)) != 0;
}
int16_t GetInt16(int i) const { return buffer()->Get<int16_t>(GetOffset(i)); }
int32_t GetInt32(int i) const { return buffer()->Get<int32_t>(GetOffset(i)); }
int64_t GetInt64(int i) const { return buffer()->Get<int64_t>(GetOffset(i)); }
uint64_t GetUint64(int i) const {
return buffer()->Get<uint64_t>(GetOffset(i));
}
float GetFloat(int i) const { return buffer()->Get<float>(GetOffset(i)); }
double GetDouble(int i) const { return buffer()->Get<double>(GetOffset(i)); }
int GetBinary(int i, uint8_t **out) const;
std::vector<uint8_t> GetBinary(int i) const;
std::string GetString(int i) const;
std::shared_ptr<Row>
GetStruct(int i, std::shared_ptr<arrow::StructType> struct_type) const;
virtual std::shared_ptr<Row> GetStruct(int i) const = 0;
std::shared_ptr<ArrayData>
GetArray(int i, std::shared_ptr<arrow::ListType> array_type) const;
virtual std::shared_ptr<ArrayData> GetArray(int i) const = 0;
std::shared_ptr<MapData>
GetMap(int i, std::shared_ptr<arrow::MapType> map_type) const;
virtual std::shared_ptr<MapData> GetMap(int i) const = 0;
virtual std::string ToString() const = 0;
protected:
void AppendValue(std::stringstream &ss, int i,
std::shared_ptr<arrow::DataType> type) const;
};
class Setter {
public:
virtual ~Setter() = default;
virtual std::shared_ptr<Buffer> buffer() const = 0;
virtual int GetOffset(int i) const = 0;
virtual void SetNullAt(int i) = 0;
virtual void SetNotNullAt(int i) = 0;
void SetInt8(int i, int8_t value) {
buffer()->UnsafePutByte<int8_t>(GetOffset(i), value);
}
void SetUInt8(int i, uint8_t value) {
buffer()->UnsafePutByte<uint8_t>(GetOffset(i), value);
}
void SetBoolean(int i, bool value) {
buffer()->UnsafePutByte<bool>(GetOffset(i), value);
}
void SetInt16(int i, int16_t value) {
buffer()->UnsafePut<int16_t>(GetOffset(i), value);
}
void SetInt32(int i, int32_t value) {
buffer()->UnsafePut<int32_t>(GetOffset(i), value);
}
void SetInt64(int i, int64_t value) {
buffer()->UnsafePut<int64_t>(GetOffset(i), value);
}
void SetFloat(int i, float value) {
buffer()->UnsafePut<float>(GetOffset(i), value);
}
void SetDouble(int i, double value) {
buffer()->UnsafePut<double>(GetOffset(i), value);
}
};
class Row : public Getter, Setter {
public:
explicit Row(const std::shared_ptr<arrow::Schema> &schema);
~Row() override = default;
void PointTo(std::shared_ptr<Buffer> buffer, int offset, int size_in_bytes);
std::shared_ptr<Buffer> buffer() const override { return buffer_; }
int base_offset() const override { return base_offset_; }
int size_bytes() const override { return size_bytes_; }
std::shared_ptr<arrow::Schema> schema() const { return schema_; }
int num_fields() const { return num_fields_; }
bool IsNullAt(int i) const override {
return util::GetBit(buffer_->data() + base_offset_,
static_cast<uint32_t>(i));
}
int GetOffset(int i) const override {
return base_offset_ + bitmap_width_bytes_ + i * 8;
}
std::shared_ptr<Row> GetStruct(int i) const override {
return Getter::GetStruct(i, std::dynamic_pointer_cast<arrow::StructType>(
schema_->field(i)->type()));
}
std::shared_ptr<ArrayData> GetArray(int i) const override {
return Getter::GetArray(i, std::dynamic_pointer_cast<arrow::ListType>(
schema_->field(i)->type()));
}
std::shared_ptr<MapData> GetMap(int i) const override {
return Getter::GetMap(i, std::dynamic_pointer_cast<arrow::MapType>(
schema_->field(i)->type()));
}
void SetNullAt(int i) override {
util::SetBit(buffer()->data() + base_offset_, i);
}
void SetNotNullAt(int i) override {
util::ClearBit(buffer()->data() + base_offset_, i);
}
std::string ToString() const override;
private:
std::shared_ptr<arrow::Schema> schema_;
const int num_fields_;
mutable std::shared_ptr<Buffer> buffer_;
int base_offset_;
int size_bytes_;
int bitmap_width_bytes_;
};
std::ostream &operator<<(std::ostream &os, const Row &data);
class ArrayData : public Getter, Setter {
public:
static std::shared_ptr<ArrayData> From(const std::vector<int32_t> &vec);
static std::shared_ptr<ArrayData> From(const std::vector<int64_t> &vec);
static std::shared_ptr<ArrayData> From(const std::vector<float> &vec);
static std::shared_ptr<ArrayData> From(const std::vector<double> &vec);
explicit ArrayData(std::shared_ptr<arrow::ListType> type);
~ArrayData() override = default;
void PointTo(std::shared_ptr<Buffer> buffer, uint32_t offset,
uint32_t size_bytes);
std::shared_ptr<Buffer> buffer() const override { return buffer_; }
int base_offset() const override { return base_offset_; }
int size_bytes() const override { return size_bytes_; }
std::shared_ptr<arrow::ListType> type() const { return type_; }
int num_elements() const { return num_elements_; }
bool IsNullAt(int i) const override {
return util::GetBit(buffer_->data() + base_offset_ + 8,
static_cast<uint32_t>(i));
}
int GetOffset(int i) const override {
return element_offset_ + i * element_size_;
}
std::shared_ptr<Row> GetStruct(int i) const override {
return Getter::GetStruct(
i, std::dynamic_pointer_cast<arrow::StructType>(type_->value_type()));
}
std::shared_ptr<ArrayData> GetArray(int i) const override {
return Getter::GetArray(
i, std::dynamic_pointer_cast<arrow::ListType>(type_->value_type()));
}
std::shared_ptr<MapData> GetMap(int i) const override {
return Getter::GetMap(
i, std::dynamic_pointer_cast<arrow::MapType>(type_->value_type()));
}
void SetNullAt(int i) override {
util::SetBit(buffer_->data() + base_offset_ + 8, i);
// we assume the corresponding column was already 0
// or will be set to 0 later by the caller side
}
void SetNotNullAt(int i) override {
util::ClearBit(buffer_->data() + base_offset_ + 8, i);
}
std::string ToString() const override;
static int CalculateHeaderInBytes(int num_elements);
static int *GetDimensions(ArrayData &array, int numDimensions);
private:
std::shared_ptr<arrow::ListType> type_;
int element_size_;
mutable std::shared_ptr<Buffer> buffer_;
int num_elements_;
uint32_t element_offset_;
uint32_t base_offset_;
uint32_t size_bytes_;
};
std::ostream &operator<<(std::ostream &os, const ArrayData &data);
class MapData {
public:
explicit MapData(std::shared_ptr<arrow::MapType> type);
void PointTo(std::shared_ptr<Buffer> buffer, uint32_t offset,
uint32_t size_bytes);
std::shared_ptr<arrow::MapType> type() { return type_; }
int num_elements() { return keys_->num_elements(); }
std::shared_ptr<ArrayData> keys_array() { return keys_; }
std::shared_ptr<ArrayData> values_array() { return values_; }
std::shared_ptr<Buffer> buffer() { return buffer_; }
uint32_t base_offset() { return base_offset_; }
uint32_t size_bytes() { return size_bytes_; }
std::string ToString() const;
// TODO to unordered_map: To_unordered_map<std::string, uint64_t> possible?
private:
std::shared_ptr<arrow::MapType> type_;
std::shared_ptr<ArrayData> keys_;
std::shared_ptr<ArrayData> values_;
mutable std::shared_ptr<Buffer> buffer_;
uint32_t base_offset_;
uint32_t size_bytes_;
};
std::ostream &operator<<(std::ostream &os, const MapData &data);
} // namespace fury