.nf
 
 
    ========== licence begin  GPL
    Copyright (c) 2000-2004 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
*****************************************************
Copyright (c) 2000-2004 SAP AG
SAP Database Technology
 
Release :      Date : 2000-11-17
*****************************************************
modname : VKB73
changed : 2000-11-17
module  : Single_Select
 
Author  : ElkeZ
Created : 1987-09-22
*****************************************************
 
Purpose : If a result set has not to be build physically,
          search in one table if there will be a result record
 
Define  :
 
        PROCEDURE
              k73_index_range (
                    VAR m                : tgg00_MessBlock;
                    VAR getrec           : tgg07_get_param;
                    VAR selrec           : tgg07_select_param;
                    VAR selfields        : tgg00_SelectFieldsParam;
                    VAR gg_strategy      : tgg07_StrategyInfo;
                    VAR finding_possible : boolean);
 
        PROCEDURE
              k73in_multindex (
                    VAR m      : tgg00_MessBlock;
                    VAR getrec : tgg07_get_param;
                    VAR selrec : tgg07_select_param;
                    VAR sel    : tgg00_SelectFieldsParam;
                    VAR strat  : tgg07_StrategyInfo);
 
        PROCEDURE
              k73sub_multindex (
                    VAR m                : tgg00_MessBlock;
                    VAR getrec           : tgg07_get_param;
                    VAR selrec           : tgg07_select_param;
                    VAR sel              : tgg00_SelectFieldsParam;
                    VAR strat            : tgg07_StrategyInfo);
 
        PROCEDURE
              k73_seq_search (
                    VAR m            : tgg00_MessBlock;
                    VAR selrec       : tgg07_select_param;
                    VAR selfields    : tgg00_SelectFieldsParam;
                    VAR gg_strategy  : tgg07_StrategyInfo;
                    finding_possible : boolean);
 
        PROCEDURE
              k73select_invrec (
                    VAR m                   : tgg00_MessBlock;
                    VAR ftrees              : tgg00_TwoFileIds;
                    VAR start_keypair       : tgg00_TwoKeys;
                    VAR stop_keypair        : tgg00_TwoKeys;
                    VAR startkey            : tgg00_Lkey;
                    stop                    : tgg00_BdInvSet;
                    VAR b                   : tgg00_Rec;
                    VAR selfields           : tgg00_SelectFieldsParam;
                    VAR result_buf          : tsp00_Buf;
                    new_inv_not_found_error : tgg00_BasisError);
 
        PROCEDURE
              k73prim_key_build (
                    VAR selrec        : tgg07_select_param;
                    VAR prim_startkey : tgg00_Lkey;
                    VAR prim_stopkey  : tgg00_Lkey;
                    VAR istop         : tgg00_BdInvSet;
                    VAR e             : tgg00_BasisError);
 
        PROCEDURE
              k73sec_key_build (
                    VAR m                : tgg00_MessBlock;
                    VAR index_strat      : tgg07_StrInvInRange;
                    VAR sec_startkey     : tgg00_Lkey;
                    VAR sec_stopkey      : tgg00_Lkey;
                    in_stpos_hint        : tsp00_Int2;
                    in_value_idx         : tsp00_Int2;
                    VAR istop            : tgg00_BdInvSet;
                    VAR finding_possible : boolean);
 
.CM *-END-* define --------------------------------------
***********************************************************
 
Use     :
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01diag_monitor_on : boolean;
 
      ------------------------------ 
 
        FROM
              Build_Strategy : VAK70;
 
        VAR
              a70glob_inv_build_strats  : tgg07_StratEnumSet;
 
      ------------------------------ 
 
        FROM
              Build_Strategy_2 : VAK71;
 
        FUNCTION
              a71code_distinct_optim (
                    VAR gg_strategy : tgg07_StrategyInfo) : tsp00_Int2;
 
      ------------------------------ 
 
        FROM
              PUT-Conversions : VSP41;
 
        PROCEDURE
              s41p4int (
                    VAR buf : tsp00_Buf;
                    pos     : tsp00_Int4;
                    source  : tsp00_Int4;
                    VAR res : tsp00_NumError);
 
      ------------------------------ 
 
        FROM
              Single_Select : VKB720;
 
        PROCEDURE
              k720ref_statistic (
                    VAR m         : tgg00_MessBlock;
                    VAR arr_index : tgg00_RefInfoIndex;
                    VAR strat     : tgg07_StrategyInfo);
 
      ------------------------------ 
 
        FROM
              Single_Select_Part2 : VKB721;
 
        PROCEDURE
              k721inv_gets (
                    VAR m            : tgg00_MessBlock;
                    VAR ftrees       : tgg00_TwoFileIds;
                    VAR startkeys    : tgg00_TwoKeys;
                    VAR stopkeys     : tgg00_TwoKeys;
                    VAR act_key      : tgg00_Lkey;
                    istop            : tgg00_BdInvSet;
                    mtype            : tgg00_MessType2;
                    VAR getrec       : tgg07_get_param;
                    VAR selrec       : tgg07_select_param;
                    VAR sel          : tgg00_SelectFieldsParam);
 
        PROCEDURE
              k721function_add (
                    VAR m      : tgg00_MessBlock;
                    VAR selrec : tgg07_select_param;
                    aggr       : boolean);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01fullkey    : tsp00_Key;
              b01niltree_id : tgg00_FileId;
 
        PROCEDURE
              b01tcreate_file (
                    VAR t       : tgg00_TransContext;
                    VAR current : tgg00_FileId);
 
        PROCEDURE
              b01destroy_file (
                    VAR t       : tgg00_TransContext;
                    VAR current : 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
              bd03AggrFuncOnIndex (
                    VAR t               : tgg00_TransContext;
                    VAR file_id         : tgg00_FileId;
                    VAR aux_file_id     : tgg00_FileId;
                    VAR start_keys      : tgg00_TwoKeys;
                    VAR stop_keys       : tgg00_TwoKeys;
                    VAR inv_field_descr : tgg00_AggrDescrRec;
                    VAR sel             : tgg00_SelectFieldsParam;
                    VAR stack_desc      : tgg00_StackDesc;
                    VAR aux_buf         : tsp00_Buf;
                    VAR result_buf      : tsp00_Buf;
                    only_one_list       : boolean;
                    bWarnOfNullValues   : boolean);
 
        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 stop         : tgg00_BdInvSet;
                    recbuf_size      : tsp00_Int4;
                    recbuf_ptr       : tsp00_MoveObjPtr;
                    VAR sel          : tgg00_SelectFieldsParam;
                    VAR stack_desc   : tgg00_StackDesc;
                    VAR granted_lock : tgg00_LockReqMode;
                    count_usage      : boolean);
 
        PROCEDURE
              b03MergeInvLists  (
                    VAR t          : tgg00_TransContext;
                    VAR file_id    : tgg00_FileId;
                    VAR f_id_dest  : tgg00_FileId;
                    VAR start_keys : tgg00_TwoKeys;
                    VAR stop_keys  : tgg00_TwoKeys;
                    prim_stop      : boolean;
                    count_only     : boolean;
                    VAR count      : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              task_temp_data_cache : VBD21;
 
        PROCEDURE
              b21mp_root_put (
                    temp_cache_ptr : tgg00_TempDataCachePtr;
                    root : tsp00_PageNo);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        FUNCTION
              g01GetSessionAuxCounter (
                    VAR t : tgg00_TransContext) : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              Select_Help_Procedures : VGG04;
 
        PROCEDURE
              g04limitinvkeys (
                    VAR m           : tgg00_MessBlock;
                    VAR inv_strat   : tgg07_StrInvInRange;
                    VAR startkey    : tgg00_Lkey;
                    VAR stopkey     : tgg00_Lkey;
                    in_stpos_hint   : tsp00_Int2;
                    in_value_idx    : tsp00_Int2);
 
        PROCEDURE
              gg04one_subq_limitinvkey (
                    VAR mblock      : tgg00_MessBlock;
                    VAR subq_buf    : tgg00_Rec;
                    VAR inv_strat   : tgg07_StrInvInRange;
                    VAR one_key     : tgg00_Lkey;
                    is_startkey     : boolean);
 
        PROCEDURE
              g04build_temp_tree_id (
                    VAR temp_tree : tgg00_FileId;
                    VAR t         : tgg00_TransContext);
 
        PROCEDURE
              g04read_subquery (
                    VAR trns        : tgg00_TransContext;
                    VAR result      : tgg00_Rec;
                    VAR subqtree_id : tgg00_FileId;
                    VAR m_key       : tgg00_Lkey;
                    VAR aux_error   : tgg00_BasisError;
                    VAR ok          : boolean);
 
        PROCEDURE
              g04index_tree_build (
                    VAR file_id    : tgg00_FileId;
                    VAR index_tree : tgg00_FileId;
                    index_no       : tsp00_Int2);
 
        PROCEDURE
              g04smallest_greater_key(
                    VAR key     : tgg00_Lkey );
 
        PROCEDURE
              g04greatest_smaller_key(
                    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);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-30 : VSP30;
 
        PROCEDURE
              s30cmp (
                    VAR buf1     : tsp00_Key;
                    fieldpos1    : tsp00_Int4;
                    fieldlength1 : tsp00_Int4;
                    VAR buf2     : tsp00_Key;
                    fieldpos2    : tsp00_Int4;
                    fieldlength2 : tsp00_Int4;
                    VAR l_result : tsp00_LcompResult);
&       IFDEF TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01mess2type (
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    mess2_type    : tgg00_MessType2);
 
        PROCEDURE
              t01c32 (
                    debug : tgg00_Debug;
                    msg   : tsp00_C32);
 
        PROCEDURE
              t01name (
                    debug : tgg00_Debug;
                    nam   : tsp00_Name);
 
        PROCEDURE
              t01sname (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname);
 
        PROCEDURE
              t01stackentry (
                    debug          : tgg00_Debug;
                    VAR st         : tgg00_StackEntry;
                    entry_index    : integer);
 
        PROCEDURE
              t01basis_error (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname;
                    b_err : tgg00_BasisError);
 
        PROCEDURE
              t01key (
                    debug   : tgg00_Debug;
                    nam     : tsp00_Sname;
                    VAR k   : tgg00_Lkey);
 
        PROCEDURE
              t01bool (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    curr_bool: boolean);
 
        PROCEDURE
              t01int4 (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01buf (
                    debug    : tgg00_Debug;
                    VAR buf  : tsp00_Buf;
                    startpos : integer;
                    endpos   : integer);
&       ENDIF
 
.CM *-END-* use -----------------------------------------
***********************************************************
 
Synonym :
 
        PROCEDURE
              s30cmp;
 
              tsp00_MoveObj tsp00_Key
 
        PROCEDURE
              s41p4int;
 
              tsp00_MoveObj tsp00_Buf
 
.CM *-END-* synonym -------------------------------------
***********************************************************
 
Specification:
 
All procedures (except K73_SINTER_SECTE) follow a specific strategy
(via inversions, if appropriate) in order to check whether
any result exists and to identify its position (primary key and
secondary key).  The actual search for results and their
delivery to the user does not occur until a FETCH.
Initialization of the strategy (strat) and of the other parameters
was performed in VKB720 (K720_SELECT).
Finding_possible indicates whether a result can exist or
whether, based on the 'between' upper and lower limits, a result
could not possibly exist.
In any case, appropriate positions are then specified.
The strategies are as follows:
 
K73_MULTINV
------------------------------------------
 
for all fields or for the first n fields of a named index,
'range' or '=' conditions have been specified.
 
K73_BETWEEN_INVLIST
------------------------------------------
 
for a singly inverted field, upper and/or lower limits have been
specified.  This procedure is also called if the result should be
built (build_result).  Most of the preparations before the search
are the same in both cases.
 
K73_IN_INVLIST
------------------------------------------
 
for a singly inverted field, an '=' condition has been specified.
 
K73_INTERSECTINV
------------------------------------------
 
For more than one singly inverted field, an '=' condition
condition has been specified for each.
 
K73_SEQ_SEARCH
------------------------------------------
 
no inversion can be used for a faster search.
 
.CM *-END-* specification -------------------------------
***********************************************************
 
Description:
 
K73_MULTINV
------------------------------------------
 
The secondary keys of the named inversion
(keypair.listkey, stopkeys.listkey) are formed in G04_MINDEX_KEY.
Startkey and stopkey are the primary-key limits already
assigned in VKB72.  They are entered in keypair.reckey
(keypair contains
the lower limit of the primary and secondary key) or stopkeys.reckey
(stopkey contains the upper limits).
Istop indicates whether there are relevant
limits for the primary key (<> binary null and <> NULL).  There is
always an upper limit present for the secondary key (secondary_stop).
Istop tells a BD procedure which limits must be taken into
account.
The upper limit of the secondary key is the same as the
lower limit (keypair.listkey) if an '=' condition exists for all
fields of the index.  If this is not the case (siir_equals= 0), the
stop key must be filled with h'FF'.  This already occurs in
G04_MINDEX_KEY.
If any record can be found, this is attempted via B03_SELECT_INVREC.
This procedure processes only the inversion lists within the specified
limits and examines only those records with primary keys within the
values described, if such values have been given.
If a record is found that fulfills the necessary qualifications,
its secondary key and primary key are found in keypair.
Invkey contains the non-updated start inversion value.
Via FILL_RESULT, its positions are sent back to the AK layer.
 
K73_BETWEEN_INVLIST
------------------------------------------
 
A file name is formed that must be absolutely unambiguous since it
exists over a longer period of time.  Several files generated via
K73_BETWEEN_INVLIST can exist simultaneously.
As in K73_MULTINV, the primary startkeys and stopkeys are assigned
in 'keypair' or 'stopkeys' and 'istop'.
In G04_BETWEEN_KEYS, the secondary keys [ listkey)
are assigned; for descending indexes (op_order_desc, op_unique_desc)
the key value is reversed.  Keypair always contains the lower limit,
even in the case of a descending index (for a descending index,
keypair.listkey and stopkeys.listkey are exchanged).
It is determined whether an inversion upper limit exists (in
the case of descending, this is the lower limit specified by the user)
and the result is indicated in istop and use_stopkey.
The temporary file is generated.  Via B03MERGE_INV, an inversion
list (invkey) is formed that contains all primary keys (within
the specified limits) for all the inversion lists within the
inversion limits (in ascending order).  During the rest of the
process, only the new inversion list is viewed.
This list ensures that records located in a primary page are
processed one after another when the page is still in the system buffer.
If the original inversion list were to be processed, the same
page might have to be addressed several times, which would lead to
additional I/O operations if the page had already been displaced from
the system buffer.  The overhead due to merging is small by comparison.
Build_result is used to decide whether or not the result set should
be built.  If yes, the new inversion list is processed via
K72_SEARCH_THROUGH_ONE_INVLIST if there is a chance that a result
exists.  The primary stopkey entry is destroyed beforehand; it would
only lead to unnecessary comparisons since conformity to the stopkey
condition is already ensured by the merge.
The temporary file is destroyed.
If the result set is not supposed to be built, the inversion
limits are set to the value of invkey and the primary-key limits are
destroyed (see above).  A search is run for the first record in the
new inversion list that fulfills the conditions and, if it is
present, its position is indicated.  The temporary inversion file must,
of course, remain so that the other primary keys can be searched out.
 
K73_IN_INVLIST
------------------------------------------
 
The inversion file name is formed; the external field number of the
inverted field (ecol_tab[ 1 ]) serves to distinguish between the
inversions of a table.
The primary startkeys and stopkeys and istop are assigned as in
K73_MULTINV (see that section).
The secondary startkey and (since it involves an '=' condition)
the identically appearing stopkey are entered in listkey and also in
invkey.  If a desc index is involved, the inversion value is
reversed; NULL values always have the length 1 (value h'00'). Other
values are stored in
the maximum length for this field (ecol_tab[ 2 ])
in order to maintain the correct sequence.
If any record can be found, this is attempted
via B03_SELECT_INVREC.  This procedure examines only the one relevant
inversion list and, within this list, only the primary keys that
are within the specified limits.
If a record is found that fulfills the necessary qualifications,
its secondary key and primary key are found in keypair.
The positions are sent back to AK via FILL_RESULT.
 
K73_INTERSECTINV
------------------------------------------
 
More than one singly inverted field is qualified by '=' conditions.
The intersection is formed in K73_SINTER_SECTE from the associated
inversion lists, i.e. a new inversion list is generated in the temporary
file invfn, which contains only primary keys that are contained in all
the inversion lists viewed and, therefore, whose records already fulfill
the '=' conditions.  Primary-key conditions
are taken into account for intersecting as they were for merging.
The secondary key (invkey) is copied to listkey.
Only this new list is viewed. The primary startkeys and stopkeys
are irrelevant, since they were already taken into account for
the intersecting operation.
If any record can be found, this is attempted
via B03_SELECT_INVREC.  This procedure examines only the one relevant
inversion list and, within this list, only the primary keys that
are within the specified limits.
If a record is found that fulfills the necessary qualifications,
its secondary key and primary key are found in keypair.
The positions are sent back to AK via FILL_RESULT.
 
K73_SEQ_SEARCH
------------------------------------------
 
A search is done, not via inversions but directly in the
primary file (fn) within the primary-key limits (startkey
and stopkey assigned in VKB72).
The mess_buffer is edited for the result.  Part1 contains
the resultcount -1, i.e. 'unknown', if a result was found; otherwise
it contains 0.
Key-value lengths of 2 bytes each and the key itself (with its
current length) are stored in part2.  These are:
 primary startkey
 primary key at which the record was found
 primary stopkey
 secondary startkey
 secondary value at which the record was found
 secondary stopkey
 
Primary file name and the inversion file name follow.
 
The primary startkey and the current primary key are always the
same for a sequential search and the data for inversions are
superfluous (key length 0, empty inversion file name).
 
The primary startkey is changed slightly.  Since the search for the
next
record (starting from the current key) is carried out during
'fetch', the last value before the current one must be transferred to
AK so that the first record is not overlooked during the 'fetch'.
 
K73_SINTER_SECTE
------------------------------------------
 
In this procedure, the intersection is formed from several inversion
lists each, with differing inversions.
In a temporary file, an inversion list is formed
that holds only primary keys that are contained in all inversions.
Invfields[ 1..cntfields ] contains the positions of field stack
entries.  These belong to the '=' conditions specified by the user.
The values are described in the next stack entry in each case.  All
identified fields are singly inverted.
In B03INTERSECT_INV, only 2 inversion lists can be intersected
at any one time. For this reason, the result of the current intersection
is always processed along with a new inversion list.
Hinvfn1/hinfkey1 always contains information on the result of
the current intersection; hinvfn1/hinvkey2 contains information on
the new inversion list being added.
In the beginning hinvfn1/hinvkey1 contains information on an
inversion list identified by the user.  In the case of a desc index,
the inversion value is reversed; NULL values always have the length
1 (value h'00'). Other values are stored with the maximum length
for this field (ecol_tab[ 2 ]) because, otherwise, the sequence
would be incorrect.  If it is an ascending_index, the NULL values
are processed with the length 1; values from variable fields are
processed either with their true length or with their maximum
length.
An unambiguous file name is formed for the temporary file (invfn).
There is a new file for each intersect_inv so that the results of
previous intersect iterations can be easily deleted.
The other inversion lists are now processed one after the other
in a loop; the presence of desc indexes must again be taken into
account.
The key value of the new inversion list always has the length
1 and the value h'01'.
Following the intersection formation (B03INTERSECT_INV), which
takes into account the primary-key limits, the now
old temporary file is deleted and the new name (invfn) is assigned
to hinvfn1.
FILL_RESULT
 
The mess_buffer is edited for the result.  Part1 contains
the resultcount -1, i.e. 'unknown', if a result was found; otherwise
it contains 0.
Key-value lengths of 2 bytes each and the key itself with its
current length are stored in part2.  These are:
 primary startkey
 primary key at which the record was found
 primary stopkey
 secondary startkey
 secondary value at which the record was found
 secondary stopkey
 
Primary file name and the inversion file name follow.
Warning14 is set in BD when a changeover is made from
one inversion list to the next. But it should not appear during
set selects (or fetches).  Therefore it must be removed.
The current primary key and the primary start key are changed
slightly.  Since a search for the
next
record (starting from the current key) is run during 'fetch', the
two keys must each receive the last value before the one they
contain so that, during the fetch, the
next
(the first) record is found.  Otherwise, fetch would overlook the
first record.
 
.CM *-END-* description ---------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
CONST
      c_build_result     = true (* KB73CREATE_TEMP_INVFILE, et al *);
      c_with_inv         = true (* KB73FILL_RESULT *);
      c_aggr             = true (* K721FUNCTION_ADD *);
      c_finding_possible = true (* KB73CHECK_ONE_INTERN_INVLIST *);
      c_usage_count      = true (* b03select_invrec *); (* h.b. PTS 1104210 *)
 
 
(*------------------------------*) 
 
PROCEDURE
      kb73check_one_intern_invlist (
            VAR m            : tgg00_MessBlock;
            VAR getrec       : tgg07_get_param;
            VAR selrec       : tgg07_select_param;
            VAR selfields    : tgg00_SelectFieldsParam;
            VAR gg_strategy  : tgg07_StrategyInfo;
            VAR ftrees       : tgg00_TwoFileIds;
            VAR startkeys    : tgg00_TwoKeys;
            VAR stopkeys     : tgg00_TwoKeys;
            istop            : tgg00_BdInvSet;
            build_result     : boolean;
            finding_possible : boolean);
 
VAR
      _coded_distinct_optim : tsp00_Int2;
      _aux_error : tgg00_BasisError;
 
BEGIN
&ifdef trace
t01bool( kb, 'build result', build_result );
&endif
IF  ( build_result )
THEN
    BEGIN
    selrec.selr.selr_inv_id := ftrees.inv_id;
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        IF  ( finding_possible )
        THEN
            BEGIN
            IF  ( isp_aggr_optim in
                gg_strategy.str_inv_in_range.siir_strat_props )
            THEN
                kb73aggr_inv_func( m, ftrees, startkeys,
                      stopkeys, selrec, selfields )
            ELSE
                BEGIN
                _coded_distinct_optim := a71code_distinct_optim( gg_strategy );
                k721inv_gets( m, ftrees, startkeys, stopkeys,
                      selrec.selr.selr_startkey, istop, mm_first,
                      getrec, selrec, selfields );
                WHILE ( m.mb_trns^.trError_gg00 = e_ok ) DO
                    BEGIN
                    IF  NOT ( _coded_distinct_optim in
                        [ NO_DISTINCT_OPTIM_GG07, AUTO_DISTINCT_OPTIM_GG07 ] )
                    THEN
                        (* we handle with DISTINCT optimization *)
                        IF  ( _coded_distinct_optim < KEYSEQLEN_OFFSET_GG07 )
                        THEN
                            (* sequenced index columns *)
                            BEGIN
                            (* jump to next secondary key *)
                            startkeys.reckey.len := MAX_KEYLEN_GG00;
                            startkeys.reckey.k   := b01fullkey;
                            IF  ( _coded_distinct_optim <> INV_DISTINCT_OPTIM_GG07 )
                            THEN
                                (* don't fill a existing full invkey *)
                                SAPDB_PascalFill ('VKB73 ',   1,    
                                      sizeof( startkeys.listkey.k ),
                                      @startkeys.listkey.k,
                                      _coded_distinct_optim + 1,
                                      startkeys.listkey.len -
                                      _coded_distinct_optim,
                                      chr( 255 ),
                                      m.mb_trns^.trError_gg00);
                            (*ENDIF*) 
                            END
                        ELSE
                            (* sequenced key output columns *)
                            IF  (( _coded_distinct_optim -
                                KEYSEQLEN_OFFSET_GG07 ) < startkeys.reckey.len )
                            THEN
                                SAPDB_PascalFill ('VKB73 ',   2,    
                                      sizeof( startkeys.reckey.k ),
                                      @startkeys.reckey.k,
                                      _coded_distinct_optim -
                                      KEYSEQLEN_OFFSET_GG07 + 1,
                                      startkeys.reckey.len -
                                      ( _coded_distinct_optim - KEYSEQLEN_OFFSET_GG07 ),
                                      chr( 255 ),
                                      m.mb_trns^.trError_gg00);
                            (*ENDIF*) 
                        (*ENDIF*) 
                    (*ENDIF*) 
                    IF  ( m.mb_trns^.trError_gg00 = e_ok )
                    THEN
                        k721inv_gets( m, ftrees, startkeys, stopkeys,
                              selrec.selr.selr_startkey, istop, mm_next,
                              getrec, selrec, selfields );
                    (*ENDIF*) 
                    END;
                (*ENDWHILE*) 
                IF  ( m.mb_trns^.trError_gg00 = e_key_not_found     ) OR
                    ( m.mb_trns^.trError_gg00 = e_qual_violation    ) OR
                    ( m.mb_trns^.trError_gg00 = e_no_next_record    ) OR
                    ( m.mb_trns^.trError_gg00 = e_inv_list_not_found) OR
                    ( m.mb_trns^.trError_gg00 = e_no_next_invkey    ) OR
                    ( m.mb_trns^.trError_gg00 = e_view_violation    )
                THEN
                    m.mb_trns^.trError_gg00 := e_ok;
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        ELSE
            (* NOT finding_possible *)
            m.mb_trns^.trError_gg00 := e_no_next_record;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( m.mb_trns^.trError_gg00 = e_file_empty ) OR
        ( m.mb_trns^.trError_gg00 = e_no_next_record )
    THEN
        m.mb_trns^.trError_gg00 := e_ok;
    (*ENDIF*) 
    IF  ( selrec.selr.selr_inv_id.fileTfn_gg00 = tfnTempInv_egg00 )
    THEN
        BEGIN
        _aux_error := m.mb_trns^.trError_gg00;
        b01destroy_file( m.mb_trns^, selrec.selr.selr_inv_id );
        ;
        IF  (( _aux_error <> e_ok ) AND
            ( _aux_error <> e_no_next_record ))
            OR
            ( m.mb_trns^.trError_gg00 = e_file_not_found )
        THEN
            m.mb_trns^.trError_gg00 := _aux_error
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
ELSE (* not build_result *)
    IF  (( m.mb_trns^.trError_gg00 = e_ok ) OR
        ( m.mb_trns^.trError_gg00 = e_file_empty ))
    THEN
        BEGIN
        IF  ( m.mb_trns^.trError_gg00 <> e_file_empty )
        THEN
            BEGIN
            IF  ( gg_strategy.str_search_first )
            THEN
                IF  ( ftrees.inv_id.fileTfn_gg00 = tfnTempInv_egg00 )
                THEN
                    k73select_invrec( m, ftrees, startkeys, stopkeys,
                          selrec.selr.selr_startkey, [  ],
                          selrec.selr_selectbuffer.buf_rec, selfields,
                          selrec.selr_selectbuffer.result.buf,
                          e_no_next_record )
                ELSE
                    k73select_invrec( m, ftrees, startkeys, stopkeys,
                          selrec.selr.selr_startkey, istop,
                          selrec.selr_selectbuffer.buf_rec, selfields,
                          selrec.selr_selectbuffer.result.buf,
                          e_no_next_record );
                (*ENDIF*) 
            (*ENDIF*) 
            END
        ELSE
            m.mb_trns^.trError_gg00 := e_no_next_record;
        (*ENDIF*) 
        kb73fill_result( m, selrec, selfields,
              startkeys.reckey, startkeys.listkey,
              stopkeys.reckey, stopkeys.listkey,
              ftrees.file_id, ftrees.inv_id,
              c_with_inv, gg_strategy );
        END
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb73aggr_inv_func (
            VAR m           : tgg00_MessBlock;
            VAR ftrees      : tgg00_TwoFileIds;
            VAR startkeys   : tgg00_TwoKeys;
            VAR stopkeys    : tgg00_TwoKeys;
            VAR selrec      : tgg07_select_param;
            VAR selfields   : tgg00_SelectFieldsParam);
 
VAR
      _do_aggr           : boolean;
      _ix, _iy           : integer;
      _stop              : integer;
      _first_len         : integer;
      _funct_fields      : tgg00_AggrDescrRec;
      _bWarnOfNullValues : boolean;
 
BEGIN
_funct_fields.agg_cnt            := 0;
_funct_fields.agg_opt_infos      := [  ];
_first_len         := 0;
_ix                := m.mb_qual^.mqual_pos;
_bWarnOfNullValues := false;
_ix   := succ(_ix);
_stop := m.mb_qual^.mqual_pos + m.mb_st^[ m.mb_qual^.mqual_pos ].epos - 2;
WHILE ( _ix <= _stop ) AND ( m.mb_trns^.trError_gg00 = e_ok )DO
    BEGIN
    CASE m.mb_st^[ _ix ].etype OF
        st_func:
            BEGIN
            CASE m.mb_st^[ _ix ].eop_func OF
                op_f_min, op_f_max,
                op_f_sum, op_f_dis_sum,
                op_f_avg, op_f_dis_avg,
                op_f_count, op_f_dis_count,
                op_f_all_count, op_f_count_kb :
                    BEGIN
                    IF  ( m.mb_st^[ _ix ].eop_func = op_f_count_kb )
                    THEN
                        m.mb_st^[ _ix ].eop_func := op_f_all_count;
                    (*ENDIF*) 
                    ;
                    (* mark column *)
                    _funct_fields.agg_cnt    := succ( _funct_fields.agg_cnt );
                    (* insert function operator *)
                    _funct_fields.agg_field_descr[ _funct_fields.agg_cnt ].
                          field_function := m.mb_st^[ _ix ].eop_func;
                    ;
                    IF  ( m.mb_st^[ _ix ].eop_func <> op_f_all_count )
                    THEN
                        (* look for column *)
                        BEGIN
                        _iy := pred(_ix);
                        WHILE ( _iy > m.mb_qual^.mqual_pos ) AND
                              ( NOT ( m.mb_st^[ _iy ].etype in
                              [ st_fixinv, st_varinv, st_func, st_output ] )) DO
                            _iy := pred( _iy );
                        (*ENDWHILE*) 
                        IF  ( m.mb_st^[ _iy ].etype in [ st_fixinv, st_varinv ] )
                        THEN
                            BEGIN
                            IF  ( m.mb_st^[ _iy ].etype = st_varinv )
                            THEN
                                _first_len := 0
                            ELSE
                                _first_len := m.mb_st^[ _iy ].elen_var;
                            (*ENDIF*) 
                            WITH _funct_fields.
                                 agg_field_descr[ _funct_fields.agg_cnt ] DO
                                BEGIN
                                field_rec_pos  := m.mb_st^[ _iy ].epos;
                                field_rec_len  := _first_len;
                                field_count    := 0;
                                field_sum_flag := false;
                                IF  ( m.mb_st^[ _iy ].eop in
                                    [ op_order_desc, op_unique_desc ] )
                                THEN
                                    field_is_descen := true
                                ELSE
                                    field_is_descen := false;
                                (*ENDIF*) 
                                END;
                            (*ENDWITH*) 
                            END
                        ELSE
                            m.mb_trns^.trError_gg00 := e_stack_type_illegal;
                        (*ENDIF*) 
                        END
                    ELSE
                        (* op_f_all_count *)
                        BEGIN
                        WITH _funct_fields.
                             agg_field_descr[ _funct_fields.agg_cnt ] DO
                            BEGIN
                            field_rec_pos   := 1;
                            field_rec_len   := 0;
                            field_count     := 0;
                            field_sum_flag  := false;
                            field_is_descen := false;
                            END;
                        (*ENDWITH*) 
                        END;
                    (*ENDIF*) 
                    ;
                    (* look for output *)
                    _iy := succ(_ix);
                    WHILE ( _iy <= _stop ) AND
                          ( NOT ( m.mb_st^[ _iy ].etype in
                          [ st_output, st_fixinv, st_varinv, st_func ])) DO
                        _iy := succ(_iy);
                    (*ENDWHILE*) 
                    IF  ( m.mb_st^[ _iy ].etype = st_output )
                    THEN
                        BEGIN
                        WITH _funct_fields.
                             agg_field_descr[ _funct_fields.agg_cnt ] DO
                            BEGIN
                            result_out_pos := m.mb_st^[ _iy ].epos;
                            result_out_len := m.mb_st^[ _iy ].elen_var;
                            END;
                        (*ENDWITH*) 
                        _ix := _iy; (* skip this entry *)
                        END
                    ELSE
                        m.mb_trns^.trError_gg00 := e_stack_type_illegal;
                    (*ENDIF*) 
                    END;
                op_f_check_null:
                    BEGIN
                    _bWarnOfNullValues := true;
                    END;
                OTHERWISE
                    BEGIN
                    END;
                END;
            (*ENDCASE*) 
            END;
        OTHERWISE
            BEGIN
            END;
        END;
    (*ENDCASE*) 
    _ix := succ( _ix );
    END;
(*ENDWHILE*) 
IF  ( m.mb_qual^.mqual_cnt > _ix - 1 )
THEN
    BEGIN
    _stop := m.mb_qual^.mqual_cnt;
    WHILE ( _ix <= _stop ) DO
        BEGIN
        IF  ( m.mb_st^[ _ix ].etype in [ st_fixprimkey, st_varprimkey ] )
        THEN
            _funct_fields.agg_opt_infos := _funct_fields.agg_opt_infos +
                  [ prim_keys ];
        (*ENDIF*) 
        _ix   := succ( _ix );
        END;
    (*ENDWHILE*) 
    END;
(*ENDIF*) 
;
&IFDEF TRACE
IF  ( prim_keys in _funct_fields.agg_opt_infos )
THEN
    t01int4( ak_strat, 'prim_keys  >', 1 );
(*ENDIF*) 
t01int4 (ak_strat, 'AGGR-OPTIM >', _funct_fields.agg_cnt);
FOR _ix := 1 TO _funct_fields.agg_cnt DO
    WITH _funct_fields.agg_field_descr[ _ix ] DO
        BEGIN
        t01int4( ak_strat,' ix  >>>>>> ', _ix );
        t01int4( ak_strat,'field_pos : ', field_rec_pos );
        t01int4( ak_strat,'field_len : ', field_rec_len );
        t01int4( ak_strat,'descending: ', ord( field_is_descen ) );
        t01int4( ak_strat,'  out_pos : ', result_out_pos );
        t01int4( ak_strat,'  out_len : ', result_out_len );
        t01int4( ak_strat,'  function: ', ord( field_function ));
        END;
    (*ENDWITH*) 
(*ENDFOR*) 
&ENDIF
kb73init_aggr( _funct_fields, selrec.selr_selectbuffer.lbuf,
      m.mb_trns^.trError_gg00 );
WITH selrec.selr_selectbuffer, result DO
    BEGIN
    keylen := selrec.selr.selr_keyl;
    len    := selrec.selr.selr_recl;
    FOR _ix := 1 TO 3 DO
        info[ keylen - 4 + _ix ] := chr(0);
    (*ENDFOR*) 
    info[ keylen ] := chr(1);
    SAPDB_PascalMove ('VKB73 ',   3,    
          sizeof(result.buf), sizeof(lbuf),
          @result.buf, 1, @lbuf, 1,
          cgg_rec_key_offset + keylen, m.mb_trns^.trError_gg00)
    END;
(*ENDWITH*) 
IF  ( m.mb_trns^.trError_gg00 <> e_ok )
THEN
    _do_aggr := false
ELSE
    BEGIN
    selfields.sfp_result_wanted       := NOT (selrec.selr.selr_one_result);
    selrec.selr.selr_distinct_id.fileTempCnt_gg00   := 1;
    selrec.selr.selr_distinct_id.fileRoot_gg00      :=
          selrec.selr.selr_disrootarr[ 1 ].dfi_root;
    selrec.selr.selr_distinct_id.fileRootCheck_gg00 :=
          selrec.selr.selr_disrootarr[ 1 ].dfi_root_check;
    _do_aggr := true;
    END;
(*ENDIF*) 
WHILE _do_aggr DO
    BEGIN
    (* for every group bd03AggrFuncOnIndex() returns aggregates values *)
    (**)
    (* CRS 1104319 Alexander Kley 25/10/1999 *)
    bd03AggrFuncOnIndex( m.mb_trns^, ftrees.inv_id,
          selrec.selr.selr_distinct_id, startkeys, stopkeys,
          _funct_fields, selfields, m.mb_qual^.mstack_desc,
          selrec.selr_selectbuffer.rbuf, selrec.selr_selectbuffer.lbuf,
          NOT selrec.selr.selr_one_result, _bWarnOfNullValues );
    IF  ( m.mb_trns^.trError_gg00 = e_no_next_record )
    THEN
        BEGIN
        m.mb_trns^.trError_gg00 := e_ok;
        _do_aggr              := false;
        END;
    (*ENDIF*) 
    kb73one_aggr( _funct_fields, selrec, selrec.selr_selectbuffer.lbuf,
          m.mb_trns^.trError_gg00 );
&   IFDEF TRACE
    t01buf (ak_strat, selrec.selr_selectbuffer.lbuf, 1, selrec.selr.selr_recl);
&   ENDIF
    IF  ( NOT selrec.selr.selr_one_result )
    THEN
        IF  ( m.mb_trns^.trError_gg00 = e_ok )
        THEN
            BEGIN
            WITH selrec.selr_selectbuffer, result DO
                SAPDB_PascalMove ('VKB73 ',   4,    
                      sizeof(lbuf), sizeof(result.buf),
                      @lbuf, 1,
                      @result.buf, 1, selrec.selr.selr_recl,
                      m.mb_trns^.trError_gg00);
            (*ENDWITH*) 
            IF  (m.mb_trns^.trError_gg00 = e_ok)
            THEN
                BEGIN
                k721function_add( m, selrec, c_aggr );
                kb73init_aggr( _funct_fields, selrec.selr_selectbuffer.lbuf,
                      m.mb_trns^.trError_gg00 );
                END
            ELSE
                _do_aggr := false;
            (*ENDIF*) 
            END
        ELSE
            IF  ( m.mb_trns^.trError_gg00 = e_no_next_record )
            THEN
                BEGIN
                m.mb_trns^.trError_gg00 := e_ok;
                _do_aggr              := false;
                END
            ELSE
                _do_aggr  := false
            (*ENDIF*) 
        (*ENDIF*) 
    ELSE
        BEGIN
        selrec.selr.selr_group_count := 1;
        _do_aggr         := false;
        END;
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb73fill_result (
            VAR m            : tgg00_MessBlock;
            VAR selrec       : tgg07_select_param;
            VAR selfields    : tgg00_SelectFieldsParam;
            VAR startprimkey : tgg00_Lkey;
            VAR startinvkey  : tgg00_Lkey;
            VAR stopprimkey  : tgg00_Lkey;
            VAR stopinvkey   : tgg00_Lkey;
            VAR primtree     : tgg00_FileId;
            VAR invtree      : tgg00_FileId;
            with_inv         : boolean;
            VAR strat        : tgg07_StrategyInfo);
 
VAR
      _aux_error : tgg00_BasisError;
      _lc2       : tsp_int_map_c2;
 
BEGIN
&ifdef trace
IF  with_inv
THEN
    BEGIN
    t01key(kb, 'startinvkey ', startinvkey );
    t01key(kb, 'stopinvkey  ', stopinvkey );
    END;
(*ENDIF*) 
t01key(kb, 'selr_startke', selrec.selr.selr_startkey );
t01key(kb, 'startprimkey', startprimkey );
t01key(kb, 'stopprimkey ', stopprimkey );
t01basis_error(kb, 'err code    ', m.mb_trns^.trError_gg00);
t01bool(kb, 'search first', strat.str_search_first);
t01mess2type( kb, 'sfp_bd_mess2', selfields.sfp_bd_mess2_type );
&endif
IF  ( m.mb_trns^.trError_gg00 in
    [ e_ok, e_no_next_record, e_no_prev_record,
    e_key_not_found, e_qual_violation, e_view_violation])
THEN
    BEGIN
    IF  ( selfields.sfp_bd_mess2_type <> mm_direct )
    THEN
        BEGIN
        IF  ( selfields.sfp_bd_mess2_type in [ mm_prev, mm_last ] )
        THEN
            BEGIN
            g04smallest_greater_key( selrec.selr.selr_startkey );
            g04smallest_greater_key( startprimkey );
            END
        ELSE
            BEGIN
            g04greatest_smaller_key( selrec.selr.selr_startkey );
            g04greatest_smaller_key( startprimkey );
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( selfields.sfp_bd_mess2_type in [ mm_first, mm_next ] )
    THEN
        BEGIN
        IF  ( stopprimkey.len = 0 )
        THEN
            BEGIN
&           ifdef trace
            t01c32 ( kb, 'set greatest possible stopprimke' );
&           endif
            stopprimkey.k[ 1 ] := chr( 255 );
            stopprimkey.len := 1;
            END;
        (*ENDIF*) 
        IF  ( with_inv )
        THEN
            BEGIN
            IF  ( stopinvkey.len = 0 )
            THEN
                BEGIN
&               ifdef trace
                t01c32 ( kb, 'set greatest possible stopinvkey' );
&               endif
                stopinvkey.k[ 1 ] := chr( 255 );
                stopinvkey.len := 1;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    ;
&   ifdef trace
    IF  with_inv
    THEN
        BEGIN
        t01key(kb, 'startinvkey ', startinvkey );
        t01key(kb, 'stopinvkey  ', stopinvkey );
        END;
    (*ENDIF*) 
    t01key(kb, 'selr_startke', selrec.selr.selr_startkey );
    t01key(kb, 'startprimkey', startprimkey );
    t01key(kb, 'stopprimkey ', stopprimkey );
    t01bool(kb, 'str_search_f', strat.str_search_first);
&   endif
    m.mb_type   := m_return_result;
    m.mb_struct := mbs_result;
    IF  ( strat.str_search_first )
    THEN
        BEGIN
        IF  ( m.mb_trns^.trError_gg00 = e_ok )
        THEN
            m.mb_qual^.mr_resnum := csp_rescnt_unknown
        ELSE
            BEGIN
            m.mb_trns^.trError_gg00 := e_ok;
            m.mb_qual^.mr_resnum := csp_rescnt_zero
            END;
        (*ENDIF*) 
        m.mb_qual^.mr_res_build := false;
        m.mb_qual^.mr_pagecnt   :=
              m.mb_trns^.trRteCommPtr_gg00^.file_record_cnt;
        m.mb_qual_len           := MB_PART1_HEAD_MXGG00 +
              cgg04_return_stack_entries * STACK_ENTRY_MXGG00;
        m.mb_data_len  := 0;
        (* a67_fetchkeys move keys into result record *)
        (* write selr.selr_startkey length and value ==> res_startkey.reckey *)
&       ifdef trace
        t01c32 ( kb, 'selr_startkey -> r_start key    ' );
&       endif
        _lc2.map_int := selrec.selr.selr_startkey.len;
        m.mb_data^.mbp_buf[ m.mb_data_len +1 ] := _lc2.map_c2[ 1 ];
        m.mb_data^.mbp_buf[ m.mb_data_len +2 ] := _lc2.map_c2[ 2 ];
        SAPDB_PascalMove ('VKB73 ',   5,    
              sizeof(selrec.selr.selr_startkey.k),
              m.mb_data_size, @selrec.selr.selr_startkey.k, 1,
              @m.mb_data^.mbp_buf, m.mb_data_len +3,
              selrec.selr.selr_startkey.len, m.mb_trns^.trError_gg00);
        m.mb_data_len  := m.mb_data_len + selrec.selr.selr_startkey.len+2;
        (* write startprimkey length and value ==> res_nextkey.reckey *)
&       ifdef trace
        t01c32 ( kb, 'startprimkey  -> r_next key     ' );
&       endif
        _lc2.map_int := startprimkey.len;
        m.mb_data^.mbp_buf[ m.mb_data_len +1 ] := _lc2.map_c2[ 1 ];
        m.mb_data^.mbp_buf[ m.mb_data_len +2 ] := _lc2.map_c2[ 2 ];
        SAPDB_PascalMove ('VKB73 ',   6,    
              sizeof(startprimkey.k), m.mb_data_size,
              @startprimkey.k, 1,
              @m.mb_data^.mbp_buf, m.mb_data_len +3,
              startprimkey.len, m.mb_trns^.trError_gg00);
        m.mb_data_len  := startprimkey.len+2 + m.mb_data_len;
        (* write stopprimkey length and value ==> res_stopkey.reckey *)
&       ifdef trace
        t01c32 ( kb, 'stopprimkey   -> r_stop key     ' );
&       endif
        _lc2.map_int := stopprimkey.len;
        m.mb_data^.mbp_buf[ m.mb_data_len +1 ] := _lc2.map_c2[ 1 ];
        m.mb_data^.mbp_buf[ m.mb_data_len +2 ] := _lc2.map_c2[ 2 ];
        SAPDB_PascalMove ('VKB73 ',   7,    
              sizeof(stopprimkey.k), m.mb_data_size,
              @stopprimkey.k, 1,
              @m.mb_data^.mbp_buf, m.mb_data_len +3,
              stopprimkey.len, m.mb_trns^.trError_gg00);
        m.mb_data_len  := stopprimkey.len+2 + m.mb_data_len;
        (**)
        IF  ( with_inv )
        THEN
            BEGIN
            (* write startinvkey length and value ==> res_startkey.listkey *)
&           ifdef trace
            t01c32 ( kb, 'startinvkey   -> r_start inv    ' );
&           endif
            _lc2.map_int := startinvkey.len;
            m.mb_data^.mbp_buf[ m.mb_data_len +1 ] := _lc2.map_c2[ 1 ];
            m.mb_data^.mbp_buf[ m.mb_data_len +2 ] := _lc2.map_c2[ 2 ];
            SAPDB_PascalMove ('VKB73 ',   8,    
                  sizeof(startinvkey.k), m.mb_data_size,
                  @startinvkey.k, 1,
                  @m.mb_data^.mbp_buf, m.mb_data_len +3,
                  startinvkey.len, m.mb_trns^.trError_gg00);
            m.mb_data_len  := startinvkey.len+2 + m.mb_data_len;
            (* write startinvkey length and value ==> res_nextkey.listkey *)
&           ifdef trace
            t01c32 ( kb, 'startinvkey   -> r_next inv     ' );
&           endif
            _lc2.map_int := startinvkey.len;
            m.mb_data^.mbp_buf[ m.mb_data_len +1 ] := _lc2.map_c2[ 1 ];
            m.mb_data^.mbp_buf[ m.mb_data_len +2 ] := _lc2.map_c2[ 2 ];
            SAPDB_PascalMove ('VKB73 ',   9,    
                  sizeof(startinvkey.k), m.mb_data_size,
                  @startinvkey.k, 1,
                  @m.mb_data^.mbp_buf, m.mb_data_len +3,
                  startinvkey.len, m.mb_trns^.trError_gg00);
            m.mb_data_len  := startinvkey.len+2 + m.mb_data_len;
            (* write stopinvkey length and value ==> res_stopkey.listkey *)
&           ifdef trace
            t01c32 ( kb, 'stopinvkey    -> r_stop inv     ' );
&           endif
            _lc2.map_int := stopinvkey.len;
            m.mb_data^.mbp_buf[ m.mb_data_len +1 ] := _lc2.map_c2[ 1 ];
            m.mb_data^.mbp_buf[ m.mb_data_len +2 ] := _lc2.map_c2[ 2 ];
            SAPDB_PascalMove ('VKB73 ',  10,    
                  sizeof(stopinvkey.k), m.mb_data_size,
                  @stopinvkey.k, 1,
                  @m.mb_data^.mbp_buf, m.mb_data_len +3,
                  stopinvkey.len, m.mb_trns^.trError_gg00);
            m.mb_data_len  := stopinvkey.len+2 + m.mb_data_len;
            END
        ELSE
            BEGIN
            _lc2.map_int := 0;
            m.mb_data^.mbp_buf[ m.mb_data_len+1 ] := _lc2.map_c2[ 1 ];
            m.mb_data^.mbp_buf[ m.mb_data_len+2 ] := _lc2.map_c2[ 2 ];
            m.mb_data^.mbp_buf[ m.mb_data_len+3 ] := _lc2.map_c2[ 1 ];
            m.mb_data^.mbp_buf[ m.mb_data_len+4 ] := _lc2.map_c2[ 2 ];
            m.mb_data^.mbp_buf[ m.mb_data_len+5 ] := _lc2.map_c2[ 1 ];
            m.mb_data^.mbp_buf[ m.mb_data_len+6 ] := _lc2.map_c2[ 2 ];
            m.mb_data_len := m.mb_data_len + 6;
            END;
        (*ENDIF*) 
        (* write base table FileID *)
        SAPDB_PascalMove ('VKB73 ',  11,    
              sizeof(primtree), m.mb_data_size,
              @primtree, 1, @m.mb_data^.mbp_buf,
              m.mb_data_len +1, FILE_ID_MXGG00, m.mb_trns^.trError_gg00);
        (* write index FileID *)
        SAPDB_PascalMove ('VKB73 ',  12,    
              sizeof(invtree), m.mb_data_size,
              @invtree, 1, @m.mb_data^.mbp_buf,
              m.mb_data_len+FILE_ID_MXGG00+1, FILE_ID_MXGG00,
              m.mb_trns^.trError_gg00);
        m.mb_data_len := m.mb_data_len + FILE_ID_MXGG00 + FILE_ID_MXGG00;
        IF  ( NOT with_inv )
        THEN
            BEGIN
            (* wozu ??? *)
            m.mb_data_len := m.mb_data_len + 1;
            m.mb_data^.mbp_buf[ m.mb_data_len ] := chr(0);
            END
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        WITH m.mb_qual^.mf_desc DO
            BEGIN
&           ifdef trace
            t01name( kb, 'set fetch desc    ' );
&           endif
            (* PTS 1001081 E.Z. *)
            m.mb_trns^.trError_gg00 := e_ok;
            m_fetch_state    := [ fs_use_recs ];
            m_resnum         := csp_rescnt_unknown;
            m_res_build      := false;
            m_restree        := b01niltree_id;
            IF  ( selrec.selr.selr_reverse_fetch )
            THEN
                m_fetch_state := m_fetch_state + [ fs_reverse_fetch ];
            (*ENDIF*) 
            m_fill3          := false;
            m_searched_pages := 0;
            m_rescnt         := -1;
            m_rowno          := -1;
            m_fns1           := primtree;
            m_fns2           := invtree;
            m_cnt            := -1; (* to be calculated in ak *)
            IF  ( with_inv )
            THEN
                m_fetch_state := m_fetch_state + [ fs_use_inv ];
            (*ENDIF*) 
            IF  (stopprimkey.k[1] <> chr(255))
                OR            (stopinvkey.k [1] <> chr(255))
            THEN
                m_fetch_state := m_fetch_state + [ fs_use_stop ];
            (*ENDIF*) 
            m_keylen         := strat.str_key_len;
            m_leng           := strat.str_rec_len-cgg_rec_key_offset-
                  strat.str_key_len;
            m_startkeys.reckey.len := selrec.selr.selr_startkey.len;
&           ifdef trace
            t01c32 ( kb, 'selr_startkey -> m_startkey key ' );
&           endif
            IF  ( selrec.selr.selr_startkey.len > 0 )
            THEN
                SAPDB_PascalMove ('VKB73 ',  13,    
                      sizeof(selrec.selr.selr_startkey.k), sizeof(m_startkeys.reckey.k),
                      @selrec.selr.selr_startkey.k, 1,
                      @m_startkeys.reckey.k, 1,
                      selrec.selr.selr_startkey.len, m.mb_trns^.trError_gg00);
            (*ENDIF*) 
            ;
&           ifdef trace
            t01c32 ( kb, 'stopprimkey   -> m_stopkey  key ' );
&           endif
            m_stopkeys.reckey.len := stopprimkey.len;
            IF  ( stopprimkey.len > 0 )
            THEN
                BEGIN
                SAPDB_PascalMove ('VKB73 ',  14,    
                      sizeof(stopprimkey.k), sizeof(m_stopkeys.reckey.k),
                      @stopprimkey.k, 1,
                      @m_stopkeys.reckey.k, 1,
                      stopprimkey.len, m.mb_trns^.trError_gg00);
                END;
            (*ENDIF*) 
            ;
&           ifdef trace
            t01c32 ( kb, 'selr_startkey -> m_firstkey key ' );
&           endif
            m_firstkeys.reckey.len := selrec.selr.selr_startkey.len;
            IF  ( selrec.selr.selr_startkey.len > 0 )
            THEN
                BEGIN
                SAPDB_PascalMove ('VKB73 ',  15,    
                      sizeof(selrec.selr.selr_startkey.k), sizeof(m_firstkeys.reckey.k),
                      @selrec.selr.selr_startkey.k, 1,
                      @m_firstkeys.reckey.k, 1,
                      selrec.selr.selr_startkey.len, m.mb_trns^.trError_gg00);
                END;
            (*ENDIF*) 
            ;
            IF  ( selfields.sfp_bd_mess2_type = mm_prev )
            THEN
                BEGIN
&               ifdef trace
                t01c32 ( kb, 'stopprimkey   -> m_start    key ' );
&               endif
                m_start.len := stopprimkey.len;
                IF  ( stopprimkey.len > 0 )
                THEN
                    BEGIN
                    SAPDB_PascalMove ('VKB73 ',  16,    
                          sizeof(stopprimkey.k), sizeof(m_start.k),
                          @stopprimkey.k, 1, @m_start.k, 1,
                          stopprimkey.len, m.mb_trns^.trError_gg00);
                    END;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
&               ifdef trace
                t01c32 ( kb, 'startprimkey  -> m_start    key ' );
&               endif
                m_start.len := startprimkey.len;
                IF  ( startprimkey.len > 0 )
                THEN
                    BEGIN
                    SAPDB_PascalMove ('VKB73 ',  17,    
                          sizeof(startprimkey.k), sizeof(m_start.k),
                          @startprimkey.k, 1, @m_start.k, 1,
                          startprimkey.len, m.mb_trns^.trError_gg00);
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  ( with_inv )
            THEN
                BEGIN
&               ifdef trace
                t01c32 ( kb, 'selr_invkey   -> m_startkey inv ' );
&               endif
                m_startkeys.listkey.len := selrec.selr.selr_invkey.len;
                IF  ( selrec.selr.selr_invkey.len > 0 )
                THEN
                    SAPDB_PascalMove ('VKB73 ',  18,    
                          sizeof(selrec.selr.selr_invkey.k), sizeof(m_startkeys.listkey.k),
                          @selrec.selr.selr_invkey.k, 1, @m_startkeys.listkey.k, 1, selrec.selr.selr_invkey.len,
                          m.mb_trns^.trError_gg00);
                (*ENDIF*) 
                ;
&               ifdef trace
                t01c32 ( kb, 'stopinvkey    -> m_stopkey  inv ' );
&               endif
                m_stopkeys.listkey.len := stopinvkey.len;
                IF  ( stopinvkey.len > 0 )
                THEN
                    SAPDB_PascalMove ('VKB73 ',  19,    
                          sizeof(stopinvkey.k), sizeof(m_stopkeys.listkey.k),
                          @stopinvkey.k, 1,
                          @m_stopkeys.listkey.k, 1,
                          stopinvkey.len, m.mb_trns^.trError_gg00);
                (*ENDIF*) 
                ;
&               ifdef trace
                t01c32 ( kb, 'selr_invkey   -> m_firstkey inv ' );
&               endif
                m_firstkeys.listkey.len := selrec.selr.selr_invkey.len;
                IF  ( selrec.selr.selr_invkey.len > 0 )
                THEN
                    SAPDB_PascalMove ('VKB73 ',  20,    
                          sizeof(selrec.selr.selr_invkey.k),
                          sizeof(m_firstkeys.listkey.k),
                          @selrec.selr.selr_invkey.k, 1,
                          @m_firstkeys.listkey.k, 1,
                          selrec.selr.selr_invkey.len, m.mb_trns^.trError_gg00);
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                m_startkeys.listkey.len := 0;
                m_stopkeys.listkey.len := 0;
                m_firstkeys.listkey.len := 0;
                END;
            (*ENDIF*) 
            m_dist_optim     := a71code_distinct_optim( strat );
            (* PTS 1104834 E.Z. *)
            k720ref_statistic (m, m_strat_info, strat);
            m_qual_kind      := strat.str_qual_kind;
            m_data           := NIL;
            m.mb_qual_len := sizeof(m.mb_qual^.mf_desc);
            m.mb_data_len  := 0;
            END;
        (*ENDWITH*) 
        END;
    (*ENDIF*) 
    END
ELSE
    IF  ( invtree.fileTfn_gg00 = tfnTemp_egg00 )
    THEN
        BEGIN
        _aux_error := m.mb_trns^.trError_gg00;
        b01destroy_file( m.mb_trns^, invtree );
        m.mb_trns^.trError_gg00 := _aux_error;
        END;
    (*ENDIF*) 
(*ENDIF*) 
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*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb73init_aggr (
            VAR funct_fields : tgg00_AggrDescrRec;
            VAR lbuf   : tsp00_Buf;
            VAR b_err  : tgg00_BasisError );
 
VAR
      move_err : tgg00_BasisError;
      ix       : tsp00_Int2;
 
BEGIN
funct_fields.agg_prim_key_cnt     := 0;
funct_fields.agg_last_sec_key.len := 0;
FOR ix := 1 TO funct_fields.agg_cnt DO
    WITH funct_fields.agg_field_descr[ ix ] DO
        BEGIN
        move_err       := e_ok;
        field_count    := 0;
        field_sum_flag := false;
        CASE field_function OF
            op_f_sum,
            op_f_dis_sum,
            op_f_avg,
            op_f_dis_avg :
                BEGIN
                lbuf[ result_out_pos ] := csp_undef_byte;
                SAPDB_PascalFill ('VKB73 ',  21,    
                      sizeof(lbuf), @lbuf, result_out_pos+1,
                      result_out_len-1, csp_defined_byte, move_err);
                END;
            op_f_count, op_f_all_count, op_f_dis_count,
            op_f_check_null :
                lbuf[ result_out_pos ] := csp_defined_byte;
            op_f_min :
                SAPDB_PascalFill ('VKB73 ',  22,    
                      sizeof(lbuf), @lbuf, result_out_pos,
                      result_out_len, csp_undef_byte, move_err);
            op_f_max :
                BEGIN
                SAPDB_PascalFill ('VKB73 ',  23,    
                      sizeof(lbuf), @lbuf, result_out_pos,
                      result_out_len, csp_defined_byte, move_err);
                IF  field_is_descen AND (field_rec_pos = 1)
                THEN
                    lbuf[ result_out_pos ] := csp_undef_byte;
                (*ENDIF*) 
                END;
            OTHERWISE
                b_err := e_stack_type_illegal;
            END;
        (*ENDCASE*) 
        END;
    (*ENDWITH*) 
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb73one_aggr (
            VAR funct_fields : tgg00_AggrDescrRec;
            VAR selrec : tgg07_select_param;
            VAR lbuf   : tsp00_Buf;
            VAR e      : tgg00_BasisError);
 
VAR
      ix   : tsp00_Int2;
      ret  : tsp00_NumError;
 
BEGIN
FOR ix := 1 TO funct_fields.agg_cnt DO
    WITH funct_fields.agg_field_descr[ ix ] DO
        CASE field_function OF
            op_f_avg,
            op_f_dis_avg :
                BEGIN
                s41p4int (lbuf, result_out_pos +
                      NUMBER_MXGG04+1, field_count, ret);
                lbuf[ result_out_pos+mxsp_resnum ]:=
                      csp_defined_byte;
                END;
            op_f_count,
            op_f_all_count,
            op_f_dis_count :
                BEGIN
                (* PTS 1114259 E.Z. *)
                SAPDB_PascalFill ('VKB73 ',  24,    
                      sizeof(lbuf), @lbuf,
                      result_out_pos+1, result_out_len-1,
                      csp_defined_byte, e);
                s41p4int (lbuf, result_out_pos+1, field_count, ret);
                lbuf[ result_out_pos ] := csp_defined_byte;
                END;
            op_f_min,
            op_f_max :
                IF  (field_count = 0) AND (selrec.selr.selr_one_result)
                THEN
                    BEGIN
                    lbuf[ result_out_pos ] := csp_undef_byte;
                    SAPDB_PascalFill ('VKB73 ',  25,    
                          sizeof(lbuf), @lbuf,
                          result_out_pos+1, result_out_len-1,
                          csp_defined_byte, e);
                    END;
                (*ENDIF*) 
            OTHERWISE
                BEGIN
                END
            END;
        (*ENDCASE*) 
    (*ENDWITH*) 
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb73create_temp_invfile (
            VAR t        : tgg00_TransContext;
            VAR inv_id   : tgg00_FileId;
            no_of_file   : integer);
 
BEGIN
IF  ( no_of_file > 0 )
THEN
    inv_id.fileLevel_gg00[ 1 ] := chr( no_of_file )
ELSE
    BEGIN
    g04build_temp_tree_id( inv_id, t );
    inv_id.fileTfn_gg00 := tfnTempInv_egg00;
    IF  ( t.trIndex_gg00 = cgg_nil_transindex )
    THEN
        t.trError_gg00 := e_nil_transindex;
    (*ENDIF*) 
    inv_id.fileTempCnt_gg00 := g01GetSessionAuxCounter ( t );
    END;
(*ENDIF*) 
b01tcreate_file( t, inv_id );
WHILE ( t.trError_gg00 = e_duplicate_filename ) DO
    BEGIN
    inv_id.fileTempCnt_gg00 := pred( inv_id.fileTempCnt_gg00 );
    b01tcreate_file( t, inv_id );
    END;
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k73sec_key_build (
            VAR m                : tgg00_MessBlock;
            VAR index_strat      : tgg07_StrInvInRange;
            VAR sec_startkey     : tgg00_Lkey;
            VAR sec_stopkey      : tgg00_Lkey;
            in_stpos_hint        : tsp00_Int2;
            in_value_idx         : tsp00_Int2;
            VAR istop            : tgg00_BdInvSet;
            VAR finding_possible : boolean);
 
VAR
      _lc_result : tsp00_LcompResult;
 
BEGIN
IF  ( index_strat.siir_startcnt > 0 ) OR
    ( index_strat.siir_stopcnt > 0 )
THEN
    BEGIN
    g04limitinvkeys( m, index_strat,
          sec_startkey, sec_stopkey, in_stpos_hint, in_value_idx );
    istop := istop + [ secondary_stop ];
    END
ELSE
    BEGIN
    sec_startkey.len := 0;
    sec_stopkey.len  := MAX_KEYLEN_GG00;
    sec_stopkey.k    := b01fullkey;
    END;
(*ENDIF*) 
IF  ( secondary_stop in istop ) AND finding_possible
THEN
    BEGIN
    s30cmp( sec_startkey.k, 1, sec_startkey.len,
          sec_stopkey.k, 1, sec_stopkey.len,
          _lc_result );
    ;
    IF  ( _lc_result = l_greater )
    THEN
        finding_possible := false;
    (*ENDIF*) 
    END;
&ifdef trace
(*ENDIF*) 
t01bool( kb, 'find poss   ', finding_possible );
t01key( kb, 'sec startkey', sec_startkey  );
t01key( kb, 'sec stopkey ', sec_stopkey  );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      k73prim_key_build (
            VAR selrec        : tgg07_select_param;
            VAR prim_startkey : tgg00_Lkey;
            VAR prim_stopkey  : tgg00_Lkey;
            VAR istop         : tgg00_BdInvSet;
            VAR e             : tgg00_BasisError);
 
BEGIN
prim_startkey.len := selrec.selr.selr_startkey.len;
IF  ( prim_startkey.len > 0 )
THEN
    BEGIN
    SAPDB_PascalMove ('VKB73 ',  26,    
          sizeof( selrec.selr.selr_startkey.k ), sizeof( prim_startkey.k ),
          @selrec.selr.selr_startkey.k, 1,
          @prim_startkey.k, 1,
          prim_startkey.len, e);
    istop := istop + [ primary_start ];
    END
ELSE
    prim_startkey.len := 0;
(*ENDIF*) 
prim_stopkey.len := selrec.selr.selr_stopkey.len;
IF  ( prim_stopkey.len > 0 )
THEN
    BEGIN
    SAPDB_PascalMove ('VKB73 ',  27,    
          sizeof( selrec.selr.selr_stopkey.k ), sizeof( prim_stopkey.k ),
          @selrec.selr.selr_stopkey.k, 1,
          @prim_stopkey.k, 1,
          prim_stopkey.len, e);
    istop := istop + [ primary_stop ];
    END;
&ifdef trace
(*ENDIF*) 
t01key( kb, 'primstartkey', prim_startkey  );
t01key( kb, 'primstopkey ', prim_stopkey  );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      k73sub_multindex (
            VAR m                : tgg00_MessBlock;
            VAR getrec           : tgg07_get_param;
            VAR selrec           : tgg07_select_param;
            VAR sel              : tgg00_SelectFieldsParam;
            VAR strat            : tgg07_StrategyInfo);
 
VAR
      _ok           : boolean;
      _ix           : tsp00_Int2;
      _stpos        : tsp00_Int2;
      _ftrees       : tgg00_TwoFileIds;
      _subqtree_id  : tgg00_FileId;
      _keypair      : tgg00_TwoKeys;
      _stopkeys     : tgg00_TwoKeys;
      _m_key        : tgg00_Lkey;
      _aux_error    : tgg00_BasisError;
      _istop        : tgg00_BdInvSet;
 
BEGIN
_aux_error := e_ok;
_stpos     := 0;
_ix        := 0;
WHILE ( _ix <= strat.str_inv_in_range.siir_startcnt - 1 ) AND
      ( _aux_error = e_ok ) DO
    IF  ( m.mb_st^[ strat.str_inv_in_range.siir_invstart[ _ix ] ].etype =
        st_dummy) AND
        ( m.mb_st^[ strat.str_inv_in_range.siir_invstart[ _ix ] + 1 ].etype =
        st_bool )
    THEN
        (* no records in subquery - file *)
        _aux_error := e_no_next_record
    ELSE
        IF  ( m.mb_st^[ strat.str_inv_in_range.siir_invstart[ _ix ] + 1 ].etype =
            st_subquery )
        THEN
            BEGIN
            _stpos := strat.str_inv_in_range.siir_invstart[ _ix ];
            _ix    := strat.str_inv_in_range.siir_startcnt;
            END
        ELSE
            _ix := succ( _ix );
        (*ENDIF*) 
    (*ENDIF*) 
(*ENDWHILE*) 
&ifdef trace
t01int4 (kb, '_stpos      ', _stpos);
&endif
IF  ( _aux_error = e_ok )
THEN
    BEGIN
    g04index_tree_build( m.mb_qual^.mtree, _ftrees.inv_id,
          strat.str_inv_in_range.siir_indexno );
    _ftrees.inv_id.fileRoot_gg00 := strat.str_inv_in_range.siir_invroot;
    _ftrees.file_id := m.mb_qual^.mtree;
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        IF  ( _stpos <> 0 )
        THEN
            BEGIN
            _m_key.len := 0;
            SAPDB_PascalMove ('VKB73 ',  28,    
                  m.mb_data_size, sizeof (_subqtree_id),
                  @m.mb_data^.mbp_buf, m.mb_st^[ _stpos + 1 ].epos,
                  @_subqtree_id, 1, FILE_ID_MXGG00, m.mb_trns^.trError_gg00);
            END;
        (*ENDIF*) 
        WHILE ( m.mb_trns^.trError_gg00 = e_ok ) AND
              ( _aux_error = e_ok ) DO
            BEGIN
            IF  ( _stpos <> 0 )
            THEN
                g04read_subquery( m.mb_trns^, selrec.selr_selectbuffer.result,
                      _subqtree_id, _m_key, _aux_error, _ok )
            ELSE
                BEGIN
                _aux_error := e_no_next_record;
                _ok        := true;
                END;
            (*ENDIF*) 
            IF  ( _ok )
            THEN
                BEGIN
                _istop := [ secondary_stop ];
                k73prim_key_build( selrec, _keypair.reckey,
                      _stopkeys.reckey, _istop, m.mb_trns^.trError_gg00 );
                IF  ( m.mb_trns^.trError_gg00 = e_ok )
                THEN
                    BEGIN
                    gg04one_subq_limitinvkey( m,
                          selrec.selr_selectbuffer.result,
                          strat.str_inv_in_range, _keypair.listkey, true );
                    gg04one_subq_limitinvkey( m,
                          selrec.selr_selectbuffer.result,
                          strat.str_inv_in_range, _stopkeys.listkey, false );
                    (* might return e_move_error *)
                    IF  ( m.mb_trns^.trError_gg00 = e_ok )
                    THEN
                        kb73check_one_intern_invlist( m, getrec,
                              selrec, sel, strat, _ftrees,
                              _keypair, _stopkeys, _istop,
                              c_build_result,
                              c_finding_possible );
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDWHILE*) 
        END;
    (*ENDIF*) 
    IF  ( a01diag_monitor_on )
    THEN
        IF  ( m.mb_trns^.trBdTcachePtr_gg00 <> NIL ) AND
            ( _ftrees.inv_id.fileTfn_gg00 = tfnMulti_egg00 )    AND
            ( _ftrees.inv_id.fileRoot_gg00 <> NIL_PAGE_NO_GG00 )
        THEN
            b21mp_root_put( m.mb_trns^.trBdTcachePtr_gg00,
                  _ftrees.inv_id.fileRoot_gg00 );
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k73_index_range (
            VAR m                : tgg00_MessBlock;
            VAR getrec           : tgg07_get_param;
            VAR selrec           : tgg07_select_param;
            VAR selfields        : tgg00_SelectFieldsParam;
            VAR gg_strategy      : tgg07_StrategyInfo;
            VAR finding_possible : boolean);
 
VAR
      _rec_count    : tsp00_Int4;
      _ftrees       : tgg00_TwoFileIds;
      _startkeys    : tgg00_TwoKeys;
      _stopkeys     : tgg00_TwoKeys;
      _istop        : tgg00_BdInvSet;
      _create_error : tgg00_BasisError;
      _tmp_key      : tgg00_Lkey;
 
BEGIN
IF  (gg_strategy.str_strategy in a70glob_inv_build_strats )
THEN
    (* NON FETCH-strategies *)
    BEGIN
    g04index_tree_build( m.mb_qual^.mtree, selrec.selr.selr_inv_id,
          gg_strategy.str_inv_in_range.siir_indexno );
    selrec.selr.selr_inv_id.fileRoot_gg00 :=
          gg_strategy.str_inv_in_range.siir_invroot;
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        _ftrees.file_id        := m.mb_qual^.mtree;
        _ftrees.inv_id         := selrec.selr.selr_inv_id;
        selrec.selr.selr_invkey.len := 0;
        _istop := [  ];
        k73sec_key_build( m, gg_strategy.str_inv_in_range,
              _startkeys.listkey, _stopkeys.listkey,
              IS_UNDEFINED_GG07, -1, _istop, finding_possible );
        k73prim_key_build( selrec, _startkeys.reckey, _stopkeys.reckey,
              _istop, m.mb_trns^.trError_gg00 );
        kb73check_one_intern_invlist( m, getrec,
              selrec, selfields, gg_strategy,
              _ftrees, _startkeys, _stopkeys, _istop,
              c_build_result, finding_possible )
        END
    (*ENDIF*) 
    END
ELSE
    (* FETCH-strategies *)
    BEGIN
    _rec_count   := 0;
    g04index_tree_build( m.mb_qual^.mtree, selrec.selr.selr_inv_id,
          gg_strategy.str_inv_in_range.siir_indexno );
    selrec.selr.selr_inv_id.fileRoot_gg00 :=
          gg_strategy.str_inv_in_range.siir_invroot;
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        _istop                 := [  ];
        _ftrees.file_id        := m.mb_qual^.mtree;
        ;
        k73sec_key_build( m, gg_strategy.str_inv_in_range, _startkeys.listkey,
              _stopkeys.listkey, IS_UNDEFINED_GG07, -1,
              _istop, finding_possible );
        IF  ( isp_order_support_reverse in gg_strategy.str_inv_in_range.
            siir_strat_props )
        THEN
            BEGIN
            (* swap start/stop key *)
            _tmp_key           := _startkeys.listkey;
            _startkeys.listkey := _stopkeys.listkey;
            _stopkeys.listkey  := _tmp_key;
&           ifdef trace
            t01sname(kb, 'reverse acc ' );
            t01key (kb, 'start list  ', _startkeys.listkey);
            t01key (kb, 'stop  list  ', _stopkeys.listkey);
&           endif
            END;
        (*ENDIF*) 
        k73prim_key_build( selrec, _startkeys.reckey, _stopkeys.reckey,
              _istop, m.mb_trns^.trError_gg00 );
        ;
        _ftrees.inv_id         := selrec.selr.selr_inv_id;
        selrec.selr.selr_invkey.len := _startkeys.listkey.len;
        IF  ( _startkeys.listkey.len > 0 )
        THEN
            SAPDB_PascalMove ('VKB73 ',  29,    
                  sizeof(_startkeys.listkey.k), sizeof(selrec.selr.selr_invkey.k),
                  @_startkeys.listkey.k, 1, @selrec.selr.selr_invkey.k, 1,
                  _startkeys.listkey.len, m.mb_trns^.trError_gg00);
        (*ENDIF*) 
        IF  ( m.mb_trns^.trError_gg00 = e_ok )
        THEN
            BEGIN
            IF  ( gg_strategy.str_strategy = strat_inv_range_merge_fetch )
            THEN
                BEGIN
                IF  ( NOT selrec.selr.selr_count_bd )
                THEN
                    kb73create_temp_invfile( m.mb_trns^, _ftrees.inv_id, 0 );
                (*ENDIF*) 
                _create_error := m.mb_trns^.trError_gg00;
                IF  ( m.mb_trns^.trError_gg00 = e_ok ) AND finding_possible
                THEN
                    BEGIN
                    b03MergeInvLists( m.mb_trns^, selrec.selr.selr_inv_id,
                          _ftrees.inv_id,  _startkeys, _stopkeys,
                          primary_stop in _istop, selrec.selr.selr_count_bd, _rec_count );
                    SAPDB_PascalFill ('VKB73 ',  30,    
                          sizeof( selrec.selr_selectbuffer.result.buf ),
                          @selrec.selr_selectbuffer.result.buf, 1,
                          selrec.selr.selr_recl, csp_defined_byte,
                          m.mb_trns^.trError_gg00 );
                    END;
                (*ENDIF*) 
                _istop := [  ];
                ;
                IF  ( _create_error = e_ok )
                THEN
                    BEGIN
                    IF  ( selrec.selr.selr_count_bd )
                    THEN
                        BEGIN
                        IF  ( m.mb_trns^.trError_gg00 = e_file_empty )
                        THEN
                            m.mb_trns^.trError_gg00 := e_ok
                        ELSE
                            selfields.sfp_act_cntresult :=
                                  selfields.sfp_act_cntresult + _rec_count;
                        (*ENDIF*) 
                        END
                    ELSE
                        kb73check_one_intern_invlist( m, getrec, selrec, selfields,
                              gg_strategy, _ftrees, _startkeys, _stopkeys, _istop,
                              NOT c_build_result, finding_possible )
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                _ftrees.inv_id := selrec.selr.selr_inv_id;
                ;
                kb73check_one_intern_invlist( m, getrec, selrec, selfields,
                      gg_strategy, _ftrees, _startkeys, _stopkeys, _istop,
                      NOT c_build_result, finding_possible );
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  ( a01diag_monitor_on )
THEN
    IF  ( m.mb_trns^.trBdTcachePtr_gg00 <> NIL )
    THEN
        IF  ( _ftrees.inv_id.fileTfn_gg00 = tfnMulti_egg00 ) AND
            ( _ftrees.inv_id.fileRoot_gg00 <> NIL_PAGE_NO_GG00 )
        THEN
            b21mp_root_put( m.mb_trns^.trBdTcachePtr_gg00,
                  _ftrees.inv_id.fileRoot_gg00 )
        ELSE
            IF  ( selrec.selr.selr_inv_id.fileTfn_gg00 = tfnMulti_egg00 ) AND
                ( selrec.selr.selr_inv_id.fileRoot_gg00 <> NIL_PAGE_NO_GG00 )
            THEN
                b21mp_root_put( m.mb_trns^.trBdTcachePtr_gg00,
                      selrec.selr.selr_inv_id.fileRoot_gg00 );
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k73in_multindex (
            VAR m      : tgg00_MessBlock;
            VAR getrec : tgg07_get_param;
            VAR selrec : tgg07_select_param;
            VAR sel    : tgg00_SelectFieldsParam;
            VAR strat  : tgg07_StrategyInfo);
 
VAR
      _finding_poss : boolean;
      _ix           : tsp00_Int2;
      _dummy_cnt    : tsp00_Int2;
      _stpos        : tsp00_Int2;
      _keypair      : tgg00_TwoKeys;
      _stopkeys     : tgg00_TwoKeys;
      _ftrees       : tgg00_TwoFileIds;
      _istop        : tgg00_BdInvSet;
 
BEGIN
&ifdef trace
t01int4 (kb, 'inelemcnt   ', strat.str_inv_in_range.siir_inelemcnt );
&endif
_dummy_cnt    := 0;
_finding_poss := true;
g04index_tree_build( m.mb_qual^.mtree, _ftrees.inv_id,
      strat.str_inv_in_range.siir_indexno );
_ftrees.inv_id.fileRoot_gg00 := strat.str_inv_in_range.siir_invroot;
_ftrees.file_id := m.mb_qual^.mtree;
_stpos := strat.str_inv_in_range.siir_IN_SUBQ_stpos;
_ix    := 1;
WHILE ( _ix <= strat.str_inv_in_range.siir_inelemcnt ) AND
      ( m.mb_trns^.trError_gg00 = e_ok ) DO
    BEGIN
    IF  ( m.mb_st^[ _stpos + _ix + _dummy_cnt ].etype <> st_dummy )
    THEN
        BEGIN
&       ifdef trace
        t01stackentry (kb, m.mb_st^[ _stpos + _ix + _dummy_cnt ],  _stpos + _ix + _dummy_cnt );
&       endif
        IF  (( m.mb_st^[ _stpos + _ix + _dummy_cnt ].etype = st_op ) AND
            ( m.mb_st^[ _stpos + _ix + _dummy_cnt ].eop = op_in ))
        THEN
            (* make procedure fault tolerant, leave WHILE *)
            _ix := strat.str_inv_in_range.siir_inelemcnt + 1
        ELSE
            BEGIN
            _istop := [  ];
            k73prim_key_build( selrec, _keypair.reckey, _stopkeys.reckey,
                  _istop, m.mb_trns^.trError_gg00 );
            IF  ( m.mb_trns^.trError_gg00 = e_ok )
            THEN
                BEGIN
                k73sec_key_build( m, strat.str_inv_in_range, _keypair.listkey,
                      _stopkeys.listkey,
                      strat.str_inv_in_range.siir_IN_SUBQ_stpos,
                      _ix + _dummy_cnt, _istop,
                      _finding_poss );
                kb73check_one_intern_invlist( m, getrec, selrec, sel,
                      strat, _ftrees, _keypair, _stopkeys, _istop,
                      c_build_result, _finding_poss )
                END;
            (*ENDIF*) 
            _ix := succ( _ix );
            END;
        (*ENDIF*) 
        END
    ELSE
        _dummy_cnt := succ( _dummy_cnt );
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
IF  ( a01diag_monitor_on )
THEN
    IF  ( m.mb_trns^.trBdTcachePtr_gg00 <> NIL )      AND
        ( _ftrees.inv_id.fileRoot_gg00 <> NIL_PAGE_NO_GG00 ) AND
        ( _ftrees.inv_id.fileTfn_gg00 = tfnMulti_egg00 )
    THEN
        b21mp_root_put( m.mb_trns^.trBdTcachePtr_gg00,
              _ftrees.inv_id.fileRoot_gg00 );
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k73_seq_search (
            VAR m            : tgg00_MessBlock;
            VAR selrec       : tgg07_select_param;
            VAR selfields    : tgg00_SelectFieldsParam;
            VAR gg_strategy  : tgg07_StrategyInfo;
            finding_possible : boolean);
 
CONST
      c_ignore_vwait = true;
 
VAR
      _is_not_ok     : boolean;
      _dummy_granted : tgg00_LockReqMode;
 
BEGIN
IF  ( finding_possible )
THEN
    BEGIN
    IF  ( gg_strategy.str_search_first )
    THEN
        BEGIN
        selfields.sfp_m_result_addr := @selrec.selr_selectbuffer.result;
        selfields.sfp_m_result_size := sizeof( selrec.selr_selectbuffer.result );
        selfields.sfp_m_result_len  := 0;
        ;
        b02kb_select_rec( m.mb_trns^, m.mb_qual^.mtree,
              selrec.selr.selr_startkey.keyVal_gg00,
              selrec.selr.selr_startkey.keyLen_gg00,
              selrec.selr.selr_stopkey.keyVal_gg00,
              selrec.selr.selr_stopkey.keyLen_gg00,
              sizeof( selrec.selr_selectbuffer.buf_rec ),
              @selrec.selr_selectbuffer.buf_rec, NOT c_ignore_vwait,
              selfields, m.mb_qual^.mstack_desc, _is_not_ok, _dummy_granted );
        ;
        IF  ( a01diag_monitor_on )
        THEN
            IF  ( m.mb_trns^.trBdTcachePtr_gg00 <> NIL )    AND
                ( m.mb_qual^.mtree.fileRoot_gg00 <> NIL_PAGE_NO_GG00 )
            THEN
                b21mp_root_put( m.mb_trns^.trBdTcachePtr_gg00,
                      m.mb_qual^.mtree.fileRoot_gg00 );
            (*ENDIF*) 
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
ELSE
    m.mb_trns^.trError_gg00 := e_no_next_record;
(*ENDIF*) 
kb73fill_result( m, selrec, selfields,
      selrec.selr.selr_startkey, selrec.selr.selr_startkey,
      selrec.selr.selr_stopkey, selrec.selr.selr_stopkey,
      m.mb_qual^.mtree, b01niltree_id,
      NOT c_with_inv, gg_strategy );
END;
 
(*------------------------------*) 
 
PROCEDURE
      k73select_invrec (
            VAR m                   : tgg00_MessBlock;
            VAR ftrees              : tgg00_TwoFileIds;
            VAR start_keypair       : tgg00_TwoKeys;
            VAR stop_keypair        : tgg00_TwoKeys;
            VAR startkey            : tgg00_Lkey;
            stop                    : tgg00_BdInvSet;
            VAR b                   : tgg00_Rec;
            VAR selfields           : tgg00_SelectFieldsParam;
            VAR result_buf          : tsp00_Buf;
            new_inv_not_found_error : tgg00_BasisError);
 
VAR
      _dummy_mode : tgg00_LockReqMode;
 
BEGIN
selfields.sfp_m_result_addr := @result_buf;
selfields.sfp_m_result_size := sizeof (result_buf);
selfields.sfp_m_result_len  := 0;
(* h.b. PTS 11042106 *)
b03select_invrec( m.mb_trns^, ftrees, start_keypair, stop_keypair,
      startkey, stop, sizeof( b ), @b, selfields, m.mb_qual^.mstack_desc,
      _dummy_mode, c_usage_count );
;
IF  ( m.mb_trns^.trError_gg00 = e_inv_list_not_found )
THEN
    m.mb_trns^.trError_gg00 := new_inv_not_found_error
ELSE
    IF  ( m.mb_trns^.trError_gg00 = e_no_next_invkey )
    THEN
        m.mb_trns^.trError_gg00 := e_no_next_record;
    (*ENDIF*) 
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
