Re: [patch] libpq one-row-at-a-time API

From: Merlin Moncure <mmoncure(at)gmail(dot)com>
To: Marko Kreen <markokr(at)gmail(dot)com>
Cc: Postgres Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: [patch] libpq one-row-at-a-time API
Date: 2012-06-15 20:54:33
Message-ID: CAHyXU0wcoW6UkzxzkQeiETSMFoEXZq9u7Yh+_NZ3JCOfgBrGqQ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Fri, Jun 15, 2012 at 1:21 PM, Marko Kreen <markokr(at)gmail(dot)com> wrote:
> The row-processor API is now in 9.2, but it solves only the
> "different-row-storage" problem, but not the "one-row-at-a-time"
> problem, as libpq is still in control until all rows are received.
>
> This means libpq cannet still be used to implement iterative
> result processing that almost all high-level languages are using.
>
> We discussed potential API for fetching on single row at a time,
> but did not reach conclusion.  Basic arguments were:
>
> 1) Tom: PQisBusy must keep current behaviour.  Thus also PQgetResult()
>   must keep current behaviour:
>   * PQisBusy() -> 0: need to call PQgetResult(), which returns PGresult
>   * PQisBusy() -> 1: need to call PQconsumeInput()
>   * PQisBusy() must be callable several times in a row, thus be
>     stateless from clients POV.
>
> 2) Me: behaviour must not be controlled by callback, but client code
>   that uses PQgetResult() + PQisBusy().
>
> Now, looking at the problem with some perspective, the solution
> is obvious: when in single-row mode, the PQgetResult() must return
> proper PGresult for that single row.  And everything else follows that.
>
> Such API is implemented in attached patch:
>
> * PQsetSingleRowMode(conn): set's single-row mode.
>
> * PQisBusy(): stops after each row in single-row mode, sets PGASYNC_ROW_READY.
>  Thus keeping the property of being repeatedly callable.
>
> * PQgetResult(): returns copy of the row if PGASYNC_ROW_READY.  Sets row
>  resultStatus to PGRES_SINGLE_TUPLE.  This needs to be different from
>  PGRES_TUPLES_OK to detect resultset end.
>
> * PQgetRowData(): can be called instead PQgetResult() to get raw row data
>  in buffer, for more efficient processing.  This is optional feature
>  that provides the original row-callback promise of avoiding unnecessary
>  row data copy.
>
> * Although PQgetRowData() makes callback API unnecessary, it is still
>  fully compatible with it - the callback should not see any difference
>  whether the resultset is processed in single-row mode or
>  old single-PGresult mode.  Unless it wants to - it can check
>  PGRES_TUPLES_OK vs. PGRES_SINGLE_TUPLE.
>
> There is some duplicate code here that can be refactored (callback exec),
> but I did not do it yet to avoid affecting existing code too much.
>
> --
> marko
>
> PS. If a squint it seems like fix of exising API instead of new feature,
> so perhaps it can still fit into 9.2?

+1 on rushing in row processing for 9.2, but only if the API feels
right (i'll spend some time to review). I found the lack of iterative
row processing to be really unfortunate.

merlin

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Jeff Janes 2012-06-15 21:51:29 Re: Resource Owner reassign Locks
Previous Message Peter Geoghegan 2012-06-15 20:51:37 Re: sortsupport for text