libpq.sgml
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:61k
- <Chapter Id="libpq-chapter">
- <Title id="libpq">libpq</Title>
- <Para>
- <FileName>libpq</FileName> is the C application programmer's interface to
- <ProductName>Postgres</ProductName>. <FileName>libpq</FileName> is a set
- of library routines that allow client programs to pass queries to the
- <ProductName>Postgres</ProductName> backend server and to receive the
- results of these queries. <FileName>libpq</FileName> is also the
- underlying engine for several other <ProductName>Postgres</ProductName>
- application interfaces, including <FileName>libpq++</FileName> (C++),
- <FileName>libpgtcl</FileName> (Tcl), <FileName>perl5</FileName>, and
- <FileName>ecpg</FileName>. So some aspects of libpq's behavior will be
- important to you if you use one of those packages.
- Three short programs are included at the end of this section to show how
- to write programs that use <FileName>libpq</FileName>. There are several
- complete examples of <FileName>libpq</FileName> applications in the
- following directories:
- <ProgramListing>
- ../src/test/regress
- ../src/test/examples
- ../src/bin/psql
- </ProgramListing>
- </Para>
- <Para>
- Frontend programs which use <FileName>libpq</FileName> must include the
- header file <FileName>libpq-fe.h</FileName> and must link with the
- <FileName>libpq</FileName> library.
- </Para>
- <Sect1>
- <Title>Database Connection Functions</Title>
- <Para>
- The following routines deal with making a connection to
- a <ProductName>Postgres</ProductName> backend server. The application
- program can have several backend connections open at one time.
- (One reason to do that is to access more than one database.)
- Each connection is represented by a PGconn object which is obtained
- from PQconnectdb() or PQsetdbLogin(). NOTE that these functions
- will always return a non-null object pointer, unless perhaps
- there is too little memory even to allocate the PGconn object.
- The PQstatus function should be called
- to check whether a connection was successfully made
- before queries are sent via the connection object.
- <ItemizedList>
- <ListItem>
- <Para>
- <Function>PQsetdbLogin</Function>
- Makes a new connection to a backend.
- <synopsis>
- PGconn *PQsetdbLogin(const char *pghost,
- const char *pgport,
- const char *pgoptions,
- const char *pgtty,
- const char *dbName,
- const char *login,
- const char *pwd)
- </synopsis>
- If any argument is NULL, then the corresponding
- environment variable (see "Environment Variables" section)
- is checked. If the environment variable
- is also not set, then hardwired defaults are used.
- The return value is a pointer to an abstract struct
- representing the connection to the backend.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQsetdb</Function>
- Makes a new connection to a backend.
- <synopsis>
- PGconn *PQsetdb(char *pghost,
- char *pgport,
- char *pgoptions,
- char *pgtty,
- char *dbName)
- </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.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQconnectdb</Function>
- Makes a new connection to a backend.
- <synopsis>
- PGconn *PQconnectdb(const char *conninfo)
- </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
- of this routine is encouraged for new application
- programming. The passed string can be empty to use all default
- parameters, or it can contain one or more parameter settings
- separated by whitespace. Each parameter setting is in the form
- keyword = value. (To write a null value or a value containing
- spaces, surround it with single quotes, eg, keyword = 'a value'.
- Single quotes within the value must be written as '. Spaces
- around the equal sign are optional.) The currently recognized
- parameter keywords are:
- <ItemizedList>
- <ListItem>
- <Para>
- <Acronym>host</Acronym> -- host to connect to.
- 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.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>port</Acronym> -- port number to connect to at the server host,
- or socket filename extension for Unix-domain connections.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>dbname</Acronym> -- database name.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>user</Acronym> -- user name for authentication.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>password</Acronym> --
- password used if the backend demands password authentication.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>authtype</Acronym> -- authorization type. (No longer used,
- since the backend now chooses how to authenticate users. libpq still
- accepts and ignores this keyword for backward compatibility.)
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>options</Acronym> -- trace/debug options to send to backend.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>tty</Acronym> -- file or tty for optional debug output from backend.
- </Para>
- </ListItem>
- </ItemizedList>
- Like PQsetdbLogin, PQconnectdb uses environment variables or built-in
- default values for unspecified options.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQconndefaults</Function>
- Returns the default connection options.
- <synopsis>
- PQconninfoOption *PQconndefaults(void)
- struct PQconninfoOption
- {
- char *keyword; /* The keyword of the option */
- char *envvar; /* Fallback environment variable name */
- char *compiled; /* Fallback compiled in default value */
- char *val; /* Option's value */
- char *label; /* Label for field in connect dialog */
- char *dispchar; /* Character to display for this field
- in a connect dialog. Values are:
- "" Display entered value as is
- "*" Password field - hide value
- "D" Debug options - don't
- create a field by default */
- int dispsize; /* Field size in characters for dialog */
- };
- </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
- PQconninfoOption structs, which ends with an entry having a NULL
- keyword pointer. Note that the default values ("val" fields)
- will depend on environment variables and other context.
- Callers must treat the connection options data as read-only.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQfinish</Function>
- Close the connection to the backend. Also frees
- memory used by the PGconn object.
- <synopsis>
- void PQfinish(PGconn *conn)
- </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.
- The PGconn pointer should not be used after PQfinish has been called.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQreset</Function>
- Reset the communication port with the backend.
- <synopsis>
- void PQreset(PGconn *conn)
- </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
- parameters previously used. This may be useful for
- error recovery if a working connection is lost.
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- <Para>
- <FileName>libpq</FileName> application 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 because they are subject to change in the future.
- (Beginning in <ProductName>Postgres</ProductName> release 6.4, the
- definition of struct PGconn is not even provided in libpq-fe.h. If you
- have old code that accesses PGconn fields directly, you can keep using it
- by including libpq-int.h too, but you are encouraged to fix the code
- soon.)
- <ItemizedList>
- <ListItem>
- <Para>
- <Function>PQdb</Function>
- Returns the database name of the connection.
- <synopsis>
- char *PQdb(PGconn *conn)
- </synopsis>
- PQdb and the next several functions return the values established
- at connection. These values are fixed for the life of the PGconn
- object.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQuser</Function>
- Returns the user name of the connection.
- <synopsis>
- char *PQuser(PGconn *conn)
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQpass</Function>
- Returns the password of the connection.
- <synopsis>
- char *PQpass(PGconn *conn)
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQhost</Function>
- Returns the server host name of the connection.
- <synopsis>
- char *PQhost(PGconn *conn)
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQport</Function>
- Returns the port of the connection.
- <synopsis>
- char *PQport(PGconn *conn)
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQtty</Function>
- Returns the debug tty of the connection.
- <synopsis>
- char *PQtty(PGconn *conn)
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQoptions</Function>
- Returns the backend options used in the connection.
- <synopsis>
- char *PQoptions(PGconn *conn)
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQstatus</Function>
- Returns the status of the connection.
- The status can be CONNECTION_OK or CONNECTION_BAD.
- <synopsis>
- ConnStatusType PQstatus(PGconn *conn)
- </synopsis>
- </Para>
- <Para>
- 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
- CONNECTION_BAD prematurely. In that case the application could
- try to recover by calling PQreset.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQerrorMessage</Function>
- Returns the error message most recently generated by
- an operation on the connection.
- <synopsis>
- char *PQerrorMessage(PGconn* conn);
- </synopsis>
- </Para>
- <Para>
- Nearly all libpq functions will set PQerrorMessage if they fail.
- Note that by libpq convention, a non-empty PQerrorMessage will
- include a trailing newline.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQbackendPID</Function>
- Returns the process ID of the backend server handling this
- connection.
- <synopsis>
- int PQbackendPID(PGconn *conn);
- </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
- server host, not the local host!
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- </Sect1>
- <Sect1>
- <Title>Query Execution Functions</Title>
- <Para>
- Once a connection to a database server has been successfully
- established, the functions described here are used to perform
- SQL queries and commands.
- <ItemizedList>
- <ListItem>
- <Para>
- <Function>PQexec</Function>
- Submit a query to <ProductName>Postgres</ProductName>
- and wait for the result.
- <synopsis>
- PGresult *PQexec(PGconn *conn,
- const char *query);
- </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
- to send the query to the backend.
- If a NULL is returned, it
- should be treated like a PGRES_FATAL_ERROR result. Use
- PQerrorMessage to get more information about the error.
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- <Para>
- The <Function>PGresult</Function> structure encapsulates the query result
- returned by the backend.
- <FileName>libpq</FileName> application programmers should be careful to
- maintain the PGresult abstraction. Use the accessor functions below to get
- at the contents of PGresult. Avoid directly referencing the fields of the
- PGresult structure because they are subject to change in the future.
- (Beginning in <ProductName>Postgres</ProductName> release 6.4, the
- definition of struct PGresult is not even provided in libpq-fe.h. If you
- have old code that accesses PGresult fields directly, you can keep using it
- by including libpq-int.h too, but you are encouraged to fix the code
- soon.)
- <ItemizedList>
- <ListItem>
- <Para>
- <Function>PQresultStatus</Function>
- Returns the result status of the query. PQresultStatus can return one of the following values:
- <synopsis>
- PGRES_EMPTY_QUERY,
- PGRES_COMMAND_OK, /* the query was a command returning no data */
- PGRES_TUPLES_OK, /* the query successfully returned tuples */
- PGRES_COPY_OUT, /* Copy Out (from server) data transfer started */
- PGRES_COPY_IN, /* Copy In (to server) data transfer started */
- PGRES_BAD_RESPONSE, /* an unexpected response was received */
- PGRES_NONFATAL_ERROR,
- PGRES_FATAL_ERROR
- </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
- happens to retrieve zero tuples still shows PGRES_TUPLES_OK.
- PGRES_COMMAND_OK is for commands that can never return tuples.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQresStatus</Function>
- Converts the enumerated type returned by PQresultStatus into
- a string constant describing the status code.
- <synopsis>
- const char *PQresStatus(ExecStatusType status);
- </synopsis>
- Older code may perform this same operation by direct access to a constant
- string array inside libpq,
- <synopsis>
- extern const char * const pgresStatus[];
- </synopsis>
- However, using the function is recommended instead, since it is more portable
- and will not fail on out-of-range values.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQresultErrorMessage</Function>
- returns the error message associated with the query, or an empty string
- if there was no error.
- <synopsis>
- const char *PQresultErrorMessage(PGresult *res);
- </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
- until destroyed, whereas the connection's error message will change when
- subsequent operations are done. Use PQresultErrorMessage when you want to
- know the status associated with a particular PGresult; use PQerrorMessage
- when you want to know the status from the latest operation on the connection.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQntuples</Function>
- Returns the number of tuples (instances)
- in the query result.
- <synopsis>
- int PQntuples(PGresult *res);
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQnfields</Function>
- Returns the number of fields
- (attributes) in each tuple of the query result.
- <synopsis>
- int PQnfields(PGresult *res);
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQbinaryTuples</Function>
- Returns 1 if the PGresult contains binary tuple data,
- 0 if it contains ASCII data.
- <synopsis>
- int PQbinaryTuples(PGresult *res);
- </synopsis>
- Currently, binary tuple data can only be returned by a query that
- extracts data from a <Acronym>BINARY</Acronym> cursor.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQfname</Function>
- Returns the field (attribute) name associated with the given field index.
- Field indices start at 0.
- <synopsis>
- char *PQfname(PGresult *res,
- int field_index);
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQfnumber</Function>
- Returns the field (attribute) index
- associated with the given field name.
- <synopsis>
- int PQfnumber(PGresult *res,
- char* field_name);
- </synopsis>
- </Para>
- <Para>
- -1 is returned if the given name does not match any field.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQftype</Function>
- 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.
- <synopsis>
- Oid PQftype(PGresult *res,
- int field_num);
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQfsize</Function>
- Returns the size in bytes of the field
- associated with the given field index.
- Field indices start at 0.
- <synopsis>
- int PQfsize(PGresult *res,
- int field_index);
- </synopsis>
- PQfsize returns the space allocated for this field in a database
- tuple, in other words the size of the server's binary representation
- of the data type. -1 is returned if the field is variable size.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQfmod</Function>
- Returns the type-specific modification data of the field
- associated with the given field index.
- Field indices start at 0.
- <synopsis>
- int PQfmod(PGresult *res,
- int field_index);
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQgetvalue</Function>
- Returns a single field (attribute) value of one tuple
- of a PGresult.
- Tuple and field indices start at 0.
- <synopsis>
- char* PQgetvalue(PGresult *res,
- int tup_num,
- int field_num);
- </synopsis>
- For most queries, the value returned by PQgetvalue
- is a null-terminated ASCII string representation
- of the attribute value. But if PQbinaryTuples() is TRUE,
- the value returned by
- PQgetvalue is the binary representation of the
- type in the internal format of the backend server
- (but not including the size word, if the field is variable-length).
- It is then the programmer's responsibility to cast and
- convert the data to the correct C type. The pointer
- returned by PQgetvalue points to storage that is
- part of the PGresult structure. One should not modify it,
- and one must explicitly
- copy the value into other storage if it is to
- be used past the lifetime of the PGresult structure itself.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQgetlength</Function>
- Returns the length of a field (attribute) in bytes.
- Tuple and field indices start at 0.
- <synopsis>
- int PQgetlength(PGresult *res,
- int tup_num,
- int field_num);
- </synopsis>
- This is the actual data length for the particular data value, that is the
- size of the object pointed to by PQgetvalue. Note that for ASCII-represented
- values, this size has little to do with the binary size reported by PQfsize.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQgetisnull</Function>
- Tests a field for a NULL entry.
- Tuple and field indices start at 0.
- <synopsis>
- int PQgetisnull(PGresult *res,
- int tup_num,
- int field_num);
- </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
- field.)
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQcmdStatus</Function>
- Returns the command status string from the SQL command that
- generated the PGresult.
- <synopsis>
- char *PQcmdStatus(PGresult *res);
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQcmdTuples</Function>
- Returns the number of rows affected by the SQL command.
- <synopsis>
- const char *PQcmdTuples(PGresult *res);
- </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
- command was anything else, it returns the empty string.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQoidStatus</Function>
- Returns a string with the object id of the tuple
- inserted, if the SQL command was an INSERT.
- Otherwise, returns an empty string.
- <synopsis>
- char* PQoidStatus(PGresult *res);
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQprint</Function>
- Prints out all the tuples and, optionally, the
- attribute names to the specified output stream.
- <synopsis>
- void PQprint(FILE* fout, /* output stream */
- PGresult* res,
- PQprintOpt* po);
- struct _PQprintOpt
- {
- pqbool header; /* print output field headings and row count */
- pqbool align; /* fill align the fields */
- pqbool standard; /* old brain dead format */
- pqbool html3; /* output html tables */
- pqbool expanded; /* expand tables */
- pqbool pager; /* use pager for output if needed */
- char *fieldSep; /* field separator */
- char *tableOpt; /* insert to HTML <table ...> */
- char *caption; /* HTML <caption> */
- char **fieldName; /* null terminated array of replacement field names */
- };
- </synopsis>
- This function is intended to replace PQprintTuples(), which is
- now obsolete. The <FileName>psql</FileName> program uses
- PQprint() to display query results.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQprintTuples</Function>
- Prints out all the tuples and, optionally, the
- attribute names to the specified output stream.
- <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*/
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQdisplayTuples</Function>
- Prints out all the tuples and, optionally, the
- attribute names to the specified output stream.
- <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 */
- </synopsis>
- PQdisplayTuples() was intended to supersede PQprintTuples(), and
- is in turn superseded by PQprint().
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQclear</Function>
- Frees the storage associated with the PGresult.
- Every query result should be freed via PQclear when
- it is no longer needed.
- <synopsis>
- void PQclear(PQresult *res);
- </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,
- you must call PQclear. Failure to do this will
- result in memory leaks in the frontend application.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQmakeEmptyPGresult</Function>
- Constructs an empty PGresult object with the given status.
- <synopsis>
- PGresult* PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status);
- </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
- status) themselves. If conn is not NULL and status indicates an error,
- the connection's current errorMessage is copied into the PGresult.
- Note that PQclear should eventually be called on the object, just
- as with a PGresult returned by libpq itself.
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- </Sect1>
- <Sect1>
- <Title>Asynchronous Query Processing</Title>
- <Para>
- The PQexec function is adequate for submitting queries in simple synchronous
- applications. It has a couple of major deficiencies however:
- <ItemizedList>
- <ListItem>
- <Para>
- PQexec waits for the query to be completed. The application may have other
- work to do (such as maintaining a user interface), in which case it won't
- want to block waiting for the response.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- Since control is buried inside PQexec, it is hard for the frontend
- to decide it would like to try to cancel the ongoing query. (It can be
- done from a signal handler, but not otherwise.)
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- PQexec can return only one PGresult structure. If the submitted query
- string contains multiple SQL commands, all but the last PGresult are
- discarded by PQexec.
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- <Para>
- Applications that do not like these limitations can instead use the
- underlying functions that PQexec is built from: PQsendQuery and
- PQgetResult.
- <ItemizedList>
- <ListItem>
- <Para>
- <Function>PQsendQuery</Function>
- Submit a query to <ProductName>Postgres</ProductName> without
- 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).
- <synopsis>
- int PQsendQuery(PGconn *conn,
- const char *query);
- </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,
- indicating that the query is done.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQgetResult</Function>
- 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.
- <synopsis>
- PGresult *PQgetResult(PGconn *conn);
- </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.)
- Each non-null result from PQgetResult should be processed using
- the same PGresult accessor functions previously described.
- Don't forget to free each result object with PQclear when done with it.
- Note that PQgetResult will block only if a query is active and the
- necessary response data has not yet been read by PQconsumeInput.
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- <Para>
- Using PQsendQuery and PQgetResult solves one of PQexec's problems:
- if a query string contains multiple SQL commands, the results of those
- commands can be obtained individually. (This allows a simple form of
- overlapped processing, by the way: the frontend can be handling the
- results of one query while the backend is still working on later
- queries in the same query string.) However, calling PQgetResult will
- still cause the frontend to block until the backend completes the
- next SQL command. This can be avoided by proper use of three more
- functions:
- <ItemizedList>
- <ListItem>
- <Para>
- <Function>PQconsumeInput</Function>
- If input is available from the backend, consume it.
- <synopsis>
- int PQconsumeInput(PGconn *conn);
- </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
- was actually collected. After calling PQconsumeInput,
- the application may check PQisBusy and/or PQnotifies to see if their state
- has changed.
- PQconsumeInput may be called even if the application is not
- prepared to deal with a result or notification just yet. The
- routine will read available data and save it in a buffer, thereby
- causing a select(2) read-ready indication to go away. The
- application can thus use PQconsumeInput to clear the select
- condition immediately, and then examine the results at leisure.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQisBusy</Function>
- 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.
- <synopsis>
- int PQisBusy(PGconn *conn);
- </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.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQsocket</Function>
- 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.
- <synopsis>
- int PQsocket(PGconn *conn);
- </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.
- If the result of select(2) indicates that data can be read from
- the backend socket, then PQconsumeInput should be called to read the
- data; after which, PQisBusy, PQgetResult, and/or PQnotifies can be
- used to process the response.
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- <Para>
- A typical frontend using these functions will have a main loop that uses
- select(2) to wait for all the conditions that it must respond to. One of
- the conditions will be input available from the backend, which in select's
- terms is readable data on the file descriptor identified by PQsocket.
- When the main loop detects input ready, it should call PQconsumeInput
- to read the input. It can then call PQisBusy, followed by PQgetResult
- if PQisBusy returns FALSE. It can also call PQnotifies to detect NOTIFY
- messages (see "Asynchronous Notification", below).
- </Para>
- <Para>
- A frontend that uses PQsendQuery/PQgetResult can also attempt to cancel
- a query that is still being processed by the backend.
- </Para>
- <Para>
- <ItemizedList>
- <ListItem>
- <Para>
- <Function>PQrequestCancel</Function>
- Request that <ProductName>Postgres</ProductName> abandon
- processing of the current query.
- <synopsis>
- int PQrequestCancel(PGconn *conn);
- </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
- effect, however. Regardless of the return value of PQrequestCancel,
- the application must continue with the normal result-reading
- sequence using PQgetResult. If the cancellation
- is effective, the current query will terminate early and return
- an error result. If the cancellation fails (say because the
- backend was already done processing the query), then there will
- be no visible result at all.
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- <Para>
- Note that if the current query is part of a transaction, cancellation
- will abort the whole transaction.
- </Para>
- <Para>
- PQrequestCancel can safely be invoked from a signal handler. So, it is
- also possible to use it in conjunction with plain PQexec, if the decision
- to cancel can be made in a signal handler. For example, psql invokes
- PQrequestCancel from a SIGINT signal handler, thus allowing interactive
- cancellation of queries that it issues through PQexec. Note that
- PQrequestCancel will have no effect if the connection is not currently open
- or the backend is not currently processing a query.
- </Para>
- </Sect1>
- <Sect1>
- <Title>Fast Path</Title>
- <Para>
- <ProductName>Postgres</ProductName> 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.
- <ItemizedList>
- <ListItem>
- <Para>
- <Function>PQfn</Function>
- Request execution of a backend function via the fast path interface.
- <synopsis>
- PGresult* PQfn(PGconn* conn,
- int fnid,
- int *result_buf,
- int *result_len,
- int result_is_int,
- PQArgBlock *args,
- int nargs);
- </synopsis>
- The fnid argument is the object identifier of the function to be
- executed.
- result_buf is the buffer in which
- to place the return value. The caller must have allocated
- sufficient space to store the return value (there is no check!).
- The actual result length will be returned in the integer pointed
- to by result_len. If a 4-byte integer result is expected, set
- result_is_int to 1; otherwise set it to 0. (Setting result_is_int to 1
- tells libpq to byte-swap the value if necessary, so that it is
- delivered as a proper int value for the client machine. When
- result_is_int is 0, the byte string sent by the backend is returned
- unmodified.)
- args and nargs specify the arguments to be passed to the function.
- <synopsis>
- typedef struct {
- int len;
- int isint;
- union {
- int *ptr;
- int integer;
- } u;
- } PQArgBlock;
- </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.
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- </Sect1>
- <Sect1>
- <Title>Asynchronous Notification</Title>
- <Para>
- <ProductName>Postgres</ProductName> supports asynchronous notification via the
- LISTEN and NOTIFY commands. A backend registers its interest in a particular
- notification condition with the LISTEN command (and can stop listening
- with the UNLISTEN command). All backends listening on a
- particular condition will be notified asynchronously when a NOTIFY of that
- condition name is executed by any 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 a database relation.
- Commonly the condition name is the same as the associated relation, but it is
- not necessary for there to be any associated relation.
- </Para>
- <Para>
- <FileName>libpq</FileName> applications submit LISTEN and UNLISTEN
- commands as ordinary SQL queries. Subsequently, arrival of NOTIFY
- messages can be detected by calling PQnotifies().
- <ItemizedList>
- <ListItem>
- <Para>
- <Function>PQnotifies</Function>
- Returns the next notification from a list of unhandled
- notification messages received from the backend. Returns NULL if
- 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.
- <synopsis>
- PGnotify* PQnotifies(PGconn *conn);
- typedef struct pgNotify
- {
- char relname[NAMEDATALEN]; /* name of relation
- * containing data */
- int be_pid; /* process id of backend */
- } PGnotify;
- </synopsis>
- After processing a PGnotify object returned by PQnotifies,
- be sure to free it with free() to avoid a memory leak.
- NOTE: in <productname>Postgres</productname> 6.4 and later,
- the be_pid is the notifying backend's, whereas in earlier versions
- it was always your own backend's PID.
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- <Para>
- The second sample program gives an example of the use
- of asynchronous notification.
- </Para>
- <Para>
- PQnotifies() does not actually read backend data; it just returns messages
- previously absorbed by another <FileName>libpq</FileName> function. In prior
- releases of <FileName>libpq</FileName>, the only way to ensure timely receipt
- of NOTIFY messages was to constantly submit queries, even empty ones, and then
- check PQnotifies() after each PQexec(). While this still works, it is
- deprecated as a waste of processing power. A better way to check for NOTIFY
- messages when you have no useful queries to make is to call PQconsumeInput(),
- then check PQnotifies(). You can use select(2) to wait for backend data to
- arrive, thereby using no CPU power unless there is something to do. Note that
- this will work OK whether you use PQsendQuery/PQgetResult or plain old PQexec
- for queries. You should, however, remember to check PQnotifies() after each
- PQgetResult or PQexec to see if any notifications came in during the
- processing of the query.
- </Para>
- </Sect1>
- <Sect1>
- <Title>Functions Associated with the COPY Command</Title>
- <Para>
- The COPY command in <ProductName>Postgres</ProductName> has options to read from
- or write to the network connection used by <FileName>libpq</FileName>.
- Therefore, functions are necessary to access this network
- connection directly so applications may take advantage of this capability.
- </Para>
- <Para>
- These functions should be executed only after obtaining a PGRES_COPY_OUT
- or PGRES_COPY_IN result object from PQexec or PQgetResult.
- </Para>
- <Para>
- <ItemizedList>
- <ListItem>
- <Para>
- <Function>PQgetline</Function>
- Reads a newline-terminated line of characters
- (transmitted by the backend server) into a buffer
- string of size length.
- <synopsis>
- int PQgetline(PGconn *conn,
- char *string,
- int length)
- </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.
- 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 two characters ".",
- which indicates that the backend server has finished sending
- the results of the copy command.
- If the application might
- receive lines that are more than length-1 characters long,
- care is needed to be sure one recognizes the "." line correctly
- (and does not, for example, mistake the end of a long data line
- for a terminator line).
- The code in
- <FileName>
- ../src/bin/psql/psql.c
- </FileName>
- contains routines that correctly handle the copy protocol.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQgetlineAsync</Function>
- Reads a newline-terminated line of characters
- (transmitted by the backend server) into a buffer
- without blocking.
- <synopsis>
- int PQgetlineAsync(PGconn *conn,
- char *buffer,
- int bufsize)
- </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
- application should call PQconsumeInput and PQgetlineAsync until the
- end-of-data signal is detected. Unlike PQgetline, this routine takes
- responsibility for detecting end-of-data.
- On each call, PQgetlineAsync will return data if a complete newline-
- terminated data line is available in libpq's input buffer, or if the
- incoming data line is too long to fit in the buffer offered by the caller.
- Otherwise, no data is returned until the rest of the line arrives.
- The routine returns -1 if the end-of-copy-data marker has been recognized,
- or 0 if no data is available, or a positive number giving the number of
- bytes of data returned. If -1 is returned, the caller must next call
- PQendcopy, and then return to normal processing.
- The data returned will not extend beyond a newline character. If possible
- a whole line will be returned at one time. But if the buffer offered by
- the caller is too small to hold a line sent by the backend, then a partial
- data line will be returned. This can be detected by testing whether the
- last returned byte is 'n' or not.
- The returned string is not null-terminated. (If you want to add a
- terminating null, be sure to pass a bufsize one smaller than the room
- actually available.)
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQputline</Function>
- Sends a null-terminated string to the backend server.
- Returns 0 if OK, EOF if unable to send the string.
- <synopsis>
- int PQputline(PGconn *conn,
- char *string);
- </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.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQputnbytes</Function>
- Sends a non-null-terminated string to the backend server.
- Returns 0 if OK, EOF if unable to send the string.
- <synopsis>
- int PQputnbytes(PGconn *conn,
- const char *buffer,
- int nbytes);
- </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.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQendcopy</Function>
- 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.
- <synopsis>
- int PQendcopy(PGconn *conn);
- </synopsis>
- </Para>
- <Para>
- As an example:
- <ProgramListing>
- PQexec(conn, "create table foo (a int4, b char(16), d float8)");
- PQexec(conn, "copy foo from stdin");
- PQputline(conn, "3thello worldt4.5n");
- PQputline(conn,"4tgoodbye worldt7.11n");
- ...
- PQputline(conn,"\.n");
- PQendcopy(conn);
- </ProgramListing>
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- <Para>
- When using PQgetResult, the application should respond to
- a PGRES_COPY_OUT result by executing PQgetline repeatedly,
- followed by PQendcopy after the terminator line is seen.
- It should then return to the PQgetResult loop until PQgetResult
- returns NULL. Similarly a PGRES_COPY_IN result is processed
- by a series of PQputline calls followed by PQendcopy, then
- return to the PQgetResult loop. This arrangement will ensure that
- a copy in or copy out command embedded in a series of SQL commands
- will be executed correctly.
- Older applications are likely to submit a copy in or copy out
- via PQexec and assume that the transaction is done after PQendcopy.
- This will work correctly only if the copy in/out is the only
- SQL command in the query string.
- </Para>
- </Sect1>
- <Sect1>
- <Title><FileName>libpq</FileName> Tracing Functions</Title>
- <Para>
- <ItemizedList>
- <ListItem>
- <Para>
- <Function>PQtrace</Function>
- Enable tracing of the frontend/backend communication to a debugging file stream.
- <synopsis>
- void PQtrace(PGconn *conn
- FILE *debug_port)
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>PQuntrace</Function>
- Disable tracing started by PQtrace
- <synopsis>
- void PQuntrace(PGconn *conn)
- </synopsis>
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- </Sect1>
- <Sect1>
- <Title>
- <FileName>libpq</FileName> Control Functions</Title>
- <Para>
- <ItemizedList>
- <ListItem>
- <Para>
- <Function>PQsetNoticeProcessor</Function>
- Control reporting of notice and warning messages generated by libpq.
- <synopsis>
- void PQsetNoticeProcessor (PGconn * conn,
- void (*noticeProcessor) (void * arg, const char * message),
- void * arg)
- </synopsis>
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- <Para>
- By default, <filename>libpq</filename> prints "notice" messages from the backend on stderr,
- as well as a few error messages that it generates by itself.
- This behavior can be overridden by supplying a callback function that
- does something else with the messages. The callback function is passed
- the text of the error message (which includes a trailing newline), plus
- a void pointer that is the same one passed to <function>PQsetNoticeProcessor</function>.
- (This pointer can be used to access application-specific state if needed.)
- The default notice processor is simply
- <ProgramListing>
- static void
- defaultNoticeProcessor(void * arg, const char * message)
- {
- fprintf(stderr, "%s", message);
- }
- </ProgramListing>
- </Para>
- <Para>
- To use a special notice processor, call <function>PQsetNoticeProcessor</function> just after
- creation of a new PGconn object.
- </Para>
- </Sect1>
- <Sect1>
- <Title>User Authentication Functions</Title>
- <Para>
- The frontend/backend authentication process is handled
- by <Function>PQconnectdb</Function> without any further intervention.
- The authentication method is now
- determined entirely by the DBA (see pga_hba.conf(5)). The following
- routines no longer have any effect and should not be used.
- </Para>
- <Para>
- <ItemizedList>
- <ListItem>
- <Para>
- <Function>fe_getauthname</Function>
- 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 <Acronym>USER</Acronym>
- environment variable or the user's entry in
- <FileName>/etc/passwd</FileName>.
- <synopsis>
- char *fe_getauthname(char* errorMessage)
- </synopsis>
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Function>fe_setauthsvc</Function>
- Specifies that <FileName>libpq</FileName> should use authentication
- service name rather than its compiled-in default.
- This value is typically taken from a command-line
- switch.
- <synopsis>
- void fe_setauthsvc(char *name,
- char* errorMessage)
- </synopsis>
- Any error messages from the authentication
- attempts are returned in the errorMessage argument.
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- </Sect1>
- <Sect1 id="libpq-envars">
- <Title>Environment Variables</Title>
- <Para>
- 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.
- <ItemizedList>
- <ListItem>
- <Para>
- <Acronym>PGHOST</Acronym> 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.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>PGPORT</Acronym> sets the default port or local Unix domain socket
- file extension for communicating with the <ProductName>Postgres</ProductName>
- backend.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>PGDATABASE</Acronym> sets the default
- <ProductName>Postgres</ProductName> database name.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>PGUSER</Acronym>
- sets the username used to connect to the database and for authentication.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>PGPASSWORD</Acronym>
- sets the password used if the backend demands password authentication.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>PGREALM</Acronym> sets the Kerberos realm to use with
- <ProductName>Postgres</ProductName>,
- if it is different from the local realm. If
- <Acronym>PGREALM</Acronym> is set, <ProductName>Postgres</ProductName>
- 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.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>PGOPTIONS</Acronym> sets additional runtime options for
- the <ProductName>Postgres</ProductName> backend.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>PGTTY</Acronym> sets the file or tty on which debugging
- messages from the backend server are displayed.
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- <Para>
- The following environment variables can be used to specify user-level default
- behavior for every Postgres session:
- <ItemizedList>
- <ListItem>
- <Para>
- <Acronym>PGDATESTYLE</Acronym>
- sets the default style of date/time representation.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>PGTZ</Acronym>
- sets the default time zone.
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- <Para>
- The following environment variables can be used to specify default internal
- behavior for every Postgres session:
- <ItemizedList>
- <ListItem>
- <Para>
- <Acronym>PGGEQO</Acronym>
- sets the default mode for the genetic optimizer.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>PGRPLANS</Acronym>
- sets the default mode to allow or disable right-sided plans in the optimizer.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>PGCOSTHEAP</Acronym>
- sets the default cost for heap searches for the optimizer.
- </Para>
- </ListItem>
- <ListItem>
- <Para>
- <Acronym>PGCOSTINDEX</Acronym>
- sets the default cost for indexed searches for the optimizer.
- </Para>
- </ListItem>
- </ItemizedList>
- </Para>
- <Para>
- Refer to the <command>SET</command> <acronym>SQL</acronym> command
- for information on correct values for these environment variables.
- </Para>
- </Sect1>
- <Sect1>
- <Title>Caveats</Title>
- <Para>
- The query buffer is 8192 bytes long, and queries over
- that length will be rejected.
- </Para>
- </Sect1>
- <Sect1>
- <Title>Sample Programs</Title>
- <Sect2>
- <Title>Sample Program 1</Title>
- <Para>
- <ProgramListing>
- /*
- * 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 (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
- {
- fprintf(stderr, "BEGIN command failedn");
- 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 (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
- {
- fprintf(stderr, "DECLARE CURSOR command failedn");
- PQclear(res);
- exit_nicely(conn);
- }
- PQclear(res);
- res = PQexec(conn, "FETCH ALL in mycursor");
- if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
- {
- fprintf(stderr, "FETCH ALL command didn't return tuples properlyn");
- 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("nn");
- /* 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);
- /* commit the transaction */
- res = PQexec(conn, "COMMIT");
- PQclear(res);
- /* close the connection to the database and cleanup */
- PQfinish(conn);
- /* fclose(debug); */
- }
- </ProgramListing>
- </Para>
- </Sect2>
- <Sect2>
- <Title>Sample Program 2</Title>
- <Para>
- <ProgramListing>
- /*
- * testlibpq2.c
- * Test of the asynchronous notification interface
- *
- * Start this program, then from psql in another window do
- * NOTIFY TBL2;
- *
- * Or, if you want to get fancy, try this:
- * 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);
- *
- * and 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 (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
- {
- fprintf(stderr, "LISTEN command failedn");
- 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' receivedn",
- notify->relname, notify->be_pid);
- free(notify);
- }
- }
- /* close the connection to the database and cleanup */
- PQfinish(conn);
- }
- </ProgramListing>
- </Para>
- </Sect2>
- <Sect2>
- <Title>Sample Program 3</Title>
- <Para>
- <ProgramListing>
- /*
- * 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 (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
- {
- fprintf(stderr, "BEGIN command failedn");
- 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 (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
- {
- fprintf(stderr, "DECLARE CURSOR command failedn");
- PQclear(res);
- exit_nicely(conn);
- }
- PQclear(res);
- res = PQexec(conn, "FETCH ALL in mycursor");
- if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
- {
- fprintf(stderr, "FETCH ALL command didn't return tuples properlyn");
- 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] = %dn",
- 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: gotn", 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 cursor */
- res = PQexec(conn, "CLOSE mycursor");
- PQclear(res);
- /* commit the transaction */
- res = PQexec(conn, "COMMIT");
- PQclear(res);
- /* close the connection to the database and cleanup */
- PQfinish(conn);
- }
- </ProgramListing>
- </Para>
- </Sect2>
- </Sect1>
- </Chapter>