Skip to Content
0
Jun 28, 2021 at 03:18 AM

why ADBC Courser is invalid?

285 Views Last edit Jun 29, 2021 at 01:49 AM 4 rev

Hi there,

I have try to use ADBC to download very big( > 8G) internal table, the code like below:

LO_CONN = cl_sql_connection=>get_connection('R/3*DEMO'). 
L_STMT_REF = NEW cl_sql_statement( con_ref = LO_CONN ).
L_STMT = `SELECT * from xxx`.
L_RES_REF = L_STMT_REF->EXECUTE_QUERY( statement = L_STMT
                                         hold_cursor = 'X' ).
GET REFERENCE OF WA_xxx INTO l_dref.
L_RES_REF->set_param_struct( l_dref ).

TABLE_LINE_COUNT = 0.
CLEAR: IT_xxx.
WHILE L_RES_REF->next( ) > 0.
    APPEND WA_xxx TO IT_xxx.
    TABLE_LINE_COUNT = TABLE_LINE_COUNT + 1.
    IF TABLE_LINE_COUNT >= MAXSIZE.
      PERFORM CONV_TABLE_TO_TEXT TABLES IT_xxx
        USING LV_FILE
              LS_TABLE .
      TABLE_LINE_COUNT = 0.
      CLEAR: IT_xxx,LS_TABLE .
    ENDIF.
  ENDWHILE.
  IF IT_xxx IS NOT INITIAL.
    PERFORM CONV_TABLE_TO_TEXT TABLES IT_xxx
        USING LV_FILE
              LS_TABLE .
    TABLE_LINE_COUNT
    CLEAR: IT_xxx,LS_TABLE .
    TABLE_LINE_COUNT = 0.

  ENDIF.

the CONV_TABLE_TO_TEXT is call GUI_DOWNLOAD function to download data to local computer.

the first cycle is correctly download the data, but second cycle in the while raise the invalid courser exception in 'L_RES_REF->next( )', I debug find next() call ADBC fetch function return sy-subrc = 9 (invalid courser). The courser have checked and it is valid before next() call ADBC fetch function. The revoke code like below.

cursor already exhausted? if yes, do nothing but return with 0.
  IF me->cursor = c_invalid_cursor.
    rows_ret = 0.
    RETURN.
  ENDIF.

  CALL 'C_DB_FUNCTION' ID 'FUNCTION' FIELD 'DB_SQL'
                       ID 'FCODE'    FIELD c_fcode_fetch_cursor
                       ID 'CONNAME'  FIELD me->con_ref->con_name
                       ID 'CONDA'    FIELD me->con_ref->con_da
                       ID 'CURSOR'   FIELD me->cursor
                       ID 'BOUND'    FIELD me->outvals_bound
                       ID 'OUTVALS'  FIELD me->parameters->param_tab
                       ID 'SQLCODE'  FIELD sql_code
                       ID 'SQLMSG'   FIELD sql_msg.

  IF sy-subrc = 0.
*   a row was fetched
    rows_ret = 1.
    add_to_rows_fetched( rows_ret ).

*   set the OUTVALS_BOUND flag; this avoids "reassignement" of the
*   output variables the next time this method is called, i.e. the
*   next fetch call uses the same output variables as the previous
*   call; this optimization works for sure only for the Oracle
*   implementation of the DBDS interface
    IF ( me->outvals_bound IS INITIAL ) AND ( me->con_ref->get_dbms( ) = 'ORA' ).
      me->outvals_bound = 'X'.
    ENDIF.
  ELSE.
    DATA error_code LIKE sy-subrc.
    error_code = sy-subrc.

*   in any case close the cursor
    close_cursor( ).
    rows_ret = 0.

    IF error_code <> 4.
*     call error handling macro.
      m_handle_error error_code sql_code sql_msg.
    ENDIF.
  ENDIF.

so why valid courser raise invalid courser exception after ADBC fetch function?