From 3c44a132ea94894cb4e0e138fc4e3d5523eae6da Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Tue, 12 Oct 1999 14:06:49 +0000 Subject: [PATCH] Update pgeasy for missing files. --- src/interfaces/libpgeasy/libpgeasy.3 | 71 +++++++ src/interfaces/libpgeasy/libpgeasy.c | 287 +++++++++++++++++++++++++++ src/interfaces/libpgeasy/libpgeasy.h | 22 ++ 3 files changed, 380 insertions(+) create mode 100644 src/interfaces/libpgeasy/libpgeasy.3 create mode 100644 src/interfaces/libpgeasy/libpgeasy.c create mode 100644 src/interfaces/libpgeasy/libpgeasy.h diff --git a/src/interfaces/libpgeasy/libpgeasy.3 b/src/interfaces/libpgeasy/libpgeasy.3 new file mode 100644 index 0000000000..e90da0e790 --- /dev/null +++ b/src/interfaces/libpgeasy/libpgeasy.3 @@ -0,0 +1,71 @@ +.\" This is -*-nroff-*- +.\" XXX standard disclaimer belongs here.... +.\" $Header: /cvsroot/pgsql/src/interfaces/libpgeasy/Attic/libpgeasy.3,v 1.1 1999/10/12 14:06:49 momjian Exp $ +.TH PGEASY INTRO 08/08/98 PostgreSQL PostgreSQL +.SH DESCRIPTION +Pgeasy allows you to cleanly interface to the libpq library, +more like a 4gl SQL interface. +.PP +It consists of set of simplified C functions that encapsulate the +functionality of libpq. +The functions are: + +.nf +PGresult *doquery(char *query); +PGconn *connectdb(); +void disconnectdb(); + +int fetch(void *param,...); +int fetchwithnulls(void *param,...); +void reset_fetch(); + +void on_error_continue(); +void on_error_stop(); + +PGresult *get_result(); +void set_result(PGresult *newres); +void unset_result(PGresult *oldres); +.fi +.PP +Many functions return a structure or value, so you can do more work +with the result if required. +.PP +You basically connect to the database with +.BR connectdb , +issue your query with +.BR doquery , +fetch the results with +.BR fetch , +and finish with +.BR disconnectdb . +.PP +For +.IR select +queries, +.BR fetch +allows you to pass pointers as parameters, and on return the variables +are filled with data from the binary cursor you opened. These binary +cursors can not be used if you are running the +.BR pgeasy +client on a system with a different architecture than the database +server. If you pass a NULL pointer parameter, the column is skipped. +.BR fetchwithnulls +allows you to retieve the +.IR null +status of the field by passing an +.IR int* +after each result pointer, which returns true or false if the field is null. +You can always use libpq functions on the PGresult pointer returned by +.BR doquery . +.BR reset_fetch +starts the fetch back at the beginning. +.PP +.BR get_result , +.BR set_result , +and +.BR unset_result +allow you to handle multiple result sets at the same time. +.PP +There are a variety of demonstration programs in the +.BR pgeasy +source directory. diff --git a/src/interfaces/libpgeasy/libpgeasy.c b/src/interfaces/libpgeasy/libpgeasy.c new file mode 100644 index 0000000000..b067466c1a --- /dev/null +++ b/src/interfaces/libpgeasy/libpgeasy.c @@ -0,0 +1,287 @@ +/* + * pgeasy.c + * +*/ + +#include +#include +#include + +#include +#include "halt.h" +#include "libpgeasy.h" + +#define NUL '\0' + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* 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; + +static in_result_block = FALSE; +static was_get_unset_result = FALSE; + +/* LOCAL VARIABLES */ +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)); + return conn; +} + +/* +** +** disconnectdb +** +*/ +void +disconnectdb() +{ + PQfinish(conn); +} + +/* +** +** doquery - returns PGresult structure +** +*/ +PGresult * +doquery(char *query) +{ + if (res != NULL && in_result_block == FALSE && was_get_unset_result == FALSE) + PQclear(res); + + was_get_unset_result = FALSE; + res = PQexec(conn, query); + + 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_fields; + + num_fields = PQnfields(res); + + if (tuple >= PQntuples(res)) + return END_OF_TUPLES; + + va_start(ap, param); + for (arg = 0; arg < num_fields; 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++; +} + +/* +** +** fetchwithnulls - returns tuple number (starts at 0), +** or the value END_OF_TUPLES +** Returns TRUE or FALSE into null indicator variables +** NULL pointers are skipped +*/ +int +fetchwithnulls(void *param,...) +{ + va_list ap; + int arg, + num_fields; + + num_fields = PQnfields(res); + + if (tuple >= PQntuples(res)) + return END_OF_TUPLES; + + va_start(ap, param); + for (arg = 0; arg < num_fields; 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 *); + if (PQgetisnull(res, tuple, arg) != 0) + *(int *) param = 1; + else + *(int *) param = 0; + param = va_arg(ap, char *); + } + va_end(ap); + return tuple++; +} + +/* +** +** 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; +} + + +/* +** +** get_result +** +*/ +PGresult * +get_result() +{ + char *cmdstatus = PQcmdStatus(res); + + was_get_unset_result = TRUE; + + /* we have to store the fetch location somewhere */ + cmdstatus[0] = NUL; + memcpy(&cmdstatus[1], &tuple, sizeof(tuple)); + + return res; +} + +/* +** +** set_result +** +*/ +void +set_result(PGresult *newres) +{ + + char *cmdstatus = PQcmdStatus(res); + + if (newres == NULL) + halt("set_result called with null result pointer\n"); + + if (res != NULL && was_get_unset_result == FALSE) + if (in_result_block == FALSE) + PQclear(res); + else + { + cmdstatus[0] = NUL; + memcpy(&cmdstatus[1], &tuple, sizeof(tuple)); + } + + in_result_block = TRUE; + was_get_unset_result = FALSE; + + cmdstatus = PQcmdStatus(newres); + memcpy(&tuple, &cmdstatus[1], sizeof(tuple)); + + res = newres; +} + + +/* +** +** unset_result +** +*/ +void +unset_result(PGresult *oldres) +{ + char *cmdstatus = PQcmdStatus(oldres); + + if (oldres == NULL) + halt("unset_result called with null result pointer\n"); + + if (in_result_block == FALSE) + halt("Unset of result without being set.\n"); + + was_get_unset_result = TRUE; + cmdstatus[0] = NUL; + memcpy(&cmdstatus[1], &tuple, sizeof(tuple)); + in_result_block = FALSE; +} + +/* +** +** reset_fetch +** +*/ +void +reset_fetch() +{ + tuple = 0; +} diff --git a/src/interfaces/libpgeasy/libpgeasy.h b/src/interfaces/libpgeasy/libpgeasy.h new file mode 100644 index 0000000000..43fbeaba85 --- /dev/null +++ b/src/interfaces/libpgeasy/libpgeasy.h @@ -0,0 +1,22 @@ +/* + * pglib.h + * +*/ + +PGresult *doquery(char *query); +PGconn *connectdb(char *dbName, + char *pghost, + char *pgport, + char *pgoptions, + char *pgtty); +void disconnectdb(void); +int fetch(void *param,...); +int fetchwithnulls(void *param,...); +void on_error_continue(void); +void on_error_stop(void); +PGresult *get_result(void); +void set_result(PGresult *newres); +void unset_result(PGresult *oldres); +void reset_fetch(void); + +#define END_OF_TUPLES (-1)