/* * pgeasy.c * */ #include #include #include #include "libpq-fe.h" #include "halt.h" #include "libpgeasy.h" #ifndef NUL #define NUL '\0' #endif #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif /* GLOBAL VARIABLES */ static PGconn *conn; static PGresult *res = NULL; static int tuple; /* stores fetch location */ #define ON_ERROR_STOP 0 #define ON_ERROR_CONTINUE 1 static int on_error_state = ON_ERROR_STOP; /* halt on errors? */ static int in_result_block = FALSE; static int was_get_unset_result = FALSE; /* * * connectdb - returns PGconn structure * */ PGconn * connectdb(char *options) { /* make a connection to the database */ conn = PQconnectdb(options); if (PQstatus(conn) == CONNECTION_BAD) halt("Connection to database using '%s' failed.\n%s\n", options, PQerrorMessage(conn)); return conn; } /* * * disconnectdb * */ void disconnectdb() { if (res != NULL && in_result_block == FALSE && was_get_unset_result == FALSE) { PQclear(res); res = NULL; } 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 */ /* XXX THIS IS A NO-NO */ 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 { /* XXX THIS IS A NO-NO */ 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; /* XXX THIS IS A NO-NO */ cmdstatus[0] = NUL; memcpy(&cmdstatus[1], &tuple, sizeof(tuple)); in_result_block = FALSE; } /* * * reset_fetch * */ void reset_fetch() { tuple = 0; }