*** a/doc/src/sgml/libpq.sgml
--- b/doc/src/sgml/libpq.sgml
***************
*** 7233,7238 **** int PQisthreadsafe();
--- 7233,7527 ----
   </sect1>
  
  
+  <sect1 id="libpq-altrowprocessor">
+   <title>Alternative row processor</title>
+ 
+   <indexterm zone="libpq-altrowprocessor">
+    <primary>PGresult</primary>
+    <secondary>PGconn</secondary>
+   </indexterm>
+ 
+   <para>
+    As the standard usage, rows are stored into <type>PGresult</type>
+    until full resultset is received.  Then such completely-filled
+    <type>PGresult</type> is passed to user.  This behavior can be
+    changed by registering alternative row processor function,
+    that will see each row data as soon as it is received
+    from network.  It has the option of processing the data
+    immediately, or storing it into custom container.
+   </para>
+ 
+   <para>
+    Note - as row processor sees rows as they arrive, it cannot know
+    whether the SQL statement actually finishes successfully on server
+    or not.  So some care must be taken to get proper
+    transactionality.
+   </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>
+        <variablelist>
+          <varlistentry>
+            <term><parameter>conn</parameter></term>
+            <listitem>
+              <para>
+                The connection object to set the row processor function.
+              </para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><parameter>func</parameter></term>
+            <listitem>
+              <para>
+                Storage handler function to set. NULL means to use the
+                default processor.
+              </para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><parameter>param</parameter></term>
+            <listitem>
+              <para>
+                A pointer to contextual parameter passed
+                to <parameter>func</parameter>.
+              </para>
+            </listitem>
+          </varlistentry>
+        </variablelist>
+      </para>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry id="libpq-pqrowprocessor">
+     <term>
+      <type>PQrowProcessor</type>
+      <indexterm>
+       <primary>PQrowProcessor</primary>
+      </indexterm>
+     </term>
+ 
+     <listitem>
+      <para>
+        The type for the row processor callback function.
+ <synopsis>
+ int (*PQrowProcessor)(PGresult *res, PGrowValue *columns, void *param);
+ 
+ typedef struct
+ {
+     int         len;            /* length in bytes of the value, -1 if NULL */
+     char       *value;          /* actual value, without null termination */
+ } PGrowValue;
+ </synopsis>
+      </para>
+ 
+      <para>
+       The <parameter>columns</parameter> array will have PQnfields()
+       elements, each one pointing to column value in network buffer.
+       The <parameter>len</parameter> field will contain number of
+       bytes in value.  If the field value is NULL then
+       <parameter>len</parameter> will be -1 and value will point
+       to position where the value would have been in buffer.
+       This allows estimating row size by pointer arithmetic.
+      </para>
+ 
+      <para>
+        This function must process or copy away row values in network
+        buffer before it returns, as next row might overwrite them.
+      </para>
+ 
+      <para>
+        This function can return 1 for success for success, and -1 for failure.
+        It can also return 0 to stop parsing network data and immediate exit
+        from <function>PQisBusy</function> function.  The supplied
+        <parameter>res</parameter> and <parameter>columns</parameter> values
+        will stay valid so row can be processed outside of callback.  Caller is
+        responsible for tracking whether the <function>PQisBusy</function>
+        returned because callback requested it or for other reasons.  Usually
+        this should happen via setting cached values to NULL before calling
+        <function>PQisBusy</function>.
+      </para>
+ 
+      <para>
+        The function is allowed to exit via exception (eg: setjmp/longjmp).
+        The connection and row are guaranteed to be in valid state.
+        The connection can later be closed
+        via <function>PQfinish</function>.  Processing can also be
+        continued without closing the connection, either with 
+        <function>getResult</function> or <function>PQisBusy</function>.
+        Then processing will continue with next row, old row that got
+        exception will be skipped.  Or you can discard all remaining
+        rows by calling <function>PQskipResult</function>.
+      </para>
+ 
+      <variablelist>
+ 
+        <varlistentry>
+          <term><parameter>res</parameter></term>
+          <listitem>
+            <para>
+              A pointer to <type>PGresult</type> object that describes
+              the row structure.
+            </para>
+            <para>
+              This object is owned by <type>PGconn</type>
+              so callback must not free it.
+            </para>
+          </listitem>
+        </varlistentry>
+ 
+        <varlistentry>
+          <term><parameter>columns</parameter></term>
+          <listitem>
+            <para>
+              Column values of the row to process.  Column values
+              are located in network buffer, the processor must
+              copy them out from there.
+            </para>
+            <para>
+              Column values are not null-terminated, so processor cannot
+              use C string functions on them directly.
+            </para>
+            <para>
+              This pointer is owned by <type>PGconn</type>
+              so callback must not free it.
+            </para>
+          </listitem>
+        </varlistentry>
+ 
+        <varlistentry>
+          <term><parameter>param</parameter></term>
+          <listitem>
+            <para>
+              Extra parameter that was given to
+ 	     <function>PQsetRowProcessor</function>.
+            </para>
+          </listitem>
+        </varlistentry>
+ 
+      </variablelist>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry id="libpq-pqgetrowprocessor">
+     <term>
+      <function>PQgetRowProcessor</function>
+      <indexterm>
+       <primary>PQgetRowProcessor</primary>
+      </indexterm>
+     </term>
+     <listitem>
+       <para>
+        Get row processor and its context parameter currently set to
+        the connection.
+ <synopsis>
+ PQrowProcessor PQgetRowProcessor(PGconn *conn, void **param);
+ </synopsis>
+       </para>
+       <para>
+         <variablelist>
+          <varlistentry>
+            <term><parameter>conn</parameter></term>
+            <listitem>
+              <para>
+                The connection object.
+              </para>
+            </listitem>
+          </varlistentry>
+ 
+          <varlistentry>
+            <term><parameter>param</parameter></term>
+            <listitem>
+              <para>
+               Location to store the extra parameter of current row processor.
+               If NULL, then parameter is not stored.
+              </para>
+            </listitem>
+          </varlistentry>
+ 
+         </variablelist>
+       </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 incoming resultset.
+ <synopsis>
+ int PQskipResult(PGconn *conn, int skipAll);
+ </synopsis>
+       </para>
+       <para>
+        The function is simple convinience method to drop one or more
+        incoming resultsets.  It is useful when handling exceptions
+        from row processor.  It is implementing by simply calling
+        <function>PQgetResult</function> once or in a loop.
+       </para>
+       <para>
+        It returns 1 if the last <function>PQgetResult</function>
+        retutrned non-NULL.  This can happen only when
+        <parameter>skipAll</parameter> is false.
+       </para>
+ 
+       <para>
+         <variablelist>
+          <varlistentry>
+            <term><parameter>conn</parameter></term>
+            <listitem>
+              <para>
+                The connection object.
+              </para>
+            </listitem>
+          </varlistentry>
+ 
+          <varlistentry>
+            <term><parameter>skipAll</parameter></term>
+            <listitem>
+              <para>
+                If true, then <function>PQgetResult</function>
+                is called until it returns NULL.  That means
+                there are no more incoming resultsets.
+              </para>
+              <para>
+                If false, <function>PQgetResult</function> is called
+                only once.  The return value shows whether
+                there was result available or not.
+              </para>
+            </listitem>
+          </varlistentry>
+ 
+         </variablelist>
+       </para>
+     </listitem>
+    </varlistentry>
+ 
+   </variablelist>
+ 
+  </sect1>
+ 
+ 
   <sect1 id="libpq-build">
    <title>Building <application>libpq</application> Programs</title>
  
