.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-10
*****************************************************
modname : VKB75
changed : 2000-11-10
module  : KB_Fetch
 
Author  : ElkeZ
Created : 1985-10-16
*****************************************************
 
Purpose : This module is used for fetches for
          result sets which are not physically build
 
 
 
Define  :
 
        PROCEDURE
              k75_fetch (VAR m : tgg00_MessBlock);
 
.CM *-END-* define --------------------------------------
***********************************************************
 
Use     :
 
&       ifdef TRACE
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01mess2type (
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    mess2_type    : tgg00_MessType2);
 
        PROCEDURE
              t01bool (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    curr_bool: boolean);
 
        PROCEDURE
              t01name (
                    debug : tgg00_Debug;
                    nam   : tsp00_Name);
 
        PROCEDURE
              t01key (
                    debug   : tgg00_Debug;
                    nam     : tsp00_Sname;
                    VAR k   : tgg00_Lkey);
 
        PROCEDURE
              t01basis_error (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname;
                    b_err : tgg00_BasisError);
 
        PROCEDURE
              t01int4 (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01fetch_desc(
                    debug       : tgg00_Debug;
                    nam         : tsp00_Sname;
                    VAR mf_desc : tgg00_FetchDesc);
&       endif
 
      ------------------------------ 
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01diag_monitor_on : boolean;
              a01diag_analyze_on : boolean;
 
      ------------------------------ 
 
        FROM
              Single_Select : VKB720;
 
        PROCEDURE
              k720monitor (
                    VAR trans         : tgg00_TransContext;
                    VAR sel           : tgg00_SelectFieldsParam;
                    start_sec         : tsp00_Int4;
                    start_microsec    : tsp00_Int4;
                    start_phys_ios    : tsp00_Int4;
                    start_suspends    : tsp00_Int4;
                    start_waits       : tsp00_Int4;
                    put_strat         : boolean;
                    arr_index         : tgg00_RefInfoIndex;
                    strat_cnt         : boolean);
 
        PROCEDURE
              k720_maxresult_get (
                    strat_maxcnt       : tsp00_Int4;
                    VAR maxresult      : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1   : VBD01;
 
        VAR
              b01fullkey    : tsp00_Key;
              b01zerokey    : tsp00_Key;
 
        PROCEDURE
              b01vstate_fileversion (
                    VAR t       : tgg00_TransContext;
                    VAR file_id : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_2   : VBD02;
 
        PROCEDURE
              b02kb_select_rec (
                    VAR t            : tgg00_TransContext;
                    VAR file_id      : tgg00_FileId;
                    VAR RecKey       : tsp00_Key;
                    VAR RecKeyLen    : tsp00_Int2;
                    VAR StopKey      : tsp00_Key;
                    StopKeyLen       : tsp00_Int4;
                    recbuf_size      : tsp00_Int4;
                    recbuf_ptr       : tsp00_MoveObjPtr;
                    ignore_vwait     : boolean;
                    VAR sel          : tgg00_SelectFieldsParam;
                    VAR stack_desc   : tgg00_StackDesc;
                    VAR unqualified  : boolean;
                    VAR granted_lock : tgg00_LockReqMode);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_3 : VBD03;
 
        PROCEDURE
              b03select_invrec (
                    VAR t            : tgg00_TransContext;
                    VAR ftrees       : tgg00_TwoFileIds;
                    VAR keypair      : tgg00_TwoKeys;
                    VAR stop_keypair : tgg00_TwoKeys;
                    VAR startkey     : tgg00_Lkey;
                    VAR invrange_set : tgg00_BdInvSet;
                    recbuf_size      : tsp00_Int4;
                    recbuf_ptr       : tsp00_MoveObjPtr;
                    VAR sel          : tgg00_SelectFieldsParam;
                    VAR stack_desc   : tgg00_StackDesc;
                    VAR granted_lock : tgg00_LockReqMode);
 
      ------------------------------ 
 
        FROM
              BD_Wrapper : VBD999;
 
        FUNCTION
              bd999GetDataIOBlockCount : tsp00_Int4;

        FUNCTION
              bd999GetPageSize : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vclock (
                    VAR sec      : tsp00_Int4;
                    VAR microsec : tsp00_Int4);
 
        PROCEDURE
              vmonitor (
                    pid          : tsp00_TaskId;
                    VAR phys_ios : tsp00_Int4;
                    VAR suspends : tsp00_Int4;
                    VAR waits    : tsp00_Int4);
 
        PROCEDURE
              vdebug_break (debug_break_pos : tsp00_Int4);
 
        PROCEDURE
              vnewbuf (count      : tsp00_Int4;
                    VAR available : tsp00_Int4;
                    VAR p         : tsp00_Addr;
                    VAR ok        : boolean);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01ConsistentReadEnabled : boolean;
 
        PROCEDURE
              g01mblock_init (
                    VAR source_trans : tgg00_TransContext;
                    mess_type  : tgg00_MessType;
                    mess2_type : tgg00_MessType2;
                    VAR mblock : tgg00_MessBlock);
 
      ------------------------------ 
 
        FROM
              Select_Help_Procedures : VGG04;
 
        PROCEDURE
              g04init_select_fields (
                    VAR sel       : tgg00_SelectFieldsParam;
                    data_addr     : tsp00_MoveObjPtr;
                    data_size     : tsp00_Int4;
                    work_st_addr  : tgg00_StackListPtr;
                    work_st_max   : tsp00_Int2;
                    work_buf_addr : tsp00_MoveObjPtr;
                    work_buf_size : tsp00_Int4;
                    curr_sqlmode  : tsp00_SqlMode;
                    fieldlistptr  : tgg00_FieldListsPtr);
 
        PROCEDURE
              g04smallest_greater_key(
                    VAR file_id    : tgg00_FileId;
                    VAR key        : tgg00_Lkey );
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalFill  (
                    mod_id         : tsp00_C6;
                    mod_intern_num : tsp00_Int4;
                    source_upb     : tsp00_Int4;
                    source         : tsp00_MoveObjPtr;
                    source_pos     : tsp00_Int4;
                    length         : tsp00_Int4;
                    fill_char      : char;
                    VAR e          : tgg00_BasisError);
 
        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_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);
 
.CM *-END-* use -----------------------------------------
***********************************************************
 
Synonym :

        PROCEDURE
              vnewbuf;

              tsp00_PageAddr tsp00_Addr
 
.CM *-END-* synonym -------------------------------------
***********************************************************
 
Description:
 
K75_FETCH
 
The type vax_optimizer_help was introduced solely to outwit the VAX
compiler. If one were to define help_buf and rec_buf individually as
variables, although both are used merely as parameters of s30gad
within the procedure, the compiler would assume that the buffers were
not needed and would assign both to the same stack address. However,
since both are needed (in VKB71), one has to trick the compiler.
.br;All the information concerning start- and stopkeys, record
lengths, etc. is contained in the following structure that is filed in
part2 of the mess buffer. In contrast to common practice, the data
part for the qualifications is behind the stack entries in part1.
 
           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           : tree_id;  (*pos 11*)
           m_fns2           : tree_id;  (*pos 43*)
           m_startkeys      : two_keys; (*pos 75, 333*)
           m_stopkeys       : two_keys; (*pos 591, 849*)
           m_firstkeys      : two_keys; (*pos 1107, 1365*)
           m_start          : lkey;     (*pos 1623*)
 
The meanings of the elements are as follows :
 
-  m_use_inv : search via an inversion
 
-  m_use_stop : stopkeys should be considered
 
-  m_single : only one result record is to be sought; i.e. with key
 
-  m_use_recs : results have to be passed to AK and are not used for
jumping to the desired position (POS [  ])
 
-  m_keylen : length of the key of the result record
 
-  m_cnt : number of desired results
 
-  m_leng : length of a result
 
-  m_fns1 : Name of the primary file
 
-  m_fns2 : Name of the secondary file
 
-  m_startkeys : Secondary key value and primary key value at which
the search is to start
 
-  m_stopkeys : Secondary key value and primary key value at which
the search is to end
 
-  m_firstkeys : Secondary key value and primary key value of the
first result found (output parameter)
 
-  m_start : Primary key value at which the search is to start in the
next inversion list
 
Loopmtype receives the information indicating the direction
in which the search will proceed as of the second result record.
SEL, a record passed to BD and VKB71 by KB, is initialized :
starting address of the stack entries of the qualification and the
data part (together in a single buffer) and two auxiliary buffers for
intermediate results (addresses in a record because it would not be
desirable for all of these buffers to travel through half the BD layer
as single parameters).
The command (fetch) and the search direction are given. ISTOP contains
the information indicating whether start- and/or stopkeys are to be
obeyed.
The desired number of results (m_cnt) are sought in a loop;
B03SELECT_INVREC is used for a search via an inversion,
B02SELECT_RECORD is used for a search without inversion.
If a requested lock is not immediately available, K53WAIT is
used to implement a wait. K53WAIT may return KB-TIMEOUT if the lock
remains unavailable despite the wait.
Once the lock is obtained, the same record (mm_direct) has to
be searched for again, so that the qualification can be checked. This
is necessary because the reason for the lock of the other process
may have been an
update. Direct searching is possible because at this juncture, the key
values of the record to be searched are already contained in the
parameters passed on as variables. Hence, it is no longer necessary to
conduct the search with the aid of an inversion.
If a record that fulfills the conditions is found, it is
transferred to part1, if the transfer is desired (m_use_recs). The
transfer is possible because the stack entries and the data part were
held in an auxiliary buffer and thus the results do not destroy the
stack entries used.
The number of results and the total length of all the results are
incremented and m_firstkeys is occupied when the first result is
available.
Any insignificant errors that arise in the repeat search after
K53WAIT are forgotten.
The direction of search is again correctly assigned (it may have
been changed in the repeat search after K53WAIT and in any case it
would have to be changed in response to FIRST/LAST following the first
result).
The loop, the search for all desired or discoverable results, may
be followed by the destruction of warning 14 that is set by BD every
time there is a change of inversion list, but that is not passed on to
the user except in the case of Ordered Selects via inversions.
Different errors are summarized in one to facilitate queries (also
in AK).
If the desired number of results have been found, (e_ok) or even
if fewer have been found (0 is possible with MFETCH if the records are
not merely to be skipped) the procedure is deemed to have run
correctly and the mess buffer is filled up accordingly. If this is not
so, the error is returned to AK.
 
.CM *-END-* description ---------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
(*------------------------------*) 
 
PROCEDURE
      k75_fetch (VAR m : tgg00_MessBlock);
 
CONST
      c_ignore_vwait  = true;
      c_not_put_strat = false;
      c_not_strat_cnt = false;
 
VAR
      _tmp_cnt        : tsp00_Int4;
      _start_sec      : tsp00_Int4;
      _start_microsec : tsp00_Int4;
      _start_phys_ios : tsp00_Int4;
      _start_suspends : tsp00_Int4;
      _start_waits    : tsp00_Int4;
      _ori_data_size  : tsp00_Int4;
      _rowno          : tsp00_Int4;
      _available      : tsp00_Int4;
      _data_ptr       : tsp00_MoveObjPtr;
      _m_ftr_help     : tgg00_TwoFileIds;
      _aux_stack_desc : tgg00_StackDesc;
      _searchkeys     : tgg00_TwoKeys;
      _tmpkeys        : tgg00_TwoKeys;
      _sel            : tgg00_SelectFieldsParam;
      _istop          : tgg00_BdInvSet;
      _unqualified    : boolean;
      _work_mtype     : tgg00_MessType2;
      _dummy_mode     : tgg00_LockReqMode;
      _ok             : boolean;
 
BEGIN
&ifdef trace
t01fetch_desc(kb, 'fetch desc 1', m.mb_qual^.mf_desc);
&endif
m.mb_qual^.mf_desc.m_firstkeys.reckey.len  := 0;
m.mb_qual^.mf_desc.m_firstkeys.listkey.len := 0;
m.mb_trns^.trRteCommPtr_gg00^.file_root    := NIL_PAGE_NO_GG00;
m.mb_trns^.trRteCommPtr_gg00^.file_record_cnt :=
      m.mb_qual^.mf_desc.m_searched_pages;
(* PTS 1001469 E.Z. *)
IF  ( a01diag_monitor_on OR a01diag_analyze_on )
THEN
    BEGIN
    vclock (_start_sec, _start_microsec);
    vmonitor (m.mb_trns^.trTaskId_gg00, _start_phys_ios, _start_suspends,
          _start_waits);
    END
(* PTS 1001518 E.Z. *)
ELSE
    BEGIN
    _start_sec      := 1;
    _start_microsec := 0;
    _start_phys_ios := 0;
    _start_suspends := 0;
    _start_waits    := 0;
    END;
(*ENDIF*) 
CASE m.mb_type2 (* logical movement *) OF
    (* create physical movement *)
    mm_direct:
        BEGIN
        IF  ( fs_reverse_fetch in m.mb_qual^.mf_desc.m_fetch_state )
        THEN
            _work_mtype := mm_last
        ELSE
            _work_mtype:= mm_first;
        (*ENDIF*) 
        END;
    mm_first:
        BEGIN
        IF  ( fs_reverse_fetch in m.mb_qual^.mf_desc.m_fetch_state )
        THEN
            _work_mtype := mm_last
        ELSE
            _work_mtype := mm_first;
        (*ENDIF*) 
        END;
    mm_last:
        BEGIN
        IF  ( fs_reverse_fetch in m.mb_qual^.mf_desc.m_fetch_state )
        THEN
            _work_mtype := mm_first
        ELSE
            _work_mtype := mm_last;
        (*ENDIF*) 
        END;
    mm_next,
    mm_last_rowno:
        BEGIN
        IF  ( fs_reverse_fetch in m.mb_qual^.mf_desc.m_fetch_state )
        THEN
            _work_mtype:= mm_prev
        ELSE
            _work_mtype:= mm_next;
        (*ENDIF*) 
        END;
    mm_prev:
        BEGIN
        IF  ( fs_reverse_fetch in m.mb_qual^.mf_desc.m_fetch_state )
        THEN
            _work_mtype:= mm_next
        ELSE
            _work_mtype:= mm_prev;
        (*ENDIF*) 
        END;
    OTHERWISE
        BEGIN
        _work_mtype:= m.mb_type2;
        END;
    END;
(*ENDCASE*) 
&ifdef trace
t01mess2type( kb, 'logical move', m.mb_type2 );
t01mess2type( kb, '_work_mtype ', _work_mtype );
&endif
IF  ( m.mb_qual^.mf_desc.m_startkeys.reckey.len = 0 ) AND
    ( _work_mtype =  mm_next )
THEN
    _work_mtype := mm_first;
(*ENDIF*) 
IF  ( m.mb_qual^.mf_desc.m_startkeys.reckey.len = 0 ) AND
    ( _work_mtype =  mm_prev )
THEN
    _work_mtype := mm_last;
(*ENDIF*) 
_aux_stack_desc          := m.mb_qual^.mstack_desc;
_aux_stack_desc.mst_addr := m.mb_st;
_ori_data_size           := m.mb_data_size;
IF  ( m.mb_qual^.mf_desc.m_data = NIL )
THEN (* remote call, qualification data is stored in m.mb_data *)
    IF  ( m.mb_data_size - m.mb_data_len < m.mb_qual^.mf_desc.m_leng )
    THEN
        m.mb_trns^.trError_gg00 := e_too_many_mb_data
    ELSE
        BEGIN
        SAPDB_PascalOverlappingMove ('VKB75 ',   1,    
              m.mb_data_size, m.mb_data_size,
              @m.mb_data^.mbp_buf, 1,
              @m.mb_data^.mbp_buf, m.mb_data_size - m.mb_data_len + 1,
              m.mb_data_len, m.mb_trns^.trError_gg00);
        _data_ptr := @m.mb_data^.mbp_buf [m.mb_data_size - m.mb_data_len + 1 ];
        m.mb_data_size  := m.mb_data_size - m.mb_data_len;
        END
    (*ENDIF*) 
ELSE (* local call, qualification data stored in m_data^ *)
    _data_ptr := @m.mb_qual^.mf_desc.m_data^;
(*ENDIF*) 
g04init_select_fields( _sel, _data_ptr, m.mb_data_size,
      m.mb_work_st, m.mb_work_st_max,
      m.mb_workbuf, m.mb_workbuf_size, m.mb_qual^.msqlmode, @m.mb_fieldlists );
_sel.sfp_acv_addr      := m.mb_trns^.trAcvPtr_gg00;   (* PTS 1121403 E.Z. *)
_sel.sfp_output_offset := m.mb_st^[ m.mb_qual^.mqual_pos ].elen_var - 1;
_sel.sfp_bd_mess_type   := m_fetch;
_sel.sfp_bd_mess2_type  := _work_mtype;
_sel.sfp_result_wanted  := true;
_sel.sfp_bd_inv_only    := m.mb_qual^.mf_desc.m_qual_kind;
_sel.sfp_bd_use_stopkey := ( fs_use_stop in m.mb_qual^.mf_desc.m_fetch_state );
IF  ( fs_use_cluster in m.mb_qual^.mf_desc.m_fetch_state )
THEN
    BEGIN
    _ok := true;
    IF (m.mb_trns^.trClusterIOPtr_gg00 = NIL)
    THEN
        BEGIN
        _available := 0;
        vnewbuf (bd999GetDataIOBlockCount, _available, m.mb_trns^.trClusterIOPtr_gg00, _ok);
        IF _ok 
        THEN
            m.mb_trns^.trClusterIOSize_gg00 := bd999GetDataIOBlockCount * bd999GetPageSize;
        END;
    IF  _ok 
    THEN 
        BEGIN
        _sel.sfp_cluster_info.clust_pIOBuffer_gg00        := m.mb_trns^.trClusterIOPtr_gg00;
        _sel.sfp_cluster_info.clust_BufferSize_gg00       := m.mb_trns^.trClusterIOSize_gg00;
        _sel.sfp_cluster_info.clust_bDoClusteredRead_gg00 := true;
        END;
    END;
&ifdef TRACE
t01int4 (kb, 'clusterIO k7', ord(_sel.sfp_cluster_info.clust_bDoClusteredRead_gg00));
&endif
_sel.sfp_resrec_maxlen  := m.mb_qual^.mf_desc.m_leng;
(* PTS 1000801 E.Z. *)
_sel.sfp_act_cntresult  := m.mb_qual^.mf_desc.m_rescnt + 1;
(* PTS 1112079 E.Z. *)
_sel.sfp_check_for_result := false;
_m_ftr_help.file_id     := m.mb_qual^.mf_desc.m_fns1;
(* prevent from checking count of treeleafnodes *)
(* when fetching a virtual result set  *)
_m_ftr_help.file_id.fileLeafNodes_gg00 := cgg_nil_leafnodes;
(* m_startkeys.reckey -> _searchkeys.reckey *)
_searchkeys.reckey.len := m.mb_qual^.mf_desc.m_startkeys.reckey.len;
SAPDB_PascalMove ('VKB75 ',   2,    
      sizeof( m.mb_qual^.mf_desc.m_startkeys.reckey.k ),
      sizeof( _searchkeys.reckey.k ),
      @m.mb_qual^.mf_desc.m_startkeys.reckey.k, 1,
      @_searchkeys.reckey.k, 1, _searchkeys.reckey.len,
      m.mb_trns^.trError_gg00);
IF  ( fs_use_inv in m.mb_qual^.mf_desc.m_fetch_state )
THEN
    BEGIN
    (* m_startkeys.listkey -> _searchkeys.listkey *)
    _searchkeys.listkey.len := m.mb_qual^.mf_desc.m_startkeys.listkey.len;
    SAPDB_PascalMove ('VKB75 ',   3,    
          sizeof( m.mb_qual^.mf_desc.m_startkeys.listkey.k ),
          sizeof( _searchkeys.listkey.k ),
          @m.mb_qual^.mf_desc.m_startkeys.listkey.k, 1,
          @_searchkeys.listkey.k, 1, _searchkeys.listkey.len,
          m.mb_trns^.trError_gg00);
    _istop := [  ];
    IF  ( _sel.sfp_bd_mess2_type in [ mm_first, mm_next ] )
    THEN
        BEGIN
        IF  ( m.mb_qual^.mf_desc.m_start.len > 0 )
        THEN
            _istop := _istop + [ primary_start ];
        (*ENDIF*) 
        IF  ( m.mb_qual^.mf_desc.m_stopkeys.reckey.k[ 1 ] <> chr( 255 ))
        THEN
            _istop := _istop + [ primary_stop ];
        (*ENDIF*) 
        IF  ( m.mb_qual^.mf_desc.m_stopkeys.listkey.k[ 1 ] <> chr( 255 ))
        THEN
            _istop := _istop + [ secondary_stop ]
        ELSE
            IF  (( m.mb_qual^.mf_desc.m_stopkeys.listkey.len > 1 ) AND
                ( m.mb_qual^.mf_desc.m_stopkeys.listkey.k[ 2 ] <> chr( 255 )))
            THEN
                _istop := _istop + [ secondary_stop ]
            (*ENDIF*) 
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  ( m.mb_qual^.mf_desc.m_start.k[ 1 ] <> chr( 255 ))
        THEN
            _istop := _istop + [ primary_start ];
        (*ENDIF*) 
        IF  m.mb_qual^.mf_desc.m_stopkeys.reckey.len > 0
        THEN
            _istop := _istop + [ primary_stop ];
        (*ENDIF*) 
        IF  ( m.mb_qual^.mf_desc.m_stopkeys.listkey.len > 0 )
        THEN
            _istop := _istop + [ secondary_stop ]
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    _m_ftr_help.inv_id := m.mb_qual^.mf_desc.m_fns2;
    (* check for index strategies root of primary file      *)
    (* to prevent structure mismatch between secondary file *)
    (* and primary file                                     *)
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        b01vstate_fileversion( m.mb_trns^, _m_ftr_help.file_id );
    (*ENDIF*) 
    END;
(*ENDIF*) 
m.mb_data_len := 0;
_sel.sfp_m_result_addr := @m.mb_data^.mbp_buf;
_sel.sfp_m_result_size := m.mb_data_size;
k720_maxresult_get( m.mb_qual^.mf_desc.m_rowno, _rowno );
(* adjust m_cnt according to wanted result count (ROWNO)*)
IF  (( m.mb_trns^.trError_gg00 = e_ok ) AND
    (( _rowno > 0 ) AND ( _rowno <> csp_maxint4 )))
THEN
    BEGIN
    (* calculate remaining records *)
    IF  (( m.mb_qual^.mf_desc.m_rescnt = 0 ) OR
        (* 1. recrord didn't already counted in m_rescnt *)
        ( m.mb_type2 = mm_next ))
    THEN
        _tmp_cnt := _rowno - m.mb_qual^.mf_desc.m_rescnt
    ELSE
        _tmp_cnt := _rowno - m.mb_qual^.mf_desc.m_rescnt + 1;
    (*ENDIF*) 
&   ifdef trace
    t01int4 (kb, '_tmp_cnt    ', _tmp_cnt );
&   endif
    IF  (( m.mb_type2 in [ mm_next, mm_first, mm_direct ] ) AND
        (* try to step foreward *)
        ( m.mb_qual^.mf_desc.m_cnt > _tmp_cnt ))
    THEN
        BEGIN
        IF  ( _tmp_cnt > 0 )  (* h.b. PTS 1001537 *)
        THEN
            m.mb_qual^.mf_desc.m_cnt := _tmp_cnt
        ELSE
            BEGIN
&           ifdef trace
            t01name(kb, '_rowno-m_recnt <=0' );
&           endif
            (* _rowno - m_rescnt should be at most 0 *)
            IF  (m.mb_type2 in [ mm_next, mm_first ])
            THEN
                BEGIN
&               ifdef trace
                t01name(kb, 'set no_next_record' );
&               endif
                m.mb_trns^.trError_gg00 := e_no_next_record;
                m.mb_qual^.mf_desc.m_cnt:= 0;
                _sel.sfp_m_result_cnt   := 0;
                END
            ELSE
                BEGIN
                (* do nothing !! *)
                (* mm_direct (within result set!) and mm_last_rowno *)
                (* should get last record                           *)
                (* mm_prev move backward and should get records     *)
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
&ifdef TRACE
(*ENDIF*) 
t01int4 (kb, 'mb_data_size', m.mb_data_size);
t01int4 (kb, 'rowno       ', _rowno);
t01int4 (kb, 'm_cnt       ', m.mb_qual^.mf_desc.m_cnt);
t01int4 (kb, 'outp offset ', _sel.sfp_output_offset);
t01int4 (kb, 'mb_datasize ', m.mb_data_size);
&endif
IF  ( NOT ( m.mb_qual^.mf_desc.m_dist_optim in
    [ NO_DISTINCT_OPTIM_GG07, AUTO_DISTINCT_OPTIM_GG07 ] ))
THEN
    BEGIN
    kb75distinct_fetch( m, _sel, _searchkeys, _istop,
          _aux_stack_desc, _m_ftr_help );
    END
ELSE
    (* no distinct optimization *)
    BEGIN
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        _sel.sfp_m_result_cnt     := m.mb_qual^.mf_desc.m_cnt;
        _sel.sfp_m_firstkeys_addr := @m.mb_qual^.mf_desc.m_firstkeys;
        IF  ( fs_use_inv in m.mb_qual^.mf_desc.m_fetch_state )
        THEN
            BEGIN
            (* h.b. PTS 1104210 *)
            b03select_invrec( m.mb_trns^, _m_ftr_help, _searchkeys,
                  m.mb_qual^.mf_desc.m_stopkeys, m.mb_qual^.mf_desc.m_start,
                  _istop, 0, NIL, _sel, _aux_stack_desc, _dummy_mode );
            IF  ( m.mb_type2 = mm_last_rowno ) AND ( m.mb_trns^.trError_gg00 in
                [ e_no_next_record, e_no_prev_record ] )
            THEN
                (* this code could be removed if b03select_invrec() *)
                (* if this routine returns updated startkey for     *)
                (* e_no_next_record, e_no_prev_record               *)
                BEGIN
&               ifdef trace
                t01name(kb, 'special last rowno' );
&               endif
                m.mb_trns^.trError_gg00 := e_ok;
                IF  ( fs_reverse_fetch in m.mb_qual^.mf_desc.m_fetch_state )
                THEN
                    _sel.sfp_bd_mess2_type  := mm_first
                ELSE
                    _sel.sfp_bd_mess2_type  := mm_last;
                (*ENDIF*) 
                _tmp_cnt                := _sel.sfp_m_result_cnt;
                _sel.sfp_m_result_cnt   := 1;
                _tmpkeys                := m.mb_qual^.mf_desc.m_stopkeys;
                b03select_invrec( m.mb_trns^, _m_ftr_help, _tmpkeys,
                      _searchkeys, m.mb_qual^.mf_desc.m_start,
                      _istop, 0, NIL, _sel, _aux_stack_desc, _dummy_mode );
                _searchkeys           := _tmpkeys;
                _sel.sfp_m_result_cnt := _tmp_cnt;
                END;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            IF  ( _sel.sfp_bd_inv_only = inv_and_primary )
            THEN
                _sel.sfp_bd_inv_only := primary_only;
            (*ENDIF*) 
            b02kb_select_rec( m.mb_trns^, _m_ftr_help.file_id,
                  _searchkeys.reckey.keyVal_gg00,
                  _searchkeys.reckey.keyLen_gg00,
                  m.mb_qual^.mf_desc.m_stopkeys.reckey.keyVal_gg00,
                  m.mb_qual^.mf_desc.m_stopkeys.reckey.keyLen_gg00,
                  0, NIL,  NOT c_ignore_vwait, _sel,
                  _aux_stack_desc, _unqualified, _dummy_mode );
            IF  (m.mb_type2 = mm_last_rowno) AND
                (m.mb_trns^.trError_gg00 in [ e_no_next_record, e_no_prev_record ])
            THEN
                BEGIN
&               ifdef trace
                t01name(kb, 'special last rowno' );
&               endif
                m.mb_trns^.trError_gg00 := e_ok;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
&       ifdef trace
        IF  ( fs_use_inv in m.mb_qual^.mf_desc.m_fetch_state )
        THEN
            t01key(kb, '_searchkey l', _searchkeys.listkey);
        (*ENDIF*) 
        t01key(kb, '_searchkey r', _searchkeys.reckey);
&       endif
        IF  ( m.mb_trns^.trError_gg00 in
            [ e_no_prev_record, e_no_next_invkey, e_no_prev_invkey ] )
        THEN
            m.mb_trns^.trError_gg00 := e_no_next_record;
        (*ENDIF*) 
        IF  ( m.mb_trns^.trError_gg00 = e_ok )
        THEN
            BEGIN
            (* update m_startkeys.reckey *)
            m.mb_qual^.mf_desc.m_startkeys.reckey.len := _searchkeys.reckey.len;
            SAPDB_PascalMove ('VKB75 ',   4,    
                  sizeof(_searchkeys.reckey.k),
                  sizeof(m.mb_qual^.mf_desc.m_startkeys.reckey.k),
                  @_searchkeys.reckey.k, 1,
                  @m.mb_qual^.mf_desc.m_startkeys.reckey.k, 1,
                  m.mb_qual^.mf_desc.m_startkeys.reckey.len,
                  m.mb_trns^.trError_gg00);
            IF  ( fs_use_inv in m.mb_qual^.mf_desc.m_fetch_state ) AND
                ( warn14_next_invlist in m.mb_trns^.trWarning_gg00 )
            THEN
                BEGIN
                m.mb_trns^.trWarning_gg00 := m.mb_trns^.trWarning_gg00 -
                      [ warn14_next_invlist ];
                IF  ( m.mb_trns^.trWarning_gg00 = [ warn0_exist ] )
                THEN
                    m.mb_trns^.trWarning_gg00 := [  ];
                (*ENDIF*) 
                ;
                (* update m_startkeys.listkey if we have new listkey *)
                m.mb_qual^.mf_desc.m_startkeys.listkey.len := _searchkeys.listkey.len;
                SAPDB_PascalMove ('VKB75 ',   5,    
                      sizeof( _searchkeys.listkey.k ),
                      sizeof( m.mb_qual^.mf_desc.m_startkeys.listkey.k ),
                      @_searchkeys.listkey.k, 1,
                      @m.mb_qual^.mf_desc.m_startkeys.listkey.k, 1,
                      m.mb_qual^.mf_desc.m_startkeys.listkey.len,
                      m.mb_trns^.trError_gg00);
                END
            (*ENDIF*) 
            END;
        (* PTS 1105717 E.Z. *)
        (*ENDIF*) 
        IF  ( fs_use_recs in m.mb_qual^.mf_desc.m_fetch_state )
        THEN
            m.mb_data_len := _sel.sfp_m_result_len;
        (*ENDIF*) 
        END;
    (* PTS 1103481 E.Z. *)
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
IF  ( m.mb_trns^.trError_gg00 = e_no_next_record )
THEN
    BEGIN
    (* close fetch window between prevkey-nextkey *)
    IF  ( _work_mtype in [ mm_first, mm_next ] ) AND
        ( m.mb_qual^.mf_desc.m_stopkeys.reckey.len > 1 )
    THEN
        g04smallest_greater_key( m.mb_qual^.mtree, m.mb_qual^.mf_desc.m_stopkeys.reckey );
    (*ENDIF*) 
    ;
&   ifdef trace
    t01name(kb, 'm_stop -> m_start ' );
&   endif
    m.mb_qual^.mf_desc.m_startkeys.reckey.len := m.mb_qual^.mf_desc.m_stopkeys.reckey.len;
    SAPDB_PascalMove ('VKB75 ',   6,    
          sizeof( m.mb_qual^.mf_desc.m_stopkeys.reckey.k ),
          sizeof( m.mb_qual^.mf_desc.m_startkeys.reckey.k ),
          @m.mb_qual^.mf_desc.m_stopkeys.reckey.k, 1,
          @m.mb_qual^.mf_desc.m_startkeys.reckey.k, 1,
          m.mb_qual^.mf_desc.m_startkeys.reckey.len,
          m.mb_trns^.trError_gg00);
    IF  ( fs_use_inv in m.mb_qual^.mf_desc.m_fetch_state ) AND
        ( warn14_next_invlist in m.mb_trns^.trWarning_gg00 )
    THEN
        BEGIN
        m.mb_trns^.trWarning_gg00 := m.mb_trns^.trWarning_gg00 -
              [ warn14_next_invlist ];
        IF  ( m.mb_trns^.trWarning_gg00 = [ warn0_exist ] )
        THEN
            m.mb_trns^.trWarning_gg00 := [  ];
        (*ENDIF*) 
        m.mb_qual^.mf_desc.m_startkeys.listkey.len :=
              m.mb_qual^.mf_desc.m_stopkeys.listkey.len;
        SAPDB_PascalMove ('VKB75 ',   7,    
              sizeof( m.mb_qual^.mf_desc.m_stopkeys.listkey.k ),
              sizeof( m.mb_qual^.mf_desc.m_startkeys.listkey.k ),
              @m.mb_qual^.mf_desc.m_stopkeys.listkey.k, 1,
              @m.mb_qual^.mf_desc.m_startkeys.listkey.k, 1,
              m.mb_qual^.mf_desc.m_startkeys.listkey.len,
              m.mb_trns^.trError_gg00);
        END
    (*ENDIF*) 
    END;
(*ENDIF*) 
m.mb_data_size := _ori_data_size;
IF  ( fs_use_inv in m.mb_qual^.mf_desc.m_fetch_state ) AND
    ( _sel.sfp_m_result_cnt > 0 )
THEN
    IF  ( warn14_next_invlist in m.mb_trns^.trWarning_gg00 )
    THEN
        BEGIN
        m.mb_trns^.trWarning_gg00 := m.mb_trns^.trWarning_gg00 -
              [ warn14_next_invlist ];
        IF  ( m.mb_trns^.trWarning_gg00 = [ warn0_exist ] )
        THEN
            m.mb_trns^.trWarning_gg00 := [  ]
        (*ENDIF*) 
        END;
    (*ENDIF*) 
(*ENDIF*) 
m.mb_qual^.mf_desc.m_searched_pages := m.mb_trns^.trRteCommPtr_gg00^.file_record_cnt;
IF  (( m.mb_trns^.trError_gg00 = e_ok )
    OR
    (( m.mb_trns^.trError_gg00 = e_no_next_record )
    AND
    ( NOT ( fs_single in m.mb_qual^.mf_desc.m_fetch_state ))
    AND
    ( fs_use_recs in m.mb_qual^.mf_desc.m_fetch_state )))
THEN
    BEGIN
    IF  ( _sel.sfp_m_result_cnt = 0 )
    THEN
        m.mb_qual^.mf_desc.m_firstkeys := m.mb_qual^.mf_desc.m_startkeys;
    (*ENDIF*) 
    m.mb_trns^.trError_gg00 := e_ok;
    m.mb_qual^.mf_desc.m_cnt:= _sel.sfp_m_result_cnt;
    m.mb_struct       := mbs_result;
    m.mb_type         := m_return_result;
    m.mb_type2        := mm_nil;
    END
ELSE
    (* PTS 1002020 E.Z. *)
    IF  ( _sel.sfp_m_result_cnt = ( m.mb_qual^.mf_desc.m_cnt - 1 )) AND
        (* positioning for FETCH POS ? *)
        ( NOT ( fs_use_recs in m.mb_qual^.mf_desc.m_fetch_state ) ) AND
        ( NOT ( fs_single in m.mb_qual^.mf_desc.m_fetch_state )) AND
        ( _sel.sfp_bd_mess2_type = mm_prev )
    THEN
        BEGIN
        (* prev to go one BEFORE the first needed row *)
        (* in case of fetch pos, fetch relative (<0)  *)
        m.mb_trns^.trError_gg00 := e_no_prev_record;
        END
    ELSE
        BEGIN
        m.mb_type      := m_return_error;
        m.mb_type2     := mm_nil;
        m.mb_data_len  := 0;
        m.mb_qual_len  := MB_PART1_HEAD_MXGG00 + 4
              (*sizeof(m.mb_qual^.m_searched_pages) *)
        END;
    (*ENDIF*) 
(*ENDIF*) 
(* PTS 1001518 E.Z. *)
IF  ( _start_sec > 0 )
THEN
    BEGIN
    k720monitor( m.mb_trns^, _sel, _start_sec,
          _start_microsec, _start_phys_ios, _start_suspends,
          _start_waits, c_not_put_strat,
          m.mb_qual^.mf_desc.m_strat_info, c_not_strat_cnt );
    END;
(*ENDIF*) 
;
&ifdef trace
t01fetch_desc(kb, 'fetch desc 2', m.mb_qual^.mf_desc);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb75distinct_fetch(
            VAR m               : tgg00_MessBlock;
            VAR sel             : tgg00_SelectFieldsParam;
            VAR searchkeys      : tgg00_TwoKeys;
            VAR istop           : tgg00_BdInvSet;
            VAR aux_stack_desc  : tgg00_StackDesc;
            VAR m_ftr_help      : tgg00_TwoFileIds);
 
CONST
      c_ignore_vwait  = true;
 
VAR
      _mfetch_cnt     : tsp00_Int4;
      _dummy_mode     : tgg00_LockReqMode;
      _fill_key       : ^tsp00_Key;
      _loopmtype      : tgg00_MessType2;
      _fill_char      : char;
      _key_fill_char  : char;
      _unqualified    : boolean;
 
BEGIN
&ifdef trace
t01mess2type( kb, 'bd mess2 typ', sel.sfp_bd_mess2_type );
&endif
CASE sel.sfp_bd_mess2_type OF
    mm_first,
    mm_next :
        _loopmtype := mm_next;
    mm_last,
    mm_prev :
        _loopmtype := mm_prev;
    OTHERWISE
        BEGIN
        _loopmtype := sel.sfp_bd_mess2_type;
        END;
    END;
(*ENDCASE*) 
IF  ( sel.sfp_bd_mess2_type in [ mm_first, mm_next ] )
THEN
    BEGIN
    _fill_key      := @b01fullkey;
    _fill_char     := chr( 255 );
    _key_fill_char := chr( 255 );
    END
ELSE
    BEGIN
    _fill_char := chr (0);
    IF  g01ConsistentReadEnabled
    THEN (* no reverse iteration of inv list supported *)
        BEGIN
        _fill_key      := @b01fullkey;
        _key_fill_char := chr (255)
        END
    ELSE
        BEGIN
        _fill_key      := @b01zerokey;
        _key_fill_char := chr (0);
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
_mfetch_cnt := 0;
WHILE (( m.mb_trns^.trError_gg00 = e_ok ) AND
      ( _mfetch_cnt < m.mb_qual^.mf_desc.m_cnt )) DO
    BEGIN
    (* foreach loop get one record        *)
    (* first access with mm_first/last !! *)
    IF  ( sel.sfp_bd_mess2_type in [ mm_next, mm_prev ] )
    THEN
        (* foreach loop adjust invkey/primkey startkey *)
        BEGIN
        IF  ( m.mb_qual^.mf_desc.m_dist_optim < KEYSEQLEN_OFFSET_GG07 )
        THEN
            (* part of index in output columns *)
            BEGIN
            IF  ( fs_use_inv in m.mb_qual^.mf_desc.m_fetch_state )
            THEN
                BEGIN
                searchkeys.reckey.len := PERM_KEY_MXSP00;
                searchkeys.reckey.k   := _fill_key^;
                IF  ( m.mb_qual^.mf_desc.m_dist_optim <> INV_DISTINCT_OPTIM_GG07 ) AND
                    ( searchkeys.listkey.len - m.mb_qual^.mf_desc.m_dist_optim > 0 )
                THEN
                    (* not complete index columns in output columns *)
                    SAPDB_PascalFill ('VKB75 ',   8,    
                          sizeof( searchkeys.listkey.k ),
                          @searchkeys.listkey.k,
                          m.mb_qual^.mf_desc.m_dist_optim + 1,
                          searchkeys.listkey.len -
                          m.mb_qual^.mf_desc.m_dist_optim,
                          _fill_char, m.mb_trns^.trError_gg00);
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                IF  ( searchkeys.reckey.len - m.mb_qual^.mf_desc.m_dist_optim > 0 )
                THEN
                    (* not complete key columns in output columns *)
                    SAPDB_PascalFill ('VKB75 ',   9,    
                          sizeof( searchkeys.reckey.k ),
                          @searchkeys.reckey.k,
                          m.mb_qual^.mf_desc.m_dist_optim + 1,
                          searchkeys.reckey.len -
                          m.mb_qual^.mf_desc.m_dist_optim,
                          _key_fill_char, m.mb_trns^.trError_gg00);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END
        ELSE
            (* all columns of index and start sequence of   *)
            (* key columns in output                        *)
            IF  (( m.mb_qual^.mf_desc.m_dist_optim - KEYSEQLEN_OFFSET_GG07 )
                < searchkeys.reckey.len )
            THEN
                BEGIN
&               ifdef trace
                t01name(kb, 'fill searchkey  r ' );
&               endif
                SAPDB_PascalFill ('VKB75 ',  10,    
                      sizeof( searchkeys.reckey.k ),
                      @searchkeys.reckey.k,
                      m.mb_qual^.mf_desc.m_dist_optim -
                      KEYSEQLEN_OFFSET_GG07 + 1,
                      searchkeys.reckey.len -
                      ( m.mb_qual^.mf_desc.m_dist_optim - KEYSEQLEN_OFFSET_GG07 ),
                      _key_fill_char, m.mb_trns^.trError_gg00);
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        REPEAT
            IF  ( fs_use_inv in m.mb_qual^.mf_desc.m_fetch_state )
            THEN
                (* h.b. PTS 1104210 *)
                b03select_invrec( m.mb_trns^, m_ftr_help, searchkeys,
                      m.mb_qual^.mf_desc.m_stopkeys,
                      m.mb_qual^.mf_desc.m_start, istop, 0, NIL, sel,
                      aux_stack_desc, _dummy_mode )
            ELSE
                b02kb_select_rec( m.mb_trns^, m_ftr_help.file_id,
                      searchkeys.reckey.k,
                      searchkeys.reckey.len,
                      m.mb_qual^.mf_desc.m_stopkeys.reckey.k,
                      m.mb_qual^.mf_desc.m_stopkeys.reckey.len,
                      0, NIL,  NOT c_ignore_vwait, sel,
                      aux_stack_desc, _unqualified, _dummy_mode );
            (*ENDIF*) 
&           ifdef trace
            t01basis_error( kb, 'bd return   ', m.mb_trns^.trError_gg00 );
            IF  ( fs_use_inv in m.mb_qual^.mf_desc.m_fetch_state )
            THEN
                t01key(kb, 'searchkey  l', searchkeys.listkey);
            (*ENDIF*) 
            t01key(kb, 'searchkey  r', searchkeys.reckey);
&           endif
        UNTIL
            m.mb_trns^.trError_gg00 <> e_key_not_found;
        (*ENDREPEAT*) 
        END;
    (*ENDIF*) 
    IF  ( m.mb_trns^.trRteCommPtr_gg00^.to_cancel )
    THEN
        m.mb_trns^.trError_gg00 := e_cancelled;
    (*ENDIF*) 
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        (* searchkeys.reckey -> m_startkeys.reckey *)
        m.mb_qual^.mf_desc.m_startkeys.reckey.len := searchkeys.reckey.len;
        SAPDB_PascalMove ('VKB75 ',  11,    
              sizeof( searchkeys.reckey.k ),
              sizeof( m.mb_qual^.mf_desc.m_startkeys.reckey.k ),
              @searchkeys.reckey.k, 1,
              @m.mb_qual^.mf_desc.m_startkeys.reckey.k, 1,
              m.mb_qual^.mf_desc.m_startkeys.reckey.len,
              m.mb_trns^.trError_gg00);
        IF  ( fs_use_inv in m.mb_qual^.mf_desc.m_fetch_state ) AND
            ( warn14_next_invlist in m.mb_trns^.trWarning_gg00 )
        THEN
            BEGIN
            m.mb_trns^.trWarning_gg00 := m.mb_trns^.trWarning_gg00 -
                  [ warn14_next_invlist ];
            IF  ( m.mb_trns^.trWarning_gg00 = [ warn0_exist ] )
            THEN
                m.mb_trns^.trWarning_gg00 := [  ];
            (*ENDIF*) 
            ;
            (* searchkeys.listkey -> m_startkeys.listkey *)
            m.mb_qual^.mf_desc.m_startkeys.listkey.len :=
                  searchkeys.listkey.len;
            SAPDB_PascalMove ('VKB75 ',  12,    
                  sizeof( searchkeys.listkey.k ),
                  sizeof( m.mb_qual^.mf_desc.m_startkeys.listkey.k ),
                  @searchkeys.listkey.k, 1,
                  @m.mb_qual^.mf_desc.m_startkeys.listkey.k, 1,
                  m.mb_qual^.mf_desc.m_startkeys.listkey.len,
                  m.mb_trns^.trError_gg00);
            END;
        (*ENDIF*) 
        IF  ( fs_use_recs in m.mb_qual^.mf_desc.m_fetch_state )
        THEN
            BEGIN
            m.mb_data_len         := m.mb_data_len + m.mb_qual^.mf_desc.m_leng;
            sel.sfp_m_result_addr := @m.mb_data^.mbp_buf[m.mb_data_len + 1];
            sel.sfp_m_result_size := m.mb_data_size - m.mb_data_len;
            sel.sfp_m_result_len  := 0;
            sel.sfp_result_length := 0
            END;
        (*ENDIF*) 
        _mfetch_cnt := succ( _mfetch_cnt );
        IF  ( _mfetch_cnt = 1 )
        THEN
            m.mb_qual^.mf_desc.m_firstkeys := m.mb_qual^.mf_desc.m_startkeys;
        (*ENDIF*) 
        END
    ELSE
        IF  ( m.mb_trns^.trError_gg00 in
            [ e_inv_list_not_found, e_key_not_found,
            e_qual_violation, e_view_violation ] )
        THEN
            m.mb_trns^.trError_gg00 := e_ok;
        (*ENDIF*) 
    (*ENDIF*) 
    sel.sfp_bd_mess2_type := _loopmtype;
    END;
(*ENDWHILE*) 
sel.sfp_m_result_cnt := _mfetch_cnt;
IF  ( m.mb_type2 = mm_last_rowno ) AND
    ( m.mb_trns^.trError_gg00 in [ e_no_next_record, e_no_prev_record ] )
THEN
    BEGIN
&   ifdef trace
    t01name(kb, 'special last rowno' );
&   endif
    m.mb_trns^.trError_gg00 := e_ok;
    END;
(*ENDIF*) 
IF  ( m.mb_trns^.trError_gg00 in
    [ e_no_prev_record, e_no_next_invkey, e_no_prev_invkey ] )
THEN
    m.mb_trns^.trError_gg00 := e_no_next_record;
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
