Skip to content

Commit fb3cfbb

Browse files
committed
BUG#34217492: Exec of stored procedures with args fails when db prefix used
MySQL itself does support calling procedures with their full name <db>.<procname>, however when calling the Connector/Python cursor.callproc() method following the before mention structure, it arises a ProgrammingError complaining about the syntax. With this patch, the issue is fixed. From now on, the <db>.<procname> syntax is acceptable. Change-Id: I5b8ec54e56bbbbabbfad1ce2a5a601a123058b53
1 parent 2276eb1 commit fb3cfbb

File tree

5 files changed

+45
-2
lines changed

5 files changed

+45
-2
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ v8.0.31
1212
=======
1313

1414
- BUG#34283402: Binary data starting with 0x00 are returned as empty string
15+
- BUG#34217492: Exec of stored procedures with args fails when db prefix used
1516
- BUG#28491115: Connector/Python crashes on 0 time value
1617
- BUG#28295478: Align exception types raised by pure Python and c-ext
1718
- BUG#27634910: Add warning count method to cursors

lib/mysql/connector/cursor.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,9 +734,14 @@ def callproc(self, procname, args=()):
734734
try:
735735
argnames = []
736736
argtypes = []
737+
738+
# MySQL itself does support calling procedures with their full
739+
# name <database>.<procedure_name>. It's necessary to split
740+
# by '.' and grab the procedure name from procname.
741+
procname_abs = procname.split(".")[-1]
737742
if args:
738743
for idx, arg in enumerate(args):
739-
argname = argfmt.format(name=procname, index=idx + 1)
744+
argname = argfmt.format(name=procname_abs, index=idx + 1)
740745
argnames.append(argname)
741746
if isinstance(arg, tuple):
742747
argtypes.append(f" CAST({argname} AS {arg[1]})")

lib/mysql/connector/cursor_cext.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,9 +430,14 @@ def callproc(self, procname, args=()):
430430
try:
431431
argnames = []
432432
argtypes = []
433+
434+
# MySQL itself does support calling procedures with their full
435+
# name <database>.<procedure_name>. It's necessary to split
436+
# by '.' and grab the procedure name from procname.
437+
procname_abs = procname.split(".")[-1]
433438
if args:
434439
for idx, arg in enumerate(args):
435-
argname = argfmt.format(name=procname, index=idx + 1)
440+
argname = argfmt.format(name=procname_abs, index=idx + 1)
436441
argnames.append(argname)
437442
if isinstance(arg, tuple):
438443
argtypes.append(f" CAST({argname} AS {arg[1]})")

tests/cext/test_cext_cursor.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,12 +300,22 @@ def _test_callproc_setup(self, cnx):
300300
"BEGIN SET pConCat := CONCAT(pStr1, pStr2); END;"
301301
)
302302

303+
stmt_create5 = f"""
304+
CREATE PROCEDURE {cnx.database}.myconnpy_sp_5(IN user_value INT)
305+
BEGIN
306+
SET @user_value = user_value;
307+
SELECT @user_value AS 'user_value', CURRENT_TIMESTAMP as
308+
'timestamp';
309+
END
310+
"""
311+
303312
try:
304313
cur = cnx.cursor()
305314
cur.execute(stmt_create1)
306315
cur.execute(stmt_create2)
307316
cur.execute(stmt_create3)
308317
cur.execute(stmt_create4)
318+
cur.execute(stmt_create5)
309319
except errors.Error as err:
310320
self.fail("Failed setting up test stored routine; {0}".format(err))
311321
cur.close()
@@ -317,6 +327,7 @@ def _test_callproc_cleanup(self, cnx):
317327
"myconnpy_sp_2",
318328
"myconnpy_sp_3",
319329
"myconnpy_sp_4",
330+
f"{cnx.database}.myconnpy_sp_5",
320331
)
321332
stmt_drop = "DROP PROCEDURE IF EXISTS {procname}"
322333

@@ -370,6 +381,11 @@ def test_callproc(self):
370381
self.assertTrue(isinstance(cur._stored_results, list))
371382
self.assertEqual(exp, result)
372383

384+
exp = (5,)
385+
result = cur.callproc(f"{self.cnx.database}.myconnpy_sp_5", exp)
386+
self.assertTrue(isinstance(cur._stored_results, list))
387+
self.assertEqual(exp, result)
388+
373389
cur.close()
374390
self._test_callproc_cleanup(self.cnx)
375391

tests/test_cursor.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,12 +801,22 @@ def _test_callproc_setup(self, cnx):
801801
"BEGIN SET pConCat := CONCAT(pStr1, pStr2); END;"
802802
)
803803

804+
stmt_create5 = f"""
805+
CREATE PROCEDURE {cnx.database}.myconnpy_sp_5(IN user_value INT)
806+
BEGIN
807+
SET @user_value = user_value;
808+
SELECT @user_value AS 'user_value', CURRENT_TIMESTAMP as
809+
'timestamp';
810+
END
811+
"""
812+
804813
try:
805814
cur = cnx.cursor()
806815
cur.execute(stmt_create1)
807816
cur.execute(stmt_create2)
808817
cur.execute(stmt_create3)
809818
cur.execute(stmt_create4)
819+
cur.execute(stmt_create5)
810820
except errors.Error as err:
811821
self.fail("Failed setting up test stored routine; {0}".format(err))
812822
cur.close()
@@ -818,6 +828,7 @@ def _test_callproc_cleanup(self, cnx):
818828
"myconnpy_sp_2",
819829
"myconnpy_sp_3",
820830
"myconnpy_sp_4",
831+
f"{cnx.database}.myconnpy_sp_5",
821832
)
822833
stmt_drop = "DROP PROCEDURE IF EXISTS {procname}"
823834

@@ -874,6 +885,11 @@ def test_callproc(self):
874885
self.assertTrue(isinstance(self.cur._stored_results, list))
875886
self.assertEqual(exp, result)
876887

888+
exp = (5,)
889+
result = self.cur.callproc(f"{self.cnx.database}.myconnpy_sp_5", exp)
890+
self.assertTrue(isinstance(self.cur._stored_results, list))
891+
self.assertEqual(exp, result)
892+
877893
self._test_callproc_cleanup(self.cnx)
878894
self.cur.close()
879895

0 commit comments

Comments
 (0)