Hi,
I was using PyGreSQL in one of my projects here, and
it was _really_ inconvenient that there was no way of
fetching NOTICEs and INFOs that came from the server.
Therefore I added such capability to the connection
object (pgobject), by means of (1) registering a
NoticeProcessor kind of callback which stores incoming
messages to the connection-specific circular buffer and
(2) method for fetching the buffered messages.
In the client python code it then looks like:
conn = connect(...)
conn.execute(...)
x = conn.notices()
now x is like [ "NOTICE: ('foo',)", "NOTICE: ('bar',)", ... ]
x = conn.notices()
now x is [], because notices() also clears the buffer.
The patch (against version 3.7) is included below.
Sincerely,
Dmitry Dvoinikov
http://www.targeted.org/
========================== CUT HERE ==========================
*** pgmodule.c.orig Wed Sep 07 16:29:25 2005
--- pgmodule.c Tue Nov 01 18:10:03 2005
***************
*** 91,96 ****
--- 91,100 ----
#define DEFAULT_VARS 1 /* enables default variables use */
#endif /* NO_DEF_VAR */
+ #ifndef NO_NOTICES
+ #define HANDLE_NOTICES 1 /* enables notices handling */
+ #endif /* NO_NOTICES */
+
#ifdef MS_WIN32
#define NO_SNPRINTF 1
#endif
***************
*** 116,121 ****
--- 120,130 ----
static PyObject *pg_default_passwd; /* default password */
#endif /* DEFAULT_VARS */
+ #ifdef HANDLE_NOTICES
+ #define MAX_BUFFERED_NOTICES 101 /* max notices (+1) to keep for
each connection */
+ static void notice_processor(void * arg, const char * message);
+ #endif /* HANDLE_NOTICES */
+
DL_EXPORT(void) init_pg(void);
int *get_type_array(PGresult *result, int nfields);
***************
*** 130,135 ****
--- 139,149 ----
int valid; /* validity flag */
PGconn *cnx; /* PostGres connection handle */
PGresult *last_result; /* last result content */
+ #ifdef HANDLE_NOTICES
+ char **notices; /* dynamically allocated circular
buffer for notices */
+ int notices_first; /* index of first filled index
in notices */
+ int notices_next; /* index of first free index in
notices */
+ #endif /* HANDLE_NOTICES */
} pgobject;
staticforward PyTypeObject PgType;
***************
*** 147,152 ****
--- 161,171 ----
pgobj->valid = 1;
pgobj->last_result = NULL;
pgobj->cnx = NULL;
+ #ifdef HANDLE_NOTICES
+ pgobj->notices = malloc(sizeof(char*) * MAX_BUFFERED_NOTICES);
+ pgobj->notices_first = 0;
+ pgobj->notices_next = 0;
+ #endif /* HANDLE_NOTICES */
return (PyObject *) pgobj;
}
***************
*** 1556,1561 ****
--- 1575,1584 ----
return NULL;
}
+ #ifdef HANDLE_NOTICES
+ PQsetNoticeProcessor(npgobj->cnx, notice_processor, npgobj);
+ #endif /* HANDLE_NOTICES */
+
return (PyObject *) npgobj;
}
***************
*** 1565,1570 ****
--- 1588,1598 ----
static void
pg_dealloc(pgobject * self)
{
+
+ #ifdef HANDLE_NOTICES
+ free(self->notices);
+ #endif /* HANDLE_NOTICES */
+
if (self->cnx)
PQfinish(self->cnx);
***************
*** 2696,2701 ****
--- 2724,2799 ----
}
#endif /* LARGE_OBJECTS */
+ #ifdef HANDLE_NOTICES
+
+ /* fetch accumulated backend notices */
+ static char pg_notices__doc__[] =
+ "notices() -- returns and clears the list of currently accumulated backend
notices for the connection.";
+
+ static void
+ notice_processor(void * arg, const char * message)
+ {
+
+ pgobject *pgobj = (pgobject *)arg;
+
+ /* skip if memory allocation failed */
+ if (pgobj->notices == NULL)
+ {
+ return;
+ }
+
+ pgobj->notices[pgobj->notices_next] = strdup(message);
+ pgobj->notices_next = (pgobj->notices_next + 1) % MAX_BUFFERED_NOTICES;
+ if (pgobj->notices_next == pgobj->notices_first)
+ {
+ free(pgobj->notices[pgobj->notices_first]);
+ pgobj->notices_first = (pgobj->notices_first + 1) %
MAX_BUFFERED_NOTICES;
+ }
+
+ }
+
+ static PyObject *
+ pg_notices(pgobject * self, PyObject * args)
+ {
+
+ PyObject *reslist,
+ *str;
+ int i;
+
+ /* allocate list for result */
+ if ((reslist = PyList_New(0)) == NULL)
+ return NULL;
+
+ /* skip if memory allocation failed */
+ if (self->notices == NULL)
+ {
+ return reslist;
+ }
+
+ /* builds result */
+ while (self->notices_first != self->notices_next)
+ {
+
+ if (self->notices[self->notices_first] != NULL) /* skip if
memory allocation failed */
+ {
+
+ str =
PyString_FromString(self->notices[self->notices_first]);
+ PyList_Append(reslist, str);
+ Py_DECREF(str);
+
+ free(self->notices[self->notices_first]);
+
+ }
+
+ self->notices_first = (self->notices_first + 1) %
MAX_BUFFERED_NOTICES;
+
+ }
+
+ return reslist;
+
+ }
+
+ #endif /* HANDLE_NOTICES */
/* connection object methods */
static struct PyMethodDef pgobj_methods[] = {
***************
*** 2724,2729 ****
--- 2822,2831 ----
{"getlo", (PyCFunction) pg_getlo, 1, pg_getlo__doc__},
{"loimport", (PyCFunction) pg_loimport, 1, pg_loimport__doc__},
#endif /* LARGE_OBJECTS */
+
+ #ifdef HANDLE_NOTICES
+ {"notices", (PyCFunction) pg_notices, 1, pg_notices__doc__},
+ #endif /* HANDLE_NOTICES */
{NULL, NULL} /* sentinel */
};
========================== CUT HERE ==========================
_______________________________________________
PyGreSQL mailing list
[email protected]
http://mailman.vex.net/mailman/listinfo/pygresql