LCOV - code coverage report
Current view: top level - src/interfaces/libpq - libpq-events.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 0.0 % 72 0
Test Date: 2026-02-17 17:20:33 Functions: 0.0 % 6 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * libpq-events.c
       4              :  *    functions for supporting the libpq "events" API
       5              :  *
       6              :  * Portions Copyright (c) 1996-2026, 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            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 2.0-1