diff options
Diffstat (limited to 'doc/src')
-rw-r--r-- | doc/src/sgml/libpq.sgml | 416 |
1 files changed, 139 insertions, 277 deletions
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 5c5dd68db30..255c5c1abb8 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -2418,14 +2418,28 @@ ExecStatusType PQresultStatus(const PGresult *res); <term><literal>PGRES_COPY_BOTH</literal></term> <listitem> <para> - Copy In/Out (to and from server) data transfer started. This is - currently used only for streaming replication. + Copy In/Out (to and from server) data transfer started. This + feature is currently used only for streaming replication, + so this status should not occur in ordinary applications. + </para> + </listitem> + </varlistentry> + + <varlistentry id="libpq-pgres-single-tuple"> + <term><literal>PGRES_SINGLE_TUPLE</literal></term> + <listitem> + <para> + The <structname>PGresult</> contains a single result tuple + from the current command. This status occurs only when + single-row mode has been selected for the query + (see <xref linkend="libpq-single-row-mode">). </para> </listitem> </varlistentry> </variablelist> - If the result status is <literal>PGRES_TUPLES_OK</literal>, then + If the result status is <literal>PGRES_TUPLES_OK</literal> or + <literal>PGRES_SINGLE_TUPLE</literal>, then the functions described below can be used to retrieve the rows returned by the query. Note that a <command>SELECT</command> command that happens to retrieve zero rows still shows @@ -2726,7 +2740,8 @@ void PQclear(PGresult *res); These functions are used to extract information from a <structname>PGresult</structname> object that represents a successful query result (that is, one that has status - <literal>PGRES_TUPLES_OK</literal>). They can also be used to extract + <literal>PGRES_TUPLES_OK</literal> or <literal>PGRES_SINGLE_TUPLE</>). + They can also be used to extract information from a successful Describe operation: a Describe's result has all the same column information that actual execution of the query would provide, but it has zero rows. For objects with other status values, @@ -3738,7 +3753,7 @@ unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length); <para> The <function>PQexec</function> function is adequate for submitting - commands in normal, synchronous applications. It has a couple of + commands in normal, synchronous applications. It has a few deficiencies, however, that can be of importance to some users: <itemizedlist> @@ -3769,6 +3784,15 @@ unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length); <function>PQexec</function>. </para> </listitem> + + <listitem> + <para> + <function>PQexec</function> always collects the command's entire result, + buffering it in a single <structname>PGresult</structname>. While + this simplifies error-handling logic for the application, it can be + impractical for results containing many rows. + </para> + </listitem> </itemizedlist> </para> @@ -3984,8 +4008,11 @@ int PQsendDescribePortal(PGconn *conn, const char *portalName); Waits for the next result from a prior <function>PQsendQuery</function>, <function>PQsendQueryParams</function>, - <function>PQsendPrepare</function>, or - <function>PQsendQueryPrepared</function> call, and returns it. + <function>PQsendPrepare</function>, + <function>PQsendQueryPrepared</function>, + <function>PQsendDescribePrepared</function>, or + <function>PQsendDescribePortal</function> + call, and returns it. A null pointer is returned when the command is complete and there will be no more results. <synopsis> @@ -4012,7 +4039,7 @@ PGresult *PQgetResult(PGconn *conn); <para> Even when <function>PQresultStatus</function> indicates a fatal error, <function>PQgetResult</function> should be called until it - returns a null pointer to allow <application>libpq</> to + returns a null pointer, to allow <application>libpq</> to process the error information completely. </para> </note> @@ -4029,7 +4056,18 @@ PGresult *PQgetResult(PGconn *conn); can be obtained individually. (This allows a simple form of overlapped processing, by the way: the client can be handling the results of one command while the server is still working on later queries in the same - command string.) However, calling <function>PQgetResult</function> + command string.) + </para> + + <para> + Another frequently-desired feature that can be obtained with + <function>PQsendQuery</function> and <function>PQgetResult</function> + is retrieving large query results a row at a time. This is discussed + in <xref linkend="libpq-single-row-mode">. + </para> + + <para> + By itself, calling <function>PQgetResult</function> will still cause the client to block until the server completes the next <acronym>SQL</acronym> command. This can be avoided by proper use of two more functions: @@ -4238,6 +4276,98 @@ int PQflush(PGconn *conn); </sect1> + <sect1 id="libpq-single-row-mode"> + <title>Retrieving Query Results Row-By-Row</title> + + <indexterm zone="libpq-single-row-mode"> + <primary>libpq</primary> + <secondary>single-row mode</secondary> + </indexterm> + + <para> + Ordinarily, <application>libpq</> collects a SQL command's + entire result and returns it to the application as a single + <structname>PGresult</structname>. This can be unworkable for commands + that return a large number of rows. For such cases, applications can use + <function>PQsendQuery</function> and <function>PQgetResult</function> in + <firstterm>single-row mode</>. In this mode, the result row(s) are + returned to the application one at a time, as they are received from the + server. + </para> + + <para> + To enter single-row mode, call <function>PQsetSingleRowMode</function> + immediately after a successful call of <function>PQsendQuery</function> + (or a sibling function). This mode selection is effective only for the + currently executing query. Then call <function>PQgetResult</function> + repeatedly, until it returns null, as documented in <xref + linkend="libpq-async">. If the query returns any rows, they are returned + as individual <structname>PGresult</structname> objects, which look like + normal query results except for having status code + <literal>PGRES_SINGLE_TUPLE</literal> instead of + <literal>PGRES_TUPLES_OK</literal>. After the last row, or immediately if + the query returns zero rows, a zero-row object with status + <literal>PGRES_TUPLES_OK</literal> is returned; this is the signal that no + more rows will arrive. (But note that it is still necessary to continue + calling <function>PQgetResult</function> until it returns null.) All of + these <structname>PGresult</structname> objects will contain the same row + description data (column names, types, etc) that an ordinary + <structname>PGresult</structname> object for the query would have. + Each object should be freed with <function>PQclear</function> as usual. + </para> + + <para> + <variablelist> + <varlistentry id="libpq-pqsetsinglerowmode"> + <term> + <function>PQsetSingleRowMode</function> + <indexterm> + <primary>PQsetSingleRowMode</primary> + </indexterm> + </term> + + <listitem> + <para> + Select single-row mode for the currently-executing query. + +<synopsis> +int PQsetSingleRowMode(PGconn *conn); +</synopsis> + </para> + + <para> + This function can only be called immediately after + <function>PQsendQuery</function> or one of its sibling functions, + before any other operation on the connection such as + <function>PQconsumeInput</function> or + <function>PQgetResult</function>. If called at the correct time, + the function activates single-row mode for the current query and + returns 1. Otherwise the mode stays unchanged and the function + returns 0. In any case, the mode reverts to normal after + completion of the current query. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + + <caution> + <para> + While processing a query, the server may return some rows and then + encounter an error, causing the query to be aborted. Ordinarily, + <application>libpq</> discards any such rows and reports only the + error. But in single-row mode, those rows will have already been + returned to the application. Hence, the application will see some + <literal>PGRES_SINGLE_TUPLE</literal> <structname>PGresult</structname> + objects followed by a <literal>PGRES_FATAL_ERROR</literal> object. For + proper transactional behavior, the application must be designed to + discard or undo whatever has been done with the previously-processed + rows, if the query ultimately fails. + </para> + </caution> + + </sect1> + <sect1 id="libpq-cancel"> <title>Canceling Queries in Progress</title> @@ -5700,274 +5830,6 @@ defaultNoticeProcessor(void *arg, const char *message) </sect1> - <sect1 id="libpq-row-processor"> - <title>Custom Row Processing</title> - - <indexterm zone="libpq-row-processor"> - <primary>PQrowProcessor</primary> - </indexterm> - - <indexterm zone="libpq-row-processor"> - <primary>row processor</primary> - <secondary>in libpq</secondary> - </indexterm> - - <para> - Ordinarily, when receiving a query result from the server, - <application>libpq</> adds each row value to the current - <type>PGresult</type> until the entire result set is received; then - the <type>PGresult</type> is returned to the application as a unit. - This approach is simple to work with, but becomes inefficient for large - result sets. To improve performance, an application can register a - custom <firstterm>row processor</> function that processes each row - as the data is received from the network. The custom row processor could - process the data fully, or store it into some application-specific data - structure for later processing. - </para> - - <caution> - <para> - The row processor function sees the rows before it is known whether the - query will succeed overall, since the server might return some rows before - encountering an error. For proper transactional behavior, it must be - possible to discard or undo whatever the row processor has done, if the - query ultimately fails. - </para> - </caution> - - <para> - When using a custom row processor, row data is not accumulated into the - <type>PGresult</type>, so the <type>PGresult</type> ultimately delivered to - the application will contain no rows (<function>PQntuples</> = - <literal>0</>). However, it still has <function>PQresultStatus</> = - <literal>PGRES_TUPLES_OK</>, and it contains correct information about the - set of columns in the query result. On the other hand, if the query fails - partway through, the returned <type>PGresult</type> has - <function>PQresultStatus</> = <literal>PGRES_FATAL_ERROR</>. The - application must be prepared to undo any actions of the row processor - whenever it gets a <literal>PGRES_FATAL_ERROR</> result. - </para> - - <para> - A custom row processor is registered for a particular connection by - calling <function>PQsetRowProcessor</function>, described below. - This row processor will be used for all subsequent query results on that - connection until changed again. A row processor function must have a - signature matching - -<synopsis> -typedef int (*PQrowProcessor) (PGresult *res, const PGdataValue *columns, - const char **errmsgp, void *param); -</synopsis> - where <type>PGdataValue</> is described by -<synopsis> -typedef struct pgDataValue -{ - int len; /* data length in bytes, or <0 if NULL */ - const char *value; /* data value, without zero-termination */ -} PGdataValue; -</synopsis> - </para> - - <para> - The <parameter>res</> parameter is the <literal>PGRES_TUPLES_OK</> - <type>PGresult</type> that will eventually be delivered to the calling - application (if no error intervenes). It contains information about - the set of columns in the query result, but no row data. In particular the - row processor must fetch <literal>PQnfields(res)</> to know the number of - data columns. - </para> - - <para> - Immediately after <application>libpq</> has determined the result set's - column information, it will make a call to the row processor with - <parameter>columns</parameter> set to NULL, but the other parameters as - usual. The row processor can use this call to initialize for a new result - set; if it has nothing to do, it can just return <literal>1</>. In - subsequent calls, one per received row, <parameter>columns</parameter> - is non-NULL and points to an array of <type>PGdataValue</> structs, one per - data column. - </para> - - <para> - <parameter>errmsgp</parameter> is an output parameter used only for error - reporting. If the row processor needs to report an error, it can set - <literal>*</><parameter>errmsgp</parameter> to point to a suitable message - string (and then return <literal>-1</>). As a special case, returning - <literal>-1</> without changing <literal>*</><parameter>errmsgp</parameter> - from its initial value of NULL is taken to mean <quote>out of memory</>. - </para> - - <para> - The last parameter, <parameter>param</parameter>, is just a void pointer - passed through from <function>PQsetRowProcessor</function>. This can be - used for communication between the row processor function and the - surrounding application. - </para> - - <para> - In the <type>PGdataValue</> array passed to a row processor, data values - cannot be assumed to be zero-terminated, whether the data format is text - or binary. A SQL NULL value is indicated by a negative length field. - </para> - - <para> - The row processor <emphasis>must</> process the row data values - immediately, or else copy them into application-controlled storage. - The value pointers passed to the row processor point into - <application>libpq</>'s internal data input buffer, which will be - overwritten by the next packet fetch. - </para> - - <para> - The row processor function must return either <literal>1</> or - <literal>-1</>. - <literal>1</> is the normal, successful result value; <application>libpq</> - will continue with receiving row values from the server and passing them to - the row processor. <literal>-1</> indicates that the row processor has - encountered an error. In that case, - <application>libpq</> will discard all remaining rows in the result set - and then return a <literal>PGRES_FATAL_ERROR</> <type>PGresult</type> to - the application (containing the specified error message, or <quote>out of - memory for query result</> if <literal>*</><parameter>errmsgp</parameter> - was left as NULL). - </para> - - <para> - Another option for exiting a row processor is to throw an exception using - C's <function>longjmp()</> or C++'s <literal>throw</>. If this is done, - processing of the incoming data can be resumed later by calling - <function>PQgetResult</>; the row processor will be invoked as normal for - any remaining rows in the current result. - As with any usage of <function>PQgetResult</>, the application - should continue calling <function>PQgetResult</> until it gets a NULL - result before issuing any new query. - </para> - - <para> - In some cases, an exception may mean that the remainder of the - query result is not interesting. In such cases the application can discard - the remaining rows with <function>PQskipResult</>, described below. - Another possible recovery option is to close the connection altogether with - <function>PQfinish</>. - </para> - - <para> - <variablelist> - <varlistentry id="libpq-pqsetrowprocessor"> - <term> - <function>PQsetRowProcessor</function> - <indexterm> - <primary>PQsetRowProcessor</primary> - </indexterm> - </term> - - <listitem> - <para> - Sets a callback function to process each row. - -<synopsis> -void PQsetRowProcessor(PGconn *conn, PQrowProcessor func, void *param); -</synopsis> - </para> - - <para> - The specified row processor function <parameter>func</> is installed as - the active row processor for the given connection <parameter>conn</>. - Also, <parameter>param</> is installed as the passthrough pointer to - pass to it. Alternatively, if <parameter>func</> is NULL, the standard - row processor is reinstalled on the given connection (and - <parameter>param</> is ignored). - </para> - - <para> - Although the row processor can be changed at any time in the life of a - connection, it's generally unwise to do so while a query is active. - In particular, when using asynchronous mode, be aware that both - <function>PQisBusy</> and <function>PQgetResult</> can call the current - row processor. - </para> - </listitem> - </varlistentry> - - <varlistentry id="libpq-pqgetrowprocessor"> - <term> - <function>PQgetRowProcessor</function> - <indexterm> - <primary>PQgetRowProcessor</primary> - </indexterm> - </term> - - <listitem> - <para> - Fetches the current row processor for the specified connection. - -<synopsis> -PQrowProcessor PQgetRowProcessor(const PGconn *conn, void **param); -</synopsis> - </para> - - <para> - In addition to returning the row processor function pointer, the - current passthrough pointer will be returned at - <literal>*</><parameter>param</>, if <parameter>param</> is not NULL. - </para> - </listitem> - </varlistentry> - - <varlistentry id="libpq-pqskipresult"> - <term> - <function>PQskipResult</function> - <indexterm> - <primary>PQskipResult</primary> - </indexterm> - </term> - - <listitem> - <para> - Discard all the remaining rows in the incoming result set. - -<synopsis> -PGresult *PQskipResult(PGconn *conn); -</synopsis> - </para> - - <para> - This is a simple convenience function to discard incoming data after a - row processor has failed or it's determined that the rest of the result - set is not interesting. <function>PQskipResult</> is exactly - equivalent to <function>PQgetResult</> except that it transiently - installs a dummy row processor function that just discards data. - The returned <type>PGresult</> can be discarded without further ado - if it has status <literal>PGRES_TUPLES_OK</>; but other status values - should be handled normally. (In particular, - <literal>PGRES_FATAL_ERROR</> indicates a server-reported error that - will still need to be dealt with.) - As when using <function>PQgetResult</>, one should usually repeat the - call until NULL is returned to ensure the connection has reached an - idle state. Another possible usage is to call - <function>PQskipResult</> just once, and then resume using - <function>PQgetResult</> to process subsequent result sets normally. - </para> - - <para> - Because <function>PQskipResult</> will wait for server input, it is not - very useful in asynchronous applications. In particular you should not - code a loop of <function>PQisBusy</> and <function>PQskipResult</>, - because that will result in the installed row processor being called - within <function>PQisBusy</>. To get the proper behavior in an - asynchronous application, you'll need to install a dummy row processor - (or set a flag to make your normal row processor do nothing) and leave - it that way until you have discarded all incoming data via your normal - <function>PQisBusy</> and <function>PQgetResult</> loop. - </para> - </listitem> - </varlistentry> - </variablelist> - </para> - - </sect1> - <sect1 id="libpq-events"> <title>Event System</title> |