Skip to content

Commit 5c81a10

Browse files
Throw a reasonable error when an array stream was already consumed (#306)
Related to #105 We shouldn't throw an InternalException when an Arrow stream was already consumed.
2 parents 3186810 + 1703573 commit 5c81a10

2 files changed

Lines changed: 12 additions & 2 deletions

File tree

src/duckdb_py/arrow/arrow_array_stream.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ unique_ptr<ArrowArrayStreamWrapper> PythonTableArrowArrayStreamFactory::Produce(
7171
auto capsule = py::reinterpret_borrow<py::capsule>(arrow_obj_handle);
7272
auto stream = capsule.get_pointer<struct ArrowArrayStream>();
7373
if (!stream->release) {
74-
throw InternalException("ArrowArrayStream was released by another thread/library");
74+
throw InvalidInputException("This ArrowArrayStream has already been consumed and cannot be scanned again.");
7575
}
7676
res->arrow_array_stream = *stream;
7777
stream->release = nullptr;
@@ -123,7 +123,7 @@ void PythonTableArrowArrayStreamFactory::GetSchemaInternal(py::handle arrow_obj_
123123
auto capsule = py::reinterpret_borrow<py::capsule>(arrow_obj_handle);
124124
auto stream = capsule.get_pointer<struct ArrowArrayStream>();
125125
if (!stream->release) {
126-
throw InternalException("ArrowArrayStream was released by another thread/library");
126+
throw InvalidInputException("This ArrowArrayStream has already been consumed and cannot be scanned again.");
127127
}
128128
stream->get_schema(stream, &schema.arrow_schema);
129129
return;

tests/fast/arrow/test_arrow_pycapsule.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,16 @@ def test_automatic_reexecution(self, duckdb_cursor):
6868
assert len(res1) == 100
6969
assert res1 == res2
7070

71+
def test_pycapsule_rescan_error_type(self, duckdb_cursor):
72+
"""Issue #105: re-executing a relation backed by a consumed PyCapsule."""
73+
pa = pytest.importorskip("pyarrow")
74+
tbl = pa.table({"a": [1]})
75+
capsule = tbl.__arrow_c_stream__() # noqa: F841
76+
rel = duckdb_cursor.sql("SELECT * FROM capsule")
77+
rel.fetchall() # consumes the capsule
78+
with pytest.raises(duckdb.InvalidInputException):
79+
rel.fetchall() # re-execution should be InvalidInputException, not InternalException
80+
7181
def test_consumer_interface_roundtrip(self, duckdb_cursor):
7282
def create_table():
7383
class MyTable:

0 commit comments

Comments
 (0)