Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 958eec6

Browse files
committed
Expose Cursor.warning_count
After the removal of automatic warnings in #774 this provides a way to check for existence of warnings without having to perform an additional query over the network.
1 parent 72ee1f3 commit 958eec6

File tree

5 files changed

+87
-4
lines changed

5 files changed

+87
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Release date: TBD
77
* Dropped support of end of life MySQL version 5.6
88
* Dropped support of end of life MariaDB versions below 10.3
99
* Dropped support of end of life Python version 3.6
10+
* Exposed `Cursor.warning_count` to check for warnings without additional query (#1056)
1011

1112

1213
## v1.0.2

pymysql/cursors.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class Cursor:
3232

3333
def __init__(self, connection):
3434
self.connection = connection
35+
self.warning_count = -1
3536
self.description = None
3637
self.rownumber = 0
3738
self.rowcount = -1
@@ -331,6 +332,7 @@ def _clear_result(self):
331332
self._result = None
332333

333334
self.rowcount = 0
335+
self.warning_count = -1
334336
self.description = None
335337
self.lastrowid = None
336338
self._rows = None
@@ -341,6 +343,7 @@ def _do_get_result(self):
341343
self._result = result = conn._result
342344

343345
self.rowcount = result.affected_rows
346+
self.warning_count = result.warning_count
344347
self.description = result.description
345348
self.lastrowid = result.insert_id
346349
self._rows = result.rows
@@ -442,6 +445,7 @@ def fetchone(self):
442445
self._check_executed()
443446
row = self.read_next()
444447
if row is None:
448+
self.warning_count = self._result.warning_count
445449
return None
446450
self.rownumber += 1
447451
return row
@@ -475,6 +479,7 @@ def fetchmany(self, size=None):
475479
for i in range(size):
476480
row = self.read_next()
477481
if row is None:
482+
self.warning_count = self._result.warning_count
478483
break
479484
rows.append(row)
480485
self.rownumber += 1

pymysql/tests/test_SSCursor.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
try:
44
from pymysql.tests import base
55
import pymysql.cursors
6-
from pymysql.constants import CLIENT
6+
from pymysql.constants import CLIENT, ER
77
except Exception:
88
# For local testing from top-level directory, without installing
99
sys.path.append("../pymysql")
1010
from pymysql.tests import base
1111
import pymysql.cursors
12-
from pymysql.constants import CLIENT
12+
from pymysql.constants import CLIENT, ER
1313

1414

1515
class TestSSCursor(base.PyMySQLTestCase):
@@ -122,6 +122,35 @@ def test_SSCursor(self):
122122
cursor.execute("DROP TABLE IF EXISTS tz_data")
123123
cursor.close()
124124

125+
def test_warnings(self):
126+
con = self.connect()
127+
cur = con.cursor(pymysql.cursors.SSCursor)
128+
cur.execute("DROP TABLE IF EXISTS `no_exists_table`")
129+
self.assertEqual(cur.warning_count, 1)
130+
131+
cur.execute("SHOW WARNINGS")
132+
w = cur.fetchone()
133+
self.assertEqual(w[1], ER.BAD_TABLE_ERROR)
134+
self.assertIn(
135+
"no_exists_table",
136+
w[2],
137+
)
138+
139+
# ensure unbuffered result is finished
140+
self.assertIsNone(cur.fetchone())
141+
142+
cur.execute("SELECT 1")
143+
self.assertEqual(cur.fetchone(), (1,))
144+
self.assertIsNone(cur.fetchone())
145+
146+
self.assertEqual(cur.warning_count, 0)
147+
148+
cur.execute("SELECT CAST('abc' AS SIGNED)")
149+
# this ensures fully retrieving the unbuffered result
150+
rows = cur.fetchmany(2)
151+
self.assertEqual(len(rows), 1)
152+
self.assertEqual(cur.warning_count, 1)
153+
125154

126155
__all__ = ["TestSSCursor"]
127156

pymysql/tests/test_cursor.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import warnings
2-
1+
from pymysql.constants import ER
32
from pymysql.tests import base
43
import pymysql.cursors
54

@@ -129,3 +128,20 @@ def test_executemany(self):
129128
)
130129
finally:
131130
cursor.execute("DROP TABLE IF EXISTS percent_test")
131+
132+
def test_warnings(self):
133+
con = self.connect()
134+
cur = con.cursor()
135+
cur.execute("DROP TABLE IF EXISTS `no_exists_table`")
136+
self.assertEqual(cur.warning_count, 1)
137+
138+
cur.execute("SHOW WARNINGS")
139+
w = cur.fetchone()
140+
self.assertEqual(w[1], ER.BAD_TABLE_ERROR)
141+
self.assertIn(
142+
"no_exists_table",
143+
w[2],
144+
)
145+
146+
cur.execute("SELECT 1")
147+
self.assertEqual(cur.warning_count, 0)

pymysql/tests/test_load_local.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from pymysql import cursors, OperationalError, Warning
2+
from pymysql.constants import ER
23
from pymysql.tests import base
34

45
import os
@@ -63,6 +64,37 @@ def test_unbuffered_load_file(self):
6364
c = conn.cursor()
6465
c.execute("DROP TABLE test_load_local")
6566

67+
def test_load_warnings(self):
68+
"""Test load local infile produces the appropriate warnings"""
69+
conn = self.connect()
70+
c = conn.cursor()
71+
c.execute("CREATE TABLE test_load_local (a INTEGER, b INTEGER)")
72+
filename = os.path.join(
73+
os.path.dirname(os.path.realpath(__file__)),
74+
"data",
75+
"load_local_warn_data.txt",
76+
)
77+
try:
78+
c.execute(
79+
(
80+
"LOAD DATA LOCAL INFILE '{0}' INTO TABLE "
81+
+ "test_load_local FIELDS TERMINATED BY ','"
82+
).format(filename)
83+
)
84+
self.assertEqual(1, c.warning_count)
85+
86+
c.execute("SHOW WARNINGS")
87+
w = c.fetchone()
88+
89+
self.assertEqual(ER.TRUNCATED_WRONG_VALUE_FOR_FIELD, w[1])
90+
self.assertIn(
91+
"incorrect integer value",
92+
w[2].lower(),
93+
)
94+
finally:
95+
c.execute("DROP TABLE test_load_local")
96+
c.close()
97+
6698

6799
if __name__ == "__main__":
68100
import unittest

0 commit comments

Comments
 (0)