diff --git a/cpp/gdb_arrow.py b/cpp/gdb_arrow.py index bab1fa8722dc..f5566cc85a17 100644 --- a/cpp/gdb_arrow.py +++ b/cpp/gdb_arrow.py @@ -1058,8 +1058,10 @@ def num_rows(self): 'Decimal256Type': 'decimal256', 'StringType': 'utf8', 'LargeStringType': 'large_utf8', + 'StringViewType': 'utf8_view', 'BinaryType': 'binary', 'LargeBinaryType': 'large_binary', + 'BinaryViewType': 'binary_view', 'FixedSizeBinaryType': 'fixed_size_binary', 'ListType': 'list', 'LargeListType': 'large_list', @@ -1831,6 +1833,46 @@ def children(self): yield self._null_child(i) +class BinaryViewArrayDataPrinter(ArrayDataPrinter): + """ + ArrayDataPrinter specialization for string/binary view. + """ + + def __init__(self, name, val): + self.is_utf8 = self.type_id == Type.STRING_VIEW + self.format_string = utf8_literal if self.is_utf8 else bytes_literal + + def display_hint(self): + return "array" + + def children(self): + if self.length == 0: + return + views_buf = self._buffer(1) + if views_buf is None: + return + endian = '<' if byte_order() == 'little' else '>' + views_bytes = bytes(views_buf.bytes_view(self.offset * 16, self.length * 16)) + null_bits = self._null_bitmap() + for i, valid in enumerate(null_bits): + if valid: + header_bytes = views_bytes[i * 16:(i + 1) * 16] + size = struct.unpack(endian + 'i', header_bytes[:4])[0] + if size: + if size <= 12: + ptr = views_buf.data + ((self.offset + i) * 16 + 4) + else: + buffer_index, offset = struct.unpack(endian + 'ii', header_bytes[8:16]) + data_buf = self._buffer(2 + buffer_index) + ptr = data_buf.data + offset + yield self._valid_child( + i, self.format_string(ptr, size)) + else: + yield self._valid_child(i, '""') + else: + yield self._null_child(i) + + class ArrayPrinter: """ Pretty-printer for arrow::Array and subclasses. @@ -1980,6 +2022,13 @@ class BaseBinaryTypeClass(DataTypeClass): array_data_printer = BinaryArrayDataPrinter +class BinaryViewTypeClass(DataTypeClass): + is_parametric = False + type_printer = PrimitiveTypePrinter + scalar_printer = BaseBinaryScalarPrinter + array_data_printer = BinaryViewArrayDataPrinter + + class FixedSizeBinaryTypeClass(DataTypeClass): is_parametric = True type_printer = FixedSizeBinaryTypePrinter @@ -2059,6 +2108,8 @@ class ExtensionTypeClass(DataTypeClass): Type.BINARY: DataTypeTraits(BaseBinaryTypeClass, 'BinaryType'), Type.LARGE_STRING: DataTypeTraits(BaseBinaryTypeClass, 'LargeStringType'), Type.LARGE_BINARY: DataTypeTraits(BaseBinaryTypeClass, 'LargeBinaryType'), + Type.STRING_VIEW: DataTypeTraits(BinaryViewTypeClass, 'StringViewType'), + Type.BINARY_VIEW: DataTypeTraits(BinaryViewTypeClass, 'BinaryViewType'), Type.FIXED_SIZE_BINARY: DataTypeTraits(FixedSizeBinaryTypeClass, 'FixedSizeBinaryType'), diff --git a/python/pyarrow/src/arrow/python/gdb.cc b/python/pyarrow/src/arrow/python/gdb.cc index 4442cc432132..6c23645305db 100644 --- a/python/pyarrow/src/arrow/python/gdb.cc +++ b/python/pyarrow/src/arrow/python/gdb.cc @@ -203,6 +203,10 @@ void TestSession() { StringType string_type; LargeBinaryType large_binary_type; LargeStringType large_string_type; + BinaryViewType binary_view_type; + StringViewType string_view_type; + auto heap_binary_view_type = binary_view(); + auto heap_string_view_type = utf8_view(); FixedSizeBinaryType fixed_size_binary_type(10); auto heap_fixed_size_binary_type = fixed_size_binary(10); @@ -366,6 +370,10 @@ void TestSession() { LargeBinaryScalar large_binary_scalar_abc{Buffer::FromString("abc")}; LargeStringScalar large_string_scalar_hehe{Buffer::FromString("héhé")}; + BinaryViewScalar binary_view_scalar_null{binary_view()}; + BinaryViewScalar binary_view_scalar_abc{Buffer::FromString("abc")}; + StringViewScalar string_view_scalar_null{utf8_view()}; + StringViewScalar string_view_scalar_hehe{Buffer::FromString("héhé")}; FixedSizeBinaryScalar fixed_size_binary_scalar{Buffer::FromString("abc"), fixed_size_binary(3)}; @@ -522,6 +530,18 @@ void TestSession() { auto heap_string_array = BinaryArrayFromStrings(utf8(), string_values); auto heap_large_string_array = BinaryArrayFromStrings(large_utf8(), string_values); + const std::vector> binary_view_values = { + std::nullopt, "abcd", std::string("\x00\x1f\xff", 3), "12345678901234567890"}; + auto heap_binary_view_array = + BinaryArrayFromStrings(binary_view(), binary_view_values); + auto heap_binary_view_array_sliced = heap_binary_view_array->Slice(1, 2); + + const std::vector> string_view_values = { + std::nullopt, "héhé", "invalid \xff char", "this string is longer than 12 bytes for view"}; + auto heap_string_view_array = + BinaryArrayFromStrings(utf8_view(), string_view_values); + auto heap_string_view_array_sliced = heap_string_view_array->Slice(1, 2); + auto heap_binary_array_sliced = heap_binary_array->Slice(1, 1); // ChunkedArray diff --git a/python/pyarrow/tests/test_gdb.py b/python/pyarrow/tests/test_gdb.py index cd44e686bb8f..e5cfd209e8cb 100644 --- a/python/pyarrow/tests/test_gdb.py +++ b/python/pyarrow/tests/test_gdb.py @@ -398,6 +398,8 @@ def test_types_stack(gdb_arrow): check_stack_repr(gdb_arrow, "string_type", "arrow::utf8()") check_stack_repr(gdb_arrow, "large_binary_type", "arrow::large_binary()") check_stack_repr(gdb_arrow, "large_string_type", "arrow::large_utf8()") + check_stack_repr(gdb_arrow, "binary_view_type", "arrow::binary_view()") + check_stack_repr(gdb_arrow, "string_view_type", "arrow::utf8_view()") check_stack_repr(gdb_arrow, "fixed_size_binary_type", "arrow::fixed_size_binary(10)") @@ -461,6 +463,8 @@ def test_types_heap(gdb_arrow): "arrow::decimal64(16, 5)") check_heap_repr(gdb_arrow, "heap_decimal128_type", "arrow::decimal128(16, 5)") + check_heap_repr(gdb_arrow, "heap_binary_view_type", "arrow::binary_view()") + check_heap_repr(gdb_arrow, "heap_string_view_type", "arrow::utf8_view()") check_heap_repr(gdb_arrow, "heap_list_type", "arrow::list(arrow::uint8())") @@ -681,6 +685,12 @@ def test_scalars_stack(gdb_arrow): check_stack_repr( gdb_arrow, "large_binary_scalar_abc", 'arrow::LargeBinaryScalar of size 3, value "abc"') + check_stack_repr( + gdb_arrow, "binary_view_scalar_null", + "arrow::BinaryViewScalar of null value") + check_stack_repr( + gdb_arrow, "binary_view_scalar_abc", + 'arrow::BinaryViewScalar of size 3, value "abc"') check_stack_repr( gdb_arrow, "string_scalar_null", @@ -701,6 +711,12 @@ def test_scalars_stack(gdb_arrow): check_stack_repr( gdb_arrow, "large_string_scalar_hehe", 'arrow::LargeStringScalar of size 6, value "héhé"') + check_stack_repr( + gdb_arrow, "string_view_scalar_null", + "arrow::StringViewScalar of null value") + check_stack_repr( + gdb_arrow, "string_view_scalar_hehe", + 'arrow::StringViewScalar of size 6, value "héhé"') check_stack_repr( gdb_arrow, "fixed_size_binary_scalar", @@ -1075,6 +1091,24 @@ def test_arrays_heap(gdb_arrow): gdb_arrow, "heap_binary_array_sliced", (r'arrow::BinaryArray of length 1, offset 1, unknown null count = ' r'{[0] = "abcd"}')) + check_heap_repr( + gdb_arrow, "heap_binary_view_array", + (r'arrow::BinaryViewArray of length 4, offset 0, null count 1 = {' + r'[0] = null, [1] = "abcd", [2] = "\000\037\377", ' + r'[3] = "12345678901234567890"}')) + check_heap_repr( + gdb_arrow, "heap_string_view_array", + (r'arrow::StringViewArray of length 4, offset 0, null count 1 = {' + r'[0] = null, [1] = "héhé", [2] = "invalid \\xff char", ' + r'[3] = "this string is longer than 12 bytes for view"}')) + check_heap_repr( + gdb_arrow, "heap_binary_view_array_sliced", + (r'arrow::BinaryViewArray of length 2, offset 1, unknown null count = ' + r'{[0] = "abcd", [1] = "\000\037\377"}')) + check_heap_repr( + gdb_arrow, "heap_string_view_array_sliced", + (r'arrow::StringViewArray of length 2, offset 1, unknown null count = ' + r'{[0] = "héhé", [1] = "invalid \\xff char"}')) # Nested check_heap_repr(