Discard any result produced by cursor.executemany()

This commit is contained in:
Daniele Varrazzo 2012-10-11 22:17:47 +01:00
parent 20d3344972
commit 4ddad45feb
5 changed files with 44 additions and 28 deletions

1
NEWS
View File

@ -14,6 +14,7 @@ What's new in psycopg 2.4.6
RealDictConnection and Cursor (ticket #114). RealDictConnection and Cursor (ticket #114).
- connect() raises an exception instead of swallowing keyword arguments - connect() raises an exception instead of swallowing keyword arguments
when a connection string is specified as well (ticket #131). when a connection string is specified as well (ticket #131).
- Discard any result produced by 'executemany()' (ticket #133).
What's new in psycopg 2.4.5 What's new in psycopg 2.4.5

View File

@ -896,7 +896,7 @@ conn_poll(connectionObject *self)
/* fetch the tuples (if there are any) and build the result. We /* fetch the tuples (if there are any) and build the result. We
* don't care if pq_fetch return 0 or 1, but if there was an error, * don't care if pq_fetch return 0 or 1, but if there was an error,
* we want to signal it to the caller. */ * we want to signal it to the caller. */
if (pq_fetch(curs) == -1) { if (pq_fetch(curs, 0) == -1) {
res = PSYCO_POLL_ERROR; res = PSYCO_POLL_ERROR;
} }

View File

@ -63,7 +63,7 @@ psyco_curs_close(cursorObject *self, PyObject *args)
EXC_IF_NO_MARK(self); EXC_IF_NO_MARK(self);
PyOS_snprintf(buffer, 127, "CLOSE \"%s\"", self->name); PyOS_snprintf(buffer, 127, "CLOSE \"%s\"", self->name);
if (pq_execute(self, buffer, 0) == -1) return NULL; if (pq_execute(self, buffer, 0, 0) == -1) return NULL;
} }
self->closed = 1; self->closed = 1;
@ -365,7 +365,8 @@ _psyco_curs_merge_query_args(cursorObject *self,
RAISES_NEG static int RAISES_NEG static int
_psyco_curs_execute(cursorObject *self, _psyco_curs_execute(cursorObject *self,
PyObject *operation, PyObject *vars, long int async) PyObject *operation, PyObject *vars,
long int async, int no_result)
{ {
int res = -1; int res = -1;
int tmp; int tmp;
@ -432,7 +433,7 @@ _psyco_curs_execute(cursorObject *self,
/* At this point, the SQL statement must be str, not unicode */ /* At this point, the SQL statement must be str, not unicode */
tmp = pq_execute(self, Bytes_AS_STRING(self->query), async); tmp = pq_execute(self, Bytes_AS_STRING(self->query), async, no_result);
Dprintf("psyco_curs_execute: res = %d, pgres = %p", tmp, self->pgres); Dprintf("psyco_curs_execute: res = %d, pgres = %p", tmp, self->pgres);
if (tmp < 0) { goto exit; } if (tmp < 0) { goto exit; }
@ -479,7 +480,7 @@ psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs)
EXC_IF_ASYNC_IN_PROGRESS(self, execute); EXC_IF_ASYNC_IN_PROGRESS(self, execute);
EXC_IF_TPC_PREPARED(self->conn, execute); EXC_IF_TPC_PREPARED(self->conn, execute);
if (0 > _psyco_curs_execute(self, operation, vars, self->conn->async)) { if (0 > _psyco_curs_execute(self, operation, vars, self->conn->async, 0)) {
return NULL; return NULL;
} }
@ -524,7 +525,7 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs)
} }
while ((v = PyIter_Next(vars)) != NULL) { while ((v = PyIter_Next(vars)) != NULL) {
if (0 > _psyco_curs_execute(self, operation, v, 0)) { if (0 > _psyco_curs_execute(self, operation, v, 0, 1)) {
Py_DECREF(v); Py_DECREF(v);
Py_XDECREF(iter); Py_XDECREF(iter);
return NULL; return NULL;
@ -655,7 +656,7 @@ _psyco_curs_prefetch(cursorObject *self)
if (self->pgres == NULL) { if (self->pgres == NULL) {
Dprintf("_psyco_curs_prefetch: trying to fetch data"); Dprintf("_psyco_curs_prefetch: trying to fetch data");
do { do {
i = pq_fetch(self); i = pq_fetch(self, 0);
Dprintf("_psycopg_curs_prefetch: result = %d", i); Dprintf("_psycopg_curs_prefetch: result = %d", i);
} while(i == 1); } while(i == 1);
} }
@ -757,7 +758,7 @@ psyco_curs_fetchone(cursorObject *self, PyObject *args)
EXC_IF_ASYNC_IN_PROGRESS(self, fetchone); EXC_IF_ASYNC_IN_PROGRESS(self, fetchone);
EXC_IF_TPC_PREPARED(self->conn, fetchone); EXC_IF_TPC_PREPARED(self->conn, fetchone);
PyOS_snprintf(buffer, 127, "FETCH FORWARD 1 FROM \"%s\"", self->name); PyOS_snprintf(buffer, 127, "FETCH FORWARD 1 FROM \"%s\"", self->name);
if (pq_execute(self, buffer, 0) == -1) return NULL; if (pq_execute(self, buffer, 0, 0) == -1) return NULL;
if (_psyco_curs_prefetch(self) < 0) return NULL; if (_psyco_curs_prefetch(self) < 0) return NULL;
} }
@ -808,7 +809,7 @@ psyco_curs_next_named(cursorObject *self)
PyOS_snprintf(buffer, 127, "FETCH FORWARD %ld FROM \"%s\"", PyOS_snprintf(buffer, 127, "FETCH FORWARD %ld FROM \"%s\"",
self->itersize, self->name); self->itersize, self->name);
if (pq_execute(self, buffer, 0) == -1) return NULL; if (pq_execute(self, buffer, 0, 0) == -1) return NULL;
if (_psyco_curs_prefetch(self) < 0) return NULL; if (_psyco_curs_prefetch(self) < 0) return NULL;
} }
@ -877,7 +878,7 @@ psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
EXC_IF_TPC_PREPARED(self->conn, fetchone); EXC_IF_TPC_PREPARED(self->conn, fetchone);
PyOS_snprintf(buffer, 127, "FETCH FORWARD %d FROM \"%s\"", PyOS_snprintf(buffer, 127, "FETCH FORWARD %d FROM \"%s\"",
(int)size, self->name); (int)size, self->name);
if (pq_execute(self, buffer, 0) == -1) { goto exit; } if (pq_execute(self, buffer, 0, 0) == -1) { goto exit; }
if (_psyco_curs_prefetch(self) < 0) { goto exit; } if (_psyco_curs_prefetch(self) < 0) { goto exit; }
} }
@ -952,7 +953,7 @@ psyco_curs_fetchall(cursorObject *self, PyObject *args)
EXC_IF_ASYNC_IN_PROGRESS(self, fetchall); EXC_IF_ASYNC_IN_PROGRESS(self, fetchall);
EXC_IF_TPC_PREPARED(self->conn, fetchall); EXC_IF_TPC_PREPARED(self->conn, fetchall);
PyOS_snprintf(buffer, 127, "FETCH FORWARD ALL FROM \"%s\"", self->name); PyOS_snprintf(buffer, 127, "FETCH FORWARD ALL FROM \"%s\"", self->name);
if (pq_execute(self, buffer, 0) == -1) { goto exit; } if (pq_execute(self, buffer, 0, 0) == -1) { goto exit; }
if (_psyco_curs_prefetch(self) < 0) { goto exit; } if (_psyco_curs_prefetch(self) < 0) { goto exit; }
} }
@ -1045,7 +1046,8 @@ psyco_curs_callproc(cursorObject *self, PyObject *args)
if (!(operation = Bytes_FromString(sql))) { goto exit; } if (!(operation = Bytes_FromString(sql))) { goto exit; }
if (0 <= _psyco_curs_execute(self, operation, parameters, self->conn->async)) { if (0 <= _psyco_curs_execute(self, operation, parameters,
self->conn->async, 0)) {
Py_INCREF(parameters); Py_INCREF(parameters);
res = parameters; res = parameters;
} }
@ -1172,7 +1174,7 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
else { else {
PyOS_snprintf(buffer, 127, "MOVE %d FROM \"%s\"", value, self->name); PyOS_snprintf(buffer, 127, "MOVE %d FROM \"%s\"", value, self->name);
} }
if (pq_execute(self, buffer, 0) == -1) return NULL; if (pq_execute(self, buffer, 0, 0) == -1) return NULL;
if (_psyco_curs_prefetch(self) < 0) return NULL; if (_psyco_curs_prefetch(self) < 0) return NULL;
} }
@ -1352,7 +1354,7 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
Py_INCREF(file); Py_INCREF(file);
self->copyfile = file; self->copyfile = file;
if (pq_execute(self, query, 0) >= 0) { if (pq_execute(self, query, 0, 0) >= 0) {
res = Py_None; res = Py_None;
Py_INCREF(Py_None); Py_INCREF(Py_None);
} }
@ -1448,7 +1450,7 @@ psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
Py_INCREF(file); Py_INCREF(file);
self->copyfile = file; self->copyfile = file;
if (pq_execute(self, query, 0) >= 0) { if (pq_execute(self, query, 0, 0) >= 0) {
res = Py_None; res = Py_None;
Py_INCREF(Py_None); Py_INCREF(Py_None);
} }
@ -1522,7 +1524,7 @@ psyco_curs_copy_expert(cursorObject *self, PyObject *args, PyObject *kwargs)
self->copyfile = file; self->copyfile = file;
/* At this point, the SQL statement must be str, not unicode */ /* At this point, the SQL statement must be str, not unicode */
if (pq_execute(self, Bytes_AS_STRING(sql), 0) >= 0) { if (pq_execute(self, Bytes_AS_STRING(sql), 0, 0) >= 0) {
res = Py_None; res = Py_None;
Py_INCREF(res); Py_INCREF(res);
} }

View File

@ -829,12 +829,16 @@ pq_flush(connectionObject *conn)
} }
/* pq_execute - execute a query, possibly asynchronously /* pq_execute - execute a query, possibly asynchronously
*
this fucntion locks the connection object * With no_result an eventual query result is discarded.
this function call Py_*_ALLOW_THREADS macros */ * Currently only used to implement cursor.executemany().
*
* This function locks the connection object
* This function call Py_*_ALLOW_THREADS macros
*/
RAISES_NEG int RAISES_NEG int
pq_execute(cursorObject *curs, const char *query, int async) pq_execute(cursorObject *curs, const char *query, int async, int no_result)
{ {
PGresult *pgres = NULL; PGresult *pgres = NULL;
char *error = NULL; char *error = NULL;
@ -938,7 +942,7 @@ pq_execute(cursorObject *curs, const char *query, int async)
to respect the old DBAPI-2.0 compatible behaviour */ to respect the old DBAPI-2.0 compatible behaviour */
if (async == 0) { if (async == 0) {
Dprintf("pq_execute: entering syncronous DBAPI compatibility mode"); Dprintf("pq_execute: entering syncronous DBAPI compatibility mode");
if (pq_fetch(curs) < 0) return -1; if (pq_fetch(curs, no_result) < 0) return -1;
} }
else { else {
PyObject *tmp; PyObject *tmp;
@ -1399,7 +1403,7 @@ exit:
} }
int int
pq_fetch(cursorObject *curs) pq_fetch(cursorObject *curs, int no_result)
{ {
int pgstatus, ex = -1; int pgstatus, ex = -1;
const char *rowcount; const char *rowcount;
@ -1463,10 +1467,18 @@ pq_fetch(cursorObject *curs)
break; break;
case PGRES_TUPLES_OK: case PGRES_TUPLES_OK:
Dprintf("pq_fetch: data from a SELECT (got tuples)"); if (!no_result) {
Dprintf("pq_fetch: got tuples");
curs->rowcount = PQntuples(curs->pgres); curs->rowcount = PQntuples(curs->pgres);
if (0 == _pq_fetch_tuples(curs)) { ex = 0; } if (0 == _pq_fetch_tuples(curs)) { ex = 0; }
/* don't clear curs->pgres, because it contains the results! */ /* don't clear curs->pgres, because it contains the results! */
}
else {
Dprintf("pq_fetch: got tuples, discarding them");
IFCLEARPGRES(curs->pgres);
curs->rowcount = -1;
ex = 0;
}
break; break;
case PGRES_EMPTY_QUERY: case PGRES_EMPTY_QUERY:

View File

@ -35,8 +35,9 @@
/* exported functions */ /* exported functions */
HIDDEN PGresult *pq_get_last_result(connectionObject *conn); HIDDEN PGresult *pq_get_last_result(connectionObject *conn);
RAISES_NEG HIDDEN int pq_fetch(cursorObject *curs); RAISES_NEG HIDDEN int pq_fetch(cursorObject *curs, int no_result);
RAISES_NEG HIDDEN int pq_execute(cursorObject *curs, const char *query, int async); RAISES_NEG HIDDEN int pq_execute(cursorObject *curs, const char *query,
int async, int no_result);
HIDDEN int pq_send_query(connectionObject *conn, const char *query); HIDDEN int pq_send_query(connectionObject *conn, const char *query);
HIDDEN int pq_begin_locked(connectionObject *conn, PGresult **pgres, HIDDEN int pq_begin_locked(connectionObject *conn, PGresult **pgres,
char **error, PyThreadState **tstate); char **error, PyThreadState **tstate);