Re: [PATCHES] libpq events patch (with sgml docs) - Mailing list pgsql-hackers
From | Andrew Chernow |
---|---|
Subject | Re: [PATCHES] libpq events patch (with sgml docs) |
Date | |
Msg-id | 48D3EBEC.1040503@esilo.com Whole thread Raw |
In response to | Re: [PATCHES] libpq events patch (with sgml docs) (Tom Lane <tgl@sss.pgh.pa.us>) |
Responses |
Re: [PATCHES] libpq events patch (with sgml docs)
("Merlin Moncure" <mmoncure@gmail.com>)
Re: [PATCHES] libpq events patch (with sgml docs) (Tom Lane <tgl@sss.pgh.pa.us>) Re: [PATCHES] libpq events patch (with sgml docs) (Tom Lane <tgl@sss.pgh.pa.us>) |
List | pgsql-hackers |
Tom Lane wrote: > > I'll go ahead and apply this patch in a little bit, but if you concur > with the above reasoning, please put together a followon patch to add > such a function. > > regards, tom lane > > I attached a patch. You have to copy the events in PQmakeEmptyPGResult because there is no where else to do this, other than copyresult but that is different because it copies from a result not a conn. PQmakeEmptyPGResult - must copy events here PQsetResultAttrs - set attributes PQsetvalue - set tuple values PQfireResultCreateEvents(conn,res) - now fire resultcreate event PQgetResult now calls PQfireResultCreateEvents. BTW, the event system might be an alternative solution for PGNoticeHooks (PGEVT_NOTICE). -- Andrew Chernow eSilo, LLC every bit counts http://www.esilo.com/ Index: doc/src/sgml/libpq.sgml =================================================================== RCS file: /projects/cvsroot/pgsql/doc/src/sgml/libpq.sgml,v retrieving revision 1.262 diff -C6 -r1.262 libpq.sgml *** doc/src/sgml/libpq.sgml 19 Sep 2008 16:40:40 -0000 1.262 --- doc/src/sgml/libpq.sgml 19 Sep 2008 18:05:55 -0000 *************** *** 4592,4604 **** <parameter>conn</parameter> is not null and <parameter>status</> indicates an error, the current error message of the specified connection is copied into the <structname>PGresult</structname>. Also, if <parameter>conn</parameter> is not null, any event handlers registered in the connection are copied into the <structname>PGresult</structname> (but they don't get ! <literal>PGEVT_RESULTCREATE</> calls). Note that <function>PQclear</function> should eventually be called on the object, just as with a <structname>PGresult</structname> returned by <application>libpq</application> itself. </para> </listitem> </varlistentry> --- 4592,4606 ---- <parameter>conn</parameter> is not null and <parameter>status</> indicates an error, the current error message of the specified connection is copied into the <structname>PGresult</structname>. Also, if <parameter>conn</parameter> is not null, any event handlers registered in the connection are copied into the <structname>PGresult</structname> (but they don't get ! <literal>PGEVT_RESULTCREATE</> calls). Although, ! <function>PQfireResultCreateEvents</function> can be used to fire ! <literal>PGEVT_RESULTCREATE</> events. Note that <function>PQclear</function> should eventually be called on the object, just as with a <structname>PGresult</structname> returned by <application>libpq</application> itself. </para> </listitem> </varlistentry> *************** *** 5242,5253 **** --- 5244,5279 ---- void *PQresultInstanceData(const PGresult *res, PGEventProc proc); </synopsis> </para> </listitem> </varlistentry> </variablelist> + + <varlistentry> + <term> + <function>PQfireResultCreateEvents</function> + <indexterm> + <primary>PQfireResultCreateEvents</primary> + </indexterm> + </term> + <listitem> + <para> + Manually fires a <literal>PGEVT_RESULTCREATE</literal> event. This is + useful for applications that create a result using + <function>PQmakeEmptyPGResult</function>, which does not fire a + <literal>PGEVT_RESULTCREATE</literal> event. It allows an application + to create the result, fill it and then fire the creation event. This + returns non-zero for success and zero for failure. + + <synopsis> + int PQfireResultCreateEvents(const PGconn conn, PGresult *res); + </synopsis> + </para> + </listitem> + </varlistentry> + </variablelist> </sect2> <sect2 id="libpq-events-example"> <title>Event Example</title> <para> Index: src/interfaces/libpq/exports.txt =================================================================== RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/exports.txt,v retrieving revision 1.20 diff -C6 -r1.20 exports.txt *** src/interfaces/libpq/exports.txt 17 Sep 2008 04:31:08 -0000 1.20 --- src/interfaces/libpq/exports.txt 19 Sep 2008 18:05:55 -0000 *************** *** 147,152 **** --- 147,153 ---- PQresultAlloc 145 PQregisterEventProc 146 PQinstanceData 147 PQsetInstanceData 148 PQresultInstanceData 149 PQresultSetInstanceData 150 + PQfireResultCreateEvents 151 Index: src/interfaces/libpq/fe-exec.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v retrieving revision 1.199 diff -C6 -r1.199 fe-exec.c *** src/interfaces/libpq/fe-exec.c 19 Sep 2008 16:40:40 -0000 1.199 --- src/interfaces/libpq/fe-exec.c 19 Sep 2008 18:05:55 -0000 *************** *** 1595,1630 **** libpq_gettext("unexpected asyncStatus: %d\n"), (int) conn->asyncStatus); res = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR); break; } ! if (res) ! { ! int i; ! ! for (i = 0; i < res->nEvents; i++) ! { ! PGEventResultCreate evt; ! ! evt.conn = conn; ! evt.result = res; ! if (!res->events[i].proc(PGEVT_RESULTCREATE, &evt, ! res->events[i].passThrough)) ! { ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n"), ! res->events[i].name); ! pqSetResultError(res, conn->errorMessage.data); ! res->resultStatus = PGRES_FATAL_ERROR; ! break; ! } ! res->events[i].resultInitialized = TRUE; ! } ! } ! return res; } /* * PQexec --- 1595,1608 ---- libpq_gettext("unexpected asyncStatus: %d\n"), (int) conn->asyncStatus); res = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR); break; } ! /* Function performs error handling: message and resultStatus. */ ! (void) PQfireResultCreateEvents(conn, res); return res; } /* * PQexec Index: src/interfaces/libpq/libpq-events.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/libpq-events.c,v retrieving revision 1.2 diff -C6 -r1.2 libpq-events.c *** src/interfaces/libpq/libpq-events.c 19 Sep 2008 16:40:40 -0000 1.2 --- src/interfaces/libpq/libpq-events.c 19 Sep 2008 18:05:55 -0000 *************** *** 172,177 **** --- 172,209 ---- for (i = 0; i < result->nEvents; i++) if (result->events[i].proc == proc) return result->events[i].data; return NULL; } + + int + PQfireResultCreateEvents(const PGconn *conn, PGresult *res) + { + int i; + + if (!conn || !res) + return FALSE; + + for (i = 0; i < res->nEvents; i++) + { + PGEventResultCreate evt; + + evt.conn = conn; + evt.result = res; + if (!res->events[i].proc(PGEVT_RESULTCREATE, &evt, + res->events[i].passThrough)) + { + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n"), + res->events[i].name); + pqSetResultError(res, conn->errorMessage.data); + res->resultStatus = PGRES_FATAL_ERROR; + return FALSE; + } + + res->events[i].resultInitialized = TRUE; + } + + return TRUE; + } + Index: src/interfaces/libpq/libpq-events.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/libpq-events.h,v retrieving revision 1.1 diff -C6 -r1.1 libpq-events.h *** src/interfaces/libpq/libpq-events.h 17 Sep 2008 04:31:08 -0000 1.1 --- src/interfaces/libpq/libpq-events.h 19 Sep 2008 18:05:55 -0000 *************** *** 81,91 **** --- 81,93 ---- /* Sets the PGresult instance data for the provided proc to data. */ extern int PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *data); /* Gets the PGresult instance data for the provided proc. */ extern void *PQresultInstanceData(const PGresult *result, PGEventProc proc); + extern int PQfireResultCreateEvents(const PGconn *conn, PGresult *res); + #ifdef __cplusplus } #endif #endif /* LIBPQ_EVENTS_H */
pgsql-hackers by date: