mirror of
https://github.com/postgres/postgres.git
synced 2025-08-24 09:27:52 +03:00
Add an "events" system to libpq, whereby applications can get callbacks that
enable them to manage private data associated with PGconns and PGresults. Andrew Chernow and Merlin Moncure
This commit is contained in:
176
src/interfaces/libpq/libpq-events.c
Normal file
176
src/interfaces/libpq/libpq-events.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* libpq-events.c
|
||||
* functions for supporting the libpq "events" API
|
||||
*
|
||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-events.c,v 1.1 2008/09/17 04:31:08 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres_fe.h"
|
||||
|
||||
#include "libpq-fe.h"
|
||||
#include "libpq-int.h"
|
||||
|
||||
|
||||
/*
|
||||
* Registers an event proc with the given PGconn.
|
||||
*
|
||||
* The same proc can't be registered more than once in a PGconn. This
|
||||
* restriction is required because we use the proc address to identify
|
||||
* the event for purposes such as PQinstanceData().
|
||||
*
|
||||
* The name argument is used within error messages to aid in debugging.
|
||||
* A name must be supplied, but it needn't be unique. The string is
|
||||
* copied, so the passed value needn't be long-lived.
|
||||
*
|
||||
* The passThrough argument is an application specific pointer and can be set
|
||||
* to NULL if not required. It is passed through to the event proc whenever
|
||||
* the event proc is called, and is not otherwise touched by libpq.
|
||||
*
|
||||
* The function returns a non-zero if successful. If the function fails,
|
||||
* zero is returned.
|
||||
*/
|
||||
int
|
||||
PQregisterEventProc(PGconn *conn, PGEventProc proc,
|
||||
const char *name, void *passThrough)
|
||||
{
|
||||
int i;
|
||||
PGEventRegister regevt;
|
||||
|
||||
if (!proc || !conn || !name || !*name)
|
||||
return FALSE; /* bad arguments */
|
||||
|
||||
for (i = 0; i < conn->nEvents; i++)
|
||||
{
|
||||
if (conn->events[i].proc == proc)
|
||||
return FALSE; /* already registered */
|
||||
}
|
||||
|
||||
if (conn->nEvents >= conn->eventArraySize)
|
||||
{
|
||||
PGEvent *e;
|
||||
int newSize;
|
||||
|
||||
newSize = conn->eventArraySize ? conn->eventArraySize * 2 : 8;
|
||||
if (conn->events)
|
||||
e = (PGEvent *) realloc(conn->events, newSize * sizeof(PGEvent));
|
||||
else
|
||||
e = (PGEvent *) malloc(newSize * sizeof(PGEvent));
|
||||
|
||||
if (!e)
|
||||
return FALSE;
|
||||
|
||||
conn->eventArraySize = newSize;
|
||||
conn->events = e;
|
||||
}
|
||||
|
||||
conn->events[conn->nEvents].proc = proc;
|
||||
conn->events[conn->nEvents].name = strdup(name);
|
||||
if (!conn->events[conn->nEvents].name)
|
||||
return FALSE;
|
||||
conn->events[conn->nEvents].passThrough = passThrough;
|
||||
conn->events[conn->nEvents].data = NULL;
|
||||
conn->nEvents++;
|
||||
|
||||
regevt.conn = conn;
|
||||
if (!proc(PGEVT_REGISTER, ®evt, passThrough))
|
||||
{
|
||||
conn->nEvents--;
|
||||
free(conn->events[conn->nEvents].name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set some "instance data" for an event within a PGconn.
|
||||
* Returns nonzero on success, zero on failure.
|
||||
*/
|
||||
int
|
||||
PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!conn || !proc)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < conn->nEvents; i++)
|
||||
{
|
||||
if (conn->events[i].proc == proc)
|
||||
{
|
||||
conn->events[i].data = data;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain the "instance data", if any, for the event.
|
||||
*/
|
||||
void *
|
||||
PQinstanceData(const PGconn *conn, PGEventProc proc)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!conn || !proc)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < conn->nEvents; i++)
|
||||
{
|
||||
if (conn->events[i].proc == proc)
|
||||
return conn->events[i].data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set some "instance data" for an event within a PGresult.
|
||||
* Returns nonzero on success, zero on failure.
|
||||
*/
|
||||
int
|
||||
PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!result || !proc)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < result->nEvents; i++)
|
||||
{
|
||||
if (result->events[i].proc == proc)
|
||||
{
|
||||
result->events[i].data = data;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain the "instance data", if any, for the event.
|
||||
*/
|
||||
void *
|
||||
PQresultInstanceData(const PGresult *result, PGEventProc proc)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!result || !proc)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < result->nEvents; i++)
|
||||
if (result->events[i].proc == proc)
|
||||
return result->events[i].data;
|
||||
|
||||
return NULL;
|
||||
}
|
Reference in New Issue
Block a user