.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-10-31
*****************************************************
modname : VKB721
changed : 2000-10-31
module  : Single_Select_Part2
 
Author  : ElkeZ
Created : 1987-09-22
*****************************************************
 
Purpose : Search in one table using the strategy
          information build in AK
 
Define  :
 
        PROCEDURE
              k721add_into_result (
                    VAR t                : tgg00_TransContext;
                    VAR selrec           : tgg07_select_param;
                    VAR next_mblock      : tgg00_MessBlockPtr);
 
        PROCEDURE
              k721call_later_output (
                    VAR m       : tgg00_MessBlock;
                    VAR res_buf : tsp00_Buf;
                    keylen      : integer);
 
        PROCEDURE
              k721do_avg (
                    VAR m        : tgg00_MessBlock;
                    VAR selrec   : tgg07_select_param;
                    later_output : boolean;
                    keylen       : integer);
 
        PROCEDURE
              k721do_rowno (
                    VAR m      : tgg00_MessBlock;
                    VAR selrec : tgg07_select_param);
 
        PROCEDURE
              k721eval_pagecount (VAR m : tgg00_MessBlock);
 
        PROCEDURE
              k721null_result (
                    VAR m         : tgg00_MessBlock;
                    VAR selrec    : tgg07_select_param;
                    VAR sel       : tgg00_SelectFieldsParam;
                    act_cntresult : tsp00_Int4;
                    later_output  : boolean;
                    h_keylen      : integer);
 
        PROCEDURE
              k721catalog_add_into_result (
                    VAR m           : tgg00_MessBlock;
                    VAR sel         : tgg00_SelectFieldsParam;
                    VAR selrec      : tgg07_select_context;
                    VAR getrec      : tgg07_get_param;
                    VAR result_rec  : tgg00_Rec;
                    VAR one_res_rec : tgg00_Rec;
                    VAR res_cnt     : tsp00_Int4);
 
        PROCEDURE
              k721read_subquery (VAR m : tgg00_MessBlock);
 
        PROCEDURE
              k721strat_distribution (
                    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
              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 selfields    : tgg00_SelectFieldsParam);
 
        PROCEDURE
              k721function_add (
                    VAR m      : tgg00_MessBlock;
                    VAR selrec : tgg07_select_param;
                    aggr       : boolean);
 
        PROCEDURE
              k721Merge_ForAggregate (
                    M           : tgg00_MessBlockPtr;
                    SelRec      : tgg07_SelectParamPtr;
                    Source      : tgg00_VoidPtr;
                    Destination : tgg00_VoidPtr;
                    Length      : tsp00_Int2;
                    Merge       : boolean);
 
        FUNCTION
              k721GetKeyAndRecInfo_ForAggregate(
                    VAR RecLength    : tsp00_Int2;
                    VAR KeyCount     : tsp00_Int2;
                    KeyOffset        : tgg00_VoidPtr;
                    KeyLength        : tgg00_VoidPtr;
                    MaxKeys          : tsp00_Int2) : boolean;
 
        FUNCTION
              k721out_entry (
                    st_addr     : tgg00_StackListPtr;
                    start_entry : integer) : integer;
 
        PROCEDURE
              k721longcol_insert_select (
                    VAR m              : tgg00_MessBlock;
                    VAR result         : tgg00_Rec;
                    VAR resf_id        : tgg00_FileId);
 
        PROCEDURE
              k721stddev (
                    trans        : tgg00_TransContextPtr;
                    VAR dist_file: tgg00_FileId;
                    VAR result   : tgg00_Rec;
                    VAR buf1     : tgg00_Rec;
                    VAR buf2     : tsp00_Buf;
                    func         : tgg00_StackOpFunc;
                    outpos       : integer);
 
.CM *-END-* define --------------------------------------
***********************************************************
 
Use     :
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01diag_monitor_on : boolean;
 
      ------------------------------ 
 
        FROM
              Build_Strategy : VAK70;
 
        VAR
              a70glob_key_build_strats   : tgg07_StratEnumSet;
              a70glob_inv_build_strats   : tgg07_StratEnumSet;
 
      ------------------------------ 
 
        FROM
              KB_stringcol_copy_trunc_expand :  vkb43;
 
        PROCEDURE
              k43_ins_copy_column (
                    VAR mtrans            : tgg00_TransContextPtr;
                    VAR mheader           : tgg00_MessBufHeader;
                    VAR src_tree          : tgg00_FileId;
                    VAR dst_tree          : tgg00_FileId;
                    VAR src_tab_id        : tgg00_Surrogate;
                    VAR src_surr          : tgg00_Surrogate;
                    VAR dst_surr          : tgg00_Surrogate;
                    dst_has_shrt_col_file : boolean;
                    VAR shrt_col_rec_ptr  : tgg00_RecPtr;
                    use_shrt_col_rec      : boolean);
 
      ------------------------------ 
 
        FROM
              KB_trans_state : VKB50;
 
        PROCEDURE
              k50hash (
                    VAR buf    : tsp00_Buf;
                    pos        : tsp00_Int4;
                    len        : tsp00_Int4;
                    VAR resbuf : tsp00_Buf;
                    respos     : integer);
 
      ------------------------------ 
 
        FROM
              KB_transaction : VKB53;
 
        PROCEDURE
              k53wait (
                    VAR t     : tgg00_TransContext;
                    MessType  : tgg00_MessType;
                    MessType2 : tgg00_MessType2);
 
      ------------------------------ 
 
        FROM
              KB_ins_del_upd : VKB61;
 
        PROCEDURE
              k61del_select (
                    VAR m          : tgg00_MessBlock;
                    VAR old_k      : tgg00_Lkey;
                    VAR old_rec    : tgg00_Rec;
                    granted_lock   : tgg00_LockReqMode);
 
        PROCEDURE
              k61ins_select (
                    VAR m       : tgg00_MessBlock;
                    VAR new_rec : tgg00_Rec;
                    is_nokey    : boolean;
                    upd_dupl    : boolean;
                    rec_count   : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              KB_inv_link_trigger_handling : VKB62;
 
        PROCEDURE
              k62late_unique_check (VAR m : tgg00_MessBlock);
 
      ------------------------------ 
 
        FROM
              KB_update : VKB63;
 
        PROCEDURE
              k63upd_select (
                    VAR m               : tgg00_MessBlock;
                    VAR rec_key         : tgg00_Lkey;
                    VAR old_rec         : tgg00_Rec;
                    sel_addr            : tgg00_SelectParamPtr;
                    result_ptr          : tsp00_MoveObjPtr;
                    result_len          : tsp00_Int4;
                    VAR new_rec         : tsp00_Buf;
                    VAR key_upd_file_id : tgg00_FileId;
                    granted_lock        : tgg00_LockReqMode);
 
      ------------------------------ 
 
        FROM
              KB_get : VKB71;
 
        PROCEDURE
              k71sel_qualification_test (
                    VAR m          : tgg00_MessBlock;
                    VAR sel        : tgg00_SelectFieldsParam;
                    check_new_rec  : boolean;
                    VAR rec        : tgg00_Rec);
 
      ------------------------------ 
 
        FROM
              Single_Select : VKB73;
 
        PROCEDURE
              k73_index_range (
                    VAR m                : tgg00_MessBlock;
                    VAR getrec           : tgg07_get_param;
                    VAR selrec           : tgg07_select_param;
                    VAR sel              : tgg00_SelectFieldsParam;
                    VAR strat            : 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
              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);
 
      ------------------------------ 
 
        FROM
              KB_Join_Select : VKB74;
 
        PROCEDURE
              k74join_with_left_result (
                    VAR m           : tgg00_MessBlock;
                    VAR getrec      : tgg07_get_param;
                    VAR sel         : tgg00_SelectFieldsParam;
                    VAR selrec      : tgg07_select_param);
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vdebug_break (debug_break_pos : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01fullkey    : tsp00_Key;
 
        PROCEDURE
              bd01CalculateRecordsAndLeaves(
                    VAR Trans           : tgg00_TransContext;
                    VAR FileId          : tgg00_FileId;
                    VAR NumberOfLeaves  : tsp00_Int4;
                    VAR NumberOfRecords : tsp00_Int4 );
 
      ------------------------------ 
 
        FROM
              filesysteminterface_2 : VBD02;
 
        PROCEDURE
              b02calculate_page_count (
                    VAR t            : tgg00_TransContext;
                    VAR file_id      : tgg00_FileId;
                    VAR startkey     : tgg00_Lkey;
                    VAR stopkey      : tgg00_Lkey;
                    VAR page_count   : tsp00_Int4);
 
        PROCEDURE
              b02eval_page_count (
                    VAR t            : tgg00_TransContext;
                    VAR file_id      : tgg00_FileId;
                    VAR startkey     : tgg00_Lkey;
                    VAR stopkey      : tgg00_Lkey;
                    count_records    : boolean;
                    VAR page_count   : tsp00_Int4;
                    VAR min_page_cnt : tsp00_Int4;
                    VAR record_cnt   : tsp00_Int4);
 
        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);
 
        PROCEDURE
              b02next_record (
                    VAR t       : tgg00_TransContext;
                    VAR file_id : tgg00_FileId;
                    VAR rk      : tgg00_Lkey;
                    inclusive   : boolean;
                    VAR b       : tgg00_Rec);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_3 : VBD03;
 
        PROCEDURE
              b03calculate_page_count (
                    VAR t            : tgg00_TransContext;
                    VAR file_id      : tgg00_FileId;
                    VAR startkey     : tgg00_Lkey;
                    VAR stopkey      : tgg00_Lkey;
                    count_records    : boolean;
                    VAR page_count   : tsp00_Int4;
                    VAR min_page_cnt : tsp00_Int4;
                    VAR record_cnt   : tsp00_Int4);
 
        PROCEDURE
              b03select_invrec (
                    VAR t            : tgg00_TransContext;
                    VAR file_ids     : tgg00_TwoFileIds;
                    VAR keypair      : tgg00_TwoKeys;
                    VAR stop_keypair : tgg00_TwoKeys;
                    VAR start_key    : 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;
                    count_usage      : boolean);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_7 : VBD07;
 
        PROCEDURE
              b07cadd_record (
                    VAR t           : tgg00_TransContext;
                    VAR act_tree_id : tgg00_FileId;
                    VAR b           : tsp00_Buf);
 
        PROCEDURE
              b07cappend_record (
                    VAR t        : tgg00_TransContext;
                    VAR file_id  : tgg00_FileId;
                    VAR tree_pos : tgg00_FilePos;
                    VAR b        : tsp00_Buf);
 
        PROCEDURE
              b07cnext_record (
                    VAR t           : tgg00_TransContext;
                    VAR act_tree_id : tgg00_FileId;
                    VAR rk          : tgg00_Lkey;
                    VAR set_result  : tgg00_BdSetResultRecord;
                    VAR tree_pos    : tgg00_FilePos;
                    VAR b           : tsp00_Buf);
 
        PROCEDURE
              b07ctget_record (VAR t : tgg00_TransContext;
                    VAR file_id  : tgg00_FileId;
                    VAR tree_pos : tgg00_FilePos;
                    VAR rk       : tgg00_Lkey;
                    VAR b        : tsp00_Buf);
 
        PROCEDURE
              b07ctrepl_record (
                    VAR t           : tgg00_TransContext;
                    VAR act_tree_id : tgg00_FileId;
                    VAR tree_pos    : tgg00_FilePos;
                    VAR b           : tsp00_Buf);
 
      ------------------------------ 
 
        FROM
              task_temp_data_cache : VBD21;
 
        PROCEDURE
              b21mp_root_put (
                    temp_cache_ptr : tgg00_TempDataCachePtr;
                    root : tsp00_PageNo);
 
      ------------------------------ 
 
        FROM
              ref_statistic : VBD73;
 
        PROCEDURE
              b73cmd_count (statement_kind : tgg00_RefInfoIndex);
 
        PROCEDURE
              b73cmds_count (
                    statement_kind : tgg00_RefInfoIndex;
                    count : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01code : tgg04_CodeGlobals;
              g01glob : tgg00_KernelGlobals;
&       ifdef trace
 
        PROCEDURE
              g01abort (
                    msg_no     : tsp00_Int4;
                    msg_label  : tsp00_C8 ;
                    msg_text   : tsp00_C24;
                    bad_value  : tsp00_Int4);
&       endif
 
      ------------------------------ 
 
        FROM
              Select_Help_Procedures : VGG04;
 
        PROCEDURE
              g04index_tree_build (
                    VAR file_id    : tgg00_FileId;
                    VAR index_tree : tgg00_FileId;
                    index_no       : tsp00_Int2);
 
        FUNCTION
              g04inv_tfn (tfn : tgg00_Tfn) : boolean;
 
        PROCEDURE
              g04limitprimkeys (
                    VAR m           : tgg00_MessBlock;
                    VAR startkeyarr : tgg07_ColPosArr;
                    VAR start_key   : tgg00_Lkey;
                    VAR stopkeyarr  : tgg07_ColPosArr;
                    VAR stop_key    : tgg00_Lkey;
                    VAR use_stopkey : boolean;
                    in_stpos_hint   : tsp00_Int2;
                    in_value_idx    : tsp00_Int2);
 
        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
              gg04one_subq_limitprimkey (
                    VAR mblock      : tgg00_MessBlock;
                    VAR subq_buf    : tgg00_Rec;
                    VAR keyarr      : tgg07_ColPosArr;
                    VAR one_key     : tgg00_Lkey;
                    VAR use_stopkey : boolean);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalOverlappingMove (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    source_upb  : tsp00_Int4;
                    dest_upb    : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    src_pos     : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    dest_pos    : tsp00_Int4;
                    length      : tsp00_Int4;
                    VAR e       : tgg00_BasisError);
 
        PROCEDURE
              SAPDB_PascalForcedFill (
                    size     : tsp00_Int4;
                    m        : tsp00_MoveObjPtr;
                    pos      : tsp00_Int4;
                    len      : tsp00_Int4;
                    fillchar : char);
 
        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-20 : VSP20;
 
        PROCEDURE
              s20ch4sw (
                    val        : tsp00_Int4;
                    sourceswap : tsp00_SwapKind;
                    VAR dest   : tgg00_RecBody;
                    di         : tsp00_Int4;
                    destswap   : tsp00_SwapKind);
 
        FUNCTION
              s20or4sw (
                    VAR source     : tsp00_Buf;
                    si             : tsp00_Int4;
                    sourceswap     : tsp00_SwapKind;
                    destswap       : tsp00_SwapKind) : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              RTE-Extension-30 : VSP30;
 
        PROCEDURE
              s30cmp (
                    VAR buf1     : tsp00_Buf;
                    fieldpos1    : tsp00_Int4;
                    fieldlength1 : tsp00_Int4;
                    VAR buf2     : tsp00_Buf;
                    fieldpos2    : tsp00_Int4;
                    fieldlength2 : tsp00_Int4;
                    VAR l_result : tsp00_LcompResult);
 
      ------------------------------ 
 
        FROM
              GET-Conversions : VSP40;
 
        PROCEDURE
              s40g4int (
                    VAR buf     : tsp00_Buf;
                    pos         : tsp00_Int4;
                    VAR dest    : tsp00_Int4;
                    VAR res     : tsp00_NumError);
 
      ------------------------------ 
 
        FROM
              PUT-Conversions : VSP41;
 
        PROCEDURE
              s41plint (
                    VAR buf     : tsp00_Buf;
                    pos         : tsp00_Int4;
                    len         : integer;
                    frac        : integer;
                    source      : tsp00_Int4;
                    VAR res     : tsp00_NumError);
 
        PROCEDURE
              s41p4int (
                    VAR buf     : tsp00_Buf;
                    pos         : tsp00_Int4;
                    source      : tsp00_Int4;
                    VAR res     : tsp00_NumError);
 
      ------------------------------ 
 
        FROM
              Number-Arithmetic : VSP51;
 
        PROCEDURE
              s51add (
                    VAR left       : tsp00_Buf;
                    lpos           : tsp00_Int4;
                    llen           : integer;
                    VAR right      : tsp00_Buf;
                    rpos           : tsp00_Int4;
                    rlen           : integer;
                    VAR result     : tsp00_Buf;
                    respos         : tsp00_Int4;
                    reslen         : integer;
                    resfrac        : integer;
                    VAR resbytelen : integer;
                    VAR ret        : tsp00_NumError);
 
        PROCEDURE
              s51sub (
                    VAR left       : tsp00_Buf;
                    lpos           : tsp00_Int4;
                    llen           : integer;
                    VAR right      : tsp00_Buf;
                    rpos           : tsp00_Int4;
                    rlen           : integer;
                    VAR result     : tsp00_Buf;
                    respos         : tsp00_Int4;
                    reslen         : integer;
                    resfrac        : integer;
                    VAR resbytelen : integer;
                    VAR ret        : tsp00_NumError);
 
        PROCEDURE
              s51mul (
                    VAR left       : tsp00_Buf;
                    lpos           : tsp00_Int4;
                    llen           : integer;
                    VAR right      : tsp00_Buf;
                    rpos           : tsp00_Int4;
                    rlen           : integer;
                    VAR result     : tsp00_Buf;
                    respos         : tsp00_Int4;
                    reslen         : integer;
                    resfrac        : integer;
                    VAR resbytelen : integer;
                    VAR ret        : tsp00_NumError);
 
        PROCEDURE
              s51div (
                    VAR left       : tsp00_Buf;
                    lpos           : tsp00_Int4;
                    llen           : integer;
                    VAR right      : tgg00_Rec;
                    rpos           : tsp00_Int4;
                    rlen           : integer;
                    VAR result     : tgg00_Rec;
                    respos         : tsp00_Int4;
                    reslen         : integer;
                    resfrac        : integer;
                    VAR resbytelen : integer;
                    VAR ret        : tsp00_NumError);
 
      ------------------------------ 
 
        FROM
              Exponential-Functions: VSP52;
 
        PROCEDURE
              s52sqrt (
                    VAR source     : tsp00_Buf;
                    spos           : tsp00_Int4;
                    slen           : integer;
                    VAR result     : tsp00_Buf;
                    respos         : tsp00_Int4;
                    reslen         : integer;
                    resfrac        : integer;
                    VAR ret        : tsp00_NumError);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01bool (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    curr_bool: boolean);
 
        PROCEDURE
              t01sname (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname);
 
        PROCEDURE
              t01key (
                    debug   : tgg00_Debug;
                    nam     : tsp00_Sname;
                    VAR k   : tgg00_Lkey);
 
        PROCEDURE
              t01treeid (
                    debug      : tgg00_Debug;
                    nam        : tsp00_Sname;
                    VAR treeid : tgg00_FileId);
 
        PROCEDURE
              t01basis_error (
                    layer : tgg00_Debug;
                    nam   : tsp00_Sname;
                    b_err : tgg00_BasisError);
 
        PROCEDURE
              t01int4 (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01buf  (
                    level     : tgg00_Debug;
                    VAR buf   : tsp00_Buf;
                    pos_start : integer;
                    pos_end   : integer);
 
        PROCEDURE
              t01name (
                    debug : tgg00_Debug;
                    nam  : tsp00_Name);
 
        PROCEDURE
              t01messblock (
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    VAR m         : tgg00_MessBlock);
 
        PROCEDURE
              t01stackentry (
                    debug          : tgg00_Debug;
                    VAR st         : tgg00_StackEntry;
                    entry_index    : integer);
&       endif
 
      ------------------------------ 
 
        FROM
              Unionhandling: VKB722;
 
        PROCEDURE
              k722_add_union_record (
                    VAR t        : tgg00_TransContext;
                    VAR selrec   : tgg07_select_param);
 
      ------------------------------ 
 
        FROM
              KB_Fetch: VKB75;
 
        PROCEDURE
              k75pre_fetch (
                    VAR t        : tgg00_TransContext;
                    VAR tree_id  : tgg00_FileId;
                    VAR key      : tgg00_Lkey);
 
.CM *-END-* use -----------------------------------------
***********************************************************
 
Synonym :
 
        PROCEDURE
              b07cadd_record;
 
              tgg00_Rec tsp00_Buf
 
        PROCEDURE
              b07cappend_record;
 
              tgg00_Rec tsp00_Buf
 
        PROCEDURE
              b07ctget_record;
 
              tgg00_Rec tsp00_Buf
 
        PROCEDURE
              b07ctrepl_record;
 
              tgg00_Rec tsp00_Buf
 
        PROCEDURE
              b07cnext_record;
 
              tsp00_MoveObj tsp00_Buf
 
        PROCEDURE
              k63upd_select;
 
              tgg00_Rec  tsp00_Buf
 
        PROCEDURE
              s20ch4sw;
 
              tsp00_MoveObj tgg00_RecBody
 
        FUNCTION
              s20or4sw;
 
              tsp00_MoveObj tsp00_Buf
 
        PROCEDURE
              s30cmp;
 
              tsp00_MoveObj tsp00_Buf
 
        PROCEDURE
              s40g4int;
 
              tsp00_MoveObj tsp00_Buf
 
        PROCEDURE
              s41plint;
 
              tsp00_MoveObj tsp00_Buf
 
        PROCEDURE
              s41p4int;
 
              tsp00_MoveObj tsp00_Buf
 
        PROCEDURE
              s51add;
 
              tsp00_MoveObj tsp00_Buf
 
        PROCEDURE
              s51sub;
 
              tsp00_MoveObj tsp00_Buf
 
        PROCEDURE
              s51mul;
 
              tsp00_MoveObj tsp00_Buf
 
        PROCEDURE
              s51div;
 
              tsp00_MoveObj tsp00_Buf
              tsp00_MoveObj tgg00_Rec
 
        PROCEDURE
              s52sqrt;
 
              tsp00_MoveObj tsp00_Buf
 
.CM *-END-* synonym -------------------------------------
***********************************************************
 
Specification:
 
K721DO_ROWNO
------------------------------------
 
If the rowno is supposed to appear in the output, due to 'distinct'
or 'order-by' data that might be present it is not
possible to immediately enter the rowno into the result record
when the result table is built while following the correct sequence.
The procedure catches up and the rowno is assigned in the output a
maximum of 32 times.
 
.CM *-END-* specification -------------------------------
***********************************************************
 
Description:
 
K721DO_AVG
------------------------------------
 
During the processing of single result records, only
the values needed for building the average (summed up)
and the number of results can be determined.
In this procedure the average values are formed out of these two
values when all records have been found.
All records that contain the totalled values are accessed in a
repeat loop.  Due to the group formation, there can be more than one of
these records.  If there is a maximum of one (no group formation,
keyl = 4), the summation record is present already in the buffer to which
otherwise
the records are being transferred from the file one after the other.
However, this record is not located in the file.
In a 'while' loop, all function stack entries are branched in.
A run-through of the stack entries is facilitated by the fact
that the last qualification stack entry and all the function stack
entries indicate how many stack entries there have been since the
previous function stack entry.
For AVG and SUM, there is a risk of an internal overflow, indicated
by the exponent 255 and the mantissa h'99 99 ..'.  A value that
has overflowed in this manner is now transferred to the NULL value.  The
NULL value cannot be entered immediately during the summation because it
would be overwritten by the value to be added during the next addition.
The average is formed from the sum (located at epos) and the
quantity of values located 11 bytes before the sum.  For the two values,
11 bytes are always available for the maximum numerical representation.
If a record has been updated (AVG formed or overflow handled),
it is replaced in the file or newly inserted.
 
K721DO_ROWNO
------------------------------------
 
After the result records have been sorted, rownos that are supposed
to appear in the output are entered here.
The positions in the result record at which the rowno value is to
be located are determined in the 1st 'while' loop and entered in
'rowarr'.  In the case of simple non-join-select, the position is
normally found in the stack entry (epos).
For join-selects, the epos gives the position for the single-table
intermediate result from which it (position onfrom) must be placed
in the total-join-result (position onto (position in buf.info) + 4).
The rowno value must therefore be written to the position onto+4.  If
several fields were combined in n_pos (onfrom < epos, onfrom+length > epos),
'onto' must still be altered by the distance from 'epos' to 'onfrom'.
 
In the repeat loop, all result records are retrieved.  The rowno
value, which is always processed as fixed(10,0) (greater values do
not fit in countresult : int4), is transferred to the first of the
desired positions and copied from there to the other positions.
The record in the file is replaced and the key of this record is
identified in hkey so that a further search can start from this key.
 
K721NULL_RESULT
------------------------------------
 
If the output list contains SET functions but no result record has
been generated because no record fulfilled the qualifications, a
Null record is generated.  This record contains the NULL value for all
fields except 'count' outputs, which are filled with 0 (represented
numerically by h'00 80 00 00 ..').  'Count' outputs are always 11 bytes
long.
 
KB721IN_KEYRECORD
------------------------------------
 
The strategy 'keyin' signifies an '=' or 'IN' condition on the
only key field.  'Cntin' indicates the number of IN values;
for '=', cntin is 1.  Cntin value stack entries are located right to
stpos (stack-entry position of the key-field stack entry).  A stack
entry can become st_dummy via G04_IN_BETWEEN_CHANGE.
The values are transferred one after another to startkey and further
processed by SELECT_GETS.
 
IN_INVLIST
------------------------------------
 
The strategy 'fieldin' signifies an '=' or IN condition on a singly
inverted field.
The inversion file name is formed that contains the userid and the
table name as does the primary file name but that has a different
identifier as its 1st byte and has as its 2nd byte the external column
number of the inverted field (located in ecol_tab[ 1 ] of the field
stack entry).
Cntin indicates the number of IN values; for '=', cntin is 1.
Cntin value stack entries are located right to stpos (stack entry
position of the field stack entries).  A stack entry can become
st_dummy via G04_IN_BETWEEN_CHANGE.
A special situation arises when '=' conditions have been entered
by the user as LIKE.  The value then appears three times in a
row in part2 (twice with a st_dummy stack entry and once with a value
stack entry).  This means that the first dummy stack entry can also be
used as a position indicator in part2.
The values are transferred one after another to invkey.  For indexes
that are set up in descending order, the value must be reversed.  This
means that the NULL values are always transformed to h'00', length 1;
all other values must be represented in the maximum length for this
field (specified in ecol_tab[ 2 ] of the field stack entry) so
that a correct sorting can be achieved.
The current field length (elen_var) can be greater than the
maximum possible length since the parameter is requested as float(18)
at 'numberfield = :param'.
For indexes that are set up in ascending order, NULL values are
used with the length 1 and values with variable fields are used with
their true length or with their maximum length (ecol_tab[ 2 ]).
 
MULTINV
------------------------------------
 
The strategy 'multindex' signifies '=' conditions or range conditions
('>','>=','<','<=', BETW, LIKE) on all or on the first x fields of a
named, multi-field index.  Named, single-field indexes are handled
as unnamed.
Via G04_MINDEX-KEY, the two secondary keys that define the
multiple 'range' (invkey, stopkey) are formed from the individual
field values.
Mi_equal = false indicates that only the first x fields of the
named index with the number index_no show a range or '=' condition.
This means that several inversion lists that all have the same
beginning must be processed.
 
INTERSECTINV
------------------------------------
 
The strategy 'intinv' signifies '=' conditions on more than one
singly inverted field.
The intersection of the associated inversion lists is formed in
K73_SINTER_SECTE, i.e. a new inversion list is formed in the
temporary file invfn which contains only primary keys
that were contained in all the inversion lists viewed, i.e. whose
records already fulfilled all the '=' conditions.
 
VIEWKEY_SEARCH
 
The strategy j_viewkey signifies that the qualification should be
tested for the primary key specified in part2 of the mess_buffer.
The key is transferred to act_key and further processed via
SELECT_GETS.
 
KB721SELECT_GETS
------------------------------------
 
In SELECT-GETS, depending on the mtype (= mm_direct, if calling
from IN_KEYRECORD; otherwise,
mm_first or mm_next), either the record identified by act_key is
found and processed directly or the next record (inclusive or
exclusive) with relation to act_key is found and processed.
Sel is the parameter that is passed on, up to the qualification
test.  Result_length describes the total length of the result
accumulated up until that time.  Since, unlike select, no fixed
output positions can be specified for insert-select, (variable length
fields and keys) and, therefore, the next field is appended to the
current record, the length must be set to 4 (2 bytes total length,
2 bytes key length) or to 4 + length of the syskey, which cannot
be ascertained by select.
Act_cntresult is required for rowno conditions.  The value
'countresult' sent back to the user is not yet updated since even
a record that has been found is not always included in the result,
depending on 'distinct' and the like.
For insert-select, the file version of the table to be searched
must be used.
The search, the qualification test and any locking of the record
that may be necessary occur in K71ALL_GET; for set updates
and set deletes, a write-lock is requested immediately.
If a lock request cannot be granted immediately (another process
has a contending lock, kb_wait_for_lock_release), it waits in K53WAIT
for the lock release or for the request timeout
value to elapse.
If everything is ok, the same record (act_key not updated) is again
searched and tested since it could have been deleted or updated in
the meantime.
During the direct search, errors such as e_key_not_found and
kb_qual/view_violation can occur and must not be allowed to cause
the entire search to be cancelled, i.e. they must be destroyed.
If a result record is found (e_ok) and there are more than one
strategy (intern_dist), an attempt is made to insert
the primary key in the help file.  If this fails (b_duplicate_key),
a result record was already formed from the same primary record and,
for this reason, it must not be inserted in the result file
(put_into = false).
Whereas it was unimportant for the search as a whole whether
processing was done for a set select, set update or set delete or an
insert-select, a different procedure must, of course, be followed when
a result record is used further.
For set updates and set deletes, the number of records processed
increases and the actual updating is executed by K61UPD_SELECT and
K61DEL_SELECT.
For insert-selects, the result record is completed
(total length of the record = len, keylen only if the length of the
user-specific key was not already assigned when the
record was built (is_nokey)).
The file version used is that of the file in which the insertion is
to be made and the insertion is executed via K61INS_SELECT.
Since the implicit locking of the key in the new file (totally
unrelated to the read lock on the primary record in the basetable)
can again lead to a wait state (kb_wait_for_lock_release),
the same procedure is applied as for the search.
For the next search, the file version of the search file is again
used (and overwritten by the other version only in the case of an error
since the other version is required for rollbacks in the insert file).
The number of records processed (countresult) is incremented only
if there were no problems; otherwise an error causes it to terminate if
the error message b_duplicate_key was not overridden by IGNORE DUPLICATES.
For set selects, the key length and total length (unlike
insert-select, fixed from very the beginning) are entered and, depending
on the degree of difficulty, inserted in the result file via
FUNCTION_ADD or K72_ADD_INTO_RESULT.
 
K72_ADD_INTO_RESULT
------------------------------------
 
The finished result record is located in selrec.result and should be
incorporated in the file result_fn/result_tr.
The incremented result counter is set at the end of the result key
(due to the ORDER_BY fields that could be contained in the key).
If the user specifies DISTINCT, a check is run in UNIQUE_ADD and,
if appropriate, the record is inserted.
If the second result record is being processed but a
SELECT .. INTO was requested, there is an error.
If only one result is expected, in many cases it does not need to
be buffered in the file (additional BD orders and I/O); there is space
in the count_buf, which is otherwise unused.
If keylen = 4, i.e. the result counter alone forms the key,
b02append_record can be used
(which is easier for BD than add_record)
since the insertion position 'all the way to the right' is already
established in the file by the counter notation
(highest-byte .. lowest-byte).
If the rowno_value (rowno < (=) value) is reached, the search is
terminated; however, this error is then destroyed in
K72_SINGLE_SELECT or VKB74 join_last_part because it is not an error
from the user's point of view but instead serves to end all loops.
 
UNIQUE_ADD
------------------------------------
 
The point is to recognize as quickly as possible whether a record
is 'distinct' from all the result records already present.  Therefore,
something is entered in the result key (after the ORDER-BY fields,
before the result counter) that serves as a type of hash value for
the entire record.  When DISTINCT is entered, the fields
specified in ORDER BY must also be output fields simultaneously,
i.e. they are also used to test distinctness.  For this reason, it
must be ensured that records with the same ORDER-BY values and
distinct 'hash' value immediately follow one another.  The record to
be examined has the highest result counter up to that point (end of
the key).  Therefore, starting from this key, a forward (previous)
search must be run in the result file until a record that appears
identical has been found or it has been determined that none can be
found because the beginning of the key (without result counter) looks
different from the record found for 'previous'.
The 'hash' value is formed by combining the hex values of up to
32 bytes that are evenly distributed throughout the record and packing
them into a 4-byte integer.
In the repeat loop, as many result records are retrieved as fit in
the buf_rec.buf at that particular time.  They are stored there as
follows:
 
 
      2    ||              ||
  ---------||--------------||
 | total   || result record||
 |  length ||              ||
  ---------||--------------||
           ||              ||
 
 
A result record has the following structure:
 
                |        keylen              |
    2      2        n       4         4       len-keylen-4
  --------------------------------------------------------
 | len | keylen | order  | hash  | result    | non-key    |
 |     |        | fields | value |  counter  |  fields    |
  --------------------------------------------------------
 
 
n stands for 0 - 248.
 
At the same time, B07CPREV_RECORD ensures that only those records
are transferred to the buffer that have the same key value (excl.
the result counter) as the current result record.  BD must carry out
this test if buf_rec.len > 0 (length to be compared).
If records have been supplied, they are examined until one
final statement on the distinctness of the new result record can be
established; not all records in the buffer necessarily have to be
examined.
The non-key fields of the records are compared.  If
they are equal (not_equal = false), the search is terminated.
The record must not be inserted.
The search is continued through several buffers, if appropriate,
until no other record is found in the result file with the same
key value (excl. the result counter).
If the record must be inserted, the result count is requested
as in K72_ADD_INTO_RESULT and, if appropriate, an error is sent.
Otherwise, the result count (already incremented in
K72_ADD_INTO_RESULT) must be lowered again.
 
FUNCTION_ADD
------------------------------------
 
This procedure is used to enter the MIN|MAX|SUM|COUNT values (AVG
is formed in DO_AVG) in result records, of which there can be more than
one due to GROUP BY.  (GROUP BY and ORDER BY requests entered
simultaneously by the user result in a series of K72_SINGLE_SELECT calls,
i.e. they do not have to be viewed simultaneously ]
The GROUP BY fields are located at the beginning of the
result-record key.  Manipulations in the key are always done with
h'00 00 00 01' as the result counter, since there is only one record
per group.
The current result record is located in 'result'.  The record
in which the function values are stored for one group, if it is already
present, is either located in count_buf (no GROUP BY specified) or is
transferred to this buffer.
If such a record does not yet exist for this group
(e_key_not_found), it is created new; for SELECT .. INTO, the number
of such buffers is again checked.
It is again assumed that the last qualification stack entry and
all function stack entries indicate how many positions there have been
since the previous function stack entry.
For DISTINCT AVG|SUM|COUNT, the existence of a particular combination
is registered in the help file specially created for this purpose by
inserting the group field values plus the current value as a key.
If there is an error (b_error <> e_ok), the entire KB processing must
be terminated; otherwise, there cannot be a harmless b_duplicate_key.
For all set functions except COUNT(*), an undef byte leads to
warning2.
For COUNT and AVG (11 bytes before the summation value already
contained in 'result'), the number of values found is entered (normally
a 1, in the case of NULL value, a 0).  The undef byte is explicitly
set to chr(0).
The summation buffer created is entered in the result file or,
if only one is expected, stored in count_buf.
If a summation buffer for this group is present, only those values
are important that are not NULL or that are required for COUNT(*)
(since NULL values are also included in the count).
'New' means that the value should be copied from the result
record to the summation record.   This is the case if, for MIN or
MAX, a value is lower or higher than the current value or that the
summation buffer contains NULL. The latter also applies for the
operators SUM and AVG.
For DISTINCT AVG|SUM|COUNT, the distinct test takes place in the
special files (group field values plus current value as a key).
If the value combination is already present,  the current value is
simply forgotten since the operators are never queried again.
Otherwise, the locally retained operator is transformed into
one without 'DISTINCT'.
Repl_needed signifies that at least one change has been carried
out in the summation buffer and, therefore, it must be replaced in
the file.
For COUNT and AVG, the counter in the summation buffer is
(additionally) incremented.
If necessary (new), the current value from 'result' is sent to
the summation buffer; for undef values, warning2 is set and, if
appropriate, the record in the file is replaced.
If a rowno condition was specified (maxresult < maxint4), only
the first maxresult results are used to form the function values;
when this limit is reached, the search is terminated.
 
PROCEDURE optimize_stack
 
This procedure is called for the strategies 'sequential', 'fieldin',
'between', 'intinv', and 'multindex' in the case where the result
table is being built immediately (and not at fetch time); the
procedure is called AFTER the startkeys and stopkeys for the
strategy have been built up via G04 calls; the
purpose of this optimization is to destroy all stack conditions that
are fully covered by the strategy itself, i.e stack conditions that
will evaluate to TRUE (VKB71) in any case because all the values
retrieved adhere to that condition due to the construction of
startkeys and stopkeys.
 
 
Note: not all conditions used for startkeys and stopkey can be
      automatically discarded :
 
      Example: multiple index (mi1, mi2, mi3)
               condition " mi1 >= 'x' AND mi2 >= 'y' "
 
               --> both conditions are used for building a startkey,
                   yet only the first condition may be discarded;
                   the second is needed to check all multiple keys
                   with mi1 > 'x'
 
Since the invalidation of stack entries is a fairly critical issue,
the software philosophy is defensive here; invalidation takes
place only at 'the last moment' before a BD call, and some
redundant checking is performed to make sure that the correct
sequence of stack entries is discarded.
 
Invalidation takes place by repeated calls to 'invalidate_stack'
 
For any of the above strategies, two phases of invalidation normally
take place: first for the secondary key(s) stack entries, then for
the primary key(s).
 
Note that a stack entry may represent a condition for both primary
and secondary keys (e.g. if the primary key is part of a multiple
index).  Hence, invalidation of conditions for primary keys
generally may not take place in the first phase.
 
After invalidation is completed, the stack is searched for
conditions remaining.  If none are left, then mqual_cnt and mqual_pos
are adjusted respectively.
 
PROCEDURE invalidate_stack
 
This procedure performs the actual invalidation of a condition
within the qualification stack.
 
 
        st_varcol,..               st_dummy
        st_value     ------>       st_dummy
         ...                         ....
        st_value + op_..           st_bool, epos=1 (TRUE)
 
 
Before a condition is invalidated, it is checked to see if it
has exactly the expected format.  If it differs in any point, then
invalidation is aborted; (an additional, not optimized condition
does no harm, the opposite is a catastrophy).
 
.CM *-END-* description ---------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
CONST
      c_check_new_rec   = true (* k71sel_qualification_test *);
      c_aggr            = true (* k721function_add          *);
      c_ignore_vwait    = true (* b02kb_select_rec *);
      c_usage_count     = true (* b03select_invrec *); (* h.b. PTS 1104210 *)
      c_use_shc_buf     = true (* PTS 1105795 M.Ki. *);
 
 
(*------------------------------*) 
 
PROCEDURE
      kb721eq_keyrecord (
            VAR m           : tgg00_MessBlock;
            VAR getrec      : tgg07_get_param;
            VAR selrec      : tgg07_select_param;
            VAR selfields   : tgg00_SelectFieldsParam;
            VAR gg_strategy : tgg07_StrategyInfo);
 
BEGIN
selfields.sfp_bd_mess2_type := mm_direct;
kb721select_gets( m, selrec.selr.selr_startkey, getrec, selrec, selfields );
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;
 
(*------------------------------*) 
 
PROCEDURE
      k721function_add (
            VAR m      : tgg00_MessBlock;
            VAR selrec : tgg07_select_param;
            aggr       : boolean);
 
VAR
      _new_rec      : boolean;
      _null_found   : boolean;
      _repl_needed  : boolean;
      _func_pos     : integer;
      _count_outlen : integer;
      _disnum       : integer;
      _output_start : integer;
      _i            : integer;
      _length       : integer;
      _checknull_pos: integer;
      _pos          : integer;
      _stpos        : integer;
      _cnt          : tsp00_Int4;
      _agg_cnt      : tsp00_Int4;
      _lres         : tsp00_LcompResult;
      _hkey         : tgg00_Lkey;
      _stddev_key   : tgg00_Lkey;
      _ret          : tsp00_NumError;
      _operator     : tgg00_StackOpFunc;
      _htree_id     : tgg00_FileId;
      _htree_pos    : tgg00_FilePos;
 
BEGIN
&ifdef trace
t01int4 (kb, 'selr_recl   ', selrec.selr.selr_recl );
t01int4 (kb, 'selr_res_key', selrec.selr.selr_res_keyl );
t01int4 (kb, 'result.recl ', selrec.selr_selectbuffer.result.len );
t01int4 (kb, 'result.keyl ', selrec.selr_selectbuffer.result.keylen );
&endif
_agg_cnt       := 1;
_checknull_pos := 0;
_null_found    := false;
selrec.selr.selr_tree_pos.tpsPno_gg00 := NIL_PAGE_NO_GG00;
selrec.selr.selr_countresult := succ(selrec.selr.selr_countresult);
_output_start  := m.mb_qual^.mqual_pos;
(* precondition: LASTFUNCTION on this position *)
_func_pos      := _output_start + m.mb_st^[ _output_start ].epos - 2;
_disnum   := 0; (* look at distinct_files *)
_htree_id := selrec.selr.selr_distinct_id;
(* reset result counter *)
FOR _i := 1 TO RESCNT_MXGG04-1 DO
    selrec.selr_selectbuffer.result.info[ selrec.selr.selr_res_keyl - RESCNT_MXGG04 + _i ] := chr(0);
(*ENDFOR*) 
selrec.selr_selectbuffer.result.info[ selrec.selr.selr_res_keyl ] := chr(1);
m.mb_trns^.trError_gg00 := e_ok;
SAPDB_PascalMove ('VKB721',   1,    
      sizeof(selrec.selr_selectbuffer.result.info), sizeof(_hkey.k),
      @selrec.selr_selectbuffer.result.info, 1, @_hkey.k, 1, selrec.selr.selr_res_keyl,
      m.mb_trns^.trError_gg00);
_hkey.len := selrec.selr.selr_res_keyl;
&ifdef trace
_hkey.keyRecLenSpace_gg00 := 0;
_hkey.keyVarOffSpace_gg00 := 0;
_hkey.keyVarCntSpace_gg00 := 0;
t01key  (kb, '_hkey       ', _hkey );
t01bool( kb, 'one result  ', selrec.selr.selr_one_result );
&endif
IF  ( m.mb_trns^.trError_gg00  = e_ok )
THEN
    BEGIN
    IF  ( selrec.selr.selr_one_result )
    THEN
        BEGIN
        IF  ( selrec.selr.selr_countresult = 1 )
        THEN
            BEGIN
            (* first entry - b07ctget_record() can't get a key *)
            (* new group begin                                 *)
            m.mb_trns^.trError_gg00 := e_key_not_found;
&           ifdef trace
            t01sname( kb, 'set KEY NOTF' );
&           endif
            END;
        (*ENDIF*) 
        END
    ELSE
        b07ctget_record (m.mb_trns^, selrec.selr.selr_resf_id,
              selrec.selr.selr_tree_pos,
              _hkey, selrec.selr_selectbuffer.lbuf);
    (*ENDIF*) 
    END;
(*ENDIF*) 
_hkey.len := _hkey.len - RESCNT_MXGG04;
IF  NOT (( m.mb_st^[ _func_pos ].etype = st_func ) AND
    ( m.mb_st^[ _func_pos ].eop_func = op_f_none ))
THEN
    BEGIN
    (* NOT LASTFUNCTION *)
    m.mb_trns^.trError_gg00 := e_stack_type_illegal;
&   ifdef trace
    t01name( kb, 'throw e_stack_type' );
    t01stackentry (kb, m.mb_st^[ _func_pos ], _func_pos );
&   endif
    END;
(*ENDIF*) 
IF  ( m.mb_trns^.trError_gg00 = e_key_not_found )
THEN
    BEGIN
    (* new group found *)
    selrec.selr.selr_group_count := succ(selrec.selr.selr_group_count);
    IF  (( selrec.selr.selr_group_count = 2 ) AND ( selrec.selr.selr_maxresult = 0 ))
    THEN
        IF  ( selrec.selr.selr_oracle_selinto
            AND ( selrec.selr.selr_resf_id.fileTfnTemp_gg00 = ttfnInto_egg00 )
            AND ( selrec.selr.selr_resf_id.fileTfn_gg00 = tfnTemp_egg00 ))
        THEN
            m.mb_trns^.trError_gg00 := e_ok
        ELSE
            m.mb_trns^.trError_gg00 := e_too_many_resultsets
        (*ENDIF*) 
    ELSE
        BEGIN
        m.mb_trns^.trError_gg00 := e_ok;
        (* m.mb_st^[ _func_pos ].epos == offset to previous function *)
        WHILE (( _func_pos - m.mb_st^[ _func_pos ].epos > _output_start ) AND
              ( m.mb_trns^.trError_gg00 = e_ok )) DO
            BEGIN
            (* loop over functions *)
            _ret := num_ok;
            _func_pos := _func_pos - m.mb_st^[ _func_pos ].epos;
            (* loop over LASTFUNCTIONs *)
            WHILE (( m.mb_st^[ _func_pos ].etype = st_func ) AND
                  ( m.mb_st^[ _func_pos ].eop_func = op_f_none )) DO
                _func_pos := _func_pos - m.mb_st^[ _func_pos ].epos;
            (*ENDWHILE*) 
            _stpos := k721out_entry (m.mb_st, _func_pos);
            ;
            IF  ( m.mb_st^[ _func_pos ].etype = st_func )
            THEN
                BEGIN
                IF  ( m.mb_st^[ _func_pos ].eop_func = op_f_check_null )
                THEN
                    _checknull_pos := m.mb_st^[ _stpos ].epos
                ELSE
                    BEGIN
                    IF  ( m.mb_st^[ _func_pos ].eop_func in [
                        op_f_dis_avg, op_f_dis_sum,
                        op_f_dis_count, op_f_stddev, op_f_dis_stddev,
                        op_f_variance, op_f_dis_variance ] )
                    THEN
                        BEGIN
                        IF  ( _disnum < cgg07_maxdistinctfiles )
                        THEN
                            _disnum := succ( _disnum )
                        ELSE
                            m.mb_trns^.trError_gg00 := e_buffer_limit;
                        (*ENDIF*) 
                        IF  ( selrec.selr_selectbuffer.result.
                            buf[ m.mb_st^[ _stpos ].epos ] <> csp_undef_byte )
                            AND
                            ( selrec.selr_selectbuffer.result.
                            buf[m.mb_st^[_stpos].epos] <> csp_oflw_byte )
                        THEN
                            BEGIN
                            SAPDB_PascalMove ('VKB721',   2,    
                                  sizeof(_hkey.k),
                                  sizeof(selrec.selr_selectbuffer.buf_rec.info),
                                  @_hkey.k, 1,
                                  @selrec.selr_selectbuffer.buf_rec.info, 1,
                                  _hkey.len,
                                  m.mb_trns^.trError_gg00);
                            SAPDB_PascalMove ('VKB721',   3,    
                                  sizeof(selrec.selr_selectbuffer.result.buf),
                                  sizeof(selrec.selr_selectbuffer.buf_rec.buf),
                                  @selrec.selr_selectbuffer.result.buf,
                                  m.mb_st^[ _stpos ].epos,
                                  @selrec.selr_selectbuffer.buf_rec.buf,
                                  _hkey.len+cgg_rec_key_offset+1,
                                  m.mb_st^[ _stpos ].elen_var,
                                  m.mb_trns^.trError_gg00);
                            selrec.selr_selectbuffer.buf_rec.keylen :=
                                  _hkey.len+m.mb_st^[ _stpos ].elen_var;
                            selrec.selr_selectbuffer.buf_rec.len :=
                                  selrec.selr_selectbuffer.buf_rec.keylen+cgg_rec_key_offset;
                            selrec.selr_selectbuffer.buf_rec.recVarcolOffset_gg00 := 0;
                            selrec.selr_selectbuffer.buf_rec.recVarcolCnt_gg00    := 0;
                            IF  m.mb_st^[ _func_pos ].eop_func in
                                [ op_f_stddev, op_f_variance,
                                op_f_dis_stddev, op_f_dis_variance ]
                            THEN
                                BEGIN
                                s20ch4sw (1, g01code.kernel_swap,
                                      selrec.selr_selectbuffer.buf_rec.info,
                                      selrec.selr_selectbuffer.buf_rec.keylen+1,
                                      sw_normal);
                                selrec.selr_selectbuffer.buf_rec.len :=
                                      selrec.selr_selectbuffer.buf_rec.len + 4
                                END;
                            (*ENDIF*) 
                            _htree_id.fileTempCnt_gg00   := _disnum;
                            _htree_id.fileRoot_gg00      := selrec.
                                  selr.selr_disrootarr[_disnum].dfi_root;
                            _htree_id.fileRootCheck_gg00 := selrec.
                                  selr.selr_disrootarr[_disnum].
                                  dfi_root_check;
                            IF  m.mb_trns^.trError_gg00 = e_ok
                            THEN
                                b07cadd_record (m.mb_trns^, _htree_id,
                                      selrec.selr_selectbuffer.buf_rec.buf)
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  ((( selrec.selr_selectbuffer.result.
                        buf[ m.mb_st^[ _stpos ].epos ] = csp_undef_byte )
                        AND ( m.mb_st^[ _func_pos ].eop_func <> op_f_all_count ))
                        OR
                        (( selrec.selr_selectbuffer.result.buf[ m.mb_st^[ _stpos ].epos ] = csp_oflw_byte )
                        AND NOT ( m.mb_st^[ _func_pos ].eop_func in [ op_f_count,
                        op_f_dis_count, op_f_all_count ] )))
                    THEN
                        BEGIN
                        _null_found := true;
                        m.mb_trns^.trWarning_gg00 := m.mb_trns^.trWarning_gg00 +
                              [ warn0_exist, warn2_null_in_builtin_func ];
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  ( NOT aggr ) AND
                    ( m.mb_st^[ _func_pos ].eop_func in
                    [ op_f_avg   , op_f_dis_avg,
                    op_f_count   , op_f_dis_count, op_f_all_count,
                    op_f_stddev  , op_f_dis_stddev,
                    op_f_variance, op_f_dis_variance ] )
                THEN
                    BEGIN
                    IF  m.mb_st^[ _func_pos ].eop_func in
                        [ op_f_avg   , op_f_dis_avg,
                        op_f_stddev  , op_f_dis_stddev,
                        op_f_variance, op_f_dis_variance ]
                    THEN
                        _pos := m.mb_st^[ _stpos ].epos + NUMBER_MXGG04
                    ELSE
                        _pos := m.mb_st^[ _stpos ].epos;
                    (*ENDIF*) 
                    IF  m.mb_st^[ _func_pos ].eop_func in
                        [ op_f_count, op_f_dis_count ]
                    THEN
                        _count_outlen := m.mb_st^[ _stpos ].elen_var
                    ELSE
                        _count_outlen := 0;
                    (*ENDIF*) 
                    IF  ((( selrec.selr_selectbuffer.result.
                        buf[m.mb_st^[_stpos].epos] = csp_undef_byte )
                        AND
                        ( m.mb_st^[_func_pos].eop_func <> op_f_all_count )) OR
                        (( selrec.selr_selectbuffer.result.
                        buf[m.mb_st^[_stpos].epos] = csp_oflw_byte )
                        AND
                        (NOT ( m.mb_st^[_func_pos].eop_func in [ op_f_count,
                        op_f_dis_count, op_f_all_count] ))))
                    THEN
                        s41p4int (selrec.selr_selectbuffer.result.buf,
                              _pos + 1, 0, _ret)
                    ELSE
                        s41p4int (selrec.selr_selectbuffer.result.buf,
                              _pos + 1, 1, _ret);
                    (*ENDIF*) 
                    selrec.selr_selectbuffer.result.buf[ _pos ] := csp_defined_byte;
                    IF  ( _count_outlen > mxsp_resnum )
                    THEN
                        SAPDB_PascalFill ('VKB721',   4,    
                              sizeof(selrec.selr_selectbuffer.result.buf),
                              @selrec.selr_selectbuffer.result.buf,
                              _pos + mxsp_resnum,
                              _count_outlen - mxsp_resnum, csp_defined_byte,
                              m.mb_trns^.trError_gg00);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDWHILE*) 
        IF  ( m.mb_trns^.trError_gg00 = e_ok )
        THEN
            BEGIN
            IF  ( _checknull_pos > 0 )
            THEN
                IF  _null_found
                THEN
                    selrec.selr_selectbuffer.result.buf[ _checknull_pos ] := csp_undef_byte
                ELSE
                    selrec.selr_selectbuffer.result.buf[ _checknull_pos ] := csp_defined_byte;
                (*ENDIF*) 
            (*ENDIF*) 
            IF  ( selrec.selr.selr_one_result )
            THEN
                BEGIN
&               ifdef trace
                t01name( kb, 'result -> lbuf    ' );
&               endif
                SAPDB_PascalMove ('VKB721',   5,    
                      sizeof(selrec.selr_selectbuffer.result.buf),
                      sizeof(selrec.selr_selectbuffer.lbuf),
                      @selrec.selr_selectbuffer.result.buf, 1,
                      @selrec.selr_selectbuffer.lbuf, 1,
                      selrec.selr_selectbuffer.result.len,
                      m.mb_trns^.trError_gg00);
                END
            ELSE
                BEGIN
&               ifdef trace
                t01buf( kb, selrec.selr_selectbuffer.result.buf, 1,
                      selrec.selr_selectbuffer.result.len );
&               endif
                (* this add will in monitoring be counted by *)
                (* b73cmds_count with selr.selr_countresult       *)
                b07cadd_record (m.mb_trns^, selrec.selr.selr_resf_id,
                      selrec.selr_selectbuffer.result.buf)
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
ELSE
    BEGIN
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        _repl_needed := false;
        WHILE (( _func_pos - m.mb_st^[ _func_pos ].epos > _output_start ) AND
              ( m.mb_trns^.trError_gg00 = e_ok )) DO
            BEGIN
            (* PTS 1123289 e.Z. *)
            _ret := num_ok;
            _func_pos      := _func_pos - m.mb_st^[ _func_pos ].epos;
            WHILE (( m.mb_st^[ _func_pos ].etype = st_func) AND
                  ( m.mb_st^[ _func_pos ].eop_func = op_f_none )) DO
                _func_pos := _func_pos - m.mb_st^[ _func_pos ].epos;
            (*ENDWHILE*) 
&           ifdef trace
            t01int4 (kb, 'new aggregat', _func_pos );
&           endif
            _stpos    := k721out_entry (m.mb_st, _func_pos);
            ;
            IF  ( m.mb_st^[ _func_pos ].etype = st_func )
            THEN
                BEGIN
                _operator := m.mb_st^[ _func_pos ].eop_func;
                IF  ( _operator = op_f_check_null )
                THEN
                    _checknull_pos := m.mb_st^[ _stpos ].epos
                ELSE
                    IF  (_operator in [ op_f_dis_sum, op_f_dis_avg,
                        op_f_dis_count,
                        op_f_stddev  , op_f_dis_stddev,
                        op_f_variance, op_f_dis_variance ] )
                    THEN
                        IF  ( _disnum < cgg07_maxdistinctfiles )
                        THEN
                            _disnum := succ(_disnum)
                        ELSE
                            m.mb_trns^.trError_gg00 := e_buffer_limit;
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
                IF  ( m.mb_trns^.trError_gg00 = e_ok )
                THEN
                    WITH m.mb_st^[ _stpos ] DO
                        BEGIN
                        IF  ((selrec.selr_selectbuffer.result.buf[ epos ] <> csp_undef_byte)
                            OR (_operator = op_f_all_count))
                        THEN
                            BEGIN
                            _new_rec := false;
                            IF  ( selrec.selr_selectbuffer.lbuf[ epos ] = csp_oflw_byte ) AND
                                (NOT ( _operator = op_f_all_count ))
                            THEN
                                _repl_needed := false
                            ELSE
                                IF  (selrec.selr_selectbuffer.result.buf[ epos ] = csp_oflw_byte)
                                    AND
                                    ( NOT(_operator in [ op_f_all_count,
                                    op_f_count, op_f_dis_count, op_f_check_null ]))
                                THEN
                                    BEGIN
                                    _repl_needed := true;
                                    selrec.selr_selectbuffer.lbuf[ epos ] := csp_oflw_byte
                                    END
                                ELSE
                                    BEGIN
                                    IF  (_operator in [ op_f_min, op_f_max ])
                                    THEN
                                        BEGIN
                                        IF  selrec.selr_selectbuffer.lbuf[epos] = csp_undef_byte
                                        THEN
                                            _new_rec := true
                                        ELSE
                                            BEGIN
                                            s30cmp (selrec.selr_selectbuffer.
                                                  result.buf,
                                                  epos+1,
                                                  elen_var-1,
                                                  selrec.selr_selectbuffer.lbuf,
                                                  epos+1, elen_var-1,
                                                  _lres);
&                                           ifdef TRACE
                                            t01buf (kb, selrec.selr_selectbuffer.
                                                  result.buf, epos + 1,
                                                  epos + elen_var -1);
                                            t01int4 (kb, 'lres        ', ord (_lres));
                                            t01buf (kb, selrec.selr_selectbuffer.
                                                  lbuf, epos + 1, epos + elen_var -1);
&                                           endif
                                            IF  ((((_operator = op_f_min)
                                                AND
                                                (_lres = l_less))
                                                OR
                                                ((_operator = op_f_max)
                                                AND
                                                (_lres = l_greater))))
                                            THEN
                                                _new_rec := true
                                            (*ENDIF*) 
                                            END
                                        (*ENDIF*) 
                                        END
                                    ELSE
                                        IF  (_operator in
                                            [ op_f_dis_avg,
                                            op_f_dis_sum,
                                            op_f_dis_count,
                                            op_f_stddev,
                                            op_f_dis_stddev,
                                            op_f_variance,
                                            op_f_dis_variance ])
                                        THEN
                                            BEGIN
                                            SAPDB_PascalMove ('VKB721',   6,    
                                                  sizeof(_hkey.k),
                                                  sizeof(selrec.selr_selectbuffer.
                                                  buf_rec.info),
                                                  @_hkey.k, 1,
                                                  @selrec.selr_selectbuffer.
                                                  buf_rec.info,
                                                  1, _hkey.len,
                                                  m.mb_trns^.trError_gg00);
                                            SAPDB_PascalMove ('VKB721',   7,    
                                                  sizeof(selrec.selr_selectbuffer.
                                                  result.buf),
                                                  sizeof(selrec.selr_selectbuffer.
                                                  buf_rec.buf),
                                                  @selrec.selr_selectbuffer.
                                                  result.buf, epos,
                                                  @selrec.selr_selectbuffer.
                                                  buf_rec.buf,
                                                  _hkey.len+cgg_rec_key_offset+1,
                                                  elen_var,
                                                  m.mb_trns^.trError_gg00);
                                            selrec.selr_selectbuffer.buf_rec.keylen :=
                                                  _hkey.len + elen_var;
                                            selrec.selr_selectbuffer.buf_rec.len    :=
                                                  selrec.selr_selectbuffer.
                                                  buf_rec.keylen + cgg_rec_key_offset;
                                            selrec.selr_selectbuffer.
                                                  buf_rec.recVarcolOffset_gg00 := 0;
                                            selrec.selr_selectbuffer.
                                                  buf_rec.recVarcolCnt_gg00    := 0;
                                            IF  m.mb_st^[ _func_pos ].eop_func in
                                                [ op_f_stddev
                                                , op_f_variance
                                                , op_f_dis_stddev
                                                , op_f_dis_variance ]
                                            THEN
                                                BEGIN
                                                s20ch4sw (1, g01code.
                                                      kernel_swap,
                                                      selrec.selr_selectbuffer.
                                                      buf_rec.info,
                                                      selrec.selr_selectbuffer.
                                                      buf_rec.keylen+1,
                                                      sw_normal);
                                                selrec.selr_selectbuffer.
                                                      buf_rec.len :=
                                                      selrec.selr_selectbuffer.
                                                      buf_rec.len + 4
                                                END;
                                            (*ENDIF*) 
                                            _htree_id.fileTempCnt_gg00   :=
                                                  _disnum;
                                            _htree_id.fileRoot_gg00      :=
                                                  selrec.selr.selr_disrootarr[_disnum
                                                  ].dfi_root;
                                            _htree_id.fileRootCheck_gg00 :=
                                                  selrec.selr.selr_disrootarr[_disnum
                                                  ].dfi_root_check;
                                            IF  selrec.selr_selectbuffer.
                                                result.buf[ epos ] <> csp_oflw_byte
                                            THEN
                                                BEGIN
                                                IF  m.mb_trns^.trError_gg00 = e_ok
                                                THEN
                                                    b07cadd_record (m.mb_trns^,
                                                       _htree_id,
                                                       selrec.selr_selectbuffer.
                                                       buf_rec.buf);
                                                (*ENDIF*) 
                                                IF  ((m.mb_trns^.trError_gg00 =
                                                    e_duplicate_key) AND
                                                    (_operator in [ op_f_stddev,
                                                    op_f_variance ]))
                                                THEN
                                                    BEGIN
                                                    _htree_pos.tpsPno_gg00 := NIL_PAGE_NO_GG00;
                                                    m.mb_trns^.trError_gg00 := e_ok;
                                                    _stddev_key.len := selrec.selr_selectbuffer.buf_rec.keylen;
                                                    SAPDB_PascalMove ('VKB721',   8,    
                                                       sizeof(selrec.selr_selectbuffer.buf_rec.buf),
                                                       sizeof(_stddev_key.k),
                                                       @selrec.selr_selectbuffer.buf_rec.buf, cgg_rec_key_offset+1,
                                                       @_stddev_key.k, 1, selrec.selr_selectbuffer.buf_rec.keylen,
                                                       m.mb_trns^.trError_gg00);
                                                    IF  m.mb_trns^.trError_gg00 = e_ok
                                                    THEN
                                                     b07ctget_record (m.mb_trns^,
                                                        _htree_id, _htree_pos, _stddev_key,
                                                        selrec.selr_selectbuffer.buf_rec.buf);
                                                    (*ENDIF*) 
                                                    s20ch4sw (1 +
                                                       s20or4sw (selrec.selr_selectbuffer.buf_rec.buf,
                                                       selrec.selr_selectbuffer.buf_rec.keylen+cgg_rec_key_offset+1,
                                                       sw_normal, g01code.kernel_swap),
                                                       g01code.kernel_swap, selrec.selr_selectbuffer.buf_rec.info,
                                                       selrec.selr_selectbuffer.buf_rec.keylen+1, sw_normal);
                                                    IF  m.mb_trns^.trError_gg00 = e_ok
                                                    THEN
                                                     b07ctrepl_record (m.mb_trns^, _htree_id, _htree_pos,
                                                        selrec.selr_selectbuffer.buf_rec.buf);
                                                    (*ENDIF*) 
                                                    END;
                                                (*ENDIF*) 
                                                END
                                            ELSE
                                                m.mb_trns^.trError_gg00 :=
                                                      e_duplicate_key;
                                            (*ENDIF*) 
                                            IF  m.mb_trns^.trError_gg00 =
                                                e_duplicate_key
                                            THEN
                                                m.mb_trns^.trError_gg00 :=
                                                      e_ok
                                            ELSE
                                                IF  (m.mb_trns^.trError_gg00 = e_ok)
                                                THEN
                                                    CASE _operator OF
                                                     op_f_dis_avg,
                                                     op_f_stddev,
                                                     op_f_dis_stddev,
                                                     op_f_variance,
                                                     op_f_dis_variance :
                                                      _operator :=
                                                         op_f_avg;
                                                     op_f_dis_sum :
                                                      _operator :=
                                                         op_f_sum;
                                                     op_f_dis_count :
                                                      _operator :=
                                                         op_f_count
                                                     END
                                                    (*ENDCASE*) 
                                                (*ENDIF*) 
                                            (*ENDIF*) 
                                            END;
                                        (*ENDIF*) 
                                    (*ENDIF*) 
                                    IF  ((_operator in [ op_f_avg,
                                        op_f_sum ]) AND
                                        (m.mb_trns^.trError_gg00 = e_ok))
                                    THEN
                                        IF  selrec.selr_selectbuffer.lbuf[ epos ] = csp_undef_byte
                                        THEN
                                            _new_rec := true
                                        ELSE
                                            BEGIN
&                                           ifdef trace
                                            t01sname( kb, 'replace val ' );
&                                           endif
                                            _repl_needed := true;
                                            IF  ( m.mb_st^[ _stpos + 1 ].etype = st_result )
                                            THEN
                                                s51add (selrec.selr_selectbuffer.result.buf,
                                                      epos+1, elen_var-1,
                                                      selrec.selr_selectbuffer.lbuf, epos+1,
                                                      elen_var-1,
                                                      selrec.selr_selectbuffer.lbuf, epos+1,
                                                      m.mb_st^[ _stpos+1 ].epos,
                                                      m.mb_st^[ _stpos+1 ].elen_var,
                                                      _length, _ret)
                                            ELSE
                                                IF  m.mb_st^[ _func_pos - 1 ].etype = st_sum_length
                                                THEN
                                                    s51add (selrec.selr_selectbuffer.result.buf,
                                                       (* new value to aggregate *)
                                                       m.mb_st^[ _stpos ].epos + 1,
                                                       m.mb_st^[ _stpos ].elen_var - 1,
                                                       (* old aggregate value *)
                                                       selrec.selr_selectbuffer.lbuf,
                                                       m.mb_st^[ _stpos ].epos + 1,
                                                       m.mb_st^[ _stpos ].elen_var - 1,
                                                       (* new aggregate value *)
                                                       selrec.selr_selectbuffer.lbuf,
                                                       m.mb_st^[ _stpos ].epos + 1,
                                                       m.mb_st^[ _func_pos - 1 ].epos,
                                                       m.mb_st^[ _func_pos - 1 ].elen_var,
                                                       _length, _ret)
                                                ELSE
                                                    s51add (selrec.selr_selectbuffer.result.buf,
                                                       epos+1, elen_var-1,
                                                       selrec.selr_selectbuffer.lbuf, epos+1,
                                                       elen_var-1,
                                                       selrec.selr_selectbuffer.lbuf, epos+1,
                                                       csp_fixed,
                                                       csp_float_frac,
                                                       _length, _ret);
                                                (*ENDIF*) 
                                            (*ENDIF*) 
                                            IF  _ret <> num_ok
                                            THEN
                                                BEGIN
                                                selrec.selr_selectbuffer.lbuf[epos  ]:= csp_oflw_byte;
                                                selrec.selr_selectbuffer.lbuf[epos+1]:= chr(255);
                                                FOR _i := 1 TO elen_var - 2 DO
                                                    selrec.selr_selectbuffer.lbuf[ epos+1+_i ] :=
                                                       chr(153)
                                                (*ENDFOR*) 
                                                END
                                            (*ENDIF*) 
                                            END;
                                        (*ENDIF*) 
                                    (*ENDIF*) 
                                    IF  (_operator in   [
                                        op_f_avg,
                                        op_f_count,
                                        op_f_all_count ])
                                        AND
                                        (m.mb_trns^.trError_gg00 = e_ok)
                                    THEN
                                        BEGIN
                                        _repl_needed := true;
                                        IF  (_operator = op_f_avg)
                                        THEN
                                            _pos := epos+NUMBER_MXGG04+1
                                        ELSE
                                            _pos := epos+1;
                                        (*ENDIF*) 
                                        s40g4int (selrec.selr_selectbuffer.lbuf, _pos, _cnt, _ret);
&                                       ifdef TRACE
                                        t01int4 (kb, 'pos         ',
                                              _pos);
                                        t01int4 (kb, 'ord(ret)    ',
                                              ord(_ret));
&                                       endif
                                        IF  _ret = num_ok
                                        THEN
                                            BEGIN
                                            IF  aggr
                                            THEN
                                                s40g4int (selrec.selr_selectbuffer.result.buf,
                                                      _pos, _agg_cnt, _ret);
                                            (*ENDIF*) 
                                            IF  _ret = num_ok
                                            THEN
                                                s41p4int (selrec.selr_selectbuffer.lbuf, _pos,
                                                      _cnt+_agg_cnt, _ret)
                                            (*ENDIF*) 
                                            END;
                                        (*ENDIF*) 
                                        END;
                                    (*ENDIF*) 
                                    IF  _new_rec
                                    THEN
                                        BEGIN
                                        SAPDB_PascalMove ('VKB721',   9,    
                                              sizeof(selrec.selr_selectbuffer.result.buf),
                                              sizeof(selrec.selr_selectbuffer.lbuf),
                                              @selrec.selr_selectbuffer.result.buf, epos,
                                              @selrec.selr_selectbuffer.lbuf, epos, elen_var,
                                              m.mb_trns^.trError_gg00);
                                        _repl_needed := true
                                        END
                                    (*ENDIF*) 
                                    END
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            _null_found := true;
                            m.mb_trns^.trWarning_gg00 :=
                                  m.mb_trns^.trWarning_gg00 +
                                  [ warn0_exist,
                                  warn2_null_in_builtin_func ];
                            END;
                        (*ENDIF*) 
                        END
                    (*ENDWITH*) 
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDWHILE*) 
        IF  (_null_found AND (_checknull_pos > 0))
        THEN
            IF  selrec.selr_selectbuffer.lbuf[ _checknull_pos ] = csp_defined_byte
            THEN
                BEGIN
                selrec.selr_selectbuffer.lbuf[ _checknull_pos ] := csp_undef_byte;
                _repl_needed := true
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (_repl_needed AND (m.mb_trns^.trError_gg00 = e_ok) AND
            NOT selrec.selr.selr_one_result)
        THEN
            BEGIN
            b73cmd_count (iins_sorts_rows_ins);
            b07ctrepl_record (m.mb_trns^, selrec.selr.selr_resf_id,
                  selrec.selr.selr_tree_pos,
                  selrec.selr_selectbuffer.lbuf)
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  selrec.selr.selr_countresult = selrec.selr.selr_rowno
THEN
    m.mb_trns^.trError_gg00 := e_enough_resultsets
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k721Merge_ForAggregate (
            M           : tgg00_MessBlockPtr;
            SelRec      : tgg07_SelectParamPtr;
            Source      : tgg00_VoidPtr;
            Destination : tgg00_VoidPtr;
            Length      : tsp00_Int2;
            Merge       : boolean);
 
BEGIN
END;
 
(*------------------------------*) 
 
FUNCTION
      k721GetKeyAndRecInfo_ForAggregate(
            VAR RecLength    : tsp00_Int2;
            VAR KeyCount     : tsp00_Int2;
            KeyOffset        : tgg00_VoidPtr;
            KeyLength        : tgg00_VoidPtr;
            MaxKeys          : tsp00_Int2) : boolean; (* returns TRUE if ok, else FALSE *)
 
BEGIN
k721GetKeyAndRecInfo_ForAggregate := false;
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb721in_keyrecord (
            VAR m           : tgg00_MessBlock;
            VAR getrec      : tgg07_get_param;
            VAR selrec      : tgg07_select_param;
            VAR selfields   : tgg00_SelectFieldsParam;
            VAR gg_strategy : tgg07_StrategyInfo);
 
VAR
      _dummy_cnt : tsp00_Int2;
      _i         : tsp00_Int2;
 
BEGIN
&ifdef trace
t01int4 (kb, 'inelemcnt   ', gg_strategy.str_key_in_range.skir_inelemcnt );
&endif
_i         := 1;
_dummy_cnt := 0;
WHILE ( _i <= gg_strategy.str_key_in_range.skir_inelemcnt ) AND
      ( m.mb_trns^.trError_gg00 = e_ok ) DO
    BEGIN
    IF  ( m.mb_st^[ gg_strategy.str_key_in_range.skir_IN_SUBQ_stpos + _i + _dummy_cnt ].
        etype <> st_dummy )
    THEN
        BEGIN
&       ifdef trace
        t01stackentry (kb,
              m.mb_st^[ gg_strategy.str_key_in_range.skir_IN_SUBQ_stpos + _i + _dummy_cnt ],
              gg_strategy.str_key_in_range.skir_IN_SUBQ_stpos + _i + _dummy_cnt );
&       endif
        IF  (( m.mb_st^[ gg_strategy.str_key_in_range.skir_IN_SUBQ_stpos + _i + _dummy_cnt ].
            etype = st_op ) AND
            ( m.mb_st^[ gg_strategy.str_key_in_range.skir_IN_SUBQ_stpos + _i + _dummy_cnt ].
            eop = op_in ))
        THEN
            (* make procedure fault tolerant, leave WHILE *)
            _i := gg_strategy.str_key_in_range.skir_inelemcnt + 1
        ELSE
            BEGIN
            selfields.sfp_bd_use_stopkey := true;
            g04limitprimkeys( m, gg_strategy.str_key_in_range.skir_keystart,
                  selrec.selr.selr_startkey, gg_strategy.str_key_in_range.skir_keystop,
                  selrec.selr.selr_stopkey,
                  selfields.sfp_bd_use_stopkey,
                  gg_strategy.str_key_in_range.skir_IN_SUBQ_stpos, _i + _dummy_cnt );
            (* might return e_move_error *)
            selfields.sfp_bd_mess2_type := mm_first;
            WHILE ( m.mb_trns^.trError_gg00 = e_ok ) DO
                BEGIN
                kb721select_gets( m, selrec.selr.selr_startkey,
                      getrec, selrec, selfields );
                END;
            (*ENDWHILE*) 
            IF  ( m.mb_trns^.trError_gg00 = e_no_next_record )
            THEN
                m.mb_trns^.trError_gg00 := e_ok;
            (*ENDIF*) 
            _i := succ( _i );
            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
        ( 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;
 
(*------------------------------*) 
 
PROCEDURE
      kb721select_gets (
            VAR m          : tgg00_MessBlock;
            VAR act_key    : tgg00_Lkey;
            VAR getrec     : tgg07_get_param;
            VAR selrec     : tgg07_select_param;
            VAR selfields  : tgg00_SelectFieldsParam);
 
VAR
      _dummy_bool   : boolean;
      _sellength    : tsp00_Int4;
      _recbuf_size  : tsp00_Int4;
      _granted_lock : tgg00_LockReqMode;
      _htree_id     : tgg00_FileId;
      _recbuf_ptr   : tsp00_MoveObjPtr;
 
BEGIN
_granted_lock := lckFree_egg00;
IF  ( m.mb_type = m_insert_select )
THEN
    BEGIN
    _htree_id := m.mb_qual^.mtree;
    selfields.sfp_result_length := cgg_rec_key_offset;
    ;
    IF  ( selrec.selr.selr_is_nokey )
    THEN
        selfields.sfp_result_length :=
              selfields.sfp_result_length + 1 + SURROGATE_MXGG00;
    (*ENDIF*) 
    END
ELSE
    selfields.sfp_result_length := 0;
(*ENDIF*) 
_sellength := selfields.sfp_result_length;
IF  ( selrec.selr.selr_write_rownum AND ( selrec.selr.selr_distinct <> no_distinct ))
THEN
    selfields.sfp_act_cntresult := 1
ELSE
    IF  ( NOT selrec.selr.selr_count_all )
    THEN
        selfields.sfp_act_cntresult := selrec.selr.selr_countresult + 1;
    (*ENDIF*) 
(*ENDIF*) 
IF  ( selfields.sfp_m_result_cnt > 1 )
THEN
    BEGIN
    selfields.sfp_resrec_maxlen :=
          selrec.selr.selr_recl + selfields.sfp_result_length;
    selrec.selr.selr_resrec_maxlen    := selfields.sfp_resrec_maxlen;
    END;
(*ENDIF*) 
m.mb_trns^.trError_gg00       := e_ok;
m.mb_qual^.mtree.fileBdUse_gg00 := [  ];
IF  ( m.mb_type = m_update )
THEN
    BEGIN
&   ifdef trace
    t01name (kb_qual, 'base tab -> longre');
&   endif
    (* base table rec --> longresult rec *)
    selfields.sfp_m_result_addr := @selrec.selr_selectbuffer.longresult;
    selfields.sfp_m_result_size :=
          sizeof( selrec.selr_selectbuffer.longresult );
    END
ELSE
    BEGIN
&   ifdef trace
    t01name (kb_qual, 'base tab -> result');
&   endif
    (* base table rec --> result rec *)
    selfields.sfp_m_result_addr := @selrec.selr_selectbuffer.result;
    selfields.sfp_m_result_size :=
          sizeof( selrec.selr_selectbuffer.result );
    END;
(*ENDIF*) 
selfields.sfp_m_result_len  := 0;
IF  ( selrec.selr.selr_intern_dist OR ( m.mb_type in [ m_update, m_delete ] ) )
THEN
    BEGIN
&   ifdef trace
    t01name (kb_qual, 'base tab -> buff_r');
&   endif
    (* base table rec --> buffer rec *)
    _recbuf_size := sizeof( selrec.selr_selectbuffer.buf_rec );
    _recbuf_ptr  := @selrec.selr_selectbuffer.buf_rec;
    END
ELSE
    BEGIN
    _recbuf_size := 0;
    _recbuf_ptr  := NIL;
    END;
(*ENDIF*) 
b02kb_select_rec( m.mb_trns^, m.mb_qual^.mtree,
      act_key.keyVal_gg00, act_key.keyLen_gg00,
      selrec.selr.selr_stopkey.keyVal_gg00, selrec.selr.selr_stopkey.keyLen_gg00,
      _recbuf_size, _recbuf_ptr, NOT c_ignore_vwait,
      selfields, m.mb_qual^.mstack_desc, _dummy_bool, _granted_lock );
;
kb721result_handle( m, selrec, getrec, selfields,
      act_key, _htree_id, _granted_lock );
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb721seq_search (
            VAR m        : tgg00_MessBlock;
            VAR getrec   : tgg07_get_param;
            VAR selrec   : tgg07_select_param;
            VAR sel      : tgg00_SelectFieldsParam;
            VAR strat    : tgg07_StrategyInfo);
 
VAR
      _qual_buf_len   : tsp00_Int2;
      _max_result_cnt : tsp00_Int2;
      _leaf_count     : tsp00_Int4;
      _record_count   : tsp00_Int4;
      _ic2            : tsp_int_map_c2;
 
BEGIN
IF  ( selrec.selr.selr_count_bd
    AND
    ( selrec.selr.selr_startkey.len = 0 )
    AND
    ( selrec.selr.selr_stopkey.len = 0 ))
THEN
    BEGIN
    SAPDB_PascalMove ('VKB721',  10,    
          m.mb_qual_size, sizeof( selrec.selr_selectbuffer.rbuf ),
          @m.mb_qual^.buf, 1,
          @selrec.selr_selectbuffer.rbuf, 1,
          m.mb_qual_len, m.mb_trns^.trError_gg00);
    ;
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        _qual_buf_len := m.mb_qual_len;
        m.mb_type      := m_column_statistic;
        m.mb_type2     := mm_key;
        bd01CalculateRecordsAndLeaves( m.mb_trns^, m.mb_qual^.mtree,
              _leaf_count, _record_count );
        IF  ( m.mb_trns^.trError_gg00 = e_ok )
        THEN
            sel.sfp_act_cntresult := sel.sfp_act_cntresult + _record_count;
        (*ENDIF*) 
        m.mb_type      := m_select;
        m.mb_type2     := mm_with_functions;
        m.mb_qual_len  := _qual_buf_len;
        SAPDB_PascalMove ('VKB721',  11,    
              sizeof( selrec.selr_selectbuffer.rbuf ),
              sizeof( m.mb_qual^.buf ),
              @selrec.selr_selectbuffer.rbuf, 1,
              @m.mb_qual^.buf, 1, m.mb_qual_len,
              m.mb_trns^.trError_gg00);
        END
    (*ENDIF*) 
    END
ELSE
    BEGIN
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        IF  ( m.mb_type IN [ m_update, m_delete, m_insert_select ] ) OR
            ( m.mb_type2 IN [ mm_with_functions, mm_with_join ] ) OR
            ( selrec.selr.selr_distinct <> no_distinct ) OR
            selrec.selr.selr_intern_dist OR
            selrec.selr.selr_union_select OR
            selrec.selr.selr_one_result
        THEN
            sel.sfp_m_result_cnt := 1
        ELSE
            BEGIN
            IF  (( selrec.selr.selr_recl MOD 2 ) = 0)
            THEN
                sel.sfp_m_result_cnt :=
                      sizeof( selrec.selr_selectbuffer.result ) DIV
                      selrec.selr.selr_recl
            ELSE
                sel.sfp_m_result_cnt :=
                      sizeof( selrec.selr_selectbuffer.result ) DIV
                      ( selrec.selr.selr_recl + 1 );
            (*ENDIF*) 
            (* h.b. PTS 1001366 *)
            IF  ( sel.sfp_m_result_cnt > selrec.selr.selr_rowno )
            THEN
                sel.sfp_m_result_cnt := selrec.selr.selr_rowno;
            (*ENDIF*) 
            IF  ( sel.sfp_m_result_cnt < 1 )
            THEN
                sel.sfp_m_result_cnt := 1;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
&       ifdef TRACE
        t01int4 (kb_qual, 'res_in_cnt  ', sel.sfp_m_result_cnt);
&       endif
        _max_result_cnt := sel.sfp_m_result_cnt;
        sel.sfp_bd_mess2_type := mm_first;
        kb721select_gets( m, selrec.selr.selr_startkey, getrec, selrec, sel);
        END;
    (*ENDIF*) 
    IF  (( m.mb_qual^.mtree.fileTfnTemp_gg00 = ttfnRecursive_egg00 )
        AND
        selrec.selr.selr_all_recursive )
    THEN
        BEGIN
        IF  ( m.mb_trns^.trError_gg00 = e_no_next_record )
        THEN
            BEGIN
&           ifdef trace
            t01name( kb, 'test next recursiv' );
&           endif
            _ic2.map_c2 := m.mb_qual^.mtree.fileLevel_gg00;
            IF  ( _ic2.map_int > 1 )
            THEN (* it was not first file *)
                BEGIN
                _ic2.map_int := pred(_ic2.map_int);
                m.mb_qual^.mtree.fileLevel_gg00 := _ic2.map_c2;
                m.mb_qual^.mtree.fileRoot_gg00  := NIL_PAGE_NO_GG00;
                sel.sfp_bd_mess2_type := mm_first;
                sel.sfp_m_result_cnt := _max_result_cnt;
                selrec.selr.selr_startkey.len := 0;
                m.mb_trns^.trError_gg00 := e_ok;
&               ifdef trace
                t01treeid( kb, 'new treeid  ',  m.mb_qual^.mtree );
&               endif
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    WHILE ( m.mb_trns^.trError_gg00 = e_ok ) DO
        BEGIN
        WHILE m.mb_trns^.trError_gg00 = e_ok DO
            kb721select_gets( m, selrec.selr.selr_startkey, getrec, selrec, sel );
        (*ENDWHILE*) 
        IF  (( m.mb_qual^.mtree.fileTfnTemp_gg00 = ttfnRecursive_egg00 ) AND
            selrec.selr.selr_all_recursive )
        THEN
            BEGIN
            IF  ( m.mb_trns^.trError_gg00 = e_no_next_record )
            THEN
                BEGIN
&               ifdef trace
                t01name( kb, 'test next recursiv' );
&               endif
                _ic2.map_c2 := m.mb_qual^.mtree.fileLevel_gg00;
                IF  ( _ic2.map_int > 1 )
                THEN (* it was not first file *)
                    BEGIN
                    _ic2.map_int := pred( _ic2.map_int );
                    m.mb_qual^.mtree.fileLevel_gg00 := _ic2.map_c2;
                    m.mb_qual^.mtree.fileRoot_gg00  := NIL_PAGE_NO_GG00;
                    sel.sfp_bd_mess2_type := mm_first;
                    sel.sfp_m_result_cnt := _max_result_cnt;
                    selrec.selr.selr_startkey.len := 0;
                    m.mb_trns^.trError_gg00  := e_ok;
&                   ifdef trace
                    t01treeid( kb, 'new treeid  ',  m.mb_qual^.mtree );
&                   endif
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  ( m.mb_trns^.trError_gg00 = e_no_next_record ) OR
        ( m.mb_trns^.trError_gg00 = e_no_prev_record )
    THEN
        m.mb_trns^.trError_gg00 := e_ok;
    (*ENDIF*) 
    END;
(*ENDIF*) 
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;
 
(*------------------------------*) 
 
PROCEDURE
      kb721subq_key_select (
            VAR m           : tgg00_MessBlock;
            VAR getrec      : tgg07_get_param;
            VAR selrec      : tgg07_select_param;
            VAR selfields   : tgg00_SelectFieldsParam;
            VAR gg_strategy : tgg07_StrategyInfo);
 
VAR
      _ok             : boolean;
      _ix             : tsp00_Int2;
      _subq_pos       : tsp00_Int2;
      _subqtree_id    : tgg00_FileId;
      _m_key          : tgg00_Lkey;
      _aux_error      : tgg00_BasisError;
 
BEGIN
_aux_error := e_ok;
_ix        := 0;
_subq_pos  := 0;
WHILE ( _ix <= MAX_COLPOSARR_IDX_GG07 ) AND ( _aux_error = e_ok ) DO
    BEGIN
    IF  ( gg_strategy.str_key_in_range.skir_keystart[ _ix ] = 0 )
    THEN
        (* break through while loop *)
        _ix := MAX_COLPOSARR_IDX_GG07
    ELSE
        IF  ( m.mb_st^[ gg_strategy.str_key_in_range.skir_keystart[ _ix ] ].
            etype = st_dummy ) AND
            ( m.mb_st^[ gg_strategy.str_key_in_range.skir_keystart[ _ix ] + 1 ].
            etype = st_bool )
        THEN
            (* no records in subquery - file *)
            _aux_error := e_no_next_record
        ELSE
            IF  ( m.mb_st^
                [ gg_strategy.str_key_in_range.skir_keystart[ _ix ] + 1 ].
                etype = st_subquery )
            THEN
                BEGIN
                _subq_pos := gg_strategy.str_key_in_range.skir_keystart[ _ix ];
                _ix       := MAX_COLPOSARR_IDX_GG07;
                END;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    _ix := succ( _ix );
    END;
(*ENDWHILE*) 
IF  ( _aux_error = e_ok )
THEN
    BEGIN
    IF  ( _subq_pos <> 0 )
    THEN
        BEGIN
        _m_key.len := 0;
        SAPDB_PascalMove ('VKB721',  12,    
              m.mb_data_size, sizeof( _subqtree_id ),
              @m.mb_data^.mbp_buf, m.mb_st^[ _subq_pos + 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  ( _subq_pos <> 0 )
        THEN
            g04read_subquery( m.mb_trns^, selrec.selr_selectbuffer.result, _subqtree_id,
                  _m_key (* updated for every loop *), _aux_error, _ok )
        ELSE
            BEGIN
            _aux_error := e_no_next_record;
            _ok        := true;
            END;
        (*ENDIF*) 
        ;
        IF  ( _ok )
        THEN
            BEGIN
            selfields.sfp_bd_use_stopkey := false;
            gg04one_subq_limitprimkey( m, selrec.selr_selectbuffer.result,
                  gg_strategy.str_key_in_range.skir_keystart,
                  selrec.selr.selr_startkey, selfields.sfp_bd_use_stopkey );
            (* might return e_move_error *)
            selfields.sfp_bd_use_stopkey := true;
            gg04one_subq_limitprimkey( m, selrec.selr_selectbuffer.result,
                  gg_strategy.str_key_in_range.skir_keystop,
                  selrec.selr.selr_stopkey, selfields.sfp_bd_use_stopkey );
            (* might return e_move_error *)
            IF  ( ksp_exact_IN_SUBQ_match in
                gg_strategy.str_key_in_range.skir_strat_props )
            THEN
                BEGIN
                selfields.sfp_bd_mess2_type := mm_direct;
                kb721select_gets( m, selrec.selr.selr_startkey, getrec,
                      selrec, selfields );
                END
            ELSE
                BEGIN
                selfields.sfp_bd_mess2_type := mm_first;
                WHILE ( m.mb_trns^.trError_gg00 = e_ok ) DO
                    kb721select_gets( m, selrec.selr.selr_startkey, getrec,
                          selrec, selfields );
                (*ENDWHILE*) 
                IF  ( m.mb_trns^.trError_gg00 = e_no_next_record ) OR
                    ( m.mb_trns^.trError_gg00 = e_no_prev_record )
                THEN
                    m.mb_trns^.trError_gg00 := e_ok;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k721stddev (
            trans        : tgg00_TransContextPtr;
            VAR dist_file: tgg00_FileId;
            VAR result   : tgg00_Rec;
            VAR buf1     : tgg00_Rec;
            VAR buf2     : tsp00_Buf;
            func         : tgg00_StackOpFunc;
            outpos       : integer);
 
VAR
      _recpos       : integer;
      _avgpos       : integer;
      _avglen       : integer;
      _i_cnt        : tsp00_Int4;
      _cnt          : tsp00_Int4;
      _set_result   : tgg00_BdSetResultRecord;
      _htree_pos    : tgg00_FilePos;
      _hkey         : tgg00_Lkey;
      _resbytelen   : integer;
      _ret          : tsp00_NumError;
 
BEGIN
_set_result.bd_key_check_len := result.keylen - RESCNT_MXGG04;
_set_result.bd_max_rec_cnt   := csp_maxint2;
_set_result.bd_max_fill_len  := mxsp_buf;
_set_result.bd_next          := false;
_set_result.bd_drop_page     := false;
_htree_pos.tpsPno_gg00 := NIL_PAGE_NO_GG00;
SAPDB_PascalMove ('VKB721',  13,    
      sizeof(result.buf), sizeof(_hkey.k),
      @result.buf, cgg_rec_key_offset+1,
      @_hkey.k, 1, result.keylen-RESCNT_MXGG04,
      trans^.trError_gg00);
_hkey.len := result.keylen - RESCNT_MXGG04;
_avgpos := outpos + 1;
_avglen := NUMBER_MXGG04 - 1;
_ret := num_ok;
s41plint (buf2, 1, csp_fixed, csp_float_frac, 0, _ret);
IF  ( trans^.trError_gg00 <> e_move_error )
THEN
    trans^.trError_gg00 := e_buffer_limit;
(*ENDIF*) 
WHILE ( trans^.trError_gg00 = e_buffer_limit ) AND ( _ret = num_ok ) DO
    BEGIN
    b07cnext_record (trans^, dist_file,
          _hkey, _set_result, _htree_pos, buf1.buf);
    IF  ( trans^.trRteCommPtr_gg00^.to_cancel )
    THEN
        trans^.trError_gg00 := e_cancelled;
    (*ENDIF*) 
    IF  ( trans^.trError_gg00 = e_key_not_found )
    THEN
        trans^.trError_gg00 := e_ok;
    (*ENDIF*) 
    IF  (( trans^.trError_gg00 = e_ok ) OR
        ( trans^.trError_gg00 = e_buffer_limit ))
    THEN
        BEGIN
        _recpos := cgg_rec_key_offset + _set_result.bd_key_check_len + 2;
        WHILE (( _recpos < _set_result.bd_fill_len ) AND
              ( _ret = num_ok )) DO
            BEGIN
&           ifdef TRACE
            t01name (kb_qual, 's51sub            ');
            t01buf (kb_qual, buf1.buf, _recpos, _recpos+_avglen-1);
            t01buf (kb_qual, result.buf, _avgpos, _avgpos+_avglen-1);
&           endif
            s51sub (buf1.buf, _recpos, _avglen,
                  result.buf, _avgpos, _avglen,
                  buf1.buf, _recpos,
                  csp_fixed, csp_float_frac,
                  _resbytelen, _ret);
&           ifdef TRACE
            t01buf (kb_qual, buf1.buf,
                  _recpos, _recpos + _resbytelen - 1);
            t01int4 (kb_qual, 'ret =       ', ord(_ret));
&           endif
            IF  ( _ret = num_ok )
            THEN
                BEGIN
&               ifdef TRACE
                t01name (kb_qual, 's51mul            ');
                t01buf (kb_qual, buf1.buf,
                      _recpos, _recpos + _avglen - 1);
&               endif
                s51mul (buf1.buf, _recpos, _avglen,
                      buf1.buf, _recpos, _avglen,
                      buf1.buf, _recpos,
                      csp_fixed, csp_float_frac,
                      _resbytelen, _ret);
&               ifdef TRACE
                t01buf (kb_qual, buf1.buf,
                      _recpos, _recpos + _resbytelen - 1);
                t01int4 (kb_qual, 'ret =       ', ord(_ret));
&               endif
                END;
            (*ENDIF*) 
            IF  ( _ret = num_ok )
            THEN
                BEGIN
                _cnt := s20or4sw (buf1.buf, _recpos + _avglen,
                      sw_normal, g01code.kernel_swap);
&               ifdef TRACE
                t01name (kb_qual, 's51add            ');
                t01int4 (kb_qual, 'cnt =       ', _cnt);
                t01buf (kb_qual, buf2, 1, mxsp_number);
                t01buf (kb_qual, buf1.buf,
                      _recpos, _recpos + _avglen - 1);
&               endif
                _i_cnt := 0;
                REPEAT
                    _i_cnt := succ(_i_cnt);
                    s51add (buf2, 1, mxsp_number,
                          buf1.buf,
                          _recpos, _resbytelen,
                          buf2, 1, csp_fixed,
                          csp_float_frac, _resbytelen, _ret);
                UNTIL
                    ( _ret <> num_ok ) OR ( _i_cnt = _cnt );
                (*ENDREPEAT*) 
&               ifdef TRACE
                t01buf (kb_qual, buf2, 1, _resbytelen);
                t01int4 (kb_qual, 'ret =       ', ord(_ret));
&               endif
                END;
            (*ENDIF*) 
            _recpos := _recpos + buf1.len
            END
        (*ENDWHILE*) 
        END
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
IF  (( trans^.trError_gg00 = e_no_next_record ) OR
    ( trans^.trError_gg00 = e_buffer_limit ) OR
    ( trans^.trError_gg00 = e_ok ))
THEN
    BEGIN
    IF  ( _ret = num_overflow )
    THEN
        BEGIN
        _ret := num_ok;
        result.buf[ _avgpos-1 ] := csp_oflw_byte
        END
    ELSE
        IF  ( _ret = num_ok )
        THEN
            BEGIN
            s41p4int (buf2, NUMBER_MXGG04 + 1, 1, _ret);
            s51sub (result.buf, _avgpos + NUMBER_MXGG04, mxsp_resnum-1,
                  buf2, NUMBER_MXGG04+1, mxsp_resnum-1,
                  result.buf, _avgpos + NUMBER_MXGG04,
                  csp_resnum_deflen, csp_float_frac,
                  _resbytelen, _ret);
&           ifdef TRACE
            t01name (kb_qual, 's51div            ');
            t01buf (kb_qual, buf2, 1, _avglen);
            t01buf (kb_qual, result.buf, _avgpos+NUMBER_MXGG04,
                  _avgpos+NUMBER_MXGG04+mxsp_resnum-1);
&           endif
            IF  ( result.buf[ _avgpos+NUMBER_MXGG04 ] = cgg04_zero_exponent )
            THEN
                s41plint (result.buf, _avgpos,
                      csp_fixed, csp_float_frac, 0, _ret)
            ELSE
                BEGIN
                s51div (buf2, 1, _avglen,
                      result, _avgpos + NUMBER_MXGG04, mxsp_resnum-1,
                      result, _avgpos,  csp_fixed, csp_float_frac,
                      _resbytelen, _ret);
&               ifdef TRACE
                t01buf (kb_qual, result.buf, _avgpos, _avgpos + _resbytelen - 1);
                t01int4 (kb_qual, 'ret =       ', ord(_ret));
&               endif
                IF  (( _ret = num_ok ) AND
                    ( result.buf[ _avgpos ] > cgg04_zero_exponent ) AND
                    (( func = op_f_stddev ) OR ( func = op_f_dis_stddev )))
                THEN
                    s52sqrt (result.buf, _avgpos, mxsp_number,
                          result.buf, _avgpos, csp_fixed,
                          csp_float_frac, _ret);
                (*ENDIF*) 
                IF  ( _ret = num_trunc )
                THEN
                    _ret := num_ok
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  ( _ret <> num_ok )
    THEN
        trans^.trError_gg00 := e_num_invalid;
    (*ENDIF*) 
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb721unique_add (
            VAR t      : tgg00_TransContext;
            VAR selrec : tgg07_select_param);
 
VAR
      _set_result : tgg00_BdSetResultRecord;
      _is_equal   : boolean;
      _i          : integer;
      _comp_len   : integer;
      _recpos     : integer;
      _lc         : tsp00_LcompResult;
      _new_key    : tgg00_Lkey;
 
BEGIN
IF  selrec.selr.selr_distinct_bytes
THEN
    BEGIN
    _recpos := selrec.selr_selectbuffer.result.keylen + cgg_rec_key_offset + 2;
    IF  selrec.selr.selr_distinct = full_distinct
    THEN
        _i := selrec.selr_selectbuffer.result.len -
              selrec.selr_selectbuffer.result.keylen - cgg_rec_key_offset - 1
    ELSE
        _i := selrec.selr_selectbuffer.result.len - 1 -
              selrec.selr_selectbuffer.result.keylen - cgg_rec_key_offset - 1;
    (*ENDIF*) 
&   ifdef TRACE
    t01int4 (kb, 'i           ', _i);
    t01buf (kb, selrec.selr_selectbuffer.result.buf, _i + 1,
          selrec.selr_selectbuffer.result.len);
&   endif
    k50hash (selrec.selr_selectbuffer.result.buf, _recpos, _i,
          selrec.selr_selectbuffer.result.buf,
          cgg_rec_key_offset + selrec.selr_selectbuffer.result.keylen - RESCNT_MXGG04 -
          cgg04_cdistinct_bytes + 1);
    END;
(*ENDIF*) 
_new_key.len := selrec.selr_selectbuffer.result.keylen - RESCNT_MXGG04;
SAPDB_PascalMove ('VKB721',  14,    
      sizeof(selrec.selr_selectbuffer.result.buf),
      sizeof(_new_key.k), @selrec.selr_selectbuffer.result.buf,
      cgg_rec_key_offset + 1,
      @_new_key.k, 1, _new_key.len, t.trError_gg00);
_is_equal := false;
WITH _set_result DO
    BEGIN
    bd_key_check_len := _new_key.len;
    bd_max_rec_cnt   := csp_maxint2;
    bd_max_fill_len  := mxsp_buf;
    bd_next          := false;
    bd_drop_page     := false;
    END;
(*ENDWITH*) 
selrec.selr.selr_tree_pos.tpsPno_gg00 := NIL_PAGE_NO_GG00;
IF  t.trError_gg00 <> e_move_error
THEN
    t.trError_gg00 := e_buffer_limit;
(*ENDIF*) 
WHILE (NOT _is_equal) AND (t.trError_gg00 = e_buffer_limit) DO
    BEGIN
    b07cnext_record (t, selrec.selr.selr_resf_id, _new_key, _set_result,
          selrec.selr.selr_tree_pos, selrec.selr_selectbuffer.buf_rec.buf);
    IF  t.trRteCommPtr_gg00^.to_cancel
    THEN
        t.trError_gg00 := e_cancelled;
    (*ENDIF*) 
    IF  t.trError_gg00 = e_key_not_found
    THEN
        t.trError_gg00 := e_ok;
    (*ENDIF*) 
    IF  ((t.trError_gg00 = e_ok) OR (t.trError_gg00 = e_buffer_limit))
    THEN
        BEGIN
        _recpos := 0;
        WHILE (NOT _is_equal AND
              (_recpos < _set_result.bd_fill_len)) DO
            BEGIN
            _i := selrec.selr_selectbuffer.result.keylen + cgg_rec_key_offset + 1;
            IF  selrec.selr.selr_distinct = full_distinct
            THEN
                _comp_len := selrec.selr_selectbuffer.result.len - _i + 1
            ELSE
                _comp_len := selrec.selr_selectbuffer.result.len - _i;
            (*ENDIF*) 
            s30cmp (selrec.selr_selectbuffer.result.buf, _i, _comp_len,
                  selrec.selr_selectbuffer.buf_rec.buf,
                  _recpos + _i, _comp_len, _lc);
            _is_equal := _lc = l_equal;
&           ifdef TRACE
            t01int4 (kb, 'i           ', _i);
            t01int4 (kb, 'comp_len    ', _comp_len);
            t01buf (kb, selrec.selr_selectbuffer.result.buf, _i,
                  selrec.selr_selectbuffer.result.len);
            t01buf (kb, selrec.selr_selectbuffer.buf_rec.buf, _recpos + _i,
                  _recpos+selrec.selr_selectbuffer.result.len);
            t01int4 (kb, 'lc          ', ord(_lc));
            IF  _is_equal
            THEN
                t01int4 (kb,'is_equal    ', 1);
&           endif
            (*ENDIF*) 
            _recpos := _recpos + selrec.selr_selectbuffer.result.len
            END;
        (*ENDWHILE*) 
        IF  NOT _is_equal
        THEN
            _recpos := _recpos - selrec.selr_selectbuffer.result.len;
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
IF  ((t.trError_gg00 = e_no_next_record) OR (t.trError_gg00 = e_buffer_limit))
THEN
    t.trError_gg00 := e_ok;
(*ENDIF*) 
IF  (t.trError_gg00 = e_ok)
THEN
    IF  NOT _is_equal
    THEN
        IF  ((selrec.selr.selr_countresult = 2) AND (selrec.selr.selr_maxresult = 0))
        THEN
            t.trError_gg00 := e_too_many_resultsets
        ELSE
            BEGIN
            b07cadd_record (t, selrec.selr.selr_resf_id,
                  selrec.selr_selectbuffer.result.buf);
            IF  ( selrec.selr.selr_one_result (* corr_single *)
                )
            THEN
                SAPDB_PascalMove ('VKB721',  15,    
                      sizeof(selrec.selr_selectbuffer.result.buf),
                      sizeof(selrec.selr_selectbuffer.lbuf),
                      @selrec.selr_selectbuffer.result.buf, 1,
                      @selrec.selr_selectbuffer.lbuf, 1,
                      selrec.selr_selectbuffer.result.len,
                      t.trError_gg00);
            (*ENDIF*) 
            IF  t.trError_gg00 = e_ok
            THEN
                IF  ((selrec.selr.selr_countresult = selrec.selr.selr_rowno)
                    OR
                    (selrec.selr.selr_oracle_selinto
                    AND (selrec.selr.selr_resf_id.fileTfnTemp_gg00 = ttfnInto_egg00)
                    AND (selrec.selr.selr_resf_id.fileTfn_gg00 = tfnTemp_egg00)))
                THEN
                    t.trError_gg00 := e_enough_resultsets
                (*ENDIF*) 
            (*ENDIF*) 
            END
        (*ENDIF*) 
    ELSE
        selrec.selr.selr_countresult := pred(selrec.selr.selr_countresult)
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k721longcol_insert_select (
            VAR m              : tgg00_MessBlock;
            VAR result         : tgg00_Rec;
            VAR resf_id        : tgg00_FileId);
      (* PTS 1105795 M.Ki. *)
 
VAR
      _has_shrt_col_file : boolean;
      _i                 : tsp00_Int2;
      _stack_pos         : tsp00_Int2;
      _rec_pos           : tsp00_Int4;
      _move_len          : tsp00_Int4;
      _default_pos       : tsp00_IntMapC2;
      _source_surr       : tgg00_Surrogate;
      _source_tab_surr   : tgg00_Surrogate;
      _dst_surr          : tgg00_Surrogate;
      _default_rec_ptr   : tgg00_RecPtr;
      (* PTS 1120890 E.Z. *)
 
      _ld_info_rec       : RECORD
            CASE boolean OF
                true :
                    (c1 : tsp00_C1);
                false :
                    (ld_info : tsp00_LdInfo);
                END;
            (*ENDCASE*) 
 
 
BEGIN
&ifdef TRACE
t01messblock ( kb, 'longcolins  ', m );
t01buf( kb, result.recBuf_gg00, 1, result.recLen_gg00 );
&ENDIF
IF  result.recLen_gg00 > MAX_RECLEN_GG00
THEN (* check if record would shrink enough to fit in page *)
    BEGIN
    _i               := 1;
    _move_len        := 0;
    _stack_pos       := m.mb_qual^.mstring_pos;
    REPEAT
        IF  m.mb_st^[ _stack_pos ].elen_var <> SURROGATE_MXGG00 + 1
        THEN
            (* PTS 1120890 E.Z. *)
            _move_len := _move_len +
                  m.mb_st^[ _stack_pos ].elen_var - (SURROGATE_MXGG00 + 1);
        (*ENDIF*) 
        _i := succ (_i);
    UNTIL
        _i > m.mb_qual^.mstring_cnt;
    (*ENDREPEAT*) 
    IF  (result.recLen_gg00 - _move_len) > MAX_RECLEN_GG00
    THEN
        m.mb_trns^.trError_gg00 := e_too_long_record
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  m.mb_trns^.trError_gg00 = e_ok
THEN
    BEGIN
    _i               := 1;
    _move_len        := 0;
    _stack_pos       := m.mb_qual^.mstring_pos;
    (* PTS 1120890 E.Z. *)
    IF  result.recKeyLen_gg00 = 0
    THEN
        _rec_pos     := cgg_rec_key_offset + SURROGATE_MXGG00 + 1 + 1
    ELSE
        _rec_pos     := cgg_rec_key_offset + result.recKeyLen_gg00 + 1;
    (*ENDIF*) 
    _source_surr     := cgg_zero_id;
    _source_tab_surr := cgg_zero_id;
    _default_rec_ptr := NIL;
&   ifdef TRACE
    t01buf( kb, result.recBuf_gg00, 1, result.recLen_gg00 );
&   ENDIF
    REPEAT
        (* PTS 1120891 E.Z. *)
        IF  m.mb_st^[_stack_pos].elen_var = mxsp_long_desc + 1
        THEN
            BEGIN
            _ld_info_rec.c1[1] := result.recBuf_gg00
                  [_rec_pos + _move_len + 1 + 8 + 8 + 2*4];
            IF  (ld_is_comment in _ld_info_rec.ld_info) OR
                (ld_is_catalog in _ld_info_rec.ld_info)
            THEN
                m.mb_trns^.trError_gg00 := e_not_implemented;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  m.mb_trns^.trError_gg00 = e_ok
        THEN
            BEGIN
&           ifdef TRACE
            t01stackentry (kb, m.mb_st^[_stack_pos], _stack_pos);
            t01int4 (kb_qual, '_i          ', _i);
            t01int4 (kb_qual, '_move_len   ', _move_len);
            t01int4 (kb_qual, '_rec_pos    ', _rec_pos);
            t01int4 (kb_qual, 'rec_key_len ', result.recKeyLen_gg00);
&           ENDIF
            _dst_surr := resf_id.fileTabId_gg00; (* PTS 1116809 M.Ki. *)
            IF  m.mb_st^[_stack_pos].ecol_tab[2] = chr(1)
            THEN
                _has_shrt_col_file := true
            ELSE
                _has_shrt_col_file := false;
            (*ENDIF*) 
            SAPDB_PascalMove ('VKB721',  16,    
                  sizeof(result.recBuf_gg00), SURROGATE_MXGG00,
                  @result.recBuf_gg00, _rec_pos + _move_len + 1,
                  @_source_surr, 1,
                  SURROGATE_MXGG00,
                  m.mb_trns^.trError_gg00);
            IF  m.mb_st^[ _stack_pos ].elen_var = SURROGATE_MXGG00 + 1
            THEN  (* null or default value *)
                BEGIN
                IF  (_source_surr = cgg_zero_id)
                THEN
                    BEGIN
                    SAPDB_PascalOverlappingMove ('VKB721',  17,    
                          sizeof(result.recBuf_gg00), sizeof(result.recBuf_gg00),
                          @result.recBuf_gg00, _rec_pos + _move_len,
                          @result.recBuf_gg00, _rec_pos,
                          SURROGATE_MXGG00 + 1,
                          m.mb_trns^.trError_gg00);
                    END
                ELSE (* default value; position of default record in data part *)
                    (*  is in surrogate                                        *)
                    BEGIN
                    _default_pos.mapC2_sp00[ 1 ] := _source_surr [SURROGATE_MXGG00 - 1];
                    _default_pos.mapC2_sp00[ 2 ] := _source_surr [SURROGATE_MXGG00];
                    _default_rec_ptr := @m.mb_data^.mbp_buf[ _default_pos.mapInt_sp00 ];
&                   ifdef TRACE
                    t01int4 (kb_qual, 'default pos ', _default_pos.mapInt_sp00);
                    t01buf  (kb_qual, _default_rec_ptr^.recBuf_gg00, 1,
                          _default_rec_ptr^.recLen_gg00 );
&                   ENDIF
                    k43_ins_copy_column (m.mb_trns, m.mb_header, m.mb_qual^.mtree,
                          resf_id,
                          _source_tab_surr, _source_surr, _dst_surr, _has_shrt_col_file,
                          _default_rec_ptr, c_use_shc_buf);
                    SAPDB_PascalMove ('VKB721',  18,    
                          SURROGATE_MXGG00, sizeof(result.recBuf_gg00),
                          @_dst_surr, 1,
                          @result.recBuf_gg00, _rec_pos + 1,
                          SURROGATE_MXGG00,
                          m.mb_trns^.trError_gg00);
                    result.recBuf_gg00[ _rec_pos ] := csp_defined_byte;
                    END;
                (*ENDIF*) 
                END
            ELSE
                BEGIN (* something was inserted into this column *)
                IF  _source_surr <> cgg_zero_id
                THEN
                    BEGIN
                    SAPDB_PascalMove ('VKB721',  19,    
                          sizeof(result.recBuf_gg00), SURROGATE_MXGG00,
                          @result.recBuf_gg00,
                          _rec_pos + _move_len + SURROGATE_MXGG00 + 1,
                          @_source_tab_surr, 1,
                          SURROGATE_MXGG00,
                          m.mb_trns^.trError_gg00);
                    k43_ins_copy_column (m.mb_trns, m.mb_header, m.mb_qual^.mtree,
                          resf_id,
                          _source_tab_surr, _source_surr, _dst_surr, _has_shrt_col_file,
                          _default_rec_ptr, NOT c_use_shc_buf);
                    SAPDB_PascalMove ('VKB721',  20,    
                          SURROGATE_MXGG00, sizeof(result.recBuf_gg00),
                          @_dst_surr, 1,
                          @result.recBuf_gg00, _rec_pos + 1,
                          SURROGATE_MXGG00,
                          m.mb_trns^.trError_gg00);
                    result.recBuf_gg00[ _rec_pos ] := csp_defined_byte;
                    END
                ELSE (* move null value to correct position *)
                    BEGIN
                    SAPDB_PascalMove ('VKB721',  21,    
                          SURROGATE_MXGG00, sizeof(result.recBuf_gg00),
                          @_source_surr, 1,
                          @result.recBuf_gg00, _rec_pos + 1,
                          SURROGATE_MXGG00,
                          m.mb_trns^.trError_gg00);
                    result.recBuf_gg00[ _rec_pos ] := csp_undef_byte;
                    END;
                (*ENDIF*) 
                (* PTS 1120891 E.Z. *)
                _move_len := _move_len +
                      m.mb_st^[ _stack_pos ].elen_var - (SURROGATE_MXGG00 + 1);
                END;
            (*ENDIF*) 
            _rec_pos   := _rec_pos + SURROGATE_MXGG00 + 1;
            _stack_pos := succ(_stack_pos);
            _i         := succ(_i);
&           ifdef TRACE
            t01buf( kb, result.buf, 1, result.recLen_gg00 );
&           ENDIF
            END
        (*ENDIF*) 
    UNTIL
        (_i > m.mb_qual^.mstring_cnt) OR (m.mb_trns^.trError_gg00 <> e_ok);
    (*ENDREPEAT*) 
    (* shrink record and correct record size and varcol offset *)
    SAPDB_PascalOverlappingMove ('VKB721',  22,    
          result.recLen_gg00, result.recLen_gg00,
          @result.recBuf_gg00, _rec_pos + _move_len,
          @result.recBuf_gg00, _rec_pos,
          result.recLen_gg00 + 1 - _rec_pos - _move_len,
          m.mb_trns^.trError_gg00);
    result.recLen_gg00          := result.recLen_gg00 - _move_len;
    result.recVarcolOffset_gg00 := result.recVarcolOffset_gg00 - _move_len;
&   ifdef TRACE
    t01buf( kb, result.buf, 1, result.recLen_gg00 );
&   ENDIF
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb721result_handle (
            VAR m              : tgg00_MessBlock;
            VAR selrec         : tgg07_select_param;
            VAR getrec         : tgg07_get_param;
            VAR selfields      : tgg00_SelectFieldsParam;
            VAR act_key        : tgg00_Lkey;
            VAR htree_id       : tgg00_FileId;
            granted_lock       : tgg00_LockReqMode);
 
VAR
      _put_into      : boolean;
      _hlen          : tsp00_Int2;
      _hvarcoloffset : tsp00_Int2;
      _hvarcolcnt    : tsp00_Int2;
      _old_tr_err    : tgg00_BasisError;
 
BEGIN
_old_tr_err := e_ok;
selrec.selr.selr_act_cntresult := selfields.sfp_m_result_cnt;
&ifdef trace
t01int4 (kb, 'act_cntresul', selrec.selr.selr_act_cntresult);
t01basis_error (kb, 'bd error    ',m.mb_trns^.trError_gg00);
&endif
;
IF  ( selrec.selr.selr_act_cntresult > 0 )
THEN
    IF  ( m.mb_trns^.trError_gg00 = e_no_next_record ) OR
        ( m.mb_trns^.trError_gg00 = e_no_prev_record )
    THEN
        BEGIN
        _old_tr_err             := m.mb_trns^.trError_gg00;
        m.mb_trns^.trError_gg00 := e_ok;
        END;
    (*ENDIF*) 
(*ENDIF*) 
IF  ( m.mb_trns^.trRteCommPtr_gg00^.to_cancel )
THEN
    m.mb_trns^.trError_gg00 := e_cancelled;
(*ENDIF*) 
IF  ( m.mb_trns^.trError_gg00 in
    [ e_key_not_found, e_qual_violation, e_view_violation ] )
THEN
    m.mb_trns^.trError_gg00 := e_ok
ELSE
    BEGIN
    IF  ( m.mb_trns^.trError_gg00 = e_buffer_limit ) AND
        ( m.mb_type = m_insert_select )
    THEN
        m.mb_trns^.trError_gg00 := e_too_long_record
    ELSE
        BEGIN
        IF  ( m.mb_trns^.trError_gg00 = e_ok )
        THEN
            BEGIN
            _put_into := true;
            IF  ( selrec.selr.selr_intern_dist )
            THEN
                BEGIN
                WITH selrec.selr_selectbuffer.buf_rec DO
                    BEGIN
                    _hlen                := len;
                    len                  := keylen + cgg_rec_key_offset;
                    _hvarcoloffset       := recVarcolOffset_gg00;
                    recVarcolOffset_gg00 := 0;
                    _hvarcolcnt          := recVarcolCnt_gg00;
                    recVarcolCnt_gg00    := 0;
                    b07cadd_record( m.mb_trns^,
                          selrec.selr.selr_distinct_id,
                          selrec.selr_selectbuffer.buf_rec.buf );
                    len                  := _hlen;
                    recVarcolOffset_gg00 := _hvarcoloffset;
                    recVarcolCnt_gg00    := _hvarcolcnt;
                    END;
                (*ENDWITH*) 
                IF  ( m.mb_trns^.trError_gg00 = e_duplicate_key )
                THEN
                    BEGIN
                    _put_into := false;
                    selfields.sfp_rows_qual := selfields.sfp_rows_qual - 1;
                    m.mb_trns^.trError_gg00 := e_ok
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  _put_into AND ( m.mb_trns^.trError_gg00 = e_ok )
            THEN
                BEGIN
                IF  ( m.mb_type in [ m_update, m_delete, m_insert_select ] )
                THEN
                    BEGIN
                    IF  ( m.mb_type in [ m_update, m_delete ] )
                    THEN
                        BEGIN
                        (* PTS 1120259 E.Z. *)
                        (*mess2_type = mm_qual*)
                        IF  ( m.mb_type = m_update )
                        THEN
                            BEGIN
                            k63upd_select( m, act_key,
                                  selrec.selr_selectbuffer.buf_rec,
                                  @selfields,
                                  @selrec.selr_selectbuffer.longresult,
                                  selfields.sfp_result_length,
                                  selrec.selr_selectbuffer.lbuf,
                                  selrec.selr.selr_intersect_id,
                                  granted_lock );
                            WHILE ( m.mb_trns^.trError_gg00 =
                                  e_wait_for_lock_release ) DO
                                BEGIN
                                k53wait( m.mb_trns^, m.mb_type,
                                      m.mb_type2 );
                                IF  ( m.mb_trns^.trError_gg00 = e_ok )
                                THEN
                                    k63upd_select( m, act_key,
                                          selrec.selr_selectbuffer.buf_rec,
                                          @selfields,
                                          @selrec.selr_selectbuffer.longresult,
                                          selfields.sfp_result_length,
                                          selrec.selr_selectbuffer.lbuf,
                                          selrec.selr.selr_intersect_id,
                                          granted_lock );
                                (*ENDIF*) 
                                END;
                            (*ENDWHILE*) 
                            END
                        ELSE
                            k61del_select( m, act_key,
                                  selrec.selr_selectbuffer.buf_rec,
                                  granted_lock );
                        (*ENDIF*) 
                        IF  ( m.mb_trns^.trError_gg00 = e_skip_key_upd )
                        THEN
                            m.mb_trns^.trError_gg00 := e_ok
                        ELSE
                            (* PTS 1120259 E.Z. *)
                            IF  ( m.mb_type = m_update)   AND
                                ( selrec.selr.selr_countresult = 1 ) AND
                                ( selrec.selr.selr_maxresult = 0 )
                            THEN
                                m.mb_trns^.trError_gg00 := e_too_many_updatesets
                            ELSE
                                selrec.selr.selr_countresult :=
                                      succ( selrec.selr.selr_countresult );
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        (* m.mb_type = m_insert_select *)
                        IF  ( selrec.selr.selr_is_nokey )
                        THEN
                            selrec.selr_selectbuffer.result.keylen :=
                                  1 + SURROGATE_MXGG00;
                        (*ENDIF*) 
                        selrec.selr_selectbuffer.result.len := selfields.sfp_result_length;
                        ;
                        IF  m.mb_qual^.mstring_cnt > 0
                        THEN (* PTS 1105795 M.Ki. *)
                            k721longcol_insert_select (m,
                                  selrec.selr_selectbuffer.result,
                                  selrec.selr.selr_resf_id);
                        (*ENDIF*) 
                        IF  m.mb_trns^.trError_gg00 = e_ok
                        THEN
                            IF  ( selrec.selr_selectbuffer.result.len > MAX_RECLEN_GG00 )
                            THEN
                                m.mb_trns^.trError_gg00 := e_too_long_record
                            ELSE
                                BEGIN
&                               ifdef TRACE
                                t01buf( kb, selrec.selr_selectbuffer.result.buf, 1,
                                      selrec.selr_selectbuffer.result.len );
                                IF  ( selrec.selr.selr_is_nokey )
                                THEN
                                    t01int4( kb, 'is_nokey    ', 1 );
&                               endif
                                (*ENDIF*) 
                                m.mb_qual^.mtree := selrec.selr.selr_resf_id;
                                k61ins_select( m,
                                      selrec.selr_selectbuffer.result,
                                      selrec.selr.selr_is_nokey,
                                      selrec.selr.selr_dupl[ 1 ] = cgg04_update_dupl,
                                      selrec.selr.selr_countresult + 1 );
                                WHILE ( m.mb_trns^.trError_gg00 =
                                      e_wait_for_lock_release ) DO
                                    BEGIN
                                    k53wait( m.mb_trns^, m.mb_type,
                                          m.mb_type2 );
                                    IF  ( m.mb_trns^.trError_gg00 = e_ok )
                                    THEN
                                        k61ins_select( m,
                                              selrec.selr_selectbuffer.result,
                                              selrec.selr.selr_is_nokey,
                                              selrec.selr.selr_dupl[ 1 ] =
                                              cgg04_update_dupl,
                                              selrec.selr.selr_countresult + 1 );
                                    (*ENDIF*) 
                                    END;
                                (*ENDWHILE*) 
                                m.mb_qual^.mtree := htree_id;
                                IF  (m.mb_trns^.trError_gg00 = e_ok)
                                THEN
                                    BEGIN
                                    selrec.selr.selr_countresult :=
                                          succ( selrec.selr.selr_countresult );
                                    IF  ( selrec.selr.selr_countresult =
                                        selrec.selr.selr_rowno )
                                    THEN
                                        m.mb_trns^.trError_gg00 :=
                                              e_enough_resultsets;
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    IF  ( m.mb_trns^.trError_gg00 =
                                        e_duplicate_key )
                                    THEN
                                        IF  ( selrec.selr.selr_dupl[ 1 ] = cgg04_ignore_dupl )
                                        THEN
                                            m.mb_trns^.trError_gg00 := e_ok;
                                        (*ENDIF*) 
                                    (*ENDIF*) 
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    (* NOT m_update, m_delete, m_insert_select *)
                    BEGIN
                    selrec.selr_selectbuffer.result.len    := selrec.selr.selr_recl;
                    selrec.selr_selectbuffer.result.keylen := selrec.selr.selr_keyl;
&                   ifdef trace
                    t01int4 (kb, 'result.len  ',
                          selrec.selr_selectbuffer.result.len);
                    t01int4 (kb, 'result.keyle',
                          selrec.selr_selectbuffer.result.keylen);
&                   endif
                    IF  ( m.mb_type2 = mm_with_functions )
                    THEN
                        (* one table select *)
                        k721function_add( m, selrec, NOT c_aggr )
                    ELSE
                        BEGIN
                        IF  ( m.mb_type2 = mm_with_join )
                        THEN
                            BEGIN
                            (* join w/o transition *)
                            k74join_with_left_result( m, getrec,
                                  selfields, selrec )
                            END
                        ELSE
                            BEGIN
                            k721add_into_result( m.mb_trns^,
                                  selrec, m.mb_next_mblock );
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  ( m.mb_trns^.trError_gg00 = e_ok ) AND ( _old_tr_err <> e_ok )
THEN
    m.mb_trns^.trError_gg00 := _old_tr_err;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k721add_into_result (
            VAR t                : tgg00_TransContext;
            VAR selrec           : tgg07_select_param;
            VAR next_mblock      : tgg00_MessBlockPtr);
 
TYPE
 
      t_rec_buf = RECORD
            CASE boolean OF
                true:
                    (buf   : tsp00_Buf);
                false:
                    (rec_head : tgg00_HeaderRec;
                    info      : tgg00_RecBody);
                END;
            (*ENDCASE*) 
 
 
VAR
      _ix          : tsp00_Int4;
      _iy          : tsp00_Int4;
      _recpos      : tsp00_Int4;
      _aligned_len : tsp00_Int4;
      _lkey        : tgg00_Lkey;
      _result_ptr  : ^t_rec_buf;
 
BEGIN
_ix          := 1;
_aligned_len := 0;
IF  ( selrec.selr.selr_act_cntresult < 1 )
THEN
    selrec.selr.selr_act_cntresult := 1
ELSE
    BEGIN
    IF  ( selrec.selr.selr_one_result )
    THEN
        selrec.selr.selr_act_cntresult := 1
    ELSE
        BEGIN
        IF  ( selrec.selr.selr_resrec_maxlen MOD 2 = 1 )
        THEN
            _aligned_len := selrec.selr.selr_resrec_maxlen + 1
        ELSE
            _aligned_len := selrec.selr.selr_resrec_maxlen;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
&ifdef TRACE
t01int4 (kb, 'selr_union  ', ord(selrec.selr.selr_union));
t01int4 (kb, 'selr_union_s', ord(selrec.selr.selr_union_select));
t01int4 (kb, 'selr_append ', ord(selrec.selr.selr_append_all ));
t01treeid( kb, 'result file ', selrec.selr.selr_resf_id );
t01int4 (kb_qual, 'resrec_maxl ', selrec.selr.selr_resrec_maxlen);
t01int4 (kb_qual, 'aligned_len ', _aligned_len);
t01int4 (kb_qual, 'act_cntreslt', selrec.selr.selr_act_cntresult);
t01int4 (kb_qual, 'rec len     ', selrec.selr_selectbuffer.result.len);
t01int4 (kb_qual, 'key len     ', selrec.selr_selectbuffer.result.keylen);
t01buf  (kb_qual, selrec.selr_selectbuffer.result.buf, 1 + cgg_rec_key_offset,
      cgg_rec_key_offset + selrec.selr_selectbuffer.result.keylen );
&endif
WHILE ( _ix <= selrec.selr.selr_act_cntresult ) AND
      ( t.trError_gg00 = e_ok ) DO
    BEGIN
    IF  ( _ix = 1 )
    THEN
        (* initialize _result_ptr with 'result' *)
        _result_ptr := @selrec.selr_selectbuffer.result
    ELSE
        BEGIN
        _result_ptr := @_result_ptr^.buf[ 1 + _aligned_len ];
        _result_ptr^.rec_head.hrecLen_gg00          :=
              selrec.selr_selectbuffer.result.recLen_gg00;
        _result_ptr^.rec_head.hrecKeyLen_gg00       :=
              selrec.selr_selectbuffer.result.recKeyLen_gg00;
        _result_ptr^.rec_head.hrecVarcolOffset_gg00 := 0;
        _result_ptr^.rec_head.hrecVarcolCnt_gg00    := 0;
        END;
    (*ENDIF*) 
    IF  ( selrec.selr.selr_union_select )
    THEN
        k722_add_union_record (t, selrec)
    ELSE
        BEGIN
        IF  (next_mblock <> NIL) AND
            (selrec.selr_selectbuffer.result.keylen > RESCNT_MXGG04)
        THEN
            IF  (next_mblock^.mb_data <> NIL) AND
                (next_mblock^.mb_qual <> NIL) AND
                (next_mblock^.mb_st   <> NIL)
            THEN
                BEGIN
                (* **** In case of following joinsteps, the pages      *)
                (*      will be read into datacache               **** *)
                _lkey.keyLen_gg00 :=
                      selrec.selr_selectbuffer.result.recKeyLen_gg00 - RESCNT_MXGG04;
                SAPDB_PascalMove ('VKB721',  23,    
                      sizeof (_result_ptr^.buf), sizeof(_lkey.keyVal_gg00),
                      @_result_ptr^.buf, cgg_rec_key_offset + 1,
                      @_lkey.keyVal_gg00, 1, _lkey.keyLen_gg00, t.trError_gg00);
                IF  ( t.trError_gg00 <> e_move_error )
                THEN
                    k75pre_fetch (t, next_mblock^.mb_qual^.mtree, _lkey);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        selrec.selr.selr_countresult := succ(selrec.selr.selr_countresult);
        (* add result counter *)
        s20ch4sw (selrec.selr.selr_countresult, g01code.kernel_swap,
              _result_ptr^.info, selrec.selr_selectbuffer.result.keylen - 3,
              sw_normal);
&       ifdef trace
        t01name (kb_qual, 'added counter     ');
        t01buf  (kb_qual, selrec.selr_selectbuffer.result.buf, 1,
              selrec.selr_selectbuffer.result.len );
&       endif
        IF  (( selrec.selr.selr_distinct <> no_distinct )
            AND NOT selrec.selr.selr_write_rownum )
        THEN
            kb721unique_add (t, selrec)
        ELSE
            BEGIN
            IF  ( selrec.selr.selr_union )
            THEN
                BEGIN
                _recpos := selrec.selr_selectbuffer.result.keylen +
                      cgg_rec_key_offset + 2;
                _iy     := selrec.selr_selectbuffer.result.len -
                      selrec.selr_selectbuffer.result.keylen -
                      cgg_rec_key_offset - 1;
&               ifdef TRACE
                t01int4 (kb, 'iy          ', _iy);
                t01buf (kb, _result_ptr^.buf, _iy + 1,
                      selrec.selr_selectbuffer.result.len);
&               endif
                k50hash (_result_ptr^.buf, _recpos, _iy,
                      _result_ptr^.buf,
                      cgg_rec_key_offset +
                      selrec.selr_selectbuffer.result.keylen - RESCNT_MXGG04 -
                      cgg04_cdistinct_bytes + 1);
                END;
            (*ENDIF*) 
            IF  ((selrec.selr.selr_countresult = 2) AND (selrec.selr.selr_maxresult = 0))
            THEN
                t.trError_gg00 := e_too_many_resultsets
            ELSE
                BEGIN
                IF  ( selrec.selr.selr_one_result )
                THEN
                    BEGIN
&                   ifdef trace
                    t01name (kb, 'buf --> lbuf      ');
&                   endif
                    SAPDB_PascalMove ('VKB721',  24,    
                          sizeof(_result_ptr^.buf),
                          sizeof(selrec.selr_selectbuffer.lbuf),
                          @_result_ptr^.buf, 1,
                          @selrec.selr_selectbuffer.lbuf, 1,
                          _result_ptr^.rec_head.hrecLen_gg00,
                          t.trError_gg00);
                    END
                ELSE
                    BEGIN
                    IF  ( selrec.selr_selectbuffer.result.keylen > RESCNT_MXGG04 )
                    THEN
                        BEGIN
                        b07cadd_record (t, selrec.selr.selr_resf_id,
                              _result_ptr^.buf);
                        IF  NOT selrec.selr.selr_no_warn8_sort
                        THEN
                            BEGIN
&                           ifdef TRACE
                            t01int4 (kb_qual, 'WARN8 SORT  ', 0);
&                           endif
                            t.trWarning_gg00 := t.trWarning_gg00 +
                                  [ warn0_exist, warn8_scan_or_sort ];
                            selrec.selr.selr_no_warn8_sort := true;
                            END;
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
&                       ifdef TRACE
                        t01int4 (bi, 'tree_page be',
                              selrec.selr.selr_tree_pos.tpsPno_gg00);
                        t01int4 (bi, 'tree_pos  be',
                              selrec.selr.selr_tree_pos.tpsIndex_gg00);
&                       endif
                        b07cappend_record (t, selrec.selr.selr_resf_id,
                              selrec.selr.selr_tree_pos, _result_ptr^.buf);
&                       ifdef TRACE
                        t01int4 (bi, 'tree_page af',
                              selrec.selr.selr_tree_pos.tpsPno_gg00);
                        t01int4 (bi, 'tree_pos  af',
                              selrec.selr.selr_tree_pos.tpsIndex_gg00);
&                       endif
                        (* PTS 1107952 E.Z. *)
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  ( t.trError_gg00 = e_ok )
            THEN
                IF  (( selrec.selr.selr_countresult = selrec.selr.selr_rowno )
                    OR
                    ( selrec.selr.selr_oracle_selinto
                    AND ( selrec.selr.selr_resf_id.fileTfnTemp_gg00 = ttfnInto_egg00 )
                    AND ( selrec.selr.selr_resf_id.fileTfn_gg00 = tfnTemp_egg00 )))
                THEN
                    t.trError_gg00 := e_enough_resultsets
                ELSE
                    BEGIN
                    IF  ( t.trRteCommPtr_gg00^.to_cancel )
                    THEN
                        t.trError_gg00 := e_cancelled;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    _ix := succ(_ix);
    END;
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k721call_later_output (
            VAR m       : tgg00_MessBlock;
            VAR res_buf : tsp00_Buf;
            keylen      : integer);
 
VAR
      _stop  : integer;
      _i     : integer;
      _ic2   : tsp_int_map_c2;
 
BEGIN
_i := m.mb_qual^.mqual_pos;
IF  m.mb_st^[ m.mb_qual^.mqual_pos ].etype = st_jump_output
THEN
    _stop := m.mb_qual^.mqual_pos + m.mb_st^[ m.mb_qual^.mqual_pos ].epos - 2
ELSE
    _stop := m.mb_qual^.mqual_pos;
(*ENDIF*) 
&ifdef TRACE
t01messblock (kb, 'later       ', m);
t01int4 (kb, 'i           ', _i);
t01int4 (kb, 'stop        ', _stop);
t01int4 (kb, 'keylen      ', keylen);
&endif
WHILE ( _i <= _stop ) DO
    BEGIN
    IF  ( m.mb_st^[ _i ].etype = st_output ) AND
        ( m.mb_st^[ _i ].eop_out = op_o_output_later )
    THEN
        BEGIN
        (* copy OUTPUT (aggregated value) to OUTPUT_LATER position *)
        SAPDB_PascalOverlappingMove ('VKB721',  25,    
              sizeof(res_buf), sizeof(res_buf),
              @res_buf, m.mb_st^[ _i - 1 ].epos,
              @res_buf, m.mb_st^[ _i ].epos, m.mb_st^[ _i ].elen_var,
              m.mb_trns^.trError_gg00);
        END;
    (*ENDIF*) 
    _i := succ(_i);
    END;
(*ENDWHILE*) 
;
(* write keylen *)
_ic2.map_int := keylen;
res_buf[ 3 ] := _ic2.map_c2[ 1 ];
res_buf[ 4 ] := _ic2.map_c2[ 2 ];
FOR _i := 1 TO RESCNT_MXGG04 - 1 DO
    res_buf[ cgg_rec_key_offset + keylen - RESCNT_MXGG04 + _i ] := chr(0);
(*ENDFOR*) 
res_buf[ cgg_rec_key_offset + keylen ] := chr(1);
END;
 
(*------------------------------*) 
 
PROCEDURE
      k721do_avg (
            VAR m        : tgg00_MessBlock;
            VAR selrec   : tgg07_select_param;
            later_output : boolean;
            keylen     : integer);
 
VAR
      _set_result     : tgg00_BdSetResultRecord;
      _no_repl_needed : boolean;
      _overfl         : boolean;
      _repl_needed    : boolean;
      _func_pos            : integer;
      _disnum         : integer;
      _output_start   : integer;
      _trunc_len      : integer;
      _length         : integer;
      _stpos          : integer;
      _cnt_repl       : tsp00_Int4;
      _hkey           : tgg00_Lkey;
      _ret            : tsp00_NumError;
      _dist_file      : tgg00_FileId;
 
BEGIN
_trunc_len        := IS_UNDEFINED_GG07;
_dist_file        := selrec.selr.selr_distinct_id;
_output_start     := m.mb_qual^.mqual_pos;
_hkey.keyLen_gg00 := 0;
_no_repl_needed   := true;
_cnt_repl         := 0;
_set_result.bd_key_check_len := 0;
_set_result.bd_max_rec_cnt   := 1;
_set_result.bd_max_fill_len  := mxsp_buf;
_set_result.bd_next          := true;
_set_result.bd_drop_page     := false;
selrec.selr.selr_tree_pos.tpsPno_gg00 := NIL_PAGE_NO_GG00;
REPEAT
    _func_pos := _output_start + m.mb_st^[ _output_start ].epos - 2;
    _disnum := 0;
    IF  ( selrec.selr.selr_one_result )
    THEN
        BEGIN
&       ifdef trace
        t01name( kb, 'lbuf --> result   ' );
&       endif
        m.mb_trns^.trError_gg00 := e_ok;
        SAPDB_PascalMove ('VKB721',  26,    
              sizeof(selrec.selr_selectbuffer.lbuf),
              sizeof(selrec.selr_selectbuffer.result.buf),
              @selrec.selr_selectbuffer.lbuf, 1,
              @selrec.selr_selectbuffer.result.buf, 1,
              selrec.selr.selr_recl, m.mb_trns^.trError_gg00);
        END
    ELSE
        b07cnext_record (m.mb_trns^, selrec.selr.selr_resf_id,
              _hkey, _set_result, selrec.selr.selr_tree_pos,
              selrec.selr_selectbuffer.result.buf);
    (*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_key_not_found )
    THEN
        m.mb_trns^.trError_gg00 := e_ok;
    (*ENDIF*) 
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        _repl_needed := false;
        WHILE (( _func_pos - m.mb_st^[ _func_pos ].epos > _output_start ) AND
              ( m.mb_trns^.trError_gg00 = e_ok )) DO
            BEGIN
            _func_pos := _func_pos - m.mb_st^[ _func_pos ].epos;
            (* loop over LASTFUNCTIONs *)
            WHILE (( m.mb_st^[ _func_pos ].etype = st_func ) AND
                  ( m.mb_st^[ _func_pos ].eop_func = op_f_none )) DO
                _func_pos := _func_pos - m.mb_st^[ _func_pos ].epos;
            (*ENDWHILE*) 
            _stpos    := k721out_entry (m.mb_st, _func_pos);
            IF  (( m.mb_st^[ _func_pos ].eop_func in [
                op_f_dis_avg, op_f_dis_sum, op_f_dis_count, op_f_dis_stddev,
                op_f_dis_variance, op_f_stddev, op_f_variance ] )) AND
                ( m.mb_st^[ _func_pos ].etype = st_func )
            THEN
                IF  ( _disnum < cgg07_maxdistinctfiles )
                THEN
                    BEGIN
                    _disnum := succ(_disnum);
                    _dist_file.fileTempCnt_gg00   := _disnum;
                    _dist_file.fileRoot_gg00      :=
                          selrec.selr.selr_disrootarr[ _disnum ].dfi_root;
                    _dist_file.fileRootCheck_gg00 :=
                          selrec.selr.selr_disrootarr[ _disnum ].dfi_root_check;
                    END
                ELSE
                    m.mb_trns^.trError_gg00 := e_buffer_limit;
                (*ENDIF*) 
            (*ENDIF*) 
            IF  (m.mb_st^[ _func_pos ].etype = st_func)
                AND
                (
                (
                ( m.mb_st^[ _func_pos ].eop_func in
                [ op_f_avg   , op_f_dis_avg,
                op_f_sum     , op_f_dis_sum ] ) AND
                (selrec.selr.selr_call_avg = sfh_all)
                )
                OR
                ( m.mb_st^[ _func_pos ].eop_func in
                [ op_f_stddev, op_f_dis_stddev,
                op_f_variance, op_f_dis_variance ] )
                )
            THEN
                BEGIN
                _no_repl_needed := false;
                IF  NOT ( m.mb_st^[ _func_pos ].eop_func in
                    [ op_f_sum, op_f_dis_sum ] )
                THEN
                    WITH m.mb_st^[ _stpos ] DO
                        BEGIN
                        IF  ( selrec.selr_selectbuffer.result.buf[ epos ] <> csp_undef_byte ) AND
                            ( selrec.selr_selectbuffer.result.buf[ epos ] <> csp_oflw_byte )
                        THEN
                            BEGIN
                            s51div (selrec.selr_selectbuffer.result.buf, epos+1, NUMBER_MXGG04-1,
                                  selrec.selr_selectbuffer.result,
                                  epos+NUMBER_MXGG04+1, mxsp_resnum-1,
                                  selrec.selr_selectbuffer.result, epos+1,
                                  csp_fixed,
                                  csp_float_frac, _length, _ret);
                            _repl_needed := true;
                            _trunc_len   := epos + NUMBER_MXGG04;
                            IF  ( m.mb_st^[ _func_pos ].eop_func in
                                [ op_f_stddev, op_f_dis_stddev,
                                op_f_variance, op_f_dis_variance ] )
                            THEN
                                k721stddev( m.mb_trns, _dist_file,
                                      selrec.selr_selectbuffer.result,
                                      selrec.selr_selectbuffer.buf_rec,
                                      selrec.selr_selectbuffer.rbuf,
                                      m.mb_st^[ _func_pos ].eop_func,
                                      m.mb_st^[ _stpos ].epos );
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDWITH*) 
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDWHILE*) 
        IF  ( later_output )
        THEN
            k721call_later_output (m, selrec.selr_selectbuffer.result.buf, keylen);
&       ifdef trace
        (*ENDIF*) 
        t01buf( kb, selrec.selr_selectbuffer.result.buf, 1,
              selrec.selr_selectbuffer.result.len );
&       endif
        IF  ( selrec.selr.selr_one_result )
        THEN
            BEGIN
&           ifdef trace
            t01name( kb, 'result --> lbuf   ' );
&           endif
            _no_repl_needed := true;
            SAPDB_PascalMove ('VKB721',  27,    
                  sizeof(selrec.selr_selectbuffer.result.buf),
                  sizeof(selrec.selr_selectbuffer.lbuf),
                  @selrec.selr_selectbuffer.result.buf, 1,
                  @selrec.selr_selectbuffer.lbuf, 1,
                  selrec.selr.selr_recl, m.mb_trns^.trError_gg00);
            END
        ELSE
            BEGIN
            IF  ( _repl_needed AND ( m.mb_trns^.trError_gg00 = e_ok ))
            THEN
                BEGIN
                _cnt_repl := succ(_cnt_repl);
                IF  (_trunc_len > 0) AND
                    (_trunc_len + mxsp_resnum-1 = selrec.selr_selectbuffer.result.recLen_gg00)
                THEN
                    selrec.selr_selectbuffer.result.recLen_gg00 := _trunc_len;
                (*ENDIF*) 
                b07ctrepl_record (m.mb_trns^, selrec.selr.selr_resf_id, selrec.selr.selr_tree_pos,
                      selrec.selr_selectbuffer.result.buf);
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END
    (*ENDIF*) 
UNTIL
    (( m.mb_trns^.trError_gg00 <> e_ok ) OR _no_repl_needed );
(*ENDREPEAT*) 
IF  ( m.mb_trns^.trError_gg00 = e_no_next_record )
THEN
    m.mb_trns^.trError_gg00 := e_ok;
(*ENDIF*) 
b73cmds_count (iins_sorts_rows_ins, _cnt_repl);
END;
 
(*------------------------------*) 
 
PROCEDURE
      k721do_rowno (
            VAR m      : tgg00_MessBlock;
            VAR selrec : tgg07_select_param);
 
VAR
      _set_result : tgg00_BdSetResultRecord;
      _last       : integer;
      _i          : integer;
      _j          : integer;
      _pos        : integer;
      _hkey       : tgg00_Lkey;
      _ret        : tsp00_NumError;
      _rowno_pos  : PACKED ARRAY [ 1..MAX_COL_PER_TAB_GG00 ] OF tsp00_Int2;
 
BEGIN
_last := m.mb_st^[ m.mb_qual^.mqual_pos ].epos + m.mb_qual^.mqual_pos - 1;
_i    := 1;
_j    := 0;
WHILE ( _i < _last ) DO
    BEGIN
    WHILE (( _i < _last ) AND ( m.mb_st^[ _i ].etype <> st_rowno )) DO
        _i := succ (_i);
    (*ENDWHILE*) 
    IF  ( _i < _last )
    THEN
        IF  ( m.mb_st^[ _i ].etype = st_rowno )
        THEN
            BEGIN
            _i := k721out_entry (m.mb_st, _i);
            IF  ( m.mb_st^[ _i ].etype = st_output )
            THEN
                BEGIN
                _j               := succ (_j);
                _rowno_pos[ _j ] := m.mb_st^[ _i ].epos;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
_set_result.bd_key_check_len := 0;
_set_result.bd_max_rec_cnt   := 1;
_set_result.bd_max_fill_len  := mxsp_buf;
_set_result.bd_next          := true;
_set_result.bd_drop_page     := false;
selrec.selr.selr_countresult      := 0;
_hkey.len            := 0;
selrec.selr.selr_tree_pos.tpsPno_gg00 := NIL_PAGE_NO_GG00;
REPEAT
    b07cnext_record (m.mb_trns^, selrec.selr.selr_resf_id, _hkey,
          _set_result, selrec.selr.selr_tree_pos,
          selrec.selr_selectbuffer.result.buf);
    IF  ( m.mb_trns^.trRteCommPtr_gg00^.to_cancel )
    THEN
        m.mb_trns^.trError_gg00 := e_cancelled;
    (*ENDIF*) 
    IF  ( m.mb_trns^.trError_gg00 = e_key_not_found )
    THEN
        m.mb_trns^.trError_gg00 := e_ok;
    (*ENDIF*) 
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        selrec.selr.selr_countresult := succ (selrec.selr.selr_countresult);
        FOR _i := 1 TO _j DO
            BEGIN
            _pos := _rowno_pos[ _i ];
            selrec.selr_selectbuffer.result.buf[ _pos ] := csp_defined_byte;
            s41plint (selrec.selr_selectbuffer.result.buf, _pos + 1,
                  csp_resnum_deflen, 0, selrec.selr.selr_countresult, _ret);
            END;
        (*ENDFOR*) 
        b07ctrepl_record (m.mb_trns^, selrec.selr.selr_resf_id,
              selrec.selr.selr_tree_pos,
              selrec.selr_selectbuffer.result.buf);
        END;
    (*ENDIF*) 
UNTIL
    ( m.mb_trns^.trError_gg00 <> e_ok );
(*ENDREPEAT*) 
IF  ( m.mb_trns^.trError_gg00 = e_no_next_record )
THEN
    m.mb_trns^.trError_gg00 := e_ok;
(*ENDIF*) 
b73cmds_count (iins_sorts_rows_ins, selrec.selr.selr_countresult);
END;
 
(*------------------------------*) 
 
PROCEDURE
      k721eval_pagecount (VAR m : tgg00_MessBlock);
 
VAR
      _ret          : tsp00_NumError;
      _pos          : integer;
      _pagecount    : tsp00_Int4;
      _record_cnt   : tsp00_Int4;
      _min_page_cnt : tsp00_Int4;
      _startkey     : tgg00_Lkey;
      _stopkey      : tgg00_Lkey;
      _CountRecords : boolean;
 
BEGIN
_pos     := 1;
_ret     := num_ok;
m.mb_trns^.trError_gg00 := e_ok;
s40g4int (m.mb_data^.mbp_4kbuf, _pos, _pagecount, _ret);
IF  _ret = num_overflow
THEN
    m.mb_trns^.trError_gg00 := e_num_overflow
ELSE
    IF  _ret = num_invalid
    THEN
        m.mb_trns^.trError_gg00 := e_num_invalid;
    (*ENDIF*) 
(*ENDIF*) 
IF  m.mb_trns^.trError_gg00 = e_ok
THEN
    BEGIN
    _pos          := _pos + mxsp_resnum - 1;
    _startkey.len := ord (m.mb_data^.mbp_buf [ _pos ]);
    SAPDB_PascalMove ('VKB721',  28,    
          m.mb_data_size, sizeof(_startkey.k),
          @m.mb_data^.mbp_buf, _pos + 1, @_startkey.k, 1, _startkey.len,
          m.mb_trns^.trError_gg00);
    _pos         := _pos + 1 + _startkey.len;
    _stopkey.len := ord (m.mb_data^.mbp_buf [ _pos ]);
    SAPDB_PascalMove ('VKB721',  29,    
          m.mb_data_size, sizeof(_stopkey.k),
          @m.mb_data^.mbp_buf, _pos + 1, @_stopkey.k, 1, _stopkey.len,
          m.mb_trns^.trError_gg00);
    IF  m.mb_trns^.trError_gg00 = e_ok
    THEN
        IF  g04inv_tfn (m.mb_qual^.mtree.fileTfn_gg00)
        THEN
            BEGIN
            _CountRecords := (m.mb_type2 <> mm_table) AND (m.mb_type2 = mm_key);
            b03calculate_page_count (m.mb_trns^, m.mb_qual^.mtree, _startkey, _stopkey,
                  _CountRecords, _pagecount, _min_page_cnt,
                  _record_cnt)
            END
        ELSE
            IF  m.mb_type2 <> mm_table
            THEN
                b02eval_page_count (m.mb_trns^, m.mb_qual^.mtree, _startkey, _stopkey,
                      m.mb_type2 = mm_key, _pagecount, _min_page_cnt,
                      _record_cnt)
            ELSE
                b02calculate_page_count (m.mb_trns^, m.mb_qual^.mtree, _startkey,
                      _stopkey, _pagecount)
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  m.mb_trns^.trError_gg00 = e_ok
THEN
    BEGIN
    s41p4int (m.mb_data^.mbp_4kbuf, 1, _pagecount, _ret);
    s41p4int (m.mb_data^.mbp_4kbuf, mxsp_resnum, _record_cnt, _ret);
    s41p4int (m.mb_data^.mbp_4kbuf, 2 * mxsp_resnum - 1,
          _min_page_cnt, _ret);
    m.mb_qual_len  := MB_PART1_HEAD_MXGG00;
    m.mb_data_len  := 3 * (mxsp_resnum - 1);
    m.mb_type := m_return_result;
    END
ELSE
    BEGIN
    m.mb_qual_len  := 0;
    m.mb_data_len  := 0;
    m.mb_type := m_return_error
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
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 selfields    : tgg00_SelectFieldsParam);
 
VAR
      _sellength    : tsp00_Int4;
      _htree_id     : tgg00_FileId;
      _granted_lock : tgg00_LockReqMode;
 
BEGIN
_granted_lock := lckFree_egg00;
IF  ( m.mb_type = m_insert_select )
THEN
    BEGIN
    _htree_id := m.mb_qual^.mtree;
    selfields.sfp_result_length := cgg_rec_key_offset;
    IF  ( selrec.selr.selr_is_nokey )
    THEN
        selfields.sfp_result_length :=
              selfields.sfp_result_length + 1 + SURROGATE_MXGG00
    (*ENDIF*) 
    END
ELSE
    selfields.sfp_result_length := 0;
(*ENDIF*) 
_sellength := selfields.sfp_result_length;
IF  ( selrec.selr.selr_write_rownum AND ( selrec.selr.selr_distinct <> no_distinct ))
THEN
    selfields.sfp_act_cntresult := 1
ELSE
    IF  ( NOT selrec.selr.selr_count_all )
    THEN
        selfields.sfp_act_cntresult := selrec.selr.selr_countresult + 1;
    (*ENDIF*) 
(*ENDIF*) 
m.mb_trns^.trError_gg00       := e_ok;
m.mb_qual^.mtree.fileBdUse_gg00 := [  ];
selfields.sfp_bd_mess2_type := mtype;
IF  ( m.mb_type = m_update )
THEN
    BEGIN
    selfields.sfp_m_result_addr := @selrec.selr_selectbuffer.longresult;
    selfields.sfp_m_result_size := sizeof( selrec.selr_selectbuffer.longresult );
    END
ELSE
    BEGIN
    selfields.sfp_m_result_addr := @selrec.selr_selectbuffer.result;
    selfields.sfp_m_result_size := sizeof( selrec.selr_selectbuffer.result );
    END;
(*ENDIF*) 
selfields.sfp_m_result_len  := 0;
(* h.b. PTS 1104210 *)
b03select_invrec( m.mb_trns^, ftrees, startkeys, stopkeys, act_key,
      istop, sizeof( selrec.selr_selectbuffer.buf_rec ),
      @selrec.selr_selectbuffer.buf_rec, selfields,
      m.mb_qual^.mstack_desc, _granted_lock, c_usage_count );
&ifdef trace
t01basis_error (kb, 'bd error    ',m.mb_trns^.trError_gg00);
&endif
kb721result_handle( m, selrec, getrec, selfields,
      startkeys.reckey, _htree_id, _granted_lock );
END;
 
(*------------------------------*) 
 
PROCEDURE
      k721null_result (
            VAR m         : tgg00_MessBlock;
            VAR selrec    : tgg07_select_param;
            VAR sel       : tgg00_SelectFieldsParam;
            act_cntresult : tsp00_Int4;
            later_output  : boolean;
            h_keylen      : integer);
 
VAR
      _func_pos : integer;
      _first    : integer;
      _pos      : integer;
      _stpos    : integer;
      _st_begin : integer;
      _m_pos    : integer;
      _m_cnt    : integer;
      _res      : tsp00_NumError;
 
BEGIN
selrec.selr_selectbuffer.result.len                  := selrec.selr.selr_recl;
selrec.selr_selectbuffer.result.keylen               := selrec.selr.selr_keyl;
selrec.selr_selectbuffer.result.recVarcolOffset_gg00 := 0;
selrec.selr_selectbuffer.result.recVarcolCnt_gg00    := 0;
_first := m.mb_qual^.mqual_pos;
_func_pos := _first - 2 + m.mb_st^[ _first ].epos;
_pos := _first + 1;
&ifdef TRACE
t01int4 (kb_qual, '_func_pos   ', _func_pos);
&endif
WHILE ( _pos < _func_pos ) DO
    BEGIN
    _st_begin := _pos;
    WHILE (_pos < _func_pos) AND (m.mb_st^[ _pos ].etype <> st_output) DO
        BEGIN
        IF  m.mb_st^[ _pos ].etype = st_func
        THEN
            _st_begin := 0;
        (*ENDIF*) 
        _pos := succ(_pos)
        END;
    (*ENDWHILE*) 
&   ifdef trace
    t01int4 (kb, '_pos        ', _pos );
    t01int4 (kb, '_st_begin   ', _st_begin );
&   endif
    IF  ( _pos < _func_pos )
    THEN
        IF  m.mb_st^[ _pos + 1 ].etype = st_output
        THEN
            BEGIN
&           ifdef trace
            t01sname( kb, 'succ(_pos)  ' );
&           endif
            _pos := succ(_pos);
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  ( _st_begin > 0 )
    THEN
        BEGIN
        _m_pos  := m.mb_qual^.mqual_pos;
        _m_cnt  := m.mb_qual^.mqual_cnt;
        m.mb_qual^.mqual_pos := _st_begin;
        m.mb_qual^.mqual_cnt := _pos - _st_begin + 1;
        sel.sfp_m_result_addr := @selrec.selr_selectbuffer.result;
        sel.sfp_m_result_size := sizeof (selrec.selr_selectbuffer.result);
        sel.sfp_m_result_len  := 0;
        k71sel_qualification_test (m, sel, c_check_new_rec,
              m.mb_data^.mbp_rec);
        m.mb_qual^.mqual_pos := _m_pos;
        m.mb_qual^.mqual_cnt := _m_cnt;
        END;
    (*ENDIF*) 
    _pos := succ(_pos)
    END;
(*ENDWHILE*) 
WHILE ((_func_pos - m.mb_st^[ _func_pos ].epos > _first) AND
      (m.mb_trns^.trError_gg00 = e_ok)) DO
    BEGIN
    _func_pos   := _func_pos - m.mb_st^[ _func_pos ].epos;
    (* loop over LASTFUNCTIONs *)
    WHILE (( m.mb_st^[ _func_pos ].etype = st_func ) AND
          ( m.mb_st^[ _func_pos ].eop_func = op_f_none )) DO
        _func_pos := _func_pos - m.mb_st^[ _func_pos ].epos;
    (*ENDWHILE*) 
    _stpos := k721out_entry (m.mb_st, _func_pos);
&   ifdef TRACE
    t01int4 (kb_qual, '_stpos      ', _stpos );
    t01int4 (kb_qual, '_func_pos   ', _func_pos);
&   endif
    IF  ((m.mb_st^[ _func_pos ].eop_func = op_f_count) OR
        (m.mb_st^[ _func_pos ].eop_func = op_f_dis_count) OR
        (m.mb_st^[ _func_pos ].eop_func = op_f_all_count)) AND
        (m.mb_st^[ _func_pos ].etype = st_func)
    THEN
        BEGIN
        _pos := m.mb_st^[ _stpos ].epos;
        selrec.selr_selectbuffer.result.buf[ _pos ] := csp_defined_byte;
        SAPDB_PascalMove ('VKB721',  30,    
              sizeof(g01glob.rescnt_0),
              sizeof(selrec.selr_selectbuffer.result.buf),
              @g01glob.rescnt_0, 2,
              @selrec.selr_selectbuffer.result.buf, _pos+1,
              sizeof(tsp00_ResNum)-1,
              m.mb_trns^.trError_gg00);
        END
    ELSE
        BEGIN
        IF  (m.mb_st^[ _func_pos ].eop_func = op_f_count_kb) AND
            (m.mb_st^[ _func_pos ].etype = st_func)
        THEN
            BEGIN
            selrec.selr_selectbuffer.result.
                  buf[ m.mb_st^[ _stpos ].epos ] := csp_defined_byte;
            s41p4int (selrec.selr_selectbuffer.result.buf,
                  m.mb_st^[ _stpos ].epos+1, act_cntresult, _res)
            END
        ELSE
            BEGIN
            IF  (m.mb_st^[ _func_pos ].eop_func = op_f_check_null) AND
                (m.mb_st^[ _func_pos ].etype = st_func)
            THEN
                selrec.selr_selectbuffer.result.buf[ m.mb_st^[ _stpos ].epos ] := csp_defined_byte
            ELSE
                BEGIN
                IF  m.mb_st^[ _func_pos ].etype = st_func
                THEN
                    BEGIN
&                   ifdef trace
                    t01sname( kb, 'st_func     ' );
&                   endif
                    selrec.selr_selectbuffer.result.
                          buf[ m.mb_st^[ _stpos ].epos ] := csp_undef_byte;
                    SAPDB_PascalFill ('VKB721',  31,    
                          sizeof(selrec.selr_selectbuffer.result.buf),
                          @selrec.selr_selectbuffer.result.buf,
                          m.mb_st^[ _stpos ].epos+1,
                          m.mb_st^[ _stpos ].elen_var - 1, csp_defined_byte,
                          m.mb_trns^.trError_gg00);
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
IF  m.mb_trns^.trError_gg00 = e_ok
THEN
    BEGIN
    IF  later_output
    THEN
        k721call_later_output (m, selrec.selr_selectbuffer.result.buf, h_keylen);
    (*ENDIF*) 
    k721add_into_result (m.mb_trns^, selrec, m.mb_next_mblock)
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k721catalog_add_into_result (
            VAR m           : tgg00_MessBlock;
            VAR sel         : tgg00_SelectFieldsParam;
            VAR selrec      : tgg07_select_context;
            VAR getrec      : tgg07_get_param;
            VAR result_rec  : tgg00_Rec;
            VAR one_res_rec : tgg00_Rec;
            VAR res_cnt     : tsp00_Int4);
 
VAR
      _selrec      : tgg07_select_param;
      _recptr      : tgg00_RecPtr;
 
BEGIN
m.mb_trns^.trError_gg00 := e_ok;
_selrec.selr := selrec;
IF  (_selrec.selr.selr_write_rownum AND (_selrec.selr.selr_distinct <> no_distinct))
THEN
    sel.sfp_act_cntresult := 1
ELSE
    IF  NOT _selrec.selr.selr_count_all
    THEN
        sel.sfp_act_cntresult := _selrec.selr.selr_countresult+1;
    (*ENDIF*) 
(*ENDIF*) 
sel.sfp_m_result_addr := @_selrec.selr_selectbuffer.result;
sel.sfp_m_result_size := sizeof (_selrec.selr_selectbuffer.result);
sel.sfp_m_result_len  := 0;
SAPDB_PascalFill ('VKB721',  32,    
      sizeof(_selrec.selr_selectbuffer.result.buf),
      @_selrec.selr_selectbuffer.result.buf,
      1, _selrec.selr.selr_recl, csp_defined_byte,
      m.mb_trns^.trError_gg00);
IF  m.mb_trns^.trError_gg00 = e_ok
THEN
    k71sel_qualification_test (m, sel, NOT c_check_new_rec, result_rec);
(*ENDIF*) 
IF  m.mb_trns^.trError_gg00 = e_ok
THEN
    BEGIN
    _selrec.selr_selectbuffer.result.len    := _selrec.selr.selr_recl;
    _selrec.selr_selectbuffer.result.keylen := _selrec.selr.selr_keyl;
    IF  ( one_res_rec.len > 0 )
    THEN
        SAPDB_PascalMove ('VKB721',  33,    
              sizeof(one_res_rec.buf),
              sizeof(_selrec.selr_selectbuffer.lbuf),
              @one_res_rec.buf, 1,
              @_selrec.selr_selectbuffer.lbuf, 1, one_res_rec.len,
              m.mb_trns^.trError_gg00);
    (*ENDIF*) 
    IF  m.mb_trns^.trError_gg00 = e_ok
    THEN
        IF  ( m.mb_type2 = mm_with_functions )
        THEN
            (* one table select *)
            k721function_add (m, _selrec, NOT c_aggr)
        ELSE
            IF  ( m.mb_type2 = mm_with_join )
            THEN
                BEGIN
                k74join_with_left_result (m, getrec, sel, _selrec );
                END
            ELSE
                k721add_into_result (m.mb_trns^, _selrec, m.mb_next_mblock);
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    selrec  := _selrec.selr;
    res_cnt := _selrec.selr.selr_countresult;
    IF  _selrec.selr.selr_one_result AND
        ( _selrec.selr.selr_countresult > 0 ) AND
        (m.mb_trns^.trError_gg00 in [e_ok, e_enough_resultsets]) (* PTS 1128074 *)
    THEN
        BEGIN
        _recptr := @_selrec.selr_selectbuffer.lbuf;
        SAPDB_PascalMove ('VKB721',  34,    
              sizeof(_selrec.selr_selectbuffer.lbuf),
              sizeof(one_res_rec.buf), @_selrec.selr_selectbuffer.lbuf, 1,
              @one_res_rec.buf, 1, _recptr^.len,
              m.mb_trns^.trError_gg00);
        END;
    (*ENDIF*) 
    END
ELSE
    IF  (m.mb_trns^.trError_gg00 = e_qual_violation) OR
        (m.mb_trns^.trError_gg00 = e_view_violation)
    THEN
        m.mb_trns^.trError_gg00 := e_ok
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k721read_subquery (VAR m : tgg00_MessBlock);
 
CONST
      c_inclusive = true;
 
VAR
      _max_keys : integer;
      _ok_e     : tgg00_BasisError;
      _key      : tgg00_Lkey;
      _rec      : tgg00_Rec;
 
BEGIN
_max_keys := m.mb_data^.mbp_rec.len;
_key.len  := m.mb_data^.mbp_rec.keylen;
m.mb_trns^.trError_gg00 := e_ok;
SAPDB_PascalMove ('VKB721',  35,    
      m.mb_data_size, sizeof (_key.k),
      @m.mb_data^.mbp_4kbuf, cgg_rec_key_offset + 1, @_key.k, 1, _key.len,
      m.mb_trns^.trError_gg00);
m.mb_data_len     := 0;
SAPDB_PascalForcedFill (m.mb_data_size,
      @m.mb_data^.mbp_buf, 1, m.mb_data_size, chr(255));
_ok_e := e_key_not_found;
IF  m.mb_trns^.trError_gg00 = e_ok
THEN
    REPEAT
        b02next_record (m.mb_trns^,
              m.mb_qual^.mtree, _key, NOT c_inclusive, _rec);
        IF  m.mb_trns^.trError_gg00 = _ok_e
        THEN
            BEGIN
            _max_keys := _max_keys - 1;
            _ok_e     := e_ok;
            IF  m.mb_data_len + cgg_rec_key_offset + _rec.keylen <=
                sizeof (tsp00_Buf)
            THEN
                BEGIN
                m.mb_trns^.trError_gg00 := e_ok;
                _key.len           := _rec.keylen;
                SAPDB_PascalMove ('VKB721',  36,    
                      sizeof (_rec.buf), sizeof (_key.k),
                      @_rec.buf, cgg_rec_key_offset + 1, @_key.k, 1, _key.len,
                      m.mb_trns^.trError_gg00);
                SAPDB_PascalMove ('VKB721',  37,    
                      sizeof (_rec.buf), m.mb_data_size,
                      @_rec.buf, 1, @m.mb_data^.mbp_buf, m.mb_data_len + 1,
                      cgg_rec_key_offset + _key.len - 8,
                      m.mb_trns^.trError_gg00);
                m.mb_data_len :=
                      m.mb_data_len + cgg_rec_key_offset + _key.len
                END
            ELSE
                m.mb_trns^.trError_gg00 := e_buffer_limit;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
    UNTIL
        (m.mb_trns^.trError_gg00 <> e_ok) OR (_max_keys = 0);
    (*ENDREPEAT*) 
(*ENDIF*) 
m.mb_qual_len  := 0;
IF  (m.mb_trns^.trError_gg00 = e_ok            ) OR
    (m.mb_trns^.trError_gg00 = e_no_next_record) OR
    (m.mb_trns^.trError_gg00 = e_buffer_limit  )
THEN
    BEGIN
    m.mb_type := m_return_result;
    IF  m.mb_trns^.trError_gg00 = e_no_next_record
    THEN
        m.mb_type2 := mm_last
    ELSE
        m.mb_type2 := mm_nil;
    (*ENDIF*) 
    m.mb_trns^.trError_gg00 := e_ok;
    END
ELSE
    BEGIN
    m.mb_data_len  := 0;
    m.mb_type      := m_return_error
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k721strat_distribution (
            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);
 
BEGIN
IF  ( gg_strategy.str_strategy in a70glob_key_build_strats )
    AND
    (( ksp_aggr_MIN_opt in gg_strategy.str_key_in_range.skir_strat_props ) OR
    ( ksp_aggr_MAX_opt in gg_strategy.str_key_in_range.skir_strat_props ))
THEN
    kb721key_MIN_MAX_search( m, getrec, selrec, selfields, gg_strategy )
ELSE
    BEGIN
    IF  ( gg_strategy.str_strategy in a70glob_inv_build_strats )
        AND
        (( isp_aggr_MIN_opt in gg_strategy.str_inv_in_range.siir_strat_props ) OR
        ( isp_aggr_MAX_opt in gg_strategy.str_inv_in_range.siir_strat_props ))
    THEN
        kb721inv_MIN_MAX_search( m, getrec, selrec, selfields, gg_strategy )
    ELSE
        BEGIN
        IF  ( gg_strategy.str_strategy in a70glob_inv_build_strats )
            AND
            (( isp_aggr_key_MIN_opt in gg_strategy.str_inv_in_range.siir_strat_props ) OR
            ( isp_aggr_key_MAX_opt in gg_strategy.str_inv_in_range.siir_strat_props ))
        THEN
            kb721inv_key_MIN_MAX_search( m, getrec, selrec, selfields, gg_strategy )
        ELSE
            BEGIN
            CASE gg_strategy.str_strategy OF
                strat_key_subq :
                    kb721subq_key_select( m, getrec, selrec, selfields, gg_strategy );
                strat_key_equal,
                strat_viewkey :
                    kb721eq_keyrecord( m, getrec, selrec, selfields, gg_strategy );
                strat_key_in :
                    kb721in_keyrecord( m, getrec, selrec, selfields, gg_strategy );
                strat_key_range :
                    kb721seq_search( m, getrec, selrec, selfields, gg_strategy );
                (*strat_inv_ordered,*)
                strat_inv_range :
                    k73_index_range( m, getrec, selrec, selfields, gg_strategy,
                          finding_possible );
                strat_inv_in :
                    k73in_multindex( m, getrec, selrec, selfields, gg_strategy );
                strat_inv_subq :
                    k73sub_multindex( m, getrec, selrec, selfields, gg_strategy );
                OTHERWISE
                    m.mb_trns^.trError_gg00 := e_unknown_strategy
                END;
            (*ENDCASE*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  ( m.mb_trns^.trError_gg00 = e_ok ) AND ( m.mb_type = m_update )
THEN
    k62late_unique_check( m );
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      k721out_entry (
            st_addr     : tgg00_StackListPtr;
            start_entry : integer) : integer;
 
VAR
      curr : integer;
 
BEGIN
&ifdef trace
t01int4 (kb, 'start_entry ', start_entry );
IF  ( st_addr^[ start_entry ].etype = st_func ) AND
    ( st_addr^[ start_entry ].eop_func = op_f_none )
THEN
    g01abort( csp3_move_error, csp3_n_check,
          'WRONG STACK CODE        ', start_entry );
&endif
(*ENDIF*) 
;
curr := succ (start_entry);
WHILE  ( NOT ( st_addr^[ curr ].etype in [ st_output, st_output_join ] )) DO
    curr := succ (curr);
(*ENDWHILE*) 
k721out_entry := curr;
&ifdef trace
t01stackentry (kb, st_addr^[curr], curr);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb721key_MIN_MAX_search (
            VAR m        : tgg00_MessBlock;
            VAR getrec   : tgg07_get_param;
            VAR selrec   : tgg07_select_param;
            VAR sel      : tgg00_SelectFieldsParam;
            VAR strat    : tgg07_StrategyInfo);
 
VAR
      _startk         : tgg00_Lkey;
      _stopk          : tgg00_Lkey;
 
BEGIN
_startk := selrec.selr.selr_startkey;
_stopk  := selrec.selr.selr_stopkey;
(* for key access we don't need any special NULL *)
(* handling, because NULL values not allowed     *)
IF  ( ksp_aggr_MIN_opt in strat.str_key_in_range.skir_strat_props )
THEN
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        sel.sfp_m_result_cnt  := 1;
        sel.sfp_bd_mess2_type := mm_first;
        kb721select_gets( m, selrec.selr.selr_startkey, getrec, selrec, sel );
        END;
    (*ENDIF*) 
(*ENDIF*) 
IF  ( ksp_aggr_MAX_opt in strat.str_key_in_range.skir_strat_props )
THEN
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        IF  ( _stopk.len = 0 )
        THEN
            BEGIN
            selrec.selr.selr_startkey.k   := b01fullkey;
            selrec.selr.selr_startkey.len := MAX_KEYLEN_GG00;
            END
        ELSE
            selrec.selr.selr_startkey := _stopk;
        (*ENDIF*) 
        selrec.selr.selr_stopkey := _startk;
        sel.sfp_m_result_cnt  := 1;
        sel.sfp_bd_mess2_type := mm_last;
        kb721select_gets( m, selrec.selr.selr_startkey, getrec, selrec, sel );
        END;
    (*ENDIF*) 
(*ENDIF*) 
IF  ( m.mb_trns^.trError_gg00 = e_no_next_record ) OR
    ( m.mb_trns^.trError_gg00 = e_no_prev_record )
THEN
    m.mb_trns^.trError_gg00 := e_ok;
(*ENDIF*) 
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;
 
(*------------------------------*) 
 
PROCEDURE
      kb721inv_MIN_MAX_search (
            VAR m        : tgg00_MessBlock;
            VAR getrec   : tgg07_get_param;
            VAR selrec   : tgg07_select_param;
            VAR sel      : tgg00_SelectFieldsParam;
            VAR strat    : tgg07_StrategyInfo);
 
CONST
      c_read_first = true;
 
VAR
      _ftrees           : tgg00_TwoFileIds;
      _startkeys        : tgg00_TwoKeys;
      _stopkeys         : tgg00_TwoKeys;
      _istop            : tgg00_BdInvSet;
      _finding_possible : boolean;
 
BEGIN
_finding_possible := true;
g04index_tree_build( m.mb_qual^.mtree, selrec.selr.selr_inv_id,
      strat.str_inv_in_range.siir_indexno );
selrec.selr.selr_inv_id.fileRoot_gg00 :=
      strat.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, strat.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 );
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        IF  ( isp_aggr_MIN_opt in strat.str_inv_in_range.siir_strat_props )
        THEN
            BEGIN
            IF  ( isp_aggr_MIN_opt_reverse in strat.str_inv_in_range.siir_strat_props )
            THEN
                BEGIN
&               ifdef trace
                t01sname( kb, 'reverse opt ' );
&               endif
                kb721inv_MIN_MAX( m, _ftrees, getrec, selrec, sel,
                      _startkeys, _stopkeys, _istop, strat,
                      NOT c_read_first, strat.str_inv_in_range.siir_MIN_recpos,
                      strat.str_inv_in_range.siir_startcnt );
                END
            ELSE
                kb721inv_MIN_MAX( m, _ftrees, getrec, selrec, sel,
                      _startkeys, _stopkeys, _istop, strat,
                      c_read_first, strat.str_inv_in_range.siir_MIN_recpos,
                      strat.str_inv_in_range.siir_startcnt );
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  ( isp_aggr_MAX_opt in strat.str_inv_in_range.siir_strat_props )
        THEN
            BEGIN
            IF  ( isp_aggr_MAX_opt_reverse in strat.str_inv_in_range.siir_strat_props )
            THEN
                BEGIN
&               ifdef trace
                t01sname( kb, 'reverse opt ' );
&               endif
                kb721inv_MIN_MAX( m, _ftrees, getrec, selrec, sel,
                      _startkeys, _stopkeys, _istop, strat,
                      c_read_first, strat.str_inv_in_range.siir_MAX_recpos,
                      strat.str_inv_in_range.siir_stopcnt );
                END
            ELSE
                kb721inv_MIN_MAX( m, _ftrees, getrec, selrec, sel,
                      _startkeys, _stopkeys, _istop, strat,
                      NOT c_read_first, strat.str_inv_in_range.siir_MAX_recpos,
                      strat.str_inv_in_range.siir_stopcnt );
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb721inv_MIN_MAX (
            VAR m        : tgg00_MessBlock;
            VAR ftrees   : tgg00_TwoFileIds;
            VAR getrec   : tgg07_get_param;
            VAR selrec   : tgg07_select_param;
            VAR sel      : tgg00_SelectFieldsParam;
            VAR startkey : tgg00_TwoKeys;
            VAR stopkey  : tgg00_TwoKeys;
            istop        : tgg00_BdInvSet;
            VAR strat    : tgg07_StrategyInfo;
            read_first   : boolean;
            recpos       : tsp00_Int2;
            sequence_len : tsp00_Int2);
 
VAR
      _start            : tgg00_TwoKeys;
      _stop             : tgg00_TwoKeys;
 
BEGIN
&ifdef trace
t01int4 (kb, 'sequence_len', sequence_len );
t01int4 (kb, 'recpos      ', recpos );
&endif
sel.sfp_m_result_cnt := 1;
IF  ( read_first )
THEN
    BEGIN
&   ifdef trace
    t01sname( kb, 'read first  ' );
&   endif
    _start := startkey;
    _stop  := stopkey;
    IF  ( recpos <> IS_UNDEFINED_GG07 )
        (* col with MIN behind equal sequence *)
    THEN
        BEGIN
        IF  ( sequence_len + 1 in strat.str_inv_in_range.siir_invcoldesc )
        THEN
            BEGIN
            (* we don't want NULL values *)
            (* field is descending       *)
&           ifdef trace
            t01name( kb, 'last field desc   ' );
&           endif
            _start.listkey.k[ recpos ] :=
                  csp_defined_byte(* negativ of csp_undef_byte*);
            SAPDB_PascalFill ('VKB721',  38,    
                  sizeof( _start.listkey.k ),
                  @_start.listkey.k,
                  recpos + 1,
                  MAX_KEYLEN_GG00 - recpos,
                  csp_undef_byte,
                  m.mb_trns^.trError_gg00);
            _start.listkey.len := MAX_KEYLEN_GG00;
            END;
        (*ENDIF*) 
        ;
&       ifdef TRACE
        t01key  (ak_strat, 'inv start   ', _start.listkey);
        t01key  (ak_strat, 'inv stop    ', _stop.listkey);
        t01key  (ak_strat, 'key start   ', _start.reckey);
        t01key  (ak_strat, 'key stop    ', _stop.reckey);
&       endif
        IF  ( m.mb_trns^.trError_gg00 <> e_move_error )
        THEN
            k721inv_gets( m, ftrees, _start, _stop,
                  selrec.selr.selr_startkey, istop,
                  mm_next, getrec, selrec, sel );
        (*ENDIF*) 
        END
    ELSE
        BEGIN
&       ifdef TRACE
        t01key  (ak_strat, 'inv start   ', _start.listkey);
        t01key  (ak_strat, 'inv stop    ', _stop.listkey);
        t01key  (ak_strat, 'key start   ', _start.reckey);
        t01key  (ak_strat, 'key stop    ', _stop.reckey);
&       endif
        k721inv_gets( m, ftrees, _start, _stop,
              selrec.selr.selr_startkey, istop,
              mm_first, getrec, selrec, sel );
        END;
    (*ENDIF*) 
    IF  ( m.mb_trns^.trError_gg00 = e_no_next_record )
    THEN
        m.mb_trns^.trError_gg00 := e_ok;
    (*ENDIF*) 
    END
ELSE
    BEGIN
&   ifdef trace
    t01sname( kb, 'read last   ' );
&   endif
    _start     := stopkey;
    _stop      := startkey;
    selrec.selr.selr_startkey := _start.reckey;
    (* reverse single primary_start --> primary_stop *)
    IF  ( primary_start in istop )
    THEN
        BEGIN
        IF  NOT ( primary_stop in istop )
        THEN
            BEGIN
            istop := istop - [ primary_start ];
            istop := istop + [ primary_stop ];
            END;
        (*ENDIF*) 
        END
    ELSE
        (* reverse single primary_stop --> primary_start *)
        IF  ( primary_stop in istop )
        THEN
            IF  NOT ( primary_start in istop )
            THEN
                BEGIN
                istop := istop - [ primary_stop ];
                istop := istop + [ primary_start ];
                END;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    IF  ( NOT ( primary_stop in istop ))
    THEN
        BEGIN
        _start.reckey.len := MAX_KEYLEN_GG00;
        _start.reckey.k   := b01fullkey;
        END;
    (*ENDIF*) 
    IF  ( recpos <> IS_UNDEFINED_GG07 )
        (* col with MAX behind equal sequence *)
    THEN
        BEGIN
        IF  ( sequence_len + 1 in strat.str_inv_in_range.siir_invcoldesc )
        THEN
            BEGIN
&           ifdef trace
            t01name( kb, 'last field desc   ' );
&           endif
            END
        ELSE
            BEGIN
            (* we don't want NULL values *)
            (* field is ascending        *)
&           ifdef trace
            t01name( kb, 'last field asc    ' );
&           endif
            (* skip whole NULL index list *)
            _start.listkey.k[ recpos ] := chr( ord( csp_undef_byte ) - 1 );
            _start.listkey.len := recpos;
            END;
        (*ENDIF*) 
        ;
&       ifdef TRACE
        t01key  (ak_strat, 'inv start   ', _start.listkey);
        t01key  (ak_strat, 'inv stop    ', _stop.listkey);
        t01key  (ak_strat, 'key start   ', _start.reckey);
        t01key  (ak_strat, 'key stop    ', _stop.reckey);
&       endif
        IF  m.mb_trns^.trError_gg00 <> e_move_error
        THEN
            k721inv_gets( m, ftrees, _start, _stop,
                  selrec.selr.selr_startkey, istop,
                  mm_prev, getrec, selrec, sel );
        (*ENDIF*) 
        END
    ELSE
        BEGIN
&       ifdef TRACE
        t01key  (ak_strat, 'inv start   ', _start.listkey);
        t01key  (ak_strat, 'inv stop    ', _stop.listkey);
        t01key  (ak_strat, 'key start   ', _start.reckey);
        t01key  (ak_strat, 'key stop    ', _stop.reckey);
&       endif
        k721inv_gets( m, ftrees, _start, _stop,
              selrec.selr.selr_startkey, istop,
              mm_last, getrec, selrec, sel );
        END;
    (*ENDIF*) 
    IF  ( m.mb_trns^.trError_gg00 = e_no_prev_record )
    THEN
        m.mb_trns^.trError_gg00 := e_ok;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb721inv_key_MIN_MAX_search (
            VAR m        : tgg00_MessBlock;
            VAR getrec   : tgg07_get_param;
            VAR selrec   : tgg07_select_param;
            VAR sel      : tgg00_SelectFieldsParam;
            VAR strat    : tgg07_StrategyInfo);
 
CONST
      c_read_first = true;
 
VAR
      _ftrees           : tgg00_TwoFileIds;
      _startkeys        : tgg00_TwoKeys;
      _stopkeys         : tgg00_TwoKeys;
      _istop            : tgg00_BdInvSet;
      _finding_possible : boolean;
 
BEGIN
_finding_possible := true;
g04index_tree_build( m.mb_qual^.mtree, selrec.selr.selr_inv_id,
      strat.str_inv_in_range.siir_indexno );
selrec.selr.selr_inv_id.fileRoot_gg00 :=
      strat.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, strat.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 );
    IF  ( m.mb_trns^.trError_gg00 = e_ok )
    THEN
        BEGIN
        IF  ( isp_aggr_key_MIN_opt in strat.str_inv_in_range.siir_strat_props )
        THEN
            BEGIN
            kb721inv_key_MIN_MAX( m, _ftrees, getrec, selrec, sel,
                  _startkeys, _stopkeys, _istop,
                  c_read_first );
            END;
        (*ENDIF*) 
        IF  ( isp_aggr_key_MAX_opt in strat.str_inv_in_range.siir_strat_props )
        THEN
            BEGIN
            kb721inv_key_MIN_MAX( m, _ftrees, getrec, selrec, sel,
                  _startkeys, _stopkeys, _istop,
                  NOT c_read_first );
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb721inv_key_MIN_MAX (
            VAR m        : tgg00_MessBlock;
            VAR ftrees   : tgg00_TwoFileIds;
            VAR getrec   : tgg07_get_param;
            VAR selrec   : tgg07_select_param;
            VAR sel      : tgg00_SelectFieldsParam;
            VAR startkey : tgg00_TwoKeys;
            VAR stopkey  : tgg00_TwoKeys;
            istop        : tgg00_BdInvSet;
            read_first   : boolean);
 
VAR
      _start            : tgg00_TwoKeys;
      _stop             : tgg00_TwoKeys;
 
BEGIN
sel.sfp_m_result_cnt := 1;
IF  ( read_first )
THEN
    BEGIN
&   ifdef trace
    t01sname( kb, 'read first  ' );
&   endif
    _start := startkey;
    _stop  := stopkey;
&   ifdef TRACE
    t01key  (ak_strat, 'inv start   ', _start.listkey);
    t01key  (ak_strat, 'inv stop    ', _stop.listkey);
    t01key  (ak_strat, 'key start   ', _start.reckey);
    t01key  (ak_strat, 'key stop    ', _stop.reckey);
&   endif
    k721inv_gets( m, ftrees, _start, _stop,
          selrec.selr.selr_startkey, istop,
          mm_first, getrec, selrec, sel );
    IF  ( m.mb_trns^.trError_gg00 = e_no_next_record )
    THEN
        m.mb_trns^.trError_gg00 := e_ok;
    (*ENDIF*) 
    END
ELSE
    BEGIN
&   ifdef trace
    t01sname( kb, 'read last   ' );
&   endif
    _start     := stopkey;
    _stop      := startkey;
    selrec.selr.selr_startkey := _start.reckey;
    (* reverse single primary_start --> primary_stop *)
    IF  ( primary_start in istop )
    THEN
        BEGIN
        IF  NOT ( primary_stop in istop )
        THEN
            BEGIN
            istop := istop - [ primary_start ];
            istop := istop + [ primary_stop ];
            END;
        (*ENDIF*) 
        END
    ELSE
        (* reverse single primary_stop --> primary_start *)
        IF  ( primary_stop in istop )
        THEN
            IF  NOT ( primary_start in istop )
            THEN
                BEGIN
                istop := istop - [ primary_stop ];
                istop := istop + [ primary_start ];
                END;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    IF  ( NOT ( primary_stop in istop ))
    THEN
        BEGIN
        _start.reckey.len := MAX_KEYLEN_GG00;
        _start.reckey.k   := b01fullkey;
        END;
&   ifdef TRACE
    (*ENDIF*) 
    t01key  (ak_strat, 'inv start   ', _start.listkey);
    t01key  (ak_strat, 'inv stop    ', _stop.listkey);
    t01key  (ak_strat, 'key start   ', _start.reckey);
    t01key  (ak_strat, 'key stop    ', _stop.reckey);
&   endif
    k721inv_gets( m, ftrees, _start, _stop,
          selrec.selr.selr_startkey, istop,
          mm_last, getrec, selrec, sel );
    IF  ( m.mb_trns^.trError_gg00 = e_no_prev_record )
    THEN
        m.mb_trns^.trError_gg00 := e_ok;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
