Skip to content

Commit 132e6c5

Browse files
Fixed bug when executing PL/SQL with a large number of binds.
1 parent 10be0c9 commit 132e6c5

File tree

3 files changed

+35
-5
lines changed

3 files changed

+35
-5
lines changed

doc/src/release_notes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Thin Mode Changes
2020
#) Fixed bugs in the implementation of the statement cache.
2121
#) Fixed bug which could cause a redirect loop with improperly configured
2222
listener redirects.
23+
#) Fixed bug when executing PL/SQL with a large number of binds.
2324
#) Eliminated unneeded round trip when using token authentication to connect
2425
to the database.
2526

src/oracledb/impl/thin/messages.pyx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -787,13 +787,15 @@ cdef class MessageWithData(Message):
787787
It indicates whether binds are IN only, IN/OUT or OUT only.
788788
"""
789789
cdef:
790-
uint16_t i, num_binds, num_bytes, temp16
790+
uint16_t i, num_bytes, temp16
791+
uint32_t temp32, num_binds
791792
BindInfo bind_info
792793
buf.skip_ub1() # flag
793-
buf.read_ub2(&num_binds) # num requests
794-
buf.read_ub4(&self.row_index) # iter num
794+
buf.read_ub2(&temp16) # num requests
795+
buf.read_ub4(&temp32) # num iters
796+
num_binds = temp32 * 256 + temp16
795797
buf.skip_ub4() # num iters this time
796-
buf.read_ub2(&temp16) # uac buffer length
798+
buf.skip_ub2() # uac buffer length
797799
buf.read_ub2(&num_bytes) # bit vector for fast fetch
798800
if num_bytes > 0:
799801
buf.skip_raw_bytes(num_bytes)

tests/test_4000_cursor_executemany.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#------------------------------------------------------------------------------
2-
# Copyright (c) 2020, 2022, Oracle and/or its affiliates.
2+
# Copyright (c) 2020, 2023, Oracle and/or its affiliates.
33
#
44
# This software is dual-licensed to you under the Universal Permissive License
55
# (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
@@ -310,5 +310,32 @@ def test_4021_defer_type_assignment(self):
310310
fetched_data = self.cursor.fetchall()
311311
self.assertEqual(data, fetched_data)
312312

313+
def test_4022_plsql_large_number_of_binds(self):
314+
"4022 - test PL/SQL with a lerge number of binds"
315+
parts = []
316+
bind_names = []
317+
all_bind_values = []
318+
out_binds = []
319+
for i in range(5):
320+
all_bind_values.append([])
321+
for i in range(350):
322+
n = len(parts) + 1
323+
bind_names.extend([f"v_out_{n}_0", f"a_{n}", f"b_{n}", f"c_{n}"])
324+
parts.append(f":v_out{n} := :a_{n} + :b_{n} + :c_{n};")
325+
out_binds.append(self.cursor.var(int,
326+
arraysize=len(all_bind_values)))
327+
for j, bind_values in enumerate(all_bind_values):
328+
bind_values.extend([out_binds[-1], n * 1 + j, n * 2 + j,
329+
n * 3 + j])
330+
lf = "\n"
331+
sql = f"begin{lf}{lf.join(parts)}{lf}end;"
332+
self.cursor.executemany(sql, all_bind_values)
333+
init_val = 6
334+
for var in out_binds:
335+
expected = [init_val, init_val + 3, init_val + 6, init_val + 9,
336+
init_val + 12]
337+
self.assertEqual(var.values, expected)
338+
init_val += 6
339+
313340
if __name__ == "__main__":
314341
test_env.run_test_cases()

0 commit comments

Comments
 (0)