Thread: Fetching rows from a cursor returned by a stored function

Fetching rows from a cursor returned by a stored function

From
James Ireland
Date:
Hi everybody

I have a stored function that returns a large number of rows as a cursor.  I am trying to prevent the entire result set
beingreturned at once.  The code fragment below hits an OutOfMemoryError on the "while(resultSet.next())" line, which I
believeis for this reason.   


    // ...get connection...

    connection.setAutoCommit(false);

    // prepare the stored function call
    statement = connection.prepareCall("{ ? = call get_events(?,?,?) }",
            ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
    statement.registerOutParameter(1, Types.OTHER);

    // set the fetch size so that the query doesn't return all results at once
    statement.setFetchDirection(ResultSet.FETCH_FORWARD);
    statement.setFetchSize(1000);

    // execute the query
    statement.execute();
    resultSet = (ResultSet)statement.getObject(1);

    while(resultSet.next()) {

        // ...process rows...


The code includes my first attempt to make this work by setting the fetch size.  This still doesn't fix it, and I can
seethat the result set that I am setting the fetch size for probably isn't the one that I am getting back and iterating
through. I can't figure out how I ought to be doing this though. 

Can anyone offer any advice on how this should be done?

Many thanks
-James

Re: Fetching rows from a cursor returned by a stored function

From
Oliver Jowett
Date:
James Ireland wrote:
> Hi everybody
>
> I have a stored function that returns a large number of rows as a
> cursor.  I am trying to prevent the entire result set being returned at
> once.  The code fragment below hits an OutOfMemoryError on the
> "while(resultSet.next())" line, which I believe is for this reason.

Unfortunately the current driver does not support cursor-based retrieval
for functions that return refcursors: it grabs the whole resultset at
once when the refcursor is retrieved as Types.OTHER.

If you don't mind the ugliness, you could register the result parameter
as Types.VARCHAR; that will give you a cursor name that you can then use
to execute FETCH queries yourself.

It might even work to execute FETCH FORWARD ALL for the cursor with a
non-zero fetchsize (and let the driver manage incremental fetches) but
I'm not sure what the behaviour of a non-zero row limit on a FETCH query
is at the protocol level..

-O

Re: Fetching rows from a cursor returned by a stored function

From
Tom Lane
Date:
Oliver Jowett <oliver@opencloud.com> writes:
> It might even work to execute FETCH FORWARD ALL for the cursor with a
> non-zero fetchsize (and let the driver manage incremental fetches) but
> I'm not sure what the behaviour of a non-zero row limit on a FETCH query
> is at the protocol level..

[ digs in code... ]  It looks like the behavior would be to (a)
materialize the entire result of FETCH FORWARD ALL inside the backend,
then (b) hand back the number of rows you requested.  Probably not what
you want :-(.  I'd suggest issuing successive "FETCH n" commands and
ignoring the protocol-level limit feature.

            regards, tom lane

Re: Fetching rows from a cursor returned by a stored function

From
James Ireland
Date:
Thanks a lot for your help.  I've implemented the successive "FETCH n" commands approach and it works a treat.

-James

Tom Lane wrote:
> Oliver Jowett <oliver@opencloud.com> writes:
>
>>It might even work to execute FETCH FORWARD ALL for the cursor with a
>>non-zero fetchsize (and let the driver manage incremental fetches) but
>>I'm not sure what the behaviour of a non-zero row limit on a FETCH query
>>is at the protocol level..
>
>
> [ digs in code... ]  It looks like the behavior would be to (a)
> materialize the entire result of FETCH FORWARD ALL inside the backend,
> then (b) hand back the number of rows you requested.  Probably not what
> you want :-(.  I'd suggest issuing successive "FETCH n" commands and
> ignoring the protocol-level limit feature.
>
>             regards, tom lane
>
> ---------------------------(end of broadcast)---------------------------
> TIP 8: explain analyze is your friend
>
>
>