@@ -1194,7 +1194,8 @@ _mysql_field_to_python(
1194
1194
static PyObject *
1195
1195
_mysql_row_to_tuple (
1196
1196
_mysql_ResultObject * self ,
1197
- MYSQL_ROW row )
1197
+ MYSQL_ROW row ,
1198
+ PyObject * unused )
1198
1199
{
1199
1200
unsigned int n , i ;
1200
1201
unsigned long * length ;
@@ -1221,7 +1222,8 @@ _mysql_row_to_tuple(
1221
1222
static PyObject *
1222
1223
_mysql_row_to_dict (
1223
1224
_mysql_ResultObject * self ,
1224
- MYSQL_ROW row )
1225
+ MYSQL_ROW row ,
1226
+ PyObject * cache )
1225
1227
{
1226
1228
unsigned int n , i ;
1227
1229
unsigned long * length ;
@@ -1243,40 +1245,42 @@ _mysql_row_to_dict(
1243
1245
Py_DECREF (v );
1244
1246
goto error ;
1245
1247
}
1246
-
1247
- PyObject * tmp = PyDict_SetDefault (r , pyname , v );
1248
- Py_DECREF (pyname );
1249
- if (!tmp ) {
1248
+ int err = PyDict_Contains (r , pyname );
1249
+ if (err < 0 ) { // error
1250
1250
Py_DECREF (v );
1251
1251
goto error ;
1252
1252
}
1253
- if (tmp == v ) {
1254
- Py_DECREF (v );
1255
- continue ;
1253
+ if (err ) { // duplicate
1254
+ Py_DECREF (pyname );
1255
+ pyname = PyUnicode_FromFormat ("%s.%s" , fields [i ].table , fields [i ].name );
1256
+ if (pyname == NULL ) {
1257
+ Py_DECREF (v );
1258
+ goto error ;
1259
+ }
1256
1260
}
1257
1261
1258
- pyname = PyUnicode_FromFormat ("%s.%s" , fields [i ].table , fields [i ].name );
1259
- if (!pyname ) {
1260
- Py_DECREF (v );
1261
- goto error ;
1262
+ err = PyDict_SetItem (r , pyname , v );
1263
+ if (cache ) {
1264
+ PyTuple_SET_ITEM (cache , i , pyname );
1265
+ } else {
1266
+ Py_DECREF (pyname );
1262
1267
}
1263
- int err = PyDict_SetItem (r , pyname , v );
1264
- Py_DECREF (pyname );
1265
1268
Py_DECREF (v );
1266
1269
if (err ) {
1267
1270
goto error ;
1268
1271
}
1269
1272
}
1270
1273
return r ;
1271
- error :
1272
- Py_XDECREF (r );
1274
+ error :
1275
+ Py_DECREF (r );
1273
1276
return NULL ;
1274
1277
}
1275
1278
1276
1279
static PyObject *
1277
1280
_mysql_row_to_dict_old (
1278
1281
_mysql_ResultObject * self ,
1279
- MYSQL_ROW row )
1282
+ MYSQL_ROW row ,
1283
+ PyObject * cache )
1280
1284
{
1281
1285
unsigned int n , i ;
1282
1286
unsigned long * length ;
@@ -1302,8 +1306,12 @@ _mysql_row_to_dict_old(
1302
1306
pyname = PyUnicode_FromString (fields [i ].name );
1303
1307
}
1304
1308
int err = PyDict_SetItem (r , pyname , v );
1305
- Py_DECREF (pyname );
1306
1309
Py_DECREF (v );
1310
+ if (cache ) {
1311
+ PyTuple_SET_ITEM (cache , i , pyname );
1312
+ } else {
1313
+ Py_DECREF (pyname );
1314
+ }
1307
1315
if (err ) {
1308
1316
goto error ;
1309
1317
}
@@ -1314,15 +1322,66 @@ _mysql_row_to_dict_old(
1314
1322
return NULL ;
1315
1323
}
1316
1324
1317
- typedef PyObject * _PYFUNC (_mysql_ResultObject * , MYSQL_ROW );
1325
+ static PyObject *
1326
+ _mysql_row_to_dict_cached (
1327
+ _mysql_ResultObject * self ,
1328
+ MYSQL_ROW row ,
1329
+ PyObject * cache )
1330
+ {
1331
+ PyObject * r = PyDict_New ();
1332
+ if (!r ) {
1333
+ return NULL ;
1334
+ }
1335
+
1336
+ unsigned int n = mysql_num_fields (self -> result );
1337
+ unsigned long * length = mysql_fetch_lengths (self -> result );
1338
+ MYSQL_FIELD * fields = mysql_fetch_fields (self -> result );
1339
+
1340
+ for (unsigned int i = 0 ; i < n ; i ++ ) {
1341
+ PyObject * c = PyTuple_GET_ITEM (self -> converter , i );
1342
+ PyObject * v = _mysql_field_to_python (c , row [i ], length [i ], & fields [i ], self -> encoding );
1343
+ if (!v ) {
1344
+ goto error ;
1345
+ }
1346
+
1347
+ PyObject * pyname = PyTuple_GET_ITEM (cache , i ); // borrowed
1348
+ int err = PyDict_SetItem (r , pyname , v );
1349
+ Py_DECREF (v );
1350
+ if (err ) {
1351
+ goto error ;
1352
+ }
1353
+ }
1354
+ return r ;
1355
+ error :
1356
+ Py_XDECREF (r );
1357
+ return NULL ;
1358
+ }
1359
+
1360
+
1361
+ typedef PyObject * _convertfunc (_mysql_ResultObject * , MYSQL_ROW , PyObject * );
1362
+ static _convertfunc * const row_converters [] = {
1363
+ _mysql_row_to_tuple ,
1364
+ _mysql_row_to_dict ,
1365
+ _mysql_row_to_dict_old
1366
+ };
1318
1367
1319
1368
Py_ssize_t
1320
1369
_mysql__fetch_row (
1321
1370
_mysql_ResultObject * self ,
1322
1371
PyObject * r , /* list object */
1323
1372
Py_ssize_t maxrows ,
1324
- _PYFUNC * convert_row )
1373
+ int how )
1325
1374
{
1375
+ _convertfunc * convert_row = row_converters [how ];
1376
+
1377
+ PyObject * cache = NULL ;
1378
+ if (maxrows > 0 && how > 0 ) {
1379
+ cache = PyTuple_New (mysql_num_fields (self -> result ));
1380
+ if (!cache ) {
1381
+ return -1 ;
1382
+ }
1383
+ }
1384
+
1326
1385
Py_ssize_t i ;
1327
1386
for (i = 0 ; i < maxrows ; i ++ ) {
1328
1387
MYSQL_ROW row ;
@@ -1335,20 +1394,29 @@ _mysql__fetch_row(
1335
1394
}
1336
1395
if (!row && mysql_errno (& (((_mysql_ConnectionObject * )(self -> conn ))-> connection ))) {
1337
1396
_mysql_Exception ((_mysql_ConnectionObject * )self -> conn );
1338
- return -1 ;
1397
+ goto error ;
1339
1398
}
1340
1399
if (!row ) {
1341
1400
break ;
1342
1401
}
1343
- PyObject * v = convert_row (self , row );
1344
- if (!v ) return -1 ;
1402
+ PyObject * v = convert_row (self , row , cache );
1403
+ if (!v ) {
1404
+ goto error ;
1405
+ }
1406
+ if (cache ) {
1407
+ convert_row = _mysql_row_to_dict_cached ;
1408
+ }
1345
1409
if (PyList_Append (r , v )) {
1346
1410
Py_DECREF (v );
1347
- return -1 ;
1411
+ goto error ;
1348
1412
}
1349
1413
Py_DECREF (v );
1350
1414
}
1415
+ Py_XDECREF (cache );
1351
1416
return i ;
1417
+ error :
1418
+ Py_XDECREF (cache );
1419
+ return -1 ;
1352
1420
}
1353
1421
1354
1422
static char _mysql_ResultObject_fetch_row__doc__ [] =
@@ -1366,15 +1434,7 @@ _mysql_ResultObject_fetch_row(
1366
1434
PyObject * args ,
1367
1435
PyObject * kwargs )
1368
1436
{
1369
- typedef PyObject * _PYFUNC (_mysql_ResultObject * , MYSQL_ROW );
1370
- static char * kwlist [] = { "maxrows" , "how" , NULL };
1371
- static _PYFUNC * row_converters [] =
1372
- {
1373
- _mysql_row_to_tuple ,
1374
- _mysql_row_to_dict ,
1375
- _mysql_row_to_dict_old
1376
- };
1377
- _PYFUNC * convert_row ;
1437
+ static char * kwlist [] = {"maxrows" , "how" , NULL };
1378
1438
int maxrows = 1 , how = 0 ;
1379
1439
PyObject * r = NULL ;
1380
1440
@@ -1386,7 +1446,6 @@ _mysql_ResultObject_fetch_row(
1386
1446
PyErr_SetString (PyExc_ValueError , "how out of range" );
1387
1447
return NULL ;
1388
1448
}
1389
- convert_row = row_converters [how ];
1390
1449
if (!maxrows ) {
1391
1450
if (self -> use ) {
1392
1451
maxrows = INT_MAX ;
@@ -1396,7 +1455,7 @@ _mysql_ResultObject_fetch_row(
1396
1455
}
1397
1456
}
1398
1457
if (!(r = PyList_New (0 ))) goto error ;
1399
- Py_ssize_t rowsadded = _mysql__fetch_row (self , r , maxrows , convert_row );
1458
+ Py_ssize_t rowsadded = _mysql__fetch_row (self , r , maxrows , how );
1400
1459
if (rowsadded == -1 ) goto error ;
1401
1460
1402
1461
/* DB-API allows return rows as list.
0 commit comments