Skip to content

Commit 7d289b2

Browse files
committed
Merge pull request #57 from methane/fix/48
Don't fetch warnings when there is next result
2 parents 4154756 + c66f025 commit 7d289b2

File tree

7 files changed

+268
-246
lines changed

7 files changed

+268
-246
lines changed

.travis.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
sudo: false
22
language: python
3+
python: "3.5"
4+
35
cache: pip
46
install:
57
- pip install tox
@@ -8,4 +10,8 @@ before_script:
810
- "mysql --help"
911
- "mysql --print-defaults"
1012
- "mysql -e 'create database mysqldb_test charset utf8mb4;'"
13+
1114
script: TESTDB=travis.cnf tox
15+
16+
17+
# vim: sw=4 ts=4 sts=4

MySQLdb/cursors.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ def _check_executed(self):
109109
def _warning_check(self):
110110
from warnings import warn
111111
if self._warnings:
112+
# When there is next result, fetching warnings cause "command
113+
# out of sync" error.
114+
if self._result and self._result.has_next:
115+
msg = "There are %d MySQL warnings." % (self._warnings,)
116+
self.messages.append(msg)
117+
warn(msg, self.Warning, 3)
118+
return
119+
112120
warnings = self._get_db().show_warnings()
113121
if warnings:
114122
# This is done in two loops in case
@@ -204,23 +212,21 @@ def execute(self, query, args=None):
204212
if isinstance(query, unicode):
205213
query = query.encode(db.unicode_literal.charset, 'surrogateescape')
206214

215+
res = None
207216
try:
208-
r = None
209-
r = self._query(query)
217+
res = self._query(query)
210218
except TypeError as m:
211219
if m.args[0] in ("not enough arguments for format string",
212220
"not all arguments converted"):
213221
self.errorhandler(self, ProgrammingError, m.args[0])
214222
else:
215223
self.errorhandler(self, TypeError, m)
216-
except (SystemExit, KeyboardInterrupt):
217-
raise
218-
except:
224+
except Exception:
219225
exc, value = sys.exc_info()[:2]
220226
self.errorhandler(self, exc, value)
221227
self._executed = query
222228
if not self._defer_warnings: self._warning_check()
223-
return r
229+
return res
224230

225231
def executemany(self, query, args):
226232
"""Execute a multi-row query.

_mysql.c

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static PyObject *_mysql_IntegrityError;
6868
static PyObject *_mysql_InternalError;
6969
static PyObject *_mysql_ProgrammingError;
7070
static PyObject *_mysql_NotSupportedError;
71-
71+
7272
typedef struct {
7373
PyObject_HEAD
7474
MYSQL connection;
@@ -88,6 +88,7 @@ typedef struct {
8888
MYSQL_RES *result;
8989
int nfields;
9090
int use;
91+
char has_next;
9192
PyObject *converter;
9293
} _mysql_ResultObject;
9394

@@ -226,7 +227,7 @@ _mysql_Exception(_mysql_ConnectionObject *c)
226227
Py_DECREF(t);
227228
return NULL;
228229
}
229-
230+
230231
static char _mysql_server_init__doc__[] =
231232
"Initialize embedded server. If this client is not linked against\n\
232233
the embedded server library, this function does nothing.\n\
@@ -249,7 +250,7 @@ static PyObject *_mysql_server_init(
249250
"already initialized");
250251
return NULL;
251252
}
252-
253+
253254
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO", kwlist,
254255
&cmd_args, &groups))
255256
return NULL;
@@ -348,7 +349,7 @@ static PyObject *_mysql_server_end(
348349
}
349350
return _mysql_Exception(NULL);
350351
}
351-
352+
352353
#if MYSQL_VERSION_ID >= 32314
353354
static char _mysql_thread_safe__doc__[] =
354355
"Indicates whether the client is compiled as thread-safe.";
@@ -406,6 +407,7 @@ _mysql_ResultObject_Initialize(
406407
else
407408
result = mysql_store_result(&(conn->connection));
408409
self->result = result;
410+
self->has_next = (char)mysql_more_results(&(conn->connection));
409411
Py_END_ALLOW_THREADS ;
410412
if (!result) {
411413
if (mysql_errno(&(conn->connection))) {
@@ -555,7 +557,7 @@ _mysql_ConnectionObject_Initialize(
555557
char *init_command=NULL,
556558
*read_default_file=NULL,
557559
*read_default_group=NULL;
558-
560+
559561
self->converter = NULL;
560562
self->open = 0;
561563
check_server_init(-1);
@@ -739,7 +741,7 @@ _mysql_connect(
739741
PyObject *kwargs)
740742
{
741743
_mysql_ConnectionObject *c=NULL;
742-
744+
743745
c = MyAlloc(_mysql_ConnectionObject, _mysql_ConnectionObject_Type);
744746
if (c == NULL) return NULL;
745747
if (_mysql_ConnectionObject_Initialize(c, args, kwargs)) {
@@ -1289,7 +1291,7 @@ _mysql_escape_dict(
12891291
Py_XDECREF(r);
12901292
return NULL;
12911293
}
1292-
1294+
12931295
static char _mysql_ResultObject_describe__doc__[] =
12941296
"Returns the sequence of 7-tuples required by the DB-API for\n\
12951297
the Cursor.description attribute.\n\
@@ -1326,7 +1328,7 @@ _mysql_ResultObject_describe(
13261328
Py_XDECREF(d);
13271329
return NULL;
13281330
}
1329-
1331+
13301332
static char _mysql_ResultObject_field_flags__doc__[] =
13311333
"Returns a tuple of field flags, one for each column in the result.\n\
13321334
" ;
@@ -1520,7 +1522,7 @@ _mysql__fetch_row(
15201522
int maxrows,
15211523
_PYFUNC *convert_row)
15221524
{
1523-
unsigned int i;
1525+
int i;
15241526
MYSQL_ROW row;
15251527

15261528
for (i = skiprows; i<(skiprows+maxrows); i++) {
@@ -1573,14 +1575,14 @@ _mysql_ResultObject_fetch_row(
15731575
_mysql_row_to_dict_old
15741576
};
15751577
_PYFUNC *convert_row;
1576-
unsigned int maxrows=1, how=0, skiprows=0, rowsadded;
1578+
int maxrows=1, how=0, skiprows=0, rowsadded;
15771579
PyObject *r=NULL;
15781580

15791581
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii:fetch_row", kwlist,
15801582
&maxrows, &how))
15811583
return NULL;
15821584
check_result_connection(self);
1583-
if (how >= sizeof(row_converters)) {
1585+
if (how >= (int)sizeof(row_converters)) {
15841586
PyErr_SetString(PyExc_ValueError, "how out of range");
15851587
return NULL;
15861588
}
@@ -1734,7 +1736,7 @@ _mysql_ConnectionObject_get_character_set_info(
17341736
{
17351737
PyObject *result;
17361738
MY_CHARSET_INFO cs;
1737-
1739+
17381740
if (!PyArg_ParseTuple(args, "")) return NULL;
17391741
check_connection(self);
17401742
mysql_get_character_set_info(&(self->connection), &cs);
@@ -2653,6 +2655,13 @@ static struct PyMemberDef _mysql_ResultObject_memberlist[] = {
26532655
READONLY,
26542656
"Type conversion mapping"
26552657
},
2658+
{
2659+
"has_next",
2660+
T_BOOL,
2661+
offsetof(_mysql_ResultObject, has_next),
2662+
READONLY,
2663+
"Has next result"
2664+
},
26562665
{NULL} /* Sentinel */
26572666
};
26582667

@@ -2717,44 +2726,44 @@ PyTypeObject _mysql_ConnectionObject_Type = {
27172726
0, /* tp_setattr */
27182727
0, /*tp_compare*/
27192728
(reprfunc)_mysql_ConnectionObject_repr, /* tp_repr */
2720-
2729+
27212730
/* Method suites for standard classes */
2722-
2731+
27232732
0, /* (PyNumberMethods *) tp_as_number */
27242733
0, /* (PySequenceMethods *) tp_as_sequence */
27252734
0, /* (PyMappingMethods *) tp_as_mapping */
2726-
2735+
27272736
/* More standard operations (here for binary compatibility) */
2728-
2737+
27292738
0, /* (hashfunc) tp_hash */
27302739
0, /* (ternaryfunc) tp_call */
27312740
0, /* (reprfunc) tp_str */
27322741
(getattrofunc)_mysql_ConnectionObject_getattro, /* tp_getattro */
27332742
(setattrofunc)_mysql_ConnectionObject_setattro, /* tp_setattro */
2734-
2743+
27352744
/* Functions to access object as input/output buffer */
27362745
0, /* (PyBufferProcs *) tp_as_buffer */
2737-
2746+
27382747
/* (tp_flags) Flags to define presence of optional/expanded features */
27392748
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
27402749
_mysql_connect__doc__, /* (char *) tp_doc Documentation string */
27412750

27422751
/* call function for all accessible objects */
27432752
(traverseproc) _mysql_ConnectionObject_traverse, /* tp_traverse */
2744-
2753+
27452754
/* delete references to contained objects */
27462755
(inquiry) _mysql_ConnectionObject_clear, /* tp_clear */
27472756

27482757
/* rich comparisons */
27492758
0, /* (richcmpfunc) tp_richcompare */
2750-
2759+
27512760
/* weak reference enabler */
27522761
0, /* (long) tp_weaklistoffset */
27532762

27542763
/* Iterators */
27552764
0, /* (getiterfunc) tp_iter */
27562765
0, /* (iternextfunc) tp_iternext */
2757-
2766+
27582767
/* Attribute descriptor and subclassing stuff */
27592768
(struct PyMethodDef *)_mysql_ConnectionObject_methods, /* tp_methods */
27602769
(struct PyMemberDef *)_mysql_ConnectionObject_memberlist, /* tp_members */
@@ -2789,45 +2798,45 @@ PyTypeObject _mysql_ResultObject_Type = {
27892798
0, /* tp_setattr */
27902799
0, /*tp_compare*/
27912800
(reprfunc)_mysql_ResultObject_repr, /* tp_repr */
2792-
2801+
27932802
/* Method suites for standard classes */
2794-
2803+
27952804
0, /* (PyNumberMethods *) tp_as_number */
27962805
0, /* (PySequenceMethods *) tp_as_sequence */
27972806
0, /* (PyMappingMethods *) tp_as_mapping */
2798-
2807+
27992808
/* More standard operations (here for binary compatibility) */
2800-
2809+
28012810
0, /* (hashfunc) tp_hash */
28022811
0, /* (ternaryfunc) tp_call */
28032812
0, /* (reprfunc) tp_str */
28042813
(getattrofunc)PyObject_GenericGetAttr, /* tp_getattro */
28052814
(setattrofunc)_mysql_ResultObject_setattro, /* tp_setattr */
2806-
2815+
28072816
/* Functions to access object as input/output buffer */
28082817
0, /* (PyBufferProcs *) tp_as_buffer */
2809-
2818+
28102819
/* Flags to define presence of optional/expanded features */
28112820
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
2812-
2821+
28132822
_mysql_ResultObject__doc__, /* (char *) tp_doc Documentation string */
28142823

28152824
/* call function for all accessible objects */
28162825
(traverseproc) _mysql_ResultObject_traverse, /* tp_traverse */
2817-
2826+
28182827
/* delete references to contained objects */
28192828
(inquiry) _mysql_ResultObject_clear, /* tp_clear */
28202829

28212830
/* rich comparisons */
28222831
0, /* (richcmpfunc) tp_richcompare */
2823-
2832+
28242833
/* weak reference enabler */
28252834
0, /* (long) tp_weaklistoffset */
28262835

28272836
/* Iterators */
28282837
0, /* (getiterfunc) tp_iter */
28292838
0, /* (iternextfunc) tp_iternext */
2830-
2839+
28312840
/* Attribute descriptor and subclassing stuff */
28322841
(struct PyMethodDef *) _mysql_ResultObject_methods, /* tp_methods */
28332842
(struct PyMemberDef *) _mysql_ResultObject_memberlist, /*tp_members */

tests/configdb.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,15 @@
1010
read_default_group = "MySQLdb-tests",
1111
)
1212

13+
1314
def connection_kwargs(kwargs):
1415
db_kwargs = connect_kwargs.copy()
1516
db_kwargs.update(kwargs)
1617
return db_kwargs
1718

19+
1820
def connection_factory(**kwargs):
1921
import MySQLdb
2022
db_kwargs = connection_kwargs(kwargs)
2123
db = MySQLdb.connect(**db_kwargs)
2224
return db
23-
24-
25-

0 commit comments

Comments
 (0)