Skip to content

Commit 70d5baf

Browse files
committed
BUG#21463298: Fix weakly-referenced object no longer exists exception
Connector/Python cursors contain a weak reference to the connection, and a weak reference to an object is not enough to keep the object alive. So when the connection object is destroyed and the cursor is used, a ReferenceError exception is raised saying that the weakly-referenced object no longer exists. With this patch a ProgrammingError exception is raised instead saying the cursor is not connected. Change-Id: I843a9e84185f8b8710383dd18d9df54910bc5840
1 parent d7ab9e6 commit 70d5baf

File tree

4 files changed

+46
-8
lines changed

4 files changed

+46
-8
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ v8.0.31
1717
- BUG#28491115: Connector/Python crashes on 0 time value
1818
- BUG#28295478: Align exception types raised by pure Python and c-ext
1919
- BUG#27634910: Add warning count method to cursors
20+
- BUG#21463298: Fix weakly-referenced object no longer exists exception
2021

2122
v8.0.30
2223
=======

lib/mysql/connector/cursor.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,8 +520,11 @@ def execute(self, operation, params=None, multi=False):
520520
if not operation:
521521
return None
522522

523-
if not self._connection:
524-
raise ProgrammingError("Cursor is not connected")
523+
try:
524+
if not self._connection:
525+
raise ProgrammingError
526+
except (ProgrammingError, ReferenceError) as err:
527+
raise ProgrammingError("Cursor is not connected") from err
525528

526529
self._connection.handle_unread_result()
527530

lib/mysql/connector/cursor_cext.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,11 @@ def execute(self, operation, params=(), multi=False):
244244
if not operation:
245245
return None
246246

247-
if not self._cnx or self._cnx.is_closed():
248-
raise ProgrammingError("Cursor is not connected", 2055)
247+
try:
248+
if not self._cnx or self._cnx.is_closed():
249+
raise ProgrammingError
250+
except (ProgrammingError, ReferenceError) as err:
251+
raise ProgrammingError("Cursor is not connected", 2055) from err
249252
self._cnx.handle_unread_result()
250253

251254
stmt = ""
@@ -352,8 +355,11 @@ def executemany(self, operation, seq_params):
352355
if not operation or not seq_params:
353356
return None
354357

355-
if not self._cnx:
356-
raise ProgrammingError("Cursor is not connected")
358+
try:
359+
if not self._cnx:
360+
raise ProgrammingError
361+
except (ProgrammingError, ReferenceError) as err:
362+
raise ProgrammingError("Cursor is not connected") from err
357363
self._cnx.handle_unread_result()
358364

359365
if not isinstance(seq_params, (list, tuple)):
@@ -1008,8 +1014,11 @@ def execute(self, operation, params=None, multi=False): # multi is unused
10081014
if not operation:
10091015
return
10101016

1011-
if not self._cnx or self._cnx.is_closed():
1012-
raise ProgrammingError("Cursor is not connected", 2055)
1017+
try:
1018+
if not self._cnx or self._cnx.is_closed():
1019+
raise ProgrammingError
1020+
except (ProgrammingError, ReferenceError) as err:
1021+
raise ProgrammingError("Cursor is not connected", 2055) from err
10131022

10141023
self._cnx.handle_unread_result(prepared=True)
10151024

tests/test_bugs.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7020,3 +7020,28 @@ def test_binary_data_started_with_0x00(self):
70207020
res = cur.fetchall()
70217021
self.assertEqual(exp, res)
70227022
cur.execute(f"DROP TABLE IF EXISTS {table_name}")
7023+
7024+
7025+
class BugOra21463298(tests.MySQLConnectorTests):
7026+
"""BUG#21463298: Fix weakly-referenced object no longer exists exception.
7027+
7028+
Connector/Python cursors contain a weak reference to the connection,
7029+
and a weak reference to an object is not enough to keep the object
7030+
alive. So when the connection object is destroyed and the cursor is
7031+
used, a ReferenceError exception is raised saying that the
7032+
weakly-referenced object no longer exists.
7033+
7034+
With this patch a ProgrammingError exception is raised instead saying
7035+
the cursor is not connected.
7036+
"""
7037+
7038+
@foreach_cnx()
7039+
def test_weakly_referenced_error(self):
7040+
config = tests.get_mysql_config()
7041+
7042+
def get_cursor():
7043+
return self.cnx.__class__(**config).cursor()
7044+
7045+
with self.assertRaises(errors.ProgrammingError) as context:
7046+
get_cursor().execute("SELECT SLEEP(1)")
7047+
self.assertEqual(context.exception.msg, "Cursor is not connected")

0 commit comments

Comments
 (0)