mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-22 17:06:33 +03:00
Added error checking to _pq_fetch_tuples()
This commit is contained in:
parent
c1715f66fe
commit
20f714f17c
122
psycopg/pqpath.c
122
psycopg/pqpath.c
|
@ -893,15 +893,19 @@ pq_get_last_result(connectionObject *conn)
|
|||
1 - result from backend (possibly data is ready)
|
||||
*/
|
||||
|
||||
static void
|
||||
static int
|
||||
_pq_fetch_tuples(cursorObject *curs)
|
||||
{
|
||||
int i, *dsize = NULL;
|
||||
int pgnfields;
|
||||
int pgbintuples;
|
||||
int rv = -1;
|
||||
PyObject *description = NULL;
|
||||
PyObject *casts = NULL;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
pthread_mutex_lock(&(curs->conn->lock));
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
pgnfields = PQnfields(curs->pgres);
|
||||
pgbintuples = PQbinaryTuples(curs->pgres);
|
||||
|
@ -909,20 +913,20 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
curs->notuples = 0;
|
||||
|
||||
/* create the tuple for description and typecasting */
|
||||
Py_BLOCK_THREADS;
|
||||
Py_XDECREF(curs->description);
|
||||
Py_XDECREF(curs->casts);
|
||||
curs->description = PyTuple_New(pgnfields);
|
||||
curs->casts = PyTuple_New(pgnfields);
|
||||
Py_CLEAR(curs->description);
|
||||
Py_CLEAR(curs->casts);
|
||||
if (!(description = PyTuple_New(pgnfields))) { goto exit; }
|
||||
if (!(casts = PyTuple_New(pgnfields))) { goto exit; }
|
||||
curs->columns = pgnfields;
|
||||
Py_UNBLOCK_THREADS;
|
||||
|
||||
/* calculate the display size for each column (cpu intensive, can be
|
||||
switched off at configuration time) */
|
||||
#ifdef PSYCOPG_DISPLAY_SIZE
|
||||
Py_BLOCK_THREADS;
|
||||
dsize = (int *)PyMem_Malloc(pgnfields * sizeof(int));
|
||||
Py_UNBLOCK_THREADS;
|
||||
if (!(dsize = PyMem_New(int, pgnfields))) {
|
||||
PyErr_NoMemory();
|
||||
goto exit;
|
||||
}
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
if (dsize != NULL) {
|
||||
int j, len;
|
||||
for (i=0; i < pgnfields; i++) {
|
||||
|
@ -935,6 +939,7 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
}
|
||||
}
|
||||
}
|
||||
Py_END_ALLOW_THREADS;
|
||||
#endif
|
||||
|
||||
/* calculate various parameters and typecasters */
|
||||
|
@ -943,13 +948,11 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
int fsize = PQfsize(curs->pgres, i);
|
||||
int fmod = PQfmod(curs->pgres, i);
|
||||
|
||||
PyObject *dtitem;
|
||||
PyObject *type;
|
||||
PyObject *dtitem = NULL;
|
||||
PyObject *type = NULL;
|
||||
PyObject *cast = NULL;
|
||||
|
||||
Py_BLOCK_THREADS;
|
||||
|
||||
dtitem = PyTuple_New(7);
|
||||
if (!(dtitem = PyTuple_New(7))) { goto exit; }
|
||||
|
||||
/* fill the right cast function by accessing three different dictionaries:
|
||||
- the per-cursor dictionary, if available (can be NULL or None)
|
||||
|
@ -957,7 +960,9 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
- the global dictionary (at module level)
|
||||
if we get no defined cast use the default one */
|
||||
|
||||
type = PyInt_FromLong(ftype);
|
||||
if (!(type = PyInt_FromLong(ftype))) {
|
||||
goto err_for;
|
||||
}
|
||||
Dprintf("_pq_fetch_tuples: looking for cast %d:", ftype);
|
||||
cast = curs_get_cast(curs, type);
|
||||
|
||||
|
@ -976,16 +981,25 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
cast, Bytes_AS_STRING(((typecastObject*)cast)->name),
|
||||
PQftype(curs->pgres,i));
|
||||
Py_INCREF(cast);
|
||||
PyTuple_SET_ITEM(curs->casts, i, cast);
|
||||
PyTuple_SET_ITEM(casts, i, cast);
|
||||
|
||||
/* 1/ fill the other fields */
|
||||
PyTuple_SET_ITEM(dtitem, 0,
|
||||
conn_text_from_chars(curs->conn, PQfname(curs->pgres, i)));
|
||||
{
|
||||
PyObject *tmp;
|
||||
if (!(tmp = conn_text_from_chars(
|
||||
curs->conn, PQfname(curs->pgres, i)))) {
|
||||
goto err_for;
|
||||
}
|
||||
PyTuple_SET_ITEM(dtitem, 0, tmp);
|
||||
}
|
||||
PyTuple_SET_ITEM(dtitem, 1, type);
|
||||
type = NULL;
|
||||
|
||||
/* 2/ display size is the maximum size of this field result tuples. */
|
||||
if (dsize && dsize[i] >= 0) {
|
||||
PyTuple_SET_ITEM(dtitem, 2, PyInt_FromLong(dsize[i]));
|
||||
PyObject *tmp;
|
||||
if (!(tmp = PyInt_FromLong(dsize[i]))) { goto err_for; }
|
||||
PyTuple_SET_ITEM(dtitem, 2, tmp);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
|
@ -996,21 +1010,35 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
if (fmod > 0) fmod = fmod - sizeof(int);
|
||||
if (fsize == -1) {
|
||||
if (ftype == NUMERICOID) {
|
||||
PyTuple_SET_ITEM(dtitem, 3,
|
||||
PyInt_FromLong((fmod >> 16) & 0xFFFF));
|
||||
PyObject *tmp;
|
||||
if (!(tmp = PyInt_FromLong((fmod >> 16)))) { goto err_for; }
|
||||
PyTuple_SET_ITEM(dtitem, 3, tmp);
|
||||
}
|
||||
else { /* If variable length record, return maximum size */
|
||||
PyTuple_SET_ITEM(dtitem, 3, PyInt_FromLong(fmod));
|
||||
PyObject *tmp;
|
||||
if (!(tmp = PyInt_FromLong(fmod))) { goto err_for; }
|
||||
PyTuple_SET_ITEM(dtitem, 3, tmp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyTuple_SET_ITEM(dtitem, 3, PyInt_FromLong(fsize));
|
||||
PyObject *tmp;
|
||||
if (!(tmp = PyInt_FromLong(fsize))) { goto err_for; }
|
||||
PyTuple_SET_ITEM(dtitem, 3, tmp);
|
||||
}
|
||||
|
||||
/* 4,5/ scale and precision */
|
||||
if (ftype == NUMERICOID) {
|
||||
PyTuple_SET_ITEM(dtitem, 4, PyInt_FromLong((fmod >> 16) & 0xFFFF));
|
||||
PyTuple_SET_ITEM(dtitem, 5, PyInt_FromLong(fmod & 0xFFFF));
|
||||
PyObject *tmp;
|
||||
|
||||
if (!(tmp = PyInt_FromLong((fmod >> 16) & 0xFFFF))) {
|
||||
goto err_for;
|
||||
}
|
||||
PyTuple_SET_ITEM(dtitem, 4, tmp);
|
||||
|
||||
if (!(tmp = PyInt_FromLong(fmod & 0xFFFF))) {
|
||||
PyTuple_SET_ITEM(dtitem, 5, tmp);
|
||||
}
|
||||
PyTuple_SET_ITEM(dtitem, 5, tmp);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
|
@ -1026,30 +1054,36 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
/* Convert into a namedtuple if available */
|
||||
if (Py_None != psyco_DescriptionType) {
|
||||
PyObject *tmp = dtitem;
|
||||
if ((dtitem = PyObject_CallObject(psyco_DescriptionType, tmp))) {
|
||||
Py_DECREF(tmp);
|
||||
}
|
||||
else {
|
||||
/* FIXME: this function is painfully missing any error check.
|
||||
* The caller doesn't expect them, so swallow it. */
|
||||
PyErr_Clear();
|
||||
dtitem = tmp;
|
||||
}
|
||||
dtitem = PyObject_CallObject(psyco_DescriptionType, tmp);
|
||||
Py_DECREF(tmp);
|
||||
if (NULL == dtitem) { goto err_for; }
|
||||
}
|
||||
|
||||
PyTuple_SET_ITEM(curs->description, i, dtitem);
|
||||
PyTuple_SET_ITEM(description, i, dtitem);
|
||||
dtitem = NULL;
|
||||
|
||||
Py_UNBLOCK_THREADS;
|
||||
continue;
|
||||
|
||||
err_for:
|
||||
Py_XDECREF(type);
|
||||
Py_XDECREF(dtitem);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (dsize) {
|
||||
Py_BLOCK_THREADS;
|
||||
PyMem_Free(dsize);
|
||||
Py_UNBLOCK_THREADS;
|
||||
}
|
||||
|
||||
curs->description = description; description = NULL;
|
||||
curs->casts = casts; casts = NULL;
|
||||
rv = 0;
|
||||
|
||||
exit:
|
||||
PyMem_Free(dsize);
|
||||
Py_XDECREF(description);
|
||||
Py_XDECREF(casts);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
pthread_mutex_unlock(&(curs->conn->lock));
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1312,7 +1346,7 @@ pq_fetch(cursorObject *curs)
|
|||
case PGRES_TUPLES_OK:
|
||||
Dprintf("pq_fetch: data from a SELECT (got tuples)");
|
||||
curs->rowcount = PQntuples(curs->pgres);
|
||||
_pq_fetch_tuples(curs); ex = 0;
|
||||
if (0 == _pq_fetch_tuples(curs)) { ex = 0; }
|
||||
/* don't clear curs->pgres, because it contains the results! */
|
||||
break;
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user