Thread: Function Issue

Function Issue

From
ALMA TAHIR
Date:
It would be very helpful if anyone could help me with below issue.
I am using below stored proc:
 CREATE OR REPLACE FUNCTION FETCH_CALL_LOGS() RETURNS refcursor AS $$
DECLARE
call_log_rec call_log % rowtype;
call_log_cursor refcursor;
BEGIN
OPEN call_log_cursor FOR
SELECT *
FROM
  call_log
   WHERE aht_read_status = 0
          ORDER BY record_sequence_number ASC limit 20 FOR UPDATE;
LOOP
    FETCH NEXT FROM call_log_cursor INTO call_log_rec;
    EXIT WHEN call_log_rec IS NULL;
    UPDATE call_log SET aht_read_status = 1 WHERE record_sequence_number = call_log_rec.record_sequence_number;
END LOOP;
RETURN call_log_cursor;
END;
$$ LANGUAGE plpgsql;
 
and trying to read response in java:
 
           java.sql.CallableStatement proc =  c.prepareCall("{ ? = call fetch_call_logs() }");
           c.setAutoCommit(false); 
           proc.registerOutParameter(1, java.sql.Types.OTHER);
             proc.execute();
             ResultSet rset2 = (ResultSet) proc
                     .getObject(1);
                 while (rset2.next()) {
                    System.out.println(rset2
                        .getString(1));
                  }
                 rset2.close();
                // c.setAutoCommit(false);
                 proc.close();
                 c.close();
 
but i am not able to get proper response back... if i comment out the fetch statement and tried doing some static update i am able to get proper response back. Stucked up with this...
I want to open a ref cursor with select for update and then update the records and get the ref cursor in response back in java.
But its not happening .... if i return ref cursor only after select it works fine but after fetch when i am returning the response back i am not getting..
Where am I doing the mistake or anything I am missing???? Please help me with the same ... it would be very helpful.....

Re: Function Issue

From
Tom Lane
Date:
ALMA TAHIR <almaheena2003@yahoo.co.in> writes:
> I want to open a ref cursor with select for update and then update
> the records and get the ref cursor in response back in java.

Your function has already sucked all the rows out of the cursor before
it returns it, so it's not surprising that further reads from the cursor
produce nothing.

You could try rewinding the cursor (see MOVE) but I'm not sure that will
help in this case, since the function has carefully ensured that none of
the rows pass the cursor query's WHERE condition anymore.  I think that
since the cursor used SELECT FOR UPDATE, it will not return the updated
rows even after rewinding.  (I could be wrong though, so it's worth
trying.)

I think you need to rethink what you're doing.  This seems like a fairly
silly application design: why not do all the processing you need on these
rows in one place?  Or at the very least, don't use one cursor to serve
two masters.  Possibly you could have the function return the rows itself
instead of passing back a refcursor.
        regards, tom lane



Re: Function Issue

From
ALMA TAHIR
Date:
hi,
thankyou for suggestions, its working now. I ma retrieving the ids in an int[] and then using one more cursor to read and return using the int[].



On Thursday, 27 February 2014 8:04 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
ALMA TAHIR <almaheena2003@yahoo.co.in> writes:
> I want to open a ref cursor with select for update and then update
> the records and get the ref cursor in response back in java.

Your function has already sucked all the rows out of the cursor before
it returns it, so it's not surprising that further reads from the cursor
produce nothing.

You could try rewinding the cursor (see MOVE) but I'm not sure that will
help in this case, since the function has carefully ensured that none of
the rows pass the cursor query's WHERE condition anymore.  I think that
since the cursor used SELECT FOR UPDATE, it will not return the updated
rows even after rewinding.  (I could be wrong though, so it's worth

trying.)


I think you need to rethink what you're doing.  This seems like a fairly
silly application design: why not do all the processing you need on these
rows in one place?  Or at the very least, don't use one cursor to serve
two masters.  Possibly you could have the function return the rows itself
instead of passing back a refcursor.

            regards, tom lane


--
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql



Re: Function Issue

From
ALMA TAHIR
Date:
Hi,

I am using below code in multi threaded environment, but when multiple threads are accessing then i get : "org.postgresql.util.PSQLException: ERROR: tuple concurrently updated" exception. But my concern is I need to use it in multi threaded env, for the same reason I am using FOR UPDATE with cursor. Then where is the issue??? Am I missing something????? Please help me with the same.....
        Statement stmt = c.createStatement();
          // Setup function to call.
          stmt.execute("CREATE OR REPLACE FUNCTION refcursorfunc() RETURNS refcursor AS '"
                                          + " DECLARE "
                                          + "    call_log_rec call_log % rowtype; "
                                          + "             call_log_cursor refcursor; "
                                          + " final_cursor refcursor; "
                                          + " idInt int[]; "
                                          + " BEGIN "
                                          + "    OPEN call_log_cursor FOR SELECT * FROM call_log WHERE aht_read_status = 0 ORDER BY record_sequence_number ASC limit 20 FOR UPDATE; "
                                          + " LOOP "
                                          + " FETCH NEXT FROM call_log_cursor INTO call_log_rec; "
                                          + " EXIT WHEN call_log_rec IS NULL; "
                                          + " UPDATE call_log SET aht_read_status = 1 WHERE CURRENT OF call_log_cursor; "
                                          + " idInt := idInt || ARRAY [call_log_rec.record_sequence_number]; "
                                          + " END LOOP;"
                                          + " OPEN final_cursor FOR SELECT record_sequence_number FROM call_log WHERE record_sequence_number  = ANY(idInt); "
                                          + "    RETURN final_cursor; "
                                          + " END;' language plpgsql");
          stmt.close();
          // We must be inside a transaction for cursors to work.
          c.setAutoCommit(false);

          // Procedure call.
          CallableStatement proc = c.prepareCall("{ ? = call refcursorfunc() }");
          proc.registerOutParameter(1, Types.OTHER);
          System.out.println("BEFORE::: Thread name::: " + Thread.currentThread().getName());
          proc.execute();
         
          ResultSet results = (ResultSet) proc.getObject(1);
          while (results.next()) {
              // do something with the results...
                          System.out.println("Hurrey got the results from SP........");
                          System.out.println("AFTER::::Thread name::: " + Thread.currentThread().getName()+ " record_sequence_number:::: "+results.getString(1));
          }
          c.commit();
          results.close();
          proc.close();



On Friday, 28 February 2014 6:47 PM, ALMA TAHIR <almaheena2003@yahoo.co.in> wrote:
hi,
thankyou for suggestions, its working now. I ma retrieving the ids in an int[] and then using one more cursor to read and return using the int[].



On Thursday, 27 February 2014 8:04 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
ALMA TAHIR <almaheena2003@yahoo.co.in> writes:
> I want to open a ref cursor with select for update and then update
> the records and get the ref cursor in response back in java.

Your function has already sucked all the rows out of the cursor before
it returns it, so it's not surprising that further reads from the cursor
produce nothing.

You could try rewinding the cursor (see MOVE) but I'm not sure that will
help in this case, since the function has carefully ensured that none of
the rows pass the cursor query's WHERE condition anymore.  I think that
since the cursor used SELECT FOR UPDATE, it will not return the updated
rows even after rewinding.  (I could be wrong though, so it's worth

trying.)


I think you need to rethink what you're doing.  This seems like a fairly
silly application design: why not do all the processing you need on these
rows in one place?  Or at the very least, don't use one cursor to serve
two masters.  Possibly you could have the function return the rows itself
instead of passing back a refcursor.

            regards, tom lane


--
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql





Re: Function Issue

From
Adrian Klaver
Date:
On 03/03/2014 03:32 AM, ALMA TAHIR wrote:
> Hi,
>
> I am using below code in multi threaded environment, but when multiple
> threads are accessing then i get : "org.postgresql.util.PSQLException:
> ERROR: tuple concurrently updated" exception. But my concern is I need
> to use it in multi threaded env, for the same reason I am using FOR
> UPDATE with cursor. Then where is the issue??? Am I missing
> something????? Please help me with the same.....


I will say up front I am wandering out of my depth, but here it goes.

I researched the above error message and it always seems to lead back to 
issue with a system catalog tuple getting concurrent updates.

So, are we seeing all the queries that are happening when you run the 
function?
In other words is there anything that touches a system catalog, say an 
ANALYZE?

Are you sure your threads are using separate transactions and are not 
tromping over each other?

What does the Postgres log show around the error message?

>
>
>
>
>


-- 
Adrian Klaver
adrian.klaver@aklaver.com