Header And Logo

PostgreSQL
| The world's most advanced open source database.

libpq-events.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * libpq-events.c
00004  *    functions for supporting the libpq "events" API
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/interfaces/libpq/libpq-events.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres_fe.h"
00016 
00017 #include "libpq-fe.h"
00018 #include "libpq-int.h"
00019 
00020 
00021 /*
00022  * Registers an event proc with the given PGconn.
00023  *
00024  * The same proc can't be registered more than once in a PGconn.  This
00025  * restriction is required because we use the proc address to identify
00026  * the event for purposes such as PQinstanceData().
00027  *
00028  * The name argument is used within error messages to aid in debugging.
00029  * A name must be supplied, but it needn't be unique.  The string is
00030  * copied, so the passed value needn't be long-lived.
00031  *
00032  * The passThrough argument is an application specific pointer and can be set
00033  * to NULL if not required.  It is passed through to the event proc whenever
00034  * the event proc is called, and is not otherwise touched by libpq.
00035  *
00036  * The function returns a non-zero if successful.  If the function fails,
00037  * zero is returned.
00038  */
00039 int
00040 PQregisterEventProc(PGconn *conn, PGEventProc proc,
00041                     const char *name, void *passThrough)
00042 {
00043     int         i;
00044     PGEventRegister regevt;
00045 
00046     if (!proc || !conn || !name || !*name)
00047         return FALSE;           /* bad arguments */
00048 
00049     for (i = 0; i < conn->nEvents; i++)
00050     {
00051         if (conn->events[i].proc == proc)
00052             return FALSE;       /* already registered */
00053     }
00054 
00055     if (conn->nEvents >= conn->eventArraySize)
00056     {
00057         PGEvent    *e;
00058         int         newSize;
00059 
00060         newSize = conn->eventArraySize ? conn->eventArraySize * 2 : 8;
00061         if (conn->events)
00062             e = (PGEvent *) realloc(conn->events, newSize * sizeof(PGEvent));
00063         else
00064             e = (PGEvent *) malloc(newSize * sizeof(PGEvent));
00065 
00066         if (!e)
00067             return FALSE;
00068 
00069         conn->eventArraySize = newSize;
00070         conn->events = e;
00071     }
00072 
00073     conn->events[conn->nEvents].proc = proc;
00074     conn->events[conn->nEvents].name = strdup(name);
00075     if (!conn->events[conn->nEvents].name)
00076         return FALSE;
00077     conn->events[conn->nEvents].passThrough = passThrough;
00078     conn->events[conn->nEvents].data = NULL;
00079     conn->events[conn->nEvents].resultInitialized = FALSE;
00080     conn->nEvents++;
00081 
00082     regevt.conn = conn;
00083     if (!proc(PGEVT_REGISTER, &regevt, passThrough))
00084     {
00085         conn->nEvents--;
00086         free(conn->events[conn->nEvents].name);
00087         return FALSE;
00088     }
00089 
00090     return TRUE;
00091 }
00092 
00093 /*
00094  * Set some "instance data" for an event within a PGconn.
00095  * Returns nonzero on success, zero on failure.
00096  */
00097 int
00098 PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data)
00099 {
00100     int         i;
00101 
00102     if (!conn || !proc)
00103         return FALSE;
00104 
00105     for (i = 0; i < conn->nEvents; i++)
00106     {
00107         if (conn->events[i].proc == proc)
00108         {
00109             conn->events[i].data = data;
00110             return TRUE;
00111         }
00112     }
00113 
00114     return FALSE;
00115 }
00116 
00117 /*
00118  * Obtain the "instance data", if any, for the event.
00119  */
00120 void *
00121 PQinstanceData(const PGconn *conn, PGEventProc proc)
00122 {
00123     int         i;
00124 
00125     if (!conn || !proc)
00126         return NULL;
00127 
00128     for (i = 0; i < conn->nEvents; i++)
00129     {
00130         if (conn->events[i].proc == proc)
00131             return conn->events[i].data;
00132     }
00133 
00134     return NULL;
00135 }
00136 
00137 /*
00138  * Set some "instance data" for an event within a PGresult.
00139  * Returns nonzero on success, zero on failure.
00140  */
00141 int
00142 PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *data)
00143 {
00144     int         i;
00145 
00146     if (!result || !proc)
00147         return FALSE;
00148 
00149     for (i = 0; i < result->nEvents; i++)
00150     {
00151         if (result->events[i].proc == proc)
00152         {
00153             result->events[i].data = data;
00154             return TRUE;
00155         }
00156     }
00157 
00158     return FALSE;
00159 }
00160 
00161 /*
00162  * Obtain the "instance data", if any, for the event.
00163  */
00164 void *
00165 PQresultInstanceData(const PGresult *result, PGEventProc proc)
00166 {
00167     int         i;
00168 
00169     if (!result || !proc)
00170         return NULL;
00171 
00172     for (i = 0; i < result->nEvents; i++)
00173         if (result->events[i].proc == proc)
00174             return result->events[i].data;
00175 
00176     return NULL;
00177 }
00178 
00179 /*
00180  * Fire RESULTCREATE events for an application-created PGresult.
00181  *
00182  * The conn argument can be NULL if event procedures won't use it.
00183  */
00184 int
00185 PQfireResultCreateEvents(PGconn *conn, PGresult *res)
00186 {
00187     int         i;
00188 
00189     if (!res)
00190         return FALSE;
00191 
00192     for (i = 0; i < res->nEvents; i++)
00193     {
00194         if (!res->events[i].resultInitialized)
00195         {
00196             PGEventResultCreate evt;
00197 
00198             evt.conn = conn;
00199             evt.result = res;
00200             if (!res->events[i].proc(PGEVT_RESULTCREATE, &evt,
00201                                      res->events[i].passThrough))
00202                 return FALSE;
00203 
00204             res->events[i].resultInitialized = TRUE;
00205         }
00206     }
00207 
00208     return TRUE;
00209 }