Decode PostgreSQL binary array format and show detailed structure.
(data: bytes)
| 9 | from typing import Optional, List |
| 10 | |
| 11 | def decode_binary_array(data: bytes) -> dict: |
| 12 | """Decode PostgreSQL binary array format and show detailed structure.""" |
| 13 | |
| 14 | if len(data) < 12: |
| 15 | return {"error": f"Data too short: {len(data)} bytes"} |
| 16 | |
| 17 | offset = 0 |
| 18 | result = {} |
| 19 | |
| 20 | # Read header |
| 21 | ndim = struct.unpack('>I', data[offset:offset+4])[0] |
| 22 | offset += 4 |
| 23 | result['ndim'] = ndim |
| 24 | |
| 25 | dataoffset = struct.unpack('>I', data[offset:offset+4])[0] |
| 26 | offset += 4 |
| 27 | result['dataoffset'] = dataoffset |
| 28 | |
| 29 | elemtype = struct.unpack('>I', data[offset:offset+4])[0] |
| 30 | offset += 4 |
| 31 | result['elemtype'] = elemtype |
| 32 | |
| 33 | # Read dimensions |
| 34 | dimensions = [] |
| 35 | for i in range(ndim): |
| 36 | dim_size = struct.unpack('>I', data[offset:offset+4])[0] |
| 37 | offset += 4 |
| 38 | lower_bound = struct.unpack('>I', data[offset:offset+4])[0] |
| 39 | offset += 4 |
| 40 | dimensions.append({'size': dim_size, 'lower_bound': lower_bound}) |
| 41 | result['dimensions'] = dimensions |
| 42 | |
| 43 | # Read NULL bitmap if present |
| 44 | if dataoffset > 0: |
| 45 | bitmap_start = 20 # After header and 1 dimension |
| 46 | bitmap_bytes = dataoffset - bitmap_start |
| 47 | bitmap = data[bitmap_start:bitmap_start+bitmap_bytes] |
| 48 | result['null_bitmap'] = bitmap.hex() |
| 49 | result['null_bitmap_binary'] = ' '.join(f'{b:08b}' for b in bitmap) |
| 50 | offset = dataoffset |
| 51 | |
| 52 | # Read elements |
| 53 | elements = [] |
| 54 | total_elements = dimensions[0]['size'] if dimensions else 0 |
| 55 | |
| 56 | for i in range(total_elements): |
| 57 | elem_len = struct.unpack('>i', data[offset:offset+4])[0] |
| 58 | offset += 4 |
| 59 | |
| 60 | if elem_len == -1: |
| 61 | elements.append({'index': i, 'length': -1, 'value': None, 'is_null': True}) |
| 62 | else: |
| 63 | value_bytes = data[offset:offset+elem_len] |
| 64 | offset += elem_len |
| 65 | |
| 66 | # For INT4, decode the value |
| 67 | if elemtype == 23: # INT4 OID |
| 68 | value = struct.unpack('>i', value_bytes)[0] |
no outgoing calls
no test coverage detected