/* * 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 #include #include #include #include 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 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( \ 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 *>(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; } 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 *", static_cast(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(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(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(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(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(arrow_metadata->key(i).c_str()), const_cast(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, 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 garrow_field_get_raw(GArrowField *field) { auto priv = GARROW_FIELD_GET_PRIVATE(field); return priv->field; }