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

Reply via email to