Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a825b84

Browse filesBrowse files
authored
Don't use PyTuple_Resize (#436)
1 parent 0887495 commit a825b84
Copy full SHA for a825b84

File tree

Expand file treeCollapse file tree

2 files changed

+33
-50
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+33
-50
lines changed

‎.travis.yml

Copy file name to clipboardExpand all lines: .travis.yml
+3-2Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ language: python
55
python:
66
- "nightly"
77
- "pypy3"
8+
- "3.9-dev"
89
- "3.8"
910
- "3.7"
1011
- "3.6"
@@ -42,7 +43,7 @@ jobs:
4243
name: "Django 2.2 test"
4344
env:
4445
- DJANGO_VERSION=2.2.7
45-
python: "3.5"
46+
python: "3.8"
4647
install:
4748
- pip install -U pip
4849
- wget https://github.com/django/django/archive/${DJANGO_VERSION}.tar.gz
@@ -58,7 +59,7 @@ jobs:
5859

5960
script:
6061
- cd django-${DJANGO_VERSION}/tests/
61-
- ./runtests.py --parallel=1 --settings=test_mysql
62+
- ./runtests.py --parallel=2 --settings=test_mysql
6263
- name: flake8
6364
python: "3.8"
6465
install:

‎MySQLdb/_mysql.c

Copy file name to clipboardExpand all lines: MySQLdb/_mysql.c
+30-48Lines changed: 30 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,19 +1298,16 @@ _mysql_row_to_dict_old(
12981298

12991299
typedef PyObject *_PYFUNC(_mysql_ResultObject *, MYSQL_ROW);
13001300

1301-
int
1301+
Py_ssize_t
13021302
_mysql__fetch_row(
13031303
_mysql_ResultObject *self,
1304-
PyObject **r,
1305-
int skiprows,
1306-
int maxrows,
1304+
PyObject *r, /* list object */
1305+
Py_ssize_t maxrows,
13071306
_PYFUNC *convert_row)
13081307
{
1309-
int i;
1310-
MYSQL_ROW row;
1311-
1312-
for (i = skiprows; i<(skiprows+maxrows); i++) {
1313-
PyObject *v;
1308+
Py_ssize_t i;
1309+
for (i = 0; i < maxrows; i++) {
1310+
MYSQL_ROW row;
13141311
if (!self->use)
13151312
row = mysql_fetch_row(self->result);
13161313
else {
@@ -1320,19 +1317,20 @@ _mysql__fetch_row(
13201317
}
13211318
if (!row && mysql_errno(&(((_mysql_ConnectionObject *)(self->conn))->connection))) {
13221319
_mysql_Exception((_mysql_ConnectionObject *)self->conn);
1323-
goto error;
1320+
return -1;
13241321
}
13251322
if (!row) {
1326-
if (_PyTuple_Resize(r, i) == -1) goto error;
13271323
break;
13281324
}
1329-
v = convert_row(self, row);
1330-
if (!v) goto error;
1331-
PyTuple_SET_ITEM(*r, i, v);
1325+
PyObject *v = convert_row(self, row);
1326+
if (!v) return -1;
1327+
if (PyList_Append(r, v)) {
1328+
Py_DECREF(v);
1329+
return -1;
1330+
}
1331+
Py_DECREF(v);
13321332
}
1333-
return i-skiprows;
1334-
error:
1335-
return -1;
1333+
return i;
13361334
}
13371335

13381336
static char _mysql_ResultObject_fetch_row__doc__[] =
@@ -1359,7 +1357,7 @@ _mysql_ResultObject_fetch_row(
13591357
_mysql_row_to_dict_old
13601358
};
13611359
_PYFUNC *convert_row;
1362-
int maxrows=1, how=0, skiprows=0, rowsadded;
1360+
int maxrows=1, how=0;
13631361
PyObject *r=NULL;
13641362

13651363
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii:fetch_row", kwlist,
@@ -1371,40 +1369,24 @@ _mysql_ResultObject_fetch_row(
13711369
return NULL;
13721370
}
13731371
convert_row = row_converters[how];
1374-
if (maxrows) {
1375-
if (!(r = PyTuple_New(maxrows))) goto error;
1376-
1377-
// see: https://docs.python.org/3/library/gc.html#gc.get_referrers
1378-
// This function can get a reference to the tuple r, and if that
1379-
// code is preempted while holding a ref to r, the _PyTuple_Resize
1380-
// will raise a SystemError because the ref count is 2.
1381-
PyObject_GC_UnTrack(r);
1382-
rowsadded = _mysql__fetch_row(self, &r, skiprows, maxrows, convert_row);
1383-
if (rowsadded == -1) goto error;
1384-
PyObject_GC_Track(r);
1385-
} else {
1372+
if (!maxrows) {
13861373
if (self->use) {
1387-
maxrows = 1000;
1388-
if (!(r = PyTuple_New(maxrows))) goto error;
1389-
while (1) {
1390-
rowsadded = _mysql__fetch_row(self, &r, skiprows,
1391-
maxrows, convert_row);
1392-
if (rowsadded == -1) goto error;
1393-
skiprows += rowsadded;
1394-
if (rowsadded < maxrows) break;
1395-
if (_PyTuple_Resize(&r, skiprows+maxrows) == -1)
1396-
goto error;
1397-
}
1374+
maxrows = INT_MAX;
13981375
} else {
1399-
/* XXX if overflow, maxrows<0? */
1400-
maxrows = (int) mysql_num_rows(self->result);
1401-
if (!(r = PyTuple_New(maxrows))) goto error;
1402-
rowsadded = _mysql__fetch_row(self, &r, 0,
1403-
maxrows, convert_row);
1404-
if (rowsadded == -1) goto error;
1376+
// todo: preallocate.
1377+
maxrows = (Py_ssize_t) mysql_num_rows(self->result);
14051378
}
14061379
}
1407-
return r;
1380+
if (!(r = PyList_New(0))) goto error;
1381+
Py_ssize_t rowsadded = _mysql__fetch_row(self, r, maxrows, convert_row);
1382+
if (rowsadded == -1) goto error;
1383+
1384+
/* DB-API allows return rows as list.
1385+
* But we need to return list because Django expecting tuple.
1386+
*/
1387+
PyObject *t = PyList_AsTuple(r);
1388+
Py_DECREF(r);
1389+
return t;
14081390
error:
14091391
Py_XDECREF(r);
14101392
return NULL;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.