../src/test/regress ../src/test/examples ../src/bin/psqlFrontend programs which use LIBPQ must include the header file
libpq-fe.h
and must link with the libpq
library.
PGconn *PQsetdb(char *pghost, char *pgport, char *pgoptions, char *pgtty, char *dbName);
char *PQdb(PGconn *conn)
char *PQhost(PGconn *conn)
char *PQoptions(PGconn *conn)
char *PQport(PGconn *conn)
char *PQtty(PGconn *conn)
ConnStatusType *PQstatus(PGconn *conn)
char *PQerrorMessage(PGconn* conn);
void PQfinish(PGconn *conn)
void PQreset(PGconn *conn)
void PQtrace(PGconn *conn, FILE* debug_port);
void PQuntrace(PGconn *conn);
PGresult *PQexec(PGconn *conn, char *query);
PGRES_EMPTY_QUERY, PGRES_COMMAND_OK, /* the query was a command */ PGRES_TUPLES_OK, /* the query successfully returned tuples */ PGRES_COPY_OUT, PGRES_COPY_IN, PGRES_BAD_RESPONSE, /* an unexpected response was received */ PGRES_NONFATAL_ERROR, PGRES_FATAL_ERROR
int PQntuples(PGresult *res);
int PQnfields(PGresult *res);
char *PQfname(PGresult *res, int field_index);
int PQfnumber(PGresult *res, char* field_name);
Oid PQftype(PGresult *res, int field_num);
int2 PQfsize(PGresult *res, int field_index);
char* PQgetvalue(PGresult *res, int tup_num, int field_num);
int PQgetlength(PGresult *res, int tup_num, int field_num);
char *PQcmdStatus(PGresult *res);
char* PQoidStatus(PGresult *res);
void PQprintTuples( PGresult* res, FILE* fout, /* output stream */ int printAttName,/* print attribute names or not*/ int terseOutput, /* delimiter bars or not?*/ int width /* width of column, variable width if 0*/ );
void PQclear(PQresult *res);
PGresult* PQfn(PGconn* conn, int fnid, int *result_buf, int *result_len, int result_is_int, PQArgBlock *args, int nargs);
typedef struct { int len; int isint; union { int *ptr; int integer; } u; } PQArgBlock;PQfn always returns a valid PGresult*. The resultStatus should be checked before the result is used. The caller is responsible for freeing the PGresult with PQclear when it is not longer needed.
PGnotify* PQNotifies(PGconn *conn);
../src/bin/psql/psql.ccontains routines that correctly handle the copy protocol.
int PQgetline(PGconn *conn, char *string, int length)
void PQputline(PGconn *conn, char *string);
int PQendcopy(PGconn *conn);
PQexec(conn, "create table foo (a int4, b char16, d float8)"); PQexec(conn, "copy foo from stdin"); PQputline(conn, "3<TAB>hello world<TAB>4.5\n"); PQputline(conn,"4<TAB>goodbye world<TAB>7.11\n"); ... PQputline(conn,".\n"); PQendcopy(conn);
void PQtrace(PGconn *conn FILE *debug_port)
void PQuntrace(PGconn *conn)
/etc/passwd
.
char *fe_getauthname(char* errorMessage)
void fe_setauthsvc(char *name, char* errorMessage)
/* * testlibpq.c * Test the C version of LIBPQ, the POSTGRES frontend library. * * */ #include <stdio.h> #include "libpq-fe.h"void exit_nicely(PGconn* conn) { PQfinish(conn); exit(1); }
main() { char *pghost, *pgport, *pgoptions, *pgtty; char* dbName; int nFields; int i,j;
/* FILE *debug; */
PGconn* conn; PGresult* res;
/* begin, by setting the parameters for a backend connection if the parameters are null, then the system will try to use reasonable defaults by looking up environment variables or, failing that, using hardwired constants */ pghost = NULL; /* host name of the backend server */ pgport = NULL; /* port of the backend server */ pgoptions = NULL; /* special options to start up the backend server */ pgtty = NULL; /* debugging tty for the backend server */ dbName = "template1";
/* make a connection to the database */ conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
/* check to see that the backend connection was successfully made */ if (PQstatus(conn) == CONNECTION_BAD) { fprintf(stderr,"Connection to database '%s' failed.0, dbName); fprintf(stderr,"%s",PQerrorMessage(conn)); exit_nicely(conn); }
/* debug = fopen("/tmp/trace.out","w"); */ /* PQtrace(conn, debug); */
/* start a transaction block */ res = PQexec(conn,"BEGIN"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr,"BEGIN command failed0); PQclear(res); exit_nicely(conn); } /* should PQclear PGresult whenever it is no longer needed to avoid memory leaks */ PQclear(res);
/* fetch instances from the pg_database, the system catalog of databases*/ res = PQexec(conn,"DECLARE myportal CURSOR FOR select * from pg_database"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr,"DECLARE CURSOR command failed0); PQclear(res); exit_nicely(conn); } PQclear(res);
res = PQexec(conn,"FETCH ALL in myportal"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr,"FETCH ALL command didn't return tuples properly0); PQclear(res); exit_nicely(conn); }
/* first, print out the attribute names */ nFields = PQnfields(res); for (i=0; i < nFields; i++) { printf("%-15s",PQfname(res,i)); } printf("0);
/* next, print out the instances */ for (i=0; i < PQntuples(res); i++) { for (j=0 ; j < nFields; j++) { printf("%-15s", PQgetvalue(res,i,j)); } printf("0); }
PQclear(res);
/* close the portal */ res = PQexec(conn, "CLOSE myportal"); PQclear(res);
/* end the transaction */ res = PQexec(conn, "END"); PQclear(res);
/* close the connection to the database and cleanup */ PQfinish(conn); /* fclose(debug); */ }
/* * testlibpq2.c * Test of the asynchronous notification interface * populate a database with the following:CREATE TABLE TBL1 (i int4);
CREATE TABLE TBL2 (i int4);
CREATE RULE r1 AS ON INSERT TO TBL1 DO [INSERT INTO TBL2 values (new.i); NOTIFY TBL2];
* Then start up this program * After the program has begun, do
INSERT INTO TBL1 values (10);
* * */ #include <stdio.h> #include "libpq-fe.h"
void exit_nicely(PGconn* conn) { PQfinish(conn); exit(1); }
main() { char *pghost, *pgport, *pgoptions, *pgtty; char* dbName; int nFields; int i,j;
PGconn* conn; PGresult* res; PGnotify* notify;
/* begin, by setting the parameters for a backend connection if the parameters are null, then the system will try to use reasonable defaults by looking up environment variables or, failing that, using hardwired constants */ pghost = NULL; /* host name of the backend server */ pgport = NULL; /* port of the backend server */ pgoptions = NULL; /* special options to start up the backend server */ pgtty = NULL; /* debugging tty for the backend server */ dbName = getenv("USER"); /* change this to the name of your test database*/
/* make a connection to the database */ conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName); /* check to see that the backend connection was successfully made */ if (PQstatus(conn) == CONNECTION_BAD) { fprintf(stderr,"Connection to database '%s' failed.0, dbName); fprintf(stderr,"%s",PQerrorMessage(conn)); exit_nicely(conn); }
res = PQexec(conn, "LISTEN TBL2"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr,"LISTEN command failed0); PQclear(res); exit_nicely(conn); } /* should PQclear PGresult whenever it is no longer needed to avoid memory leaks */ PQclear(res);
while (1) { /* async notification only come back as a result of a query*/ /* we can send empty queries */ res = PQexec(conn, " "); /* printf("res->status = %s0, pgresStatus[PQresultStatus(res)]); */ /* check for asynchronous returns */ notify = PQnotifies(conn); if (notify) { fprintf(stderr, "ASYNC NOTIFY of '%s' from backend pid '%d' received0, notify->relname, notify->be_pid); free(notify); break; } PQclear(res); }
/* close the connection to the database and cleanup */ PQfinish(conn);
}
/* * testlibpq3.c * Test the C version of LIBPQ, the POSTGRES frontend library. * tests the binary cursor interface * * * populate a database by doing the following:CREATE TABLE test1 (i int4, d float4, p polygon);
INSERT INTO test1 values (1, 3.567, '(3.0, 4.0, 1.0, 2.0)'::polygon);
INSERT INTO test1 values (2, 89.05, '(4.0, 3.0, 2.0, 1.0)'::polygon);
the expected output is:
tuple 0: got i = (4 bytes) 1, d = (4 bytes) 3.567000, p = (4 bytes) 2 points boundbox = (hi=3.000000/4.000000, lo = 1.000000,2.000000) tuple 1: got i = (4 bytes) 2, d = (4 bytes) 89.050003, p = (4 bytes) 2 points boundbox = (hi=4.000000/3.000000, lo = 2.000000,1.000000)
* */ #include <stdio.h> #include "libpq-fe.h" #include "utils/geo-decls.h" /* for the POLYGON type */
void exit_nicely(PGconn* conn) { PQfinish(conn); exit(1); }
main() { char *pghost, *pgport, *pgoptions, *pgtty; char* dbName; int nFields; int i,j; int i_fnum, d_fnum, p_fnum;
PGconn* conn; PGresult* res;
/* begin, by setting the parameters for a backend connection if the parameters are null, then the system will try to use reasonable defaults by looking up environment variables or, failing that, using hardwired constants */ pghost = NULL; /* host name of the backend server */ pgport = NULL; /* port of the backend server */ pgoptions = NULL; /* special options to start up the backend server */ pgtty = NULL; /* debugging tty for the backend server */
dbName = getenv("USER"); /* change this to the name of your test database*/
/* make a connection to the database */ conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
/* check to see that the backend connection was successfully made */ if (PQstatus(conn) == CONNECTION_BAD) { fprintf(stderr,"Connection to database '%s' failed.0, dbName); fprintf(stderr,"%s",PQerrorMessage(conn)); exit_nicely(conn); }
/* start a transaction block */ res = PQexec(conn,"BEGIN"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr,"BEGIN command failed0); PQclear(res); exit_nicely(conn); } /* should PQclear PGresult whenever it is no longer needed to avoid memory leaks */ PQclear(res);
/* fetch instances from the pg_database, the system catalog of databases*/ res = PQexec(conn,"DECLARE mycursor BINARY CURSOR FOR select * from test1"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr,"DECLARE CURSOR command failed0); PQclear(res); exit_nicely(conn); } PQclear(res);
res = PQexec(conn,"FETCH ALL in mycursor"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr,"FETCH ALL command didn't return tuples properly0); PQclear(res); exit_nicely(conn); }
i_fnum = PQfnumber(res,"i"); d_fnum = PQfnumber(res,"d"); p_fnum = PQfnumber(res,"p");
for (i=0;i<3;i++) { printf("type[%d] = %d, size[%d] = %d0, i, PQftype(res,i), i, PQfsize(res,i)); } for (i=0; i < PQntuples(res); i++) { int *ival; float *dval; int plen; POLYGON* pval; /* we hard-wire this to the 3 fields we know about */ ival = (int*)PQgetvalue(res,i,i_fnum); dval = (float*)PQgetvalue(res,i,d_fnum); plen = PQgetlength(res,i,p_fnum);
/* plen doesn't include the length field so need to increment by VARHDSZ*/ pval = (POLYGON*) malloc(plen + VARHDRSZ); pval->size = plen; memmove((char*)&pval->npts, PQgetvalue(res,i,p_fnum), plen); printf("tuple %d: got0, i); printf(" i = (%d bytes) %d,0, PQgetlength(res,i,i_fnum), *ival); printf(" d = (%d bytes) %f,0, PQgetlength(res,i,d_fnum), *dval); printf(" p = (%d bytes) %d points boundbox = (hi=%f/%f, lo = %f,%f)0, PQgetlength(res,i,d_fnum), pval->npts, pval->boundbox.xh, pval->boundbox.yh, pval->boundbox.xl, pval->boundbox.yl); }
PQclear(res);
/* close the portal */ res = PQexec(conn, "CLOSE mycursor"); PQclear(res);
/* end the transaction */ res = PQexec(conn, "END"); PQclear(res);
/* close the connection to the database and cleanup */ PQfinish(conn);
}