Skip to content

Commit 4bbc320

Browse files
Fixed bug resulting in an exception when Cursor.executemany() is called
with bind variables and an empty parameter set (#508).
1 parent c8678fa commit 4bbc320

File tree

5 files changed

+35
-22
lines changed

5 files changed

+35
-22
lines changed

doc/src/release_notes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ Thin Mode Changes
4444
frame <dataframeformat>`.
4545
#) Fixed bug using :ref:`Oracle Advanced Queuing <aqusermanual>` when
4646
attempting to dequeue using an invalid :attr:`DeqOptions.msgid`.
47+
#) Fixed bug resulting in an exception when :meth:`Cursor.executemany()` is
48+
called with SQL containing bind variables and an empty parameter set
49+
(`issue 508 <https://github.com/oracle/python-oracledb/issues/508>`__).
4750

4851
Thick Mode Changes
4952
++++++++++++++++++

src/oracledb/cursor.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -755,9 +755,10 @@ def executemany(
755755
num_execs = self._impl._prepare_for_executemany(
756756
self, statement, parameters
757757
)
758-
self._impl.executemany(
759-
self, num_execs, bool(batcherrors), bool(arraydmlrowcounts)
760-
)
758+
if num_execs > 0:
759+
self._impl.executemany(
760+
self, num_execs, bool(batcherrors), bool(arraydmlrowcounts)
761+
)
761762

762763
def fetchall(self) -> list:
763764
"""
@@ -1007,9 +1008,10 @@ async def executemany(
10071008
num_execs = self._impl._prepare_for_executemany(
10081009
self, statement, parameters
10091010
)
1010-
await self._impl.executemany(
1011-
self, num_execs, bool(batcherrors), bool(arraydmlrowcounts)
1012-
)
1011+
if num_execs > 0:
1012+
await self._impl.executemany(
1013+
self, num_execs, bool(batcherrors), bool(arraydmlrowcounts)
1014+
)
10131015

10141016
async def fetchall(self) -> list:
10151017
"""

src/oracledb/impl/thick/cursor.pyx

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -346,22 +346,21 @@ cdef class ThickCursorImpl(BaseCursorImpl):
346346
if self.bind_vars is not None:
347347
self._perform_binds(cursor.connection, num_execs_int)
348348

349-
if num_execs_int > 0:
350-
with nogil:
351-
status = dpiStmt_executeMany(self._handle, mode, num_execs_int)
352-
dpiContext_getError(driver_info.context, &error_info)
353-
dpiStmt_getRowCount(self._handle, &rowcount)
354-
if not self._stmt_info.isPLSQL:
355-
self.rowcount = rowcount
356-
if status < 0:
357-
error = _create_new_from_info(&error_info)
358-
if self._stmt_info.isPLSQL and error_info.offset == 0:
359-
error.offset = rowcount
360-
raise error.exc_type(error)
361-
elif error_info.isWarning:
362-
self.warning = _create_new_from_info(&error_info)
363-
if self._stmt_info.isReturning or self._stmt_info.isPLSQL:
364-
self._transform_binds()
349+
with nogil:
350+
status = dpiStmt_executeMany(self._handle, mode, num_execs_int)
351+
dpiContext_getError(driver_info.context, &error_info)
352+
dpiStmt_getRowCount(self._handle, &rowcount)
353+
if not self._stmt_info.isPLSQL:
354+
self.rowcount = rowcount
355+
if status < 0:
356+
error = _create_new_from_info(&error_info)
357+
if self._stmt_info.isPLSQL and error_info.offset == 0:
358+
error.offset = rowcount
359+
raise error.exc_type(error)
360+
elif error_info.isWarning:
361+
self.warning = _create_new_from_info(&error_info)
362+
if self._stmt_info.isReturning or self._stmt_info.isPLSQL:
363+
self._transform_binds()
365364

366365
def get_array_dml_row_counts(self):
367366
"""

tests/test_4000_cursor_executemany.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,10 @@ def test_4027(self):
437437
with self.assertRaisesFullCode("DPY-2016"):
438438
self.cursor.executemany(None, 4)
439439

440+
def test_4028(self):
441+
"4028 - test executemany with empty parameter set"
442+
self.cursor.executemany("insert into TestTempTable values (:1)", [])
443+
440444

441445
if __name__ == "__main__":
442446
test_env.run_test_cases()

tests/test_6100_cursor_executemany_async.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,11 @@ async def test_6123(self):
378378
with self.assertRaisesFullCode("DPY-2001"):
379379
await cursor.executemany(None, [1, 2])
380380

381+
async def test_6124(self):
382+
"6124 - test executemany with empty parameter set"
383+
sql = "insert into TestTempTable values (:1)"
384+
await self.cursor.executemany(sql, [])
385+
381386

382387
if __name__ == "__main__":
383388
test_env.run_test_cases()

0 commit comments

Comments
 (0)