Skip to content

Commit b9891f0

Browse files
Fixed additional scenarios where a query is re-executed with LOBs or
JSON columns after the underlying table is dropped and recreated.
1 parent ef1ded8 commit b9891f0

File tree

5 files changed

+52
-5
lines changed

5 files changed

+52
-5
lines changed

doc/src/release_notes.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ Thin Mode Changes
1818
#) Replaced regular expressions for parsing SQL with regular expressions that
1919
perform better
2020
(`issue 172 <https://github.com/oracle/python-oracledb/issues/172>`__).
21-
#) Fixed bug when a query is re-executed with the setting
22-
``oracledb.defaults.fetch_lobs = False`` after a table underlying the query
23-
is dropped and recreated.
21+
#) Fixed bug when a query is re-executed containing LOBs (either fetched as
22+
LOB locators or as strings/bytes) or JSON data after a table underlying the
23+
query is dropped and recreated.
2424
#) Fixed bug when warning message is encountered during connect
2525
(`issue 171 <https://github.com/oracle/python-oracledb/issues/171>`__).
2626

src/oracledb/impl/thin/cursor.pyx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ cdef class ThinCursorImpl(BaseCursorImpl):
9696
if typ_impl.is_xml_type:
9797
var_impl.outconverter = \
9898
lambda v: v if isinstance(v, str) else v.read()
99-
self._statement._always_full_execute = self._statement._requires_define
10099

101100
cdef int _fetch_rows(self, object cursor) except -1:
102101
"""

src/oracledb/impl/thin/messages.pyx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ cdef class MessageWithData(Message):
454454
for i, var_impl in enumerate(cursor_impl.fetch_var_impls):
455455
cursor_impl._create_fetch_var(conn, self.cursor, type_handler,
456456
i, var_impl._fetch_info)
457+
cursor_impl._statement._adjust_requires_define()
457458
statement._last_output_type_handler = type_handler
458459

459460
# the list of output variables is equivalent to the fetch variables
@@ -717,6 +718,7 @@ cdef class MessageWithData(Message):
717718
self._adjust_fetch_info(prev_fetch_var_impls[i], fetch_info)
718719
cursor_impl._create_fetch_var(conn, self.cursor, type_handler, i,
719720
fetch_info)
721+
cursor_impl._statement._adjust_requires_define()
720722
buf.read_ub4(&num_bytes)
721723
if num_bytes > 0:
722724
buf.skip_raw_bytes_chunked() # current date

src/oracledb/impl/thin/statement.pyx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,18 @@ cdef class Statement:
146146
else:
147147
self._bind_info_dict[info._bind_name] = [info]
148148

149+
cdef int _adjust_requires_define(self) except -1:
150+
"""
151+
The define step is only supposed to be done once for each cursor, but a
152+
full execute is required if a define was ever performed, so perform
153+
that adjustment here, if needed.
154+
"""
155+
if self._requires_define:
156+
if self._always_full_execute:
157+
self._requires_define = False
158+
else:
159+
self._always_full_execute = True
160+
149161
cdef _determine_statement_type(self, str sql):
150162
"""
151163
Determine the type of the SQL statement by examining the first keyword

tests/test_4300_cursor_other.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ def test_4369_bind_order_for_plsql(self):
914914
self.assertEqual(fetched_rows, rows)
915915

916916
def test_4370_rebuild_table_with_lob_in_cached_query(self):
917-
"4370 - test rebuild of table with LOB in cached query"
917+
"4370 - test rebuild of table with LOB in cached query (as string)"
918918
table_name = "test_4370"
919919
drop_sql = f"drop table {table_name} purge"
920920
create_sql = f"""
@@ -945,5 +945,39 @@ def test_4370_rebuild_table_with_lob_in_cached_query(self):
945945
self.cursor.execute(query_sql)
946946
self.assertEqual(self.cursor.fetchall(), data)
947947

948+
def test_4371_rebuild_table_with_lob_in_cached_query(self):
949+
"4371 - test rebuild of table with LOB in cached query (as LOB)"
950+
table_name = "test_4371"
951+
drop_sql = f"drop table {table_name} purge"
952+
create_sql = f"""
953+
create table {table_name} (
954+
Col1 number(9) not null,
955+
Col2 clob not null
956+
)"""
957+
insert_sql = f"insert into {table_name} values (:1, :2)"
958+
query_sql = f"select * from {table_name} order by Col1"
959+
data = [
960+
(1, "CLOB value 1"),
961+
(2, "CLOB value 2")
962+
]
963+
try:
964+
self.cursor.execute(drop_sql)
965+
except:
966+
pass
967+
self.cursor.execute(create_sql)
968+
self.cursor.executemany(insert_sql, data)
969+
self.cursor.execute(query_sql)
970+
fetched_data = [(n, c.read()) for n, c in self.cursor]
971+
self.assertEqual(fetched_data, data)
972+
self.cursor.execute(query_sql)
973+
fetched_data = [(n, c.read()) for n, c in self.cursor]
974+
self.assertEqual(fetched_data, data)
975+
self.cursor.execute(drop_sql)
976+
self.cursor.execute(create_sql)
977+
self.cursor.executemany(insert_sql, data)
978+
self.cursor.execute(query_sql)
979+
fetched_data = [(n, c.read()) for n, c in self.cursor]
980+
self.assertEqual(fetched_data, data)
981+
948982
if __name__ == "__main__":
949983
test_env.run_test_cases()

0 commit comments

Comments
 (0)