libpqtypes - events.c

Home Page

array.c
datetime.c
error.c
events.c
exec.c
geo.c
getaddrinfo.h
handler.c
libpqtypes-int.h
libpqtypes.h
misc.c
network.c
numerics.c
param.c
port.c
record.c
regression-test.c
spec.c
utils.c
varlena.c
  1 
  2 /*
  3  * events.c
  4  *   The libpq PGEventProc implementation.
  5  *
  6  * Copyright (c) 2011 eSilo, LLC. All rights reserved.
  7  * This is free software; see the source for copying conditions.  There is
  8  * NO warranty; not even for MERCHANTABILITY or  FITNESS FOR A  PARTICULAR
  9  * PURPOSE.
 10  */
 11 
 12 #include "libpqtypes-int.h"
 13 
 14 static PGtypeData *
 15 allocTypeData(PGconn *conn);
 16 
 17 static void
 18 freeTypeData(PGtypeData *typeData);
 19 
 20 /* Deprecated, use PQinitTypes instead */
 21 int
 22 PQtypesRegister(PGconn *conn)
 23 {
 24   return PQinitTypes(conn);
 25 }
 26 
 27 int
 28 pqt_eventproc(PGEventId id, void *info, void *passThrough)
 29 {
 30   switch (id)
 31   {
 32     case PGEVT_REGISTER:
 33     {
 34       PGEventRegister *e = (PGEventRegister *) info;
 35       void *data = allocTypeData(e->conn);
 36       if (!data)
 37         return FALSE;
 38       PQsetInstanceData((PGconn *) e->conn, pqt_eventproc, data);
 39       break;
 40     }
 41 
 42     case PGEVT_CONNRESET:
 43     {
 44       /* No special handling for PGEVT_CONNRESET.  Previously, types were
 45        * automatically re-registered but this idea fails miserably during
 46        * asynchronous resets.  Yanked in favor of using the following
 47        * call sequence: PQresetXXX, PQclearTypes, PQregisterTypes.
 48        */
 49       break;
 50     }
 51 
 52     case PGEVT_CONNDESTROY:
 53     {
 54       PGEventConnDestroy *e = (PGEventConnDestroy *) info;
 55       freeTypeData((PGtypeData *) PQinstanceData(e->conn, pqt_eventproc));
 56       break;
 57     }
 58 
 59     case PGEVT_RESULTCREATE:
 60     {
 61       PGtypeData *resData;
 62       PGEventResultCreate *e = (PGEventResultCreate *) info;
 63       PGtypeData *connData = (PGtypeData *) PQinstanceData(
 64         e->conn, pqt_eventproc);
 65 
 66       if (!connData || !(resData = allocTypeData(e->conn)))
 67         return FALSE;
 68 
 69       /* copy type handlers from PGconn's typeData */
 70       if (connData->typhcnt > 0)
 71       {
 72         resData->typhandlers = pqt_duphandlers(
 73           connData->typhandlers, connData->typhcnt);
 74 
 75         if (resData->typhandlers)
 76           resData->typhcnt = connData->typhcnt;
 77       }
 78 
 79       /* copy type specs from PGconn's typeData */
 80       if (connData->typspeccnt > 0)
 81       {
 82         resData->typspecs = pqt_dupspecs(
 83           connData->typspecs, connData->typspeccnt);
 84 
 85         if (resData->typspecs)
 86           resData->typspeccnt = connData->typspeccnt;
 87       }
 88 
 89       PQresultSetInstanceData((PGresult *) e->result, pqt_eventproc, resData);
 90       break;
 91     }
 92 
 93     case PGEVT_RESULTCOPY:
 94     {
 95       PGtypeData *destData;
 96       PGEventResultCopy *e = (PGEventResultCopy *) info;
 97       PGtypeData *srcData = (PGtypeData *) PQresultInstanceData(
 98         e->src, pqt_eventproc);
 99 
100       if (!srcData || !(destData = allocTypeData(NULL)))
101         return FALSE;
102 
103       memcpy(&destData->fmtinfo, &srcData->fmtinfo, sizeof(PGtypeFormatInfo));
104 
105       /* copy type handlers from PGresult's typeData */
106       if (srcData->typhcnt > 0)
107       {
108         destData->typhandlers = pqt_duphandlers(
109           srcData->typhandlers, srcData->typhcnt);
110 
111         if (destData->typhandlers)
112           destData->typhcnt = srcData->typhcnt;
113       }
114 
115       /* copy type specs from PGresult's typeData */
116       if (srcData->typspeccnt > 0)
117       {
118         destData->typspecs = pqt_dupspecs(
119           srcData->typspecs, srcData->typspeccnt);
120 
121         if (destData->typspecs)
122           destData->typspeccnt = srcData->typspeccnt;
123       }
124 
125       PQresultSetInstanceData(e->dest, pqt_eventproc, destData);
126       break;
127     }
128 
129     case PGEVT_RESULTDESTROY:
130     {
131       PGEventResultDestroy *e = (PGEventResultDestroy *) info;
132       freeTypeData((PGtypeData *) PQresultInstanceData(
133         e->result, pqt_eventproc));
134       break;
135     }
136   }
137 
138   return TRUE;
139 }
140 
141 static PGtypeData *
142 allocTypeData(PGconn *conn)
143 {
144   PGtypeData *typeData = (PGtypeData *) malloc(sizeof(PGtypeData));
145 
146   if (typeData)
147   {
148     memset(typeData, 0, sizeof(PGtypeData));
149 
150     /* get type formatting info from conn */
151     if (conn)
152       pqt_getfmtinfo(conn, &typeData->fmtinfo);
153   }
154 
155   return typeData;
156 }
157 
158 static void
159 freeTypeData(PGtypeData *typeData)
160 {
161   if (typeData)
162   {
163     pqt_cleartypes(typeData);
164 
165     pqt_freespecs(typeData->typspecs, typeData->typspeccnt);
166     typeData->typspecs = NULL;
167     typeData->typspeccnt = 0;
168     typeData->typspecmax = 0;
169 
170     free(typeData);
171   }
172 }