diff --git a/cpp/gdb_arrow.py b/cpp/gdb_arrow.py index 7c95a7c72b1..bab1fa8722d 100644 --- a/cpp/gdb_arrow.py +++ b/cpp/gdb_arrow.py @@ -858,16 +858,19 @@ def __getitem__(self, i): 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 @@ def __init__(self, address): 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 @@ def format(self, precision, scale): 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 @@ def num_rows(self): '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 @@ class ExtensionTypeClass(DataTypeClass): 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 @@ class ExtensionTypeClass(DataTypeClass): Type.EXTENSION: DataTypeTraits(ExtensionTypeClass, 'ExtensionType'), } -max_type_id = len(type_traits_by_id) - 1 - def lookup_type_class(type_id): """ @@ -2368,11 +2383,15 @@ def to_string(self): 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 89135239f26..4442cc43213 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( diff --git a/python/pyarrow/tests/test_gdb.py b/python/pyarrow/tests/test_gdb.py index 912953ae60d..cd44e686bb8 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), "