aboutsummaryrefslogtreecommitdiff
path: root/doc/man/libpq.3
diff options
context:
space:
mode:
Diffstat (limited to 'doc/man/libpq.3')
-rw-r--r--doc/man/libpq.3962
1 files changed, 962 insertions, 0 deletions
diff --git a/doc/man/libpq.3 b/doc/man/libpq.3
new file mode 100644
index 00000000000..01d731a1541
--- /dev/null
+++ b/doc/man/libpq.3
@@ -0,0 +1,962 @@
+.\" This is -*-nroff-*-
+.\" XXX standard disclaimer belongs here....
+.\" $Header: /cvsroot/pgsql/doc/man/Attic/libpq.3,v 1.1.1.1 1996/08/18 22:14:25 scrappy Exp $
+.TH LIBPQ INTRO 03/12/94 Postgres95 Postgres95
+.SH DESCRIPTION
+Libpq is the programmer's interface to Postgres. Libpq is a set of
+library routines that allows queries to pass to the Postgres backend and
+instances to return through an IPC channel.
+.PP
+This version of the documentation describes the C interface library.
+Three short programs are included at the end of this section to show how
+to write programs that use Libpq.
+.PP
+There are several examples of Libpq applications in the following
+directories:
+.nf
+\&../src/test/regress
+\&../src/test/examples
+\&../src/bin/psql
+.fi
+.PP
+Frontend programs which use Libpq must include the header file
+.B "libpq-fe.h"
+and must link with the
+.B libpq
+library.
+.SH "Control and Initialization"
+.PP
+The following environment variables can be used to set up default
+environment values to avoid hard-coding database names into
+an application program:
+.sp
+\(bu
+.B PGHOST
+sets the default server name.
+.sp
+\(bu
+.B PGOPTIONS
+sets additional runtime options for the Postgres backend.
+.sp
+\(bu
+.B PGPORT
+sets the default port for communicating with the Postgres backend.
+.sp
+\(bu
+.B PGTTY
+sets the file or tty on which debugging messages from the backend server
+are displayed.
+.sp
+\(bu
+.B PGDATABASE
+sets the default Postgres database name.
+.sp
+\(bu
+.B PGREALM
+sets the
+.I Kerberos
+realm to use with Postgres, if it is different from the local realm. If
+.B PGREALM
+is set, Postgres applications will attempt authentication with servers
+for this realm and use separate ticket files to avoid conflicts with
+local ticket files. This environment variable is only used if
+.I Kerberos
+authentication is enabled.
+.SH "Database Connection Functions"
+.PP
+The following routines deal with making a connection to a backend
+from a C program.
+.PP
+.B PQsetdb
+.IP
+Makes a new connection to a backend.
+.nf
+PGconn *PQsetdb(char *pghost,
+ char *pgport,
+ char *pgoptions,
+ char *pgtty,
+ char *dbName);
+.fi
+If any argument is NULL, then the corresponding environment variable
+is checked. If the environment variable is also not set, then hardwired
+defaults are used.
+.IP
+.I PQsetdb
+always returns a valid PGconn pointer. The
+.I PQstatus
+(see below) command should be called to ensure that a connection was
+properly made before queries are sent via the connection. Libpq
+programmers should be careful to maintain the PGconn abstraction. Use
+the accessor functions below to get at the contents of PGconn. Avoid
+directly referencing the fields of the PGconn structure as they are
+subject to change in the future.
+.IP
+.B PQdb
+returns the database name of the connection.
+.nf
+char *PQdb(PGconn *conn)
+.fi
+.B PQhost
+returns the host name of the connection.
+.nf
+char *PQhost(PGconn *conn)
+.fi
+.B PQoptions
+returns the pgoptions used in the connection.
+.nf
+char *PQoptions(PGconn *conn)
+.fi
+.B PQport
+returns the pgport of the connection.
+.nf
+char *PQport(PGconn *conn)
+.fi
+.B PQtty
+returns the pgtty of the connection.
+.nf
+char *PQtty(PGconn *conn)
+.fi
+.B PQstatus
+Returns the status of the connection. The status can be CONNECTION_OK or
+CONNECTION_BAD.
+.nf
+ConnStatusType *PQstatus(PGconn *conn)
+.fi
+.B PQerrorMessage
+returns the error message associated with the connection
+.nf
+char *PQerrorMessage(PGconn* conn);
+.fi
+.PP
+.B PQfinish
+.IP
+Close the connection to the backend. Also frees memory used by the
+PGconn structure. The PGconn pointer should not be used after PQfinish
+has been called.
+.nf
+void PQfinish(PGconn *conn)
+.fi
+.PP
+.B PQreset
+.IP
+Reset the communication port with the backend. This function will close
+the IPC socket connection to the backend and attempt to reestablish a
+new connection to the same backend.
+.nf
+void PQreset(PGconn *conn)
+.fi
+.PP
+.B PQtrace
+.IP
+Enables tracing of messages passed between the frontend and the backend.
+The messages are echoed to the debug_port file stream.
+.nf
+void PQtrace(PGconn *conn,
+ FILE* debug_port);
+.fi
+.PP
+.B PQuntrace
+.IP
+Disables tracing of messages passed between the frontend and the backend.
+.nf
+void PQuntrace(PGconn *conn);
+.fi
+.PP
+.SH "Query Execution Functions"
+.PP
+.B PQexec
+.IP
+Submit a query to Postgres. Returns a PGresult pointer if the query was
+successful or a NULL otherwise. If a NULL is returned,
+.I PQerrorMessage
+can be used to get more information about the error.
+.nf
+PGresult *PQexec(PGconn *conn,
+ char *query);
+.fi
+The PGresult structure encapsulates the query result returned by the
+backend. Libpq programmers should be careful to maintain the PGresult
+abstraction. Use the accessor functions described below to retrieve the
+results of the query. Avoid directly referencing the fields of the PGresult
+structure as they are subject to change in the future.
+.PP
+.B PQresultStatus
+.IP
+Returns the result status of the query.
+.I PQresultStatus
+can return one of the following values:
+.nf
+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
+.fi
+.IP
+If the result status is PGRES_TUPLES_OK, then the following routines can
+be used to retrieve the tuples returned by the query.
+.IP
+
+.B PQntuples
+returns the number of tuples (instances) in the query result.
+.nf
+int PQntuples(PGresult *res);
+.fi
+
+.B PQnfields
+returns the number of fields (attributes) in the query result.
+.nf
+int PQnfields(PGresult *res);
+.fi
+
+.B PQfname
+returns the field (attribute) name associated with the given field index.
+Field indices start at 0.
+.nf
+char *PQfname(PGresult *res,
+ int field_index);
+.fi
+
+.B PQfnumber
+returns the field (attribute) index associated with the given field name.
+.nf
+int PQfnumber(PGresult *res,
+ char* field_name);
+.fi
+
+.B PQftype
+returns the field type associated with the given field index. The
+integer returned is an internal coding of the type. Field indices start
+at 0.
+.nf
+Oid PQftype(PGresult *res,
+ int field_num);
+.fi
+
+.B PQfsize
+returns the size in bytes of the field associated with the given field
+index. If the size returned is -1, the field is a variable length field.
+Field indices start at 0.
+.nf
+int2 PQfsize(PGresult *res,
+ int field_index);
+.fi
+
+.B PQgetvalue
+returns the field (attribute) value. For most queries, the value
+returned by
+.I PQgetvalue
+is a null-terminated ASCII string representation
+of the attribute value. If the query was a result of a
+.B BINARY
+cursor, then the value returned by
+.I PQgetvalue
+is the binary representation of the type in the internal format of the
+backend server. It is the programmer's responsibility to cast and
+convert the data to the correct C type. The value returned by
+.I PQgetvalue
+points to storage that is part of the PGresult structure. One must
+explicitly copy the value into other storage if it is to be used past
+the lifetime of the PGresult structure itself.
+.nf
+char* PQgetvalue(PGresult *res,
+ int tup_num,
+ int field_num);
+.fi
+
+.B PQgetlength
+returns the length of a field (attribute) in bytes. If the field
+is a
+.I "struct varlena" ,
+the length returned here does
+.B not
+include the size field of the varlena, i.e., it is 4 bytes less.
+.nf
+int PQgetlength(PGresult *res,
+ int tup_num,
+ int field_num);
+.fi
+
+.B PQgetisnull
+returns the NULL status of a field.
+.nf
+int PQgetisnull(PGresult *res,
+ int tup_num,
+ int field_num);
+.fi
+
+.PP
+.B PQcmdStatus
+.IP
+Returns the command status associated with the last query command.
+.nf
+char *PQcmdStatus(PGresult *res);
+.fi
+.PP
+.B PQoidStatus
+.IP
+Returns a string with the object id of the tuple inserted if the last
+query is an INSERT command. Otherwise, returns an empty string.
+.nf
+char* PQoidStatus(PGresult *res);
+.fi
+.PP
+.B PQprint
+.IP
++ Prints out all the tuples in an intelligent manner. The
+.B psql
++ program uses this function for its output.
+.nf
+void PQprint(
+ FILE* fout, /* output stream */
+ PGresult* res, /* query results */
+ PQprintOpt *ps /* option structure */
+ );
+
+.fi
+.I PQprintOpt
+is a typedef'ed structure as defined below.
+.(C
+typedef struct _PQprintOpt {
+ bool header; /* print table headings and row count */
+ bool align; /* fill align the fields */
+ bool standard; /* old brain dead format (needs align) */
+ bool html3; /* output html3+ tables */
+ bool expanded; /* expand tables */
+ bool pager; /* use pager if needed */
+ char *fieldSep; /* field separator */
+ char *caption; /* html table caption (or NULL) */
+ char **fieldName; /* null terminated array of field names (or NULL) */
+} PQprintOpt;
+.fi
+.LP
+.B PQclear
+.IP
+Frees the storage associated with the PGresult. Every query result
+should be properly freed when it is no longer used. Failure to do this
+will result in memory leaks in the frontend application. The PQresult*
+passed in should be a value which is returned from PQexec(). Calling
+PQclear() on an uninitialized PQresult pointer will very likely result
+in a core dump.
+.nf
+void PQclear(PQresult *res);
+.fi
+.PP
+.SH "Fast Path"
+.PP
+Postgres provides a
+.B "fast path"
+interface to send function calls to the backend. This is a trapdoor
+into system internals and can be a potential security hole. Most users
+will not need this feature.
+.nf
+PGresult* PQfn(PGconn* conn,
+ int fnid,
+ int *result_buf,
+ int *result_len,
+ int result_is_int,
+ PQArgBlock *args,
+ int nargs);
+.fi
+.PP
+The
+.I fnid
+argument is the object identifier of the function to be executed.
+.I result_buf
+is the buffer in which to load the return value. The caller must have
+allocated sufficient space to store the return value.
+The result length will be returned in the storage pointed to by
+.I result_len.
+If the result is to be an integer value, than
+.I result_is_int
+should be set to 1; otherwise it should be set to 0.
+.I args
+and
+.I nargs
+specify the arguments to the function.
+.nf
+typedef struct {
+ int len;
+ int isint;
+ union {
+ int *ptr;
+ int integer;
+ } u;
+} PQArgBlock;
+.fi
+.PP
+.I 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
+.I PQclear
+when it is not longer needed.
+.PP
+.SH "Asynchronous Notification"
+.PP
+Postgres supports asynchronous notification via the
+.I LISTEN
+and
+.I NOTIFY
+commands. A backend registers its interest in a particular relation
+with the LISTEN command. All backends listening on a particular
+relation will be notified asynchronously when a NOTIFY of that relation
+name is executed by another backend. No additional information is
+passed from the notifier to the listener. Thus, typically, any actual
+data that needs to be communicated is transferred through the relation.
+.PP
+Libpq applications are notified whenever a connected backend has
+received an asynchronous notification. However, the communication from
+the backend to the frontend is not asynchronous. Notification comes
+piggy-backed on other query results. Thus, an application must submit
+queries, even empty ones, in order to receive notice of backend
+notification. In effect, the Libpq application must poll the backend to
+see if there is any pending notification information. After the
+execution of a query, a frontend may call
+.I PQNotifies
+to see if any notification data is available from the backend.
+.PP
+.B PQNotifies
+.IP
+returns the notification from a list of unhandled notifications from the
+backend. Returns NULL if there are no pending notifications from the
+backend.
+.I PQNotifies
+behaves like the popping of a stack. Once a notification is returned
+from
+.I PQnotifies,
+it is considered handled and will be removed from the list of
+notifications.
+.nf
+PGnotify* PQNotifies(PGconn *conn);
+.fi
+.PP
+The second sample program gives an example of the use of asynchronous
+notification.
+.PP
+.SH "Functions Associated with the COPY Command"
+.PP
+The
+.I copy
+command in Postgres has options to read from or write to the network
+connection used by Libpq. Therefore, functions are necessary to
+access this network connection directly so applications may take full
+advantage of this capability.
+.PP
+.B PQgetline
+.IP
+Reads a newline-terminated line of characters (transmitted by the
+backend server) into a buffer
+.I string
+of size
+.I length .
+Like
+.I fgets (3),
+this routine copies up to
+.I length "-1"
+characters into
+.I string .
+It is like
+.I gets (3),
+however, in that it converts the terminating newline into a null
+character.
+.IP
+.I PQgetline
+returns EOF at EOF, 0 if the entire line has been read, and 1 if the
+buffer is full but the terminating newline has not yet been read.
+.IP
+Notice that the application must check to see if a new line consists
+of the single character \*(lq.\*(rq, which indicates that the backend
+server has finished sending the results of the
+.I copy
+command. Therefore, if the application ever expects to receive lines
+that are more than
+.I length "-1"
+characters long, the application must be sure to check the return
+value of
+.I PQgetline
+very carefully.
+.IP
+The code in
+.nf
+\&../src/bin/psql/psql.c
+.fi
+contains routines that correctly handle the copy protocol.
+.nf
+int PQgetline(PGconn *conn,
+ char *string,
+ int length)
+.fi
+.PP
+.B PQputline
+.IP
+Sends a null-terminated
+.I string
+to the backend server.
+.IP
+The application must explicitly send the single character \*(lq.\*(rq
+to indicate to the backend that it has finished sending its data.
+.nf
+void PQputline(PGconn *conn,
+ char *string);
+.fi
+.PP
+.B PQendcopy
+.IP
+Syncs with the backend. This function waits until the backend has
+finished the copy. It should either be issued when the
+last string has been sent to the backend using
+.I PQputline
+or when the last string has been received from the backend using
+.I PGgetline .
+It must be issued or the backend may get \*(lqout of sync\*(rq with
+the frontend. Upon return from this function, the backend is ready to
+receive the next query.
+.IP
+The return value is 0 on successful completion, nonzero otherwise.
+.nf
+int PQendcopy(PGconn *conn);
+.fi
+As an example:
+.nf
+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\en");
+PQputline(conn,"4<TAB>goodbye world<TAB>7.11\en");
+\&...
+PQputline(conn,".\en");
+PQendcopy(conn);
+.fi
+.PP
+.SH "LIBPQ Tracing Functions"
+.PP
+.B PQtrace
+.IP
+Enable tracing of the frontend/backend communication to a debugging file
+stream.
+.nf
+void PQtrace(PGconn *conn
+ FILE *debug_port)
+.fi
+.PP
+.B PQuntrace
+.IP
+Disable tracing started by
+.I PQtrace
+.nf
+void PQuntrace(PGconn *conn)
+.fi
+.PP
+.SH "User Authentication Functions"
+.PP
+If the user has generated the appropriate authentication credentials
+(e.g., obtaining
+.I Kerberos
+tickets), the frontend/backend authentication process is handled by
+.I PQexec
+without any further intervention. The following routines may be
+called by Libpq programs to tailor the behavior of the authentication
+process.
+.PP
+.B fe_getauthname
+.IP
+Returns a pointer to static space containing whatever name the user
+has authenticated. Use of this routine in place of calls to
+.I getenv (3)
+or
+.I getpwuid (3)
+by applications is highly recommended, as it is entirely possible that
+the authenticated user name is
+.B not
+the same as value of the
+.B USER
+environment variable or the user's entry in
+.I /etc/passwd .
+.nf
+char *fe_getauthname(char* errorMessage)
+.fi
+.PP
+.B fe_setauthsvc
+.IP
+Specifies that Libpq should use authentication service
+.I name
+rather than its compiled-in default. This value is typically taken
+from a command-line switch.
+.nf
+void fe_setauthsvc(char *name,
+ char* errorMessage)
+.fi
+Any error messages from the authentication attempts are returned in the
+errorMessage argument.
+.PP
+.SH "BUGS"
+.PP
+The query buffer is 8192 bytes long, and queries over that length will
+be silently truncated.
+.PP
+.SH "Sample Programs"
+.bp
+.SH "Sample Program 1"
+.PP
+.nf M
+/*
+ * 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.\n", 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 failed\n");
+ 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 failed\n");
+ 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 properly\n");
+ 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("\n\n");
+
+ /* 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("\n");
+ }
+
+ 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); */
+}
+.fi
+.bp
+.SH "Sample Program 2"
+.PP
+.nf M
+/*
+ * 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.\n", dbName);
+ fprintf(stderr,"%s",PQerrorMessage(conn));
+ exit_nicely(conn);
+ }
+
+ res = PQexec(conn, "LISTEN TBL2");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+ fprintf(stderr,"LISTEN command failed\n");
+ 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 = %s\n", pgresStatus[PQresultStatus(res)]); */
+ /* check for asynchronous returns */
+ notify = PQnotifies(conn);
+ if (notify) {
+ fprintf(stderr,
+ "ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
+ notify->relname, notify->be_pid);
+ free(notify);
+ break;
+ }
+ PQclear(res);
+ }
+
+ /* close the connection to the database and cleanup */
+ PQfinish(conn);
+
+}
+.fi
+.bp
+.SH "Sample Program 3"
+.PP
+.nf M
+/*
+ * 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.\n", 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 failed\n");
+ 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 failed\n");
+ 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 properly\n");
+ 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] = %d\n",
+ 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: got\n", i);
+ printf(" i = (%d bytes) %d,\n",
+ PQgetlength(res,i,i_fnum), *ival);
+ printf(" d = (%d bytes) %f,\n",
+ PQgetlength(res,i,d_fnum), *dval);
+ printf(" p = (%d bytes) %d points \tboundbox = (hi=%f/%f, lo = %f,%f)\n",
+ 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);
+
+}
+.fi