diff options
Diffstat (limited to 'src/arrow/c_glib/arrow-glib/field.cpp')
-rw-r--r-- | src/arrow/c_glib/arrow-glib/field.cpp | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/src/arrow/c_glib/arrow-glib/field.cpp b/src/arrow/c_glib/arrow-glib/field.cpp new file mode 100644 index 000000000..1bb2dd181 --- /dev/null +++ b/src/arrow/c_glib/arrow-glib/field.cpp @@ -0,0 +1,441 @@ +/* + * 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 <arrow-glib/data-type.hpp> +#include <arrow-glib/error.hpp> +#include <arrow-glib/field.hpp> +#include <arrow-glib/internal-hash-table.hpp> + +#include <arrow/c/bridge.h> + +G_BEGIN_DECLS + +/** + * SECTION: field + * @short_description: Field class + * + * #GArrowField is a class for field. Field is metadata of a + * column. It has name, data type (#GArrowDataType) and nullable + * information of the column. + */ + +typedef struct GArrowFieldPrivate_ { + std::shared_ptr<arrow::Field> field; + GArrowDataType *data_type; +} GArrowFieldPrivate; + +enum { + PROP_FIELD = 1, + PROP_DATA_TYPE +}; + +G_DEFINE_TYPE_WITH_PRIVATE(GArrowField, + garrow_field, + G_TYPE_OBJECT) + +#define GARROW_FIELD_GET_PRIVATE(obj) \ + static_cast<GArrowFieldPrivate *>( \ + garrow_field_get_instance_private( \ + GARROW_FIELD(obj))) + +static void +garrow_field_dispose(GObject *object) +{ + auto priv = GARROW_FIELD_GET_PRIVATE(object); + + if (priv->data_type) { + g_object_unref(priv->data_type); + priv->data_type = nullptr; + } + + G_OBJECT_CLASS(garrow_field_parent_class)->dispose(object); +} + +static void +garrow_field_finalize(GObject *object) +{ + auto priv = GARROW_FIELD_GET_PRIVATE(object); + + priv->field.~shared_ptr(); + + G_OBJECT_CLASS(garrow_field_parent_class)->finalize(object); +} + +static void +garrow_field_set_property(GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + auto priv = GARROW_FIELD_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_FIELD: + priv->field = + *static_cast<std::shared_ptr<arrow::Field> *>(g_value_get_pointer(value)); + break; + case PROP_DATA_TYPE: + priv->data_type = GARROW_DATA_TYPE(g_value_dup_object(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +garrow_field_init(GArrowField *object) +{ + auto priv = GARROW_FIELD_GET_PRIVATE(object); + new(&priv->field) std::shared_ptr<arrow::Field>; +} + +static void +garrow_field_class_init(GArrowFieldClass *klass) +{ + auto gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->dispose = garrow_field_dispose; + gobject_class->finalize = garrow_field_finalize; + gobject_class->set_property = garrow_field_set_property; + + GParamSpec *spec; + spec = g_param_spec_pointer("field", + "Field", + "The raw std::shared<arrow::Field> *", + static_cast<GParamFlags>(G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property(gobject_class, PROP_FIELD, spec); + + spec = g_param_spec_object("data-type", + "Data type", + "The data type", + GARROW_TYPE_DATA_TYPE, + static_cast<GParamFlags>(G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property(gobject_class, PROP_DATA_TYPE, spec); +} + +/** + * garrow_field_import: + * @c_abi_schema: (not nullable): A `struct ArrowSchema *`. + * @error: (nullable): Return location for a #GError or %NULL. + * + * Returns: (transfer full) (nullable): An imported #GArrowField on success, + * %NULL on error. + * + * You don't need to release the passed `struct ArrowSchema *`, + * even if this function reports an error. + * + * Since: 6.0.0 + */ +GArrowField * +garrow_field_import(gpointer c_abi_schema, GError **error) +{ + auto arrow_field_result = + arrow::ImportField(static_cast<ArrowSchema *>(c_abi_schema)); + if (garrow::check(error, arrow_field_result, "[field][import]")) { + return garrow_field_new_raw(&(*arrow_field_result), nullptr); + } else { + return NULL; + } +} + +/** + * garrow_field_new: + * @name: The name of the field. + * @data_type: The data type of the field. + * + * Returns: A newly created #GArrowField. + */ +GArrowField * +garrow_field_new(const gchar *name, + GArrowDataType *data_type) +{ + auto arrow_data_type = garrow_data_type_get_raw(data_type); + auto arrow_field = std::make_shared<arrow::Field>(name, arrow_data_type); + return garrow_field_new_raw(&arrow_field, data_type); +} + +/** + * garrow_field_new_full: + * @name: The name of the field. + * @data_type: The data type of the field. + * @nullable: Whether null may be included or not. + * + * Returns: A newly created #GArrowField. + */ +GArrowField * +garrow_field_new_full(const gchar *name, + GArrowDataType *data_type, + gboolean nullable) +{ + auto arrow_field = + std::make_shared<arrow::Field>(name, + garrow_data_type_get_raw(data_type), + nullable); + return garrow_field_new_raw(&arrow_field, data_type); +} + +/** + * garrow_field_export: + * @field: A #GArrowField. + * @error: (nullable): Return location for a #GError or %NULL. + * + * Returns: (transfer full) (nullable): An exported #GArrowField as + * `struct ArrowStruct *` on success, %NULL on error. + * + * It should be freed with the `ArrowSchema::release` callback then + * g_free() when no longer needed. + * + * Since: 6.0.0 + */ +gpointer +garrow_field_export(GArrowField *field, GError **error) +{ + const auto arrow_field = garrow_field_get_raw(field); + auto c_abi_schema = g_new(ArrowSchema, 1); + auto status = arrow::ExportField(*arrow_field, c_abi_schema); + if (garrow::check(error, status, "[field][export]")) { + return c_abi_schema; + } else { + g_free(c_abi_schema); + return NULL; + } +} + +/** + * garrow_field_get_name: + * @field: A #GArrowField. + * + * Returns: The name of the field. + */ +const gchar * +garrow_field_get_name(GArrowField *field) +{ + const auto arrow_field = garrow_field_get_raw(field); + return arrow_field->name().c_str(); +} + +/** + * garrow_field_get_data_type: + * @field: A #GArrowField. + * + * Returns: (transfer none): The data type of the field. + */ +GArrowDataType * +garrow_field_get_data_type(GArrowField *field) +{ + auto priv = GARROW_FIELD_GET_PRIVATE(field); + return priv->data_type; +} + +/** + * garrow_field_is_nullable: + * @field: A #GArrowField. + * + * Returns: Whether the filed may include null or not. + */ +gboolean +garrow_field_is_nullable(GArrowField *field) +{ + const auto arrow_field = garrow_field_get_raw(field); + return arrow_field->nullable(); +} + +/** + * garrow_field_equal: + * @field: A #GArrowField. + * @other_field: A #GArrowField to be compared. + * + * Returns: %TRUE if both of them have the same data, %FALSE + * otherwise. + */ +gboolean +garrow_field_equal(GArrowField *field, + GArrowField *other_field) +{ + const auto arrow_field = garrow_field_get_raw(field); + const auto arrow_other_field = garrow_field_get_raw(other_field); + return arrow_field->Equals(arrow_other_field); +} + +/** + * garrow_field_to_string: + * @field: A #GArrowField. + * + * Returns: The string representation of the field. + */ +gchar * +garrow_field_to_string(GArrowField *field) +{ + const auto arrow_field = garrow_field_get_raw(field); + return g_strdup(arrow_field->ToString().c_str()); +} + +/** + * garrow_field_to_string_metadata: + * @field: A #GArrowField. + * @show_metadata: Whether include metadata or not. + * + * Returns: The string representation of the field. + * + * It should be freed with g_free() when no longer needed. + * + * Since: 3.0.0 + */ +gchar * +garrow_field_to_string_metadata(GArrowField *field, gboolean show_metadata) +{ + const auto arrow_field = garrow_field_get_raw(field); + return g_strdup(arrow_field->ToString(show_metadata).c_str()); +} + +/** + * garrow_field_has_metadata: + * @field: A #GArrowField. + * + * Returns: %TRUE if the field has metadata, %FALSE otherwise. + * + * Since: 3.0.0 + */ +gboolean +garrow_field_has_metadata(GArrowField *field) +{ + const auto arrow_field = garrow_field_get_raw(field); + return arrow_field->HasMetadata(); +} + +/** + * garrow_field_get_metadata: + * @field: A #GArrowField. + * + * Returns: (element-type utf8 utf8) (nullable) (transfer full): The + * metadata in the field. + * + * It should be freed with g_hash_table_unref() when no longer needed. + * + * Since: 3.0.0 + */ +GHashTable * +garrow_field_get_metadata(GArrowField *field) +{ + const auto arrow_field = garrow_field_get_raw(field); + if (!arrow_field->HasMetadata()) { + return NULL; + } + + auto arrow_metadata = arrow_field->metadata(); + auto metadata = g_hash_table_new(g_str_hash, g_str_equal); + const auto n = arrow_metadata->size(); + for (int64_t i = 0; i < n; ++i) { + g_hash_table_insert(metadata, + const_cast<gchar *>(arrow_metadata->key(i).c_str()), + const_cast<gchar *>(arrow_metadata->value(i).c_str())); + } + return metadata; +} + +/** + * garrow_field_with_metadata: + * @field: A #GArrowField. + * @metadata: (element-type utf8 utf8): A new associated metadata. + * + * Returns: (transfer full): The new field with the given metadata. + * + * Since: 3.0.0 + */ +GArrowField * +garrow_field_with_metadata(GArrowField *field, + GHashTable *metadata) +{ + const auto arrow_field = garrow_field_get_raw(field); + auto arrow_metadata = garrow_internal_hash_table_to_metadata(metadata); + auto arrow_new_field = arrow_field->WithMetadata(arrow_metadata); + return garrow_field_new_raw(&arrow_new_field, + garrow_field_get_data_type(field)); +} + +/** + * garrow_field_with_merged_metadata: + * @field: A #GArrowField. + * @metadata: (element-type utf8 utf8): An additional associated metadata. + * + * Returns: (transfer full): The new field that also has the given + * metadata. If both of the existing metadata and the given metadata + * have the same keys, the values in the given metadata are used. + * + * Since: 3.0.0 + */ +GArrowField * +garrow_field_with_merged_metadata(GArrowField *field, + GHashTable *metadata) +{ + const auto arrow_field = garrow_field_get_raw(field); + auto arrow_metadata = garrow_internal_hash_table_to_metadata(metadata); + auto arrow_new_field = arrow_field->WithMergedMetadata(arrow_metadata); + return garrow_field_new_raw(&arrow_new_field, + garrow_field_get_data_type(field)); +} + +/** + * garrow_field_remove_metadata: + * @field: A #GArrowField. + * + * Returns: (transfer full): The new field that doesn't have metadata. + * + * Since: 3.0.0 + */ +GArrowField * +garrow_field_remove_metadata(GArrowField *field) +{ + const auto arrow_field = garrow_field_get_raw(field); + auto arrow_new_field = arrow_field->RemoveMetadata(); + return garrow_field_new_raw(&arrow_new_field, + garrow_field_get_data_type(field)); +} + +G_END_DECLS + +GArrowField * +garrow_field_new_raw(std::shared_ptr<arrow::Field> *arrow_field, + GArrowDataType *data_type) +{ + bool data_type_need_unref = false; + if (!data_type) { + auto arrow_data_type = (*arrow_field)->type(); + data_type = garrow_data_type_new_raw(&arrow_data_type); + data_type_need_unref = true; + } + auto field = GARROW_FIELD(g_object_new(GARROW_TYPE_FIELD, + "field", arrow_field, + "data-type", data_type, + NULL)); + if (data_type_need_unref) { + g_object_unref(data_type); + } + return field; +} + +std::shared_ptr<arrow::Field> +garrow_field_get_raw(GArrowField *field) +{ + auto priv = GARROW_FIELD_GET_PRIVATE(field); + return priv->field; +} |