Search code examples
c++plsqloracle-pro-c

Using Pro*C, how to fetch from a cursor opened in PL stored function without setting 'sqlcheck=semantics' option?


I am trying to fetch data from a cursor variable opened in a stored function but I always get "fetch out of sequence" error message.

Here is the stored function:

CREATE OR REPLACE FUNCTION test_function RETURN SYS_REFCURSOR AS
  p_recordset SYS_REFCURSOR;
BEGIN
  OPEN p_recordset FOR SELECT '1' FROM DUAL UNION SELECT '2' FROM DUAL;
  RETURN p_recordset;
END TEST_FUNCTION;

And the Pro*C code:

int myfunction()
{
  ...
  EXEC SQL BEGIN DECLARE SECTION;
  SQL_CURSOR sql_cursor_pl;
  VARCHAR string_field[20];
  EXEC SQL END DECLARE SECTION;

  EXEC SQL ALLOCATE :sql_cursor_pl;

  // It is not possible to use embedded PL/SQL block as seen in other 
  // examples because it requieres a compilation time access to database 
  // that I don't have, so as far as I know I have to use EXEC SQL CALL
  EXEC SQL CALL sch.test_function() INTO :sql_cursor_pl;

  EXEC SQL WHENEVER NOT FOUND DO break;

  //for ( ; ; )
  while (sqlca.sqlcode == '\0')
  {
    EXEC SQL FETCH :sql_cursor_pl INTO :string_field;
    ...
  }

  EXEC SQL CLOSE :sql_cursor_pl;
  ...
}

The stored function works fine if I use it in other PL block like the one below, so I think the problem should be in Pro*C code.

DECLARE
  mycursor sys_refcursor;
  string_field VARCHAR(20)
BEGIN
  mycursor := sch.test_function();
  LOOP
    FETCH mycursor INTO string_field;
    EXIT WHEN mycursor%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(string_field);
  END LOOP;
  CLOSE mycursor;
END;

Solution

  • I think I have found the problem and one solution. When opening a cursor in a PL/SQL block the cursor index starts from 0, but Pro*C ones start from 1. The problem I think is that Pro*C does not update cursor index at all, so one solution could be making an increment manually like this as seen here.

    ...
    while (sqlca.sqlcode == '\0')
    {
      sql_cursor_pl.curocn++;
      EXEC SQL FETCH :sql_cursor_pl INTO :string_field;
      ...
    }
    ...