From 0b31fead6e1afe87c9dab7181515588eae084b02 Mon Sep 17 00:00:00 2001 From: Dewey Dunnington Date: Sun, 17 Sep 2023 14:42:54 +0200 Subject: [PATCH] Add generic `GeoArrowArrayReader` to use any array with the visitor pattern (#56) * start on generic handler * theoretical support for WKT/WKB visiting * add array reader * test some of the visiting * with wkb test * use array reader to simplify kernel * run apt-get update in ubuntu job --- .github/workflows/build-and-test.yaml | 1 + CMakeLists.txt | 4 + src/geoarrow/array_reader.c | 108 +++++++++++++++++++++ src/geoarrow/array_reader_test.cc | 132 ++++++++++++++++++++++++++ src/geoarrow/array_view.c | 40 ++++++-- src/geoarrow/array_view_test.cc | 11 --- src/geoarrow/geoarrow.h | 23 +++++ src/geoarrow/geoarrow_type.h | 3 + src/geoarrow/kernel.c | 120 ++++------------------- 9 files changed, 321 insertions(+), 121 deletions(-) create mode 100644 src/geoarrow/array_reader.c create mode 100644 src/geoarrow/array_reader_test.cc diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml index 3542abdc..4e0425c4 100644 --- a/.github/workflows/build-and-test.yaml +++ b/.github/workflows/build-and-test.yaml @@ -26,6 +26,7 @@ jobs: - name: Install dependencies run: | + sudo apt-get update sudo apt install -y -V ca-certificates lsb-release wget cmake valgrind wget https://apache.jfrog.io/artifactory/arrow/$(lsb_release --id --short | tr 'A-Z' 'a-z')/apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb sudo apt-get install -y -V ./apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d52a91f..7c30dd7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,7 @@ add_library( src/geoarrow/wkb_writer.c src/geoarrow/wkt_reader.c src/geoarrow/wkt_writer.c + src/geoarrow/array_reader.c ${GEOARROW_DOUBLE_PARSE_SOURCE} ${GEOARROW_DOUBLE_PRINT_SOURCE} src/geoarrow/nanoarrow.c) @@ -166,6 +167,7 @@ if(GEOARROW_BUILD_TESTS) add_executable(wkb_writer_test src/geoarrow/wkb_writer_test.cc) add_executable(wkt_reader_test src/geoarrow/wkt_reader_test.cc) add_executable(wkt_writer_test src/geoarrow/wkt_writer_test.cc) + add_executable(array_reader_test src/geoarrow/array_reader_test.cc) add_executable(wkx_files_test src/geoarrow/wkx_files_test.cc) add_executable(geoarrow_arrow_test src/geoarrow/geoarrow_arrow_test.cc) @@ -189,6 +191,7 @@ if(GEOARROW_BUILD_TESTS) target_link_libraries(wkb_writer_test geoarrow gtest_main) target_link_libraries(wkt_reader_test geoarrow gtest_main) target_link_libraries(wkt_writer_test geoarrow gtest_main) + target_link_libraries(array_reader_test geoarrow gtest_main) target_link_libraries(wkx_files_test geoarrow gtest_main) target_link_libraries(geoarrow_arrow_test geoarrow arrow_shared gtest_main) @@ -208,5 +211,6 @@ if(GEOARROW_BUILD_TESTS) gtest_discover_tests(wkt_reader_test) gtest_discover_tests(wkt_writer_test) gtest_discover_tests(wkx_files_test) + gtest_discover_tests(array_reader_test) gtest_discover_tests(geoarrow_arrow_test) endif() diff --git a/src/geoarrow/array_reader.c b/src/geoarrow/array_reader.c new file mode 100644 index 00000000..a92198cb --- /dev/null +++ b/src/geoarrow/array_reader.c @@ -0,0 +1,108 @@ + +#include "geoarrow.h" + +#include "nanoarrow.h" + +struct GeoArrowArrayReaderPrivate { + struct GeoArrowWKTReader wkt_reader; + struct GeoArrowWKBReader wkb_reader; +}; + +static GeoArrowErrorCode GeoArrowArrayViewVisitWKT(struct GeoArrowArrayView* array_view, + int64_t offset, int64_t length, + struct GeoArrowWKTReader* reader, + struct GeoArrowVisitor* v) { + struct GeoArrowStringView item; + const int32_t* offset_begin = array_view->offsets[0] + array_view->offset[0] + offset; + + for (int64_t i = 0; i < length; i++) { + if (!array_view->validity_bitmap || + ArrowBitGet(array_view->validity_bitmap, array_view->offset[0] + offset + i)) { + item.data = (const char*)(array_view->data + offset_begin[i]); + item.size_bytes = offset_begin[i + 1] - offset_begin[i]; + NANOARROW_RETURN_NOT_OK(GeoArrowWKTReaderVisit(reader, item, v)); + } else { + NANOARROW_RETURN_NOT_OK(v->feat_start(v)); + NANOARROW_RETURN_NOT_OK(v->null_feat(v)); + NANOARROW_RETURN_NOT_OK(v->feat_end(v)); + } + } + + return GEOARROW_OK; +} + +static GeoArrowErrorCode GeoArrowArrayViewVisitWKB(struct GeoArrowArrayView* array_view, + int64_t offset, int64_t length, + struct GeoArrowWKBReader* reader, + struct GeoArrowVisitor* v) { + struct GeoArrowBufferView item; + const int32_t* offset_begin = array_view->offsets[0] + array_view->offset[0] + offset; + + for (int64_t i = 0; i < length; i++) { + if (!array_view->validity_bitmap || + ArrowBitGet(array_view->validity_bitmap, array_view->offset[0] + offset + i)) { + item.data = array_view->data + offset_begin[i]; + item.size_bytes = offset_begin[i + 1] - offset_begin[i]; + NANOARROW_RETURN_NOT_OK(GeoArrowWKBReaderVisit(reader, item, v)); + } else { + NANOARROW_RETURN_NOT_OK(v->feat_start(v)); + NANOARROW_RETURN_NOT_OK(v->null_feat(v)); + NANOARROW_RETURN_NOT_OK(v->feat_end(v)); + } + } + + return GEOARROW_OK; +} + +GeoArrowErrorCode GeoArrowArrayReaderInit(struct GeoArrowArrayReader* reader) { + struct GeoArrowArrayReaderPrivate* private_data = + (struct GeoArrowArrayReaderPrivate*)ArrowMalloc( + sizeof(struct GeoArrowArrayReaderPrivate)); + + if (private_data == NULL) { + return ENOMEM; + } + + int result = GeoArrowWKTReaderInit(&private_data->wkt_reader); + if (result != GEOARROW_OK) { + ArrowFree(private_data); + return result; + } + + result = GeoArrowWKBReaderInit(&private_data->wkb_reader); + if (result != GEOARROW_OK) { + GeoArrowWKTReaderReset(&private_data->wkt_reader); + ArrowFree(private_data); + return result; + } + + reader->private_data = private_data; + return GEOARROW_OK; +} + +void GeoArrowArrayReaderReset(struct GeoArrowArrayReader* reader) { + struct GeoArrowArrayReaderPrivate* private_data = + (struct GeoArrowArrayReaderPrivate*)reader->private_data; + GeoArrowWKBReaderReset(&private_data->wkb_reader); + GeoArrowWKTReaderReset(&private_data->wkt_reader); + ArrowFree(reader->private_data); +} + +GeoArrowErrorCode GeoArrowArrayReaderVisit(struct GeoArrowArrayReader* reader, + struct GeoArrowArrayView* array_view, + int64_t offset, int64_t length, + struct GeoArrowVisitor* v) { + struct GeoArrowArrayReaderPrivate* private_data = + (struct GeoArrowArrayReaderPrivate*)reader->private_data; + + switch (array_view->schema_view.type) { + case GEOARROW_TYPE_WKT: + return GeoArrowArrayViewVisitWKT(array_view, offset, length, + &private_data->wkt_reader, v); + case GEOARROW_TYPE_WKB: + return GeoArrowArrayViewVisitWKB(array_view, offset, length, + &private_data->wkb_reader, v); + default: + return GeoArrowArrayViewVisit(array_view, offset, length, v); + } +} diff --git a/src/geoarrow/array_reader_test.cc b/src/geoarrow/array_reader_test.cc new file mode 100644 index 00000000..31b174c5 --- /dev/null +++ b/src/geoarrow/array_reader_test.cc @@ -0,0 +1,132 @@ + +#include + +#include "geoarrow.h" + +#include "wkx_testing.hpp" + +TEST(ArrayReaderTest, ArrayReaderTestBasic) { + struct GeoArrowArrayReader reader; + ASSERT_EQ(GeoArrowArrayReaderInit(&reader), GEOARROW_OK); + GeoArrowArrayReaderReset(&reader); +} + +TEST(ArrayReaderTest, ArrayReaderTestVisitWKT) { + struct ArrowSchema schema; + struct ArrowArray array; + enum GeoArrowType type = GEOARROW_TYPE_WKT; + + // Build the array for [POINT (30 10), null] + ASSERT_EQ(GeoArrowSchemaInit(&schema, type), GEOARROW_OK); + ASSERT_EQ(ArrowArrayInitFromSchema(&array, &schema, nullptr), GEOARROW_OK); + ASSERT_EQ(ArrowArrayStartAppending(&array), GEOARROW_OK); + + ASSERT_EQ(ArrowArrayAppendString(&array, ArrowCharView("POINT (30 10)")), GEOARROW_OK); + ASSERT_EQ(ArrowArrayAppendNull(&array, 1), GEOARROW_OK); + + ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), GEOARROW_OK); + + // Set the array view + struct GeoArrowArrayView array_view; + EXPECT_EQ(GeoArrowArrayViewInitFromType(&array_view, type), GEOARROW_OK); + EXPECT_EQ(GeoArrowArrayViewSetArray(&array_view, &array, nullptr), GEOARROW_OK); + + // Check its contents + WKXTester tester; + struct GeoArrowArrayReader reader; + ASSERT_EQ(GeoArrowArrayReaderInit(&reader), GEOARROW_OK); + EXPECT_EQ(GeoArrowArrayReaderVisit(&reader, &array_view, 0, array.length, + tester.WKTVisitor()), + GEOARROW_OK); + auto values = tester.WKTValues(""); + ASSERT_EQ(values.size(), 2); + EXPECT_EQ(values[0], "POINT (30 10)"); + EXPECT_EQ(values[1], ""); + + schema.release(&schema); + array.release(&array); + GeoArrowArrayReaderReset(&reader); +} + +TEST(ArrayReaderTest, ArrayReaderTestVisitWKB) { + struct ArrowSchema schema; + struct ArrowArray array; + enum GeoArrowType type = GEOARROW_TYPE_WKB; + + std::basic_string point({0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40}); + struct ArrowBufferView point_view; + point_view.data.as_uint8 = point.data(); + point_view.size_bytes = point.size(); + + // Build the array for [POINT (30 10), null] + ASSERT_EQ(GeoArrowSchemaInit(&schema, type), GEOARROW_OK); + ASSERT_EQ(ArrowArrayInitFromSchema(&array, &schema, nullptr), GEOARROW_OK); + ASSERT_EQ(ArrowArrayStartAppending(&array), GEOARROW_OK); + + ASSERT_EQ(ArrowArrayAppendBytes(&array, point_view), GEOARROW_OK); + ASSERT_EQ(ArrowArrayAppendNull(&array, 1), GEOARROW_OK); + + ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), GEOARROW_OK); + + // Set the array view + struct GeoArrowArrayView array_view; + EXPECT_EQ(GeoArrowArrayViewInitFromType(&array_view, type), GEOARROW_OK); + EXPECT_EQ(GeoArrowArrayViewSetArray(&array_view, &array, nullptr), GEOARROW_OK); + + // Check its contents + WKXTester tester; + struct GeoArrowArrayReader reader; + ASSERT_EQ(GeoArrowArrayReaderInit(&reader), GEOARROW_OK); + EXPECT_EQ(GeoArrowArrayReaderVisit(&reader, &array_view, 0, array.length, + tester.WKTVisitor()), + GEOARROW_OK); + auto values = tester.WKTValues(""); + ASSERT_EQ(values.size(), 2); + EXPECT_EQ(values[0], "POINT (30 10)"); + EXPECT_EQ(values[1], ""); + + schema.release(&schema); + array.release(&array); + GeoArrowArrayReaderReset(&reader); +} + +TEST(ArrayReaderTest, ArrayReaderTestVisitGeoArrow) { + struct ArrowSchema schema; + struct ArrowArray array; + enum GeoArrowType type = GEOARROW_TYPE_POINT; + + // Build the array for [POINT (30 10), null] + ASSERT_EQ(GeoArrowSchemaInit(&schema, type), GEOARROW_OK); + ASSERT_EQ(ArrowArrayInitFromSchema(&array, &schema, nullptr), GEOARROW_OK); + ASSERT_EQ(ArrowArrayStartAppending(&array), GEOARROW_OK); + + ASSERT_EQ(ArrowArrayAppendDouble(array.children[0], 30), GEOARROW_OK); + ASSERT_EQ(ArrowArrayAppendDouble(array.children[1], 10), GEOARROW_OK); + ASSERT_EQ(ArrowArrayFinishElement(&array), GEOARROW_OK); + ASSERT_EQ(ArrowArrayAppendNull(&array, 1), GEOARROW_OK); + + ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), GEOARROW_OK); + + // Set the array view + struct GeoArrowArrayView array_view; + EXPECT_EQ(GeoArrowArrayViewInitFromType(&array_view, type), GEOARROW_OK); + EXPECT_EQ(GeoArrowArrayViewSetArray(&array_view, &array, nullptr), GEOARROW_OK); + + // Check its contents + WKXTester tester; + struct GeoArrowArrayReader reader; + ASSERT_EQ(GeoArrowArrayReaderInit(&reader), GEOARROW_OK); + EXPECT_EQ(GeoArrowArrayReaderVisit(&reader, &array_view, 0, array.length, + tester.WKTVisitor()), + GEOARROW_OK); + auto values = tester.WKTValues(""); + ASSERT_EQ(values.size(), 2); + EXPECT_EQ(values[0], "POINT (30 10)"); + EXPECT_EQ(values[1], ""); + + schema.release(&schema); + array.release(&array); + GeoArrowArrayReaderReset(&reader); +} diff --git a/src/geoarrow/array_view.c b/src/geoarrow/array_view.c index d84c2e8b..f8583096 100644 --- a/src/geoarrow/array_view.c +++ b/src/geoarrow/array_view.c @@ -25,8 +25,9 @@ static int GeoArrowArrayViewInitInternal(struct GeoArrowArrayView* array_view, array_view->n_offsets = 3; break; default: - GeoArrowErrorSet(error, "Unsupported geometry type in GeoArrowArrayViewInit()"); - return EINVAL; + // i.e., serialized type + array_view->n_offsets = 1; + break; } for (int i = 0; i < 4; i++) { @@ -38,6 +39,7 @@ static int GeoArrowArrayViewInitInternal(struct GeoArrowArrayView* array_view, for (int i = 0; i < 3; i++) { array_view->offsets[i] = NULL; } + array_view->data = NULL; array_view->coords.n_coords = 0; switch (array_view->schema_view.dimensions) { @@ -52,8 +54,9 @@ static int GeoArrowArrayViewInitInternal(struct GeoArrowArrayView* array_view, array_view->coords.n_values = 4; break; default: - GeoArrowErrorSet(error, "Unsupported dimensions in GeoArrowArrayViewInit()"); - return EINVAL; + // i.e., serialized type + array_view->coords.n_coords = 0; + break; } switch (array_view->schema_view.coord_type) { @@ -64,8 +67,9 @@ static int GeoArrowArrayViewInitInternal(struct GeoArrowArrayView* array_view, array_view->coords.coords_stride = array_view->coords.n_values; break; default: - GeoArrowErrorSet(error, "Unsupported coord type in GeoArrowArrayViewInit()"); - return EINVAL; + // i.e., serialized type + array_view->coords.coords_stride = 0; + break; } for (int i = 0; i < 4; i++) { @@ -197,10 +201,32 @@ static int GeoArrowArrayViewSetArrayInternal(struct GeoArrowArrayView* array_vie level + 1); } +GeoArrowErrorCode GeoArrowArrayViewSetArraySerialized( + struct GeoArrowArrayView* array_view, struct ArrowArray* array, + struct GeoArrowError* error) { + array_view->length[0] = array->length; + array_view->offset[0] = array->offset; + + array_view->offsets[0] = (const int32_t*)array->buffers[1]; + array_view->data = (const uint8_t*)array->buffers[2]; + return GEOARROW_OK; +} + GeoArrowErrorCode GeoArrowArrayViewSetArray(struct GeoArrowArrayView* array_view, struct ArrowArray* array, struct GeoArrowError* error) { - NANOARROW_RETURN_NOT_OK(GeoArrowArrayViewSetArrayInternal(array_view, array, error, 0)); + switch (array_view->schema_view.type) { + case GEOARROW_TYPE_WKT: + case GEOARROW_TYPE_WKB: + NANOARROW_RETURN_NOT_OK( + GeoArrowArrayViewSetArraySerialized(array_view, array, error)); + break; + default: + NANOARROW_RETURN_NOT_OK( + GeoArrowArrayViewSetArrayInternal(array_view, array, error, 0)); + break; + } + array_view->validity_bitmap = array->buffers[0]; return GEOARROW_OK; } diff --git a/src/geoarrow/array_view_test.cc b/src/geoarrow/array_view_test.cc index fac0cc46..582cf516 100644 --- a/src/geoarrow/array_view_test.cc +++ b/src/geoarrow/array_view_test.cc @@ -102,17 +102,6 @@ INSTANTIATE_TEST_SUITE_P( GEOARROW_TYPE_INTERLEAVED_MULTILINESTRING_ZM, GEOARROW_TYPE_INTERLEAVED_MULTIPOLYGON_ZM)); -TEST(ArrayViewTest, ArrayViewTestInitErrors) { - struct GeoArrowArrayView array_view; - struct GeoArrowError error; - struct ArrowSchema schema; - - ASSERT_EQ(GeoArrowSchemaInitExtension(&schema, GEOARROW_TYPE_WKB), GEOARROW_OK); - EXPECT_EQ(GeoArrowArrayViewInitFromSchema(&array_view, &schema, &error), EINVAL); - EXPECT_STREQ(error.message, "Unsupported geometry type in GeoArrowArrayViewInit()"); - schema.release(&schema); -} - TEST(ArrayViewTest, ArrayViewTestSetArrayErrors) { struct GeoArrowArrayView array_view; struct GeoArrowError error; diff --git a/src/geoarrow/geoarrow.h b/src/geoarrow/geoarrow.h index 89579239..02621def 100644 --- a/src/geoarrow/geoarrow.h +++ b/src/geoarrow/geoarrow.h @@ -429,6 +429,29 @@ GeoArrowErrorCode GeoArrowWKBReaderVisit(struct GeoArrowWKBReader* reader, /// \brief Free resources held by a GeoArrowWKBWriter void GeoArrowWKBReaderReset(struct GeoArrowWKBReader* reader); +/// \brief Array reader for any geoarrow extension array +struct GeoArrowArrayReader { + void* private_data; +}; + +/// \brief Initialize the memory of a GeoArrowArrayReader +/// +/// If GEOARROW_OK is returned, the caller is responsible for calling +/// GeoArrowArrayReaderReset(). +GeoArrowErrorCode GeoArrowArrayReaderInit(struct GeoArrowArrayReader* reader); + +/// \brief Visit a GeoArrowArray +/// +/// The caller must have initialized the GeoArrowVisitor with the appropriate +/// writer before calling this function. +GeoArrowErrorCode GeoArrowArrayReaderVisit(struct GeoArrowArrayReader* reader, + struct GeoArrowArrayView* array_view, + int64_t offset, int64_t length, + struct GeoArrowVisitor* v); + +/// \brief Free resources held by a GeoArrowArrayReader +void GeoArrowArrayReaderReset(struct GeoArrowArrayReader* reader); + /// @} #ifdef __cplusplus diff --git a/src/geoarrow/geoarrow_type.h b/src/geoarrow/geoarrow_type.h index 2928e370..72aa9d44 100644 --- a/src/geoarrow/geoarrow_type.h +++ b/src/geoarrow/geoarrow_type.h @@ -408,6 +408,9 @@ struct GeoArrowArrayView { /// \brief The last offset value in each offset bufer int32_t last_offset[3]; + /// \brief For serialized types, a pointer to the start of the data buffer + const uint8_t* data; + /// \brief Generic view of the coordinates in this array struct GeoArrowCoordView coords; }; diff --git a/src/geoarrow/kernel.c b/src/geoarrow/kernel.c index 387d6112..50c813df 100644 --- a/src/geoarrow/kernel.c +++ b/src/geoarrow/kernel.c @@ -99,10 +99,8 @@ struct GeoArrowBox2DPrivate { struct GeoArrowVisitorKernelPrivate { struct GeoArrowVisitor v; int visit_by_feature; - struct GeoArrowWKBReader wkb_reader; - struct GeoArrowWKTReader wkt_reader; + struct GeoArrowArrayReader reader; struct GeoArrowArrayView array_view; - struct ArrowArrayView na_array_view; struct GeoArrowWKBWriter wkb_writer; struct GeoArrowWKTWriter wkt_writer; struct GeoArrowBuilder builder; @@ -144,22 +142,14 @@ static int finish_push_batch_do_nothing(struct GeoArrowVisitorKernelPrivate* pri static void kernel_release_visitor(struct GeoArrowKernel* kernel) { struct GeoArrowVisitorKernelPrivate* private_data = (struct GeoArrowVisitorKernelPrivate*)kernel->private_data; - if (private_data->wkb_reader.private_data != NULL) { - GeoArrowWKBReaderReset(&private_data->wkb_reader); - } - - if (private_data->wkt_reader.private_data != NULL) { - GeoArrowWKTReaderReset(&private_data->wkt_reader); + if (private_data->reader.private_data != NULL) { + GeoArrowArrayReaderReset(&private_data->reader); } if (private_data->builder.private_data != NULL) { GeoArrowBuilderReset(&private_data->builder); } - if (private_data->na_array_view.storage_type != NANOARROW_TYPE_UNINITIALIZED) { - ArrowArrayViewReset(&private_data->na_array_view); - } - if (private_data->wkb_writer.private_data != NULL) { GeoArrowWKBWriterReset(&private_data->wkb_writer); } @@ -178,75 +168,8 @@ static void kernel_release_visitor(struct GeoArrowKernel* kernel) { kernel->release = NULL; } -static int kernel_push_batch_wkb(struct GeoArrowKernel* kernel, struct ArrowArray* array, - struct ArrowArray* out, struct GeoArrowError* error) { - struct GeoArrowVisitorKernelPrivate* private_data = - (struct GeoArrowVisitorKernelPrivate*)kernel->private_data; - - private_data->v.error = error; - struct ArrowArrayView* array_view = &private_data->na_array_view; - struct GeoArrowBufferView buffer_view; - NANOARROW_RETURN_NOT_OK( - ArrowArrayViewSetArray(array_view, array, (struct ArrowError*)error)); - - for (int64_t i = 0; i < array->length; i++) { - if (ArrowArrayViewIsNull(array_view, i)) { - NANOARROW_RETURN_NOT_OK(private_data->v.feat_start(&private_data->v)); - NANOARROW_RETURN_NOT_OK(private_data->v.null_feat(&private_data->v)); - NANOARROW_RETURN_NOT_OK(private_data->v.feat_end(&private_data->v)); - } else { - struct ArrowBufferView value = ArrowArrayViewGetBytesUnsafe(array_view, i); - buffer_view.data = value.data.as_uint8; - buffer_view.size_bytes = value.size_bytes; - int result = GeoArrowWKBReaderVisit(&private_data->wkb_reader, buffer_view, - &private_data->v); - if (result == EAGAIN) { - NANOARROW_RETURN_NOT_OK(private_data->v.feat_end(&private_data->v)); - } else if (result != NANOARROW_OK) { - return result; - } - } - } - - return private_data->finish_push_batch(private_data, out, error); -} - -static int kernel_push_batch_wkt(struct GeoArrowKernel* kernel, struct ArrowArray* array, - struct ArrowArray* out, struct GeoArrowError* error) { - struct GeoArrowVisitorKernelPrivate* private_data = - (struct GeoArrowVisitorKernelPrivate*)kernel->private_data; - - private_data->v.error = error; - struct ArrowArrayView* array_view = &private_data->na_array_view; - struct GeoArrowStringView buffer_view; - NANOARROW_RETURN_NOT_OK( - ArrowArrayViewSetArray(array_view, array, (struct ArrowError*)error)); - - for (int64_t i = 0; i < array->length; i++) { - if (ArrowArrayViewIsNull(array_view, i)) { - NANOARROW_RETURN_NOT_OK(private_data->v.feat_start(&private_data->v)); - NANOARROW_RETURN_NOT_OK(private_data->v.null_feat(&private_data->v)); - NANOARROW_RETURN_NOT_OK(private_data->v.feat_end(&private_data->v)); - } else { - struct ArrowStringView value = ArrowArrayViewGetStringUnsafe(array_view, i); - buffer_view.data = value.data; - buffer_view.size_bytes = value.size_bytes; - int result = GeoArrowWKTReaderVisit(&private_data->wkt_reader, buffer_view, - &private_data->v); - if (result == EAGAIN) { - NANOARROW_RETURN_NOT_OK(private_data->v.feat_end(&private_data->v)); - } else if (result != NANOARROW_OK) { - return result; - } - } - } - - return private_data->finish_push_batch(private_data, out, error); -} - -static int kernel_push_batch_geoarrow(struct GeoArrowKernel* kernel, - struct ArrowArray* array, struct ArrowArray* out, - struct GeoArrowError* error) { +static int kernel_push_batch(struct GeoArrowKernel* kernel, struct ArrowArray* array, + struct ArrowArray* out, struct GeoArrowError* error) { struct GeoArrowVisitorKernelPrivate* private_data = (struct GeoArrowVisitorKernelPrivate*)kernel->private_data; @@ -254,16 +177,16 @@ static int kernel_push_batch_geoarrow(struct GeoArrowKernel* kernel, GeoArrowArrayViewSetArray(&private_data->array_view, array, error)); private_data->v.error = error; - NANOARROW_RETURN_NOT_OK(GeoArrowArrayViewVisit(&private_data->array_view, 0, - array->length, &private_data->v)); + NANOARROW_RETURN_NOT_OK(GeoArrowArrayReaderVisit(&private_data->reader, + &private_data->array_view, 0, + array->length, &private_data->v)); return private_data->finish_push_batch(private_data, out, error); } -static int kernel_push_batch_geoarrow_by_feature(struct GeoArrowKernel* kernel, - struct ArrowArray* array, - struct ArrowArray* out, - struct GeoArrowError* error) { +static int kernel_push_batch_by_feature(struct GeoArrowKernel* kernel, + struct ArrowArray* array, struct ArrowArray* out, + struct GeoArrowError* error) { struct GeoArrowVisitorKernelPrivate* private_data = (struct GeoArrowVisitorKernelPrivate*)kernel->private_data; @@ -271,10 +194,10 @@ static int kernel_push_batch_geoarrow_by_feature(struct GeoArrowKernel* kernel, GeoArrowArrayViewSetArray(&private_data->array_view, array, error)); private_data->v.error = error; - + int result; for (int64_t i = 0; i < array->length; i++) { - int result = - GeoArrowArrayViewVisit(&private_data->array_view, i, 1, &private_data->v); + result = GeoArrowArrayReaderVisit(&private_data->reader, &private_data->array_view, i, + 1, &private_data->v); if (result == EAGAIN) { NANOARROW_RETURN_NOT_OK(private_data->v.feat_end(&private_data->v)); @@ -300,21 +223,12 @@ static int kernel_visitor_start(struct GeoArrowKernel* kernel, struct ArrowSchem case GEOARROW_TYPE_LARGE_WKB: case GEOARROW_TYPE_LARGE_WKT: return EINVAL; - case GEOARROW_TYPE_WKT: - kernel->push_batch = &kernel_push_batch_wkt; - NANOARROW_RETURN_NOT_OK(GeoArrowWKTReaderInit(&private_data->wkt_reader)); - ArrowArrayViewInitFromType(&private_data->na_array_view, NANOARROW_TYPE_STRING); - break; - case GEOARROW_TYPE_WKB: - kernel->push_batch = &kernel_push_batch_wkb; - GeoArrowWKBReaderInit(&private_data->wkb_reader); - ArrowArrayViewInitFromType(&private_data->na_array_view, NANOARROW_TYPE_BINARY); - break; default: + NANOARROW_RETURN_NOT_OK(GeoArrowArrayReaderInit(&private_data->reader)); if (private_data->visit_by_feature) { - kernel->push_batch = &kernel_push_batch_geoarrow_by_feature; + kernel->push_batch = &kernel_push_batch_by_feature; } else { - kernel->push_batch = &kernel_push_batch_geoarrow; + kernel->push_batch = &kernel_push_batch; } NANOARROW_RETURN_NOT_OK( GeoArrowArrayViewInitFromType(&private_data->array_view, schema_view.type));