@@ -1298,19 +1298,16 @@ _mysql_row_to_dict_old(
12981298
12991299typedef 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
13381336static 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