From: Andrew Chernow <ac@esilo.com>
To: Tom Lane <tgl@sss.pgh.pa.us>
Cc: Alvaro Herrera <alvherre@commandprompt.com>
Cc: PostgreSQL-development <pgsql-hackers@postgresql.org>
Cc: Merlin Moncure <mmoncure@gmail.com>
Subject: Re: [PATCHES] libpq events patch (with sgml docs)
Date: Fri, 19 Sep 2008 14:14:04 -0400
Message-ID: <48D3EBEC.1040503@esilo.com> (raw)
In-Reply-To: <28666.1221840662@sss.pgh.pa.us>
References: <48C18533.2000204@esilo.com>
<20080905192215.GK4353@alvh.no-ip.org>
<48C18B48.509@esilo.com>
<20080905194853.GL4353@alvh.no-ip.org>
<48C191A7.3000205@esilo.com>
<20080905201504.GM4353@alvh.no-ip.org>
<48C19759.90402@esilo.com>
<27615.1221619326@sss.pgh.pa.us>
<48D072E3.6010703@esilo.com>
<28673.1221622817@sss.pgh.pa.us>
<48D080B0.6070104@esilo.com>
<454.1221626213@sss.pgh.pa.us>
<48D0DFBE.9050900@esilo.com>
<8872.1221653812@sss.pgh.pa.us>
<48D1041D.5070808@esilo.com>
<10839.1221658586@sss.pgh.pa.us>
<48D11443.4010608@esilo.com>
<48D11631.8070709@esilo.com>
<28666.1221840662@sss.pgh.pa.us>
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/Attachments:pgevents.patch (text/plain, 7.3K) download
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 */
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-patches@postgresql.org
Cc: ac@esilo.com, tgl@sss.pgh.pa.us, alvherre@commandprompt.com, pgsql-hackers@postgresql.org, mmoncure@gmail.com
Subject: Re: [PATCHES] libpq events patch (with sgml docs)
In-Reply-To: <48D3EBEC.1040503@esilo.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox