This is an automated email from the ASF dual-hosted git repository.

kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new 9833a0aab3 GH-21429: [GLib] Add GArrowDenseUnionArrayBuilder (#34981)
9833a0aab3 is described below

commit 9833a0aab31451a7dc8c3159ee7d7eac24cb5af7
Author: Sutou Kouhei <[email protected]>
AuthorDate: Sat Apr 8 16:29:29 2023 +0900

    GH-21429: [GLib] Add GArrowDenseUnionArrayBuilder (#34981)
    
    ### Rationale for this change
    
    It's a missing binding.
    
    ### What changes are included in this PR?
    
    Add `arrow::DenseUnionBuilder` binding and related features.
    
    ### Are these changes tested?
    
    Yes.
    
    ### Are there any user-facing changes?
    
    Yes.
    
    **This PR includes breaking changes to public APIs.**
    * Closes: #21429
    
    Authored-by: Sutou Kouhei <[email protected]>
    Signed-off-by: Sutou Kouhei <[email protected]>
---
 c_glib/arrow-glib/array-builder.cpp                | 534 ++++++++++++---------
 c_glib/arrow-glib/array-builder.h                  |  64 ++-
 c_glib/arrow-glib/array-builder.hpp                |  11 +-
 c_glib/arrow-glib/table-builder.cpp                |   1 -
 c_glib/test/test-dense-union-array-builder.rb      | 172 +++++++
 .../lib/arrow/dense-union-array-builder.rb         |  88 ++++
 ruby/red-arrow/lib/arrow/loader.rb                 |   1 +
 ruby/red-arrow/lib/arrow/struct-array-builder.rb   |   5 -
 .../test/raw-records/test-dense-union-array.rb     |  11 +-
 ruby/red-arrow/test/raw-records/test-list-array.rb |  31 +-
 ruby/red-arrow/test/raw-records/test-map-array.rb  |  42 +-
 .../test/raw-records/test-sparse-union-array.rb    |  11 +-
 .../test/raw-records/test-struct-array.rb          |  23 +-
 .../test/values/test-dense-union-array.rb          |  13 +-
 ruby/red-arrow/test/values/test-list-array.rb      |  29 +-
 ruby/red-arrow/test/values/test-map-array.rb       |  36 +-
 .../test/values/test-sparse-union-array.rb         |  13 +-
 ruby/red-arrow/test/values/test-struct-array.rb    |  21 +-
 18 files changed, 826 insertions(+), 280 deletions(-)

diff --git a/c_glib/arrow-glib/array-builder.cpp 
b/c_glib/arrow-glib/array-builder.cpp
index aa7bee20e9..e0ffc0b345 100644
--- a/c_glib/arrow-glib/array-builder.cpp
+++ b/c_glib/arrow-glib/array-builder.cpp
@@ -32,7 +32,7 @@ garrow_array_builder_append_value(GArrowArrayBuilder *builder,
                                   const gchar *context)
 {
   auto arrow_builder =
-    static_cast<BUILDER>(garrow_array_builder_get_raw(builder));
+    std::static_pointer_cast<BUILDER>(garrow_array_builder_get_raw(builder));
   auto status = arrow_builder->Append(value);
   return garrow_error_check(error, status, context);
 }
@@ -106,7 +106,7 @@ garrow_array_builder_append_values(GArrowArrayBuilder 
*builder,
                                    const gchar *context)
 {
   auto arrow_builder =
-    static_cast<BUILDER>(garrow_array_builder_get_raw(builder));
+    std::static_pointer_cast<BUILDER>(garrow_array_builder_get_raw(builder));
   return garrow_array_builder_append_values(
     values,
     values_length,
@@ -132,7 +132,7 @@ garrow_array_builder_append_values(GArrowArrayBuilder 
*builder,
                                    const gchar *context)
 {
   auto arrow_builder =
-    static_cast<BUILDER>(garrow_array_builder_get_raw(builder));
+    std::static_pointer_cast<BUILDER>(garrow_array_builder_get_raw(builder));
   arrow::Status status;
   if (is_valids_length > 0 && values_length != is_valids_length) {
     g_set_error(error,
@@ -213,7 +213,7 @@ garrow_array_builder_append_values(
   GET_VALUE_FUNCTION get_value_function)
 {
   auto arrow_builder =
-    static_cast<arrow::FixedSizeBinaryBuilder *>(
+    std::static_pointer_cast<arrow::FixedSizeBinaryBuilder>(
       garrow_array_builder_get_raw(builder));
   if (is_valids_length > 0 && values_length != is_valids_length) {
     g_set_error(error,
@@ -292,7 +292,7 @@ garrow_array_builder_append_values(GArrowArrayBuilder 
*builder,
                                    const gchar *context)
 {
   auto arrow_builder =
-    static_cast<BUILDER>(garrow_array_builder_get_raw(builder));
+    std::static_pointer_cast<BUILDER>(garrow_array_builder_get_raw(builder));
   auto value_size = arrow_builder->byte_width();
   gsize raw_values_size;
   auto raw_values =
@@ -470,12 +470,18 @@ G_BEGIN_DECLS
  *
  * #GArrowDecimal256ArrayBuilder is the class to create a new
  * #GArrowDecimal256Array.
+ *
+ * #GArrowUnionArrayBuilder is the base class for union builder class
+ * such as #GArrowDenseUnionArrayBuilder.
+ *
+ * #GArrowDenseUnionArrayBuilder is the class to create a new
+ * #GArrowDenseUnionArray.
  */
 
-typedef struct GArrowArrayBuilderPrivate_ {
-  arrow::ArrayBuilder *array_builder;
-  gboolean have_ownership;
-} GArrowArrayBuilderPrivate;
+struct GArrowArrayBuilderPrivate {
+  std::shared_ptr<arrow::ArrayBuilder> array_builder;
+  GList *children;
+};
 
 enum {
   PROP_0,
@@ -495,14 +501,19 @@ static void
 garrow_array_builder_finalize(GObject *object)
 {
   auto priv = GARROW_ARRAY_BUILDER_GET_PRIVATE(object);
-
-  if (priv->have_ownership) {
-    delete priv->array_builder;
-  }
-
+  priv->array_builder.~shared_ptr();
   G_OBJECT_CLASS(garrow_array_builder_parent_class)->finalize(object);
 }
 
+static void
+garrow_array_builder_dispose(GObject *object)
+{
+  auto priv = GARROW_ARRAY_BUILDER_GET_PRIVATE(object);
+  g_list_free_full(priv->children, g_object_unref);
+  priv->children = nullptr;
+  G_OBJECT_CLASS(garrow_array_builder_parent_class)->dispose(object);
+}
+
 static void
 garrow_array_builder_set_property(GObject *object,
                                   guint prop_id,
@@ -514,7 +525,8 @@ garrow_array_builder_set_property(GObject *object,
   switch (prop_id) {
   case PROP_ARRAY_BUILDER:
     priv->array_builder =
-      static_cast<arrow::ArrayBuilder *>(g_value_get_pointer(value));
+      *static_cast<std::shared_ptr<arrow::ArrayBuilder> *>(
+        g_value_get_pointer(value));
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -522,41 +534,26 @@ garrow_array_builder_set_property(GObject *object,
   }
 }
 
-static void
-garrow_array_builder_get_property(GObject *object,
-                                  guint prop_id,
-                                  GValue *value,
-                                  GParamSpec *pspec)
-{
-  switch (prop_id) {
-  default:
-    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
-    break;
-  }
-}
-
 static void
 garrow_array_builder_init(GArrowArrayBuilder *builder)
 {
   auto priv = GARROW_ARRAY_BUILDER_GET_PRIVATE(builder);
-  priv->have_ownership = TRUE;
+  new(&priv->array_builder) std::shared_ptr<arrow::ArrayBuilder>;
 }
 
 static void
 garrow_array_builder_class_init(GArrowArrayBuilderClass *klass)
 {
-  GObjectClass *gobject_class;
-  GParamSpec *spec;
-
-  gobject_class = G_OBJECT_CLASS(klass);
+  auto gobject_class = G_OBJECT_CLASS(klass);
 
   gobject_class->finalize     = garrow_array_builder_finalize;
+  gobject_class->dispose      = garrow_array_builder_dispose;
   gobject_class->set_property = garrow_array_builder_set_property;
-  gobject_class->get_property = garrow_array_builder_get_property;
 
+  GParamSpec *spec;
   spec = g_param_spec_pointer("array-builder",
                               "Array builder",
-                              "The raw arrow::ArrayBuilder *",
+                              "The raw std::shared_ptr<arrow::ArrayBuilder>",
                               static_cast<GParamFlags>(G_PARAM_WRITABLE |
                                                        
G_PARAM_CONSTRUCT_ONLY));
   g_object_class_install_property(gobject_class, PROP_ARRAY_BUILDER, spec);
@@ -571,24 +568,11 @@ garrow_array_builder_new(const 
std::shared_ptr<arrow::DataType> &type,
   std::unique_ptr<arrow::ArrayBuilder> arrow_builder;
   auto status = arrow::MakeBuilder(memory_pool, type, &arrow_builder);
   if (!garrow_error_check(error, status, context)) {
-    return NULL;
+    return nullptr;
   }
-  return garrow_array_builder_new_raw(arrow_builder.release());
-}
-
-/**
- * garrow_array_builder_release_ownership: (skip)
- * @builder: A #GArrowArrayBuilder.
- *
- * Release ownership of `arrow::ArrayBuilder` in `builder`.
- *
- * Since: 0.8.0
- */
-void
-garrow_array_builder_release_ownership(GArrowArrayBuilder *builder)
-{
-  auto priv = GARROW_ARRAY_BUILDER_GET_PRIVATE(builder);
-  priv->have_ownership = FALSE;
+  std::shared_ptr<arrow::ArrayBuilder>
+    shared_arrow_builder(std::move(arrow_builder));
+  return garrow_array_builder_new_raw(&shared_arrow_builder);
 }
 
 /**
@@ -703,6 +687,50 @@ garrow_array_builder_get_n_nulls(GArrowArrayBuilder 
*builder)
   return arrow_builder->null_count();
 }
 
+/**
+ * garrow_array_builder_get_child:
+ * @builder: A #GArrowArrayBuilder.
+ * @i: The index of the child.
+ *
+ * Returns: (transfer none): The #GArrowArrayBuilder for the i-th child.
+ *
+ * Since: 12.0.0
+ */
+GArrowArrayBuilder *
+garrow_array_builder_get_child(GArrowArrayBuilder *builder,
+                               gint i)
+{
+  auto children = garrow_array_builder_get_children(builder);
+  auto child = g_list_nth_data(children, i);
+  return GARROW_ARRAY_BUILDER(child);
+}
+
+/**
+ * garrow_array_builder_get_children:
+ * @builder: A #GArrowArrayBuilder.
+ *
+ * Returns: (element-type GArrowArrayBuilder) (transfer none):
+ *   The #GArrowArrayBuilder for all fields.
+ *
+ * Since: 12.0.0
+ */
+GList *
+garrow_array_builder_get_children(GArrowArrayBuilder *builder)
+{
+  auto priv = GARROW_ARRAY_BUILDER_GET_PRIVATE(builder);
+  if (!priv->children) {
+    auto arrow_builder = garrow_array_builder_get_raw(builder);
+    GList *children = nullptr;
+    for (int i = 0; i < arrow_builder->num_children(); ++i) {
+      auto arrow_child = arrow_builder->child_builder(i);
+      auto child = garrow_array_builder_new_raw(&arrow_child);
+      children = g_list_prepend(children, child);
+    }
+    priv->children = g_list_reverse(children);
+  }
+  return priv->children;
+}
+
 /**
  * garrow_array_builder_resize:
  * @builder: A #GArrowArrayBuilder.
@@ -996,7 +1024,7 @@ 
garrow_boolean_array_builder_append_value(GArrowBooleanArrayBuilder *builder,
                                           gboolean value,
                                           GError **error)
 {
-  return garrow_array_builder_append_value<arrow::BooleanBuilder *>
+  return garrow_array_builder_append_value<arrow::BooleanBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      static_cast<bool>(value),
      error,
@@ -1034,7 +1062,7 @@ 
garrow_boolean_array_builder_append_values(GArrowBooleanArrayBuilder *builder,
   for (gint64 i = 0; i < values_length; ++i) {
     arrow_values[i] = values[i];
   }
-  return garrow_array_builder_append_values<arrow::BooleanBuilder *>
+  return garrow_array_builder_append_values<arrow::BooleanBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      arrow_values,
      values_length,
@@ -1113,8 +1141,10 @@ GArrowIntArrayBuilder *
 garrow_int_array_builder_new(void)
 {
   auto memory_pool = arrow::default_memory_pool();
-  auto arrow_builder = new arrow::AdaptiveIntBuilder(memory_pool);
-  auto builder = garrow_array_builder_new_raw(arrow_builder,
+  auto arrow_builder =
+    std::static_pointer_cast<arrow::ArrayBuilder>(
+      std::make_shared<arrow::AdaptiveIntBuilder>(memory_pool));
+  auto builder = garrow_array_builder_new_raw(&arrow_builder,
                                               GARROW_TYPE_INT_ARRAY_BUILDER);
   return GARROW_INT_ARRAY_BUILDER(builder);
 }
@@ -1155,7 +1185,7 @@ 
garrow_int_array_builder_append_value(GArrowIntArrayBuilder *builder,
                                       gint64 value,
                                       GError **error)
 {
-  return garrow_array_builder_append_value<arrow::AdaptiveIntBuilder *>
+  return garrow_array_builder_append_value<arrow::AdaptiveIntBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -1189,7 +1219,7 @@ 
garrow_int_array_builder_append_values(GArrowIntArrayBuilder *builder,
                                        gint64 is_valids_length,
                                        GError **error)
 {
-  return garrow_array_builder_append_values<arrow::AdaptiveIntBuilder *>
+  return garrow_array_builder_append_values<arrow::AdaptiveIntBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      reinterpret_cast<const int64_t *>(values),
      values_length,
@@ -1270,8 +1300,10 @@ GArrowUIntArrayBuilder *
 garrow_uint_array_builder_new(void)
 {
   auto memory_pool = arrow::default_memory_pool();
-  auto arrow_builder = new arrow::AdaptiveUIntBuilder(memory_pool);
-  auto builder = garrow_array_builder_new_raw(arrow_builder,
+  auto arrow_builder =
+    std::static_pointer_cast<arrow::ArrayBuilder>(
+      std::make_shared<arrow::AdaptiveUIntBuilder>(memory_pool));
+  auto builder = garrow_array_builder_new_raw(&arrow_builder,
                                               GARROW_TYPE_UINT_ARRAY_BUILDER);
   return GARROW_UINT_ARRAY_BUILDER(builder);
 }
@@ -1312,7 +1344,7 @@ 
garrow_uint_array_builder_append_value(GArrowUIntArrayBuilder *builder,
                                        guint64 value,
                                        GError **error)
 {
-  return garrow_array_builder_append_value<arrow::AdaptiveUIntBuilder *>
+  return garrow_array_builder_append_value<arrow::AdaptiveUIntBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -1346,7 +1378,7 @@ 
garrow_uint_array_builder_append_values(GArrowUIntArrayBuilder *builder,
                                         gint64 is_valids_length,
                                         GError **error)
 {
-  return garrow_array_builder_append_values<arrow::AdaptiveUIntBuilder *>
+  return garrow_array_builder_append_values<arrow::AdaptiveUIntBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      reinterpret_cast<const uint64_t *>(values),
      values_length,
@@ -1464,7 +1496,7 @@ 
garrow_int8_array_builder_append_value(GArrowInt8ArrayBuilder *builder,
                                        gint8 value,
                                        GError **error)
 {
-  return garrow_array_builder_append_value<arrow::Int8Builder *>
+  return garrow_array_builder_append_value<arrow::Int8Builder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -1498,7 +1530,7 @@ 
garrow_int8_array_builder_append_values(GArrowInt8ArrayBuilder *builder,
                                         gint64 is_valids_length,
                                         GError **error)
 {
-  return garrow_array_builder_append_values<arrow::Int8Builder *>
+  return garrow_array_builder_append_values<arrow::Int8Builder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -1614,7 +1646,7 @@ 
garrow_uint8_array_builder_append_value(GArrowUInt8ArrayBuilder *builder,
                                   guint8 value,
                                   GError **error)
 {
-  return garrow_array_builder_append_value<arrow::UInt8Builder *>
+  return garrow_array_builder_append_value<arrow::UInt8Builder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -1648,7 +1680,7 @@ 
garrow_uint8_array_builder_append_values(GArrowUInt8ArrayBuilder *builder,
                                          gint64 is_valids_length,
                                          GError **error)
 {
-  return garrow_array_builder_append_values<arrow::UInt8Builder *>
+  return garrow_array_builder_append_values<arrow::UInt8Builder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -1764,7 +1796,7 @@ 
garrow_int16_array_builder_append_value(GArrowInt16ArrayBuilder *builder,
                                         gint16 value,
                                         GError **error)
 {
-  return garrow_array_builder_append_value<arrow::Int16Builder *>
+  return garrow_array_builder_append_value<arrow::Int16Builder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -1798,7 +1830,7 @@ 
garrow_int16_array_builder_append_values(GArrowInt16ArrayBuilder *builder,
                                          gint64 is_valids_length,
                                          GError **error)
 {
-  return garrow_array_builder_append_values<arrow::Int16Builder *>
+  return garrow_array_builder_append_values<arrow::Int16Builder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -1914,7 +1946,7 @@ 
garrow_uint16_array_builder_append_value(GArrowUInt16ArrayBuilder *builder,
                                          guint16 value,
                                          GError **error)
 {
-  return garrow_array_builder_append_value<arrow::UInt16Builder *>
+  return garrow_array_builder_append_value<arrow::UInt16Builder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -1948,7 +1980,7 @@ 
garrow_uint16_array_builder_append_values(GArrowUInt16ArrayBuilder *builder,
                                           gint64 is_valids_length,
                                           GError **error)
 {
-  return garrow_array_builder_append_values<arrow::UInt16Builder *>
+  return garrow_array_builder_append_values<arrow::UInt16Builder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -2064,7 +2096,7 @@ 
garrow_int32_array_builder_append_value(GArrowInt32ArrayBuilder *builder,
                                         gint32 value,
                                         GError **error)
 {
-  return garrow_array_builder_append_value<arrow::Int32Builder *>
+  return garrow_array_builder_append_value<arrow::Int32Builder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -2098,7 +2130,7 @@ 
garrow_int32_array_builder_append_values(GArrowInt32ArrayBuilder *builder,
                                          gint64 is_valids_length,
                                          GError **error)
 {
-  return garrow_array_builder_append_values<arrow::Int32Builder *>
+  return garrow_array_builder_append_values<arrow::Int32Builder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -2214,7 +2246,7 @@ 
garrow_uint32_array_builder_append_value(GArrowUInt32ArrayBuilder *builder,
                                          guint32 value,
                                          GError **error)
 {
-  return garrow_array_builder_append_value<arrow::UInt32Builder *>
+  return garrow_array_builder_append_value<arrow::UInt32Builder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -2248,7 +2280,7 @@ 
garrow_uint32_array_builder_append_values(GArrowUInt32ArrayBuilder *builder,
                                           gint64 is_valids_length,
                                           GError **error)
 {
-  return garrow_array_builder_append_values<arrow::UInt32Builder *>
+  return garrow_array_builder_append_values<arrow::UInt32Builder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -2364,7 +2396,7 @@ 
garrow_int64_array_builder_append_value(GArrowInt64ArrayBuilder *builder,
                                         gint64 value,
                                         GError **error)
 {
-  return garrow_array_builder_append_value<arrow::Int64Builder *>
+  return garrow_array_builder_append_value<arrow::Int64Builder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -2398,7 +2430,7 @@ 
garrow_int64_array_builder_append_values(GArrowInt64ArrayBuilder *builder,
                                          gint64 is_valids_length,
                                          GError **error)
 {
-  return garrow_array_builder_append_values<arrow::Int64Builder *>
+  return garrow_array_builder_append_values<arrow::Int64Builder>
     (GARROW_ARRAY_BUILDER(builder),
      reinterpret_cast<const int64_t *>(values),
      values_length,
@@ -2514,7 +2546,7 @@ 
garrow_uint64_array_builder_append_value(GArrowUInt64ArrayBuilder *builder,
                                          guint64 value,
                                          GError **error)
 {
-  return garrow_array_builder_append_value<arrow::UInt64Builder *>
+  return garrow_array_builder_append_value<arrow::UInt64Builder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -2548,7 +2580,7 @@ 
garrow_uint64_array_builder_append_values(GArrowUInt64ArrayBuilder *builder,
                                           gint64 is_valids_length,
                                           GError **error)
 {
-  return garrow_array_builder_append_values<arrow::UInt64Builder *>
+  return garrow_array_builder_append_values<arrow::UInt64Builder>
     (GARROW_ARRAY_BUILDER(builder),
      reinterpret_cast<const uint64_t *>(values),
      values_length,
@@ -2649,7 +2681,7 @@ garrow_half_float_array_builder_append_value(
   guint16 value,
   GError **error)
 {
-  return garrow_array_builder_append_value<arrow::HalfFloatBuilder *>
+  return garrow_array_builder_append_value<arrow::HalfFloatBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -2684,7 +2716,7 @@ garrow_half_float_array_builder_append_values(
   gint64 is_valids_length,
   GError **error)
 {
-  return garrow_array_builder_append_values<arrow::HalfFloatBuilder *>
+  return garrow_array_builder_append_values<arrow::HalfFloatBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -2757,7 +2789,7 @@ 
garrow_float_array_builder_append_value(GArrowFloatArrayBuilder *builder,
                                         gfloat value,
                                         GError **error)
 {
-  return garrow_array_builder_append_value<arrow::FloatBuilder *>
+  return garrow_array_builder_append_value<arrow::FloatBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -2791,7 +2823,7 @@ 
garrow_float_array_builder_append_values(GArrowFloatArrayBuilder *builder,
                                          gint64 is_valids_length,
                                          GError **error)
 {
-  return garrow_array_builder_append_values<arrow::FloatBuilder *>
+  return garrow_array_builder_append_values<arrow::FloatBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -2907,7 +2939,7 @@ 
garrow_double_array_builder_append_value(GArrowDoubleArrayBuilder *builder,
                                          gdouble value,
                                          GError **error)
 {
-  return garrow_array_builder_append_value<arrow::DoubleBuilder *>
+  return garrow_array_builder_append_value<arrow::DoubleBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -2941,7 +2973,7 @@ 
garrow_double_array_builder_append_values(GArrowDoubleArrayBuilder *builder,
                                           gint64 is_valids_length,
                                           GError **error)
 {
-  return garrow_array_builder_append_values<arrow::DoubleBuilder *>
+  return garrow_array_builder_append_values<arrow::DoubleBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -3062,9 +3094,8 @@ 
garrow_binary_array_builder_append_value(GArrowBinaryArrayBuilder *builder,
                                          GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::BinaryBuilder *>(
+    std::static_pointer_cast<arrow::BinaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
   auto status = arrow_builder->Append(value, length);
   return garrow_error_check(error,
                             status,
@@ -3087,9 +3118,8 @@ 
garrow_binary_array_builder_append_value_bytes(GArrowBinaryArrayBuilder *builder
                                                GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::BinaryBuilder *>(
+    std::static_pointer_cast<arrow::BinaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
   gsize size;
   auto data = g_bytes_get_data(value, &size);
   auto status = arrow_builder->Append(static_cast<const uint8_t *>(data),
@@ -3126,7 +3156,7 @@ 
garrow_binary_array_builder_append_values(GArrowBinaryArrayBuilder *builder,
                                           gint64 is_valids_length,
                                           GError **error)
 {
-  return garrow_array_builder_append_values<arrow::BinaryBuilder *>
+  return garrow_array_builder_append_values<arrow::BinaryBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -3225,9 +3255,8 @@ 
garrow_large_binary_array_builder_append_value(GArrowLargeBinaryArrayBuilder *bu
                                                GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::LargeBinaryBuilder *>(
+    std::static_pointer_cast<arrow::LargeBinaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
   auto status = arrow_builder->Append(value, length);
   return garrow_error_check(error,
                             status,
@@ -3250,9 +3279,8 @@ 
garrow_large_binary_array_builder_append_value_bytes(GArrowLargeBinaryArrayBuild
                                                      GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::LargeBinaryBuilder *>(
+    std::static_pointer_cast<arrow::LargeBinaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
   gsize size;
   gconstpointer data = g_bytes_get_data(value, &size);
   auto status = arrow_builder->Append(static_cast<const uint8_t *>(data),
@@ -3289,7 +3317,7 @@ 
garrow_large_binary_array_builder_append_values(GArrowLargeBinaryArrayBuilder *b
                                                 gint64 is_valids_length,
                                                 GError **error)
 {
-  return garrow_array_builder_append_values<arrow::LargeBinaryBuilder *>
+  return garrow_array_builder_append_values<arrow::LargeBinaryBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -3450,9 +3478,8 @@ 
garrow_string_array_builder_append_string_len(GArrowStringArrayBuilder *builder,
                                               GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::StringBuilder *>(
+    std::static_pointer_cast<arrow::StringBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
   auto status = arrow_builder->Append(value, length);
   return garrow_error_check(error,
                             status,
@@ -3524,7 +3551,7 @@ 
garrow_string_array_builder_append_strings(GArrowStringArrayBuilder *builder,
                                            gint64 is_valids_length,
                                            GError **error)
 {
-  return garrow_array_builder_append_values<arrow::StringBuilder *>
+  return garrow_array_builder_append_values<arrow::StringBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -3605,7 +3632,7 @@ gboolean 
garrow_large_string_array_builder_append_string_len(
   GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::LargeStringBuilder *>(
+    std::static_pointer_cast<arrow::LargeStringBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
   auto status = arrow_builder->Append(value, length);
   return garrow_error_check(error,
@@ -3640,7 +3667,7 @@ 
garrow_large_string_array_builder_append_strings(GArrowLargeStringArrayBuilder *
                                                  gint64 is_valids_length,
                                                  GError **error)
 {
-  return garrow_array_builder_append_values<arrow::LargeStringBuilder *>
+  return garrow_array_builder_append_values<arrow::LargeStringBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -3705,9 +3732,8 @@ garrow_fixed_size_binary_array_builder_append_value(
 {
   const gchar *context = "[fixed-size-binary-array-builder][append-value]";
   auto arrow_builder =
-    static_cast<arrow::FixedSizeBinaryBuilder *>(
+    std::static_pointer_cast<arrow::FixedSizeBinaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
   arrow::Status status;
   if (value) {
     if (arrow_builder->byte_width() != length) {
@@ -3745,7 +3771,7 @@ garrow_fixed_size_binary_array_builder_append_value_bytes(
 {
   const gchar *context = 
"[fixed-size-binary-array-builder][append-value-bytes]";
   auto arrow_builder =
-    static_cast<arrow::FixedSizeBinaryBuilder *>(
+    std::static_pointer_cast<arrow::FixedSizeBinaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
 
   gsize size;
@@ -3836,7 +3862,7 @@ 
garrow_fixed_size_binary_array_builder_append_values_packed(
   gint64 is_valids_length,
   GError **error)
 {
-  return garrow_array_builder_append_values<arrow::FixedSizeBinaryBuilder *>
+  return garrow_array_builder_append_values<arrow::FixedSizeBinaryBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      is_valids,
@@ -3912,7 +3938,7 @@ 
garrow_date32_array_builder_append_value(GArrowDate32ArrayBuilder *builder,
                                          gint32 value,
                                          GError **error)
 {
-  return garrow_array_builder_append_value<arrow::Date32Builder *>
+  return garrow_array_builder_append_value<arrow::Date32Builder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -3947,7 +3973,7 @@ 
garrow_date32_array_builder_append_values(GArrowDate32ArrayBuilder *builder,
                                           gint64 is_valids_length,
                                           GError **error)
 {
-  return garrow_array_builder_append_values<arrow::Date32Builder *>
+  return garrow_array_builder_append_values<arrow::Date32Builder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -4069,7 +4095,7 @@ 
garrow_date64_array_builder_append_value(GArrowDate64ArrayBuilder *builder,
                                          gint64 value,
                                          GError **error)
 {
-  return garrow_array_builder_append_value<arrow::Date64Builder *>
+  return garrow_array_builder_append_value<arrow::Date64Builder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -4104,7 +4130,7 @@ 
garrow_date64_array_builder_append_values(GArrowDate64ArrayBuilder *builder,
                                           gint64 is_valids_length,
                                           GError **error)
 {
-  return garrow_array_builder_append_values<arrow::Date64Builder *>
+  return garrow_array_builder_append_values<arrow::Date64Builder>
     (GARROW_ARRAY_BUILDER(builder),
      reinterpret_cast<const int64_t *>(values),
      values_length,
@@ -4228,7 +4254,7 @@ 
garrow_timestamp_array_builder_append_value(GArrowTimestampArrayBuilder *builder
                                             gint64 value,
                                             GError **error)
 {
-  return garrow_array_builder_append_value<arrow::TimestampBuilder *>
+  return garrow_array_builder_append_value<arrow::TimestampBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -4263,7 +4289,7 @@ 
garrow_timestamp_array_builder_append_values(GArrowTimestampArrayBuilder *builde
                                              gint64 is_valids_length,
                                              GError **error)
 {
-  return garrow_array_builder_append_values<arrow::TimestampBuilder *>
+  return garrow_array_builder_append_values<arrow::TimestampBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      reinterpret_cast<const int64_t *>(values),
      values_length,
@@ -4387,7 +4413,7 @@ 
garrow_time32_array_builder_append_value(GArrowTime32ArrayBuilder *builder,
                                          gint32 value,
                                          GError **error)
 {
-  return garrow_array_builder_append_value<arrow::Time32Builder *>
+  return garrow_array_builder_append_value<arrow::Time32Builder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -4422,7 +4448,7 @@ 
garrow_time32_array_builder_append_values(GArrowTime32ArrayBuilder *builder,
                                           gint64 is_valids_length,
                                           GError **error)
 {
-  return garrow_array_builder_append_values<arrow::Time32Builder *>
+  return garrow_array_builder_append_values<arrow::Time32Builder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -4546,7 +4572,7 @@ 
garrow_time64_array_builder_append_value(GArrowTime64ArrayBuilder *builder,
                                          gint64 value,
                                          GError **error)
 {
-  return garrow_array_builder_append_value<arrow::Time64Builder *>
+  return garrow_array_builder_append_value<arrow::Time64Builder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -4581,7 +4607,7 @@ 
garrow_time64_array_builder_append_values(GArrowTime64ArrayBuilder *builder,
                                           gint64 is_valids_length,
                                           GError **error)
 {
-  return garrow_array_builder_append_values<arrow::Time64Builder *>
+  return garrow_array_builder_append_values<arrow::Time64Builder>
     (GARROW_ARRAY_BUILDER(builder),
      reinterpret_cast<const int64_t *>(values),
      values_length,
@@ -4685,7 +4711,7 @@ garrow_month_interval_array_builder_append_value(
   gint32 value,
   GError **error)
 {
-  return garrow_array_builder_append_value<arrow::MonthIntervalBuilder *>
+  return garrow_array_builder_append_value<arrow::MonthIntervalBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      value,
      error,
@@ -4720,7 +4746,7 @@ garrow_month_interval_array_builder_append_values(
   gint64 is_valids_length,
   GError **error)
 {
-  return garrow_array_builder_append_values<arrow::MonthIntervalBuilder *>
+  return garrow_array_builder_append_values<arrow::MonthIntervalBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      values,
      values_length,
@@ -4781,7 +4807,7 @@ garrow_day_time_interval_array_builder_append_value(
 {
   if (value) {
     auto arrow_day_millisecond = garrow_day_millisecond_get_raw(value);
-    return garrow_array_builder_append_value<arrow::DayTimeIntervalBuilder *>
+    return garrow_array_builder_append_value<arrow::DayTimeIntervalBuilder>
       (GARROW_ARRAY_BUILDER(builder),
        *arrow_day_millisecond,
        error,
@@ -4821,7 +4847,7 @@ garrow_day_time_interval_array_builder_append_values(
   GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::DayTimeIntervalBuilder *>(
+    std::static_pointer_cast<arrow::DayTimeIntervalBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
 
   return garrow_array_builder_append_values(
@@ -4903,7 +4929,7 @@ garrow_month_day_nano_interval_array_builder_append_value(
 {
   if (value) {
     auto arrow_month_day_nano = garrow_month_day_nano_get_raw(value);
-    return 
garrow_array_builder_append_value<arrow::MonthDayNanoIntervalBuilder *>(
+    return 
garrow_array_builder_append_value<arrow::MonthDayNanoIntervalBuilder>(
       GARROW_ARRAY_BUILDER(builder),
       *arrow_month_day_nano,
       error,
@@ -4943,7 +4969,7 @@ 
garrow_month_day_nano_interval_array_builder_append_values(
   GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::MonthDayNanoIntervalBuilder *>(
+    std::static_pointer_cast<arrow::MonthDayNanoIntervalBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
 
   return garrow_array_builder_append_values(
@@ -5045,11 +5071,9 @@ 
garrow_binary_dictionary_array_builder_append_value(GArrowBinaryDictionaryArrayB
                                                     GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::BinaryDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::BinaryDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
   auto status = arrow_builder->Append(value, length);
-
   return garrow_error_check(error,
                             status,
                             "[binary-dictionary-array-builder][append-value]");
@@ -5071,14 +5095,12 @@ 
garrow_binary_dictionary_array_builder_append_value_bytes(GArrowBinaryDictionary
                                                           GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::BinaryDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::BinaryDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
   gsize size;
   auto data = g_bytes_get_data(value, &size);
   auto status = arrow_builder->Append(static_cast<const uint8_t *>(data),
                                       size);
-
   return garrow_error_check(error,
                             status,
                             
"[binary-dictionary-array-builder][append-value-bytes]");
@@ -5100,12 +5122,10 @@ 
garrow_binary_dictionary_array_builder_append_array(GArrowBinaryDictionaryArrayB
                                                     GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::BinaryDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::BinaryDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
   auto arrow_array = 
garrow_array_get_raw<arrow::BinaryType>(GARROW_ARRAY(array));
-
   auto status = arrow_builder->AppendArray(*arrow_array);
-
   return garrow_error_check(error,
                             status,
                             
"[binary-dictionary-array-builder][append-binary-array]");
@@ -5139,7 +5159,7 @@ 
garrow_binary_dictionary_array_builder_append_indices(GArrowBinaryDictionaryArra
 {
   static const char *context = 
"[binary-dictionary-array-builder][append-indices]";
   auto arrow_builder =
-    static_cast<arrow::BinaryDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::BinaryDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
   auto append_function = [&arrow_builder](
       const gint64 *values,
@@ -5163,7 +5183,7 @@ 
garrow_binary_dictionary_array_builder_append_indices(GArrowBinaryDictionaryArra
 gint64 
garrow_binary_dictionary_array_builder_get_dictionary_length(GArrowBinaryDictionaryArrayBuilder
 *builder)
 {
   auto arrow_builder =
-    static_cast<arrow::BinaryDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::BinaryDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
   return arrow_builder->dictionary_length();
 }
@@ -5187,7 +5207,7 @@ 
garrow_binary_dictionary_array_builder_finish_delta(GArrowBinaryDictionaryArrayB
 {
   static const char *context = 
"[binary-dictionary-array-builder][finish-delta]";
   auto arrow_builder =
-    static_cast<arrow::BinaryDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::BinaryDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
   std::shared_ptr<arrow::Array> arrow_indices, arrow_delta;
   auto status = arrow_builder->FinishDelta(&arrow_indices, &arrow_delta);
@@ -5215,12 +5235,10 @@ 
garrow_binary_dictionary_array_builder_insert_memo_values(GArrowBinaryDictionary
                                                           GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::BinaryDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::BinaryDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
   auto arrow_array = 
garrow_array_get_raw<arrow::BinaryType>(GARROW_ARRAY(values));
-
   auto status = arrow_builder->InsertMemoValues(*arrow_array);
-
   return garrow_error_check(error,
                             status,
                             
"[binary-dictionary-array-builder][insert-memo-values]");
@@ -5238,7 +5256,7 @@ void
 
garrow_binary_dictionary_array_builder_reset_full(GArrowBinaryDictionaryArrayBuilder
 *builder)
 {
   auto arrow_builder =
-    static_cast<arrow::BinaryDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::BinaryDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
   arrow_builder->ResetFull();
 }
@@ -5313,12 +5331,10 @@ 
garrow_string_dictionary_array_builder_append_string(GArrowStringDictionaryArray
                                                      GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::StringDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::StringDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
   auto status = arrow_builder->Append(value,
                                       static_cast<guint32>(strlen(value)));
-
   return garrow_error_check(error,
                             status,
                             
"[string-dictionary-array-builder][append-string]");
@@ -5340,12 +5356,10 @@ 
garrow_string_dictionary_array_builder_append_array(GArrowStringDictionaryArrayB
                                                     GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::StringDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::StringDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
   auto arrow_array = 
garrow_array_get_raw<arrow::StringType>(GARROW_ARRAY(array));
-
   auto status = arrow_builder->AppendArray(*arrow_array);
-
   return garrow_error_check(error,
                             status,
                             
"[string-dictionary-array-builder][append-string-array]");
@@ -5379,7 +5393,7 @@ 
garrow_string_dictionary_array_builder_append_indices(GArrowStringDictionaryArra
 {
   static const char *context = 
"[string-dictionary-array-builder][append-indices]";
   auto arrow_builder =
-    static_cast<arrow::StringDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::StringDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
   auto append_function = [&arrow_builder](
       const gint64 *values,
@@ -5403,7 +5417,7 @@ 
garrow_string_dictionary_array_builder_append_indices(GArrowStringDictionaryArra
 gint64 
garrow_string_dictionary_array_builder_get_dictionary_length(GArrowStringDictionaryArrayBuilder
 *builder)
 {
   auto arrow_builder =
-    static_cast<arrow::StringDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::StringDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
   return arrow_builder->dictionary_length();
 }
@@ -5427,7 +5441,7 @@ 
garrow_string_dictionary_array_builder_finish_delta(GArrowStringDictionaryArrayB
 {
   static const char *context = 
"[string-dictionary-array-builder][finish-delta]";
   auto arrow_builder =
-    static_cast<arrow::StringDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::StringDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
   std::shared_ptr<arrow::Array> arrow_indices, arrow_delta;
   auto status = arrow_builder->FinishDelta(&arrow_indices, &arrow_delta);
@@ -5455,12 +5469,10 @@ 
garrow_string_dictionary_array_builder_insert_memo_values(GArrowStringDictionary
                                                           GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::StringDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::StringDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
   auto arrow_array = 
garrow_array_get_raw<arrow::StringType>(GARROW_ARRAY(values));
-
   auto status = arrow_builder->InsertMemoValues(*arrow_array);
-
   return garrow_error_check(error,
                             status,
                             
"[string-dictionary-array-builder][insert-memo-values]");
@@ -5478,7 +5490,7 @@ void
 
garrow_string_dictionary_array_builder_reset_full(GArrowStringDictionaryArrayBuilder
 *builder)
 {
   auto arrow_builder =
-    static_cast<arrow::StringDictionaryBuilder *>(
+    std::static_pointer_cast<arrow::StringDictionaryBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
   arrow_builder->ResetFull();
 }
@@ -5655,9 +5667,8 @@ 
garrow_list_array_builder_append_value(GArrowListArrayBuilder *builder,
                                        GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::ListBuilder *>(
+    std::static_pointer_cast<arrow::ListBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
   auto status = arrow_builder->Append();
   return garrow_error_check(error, status, 
"[list-array-builder][append-value]");
 }
@@ -5693,11 +5704,10 @@ 
garrow_list_array_builder_get_value_builder(GArrowListArrayBuilder *builder)
   auto priv = GARROW_LIST_ARRAY_BUILDER_GET_PRIVATE(builder);
   if (!priv->value_builder) {
     auto arrow_builder =
-      static_cast<arrow::ListBuilder *>(
+      std::static_pointer_cast<arrow::ListBuilder>(
         garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
     auto arrow_value_builder = arrow_builder->value_builder();
     priv->value_builder = garrow_array_builder_new_raw(arrow_value_builder);
-    garrow_array_builder_release_ownership(priv->value_builder);
   }
   return priv->value_builder;
 }
@@ -5791,9 +5801,8 @@ 
garrow_large_list_array_builder_append_value(GArrowLargeListArrayBuilder *builde
                                              GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::LargeListBuilder *>(
+    std::static_pointer_cast<arrow::LargeListBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
   auto status = arrow_builder->Append();
   return garrow_error_check(error, status, 
"[large-list-array-builder][append-value]");
 }
@@ -5833,48 +5842,24 @@ 
garrow_large_list_array_builder_get_value_builder(GArrowLargeListArrayBuilder *b
   auto priv = GARROW_LARGE_LIST_ARRAY_BUILDER_GET_PRIVATE(builder);
   if (!priv->value_builder) {
     auto arrow_builder =
-      static_cast<arrow::LargeListBuilder *>(
+      std::static_pointer_cast<arrow::LargeListBuilder>(
         garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
     auto arrow_value_builder = arrow_builder->value_builder();
     priv->value_builder = garrow_array_builder_new_raw(arrow_value_builder);
-    garrow_array_builder_release_ownership(priv->value_builder);
   }
   return priv->value_builder;
 }
 
 
-typedef struct GArrowStructArrayBuilderPrivate_ {
-  GList *field_builders;
-} GArrowStructArrayBuilderPrivate;
-
-G_DEFINE_TYPE_WITH_PRIVATE(GArrowStructArrayBuilder,
-                           garrow_struct_array_builder,
-                           GARROW_TYPE_ARRAY_BUILDER)
+G_DEFINE_TYPE(GArrowStructArrayBuilder,
+              garrow_struct_array_builder,
+              GARROW_TYPE_ARRAY_BUILDER)
 
 #define GARROW_STRUCT_ARRAY_BUILDER_GET_PRIVATE(obj)         \
   static_cast<GArrowStructArrayBuilderPrivate *>(            \
      garrow_struct_array_builder_get_instance_private(       \
        GARROW_STRUCT_ARRAY_BUILDER(obj)))
 
-static void
-garrow_struct_array_builder_dispose(GObject *object)
-{
-  auto priv = GARROW_STRUCT_ARRAY_BUILDER_GET_PRIVATE(object);
-
-  for (auto node = priv->field_builders; node; node = g_list_next(node)) {
-    auto field_builder = static_cast<GArrowArrayBuilder *>(node->data);
-    GArrowArrayBuilderPrivate *field_builder_priv;
-
-    field_builder_priv = GARROW_ARRAY_BUILDER_GET_PRIVATE(field_builder);
-    field_builder_priv->array_builder = nullptr;
-    g_object_unref(field_builder);
-  }
-  g_list_free(priv->field_builders);
-  priv->field_builders = NULL;
-
-  G_OBJECT_CLASS(garrow_struct_array_builder_parent_class)->dispose(object);
-}
-
 static void
 garrow_struct_array_builder_init(GArrowStructArrayBuilder *builder)
 {
@@ -5883,11 +5868,6 @@ 
garrow_struct_array_builder_init(GArrowStructArrayBuilder *builder)
 static void
 garrow_struct_array_builder_class_init(GArrowStructArrayBuilderClass *klass)
 {
-  GObjectClass *gobject_class;
-
-  gobject_class = G_OBJECT_CLASS(klass);
-
-  gobject_class->dispose = garrow_struct_array_builder_dispose;
 }
 
 /**
@@ -5969,9 +5949,8 @@ 
garrow_struct_array_builder_append_value(GArrowStructArrayBuilder *builder,
                                          GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::StructBuilder *>(
+    std::static_pointer_cast<arrow::StructBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
   auto status = arrow_builder->Append();
   return garrow_error_check(error,
                             status,
@@ -6003,42 +5982,31 @@ 
garrow_struct_array_builder_append_null(GArrowStructArrayBuilder *builder,
  * @i: The index of the field in the struct.
  *
  * Returns: (transfer none): The #GArrowArrayBuilder for the i-th field.
+ *
+ * Deprecated: 12.0.0:
+ *   Use garrow_array_builder_get_child() instead.
  */
 GArrowArrayBuilder *
 garrow_struct_array_builder_get_field_builder(GArrowStructArrayBuilder 
*builder,
                                               gint i)
 {
-  auto field_builders = 
garrow_struct_array_builder_get_field_builders(builder);
-  auto field_builder = g_list_nth_data(field_builders, i);
-  return static_cast<GArrowArrayBuilder *>(field_builder);
+  return garrow_array_builder_get_child(GARROW_ARRAY_BUILDER(builder), i);
 }
 
 /**
  * garrow_struct_array_builder_get_field_builders:
  * @builder: A #GArrowStructArrayBuilder.
  *
- * Returns: (element-type GArrowArray) (transfer none):
+ * Returns: (element-type GArrowArrayBuilder) (transfer none):
  *   The #GArrowArrayBuilder for all fields.
+ *
+ * Deprecated: 12.0.0:
+ *   Use garrow_array_builder_get_children() instead.
  */
 GList *
 garrow_struct_array_builder_get_field_builders(GArrowStructArrayBuilder 
*builder)
 {
-  auto priv = GARROW_STRUCT_ARRAY_BUILDER_GET_PRIVATE(builder);
-  if (!priv->field_builders) {
-    auto arrow_struct_builder =
-      static_cast<arrow::StructBuilder *>(
-        garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
-    GList *field_builders = NULL;
-    for (int i = 0; i < arrow_struct_builder->num_fields(); ++i) {
-      auto arrow_field_builder = arrow_struct_builder->field_builder(i);
-      auto field_builder = garrow_array_builder_new_raw(arrow_field_builder);
-      field_builders = g_list_prepend(field_builders, field_builder);
-    }
-    priv->field_builders = g_list_reverse(field_builders);
-  }
-
-  return priv->field_builders;
+  return garrow_array_builder_get_children(GARROW_ARRAY_BUILDER(builder));
 }
 
 
@@ -6140,9 +6108,8 @@ 
garrow_map_array_builder_append_value(GArrowMapArrayBuilder *builder,
                                       GError **error)
 {
   auto arrow_builder =
-    static_cast<arrow::MapBuilder *>(
+    std::static_pointer_cast<arrow::MapBuilder>(
       garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
-
   auto status = arrow_builder->Append();
   return garrow::check(error,
                        status,
@@ -6176,7 +6143,7 @@ 
garrow_map_array_builder_append_values(GArrowMapArrayBuilder *builder,
                                        gint64 is_valids_length,
                                        GError **error)
 {
-  return garrow_array_builder_append_values<arrow::MapBuilder *>
+  return garrow_array_builder_append_values<arrow::MapBuilder>
     (GARROW_ARRAY_BUILDER(builder),
      reinterpret_cast<const int32_t *>(offsets),
      offsets_length,
@@ -6245,11 +6212,10 @@ 
garrow_map_array_builder_get_key_builder(GArrowMapArrayBuilder *builder)
   auto priv = GARROW_MAP_ARRAY_BUILDER_GET_PRIVATE(builder);
   if (!priv->key_builder) {
     auto arrow_builder =
-      static_cast<arrow::MapBuilder *>(
+      std::static_pointer_cast<arrow::MapBuilder>(
         garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
     auto arrow_key_builder = arrow_builder->key_builder();
     priv->key_builder = garrow_array_builder_new_raw(arrow_key_builder);
-    garrow_array_builder_release_ownership(priv->key_builder);
   }
   return priv->key_builder;
 }
@@ -6268,11 +6234,10 @@ 
garrow_map_array_builder_get_item_builder(GArrowMapArrayBuilder *builder)
   auto priv = GARROW_MAP_ARRAY_BUILDER_GET_PRIVATE(builder);
   if (!priv->item_builder) {
     auto arrow_builder =
-      static_cast<arrow::MapBuilder *>(
+      std::static_pointer_cast<arrow::MapBuilder>(
         garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
     auto arrow_item_builder = arrow_builder->item_builder();
     priv->item_builder = garrow_array_builder_new_raw(arrow_item_builder);
-    garrow_array_builder_release_ownership(priv->item_builder);
   }
   return priv->item_builder;
 }
@@ -6294,11 +6259,10 @@ 
garrow_map_array_builder_get_value_builder(GArrowMapArrayBuilder *builder)
   auto priv = GARROW_MAP_ARRAY_BUILDER_GET_PRIVATE(builder);
   if (!priv->value_builder) {
     auto arrow_builder =
-      static_cast<arrow::MapBuilder *>(
+      std::static_pointer_cast<arrow::MapBuilder>(
         garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
     auto arrow_value_builder = arrow_builder->value_builder();
     priv->value_builder = garrow_array_builder_new_raw(arrow_value_builder);
-    garrow_array_builder_release_ownership(priv->value_builder);
   }
   return priv->value_builder;
 }
@@ -6374,7 +6338,7 @@ 
garrow_decimal128_array_builder_append_value(GArrowDecimal128ArrayBuilder *build
 {
   if (value) {
     auto arrow_decimal = garrow_decimal128_get_raw(value);
-    return garrow_array_builder_append_value<arrow::Decimal128Builder *>
+    return garrow_array_builder_append_value<arrow::Decimal128Builder>
       (GARROW_ARRAY_BUILDER(builder),
        *arrow_decimal,
        error,
@@ -6498,7 +6462,7 @@ 
garrow_decimal256_array_builder_append_value(GArrowDecimal256ArrayBuilder *build
 {
   if (value) {
     auto arrow_decimal = garrow_decimal256_get_raw(value);
-    return garrow_array_builder_append_value<arrow::Decimal256Builder *>
+    return garrow_array_builder_append_value<arrow::Decimal256Builder>
       (GARROW_ARRAY_BUILDER(builder),
        *arrow_decimal,
        error,
@@ -6552,14 +6516,119 @@ garrow_decimal256_array_builder_append_values(
 }
 
 
+G_DEFINE_ABSTRACT_TYPE(GArrowUnionArrayBuilder,
+                       garrow_union_array_builder,
+                       GARROW_TYPE_ARRAY_BUILDER)
+
+static void
+garrow_union_array_builder_init(GArrowUnionArrayBuilder *builder)
+{
+}
+
+static void
+garrow_union_array_builder_class_init(GArrowUnionArrayBuilderClass *klass)
+{
+}
+
+/**
+ * garrow_union_array_builder_append_child:
+ * @builder: A #GArrowUnionArrayBuilder.
+ * @child: A #GArrowArrayBuilder for new child.
+ * @filed_name: (nullable): A field name for new child.
+ *
+ * Returns: The type ID for the appended child.
+ *
+ * Since: 12.0.00
+ */
+gint8
+garrow_union_array_builder_append_child(GArrowUnionArrayBuilder *builder,
+                                        GArrowArrayBuilder *child,
+                                        const gchar *field_name)
+{
+  auto arrow_builder =
+    std::static_pointer_cast<arrow::BasicUnionBuilder>(
+      garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
+  auto arrow_child = garrow_array_builder_get_raw(child);
+  if (!field_name) {
+    field_name = "";
+  }
+  return arrow_builder->AppendChild(arrow_child, field_name);
+}
+
+/**
+ * garrow_union_array_builder_append_value:
+ * @builder: A #GArrowUnionArrayBuilder.
+ * @value: A type ID value.
+ * @error: (nullable): Return location for a #GError or %NULL.
+ *
+ * Append an element to the union array. This must be followed by an
+ * append to the appropriate child builder.
+ *
+ * Returns: %TRUE on success, %FALSE if there was an error.
+ *
+ * Since: 12.0.0
+ */
+gboolean
+garrow_union_array_builder_append_value(GArrowUnionArrayBuilder *builder,
+                                        gint8 value,
+                                        GError **error)
+{
+  if (GARROW_IS_DENSE_UNION_ARRAY_BUILDER(builder)) {
+    auto arrow_builder =
+      std::static_pointer_cast<arrow::DenseUnionBuilder>(
+        garrow_array_builder_get_raw(GARROW_ARRAY_BUILDER(builder)));
+    auto status = arrow_builder->Append(value);
+    return garrow_error_check(error,
+                              status,
+                              "[union-array-builder][append-value]");
+  }
+  return false;
+}
+
+
+G_DEFINE_TYPE(GArrowDenseUnionArrayBuilder,
+              garrow_dense_union_array_builder,
+              GARROW_TYPE_UNION_ARRAY_BUILDER)
+
+static void
+garrow_dense_union_array_builder_init(GArrowDenseUnionArrayBuilder *builder)
+{
+}
+
+static void
+garrow_dense_union_array_builder_class_init(GArrowDenseUnionArrayBuilderClass 
*klass)
+{
+}
+
+/**
+ * garrow_dense_union_array_builder_new:
+ *
+ * Returns: (nullable): A newly created #GArrowDenseUnionArrayBuilder.
+ *
+ * Since: 12.0.0
+ */
+GArrowDenseUnionArrayBuilder *
+garrow_dense_union_array_builder_new(void)
+{
+  auto memory_pool = arrow::default_memory_pool();
+  auto arrow_builder =
+    std::static_pointer_cast<arrow::ArrayBuilder>(
+      std::make_shared<arrow::DenseUnionBuilder>(memory_pool));
+  auto builder =
+    garrow_array_builder_new_raw(&arrow_builder,
+                                 GARROW_TYPE_DENSE_UNION_ARRAY_BUILDER);
+  return GARROW_DENSE_UNION_ARRAY_BUILDER(builder);
+}
+
+
 G_END_DECLS
 
 GArrowArrayBuilder *
-garrow_array_builder_new_raw(arrow::ArrayBuilder *arrow_builder,
+garrow_array_builder_new_raw(std::shared_ptr<arrow::ArrayBuilder> 
*arrow_builder,
                              GType type)
 {
   if (type == G_TYPE_INVALID) {
-    switch (arrow_builder->type()->id()) {
+    switch ((*arrow_builder)->type()->id()) {
     case arrow::Type::type::NA:
       type = GARROW_TYPE_NULL_ARRAY_BUILDER;
       break;
@@ -6659,7 +6728,8 @@ garrow_array_builder_new_raw(arrow::ArrayBuilder 
*arrow_builder,
     case arrow::Type::type::DICTIONARY:
       {
         auto dict_type =
-          
std::static_pointer_cast<arrow::DictionaryType>(arrow_builder->type());
+          std::static_pointer_cast<arrow::DictionaryType>(
+            (*arrow_builder)->type());
         switch (dict_type->value_type()->id()) {
           case arrow::Type::type::BINARY:
             type = GARROW_TYPE_BINARY_DICTIONARY_ARRAY_BUILDER;
@@ -6673,6 +6743,9 @@ garrow_array_builder_new_raw(arrow::ArrayBuilder 
*arrow_builder,
         }
       }
       break;
+    case arrow::Type::type::DENSE_UNION:
+      type = GARROW_TYPE_DENSE_UNION_ARRAY_BUILDER;
+      break;
     default:
       type = GARROW_TYPE_ARRAY_BUILDER;
       break;
@@ -6686,7 +6759,20 @@ garrow_array_builder_new_raw(arrow::ArrayBuilder 
*arrow_builder,
   return builder;
 }
 
-arrow::ArrayBuilder *
+GArrowArrayBuilder *
+garrow_array_builder_new_raw(arrow::ArrayBuilder *arrow_builder,
+                             GType type)
+{
+  struct NothingDeleter {
+    void operator()(arrow::ArrayBuilder *arrow_builder) {
+    }
+  };
+  std::shared_ptr<arrow::ArrayBuilder> arrow_shared_builder(arrow_builder,
+                                                            NothingDeleter());
+  return garrow_array_builder_new_raw(&arrow_shared_builder, type);
+}
+
+std::shared_ptr<arrow::ArrayBuilder>
 garrow_array_builder_get_raw(GArrowArrayBuilder *builder)
 {
   auto priv = GARROW_ARRAY_BUILDER_GET_PRIVATE(builder);
diff --git a/c_glib/arrow-glib/array-builder.h 
b/c_glib/arrow-glib/array-builder.h
index 741390739f..de4bd63c6f 100644
--- a/c_glib/arrow-glib/array-builder.h
+++ b/c_glib/arrow-glib/array-builder.h
@@ -36,8 +36,6 @@ struct _GArrowArrayBuilderClass
   GObjectClass parent_class;
 };
 
-void garrow_array_builder_release_ownership(GArrowArrayBuilder *builder);
-
 GArrowDataType *
 garrow_array_builder_get_value_data_type(GArrowArrayBuilder *builder);
 GArrowType garrow_array_builder_get_value_type(GArrowArrayBuilder *builder);
@@ -54,6 +52,13 @@ GARROW_AVAILABLE_IN_2_0
 gint64 garrow_array_builder_get_length(GArrowArrayBuilder *builder);
 GARROW_AVAILABLE_IN_2_0
 gint64 garrow_array_builder_get_n_nulls(GArrowArrayBuilder *builder);
+GARROW_AVAILABLE_IN_12_0
+GArrowArrayBuilder *
+garrow_array_builder_get_child(GArrowArrayBuilder *builder,
+                               gint i);
+GARROW_AVAILABLE_IN_12_0
+GList *
+garrow_array_builder_get_children(GArrowArrayBuilder *builder);
 
 GARROW_AVAILABLE_IN_2_0
 gboolean garrow_array_builder_resize(GArrowArrayBuilder *builder,
@@ -1407,9 +1412,15 @@ gboolean 
garrow_struct_array_builder_append_null(GArrowStructArrayBuilder *build
                                                  GError **error);
 #endif
 
-GArrowArrayBuilder 
*garrow_struct_array_builder_get_field_builder(GArrowStructArrayBuilder 
*builder,
-                                                                  gint i);
-GList *garrow_struct_array_builder_get_field_builders(GArrowStructArrayBuilder 
*builder);
+#ifndef GARROW_DISABLE_DEPRECATED
+GARROW_DEPRECATED_IN_12_0_FOR(garrow_array_builder_get_child)
+GArrowArrayBuilder *
+garrow_struct_array_builder_get_field_builder(GArrowStructArrayBuilder 
*builder,
+                                              gint i);
+GARROW_DEPRECATED_IN_12_0_FOR(garrow_array_builder_get_children)
+GList *
+garrow_struct_array_builder_get_field_builders(GArrowStructArrayBuilder 
*builder);
+#endif
 
 
 #define GARROW_TYPE_MAP_ARRAY_BUILDER        \
@@ -1530,4 +1541,47 @@ garrow_decimal256_array_builder_append_values(
   gint64 is_valids_length,
   GError **error);
 
+
+#define GARROW_TYPE_UNION_ARRAY_BUILDER         \
+  (garrow_union_array_builder_get_type())
+G_DECLARE_DERIVABLE_TYPE(GArrowUnionArrayBuilder,
+                         garrow_union_array_builder,
+                         GARROW,
+                         UNION_ARRAY_BUILDER,
+                         GArrowArrayBuilder)
+struct _GArrowUnionArrayBuilderClass
+{
+  GArrowArrayBuilderClass parent_class;
+};
+
+GARROW_AVAILABLE_IN_12_0
+gint8
+garrow_union_array_builder_append_child(GArrowUnionArrayBuilder *builder,
+                                        GArrowArrayBuilder *child,
+                                        const gchar *filed_name);
+
+GARROW_AVAILABLE_IN_12_0
+gboolean
+garrow_union_array_builder_append_value(GArrowUnionArrayBuilder *builder,
+                                        gint8 value,
+                                        GError **error);
+
+
+#define GARROW_TYPE_DENSE_UNION_ARRAY_BUILDER   \
+  (garrow_dense_union_array_builder_get_type())
+G_DECLARE_DERIVABLE_TYPE(GArrowDenseUnionArrayBuilder,
+                         garrow_dense_union_array_builder,
+                         GARROW,
+                         DENSE_UNION_ARRAY_BUILDER,
+                         GArrowUnionArrayBuilder)
+struct _GArrowDenseUnionArrayBuilderClass
+{
+  GArrowUnionArrayBuilderClass parent_class;
+};
+
+GARROW_AVAILABLE_IN_12_0
+GArrowDenseUnionArrayBuilder *
+garrow_dense_union_array_builder_new(void);
+
+
 G_END_DECLS
diff --git a/c_glib/arrow-glib/array-builder.hpp 
b/c_glib/arrow-glib/array-builder.hpp
index bcdc58fd88..89b91ac579 100644
--- a/c_glib/arrow-glib/array-builder.hpp
+++ b/c_glib/arrow-glib/array-builder.hpp
@@ -22,6 +22,11 @@
 #include <arrow-glib/array.hpp>
 #include <arrow-glib/array-builder.h>
 
-GArrowArrayBuilder *garrow_array_builder_new_raw(arrow::ArrayBuilder 
*arrow_builder,
-                                                 GType type=G_TYPE_INVALID);
-arrow::ArrayBuilder *garrow_array_builder_get_raw(GArrowArrayBuilder *builder);
+GArrowArrayBuilder *
+garrow_array_builder_new_raw(std::shared_ptr<arrow::ArrayBuilder> 
*arrow_builder,
+                             GType type=G_TYPE_INVALID);
+GArrowArrayBuilder *
+garrow_array_builder_new_raw(arrow::ArrayBuilder *arrow_builder,
+                             GType type=G_TYPE_INVALID);
+std::shared_ptr<arrow::ArrayBuilder>
+garrow_array_builder_get_raw(GArrowArrayBuilder *builder);
diff --git a/c_glib/arrow-glib/table-builder.cpp 
b/c_glib/arrow-glib/table-builder.cpp
index 0ea41281db..5b423f8e49 100644
--- a/c_glib/arrow-glib/table-builder.cpp
+++ b/c_glib/arrow-glib/table-builder.cpp
@@ -64,7 +64,6 @@ garrow_record_batch_builder_constructed(GObject *object)
   for (int i = 0; i < n_columns; ++i) {
     auto arrow_array_builder = arrow_builder->GetField(i);
     auto array_builder = garrow_array_builder_new_raw(arrow_array_builder);
-    garrow_array_builder_release_ownership(array_builder);
     g_ptr_array_add(priv->column_builders, array_builder);
   }
 
diff --git a/c_glib/test/test-dense-union-array-builder.rb 
b/c_glib/test/test-dense-union-array-builder.rb
new file mode 100644
index 0000000000..1b2ed913fc
--- /dev/null
+++ b/c_glib/test/test-dense-union-array-builder.rb
@@ -0,0 +1,172 @@
+# 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.
+
+class TestDenseUnionArrayBuilder < Test::Unit::TestCase
+  include Helper::Buildable
+
+  def setup
+    @builder = Arrow::DenseUnionArrayBuilder.new
+  end
+
+  def create_dense_union_array(type_ids, value_offsets, fields)
+    Arrow::DenseUnionArray.new(build_int8_array(type_ids),
+                               build_int32_array(value_offsets),
+                               fields)
+  end
+
+  def test_append_null
+    int16_child_builder = Arrow::Int16ArrayBuilder.new
+    int16_child_type_id = @builder.append_child(int16_child_builder, "0")
+
+    type_ids = []
+    value_offsets = []
+    int16_child_values = []
+
+    @builder.append_null
+    # expected
+    type_ids << int16_child_type_id
+    value_offsets << int16_child_values.size
+    int16_child_values << nil
+
+    fields = [
+      build_int16_array(int16_child_values),
+    ]
+    assert_equal(create_dense_union_array(type_ids, value_offsets, fields),
+                 @builder.finish)
+  end
+
+  def test_append_nulls
+    int16_child_builder = Arrow::Int16ArrayBuilder.new
+    int16_child_type_id = @builder.append_child(int16_child_builder, "0")
+
+    type_ids = []
+    value_offsets = []
+    int16_child_values = []
+
+    @builder.append_nulls(3)
+    # expected
+    3.times do
+      type_ids << int16_child_type_id
+      value_offsets << int16_child_values.size
+      int16_child_values << nil
+    end
+
+    fields = [
+      build_int16_array(int16_child_values),
+    ]
+    assert_equal(create_dense_union_array(type_ids, value_offsets, fields),
+                 @builder.finish)
+  end
+
+  def test_append_empty_value
+    int16_child_builder = Arrow::Int16ArrayBuilder.new
+    int16_child_type_id = @builder.append_child(int16_child_builder, "0")
+
+    type_ids = []
+    value_offsets = []
+    int16_child_values = []
+
+    @builder.append_empty_value
+    # expected
+    type_ids << int16_child_type_id
+    value_offsets << int16_child_values.size
+    int16_child_values << 0
+
+    fields = [
+      build_int16_array(int16_child_values),
+    ]
+    assert_equal(create_dense_union_array(type_ids, value_offsets, fields),
+                 @builder.finish)
+  end
+
+  def test_append_empty_values
+    int16_child_builder = Arrow::Int16ArrayBuilder.new
+    int16_child_type_id = @builder.append_child(int16_child_builder, "0")
+
+    type_ids = []
+    value_offsets = []
+    int16_child_values = []
+
+    @builder.append_empty_values(3)
+    # expected
+    3.times do
+      type_ids << int16_child_type_id
+      value_offsets << int16_child_values.size
+      int16_child_values << 0
+    end
+
+    fields = [
+      build_int16_array(int16_child_values),
+    ]
+    assert_equal(create_dense_union_array(type_ids, value_offsets, fields),
+                 @builder.finish)
+  end
+
+  def test_append_value
+    int16_child_builder = Arrow::Int16ArrayBuilder.new
+    int16_child_type_id = @builder.append_child(int16_child_builder, "0")
+    string_child_builder = Arrow::StringArrayBuilder.new
+    string_child_type_id = @builder.append_child(string_child_builder, "1")
+
+    type_ids = []
+    value_offsets = []
+    int16_child_values = []
+    string_child_values = []
+
+    @builder.append_value(int16_child_type_id)
+    int16_child_builder.append_value(1)
+    # expected
+    type_ids << int16_child_type_id
+    value_offsets << int16_child_values.size
+    int16_child_values << 1
+
+    @builder.append_value(string_child_type_id)
+    string_child_builder.append_value("a")
+    # expected
+    type_ids << string_child_type_id
+    value_offsets << string_child_values.size
+    string_child_values << "a"
+
+    @builder.append_value(int16_child_type_id)
+    int16_child_builder.append_null
+    # expected
+    type_ids << int16_child_type_id
+    value_offsets << int16_child_values.size
+    int16_child_values << nil
+
+    @builder.append_value(string_child_type_id)
+    string_child_builder.append_value("b")
+    # expected
+    type_ids << string_child_type_id
+    value_offsets << string_child_values.size
+    string_child_values << "b"
+
+    @builder.append_value(string_child_type_id)
+    string_child_builder.append_value("c")
+    # expected
+    type_ids << string_child_type_id
+    value_offsets << string_child_values.size
+    string_child_values << "c"
+
+    fields = [
+      build_int16_array(int16_child_values),
+      build_string_array(string_child_values),
+    ]
+    assert_equal(create_dense_union_array(type_ids, value_offsets, fields),
+                 @builder.finish)
+  end
+end
diff --git a/ruby/red-arrow/lib/arrow/dense-union-array-builder.rb 
b/ruby/red-arrow/lib/arrow/dense-union-array-builder.rb
new file mode 100644
index 0000000000..69c4f225ba
--- /dev/null
+++ b/ruby/red-arrow/lib/arrow/dense-union-array-builder.rb
@@ -0,0 +1,88 @@
+# 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 Arrow
+  class DenseUnionArrayBuilder
+    alias_method :append_value_raw, :append_value
+
+    # @overload append_value
+    #
+    #   Starts appending an union record. You need to append values of
+    #   fields.
+    #
+    # @overload append_value(value)
+    #
+    #   Appends an union record including values of fields.
+    #
+    #   @param value [nil, Hash] The union record value.
+    #
+    #     If this is `nil`, the union record is null.
+    #
+    #     If this is `Hash`, it's  values of fields.
+    #
+    # @since 12.0.0
+    def append_value(value)
+      if value.nil?
+        append_null
+      else
+        key = value.keys[0]
+        child_info = child_infos[key]
+        append_value_raw(child_info[:id])
+        child_info[:builder].append(value.values[0])
+      end
+    end
+
+    def append_values(values, is_valids=nil)
+      if is_valids
+        is_valids.each_with_index do |is_valid, i|
+          if is_valid
+            append_value(values[i])
+          else
+            append_null
+          end
+        end
+      else
+        values.each do |value|
+          append_value(value)
+        end
+      end
+    end
+
+    alias_method :append_child_raw, :append_child
+    def append_child(builder, filed_name=nil)
+      @child_infos = nil
+      append_child_raw(builder, field_name)
+    end
+
+    private
+    def child_infos
+      @child_infos ||= create_child_infos
+    end
+
+    def create_child_infos
+      infos = {}
+      type = value_data_type
+      type.fields.zip(children, type.type_codes).each do |field, child, id|
+        infos[field.name] = {
+          builder: child,
+          id: id,
+        }
+      end
+      infos
+    end
+  end
+end
diff --git a/ruby/red-arrow/lib/arrow/loader.rb 
b/ruby/red-arrow/lib/arrow/loader.rb
index 200b4b6d65..a885aeb4ff 100644
--- a/ruby/red-arrow/lib/arrow/loader.rb
+++ b/ruby/red-arrow/lib/arrow/loader.rb
@@ -71,6 +71,7 @@ module Arrow
       require "arrow/decimal256-array-builder"
       require "arrow/decimal256-data-type"
       require "arrow/dense-union-array"
+      require "arrow/dense-union-array-builder"
       require "arrow/dense-union-data-type"
       require "arrow/dictionary-array"
       require "arrow/dictionary-data-type"
diff --git a/ruby/red-arrow/lib/arrow/struct-array-builder.rb 
b/ruby/red-arrow/lib/arrow/struct-array-builder.rb
index ce883166a0..57c94c4ea9 100644
--- a/ruby/red-arrow/lib/arrow/struct-array-builder.rb
+++ b/ruby/red-arrow/lib/arrow/struct-array-builder.rb
@@ -110,11 +110,6 @@ module Arrow
       end
     end
 
-    alias_method :append_null_raw, :append_null
-    def append_null
-      append_null_raw
-    end
-
     # @since 0.12.0
     def append(*values)
       if values.empty?
diff --git a/ruby/red-arrow/test/raw-records/test-dense-union-array.rb 
b/ruby/red-arrow/test/raw-records/test-dense-union-array.rb
index 4132f1edfd..6f260c369b 100644
--- a/ruby/red-arrow/test/raw-records/test-dense-union-array.rb
+++ b/ruby/red-arrow/test/raw-records/test-dense-union-array.rb
@@ -79,7 +79,11 @@ module RawRecordsDenseUnionArrayTests
   def remove_field_names(records)
     records.collect do |record|
       record.collect do |column|
-        column.values[0]
+        if column.nil?
+          column
+        else
+          column.values[0]
+        end
       end
     end
   end
@@ -497,12 +501,11 @@ module RawRecordsDenseUnionArrayTests
                      type_codes: [0, 1],
                    },
                    records)
-    assert_equal(remove_field_names(records),
+    assert_equal(remove_field_names(remove_field_names(records)),
                  target.raw_records)
   end
 
   def test_dense_union
-    omit("Need to add support for DenseUnionArrayBuilder")
     records = [
       [{"0" => {"field1" => true}}],
       [{"1" => nil}],
@@ -523,7 +526,7 @@ module RawRecordsDenseUnionArrayTests
                      type_codes: [0, 1],
                    },
                    records)
-    assert_equal(remove_field_names(records),
+    assert_equal(remove_field_names(remove_field_names(records)),
                  target.raw_records)
   end
 
diff --git a/ruby/red-arrow/test/raw-records/test-list-array.rb 
b/ruby/red-arrow/test/raw-records/test-list-array.rb
index bd40959516..31410ce55f 100644
--- a/ruby/red-arrow/test/raw-records/test-list-array.rb
+++ b/ruby/red-arrow/test/raw-records/test-list-array.rb
@@ -509,13 +509,32 @@ module RawRecordsListArrayTests
     assert_equal(records, target.raw_records)
   end
 
-  def test_sparse
+  def remove_union_field_names(records)
+    records.collect do |record|
+      record.collect do |column|
+        if column.nil?
+          column
+        else
+          column.collect do |value|
+            if value.nil?
+              value
+            else
+              value.values[0]
+            end
+          end
+        end
+      end
+    end
+  end
+
+  def test_sparse_union
     omit("Need to add support for SparseUnionArrayBuilder")
     records = [
       [
         [
           {"field1" => true},
           nil,
+          {"field2" => 29},
           {"field2" => nil},
         ],
       ],
@@ -536,16 +555,17 @@ module RawRecordsListArrayTests
                      type_codes: [0, 1],
                    },
                    records)
-    assert_equal(records, target.raw_records)
+    assert_equal(remove_union_field_names(records),
+                 target.raw_records)
   end
 
-  def test_dense
-    omit("Need to add support for DenseUnionArrayBuilder")
+  def test_dense_union
     records = [
       [
         [
           {"field1" => true},
           nil,
+          {"field2" => 29},
           {"field2" => nil},
         ],
       ],
@@ -566,7 +586,8 @@ module RawRecordsListArrayTests
                      type_codes: [0, 1],
                    },
                    records)
-    assert_equal(records, target.raw_records)
+    assert_equal(remove_union_field_names(records),
+                 target.raw_records)
   end
 
   def test_dictionary
diff --git a/ruby/red-arrow/test/raw-records/test-map-array.rb 
b/ruby/red-arrow/test/raw-records/test-map-array.rb
index 7592a65af3..e93d108d97 100644
--- a/ruby/red-arrow/test/raw-records/test-map-array.rb
+++ b/ruby/red-arrow/test/raw-records/test-map-array.rb
@@ -395,10 +395,34 @@ module RawRecordsMapArrayTests
     assert_equal(records, target.raw_records)
   end
 
+  def remove_union_field_names(records)
+    records.collect do |record|
+      record.collect do |column|
+        if column.nil?
+          column
+        else
+          value = {}
+          column.each do |k, v|
+            v = v.values[0] unless v.nil?
+            value[k] = v
+          end
+          value
+        end
+      end
+    end
+  end
+
   def test_sparse_union
     omit("Need to add support for SparseUnionArrayBuilder")
     records = [
-      [{"key1" => {"field" => true, "key2" => nil, "key3" => {"field" => 
nil}}}],
+      [
+        {
+          "key1" => {"field1" => true},
+          "key2" => nil,
+          "key3" => {"field2" => 29},
+          "key4" => {"field2" => nil},
+        },
+      ],
       [nil],
     ]
     target = build({
@@ -416,13 +440,20 @@ module RawRecordsMapArrayTests
                      type_codes: [0, 1],
                    },
                    records)
-    assert_equal(records, target.raw_records)
+    assert_equal(remove_union_field_names(records),
+                 target.raw_records)
   end
 
   def test_dense_union
-    omit("Need to add support for DenseUnionArrayBuilder")
     records = [
-      [{"key1" => {"field1" => true}, "key2" => nil, "key3" => {"field2" => 
nil}}],
+      [
+        {
+          "key1" => {"field1" => true},
+          "key2" => nil,
+          "key3" => {"field2" => 29},
+          "key4" => {"field2" => nil},
+        },
+      ],
       [nil],
     ]
     target = build({
@@ -440,7 +471,8 @@ module RawRecordsMapArrayTests
                      type_codes: [0, 1],
                    },
                    records)
-    assert_equal(records, target.raw_records)
+    assert_equal(remove_union_field_names(records),
+                 target.raw_records)
   end
 
   def test_dictionary
diff --git a/ruby/red-arrow/test/raw-records/test-sparse-union-array.rb 
b/ruby/red-arrow/test/raw-records/test-sparse-union-array.rb
index c3219d29e6..d2ddddcc9a 100644
--- a/ruby/red-arrow/test/raw-records/test-sparse-union-array.rb
+++ b/ruby/red-arrow/test/raw-records/test-sparse-union-array.rb
@@ -69,7 +69,11 @@ module RawRecordsSparseUnionArrayTests
   def remove_field_names(records)
     records.collect do |record|
       record.collect do |column|
-        column.values[0]
+        if column.nil?
+          column
+        else
+          column.values[0]
+        end
       end
     end
   end
@@ -487,12 +491,11 @@ module RawRecordsSparseUnionArrayTests
                      type_codes: [0, 1],
                    },
                    records)
-    assert_equal(remove_field_names(records),
+    assert_equal(remove_field_names(remove_field_names(records)),
                  target.raw_records)
   end
 
   def test_dense_union
-    omit("Need to add support for DenseUnionArrayBuilder")
     records = [
       [{"0" => {"field1" => true}}],
       [{"1" => nil}],
@@ -513,7 +516,7 @@ module RawRecordsSparseUnionArrayTests
                      type_codes: [0, 1],
                    },
                    records)
-    assert_equal(remove_field_names(records),
+    assert_equal(remove_field_names(remove_field_names(records)),
                  target.raw_records)
   end
 
diff --git a/ruby/red-arrow/test/raw-records/test-struct-array.rb 
b/ruby/red-arrow/test/raw-records/test-struct-array.rb
index ea33a15156..6f8e30cbb7 100644
--- a/ruby/red-arrow/test/raw-records/test-struct-array.rb
+++ b/ruby/red-arrow/test/raw-records/test-struct-array.rb
@@ -426,12 +426,27 @@ module RawRecordsStructArrayTests
     assert_equal(records, target.raw_records)
   end
 
+  def remove_union_field_names(records)
+    records.collect do |record|
+      record.collect do |column|
+        if column.nil?
+          column
+        else
+          value = column["field"]
+          value = value.values[0] unless value.nil?
+          {"field" => value}
+        end
+      end
+    end
+  end
+
   def test_sparse_union
     omit("Need to add support for SparseUnionArrayBuilder")
     records = [
       [{"field" => {"field1" => true}}],
       [nil],
       [{"field" => nil}],
+      [{"field" => {"field2" => 29}}],
       [{"field" => {"field2" => nil}}],
     ]
     target = build({
@@ -449,15 +464,16 @@ module RawRecordsStructArrayTests
                      type_codes: [0, 1],
                    },
                    records)
-    assert_equal(records, target.raw_records)
+    assert_equal(remove_union_fields(records),
+                 target.raw_records)
   end
 
   def test_dense_union
-    omit("Need to add support for DenseUnionArrayBuilder")
     records = [
       [{"field" => {"field1" => true}}],
       [nil],
       [{"field" => nil}],
+      [{"field" => {"field2" => 29}}],
       [{"field" => {"field2" => nil}}],
     ]
     target = build({
@@ -475,7 +491,8 @@ module RawRecordsStructArrayTests
                      type_codes: [0, 1],
                    },
                    records)
-    assert_equal(records, target.raw_records)
+    assert_equal(remove_union_field_names(records),
+                 target.raw_records)
   end
 
   def test_dictionary
diff --git a/ruby/red-arrow/test/values/test-dense-union-array.rb 
b/ruby/red-arrow/test/values/test-dense-union-array.rb
index 4d411fd35f..1769e5d3af 100644
--- a/ruby/red-arrow/test/values/test-dense-union-array.rb
+++ b/ruby/red-arrow/test/values/test-dense-union-array.rb
@@ -66,7 +66,11 @@ module ValuesDenseUnionArrayTests
 
   def remove_field_names(values)
     values.collect do |value|
-      value.values[0]
+      if value.nil?
+        value
+      else
+        value.values[0]
+      end
     end
   end
 
@@ -466,6 +470,7 @@ module ValuesDenseUnionArrayTests
     values = [
       {"0" => {"field1" => true}},
       {"1" => nil},
+      {"0" => {"field2" => 29}},
       {"0" => {"field2" => nil}},
     ]
     target = build({
@@ -483,15 +488,15 @@ module ValuesDenseUnionArrayTests
                      type_codes: [0, 1],
                    },
                    values)
-    assert_equal(remove_field_names(values),
+    assert_equal(remove_field_names(remove_field_names(values)),
                  target.values)
   end
 
   def test_dense_union
-    omit("Need to add support for DenseUnionArrayBuilder")
     values = [
       {"0" => {"field1" => true}},
       {"1" => nil},
+      {"0" => {"field2" => 29}},
       {"0" => {"field2" => nil}},
     ]
     target = build({
@@ -509,7 +514,7 @@ module ValuesDenseUnionArrayTests
                      type_codes: [0, 1],
                    },
                    values)
-    assert_equal(remove_field_names(values),
+    assert_equal(remove_field_names(remove_field_names(values)),
                  target.values)
   end
 
diff --git a/ruby/red-arrow/test/values/test-list-array.rb 
b/ruby/red-arrow/test/values/test-list-array.rb
index 5ed76432a2..dbb9e7013c 100644
--- a/ruby/red-arrow/test/values/test-list-array.rb
+++ b/ruby/red-arrow/test/values/test-list-array.rb
@@ -476,12 +476,29 @@ module ValuesListArrayTests
     assert_equal(values, target.values)
   end
 
-  def test_sparse
+  def remove_union_field_names(values)
+    values.collect do |value|
+      if value.nil?
+        value
+      else
+        value.collect do |v|
+          if v.nil?
+            v
+          else
+            v.values[0]
+          end
+        end
+      end
+    end
+  end
+
+  def test_sparse_union
     omit("Need to add support for SparseUnionArrayBuilder")
     values = [
       [
         {"field1" => true},
         nil,
+        {"field2" => 29},
         {"field2" => nil},
       ],
       nil,
@@ -501,15 +518,16 @@ module ValuesListArrayTests
                      type_codes: [0, 1],
                    },
                    values)
-    assert_equal(values, target.values)
+    assert_equal(remove_union_field_names(values),
+                 target.values)
   end
 
-  def test_dense
-    omit("Need to add support for DenseUnionArrayBuilder")
+  def test_dense_union
     values = [
       [
         {"field1" => true},
         nil,
+        {"field2" => 29},
         {"field2" => nil},
       ],
       nil,
@@ -529,7 +547,8 @@ module ValuesListArrayTests
                      type_codes: [0, 1],
                    },
                    values)
-    assert_equal(values, target.values)
+    assert_equal(remove_union_field_names(values),
+                 target.values)
   end
 
   def test_dictionary
diff --git a/ruby/red-arrow/test/values/test-map-array.rb 
b/ruby/red-arrow/test/values/test-map-array.rb
index 5132e79df6..a84d174128 100644
--- a/ruby/red-arrow/test/values/test-map-array.rb
+++ b/ruby/red-arrow/test/values/test-map-array.rb
@@ -383,10 +383,30 @@ module ValuesMapArrayTests
     assert_equal(values, target.values)
   end
 
+  def remove_union_field_names(values)
+    values.collect do |value|
+      if value.nil?
+        value
+      else
+        val = {}
+        value.each do |k, v|
+          v = v.values[0] unless v.nil?
+          val[k] = v
+        end
+        val
+      end
+    end
+  end
+
   def test_sparse_union
     omit("Need to add support for SparseUnionArrayBuilder")
     values = [
-      {"key1" => {"field1" => true}, "key2" => nil, "key3" => {"field2" => 
nil}},
+      {
+        "key1" => {"field1" => true},
+        "key2" => nil,
+        "key3" => {"field2" => 29},
+        "key4" => {"field2" => nil},
+      },
       nil,
     ]
     target = build({
@@ -404,13 +424,18 @@ module ValuesMapArrayTests
                      type_codes: [0, 1],
                    },
                    values)
-    assert_equal(values, target.values)
+    assert_equal(remove_union_field_names(values),
+                 target.values)
   end
 
   def test_dense_union
-    omit("Need to add support for DenseUnionArrayBuilder")
     values = [
-      {"key1" => {"field1" => true}, "key2" => nil, "key3" => {"field2" => 
nil}},
+      {
+        "key1" => {"field1" => true},
+        "key2" => nil,
+        "key3" => {"field2" => 29},
+        "key4" => {"field2" => nil},
+      },
       nil,
     ]
     target = build({
@@ -428,7 +453,8 @@ module ValuesMapArrayTests
                      type_codes: [0, 1],
                    },
                    values)
-    assert_equal(values, target.values)
+    assert_equal(remove_union_field_names(values),
+                 target.values)
   end
 
   def test_dictionary
diff --git a/ruby/red-arrow/test/values/test-sparse-union-array.rb 
b/ruby/red-arrow/test/values/test-sparse-union-array.rb
index 04b43e1bf1..f60d1e514e 100644
--- a/ruby/red-arrow/test/values/test-sparse-union-array.rb
+++ b/ruby/red-arrow/test/values/test-sparse-union-array.rb
@@ -57,7 +57,11 @@ module ValuesSparseUnionArrayTests
 
   def remove_field_names(values)
     values.collect do |value|
-      value.values[0]
+      if value.nil?
+        value
+      else
+        value.values[0]
+      end
     end
   end
 
@@ -457,6 +461,7 @@ module ValuesSparseUnionArrayTests
     values = [
       {"0" => {"field1" => true}},
       {"1" => nil},
+      {"0" => {"field2" => 29}},
       {"0" => {"field2" => nil}},
     ]
     target = build({
@@ -474,15 +479,15 @@ module ValuesSparseUnionArrayTests
                      type_codes: [0, 1],
                    },
                    values)
-    assert_equal(remove_field_names(values),
+    assert_equal(remove_field_names(remove_field_names(values)),
                  target.values)
   end
 
   def test_dense_union
-    omit("Need to add support for DenseUnionArrayBuilder")
     values = [
       {"0" => {"field1" => true}},
       {"1" => nil},
+      {"0" => {"field2" => 29}},
       {"0" => {"field2" => nil}},
     ]
     target = build({
@@ -500,7 +505,7 @@ module ValuesSparseUnionArrayTests
                      type_codes: [0, 1],
                    },
                    values)
-    assert_equal(remove_field_names(values),
+    assert_equal(remove_field_names(remove_field_names(values)),
                  target.values)
   end
 
diff --git a/ruby/red-arrow/test/values/test-struct-array.rb 
b/ruby/red-arrow/test/values/test-struct-array.rb
index ec94731b50..966f5b9ec1 100644
--- a/ruby/red-arrow/test/values/test-struct-array.rb
+++ b/ruby/red-arrow/test/values/test-struct-array.rb
@@ -423,12 +423,25 @@ module ValuesStructArrayTests
     assert_equal(values, target.values)
   end
 
+  def remove_union_field_names(values)
+    values.collect do |value|
+      if value.nil?
+        value
+      else
+        v = value["field"]
+        v = v.values[0] unless v.nil?
+        {"field" => v}
+      end
+    end
+  end
+
   def test_sparse_union
     omit("Need to add support for SparseUnionArrayBuilder")
     values = [
       {"field" => {"field1" => true}},
       nil,
       {"field" => nil},
+      {"field" => {"field2" => 29}},
       {"field" => {"field2" => nil}},
     ]
     target = build({
@@ -446,15 +459,16 @@ module ValuesStructArrayTests
                      type_codes: [0, 1],
                    },
                    values)
-    assert_equal(values, target.values)
+    assert_equal(remove_union_field_names(values),
+                 target.values)
   end
 
   def test_dense_union
-    omit("Need to add support for DenseUnionArrayBuilder")
     values = [
       {"field" => {"field1" => true}},
       nil,
       {"field" => nil},
+      {"field" => {"field2" => 29}},
       {"field" => {"field2" => nil}},
     ]
     target = build({
@@ -472,7 +486,8 @@ module ValuesStructArrayTests
                      type_codes: [0, 1],
                    },
                    values)
-    assert_equal(values, target.values)
+    assert_equal(remove_union_field_names(values),
+                 target.values)
   end
 
   def test_dictionary


Reply via email to