mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-01-31 09:24:07 +03:00
Extra attributes for ProgrammingError exception.
This commit is contained in:
parent
d5674253ca
commit
96ff591d79
|
@ -1,5 +1,9 @@
|
|||
2006-01-05 Federico Di Gregorio <fog@initd.org>
|
||||
|
||||
* psycopg/psycopgmodule.c (psyco_set_error): added function to set extra
|
||||
parameters on ProgrammingError instances. Also modified all occurances of
|
||||
PyErr_SetString(ProgrammingError,...) to psycopg_set_error().
|
||||
|
||||
* setup.{cfg,py}: we now use pg_config to locate PostgreSQL libraries
|
||||
and headers (modified patch from lbruno, see #70.)
|
||||
|
||||
|
|
|
@ -241,14 +241,15 @@ _psyco_curs_execute(cursorObject *self,
|
|||
if (self->conn->async_cursor != NULL
|
||||
&& self->conn->async_cursor != (PyObject*)self) {
|
||||
pthread_mutex_unlock(&(self->conn->lock));
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"asynchronous query already in execution");
|
||||
psyco_set_error(ProgrammingError, (PyObject*)self,
|
||||
"asynchronous query already in execution", NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
pthread_mutex_unlock(&(self->conn->lock));
|
||||
|
||||
if (!PyObject_IsTrue(operation)) {
|
||||
PyErr_SetString(ProgrammingError, "can't execute an empty query");
|
||||
psyco_set_error(ProgrammingError, (PyObject*)self,
|
||||
"can't execute an empty query", NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -334,7 +335,8 @@ _psyco_curs_execute(cursorObject *self,
|
|||
if (!strcmp(s, "not enough arguments for format string")
|
||||
|| !strcmp(s, "not all arguments converted")) {
|
||||
Dprintf("psyco_curs_execute: -> got a match");
|
||||
PyErr_SetString(ProgrammingError, s);
|
||||
psyco_set_error(ProgrammingError, (PyObject*)self,
|
||||
s, NULL, NULL);
|
||||
pe = 1;
|
||||
}
|
||||
|
||||
|
@ -403,18 +405,19 @@ psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
|
||||
if (self->name != NULL) {
|
||||
if (self->query != Py_None) {
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"can't call .execute() on named cursors more than once");
|
||||
psyco_set_error(ProgrammingError, (PyObject*)self,
|
||||
"can't call .execute() on named cursors more than once",
|
||||
NULL, NULL);
|
||||
return NULL;
|
||||
}
|
||||
if (self->conn->isolation_level == 0) {
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"can't use a named cursor outside of transactions");
|
||||
psyco_set_error(ProgrammingError, (PyObject*)self,
|
||||
"can't use a named cursor outside of transactions", NULL, NULL);
|
||||
return NULL;
|
||||
}
|
||||
if (self->conn->mark != self->mark) {
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"named cursor isn't valid anymore");
|
||||
psyco_set_error(ProgrammingError, (PyObject*)self,
|
||||
"named cursor isn't valid anymore", NULL, NULL);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -449,8 +452,8 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
EXC_IF_CURS_CLOSED(self);
|
||||
|
||||
if (self->name != NULL) {
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"can't call .executemany() on named cursors");
|
||||
psyco_set_error(ProgrammingError, (PyObject*)self,
|
||||
"can't call .executemany() on named cursors", NULL, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -533,7 +536,8 @@ psyco_curs_mogrify(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
if (!strcmp(s, "not enough arguments for format string")
|
||||
|| !strcmp(s, "not all arguments converted")) {
|
||||
Dprintf("psyco_curs_execute: -> got a match");
|
||||
PyErr_SetString(ProgrammingError, s);
|
||||
psyco_set_error(ProgrammingError, (PyObject*)self,
|
||||
s, NULL, NULL);
|
||||
pe = 1;
|
||||
}
|
||||
|
||||
|
@ -585,8 +589,8 @@ _psyco_curs_prefetch(cursorObject *self)
|
|||
if (self->conn->async_cursor != NULL
|
||||
&& self->conn->async_cursor != (PyObject*)self) {
|
||||
pthread_mutex_unlock(&(self->conn->lock));
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"asynchronous fetch by wrong cursor");
|
||||
psyco_set_error(ProgrammingError, (PyObject*)self,
|
||||
"asynchronous fetch by wrong cursor", NULL, NULL);
|
||||
return -2;
|
||||
}
|
||||
pthread_mutex_unlock(&(self->conn->lock));
|
||||
|
@ -880,8 +884,8 @@ psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
EXC_IF_CURS_CLOSED(self);
|
||||
|
||||
if (self->name != NULL) {
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"can't call .callproc() on named cursors");
|
||||
psyco_set_error(ProgrammingError, (PyObject*)self,
|
||||
"can't call .callproc() on named cursors", NULL, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1003,14 +1007,14 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
} else if (strcmp( mode, "absolute") == 0) {
|
||||
newpos = value;
|
||||
} else {
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"scroll mode must be 'relative' or 'absolute'");
|
||||
psyco_set_error(ProgrammingError, (PyObject*)self,
|
||||
"scroll mode must be 'relative' or 'absolute'", NULL, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (newpos < 0 || newpos >= self->rowcount ) {
|
||||
PyErr_SetString(PyExc_IndexError,
|
||||
"scroll destination out of bounds");
|
||||
psyco_set_error(ProgrammingError, (PyObject*)self,
|
||||
"scroll destination out of bounds", NULL, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
|
|||
}
|
||||
|
||||
/* else set the right exception and return NULL */
|
||||
PyErr_SetString(ProgrammingError, "can't adapt");
|
||||
psyco_set_error(ProgrammingError, NULL, "can't adapt", NULL, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,12 +46,15 @@
|
|||
void
|
||||
pq_raise(connectionObject *conn, cursorObject *curs, PyObject *exc, char *msg)
|
||||
{
|
||||
PyObject *pgc = (PyObject*)curs;
|
||||
|
||||
char *err = NULL;
|
||||
char *err2 = NULL;
|
||||
char *code = NULL;
|
||||
char *buf = NULL;
|
||||
|
||||
if ((conn == NULL && curs == NULL) || (curs != NULL && conn == NULL)) {
|
||||
PyErr_SetString(Error,
|
||||
"psycopg went psycotic and raised a null error");
|
||||
PyErr_SetString(Error, "psycopg went psycotic and raised a null error");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -102,20 +105,31 @@ pq_raise(connectionObject *conn, cursorObject *curs, PyObject *exc, char *msg)
|
|||
else
|
||||
exc = ProgrammingError;
|
||||
}
|
||||
|
||||
/* try to remove the initial "ERROR: " part from the postgresql error */
|
||||
if (err && strlen(err) > 8) err = &(err[8]);
|
||||
|
||||
/* try to remove the initial "ERROR: " part from the postgresql error */
|
||||
if (err && strlen(err) > 8) err2 = &(err[8]);
|
||||
else err2 = err;
|
||||
|
||||
/* if msg is not NULL, add it to the error message, after a '\n' */
|
||||
if (msg && code) {
|
||||
PyErr_Format(exc, "[%s] %s\n%s", code, err, msg);
|
||||
int len = strlen(code) + strlen(err) + strlen(msg) + 5;
|
||||
if ((buf = PyMem_Malloc(len))) {
|
||||
snprintf(buf, len, "[%s] %s\n%s", code, err2, msg);
|
||||
psyco_set_error(exc, pgc, buf, err, code);
|
||||
}
|
||||
}
|
||||
else if (msg) {
|
||||
PyErr_Format(exc, "%s\n%s", err, msg);
|
||||
int len = strlen(err) + strlen(msg) + 2;
|
||||
if ((buf = PyMem_Malloc(len))) {
|
||||
snprintf(buf, len, "%s\n%s", err2, msg);
|
||||
psyco_set_error(exc, pgc, buf, err, code);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(exc, err);
|
||||
psyco_set_error(exc, pgc, err2, err, code);
|
||||
}
|
||||
|
||||
if (buf != NULL) PyMem_Free(buf);
|
||||
}
|
||||
|
||||
/* pq_set_critical, pq_resolve_critical - manage critical errors
|
||||
|
|
|
@ -99,7 +99,11 @@ typedef struct {
|
|||
|
||||
/* the Decimal type, used by the DECIMAL typecaster */
|
||||
extern PyObject *decimalType;
|
||||
|
||||
|
||||
/* some utility functions */
|
||||
extern void psyco_set_error(PyObject *exc, PyObject *curs, char *msg,
|
||||
char *pgerror, char *pgcode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -366,6 +366,46 @@ psyco_errors_set(PyObject *type)
|
|||
PyObject_SetAttrString(type, "NotSupportedError", NotSupportedError);
|
||||
}
|
||||
|
||||
/* psyco_error_new
|
||||
|
||||
Create a new error of the given type with extra attributes. */
|
||||
|
||||
void
|
||||
psyco_set_error(PyObject *exc, PyObject *curs, char *msg,
|
||||
char *pgerror, char *pgcode)
|
||||
{
|
||||
PyObject *t;
|
||||
|
||||
PyObject *err = PyObject_CallFunction(exc, "s", msg);
|
||||
|
||||
if (err) {
|
||||
if (pgerror) {
|
||||
t = PyString_FromString(pgerror);
|
||||
}
|
||||
else {
|
||||
t = Py_None ; Py_INCREF(t);
|
||||
}
|
||||
PyObject_SetAttrString(err, "pgerror", t);
|
||||
Py_DECREF(t);
|
||||
|
||||
if (pgcode) {
|
||||
t = PyString_FromString(pgcode);
|
||||
}
|
||||
else {
|
||||
t = Py_None ; Py_INCREF(t);
|
||||
}
|
||||
PyObject_SetAttrString(err, "pgcode", t);
|
||||
Py_DECREF(t);
|
||||
|
||||
if (curs)
|
||||
PyObject_SetAttrString(err, "cursor", curs);
|
||||
else
|
||||
PyObject_SetAttrString(err, "cursor", Py_None);
|
||||
|
||||
PyErr_SetObject(exc, err);
|
||||
}
|
||||
}
|
||||
|
||||
/* psyco_decimal_init
|
||||
|
||||
Initialize the module's pointer to the decimal type. */
|
||||
|
|
Loading…
Reference in New Issue
Block a user