Skip to content

Commit 55e9491

Browse files
Raise helpful exception for requested_schema programming errors.
1 parent c3c2573 commit 55e9491

File tree

5 files changed

+67
-0
lines changed

5 files changed

+67
-0
lines changed

doc/src/release_notes.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ Common Changes
3636
#) Fixed bug that caused ``ORA-03137: malformed TTC packet from client
3737
rejected`` exception to be raised when attempting to call
3838
:meth:`Cursor.parse()` on a scrollable cursor.
39+
#) Error ``DPY-2069: requested schema has {num_schema_columns} columns defined
40+
but {num_fetched_columns} columns are being fetched`` is now raised when
41+
the number of elements in the ``requested_schema`` parameter to
42+
:meth:`Connection.fetch_df_all()` and :meth:`Connection.fetch_df_batches()`
43+
doesn't match the number of columns being fetched. Previously this scenario
44+
would throw unhelpful execptions or cause a segfault under certain
45+
circumstances.
3946
#) Error ``DPY-2068: scroll operation is not supported on a non-scrollable
4047
cursor`` is now raised when using :meth:`Cursor.scroll()` method on a
4148
non-scrollable cursor.

src/oracledb/errors.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ def _raise_not_supported(feature: str) -> None:
292292
ERR_EMPTY_STATEMENT = 2066
293293
ERR_WRONG_DIRECT_PATH_DATA_TYPE = 2067
294294
ERR_SCROLL_NOT_SUPPORTED = 2068
295+
ERR_WRONG_REQUESTED_SCHEMA_LENGTH = 2069
295296

296297
# error numbers that result in NotSupportedError
297298
ERR_TIME_NOT_SUPPORTED = 3000
@@ -1007,6 +1008,10 @@ def _raise_not_supported(feature: str) -> None:
10071008
'found object of type "{actual_schema}.{actual_name}" when '
10081009
'expecting object of type "{expected_schema}.{expected_name}"'
10091010
),
1011+
ERR_WRONG_REQUESTED_SCHEMA_LENGTH: (
1012+
"requested schema has {num_schema_columns} columns defined but "
1013+
"{num_fetched_columns} are being fetched"
1014+
),
10101015
ERR_WRONG_SCROLL_MODE: (
10111016
"scroll mode must be relative, absolute, first or last"
10121017
),

src/oracledb/impl/base/cursor.pyx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,13 @@ cdef class BaseCursorImpl:
326326
Initializes the fetch variable lists in preparation for creating the
327327
fetch variables used in fetching rows from the database.
328328
"""
329+
cdef ssize_t num_schema_columns
330+
if self.schema_impl is not None:
331+
num_schema_columns = len(self.schema_impl.child_schemas)
332+
if num_schema_columns != num_columns:
333+
errors._raise_err(errors.ERR_WRONG_REQUESTED_SCHEMA_LENGTH,
334+
num_schema_columns=num_schema_columns,
335+
num_fetched_columns=num_columns)
329336
self.fetch_metadata = [None] * num_columns
330337
self.fetch_vars = [None] * num_columns
331338
self.fetch_var_impls = [None] * num_columns

tests/test_9300_dataframe_requested_schema.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,3 +755,28 @@ def test_9327(value, conn, test_env):
755755
conn.fetch_df_all(
756756
"select :1 from dual", [value], requested_schema=requested_schema
757757
)
758+
759+
760+
@pytest.mark.parametrize("num_elements", [1, 3])
761+
def test_9328(num_elements, conn, test_env):
762+
"9328 - fetch_df_all() with wrong requested_schema size"
763+
elements = [(f"COL_{i}", pyarrow.string()) for i in range(num_elements)]
764+
requested_schema = pyarrow.schema(elements)
765+
with test_env.assert_raises_full_code("DPY-2069"):
766+
conn.fetch_df_all(
767+
"select user, user from dual", requested_schema=requested_schema
768+
)
769+
770+
771+
@pytest.mark.parametrize("num_elements", [1, 3])
772+
def test_9329(num_elements, conn, test_env):
773+
"9329 - fetch_df_batches() with wrong requested_schema size"
774+
elements = [(f"COL_{i}", pyarrow.string()) for i in range(num_elements)]
775+
requested_schema = pyarrow.schema(elements)
776+
with test_env.assert_raises_full_code("DPY-2069"):
777+
list(
778+
conn.fetch_df_batches(
779+
"select user, user from dual",
780+
requested_schema=requested_schema,
781+
)
782+
)

tests/test_9400_dataframe_requested_schema_async.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,3 +778,26 @@ async def test_9427(value, async_conn, test_env):
778778
await async_conn.fetch_df_all(
779779
"select :1 from dual", [value], requested_schema=requested_schema
780780
)
781+
782+
783+
@pytest.mark.parametrize("num_elements", [1, 3])
784+
async def test_9428(num_elements, async_conn, test_env):
785+
"9428 - fetch_df_all() with wrong requested_schema size"
786+
elements = [(f"COL_{i}", pyarrow.string()) for i in range(num_elements)]
787+
requested_schema = pyarrow.schema(elements)
788+
with test_env.assert_raises_full_code("DPY-2069"):
789+
await async_conn.fetch_df_all(
790+
"select user, user from dual", requested_schema=requested_schema
791+
)
792+
793+
794+
@pytest.mark.parametrize("num_elements", [1, 3])
795+
async def test_9429(num_elements, async_conn, test_env):
796+
"9429 - fetch_df_batches() with wrong requested_schema size"
797+
elements = [(f"COL_{i}", pyarrow.string()) for i in range(num_elements)]
798+
requested_schema = pyarrow.schema(elements)
799+
with test_env.assert_raises_full_code("DPY-2069"):
800+
async for df in async_conn.fetch_df_batches(
801+
"select user, user from dual", requested_schema=requested_schema
802+
):
803+
pass

0 commit comments

Comments
 (0)