blob: 60e0b6aaf16ceccf017e4cc8cde42265d325bf8a [file] [log] [blame]
// 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.
#include <gtest/gtest.h>
#include <nanoarrow/nanoarrow.hpp>
#include "postgres_copy_test_common.h"
#include "postgresql/copy/reader.h"
namespace adbcpq {
class PostgresCopyStreamTester {
public:
ArrowErrorCode Init(const PostgresType& root_type, ArrowError* error = nullptr) {
NANOARROW_RETURN_NOT_OK(reader_.Init(root_type));
NANOARROW_RETURN_NOT_OK(reader_.InferOutputSchema(error));
NANOARROW_RETURN_NOT_OK(reader_.InitFieldReaders(error));
return NANOARROW_OK;
}
ArrowErrorCode ReadAll(ArrowBufferView* data, ArrowError* error = nullptr) {
NANOARROW_RETURN_NOT_OK(reader_.ReadHeader(data, error));
int result;
do {
result = reader_.ReadRecord(data, error);
} while (result == NANOARROW_OK);
return result;
}
void GetSchema(ArrowSchema* out) { reader_.GetSchema(out); }
ArrowErrorCode GetArray(ArrowArray* out, ArrowError* error = nullptr) {
return reader_.GetArray(out, error);
}
private:
PostgresCopyStreamReader reader_;
};
TEST(PostgresCopyUtilsTest, PostgresCopyReadBoolean) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyBoolean;
data.size_bytes = sizeof(kTestPgCopyBoolean);
auto col_type = PostgresType(PostgresTypeId::kBool);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyBoolean, sizeof(kTestPgCopyBoolean));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 3);
ASSERT_EQ(array->n_children, 1);
const uint8_t* validity =
reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
const uint8_t* data_buffer =
reinterpret_cast<const uint8_t*>(array->children[0]->buffers[1]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_FALSE(ArrowBitGet(validity, 2));
ASSERT_TRUE(ArrowBitGet(data_buffer, 0));
ASSERT_FALSE(ArrowBitGet(data_buffer, 1));
ASSERT_FALSE(ArrowBitGet(data_buffer, 2));
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadSmallInt) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopySmallInt;
data.size_bytes = sizeof(kTestPgCopySmallInt);
auto col_type = PostgresType(PostgresTypeId::kInt2);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopySmallInt, sizeof(kTestPgCopySmallInt));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 5);
ASSERT_EQ(array->n_children, 1);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto data_buffer = reinterpret_cast<const int16_t*>(array->children[0]->buffers[1]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_TRUE(ArrowBitGet(validity, 2));
ASSERT_TRUE(ArrowBitGet(validity, 3));
ASSERT_FALSE(ArrowBitGet(validity, 4));
ASSERT_EQ(data_buffer[0], -123);
ASSERT_EQ(data_buffer[1], -1);
ASSERT_EQ(data_buffer[2], 1);
ASSERT_EQ(data_buffer[3], 123);
ASSERT_EQ(data_buffer[4], 0);
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadInteger) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyInteger;
data.size_bytes = sizeof(kTestPgCopyInteger);
auto col_type = PostgresType(PostgresTypeId::kInt4);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyInteger, sizeof(kTestPgCopyInteger));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 5);
ASSERT_EQ(array->n_children, 1);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto data_buffer = reinterpret_cast<const int32_t*>(array->children[0]->buffers[1]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_TRUE(ArrowBitGet(validity, 2));
ASSERT_TRUE(ArrowBitGet(validity, 3));
ASSERT_FALSE(ArrowBitGet(validity, 4));
ASSERT_EQ(data_buffer[0], -123);
ASSERT_EQ(data_buffer[1], -1);
ASSERT_EQ(data_buffer[2], 1);
ASSERT_EQ(data_buffer[3], 123);
ASSERT_EQ(data_buffer[4], 0);
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadBigInt) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyBigInt;
data.size_bytes = sizeof(kTestPgCopyBigInt);
auto col_type = PostgresType(PostgresTypeId::kInt8);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyBigInt, sizeof(kTestPgCopyBigInt));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 5);
ASSERT_EQ(array->n_children, 1);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto data_buffer = reinterpret_cast<const int64_t*>(array->children[0]->buffers[1]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_TRUE(ArrowBitGet(validity, 2));
ASSERT_TRUE(ArrowBitGet(validity, 3));
ASSERT_FALSE(ArrowBitGet(validity, 4));
ASSERT_EQ(data_buffer[0], -123);
ASSERT_EQ(data_buffer[1], -1);
ASSERT_EQ(data_buffer[2], 1);
ASSERT_EQ(data_buffer[3], 123);
ASSERT_EQ(data_buffer[4], 0);
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadReal) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyReal;
data.size_bytes = sizeof(kTestPgCopyReal);
auto col_type = PostgresType(PostgresTypeId::kFloat4);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyReal, sizeof(kTestPgCopyReal));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 5);
ASSERT_EQ(array->n_children, 1);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto data_buffer = reinterpret_cast<const float*>(array->children[0]->buffers[1]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_TRUE(ArrowBitGet(validity, 2));
ASSERT_TRUE(ArrowBitGet(validity, 3));
ASSERT_FALSE(ArrowBitGet(validity, 4));
ASSERT_FLOAT_EQ(data_buffer[0], -123.456);
ASSERT_EQ(data_buffer[1], -1);
ASSERT_EQ(data_buffer[2], 1);
ASSERT_FLOAT_EQ(data_buffer[3], 123.456);
ASSERT_EQ(data_buffer[4], 0);
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadDoublePrecision) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyDoublePrecision;
data.size_bytes = sizeof(kTestPgCopyDoublePrecision);
auto col_type = PostgresType(PostgresTypeId::kFloat8);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyDoublePrecision,
sizeof(kTestPgCopyDoublePrecision));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 5);
ASSERT_EQ(array->n_children, 1);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto data_buffer = reinterpret_cast<const double*>(array->children[0]->buffers[1]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_TRUE(ArrowBitGet(validity, 2));
ASSERT_TRUE(ArrowBitGet(validity, 3));
ASSERT_FALSE(ArrowBitGet(validity, 4));
ASSERT_DOUBLE_EQ(data_buffer[0], -123.456);
ASSERT_EQ(data_buffer[1], -1);
ASSERT_EQ(data_buffer[2], 1);
ASSERT_DOUBLE_EQ(data_buffer[3], 123.456);
ASSERT_EQ(data_buffer[4], 0);
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadDate) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyDate;
data.size_bytes = sizeof(kTestPgCopyDate);
auto col_type = PostgresType(PostgresTypeId::kDate);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyDate, sizeof(kTestPgCopyDate));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 3);
ASSERT_EQ(array->n_children, 1);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto data_buffer = reinterpret_cast<const int32_t*>(array->children[0]->buffers[1]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_FALSE(ArrowBitGet(validity, 2));
ASSERT_EQ(data_buffer[0], -25567);
ASSERT_EQ(data_buffer[1], 47482);
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadTime) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyTime;
data.size_bytes = sizeof(kTestPgCopyTime);
auto col_type = PostgresType(PostgresTypeId::kTime);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyTime, sizeof(kTestPgCopyTime));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 4);
ASSERT_EQ(array->n_children, 1);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto data_buffer = reinterpret_cast<const int64_t*>(array->children[0]->buffers[1]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_TRUE(ArrowBitGet(validity, 2));
ASSERT_FALSE(ArrowBitGet(validity, 3));
ASSERT_EQ(data_buffer[0], 0);
ASSERT_EQ(data_buffer[1], 86399000000);
ASSERT_EQ(data_buffer[2], 49376123456);
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadNumeric) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyNumeric;
data.size_bytes = sizeof(kTestPgCopyNumeric);
auto col_type = PostgresType(PostgresTypeId::kNumeric);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyNumeric, sizeof(kTestPgCopyNumeric));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 9);
ASSERT_EQ(array->n_children, 1);
nanoarrow::UniqueSchema schema;
tester.GetSchema(schema.get());
nanoarrow::UniqueArrayView array_view;
ASSERT_EQ(ArrowArrayViewInitFromSchema(array_view.get(), schema.get(), nullptr),
NANOARROW_OK);
ASSERT_EQ(array_view->children[0]->storage_type, NANOARROW_TYPE_STRING);
ASSERT_EQ(ArrowArrayViewSetArray(array_view.get(), array.get(), nullptr), NANOARROW_OK);
auto validity = array_view->children[0]->buffer_views[0].data.as_uint8;
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_TRUE(ArrowBitGet(validity, 2));
ASSERT_TRUE(ArrowBitGet(validity, 3));
ASSERT_TRUE(ArrowBitGet(validity, 4));
ASSERT_TRUE(ArrowBitGet(validity, 5));
ASSERT_TRUE(ArrowBitGet(validity, 6));
ASSERT_TRUE(ArrowBitGet(validity, 7));
ASSERT_FALSE(ArrowBitGet(validity, 8));
struct ArrowStringView item;
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 0);
EXPECT_EQ(std::string(item.data, item.size_bytes), "1000000");
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 1);
EXPECT_EQ(std::string(item.data, item.size_bytes), "0.00001234");
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 2);
EXPECT_EQ(std::string(item.data, item.size_bytes), "1.0000");
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 3);
EXPECT_EQ(std::string(item.data, item.size_bytes), "-123.456");
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 4);
EXPECT_EQ(std::string(item.data, item.size_bytes), "123.456");
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 5);
EXPECT_EQ(std::string(item.data, item.size_bytes), "nan");
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 6);
EXPECT_EQ(std::string(item.data, item.size_bytes), "-inf");
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 7);
EXPECT_EQ(std::string(item.data, item.size_bytes), "inf");
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadNumeric16_10) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyNumeric16_10;
data.size_bytes = sizeof(kTestPgCopyNumeric16_10);
auto col_type = PostgresType(PostgresTypeId::kNumeric);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyNumeric16_10,
sizeof(kTestPgCopyNumeric16_10));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 7);
ASSERT_EQ(array->n_children, 1);
nanoarrow::UniqueSchema schema;
tester.GetSchema(schema.get());
nanoarrow::UniqueArrayView array_view;
ASSERT_EQ(ArrowArrayViewInitFromSchema(array_view.get(), schema.get(), nullptr),
NANOARROW_OK);
ASSERT_EQ(array_view->children[0]->storage_type, NANOARROW_TYPE_STRING);
ASSERT_EQ(ArrowArrayViewSetArray(array_view.get(), array.get(), nullptr), NANOARROW_OK);
auto validity = array_view->children[0]->buffer_views[0].data.as_uint8;
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_TRUE(ArrowBitGet(validity, 2));
ASSERT_TRUE(ArrowBitGet(validity, 3));
ASSERT_TRUE(ArrowBitGet(validity, 4));
ASSERT_TRUE(ArrowBitGet(validity, 5));
ASSERT_FALSE(ArrowBitGet(validity, 6));
struct ArrowStringView item;
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 0);
EXPECT_EQ(std::string(item.data, item.size_bytes), "0.0000000000");
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 1);
EXPECT_EQ(std::string(item.data, item.size_bytes), "1.0123400000");
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 2);
EXPECT_EQ(std::string(item.data, item.size_bytes), "1.0123456789");
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 3);
EXPECT_EQ(std::string(item.data, item.size_bytes), "-1.0123400000");
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 4);
EXPECT_EQ(std::string(item.data, item.size_bytes), "-1.0123456789");
item = ArrowArrayViewGetStringUnsafe(array_view->children[0], 5);
EXPECT_EQ(std::string(item.data, item.size_bytes), "nan");
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadTimestamp) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyTimestamp;
data.size_bytes = sizeof(kTestPgCopyTimestamp);
auto col_type = PostgresType(PostgresTypeId::kTimestamp);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyTimestamp, sizeof(kTestPgCopyTimestamp));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 3);
ASSERT_EQ(array->n_children, 1);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto data_buffer = reinterpret_cast<const int64_t*>(array->children[0]->buffers[1]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_FALSE(ArrowBitGet(validity, 3));
ASSERT_EQ(data_buffer[0], -2208943504000000);
ASSERT_EQ(data_buffer[1], 4102490096000000);
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadInterval) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyInterval;
data.size_bytes = sizeof(kTestPgCopyInterval);
auto col_type = PostgresType(PostgresTypeId::kInterval);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyInterval, sizeof(kTestPgCopyInterval));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 3);
ASSERT_EQ(array->n_children, 1);
nanoarrow::UniqueSchema schema;
tester.GetSchema(schema.get());
nanoarrow::UniqueArrayView array_view;
ASSERT_EQ(ArrowArrayViewInitFromSchema(array_view.get(), schema.get(), nullptr),
NANOARROW_OK);
ASSERT_EQ(array_view->children[0]->storage_type,
NANOARROW_TYPE_INTERVAL_MONTH_DAY_NANO);
ASSERT_EQ(ArrowArrayViewSetArray(array_view.get(), array.get(), nullptr), NANOARROW_OK);
auto validity = array_view->children[0]->buffer_views[0].data.as_uint8;
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_FALSE(ArrowBitGet(validity, 2));
struct ArrowInterval interval;
ArrowIntervalInit(&interval, NANOARROW_TYPE_INTERVAL_MONTH_DAY_NANO);
ArrowArrayViewGetIntervalUnsafe(array_view->children[0], 0, &interval);
ASSERT_EQ(interval.months, -1);
ASSERT_EQ(interval.days, -2);
ASSERT_EQ(interval.ns, -4000000000);
ArrowArrayViewGetIntervalUnsafe(array_view->children[0], 1, &interval);
ASSERT_EQ(interval.months, 1);
ASSERT_EQ(interval.days, 2);
ASSERT_EQ(interval.ns, 4000000000);
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadText) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyText;
data.size_bytes = sizeof(kTestPgCopyText);
auto col_type = PostgresType(PostgresTypeId::kText);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyText, sizeof(kTestPgCopyText));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 3);
ASSERT_EQ(array->n_children, 1);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto offsets = reinterpret_cast<const int32_t*>(array->children[0]->buffers[1]);
auto data_buffer = reinterpret_cast<const char*>(array->children[0]->buffers[2]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_FALSE(ArrowBitGet(validity, 2));
ASSERT_EQ(offsets[0], 0);
ASSERT_EQ(offsets[1], 3);
ASSERT_EQ(offsets[2], 7);
ASSERT_EQ(offsets[3], 7);
ASSERT_EQ(std::string(data_buffer + 0, 3), "abc");
ASSERT_EQ(std::string(data_buffer + 3, 4), "1234");
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadEnum) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyEnum;
data.size_bytes = sizeof(kTestPgCopyEnum);
auto col_type = PostgresType(PostgresTypeId::kEnum);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyEnum, sizeof(kTestPgCopyEnum));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 3);
ASSERT_EQ(array->n_children, 1);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto offsets = reinterpret_cast<const int32_t*>(array->children[0]->buffers[1]);
auto data_buffer = reinterpret_cast<const char*>(array->children[0]->buffers[2]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_FALSE(ArrowBitGet(validity, 2));
ASSERT_EQ(offsets[0], 0);
ASSERT_EQ(offsets[1], 2);
ASSERT_EQ(offsets[2], 5);
ASSERT_EQ(offsets[3], 5);
ASSERT_EQ(std::string(data_buffer + 0, 2), "ok");
ASSERT_EQ(std::string(data_buffer + 2, 3), "sad");
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadJson) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyJson;
data.size_bytes = sizeof(kTestPgCopyJson);
auto col_type = PostgresType(PostgresTypeId::kJson);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyJson, sizeof(kTestPgCopyJson));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 3);
ASSERT_EQ(array->n_children, 1);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto offsets = reinterpret_cast<const int32_t*>(array->children[0]->buffers[1]);
auto data_buffer = reinterpret_cast<const char*>(array->children[0]->buffers[2]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_FALSE(ArrowBitGet(validity, 2));
ASSERT_EQ(offsets[0], 0);
ASSERT_EQ(offsets[1], 9);
ASSERT_EQ(offsets[2], 18);
ASSERT_EQ(offsets[3], 18);
ASSERT_EQ(std::string(data_buffer, 9), "[1, 2, 3]");
ASSERT_EQ(std::string(data_buffer + 9, 9), "[4, 5, 6]");
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadJsonb) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyJsonb;
data.size_bytes = sizeof(kTestPgCopyJsonb);
auto col_type = PostgresType(PostgresTypeId::kJsonb);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
struct ArrowError error;
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data, &error), ENODATA) << error.message;
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyJsonb, sizeof(kTestPgCopyJsonb));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get(), &error), NANOARROW_OK) << error.message;
ASSERT_EQ(array->length, 3);
ASSERT_EQ(array->n_children, 1);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto offsets = reinterpret_cast<const int32_t*>(array->children[0]->buffers[1]);
auto data_buffer = reinterpret_cast<const char*>(array->children[0]->buffers[2]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_FALSE(ArrowBitGet(validity, 2));
ASSERT_EQ(offsets[0], 0);
ASSERT_EQ(offsets[1], 9);
ASSERT_EQ(offsets[2], 18);
ASSERT_EQ(offsets[3], 18);
ASSERT_EQ(std::string(data_buffer, 9), "[1, 2, 3]");
ASSERT_EQ(std::string(data_buffer + 9, 9), "[4, 5, 6]");
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadBinary) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyBinary;
data.size_bytes = sizeof(kTestPgCopyBinary);
auto col_type = PostgresType(PostgresTypeId::kBytea);
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyBinary, sizeof(kTestPgCopyBinary));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 5);
ASSERT_EQ(array->n_children, 1);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto offsets = reinterpret_cast<const int32_t*>(array->children[0]->buffers[1]);
auto data_buffer = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[2]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_TRUE(ArrowBitGet(validity, 2));
ASSERT_TRUE(ArrowBitGet(validity, 3));
ASSERT_FALSE(ArrowBitGet(validity, 4));
ASSERT_EQ(offsets[0], 0);
ASSERT_EQ(offsets[1], 0);
ASSERT_EQ(offsets[2], 2);
ASSERT_EQ(offsets[3], 6);
ASSERT_EQ(offsets[4], 8);
ASSERT_EQ(offsets[5], 8);
ASSERT_EQ(data_buffer[0], 0x00);
ASSERT_EQ(data_buffer[1], 0x01);
ASSERT_EQ(data_buffer[2], 0x01);
ASSERT_EQ(data_buffer[3], 0x02);
ASSERT_EQ(data_buffer[4], 0x03);
ASSERT_EQ(data_buffer[5], 0x04);
ASSERT_EQ(data_buffer[6], 0xfe);
ASSERT_EQ(data_buffer[7], 0xff);
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadArray) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyIntegerArray;
data.size_bytes = sizeof(kTestPgCopyIntegerArray);
auto col_type = PostgresType(PostgresTypeId::kInt4).Array();
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyIntegerArray,
sizeof(kTestPgCopyIntegerArray));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 3);
ASSERT_EQ(array->n_children, 1);
ASSERT_EQ(array->children[0]->n_children, 1);
ASSERT_EQ(array->children[0]->children[0]->length, 5);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto offsets = reinterpret_cast<const int32_t*>(array->children[0]->buffers[1]);
auto data_buffer =
reinterpret_cast<const int32_t*>(array->children[0]->children[0]->buffers[1]);
ASSERT_NE(validity, nullptr);
ASSERT_NE(data_buffer, nullptr);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_FALSE(ArrowBitGet(validity, 2));
ASSERT_EQ(offsets[0], 0);
ASSERT_EQ(offsets[1], 2);
ASSERT_EQ(offsets[2], 5);
ASSERT_EQ(offsets[3], 5);
ASSERT_EQ(data_buffer[0], -123);
ASSERT_EQ(data_buffer[1], -1);
ASSERT_EQ(data_buffer[2], 0);
ASSERT_EQ(data_buffer[3], 1);
ASSERT_EQ(data_buffer[4], 123);
}
TEST(PostgresCopyUtilsTest, PostgresCopyReadCustomRecord) {
ArrowBufferView data;
data.data.as_uint8 = kTestPgCopyCustomRecord;
data.size_bytes = sizeof(kTestPgCopyCustomRecord);
auto col_type = PostgresType(PostgresTypeId::kRecord);
col_type.AppendChild("nested1", PostgresType(PostgresTypeId::kInt4));
col_type.AppendChild("nested2", PostgresType(PostgresTypeId::kFloat8));
PostgresType input_type(PostgresTypeId::kRecord);
input_type.AppendChild("col", col_type);
PostgresCopyStreamTester tester;
ASSERT_EQ(tester.Init(input_type), NANOARROW_OK);
ASSERT_EQ(tester.ReadAll(&data), ENODATA);
ASSERT_EQ(data.data.as_uint8 - kTestPgCopyCustomRecord,
sizeof(kTestPgCopyCustomRecord));
ASSERT_EQ(data.size_bytes, 0);
nanoarrow::UniqueArray array;
ASSERT_EQ(tester.GetArray(array.get()), NANOARROW_OK);
ASSERT_EQ(array->length, 3);
ASSERT_EQ(array->n_children, 1);
ASSERT_EQ(array->children[0]->n_children, 2);
ASSERT_EQ(array->children[0]->children[0]->length, 3);
ASSERT_EQ(array->children[0]->children[1]->length, 3);
auto validity = reinterpret_cast<const uint8_t*>(array->children[0]->buffers[0]);
auto data_buffer1 =
reinterpret_cast<const int32_t*>(array->children[0]->children[0]->buffers[1]);
auto data_buffer2 =
reinterpret_cast<const double*>(array->children[0]->children[1]->buffers[1]);
ASSERT_TRUE(ArrowBitGet(validity, 0));
ASSERT_TRUE(ArrowBitGet(validity, 1));
ASSERT_FALSE(ArrowBitGet(validity, 2));
ASSERT_EQ(data_buffer1[0], 123);
ASSERT_EQ(data_buffer1[1], 12);
ASSERT_EQ(data_buffer1[2], 0);
ASSERT_DOUBLE_EQ(data_buffer2[0], 456.789);
ASSERT_DOUBLE_EQ(data_buffer2[1], 345.678);
ASSERT_DOUBLE_EQ(data_buffer2[2], 0);
}
} // namespace adbcpq