LCOV - code coverage report
Current view: top level - src/interfaces/libpq - libpq-events.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 0 72 0.0 %
Date: 2024-05-09 16:10:48 Functions: 0 6 0.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-2024, 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 1.14