Skip to content

Commit de27b93

Browse files
rustyconoverclaude
andcommitted
fix: build empty batches for union and extension schemas
pa.array([], type=...) has no builder for union or extension types, so the ungrouped-empty aggregate client result, the filter_v2 bind check and the dynamic aggregate fixture failed for such an output schema. Use vgi_rpc.utils.empty_batch / pa.nulls(0, ...). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 4319088 commit de27b93

3 files changed

Lines changed: 11 additions & 11 deletions

File tree

‎vgi/_test_fixtures/aggregate/dynamic.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,9 @@ def _slice_to_frame(
232232
t = t.filter(null_mask)
233233
slices.append(t)
234234
if not slices:
235-
return pa.table({c: pa.array([], type=cols[i].type) for i, c in enumerate(col_names)})
235+
# pa.nulls(0, ...), not pa.array([], ...): the latter has no
236+
# builder for union or extension types.
237+
return pa.table({c: pa.nulls(0, type=cols[i].type) for i, c in enumerate(col_names)})
236238
return pa.concat_tables(slices)
237239

238240
@staticmethod

‎vgi/client/aggregate.py‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050

5151
import pyarrow as pa
5252
from vgi_rpc.rpc import RpcError
53+
from vgi_rpc.utils import empty_batch
5354

5455
from vgi.aggregate_function import GROUP_COLUMN_NAME
5556
from vgi.arguments import Arguments
@@ -783,12 +784,9 @@ def aggregate_function(
783784
batch = next(batches, None)
784785

785786
if not group_keys:
786-
results = [
787-
pa.RecordBatch.from_arrays(
788-
[pa.array([], type=field.type) for field in session.output_schema],
789-
schema=session.output_schema,
790-
)
791-
]
787+
# empty_batch, not pa.array([], type=...): that has no builder
788+
# for union or extension types.
789+
results = [empty_batch(session.output_schema)]
792790
else:
793791
results = [
794792
session.finalize(range(start, min(start + finalize_chunk_size, len(group_keys))))

‎vgi/filter_v2.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from typing import Literal as TypingLiteral
1717

1818
import pyarrow as pa
19+
from vgi_rpc.utils import empty_batch
1920

2021
FILTER_ENCODING = "vgi.filters.v2"
2122
FILTER_VERSION = "2"
@@ -765,10 +766,9 @@ def _predicate(self, obj: dict[str, object], where: str, *, update: bool = False
765766
and not isinstance(expression, RuntimeFilter)
766767
and not _REPLAYING_ACCEPTED_STATE.get()
767768
):
768-
empty = pa.RecordBatch.from_arrays(
769-
[pa.array([], type=field.type) for field in self.output_schema],
770-
schema=self.output_schema,
771-
)
769+
# empty_batch, not pa.array([], type=...): that has no builder
770+
# for union or extension types.
771+
empty = empty_batch(self.output_schema)
772772
try:
773773
_evaluate_expression(expression, empty, self.context)
774774
except Exception as exc:

0 commit comments

Comments
 (0)