LCOV - code coverage report
Current view: top level - src/interfaces/libpq - libpq-events.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 95 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 6 0
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 0.0 % 68 0

             Branch data     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                 :           0 :         int                     i;
      44                 :           0 :         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                 :           0 :         }
      54                 :             : 
      55         [ #  # ]:           0 :         if (conn->nEvents >= conn->eventArraySize)
      56                 :             :         {
      57                 :           0 :                 PGEvent    *e;
      58                 :           0 :                 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         [ #  # ]:           0 :         }
      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                 :           0 : }
      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                 :           0 :         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                 :           0 :         }
     113                 :             : 
     114                 :           0 :         return false;
     115                 :           0 : }
     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                 :           0 :         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                 :           0 :         }
     133                 :             : 
     134                 :           0 :         return NULL;
     135                 :           0 : }
     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                 :           0 :         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                 :           0 :         }
     157                 :             : 
     158                 :           0 :         return false;
     159                 :           0 : }
     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                 :           0 :         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                 :           0 : }
     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                 :           0 :         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                 :           0 :                         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                 :           0 :                 }
     208                 :           0 :         }
     209                 :             : 
     210                 :           0 :         return result;
     211                 :           0 : }
        

Generated by: LCOV version 2.3.2-1