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

pitrou 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 ee6ff0a1b6 GH-50660: [C++][Dev] Add Decimal32 and Decimal64 GDB 
pretty-printers (#50723)
ee6ff0a1b6 is described below

commit ee6ff0a1b6b1bceedcea868265b4b0965d0056d0
Author: fenfeng9 <[email protected]>
AuthorDate: Thu Jul 30 16:23:37 2026 +0800

    GH-50660: [C++][Dev] Add Decimal32 and Decimal64 GDB pretty-printers 
(#50723)
    
    ### Rationale for this change
    The Arrow GDB pretty-printers support `Decimal128` and `Decimal256`, but do 
not support `Decimal32` or `Decimal64`.
    
    ### What changes are included in this PR?
    * Add GDB pretty-printer support and tests for `Decimal32` and `Decimal64`.
    * Remove the unused `max_type_id` variable.
    
    ### Are these changes tested?
    Yes.
    
    ### Are there any user-facing changes?
    No.
    * GitHub Issue: #50660
    
    Authored-by: fenfeng9 <[email protected]>
    Signed-off-by: Antoine Pitrou <[email protected]>
---
 cpp/gdb_arrow.py                       | 35 +++++++++++----
 python/pyarrow/src/arrow/python/gdb.cc | 32 ++++++++++++++
 python/pyarrow/tests/test_gdb.py       | 79 ++++++++++++++++++++++++++++++++++
 3 files changed, 138 insertions(+), 8 deletions(-)

diff --git a/cpp/gdb_arrow.py b/cpp/gdb_arrow.py
index 7c95a7c72b..bab1fa8722 100644
--- a/cpp/gdb_arrow.py
+++ b/cpp/gdb_arrow.py
@@ -858,16 +858,19 @@ class MetadataPtr(Sequence):
         return self.md[i]
 
 
-DecimalTraits = namedtuple('DecimalTraits', ('bit_width', 'struct_format_le'))
+DecimalTraits = namedtuple(
+    'DecimalTraits', ('bit_width', 'struct_format_le', 'storage_member'))
 
 decimal_traits = {
-    128: DecimalTraits(128, 'Qq'),
-    256: DecimalTraits(256, 'QQQq'),
+    32: DecimalTraits(32, 'i', 'value_'),
+    64: DecimalTraits(64, 'q', 'value_'),
+    128: DecimalTraits(128, 'Qq', 'array_'),
+    256: DecimalTraits(256, 'QQQq', 'array_'),
 }
 
 class BaseDecimal:
     """
-    Base class for arrow::BasicDecimal{128,256...} values.
+    Base class for arrow::BasicDecimal{32,64,128,256...} values.
     """
 
     def __init__(self, address):
@@ -877,9 +880,9 @@ class BaseDecimal:
     def from_value(cls, val):
         """
         Create a decimal from a gdb.Value representing the corresponding
-        arrow::BasicDecimal{128,256...}.
+        arrow::BasicDecimal{32,64,128,256...}.
         """
-        return cls(val['array_'].address)
+        return cls(val[cls.traits.storage_member].address)
 
     @classmethod
     def from_address(cls, address):
@@ -926,6 +929,14 @@ class BaseDecimal:
             return str(decimal.Decimal(v).scaleb(-scale))
 
 
+class Decimal32(BaseDecimal):
+    traits = decimal_traits[32]
+
+
+class Decimal64(BaseDecimal):
+    traits = decimal_traits[64]
+
+
 class Decimal128(BaseDecimal):
     traits = decimal_traits[128]
 
@@ -935,6 +946,8 @@ class Decimal256(BaseDecimal):
 
 
 decimal_bits_to_class = {
+    32: Decimal32,
+    64: Decimal64,
     128: Decimal128,
     256: Decimal256,
 }
@@ -1039,6 +1052,8 @@ type_reprs = {
     'DayTimeIntervalType': 'day_time_interval',
     'MonthDayNanoIntervalType': 'month_day_nano_interval',
     'DurationType': 'duration',
+    'Decimal32Type': 'decimal32',
+    'Decimal64Type': 'decimal64',
     'Decimal128Type': 'decimal128',
     'Decimal256Type': 'decimal256',
     'StringType': 'utf8',
@@ -2061,6 +2076,8 @@ type_traits_by_id = {
     Type.INTERVAL_MONTH_DAY_NANO: DataTypeTraits(MonthDayNanoIntervalTypeClass,
                                                  'MonthDayNanoIntervalType'),
 
+    Type.DECIMAL32: DataTypeTraits(DecimalTypeClass, 'Decimal32Type'),
+    Type.DECIMAL64: DataTypeTraits(DecimalTypeClass, 'Decimal64Type'),
     Type.DECIMAL128: DataTypeTraits(DecimalTypeClass, 'Decimal128Type'),
     Type.DECIMAL256: DataTypeTraits(DecimalTypeClass, 'Decimal256Type'),
 
@@ -2078,8 +2095,6 @@ type_traits_by_id = {
     Type.EXTENSION: DataTypeTraits(ExtensionTypeClass, 'ExtensionType'),
 }
 
-max_type_id = len(type_traits_by_id) - 1
-
 
 def lookup_type_class(type_id):
     """
@@ -2368,11 +2383,15 @@ class DecimalPrinter:
 
 printers = {
     "arrow::ArrayData": ArrayDataPrinter,
+    "arrow::BasicDecimal32": partial(DecimalPrinter, 32),
+    "arrow::BasicDecimal64": partial(DecimalPrinter, 64),
     "arrow::BasicDecimal128": partial(DecimalPrinter, 128),
     "arrow::BasicDecimal256": partial(DecimalPrinter, 256),
     "arrow::ChunkedArray": ChunkedArrayPrinter,
     "arrow::Datum": DatumPrinter,
     "arrow::DayTimeIntervalType::DayMilliseconds": DayMillisecondsPrinter,
+    "arrow::Decimal32": partial(DecimalPrinter, 32),
+    "arrow::Decimal64": partial(DecimalPrinter, 64),
     "arrow::Decimal128": partial(DecimalPrinter, 128),
     "arrow::Decimal256": partial(DecimalPrinter, 256),
     "arrow::MonthDayNanoIntervalType::MonthDayNanos": MonthDayNanosPrinter,
diff --git a/python/pyarrow/src/arrow/python/gdb.cc 
b/python/pyarrow/src/arrow/python/gdb.cc
index 89135239f2..4442cc4321 100644
--- a/python/pyarrow/src/arrow/python/gdb.cc
+++ b/python/pyarrow/src/arrow/python/gdb.cc
@@ -145,6 +145,18 @@ void TestSession() {
       {"key_text", "key_binary"}, {"some value", std::string("z") + '\x00' + 
"\x1f\xff"});
 
   // Decimals
+  Decimal32 decimal32_zero{};
+  Decimal32 decimal32_pos{"987654321"};
+  Decimal32 decimal32_neg{"-987654321"};
+  BasicDecimal32 basic_decimal32_zero{};
+  BasicDecimal32 basic_decimal32_pos{decimal32_pos.value()};
+  BasicDecimal32 basic_decimal32_neg{decimal32_neg.value()};
+  Decimal64 decimal64_zero{};
+  Decimal64 decimal64_pos{"987654321098765432"};
+  Decimal64 decimal64_neg{"-987654321098765432"};
+  BasicDecimal64 basic_decimal64_zero{};
+  BasicDecimal64 basic_decimal64_pos{decimal64_pos.value()};
+  BasicDecimal64 basic_decimal64_neg{decimal64_neg.value()};
   Decimal128 decimal128_zero{};
   Decimal128 decimal128_pos{"98765432109876543210987654321098765432"};
   Decimal128 decimal128_neg{"-98765432109876543210987654321098765432"};
@@ -194,8 +206,12 @@ void TestSession() {
   FixedSizeBinaryType fixed_size_binary_type(10);
   auto heap_fixed_size_binary_type = fixed_size_binary(10);
 
+  Decimal32Type decimal32_type(8, 3);
+  Decimal64Type decimal64_type(16, 5);
   Decimal128Type decimal128_type(16, 5);
   Decimal256Type decimal256_type(42, 12);
+  auto heap_decimal32_type = decimal32(8, 3);
+  auto heap_decimal64_type = decimal64(16, 5);
   auto heap_decimal128_type = decimal128(16, 5);
 
   ListType list_type(uint8());
@@ -300,6 +316,17 @@ void TestSession() {
   Date64Scalar date64_scalar{45 * 86400000LL};
   Date64Scalar date64_scalar_null{};
 
+  Decimal32Scalar decimal32_scalar_pos{Decimal32("1234567"), decimal32(9, 4)};
+  Decimal32Scalar decimal32_scalar_neg{Decimal32("-1234567"), decimal32(9, 4)};
+  Decimal32Scalar decimal32_scalar_null{decimal32(9, 4)};
+  auto heap_decimal32_scalar = *MakeScalar(decimal32(9, 4), 
Decimal32("1234567"));
+
+  Decimal64Scalar decimal64_scalar_pos{Decimal64("12345678901234567"), 
decimal64(18, 4)};
+  Decimal64Scalar decimal64_scalar_neg{Decimal64("-12345678901234567"), 
decimal64(18, 4)};
+  Decimal64Scalar decimal64_scalar_null{decimal64(18, 4)};
+  auto heap_decimal64_scalar =
+      *MakeScalar(decimal64(18, 4), Decimal64("12345678901234567"));
+
   Decimal128Scalar decimal128_scalar_pos_scale_pos{Decimal128("1234567"),
                                                    decimal128(10, 4)};
   Decimal128Scalar decimal128_scalar_pos_scale_neg{Decimal128("-1234567"),
@@ -467,11 +494,16 @@ void TestSession() {
   auto heap_timestamp_array_ns = SliceArrayFromJSON(
       timestamp(TimeUnit::NANO), R"([null, "1900-02-28 12:34:56.987654321"])");
 
+  auto heap_decimal32_array =
+      SliceArrayFromJSON(decimal32(9, 4), R"([null, "-12345.6789", 
"12345.6789"])");
+  auto heap_decimal64_array = SliceArrayFromJSON(
+      decimal64(18, 4), R"([null, "-12345678901234.5678", 
"12345678901234.5678"])");
   auto heap_decimal128_array = SliceArrayFromJSON(
       decimal128(30, 6),
       R"([null, "-1234567890123456789.012345", 
"1234567890123456789.012345"])");
   auto heap_decimal256_array = SliceArrayFromJSON(
       decimal256(50, 6), R"([null, 
"-123456789012345678901234567890123456789.012345"])");
+  auto heap_decimal32_array_sliced = heap_decimal32_array->Slice(1, 1);
   auto heap_decimal128_array_sliced = heap_decimal128_array->Slice(1, 1);
 
   auto heap_fixed_size_binary_array = 
BinaryArrayFromStrings<FixedSizeBinaryBuilder>(
diff --git a/python/pyarrow/tests/test_gdb.py b/python/pyarrow/tests/test_gdb.py
index 912953ae60..cd44e686bb 100644
--- a/python/pyarrow/tests/test_gdb.py
+++ b/python/pyarrow/tests/test_gdb.py
@@ -286,6 +286,32 @@ def test_buffer_heap(gdb_arrow):
 
 
 def test_decimals(gdb_arrow):
+    v32 = "987654321"
+    check_stack_repr(gdb_arrow, "decimal32_zero", "arrow::Decimal32(0)")
+    check_stack_repr(gdb_arrow, "decimal32_pos",
+                     f"arrow::Decimal32({v32})")
+    check_stack_repr(gdb_arrow, "decimal32_neg",
+                     f"arrow::Decimal32(-{v32})")
+    check_stack_repr(gdb_arrow, "basic_decimal32_zero",
+                     "arrow::BasicDecimal32(0)")
+    check_stack_repr(gdb_arrow, "basic_decimal32_pos",
+                     f"arrow::BasicDecimal32({v32})")
+    check_stack_repr(gdb_arrow, "basic_decimal32_neg",
+                     f"arrow::BasicDecimal32(-{v32})")
+
+    v64 = "987654321098765432"
+    check_stack_repr(gdb_arrow, "decimal64_zero", "arrow::Decimal64(0)")
+    check_stack_repr(gdb_arrow, "decimal64_pos",
+                     f"arrow::Decimal64({v64})")
+    check_stack_repr(gdb_arrow, "decimal64_neg",
+                     f"arrow::Decimal64(-{v64})")
+    check_stack_repr(gdb_arrow, "basic_decimal64_zero",
+                     "arrow::BasicDecimal64(0)")
+    check_stack_repr(gdb_arrow, "basic_decimal64_pos",
+                     f"arrow::BasicDecimal64({v64})")
+    check_stack_repr(gdb_arrow, "basic_decimal64_neg",
+                     f"arrow::BasicDecimal64(-{v64})")
+
     v128 = "98765432109876543210987654321098765432"
     check_stack_repr(gdb_arrow, "decimal128_zero", "arrow::Decimal128(0)")
     check_stack_repr(gdb_arrow, "decimal128_pos",
@@ -359,6 +385,10 @@ def test_types_stack(gdb_arrow):
     check_stack_repr(gdb_arrow, "duration_type_ns",
                      "arrow::duration(arrow::TimeUnit::NANO)")
 
+    check_stack_repr(gdb_arrow, "decimal32_type",
+                     "arrow::decimal32(8, 3)")
+    check_stack_repr(gdb_arrow, "decimal64_type",
+                     "arrow::decimal64(16, 5)")
     check_stack_repr(gdb_arrow, "decimal128_type",
                      "arrow::decimal128(16, 5)")
     check_stack_repr(gdb_arrow, "decimal256_type",
@@ -425,6 +455,10 @@ def test_types_heap(gdb_arrow):
         gdb_arrow, "heap_timestamp_type_ns_timezone",
         'arrow::timestamp(arrow::TimeUnit::NANO, "Europe/Paris")')
 
+    check_heap_repr(gdb_arrow, "heap_decimal32_type",
+                    "arrow::decimal32(8, 3)")
+    check_heap_repr(gdb_arrow, "heap_decimal64_type",
+                    "arrow::decimal64(16, 5)")
     check_heap_repr(gdb_arrow, "heap_decimal128_type",
                     "arrow::decimal128(16, 5)")
 
@@ -565,6 +599,28 @@ def test_scalars_stack(gdb_arrow):
     check_stack_repr(gdb_arrow, "date64_scalar_null",
                      "arrow::Date64Scalar of null value")
 
+    check_stack_repr(
+        gdb_arrow, "decimal32_scalar_null",
+        "arrow::Decimal32Scalar of null value [precision=9, scale=4]")
+    check_stack_repr(
+        gdb_arrow, "decimal32_scalar_pos",
+        "arrow::Decimal32Scalar of value 123.4567 [precision=9, scale=4]")
+    check_stack_repr(
+        gdb_arrow, "decimal32_scalar_neg",
+        "arrow::Decimal32Scalar of value -123.4567 [precision=9, scale=4]")
+
+    check_stack_repr(
+        gdb_arrow, "decimal64_scalar_null",
+        "arrow::Decimal64Scalar of null value [precision=18, scale=4]")
+    check_stack_repr(
+        gdb_arrow, "decimal64_scalar_pos",
+        ("arrow::Decimal64Scalar of value 1234567890123.4567 "
+         "[precision=18, scale=4]"))
+    check_stack_repr(
+        gdb_arrow, "decimal64_scalar_neg",
+        ("arrow::Decimal64Scalar of value -1234567890123.4567 "
+         "[precision=18, scale=4]"))
+
     check_stack_repr(
         gdb_arrow, "decimal128_scalar_null",
         "arrow::Decimal128Scalar of null value [precision=10, scale=4]")
@@ -730,6 +786,13 @@ def test_scalars_heap(gdb_arrow):
     check_heap_repr(gdb_arrow, "heap_null_scalar", "arrow::NullScalar")
     check_heap_repr(gdb_arrow, "heap_bool_scalar",
                     "arrow::BooleanScalar of value true")
+    check_heap_repr(
+        gdb_arrow, "heap_decimal32_scalar",
+        "arrow::Decimal32Scalar of value 123.4567 [precision=9, scale=4]")
+    check_heap_repr(
+        gdb_arrow, "heap_decimal64_scalar",
+        ("arrow::Decimal64Scalar of value 1234567890123.4567 "
+         "[precision=18, scale=4]"))
     check_heap_repr(
         gdb_arrow, "heap_decimal128_scalar",
         "arrow::Decimal128Scalar of value 123.4567 [precision=10, scale=4]")
@@ -944,6 +1007,17 @@ def test_arrays_heap(gdb_arrow):
              "[1] = -2203932303012345679ns [too large to represent]}"))
 
     # Decimal
+    check_heap_repr(
+        gdb_arrow, "heap_decimal32_array",
+        ("arrow::Decimal32Array of type arrow::decimal32(9, 4), "
+         "length 3, offset 0, null count 1 = {"
+         "[0] = null, [1] = -12345.6789, [2] = 12345.6789}"))
+    check_heap_repr(
+        gdb_arrow, "heap_decimal64_array",
+        ("arrow::Decimal64Array of type arrow::decimal64(18, 4), "
+         "length 3, offset 0, null count 1 = {"
+         "[0] = null, [1] = -12345678901234.5678, "
+         "[2] = 12345678901234.5678}"))
     check_heap_repr(
         gdb_arrow, "heap_decimal128_array",
         ("arrow::Decimal128Array of type arrow::decimal128(30, 6), "
@@ -956,6 +1030,11 @@ def test_arrays_heap(gdb_arrow):
          "length 2, offset 0, null count 1 = {"
          "[0] = null, "
          "[1] = -123456789012345678901234567890123456789.012345}"))
+    check_heap_repr(
+        gdb_arrow, "heap_decimal32_array_sliced",
+        ("arrow::Decimal32Array of type arrow::decimal32(9, 4), "
+         "length 1, offset 1, unknown null count = {"
+         "[0] = -12345.6789}"))
     check_heap_repr(
         gdb_arrow, "heap_decimal128_array_sliced",
         ("arrow::Decimal128Array of type arrow::decimal128(30, 6), "

Reply via email to