Skip to content

Commit a4e51ba

Browse files
committed
fix: work around PyArrow to sort extension columns
1 parent 166db8c commit a4e51ba

2 files changed

Lines changed: 85 additions & 2 deletions

File tree

adbc_drivers_validation/compare.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,39 @@ def compare_schemas(
247247
compare_fields(expected_field, actual_field, ())
248248

249249

250+
def sort_oblivious(table: pyarrow.Table, sort_keys: typing.Any) -> pyarrow.Table:
251+
# sort, ignorant of extension types
252+
# we have to cast to the storage type and back
253+
cols = []
254+
fields = []
255+
for field, col in zip(table.schema, table.columns):
256+
if field.type.id == 31:
257+
col = pyarrow.chunked_array(
258+
(c.storage for c in col.chunks),
259+
type=col.type.storage_type,
260+
)
261+
field = pyarrow.field(
262+
field.name,
263+
field.type.storage_type,
264+
field.nullable,
265+
field.metadata,
266+
)
267+
fields.append(field)
268+
cols.append(col)
269+
new_table = pyarrow.Table.from_arrays(cols, schema=pyarrow.schema(fields))
270+
new_table = new_table.sort_by(sort_keys)
271+
272+
cols = []
273+
for field, col in zip(table.schema, new_table.columns):
274+
if field.type.id == 31:
275+
col = pyarrow.chunked_array(
276+
(field.type.wrap_array(c) for c in col.chunks),
277+
type=field.type,
278+
)
279+
cols.append(col)
280+
return pyarrow.Table.from_arrays(cols, schema=table.schema)
281+
282+
250283
def compare_tables(
251284
expected: pyarrow.Table,
252285
actual: pyarrow.Table,
@@ -258,8 +291,8 @@ def compare_tables(
258291
actual = make_nullable(actual)
259292

260293
if sort_keys := meta.get("sort-keys", None):
261-
expected = expected.sort_by(sort_keys)
262-
actual = actual.sort_by(sort_keys)
294+
expected = sort_oblivious(expected, sort_keys)
295+
actual = sort_oblivious(actual, sort_keys)
263296

264297
compare_schemas(expected.schema, actual.schema)
265298
if expected != actual:

tests/test_compare.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,53 @@ def test_compare_schemas_nullability():
128128
)
129129
def test_scalar_to_py_smart(value: pyarrow.Scalar, expected: typing.Any) -> None:
130130
assert compare.scalar_to_py_smart(value) == expected
131+
132+
133+
@pytest.mark.parametrize(
134+
"table, sort_keys, expected",
135+
[
136+
pytest.param(
137+
pyarrow.Table.from_pylist(
138+
[
139+
{"idx": 1, "value": 0},
140+
{"idx": 0, "value": 1},
141+
{"idx": 2, "value": 2},
142+
]
143+
),
144+
[("idx", "descending")],
145+
pyarrow.Table.from_pylist(
146+
[
147+
{"idx": 2, "value": 2},
148+
{"idx": 1, "value": 0},
149+
{"idx": 0, "value": 1},
150+
]
151+
),
152+
id="int",
153+
),
154+
pytest.param(
155+
pyarrow.Table.from_pydict(
156+
{
157+
"idx": pyarrow.opaque(pyarrow.int64(), "test", "").wrap_array(
158+
pyarrow.array([1, 0, 2])
159+
),
160+
"value": pyarrow.array([0, 1, 2]),
161+
}
162+
),
163+
[("idx", "descending")],
164+
pyarrow.Table.from_pydict(
165+
{
166+
"idx": pyarrow.opaque(pyarrow.int64(), "test", "").wrap_array(
167+
pyarrow.array([2, 1, 0])
168+
),
169+
"value": pyarrow.array([2, 0, 1]),
170+
}
171+
),
172+
id="extension",
173+
),
174+
],
175+
)
176+
def test_sort_oblivious(
177+
table: pyarrow.Table, sort_keys: list, expected: pyarrow.Table
178+
) -> None:
179+
result = compare.sort_oblivious(table, sort_keys)
180+
assert result.equals(expected)

0 commit comments

Comments
 (0)