You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by ko...@apache.org on 2024/04/26 08:12:11 UTC

(arrow) branch main updated: GH-41327: [Ruby] Show type name in Arrow::Table#to_s (#41328)

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 e559a28cc1 GH-41327: [Ruby] Show type name in Arrow::Table#to_s (#41328)
e559a28cc1 is described below

commit e559a28cc19f87c2b1933bd2f7c9800ba290d5ab
Author: Sutou Kouhei <ko...@clear-code.com>
AuthorDate: Fri Apr 26 17:12:05 2024 +0900

    GH-41327: [Ruby] Show type name in Arrow::Table#to_s (#41328)
    
    ### Rationale for this change
    
    It's useful to detect type difference.
    
    ### What changes are included in this PR?
    
    Add `:show_column_type` option to `Arrow::Table#to_s` and enables it by default.
    
    This is a backward incompatible change but this'll help users.
    
    ### Are these changes tested?
    
    Yes.
    
    ### Are there any user-facing changes?
    
    Yes.
    
    **This PR includes breaking changes to public APIs.**
    
    * GitHub Issue: #41327
    
    Authored-by: Sutou Kouhei <ko...@clear-code.com>
    Signed-off-by: Sutou Kouhei <ko...@clear-code.com>
---
 ruby/red-arrow/lib/arrow/field-containable.rb     |   2 +-
 ruby/red-arrow/lib/arrow/table-formatter.rb       |  40 +-
 ruby/red-arrow/lib/arrow/table-list-formatter.rb  |   6 +-
 ruby/red-arrow/lib/arrow/table-table-formatter.rb |   7 +
 ruby/red-arrow/test/test-csv-loader.rb            |  72 +--
 ruby/red-arrow/test/test-group.rb                 |  13 +
 ruby/red-arrow/test/test-schema.rb                |   2 +-
 ruby/red-arrow/test/test-slicer.rb                | 345 +++++++-------
 ruby/red-arrow/test/test-struct-data-type.rb      |   2 +-
 ruby/red-arrow/test/test-table.rb                 | 535 ++++++++++++----------
 10 files changed, 595 insertions(+), 429 deletions(-)

diff --git a/ruby/red-arrow/lib/arrow/field-containable.rb b/ruby/red-arrow/lib/arrow/field-containable.rb
index e4dbf4ec26..103e901f5d 100644
--- a/ruby/red-arrow/lib/arrow/field-containable.rb
+++ b/ruby/red-arrow/lib/arrow/field-containable.rb
@@ -29,7 +29,7 @@ module Arrow
         return nil if index < 0 or index >= n_fields
         get_field(index)
       else
-        message = "field name or index must be String, Symbol or Integer"
+        message = +"field name or index must be String, Symbol or Integer"
         message << ": <#{name_or_index.inspect}>"
         raise ArgumentError, message
       end
diff --git a/ruby/red-arrow/lib/arrow/table-formatter.rb b/ruby/red-arrow/lib/arrow/table-formatter.rb
index d039679f9a..b93faf09cb 100644
--- a/ruby/red-arrow/lib/arrow/table-formatter.rb
+++ b/ruby/red-arrow/lib/arrow/table-formatter.rb
@@ -24,7 +24,8 @@ module Arrow
       attr_reader :head_values
       attr_reader :tail_values
       attr_reader :sample_values
-      def initialize(column, head_values, tail_values)
+      def initialize(table_formatter, column, head_values, tail_values)
+        @table_formatter = table_formatter
         @column = column
         @head_values = head_values
         @tail_values = tail_values
@@ -36,6 +37,15 @@ module Arrow
         @data_type ||= @column.data_type
       end
 
+      def formatted_data_type_name
+        @formatted_data_type_name ||= "(#{data_type.name})"
+      end
+
+      def aligned_data_type_name
+        @aligned_data_type_name ||=
+          "%*s" % [aligned_name.size, formatted_data_type_name]
+      end
+
       def name
         @name ||= @column.name
       end
@@ -63,7 +73,7 @@ module Arrow
             formatted_value = format_value(value[field_name], field_value_width)
             "#{formatted_name}: #{formatted_value}"
           end
-          formatted = "{"
+          formatted = +"{"
           formatted << formatted_values.join(", ")
           formatted << "}"
           "%-*s" % [width, formatted]
@@ -90,9 +100,16 @@ module Arrow
       end
 
       def format_aligned_name(name, data_type, sample_values)
+        if @table_formatter.show_column_type?
+          min_width = formatted_data_type_name.size
+        else
+          min_width = 0
+        end
         case data_type
         when TimestampDataType
-          "%*s" % [::Time.now.iso8601.size, name]
+          width = ::Time.now.iso8601.size
+          width = min_width if width < min_width
+          "%*s" % [width, name]
         when IntegerDataType
           have_null = false
           have_negative = false
@@ -118,9 +135,12 @@ module Arrow
           end
           width += 1 if have_negative # Need "-"
           width = [width, FORMATTED_NULL.size].max if have_null
+          width = min_width if width < min_width
           "%*s" % [width, name]
         when FloatDataType, DoubleDataType
-          "%*s" % [FLOAT_N_DIGITS, name]
+          width = FLOAT_N_DIGITS
+          width = min_width if width < min_width
+          "%*s" % [width, name]
         when StructDataType
           field_widths = data_type.fields.collect do |field|
             field_value_width = compute_field_value_width(field, sample_values)
@@ -130,9 +150,11 @@ module Arrow
           if field_widths.size > 0
             width += (", ".size * (field_widths.size - 1))
           end
+          width = min_width if width < min_width
           "%*s" % [width, name]
         else
-          name
+          width = min_width
+          "%*s" % [width, name]
         end
       end
     end
@@ -143,7 +165,7 @@ module Arrow
     end
 
     def format
-      text = ""
+      text = +""
       n_rows = @table.n_rows
       border = @options[:border] || 10
 
@@ -159,7 +181,7 @@ module Arrow
         else
           tail_values = []
         end
-        ColumnFormatter.new(column, head_values, tail_values)
+        ColumnFormatter.new(self, column, head_values, tail_values)
       end
 
       format_header(text, column_formatters)
@@ -186,5 +208,9 @@ module Arrow
 
       text
     end
+
+    def show_column_type?
+      @options.fetch(:show_column_type, true)
+    end
   end
 end
diff --git a/ruby/red-arrow/lib/arrow/table-list-formatter.rb b/ruby/red-arrow/lib/arrow/table-list-formatter.rb
index 4fe2934160..3e4d410ffb 100644
--- a/ruby/red-arrow/lib/arrow/table-list-formatter.rb
+++ b/ruby/red-arrow/lib/arrow/table-list-formatter.rb
@@ -27,9 +27,9 @@ module Arrow
         text << ("=" * 20 + " #{start_offset + nth_row} " + "=" * 20 + "\n")
         row.each_with_index do |column_value, nth_column|
           column_formatter = column_formatters[nth_column]
-          formatted_name = column_formatter.name
-          formatted_value = column_formatter.format_value(column_value)
-          text << "#{formatted_name}: #{formatted_value}\n"
+          text << column_formatter.name
+          text << "(#{column_formatter.data_type.name})" if show_column_type?
+          text << ": #{column_formatter.format_value(column_value)}\n"
         end
       end
     end
diff --git a/ruby/red-arrow/lib/arrow/table-table-formatter.rb b/ruby/red-arrow/lib/arrow/table-table-formatter.rb
index 36121e1b6f..acf4aca8bb 100644
--- a/ruby/red-arrow/lib/arrow/table-table-formatter.rb
+++ b/ruby/red-arrow/lib/arrow/table-table-formatter.rb
@@ -26,6 +26,13 @@ module Arrow
         text << "\t"
         text << column_formatter.aligned_name
       end
+      if show_column_type?
+        text << "\n"
+        column_formatters.each do |column_formatter|
+          text << "\t"
+          text << column_formatter.aligned_data_type_name
+        end
+      end
       text << "\n"
     end
 
diff --git a/ruby/red-arrow/test/test-csv-loader.rb b/ruby/red-arrow/test/test-csv-loader.rb
index 0b21f6f9b7..1e0445db06 100644
--- a/ruby/red-arrow/test/test-csv-loader.rb
+++ b/ruby/red-arrow/test/test-csv-loader.rb
@@ -27,80 +27,88 @@ class CSVLoaderTest < Test::Unit::TestCase
     test("String: data: with header") do
       data = fixture_path("with-header-float.csv").read
       assert_equal(<<-TABLE, load_csv(data).to_s)
-	name	     score
-0	alice	 10.100000
-1	bob 	 29.200000
-2	chris	 -1.300000
+	  name	     score
+	(utf8)	  (double)
+0	alice 	 10.100000
+1	bob   	 29.200000
+2	chris 	 -1.300000
       TABLE
     end
 
     test("String: data: without header") do
       data = fixture_path("without-header-float.csv").read
       assert_equal(<<-TABLE, load_csv(data).to_s)
-	0	         1
-0	alice	 10.100000
-1	bob	 29.200000
-2	chris	 -1.300000
+	     0	         1
+	(utf8)	  (double)
+0	alice 	 10.100000
+1	bob   	 29.200000
+2	chris 	 -1.300000
       TABLE
     end
 
     test("String: path: with header") do
       path = fixture_path("with-header-float.csv").to_s
       assert_equal(<<-TABLE, load_csv(path).to_s)
-	name	     score
-0	alice	 10.100000
-1	bob 	 29.200000
-2	chris	 -1.300000
+	  name	     score
+	(utf8)	  (double)
+0	alice 	 10.100000
+1	bob   	 29.200000
+2	chris 	 -1.300000
       TABLE
     end
 
     test("String: path: without header") do
       path = fixture_path("without-header-float.csv").to_s
       assert_equal(<<-TABLE, load_csv(path).to_s)
-	0	         1
-0	alice	 10.100000
-1	bob	 29.200000
-2	chris	 -1.300000
+	     0	         1
+	(utf8)	  (double)
+0	alice 	 10.100000
+1	bob   	 29.200000
+2	chris 	 -1.300000
       TABLE
     end
 
     test("Pathname: with header") do
       path = fixture_path("with-header-float.csv")
       assert_equal(<<-TABLE, load_csv(path).to_s)
-	name	     score
-0	alice	 10.100000
-1	bob 	 29.200000
-2	chris	 -1.300000
+	  name	     score
+	(utf8)	  (double)
+0	alice 	 10.100000
+1	bob   	 29.200000
+2	chris 	 -1.300000
       TABLE
     end
 
     test("Pathname: without header") do
       path = fixture_path("without-header-float.csv")
       assert_equal(<<-TABLE, load_csv(path).to_s)
-	0	         1
-0	alice	 10.100000
-1	bob	 29.200000
-2	chris	 -1.300000
+	     0	         1
+	(utf8)	  (double)
+0	alice 	 10.100000
+1	bob   	 29.200000
+2	chris 	 -1.300000
       TABLE
     end
 
     test("null: with double quote") do
       path = fixture_path("null-with-double-quote.csv").to_s
       assert_equal(<<-TABLE, load_csv(path).to_s)
-	name	 score
-0	alice	    10
-1	bob 	(null)
-2	chris	    -1
+	  name	 score
+	(utf8)	(int8)
+0	alice 	    10
+1	bob   	(null)
+2	chris 	    -1
       TABLE
     end
 
     test("null: without double quote") do
       path = fixture_path("null-without-double-quote.csv").to_s
       assert_equal(<<-TABLE, load_csv(path).to_s)
-	name	 score
-0	alice	    10
-1	bob 	(null)
-2	chris	    -1
+	  name	 score
+	(utf8)	(int8)
+0	alice 	    10
+1	bob   	(null)
+2	chris 	    -1
       TABLE
     end
 
diff --git a/ruby/red-arrow/test/test-group.rb b/ruby/red-arrow/test/test-group.rb
index 68e927df69..f4831289ed 100644
--- a/ruby/red-arrow/test/test-group.rb
+++ b/ruby/red-arrow/test/test-group.rb
@@ -43,6 +43,7 @@ class GroupTest < Test::Unit::TestCase
       table = Arrow::Table.new(raw_table)
       assert_equal(<<-TABLE, table.group(:time).count.to_s)
 	                     time	count(int)
+	              (timestamp)	   (int64)
 0	#{time_values[0].iso8601}	         1
 1	#{time_values[1].iso8601}	         1
       TABLE
@@ -53,6 +54,7 @@ class GroupTest < Test::Unit::TestCase
     test("single") do
       assert_equal(<<-TABLE, @table.group(:group_key1).count.to_s)
 	group_key1	count(group_key2)	count(int)	count(uint)	count(float)	count(string)
+	   (uint8)	          (int64)	   (int64)	    (int64)	     (int64)	      (int64)
 0	         1	                2	         2	          1	           1	            2
 1	         2	                1	         0	          1	           1	            1
 2	         3	                3	         3	          3	           3	            2
@@ -62,6 +64,7 @@ class GroupTest < Test::Unit::TestCase
     test("multiple") do
       assert_equal(<<-TABLE, @table.group(:group_key1, :group_key2).count.to_s)
 	group_key1	group_key2	count(int)	count(uint)	count(float)	count(string)
+	   (uint8)	   (uint8)	   (int64)	    (int64)	     (int64)	      (int64)
 0	         1	         1	         2	          1	           1	            2
 1	         2	         1	         0	          1	           1	            1
 2	         3	         1	         1	          1	           1	            0
@@ -73,6 +76,7 @@ class GroupTest < Test::Unit::TestCase
       group = @table.group(:group_key1, :group_key2)
       assert_equal(<<-TABLE, group.count(:int, :uint).to_s)
 	group_key1	group_key2	count(int)	count(uint)
+	   (uint8)	   (uint8)	   (int64)	    (int64)
 0	         1	         1	         2	          1
 1	         2	         1	         0	          1
 2	         3	         1	         1	          1
@@ -85,6 +89,7 @@ class GroupTest < Test::Unit::TestCase
     test("single") do
       assert_equal(<<-TABLE, @table.group(:group_key1).sum.to_s)
 	group_key1	sum(group_key2)	sum(int)	sum(uint)	sum(float)
+	   (uint8)	       (uint64)	 (int64)	 (uint64)	  (double)
 0	         1	              2	      -3	        1	  2.200000
 1	         2	              1	  (null)	        3	  3.300000
 2	         3	              5	     -15	       15	 16.500000
@@ -94,6 +99,7 @@ class GroupTest < Test::Unit::TestCase
     test("multiple") do
       assert_equal(<<-TABLE, @table.group(:group_key1, :group_key2).sum.to_s)
 	group_key1	group_key2	sum(int)	sum(uint)	sum(float)
+	   (uint8)	   (uint8)	 (int64)	 (uint64)	  (double)
 0	         1	         1	      -3	        1	  2.200000
 1	         2	         1	  (null)	        3	  3.300000
 2	         3	         1	      -4	        4	  4.400000
@@ -106,6 +112,7 @@ class GroupTest < Test::Unit::TestCase
     test("single") do
       assert_equal(<<-TABLE, @table.group(:group_key1).mean.to_s)
 	group_key1	mean(group_key2)	 mean(int)	mean(uint)	mean(float)
+	   (uint8)	        (double)	  (double)	  (double)	   (double)
 0	         1	        1.000000	 -1.500000	  1.000000	   2.200000
 1	         2	        1.000000	    (null)	  3.000000	   3.300000
 2	         3	        1.666667	 -5.000000	  5.000000	   5.500000
@@ -115,6 +122,7 @@ class GroupTest < Test::Unit::TestCase
     test("multiple") do
       assert_equal(<<-TABLE, @table.group(:group_key1, :group_key2).mean.to_s)
 	group_key1	group_key2	 mean(int)	mean(uint)	mean(float)
+	   (uint8)	   (uint8)	  (double)	  (double)	   (double)
 0	         1	         1	 -1.500000	  1.000000	   2.200000
 1	         2	         1	    (null)	  3.000000	   3.300000
 2	         3	         1	 -4.000000	  4.000000	   4.400000
@@ -127,6 +135,7 @@ class GroupTest < Test::Unit::TestCase
     test("single") do
       assert_equal(<<-TABLE, @table.group(:group_key1).min.to_s)
 	group_key1	min(group_key2)	min(int)	min(uint)	min(float)
+	   (uint8)	        (uint8)	 (int32)	 (uint32)	   (float)
 0	         1	              1	      -2	        1	  2.200000
 1	         2	              1	  (null)	        3	  3.300000
 2	         3	              1	      -6	        4	  4.400000
@@ -136,6 +145,7 @@ class GroupTest < Test::Unit::TestCase
     test("multiple") do
       assert_equal(<<-TABLE, @table.group(:group_key1, :group_key2).min.to_s)
 	group_key1	group_key2	min(int)	min(uint)	min(float)
+	   (uint8)	   (uint8)	 (int32)	 (uint32)	   (float)
 0	         1	         1	      -2	        1	  2.200000
 1	         2	         1	  (null)	        3	  3.300000
 2	         3	         1	      -4	        4	  4.400000
@@ -148,6 +158,7 @@ class GroupTest < Test::Unit::TestCase
     test("single") do
       assert_equal(<<-TABLE, @table.group(:group_key1).max.to_s)
 	group_key1	max(group_key2)	max(int)	max(uint)	max(float)
+	   (uint8)	        (uint8)	 (int32)	 (uint32)	   (float)
 0	         1	              1	      -1	        1	  2.200000
 1	         2	              1	  (null)	        3	  3.300000
 2	         3	              2	      -4	        6	  6.600000
@@ -157,6 +168,7 @@ class GroupTest < Test::Unit::TestCase
     test("multiple") do
       assert_equal(<<-TABLE, @table.group(:group_key1, :group_key2).max.to_s)
 	group_key1	group_key2	max(int)	max(uint)	max(float)
+	   (uint8)	   (uint8)	 (int32)	 (uint32)	   (float)
 0	         1	         1	      -1	        1	  2.200000
 1	         2	         1	  (null)	        3	  3.300000
 2	         3	         1	      -4	        4	  4.400000
@@ -170,6 +182,7 @@ class GroupTest < Test::Unit::TestCase
       group = @table.group(:group_key1, :group_key2)
       assert_equal(<<-TABLE, group.aggregate("count(int)", "sum(uint)").to_s)
 	group_key1	group_key2	count(int)	sum(uint)
+	   (uint8)	   (uint8)	   (int64)	 (uint64)
 0	         1	         1	         2	        1
 1	         2	         1	         0	        3
 2	         3	         1	         1	        4
diff --git a/ruby/red-arrow/test/test-schema.rb b/ruby/red-arrow/test/test-schema.rb
index 20d73b2726..c4164d8390 100644
--- a/ruby/red-arrow/test/test-schema.rb
+++ b/ruby/red-arrow/test/test-schema.rb
@@ -95,7 +95,7 @@ class SchemaTest < Test::Unit::TestCase
 
       test("[invalid]") do
         invalid = []
-        message = "field name or index must be String, Symbol or Integer"
+        message = +"field name or index must be String, Symbol or Integer"
         message << ": <#{invalid.inspect}>"
         assert_raise(ArgumentError.new(message)) do
           @schema[invalid]
diff --git a/ruby/red-arrow/test/test-slicer.rb b/ruby/red-arrow/test/test-slicer.rb
index d33748a387..89cf34b0d1 100644
--- a/ruby/red-arrow/test/test-slicer.rb
+++ b/ruby/red-arrow/test/test-slicer.rb
@@ -45,11 +45,12 @@ class SlicerTest < Test::Unit::TestCase
         slicer.visible
       end
       assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    1	true   
-1	    8	true   
-2	   16	true   
-3	  256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       1	true   
+1	       8	true   
+2	      16	true   
+3	     256	true   
       TABLE
     end
 
@@ -58,15 +59,16 @@ class SlicerTest < Test::Unit::TestCase
         slicer.count
       end
       assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    1	true   
-1	    2	false  
-2	    4	 (null)
-3	    8	true   
-4	   16	true   
-5	   32	false  
-6	   64	 (null)
-7	  256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       1	true   
+1	       2	false  
+2	       4	 (null)
+3	       8	true   
+4	      16	true   
+5	      32	false  
+6	      64	 (null)
+7	     256	true   
       TABLE
     end
   end
@@ -77,9 +79,10 @@ class SlicerTest < Test::Unit::TestCase
         !slicer.visible
       end
       assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    2	false  
-1	   32	false  
+	   count	visible
+	(uint32)	 (bool)
+0	       2	false  
+1	      32	false  
       TABLE
     end
 
@@ -88,8 +91,9 @@ class SlicerTest < Test::Unit::TestCase
         !slicer.count
       end
       assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    0	 (null)
+	   count	visible
+	(uint32)	 (bool)
+0	       0	 (null)
       TABLE
     end
   end
@@ -99,11 +103,12 @@ class SlicerTest < Test::Unit::TestCase
       slicer.visible.null?
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	 count	visible
-0	     0	 (null)
-1	     4	 (null)
-2	    64	 (null)
-3	(null)	 (null)
+	   count	visible
+	(uint32)	 (bool)
+0	       0	 (null)
+1	       4	 (null)
+2	      64	 (null)
+3	  (null)	 (null)
     TABLE
   end
 
@@ -112,13 +117,14 @@ class SlicerTest < Test::Unit::TestCase
       slicer.visible.valid?
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    1	true   
-1	    2	false  
-2	    8	true   
-3	   16	true   
-4	   32	false  
-5	  256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       1	true   
+1	       2	false  
+2	       8	true   
+3	      16	true   
+4	      32	false  
+5	     256	true   
     TABLE
   end
 
@@ -128,11 +134,12 @@ class SlicerTest < Test::Unit::TestCase
         slicer.visible == nil
       end
       assert_equal(<<-TABLE, sliced_table.to_s)
-	 count	visible
-0	     0	 (null)
-1	     4	 (null)
-2	    64	 (null)
-3	(null)	 (null)
+	   count	visible
+	(uint32)	 (bool)
+0	       0	 (null)
+1	       4	 (null)
+2	      64	 (null)
+3	  (null)	 (null)
       TABLE
     end
 
@@ -141,11 +148,12 @@ class SlicerTest < Test::Unit::TestCase
         slicer.visible == true
       end
       assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    1	true   
-1	    8	true   
-2	   16	true   
-3	  256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       1	true   
+1	       8	true   
+2	      16	true   
+3	     256	true   
       TABLE
     end
   end
@@ -156,13 +164,14 @@ class SlicerTest < Test::Unit::TestCase
         !(slicer.visible == nil)
       end
       assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    1	true   
-1	    2	false  
-2	    8	true   
-3	   16	true   
-4	   32	false  
-5	  256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       1	true   
+1	       2	false  
+2	       8	true   
+3	      16	true   
+4	      32	false  
+5	     256	true   
       TABLE
     end
 
@@ -171,9 +180,10 @@ class SlicerTest < Test::Unit::TestCase
         !(slicer.visible == true)
       end
       assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    2	false  
-1	   32	false  
+	   count	visible
+	(uint32)	 (bool)
+0	       2	false  
+1	      32	false  
       TABLE
     end
   end
@@ -184,13 +194,14 @@ class SlicerTest < Test::Unit::TestCase
         slicer.visible != nil
       end
       assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    1	true   
-1	    2	false  
-2	    8	true   
-3	   16	true   
-4	   32	false  
-5	  256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       1	true   
+1	       2	false  
+2	       8	true   
+3	      16	true   
+4	      32	false  
+5	     256	true   
       TABLE
     end
 
@@ -199,9 +210,10 @@ class SlicerTest < Test::Unit::TestCase
         slicer.visible != true
       end
       assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    2	false  
-1	   32	false  
+	   count	visible
+	(uint32)	 (bool)
+0	       2	false  
+1	      32	false  
       TABLE
     end
   end
@@ -211,12 +223,13 @@ class SlicerTest < Test::Unit::TestCase
       slicer.count < 16
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    0	 (null)
-1	    1	true   
-2	    2	false  
-3	    4	 (null)
-4	    8	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       0	 (null)
+1	       1	true   
+2	       2	false  
+3	       4	 (null)
+4	       8	true   
     TABLE
   end
 
@@ -225,11 +238,12 @@ class SlicerTest < Test::Unit::TestCase
       !(slicer.count < 16)
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	   16	true   
-1	   32	false  
-2	   64	 (null)
-3	  256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	      16	true   
+1	      32	false  
+2	      64	 (null)
+3	     256	true   
     TABLE
   end
 
@@ -238,13 +252,14 @@ class SlicerTest < Test::Unit::TestCase
       slicer.count <= 16
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    0	 (null)
-1	    1	true   
-2	    2	false  
-3	    4	 (null)
-4	    8	true   
-5	   16	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       0	 (null)
+1	       1	true   
+2	       2	false  
+3	       4	 (null)
+4	       8	true   
+5	      16	true   
     TABLE
   end
 
@@ -253,10 +268,11 @@ class SlicerTest < Test::Unit::TestCase
       !(slicer.count <= 16)
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	   32	false  
-1	   64	 (null)
-2	  256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	      32	false  
+1	      64	 (null)
+2	     256	true   
     TABLE
   end
 
@@ -265,10 +281,11 @@ class SlicerTest < Test::Unit::TestCase
       slicer.count > 16
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	   32	false  
-1	   64	 (null)
-2	  256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	      32	false  
+1	      64	 (null)
+2	     256	true   
     TABLE
   end
 
@@ -277,13 +294,14 @@ class SlicerTest < Test::Unit::TestCase
       !(slicer.count > 16)
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    0	 (null)
-1	    1	true   
-2	    2	false  
-3	    4	 (null)
-4	    8	true   
-5	   16	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       0	 (null)
+1	       1	true   
+2	       2	false  
+3	       4	 (null)
+4	       8	true   
+5	      16	true   
     TABLE
   end
 
@@ -292,11 +310,12 @@ class SlicerTest < Test::Unit::TestCase
       slicer.count >= 16
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	   16	true   
-1	   32	false  
-2	   64	 (null)
-3	  256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	      16	true   
+1	      32	false  
+2	      64	 (null)
+3	     256	true   
     TABLE
   end
 
@@ -305,12 +324,13 @@ class SlicerTest < Test::Unit::TestCase
       !(slicer.count >= 16)
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    0	 (null)
-1	    1	true   
-2	    2	false  
-3	    4	 (null)
-4	    8	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       0	 (null)
+1	       1	true   
+2	       2	false  
+3	       4	 (null)
+4	       8	true   
     TABLE
   end
 
@@ -319,11 +339,12 @@ class SlicerTest < Test::Unit::TestCase
       slicer.count.in?([1, 4, 16, 64])
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    1	true   
-1	    4	 (null)
-2	   16	true   
-3	   64	 (null)
+	   count	visible
+	(uint32)	 (bool)
+0	       1	true   
+1	       4	 (null)
+2	      16	true   
+3	      64	 (null)
     TABLE
   end
 
@@ -332,13 +353,14 @@ class SlicerTest < Test::Unit::TestCase
       !slicer.count.in?([1, 4, 16, 64])
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	 count	visible
-0	     0	 (null)
-1	     2	false  
-2	     8	true   
-3	    32	false  
-4	(null)	 (null)
-5	   256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       0	 (null)
+1	       2	false  
+2	       8	true   
+3	      32	false  
+4	  (null)	 (null)
+5	     256	true   
     TABLE
   end
 
@@ -347,9 +369,10 @@ class SlicerTest < Test::Unit::TestCase
       slicer.visible & (slicer.count >= 16)
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	   16	true   
-1	  256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	      16	true   
+1	     256	true   
     TABLE
   end
 
@@ -358,12 +381,13 @@ class SlicerTest < Test::Unit::TestCase
       slicer.visible | (slicer.count >= 16)
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    1	true   
-1	    8	true   
-2	   16	true   
-3	   32	false  
-4	  256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       1	true   
+1	       8	true   
+2	      16	true   
+3	      32	false  
+4	     256	true   
     TABLE
   end
 
@@ -372,10 +396,11 @@ class SlicerTest < Test::Unit::TestCase
       slicer.visible ^ (slicer.count >= 16)
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    1	true   
-1	    8	true   
-2	   32	false  
+	   count	visible
+	(uint32)	 (bool)
+0	       1	true   
+1	       8	true   
+2	      32	false  
     TABLE
   end
 
@@ -386,15 +411,16 @@ class SlicerTest < Test::Unit::TestCase
       end
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	 count	visible
-0	     0	 (null)
-1	     1	true   
-2	     4	 (null)
-3	     8	true   
-4	    16	true   
-5	    64	 (null)
-6	(null)	 (null)
-7	   256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       0	 (null)
+1	       1	true   
+2	       4	 (null)
+3	       8	true   
+4	      16	true   
+5	      64	 (null)
+6	  (null)	 (null)
+7	     256	true   
     TABLE
   end
 
@@ -405,9 +431,10 @@ class SlicerTest < Test::Unit::TestCase
       end
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    2	false  
-1	   32	false  
+	   count	visible
+	(uint32)	 (bool)
+0	       2	false  
+1	      32	false  
     TABLE
   end
 
@@ -418,9 +445,10 @@ class SlicerTest < Test::Unit::TestCase
       end
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	count	visible
-0	    2	false  
-1	   32	false  
+	   count	visible
+	(uint32)	 (bool)
+0	       2	false  
+1	      32	false  
     TABLE
   end
 
@@ -431,15 +459,16 @@ class SlicerTest < Test::Unit::TestCase
       end
     end
     assert_equal(<<-TABLE, sliced_table.to_s)
-	 count	visible
-0	     0	 (null)
-1	     1	true   
-2	     4	 (null)
-3	     8	true   
-4	    16	true   
-5	    64	 (null)
-6	(null)	 (null)
-7	   256	true   
+	   count	visible
+	(uint32)	 (bool)
+0	       0	 (null)
+1	       1	true   
+2	       4	 (null)
+3	       8	true   
+4	      16	true   
+5	      64	 (null)
+6	  (null)	 (null)
+7	     256	true   
     TABLE
   end
 
@@ -456,6 +485,7 @@ class SlicerTest < Test::Unit::TestCase
       end
       assert_equal(<<~TABLE, sliced_table.to_s)
 	string
+	(utf8)
 0	Arrow 
 1	window
       TABLE
@@ -467,6 +497,7 @@ class SlicerTest < Test::Unit::TestCase
       end
       assert_equal(<<~TABLE, sliced_table.to_s)
 	string
+	(utf8)
 0	array 
 1	Arrow 
       TABLE
@@ -478,6 +509,7 @@ class SlicerTest < Test::Unit::TestCase
       end
       assert_equal(<<~TABLE, sliced_table.to_s)
 	string
+	(utf8)
 0	array 
 1	carrot
       TABLE
@@ -489,6 +521,7 @@ class SlicerTest < Test::Unit::TestCase
       end
       assert_equal(<<~TABLE, sliced_table.to_s)
 	string
+	(utf8)
 0	array 
 1	Arrow 
 2	carrot
@@ -501,6 +534,7 @@ class SlicerTest < Test::Unit::TestCase
       end
       assert_equal(<<~TABLE, sliced_table.to_s)
 	string
+	(utf8)
 0	Arrow 
 1	window
       TABLE
@@ -512,6 +546,7 @@ class SlicerTest < Test::Unit::TestCase
       end
       assert_equal(<<~TABLE, sliced_table.to_s)
 	string
+	(utf8)
 0	Arrow 
 1	window
       TABLE
@@ -523,6 +558,7 @@ class SlicerTest < Test::Unit::TestCase
       end
       assert_equal(<<~TABLE, sliced_table.to_s)
 	string
+	(utf8)
 0	array 
 1	Arrow 
 2	carrot
@@ -545,6 +581,7 @@ class SlicerTest < Test::Unit::TestCase
       end
       assert_equal(<<~TABLE, sliced_table.to_s)
 	string
+	(utf8)
 0	carrot
       TABLE
     end
diff --git a/ruby/red-arrow/test/test-struct-data-type.rb b/ruby/red-arrow/test/test-struct-data-type.rb
index d106e38b1d..9bf9a17dd6 100644
--- a/ruby/red-arrow/test/test-struct-data-type.rb
+++ b/ruby/red-arrow/test/test-struct-data-type.rb
@@ -101,7 +101,7 @@ class StructDataTypeTest < Test::Unit::TestCase
 
       test("[invalid]") do
         invalid = []
-        message = "field name or index must be String, Symbol or Integer"
+        message = +"field name or index must be String, Symbol or Integer"
         message << ": <#{invalid.inspect}>"
         assert_raise(ArgumentError.new(message)) do
           @data_type[invalid]
diff --git a/ruby/red-arrow/test/test-table.rb b/ruby/red-arrow/test/test-table.rb
index 883cf70c26..a69e926156 100644
--- a/ruby/red-arrow/test/test-table.rb
+++ b/ruby/red-arrow/test/test-table.rb
@@ -87,24 +87,26 @@ class TableTest < Test::Unit::TestCase
       target_rows_raw = [nil, true, true, false, true, false, true, true]
       target_rows = Arrow::BooleanArray.new(target_rows_raw)
       assert_equal(<<-TABLE, @table.slice(target_rows).to_s)
-	count	visible
-0	    2	false  
-1	    4	 (null)
-2	   16	true   
-3	   64	 (null)
-4	  128	 (null)
+	  count	visible
+	(uint8)	 (bool)
+0	      2	false  
+1	      4	 (null)
+2	     16	true   
+3	     64	 (null)
+4	    128	 (null)
       TABLE
     end
 
     test("Array: boolean") do
       target_rows_raw = [nil, true, true, false, true, false, true, true]
       assert_equal(<<-TABLE, @table.slice(target_rows_raw).to_s)
-	count	visible
-0	    2	false  
-1	    4	 (null)
-2	   16	true   
-3	   64	 (null)
-4	  128	 (null)
+	  count	visible
+	(uint8)	 (bool)
+0	      2	false  
+1	      4	 (null)
+2	     16	true   
+3	     64	 (null)
+4	    128	 (null)
       TABLE
     end
 
@@ -131,83 +133,93 @@ class TableTest < Test::Unit::TestCase
 
     test("Range: positive: include end") do
       assert_equal(<<-TABLE, @table.slice(2..4).to_s)
-	count	visible
-0	    4	 (null)
-1	    8	true   
-2	   16	true   
+	  count	visible
+	(uint8)	 (bool)
+0	      4	 (null)
+1	      8	true   
+2	     16	true   
       TABLE
     end
 
     test("Range: positive: exclude end") do
       assert_equal(<<-TABLE, @table.slice(2...4).to_s)
-	count	visible
-0	    4	 (null)
-1	    8	true   
+	  count	visible
+	(uint8)	 (bool)
+0	      4	 (null)
+1	      8	true   
       TABLE
     end
 
     test("Range: negative: include end") do
       assert_equal(<<-TABLE, @table.slice(-4..-2).to_s)
-	count	visible
-0	   16	true   
-1	   32	false  
-2	   64	 (null)
+	  count	visible
+	(uint8)	 (bool)
+0	     16	true   
+1	     32	false  
+2	     64	 (null)
       TABLE
     end
 
     test("Range: negative: exclude end") do
       assert_equal(<<-TABLE, @table.slice(-4...-2).to_s)
-	count	visible
-0	   16	true   
-1	   32	false  
+	  count	visible
+	(uint8)	 (bool)
+0	     16	true   
+1	     32	false  
       TABLE
     end
 
     test("[from, to]: positive") do
       assert_equal(<<-TABLE, @table.slice(0, 2).to_s)
-	count	visible
-0	    1	true   
-1	    2	false  
+	  count	visible
+	(uint8)	 (bool)
+0	      1	true   
+1	      2	false  
       TABLE
     end
 
     test("[from, to]: negative") do
       assert_equal(<<-TABLE, @table.slice(-4, 2).to_s)
-	count	visible
-0	   16	true   
-1	   32	false  
+	  count	visible
+	(uint8)	 (bool)
+0	     16	true   
+1	     32	false  
       TABLE
     end
 
     test("{key: Number}") do
       assert_equal(<<-TABLE, @table.slice(count: 16).to_s)
-	count	visible
-0	   16	true   
+	  count	visible
+	(uint8)	 (bool)
+0	     16	true   
       TABLE
     end
 
     test("{key: String}") do
       table = Arrow::Table.new(name: Arrow::StringArray.new(["a", "b", "c"]))
       assert_equal(<<-TABLE, table.slice(name: 'b').to_s)
-	name
-0	b   
+	  name
+	(utf8)
+0	b     
       TABLE
     end
 
     test("{key: true}") do
       assert_equal(<<-TABLE, @table.slice(visible: true).to_s)
-	count	visible
-0	    1	true   
-1	    8	true   
-2	   16	true   
+	  count	visible
+	(uint8)	 (bool)
+0	      1	true   
+1	      8	true   
+2	     16	true   
       TABLE
     end
 
     test("{key: false}") do
       assert_equal(<<-TABLE, @table.slice(visible: false).to_s)
-	count	visible
-0	    2	false  
-1	   32	false  
+	  count	visible
+	(uint8)	 (bool)
+0	      2	false  
+1	     32	false  
       TABLE
     end
 
@@ -218,11 +230,12 @@ class TableTest < Test::Unit::TestCase
         omit("beginless range isn't supported")
       end
       assert_equal(<<-TABLE, @table.slice(count: range).to_s)
-	count	visible
-0	    1	true   
-1	    2	false  
-2	    4	 (null)
-3	    8	true   
+	  count	visible
+	(uint8)	 (bool)
+0	      1	true   
+1	      2	false  
+2	      4	 (null)
+3	      8	true   
       TABLE
     end
 
@@ -233,10 +246,11 @@ class TableTest < Test::Unit::TestCase
         omit("beginless range isn't supported")
       end
       assert_equal(<<-TABLE, @table.slice(count: range).to_s)
-	count	visible
-0	    1	true   
-1	    2	false  
-2	    4	 (null)
+	  count	visible
+	(uint8)	 (bool)
+0	      1	true   
+1	      2	false  
+2	      4	 (null)
       TABLE
     end
 
@@ -247,39 +261,43 @@ class TableTest < Test::Unit::TestCase
         omit("endless range isn't supported")
       end
       assert_equal(<<-TABLE, @table.slice(count: range).to_s)
-	count	visible
-0	   16	true   
-1	   32	false  
-2	   64	 (null)
-3	  128	 (null)
+	  count	visible
+	(uint8)	 (bool)
+0	     16	true   
+1	     32	false  
+2	     64	 (null)
+3	    128	 (null)
       TABLE
     end
 
     test("{key: Range}: include end") do
       assert_equal(<<-TABLE, @table.slice(count: 1..16).to_s)
-	count	visible
-0	    1	true   
-1	    2	false  
-2	    4	 (null)
-3	    8	true   
-4	   16	true   
+	  count	visible
+	(uint8)	 (bool)
+0	      1	true   
+1	      2	false  
+2	      4	 (null)
+3	      8	true   
+4	     16	true   
       TABLE
     end
 
     test("{key: Range}: exclude end") do
       assert_equal(<<-TABLE, @table.slice(count: 1...16).to_s)
-	count	visible
-0	    1	true   
-1	    2	false  
-2	    4	 (null)
-3	    8	true   
+	  count	visible
+	(uint8)	 (bool)
+0	      1	true   
+1	      2	false  
+2	      4	 (null)
+3	      8	true   
       TABLE
     end
 
     test("{key1: Range, key2: true}") do
       assert_equal(<<-TABLE, @table.slice(count: 0..8, visible: false).to_s)
-	count	visible
-0	    2	false  
+	  count	visible
+	(uint8)	 (bool)
+0	      2	false  
       TABLE
     end
 
@@ -372,44 +390,47 @@ class TableTest < Test::Unit::TestCase
       test("add") do
         name_array = Arrow::StringArray.new(["a", "b", "c", "d", "e", "f", "g", "h"])
         assert_equal(<<-TABLE, @table.merge(:name => name_array).to_s)
-	count	visible	name
-0	    1	true   	a   
-1	    2	false  	b   
-2	    4	 (null)	c   
-3	    8	true   	d   
-4	   16	true   	e   
-5	   32	false  	f   
-6	   64	 (null)	g   
-7	  128	 (null)	h   
+	  count	visible	  name
+	(uint8)	 (bool)	(utf8)
+0	      1	true   	a     
+1	      2	false  	b     
+2	      4	 (null)	c     
+3	      8	true   	d     
+4	     16	true   	e     
+5	     32	false  	f     
+6	     64	 (null)	g     
+7	    128	 (null)	h     
         TABLE
       end
 
       test("remove") do
         assert_equal(<<-TABLE, @table.merge(:visible => nil).to_s)
-	count
-0	    1
-1	    2
-2	    4
-3	    8
-4	   16
-5	   32
-6	   64
-7	  128
+	  count
+	(uint8)
+0	      1
+1	      2
+2	      4
+3	      8
+4	     16
+5	     32
+6	     64
+7	    128
         TABLE
       end
 
       test("replace") do
         visible_array = Arrow::Int32Array.new([1] * @visible_array.length)
         assert_equal(<<-TABLE, @table.merge(:visible => visible_array).to_s)
-	count	visible
-0	    1	      1
-1	    2	      1
-2	    4	      1
-3	    8	      1
-4	   16	      1
-5	   32	      1
-6	   64	      1
-7	  128	      1
+	  count	visible
+	(uint8)	(int32)
+0	      1	      1
+1	      2	      1
+2	      4	      1
+3	      8	      1
+4	     16	      1
+5	     32	      1
+6	     64	      1
+7	    128	      1
         TABLE
       end
     end
@@ -419,15 +440,16 @@ class TableTest < Test::Unit::TestCase
         name_array = Arrow::StringArray.new(["a", "b", "c", "d", "e", "f", "g", "h"])
         table = Arrow::Table.new("name" => name_array)
         assert_equal(<<-TABLE, @table.merge(table).to_s)
-	count	visible	name
-0	    1	true   	a   
-1	    2	false  	b   
-2	    4	 (null)	c   
-3	    8	true   	d   
-4	   16	true   	e   
-5	   32	false  	f   
-6	   64	 (null)	g   
-7	  128	 (null)	h   
+	  count	visible	  name
+	(uint8)	 (bool)	(utf8)
+0	      1	true   	a     
+1	      2	false  	b     
+2	      4	 (null)	c     
+3	      8	true   	d     
+4	     16	true   	e     
+5	     32	false  	f     
+6	     64	 (null)	g     
+7	    128	 (null)	h     
         TABLE
       end
 
@@ -435,15 +457,16 @@ class TableTest < Test::Unit::TestCase
         visible_array = Arrow::Int32Array.new([1] * @visible_array.length)
         table = Arrow::Table.new("visible" => visible_array)
         assert_equal(<<-TABLE, @table.merge(table).to_s)
-	count	visible
-0	    1	      1
-1	    2	      1
-2	    4	      1
-3	    8	      1
-4	   16	      1
-5	   32	      1
-6	   64	      1
-7	  128	      1
+	  count	visible
+	(uint8)	(int32)
+0	      1	      1
+1	      2	      1
+2	      4	      1
+3	      8	      1
+4	     16	      1
+5	     32	      1
+6	     64	      1
+7	    128	      1
         TABLE
       end
     end
@@ -457,29 +480,31 @@ class TableTest < Test::Unit::TestCase
   sub_test_case("#remove_column") do
     test("String") do
       assert_equal(<<-TABLE, @table.remove_column("visible").to_s)
-	count
-0	    1
-1	    2
-2	    4
-3	    8
-4	   16
-5	   32
-6	   64
-7	  128
+	  count
+	(uint8)
+0	      1
+1	      2
+2	      4
+3	      8
+4	     16
+5	     32
+6	     64
+7	    128
       TABLE
     end
 
     test("Symbol") do
       assert_equal(<<-TABLE, @table.remove_column(:visible).to_s)
-	count
-0	    1
-1	    2
-2	    4
-3	    8
-4	   16
-5	   32
-6	   64
-7	  128
+	  count
+	(uint8)
+0	      1
+1	      2
+2	      4
+3	      8
+4	     16
+5	     32
+6	     64
+7	    128
       TABLE
     end
 
@@ -491,29 +516,31 @@ class TableTest < Test::Unit::TestCase
 
     test("Integer") do
       assert_equal(<<-TABLE, @table.remove_column(1).to_s)
-	count
-0	    1
-1	    2
-2	    4
-3	    8
-4	   16
-5	   32
-6	   64
-7	  128
+	  count
+	(uint8)
+0	      1
+1	      2
+2	      4
+3	      8
+4	     16
+5	     32
+6	     64
+7	    128
       TABLE
     end
 
     test("negative integer") do
       assert_equal(<<-TABLE, @table.remove_column(-1).to_s)
-	count
-0	    1
-1	    2
-2	    4
-3	    8
-4	   16
-5	   32
-6	   64
-7	  128
+	  count
+	(uint8)
+0	      1
+1	      2
+2	      4
+3	      8
+4	     16
+5	     32
+6	     64
+7	    128
       TABLE
     end
 
@@ -544,29 +571,33 @@ class TableTest < Test::Unit::TestCase
 
     test("names") do
       assert_equal(<<-TABLE, @table.select_columns(:c, :a).to_s)
-	c	a
-0	1	1
+	      c	      a
+	(uint8)	(uint8)
+0	      1	      1
       TABLE
     end
 
     test("range") do
       assert_equal(<<-TABLE, @table.select_columns(2...4).to_s)
-	c	d
-0	1	1
+	      c	      d
+	(uint8)	(uint8)
+0	      1	      1
       TABLE
     end
 
     test("indexes") do
       assert_equal(<<-TABLE, @table.select_columns(0, -1, 2).to_s)
-	a	e	c
-0	1	1	1
+	      a	      e	      c
+	(uint8)	(uint8)	(uint8)
+0	      1	      1	      1
       TABLE
     end
 
     test("mixed") do
       assert_equal(<<-TABLE, @table.select_columns(:a, -1, 2..3).to_s)
-	a	e	c	d
-0	1	1	1	1
+	      a	      e	      c	      d
+	(uint8)	(uint8)	(uint8)	(uint8)
+0	      1	      1	      1	      1
       TABLE
     end
 
@@ -575,8 +606,9 @@ class TableTest < Test::Unit::TestCase
         column.name == "a" or i.odd?
       end
       assert_equal(<<-TABLE, selected_table.to_s)
-	a	b	d
-0	1	1	1
+	      a	      b	      d
+	(uint8)	(uint8)	(uint8)
+0	      1	      1	      1
       TABLE
     end
 
@@ -585,15 +617,17 @@ class TableTest < Test::Unit::TestCase
         column.name == "a"
       end
       assert_equal(<<-TABLE, selected_table.to_s)
-	a
-0	1
+	      a
+	(uint8)
+0	      1
       TABLE
     end
 
     test("empty result") do
       selected_table = @table.filter([false] * @table.size).select_columns(:a)
       assert_equal(<<-TABLE, selected_table.to_s)
-	a
+	      a
+	(uint8)
       TABLE
     end
   end
@@ -682,7 +716,7 @@ class TableTest < Test::Unit::TestCase
         output = create_output(".json")
         # TODO: Implement this.
         # @table.save(output, format: :json)
-        columns = ""
+        columns = +""
         @table.each_record.each do |record|
           column = {
             "count" => record.count,
@@ -789,10 +823,11 @@ class TableTest < Test::Unit::TestCase
             path = fixture_path("with-header.csv")
             table = Arrow::Table.load(path, skip_lines: /^\#/)
             assert_equal(<<-TABLE, table.to_s)
-	name	score
-0	alice	   10
-1	bob 	   29
-2	chris	   -1
+	  name	 score
+	(utf8)	(int8)
+0	alice 	    10
+1	bob   	    29
+2	chris 	    -1
             TABLE
           end
 
@@ -808,10 +843,11 @@ chris,-1
               CSV
             end
             assert_equal(<<-TABLE, Arrow::Table.load(file.path).to_s)
-	name	score
-0	alice	   10
-1	bob 	   29
-2	chris	   -1
+	  name	  score
+	(utf8)	(int64)
+0	alice 	     10
+1	bob   	     29
+2	chris 	     -1
             TABLE
           end
 
@@ -826,10 +862,11 @@ chris\t-1
             file.close
             table = Arrow::Table.load(file.path)
             assert_equal(<<-TABLE, table.to_s)
-	name	score
-0	alice	   10
-1	bob 	   29
-2	chris	   -1
+	  name	  score
+	(utf8)	(int64)
+0	alice 	     10
+1	bob   	     29
+2	chris 	     -1
             TABLE
           end
         end
@@ -881,7 +918,7 @@ chris\t-1
                          output.data.to_s,
                          content_type) do |port|
           input = URI("http://127.0.0.1:#{port}#{path}")
-          loaded_table = Arrow::Table.load(input)
+          loaded_table = Arrow::Table.load(input, schema: @table.schema)
           assert_equal(@table.to_s, loaded_table.to_s)
         end
       end
@@ -962,15 +999,16 @@ chris\t-1
     packed_table = @table.pack
     column_n_chunks = packed_table.columns.collect {|c| c.data.n_chunks}
     assert_equal([[1, 1], <<-TABLE], [column_n_chunks, packed_table.to_s])
-	count	visible
-0	    1	true   
-1	    2	false  
-2	    4	 (null)
-3	    8	true   
-4	   16	true   
-5	   32	false  
-6	   64	 (null)
-7	  128	 (null)
+	  count	visible
+	(uint8)	 (bool)
+0	      1	true   
+1	      2	false  
+2	      4	 (null)
+3	      8	true   
+4	     16	true   
+5	     32	false  
+6	     64	 (null)
+7	    128	 (null)
     TABLE
   end
 
@@ -1009,19 +1047,20 @@ visible:
       test(":list") do
         assert_equal(<<-TABLE, @table.to_s(format: :list))
 ==================== 0 ====================
-count: 1
-visible: true
+count(uint8): 1
+visible(bool): true
 ==================== 1 ====================
-count: 2
-visible: false
+count(uint8): 2
+visible(bool): false
         TABLE
       end
 
       test(":table") do
         assert_equal(<<-TABLE, @table.to_s(format: :table))
-	count	visible
-0	    1	true   
-1	    2	false  
+	  count	visible
+	(uint8)	 (bool)
+0	      1	true   
+1	      2	false  
         TABLE
       end
 
@@ -1033,6 +1072,35 @@ visible: false
       end
     end
 
+    sub_test_case(":show_column_type") do
+      def setup
+        columns = {
+          "count" => Arrow::UInt8Array.new([1, 2]),
+          "visible" => Arrow::BooleanArray.new([true, false]),
+        }
+        @table = Arrow::Table.new(columns)
+      end
+
+      test(":list") do
+        assert_equal(<<-TABLE, @table.to_s(format: :list, show_column_type: false))
+==================== 0 ====================
+count: 1
+visible: true
+==================== 1 ====================
+count: 2
+visible: false
+        TABLE
+      end
+
+      test(":table") do
+        assert_equal(<<-TABLE, @table.to_s(format: :table, show_column_type: false))
+	count	visible
+0	    1	true   
+1	    2	false  
+        TABLE
+      end
+    end
+
     sub_test_case("#==") do
       test("Arrow::Table") do
         assert do
@@ -1058,13 +1126,14 @@ visible: false
     test("Array: boolean") do
       filter = [nil, true, true, false, true, false, true, true]
       assert_equal(<<-TABLE, @table.filter(filter, @options).to_s)
-	 count	visible
-0	(null)	 (null)
-1	     2	false  
-2	     4	 (null)
-3	    16	true   
-4	    64	 (null)
-5	   128	 (null)
+	  count	visible
+	(uint8)	 (bool)
+0	 (null)	 (null)
+1	      2	false  
+2	      4	 (null)
+3	     16	true   
+4	     64	 (null)
+5	    128	 (null)
       TABLE
     end
 
@@ -1072,13 +1141,14 @@ visible: false
       array = [nil, true, true, false, true, false, true, true]
       filter = Arrow::BooleanArray.new(array)
       assert_equal(<<-TABLE, @table.filter(filter, @options).to_s)
-	 count	visible
-0	(null)	 (null)
-1	     2	false  
-2	     4	 (null)
-3	    16	true   
-4	    64	 (null)
-5	   128	 (null)
+	  count	visible
+	(uint8)	 (bool)
+0	 (null)	 (null)
+1	      2	false  
+2	      4	 (null)
+3	     16	true   
+4	     64	 (null)
+5	    128	 (null)
       TABLE
     end
 
@@ -1090,13 +1160,14 @@ visible: false
       ]
       filter = Arrow::ChunkedArray.new(filter_chunks)
       assert_equal(<<-TABLE, @table.filter(filter, @options).to_s)
-	 count	visible
-0	(null)	 (null)
-1	     2	false  
-2	     4	 (null)
-3	    16	true   
-4	    64	 (null)
-5	   128	 (null)
+	  count	visible
+	(uint8)	 (bool)
+0	 (null)	 (null)
+1	      2	false  
+2	      4	 (null)
+3	     16	true   
+4	     64	 (null)
+5	    128	 (null)
       TABLE
     end
   end
@@ -1105,20 +1176,22 @@ visible: false
     test("Arrow: boolean") do
       indices = [1, 0, 2]
       assert_equal(<<-TABLE, @table.take(indices).to_s)
-	count	visible
-0	    2	false  
-1	    1	true   
-2	    4	 (null)
+	  count	visible
+	(uint8)	 (bool)
+0	      2	false  
+1	      1	true   
+2	      4	 (null)
       TABLE
     end
 
     test("Arrow::Array") do
       indices = Arrow::Int16Array.new([1, 0, 2])
       assert_equal(<<-TABLE, @table.take(indices).to_s)
-	count	visible
-0	    2	false  
-1	    1	true   
-2	    4	 (null)
+	  count	visible
+	(uint8)	 (bool)
+0	      2	false  
+1	      1	true   
+2	      4	 (null)
       TABLE
     end
 
@@ -1129,10 +1202,11 @@ visible: false
       ]
       indices = Arrow::ChunkedArray.new(chunks)
       assert_equal(<<-TABLE, @table.take(indices).to_s)
-	count	visible
-0	    2	false  
-1	    1	true   
-2	    4	 (null)
+	  count	visible
+	(uint8)	 (bool)
+0	      2	false  
+1	      1	true   
+2	      4	 (null)
       TABLE
     end
   end
@@ -1144,9 +1218,10 @@ visible: false
       table2 = Arrow::Table.new(b: [false])
       concatenated = table1.concatenate([table2], unify_schemas: true)
       assert_equal(<<-TABLE, concatenated.to_s)
-	a	b
-0	true	false
-1	(null)	false
+	     a	     b
+	(bool)	(bool)
+0	true  	false 
+1	(null)	false 
       TABLE
     end
   end