--- /dev/null
+
+
libpq C++ Binding
+
+libpq++ is the C++ API to
+libpq++ is a set of classes which allow
+client programs to connect to the
+
Postgres backend server. These connections
+come in two forms: a Database Class and a Large Object class.
+
+The Database Class is intended for manipulating a database. You can
+send all sorts of SQL queries to the
Postgres
+backend server and retrieve the responses of the server.
+
+The Large Object Class is intended for manipulating a large object
+in a database. Although a Large Object instance can send normal
+queries to the
Postgres backend server
+it is only intended for simple
+queries that do not return any data. A large object should be seen
+as a file stream. In future it should behave much like the C++ file
+streams
+cin,
+cout
+and
+cerr.
+
+This chapter is based on the documentation
+for the libpq C library. Three
+short programs are listed at the end of this section as examples of
+libpq++ programming
+(though not necessarily of good programming).
+There are several examples of libpq++
+applications in
+src/libpq++/examples, including the source
+code for the three examples in this chapter.
+
+
+
Control and Initialization
+
+
+
+
Environment Variables
+
+The following environment variables can be used to set up default
+values for an environment and to avoid hard-coding database names into
+an application program:
+
+
+Refer to the for a complete
+list of available connection options.
+
+
+The following environment variables can be used to select default
+connection parameter values, which will be used by PQconnectdb or
+PQsetdbLogin if no value is directly specified by the calling code.
+These are useful to avoid hard-coding database names into simple
+application programs.
+
+
+
+
PGHOST sets the default server name.
+If a non-zero-length string is specified, TCP/IP communication is used.
+Without a host name, libpq will connect using a local Unix domain socket.
+
+
+
+
PGPORT sets the default port or local Unix domain socket
+file extension for communicating with the
Postgres
+backend.
+
+
+
+
PGDATABASE sets the default
+
+
+
+sets the username used to connect to the database and for authentication.
+
+
+
+sets the password used if the backend demands password authentication.
+
+
+
+
PGREALM sets the Kerberos realm to use with
+ if it is different from the local realm. If
+
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 Kerberos authentication is selected by the backend.
+
+
+
+
PGOPTIONS sets additional runtime options for
+
+
+
+
PGTTY sets the file or tty on which debugging
+messages from the backend server are displayed.
+
+
+
+
+
+The following environment variables can be used to specify user-level default
+behavior for every Postgres session:
+
+
+
+sets the default style of date/time representation.
+
+
+
+sets the default time zone.
+
+
+
+
+
+The following environment variables can be used to specify default internal
+behavior for every Postgres session:
+
+
+
+sets the default mode for the genetic optimizer.
+
+
+
+sets the default mode to allow or disable right-sided plans in the optimizer.
+
+
+
+sets the default cost for heap searches for the optimizer.
+
+
+
+sets the default cost for indexed searches for the optimizer.
+
+
+
+
+
+Refer to the
SET SQL command
+for information on correct values for these environment variables.
+
+
+
+
Database Connection Functions
+
+
+
+
Database Environment Class: PGenv
+
+The database environment class provides C++ objects for manipulating the
+above environment variables:
+
+
+
+PGenv
+creates an environment for the running program.
+
+
+PGenv()
+PGenv(char* auth, char* host, char* port, char* option, char* tty)
+
+
+The first form of this object's constructor sets up the defaults for
+the program from the environment variables listed above.
+The second allows the programmer to hardcode the values into the program.
+The values of the second form relate directly to the environment variables
+above.
+
+
+
+
+
Database Class: PGdatabase
+
+The database class is a provides C++ objects that have a connection
+to a backend server. To create such an object one first need
+the apropriate environment for the backend to access.
+The following constructors deal with making a connection to a backend
+server from a C++ program.
+
+
+
+PGdatabase
+makes a new connection to a backend database server.
+
+PGdatabase(PGenv *env, char *dbName)
+
+After a PGdatabase has been created it should be checked to make sure
+the connection to the database succeded before sending
+queries to the object. This can easily be done by
+retrieving the current status of the PGdatabase object with the
+status method.
+
+
+status
+returns the status of the PGdatabase object.
+
+ConnStatus PGdatabase::status()
+
+
+The following values are allowed:
+
+
+CONNECTION_OK
+
+CONNECTION_BAD
+
+
+
+
+
+
Query Execution Functions
+
+
+
+PGdatabase::exec
+submits a query to
Postgres
+and returns result status. In case of an error
+PGdatabase::errormessage
+can be used to get more information on the error.
+
+void ExecStatusType PGdatabase::exec(char *query);
+
+
+The following status results can be expected:
+
+
+
+PGRES_EMPTY_QUERY
+
+PGRES_COMMAND_OK, if the query was a command
+
+PGRES_TUPLES_OK, if the query successfully returned tuples
+
+PGRES_COPY_OUT
+
+PGRES_COPY_IN
+
+PGRES_BAD_RESPONSE, if an unexpected response was received
+
+PGRES_NONFATAL_ERROR
+
+PGRES_FATAL_ERROR
+
+
+
+
+If the result status is PGRES_TUPLES_OK, then the following routines can
+be used to retrieve the tuples returned by the query.
+
+
+
+PGdatabase::ntuples
+returns the number of tuples (instances) in the query result.
+
+int PGdatabase::ntuples()
+
+
+
+PGdatabase::nfields
+returns the number of fields (attributes) in the query result.
+
+int PGdatabase::nfields()
+
+
+
+PGdatabase::fieldname
+returns the field (attribute) name associated with the given field index.
+Field indices start at zero.
+
+char* PGdatabase::fieldname(int field_index)
+
+
+
+PGdatabase::fieldnum
+returns the field (attribute) index associated with the given field name.
+
+int PGdatabase::fieldnum(char* field_name)
+
+
+
+PGdatabase::fieldtype
+returns the field type of associated with the given field index or name.
+The integer returned is an internal coding of the type. Field indices start
+at zero.
+
+Oid PGdatabase::fieldtype(int field_index)
+Oid PGdatabase::fieldtype(char* field_name)
+
+
+
+PGdatabase::fieldsize
+returns the size in bytes of the field associated with the given field
+index or name. If the size returned is -1, the field is a variable length
+field. Field indices start at zero.
+
+int2 PGdatabase::fieldsize(int field_index)
+int2 PGdatabase::fieldsize(char* field_name)
+
+
+
+PGdatabase::getvalue
+returns the field (attribute) value. For most queries, the values
+returned by
+PGdatabase::getvalue
+is a null-terminated ASCII string representation
+of the attribute value. If the query was a result of a
+cursor, then the values returned by
+PGdatabase::getvalue
+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 return by
+PGdatabase::getvalue
+points to storage that is part of the PGdatabase structure.
+ One must
+explicitly copy the value into other storage if it is to be used past
+the next query.
+
+char* PGdatabase::getvalue(int tup_num, int field_index)
+char* PGdatabase::getvalue(int tup_num, char* field_name)
+
+
+
+PGdatabase::getlength
+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.
+
+int PGdatabase::getlength(int tup_num, int field_index)
+int PGdatabase::getlength(int tup_num, char* field_name)
+
+
+
+PGdatabase::printtuples
+prints out all the tuples and, optionally, the attribute names to the
+specified output stream.
+
+void PGdatabase::printtuples(
+ 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*/
+ );
+
+
+
+
+
+
Asynchronous Notification
+
+
Postgres supports asynchronous notification
+via the LISTEN and NOTIFY
+commands. A backend registers its interest in a particular semaphore
+with the LISTEN command.
+ All backends that are listening on a
+particular named semaphore will be notified asynchronously when
+a NOTIFY of
+that 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.
+
+
+In the past, the documentation has associated the names used for asyncronous
+notification with relations or classes. However, there is in fact no
+direct linkage of the two concepts in the implementation, and the
+named semaphore in fact does not need to have a corresponding relation
+previously defined.
+
+
+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.
+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
+PGdatabase::notifies
+to see if any notification data is currently available from the backend.
+PGdatabase::notifies
+returns the notification from a list of unhandled notifications from the
+backend. The function eturns NULL if there is no pending notifications from the
+backend.
+PGdatabase::notifies
+behaves like the popping of a stack. Once a notification is returned
+from PGdatabase::notifies,
+it is considered handled and will be removed from the list of
+notifications.
+
+
+
+PGdatabase::notifies
+retrieves pending notifications from the server.
+
+
+PGnotify* PGdatabase::notifies()
+
+
+
+
+The second sample program gives an example of the use of asynchronous
+notification.
+
+
+
Functions Associated with the COPY Command
+
+The
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.
+
+
+
+PGdatabase::getline
+reads a newline-terminated line of characters (transmitted by the
+backend server) into a buffer
+string
+of size length.
+
+int PGdatabase::getline(char* string, int length)
+
+
+Like the Unix system routine
+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.
+
+PGdatabase::getline
+returns EOF at end of file, 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 a single period ("."), which indicates that the backend
+server has finished sending the results of the
+copy.
+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 PGdatabase::getline very carefully.
+
+
+PGdatabase::putline
+Sends a null-terminated string
+to the backend server.
+
+void PGdatabase::putline(char* string)
+
+
+The application must explicitly send a single period character (".")
+to indicate to the backend that it has finished sending its data.
+
+
+PGdatabase::endcopy
+syncs with the backend.
+
+int PGdatabase::endcopy()
+
+ This function waits until the backend has
+finished processing the copy.
+It should either be issued when the
+last string has been sent to the backend using
+PGdatabase::putline
+or when the last string has been received from the backend using
+PGdatabase::getline.
+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.
+
+
+
+As an example:
+
+PGdatabase data;
+data.exec("create table foo (a int4, b char16, d float8)");
+data.exec("copy foo from stdin");
+data.putline("3\etHello World\et4.5\en");
+data.putline("4\etGoodbye World\et7.11\en");
+\&...
+data.putline(".\en");
+data.endcopy();
+
+
+
+
+
Caveats
+
+The query buffer is 8192 bytes long, and queries over that length will
+be silently truncated.
+
+The PGlobj class is largely untested. Use with caution.
+
+
\ No newline at end of file
PQsetdbLogin
Makes a new connection to a backend.
-<ProgramListing>
+<synopsis>
PGconn *PQsetdbLogin(const char *pghost,
const char *pgport,
const char *pgoptions,
const char *dbName,
const char *login,
const char *pwd)
-ProgramListing>
+synopsis>
If any argument is NULL, then the corresponding
environment variable (see "Environment Variables" section)
is checked. If the environment variable
PQsetdb
Makes a new connection to a backend.
-<ProgramListing>
+<synopsis>
PGconn *PQsetdb(char *pghost,
char *pgport,
char *pgoptions,
char *pgtty,
char *dbName)
-ProgramListing>
+synopsis>
This is a macro that calls PQsetdbLogin() with null pointers
for the login and pwd parameters. It is provided primarily
for backward compatibility with old programs.
PQconnectdb
Makes a new connection to a backend.
-<ProgramListing>
+<synopsis>
PGconn *PQconnectdb(const char *conninfo)
-ProgramListing>
+synopsis>
This routine opens a new database connection using parameters
taken from a string. Unlike PQsetdbLogin(), the parameter set
can be extended without changing the function signature, so use
PQconndefaults
Returns the default connection options.
-<ProgramListing>
+<synopsis>
PQconninfoOption *PQconndefaults(void)
struct PQconninfoOption
int dispsize; /* Field size in characters for dialog */
};
-ProgramListing>
+synopsis>
Returns the address of the connection options structure. This may
be used to determine all possible PQconnectdb options and their
current default values. The return value points to an array of
PQfinish
Close the connection to the backend. Also frees
memory used by the PGconn object.
-<ProgramListing>
+<synopsis>
void PQfinish(PGconn *conn)
-ProgramListing>
+synopsis>
Note that even if the backend connection attempt fails (as
indicated by PQstatus), the application should call PQfinish
to free the memory used by the PGconn object.
PQreset
Reset the communication port with the backend.
-<ProgramListing>
+<synopsis>
void PQreset(PGconn *conn)
-ProgramListing>
+synopsis>
This function will close the connection
to the backend and attempt to reestablish a new
connection to the same postmaster, using all the same
PQdb
Returns the database name of the connection.
-<ProgramListing>
+<synopsis>
char *PQdb(PGconn *conn)
-ProgramListing>
+synopsis>
PQdb and the next several functions return the values established
at connection. These values are fixed for the life of the PGconn
object.
PQuser
Returns the user name of the connection.
-<ProgramListing>
+<synopsis>
char *PQuser(PGconn *conn)
-ProgramListing>
+synopsis>
PQpass
Returns the password of the connection.
-<ProgramListing>
+<synopsis>
char *PQpass(PGconn *conn)
-ProgramListing>
+synopsis>
PQhost
Returns the server host name of the connection.
-<ProgramListing>
+<synopsis>
char *PQhost(PGconn *conn)
-ProgramListing>
+synopsis>
PQport
Returns the port of the connection.
-<ProgramListing>
+<synopsis>
char *PQport(PGconn *conn)
-ProgramListing>
+synopsis>
PQtty
Returns the debug tty of the connection.
-<ProgramListing>
+<synopsis>
char *PQtty(PGconn *conn)
-ProgramListing>
+synopsis>
PQoptions
Returns the backend options used in the connection.
-<ProgramListing>
+<synopsis>
char *PQoptions(PGconn *conn)
-ProgramListing>
+synopsis>
PQstatus
Returns the status of the connection.
The status can be CONNECTION_OK or CONNECTION_BAD.
-<ProgramListing>
+<synopsis>
ConnStatusType *PQstatus(PGconn *conn)
-
-
+
+
A failed connection attempt is signaled by status CONNECTION_BAD.
Ordinarily, an OK status will remain so until PQfinish, but a
communications failure might result in the status changing to
PQerrorMessage
Returns the error message most recently generated by
an operation on the connection.
-<ProgramListing>
+<synopsis>
char *PQerrorMessage(PGconn* conn);
-
-
+
+
Nearly all libpq functions will set PQerrorMessage if they fail.
Note that by libpq convention, a non-empty PQerrorMessage will
include a trailing newline.
PQbackendPID
Returns the process ID of the backend server handling this
connection.
-<ProgramListing>
+<synopsis>
int PQbackendPID(PGconn *conn);
-ProgramListing>
+synopsis>
The backend PID is useful for debugging purposes and for comparison
to NOTIFY messages (which include the PID of the notifying backend).
Note that the PID belongs to a process executing on the database
PQexec
Submit a query to
Postgres
and wait for the result.
-<ProgramListing>
+<synopsis>
PGresult *PQexec(PGconn *conn,
const char *query);
-ProgramListing>
+synopsis>
Returns a PGresult pointer or possibly a NULL pointer.
A non-NULL pointer will generally be returned except in
out-of-memory conditions or serious errors such as inability
PQresultStatus
Returns the result status of the query. PQresultStatus can return one of the following values:
-<ProgramListing>
+<synopsis>
PGRES_EMPTY_QUERY,
PGRES_COMMAND_OK, /* the query was a command returning no data */
PGRES_TUPLES_OK, /* the query successfully returned tuples */
PGRES_BAD_RESPONSE, /* an unexpected response was received */
PGRES_NONFATAL_ERROR,
PGRES_FATAL_ERROR
-ProgramListing>
+synopsis>
If the result status is PGRES_TUPLES_OK, then the
routines described below can be used to retrieve the
tuples returned by the query. Note that a SELECT that
PQresultErrorMessage
returns the error message associated with the query, or an empty string
if there was no error.
-<ProgramListing>
+<synopsis>
const char *PQresultErrorMessage(PGresult *res);
-ProgramListing>
+synopsis>
Immediately following a PQexec or PQgetResult call, PQerrorMessage
(on the connection) will return the same string as PQresultErrorMessage
(on the result). However, a PGresult will retain its error message
PQntuples
Returns the number of tuples (instances)
in the query result.
-<ProgramListing>
+<synopsis>
int PQntuples(PGresult *res);
-ProgramListing>
+synopsis>
PQnfields
Returns the number of fields
(attributes) in each tuple of the query result.
-<ProgramListing>
+<synopsis>
int PQnfields(PGresult *res);
-ProgramListing>
+synopsis>
PQbinaryTuples
Returns 1 if the PGresult contains binary tuple data,
0 if it contains ASCII data.
-<ProgramListing>
+<synopsis>
int PQbinaryTuples(PGresult *res);
-ProgramListing>
+synopsis>
Currently, binary tuple data can only be returned by a query that
extracts data from a
BINARY cursor.
PQfname
- Returns the field (attribute) name associated with the given field index. Field indices
- start at 0.
-<ProgramListing>
+ Returns the field (attribute) name associated with the given field index.
+ Field indices start at 0.
+<synopsis>
char *PQfname(PGresult *res,
int field_index);
-ProgramListing>
+synopsis>
PQfnumber
Returns the field (attribute) index
associated with the given field name.
-<ProgramListing>
+<synopsis>
int PQfnumber(PGresult *res,
char* field_name);
-
-
+
+
-1 is returned if the given name does not match any field.
given field index. The integer returned is an
internal coding of the type. Field indices start
at 0.
-<ProgramListing>
+<synopsis>
Oid PQftype(PGresult *res,
int field_num);
-ProgramListing>
+synopsis>
associated with the given field index. If the size
returned is -1, the field is a variable length
field. Field indices start at 0.
-<ProgramListing>
+<synopsis>
int PQfsize(PGresult *res,
int field_index);
-ProgramListing>
+synopsis>
Returns the type-specific modification data of the field
associated with the given field index.
Field indices start at 0.
-<ProgramListing>
+<synopsis>
int PQfmod(PGresult *res,
int field_index);
-ProgramListing>
+synopsis>
Returns a single field (attribute) value of one tuple
of a PGresult.
Tuple and field indices start at 0.
-<ProgramListing>
+<synopsis>
char* PQgetvalue(PGresult *res,
int tup_num,
int field_num);
-ProgramListing>
+synopsis>
For most queries, the value returned by PQgetvalue
is a null-terminated ASCII string representation
of the attribute value. If the query extracted data from
PQgetisnull
Tests a field for a NULL entry.
Tuple and field indices start at 0.
-<ProgramListing>
+<synopsis>
int PQgetisnull(PGresult *res,
int tup_num,
int field_num);
-ProgramListing>
+synopsis>
This function returns 1 if the field contains a NULL, 0 if
it contains a non-null value. (Note that PQgetvalue
will return an empty string, not a null pointer, for a NULL
Returns the length of a field
(attribute) in bytes.
Tuple and field indices start at 0.
-<ProgramListing>
+<synopsis>
int PQgetlength(PGresult *res,
int tup_num,
int field_num);
-ProgramListing>
+synopsis>
This is the actual data length for the particular data value,
whereas PQfsize shows the allocated space for all entries in
this column.
PQcmdStatus
Returns the command status string from the SQL command that
generated the PGresult.
-<ProgramListing>
+<synopsis>
char *PQcmdStatus(PGresult *res);
-ProgramListing>
+synopsis>
PQcmdTuples
Returns the number of rows affected by the SQL command.
-<ProgramListing>
+<synopsis>
const char *PQcmdTuples(PGresult *res);
-ProgramListing>
+synopsis>
If the SQL command that generated the
PGresult was INSERT, UPDATE or DELETE, this returns a
string containing the number of rows affected. If the
Returns a string with the object id of the tuple
inserted, if the SQL command was an INSERT.
Otherwise, returns an empty string.
-<ProgramListing>
+<synopsis>
char* PQoidStatus(PGresult *res);
-ProgramListing>
+synopsis>
PQprint
Prints out all the tuples and, optionally, the
attribute names to the specified output stream.
-<ProgramListing>
+<synopsis>
void PQprint(FILE* fout, /* output stream */
PGresult* res,
PQprintOpt* po);
char *caption; /* HTML <caption> */
char **fieldName; /* null terminated array of replacement field names */
};
-ProgramListing>
+synopsis>
This function is intended to replace PQprintTuples(), which is
now obsolete. The psql program uses
PQprint() to display query results.
PQprintTuples
Prints out all the tuples and, optionally, the
attribute names to the specified output stream.
-<ProgramListing>
+<synopsis>
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*/
-ProgramListing>
+synopsis>
PQdisplayTuples
Prints out all the tuples and, optionally, the
attribute names to the specified output stream.
-<ProgramListing>
+<synopsis>
void PQdisplayTuples(PGresult* res,
FILE* fout, /* output stream */
int fillAlign, /* space fill to align columns */
const char *fieldSep, /* field separator */
int printHeader, /* display headers? */
int quiet); /* suppress print of row count at end */
-ProgramListing>
+synopsis>
PQdisplayTuples() was intended to supersede PQprintTuples(), and
is in turn superseded by PQprint().
Frees the storage associated with the PGresult.
Every query result should be freed via PQclear when
it is no longer needed.
-<ProgramListing>
+<synopsis>
void PQclear(PQresult *res);
-ProgramListing>
+synopsis>
You can keep a PGresult object around for as long as you
need it; it does not go away when you issue a new query,
nor even if you close the connection. To get rid of it,
PQmakeEmptyPGresult
Constructs an empty PGresult object with the given status.
-<ProgramListing>
+<synopsis>
PGresult* PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status);
-ProgramListing>
+synopsis>
This is libpq's internal routine to allocate and initialize an empty
PGresult object. It is exported because some applications find it
useful to generate result objects (particularly objects with error
waiting for the result(s). TRUE is returned if the query was
successfully dispatched, FALSE if not (in which case, use
PQerrorMessage to get more information about the failure).
-<ProgramListing>
+<synopsis>
int PQsendQuery(PGconn *conn,
const char *query);
-ProgramListing>
+synopsis>
After successfully calling PQsendQuery, call PQgetResult one or more
times to obtain the query results. PQsendQuery may not be called
again (on the same connection) until PQgetResult has returned NULL,
Wait for the next result from a prior PQsendQuery,
and return it. NULL is returned when the query is complete
and there will be no more results.
-<ProgramListing>
+<synopsis>
PGresult *PQgetResult(PGconn *conn);
-ProgramListing>
+synopsis>
PQgetResult must be called repeatedly until it returns NULL,
indicating that the query is done. (If called when no query is
active, PQgetResult will just return NULL at once.)
PQconsumeInput
If input is available from the backend, consume it.
-<ProgramListing>
+<synopsis>
int PQconsumeInput(PGconn *conn);
-ProgramListing>
+synopsis>
PQconsumeInput normally returns 1 indicating "no error", but returns
0 if there was some kind of trouble (in which case PQerrorMessage
is set). Note that the result does not say whether any input data
Returns TRUE if a query is busy, that is, PQgetResult would block
waiting for input. A FALSE return indicates that PQgetResult can
be called with assurance of not blocking.
-<ProgramListing>
+<synopsis>
int PQisBusy(PGconn *conn);
-ProgramListing>
+synopsis>
PQisBusy will not itself attempt to read data from the backend;
therefore PQconsumeInput must be invoked first, or the busy
state will never end.
Obtain the file descriptor number for the backend connection socket.
A valid descriptor will be >= 0; a result of -1 indicates that
no backend connection is currently open.
-<ProgramListing>
+<synopsis>
int PQsocket(PGconn *conn);
-ProgramListing>
+synopsis>
PQsocket should be used to obtain the backend socket descriptor
in preparation for executing select(2). This allows an application
to wait for either backend responses or other conditions.
PQrequestCancel
Request that
Postgres abandon
processing of the current query.
-<ProgramListing>
+<synopsis>
int PQrequestCancel(PGconn *conn);
-ProgramListing>
+synopsis>
The return value is TRUE if the cancel request was successfully
dispatched, FALSE if not. (If not, PQerrorMessage tells why not.)
Successful dispatch is no guarantee that the request will have any
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.
-<ProgramListing>
+<synopsis>
PGresult* PQfn(PGconn* conn,
int fnid,
int *result_buf,
int result_is_int,
PQArgBlock *args,
int nargs);
-ProgramListing>
+synopsis>
The fnid argument is the object identifier of the function to be
executed.
result_buf is the buffer in which
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.
-<ProgramListing>
+<synopsis>
typedef struct {
int len;
int isint;
int integer;
} u;
} PQArgBlock;
-ProgramListing>
+synopsis>
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 no longer needed.
there are no pending notifications. Once a notification is
returned from PQnotifies, it is considered handled and will be
removed from the list of notifications.
-<ProgramListing>
+<synopsis>
PGnotify* PQnotifies(PGconn *conn);
-ProgramListing>
+synopsis>
After processing a PGnotify object returned by PQnotifies,
be sure to free it with free() to avoid a memory leak.
Reads a newline-terminated line of characters
(transmitted by the backend server) into a buffer
string of size length.
-<ProgramListing>
+<synopsis>
int PQgetline(PGconn *conn,
char *string,
int length)
-ProgramListing>
+synopsis>
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.
Reads a newline-terminated line of characters
(transmitted by the backend server) into a buffer
without blocking.
-<ProgramListing>
+<synopsis>
int PQgetlineAsync(PGconn *conn,
char *buffer,
int bufsize)
-ProgramListing>
+synopsis>
This routine is similar to PQgetline, but it can be used by applications
that must read COPY data asynchronously, that is without blocking.
Having issued the COPY command and gotten a PGRES_COPY_OUT response, the
PQputline
Sends a null-terminated string to the backend server.
Returns 0 if OK, EOF if unable to send the string.
-<ProgramListing>
+<synopsis>
int PQputline(PGconn *conn,
char *string);
-ProgramListing>
+synopsis>
Note the application must explicitly send the two
characters "\." on a final line to indicate to the backend that it
has finished sending its data.
PQputnbytes
Sends a non-null-terminated string to the backend server.
Returns 0 if OK, EOF if unable to send the string.
-<ProgramListing>
+<synopsis>
int PQputnbytes(PGconn *conn,
const char *buffer,
int nbytes);
-ProgramListing>
+synopsis>
This is exactly like PQputline, except that the data buffer need
not be null-terminated since the number of bytes to send is
specified directly.
receive the next query.
The return value is 0 on successful completion,
nonzero otherwise.
-<ProgramListing>
+<synopsis>
int PQendcopy(PGconn *conn);
-ProgramListing>
+synopsis>
As an example:
PQtrace
Enable tracing of the frontend/backend communication to a debugging file stream.
-<ProgramListing>
+<synopsis>
void PQtrace(PGconn *conn
FILE *debug_port)
-ProgramListing>
+synopsis>
PQuntrace
Disable tracing started by PQtrace
-<ProgramListing>
+<synopsis>
void PQuntrace(PGconn *conn)
-ProgramListing>
+synopsis>
PQsetNoticeProcessor
Control reporting of notice and warning messages generated by libpq.
-<ProgramListing>
+<synopsis>
void PQsetNoticeProcessor (PGconn * conn,
void (*noticeProcessor) (void * arg, const char * message),
void * arg)
-ProgramListing>
+synopsis>
user name is not the same as value of the
USER
environment variable or the user's entry in
/etc/passwd.
-<ProgramListing>
+<synopsis>
char *fe_getauthname(char* errorMessage)
-ProgramListing>
+synopsis>
service name rather than its compiled-in default.
This value is typically taken from a command-line
switch.
-<ProgramListing>
+<synopsis>
void fe_setauthsvc(char *name,
char* errorMessage)
-ProgramListing>
+synopsis>
Any error messages from the authentication
attempts are returned in the errorMessage argument.
-
+ id="libpq-envars">
Environment Variables
-
PGDATABASE sets the default
Postgres database name.
+
PGDATABASE sets the default
-
PGREALM sets the Kerberos realm to use with
Postgres,
+
PGREALM sets the Kerberos realm to use with
if it is different from the local realm. If
-
PGREALM is set,
Postgres applications will attempt
+
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
-
PGOPTIONS sets additional runtime options for the
Postgres backend.
+
PGOPTIONS sets additional runtime options for
-
PGTTY sets the file or tty on which debugging messages from the backend server are displayed.
+
PGTTY sets the file or tty on which debugging
+messages from the backend server are displayed.
- /*
- * 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 mycursor 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 mycursor");
- 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");
-
- /* 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 cursor */
- 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);
-
- /* fclose(debug); */
- }
+/*
+* 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 when done to avoid memory leaks */
+ PQclear(res);
+
+ /* fetch instances from the pg_database, the system catalog of databases*/
+ res = PQexec(conn,"DECLARE mycursor 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 mycursor");
+ 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");
+
+ /* 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 cursor */
+ 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);
+
+/* 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.\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) {
- /* wait a little bit between checks;
- * waiting with select() would be more efficient.
- */
- sleep(1);
- /* collect any asynchronous backend messages */
- PQconsumeInput(conn);
- /* check for asynchronous notify messages */
- while ((notify = PQnotifies(conn)) != NULL) {
- fprintf(stderr,
- "ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
- notify->relname, notify->be_pid);
- free(notify);
- }
- }
-
- /* close the connection to the database and cleanup */
- PQfinish(conn);
-
- }
+/*
+ * 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) {
+ /* wait a little bit between checks;
+ * waiting with select() would be more efficient.
+ */
+ sleep(1);
+ /* collect any asynchronous backend messages */
+ PQconsumeInput(conn);
+ /* check for asynchronous notify messages */
+ while ((notify = PQnotifies(conn)) != NULL) {
+ fprintf(stderr,
+ "ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
+ notify->relname, notify->be_pid);
+ free(notify);
+ }
+ }
+
+ /* 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.\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;
- /*/
- 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 boundbox = (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 cursor */
- 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);
-
- }
+/*
+ * 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;
+ /*/
+ 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"
+ " boundbox = (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 cursor */
+ 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);
+
+}