Add a PQfireResultCreateEvents function to allow applications to mimic the
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 19 Sep 2008 20:06:13 +0000 (20:06 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 19 Sep 2008 20:06:13 +0000 (20:06 +0000)
sequence of operations that libpq goes through while creating a PGresult.
Also, remove ill-considered "const" decoration on parameters passed to
event procedures.

doc/src/sgml/libpq.sgml
src/interfaces/libpq/exports.txt
src/interfaces/libpq/libpq-events.c
src/interfaces/libpq/libpq-events.h

index b72124b765fa344d2b194b0ede5be97f0f4cbe05..b71bf4d43a85ad0af1a119875b3928b73c5ed77f 100644 (file)
@@ -4592,10 +4592,11 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>);
       <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
+      Also, if <parameter>conn</parameter> is not null, any event procedures
       registered in the connection are copied into the
-      <structname>PGresult</structname> (but they don't get
-      <literal>PGEVT_RESULTCREATE</> calls).
+      <structname>PGresult</structname>.  (They do not get
+      <literal>PGEVT_RESULTCREATE</> calls, but see
+      <function>PQfireResultCreateEvents</function>.)
       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.
@@ -4603,6 +4604,46 @@ char *pg_encoding_to_char(int <replaceable>encoding_id</replaceable>);
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term>
+     <function>PQfireResultCreateEvents</function>
+     <indexterm>
+      <primary>PQfireResultCreateEvents</primary>
+     </indexterm>
+    </term>
+    <listitem>
+     <para>
+      Fires a <literal>PGEVT_RESULTCREATE</literal> event (see <xref
+      linkend="libpq-events">) for each event procedure registered in the
+      <structname>PGresult</structname> object.  Returns non-zero for success,
+      zero if any event procedure fails.
+
+      <synopsis>
+       int PQfireResultCreateEvents(PGconn *conn, PGresult *res);
+      </synopsis>
+     </para>
+
+     <para>
+      The <literal>conn</> argument is passed through to event procedures
+      but not used directly.  It can be <literal>NULL</> if the event
+      procedures won't use it.
+     </para>
+
+     <para>
+      Event procedures that have already received a
+      <literal>PGEVT_RESULTCREATE</> or <literal>PGEVT_RESULTCOPY</> event
+      for this object are not fired again.
+     </para>
+
+     <para>
+      The main reason that this function is separate from
+      <function>PQmakeEmptyPGResult</function> is that it is often appropriate
+      to create a <structname>PGresult</structname> and fill it with data
+      before invoking the event procedures.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term>
      <function>PQcopyResult</function>
@@ -4904,7 +4945,7 @@ defaultNoticeProcessor(void *arg, const char *message)
       <synopsis>
 typedef struct
 {
-    const PGconn *conn;
+    PGconn *conn;
 } PGEventRegister;
       </synopsis>
 
@@ -4937,7 +4978,7 @@ typedef struct
       <synopsis>
 typedef struct
 {
-    const PGconn *conn;
+    PGconn *conn;
 } PGEventConnReset;
       </synopsis>
 
@@ -4967,7 +5008,7 @@ typedef struct
       <synopsis>
 typedef struct
 {
-    const PGconn *conn;
+    PGconn *conn;
 } PGEventConnDestroy;
       </synopsis>
 
@@ -4995,7 +5036,7 @@ typedef struct
       <synopsis>
 typedef struct
 {
-    const PGconn *conn;
+    PGconn *conn;
     PGresult *result;
 } PGEventResultCreate;
       </synopsis>
@@ -5063,7 +5104,7 @@ typedef struct
       <synopsis>
 typedef struct
 {
-    const PGresult *result;
+    PGresult *result;
 } PGEventResultDestroy;
       </synopsis>
 
index 3034a17adf238c7b674b1bb4ad91e6853d3f5e69..ef43d6baea562acf160a50c90df77eb09c32a217 100644 (file)
@@ -150,3 +150,4 @@ PQinstanceData            147
 PQsetInstanceData         148
 PQresultInstanceData      149
 PQresultSetInstanceData   150
+PQfireResultCreateEvents  151
index 8a894ff89e5f72fc84d76528c855612773b46761..a50a18fdbd49c819dd2aba8c74a149db455e4fcc 100644 (file)
@@ -175,3 +175,35 @@ PQresultInstanceData(const PGresult *result, PGEventProc proc)
 
        return NULL;
 }
+
+/*
+ * Fire RESULTCREATE events for an application-created PGresult.
+ *
+ * The conn argument can be NULL if event procedures won't use it.
+ */
+int
+PQfireResultCreateEvents(PGconn *conn, PGresult *res)
+{
+       int i;
+
+       if (!res)
+               return FALSE;
+
+       for (i = 0; i < res->nEvents; i++)
+       {
+               if (!res->events[i].resultInitialized)
+               {
+                       PGEventResultCreate evt;
+
+                       evt.conn = conn;
+                       evt.result = res;
+                       if (!res->events[i].proc(PGEVT_RESULTCREATE, &evt,
+                                                                        res->events[i].passThrough))
+                               return FALSE;
+
+                       res->events[i].resultInitialized = TRUE;
+               }
+       }
+
+       return TRUE;
+}
index 7eaad9c9ae79fc4b1383bcb2da59cb7260bdb416..aa54b3f3d801b26e8744519ad0bb562e2902d022 100644 (file)
@@ -36,22 +36,22 @@ typedef enum
 
 typedef struct
 {
-       const PGconn *conn;
+       PGconn *conn;
 } PGEventRegister;
 
 typedef struct
 {
-       const PGconn *conn;
+       PGconn *conn;
 } PGEventConnReset;
 
 typedef struct
 {
-       const PGconn *conn;
+       PGconn *conn;
 } PGEventConnDestroy;
 
 typedef struct
 {
-       const PGconn *conn;
+       PGconn *conn;
        PGresult *result;
 } PGEventResultCreate;
 
@@ -63,7 +63,7 @@ typedef struct
 
 typedef struct
 {
-       const PGresult *result;
+       PGresult *result;
 } PGEventResultDestroy;
 
 typedef int (*PGEventProc) (PGEventId evtId, void *evtInfo, void *passThrough);
@@ -84,6 +84,9 @@ extern int    PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *dat
 /* Gets the PGresult instance data for the provided proc. */
 extern void *PQresultInstanceData(const PGresult *result, PGEventProc proc);
 
+/* Fires RESULTCREATE events for an application-created PGresult. */
+extern int     PQfireResultCreateEvents(PGconn *conn, PGresult *res);
+
 #ifdef __cplusplus
 }
 #endif