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 */
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers