summaryrefslogtreecommitdiff
path: root/doc/manual/libpq.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/manual/libpq.html')
-rw-r--r--doc/manual/libpq.html815
1 files changed, 815 insertions, 0 deletions
diff --git a/doc/manual/libpq.html b/doc/manual/libpq.html
new file mode 100644
index 00000000000..71f8e7a1502
--- /dev/null
+++ b/doc/manual/libpq.html
@@ -0,0 +1,815 @@
+<HTML>
+<HEAD>
+ <TITLE>The POSTGRES95 User Manual - LIBPQ</TITLE>
+</HEAD>
+
+<BODY>
+
+<font size=-1>
+<A HREF="pg95user.html">[ TOC ]</A>
+<A HREF="xindex.html">[ Previous ]</A>
+<A HREF="lobj.html">[ Next ]</A>
+</font>
+<HR>
+<H1>12. <B>LIBPQ</B></H1>
+<HR>
+ <B>LIBPQ</B> is the application programming interface to POSTGRES.
+ <B>LIBPQ</B> is a set of library routines which allows
+ client programs to pass queries to the POSTGRES backend
+ server and to receive the results of these queries.
+ This version of the documentation describes the <B>C</B>
+ interface library. Three short programs are included
+ at the end of this section to show how to write programs that use <B>LIBPQ</B>.
+ There are several examples of <B>LIBPQ</B> applications in the
+ following directories:
+
+<pre> ../src/test/regress
+ ../src/test/examples
+ ../src/bin/psql
+</pre>
+ Frontend programs which use <B>LIBPQ</B> must include the
+ header file <CODE>libpq-fe.h</CODE> and must link with the <B>libpq</B>
+ library.
+
+<H2><A NAME="control-and-initialization">12.1. Control and Initialization</A></H2>
+ The following environment variables can be used to set
+ up default environment values to avoid hard-coding
+ database names into an application program:
+
+<UL>
+ <LI><B>PGHOST</B> sets the default server name.
+ <LI><B>PGOPTIONS</B> sets additional runtime options for the POSTGRES backend.
+ <LI><B>PGPORT</B> sets the default port for communicating with the POSTGRES backend.
+ <LI><B>PGTTY</B> sets the file or tty on which debugging messages from the backend server are displayed.
+ <LI><B>PGDATABASE</B> sets the default POSTGRES database name.
+ <LI><B>PGREALM</B> sets the Kerberos realm to use with POSTGRES, if it is different from the local realm. If
+ <LI><B>PGREALM</B> 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 Kerberos authentication is enabled.
+</UL>
+
+<H2><A NAME="database-connection-functions">12.2. Database Connection Functions</A></H2>
+ The following routines deal with making a connection to
+ a backend from a <B>C</B> program.
+
+ <DL>
+ <DT><B>PQsetdb</B>
+ <DD>Makes a new connection to a backend.
+<pre> PGconn &#42;PQsetdb(char &#42;pghost,
+ char &#42;pgport,
+ char &#42;pgoptions,
+ char &#42;pgtty,
+ char &#42;dbName);
+</pre>
+ <DD>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.
+ <DD>PQsetdb always returns a valid PGconn pointer.
+ <DD>The PQstatus (see below) command should be called
+ to ensure that a connection was properly made
+ before queries are sent via the connection. <B>LIBPQ</B>
+ programmers should be careful to maintain the
+ <DD>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.<br>
+ <DT><B>PQdb</B>
+ <DD>Returns the database name of the connection.
+<pre> char &#42;PQdb(PGconn &#42;conn)
+</pre><br>
+ <DT><B>PQhost</B>
+ <DD>Returns the host name of the connection.
+<pre> char &#42;PQhost(PGconn &#42;conn)
+</pre><br>
+ <DT><B>PQoptions</B>
+ <DD>Returns the pgoptions used in the connection.
+<pre> char &#42;PQoptions(PGconn &#42;conn)
+</pre><br>
+ <DT><B>PQport</B>
+ <DD>Returns the pgport of the connection.
+<pre> char &#42;PQport(PGconn &#42;conn)
+</pre><br>
+ <DT><B>PQtty</B>
+ <DD>Returns the pgtty of the connection.
+<pre> char &#42;PQtty(PGconn &#42;conn)
+</pre><br>
+ <DT><B>PQstatus</B>
+ <DD>Returns the status of the connection.
+ <DD>The status can be CONNECTION_OK or CONNECTION_BAD.
+<pre> ConnStatusType &#42;PQstatus(PGconn &#42;conn)
+</pre><br>
+ <DT><B>PQerrorMessage</B>
+ <DD>Returns the error message associated with the connection
+<pre> char &#42;PQerrorMessage(PGconn&#42; conn);
+</pre><br>
+
+ <DT><B>PQfinish</B>
+ <DD>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.
+<pre> void PQfinish(PGconn &#42;conn)
+</pre><br>
+ <DT><B>PQreset</B>
+ <DD>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.
+<pre> void PQreset(PGconn &#42;conn)
+</pre><br>
+ <DT><B>PQtrace</B>
+ <DD>Enables tracing of messages passed between the
+ frontend and the backend. The messages are echoed
+ to the debug_port file stream.
+<pre> void PQtrace(PGconn &#42;conn,
+ FILE&#42; debug_port);
+</pre><br>
+ <DT><B>PQuntrace</B>
+ <DD>Disables tracing of messages passed between the
+ frontend and the backend.
+<pre> void PQuntrace(PGconn &#42;conn);
+</pre><br>
+</DL>
+<H2><A NAME="query-execution-functions">12.3. Query Execution Functions</A></H2>
+<DL>
+ <DT><B>PQexec</B>
+ <DD>Submit a query to POSTGRES. Returns a PGresult
+ pointer if the query was successful or a NULL otherwise. If a NULL is returned, PQerrorMessage can
+ be used to get more information about the error.
+<pre> PGresult &#42;PQexec(PGconn &#42;conn,
+ char &#42;query);
+</pre>
+ <DD>The <B>PGresult</B> structure encapsulates the query
+ result returned by the backend. <B>LIBPQ</B> 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.<br>
+ <DT><B>PQresultStatus</B>
+ <DD>Returns the result status of the query. PQresultStatus can return one of the following values:
+<pre> PGRES_EMPTY_QUERY,
+ PGRES_COMMAND_OK, /&#42; the query was a command &#42;/
+ PGRES_TUPLES_OK, /&#42; the query successfully returned tuples &#42;/
+ PGRES_COPY_OUT,
+ PGRES_COPY_IN,
+ PGRES_BAD_RESPONSE, /&#42; an unexpected response was received &#42;/
+ PGRES_NONFATAL_ERROR,
+ PGRES_FATAL_ERROR
+</pre>
+ <DD>If the result status is PGRES_TUPLES_OK, then the
+ following routines can be used to retrieve the
+ tuples returned by the query.<br>
+ <DT><B>PQntuples</B> returns the number of tuples (instances)
+ in the query result.
+
+<pre> int PQntuples(PGresult &#42;res);
+</pre><br>
+ <DT><B>PQnfields</B>
+ <DD>Returns the number of fields
+ (attributes) in the query result.
+
+<pre> int PQnfields(PGresult &#42;res);
+</pre><br>
+ <DT><B>PQfname</B>
+ <DD>Returns the field (attribute) name associated with the given field index. Field indices
+ start at 0.
+
+<pre> char &#42;PQfname(PGresult &#42;res,
+ int field_index);
+</pre><br>
+ <DT><B>PQfnumber</B>
+ <DD>Returns the field (attribute) index
+ associated with the given field name.
+
+<pre> int PQfnumber(PGresult &#42;res,
+ char&#42; field_name);
+</pre><br>
+ <DT><B>PQftype</B>
+ <DD>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.
+
+<pre> Oid PQftype(PGresult &#42;res,
+ int field_num);
+</pre><br>
+ <DT><B>PQfsize</B>
+ <DD>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.
+
+<pre> int2 PQfsize(PGresult &#42;res,
+ int field_index);
+</pre><br>
+ <DT><B>PQgetvalue</B>
+ <DD>Returns the field (attribute) value.
+ For most queries, the value returned by PQgetvalue
+ is a null-terminated ASCII string representation
+ of the attribute value. If the query was a result
+ of a <B>BINARY</B> cursor, then the value returned by
+ 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 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.
+
+<pre> char&#42; PQgetvalue(PGresult &#42;res,
+ int tup_num,
+ int field_num);
+</pre><br>
+ <DT><B>PQgetlength</B>
+ <DD>Returns the length of a field
+ (attribute) in bytes. If the field is a struct
+ varlena, the length returned here does not include
+ the size field of the varlena, i.e., it is 4 bytes
+ less.
+<pre> int PQgetlength(PGresult &#42;res,
+ int tup_num,
+ int field_num);
+</pre><br>
+ <DT><B>PQcmdStatus</B>
+ Returns the command status associated with the
+ last query command.
+<pre>
+ char &#42;PQcmdStatus(PGresult &#42;res);
+</pre><br>
+ <DT><B>PQoidStatus</B>
+ Returns a string with the object id of the tuple
+ inserted if the last query is an INSERT command.
+ Otherwise, returns an empty string.
+<pre> char&#42; PQoidStatus(PGresult &#42;res);
+</pre><br>
+ <DT><B>PQprintTuples</B>
+ Prints out all the tuples and, optionally, the
+ attribute names to the specified output stream.
+ The programs psql and monitor both use PQprintTuples for output.
+
+<pre> void PQprintTuples(
+ PGresult&#42; res,
+ FILE&#42; fout, /&#42; output stream &#42;/
+ int printAttName,/&#42; print attribute names or not&#42;/
+ int terseOutput, /&#42; delimiter bars or not?&#42;/
+ int width /&#42; width of column, variable width if 0&#42;/
+ );
+</pre><br>
+
+ <DT><B>PQclear</B>
+ 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.
+<pre> void PQclear(PQresult &#42;res);
+</pre><br>
+</DL>
+<H2><A NAME="fast-path">12.4. Fast Path</A></H2>
+ POSTGRES provides a 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.
+
+<pre> PGresult&#42; PQfn(PGconn&#42; conn,
+ int fnid,
+ int &#42;result_buf,
+ int &#42;result_len,
+ int result_is_int,
+ PQArgBlock &#42;args,
+ int nargs);
+</pre><br>
+
+ The fnid argument is the object identifier of the function to be executed. 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 result_len. If the result is to be an integer
+ value, than result_is_int should be set to 1; otherwise
+ it should be set to 0. args and nargs specify the
+ arguments to the function.
+<pre> typedef struct {
+ int len;
+ int isint;
+ union {
+ int &#42;ptr;
+ int integer;
+ } u;
+ } PQArgBlock;
+</pre>
+ PQfn always returns a valid PGresult&#42;. 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.
+<H2><A NAME="asynchronous-notification">12.5. Asynchronous Notification</A></H2>
+ POSTGRES supports asynchronous notification via the
+ LISTEN and 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.
+ <B>LIBPQ</B> 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
+ <B>LIBPQ</B> application must poll the backend to see if there
+ is any pending notification information. After the
+ execution of a query, a frontend may call PQNotifies to
+ see if any notification data is available from the
+ backend.
+<DL>
+ <DT><B>PQNotifies</B>
+ <DD>returns the notification from a list of unhandled
+ notifications from the backend. Returns NULL if
+ there are no pending notifications from the backend. PQNotifies behaves like the popping of a
+ stack. Once a notification is returned from PQnotifies, it is considered handled and will be
+ removed from the list of notifications.
+<pre> PGnotify&#42; PQNotifies(PGconn &#42;conn);
+</pre><br>
+</DL>
+ The second sample program gives an example of the use
+ of asynchronous notification.
+<H2><A NAME="functions-associated-with-the-copy-command">12.6. Functions Associated with the COPY Command</A></H2>
+ The copy command in POSTGRES has options to read from
+ or write to the network connection used by <B>LIBPQ</B>.
+ Therefore, functions are necessary to access this network connection directly so applications may take full
+ advantage of this capability.
+<DL>
+ <DT><B>PQgetline</B>
+ <DD>Reads a newline-terminated line of characters
+ (transmitted by the backend server) into a buffer
+ string of size length. Like fgets(3), this routine copies up to length-1 characters into string.
+ It is like gets(3), however, in that it converts
+ the terminating newline into a null character.
+ 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.
+ Notice that the application must check to see if a
+ new line consists of the single character ".",
+ which indicates that the backend server has finished sending the results of the copy command.
+ Therefore, if the application ever expects to
+ receive lines that are more than length-1 characters long, the application must be sure to check
+ the return value of PQgetline very carefully.
+ The code in
+
+<pre> ../src/bin/psql/psql.c
+</pre>
+ contains routines that correctly handle the copy
+ protocol.
+<pre> int PQgetline(PGconn &#42;conn,
+ char &#42;string,
+ int length)
+</pre><br>
+ <DT><B>PQputline</B>
+ <DD>Sends a null-terminated string to the backend
+ server.
+ The application must explicitly send the single
+ character "." to indicate to the backend that it
+ has finished sending its data.
+
+<pre> void PQputline(PGconn &#42;conn,
+ char &#42;string);
+</pre><br>
+ <DT><B>PQendcopy</B>
+ <DD>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 PQputline or when the
+ last string has been received from the backend
+ using PGgetline. It must be issued or the backend
+ may get "out of sync" with the frontend. Upon
+ return from this function, the backend is ready to
+ receive the next query.
+ The return value is 0 on successful completion,
+ nonzero otherwise.
+<pre> int PQendcopy(PGconn &#42;conn);
+</pre><br>
+ As an example:
+<pre> PQexec(conn, "create table foo (a int4, b char16, d float8)");
+ PQexec(conn, "copy foo from stdin");
+ PQputline(conn, "3&lt;TAB&gt;hello world&lt;TAB&gt;4.5\n");
+ PQputline(conn,"4&lt;TAB&gt;goodbye world&lt;TAB&gt;7.11\n");
+ ...
+ PQputline(conn,".\n");
+ PQendcopy(conn);
+</pre><br>
+</DL>
+<H2><A NAME="tracing-functions">12.7. <B>LIBPQ</B> Tracing Functions</A></H2>
+<DL>
+ <DT><B>PQtrace</B>
+ <DD>Enable tracing of the frontend/backend communication to a debugging file stream.
+<pre> void PQtrace(PGconn &#42;conn
+ FILE &#42;debug_port)
+</pre><br>
+
+ <DT><B>PQuntrace</B>
+ <DD>Disable tracing started by PQtrace
+<pre> void PQuntrace(PGconn &#42;conn)
+</pre><br>
+</DL>
+<H2><A NAME="authentication-functions">12.8. User Authentication Functions</A></H2>
+ If the user has generated the appropriate authentication credentials (e.g., obtaining <B>Kerberos</B> tickets),
+ the frontend/backend authentication process is handled
+ by <B>PQexec</B> without any further intervention. The following routines may be called by <B>LIBPQ</B> programs to tailor the behavior of the authentication process.
+<DL>
+ <DT><B>fe_getauthname</B>
+ <DD>Returns a pointer to static space containing whatever name the user has authenticated. Use of this
+ routine in place of calls to getenv(3) or getpwuid(3) by applications is highly recommended, as
+ it is entirely possible that the authenticated
+ user name is not the same as value of the <B>USER</B>
+ environment variable or the user's entry in
+ <CODE>/etc/passwd</CODE>.
+
+<pre> char &#42;fe_getauthname(char&#42; errorMessage)
+</pre><br>
+ <DT><B>fe_setauthsvc</B>
+ <DD>Specifies that <B>LIBPQ</B> should use authentication
+ service name rather than its compiled-in default.
+ <DD>This value is typically taken from a command-line
+ switch.
+<pre> void fe_setauthsvc(char &#42;name,
+ char&#42; errorMessage)
+</pre>
+ <DD>Any error messages from the authentication
+ attempts are returned in the errorMessage argument.
+</DL>
+
+<H2><A NAME="bugs">12.9. BUGS</A></H2>
+ The query buffer is 8192 bytes long, and queries over
+ that length will be silently truncated.
+<H2><A NAME="sample-programs">12.10. Sample Programs</H2>
+<p>
+<H3><A NAME="sample-program-1">12.10.1. Sample Program 1</A></H3>
+<pre>
+ /&#42;
+ &#42; testlibpq.c
+ &#42; Test the C version of LIBPQ, the POSTGRES frontend library.
+ &#42;
+ &#42;
+ &#42;/
+ #include &lt;stdio.h&gt;
+ #include "libpq-fe.h"
+<p>
+ void
+ exit_nicely(PGconn&#42; conn)
+ {
+ PQfinish(conn);
+ exit(1);
+ }
+<p>
+ main()
+ {
+ char &#42;pghost, &#42;pgport, &#42;pgoptions, &#42;pgtty;
+ char&#42; dbName;
+ int nFields;
+ int i,j;
+<p>
+ /&#42; FILE &#42;debug; &#42;/
+<p>
+ PGconn&#42; conn;
+ PGresult&#42; res;
+<p>
+ /&#42; 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 &#42;/
+ pghost = NULL; /&#42; host name of the backend server &#42;/
+ pgport = NULL; /&#42; port of the backend server &#42;/
+ pgoptions = NULL; /&#42; special options to start up the backend server &#42;/
+ pgtty = NULL; /&#42; debugging tty for the backend server &#42;/
+ dbName = "template1";
+<p>
+ /&#42; make a connection to the database &#42;/
+ conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
+<p>
+ /&#42; check to see that the backend connection was successfully made &#42;/
+ if (PQstatus(conn) == CONNECTION_BAD) {
+ fprintf(stderr,"Connection to database '&#37;s' failed.0, dbName);
+ fprintf(stderr,"&#37;s",PQerrorMessage(conn));
+ exit_nicely(conn);
+ }
+<p>
+ /&#42; debug = fopen("/tmp/trace.out","w"); &#42;/
+ /&#42; PQtrace(conn, debug); &#42;/
+<p>
+ /&#42; start a transaction block &#42;/
+
+ res = PQexec(conn,"BEGIN");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+ fprintf(stderr,"BEGIN command failed0);
+ PQclear(res);
+ exit_nicely(conn);
+ }
+ /&#42; should PQclear PGresult whenever it is no longer needed to avoid
+ memory leaks &#42;/
+ PQclear(res);
+<p>
+ /&#42; fetch instances from the pg_database, the system catalog of databases&#42;/
+ res = PQexec(conn,"DECLARE myportal CURSOR FOR select &#42; from pg_database");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+ fprintf(stderr,"DECLARE CURSOR command failed0);
+ PQclear(res);
+ exit_nicely(conn);
+ }
+ PQclear(res);
+<p>
+ 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);
+ }
+<p>
+ /&#42; first, print out the attribute names &#42;/
+ nFields = PQnfields(res);
+ for (i=0; i &lt; nFields; i++) {
+ printf("&#37;-15s",PQfname(res,i));
+ }
+ printf("0);
+<p>
+ /&#42; next, print out the instances &#42;/
+ for (i=0; i &lt; PQntuples(res); i++) {
+ for (j=0 ; j &lt; nFields; j++) {
+ printf("&#37;-15s", PQgetvalue(res,i,j));
+ }
+ printf("0);
+ }
+<p>
+ PQclear(res);
+<p>
+ /&#42; close the portal &#42;/
+ res = PQexec(conn, "CLOSE myportal");
+ PQclear(res);
+<p>
+ /&#42; end the transaction &#42;/
+ res = PQexec(conn, "END");
+ PQclear(res);
+<p>
+ /&#42; close the connection to the database and cleanup &#42;/
+ PQfinish(conn);
+
+ /&#42; fclose(debug); &#42;/
+ }
+</pre>
+<p>
+<H3><A NAME="sample-program-2">12.10.2. Sample Program 2</A></H3>
+<pre>
+ /&#42;
+ &#42; testlibpq2.c
+ &#42; Test of the asynchronous notification interface
+ &#42;
+ populate a database with the following:
+<p>
+ CREATE TABLE TBL1 (i int4);
+<p>
+ CREATE TABLE TBL2 (i int4);
+<p>
+ CREATE RULE r1 AS ON INSERT TO TBL1 DO [INSERT INTO TBL2 values (new.i); NOTIFY TBL2];
+<p>
+ &#42; Then start up this program
+ &#42; After the program has begun, do
+<p>
+ INSERT INTO TBL1 values (10);
+<p>
+ &#42;
+ &#42;
+ &#42;/
+ #include &lt;stdio.h&gt;
+ #include "libpq-fe.h"
+<p>
+ void exit_nicely(PGconn&#42; conn)
+ {
+ PQfinish(conn);
+ exit(1);
+ }
+<p>
+ main()
+ {
+ char &#42;pghost, &#42;pgport, &#42;pgoptions, &#42;pgtty;
+ char&#42; dbName;
+ int nFields;
+ int i,j;
+<p>
+ PGconn&#42; conn;
+ PGresult&#42; res;
+ PGnotify&#42; notify;
+<p>
+ /&#42; 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 &#42;/
+ pghost = NULL; /&#42; host name of the backend server &#42;/
+ pgport = NULL; /&#42; port of the backend server &#42;/
+ pgoptions = NULL; /&#42; special options to start up the backend server &#42;/
+ pgtty = NULL; /&#42; debugging tty for the backend server &#42;/
+ dbName = getenv("USER"); /&#42; change this to the name of your test database&#42;/
+<p>
+ /&#42; make a connection to the database &#42;/
+ conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
+
+ /&#42; check to see that the backend connection was successfully made &#42;/
+ if (PQstatus(conn) == CONNECTION_BAD) {
+ fprintf(stderr,"Connection to database '&#37;s' failed.0, dbName);
+ fprintf(stderr,"&#37;s",PQerrorMessage(conn));
+ exit_nicely(conn);
+ }
+<p>
+ res = PQexec(conn, "LISTEN TBL2");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+ fprintf(stderr,"LISTEN command failed0);
+ PQclear(res);
+ exit_nicely(conn);
+ }
+ /&#42; should PQclear PGresult whenever it is no longer needed to avoid
+ memory leaks &#42;/
+ PQclear(res);
+<p>
+ while (1) {
+ /&#42; async notification only come back as a result of a query&#42;/
+ /&#42; we can send empty queries &#42;/
+ res = PQexec(conn, " ");
+ /&#42; printf("res-&gt;status = &#37;s0, pgresStatus[PQresultStatus(res)]); &#42;/
+ /&#42; check for asynchronous returns &#42;/
+ notify = PQnotifies(conn);
+ if (notify) {
+ fprintf(stderr,
+ "ASYNC NOTIFY of '&#37;s' from backend pid '&#37;d' received0,
+ notify-&gt;relname, notify-&gt;be_pid);
+ free(notify);
+ break;
+ }
+ PQclear(res);
+ }
+<p>
+ /&#42; close the connection to the database and cleanup &#42;/
+ PQfinish(conn);
+<p>
+ }
+</pre>
+<p>
+<H3><A NAME="sample-program-3">12.10.3. Sample Program 3</A></H3>
+<pre>
+ /&#42;
+ &#42; testlibpq3.c
+ &#42; Test the C version of LIBPQ, the POSTGRES frontend library.
+ &#42; tests the binary cursor interface
+ &#42;
+ &#42;
+ &#42;
+ populate a database by doing the following:
+<p>
+ CREATE TABLE test1 (i int4, d float4, p polygon);
+<p>
+ INSERT INTO test1 values (1, 3.567, '(3.0, 4.0, 1.0, 2.0)'::polygon);
+<p>
+ INSERT INTO test1 values (2, 89.05, '(4.0, 3.0, 2.0, 1.0)'::polygon);
+<p>
+ the expected output is:
+<p>
+ 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)
+<p>
+ &#42;
+ &#42;/
+ #include &lt;stdio.h&gt;
+ #include "libpq-fe.h"
+ #include "utils/geo-decls.h" /&#42; for the POLYGON type &#42;/
+<p>
+ void exit_nicely(PGconn&#42; conn)
+ {
+ PQfinish(conn);
+ exit(1);
+ }
+<p>
+ main()
+ {
+ char &#42;pghost, &#42;pgport, &#42;pgoptions, &#42;pgtty;
+ char&#42; dbName;
+ int nFields;
+ int i,j;
+ int i_fnum, d_fnum, p_fnum;
+<p>
+ PGconn&#42; conn;
+ PGresult&#42; res;
+<p>
+ /&#42; 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 &#42;/
+ pghost = NULL; /&#42; host name of the backend server &#42;/
+ pgport = NULL; /&#42; port of the backend server &#42;/
+ pgoptions = NULL; /&#42; special options to start up the backend server &#42;/
+ pgtty = NULL; /&#42; debugging tty for the backend server &#42;/
+<p>
+ dbName = getenv("USER"); /&#42; change this to the name of your test database&#42;/
+<p>
+ /&#42; make a connection to the database &#42;/
+ conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
+<p>
+ /&#42; check to see that the backend connection was successfully made &#42;/
+ if (PQstatus(conn) == CONNECTION_BAD) {
+ fprintf(stderr,"Connection to database '&#37;s' failed.0, dbName);
+ fprintf(stderr,"&#37;s",PQerrorMessage(conn));
+ exit_nicely(conn);
+ }
+<p>
+ /&#42; start a transaction block &#42;/
+ res = PQexec(conn,"BEGIN");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+ fprintf(stderr,"BEGIN command failed0);
+ PQclear(res);
+ exit_nicely(conn);
+ }
+ /&#42; should PQclear PGresult whenever it is no longer needed to avoid
+ memory leaks &#42;/
+ PQclear(res);
+<p>
+ /&#42; fetch instances from the pg_database, the system catalog of databases&#42;/
+ res = PQexec(conn,"DECLARE mycursor BINARY CURSOR FOR select &#42; from test1");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+ fprintf(stderr,"DECLARE CURSOR command failed0);
+ PQclear(res);
+ exit_nicely(conn);
+ }
+ PQclear(res);
+<p>
+ 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);
+ }
+<p>
+ i_fnum = PQfnumber(res,"i");
+ d_fnum = PQfnumber(res,"d");
+ p_fnum = PQfnumber(res,"p");
+<p>
+ for (i=0;i&lt;3;i++) {
+ printf("type[&#37;d] = &#37;d, size[&#37;d] = &#37;d0,
+ i, PQftype(res,i),
+ i, PQfsize(res,i));
+ }
+ for (i=0; i &lt; PQntuples(res); i++) {
+ int &#42;ival;
+ float &#42;dval;
+ int plen;
+ POLYGON&#42; pval;
+ /&#42; we hard-wire this to the 3 fields we know about &#42;/
+ ival = (int&#42;)PQgetvalue(res,i,i_fnum);
+ dval = (float&#42;)PQgetvalue(res,i,d_fnum);
+ plen = PQgetlength(res,i,p_fnum);
+<p>
+ /&#42; plen doesn't include the length field so need to increment by VARHDSZ&#42;/
+ pval = (POLYGON&#42;) malloc(plen + VARHDRSZ);
+ pval-&gt;size = plen;
+ memmove((char&#42;)&amp;pval-&gt;npts, PQgetvalue(res,i,p_fnum), plen);
+ printf("tuple &#37;d: got0, i);
+ printf(" i = (&#37;d bytes) &#37;d,0,
+ PQgetlength(res,i,i_fnum), &#42;ival);
+ printf(" d = (&#37;d bytes) &#37;f,0,
+ PQgetlength(res,i,d_fnum), &#42;dval);
+ printf(" p = (&#37;d bytes) &#37;d points boundbox = (hi=&#37;f/&#37;f, lo = &#37;f,&#37;f)0,
+ PQgetlength(res,i,d_fnum),
+ pval-&gt;npts,
+ pval-&gt;boundbox.xh,
+ pval-&gt;boundbox.yh,
+ pval-&gt;boundbox.xl,
+ pval-&gt;boundbox.yl);
+ }
+<p>
+ PQclear(res);
+<p>
+ /&#42; close the portal &#42;/
+ res = PQexec(conn, "CLOSE mycursor");
+ PQclear(res);
+<p>
+ /&#42; end the transaction &#42;/
+ res = PQexec(conn, "END");
+ PQclear(res);
+<p>
+ /&#42; close the connection to the database and cleanup &#42;/
+ PQfinish(conn);
+<p>
+ }
+</pre>
+<HR>
+<font size=-1>
+<A HREF="pg95user.html">[ TOC ]</A>
+<A HREF="xindex.html">[ Previous ]</A>
+<A HREF="lobj.html">[ Next ]</A>
+</font>
+</BODY>
+</HTML>