Skip to content

Commit

Permalink
ARROW-8055: [GLib][Ruby] Add some metadata bindings to GArrowSchema
Browse files Browse the repository at this point in the history
Closes #6566 from kou/glib-schema-metadta

Authored-by: Sutou Kouhei <kou@clear-code.com>
Signed-off-by: Wes McKinney <wesm+git@apache.org>
  • Loading branch information
kou authored and wesm committed Mar 11, 2020
1 parent fe60470 commit 2891311
Show file tree
Hide file tree
Showing 10 changed files with 230 additions and 3 deletions.
2 changes: 1 addition & 1 deletion c_glib/arrow-glib/local-file-system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ garrow_local_file_system_class_init(GArrowLocalFileSystemClass *klass)

/**
* garrow_local_file_system_new:
* @options: (nullable) A #GArrowLocalFileSystemOptions.
* @options: (nullable): A #GArrowLocalFileSystemOptions.
*
* Returns: (transfer full): A newly created #GArrowLocalFileSystem.
*
Expand Down
78 changes: 78 additions & 0 deletions c_glib/arrow-glib/schema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,24 @@ garrow_schema_to_string(GArrowSchema *schema)
return g_strdup(arrow_schema->ToString().c_str());
}

/**
* garrow_schema_to_string_metadata:
* @schema: A #GArrowSchema.
* @show_metadata: Whether include metadata or not.
*
* Returns: The string representation of the schema.
*
* It should be freed with g_free() when no longer needed.
*
* Since: 0.17.0
*/
gchar *
garrow_schema_to_string_metadata(GArrowSchema *schema, gboolean show_metadata)
{
const auto arrow_schema = garrow_schema_get_raw(schema);
return g_strdup(arrow_schema->ToString(show_metadata).c_str());
}

/**
* garrow_schema_add_field:
* @schema: A #GArrowSchema.
Expand Down Expand Up @@ -344,6 +362,66 @@ garrow_schema_replace_field(GArrowSchema *schema,
}
}

/**
* garrow_schema_get_metadata:
* @schema: A #GArrowSchema.
*
* Returns: (element-type utf8 utf8) (nullable) (transfer full): The
* metadata in the schema.
*
* It should be freed with g_hash_table_unref() when no longer needed.
*
* Since: 0.17.0
*/
GHashTable *
garrow_schema_get_metadata(GArrowSchema *schema)
{
const auto arrow_schema = garrow_schema_get_raw(schema);
if (!arrow_schema->HasMetadata()) {
return NULL;
}

auto arrow_metadata = arrow_schema->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_schema_with_metadata:
* @schema: A #GArrowSchema.
* @metadata: (element-type utf8 utf8): A new associated metadata.
*
* Returns: (transfer full): The new schema with the given metadata.
*
* Since: 0.17.0
*/
GArrowSchema *
garrow_schema_with_metadata(GArrowSchema *schema,
GHashTable *metadata)
{
const auto arrow_schema = garrow_schema_get_raw(schema);
auto arrow_metadata = std::make_shared<arrow::KeyValueMetadata>();
g_hash_table_foreach(metadata,
[](gpointer key,
gpointer value,
gpointer user_data) {
auto arrow_metadata =
static_cast<std::shared_ptr<arrow::KeyValueMetadata> *>(user_data);
(*arrow_metadata)->Append(static_cast<gchar *>(key),
static_cast<gchar *>(value));
},
&arrow_metadata);
auto arrow_new_schema = arrow_schema->WithMetadata(arrow_metadata);
return garrow_schema_new_raw(&arrow_new_schema);
}


G_END_DECLS

GArrowSchema *
Expand Down
13 changes: 12 additions & 1 deletion c_glib/arrow-glib/schema.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ gint garrow_schema_get_field_index (GArrowSchema *schema,
guint garrow_schema_n_fields (GArrowSchema *schema);
GList *garrow_schema_get_fields (GArrowSchema *schema);

gchar *garrow_schema_to_string (GArrowSchema *schema);
gchar *garrow_schema_to_string(GArrowSchema *schema);
GARROW_AVAILABLE_IN_0_17
gchar *garrow_schema_to_string_metadata(GArrowSchema *schema,
gboolean show_metadata);

GArrowSchema *garrow_schema_add_field (GArrowSchema *schema,
guint i,
Expand All @@ -63,4 +66,12 @@ GArrowSchema *garrow_schema_replace_field (GArrowSchema *schema,
GArrowField *field,
GError **error);

GARROW_AVAILABLE_IN_0_17
GHashTable *
garrow_schema_get_metadata(GArrowSchema *schema);
GARROW_AVAILABLE_IN_0_17
GArrowSchema *
garrow_schema_with_metadata(GArrowSchema *schema,
GHashTable *metadata);

G_END_DECLS
25 changes: 24 additions & 1 deletion c_glib/arrow-glib/version.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,15 @@
*/
#define GARROW_VERSION_1_0 G_ENCODE_VERSION(1, 0)

/**
* GARROW_VERSION_0_17:
*
* You can use this macro value for compile time API version check.
*
* Since: 0.17.0
*/
#define GARROW_VERSION_0_17 G_ENCODE_VERSION(0, 17)

/**
* GARROW_VERSION_0_15:
*
Expand Down Expand Up @@ -219,12 +228,26 @@
# define GARROW_DEPRECATED_IN_1_0_FOR(function)
#endif

#if GARROW_VERSION_MAX_ALLOWED < GARROW_VERSION_0_1
#if GARROW_VERSION_MAX_ALLOWED < GARROW_VERSION_1_0
# define GARROW_AVAILABLE_IN_1_0 GARROW_UNAVAILABLE(1, 0)
#else
# define GARROW_AVAILABLE_IN_1_0
#endif

#if GARROW_VERSION_MIN_REQUIRED >= GARROW_VERSION_0_17
# define GARROW_DEPRECATED_IN_0_17 GARROW_DEPRECATED
# define GARROW_DEPRECATED_IN_0_17_FOR(function) GARROW_DEPRECATED_FOR(function)
#else
# define GARROW_DEPRECATED_IN_0_17
# define GARROW_DEPRECATED_IN_0_17_FOR(function)
#endif

#if GARROW_VERSION_MAX_ALLOWED < GARROW_VERSION_0_17
# define GARROW_AVAILABLE_IN_0_17 GARROW_UNAVAILABLE(0, 17)
#else
# define GARROW_AVAILABLE_IN_0_17
#endif

#if GARROW_VERSION_MIN_REQUIRED >= GARROW_VERSION_0_15
# define GARROW_DEPRECATED_IN_0_15 GARROW_DEPRECATED
# define GARROW_DEPRECATED_IN_0_15_FOR(function) GARROW_DEPRECATED_FOR(function)
Expand Down
4 changes: 4 additions & 0 deletions c_glib/doc/arrow-glib/arrow-glib-docs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@
<title>Index of new symbols in 1.0.0</title>
<xi:include href="xml/api-index-1.0.0.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-0-17-0" role="0.17.0">
<title>Index of new symbols in 0.17.0</title>
<xi:include href="xml/api-index-0.17.0.xml"><xi:fallback /></xi:include>
</index>
<index id="api-index-0-15-0" role="0.15.0">
<title>Index of new symbols in 0.15.0</title>
<xi:include href="xml/api-index-0.15.0.xml"><xi:fallback /></xi:include>
Expand Down
53 changes: 53 additions & 0 deletions c_glib/test/test-schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
# under the License.

class TestSchema < Test::Unit::TestCase
include Helper::Omittable

def test_equal
fields1 = [
Arrow::Field.new("enabled", Arrow::BooleanDataType.new),
Expand Down Expand Up @@ -92,6 +94,35 @@ def test_to_s
SCHEMA
end

sub_test_case("#to_string_metadata") do
def setup
require_gi_bindings(3, 4, 2)

fields = [
Arrow::Field.new("enabled", Arrow::BooleanDataType.new),
Arrow::Field.new("required", Arrow::BooleanDataType.new),
]
schema = Arrow::Schema.new(fields)
@schema = schema.with_metadata("key" => "value")
end

def test_true
assert_equal(<<-SCHEMA.chomp, @schema.to_string_metadata(true))
enabled: bool
required: bool
-- metadata --
key: value
SCHEMA
end

def test_false
assert_equal(<<-SCHEMA.chomp, @schema.to_string_metadata(false))
enabled: bool
required: bool
SCHEMA
end
end

def test_add_field
fields = [
Arrow::Field.new("enabled", Arrow::BooleanDataType.new),
Expand Down Expand Up @@ -132,4 +163,26 @@ def test_replace_field
new: bool
SCHEMA
end

sub_test_case("#metadata") do
def setup
require_gi_bindings(3, 4, 2)

fields = [
Arrow::Field.new("enabled", Arrow::BooleanDataType.new),
Arrow::Field.new("required", Arrow::BooleanDataType.new),
]
@schema = Arrow::Schema.new(fields)
end

def test_existent
schema_with_metadata = @schema.with_metadata("key" => "value")
assert_equal({"key" => "value"},
schema_with_metadata.metadata)
end

def test_nonexistent
assert_nil(@schema.metadata)
end
end
end
5 changes: 5 additions & 0 deletions ruby/red-arrow/lib/arrow/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,10 @@ def initialize(fields)
end

alias_method :[], :find_field

alias_method :to_s_raw, :to_s
def to_s(show_metadata: false)
to_string_metadata(show_metadata)
end
end
end
1 change: 1 addition & 0 deletions ruby/red-arrow/test/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@
require "test-unit"

require_relative "helper/fixture"
require_relative "helper/omittable"
36 changes: 36 additions & 0 deletions ruby/red-arrow/test/helper/omittable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 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.

module Helper
module Omittable
def require_gi_bindings(major, minor, micro)
return if GLib.check_binding_version?(major, minor, micro)
message =
"Require gobject-introspection #{major}.#{minor}.#{micro} or later: " +
GLib::BINDING_VERSION.join(".")
omit(message)
end

def require_gi(major, minor, micro)
return if GObjectIntrospection::Version.or_later?(major, minor, micro)
message =
"Require GObject Introspection #{major}.#{minor}.#{micro} or later: " +
GObjectIntrospection::Version::STRING
omit(message)
end
end
end
16 changes: 16 additions & 0 deletions ruby/red-arrow/test/test-schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
# under the License.

class SchemaTest < Test::Unit::TestCase
include Helper::Omittable

def setup
@count_field = Arrow::Field.new("count", :uint32)
@visible_field = Arrow::Field.new("visible", :boolean)
Expand Down Expand Up @@ -114,5 +116,19 @@ def setup
end
end
end

sub_test_case("#to_s") do
test("show_metadata") do
require_gi_bindings(3, 4, 2)

schema = @schema.with_metadata("key" => "value")
assert_equal(<<-SCHEMA.chomp, schema.to_s(show_metadata: true))
count: uint32
visible: bool
-- metadata --
key: value
SCHEMA
end
end
end
end

0 comments on commit 2891311

Please sign in to comment.