LCOV - differential code coverage report
Current view: top level - src/interfaces/libpq - libpq-events.c (source / functions) Coverage Total Hit UBC
Current: Differential Code Coverage HEAD vs 15 Lines: 0.0 % 72 0 72
Current Date: 2023-04-08 15:15:32 Functions: 0.0 % 6 0 6
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * libpq-events.c
       4                 :  *    functions for supporting the libpq "events" API
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7                 :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :  *
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *    src/interfaces/libpq/libpq-events.c
      12                 :  *
      13                 :  *-------------------------------------------------------------------------
      14                 :  */
      15                 : #include "postgres_fe.h"
      16                 : 
      17                 : #include "libpq-fe.h"
      18                 : #include "libpq-int.h"
      19                 : 
      20                 : 
      21                 : /*
      22                 :  * Registers an event proc with the given PGconn.
      23                 :  *
      24                 :  * The same proc can't be registered more than once in a PGconn.  This
      25                 :  * restriction is required because we use the proc address to identify
      26                 :  * the event for purposes such as PQinstanceData().
      27                 :  *
      28                 :  * The name argument is used within error messages to aid in debugging.
      29                 :  * A name must be supplied, but it needn't be unique.  The string is
      30                 :  * copied, so the passed value needn't be long-lived.
      31                 :  *
      32                 :  * The passThrough argument is an application specific pointer and can be set
      33                 :  * to NULL if not required.  It is passed through to the event proc whenever
      34                 :  * the event proc is called, and is not otherwise touched by libpq.
      35                 :  *
      36                 :  * The function returns a non-zero if successful.  If the function fails,
      37                 :  * zero is returned.
      38                 :  */
      39                 : int
      40 UBC           0 : PQregisterEventProc(PGconn *conn, PGEventProc proc,
      41                 :                     const char *name, void *passThrough)
      42                 : {
      43                 :     int         i;
      44                 :     PGEventRegister regevt;
      45                 : 
      46               0 :     if (!proc || !conn || !name || !*name)
      47               0 :         return false;           /* bad arguments */
      48                 : 
      49               0 :     for (i = 0; i < conn->nEvents; i++)
      50                 :     {
      51               0 :         if (conn->events[i].proc == proc)
      52               0 :             return false;       /* already registered */
      53                 :     }
      54                 : 
      55               0 :     if (conn->nEvents >= conn->eventArraySize)
      56                 :     {
      57                 :         PGEvent    *e;
      58                 :         int         newSize;
      59                 : 
      60               0 :         newSize = conn->eventArraySize ? conn->eventArraySize * 2 : 8;
      61               0 :         if (conn->events)
      62               0 :             e = (PGEvent *) realloc(conn->events, newSize * sizeof(PGEvent));
      63                 :         else
      64               0 :             e = (PGEvent *) malloc(newSize * sizeof(PGEvent));
      65                 : 
      66               0 :         if (!e)
      67               0 :             return false;
      68                 : 
      69               0 :         conn->eventArraySize = newSize;
      70               0 :         conn->events = e;
      71                 :     }
      72                 : 
      73               0 :     conn->events[conn->nEvents].proc = proc;
      74               0 :     conn->events[conn->nEvents].name = strdup(name);
      75               0 :     if (!conn->events[conn->nEvents].name)
      76               0 :         return false;
      77               0 :     conn->events[conn->nEvents].passThrough = passThrough;
      78               0 :     conn->events[conn->nEvents].data = NULL;
      79               0 :     conn->events[conn->nEvents].resultInitialized = false;
      80               0 :     conn->nEvents++;
      81                 : 
      82               0 :     regevt.conn = conn;
      83               0 :     if (!proc(PGEVT_REGISTER, &regevt, passThrough))
      84                 :     {
      85               0 :         conn->nEvents--;
      86               0 :         free(conn->events[conn->nEvents].name);
      87               0 :         return false;
      88                 :     }
      89                 : 
      90               0 :     return true;
      91                 : }
      92                 : 
      93                 : /*
      94                 :  * Set some "instance data" for an event within a PGconn.
      95                 :  * Returns nonzero on success, zero on failure.
      96                 :  */
      97                 : int
      98               0 : PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data)
      99                 : {
     100                 :     int         i;
     101                 : 
     102               0 :     if (!conn || !proc)
     103               0 :         return false;
     104                 : 
     105               0 :     for (i = 0; i < conn->nEvents; i++)
     106                 :     {
     107               0 :         if (conn->events[i].proc == proc)
     108                 :         {
     109               0 :             conn->events[i].data = data;
     110               0 :             return true;
     111                 :         }
     112                 :     }
     113                 : 
     114               0 :     return false;
     115                 : }
     116                 : 
     117                 : /*
     118                 :  * Obtain the "instance data", if any, for the event.
     119                 :  */
     120                 : void *
     121               0 : PQinstanceData(const PGconn *conn, PGEventProc proc)
     122                 : {
     123                 :     int         i;
     124                 : 
     125               0 :     if (!conn || !proc)
     126               0 :         return NULL;
     127                 : 
     128               0 :     for (i = 0; i < conn->nEvents; i++)
     129                 :     {
     130               0 :         if (conn->events[i].proc == proc)
     131               0 :             return conn->events[i].data;
     132                 :     }
     133                 : 
     134               0 :     return NULL;
     135                 : }
     136                 : 
     137                 : /*
     138                 :  * Set some "instance data" for an event within a PGresult.
     139                 :  * Returns nonzero on success, zero on failure.
     140                 :  */
     141                 : int
     142               0 : PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *data)
     143                 : {
     144                 :     int         i;
     145                 : 
     146               0 :     if (!result || !proc)
     147               0 :         return false;
     148                 : 
     149               0 :     for (i = 0; i < result->nEvents; i++)
     150                 :     {
     151               0 :         if (result->events[i].proc == proc)
     152                 :         {
     153               0 :             result->events[i].data = data;
     154               0 :             return true;
     155                 :         }
     156                 :     }
     157                 : 
     158               0 :     return false;
     159                 : }
     160                 : 
     161                 : /*
     162                 :  * Obtain the "instance data", if any, for the event.
     163                 :  */
     164                 : void *
     165               0 : PQresultInstanceData(const PGresult *result, PGEventProc proc)
     166                 : {
     167                 :     int         i;
     168                 : 
     169               0 :     if (!result || !proc)
     170               0 :         return NULL;
     171                 : 
     172               0 :     for (i = 0; i < result->nEvents; i++)
     173               0 :         if (result->events[i].proc == proc)
     174               0 :             return result->events[i].data;
     175                 : 
     176               0 :     return NULL;
     177                 : }
     178                 : 
     179                 : /*
     180                 :  * Fire RESULTCREATE events for an application-created PGresult.
     181                 :  *
     182                 :  * The conn argument can be NULL if event procedures won't use it.
     183                 :  */
     184                 : int
     185               0 : PQfireResultCreateEvents(PGconn *conn, PGresult *res)
     186                 : {
     187               0 :     int         result = true;
     188                 :     int         i;
     189                 : 
     190               0 :     if (!res)
     191               0 :         return false;
     192                 : 
     193               0 :     for (i = 0; i < res->nEvents; i++)
     194                 :     {
     195                 :         /* It's possible event was already fired, if so don't repeat it */
     196               0 :         if (!res->events[i].resultInitialized)
     197                 :         {
     198                 :             PGEventResultCreate evt;
     199                 : 
     200               0 :             evt.conn = conn;
     201               0 :             evt.result = res;
     202               0 :             if (res->events[i].proc(PGEVT_RESULTCREATE, &evt,
     203               0 :                                     res->events[i].passThrough))
     204               0 :                 res->events[i].resultInitialized = true;
     205                 :             else
     206               0 :                 result = false;
     207                 :         }
     208                 :     }
     209                 : 
     210               0 :     return result;
     211                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a