.nf
 
 .nf
 
    ========== licence begin  GPL
    Copyright (c) 2000-2005 SAP AG
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
.fo
 
 
.fo
*****************************************************
Copyright (c) 2000-2005 SAP AG
SAP Database Technology
 
Release :      Date : 2000-11-07
*****************************************************
modname : VAK74
changed : 2000-11-07
module  : Fetch_Without_Resulttable
 
Author  : ElkeZ
Created : 1985-10-16
*****************************************************
 
Purpose : Provides the procedures in order to get the
          desired result in the case of a FETCH without
          result set.
 
Define  :
 
        PROCEDURE
              a74_search_fetch (
                    VAR acv        : tak_all_command_glob;
                    VAR sparr      : tak_syspointerarr;
                    mtype          : tgg00_MessType2;
                    pos            : tsp00_Int4;
                    VAR resn_rec   : tak_sysbufferaddress;
                    single_fetch   : boolean;
                    mfetch_count   : tsp00_Int4);
 
        PROCEDURE
              a74_copy_twokeys (
                    VAR acv     : tak_all_command_glob;
                    VAR keysbuf : tak_res_keysbuf;
                    VAR source  : tak_two_keyspecs;
                    VAR dest    : tak_two_keyspecs;
                    res_stat    : tak_sresstate);
 
.CM *-END-* define --------------------------------------
***********************************************************
 
Use     :
 
        FROM
              AK_universal_semantic_tools : VAK06;
 
        PROCEDURE
              a06cpy_mblock (
                    VAR acv        : tak_all_command_glob;
                    VAR src_mblock : tgg00_MessBlock;
                    VAR dst_mblock : tgg00_MessBlock;
                    withoutData    : boolean;
                    VAR e          : tgg00_BasisError);
 
        PROCEDURE
              a06init_curr_retpart (VAR acv : tak_all_command_glob);
 
        PROCEDURE
              a06retpart_move (
                    VAR acv     : tak_all_command_glob;
                    moveobj_ptr : tsp00_MoveObjPtr;
                    move_len    : tsp00_Int4);
 
        PROCEDURE
              a06finish_curr_retpart (
                    VAR acv   : tak_all_command_glob;
                    part_kind : tsp1_part_kind;
                    arg_count : tsp00_Int2);
 
        PROCEDURE
              a06rsend_mess_buf (
                    VAR acv     : tak_all_command_glob;
                    VAR mbuf    : tgg00_MessBlock;
                    result_req  : boolean;
                    VAR e       : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK07;
 
        PROCEDURE
              a07_b_put_error (
                    VAR acv  : tak_all_command_glob;
                    b_err    : tgg00_BasisError;
                    err_code : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK071;
 
        FUNCTION
              a071_return_code (
                    b_err   : tgg00_BasisError;
                    sqlmode : tsp00_SqlMode) : tsp00_Int2;
 
      ------------------------------ 
 
        FROM
              Systeminfo_cache : VAK10;
 
        PROCEDURE
              a10get_sysinfo (
                    VAR acv      : tak_all_command_glob;
                    VAR syskey   : tgg00_SysInfoKey;
                    dstate       : tak_directory_state;
                    VAR syspoint : tak_sysbufferaddress;
                    VAR b_err    : tgg00_BasisError);
 
        PROCEDURE
              a10repl_sysinfo (
                    VAR acv      : tak_all_command_glob;
                    VAR syspoint : tak_sysbufferaddress;
                    VAR b_err    : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              Long-Support-Getval: VAK508;
 
        PROCEDURE
              a508_lget_long_columns (
                    VAR acv             : tak_all_command_glob;
                    VAR change_rec      : tak_changerecord;
                    VAR lcol_lock       : boolean;
                    rec_cnt             : integer;
                    rec_len             : integer;
                    startpos            : integer);
 
        FUNCTION
              a508_lcol_found (
                    VAR acv        : tak_all_command_glob;
                    VAR change_rec : tak_changerecord) : boolean;
 
      ------------------------------ 
 
        FROM
              Select_Syntax : VAK60;
 
        PROCEDURE
              a60_change_results (
                    VAR acv        : tak_all_command_glob;
                    VAR data       : tsp00_MoveObj;
                    VAR change_rec : tak_changerecord;
                    startpos       : integer;
                    curr_resreclen : integer);
 
        PROCEDURE
              a60rescount (
                    VAR acv  : tak_all_command_glob;
                    rescount : tsp00_Int4);
 
        PROCEDURE
              a60_put_result (
                    VAR acv    : tak_all_command_glob;
                    VAR mblock : tgg00_MessBlock;
                    spos       : integer);
 
      ------------------------------ 
 
        FROM
              Resulttable: VAK73;
 
        PROCEDURE
              a73_infolen_get (
                    VAR acv        : tak_all_command_glob;
                    no_of_out_cols : integer;
                    VAR output_len : tsp00_Int2);
 
        FUNCTION
              a73_calc_unused_space (
                    VAR acv : tak_all_command_glob) : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              Single_Select : VKB720;
 
        PROCEDURE
              k720_maxresult_get (
                    strat_maxcnt       : tsp00_Int4;
                    VAR maxresult      : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              Select_Help_Procedures : VGG04;
 
        PROCEDURE
              g04smallest_greater_key(
                    VAR file_id    : tgg00_FileId;
                    VAR key        : tgg00_Lkey );
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        PROCEDURE
              g01mblock_init (
                    VAR source_trans : tgg00_TransContext;
                    mess_type  : tgg00_MessType;
                    mess2_type : tgg00_MessType2;
                    VAR mblock : tgg00_MessBlock);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalMove  (
                    mod_id          : tsp00_C6;
                    mod_intern_num  : tsp00_Int4;
                    source_upb      : tsp00_Int4;
                    destin_upb      : tsp00_Int4;
                    source          : tsp00_MoveObjPtr;
                    source_pos      : tsp00_Int4;
                    destin          : tsp00_MoveObjPtr;
                    destin_pos      : tsp00_Int4;
                    length          : tsp00_Int4;
                    VAR e           : tgg00_BasisError);
 
        PROCEDURE
              SAPDB_PascalOverlappingMove (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    source_upb  : tsp00_Int4;
                    dest_upb    : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    src_pos     : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    dest_pos    : tsp00_Int4;
                    length      : tsp00_Int4;
                    VAR e       : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vdebug_break (debug_break_pos : tsp00_Int4);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01messblock (
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    VAR m         : tgg00_MessBlock);
 
        PROCEDURE
              t01basis_error (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname;
                    b_err : tgg00_BasisError);
 
        PROCEDURE
              t01fetch_desc(
                    debug       : tgg00_Debug;
                    nam         : tsp00_Sname;
                    VAR mf_desc : tgg00_FetchDesc);
 
        PROCEDURE
              t01c32 (
                    debug : tgg00_Debug;
                    msg   : tsp00_C32);
 
        PROCEDURE
              t01dist_optim(
                    debug       : tgg00_Debug;
                    nam         : tsp00_Sname;
                    dist_optim  : tsp00_Int2);
 
        PROCEDURE
              t01sname (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname);
 
        PROCEDURE
              t01p2bool (
                    debug : tgg00_Debug;
                    nam_1 : tsp00_Sname;
                    bool1 : boolean;
                    nam_2 : tsp00_Sname;
                    bool2 : boolean);
 
        PROCEDURE
              t01p2int4 (
                    debug : tgg00_Debug;
                    nam_1 : tsp00_Sname;
                    int_1 : tsp00_Int4;
                    nam_2 : tsp00_Sname;
                    int_2 : tsp00_Int4);
 
        PROCEDURE
              t01name (
                    debug : tgg00_Debug;
                    nam   : tsp00_Name);
 
        PROCEDURE
              t01buf (
                    debug    : tgg00_Debug;
                    VAR buf  : tak_res_keysbuf;
                    startpos : integer;
                    endpos   : integer);
 
        PROCEDURE
              t01mess2type (
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    mess2_type    : tgg00_MessType2);
 
        PROCEDURE
              t01bool (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    curr_bool: boolean);
 
        PROCEDURE
              t01handling (
                    debug : tgg00_Debug;
                    nam : tsp00_Sname;
                    s   : tgg00_HandlingSet);
 
        PROCEDURE
              t01int4 (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01key (
                    debug   : tgg00_Debug;
                    nam     : tsp00_Sname;
                    VAR k   : tgg00_Lkey);
 
        PROCEDURE
              t01moveobj (
                    debug    : tgg00_Debug;
                    VAR buf  : tsp00_MoveObj;
                    startpos : tsp00_Int4;
                    endpos   : tsp00_Int4);
&       endif
 
.CM *-END-* use -----------------------------------------
***********************************************************
 
Synonym :
 
        PROCEDURE
              t01buf;
 
              tsp00_Buf tak_res_keysbuf
 
.CM *-END-* synonym -------------------------------------
***********************************************************
Specification:
 
Following fetches are semanticly equivalent:
 
(mass) fetch absolute  1 = (mass) fetch first
(mass) fetch absolute -1 = (mass) fetch last
(mass) fetch relative  0 = (mass) fetch same
 
Mass fetches delivers more than one row from desired position
towards EOF. Exceptions are 'mfetch last' and 'mfetch prev'.
These mass fetches delivers rows from desired postion
towards EOF to have more semantic. Otherwise
'mfetch last' is equivalent 'fetch last' and 'mfetch prev' is
equivalent 'mfetch relative -1'.
 
 
.CM *-END-* specification -------------------------------
***********************************************************
 
Description:
A74_SEARCH_FETCH
------------------------
 
The system-information record in which the stack entries and data for the
qualification are located is fetched; the record with the information on how
far in the result set fetching has already been performed is used.
Depending on the search direction, preparatory measures are taken: in FIRST
and LAST, entries are made in the key pairs (primary keys and inversion keys)
starting from which the search is to be made (always res_nextkeys or
res_prevkeys).
In DIRECT (specification of POS [  ]), an attempt is made, starting from
known positions (<> -1) in the result set, to find the shortest route to the
desired position. The search can be made starting from res_nextpos or
res_prevpos (different according to preceding MFETCHes) or from the beginning
of the result set. ACT_CNT specifies the number of results to be processed.
USE_RECS specifies that they are to be jumped and not returned to AK (the
search itself is performed in a loop in KB). After this jump, entries must be
made in that key pair in which entries were not already implicitly made in the
course of the jump. After this jump, the position one before the desired
position is reached, so that, both in FETCH and also in MFETCH, the search can
always be continued with NEXT.
A distinction is made as to whether the user has specified FETCH
(single_fetch) or MFETCH.
In FETCH, a search is made by calling RECORD_FETCH with ACT_CNT = 1 for
precisely only one result record, which is to be delivered in its full length
(with Key and key/keys of the base table(s) required for FOR UPDATE) (ACT_LENG
= RES_RECLEN).
If it was a SELECT with 'FOR UPDATE' (res_length=length of the output
desired by the user < length of a result record (the primary keys of the base
tables are also in there)), the keys are transferred to the extra sysinfo
record for Join View keys or to the normal record, which also contains the
other information required for FETCH. RES_USEUPDK specifies whether it is then
possible to perform a ... CURRENT OF with this result-set name or not.
A60_PUT_RESULT
transfers the result from part1 of the Mess-Buffer to the SQL_PACKET (if
there is still space for it there in addition to the long infos).
If MFETCH was specified, it is not possible for a command with CURRENT
OF to be used.
It is determined how many of the desired results can be accommodated in the
SQL_PACKET together with the info part. As least one result is fetched
and, if necessary, intermediately stored in the Mess-Buffer, so that it can be
fetched with FETCH REST.
In a loop, as many results are fetched as will fit into the SQL_PACKET
or as the user has requested. This is done in that, each time, a maximum of one
buffer is filled with results by calling RECORD_FETCH.
After the first call of RECORD_FETCH (foundrecs = 0), error 100 may
possibly be returned; the search direction is changed from FIRST/LAST to
NEXT/PREV.
_FS_FIRST_LOOP specifies whether, in RECORD_FETCH, entries are to be made not only
in RES_NEXTKEYS (in FIRST/NEXT), but also in RES_PREVKEYS (entry with the first
key when first called).
If code conversions are necessary (atcolcount > 0), these are performed for
all results (part2.m_cnt) by the repeated calling of A60_CHANGE_RESULTS.
Since, in MFETCH, not the entire result record, but only its info part
(also excluding any implicitly appended primary keys for FOR UPDATE) is
delivered (the keys for further search are in the structure in part2 of the
Mess-Buffer), the positions given here are different from those in FETCH.
If one of the result records will no longer fit into the request segment
because of the long long infos, it is intermediately stored in part2 of the
Mess-Buffer.
Otherwise, the results are moved directly to the SQL_PACKET. It
applies in this connection that, also for MFETCH PREV/LAST, the result with the
smallest key is at the extreme left in the SQL_PACKET, i.e. the SQL_PACKET
is filled from right to left. This also means that, if fewer than the
desired number of results exist, the filled part of part2 of the
SQL_PACKET has to be pulled up to part1.
The number of results found is, byte-swapped if necessary, entered in the
first two bytes of part2.
 
RECORD_FETCH
 
Depending on the search direction, different key pairs are used for making
entries in the structure in part2 of the Mess-Buffer. There are also
differences as to whether a search is to be made via an inversion (teuseinv in
res_resstate) or not.
It is also specified whether a stop key with a significant value exists.
 
BUILD_FETCH_MESS_BUF
 
The following parameters are passed:
 
-  STARTKEYS : Key pair (consists of one inversion-list value and one primary
key) at which the search is to begin
 
-  STOPKEYS : Key pair at which the search is to end
 
-  ONE_STARTKEY : if the search is to be made via an inversion (specified in
MREC.RESST), it may be that the search is not to be started at the first
primary key in the next inversion list, but at the primary-key value identified
by ONE_STARTKEY
 
-  FIRSTKEYS : Key pair in which, if _FS_FIRST_LOOP = true, are to be entered the key
values (inversion key and primary key) of the first result found
 
-  MREC : contains information on whether there was a FETCH (single, i.e.
result must be the entire record, not only the Info part), how long a result is
(act_leng), how many results are to be fetched (act_cnt) etc.
 
-  STOP : specifies whether STOPKEYS is to be used or not
In this procedure, entries are made in the structure in part2 of
the Mess-Buffer, which has the following appearance:
 
           m_use_inv        : boolean;
           m_use_stop       : boolean;
           m_single         : boolean;
           m_use_recs       : boolean;
           m_keylen         : int2;
           m_cnt            : int2;
           m_leng           : int2;
           m_fns1           : filename; (*pos 11*)
           m_fns2           : filename; (*pos 39*)
           m_startkeys      : two_keys; (*pos 67, 325*)
           m_stopkeys       : two_keys; (*pos 583, 841*)
           m_firstkeys      : two_keys; (*pos 1099, 1357*)
           m_start          : lkey;     (*pos 1615*)
 
Here, m_use_recs specifies whether the results are required in AK or whether
they are just to be jumped in order to reach the desired position
(specification of POS [  ]).
M_keylen is required in order to identify the start position of the info
part in a result record.
M_fns1 is the file name of the primary file, with m_fns2 being the name of
the secondary file.
After the command has been executed (A06_SEND_MESS_BUF), the transaction
status is reset to its original value, which may have been extended for this
(M)FETCH request to include information for WITH LOCK ...
(state:= state + tmtrans_count.state).
If there is no error, entries are made in the STRATKEYS key pair and, if
applicable, in the FIRSTKEYS key pair.
The values for the positions must be re-determined, so that they can be
used in the next (M)FETCH POS [  ].
Only mm_next (even if (M)FETCH DIRECT/FIRST) specified), mm_last, mm_prev
and mm_same (only in FETCH, not in MFETCH) may appear for the POSTYPE (search is
made with STEPTYPE).
If mm_last was specified, the position of the result is unknown (-1), since the
total number of results is not known. If mm_next/mm_prev was specified,
the position must be changed by the number of results found. Only when
BUILD_FETCH_MESS_BUF is first called for an MFETCH/FETCH (_fs_first_loop) need
an entry be made in the position that is required for FETCHes with opposite
search direction.
 
.CM *-END-* description ---------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
CONST
      c_stop             = true (* ak74build_fetch_mess_buf *);
 
TYPE
      t_fetch_switch = (
            _fs_first_loop,
            _fs_single_fetch,
            _fs_use_recs,
            _fs_rowno_set,
            _fs_last_rowno );
 
      mfetch_rec = RECORD
            fr_act_cnt       : tsp00_Int4;
            fr_resnamerec    : tak_sysbufferaddress;
            fr_act_leng      : tsp00_Int2;
            fr_resstate      : tak_sresstate;
            fr_stepkind      : tgg00_MessType2;
            fr_poskind       : tgg00_MessType2;
            fr_switches      : SET OF t_fetch_switch;
      END;
 
 
 
(*------------------------------*) 
 
PROCEDURE
      ak74build_fetch_mess_buf (
            VAR acv             : tak_all_command_glob;
            VAR sparr           : tak_syspointerarr;
            VAR mblock          : tgg00_MessBlock;
            VAR startkeys       : tak_two_keyspecs;
            VAR stopkeys        : tak_two_keyspecs;
            VAR one_startkey    : tak_keyspec;
            VAR firstkeys       : tak_two_keyspecs;
            VAR mrec            : mfetch_rec;
            rescnt              : tsp00_Int4;
            direct_retpart_move : boolean;
            stop                : boolean);
 
CONST
      c_without_data = true;
 
VAR
      _e              : tgg00_BasisError;
      _first_free     : integer;
      _data_len       : tsp00_Int4;
      _stratptr       : tgg07_StrategyInfoPtr;
 
BEGIN
&ifdef trace
t01int4 (ak_sem, 'rescnt      ', rescnt );
t01bool (ak_sem, 'direct_retpa', direct_retpart_move );
&endif
g01mblock_init (acv.a_transinf.tri_trans,
      m_fetch, mrec.fr_stepkind, acv.a_mblock);
_first_free                  := mblock.mb_qual^.mfirst_free;
mblock.mb_qual^.mfirst_free := 1; (* don't copy stack entries ! *)
_data_len                    := mblock.mb_data_len;
(* don't copy data *)
mblock.mb_data_len := 0;
acv.a_mblock.mb_qual       := acv.a_mb_qual_addr;
acv.a_mblock.mb_qual_size  := acv.a_mb_qual_size;
acv.a_mblock.mb_strat      := acv.a_mb_strat_addr;
acv.a_mblock.mb_strat_size := acv.a_mb_strat_size;
IF  ( direct_retpart_move )
THEN
    BEGIN
    acv.a_mblock.mb_data := @acv.a_curr_retpart^.sp1p_buf[
          acv.a_curr_retpart^.sp1p_buf_len + 1];
    acv.a_mblock.mb_data_size := acv.a_curr_retpart^.sp1p_buf_size -
          acv.a_curr_retpart^.sp1p_buf_len
    END
ELSE
    BEGIN
    acv.a_mblock.mb_data      := acv.a_mb_data_addr;
    acv.a_mblock.mb_data_size := acv.a_mb_data_size;
    END;
(*ENDIF*) 
a06cpy_mblock (acv, mblock, acv.a_mblock, NOT c_without_data, _e);
acv.a_mblock.mb_st                := mblock.mb_st;
acv.a_mblock.mb_st_size           := mblock.mb_st_size;
acv.a_mblock.mb_st_max            := mblock.mb_st_max;
acv.a_mblock.mb_qual^.mst_addr    := mblock.mb_st;
acv.a_mblock.mb_qual^.mfirst_free := _first_free;
mblock.mb_qual^.mfirst_free       := _first_free;
(* PTS 1106955 E.Z. *)
acv.a_mblock.mb_qual^.msqlmode := sparr.px[ 2 ]^.sreskey.res_pars_sqlmode;
mblock.mb_data_len := _data_len;
IF  ( _e <> e_ok )
THEN
    a07_b_put_error (acv, _e, 1)
ELSE
    BEGIN
    WITH acv.a_mblock.mb_qual^.mf_desc DO
        BEGIN
        m_fetch_state := [];
        acv.a_mblock.mb_type  := m_fetch;
        acv.a_mblock.mb_type2 := mrec.fr_stepkind;
        (* PTS 1000801 E.Z. *)
        m_rescnt     := rescnt;
        (* h.b. PTS 1001366 *)
        m_rowno      := sparr.px[ 2 ]^.sreskey.res_rowno;
        IF  ( stop )
        THEN
            m_fetch_state := m_fetch_state + [ fs_use_stop ];
        (* get cluster io info from strat *)
        (*ENDIF*) 
        IF  ( mblock.mb_strat <> NIL )         AND
            ( mblock.mb_qual <> NIL )          AND
            ( mblock.mb_st <> NIL)             AND
            ( mblock.mb_qual^.mstrat_pos > 0 ) AND
            ( mblock.mb_st^[ mblock.mb_qual^.mstrat_pos ].epos + STRATEGY_START_MXGG07 <= mblock.mb_strat_len )
        THEN
            BEGIN
            _stratptr := @mblock.mb_strat^[mblock.mb_st^[ mblock.mb_qual^.mstrat_pos ].epos];
            IF  _stratptr^.str_use_clusterIO
            THEN
                m_fetch_state := m_fetch_state + [ fs_use_cluster ];
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        m_cnt        := mrec.fr_act_cnt;
        m_keylen     := sparr.px[ 2 ]^.sreskey.res_keylen;
        m_leng       := mrec.fr_act_leng;
        IF  ( _fs_single_fetch in mrec.fr_switches )
        THEN
            m_fetch_state := m_fetch_state + [ fs_single ];
        (*ENDIF*) 
        IF  ( _fs_use_recs in mrec.fr_switches )
        THEN
            m_fetch_state := m_fetch_state + [ fs_use_recs ];
        (*ENDIF*) 
        m_dist_optim := sparr.px[ 2 ]^.sreskey.res_dist_optim;
        m_qual_kind  := sparr.px[ 2 ]^.sreskey.res_qual_kind;
        m_strat_info := sparr.px[ 2 ]^.sreskey.res_strat_info;
        m_searched_pages := sparr.px[2]^.sreskey.res_searched_pages;
        IF  ( rs_useinv in mrec.fr_resstate ) AND
            (( mrec.fr_stepkind <> mm_direct ) OR ( m_qual_kind = inv_only ))
        THEN
            m_fetch_state := m_fetch_state + [ fs_use_inv ];
        (*ENDIF*) 
        IF  ( sparr.px[ 2 ]^.sreskey.res_reverse_access )
        THEN
            m_fetch_state := m_fetch_state + [ fs_reverse_fetch ];
&       ifdef trace
        (*ENDIF*) 
        t01name(ak_sem, 'start -> m_startke');
&       endif
        ak74copy2_twokeys (acv,
              sparr.px[ 2 ]^.sreskey.res_keysbuf,
              startkeys, m_startkeys,
              mrec.fr_resstate);
        IF  ( acv.a_returncode = 0 )
        THEN
            BEGIN
&           ifdef trace
            t01name(ak_sem, 'stop -> m_stopkey ');
&           endif
            ak74copy2_twokeys (acv,
                  sparr.px[ 2 ]^.sreskey.res_keysbuf,
                  stopkeys, m_stopkeys,
                  mrec.fr_resstate)
            END;
        (*ENDIF*) 
        IF  ( acv.a_returncode = 0 )
        THEN
            BEGIN
&           ifdef trace
            t01name(ak_sem, 'one_star-> m_start');
&           endif
            m_start.len := one_startkey.ks_len;
            SAPDB_PascalMove ('VAK74 ',   1,    
                  sizeof(sparr.px[ 2 ]^.sreskey.res_keysbuf), sizeof(m_start.k),
                  @sparr.px[ 2 ]^.sreskey.res_keysbuf, one_startkey.ks_pos,
                  @m_start.k, 1,
                  m_start.len, acv.a_returncode);
            END;
        (*ENDIF*) 
        IF  ( acv.a_mblock.mb_type2 in
            [ mm_direct, mm_next, mm_first, mm_last_rowno ] ) AND
            ( m_start.len > 0 )
        THEN
            BEGIN
&           ifdef trace
            t01name(ak_sem, 'manip. m_start    ');
&           endif
            g04smallest_greater_key( acv.a_mblock.mb_qual^.mtree, m_start );
            END
        ELSE
            BEGIN
            (* where is code for fetch prev/last ??? *)
            END;
        (*ENDIF*) 
        m_fns1                    := sparr.px[ 2 ]^.sreskey.res_treeids.file_id;
        m_fns1.fileHandling_gg00  := acv.a_mblock.mb_qual^.mtree.fileHandling_gg00;
        m_fns1.fileLeafNodes_gg00 := cgg_nil_leafnodes;
        (* PTS 1111576 E.Z. *)
        IF  hsConsistentLock_egg00 in m_fns1.fileHandling_gg00
        THEN
            m_fns1.fileHandling_gg00 := m_fns1.fileHandling_gg00 +
                  [ hsCollisionTest_egg00 ] - [ hsConsistentLock_egg00 ];
        (*ENDIF*) 
        IF  (hsPermLock_egg00 in m_fns1.fileHandling_gg00) AND
            NOT (hsIntentExcl_egg00 in m_fns1.fileHandling_gg00)
        THEN
            m_fns1.fileHandling_gg00 := m_fns1.fileHandling_gg00 + [ hsWithoutLock_egg00 ];
        (*ENDIF*) 
        m_fns2      := sparr.px[ 2 ]^.sreskey.res_treeids.inv_id;
        m_data := mblock.mb_data;
        acv.a_mblock.mb_qual_len := sizeof (acv.a_mblock.mb_qual^.mf_desc);
&       ifdef trace
        t01fetch_desc(ak_sem, 'fetch desc  ', acv.a_mblock.mb_qual^.mf_desc);
&       endif
        END;
    (*ENDWITH*) 
    END;
(*ENDIF*) 
IF  acv.a_returncode = 0
THEN
    BEGIN
    a06rsend_mess_buf (acv, acv.a_mblock, cak_return_req, _e);
    (* Do NOT change e to mb_trns^.trError_gg00 *)
&   ifdef TRACE
    t01basis_error (ak_sem, 'b_error     ', _e);
    t01fetch_desc(ak_sem, 'fetch desc  ', acv.a_mblock.mb_qual^.mf_desc);
    IF  ( fs_use_inv in acv.a_mblock.mb_qual^.mf_desc.m_fetch_state )
    THEN
        BEGIN
        t01key (ak_sem, 'm_startk inv', acv.a_mblock.mb_qual^.mf_desc.
              m_startkeys.listkey);
        t01key (ak_sem, 'm_stopk  inv', acv.a_mblock.mb_qual^.mf_desc.
              m_stopkeys.listkey);
        END;
    (*ENDIF*) 
    t01key (ak_sem, 'm_startk key', acv.a_mblock.mb_qual^.mf_desc.
          m_startkeys.reckey);
    t01key (ak_sem, 'm_stopk  key', acv.a_mblock.mb_qual^.mf_desc.
          m_stopkeys.reckey);
&   endif
    END;
(*ENDIF*) 
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    IF  ( _e <> e_ok )
    THEN
        BEGIN
        IF  ( acv.a_mblock.mb_trns^.trError_gg00 in [ e_no_next_record,
            e_no_prev_record, e_no_next_invkey, e_no_prev_invkey ] )
        THEN
            BEGIN
            IF  ( mrec.fr_stepkind in [ mm_next, mm_last_rowno, mm_first ] )
            THEN
                (* steps to EOF *)
                BEGIN
                sparr.px[ 2 ]^.sreskey.res_bof := false;
                sparr.px[ 2 ]^.sreskey.res_eof := true;
                sparr.px[ 2 ]^.sreskey.res_nextpos := -1;
                sparr.px[ 2 ]^.sreskey.res_prevpos := -1;
                (* reset res_prevkeys *)
&               ifdef trace
                t01name(ak_sem, 'reset next/prev   ');
                t01name(ak_sem, 'r_stop  -> r_prev ');
&               endif
                a74_copy_twokeys (acv,
                      sparr.px[ 2 ]^.sreskey.res_keysbuf,
                      sparr.px[ 2 ]^.sreskey.res_stopkeys,
                      sparr.px[ 2 ]^.sreskey.res_prevkeys,
                      sparr.px[ 2 ]^.sreskey.res_resstate);
&               ifdef trace
                t01name(ak_sem, 'r_stop  -> r_next ');
&               endif
                a74_copy_twokeys (acv,
                      sparr.px[ 2 ]^.sreskey.res_keysbuf,
                      sparr.px[ 2 ]^.sreskey.res_stopkeys,
                      sparr.px[ 2 ]^.sreskey.res_nextkeys,
                      sparr.px[ 2 ]^.sreskey.res_resstate);
                END
            ELSE
                BEGIN
                sparr.px[ 2 ]^.sreskey.res_bof := true;
                sparr.px[ 2 ]^.sreskey.res_eof := false;
                sparr.px[ 2 ]^.sreskey.res_nextpos :=  0;
                sparr.px[ 2 ]^.sreskey.res_prevpos := -1;
                (* reset res_nextkeys *)
&               ifdef trace
                t01name(ak_sem, 'reset next/prev   ');
                t01name(ak_sem, 'r_start -> r_next ');
&               endif
                a74_copy_twokeys (acv,
                      sparr.px[ 2 ]^.sreskey.res_keysbuf,
                      sparr.px[ 2 ]^.sreskey.res_startkeys,
                      sparr.px[ 2 ]^.sreskey.res_nextkeys,
                      sparr.px[ 2 ]^.sreskey.res_resstate);
&               ifdef trace
                t01name(ak_sem, 'r_start -> r_prev ');
&               endif
                a74_copy_twokeys (acv,
                      sparr.px[ 2 ]^.sreskey.res_keysbuf,
                      sparr.px[ 2 ]^.sreskey.res_startkeys,
                      sparr.px[ 2 ]^.sreskey.res_prevkeys,
                      sparr.px[ 2 ]^.sreskey.res_resstate);
                END;
            (*ENDIF*) 
            acv.a_mblock.mb_trns^.trError_gg00 := e_no_next_record;
            END
        ELSE
            acv.a_mblock.mb_trns^.trError_gg00 := _e;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        sparr.px[ 2 ]^.sreskey.res_bof := false;
        sparr.px[ 2 ]^.sreskey.res_eof := false;
        END;
    (*ENDIF*) 
    IF  ( acv.a_mblock.mb_trns^.trError_gg00 = e_ok ) OR
        ( acv.a_mblock.mb_trns^.trError_gg00 = e_no_next_record )
    THEN
        BEGIN
        sparr.px[ 2 ]^.sreskey.res_searched_pages :=
              acv.a_mblock.mb_qual^.mf_desc.m_searched_pages;
        IF  (( sparr.px[ 2 ]^.sreskey.res_searched_pages > cak68_updstat_minpages )
            AND
            ( sparr.px[ 2 ]^.sreskey.res_searched_pages >
            sparr.px[ 2 ]^.sreskey.res_known_pages * cak68_updstat_factor)
            AND
            NOT mrec.fr_resnamerec^.sresname.resimpl_upd_stat
            (* upd_stat is not written in resname_rec *)
            )
        THEN
            BEGIN
            mrec.fr_resnamerec^.sresname.resimpl_upd_stat := true;
            a10repl_sysinfo (acv, mrec.fr_resnamerec, _e);
            (* if there is an error, it doesn't matter *)
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( acv.a_mblock.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        IF  ( direct_retpart_move )
        THEN
            acv.a_curr_retpart^.sp1p_buf_len :=
                  acv.a_curr_retpart^.sp1p_buf_len + acv.a_mblock.mb_data_len;
        (*ENDIF*) 
        ;
&       ifdef trace
        t01c32(ak_sem, 'm_startkey -> startkey          ');
&       endif
        ak74copy1_twokeys (acv, acv.a_mblock.mb_qual^.mf_desc.m_startkeys,
              sparr.px[ 2 ]^.sreskey.res_keysbuf, startkeys, mrec.fr_resstate,
              sparr.px[ 2 ]^.sreskey.res_startkeys.listkeyspec.ks_pos -
              sparr.px[ 2 ]^.sreskey.res_startkeys.reckeyspec.ks_pos, (* primlen *)
              sparr.px[ 2 ]^.sreskey.res_stopkeys.reckeyspec.ks_pos -
              sparr.px[ 2 ]^.sreskey.res_startkeys.listkeyspec.ks_pos (* invlen *));
        IF  ( _fs_first_loop in mrec.fr_switches )
        THEN
            BEGIN
&           ifdef trace
            t01c32(ak_sem, 'm_firstkey -> firstkey          ');
&           endif
            ak74copy1_twokeys (acv, acv.a_mblock.mb_qual^.mf_desc.m_firstkeys,
                  sparr.px[ 2 ]^.sreskey.res_keysbuf, firstkeys, mrec.fr_resstate,
                  sparr.px[ 2 ]^.sreskey.res_startkeys.listkeyspec.ks_pos -
                  sparr.px[ 2 ]^.sreskey.res_startkeys.reckeyspec.ks_pos,
                  sparr.px[ 2 ]^.sreskey.res_stopkeys.reckeyspec.ks_pos -
                  sparr.px[ 2 ]^.sreskey.res_startkeys.listkeyspec.ks_pos);
            END;
        (*ENDIF*) 
        ;
&       ifdef trace
        t01bool (ak_sem, 'first loop  ', _fs_first_loop in mrec.fr_switches );
        t01mess2type( ak_sem, 'poskind     ', mrec.fr_poskind );
        t01p2int4( ak_sem, 'res_nextpos1', sparr.px[ 2 ]^.sreskey.res_nextpos,
              'res_prevpos1', sparr.px[ 2 ]^.sreskey.res_prevpos );
&       endif
        CASE mrec.fr_poskind OF
            mm_last :
                (* FETCH LAST *)
                BEGIN
                sparr.px[ 2 ]^.sreskey.res_prevpos := -1;
                sparr.px[ 2 ]^.sreskey.res_nextpos := -1;
                END;
            mm_next :
                BEGIN
                IF  ( _fs_first_loop in mrec.fr_switches )
                THEN
                    BEGIN
                    IF  ( sparr.px[ 2 ]^.sreskey.res_nextpos <> -1 )
                    THEN
                        BEGIN
                        IF  ( acv.a_mblock.mb_qual^.mf_desc.m_cnt = 0 )
                        THEN
                            BEGIN
                            sparr.px[ 2 ]^.sreskey.res_eof     := true;
                            sparr.px[ 2 ]^.sreskey.res_prevpos :=
                                  sparr.px[ 2 ]^.sreskey.res_nextpos
                            END
                        ELSE
                            sparr.px[ 2 ]^.sreskey.res_prevpos :=
                                  succ(sparr.px[ 2 ]^.sreskey.res_nextpos);
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  ( sparr.px[ 2 ]^.sreskey.res_nextpos <> -1 )
                THEN
                    sparr.px[ 2 ]^.sreskey.res_nextpos :=
                          sparr.px[ 2 ]^.sreskey.res_nextpos +
                          acv.a_mblock.mb_qual^.mf_desc.m_cnt;
                (*ENDIF*) 
                END;
            mm_first :
                (* FETCH FIRST *)
                BEGIN
                (* PTS 1122802 E.Z. *)
                IF  ( _fs_first_loop in mrec.fr_switches )
                THEN
                    IF  ( acv.a_mblock.mb_qual^.mf_desc.m_cnt = 0 )
                    THEN
                        sparr.px[ 2 ]^.sreskey.res_prevpos := 0
                    ELSE
                        sparr.px[ 2 ]^.sreskey.res_prevpos := 1;
                    (*ENDIF*) 
                (*ENDIF*) 
                IF  ( sparr.px[ 2 ]^.sreskey.res_nextpos <> -1 )
                THEN
                    sparr.px[ 2 ]^.sreskey.res_nextpos :=
                          sparr.px[ 2 ]^.sreskey.res_nextpos +
                          acv.a_mblock.mb_qual^.mf_desc.m_cnt;
                (*ENDIF*) 
                END;
            mm_prev :
                BEGIN
                IF  ( _fs_first_loop in mrec.fr_switches )
                THEN
                    BEGIN
                    IF  ( sparr.px[ 2 ]^.sreskey.res_prevpos > 0 )
                    THEN
                        BEGIN
                        IF  ( acv.a_mblock.mb_qual^.mf_desc.m_cnt = 0 )
                        THEN
                            BEGIN
                            sparr.px[ 2 ]^.sreskey.res_bof     := true;
                            sparr.px[ 2 ]^.sreskey.res_nextpos :=
                                  sparr.px[ 2 ]^.sreskey.res_prevpos;
                            END
                        ELSE
                            sparr.px[ 2 ]^.sreskey.res_nextpos :=
                                  pred(sparr.px[ 2 ]^.sreskey.res_prevpos);
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  ( sparr.px[ 2 ]^.sreskey.res_prevpos > 0 )
                THEN
                    sparr.px[ 2 ]^.sreskey.res_prevpos :=
                          sparr.px[ 2 ]^.sreskey.res_prevpos -
                          acv.a_mblock.mb_qual^.mf_desc.m_cnt
                (*ENDIF*) 
                END;
            mm_direct:
                BEGIN
                IF  ( sparr.px[ 2 ]^.sreskey.res_nextpos <> -1 )
                THEN
                    (* neutral for single fetch *)
                    sparr.px[ 2 ]^.sreskey.res_nextpos :=
                          sparr.px[ 2 ]^.sreskey.res_nextpos +
                          acv.a_mblock.mb_qual^.mf_desc.m_cnt - 1;
                (*ENDIF*) 
                END;
            OTHERWISE
                BEGIN
                END
            END;
        (*ENDCASE*) 
        (* PTS 1105717 E.Z. *)
        IF  ( acv.a_mblock.mb_qual^.mf_desc.m_cnt < mrec.fr_act_cnt )
            AND
            ( mrec.fr_act_cnt > 1 )
        THEN
            BEGIN
&           ifdef trace
            t01name(ak_sem, 'm_cnt < fr_act_cnt');
&           endif
            IF  ( mrec.fr_stepkind in [ mm_next, mm_first ] )
            THEN
                BEGIN
                IF  ( sparr.px[ 2 ]^.sreskey.res_nextpos <> -1 )
                THEN
                    sparr.px[ 2 ]^.sreskey.res_nextpos :=
                          succ(sparr.px[ 2 ]^.sreskey.res_nextpos);
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                IF  ( mrec.fr_stepkind in [ mm_prev, mm_last ] )
                THEN
                    BEGIN
                    IF  ( sparr.px[ 2 ]^.sreskey.res_prevpos <> -1 )
                    THEN
                        sparr.px[ 2 ]^.sreskey.res_prevpos :=
                              pred(sparr.px[ 2 ]^.sreskey.res_prevpos);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END
    ELSE
        (* acv.a_mblock.mb_trns^.trError_gg00 <> e_ok *)
        BEGIN
        IF  ( acv.a_mblock.mb_trns^.trError_gg00 = e_old_fileversion )
        THEN
            a07_b_put_error (acv, e_invalid_mix_dml_ddl, 1)
        ELSE
            a07_b_put_error (acv, acv.a_mblock.mb_trns^.trError_gg00, 1)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
&ifdef trace
t01p2int4( ak_sem, 'res_nextpos ', sparr.px[ 2 ]^.sreskey.res_nextpos,
      'res_prevpos ', sparr.px[ 2 ]^.sreskey.res_prevpos );
t01p2bool( ak_sem, 'res_bof     ', sparr.px[ 2 ]^.sreskey.res_bof ,
      'res_eof     ', sparr.px[ 2 ]^.sreskey.res_eof );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak74copy1_twokeys (
            VAR acv     : tak_all_command_glob;
            VAR source  : tgg00_TwoKeys;
            VAR keysbuf : tak_res_keysbuf;
            VAR dest    : tak_two_keyspecs;
            res_stat    : tak_sresstate;
            primlen     : integer;
            invlen      : integer);
 
BEGIN
&ifdef TRACE
IF  rs_useinv in res_stat
THEN
    t01key (ak_sem, 'listkey     ', source.listkey);
(*ENDIF*) 
t01key (ak_sem, 'reckey      ', source.reckey);
&endif
(* PTS 1001717 E.Z. *)
IF  source.reckey.len > primlen
THEN
    dest.reckeyspec.ks_len := primlen
ELSE
    dest.reckeyspec.ks_len := source.reckey.len;
(*ENDIF*) 
SAPDB_PascalMove ('VAK74 ',   2,    
      sizeof(source.reckey.k), sizeof(keysbuf),
      @source.reckey.k, 1, @keysbuf, dest.reckeyspec.ks_pos,
      dest.reckeyspec.ks_len, acv.a_returncode);
IF  (rs_useinv in res_stat) AND
    (acv.a_returncode = 0)
THEN
    BEGIN
    (* PTS 1001717 E.Z. *)
    IF  source.listkey.len > invlen
    THEN
        dest.listkeyspec.ks_len := invlen
    ELSE
        dest.listkeyspec.ks_len := source.listkey.len;
    (*ENDIF*) 
    SAPDB_PascalMove ('VAK74 ',   3,    
          sizeof(source.listkey.k), sizeof(keysbuf),
          @source.listkey.k, 1, @keysbuf, dest.listkeyspec.ks_pos,
          dest.listkeyspec.ks_len, acv.a_returncode)
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak74copy2_twokeys (
            VAR acv     : tak_all_command_glob;
            VAR keysbuf : tak_res_keysbuf;
            VAR source  : tak_two_keyspecs;
            VAR dest    : tgg00_TwoKeys;
            res_stat    : tak_sresstate);
 
BEGIN
dest.reckey.len := source.reckeyspec.ks_len;
SAPDB_PascalMove ('VAK74 ',   4,    
      sizeof(keysbuf), sizeof(dest.reckey.k),
      @keysbuf, source.reckeyspec.ks_pos, @dest.reckey.k, 1,
      dest.reckey.len, acv.a_returncode);
IF  ( rs_useinv in res_stat ) AND ( acv.a_returncode = 0 )
THEN
    BEGIN
    dest.listkey.len := source.listkeyspec.ks_len;
    SAPDB_PascalMove ('VAK74 ',   5,    
          sizeof(keysbuf), sizeof(dest.listkey.k),
          @keysbuf, source.listkeyspec.ks_pos, @dest.listkey.k, 1,
          dest.listkey.len, acv.a_returncode)
    END;
(*ENDIF*) 
;
&ifdef TRACE
IF  rs_useinv in res_stat
THEN
    t01key (ak_sem, 'listkey     ', dest.listkey);
(*ENDIF*) 
t01int4 (ak_sem, 'src list pos', source.listkeyspec.ks_pos );
t01int4 (ak_sem, 'src list len', source.listkeyspec.ks_len );
t01key (ak_sem, 'reckey      ', dest.reckey);
t01int4 (ak_sem, 'src key pos ', source.reckeyspec.ks_pos );
t01int4 (ak_sem, 'src key len ', source.reckeyspec.ks_len );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      a74_copy_twokeys (
            VAR acv     : tak_all_command_glob;
            VAR keysbuf : tak_res_keysbuf;
            VAR source  : tak_two_keyspecs;
            VAR dest    : tak_two_keyspecs;
            res_stat    : tak_sresstate);
 
BEGIN
dest.reckeyspec.ks_len := source.reckeyspec.ks_len;
SAPDB_PascalMove ('VAK74 ',   6,    
      sizeof(keysbuf), sizeof(keysbuf),
      @keysbuf, source.reckeyspec.ks_pos,
      @keysbuf, dest.reckeyspec.ks_pos, dest.reckeyspec.ks_len,
      acv.a_returncode);
IF  (rs_useinv in res_stat)AND
    (acv.a_returncode = 0)
THEN
    BEGIN
    dest.listkeyspec.ks_len := source.listkeyspec.ks_len;
    SAPDB_PascalMove ('VAK74 ',   7,    
          sizeof(keysbuf), sizeof(keysbuf),
          @keysbuf, source.listkeyspec.ks_pos,
          @keysbuf, dest.listkeyspec.ks_pos, dest.listkeyspec.ks_len,
          acv.a_returncode)
    END;
&ifdef trace
(*ENDIF*) 
IF  (rs_useinv in res_stat)
THEN
    BEGIN
    t01int4 (ak_sem, 'src list pos', source.listkeyspec.ks_pos );
    t01int4 (ak_sem, 'src list len', source.listkeyspec.ks_len );
    t01sname(ak_sem, 'listkey:    ' );
    t01buf( ak_sem, keysbuf, source.listkeyspec.ks_pos,
          source.listkeyspec.ks_pos + source.listkeyspec.ks_len );
    END;
(*ENDIF*) 
t01int4 (ak_sem, 'src key pos ', source.reckeyspec.ks_pos );
t01int4 (ak_sem, 'src key len ', source.reckeyspec.ks_len );
t01sname(ak_sem, 'reckey:     ' );
t01buf( ak_sem, keysbuf, source.reckeyspec.ks_pos,
      source.reckeyspec.ks_pos + source.reckeyspec.ks_len );
IF  (rs_useinv in res_stat)
THEN
    BEGIN
    t01int4 (ak_sem, 'dst list pos', dest.listkeyspec.ks_pos );
    t01int4 (ak_sem, 'dst list len', dest.listkeyspec.ks_len );
    END;
(*ENDIF*) 
t01int4 (ak_sem, 'dst key pos ', dest.reckeyspec.ks_pos );
t01int4 (ak_sem, 'dst key len ', dest.reckeyspec.ks_len );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak74record_fetch (
            VAR acv             : tak_all_command_glob;
            VAR sparr           : tak_syspointerarr;
            VAR mblock          : tgg00_MessBlock;
            VAR mrec            : mfetch_rec;
            direct_retp_move    : boolean);
 
BEGIN
&ifdef trace
t01mess2type( ak_sem, 'fr_stepkind ', mrec.fr_stepkind );
t01mess2type( ak_sem, 'fr_poskind  ', mrec.fr_poskind );
t01int4 (ak_sem, 'fr_act_cnt  ', mrec.fr_act_cnt);
&endif
IF  ( mrec.fr_stepkind = mm_direct )
THEN
    BEGIN
&   ifdef trace
    t01name(ak_sem, 'r_next -> startkey');
    t01name(ak_sem, 'r_stop -> stopkey ');
    t01name(ak_sem, 'r_start -> one_sta');
    t01name(ak_sem, 'r_prev -> firstkey');
&   endif
    ak74build_fetch_mess_buf (acv, sparr, mblock,
          sparr.px[ 2 ]^.sreskey.res_nextkeys,(* startkeys *)
          sparr.px[ 2 ]^.sreskey.res_stopkeys,(* stopkeys*)
          sparr.px[ 2 ]^.sreskey.res_startkeys.reckeyspec,(* one_startkey*)
          sparr.px[ 2 ]^.sreskey.res_prevkeys,(* firstkeys *)
          mrec, sparr.px[ 2 ]^.sreskey.res_nextpos, (* rescnt *)
          direct_retp_move, NOT c_stop);
&   ifdef trace
    t01name(ak_sem, 'r_next updated    ');
    t01name(ak_sem, 'r_prev updated    ');
&   endif
    END
ELSE
    BEGIN
    IF  NOT (rs_useinv in sparr.px[ 2 ]^.sreskey.res_resstate)
    THEN
        BEGIN
        CASE mrec.fr_stepkind OF
            mm_first, mm_next, mm_last_rowno :
                BEGIN
&               ifdef trace
                t01name(ak_sem, 'r_next -> startkey');
                t01name(ak_sem, 'r_stop -> stopkey ');
                t01name(ak_sem, 'r_start -> one_sta');
                t01name(ak_sem, 'r_prev -> firstkey');
&               endif
                ak74build_fetch_mess_buf (acv,
                      sparr, mblock,
                      sparr.px[ 2 ]^.sreskey.res_nextkeys,
                      sparr.px[ 2 ]^.sreskey.res_stopkeys,
                      sparr.px[ 2 ]^.sreskey.res_startkeys.reckeyspec,
                      sparr.px[ 2 ]^.sreskey.res_prevkeys,
                      mrec, sparr.px[ 2 ]^.sreskey.res_nextpos,
                      direct_retp_move,
                      sparr.px[ 2 ]^.sreskey.
                      res_keysbuf[ sparr.px[ 2 ]^.sreskey.res_stopkeys.
                      reckeyspec.ks_pos ] <> chr(255));
&               ifdef trace
                t01name(ak_sem, 'r_next updated    ');
                t01name(ak_sem, 'r_prev updated    ');
&               endif
                END;
            mm_last, mm_prev :
                BEGIN
&               ifdef trace
                t01name(ak_sem, 'r_prev -> startkey');
                t01name(ak_sem, 'r_start -> stopkey');
                t01name(ak_sem, 'r_stop -> one_sta ');
                t01name(ak_sem, 'r_next -> firstkey');
&               endif
                ak74build_fetch_mess_buf (acv,
                      sparr, mblock,
                      sparr.px[ 2 ]^.sreskey.res_prevkeys,
                      sparr.px[ 2 ]^.sreskey.res_startkeys,
                      sparr.px[ 2 ]^.sreskey.res_stopkeys.reckeyspec,
                      sparr.px[ 2 ]^.sreskey.res_nextkeys,
                      mrec, sparr.px[ 2 ]^.sreskey.res_nextpos,
                      direct_retp_move,
                      sparr.px[ 2 ]^.sreskey.res_startkeys.
                      reckeyspec.ks_len <> 0);
&               ifdef trace
                t01name(ak_sem, 'r_prev updated    ');
                t01name(ak_sem, 'r_next updated    ');
&               endif
                END;
            END;
        (*ENDCASE*) 
        END
    ELSE
        BEGIN
        CASE mrec.fr_stepkind OF
            mm_first, mm_next, mm_last_rowno :
                BEGIN
&               ifdef trace
                t01name(ak_sem, 'r_next -> startkey');
                t01name(ak_sem, 'r_stop -> stopkey ');
                t01name(ak_sem, 'r_start -> one_sta');
                t01name(ak_sem, 'r_prev -> firstkey');
&               endif
                ak74build_fetch_mess_buf (acv,
                      sparr, mblock,
                      sparr.px[ 2 ]^.sreskey.res_nextkeys,
                      sparr.px[ 2 ]^.sreskey.res_stopkeys,
                      sparr.px[ 2 ]^.sreskey.res_startkeys.reckeyspec,
                      sparr.px[ 2 ]^.sreskey.res_prevkeys,
                      mrec, sparr.px[ 2 ]^.sreskey.res_nextpos,
                      direct_retp_move,
                      ((sparr.px[ 2 ]^.sreskey.
                      res_keysbuf[ sparr.px[ 2 ]^.sreskey.res_stopkeys.
                      reckeyspec.ks_pos  ] <> chr(255)) OR
                      ( sparr.px[ 2 ]^.sreskey.
                      res_keysbuf[ sparr.px[ 2 ]^.sreskey.res_stopkeys.
                      listkeyspec.ks_pos ] <> chr(255))));
&               ifdef trace
                t01name(ak_sem, 'r_next updated    ');
                t01name(ak_sem, 'r_prev updated    ');
&               endif
                END;
            mm_last, mm_prev :
                BEGIN
&               ifdef trace
                t01name(ak_sem, 'r_prev -> startkey');
                t01name(ak_sem, 'r_start -> stopkey');
                t01name(ak_sem, 'r_stop -> one_sta ');
                t01name(ak_sem, 'r_next -> firstkey');
&               endif
                ak74build_fetch_mess_buf (acv,
                      sparr, mblock,
                      sparr.px[ 2 ]^.sreskey.res_prevkeys,
                      sparr.px[ 2 ]^.sreskey.res_startkeys,
                      sparr.px[ 2 ]^.sreskey.res_stopkeys.reckeyspec,
                      sparr.px[ 2 ]^.sreskey.res_nextkeys,
                      mrec, sparr.px[ 2 ]^.sreskey.res_nextpos,
                      direct_retp_move,
                      ((sparr.px[ 2 ]^.sreskey.res_startkeys.
                      reckeyspec.ks_len <> 0) OR
                      ( sparr.px[ 2 ]^.sreskey.res_startkeys.
                      listkeyspec.ks_len <> 0)));
&               ifdef trace
                t01name(ak_sem, 'r_prev updated    ');
                t01name(ak_sem, 'r_next updated    ');
&               endif
                END;
            END;
        (*ENDCASE*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a74_search_fetch (
            VAR acv        : tak_all_command_glob;
            VAR sparr      : tak_syspointerarr;
            mtype          : tgg00_MessType2;
            pos            : tsp00_Int4;
            VAR resn_rec   : tak_sysbufferaddress;
            single_fetch   : boolean;
            mfetch_count   : tsp00_Int4);
 
VAR
      _mrec                : mfetch_rec;
      _p_messbuf           : tak_sysbufferaddress;
      _ke                  : tgg00_SysInfoKey;
      _foundrecs           : tsp00_Int4;
      _start_pos           : tsp00_Int4;
      _func_code           : tsp00_Int4;
      _rowno               : tsp00_Int4;
      _tmp_int             : tsp00_Int4;
      _fetch_from_user     : boolean;
      _lcol_lock           : boolean;
      _lcol_found          : boolean;
      _direct_retpart_move : boolean;
      _tmp_bool            : boolean;
      _b_err               : tgg00_BasisError;
      _e                   : tgg00_BasisError;
 
BEGIN
acv.a_mblock.mb_trns := @acv.a_transinf.tri_trans;
_direct_retpart_move  := false;
acv.a_long_desc_pos      := 0;
_b_err                := e_ok;
_ke                   := sparr.px[ 2 ]^.syskey;
_ke.sentrytyp         := cak_emessblock;
a10get_sysinfo (acv, _ke, d_release, _p_messbuf, _e);
IF  ( _e <> e_ok ) OR (( mfetch_count < 0 ) AND NOT single_fetch )
THEN
    BEGIN
    IF  ( _e <> e_ok )
    THEN
        a07_b_put_error (acv, _e, 1)
    ELSE
        a07_b_put_error (acv, e_invalid_unsign_integer, 1)
    (*ENDIF*) 
    END
ELSE
    BEGIN
&   ifdef trace
    t01mess2type(ak_sem, 'mtype       ', mtype);
    t01int4 (ak_sem, 'position    ', pos );
    t01bool (ak_sem, 'single fetch', single_fetch);
    t01int4 (ak_sem, 'mfetch_count', mfetch_count );
    t01int4 (ak_sem, 'res_nextpos ', sparr.px[ 2 ]^.sreskey.res_nextpos);
    t01int4 (ak_sem, 'res_prevpos ', sparr.px[ 2 ]^.sreskey.res_prevpos);
    t01bool (ak_sem, 'res_bof     ', sparr.px[ 2 ]^.sreskey.res_bof);
    t01bool (ak_sem, 'res_eof     ', sparr.px[ 2 ]^.sreskey.res_eof);
    t01messblock( ak_sem, 'FETCH MBLOCK', _p_messbuf^.smessblock.mbr_mess_block );
&   endif
    IF  ( sparr.px[ 2 ]^.sreskey.res_actres = 0 )
    THEN
        a07_b_put_error (acv, e_no_next_record, 1)
    ELSE
        (* there is at least one result record *)
        BEGIN
        _mrec.fr_switches := [];
        _mrec.fr_resstate := sparr.px[ 2 ]^.sreskey.res_resstate;
        k720_maxresult_get(sparr.px[ 2 ]^.sreskey.res_rowno, _rowno);
        IF  ( _rowno > 0 ) AND ( _rowno <> csp_maxint4 )
        THEN
            BEGIN
            _mrec.fr_switches := _mrec.fr_switches + [ _fs_rowno_set ];
            IF  ( mtype = mm_last )
            THEN
                BEGIN
                _mrec.fr_switches := _mrec.fr_switches + [ _fs_last_rowno ];
                mtype := mm_last_rowno;
                pos   := _rowno;
&               ifdef trace
                t01name(ak_sem, 'set mm_last_rowno ');
                t01int4(ak_sem, 'pos         ', pos);
&               endif
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        ;
        (* apply common mappings *)
        IF  ((mtype = mm_next) AND sparr.px[ 2 ]^.sreskey.res_bof)
        THEN
            (* the 'FETCH NEXT' with BOF *)
            mtype := mm_first
        ELSE
            BEGIN
            IF  ((mtype = mm_prev) AND sparr.px[ 2 ]^.sreskey.res_eof)
            THEN
                (* the 'FETCH PREV' with EOF *)
                mtype := mm_last
            ELSE
                BEGIN
                IF  ( mtype = mm_direct )
                THEN
                    BEGIN
                    CASE pos OF
                        1 :
                            (* FETCH ABSOLUTE  1 = FETCH FIRST *)
                            mtype := mm_first;
                        -1 :
                            (* FETCH ABSOLUTE -1 = FETCH LAST *)
                            mtype := mm_last;
                        OTHERWISE
                            BEGIN
                            (* do nothing *)
                            END;
                        END;
                    (*ENDCASE*) 
                    END
                ELSE
                    BEGIN
                    IF  (( mtype = mm_search ) AND ( pos = 0 ))
                    THEN
                        (* FETCH RELATIVE 0 = FETCH SAME *)
                        mtype := mm_same;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        _fetch_from_user := true;
        IF  ( acv.a_ex_kind = only_executing )
        THEN
            BEGIN
            IF  ( sparr.px[ 1 ]^.sparsinfo.p_function_code > csp1_min_masscmd_fc )
            THEN
                _func_code := sparr.px[ 1 ]^.sparsinfo.p_function_code -
                      csp1_min_masscmd_fc
            ELSE
                _func_code := sparr.px[ 1 ]^.sparsinfo.p_function_code;
            (*ENDIF*) 
            IF  ( _func_code <> csp1_fetch_relative_fc ) AND
                (( _func_code < csp1_fetch_first_fc ) OR
                ( _func_code > csp1_fetch_same_fc ))
            THEN (* where pos of *)
                _fetch_from_user := false;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        _lcol_lock  := false;
        _lcol_found := false;
        IF  ( sparr.px[ 2 ]^.sreskey.res_change.cr_colcount > 0 ) AND
            _fetch_from_user
        THEN
            BEGIN
            IF  a508_lcol_found (acv, sparr.px[ 2 ]^.sreskey.res_change)
            THEN
                BEGIN
                _lcol_found := true;
                (* PTS 1111576 E.Z. *)
                IF  (NOT (hsPermLock_egg00 in
                    _p_messbuf^.smessblock.mbr_mess_block.mb_qual^.
                    mtree.fileHandling_gg00))
                THEN
                    BEGIN
                    _lcol_lock     := (_p_messbuf^.smessblock.
                          mbr_mess_block.mb_qual^.mtree.
                          fileHandling_gg00 <> _p_messbuf^.smessblock.
                          mbr_mess_block.mb_qual^.mtree.fileHandling_gg00
                          + [ hsTempLock_egg00 ]
                          - [ hsWithoutLock_egg00 ]);
&                   ifdef trace
                    t01handling (ak_sem, 'lsuphandling',
                          _p_messbuf^.smessblock.mbr_mess_block.
                          mb_qual^.mtree.fileHandling_gg00);
                    t01int4(ak_sem, 'res_build   ', ord (sparr.px[ 2 ]^.sreskey.res_build));
                    t01int4(ak_sem, 'lcol_lock   ', ord (_lcol_lock));
&                   endif
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (* PTS 1111576 E.Z. *)
        (*ENDIF*) 
        _mrec.fr_resnamerec := resn_rec;
        CASE mtype OF
            mm_first :
                BEGIN
                (* reset res_nextkeys *)
                sparr.px[ 2 ]^.sreskey.res_nextpos := 0;
&               ifdef trace
                t01name(ak_sem, 'r_start -> r_next ');
&               endif
                a74_copy_twokeys (acv,
                      sparr.px[ 2 ]^.sreskey.res_keysbuf,
                      sparr.px[ 2 ]^.sreskey.res_startkeys,
                      sparr.px[ 2 ]^.sreskey.res_nextkeys,
                      sparr.px[ 2 ]^.sreskey.res_resstate)
                END;
            mm_last :
                BEGIN
                (* reset res_prevkeys *)
&               ifdef trace
                t01name(ak_sem, 'r_stop -> r_prev  ');
&               endif
                a74_copy_twokeys (acv,
                      sparr.px[ 2 ]^.sreskey.res_keysbuf,
                      sparr.px[ 2 ]^.sreskey.res_stopkeys,
                      sparr.px[ 2 ]^.sreskey.res_prevkeys,
                      sparr.px[ 2 ]^.sreskey.res_resstate);
                END;
            mm_last_rowno,
            mm_direct,
            mm_search :
                BEGIN
                ak74prepare_fetch( acv, sparr,
                      _p_messbuf^.smessblock, mtype, pos, _mrec, _rowno );
                END;
            mm_same :
                BEGIN
                IF  ( sparr.px[ 2 ]^.sreskey.res_bof OR
                    sparr.px[ 2 ]^.sreskey.res_eof )
                THEN
                    a07_b_put_error (acv, e_current_of_needs_fetch, 1);
                (*ENDIF*) 
                IF  ( NOT single_fetch )
                THEN
                    BEGIN
&                   ifdef trace
                    t01name(ak_sem, 'r_prev -> r_next  ');
&                   endif
                    a74_copy_twokeys (acv,
                          sparr.px[ 2 ]^.sreskey.res_keysbuf,
                          sparr.px[ 2 ]^.sreskey.res_prevkeys,
                          sparr.px[ 2 ]^.sreskey.res_nextkeys,
                          sparr.px[ 2 ]^.sreskey.res_resstate);
                    sparr.px[ 2 ]^.sreskey.res_nextpos :=
                          sparr.px[ 2 ]^.sreskey.res_prevpos
                    END;
                (*ENDIF*) 
                END;
            OTHERWISE
                BEGIN
                IF  ( sparr.px[ 2 ]^.sreskey.res_eof AND ( mtype = mm_next )) OR
                    ( sparr.px[ 2 ]^.sreskey.res_bof AND ( mtype = mm_prev ))
                THEN
                    a07_b_put_error (acv, e_row_not_found, 1);
                (*ENDIF*) 
                IF  ( _fs_rowno_set in _mrec.fr_switches )
                THEN
                    BEGIN
                    IF  ( mtype = mm_next ) AND
                        ( sparr.px[ 2 ]^.sreskey.res_nextpos >= _rowno )
                    THEN
                        BEGIN
                        a07_b_put_error (acv, e_row_not_found, 1);
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            END;
        (*ENDCASE*) 
        ;
        (* common fetch part *)
        IF  ( acv.a_returncode = 0 )
            (* there could be e_row_not_found *)
        THEN
            BEGIN
            _mrec.fr_poskind  := mtype;
            _mrec.fr_switches := _mrec.fr_switches + [ _fs_use_recs ];
            _mrec.fr_switches := _mrec.fr_switches + [ _fs_first_loop ];
            IF  ( single_fetch )
            THEN
                _mrec.fr_switches  := _mrec.fr_switches + [ _fs_single_fetch ];
            (*ENDIF*) 
            IF  ( _fetch_from_user )
            THEN
                BEGIN
                IF  ( acv.a_curr_retpart = NIL )
                THEN
                    a06init_curr_retpart( acv );
                (*ENDIF*) 
                a60rescount( acv, 1 );
                END;
            (*ENDIF*) 
            IF  ( mtype = mm_same )
            THEN
                BEGIN
                IF  (( single_fetch ) OR
                    ( NOT single_fetch AND ( mfetch_count = 1 )))
                THEN
                    BEGIN
                    _mrec.fr_stepkind := mm_direct;
                    _mrec.fr_poskind  := mm_direct;
                    END
                ELSE
                    BEGIN
                    _mrec.fr_stepkind := mm_first;
                    _mrec.fr_poskind  := mm_direct;
                    END;
                (*ENDIF*) 
                END
            ELSE
                (* mm_first, mm_last, mm_next, mm_prev, mm_direct, mm_search *)
                BEGIN
                IF  ( mtype = mm_last_rowno )
                THEN
                    BEGIN
                    _mrec.fr_stepkind := mm_last;
                    _mrec.fr_poskind  := mm_last;
                    END
                ELSE
                    BEGIN
                    IF  mtype in [ mm_direct, mm_search ]
                    THEN
                        BEGIN
                        (* we are positioned on demanded row *)
&                       ifdef trace
                        t01dist_optim( ak_sem, 'res_dist_opt',
                              sparr.px[ 2 ]^.sreskey.res_dist_optim);
&                       endif
                        _mrec.fr_stepkind := mm_first;
                        _mrec.fr_poskind  := mm_direct;
                        END
                    ELSE
                        (* mm_first, mm_last, mm_next, mm_prev *)
                        _mrec.fr_stepkind := mtype;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
&           ifdef trace
            t01mess2type( ak_sem, 'stepkind    ', _mrec.fr_stepkind );
            t01mess2type( ak_sem, 'poskind     ', _mrec.fr_poskind );
            t01p2int4( ak_sem, 'res_nextpos ', sparr.px[ 2 ]^.sreskey.res_nextpos,
                  'res_prevpos ', sparr.px[ 2 ]^.sreskey.res_prevpos );
            t01p2bool( ak_sem, 'res_bof     ', sparr.px[ 2 ]^.sreskey.res_bof ,
                  'res_eof     ', sparr.px[ 2 ]^.sreskey.res_eof );
&           endif
            IF  ( single_fetch )
            THEN
                BEGIN
                ak74single_fetch( acv, sparr,
                      _p_messbuf^.smessblock, _mrec, _fetch_from_user );
                _foundrecs := 1;
                END
            ELSE
                BEGIN  (* there is 'mfetch' command *)
                ak74mass_fetch( acv, sparr,
                      _p_messbuf^.smessblock, _mrec, _foundrecs,
                      mfetch_count );
                END;
            (*ENDIF*) 
            ;
            (* common part for fetch and mfetch *)
&           ifdef TRACE
            t01int4 (ak_sem, 'act_leng    ', _mrec.fr_act_leng);
&           endif
            (* PTS 1105717 E.Z. *)
            IF  ( _fetch_from_user AND (acv.a_returncode = 0))
            THEN
                BEGIN
                IF  ( acv.a_long_desc_pos > 0 )
                THEN
                    BEGIN
                    _start_pos := -(sparr.px[ 2 ]^.sreskey.res_keylen +
                          cgg_rec_key_offset);   (* h.b. 1995-05-31 *)
                    IF  ( _lcol_found )
                    THEN
                        (* PTS 1111576 E.Z. *)
                        a508_lget_long_columns (acv,
                              sparr.px[ 2 ]^.sreskey.res_change,
                              _lcol_lock, _foundrecs, _mrec.fr_act_leng,
                              _start_pos)
                              (* PTS 1111576 E.Z. *)
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  ( acv.a_curr_retpart <> NIL )
                THEN
                    BEGIN
                    IF  (acv.a_curr_retpart^.sp1p_buf_len > 0) OR NOT single_fetch
                    THEN
                        a06finish_curr_retpart (acv, sp1pk_data, _foundrecs);
                    (* PTS 1116801 E.Z. *)
                    (* PTS 1105717 E.Z. *)
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  (mtype = mm_direct) AND (pos < 0)
                THEN
                    a60rescount (acv, pos - 1 + acv.a_mblock.mb_qual^.mf_desc.m_cnt)
                ELSE
                    IF  ( _mrec.fr_act_cnt > acv.a_mblock.mb_qual^.mf_desc.m_cnt )
                        AND
                        ( NOT single_fetch )
                        AND
                        ( _mrec.fr_stepkind = mm_next )
                    THEN
                        BEGIN
&                       ifdef trace
                        t01int4 (ak_sem, 'set rescount', sparr.px[ 2 ]^.sreskey.res_nextpos - 1);
&                       endif
                        a60rescount (acv, sparr.px[ 2 ]^.sreskey.res_nextpos - 1);
                        END
                    ELSE
                        BEGIN
&                       ifdef trace
                        t01int4 (ak_sem, 'set rescount', sparr.px[ 2 ]^.sreskey.res_nextpos);
&                       endif
                        a60rescount (acv, sparr.px[ 2 ]^.sreskey.res_nextpos);
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
&ifdef trace
t01p2int4( ak_sem, 'res_nextpos ', sparr.px[ 2 ]^.sreskey.res_nextpos,
      'res_prevpos ', sparr.px[ 2 ]^.sreskey.res_prevpos );
t01p2bool( ak_sem, 'res_bof     ', sparr.px[ 2 ]^.sreskey.res_bof ,
      'res_eof     ', sparr.px[ 2 ]^.sreskey.res_eof );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak74prepare_fetch(
            VAR acv             : tak_all_command_glob;
            VAR sparr           : tak_syspointerarr;
            VAR orig_mblock     : tak_messblock_record;
            VAR mtype           : tgg00_MessType2;
            VAR pos             : tsp00_Int4;
            VAR mrec            : mfetch_rec;
            rowno               : tsp00_Int4);
 
VAR
      _start_from_bof     : boolean;
 
BEGIN
_start_from_bof  := false;
mrec.fr_act_leng := 0; (* PTS 1115983 *)
mrec.fr_switches := mrec.fr_switches - [ _fs_single_fetch, _fs_use_recs ];
IF  ( mtype = mm_search )
THEN
    BEGIN
    (* pos is relative position *)
    IF  ( sparr.px[ 2 ]^.sreskey.res_eof AND ( pos >= 0 )) OR
        ( sparr.px[ 2 ]^.sreskey.res_bof AND ( pos <= 0 ))
    THEN
        a07_b_put_error (acv, e_row_not_found, 1)
    ELSE
        BEGIN
        (* calculate absolute position *)
        IF  ( pos >= 0 ) AND ( sparr.px[ 2 ]^.sreskey.res_nextpos <> -1 )
        THEN
            (* relpos >= 0 AND valid res_nextpos *)
            BEGIN
&           ifdef trace
            t01c32(ak_sem, 'relpos > 0 AND valid nextpos    ');
&           endif
            mtype := mm_direct;
            IF  ( NOT sparr.px[ 2 ]^.sreskey.res_bof )
            THEN
                pos := sparr.px[ 2 ]^.sreskey.res_nextpos + pos
            ELSE
                BEGIN
                (*pos := 0 + pos; *)
                END;
            (*ENDIF*) 
            IF  ( rowno > 0 ) AND ( rowno <> csp_maxint4 ) AND
                ( pos > rowno )
            THEN
                BEGIN
                sparr.px[ 2 ]^.sreskey.res_bof := false;
                sparr.px[ 2 ]^.sreskey.res_eof := true;
                sparr.px[ 2 ]^.sreskey.res_nextpos := -1;
                sparr.px[ 2 ]^.sreskey.res_prevpos := -1;
                a07_b_put_error (acv, e_row_not_found, 1)
                END;
            (*ENDIF*) 
            END
        ELSE
            (* relpos < 0 OR invalid res_nextpos *)
            BEGIN
&           ifdef trace
            t01c32(ak_sem, 'relpos < 0 OR invalid nextpos   ');
&           endif
            IF  ( sparr.px[ 2 ]^.sreskey.res_prevpos <> -1 )
            THEN
                (* relpos < 0 and valid res_prevpos          *)
                (* OR                                        *)
                (* invalid res_nextpos and valid res_prevpos *)
                BEGIN
&               ifdef trace
                t01c32(ak_sem, 'relpos < 0 AND valid prevpos    ');
                t01sname(ak_sem, 'OR          ' );
                t01c32(ak_sem, 'invalid nextpos AND valid prevpo');
&               endif
                IF  ( sparr.px[ 2 ]^.sreskey.res_eof )
                THEN
                    pos := sparr.px[ 2 ]^.sreskey.res_prevpos + pos + 1
                ELSE
                    pos := sparr.px[ 2 ]^.sreskey.res_prevpos + pos;
                (*ENDIF*) 
                IF  ( pos <= 0 ) (*new calculated pos*)
                THEN
                    (* new absolute position within BOF *)
                    BEGIN
                    sparr.px[ 2 ]^.sreskey.res_bof := true;
                    sparr.px[ 2 ]^.sreskey.res_eof := false;
                    sparr.px[ 2 ]^.sreskey.res_nextpos := 0;
                    sparr.px[ 2 ]^.sreskey.res_prevpos := 0;
                    a07_b_put_error (acv, e_row_not_found, 1)
                    END
                ELSE
                    BEGIN
&                   ifdef trace
                    t01c32(ak_sem, 'relpos > 0 AND valid prevpos    ');
                    t01sname(ak_sem, 'AND         ' );
                    t01c32(ak_sem, 'invalid nextpos                 ');
&                   endif
                    mtype := mm_direct;
                    END;
                (*ENDIF*) 
                END
            ELSE
                (* (relpos < 0 OR invalid res_nextpos) AND invalid res_prevpos *)
                BEGIN
                (* mtype stays mm_search *)
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
&ifdef trace
t01mess2type( ak_sem, 'mytpe 2     ', mtype );
t01int4 (ak_sem, 'pos         ', pos);
t01p2int4( ak_sem, 'res_nextpos ', sparr.px[ 2 ]^.sreskey.res_nextpos,
      'res_prevpos ', sparr.px[ 2 ]^.sreskey.res_prevpos );
t01p2bool( ak_sem, 'res_bof     ', sparr.px[ 2 ]^.sreskey.res_bof,
      'res_eof     ', sparr.px[ 2 ]^.sreskey.res_eof );
&endif
IF  (( mtype in [ mm_direct, mm_last_rowno ] ) AND ( acv.a_returncode = 0 ))
THEN
    BEGIN
    (* absolute position is calculated *)
    (* pos is absolute position *)
    IF  ( sparr.px[ 2 ]^.sreskey.res_bof )
    THEN
        BEGIN
&       ifdef trace
        t01sname(ak_sem, 'res_bof     ' );
&       endif
        IF  ( pos < 0 )
        THEN
            BEGIN
            (* reset res_prevkeys *)
&           ifdef trace
            t01name(ak_sem, 'r_stop  -> r_prev ');
&           endif
            a74_copy_twokeys (acv,
                  sparr.px[ 2 ]^.sreskey.res_keysbuf,
                  sparr.px[ 2 ]^.sreskey.res_stopkeys,
                  sparr.px[ 2 ]^.sreskey.res_prevkeys,
                  sparr.px[ 2 ]^.sreskey.res_resstate);
            END
        ELSE
            BEGIN
            (* reset res_nextkeys *)
&           ifdef trace
            t01name(ak_sem, 'r_start -> r_next ');
&           endif
            a74_copy_twokeys (acv,
                  sparr.px[ 2 ]^.sreskey.res_keysbuf,
                  sparr.px[ 2 ]^.sreskey.res_startkeys,
                  sparr.px[ 2 ]^.sreskey.res_nextkeys,
                  sparr.px[ 2 ]^.sreskey.res_resstate);
            _start_from_bof := true;
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( pos = 0 )
    THEN
        BEGIN
        sparr.px[ 2 ]^.sreskey.res_bof := true;
        sparr.px[ 2 ]^.sreskey.res_eof := false;
        sparr.px[ 2 ]^.sreskey.res_nextpos := 0;
        sparr.px[ 2 ]^.sreskey.res_prevpos := 0;
        a07_b_put_error (acv, e_row_not_found, 1)
        END
    ELSE
        BEGIN
        IF  ( pos < 0 )
        THEN
            (* abspos < 0, step in direction EOF *)
            BEGIN
            IF  ( _fs_rowno_set in mrec.fr_switches )
            THEN
                BEGIN
                (* FETCH POS -<int> on ROWNO result set *)
                (* position to end of result set        *)
                mrec.fr_stepkind  := mm_last_rowno;
                mrec.fr_poskind   := mm_next;
                mrec.fr_act_cnt   := rowno;
&               ifdef trace
                t01name(ak_sem, 'fetch abs -x rowno');
                t01name(ak_sem, 'r_start -> r_next ');
&               endif
                a74_copy_twokeys (acv,
                      sparr.px[ 2 ]^.sreskey.res_keysbuf,
                      sparr.px[ 2 ]^.sreskey.res_startkeys,
                      sparr.px[ 2 ]^.sreskey.res_nextkeys,
                      sparr.px[ 2 ]^.sreskey.res_resstate);
                ak74record_fetch (acv, sparr, orig_mblock.mbr_mess_block,
                      mrec, false);
                mrec.fr_stepkind  := mm_last;
                mrec.fr_act_cnt :=  -pos;
&               ifdef trace
                t01name(ak_sem, 'r_next -> r_prev  ');
&               endif
                a74_copy_twokeys (acv,
                      sparr.px[ 2 ]^.sreskey.res_keysbuf,
                      sparr.px[ 2 ]^.sreskey.res_nextkeys,
                      sparr.px[ 2 ]^.sreskey.res_prevkeys,
                      sparr.px[ 2 ]^.sreskey.res_resstate);
                END
            ELSE
                BEGIN
                mrec.fr_stepkind := mm_last;
                (* position one col before demanded col *)
                mrec.fr_act_cnt :=  -pos;
&               ifdef trace
                t01name(ak_sem, 'r_stop -> r_prev  ');
&               endif
                a74_copy_twokeys (acv,
                      sparr.px[ 2 ]^.sreskey.res_keysbuf,
                      sparr.px[ 2 ]^.sreskey.res_stopkeys,
                      sparr.px[ 2 ]^.sreskey.res_prevkeys,
                      sparr.px[ 2 ]^.sreskey.res_resstate);
                END;
            (*ENDIF*) 
            END
        ELSE
            (* abpos > 0, step in direction EOF *)
            BEGIN
            IF  ( mtype = mm_last_rowno )
            THEN
                mrec.fr_stepkind := mm_last_rowno
            ELSE
                mrec.fr_stepkind := mm_next;
            (*ENDIF*) 
            IF  ( sparr.px[ 2 ]^.sreskey.res_nextpos <> -1 )
            THEN
                (* abspos > 0 and valid res_nextpos *)
                BEGIN
                IF  ( pos > sparr.px[ 2 ]^.sreskey.res_nextpos )
                THEN
                    (* abspos > res_nextpos *)
                    (* position from actual res_nextpos *)
                    BEGIN
                    mrec.fr_act_cnt := pos -
                          sparr.px[ 2 ]^.sreskey.res_nextpos;
                    END
                ELSE
                    BEGIN
                    (* pos <= res_nextpos *)
                    (* position from beginning *)
                    mrec.fr_act_cnt := pos;
                    sparr.px[ 2 ]^.sreskey.res_nextpos := 0;
&                   ifdef trace
                    t01name(ak_sem, 'r_start -> r_next ');
&                   endif
                    a74_copy_twokeys (acv,
                          sparr.px[ 2 ]^.sreskey.res_keysbuf,
                          sparr.px[ 2 ]^.sreskey.res_startkeys,
                          sparr.px[ 2 ]^.sreskey.res_nextkeys,
                          sparr.px[ 2 ]^.sreskey.res_resstate);
                    _start_from_bof := true;
                    END;
                (*ENDIF*) 
                END
            ELSE
                (* invalid res_nextpos and pos > 0 *)
                (* position from beginning *)
                BEGIN
                mrec.fr_act_cnt := pos;
                sparr.px[ 2 ]^.sreskey.res_nextpos := 0;
&               ifdef trace
                t01name(ak_sem, 'r_start -> r_next ');
&               endif
                a74_copy_twokeys (acv,
                      sparr.px[ 2 ]^.sreskey.res_keysbuf,
                      sparr.px[ 2 ]^.sreskey.res_startkeys,
                      sparr.px[ 2 ]^.sreskey.res_nextkeys,
                      sparr.px[ 2 ]^.sreskey.res_resstate);
                _start_from_bof := true;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  _start_from_bof AND (mrec.fr_stepkind = mm_next)
    THEN
        mrec.fr_stepkind := mm_first;
    (*ENDIF*) 
    END
ELSE
    BEGIN
    (* mtype = mm_search if                        *)
    (* pos < 0 AND invalid res_prevpos             *)
    (* OR                                          *)
    (* invalid res_nextpos AND invalid res_prevpos *)
    (* step from actual unknown position (use keys)*)
    (* position one col before demanded col        *)
    IF  ( pos > 0 )
    THEN
        BEGIN
        mrec.fr_stepkind  := mm_next;
        mrec.fr_act_cnt   := pos;
        END
    ELSE
        BEGIN
        mrec.fr_stepkind  := mm_prev;
        mrec.fr_act_cnt := -pos;
        END
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
IF  ( acv.a_returncode = 0 )
    (* there could be e_row_not_found *)
THEN
    BEGIN
    IF  ( mtype = mm_last_rowno )
    THEN
        mrec.fr_poskind := mm_next
    ELSE
        mrec.fr_poskind := mrec.fr_stepkind;
    (*ENDIF*) 
    acv.a_mblock.mb_trns^.trError_gg00 := e_ok;
&   ifdef TRACE
    t01mess2type( ak_sem, 'stepkind    ', mrec.fr_stepkind );
    t01mess2type( ak_sem, 'poskind     ', mrec.fr_poskind );
    t01int4 (ak_sem, 'fr_act_cnt  ', mrec.fr_act_cnt);
&   endif
    IF  ( mrec.fr_act_cnt > 0 )
    THEN
        BEGIN
        ak74record_fetch (acv, sparr, orig_mblock.mbr_mess_block,
              mrec, false);
        END
    ELSE
        acv.a_mblock.mb_trns^.trError_gg00 := e_ok;
    (*ENDIF*) 
    IF  ( mrec.fr_stepkind in [ mm_prev, mm_last ] )
    THEN
        BEGIN
&       ifdef trace
        t01name(ak_sem, 'r_prev -> r_next  ');
&       endif
        a74_copy_twokeys (acv,
              sparr.px[ 2 ]^.sreskey.res_keysbuf,
              sparr.px[ 2 ]^.sreskey.res_prevkeys,
              sparr.px[ 2 ]^.sreskey.res_nextkeys,
              sparr.px[ 2 ]^.sreskey.res_resstate);
        sparr.px[ 2 ]^.sreskey.res_nextpos :=
              sparr.px[ 2 ]^.sreskey.res_prevpos
        END
    ELSE
        IF  ( mrec.fr_stepkind in [ mm_first, mm_next, mm_last_rowno ] )
        THEN
            BEGIN
&           ifdef trace
            t01name(ak_sem, 'r_next -> r_prev  ');
&           endif
            a74_copy_twokeys (acv,
                  sparr.px[ 2 ]^.sreskey.res_keysbuf,
                  sparr.px[ 2 ]^.sreskey.res_nextkeys,
                  sparr.px[ 2 ]^.sreskey.res_prevkeys,
                  sparr.px[ 2 ]^.sreskey.res_resstate);
            sparr.px[ 2 ]^.sreskey.res_prevpos :=
                  sparr.px[ 2 ]^.sreskey.res_nextpos
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  ( acv.a_mblock.mb_trns^.trError_gg00 <> e_ok )
    THEN
        a07_b_put_error (acv, acv.a_mblock.mb_trns^.trError_gg00, 1);
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
&ifdef trace
t01mess2type( ak_sem, 'out mtype   ', mtype );
t01p2int4( ak_sem, 'res_nextpos ', sparr.px[ 2 ]^.sreskey.res_nextpos,
      'res_prevpos ', sparr.px[ 2 ]^.sreskey.res_prevpos );
t01p2bool( ak_sem, 'res_bof     ', sparr.px[ 2 ]^.sreskey.res_bof ,
      'res_eof     ', sparr.px[ 2 ]^.sreskey.res_eof );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak74single_fetch(
            VAR acv             : tak_all_command_glob;
            VAR sparr           : tak_syspointerarr;
            VAR orig_mblock     : tak_messblock_record;
            VAR mrec            : mfetch_rec;
            fill_ret_segm       : boolean);
 
VAR
      _output_offset       : tsp00_Int4;
      _direct_retpart_move : boolean;
 
BEGIN
_output_offset :=
      orig_mblock.mbr_mess_block.
      mb_st^[orig_mblock.mbr_mess_block.
      mb_qual^.mqual_pos].elen_var - 1;
_direct_retpart_move := ( sparr.px[ 2 ]^.sreskey.res_keylen +
      cgg_rec_key_offset - _output_offset = 0 ) AND
      fill_ret_segm;
&ifdef trace
t01int4 (ak_sem, 'output_offse', _output_offset);
t01bool (ak_sem, 'direct_ret_m', _direct_retpart_move);
&endif
mrec.fr_act_cnt   := 1;
mrec.fr_act_leng  := sparr.px[ 2 ]^.sreskey.res_reclen - _output_offset;
IF  ( _direct_retpart_move )
THEN
    a06init_curr_retpart (acv);
(*ENDIF*) 
IF  ( acv.a_returncode = 0 )
THEN
    ak74record_fetch (acv, sparr, orig_mblock.mbr_mess_block,
          mrec, _direct_retpart_move);
(*ENDIF*) 
IF  ( acv.a_mblock.mb_trns^.trError_gg00 <> e_ok )
THEN
    BEGIN
    sparr.px[ 2 ]^.sreskey.res_useupdk := 0;
    a07_b_put_error (acv, acv.a_mblock.mb_trns^.trError_gg00, 1);
    END;
(*ENDIF*) 
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    (* now we have positions on the result set *)
    sparr.px[ 2 ]^.sreskey.res_bof := false;
    acv.a_mblock.mb_data_len :=
          sparr.px[ 2 ]^.sreskey.res_length - _output_offset;
    IF  ( sparr.px[ 2 ]^.sreskey.res_for_update )
    THEN
        BEGIN
        sparr.px[ 2 ]^.sreskey.res_useupdk :=
              sparr.px[ 2 ]^.sreskey.res_upd_tabcnt;
        SAPDB_PascalMove ('VAK74 ',   8,    
              acv.a_mblock.mb_data_size,
              sizeof(sparr.px[ 2 ]^.sreskey.res_keysbuf),
              @acv.a_mblock.mb_data^.mbp_buf,
              sparr.px[ 2 ]^.sreskey.res_length - _output_offset + 1,
              @sparr.px[ 2 ]^.sreskey.res_keysbuf,
              sparr.px[ 2 ]^.sreskey.res_updkey.ks_pos,
              sparr.px[ 2 ]^.sreskey.res_reclen -
              sparr.px[ 2 ]^.sreskey.res_length,
              acv.a_returncode);
        END;
    (*ENDIF*) 
    IF  ( fill_ret_segm )
    THEN
        BEGIN
        IF  ( sparr.px[ 2 ]^.sreskey.res_change.cr_colcount > 0 ) AND
            ( acv.a_returncode = 0 )
        THEN
            a60_change_results (acv, acv.a_mblock.mb_data^.mbp_buf,
                  sparr.px[ 2 ]^.sreskey.res_change,
                  -_output_offset,
                  sparr.px[ 2 ]^.sreskey.res_length);
        (*ENDIF*) 
        IF  ( NOT _direct_retpart_move ) AND
            ( acv.a_returncode = 0 )
        THEN
            a60_put_result (acv, acv.a_mblock,
                  sparr.px[ 2 ]^.sreskey.res_keylen +
                  cgg_rec_key_offset - _output_offset)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak74mass_fetch(
            VAR acv             : tak_all_command_glob;
            VAR sparr           : tak_syspointerarr;
            VAR orig_mblock     : tak_messblock_record;
            VAR mrec            : mfetch_rec;
            VAR foundrecs       : tsp00_Int4;
            mfetch_count        : tsp00_Int4);
 
VAR
      _unused_leng         : tsp00_Int4;
      _i                   : tsp00_Int4;
      _col_no              : tsp00_Int4;
      _cnt                 : tsp00_Int4;
      _direct_retpart_move : boolean;
      _special_handling    : boolean;
 
BEGIN
a06init_curr_retpart (acv);
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    (* bring results in right order *)
    _special_handling := ( mrec.fr_stepkind in [ mm_prev, mm_last ] );
    _direct_retpart_move := false;
    foundrecs := 0;
    sparr.px[ 2 ]^.sreskey.res_useupdk := 0;
    _i := 0;
    (* PTS 1116917 E.Z. *)
    _unused_leng := a73_calc_unused_space (acv);
&   ifdef trace
    t01int4 (ak_sem, '_unused_leng', _unused_leng);
    t01int4 (ak_sem, 'res_reclen  ', sparr.px[ 2 ]^.sreskey.res_reclen);
    t01int4 (ak_sem, 'res_length  ', sparr.px[ 2 ]^.sreskey.res_length);
&   endif
    IF  ( acv.a_init_ex_kind = only_executing )
    THEN
        (* PTS 1000479 E.Z. *)
        IF  ( sparr.px[ 1 ]^.sparsinfo.p_resinfolen < 0 )
        THEN
            BEGIN
            _col_no := -sparr.px[ 1 ]^.sparsinfo.p_resinfolen;
            IF  ( _col_no > sparr.px[ 2 ]^.sreskey.res_outcolno )
            THEN
                _col_no := sparr.px[ 2 ]^.sreskey.res_outcolno;
            (*ENDIF*) 
            a73_infolen_get (acv, _col_no, mrec.fr_act_leng)
            END
        ELSE
            mrec.fr_act_leng := sparr.px[ 1 ]^.sparsinfo.p_resinfolen
        (*ENDIF*) 
    ELSE
        mrec.fr_act_leng := sparr.px[ 2 ]^.sreskey.res_length -
              sparr.px[ 2 ]^.sreskey.res_keylen - cgg_rec_key_offset;
    (*ENDIF*) 
    (* PTS 1106648 E.Z. *)
    IF  NOT ( _special_handling )
    THEN
        BEGIN
&       ifdef trace
        t01name(ak_sem, 'set direct retpart');
&       endif
        _direct_retpart_move := true;
        _unused_leng := _unused_leng - (sparr.px[ 2 ]^.sreskey.res_reclen -
              sparr.px[ 2 ]^.sreskey.res_length);
        END;
    (*ENDIF*) 
    IF  ( _unused_leng < mrec.fr_act_leng )
    THEN
        _cnt := 1
    ELSE
        _cnt := _unused_leng DIV mrec.fr_act_leng;
    (*ENDIF*) 
    IF  ( _cnt > mfetch_count )
    THEN
        _cnt := mfetch_count;
    (*ENDIF*) 
    ;
    (* PTS 1119953 E.Z. *)
    IF  ( sparr.px[ 2 ]^.sreskey.res_for_update AND ( mfetch_count = 1 ))
    THEN
        mrec.fr_act_leng := mrec.fr_act_leng +
              sparr.px[ 2 ]^.sreskey.res_reclen -
              sparr.px[ 2 ]^.sreskey.res_length;
    (*ENDIF*) 
    IF  ( _special_handling AND ( mrec.fr_act_leng < _unused_leng ))
    THEN
        acv.a_curr_retpart^.sp1p_buf_len :=
              acv.a_curr_retpart^.sp1p_buf_len + _cnt * mrec.fr_act_leng;
    (*ENDIF*) 
    acv.a_mblock.mb_trns^.trError_gg00 := e_ok;
&   ifdef trace
    t01int4 (ak_sem, '_cnt        ', _cnt);
&   endif
    (* if we do not copy results direct to return part *)
    (* it can be the case that we need some kb orders  *)
    (* with small usable space in messblock            *)
    REPEAT
        (*  h.b. *)
        IF  ( _direct_retpart_move )
        THEN
            mrec.fr_act_cnt := _cnt - foundrecs
        ELSE
            BEGIN
            mrec.fr_act_cnt := ( acv.a_mblock.mb_data_size -
                  orig_mblock.mbr_mess_block.mb_data_len )
                  DIV mrec.fr_act_leng;
            IF  ( mrec.fr_act_cnt > _cnt - foundrecs )
            THEN
                mrec.fr_act_cnt := _cnt - foundrecs
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        ak74record_fetch (acv, sparr, orig_mblock.mbr_mess_block,
              mrec, _direct_retpart_move);
        IF  ( foundrecs = 0 )
        THEN
            (* initializing after first loop *)
            BEGIN
            mrec.fr_switches := mrec.fr_switches - [ _fs_first_loop ];
            IF  ( acv.a_mblock.mb_qual^.mf_desc.m_cnt = 0 )
            THEN
                a07_b_put_error (acv, e_row_not_found, 1);
            (*ENDIF*) 
            IF  ( mrec.fr_stepkind in [ mm_first, mm_direct ] )
            THEN
                (* now fetch next records *)
                mrec.fr_stepkind := mm_next
            ELSE
                BEGIN
                IF  mrec.fr_stepkind = mm_last
                THEN
                    (* now fetch previous records *)
                    mrec.fr_stepkind := mm_prev;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  (( acv.a_returncode = 0 ) AND
            ( acv.a_mblock.mb_trns^.trError_gg00 = e_ok ))
        THEN
            BEGIN
            IF  ( sparr.px[ 2 ]^.sreskey.res_for_update AND ( _cnt = 1 ))
            THEN
                BEGIN
                sparr.px[ 2 ]^.sreskey.res_useupdk :=
                      sparr.px[ 2 ]^.sreskey.res_upd_tabcnt;
                (* PTS 1119953 E.Z. *)
                SAPDB_PascalMove ('VAK74 ',   9,    
                      acv.a_mblock.mb_data_size,
                      sizeof(sparr.px[ 2 ]^.sreskey.res_keysbuf),
                      @acv.a_mblock.mb_data^.mbp_buf,
                      mrec.fr_act_leng -
                      sparr.px[ 2 ]^.sreskey.res_reclen +
                      sparr.px[ 2 ]^.sreskey.res_length + 1,
                      @sparr.px[ 2 ]^.sreskey.res_keysbuf,
                      sparr.px[ 2 ]^.sreskey.res_updkey.ks_pos,
                      sparr.px[ 2 ]^.sreskey.res_reclen -
                      sparr.px[ 2 ]^.sreskey.res_length,
                      acv.a_returncode);
                END;
            (*ENDIF*) 
            IF  ( sparr.px[ 2 ]^.sreskey.res_change.cr_colcount > 0 ) AND
                ( acv.a_returncode = 0 )
            THEN
                FOR _i := 1 TO acv.a_mblock.mb_qual^.mf_desc.m_cnt DO
                    a60_change_results (acv,
                          acv.a_mblock.mb_data^.mbp_buf,
                          sparr.px[ 2 ]^.sreskey.res_change,
                          (_i-1) * mrec.fr_act_leng-
                          sparr.px[ 2 ]^.sreskey.res_keylen - cgg_rec_key_offset,
                          cgg_rec_key_offset +
                          sparr.px[ 2 ]^.sreskey.res_keylen + mrec.fr_act_leng);
                (*ENDFOR*) 
            (*ENDIF*) 
            IF  ( mrec.fr_act_leng > _unused_leng ) AND
                ( acv.a_returncode = 0 )
            THEN
                (* PTS 1116801 E.Z. *)
                a07_b_put_error (acv, e_stack_overflow, 1)
            ELSE
                IF  ( _special_handling )
                THEN
                    (* reverse result order *)
                    BEGIN
&                   ifdef trace
                    t01name(ak_sem, 'reverse reslt orde');
                    t01p2int4(ak_sem, 'm_cnt       ', acv.a_mblock.mb_qual^.mf_desc.m_cnt,
                          'foundrecs   ', foundrecs );
&                   endif
                    _i := 1;
                    WHILE ( _i <= acv.a_mblock.mb_qual^.mf_desc.m_cnt ) AND
                          ( acv.a_returncode = 0 ) DO
                        BEGIN
                        SAPDB_PascalMove ('VAK74 ',  10,    
                              acv.a_mblock.mb_data_size, (* src *)
                              acv.a_curr_retpart^.sp1p_buf_size, (* dst *)
                              @acv.a_mblock.mb_data^.mbp_buf,
                              (_i - 1) * mrec.fr_act_leng + 1,
                              @acv.a_curr_retpart^.sp1p_buf,
                              acv.a_curr_retpart^.sp1p_buf_len
                              -( foundrecs + _i)* mrec.fr_act_leng + 1,
                              mrec.fr_act_leng,
                              acv.a_returncode);
                        _i := succ(_i)
                        END
                    (*ENDWHILE*) 
                    END
                ELSE
                    BEGIN
&                   ifdef trace
                    t01int4 (ak_sem, 'MOVE-LEN    ',
                          acv.a_mblock.mb_qual^.mf_desc.m_cnt * mrec.fr_act_leng);
                    (*t01moveobj (ak_sem, acv.a_mblock.mb_data^.mbp_buf,
                          1, acv.a_mblock.mb_qual^.mf_desc.m_cnt * mrec.fr_act_leng);*)
&                   endif
                    IF  ( NOT _direct_retpart_move )
                    THEN
                        a06retpart_move (acv,
                              @acv.a_mblock.mb_data^.mbp_buf,
                              acv.a_mblock.mb_qual^.mf_desc.
                              m_cnt * mrec.fr_act_leng);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            foundrecs := foundrecs +
                  acv.a_mblock.mb_qual^.mf_desc.m_cnt;
            END;
        (*ENDIF*) 
    UNTIL
        (( foundrecs = _cnt ) OR
        (* no more results from file *)
        ( mrec.fr_act_cnt > acv.a_mblock.mb_qual^.mf_desc.m_cnt ) OR
        ( acv.a_returncode <> 0 ) OR
        ( acv.a_mblock.mb_trns^.trError_gg00 = e_no_next_record ));
    (*ENDREPEAT*) 
    IF  ( acv.a_returncode = 0 )
    THEN
        BEGIN
        IF  ( acv.a_mblock.mb_trns^.trError_gg00 = e_no_next_record )
            OR
            ( mrec.fr_act_cnt > acv.a_mblock.mb_qual^.mf_desc.m_cnt )
        THEN
            acv.a_curr_retpart^.sp1p_attributes := [ sp1pa_last_packet ];
        (*ENDIF*) 
        sparr.px[ 2 ]^.sreskey.res_bof := false;
        IF  ( _special_handling AND
            ( acv.a_curr_retpart^.sp1p_buf_len > ( foundrecs * mrec.fr_act_leng )))
        THEN
            SAPDB_PascalOverlappingMove ('VAK74 ',  11,    
                  acv.a_curr_retpart^.sp1p_buf_size,
                  acv.a_curr_retpart^.sp1p_buf_size,
                  @acv.a_curr_retpart^.sp1p_buf,
                  acv.a_curr_retpart^.sp1p_buf_len
                  -foundrecs * mrec.fr_act_leng + 1,
                  @acv.a_curr_retpart^.sp1p_buf,
                  1,
                  foundrecs * mrec.fr_act_leng,
                  acv.a_returncode);
        (*ENDIF*) 
        acv.a_curr_retpart^.sp1p_buf_len := foundrecs * mrec.fr_act_leng;
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
