aboutsummaryrefslogtreecommitdiff
path: root/contrib/pginterface/pginterface.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/pginterface/pginterface.c')
-rw-r--r--contrib/pginterface/pginterface.c212
1 files changed, 212 insertions, 0 deletions
diff --git a/contrib/pginterface/pginterface.c b/contrib/pginterface/pginterface.c
new file mode 100644
index 00000000000..58f7cfa7eb6
--- /dev/null
+++ b/contrib/pginterface/pginterface.c
@@ -0,0 +1,212 @@
+/*
+ * pginterface.c
+ *
+*/
+
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <libpq-fe.h>
+#include "halt.h"
+#include "pginterface.h"
+
+static void sig_disconnect();
+static void set_signals();
+
+#define NUL '\0'
+
+/* GLOBAL VARIABLES */
+static PGconn* conn;
+static PGresult* res = NULL;
+
+#define ON_ERROR_STOP 0
+#define ON_ERROR_CONTINUE 1
+
+static int on_error_state = ON_ERROR_STOP;
+
+/* LOCAL VARIABLES */
+static sigset_t block_sigs, unblock_sigs;
+static int tuple;
+
+/*
+**
+** connectdb - returns PGconn structure
+**
+*/
+PGconn *connectdb( char *dbName,
+ char *pghost,
+ char *pgport,
+ char *pgoptions,
+ char *pgtty)
+{
+ /* make a connection to the database */
+ conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
+ if (PQstatus(conn) == CONNECTION_BAD)
+ halt("Connection to database '%s' failed.\n%s\n", dbName,
+ PQerrorMessage(conn));
+ set_signals();
+ return conn;
+}
+
+/*
+**
+** disconnectdb
+**
+*/
+void disconnectdb()
+{
+ PQfinish(conn);
+}
+
+/*
+**
+** doquery - returns PGresult structure
+**
+*/
+PGresult *doquery(char *query)
+{
+ if (res != NULL)
+ PQclear(res);
+
+ sigprocmask(SIG_SETMASK,&block_sigs,NULL);
+ res = PQexec(conn, query);
+ sigprocmask(SIG_SETMASK,&unblock_sigs,NULL);
+
+ if (on_error_state == ON_ERROR_STOP &&
+ (res == NULL ||
+ PQresultStatus(res) == PGRES_BAD_RESPONSE ||
+ PQresultStatus(res) == PGRES_NONFATAL_ERROR ||
+ PQresultStatus(res) == PGRES_FATAL_ERROR))
+ {
+ if (res != NULL)
+ fprintf(stderr,"query error: %s\n",PQcmdStatus(res));
+ else fprintf(stderr,"connection error: %s\n",PQerrorMessage(conn));
+ PQfinish(conn);
+ halt("failed request: %s\n", query);
+ }
+ tuple = 0;
+ return res;
+}
+
+/*
+**
+** fetch - returns tuple number (starts at 0), or the value END_OF_TUPLES
+** NULL pointers are skipped
+**
+*/
+int fetch(void *param, ...)
+{
+ va_list ap;
+ int arg, num_args;
+
+ num_args = PQnfields(res);
+
+ if (tuple >= PQntuples(res))
+ return END_OF_TUPLES;
+
+ va_start(ap, param);
+ for (arg = 0; arg < num_args; arg++)
+ {
+ if (param != NULL)
+ {
+ if (PQfsize(res, arg) == -1)
+ {
+ memcpy(param,PQgetvalue(res,tuple,arg),PQgetlength(res,tuple,arg));
+ ((char *)param)[PQgetlength(res,tuple,arg)] = NUL;
+ }
+ else
+ memcpy(param,PQgetvalue(res,tuple,arg),PQfsize(res,arg));
+ }
+ param = va_arg(ap, char *);
+ }
+ va_end(ap);
+ return tuple++;
+}
+
+/*
+**
+** fetchisnull - returns tuple number (starts at 0), or the value END_OF_TUPLES
+** NULL pointers are skipped
+** Returns true or false into null indicator variables
+*/
+int fetchisnull(void *param, ...)
+{
+ va_list ap;
+ int arg, num_args;
+
+ if (tuple == 0)
+ halt("pginterface:fetchisnull(): You must call fetch() first.\n");
+
+ num_args = PQnfields(res);
+
+ if (tuple-1 >= PQntuples(res))
+ return END_OF_TUPLES;
+ va_start(ap, param);
+ for (arg = 0; arg < num_args; arg++)
+ {
+ if (param != NULL)
+ {
+ if (PQgetisnull(res,tuple-1,arg) != 0)
+ *(int *)param = 1;
+ else
+ *(int *)param = 0;
+ }
+ param = va_arg(ap, char *);
+ }
+ va_end(ap);
+ return tuple-1;
+}
+
+/*
+**
+** on_error_stop
+**
+*/
+void on_error_stop()
+{
+ on_error_state = ON_ERROR_STOP;
+}
+
+/*
+**
+** on_error_continue
+**
+*/
+void on_error_continue()
+{
+ on_error_state = ON_ERROR_CONTINUE;
+}
+
+/*
+**
+** sig_disconnect
+**
+*/
+static void sig_disconnect()
+{
+ fprintf(stderr,"exiting...\n");
+ PQfinish(conn);
+ exit(1);
+}
+
+/*
+**
+** set_signals
+**
+*/
+static void set_signals()
+{
+ sigemptyset(&block_sigs);
+ sigemptyset(&unblock_sigs);
+ sigaddset(&block_sigs,SIGTERM);
+ sigaddset(&block_sigs,SIGHUP);
+ sigaddset(&block_sigs,SIGINT);
+/* sigaddset(&block_sigs,SIGQUIT); no block */
+ sigprocmask(SIG_SETMASK,&unblock_sigs,NULL);
+ signal(SIGTERM,sig_disconnect);
+ signal(SIGHUP,sig_disconnect);
+ signal(SIGINT,sig_disconnect);
+ signal(SIGQUIT,sig_disconnect);
+}