| /* | |
| * 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 "paimon/common/data/internal_row.h" | |
| #include <cstddef> | |
| #include <string_view> | |
| #include <utility> | |
| #include <variant> | |
| #include <vector> | |
| #include "arrow/api.h" | |
| #include "arrow/array/array_base.h" | |
| #include "arrow/array/array_nested.h" | |
| #include "arrow/ipc/json_simple.h" | |
| #include "gtest/gtest.h" | |
| #include "paimon/common/data/columnar/columnar_row.h" | |
| #include "paimon/common/data/internal_array.h" | |
| #include "paimon/common/data/internal_map.h" | |
| #include "paimon/common/utils/date_time_utils.h" | |
| #include "paimon/common/utils/decimal_utils.h" | |
| #include "paimon/data/decimal.h" | |
| #include "paimon/data/timestamp.h" | |
| #include "paimon/memory/memory_pool.h" | |
| #include "paimon/status.h" | |
| #include "paimon/testing/utils/testharness.h" | |
| namespace paimon::test { | |
| TEST(InternalRowTest, TestCreateFieldGetter) { | |
| auto timezone = DateTimeUtils::GetLocalTimezoneName(); | |
| arrow::FieldVector fields = { | |
| arrow::field("f0", arrow::boolean()), | |
| arrow::field("f1", arrow::int8()), | |
| arrow::field("f2", arrow::int16()), | |
| arrow::field("f3", arrow::int32()), | |
| arrow::field("f4", arrow::int64()), | |
| arrow::field("f5", arrow::float32()), | |
| arrow::field("f6", arrow::float64()), | |
| arrow::field("f7", arrow::utf8()), | |
| arrow::field("f8", arrow::binary()), | |
| arrow::field("f9", arrow::timestamp(arrow::TimeUnit::SECOND)), | |
| arrow::field("f10", arrow::timestamp(arrow::TimeUnit::MILLI)), | |
| arrow::field("f11", arrow::timestamp(arrow::TimeUnit::MICRO)), | |
| arrow::field("f12", arrow::timestamp(arrow::TimeUnit::NANO)), | |
| arrow::field("f13", arrow::timestamp(arrow::TimeUnit::SECOND, timezone)), | |
| arrow::field("f14", arrow::timestamp(arrow::TimeUnit::MILLI, timezone)), | |
| arrow::field("f15", arrow::timestamp(arrow::TimeUnit::MICRO, timezone)), | |
| arrow::field("f16", arrow::timestamp(arrow::TimeUnit::NANO, timezone)), | |
| arrow::field("f17", arrow::decimal128(30, 5)), | |
| arrow::field("f18", arrow::date32()), | |
| arrow::field("f19", arrow::list(arrow::int32())), | |
| arrow::field("f20", arrow::map(arrow::boolean(), arrow::int64())), | |
| arrow::field("f21", | |
| arrow::struct_({field("sub1", arrow::int64()), field("sub2", arrow::float64()), | |
| field("sub3", arrow::boolean())})), | |
| }; | |
| auto src_array = std::dynamic_pointer_cast<arrow::StructArray>( | |
| arrow::ipc::internal::json::ArrayFromJSON(arrow::struct_(fields), R"([ | |
| [true, 1, 2, 3, 4, 5.1, 6.12, "abc", "def", "1970-01-02 00:00:01", "1970-01-02 00:00:00.001", | |
| "1970-01-02 00:00:00.000001", "1970-01-02 00:00:00.000000001", "1970-01-02 00:00:02", "1970-01-02 00:00:00.002", | |
| "1970-01-02 00:00:00.000002", "1970-01-02 00:00:00.000000002", "-123456789987654321.45678", 12345, | |
| [1, 2, 3], [[true, 3], [false, 4]], [10, 10.1, false]] | |
| ])") | |
| .ValueOrDie()); | |
| auto pool = GetDefaultPool(); | |
| ColumnarRow row(src_array->fields(), pool, /*row_id=*/0); | |
| std::vector<InternalRow::FieldGetterFunc> getters; | |
| for (size_t i = 0; i < fields.size(); i++) { | |
| ASSERT_OK_AND_ASSIGN( | |
| InternalRow::FieldGetterFunc getter, | |
| InternalRow::CreateFieldGetter(i, fields[i]->type(), /*use_view=*/true)); | |
| getters.push_back(getter); | |
| } | |
| ASSERT_EQ(getters[0](row), VariantType(true)); | |
| ASSERT_EQ(getters[1](row), VariantType(static_cast<char>(1))); | |
| ASSERT_EQ(getters[2](row), VariantType(static_cast<int16_t>(2))); | |
| ASSERT_EQ(getters[3](row), VariantType(static_cast<int32_t>(3))); | |
| ASSERT_EQ(getters[4](row), VariantType(static_cast<int64_t>(4))); | |
| ASSERT_EQ(getters[5](row), VariantType(static_cast<float>(5.1))); | |
| ASSERT_EQ(getters[6](row), VariantType(static_cast<double>(6.12))); | |
| auto string_view7 = DataDefine::GetVariantValue<std::string_view>(getters[7](row)); | |
| ASSERT_EQ(std::string(string_view7), "abc"); | |
| auto string_view8 = DataDefine::GetVariantValue<std::string_view>(getters[8](row)); | |
| ASSERT_EQ(std::string(string_view8), "def"); | |
| ASSERT_EQ(getters[9](row), VariantType(Timestamp(1 * DateTimeUtils::MILLIS_PER_DAY + 1000, 0))); | |
| ASSERT_EQ(getters[10](row), VariantType(Timestamp(1 * DateTimeUtils::MILLIS_PER_DAY + 1, 0))); | |
| ASSERT_EQ(getters[11](row), VariantType(Timestamp(1 * DateTimeUtils::MILLIS_PER_DAY, 1000))); | |
| ASSERT_EQ(getters[12](row), VariantType(Timestamp(1 * DateTimeUtils::MILLIS_PER_DAY, 1))); | |
| ASSERT_EQ(getters[13](row), | |
| VariantType(Timestamp(1 * DateTimeUtils::MILLIS_PER_DAY + 2000, 0))); | |
| ASSERT_EQ(getters[14](row), VariantType(Timestamp(1 * DateTimeUtils::MILLIS_PER_DAY + 2, 0))); | |
| ASSERT_EQ(getters[15](row), VariantType(Timestamp(1 * DateTimeUtils::MILLIS_PER_DAY, 2000))); | |
| ASSERT_EQ(getters[16](row), VariantType(Timestamp(1 * DateTimeUtils::MILLIS_PER_DAY, 2))); | |
| ASSERT_EQ( | |
| getters[17](row), | |
| VariantType(Decimal(30, 5, DecimalUtils::StrToInt128("-12345678998765432145678").value()))); | |
| ASSERT_EQ(getters[18](row), VariantType(12345)); | |
| ASSERT_EQ(DataDefine::GetVariantValue<std::shared_ptr<InternalArray>>(getters[19](row)) | |
| ->ToIntArray() | |
| .value(), | |
| std::vector<int32_t>({1, 2, 3})); | |
| ASSERT_EQ(DataDefine::GetVariantValue<std::shared_ptr<InternalMap>>(getters[20](row)) | |
| ->KeyArray() | |
| ->ToBooleanArray() | |
| .value(), | |
| std::vector<char>({true, false})); | |
| ASSERT_EQ(DataDefine::GetVariantValue<std::shared_ptr<InternalMap>>(getters[20](row)) | |
| ->ValueArray() | |
| ->ToLongArray() | |
| .value(), | |
| std::vector<int64_t>({3l, 4l})); | |
| auto inner_row = DataDefine::GetVariantValue<std::shared_ptr<InternalRow>>(getters[21](row)); | |
| ASSERT_EQ(inner_row->GetLong(0), 10l); | |
| ASSERT_EQ(inner_row->GetDouble(1), 10.1); | |
| ASSERT_EQ(inner_row->GetBoolean(2), false); | |
| } | |
| TEST(InternalRowTest, TestCreateFieldGetterWithNull) { | |
| arrow::FieldVector fields = {arrow::field("f0", arrow::boolean()), | |
| arrow::field("f1", arrow::int8())}; | |
| auto src_array = std::dynamic_pointer_cast<arrow::StructArray>( | |
| arrow::ipc::internal::json::ArrayFromJSON(arrow::struct_(fields), R"([ | |
| [true, null] | |
| ])") | |
| .ValueOrDie()); | |
| auto pool = GetDefaultPool(); | |
| ColumnarRow row(src_array->fields(), pool, /*row_id=*/0); | |
| std::vector<InternalRow::FieldGetterFunc> getters; | |
| for (size_t i = 0; i < fields.size(); i++) { | |
| ASSERT_OK_AND_ASSIGN( | |
| InternalRow::FieldGetterFunc getter, | |
| InternalRow::CreateFieldGetter(i, fields[i]->type(), /*use_view=*/true)); | |
| getters.push_back(getter); | |
| } | |
| ASSERT_EQ(getters[0](row), VariantType(true)); | |
| ASSERT_TRUE(DataDefine::IsVariantNull(getters[1](row))); | |
| } | |
| TEST(InternalRowTest, TestCreateFieldGetterWithInvalidType) { | |
| arrow::FieldVector fields = {arrow::field("f0", arrow::large_utf8())}; | |
| auto src_array = std::dynamic_pointer_cast<arrow::StructArray>( | |
| arrow::ipc::internal::json::ArrayFromJSON(arrow::struct_(fields), R"([ | |
| ["hello"] | |
| ])") | |
| .ValueOrDie()); | |
| auto pool = GetDefaultPool(); | |
| ColumnarRow row(src_array->fields(), pool, /*row_id=*/0); | |
| ASSERT_NOK_WITH_MSG(InternalRow::CreateFieldGetter(0, fields[0]->type(), /*use_view=*/true), | |
| "not support in data getter"); | |
| } | |
| } // namespace paimon::test |