Skip to content

Commit 884a1ed

Browse files
Fixed bug preventing a cursor from being reused after it was bound as a
REF CURSOR to a PL/SQL block that closes it.
1 parent 0acdfdb commit 884a1ed

File tree

5 files changed

+47
-0
lines changed

5 files changed

+47
-0
lines changed

doc/src/release_notes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Thin Mode Changes
2222
(`issue 65 <https://github.com/oracle/python-oracledb/issues/65>`__).
2323
#) Fixed bug when fetching nested cursors with more columns than the parent
2424
cursor.
25+
#) Fixed bug preventing a cursor from being reused after it was bound as a
26+
REF CURSOR to a PL/SQL block that closes it.
2527

2628
Thick Mode Changes
2729
++++++++++++++++++

src/oracledb/impl/thick/var.pyx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ cdef class ThickVarImpl(BaseVarImpl):
203203
cursor_impl.prefetchrows) < 0:
204204
_raise_from_odpi()
205205
cursor_impl._fixup_ref_cursor = True
206+
cursor.statement = None
206207

207208
cdef int _set_num_elements_in_array(self, uint32_t num_elements) except -1:
208209
"""

src/oracledb/impl/thin/messages.pyx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,7 @@ cdef class MessageWithData(Message):
10221022
else:
10231023
buf.write_ub4(1)
10241024
buf.write_ub4(cursor_impl._statement._cursor_id)
1025+
value.statement = None
10251026
elif ora_type_num == TNS_DATA_TYPE_BOOLEAN:
10261027
buf.write_bool(value)
10271028
elif ora_type_num == TNS_DATA_TYPE_INTERVAL_DS:

tests/sql/create_schema.sql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,10 @@ create or replace package &main_user..pkg_TestRefCursors as
876876
a_Cursor out sys_refcursor
877877
);
878878

879+
procedure TestCloseCursor (
880+
a_Cursor sys_refcursor
881+
);
882+
879883
end;
880884
/
881885

@@ -929,6 +933,22 @@ create or replace package body &main_user..pkg_TestRefCursors as
929933
from dual;
930934
end;
931935

936+
procedure TestCloseCursor (
937+
a_Cursor sys_refcursor
938+
) is
939+
t_Id number;
940+
t_StrVal varchar2(400);
941+
begin
942+
delete from TestTempTable;
943+
fetch a_Cursor into t_Id, t_StrVal;
944+
if not a_Cursor%notfound then
945+
insert into TestTempTable (IntCol, StringCol1)
946+
values (t_Id, t_StrVal);
947+
end if;
948+
close a_Cursor;
949+
commit;
950+
end;
951+
932952
end;
933953
/
934954

tests/test_1300_cursor_var.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,5 +301,28 @@ def test_1313_fetch_nested_cursors_with_more_cols_than_parent(self):
301301
]
302302
self.assertEqual(rows, expected_value)
303303

304+
def test_1314_reuse_closed_ref_cursor_with_different_sql(self):
305+
"1314 - test reusing a closed ref cursor for executing different sql"
306+
sql = "select 13141, 'String 13141' from dual"
307+
ref_cursor = self.connection.cursor()
308+
ref_cursor.prefetchrows = 0
309+
ref_cursor.execute(sql)
310+
plsql = "begin pkg_TestRefCursors.TestCloseCursor(:rcursor); end;"
311+
self.cursor.execute(plsql, rcursor=ref_cursor)
312+
sql = "select 13142, 'String 13142' from dual"
313+
ref_cursor.execute(sql)
314+
self.assertEqual(ref_cursor.fetchall(), [(13142, 'String 13142'),])
315+
316+
def test_1315_reuse_closed_ref_cursor_with_same_sql(self):
317+
"1315 - test reusing a closed ref cursor for executing same sql"
318+
sql = "select 1315, 'String 1315' from dual"
319+
ref_cursor = self.connection.cursor()
320+
ref_cursor.prefetchrows = 0
321+
ref_cursor.execute(sql)
322+
plsql = "begin pkg_TestRefCursors.TestCloseCursor(:rcursor); end;"
323+
self.cursor.execute(plsql, rcursor=ref_cursor)
324+
ref_cursor.execute(sql)
325+
self.assertEqual(ref_cursor.fetchall(), [(1315, 'String 1315'),])
326+
304327
if __name__ == "__main__":
305328
test_env.run_test_cases()

0 commit comments

Comments
 (0)