summaryrefslogtreecommitdiff
path: root/psycopg
diff options
context:
space:
mode:
authorFederico Di Gregorio <fog@initd.org>2006-01-05 08:13:03 +0000
committerFederico Di Gregorio <fog@initd.org>2006-01-05 08:13:03 +0000
commit96ff591d7996e05b25be0afa5d999bb6028255e1 (patch)
tree7bc752fd31c984033a659fc332895e98df56fd2b /psycopg
parentd5674253ca184e9ddedec34a3475104dbc6e2962 (diff)
downloadpsycopg2-96ff591d7996e05b25be0afa5d999bb6028255e1.tar.gz
Extra attributes for ProgrammingError exception.
Diffstat (limited to 'psycopg')
-rw-r--r--psycopg/cursor_type.c46
-rw-r--r--psycopg/microprotocols.c2
-rw-r--r--psycopg/pqpath.c30
-rw-r--r--psycopg/psycopg.h6
-rw-r--r--psycopg/psycopgmodule.c40
5 files changed, 93 insertions, 31 deletions
diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c
index 2aadc78..d6776d9 100644
--- a/psycopg/cursor_type.c
+++ b/psycopg/cursor_type.c
@@ -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;
}
diff --git a/psycopg/microprotocols.c b/psycopg/microprotocols.c
index 4f97279..73abbfc 100644
--- a/psycopg/microprotocols.c
+++ b/psycopg/microprotocols.c
@@ -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;
}
diff --git a/psycopg/pqpath.c b/psycopg/pqpath.c
index 4ee8781..7bceed2 100644
--- a/psycopg/pqpath.c
+++ b/psycopg/pqpath.c
@@ -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
diff --git a/psycopg/psycopg.h b/psycopg/psycopg.h
index 4da312e..7a7a202 100644
--- a/psycopg/psycopg.h
+++ b/psycopg/psycopg.h
@@ -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
diff --git a/psycopg/psycopgmodule.c b/psycopg/psycopgmodule.c
index bef1e7a..58a57f9 100644
--- a/psycopg/psycopgmodule.c
+++ b/psycopg/psycopgmodule.c
@@ -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. */