| /* |
| * 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 <stdlib.h> |
| |
| #include <arrow-glib/arrow-glib.h> |
| |
| #define EXAMPLE_TYPE_UUID_ARRAY (example_uuid_array_get_type()) |
| G_DECLARE_DERIVABLE_TYPE(ExampleUUIDArray, |
| example_uuid_array, |
| EXAMPLE, |
| UUID_ARRAY, |
| GArrowExtensionArray) |
| struct _ExampleUUIDArrayClass |
| { |
| GArrowExtensionArrayClass parent_class; |
| }; |
| |
| G_DEFINE_TYPE(ExampleUUIDArray, |
| example_uuid_array, |
| GARROW_TYPE_EXTENSION_ARRAY) |
| |
| static void |
| example_uuid_array_init(ExampleUUIDArray *object) |
| { |
| } |
| |
| static void |
| example_uuid_array_class_init(ExampleUUIDArrayClass *klass) |
| { |
| } |
| |
| |
| #define EXAMPLE_TYPE_UUID_DATA_TYPE (example_uuid_data_type_get_type()) |
| G_DECLARE_DERIVABLE_TYPE(ExampleUUIDDataType, |
| example_uuid_data_type, |
| EXAMPLE, |
| UUID_DATA_TYPE, |
| GArrowExtensionDataType) |
| struct _ExampleUUIDDataTypeClass |
| { |
| GArrowExtensionDataTypeClass parent_class; |
| }; |
| |
| |
| G_DEFINE_TYPE(ExampleUUIDDataType, |
| example_uuid_data_type, |
| GARROW_TYPE_EXTENSION_DATA_TYPE) |
| |
| static gchar * |
| example_uuid_data_type_get_extension_name(GArrowExtensionDataType *data_type) |
| { |
| return g_strdup("uuid"); |
| } |
| |
| static gboolean |
| example_uuid_data_type_equal(GArrowExtensionDataType *data_type, |
| GArrowExtensionDataType *other_data_type) |
| { |
| /* Compare parameters if they exists. */ |
| return TRUE; |
| } |
| |
| static const gchar *example_uuid_data_type_serialize_id = "uuid-serialized"; |
| static ExampleUUIDDataType *example_uuid_data_type_new(void); |
| |
| static GArrowDataType * |
| example_uuid_data_type_deserialize(GArrowExtensionDataType *data_type, |
| GArrowDataType *storage_data_type, |
| GBytes *serialized_data, |
| GError **error) |
| { |
| gsize raw_data_size; |
| gconstpointer raw_data = g_bytes_get_data(serialized_data, &raw_data_size); |
| if (!(raw_data_size == strlen(example_uuid_data_type_serialize_id) && |
| strncmp(raw_data, |
| example_uuid_data_type_serialize_id, |
| raw_data_size) == 0)) { |
| g_set_error(error, |
| GARROW_ERROR, |
| GARROW_ERROR_INVALID, |
| "[uuid-data-type][deserialize] " |
| "identifier must be <%s>: <%.*s>", |
| example_uuid_data_type_serialize_id, |
| (gint)raw_data_size, |
| (const gchar *)raw_data); |
| return NULL; |
| } |
| |
| GArrowDataType *expected_storage_data_type; |
| g_object_get(data_type, |
| "storage-data-type", &expected_storage_data_type, |
| NULL); |
| if (!garrow_data_type_equal(storage_data_type, |
| expected_storage_data_type)) { |
| gchar *expected = garrow_data_type_to_string(expected_storage_data_type); |
| gchar *actual = garrow_data_type_to_string(storage_data_type); |
| g_set_error(error, |
| GARROW_ERROR, |
| GARROW_ERROR_INVALID, |
| "[uuid-data-type][deserialize] " |
| "storage data type must be <%s>: <%s>", |
| expected, |
| actual); |
| g_free(actual); |
| g_free(expected); |
| return NULL; |
| } |
| |
| return GARROW_DATA_TYPE(example_uuid_data_type_new()); |
| } |
| |
| static GBytes * |
| example_uuid_data_type_serialize(GArrowExtensionDataType *data_type) |
| { |
| return g_bytes_new_static(example_uuid_data_type_serialize_id, |
| strlen(example_uuid_data_type_serialize_id)); |
| } |
| |
| static GType |
| example_uuid_data_type_get_array_gtype(GArrowExtensionDataType *data_type) |
| { |
| return EXAMPLE_TYPE_UUID_ARRAY; |
| } |
| |
| static void |
| example_uuid_data_type_init(ExampleUUIDDataType *object) |
| { |
| } |
| |
| static void |
| example_uuid_data_type_class_init(ExampleUUIDDataTypeClass *klass) |
| { |
| GArrowExtensionDataTypeClass *extension_klass = |
| GARROW_EXTENSION_DATA_TYPE_CLASS(klass); |
| extension_klass->get_extension_name = |
| example_uuid_data_type_get_extension_name; |
| extension_klass->equal = example_uuid_data_type_equal; |
| extension_klass->deserialize = example_uuid_data_type_deserialize; |
| extension_klass->serialize = example_uuid_data_type_serialize; |
| extension_klass->get_array_gtype = example_uuid_data_type_get_array_gtype; |
| } |
| |
| static ExampleUUIDDataType * |
| example_uuid_data_type_new(void) |
| { |
| GArrowFixedSizeBinaryDataType *storage_data_type = |
| garrow_fixed_size_binary_data_type_new(16); |
| return g_object_new(EXAMPLE_TYPE_UUID_DATA_TYPE, |
| "storage-data-type", storage_data_type, |
| NULL); |
| } |
| |
| |
| int |
| main(int argc, char **argv) |
| { |
| GArrowExtensionDataTypeRegistry *registry = |
| garrow_extension_data_type_registry_default(); |
| |
| /* Create UUID extension data type. */ |
| ExampleUUIDDataType *uuid_data_type = example_uuid_data_type_new(); |
| GArrowExtensionDataType *extension_data_type = |
| GARROW_EXTENSION_DATA_TYPE(uuid_data_type); |
| /* Register the created UUID extension data type. */ |
| GError *error = NULL; |
| if (!garrow_extension_data_type_registry_register(registry, |
| extension_data_type, |
| &error)) { |
| g_print("failed to register: %s\n", error->message); |
| g_error_free(error); |
| g_object_unref(registry); |
| return EXIT_FAILURE; |
| } |
| |
| { |
| /* Build storage data for the created UUID extension data type. */ |
| GArrowFixedSizeBinaryDataType *storage_data_type; |
| g_object_get(extension_data_type, |
| "storage-data-type", &storage_data_type, |
| NULL); |
| GArrowFixedSizeBinaryArrayBuilder *builder = |
| garrow_fixed_size_binary_array_builder_new(storage_data_type); |
| g_object_unref(storage_data_type); |
| garrow_fixed_size_binary_array_builder_append_value( |
| builder, |
| (const guint8 *)"0123456789012345", |
| 16, |
| &error); |
| if (!error) { |
| garrow_array_builder_append_null(GARROW_ARRAY_BUILDER(builder), &error); |
| } |
| if (!error) { |
| garrow_fixed_size_binary_array_builder_append_value( |
| builder, |
| (const guint8 *)"abcdefghijklmnop", |
| 16, |
| &error); |
| } |
| if (error) { |
| g_print("failed to append elements: %s\n", error->message); |
| g_error_free(error); |
| g_object_unref(builder); |
| goto exit; |
| } |
| GArrowArray *storage = |
| garrow_array_builder_finish(GARROW_ARRAY_BUILDER(builder), &error); |
| g_object_unref(builder); |
| if (error) { |
| g_print("failed to build storage: %s\n", error->message); |
| g_error_free(error); |
| goto exit; |
| } |
| |
| /* Wrap the created storage data as the created UUID extension array. */ |
| GArrowExtensionArray *extension_array = |
| garrow_extension_data_type_wrap_array(extension_data_type, |
| storage); |
| g_object_unref(storage); |
| gint64 n_rows = garrow_array_get_length(GARROW_ARRAY(extension_array)); |
| |
| /* Create a record batch to serialize the created UUID extension array. */ |
| GList *fields = NULL; |
| fields = g_list_append(fields, |
| garrow_field_new("uuid", |
| GARROW_DATA_TYPE(uuid_data_type))); |
| GArrowSchema *schema = garrow_schema_new(fields); |
| g_list_free_full(fields, g_object_unref); |
| GList *columns = NULL; |
| columns = g_list_append(columns, extension_array); |
| GArrowRecordBatch *record_batch = |
| garrow_record_batch_new(schema, n_rows, columns, &error); |
| g_list_free_full(columns, g_object_unref); |
| if (error) { |
| g_print("failed to create record batch: %s\n", error->message); |
| g_error_free(error); |
| g_object_unref(schema); |
| goto exit; |
| } |
| |
| /* Serialize the created record batch. */ |
| GArrowResizableBuffer *buffer = garrow_resizable_buffer_new(0, &error); |
| if (error) { |
| g_print("failed to create buffer: %s\n", error->message); |
| g_error_free(error); |
| g_object_unref(schema); |
| g_object_unref(record_batch); |
| goto exit; |
| } |
| { |
| GArrowBufferOutputStream *output = |
| garrow_buffer_output_stream_new(buffer); |
| GArrowRecordBatchStreamWriter *writer = |
| garrow_record_batch_stream_writer_new(GARROW_OUTPUT_STREAM(output), |
| schema, |
| &error); |
| if (error) { |
| g_print("failed to create writer: %s\n", error->message); |
| g_error_free(error); |
| g_object_unref(output); |
| g_object_unref(buffer); |
| g_object_unref(schema); |
| g_object_unref(record_batch); |
| goto exit; |
| } |
| garrow_record_batch_writer_write_record_batch( |
| GARROW_RECORD_BATCH_WRITER(writer), |
| record_batch, |
| &error); |
| if (error) { |
| g_print("failed to write record batch: %s\n", error->message); |
| g_error_free(error); |
| g_object_unref(writer); |
| g_object_unref(output); |
| g_object_unref(buffer); |
| g_object_unref(schema); |
| g_object_unref(record_batch); |
| goto exit; |
| } |
| g_object_unref(schema); |
| g_object_unref(record_batch); |
| garrow_record_batch_writer_close(GARROW_RECORD_BATCH_WRITER(writer), |
| &error); |
| g_object_unref(writer); |
| g_object_unref(output); |
| if (error) { |
| g_print("failed to close writer: %s\n", error->message); |
| g_error_free(error); |
| g_object_unref(buffer); |
| goto exit; |
| } |
| } |
| |
| /* Deserialize the serialized record batch. */ |
| { |
| GArrowBufferInputStream *input = |
| garrow_buffer_input_stream_new(GARROW_BUFFER(buffer)); |
| GArrowRecordBatchStreamReader *reader = |
| garrow_record_batch_stream_reader_new(GARROW_INPUT_STREAM(input), |
| &error); |
| if (error) { |
| g_print("failed to create reader: %s\n", error->message); |
| g_error_free(error); |
| g_object_unref(input); |
| g_object_unref(buffer); |
| goto exit; |
| } |
| record_batch = |
| garrow_record_batch_reader_read_next(GARROW_RECORD_BATCH_READER(reader), |
| &error); |
| if (error) { |
| g_print("failed to read record batch: %s\n", error->message); |
| g_error_free(error); |
| g_object_unref(reader); |
| g_object_unref(input); |
| g_object_unref(buffer); |
| goto exit; |
| } |
| /* Show the deserialize record batch. */ |
| gchar *record_batch_content = |
| garrow_record_batch_to_string(record_batch, |
| &error); |
| if (error) { |
| g_print("failed to dump record batch content: %s\n", error->message); |
| g_error_free(error); |
| error = NULL; |
| } else { |
| g_print("record batch:\n%s\n", record_batch_content); |
| } |
| /* Get the deserialize UUID extension array. */ |
| GArrowArray *deserialized_array = |
| garrow_record_batch_get_column_data(record_batch, 0); |
| g_print("array: %s\n", G_OBJECT_TYPE_NAME(deserialized_array)); |
| g_object_unref(deserialized_array); |
| |
| g_object_unref(record_batch); |
| g_object_unref(reader); |
| g_object_unref(input); |
| } |
| |
| g_object_unref(buffer); |
| } |
| |
| exit: |
| /* Unregister the created UUID extension data type. */ |
| { |
| gchar *data_type_name = |
| garrow_extension_data_type_get_extension_name(extension_data_type); |
| gboolean success = |
| garrow_extension_data_type_registry_unregister(registry, |
| data_type_name, |
| &error); |
| g_free(data_type_name); |
| if (!success) { |
| g_print("failed to unregister: %s\n", error->message); |
| g_error_free(error); |
| g_object_unref(registry); |
| return EXIT_FAILURE; |
| } |
| } |
| |
| g_object_unref(registry); |
| |
| return EXIT_SUCCESS; |
| } |