.nf
 
 .nf
 
    ========== licence begin  GPL
    Copyright (c) 2000-2005 SAP AG
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
.fo
 
 
.fo
*****************************************************
Copyright (c) 2000-2005 SAP AG
SAP Database Technology
 
Release :      Date : 2000-11-23
*****************************************************
modname : VAK720
changed : 2000-11-23
module  : Build_Strategy_Decision
 
Author  : GertG / HolgerB
Created : 1985-10-16
*****************************************************
 
Purpose : decision for a strategy in one table
 
Define  :
 
        PROCEDURE
              a720strategy_decision (
                    VAR acv              : tak_all_command_glob;
                    VAR sparr            : tak_syspointerarr;
                    VAR access_info      : tak70_strategy_record;
                    VAR gg_strategy      : tgg07_StrategyInfo;
                    VAR chosen_strat     : tak70_one_strat;
                    VAR order_fields     : tak00_ord_fields;
                    VAR StratInfo_len    : tsp00_Int2;
                    call_for_L1          : boolean);
 
        PROCEDURE
              a720decide_L2_range(
                    VAR acv          : tak_all_command_glob;
                    VAR sparr        : tak_syspointerarr;
                    VAR access_info  : tak70_strategy_record;
                    VAR gg_strategy  : tgg07_StrategyInfo;
                    VAR StratInfo_len: tsp00_Int2;
                    VAR eval_info    : tak71_page_eval_rec;
                    L1_pageIO        : tsp00_Int4;
                    VAR L1_stratvalue: tsp00_Longreal;
                    VAR key_range    : tgg07_StrKeyInRange);
 
        PROCEDURE
              a720glob_init_eval_stat;
 
.CM *-END-* define --------------------------------------
 
Use     :
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01diag_reverse_fetch  : boolean;
              a01aggr_optim          : boolean;
              a01diag_minmax_optim   : boolean;
 
      ------------------------------ 
 
        FROM
              AK_universal_semantic_tools : VAK06;
 
        PROCEDURE
              a06find_colinfo (
                    base_ptr        : tak_sysbufferaddress;
                    VAR stack_entry : tgg00_StackEntry;
                    VAR colinfo_ptr : tak00_colinfo_ptr);
 
        PROCEDURE
              a06eval_page_count (
                    VAR acv          : tak_all_command_glob;
                    VAR file_id      : tgg00_FileId;
                    VAR startkey     : tgg00_Lkey;
                    VAR stopkey      : tgg00_Lkey;
                    do_sample        : boolean;
                    count_records    : boolean;
                    VAR page_count   : tsp00_Int4;
                    VAR min_page_cnt : tsp00_Int4;
                    VAR record_cnt   : tsp00_Int4;
                    VAR b_err        : tgg00_BasisError);
 
        PROCEDURE
              a06extcolno (
                    VAR baserec     : tak_baserecord;
                    extcolno        : integer;
                    VAR colinfo_ptr : tak00_colinfo_ptr);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK07;
 
        PROCEDURE
              a07ak_system_error (
                    VAR acv  : tak_all_command_glob;
                    modul_no : integer;
                    id       : integer);
 
        PROCEDURE
              a07_b_put_error (
                    VAR acv  : tak_all_command_glob;
                    b_err    : tgg00_BasisError;
                    err_code : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK071;
 
        FUNCTION
              a07_return_code (
                    b_err   : tgg00_BasisError;
                    sqlmode : tsp00_SqlMode) : tsp00_Int2;
 
      ------------------------------ 
 
        FROM
              AK_Index : VAK24;
 
        PROCEDURE
              a24fnd_indexno (
                    VAR acv            : tak_all_command_glob;
                    VAR tabid          : tgg00_Surrogate;
                    indexno            : integer;
                    VAR index_scan_rec : tak_index_scan_record);
 
        FUNCTION
              a24IndexFieldCount (
                    VAR index_def : tak_multindex) : integer;
 
        FUNCTION
              a24IndexMatch (
                    VAR acv        : tak_all_command_glob;
                    VAR index_def  : tak_multindex;
                    stackStart     : integer;
                    stackEnd       : integer) : boolean;
 
        PROCEDURE
              a24init_index_scan (
                    VAR acv            : tak_all_command_glob;
                    VAR tabid          : tgg00_Surrogate;
                    VAR index_scan_rec : tak_index_scan_record);
 
        FUNCTION
              a24IsFunctionBasedIndex(VAR index_def : tak_multindex) : boolean;
 
        PROCEDURE
              a24finish_index_scan (
                    VAR acv            : tak_all_command_glob;
                    VAR index_scan_rec : tak_index_scan_record);
 
        FUNCTION
              a24next_named_index (
                    VAR acv            : tak_all_command_glob;
                    VAR index_scan_rec : tak_index_scan_record) : boolean;
 
        PROCEDURE
              a24get_indexname (
                    VAR acv        : tak_all_command_glob;
                    indexbuf       : tak_sysbufferaddress;
                    index          : integer;
                    VAR index_name : tsp00_KnlIdentifier);
 
      ------------------------------ 
 
        FROM
              AK_update_statistics : VAK28;
 
        FUNCTION
              a28primrows (
                    VAR acv     : tak_all_command_glob;
                    VAR baserec : tak_baserecord) : tsp00_Int4;
 
        FUNCTION
              a28prim_pages (
                    VAR acv     : tak_all_command_glob;
                    VAR baserec : tak_baserecord) : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              Build_Strategy   : VAK70;
 
        VAR
              a70glob_build_strats          : tgg07_StratEnumSet;
              a70glob_fetch_strats          : tgg07_StratEnumSet;
              a70glob_key_strats            : tgg07_StratEnumSet;
              a70glob_inv_strats            : tgg07_StratEnumSet;
              a70glob_in_strats             : tgg07_StratEnumSet;
              a70glob_subq_strats           : tgg07_StratEnumSet;
              a70glob_accessop_uknwn_strats : tgg07_StratEnumSet;
              a70glob_accessop_known_strats : tgg07_StratEnumSet;
 
      ------------------------------ 
 
        FROM
              Build_Strategy_2 : VAK71;
 
        PROCEDURE
              a71create_key_sequence (
                    VAR acv            : tak_all_command_glob;
                    VAR sparr          : tak_syspointerarr;
                    VAR access_info    : tak70_strategy_record);
 
        PROCEDURE
              a71create_inv_sequence(
                    VAR acv            : tak_all_command_glob;
                    VAR access_info    : tak70_strategy_record;
                    VAR inv_strat      : tak70_one_strat;
                    VAR index_def      : tak_multindex);
 
        FUNCTION
              a71is_duplicate_avoidance (
                    VAR gg_strategy  : tgg07_StrategyInfo;
                    stratenum        : tgg07_StratEnum;
                    VAR strat_data   : tgg07_StrRaw;
                    VAR qprop        : tak70_query_properties) : boolean;
 
        PROCEDURE
              a71check_fetch_optimization (
                    VAR acv         : tak_all_command_glob;
                    VAR config      : tak00_access_configuration;
                    VAR qprop       : tak70_query_properties;
                    VAR gg_strategy : tgg07_StrategyInfo;
                    VAR strategy    : tgg07_StratEnum;
                    VAR strat_data  : tgg07_StrRaw);
 
        PROCEDURE
              a71calculate_pageIO (
                    VAR acv             : tak_all_command_glob;
                    VAR sparr           : tak_syspointerarr;
                    VAR access_info     : tak70_strategy_record;
                    VAR strategy        : tak70_one_strat;
                    VAR eval_values     : tak70_eval_rec;
                    read_primpages      : tsp00_Int4;
                    VAR key_strat_value : tsp00_Longreal;
                    index_pagesize      : tsp00_Int4;
                    outrec_len          : tsp00_Int2);
 
        PROCEDURE
              a71search_thru_index (
                    VAR acv        : tak_all_command_glob;
                    VAR column     : tgg00_StackEntry;
                    VAR index_def  : tak_multindex;
                    VAR invfield   : tsp00_Int2);
 
        PROCEDURE
              a71decide_min_rows (
                    VAR acv          : tak_all_command_glob;
                    VAR access_info  : tak70_strategy_record;
                    readIO_pages     : tsp00_Int4;
                    readIO_rows      : tsp00_Int4);
 
        FUNCTION
              a71stratval_calc(
                    VAR access_info  : tak70_strategy_record;
                    read_pages       : tsp00_Int4;
                    read_primrows    : tsp00_Int4;
                    index_pagesize   : tsp00_Int4;
                    count_recs       : boolean ) : tsp00_Longreal;
 
      ------------------------------ 
 
        FROM
              hint_trace_routines : VAK81;
 
&       ifdef trace
        PROCEDURE
              a81debug_access_config (
                    debug       : tgg00_Debug;
                    VAR config  : tak00_access_configuration);
&       endif
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01fullkey    : tsp00_Key;
 
        PROCEDURE
              b01filestate (
                    VAR t       : tgg00_TransContext;
                    VAR file_id : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01vtrace             : tgg00_VtraceState;
 
        FUNCTION
              g01max_merge : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              Select_Help_Procedures : VGG04;
 
        PROCEDURE
              g04limitprimkeys (
                    VAR mblock      : 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
              g04limitinvkeys (
                    VAR mblock     : tgg00_MessBlock;
                    VAR inv_strat  : tgg07_StrInvInRange;
                    VAR startkey   : tgg00_Lkey;
                    VAR stopkey    : tgg00_Lkey;
                    in_stpos_hint  : tsp00_Int2;
                    in_value_idx   : tsp00_Int2);
 
        PROCEDURE
              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);
 
        PROCEDURE
              gg04one_subq_limitinvkey (
                    VAR mblock      : tgg00_MessBlock;
                    VAR subq_buf    : tgg00_Rec;
                    VAR inv_strat   : tgg07_StrInvInRange;
                    VAR one_key     : tgg00_Lkey;
                    is_startkey     : boolean);
 
        PROCEDURE
              g04index_tree_build (
                    VAR file_id    : tgg00_FileId;
                    VAR index_tree : tgg00_FileId;
                    index_no       : tsp00_Int2);
 
        FUNCTION
              g04inv_tfn (tfn : tgg00_Tfn) : boolean;
 
      ------------------------------ 
 
        FROM
              Trace_Help_Procedures : VGG041;
 
        PROCEDURE
              g041int4_to_trace (
                    VAR t  : tgg00_TransContext;
                    name   : tsp00_Name;
                    intval : tsp00_Int4);
 
        PROCEDURE
              g041c30_to_trace (
                    VAR t  : tgg00_TransContext;
                    msg    : tsp00_C30);
 
        PROCEDURE
              g041name_to_trace (
                    VAR t  : tgg00_TransContext;
                    name   : tsp00_Name);
 
        PROCEDURE
              g041bool_to_trace (
                    VAR t  : tgg00_TransContext;
                    name   : tsp00_Name;
                    boolval: boolean);
 
        PROCEDURE
              g041identifier_to_trace (
                    VAR t  : tgg00_TransContext;
                    name   : tsp00_KnlIdentifier);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalMove  (
                    mod_id         : tsp00_C6;
                    mod_intern_num : tsp00_Int4;
                    source_upb     : tsp00_Int4;
                    destin_upb     : tsp00_Int4;
                    source         : tsp00_MoveObjPtr;
                    source_pos     : tsp00_Int4;
                    destin         : tsp00_MoveObjPtr;
                    destin_pos     : tsp00_Int4;
                    length         : tsp00_Int4;
                    VAR e          : tgg00_BasisError);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vdebug_break (debug_break_pos : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01key (
                    debug   : tgg00_Debug;
                    nam     : tsp00_Sname;
                    VAR k   : tgg00_Lkey);
 
        PROCEDURE
              t01stackentry (
                    debug          : tgg00_Debug;
                    VAR st         : tgg00_StackEntry;
                    entry_index    : integer);
 
        PROCEDURE
              t01strat_enum (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname;
                    strat : tgg07_StratEnum);
 
        PROCEDURE
              t01p2int4 (
                    debug : tgg00_Debug;
                    nam_1 : tsp00_Sname;
                    int_1 : tsp00_Int4;
                    nam_2 : tsp00_Sname;
                    int_2 : tsp00_Int4);
 
        PROCEDURE
              t01bool (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    curr_bool: boolean);
 
        PROCEDURE
              t01real (
                    layer  : tgg00_Debug;
                    nam    : tsp00_Sname;
                    r      : tsp00_Longreal;
                    digits : integer);
 
        PROCEDURE
              t01int4 (
                    level : tgg00_Debug;
                    nam : tsp00_Sname;
                    int : tsp00_Int4);
 
        PROCEDURE
              t01sname (
                    level : tgg00_Debug;
                    nam : tsp00_Sname);
 
        PROCEDURE
              t01name (
                    level : tgg00_Debug;
                    nam : tsp00_Name);
 
        PROCEDURE
              t01treeid (
                    debug      : tgg00_Debug;
                    nam        : tsp00_Sname;
                    VAR treeid : tgg00_FileId);
 
        PROCEDURE
              t01columnset (
                    debug           : tgg00_Debug;
                    nam             : tsp00_Sname;
                    columnset       : tak_columnset);
 
      ------------------------------ 
 
        FROM
              Trace_Strategy_1 : VAK725;
 
        PROCEDURE
              a725output_access_info (
                    level           : tgg00_Debug;
                    nam             : tsp00_Sname;
                    VAR access_info : tak70_strategy_record);
 
        PROCEDURE
              a725output_keystrat(
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    VAR key_strat : tgg07_StrKeyInRange);
 
        PROCEDURE
              a725output_invstrat(
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    VAR inv_strat : tgg07_StrInvInRange);
 
        PROCEDURE
              a725output_one_strat (
                    layer           : tgg00_Debug;
                    VAR one_strat   : tak70_one_strat);
 
        PROCEDURE
              a725output_colposarr (
                    debug       : tgg00_Debug;
                    nam         : tsp00_Sname;
                    VAR keypos  : tgg07_ColPosArr);
 
        PROCEDURE
              a725output_query_prop (
                    debug   : tgg00_Debug;
                    qprop   : tak70_query_properties);
 
        PROCEDURE
              a725output_colposarr_ex (
                    debug       : tgg00_Debug;
                    nam         : tsp00_Sname;
                    VAR keypos  : tgg07_ColPosArr;
                    length      : tsp00_Int2);
&       endif
 
      ------------------------------ 
 
        FROM
              Trace_Strategy_2 : VAK727;
 
        PROCEDURE
              a727trace_strategy_text(
                    VAR transid : tgg00_TransContext;
                    name       : tsp00_Sname;
                    strategy   : tgg07_StratEnum);
 
        PROCEDURE
              a727trace_access_info (
                    VAR transid     : tgg00_TransContext;
                    proc_name       : tsp00_Name;
                    VAR access_info : tak70_strategy_record);
 
        PROCEDURE
              a727trace_strat_costs (
                    VAR transid  : tgg00_TransContext;
                    VAR strategy : tak70_one_strat);
 
        PROCEDURE
              a727trace_one_strat (
                    VAR transid     : tgg00_TransContext;
                    proc_name       : tsp00_Name;
                    VAR one_strat   : tak70_one_strat);
 
        PROCEDURE
              a727trace_eval (
                    VAR transid : tgg00_TransContext;
                    txt        : tsp00_C30;
                    cnt_rec    : boolean;
                    all_rows   : tsp00_Int4;
                    act_rows   : tsp00_Int4;
                    all_pages  : tsp00_Int4;
                    min_pages  : tsp00_Int4;
                    act_pages  : tsp00_Int4;
                    fraction   : tsp00_Longreal);
 
        PROCEDURE
              a727trace_invstrat(
                    VAR transid   : tgg00_TransContext;
                    name          : tsp00_Sname;
                    VAR inv_strat : tgg07_StrInvInRange;
                    trace_keyarr  : boolean);
 
.CM *-END-* use -----------------------------------------
 
Synonym :
 
.CM *-END-* synonym -------------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
CONST
      (* maximum number of values to evaluate in SUBQ conditions *)
      c_max_subq_eval_cnt = 50;
      c_sample            = true;
      c_count_recs        = true;
 
TYPE
 
      t_key_eval_rec = RECORD
            ker_strat_range   : tak70_eval_rec;
            ker_strat_IN_SUBQ : tak70_eval_rec;
            ker_subq_strat    : boolean;
      END;
 
 
VAR
      a720_strat_eval_rec : t_key_eval_rec;
 
 
(*------------------------------*) 
 
PROCEDURE
      a720strategy_decision (
            VAR acv              : tak_all_command_glob;
            VAR sparr            : tak_syspointerarr;
            VAR access_info      : tak70_strategy_record;
            VAR gg_strategy      : tgg07_StrategyInfo; (*const*)
            VAR chosen_strat     : tak70_one_strat; (*INOUT*)
            VAR order_fields     : tak00_ord_fields; (*const*)
            VAR StratInfo_len    : tsp00_Int2;
            call_for_L1          : boolean);
 
VAR
      _index_strategy       : tak70_one_strat;
      _key_strategy         : tak70_one_strat;
      _eval_rec             : t_key_eval_rec;
      _ix                   : tsp00_Int2;
      _decide_strat1        : boolean;
 
BEGIN
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    g041c30_to_trace ( acv.a_transinf.tri_trans,
          '>>A720STRATEGY_DECISION>>     ' );
(*ENDIF*) 
_key_strategy.ostr_strategy         := strat_undecided;
_key_strategy.ostr_wholeIO_pages    := IS_UNDEFINED_GG07;
_key_strategy.ostr_readIO_pages     := IS_UNDEFINED_GG07;
_key_strategy.ostr_readIO_primpages := IS_UNDEFINED_GG07;
_key_strategy.ostr_readIO_rows      := IS_UNDEFINED_GG07;
_key_strategy.ostr_strat_value      := IS_UNDEFINED_GG07;
_key_strategy.ostr_filler1          := ' ';
_key_strategy.ostr_filler2          := 0;
;
a71create_key_sequence( acv, sparr, access_info );
;
ak720test_keystrat_props( acv, sparr, access_info, _key_strategy, order_fields );
;
IF  ( call_for_L1 ) AND
    ( ksp_order_support in _key_strategy.ostr_key_in_range.skir_strat_props )
THEN
    BEGIN
    IF  ( ksp_order_support_reverse in
        _key_strategy.ostr_key_in_range.skir_strat_props )
    THEN
        gg_strategy.str_key_order_support := kos_desc
    ELSE
        gg_strategy.str_key_order_support := kos_asc;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    a727trace_access_info( acv.a_transinf.tri_trans,
          'A720STRATEGY_DECIS', access_info );
    END;
(*ENDIF*) 
;
&ifdef trace
a725output_access_info( ak_strat, 'access info ', access_info );
&endif
;
_index_strategy.ostr_strategy         := strat_undecided;
_index_strategy.ostr_wholeIO_pages    := IS_UNDEFINED_GG07;
_index_strategy.ostr_readIO_pages     := IS_UNDEFINED_GG07;
_index_strategy.ostr_readIO_primpages := IS_UNDEFINED_GG07;
_index_strategy.ostr_readIO_rows      := IS_UNDEFINED_GG07;
_index_strategy.ostr_strat_value      := IS_UNDEFINED_GG07;
_index_strategy.ostr_filler1          := ' ';
_index_strategy.ostr_filler2          := 0;
;
_eval_rec                         := a720_strat_eval_rec;
IF  NOT ( qp_no_result_set in access_info.srec_query_prop.qps_switches )
THEN
    BEGIN
    IF  ( NOT ( sp_exact_match in access_info.srec_keyaccess.ka_sequence_props )
        OR
        (* don't use exact key if others requested *)
        (( cs_indexaccess in access_info.srec_config.cfg_switches ) AND
        ( sparr.pbasep^.sbase.bindexexist ))
        )
    THEN
        BEGIN
        IF  ( acv.a_ex_kind = only_parsing ) AND
            ( cs_pretend_parameter in access_info.srec_config.cfg_switches )
        THEN
            access_info.srec_query_prop.qps_switches :=
                  access_info.srec_query_prop.qps_switches +
                  [ qp_missing_value ];
        (*ENDIF*) 
        IF  NOT ( qp_missing_value in access_info.srec_query_prop.qps_switches )
        THEN
            BEGIN
            IF  ( access_info.srec_primpages = IS_UNDEFINED_GG07 )
            THEN
                ak720get_file_samples( acv, sparr, acv.a_mblock.mb_qual^.mtree,
                      access_info.srec_primpages, access_info.srec_primrows,
                      access_info );
            (*ENDIF*) 
            ;
            ak720key_decision( acv, sparr, access_info, gg_strategy,
                  _eval_rec, _key_strategy );
            ;
            IF  ( sparr.pbasep^.sbase.bindexexist ) AND
                ( NOT ( cs_keyaccess in access_info.srec_config.cfg_switches ))
            THEN
                BEGIN
                (* there are index access pathes *)
                ak720index_decision( acv, sparr, access_info, gg_strategy, order_fields,
                      _eval_rec, _index_strategy );
                END
            ELSE
                BEGIN
&               ifdef trace
                t01sname( ak_strat, 'NO INDEX    ' );
&               endif
                END;
            (*ENDIF*) 
            IF  ( qp_missing_value in access_info.srec_query_prop.qps_switches )
            THEN
                BEGIN
&               ifdef trace
                t01name( ak_strat, 'missing val found!');
&               endif
                _key_strategy.ostr_strategy := strat_undecided;
                END;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            (* last a71create_key_sequence() exposes broken access *)
            END;
        (*ENDIF*) 
        ;
&       ifdef TRACE
        t01int4( ak_strat, 'stat ppages ', access_info.srec_primpages );
        t01int4( ak_strat, 'stat prows  ', access_info.srec_primrows );
        t01bool( ak_strat, 'count record', ( cs_count_records in
              access_info.srec_config.cfg_switches ));
        t01bool( ak_strat, 'no result   ', ( qp_no_result_set in
              access_info.srec_query_prop.qps_switches ));
        t01name( ak_strat, 'best strategies : ' );
        t01strat_enum( ak_strat, 'best key str', _key_strategy.ostr_strategy );
        t01int4( ak_strat, 'whole  pages', _key_strategy.ostr_wholeIO_pages );
        t01int4( ak_strat, 'read   pages', _key_strategy.ostr_readIO_pages );
        t01int4( ak_strat, 'read  ppages', _key_strategy.ostr_readIO_primpages );
        t01strat_enum( ak_strat, 'best inv str', _index_strategy.ostr_strategy );
        t01int4( ak_strat, 'whole  pages', _index_strategy.ostr_wholeIO_pages );
        t01int4( ak_strat, 'read   pages', _index_strategy.ostr_readIO_pages );
        t01int4( ak_strat, 'read  ppages', _index_strategy.ostr_readIO_primpages );
&       endif
        (* decide for strategy *)
        IF  ( _index_strategy.ostr_strategy = strat_undecided ) AND
            ( _key_strategy.ostr_strategy = strat_undecided )
        THEN
            BEGIN
&           ifdef trace
            t01name( ak_strat, 'set UNDECIDED     ');
&           endif
            chosen_strat.ostr_strategy := strat_undecided;
            StratInfo_len              := STRATEGY_START_MXGG07;
            FOR _ix := 0 TO MAX_COLPOSARR_IDX_GG07 DO
                BEGIN
                chosen_strat.ostr_key_in_range.skir_keystart[ _ix ] := 0;
                chosen_strat.ostr_key_in_range.skir_keystop [ _ix ] := 0;
                END;
            (*ENDFOR*) 
            chosen_strat.ostr_wholeIO_pages     := IS_UNDEFINED_GG07;
            chosen_strat.ostr_readIO_pages      := IS_UNDEFINED_GG07;
            chosen_strat.ostr_readIO_primpages  := IS_UNDEFINED_GG07;
            chosen_strat.ostr_readIO_rows       := IS_UNDEFINED_GG07;
            chosen_strat.ostr_strat_value       := IS_UNDEFINED_GG07;
            END
        ELSE
            BEGIN
            ak720choose_strat( access_info.srec_config,
                  _key_strategy, _index_strategy, _decide_strat1 );
            ;
            IF  ( _decide_strat1 )
            THEN
                (* make key strategy *)
                BEGIN
                StratInfo_len := STRATEGY_START_MXGG07 +
                      sizeof( chosen_strat.ostr_key_in_range );
                chosen_strat       := _key_strategy;
                acv.a_sample_pages := access_info.srec_primpages;
                END
            ELSE
                (* make index strategy *)
                BEGIN
                chosen_strat  := _index_strategy;
                StratInfo_len := STRATEGY_START_MXGG07 +
                      sizeof( chosen_strat.ostr_inv_in_range );
                (* acv.a_sample_pages already set in ak720eval_one_index *)
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
&       ifdef trace
        t01sname( ak_strat, 'key equal ! ' );
&       endif
        (* we have complete key, i.e. best access path *)
        (* parameter don't influence strategy          *)
        (**)
        acv.a_sample_pages := a28prim_pages( acv, sparr.pbasep^.sbase );
        access_info.srec_primrows := acv.a_sample_pages;
        ak720build_key_equal_strat( acv, access_info, gg_strategy, chosen_strat );
        StratInfo_len := STRATEGY_START_MXGG07 +
              sizeof( gg_strategy.str_key_in_range );
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  ( qp_no_result_set in access_info.srec_query_prop.qps_switches )
THEN
    BEGIN
    chosen_strat.ostr_strategy := strat_no_result;
    StratInfo_len := STRATEGY_START_MXGG07;
    chosen_strat.ostr_wholeIO_pages     := 0;
    chosen_strat.ostr_readIO_pages      := 0;
    chosen_strat.ostr_readIO_primpages  := 0;
    chosen_strat.ostr_readIO_rows       := 0;
    chosen_strat.ostr_strat_value       := 0;
    ;
    IF  ( access_info.srec_L1_strategy ) AND
        ( cs_count_records in access_info.srec_config.cfg_switches )
    THEN
        BEGIN
        access_info.srec_readIO_rows_min  := 0;
        access_info.srec_readIO_pages_min := 0;
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
&ifdef TRACE
t01strat_enum( ak_strat, 'choosen stra', chosen_strat.ostr_strategy );
a725output_one_strat( ak_strat, chosen_strat );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    a727trace_one_strat( acv.a_transinf.tri_trans,
          'A720STRATEGY_DECIS', chosen_strat );
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720key_decision (
            VAR acv            : tak_all_command_glob;
            VAR sparr          : tak_syspointerarr;
            VAR access_info    : tak70_strategy_record;
            VAR gg_strategy    : tgg07_StrategyInfo; (*const*)
            VAR eval_rec       : t_key_eval_rec;
            VAR best_key_strat : tak70_one_strat);
 
VAR
      _best_insubq_strat        : tak70_one_strat;
      _in_stpos                 : tsp00_Int2;
      _in_elemcnt               : tsp00_Int2;
      _decide_for_range_strat   : boolean;
 
BEGIN
(* best_key_strat.skir_keystart, best_key_strat.skir_keystop invalid yet !*)
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720KEY_DECISION>>         ' );
    END;
(*ENDIF*) 
_best_insubq_strat.ostr_strategy        := strat_undecided;
_best_insubq_strat.ostr_key_in_range.skir_strat_props :=
      best_key_strat.ostr_key_in_range.skir_strat_props;
_best_insubq_strat.ostr_wholeIO_pages   := IS_UNDEFINED_GG07;
_best_insubq_strat.ostr_readIO_pages    := IS_UNDEFINED_GG07;
_best_insubq_strat.ostr_readIO_primpages:= IS_UNDEFINED_GG07;
_best_insubq_strat.ostr_readIO_rows     := IS_UNDEFINED_GG07;
_best_insubq_strat.ostr_strat_value     := IS_UNDEFINED_GG07;
_best_insubq_strat.ostr_filler1         := ' ';
_best_insubq_strat.ostr_filler2         := 0;
;
&ifdef trace
a725output_query_prop( ak_strat, access_info.srec_query_prop );
&endif
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    IF  ( sp_IN_usage_start in access_info.srec_keyaccess.ka_sequence_props ) OR
        ( sp_IN_usage_stop in access_info.srec_keyaccess.ka_sequence_props )
    THEN
        BEGIN
        (* use IN as range operator *)
        _in_stpos   := access_info.srec_keyaccess.ka_infield.in_stpos;
        _in_elemcnt := access_info.srec_keyaccess.ka_infield.in_elemcnt;
        END
    ELSE
        BEGIN
        _in_stpos   := 0;
        _in_elemcnt := 0;
        END;
    (*ENDIF*) 
    ;
    ak720keyeval( acv, access_info,
          access_info.srec_keyaccess.ka_startfields,
          access_info.srec_keyaccess.ka_stopfields,
          eval_rec, access_info.srec_config,
          best_key_strat.ostr_key_in_range.skir_strat_props );
    ;
    ak720build_key_range_strat( acv, sparr, access_info, gg_strategy,
          eval_rec, best_key_strat );
    (* best_key_strat.skir_keystart, best_key_strat.skir_keystop valid *)
    ;
    IF  ( sp_SUBQ_usage in access_info.srec_keyaccess.ka_sequence_props ) AND
        ( NOT ( cs_keyrange in access_info.srec_config.cfg_switches )) AND
        ( acv.a_returncode = 0 )
    THEN
        BEGIN
        (* evaluate witht SUBQ *)
        ak720key_SUBQ_eval( acv, access_info,
              access_info.srec_keyaccess.ka_startfields,
              access_info.srec_keyaccess.ka_stopfields,
              access_info.srec_keyaccess.ka_startfields
              [ access_info.srec_keyaccess.ka_SUBQ_idx ],
              eval_rec,
              access_info.srec_config,
              _best_insubq_strat.ostr_key_in_range.skir_strat_props );
        END
    ELSE
        BEGIN
        IF  ( sp_IN_usage in access_info.srec_keyaccess.ka_sequence_props ) AND
            ( NOT ( cs_keyrange in access_info.srec_config.cfg_switches )) AND
            ( acv.a_returncode = 0 )
        THEN
            BEGIN
            (* evaluate with IN *)
            ak720key_IN_eval( acv, access_info,
                  access_info.srec_keyaccess.ka_startfields,
                  access_info.srec_keyaccess.ka_stopfields,
                  access_info.srec_keyaccess.ka_infield.in_stpos,
                  access_info.srec_keyaccess.ka_infield.in_elemcnt,
                  eval_rec,
                  access_info.srec_config,
                  _best_insubq_strat.ostr_key_in_range.skir_strat_props );
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    ;
    IF  ((( sp_SUBQ_usage in access_info.srec_keyaccess.ka_sequence_props ) OR
        ( sp_IN_usage in access_info.srec_keyaccess.ka_sequence_props ))
        AND
        ( NOT ( cs_keyrange in access_info.srec_config.cfg_switches )))
    THEN
        (* build IN/SUBQ strategy *)
        BEGIN
        ak720build_key_INSUBQ_strat( acv, sparr, access_info, gg_strategy,
              eval_rec, _best_insubq_strat );
        END;
    (*ENDIF*) 
    ;
    END;
(*ENDIF*) 
;
(* decide for key strategy *)
ak720choose_strat( access_info.srec_config,
      best_key_strat, _best_insubq_strat, _decide_for_range_strat);
;
IF  ( _decide_for_range_strat )
THEN
    BEGIN
    (* do nothing, best_key_strat already filled *)
&   ifdef trace
    t01name( ak_strat, 'choose key range  ' );
&   endif
    END
ELSE
    BEGIN
    (* chose IN/SUBQ condition *)
    best_key_strat := _best_insubq_strat;
&   ifdef trace
    t01name( ak_strat, 'choose key IN/SUBQ' );
&   endif
    END;
(*ENDIF*) 
;
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    a727trace_one_strat( acv.a_transinf.tri_trans,
          'A720KEY_DECISION  ', best_key_strat );
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720index_decision (
            VAR acv            : tak_all_command_glob;
            VAR sparr          : tak_syspointerarr;
            VAR access_info    : tak70_strategy_record;
            VAR gg_strategy    : tgg07_StrategyInfo; (*const*)
            VAR order_fields   : tak00_ord_fields; (*const*)
            VAR eval_rec       : t_key_eval_rec;
            VAR best_inv_strat : tak70_one_strat);
 
VAR
      _i               : tsp00_Int2;
      _startcnt        : tsp00_Int2;
      _stopcnt         : tsp00_Int2;
      _inv_strat       : tak70_one_strat;
      _inv_tabid       : tgg00_Surrogate;
      _index_scan_rec  : tak_index_scan_record;
      _index_name      : tsp00_KnlIdentifier;
      _msg             : tsp00_C30;
      _usable          : boolean;
 
BEGIN
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720INDEX_DECISION>>       ' );
    END;
(*ENDIF*) 
_inv_tabid := sparr.pbasep^.sbase.btreeid.fileTabId_gg00;
_usable    := false;
;
IF  ( cs_indexaccess in access_info.srec_config.cfg_switches ) AND
    ( access_info.srec_config.cfg_indexno <> 0 )
THEN
    BEGIN
    (**************************)
    (* predefined index usage *)
    (**************************)
&   ifdef trace
    t01sname( ak_strat, 'predefined  ' );
&   endif
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        g041c30_to_trace( acv.a_transinf.tri_trans,
              'PREDEFINED INVACCESS          ' );
        END;
    (*ENDIF*) 
    a24fnd_indexno( acv, _inv_tabid, access_info.srec_config.cfg_indexno,
          _index_scan_rec );
    IF  ( _index_scan_rec.isr_buf <> NIL )
    THEN
        BEGIN
        IF  ( g01vtrace.vtrStrategy_gg00 )
        THEN
            BEGIN
            a24get_indexname( acv, _index_scan_rec.isr_buf,
                  _index_scan_rec.isr_index, _index_name );
            _msg := '------- INDEXSTRATEGY --------';
            g041c30_to_trace( acv.a_transinf.tri_trans, _msg );
            g041identifier_to_trace( acv.a_transinf.tri_trans, _index_name );
            END;
        (*ENDIF*) 
        ;
        (* fill _inv_strat but without key access path *)
        ak720get_invstrat_info( acv, sparr, gg_strategy, access_info,
              _inv_strat,
              _index_scan_rec.isr_buf^.smindex.
              indexdef[ _index_scan_rec.isr_index ],
              order_fields, _usable );
        ;
        IF  ( _usable )
        THEN
            ak720eval_one_index( acv, sparr, access_info, gg_strategy,
                  _inv_strat, eval_rec,
                  best_inv_strat );
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
IF  NOT ( _usable )
THEN
    (******************************************************)
    (* predefined index usage not possible or not defined *)
    (******************************************************)
    BEGIN
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        g041name_to_trace( acv.a_transinf.tri_trans, 'TEST INDICES:     ' );
        END;
    (*ENDIF*) 
    a24init_index_scan( acv, _inv_tabid, _index_scan_rec );
    WHILE ( a24next_named_index( acv, _index_scan_rec ) AND
          ( acv.a_returncode = 0 ) AND
          NOT ( qp_no_result_set in access_info.srec_query_prop.qps_switches )) DO
        BEGIN
        IF  ( NOT _index_scan_rec.isr_buf^.smindex.
            indexdef[ _index_scan_rec.isr_index ].idisabled )
        THEN
            BEGIN
            IF  ( g01vtrace.vtrStrategy_gg00 )
            THEN
                BEGIN
                a24get_indexname( acv, _index_scan_rec.isr_buf,
                      _index_scan_rec.isr_index, _index_name );
                _msg := '------- INDEXSTRATEGY --------';
                g041c30_to_trace( acv.a_transinf.tri_trans, _msg );
                g041identifier_to_trace( acv.a_transinf.tri_trans, _index_name );
                END;
            (*ENDIF*) 
            ;
            (* fill _inv_strat but without key access path *)
            ak720get_invstrat_info( acv, sparr, gg_strategy, access_info,
                  _inv_strat,
                  _index_scan_rec.isr_buf^.smindex.
                  indexdef[ _index_scan_rec.isr_index ],
                  order_fields, _usable );
            ;
            IF  ( _usable )
            THEN
                ak720eval_one_index( acv, sparr, access_info, gg_strategy,
                      _inv_strat, eval_rec,
                      best_inv_strat );
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    a24finish_index_scan( acv, _index_scan_rec );
    END;
(*ENDIF*) 
;
IF  (( best_inv_strat.ostr_strategy <> strat_undecided ) AND
    (NOT (qp_missing_value in access_info.srec_query_prop.qps_switches)))
THEN
    BEGIN
    (* complete index strategy with correct key access path *)
&   ifdef trace
    t01int4( ak_strat, 'get key accp',
          access_info.srec_keyaccess.ka_SUBQ_idx );
&   endif
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        a727trace_access_info( acv.a_transinf.tri_trans,
              'AK720INDEX_DECISIO', access_info );
    (*ENDIF*) 
    IF  ( eval_rec.ker_subq_strat )
    THEN
        BEGIN
        (* if we use an index as access path, we don't like to    *)
        (* use several primary keys ( each for every SUBQ value ) *)
        (* for each key in key list of this index                 *)
        _startcnt := access_info.srec_keyaccess.ka_SUBQ_idx;
        _stopcnt  := access_info.srec_keyaccess.ka_SUBQ_idx;
        IF  ( g01vtrace.vtrStrategy_gg00 )
        THEN
            BEGIN
            g041int4_to_trace( acv.a_transinf.tri_trans, 'remove IN/SUBQ pos',
                  access_info.srec_keyaccess.ka_SUBQ_idx );
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        _startcnt := access_info.srec_keyaccess.ka_startcnt;
        _stopcnt  := access_info.srec_keyaccess.ka_stopcnt;
        IF  ( g01vtrace.vtrStrategy_gg00 )
        THEN
            BEGIN
            g041int4_to_trace( acv.a_transinf.tri_trans, 'get key start     ',
                  access_info.srec_keyaccess.ka_startcnt );
            g041int4_to_trace( acv.a_transinf.tri_trans, 'get key stop      ',
                  access_info.srec_keyaccess.ka_stopcnt );
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    FOR _i := 0 TO MAX_COLPOSARR_IDX_GG07 DO
        IF  ( _i < _startcnt )
        THEN
            best_inv_strat.ostr_inv_in_range.siir_keystart[ _i ] :=
                  access_info.srec_keyaccess.ka_startfields[ _i ]
        ELSE
            best_inv_strat.ostr_inv_in_range.siir_keystart[ _i ] := 0;
        (*ENDIF*) 
    (*ENDFOR*) 
    FOR _i := 0 TO MAX_COLPOSARR_IDX_GG07 DO
        IF  ( _i < _stopcnt )
        THEN
            best_inv_strat.ostr_inv_in_range.siir_keystop[ _i ] :=
                  access_info.srec_keyaccess.ka_stopfields[ _i ]
        ELSE
            best_inv_strat.ostr_inv_in_range.siir_keystop[ _i ] := 0;
        (*ENDIF*) 
    (*ENDFOR*) 
&   ifdef trace
    a725output_one_strat( ak_strat, best_inv_strat );
&   endif
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        a727trace_one_strat( acv.a_transinf.tri_trans,
              'BEST INDEX STRAT  ', best_inv_strat );
        END;
    (*ENDIF*) 
    END
ELSE
    BEGIN
&   ifdef trace
    t01name( ak_strat, 'all idx unaccessib' );
&   endif
    (* set strat_undecided for missing value *)
    best_inv_strat.ostr_strategy := strat_undecided;
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        g041c30_to_trace( acv.a_transinf.tri_trans,
              'all indices inaccessible !    ' (* or missing value! *));
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720eval_one_index (
            VAR acv            : tak_all_command_glob;
            VAR sparr          : tak_syspointerarr;
            VAR access_info    : tak70_strategy_record;
            VAR gg_strategy    : tgg07_StrategyInfo; (*const*)
            VAR act_inv_strat  : tak70_one_strat;
            VAR key_eval_rec   : t_key_eval_rec;
            VAR best_inv_strat : tak70_one_strat);
 
VAR
      _eval_range            : tak70_eval_rec;
      _eval_IN_SUBQ          : tak70_eval_rec;
      _dummy_cnt             : tsp00_Int4;
      _index_pagesize        : tsp00_Int4;
      _inv_file              : tgg00_FileId;
      _act_insubq_strat      : tak70_one_strat;
      _decide_strat1         : boolean;
 
BEGIN
_act_insubq_strat  := act_inv_strat;
_act_insubq_strat.ostr_strategy := strat_undecided;
&ifdef trace
t01sname( ak_strat, 'History:    ' );
t01int4 ( ak_strat, 'best IO page', best_inv_strat.ostr_wholeIO_pages );
&endif
g04index_tree_build( acv.a_mblock.mb_qual^.mtree, _inv_file,
      act_inv_strat.ostr_inv_in_range.siir_indexno );
_inv_file.fileRoot_gg00 := access_info.srec_invaccess.
      ia_inv_root[ act_inv_strat.ostr_inv_in_range.siir_indexno - 1 ];
;
ak720get_file_samples( acv, sparr, _inv_file, _index_pagesize,
      _dummy_cnt (* use value from primary table *), access_info );
;
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    ak720indexeval( acv, access_info, act_inv_strat.ostr_inv_in_range,
          _inv_file, _index_pagesize,
          access_info.srec_config,
          _eval_range );
    ;
    act_inv_strat.ostr_strategy := strat_inv_range;
    ak720build_inv_strat( acv, sparr, access_info, gg_strategy,
          key_eval_rec, act_inv_strat, _index_pagesize, _eval_range );
    ;
    IF  ( sp_SUBQ_usage in access_info.srec_invaccess.ia_sequence_props ) AND
        ( NOT ( cs_indexrange in access_info.srec_config.cfg_switches )) AND
        ( acv.a_returncode = 0 )
    THEN
        BEGIN
        (* evaluate witht SUBQ *)
        ak720index_SUBQ_eval( acv, access_info,
              _act_insubq_strat.ostr_inv_in_range,
              _inv_file, _eval_range.er_read_pages,
              _index_pagesize, access_info.srec_config,
              _eval_IN_SUBQ );
        END
    ELSE
        BEGIN
        IF  ( sp_IN_usage in access_info.srec_invaccess.ia_sequence_props ) AND
            ( NOT ( cs_indexrange in access_info.srec_config.cfg_switches )) AND
            ( acv.a_returncode = 0 )
        THEN
            BEGIN
            ;
            (* evaluate with IN *)
            ak720index_IN_eval( acv, access_info,
                  _act_insubq_strat.ostr_inv_in_range,
                  _inv_file, _eval_range.er_read_pages,
                  _index_pagesize, access_info.srec_config,
                  _eval_IN_SUBQ );
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ((( sp_SUBQ_usage in access_info.srec_invaccess.ia_sequence_props ) OR
        ( sp_IN_usage in access_info.srec_invaccess.ia_sequence_props ))
        AND
        ( NOT ( cs_indexrange in access_info.srec_config.cfg_switches )))
    THEN
        BEGIN
        IF  ( sp_SUBQ_usage in access_info.srec_invaccess.ia_sequence_props )
        THEN
            _act_insubq_strat.ostr_strategy := strat_inv_subq
        ELSE
            _act_insubq_strat.ostr_strategy := strat_inv_in;
        (*ENDIF*) 
        ak720build_inv_strat( acv, sparr, access_info, gg_strategy,
              key_eval_rec, _act_insubq_strat, _index_pagesize, _eval_IN_SUBQ );
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
(* decide for inv strategy *)
ak720choose_strat( access_info.srec_config,
      act_inv_strat, _act_insubq_strat, _decide_strat1 );
;
IF  ( _decide_strat1 )
THEN
    BEGIN
    (* do nothing, act_in_strat already filled *)
&   ifdef trace
    t01name( ak_strat, 'choose inv range  ' );
&   endif
    END
ELSE
    BEGIN
    (* chose IN/SUBQ condition *)
    act_inv_strat := _act_insubq_strat;
&   ifdef trace
    t01name( ak_strat, 'choose inv IN/SUBQ' );
&   endif
    END;
(*ENDIF*) 
;
(* set best index access *)
ak720choose_strat( access_info.srec_config,
      best_inv_strat, act_inv_strat, _decide_strat1 );
;
IF  ( NOT _decide_strat1 )
THEN
    BEGIN
    IF  ( best_inv_strat.ostr_strategy = strat_undecided )
    THEN
        BEGIN
&       ifdef trace
        t01sname( ak_strat, 'init bestqul' );
&       endif
        END
    ELSE
        BEGIN
        (* catch the better strategy *)
&       ifdef trace
        t01sname( ak_strat, 'better inv  ' );
&       endif
        END;
    (*ENDIF*) 
    best_inv_strat     := act_inv_strat;
    acv.a_sample_pages := _index_pagesize; (* remark initial/best index size *)
    END
ELSE
    BEGIN
    (* actual strat not better than best strat *)
    (* nothing to do                           *)
    END;
(*ENDIF*) 
;
&ifdef TRACE
t01int4( ak_strat, 'best IO cost', best_inv_strat.ostr_wholeIO_pages );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720indexeval(
            VAR acv             : tak_all_command_glob;
            VAR access_info     : tak70_strategy_record;
            VAR inv_strat       : tgg07_StrInvInRange;
            VAR inv_file        : tgg00_FileId;
            index_pagesize      : tsp00_Int4;
            VAR config          : tak00_access_configuration;
            VAR eval_range      : tak70_eval_rec); (* OUT *)
 
VAR
      _all_invpages    : tsp00_Int4;
      _startkey        : tgg00_Lkey;
      _stopkey         : tgg00_Lkey;
      _b_err           : tgg00_BasisError;
      _count_recs      : boolean;
 
BEGIN
&ifdef trace
t01name( ak_strat, 'ak720indexeval    ' );
a725output_colposarr( ak_strat, 'invstart    ', inv_strat.siir_invstart );
a725output_colposarr( ak_strat, 'invstop     ', inv_strat.siir_invstop );
t01int4( ak_strat, 'siir_startcn', inv_strat.siir_startcnt );
t01int4( ak_strat, 'siir_stopcnt', inv_strat.siir_stopcnt );
t01int4( ak_strat, 'IN_SUBQ_stpo', inv_strat.siir_IN_SUBQ_stpos );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720INDEXEVAL>>            ' );
    END;
(*ENDIF*) 
_count_recs := ( cs_count_records in config.cfg_switches );
;
eval_range.er_strat_value    := 1; (* full range *)
IF  ( inv_strat.siir_startcnt > 0 ) OR
    ( inv_strat.siir_stopcnt > 0 )
THEN
    BEGIN
    g04limitinvkeys( acv.a_mblock, inv_strat,
          _startkey, _stopkey,
          IS_UNDEFINED_GG07, -1 (* use an IN as range *) );
&   ifdef trace
    t01key( ak_strat, 'startkey    ', _startkey );
    t01key( ak_strat, 'stopkey     ', _stopkey );
&   endif
    END
ELSE
    BEGIN
    _startkey.len := 0;
    _stopkey.len  := 0;
    END;
(*ENDIF*) 
;
IF  ( acv.a_mblock.mb_trns^.trError_gg00 = e_move_error )
THEN
    acv.a_returncode :=
          a07_return_code( e_move_error, acv.a_sqlmode );
(*ENDIF*) 
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    _all_invpages := 0;
    IF  (( _startkey.len > 0 ) OR ( _stopkey.len > 0 ))
    THEN
        BEGIN
        eval_range.er_read_pages  := index_pagesize;
        eval_range.er_read_primrows    := -1;
        _b_err         := e_ok;
        a06eval_page_count( acv, inv_file,
              _startkey, _stopkey,
              c_sample, _count_recs,
              eval_range.er_read_pages,
              _all_invpages, eval_range.er_read_primrows, _b_err );
        ;
        IF  ( _b_err <> e_ok )
        THEN
            BEGIN
            IF  ( _b_err = e_inv_not_found )
            THEN
                a07_b_put_error( acv, e_old_fileversion, 1 )
            ELSE
                a07_b_put_error( acv, _b_err, 1 );
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        eval_range.er_read_pages := index_pagesize;
        IF  ( _count_recs )
        THEN
            eval_range.er_read_primrows := access_info.srec_primrows
        ELSE
            eval_range.er_read_primrows := IS_UNDEFINED_GG07;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _count_recs )
    THEN
        BEGIN
        IF  ( eval_range.er_read_primrows < 0 )
        THEN
            BEGIN
            eval_range.er_read_primrows := IS_UNDEFINED_GG07;
            _count_recs := false;
            END;
        (*ENDIF*) 
        END
    ELSE
        eval_range.er_read_primrows := IS_UNDEFINED_GG07;
    (*ENDIF*) 
    ;
&   ifdef trace
    IF  ( eval_range.er_read_pages > index_pagesize + 2 ) AND
        (* not faked pages *)
        NOT ( qp_archive_access in access_info.srec_query_prop.qps_switches )
    THEN
        a07ak_system_error( acv, 720, 5 );
    (*ENDIF*) 
    ;
&   endif
    IF  ( eval_range.er_read_pages > index_pagesize )
    THEN
        (* leazy propagation of subtree sizes *)
        eval_range.er_read_pages := index_pagesize;
    (*ENDIF*) 
    ;
    (* calculate access fraction *)
    eval_range.er_strat_value := a71stratval_calc( access_info,
          eval_range.er_read_pages, eval_range.er_read_primrows,
          index_pagesize, _count_recs );
    END;
(*ENDIF*) 
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        a727trace_eval( acv.a_transinf.tri_trans,
              '------- AK720INDEXEVAL -------',
              _count_recs, access_info.srec_primrows,
              eval_range.er_read_primrows,
              index_pagesize, _all_invpages, eval_range.er_read_pages,
              eval_range.er_strat_value );
    (*ENDIF*) 
    ;
&   ifdef trace
    t01bool( ak_strat, 'count record', _count_recs );
    t01int4( ak_strat, 'prim  rows  ', access_info.srec_primrows );
    IF  ( _count_recs )
    THEN
        t01int4( ak_strat, 'read primrow', eval_range.er_read_primrows );
    (*ENDIF*) 
    t01int4( ak_strat, 'prim  pages ', access_info.srec_primpages );
    t01int4( ak_strat, 'min page cnt', _all_invpages );
    t01int4( ak_strat, 'read ipages ', eval_range.er_read_pages );
    t01real( ak_strat, 'strat val   ', eval_range.er_strat_value, 3 );
&   endif
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720index_SUBQ_eval (
            VAR acv           : tak_all_command_glob;
            VAR access_info   : tak70_strategy_record;
            VAR inv_strat     : tgg07_StrInvInRange;
            VAR inv_tree      : tgg00_FileId;
            range_pages       : tsp00_Int4;
            index_pagesize    : tsp00_Int4;
            VAR config        : tak00_access_configuration;
            VAR eval_SUBQ     : tak70_eval_rec);(* OUT *)
 
VAR
      _scoured_pages    : tsp00_Int4;
      _record_cnt       : tsp00_Int4;
      _all_page_cnt     : tsp00_Int4;
      _max_pages        : tsp00_Int4;
      _startkey         : tgg00_Lkey;
      _stopkey          : tgg00_Lkey;
      _next_key         : tgg00_Lkey;
      _fract            : tsp00_Longreal;
      _subqtree_id      : tgg00_FileId;
      _rec_buf          : tgg00_Rec;
      _subq_rowcnt      : tsp00_Int2;
      _aux_error        : tgg00_BasisError;
      _e                : tgg00_BasisError;
      _success          : boolean;
      _count_recs       : boolean;
      _read_limit       : boolean;
 
BEGIN
&ifdef trace
a725output_colposarr( ak_strat, 'invstart    ', inv_strat.siir_invstart );
a725output_colposarr( ak_strat, 'invstop     ', inv_strat.siir_invstop );
t01int4( ak_strat, 'RANGE pages ', range_pages );
IF  ( inv_strat.siir_subq_idx = IS_UNDEFINED_GG07 )
THEN
    a07ak_system_error( acv, 720, 3 );
&endif
(*ENDIF*) 
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720INDEX_SUBQ_EVAL>>      ' );
    END;
(*ENDIF*) 
_all_page_cnt := 0;
eval_SUBQ.er_strat_value   := 0;
eval_SUBQ.er_read_pages := 0;
eval_SUBQ.er_read_primrows   := IS_UNDEFINED_GG07;
;
SAPDB_PascalMove ('VAK720',   1,    
      acv.a_mblock.mb_data_size, sizeof( _subqtree_id ),
      @acv.a_mblock.mb_data^.mbp_buf,
      acv.a_mblock.mb_st^[
      inv_strat.siir_IN_SUBQ_stpos + 1 ].epos,
      @_subqtree_id, 1,
      FILE_ID_MXGG00,
      acv.a_returncode);
&ifdef trace
t01treeid( ak_strat, 'subq treeid ', _subqtree_id );
t01int4( ak_strat, 'read limit  ', range_pages );
&endif
_aux_error := acv.a_returncode;
_e         := e_ok;
acv.a_mblock.mb_trns^.trError_gg00 := e_ok;
_subq_rowcnt:= 0;
_next_key.len := 0;
_count_recs := ( cs_count_records in config.cfg_switches );
_read_limit := false;
_max_pages  := range_pages;
&ifdef trace
t01int4( ak_strat, 'read limit  ', _max_pages );
&endif
;
WHILE ( _e = e_ok ) AND ( _aux_error = e_ok ) AND
      ( acv.a_mblock.mb_trns^.trError_gg00 = e_ok ) AND
      ( NOT _read_limit ) DO
    BEGIN
    g04read_subquery( acv.a_mblock.mb_trns^, _rec_buf,
          _subqtree_id, _next_key, _aux_error, _success );
    ;
    IF  ( _success )
    THEN
        BEGIN
        _subq_rowcnt    := succ( _subq_rowcnt );
        IF  ( _subq_rowcnt <= c_max_subq_eval_cnt )
        THEN
            BEGIN
            (* use subquery result for build of keys *)
            gg04one_subq_limitinvkey( acv.a_mblock, _rec_buf,
                  inv_strat, _startkey, true );
            gg04one_subq_limitinvkey( acv.a_mblock, _rec_buf,
                  inv_strat, _stopkey, false );
            IF  ( acv.a_mblock.mb_trns^.trError_gg00 = e_move_error )
            THEN
                _e := e_move_error
            ELSE
                BEGIN
                _record_cnt    := -1;
                _all_page_cnt  := 0;
                _scoured_pages := index_pagesize;
                a06eval_page_count( acv, inv_tree,
                      _startkey, _stopkey,
                      c_sample, _count_recs,
                      _scoured_pages,
                      _all_page_cnt, _record_cnt, _e );
                END;
            (*ENDIF*) 
            IF  ( _e <> e_ok )
            THEN
                BEGIN
                IF  ( _e = e_inv_not_found )
                THEN
                    a07_b_put_error( acv, e_old_fileversion, 1 )
                ELSE
                    a07_b_put_error( acv, _e, 1 );
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                IF  ( _count_recs ) AND ( _record_cnt < 0 )
                THEN
                    BEGIN
                    _record_cnt := IS_UNDEFINED_GG07;
                    _count_recs := false;
                    END;
                (*ENDIF*) 
                IF  ( _scoured_pages > index_pagesize )
                THEN
                    (* leazy propagation of subtree sizes *)
                    _scoured_pages := index_pagesize;
                (*ENDIF*) 
                ;
                (* calculate access fraction *)
                _fract := a71stratval_calc( access_info, _scoured_pages,
                      _record_cnt, index_pagesize, _count_recs );
                END;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            (* more than c_max_subq_eval_cnt elements *)
&           ifdef TRACE
            t01sname( ak_strat, 'use avg val ' );
&           endif
            _fract := eval_SUBQ.er_strat_value / ( _subq_rowcnt - 1 );
            IF  ( _count_recs )
            THEN
                _record_cnt :=
                      trunc(( eval_SUBQ.er_read_primrows / ( _subq_rowcnt - 1 )) + 1 );
            (*ENDIF*) 
            _scoured_pages :=
                  trunc(( eval_SUBQ.er_read_pages / ( _subq_rowcnt - 1 )) + 1 );
            END;
        (*ENDIF*) 
&       ifdef TRACE
        t01real( ak_strat, 'fract single', _fract, 3 );
        t01int4( ak_strat, 'min page cnt', _all_page_cnt );
        t01int4( ak_strat, 'scoured page', _scoured_pages );
        t01int4( ak_strat, 'record cnt  ', _record_cnt );
&       endif
        (* Let's add it: eval_SUBQ.er_read_pages and, if wanted, records *)
        eval_SUBQ.er_strat_value := eval_SUBQ.er_strat_value + _fract;
        IF  ( _count_recs )
        THEN
            BEGIN
            (* initialize row count *)
            IF  ( eval_SUBQ.er_read_primrows = IS_UNDEFINED_GG07 )
            THEN
                eval_SUBQ.er_read_primrows := 0;
            (*ENDIF*) 
            eval_SUBQ.er_read_primrows :=
                  eval_SUBQ.er_read_primrows + _record_cnt;
            END;
        (*ENDIF*) 
        eval_SUBQ.er_read_pages :=
              eval_SUBQ.er_read_pages + _scoured_pages;
&       ifdef TRACE
        t01real( ak_strat, 'SUM stratval', eval_SUBQ.er_strat_value, 3 );
        t01int4( ak_strat, 'SUM pages   ', eval_SUBQ.er_read_pages );
        t01int4( ak_strat, 'SUM records ', eval_SUBQ.er_read_primrows );
&       endif
        END
    ELSE
        BEGIN
        IF  ( acv.a_mblock.mb_trns^.trError_gg00 <> e_ok )
        THEN
            a07_b_put_error( acv, acv.a_mblock.mb_trns^.trError_gg00, 1 )
        ELSE
            IF  ( _aux_error = e_no_next_record ) AND
                ( eval_SUBQ.er_read_pages = 0 )
            THEN
                BEGIN
                eval_SUBQ.er_strat_value := 1 / access_info.srec_primpages;
                IF  ( cs_count_records in config.cfg_switches )
                THEN
                    eval_SUBQ.er_read_primrows := 0;
                (*ENDIF*) 
                eval_SUBQ.er_read_pages := 1;
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    _read_limit := ( eval_SUBQ.er_read_pages >= _max_pages );
    END;
(*ENDWHILE*) 
IF  (( g01vtrace.vtrStrategy_gg00 ) AND ( _read_limit ))
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          'exceed strat limit!           ' );
    END;
(*ENDIF*) 
IF  ( eval_SUBQ.er_strat_value = 0 )
THEN
    BEGIN
    eval_SUBQ.er_strat_value    := 1;
    eval_SUBQ.er_read_pages  := range_pages + 1;
    END;
(*ENDIF*) 
IF  ( NOT _count_recs )
THEN
    eval_SUBQ.er_read_primrows := IS_UNDEFINED_GG07;
(*ENDIF*) 
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        a727trace_eval( acv.a_transinf.tri_trans,
              '--- AK720INDEX_SUBQ_EVAL -----',
              _count_recs, access_info.srec_primrows,
              eval_SUBQ.er_read_primrows,
              index_pagesize, _all_page_cnt,
              eval_SUBQ.er_read_pages, eval_SUBQ.er_strat_value );
    (*ENDIF*) 
    ;
&   ifdef TRACE
    t01bool( ak_strat, 'Count Record', _count_recs );
    t01int4( ak_strat, 'prim  rows  ', access_info.srec_primrows );
    t01int4( ak_strat, 'prim  pages ', access_info.srec_primpages );
    t01int4( ak_strat, 'min page cnt', _all_page_cnt );
    t01int4( ak_strat, 'read ipages ', eval_SUBQ.er_read_pages );
    t01int4( ak_strat, 'read prows  ', eval_SUBQ.er_read_primrows );
    t01real( ak_strat, 'strat value ', eval_SUBQ.er_strat_value, 3 );
&   endif
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720index_IN_eval (
            VAR acv           : tak_all_command_glob;
            VAR access_info   : tak70_strategy_record;
            VAR inv_strat     : tgg07_StrInvInRange;
            VAR inv_tree      : tgg00_FileId;
            range_pages       : tsp00_Int4;
            index_pagesize    : tsp00_Int4;
            VAR config        : tak00_access_configuration;
            VAR eval_IN       : tak70_eval_rec);
 
VAR
      _ix               : tsp00_Int2;
      _st_dummy_cnt     : tsp00_Int2;
      _in_stack         : tsp00_Int2;
      _scoured_pages    : tsp00_Int4;
      _record_cnt       : tsp00_Int4;
      _all_page_cnt     : tsp00_Int4;
      _max_pages        : tsp00_Int4;
      _startkey         : tgg00_Lkey;
      _stopkey          : tgg00_Lkey;
      _fract            : tsp00_Longreal;
      _e                : tgg00_BasisError;
 
BEGIN
&ifdef trace
a725output_colposarr( ak_strat, 'invstart    ', inv_strat.siir_invstart );
a725output_colposarr( ak_strat, 'invstop     ', inv_strat.siir_invstop );
t01int4( ak_strat, 'IN elemcnt  ', inv_strat.siir_inelemcnt );
t01int4( ak_strat, 'RANGE pages ', range_pages );
IF  ( inv_strat.siir_IN_SUBQ_stpos = IS_UNDEFINED_GG07 )
THEN
    a07ak_system_error( acv, 720, 4 );
&endif
(*ENDIF*) 
_all_page_cnt := 0;
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720INDEX_IN_EVAL>>        ' );
    END;
(*ENDIF*) 
_max_pages  := range_pages;
&ifdef trace
t01int4( ak_strat, 'read limit  ', _max_pages );
&endif
;
eval_IN.er_strat_value    := 0;
eval_IN.er_read_pages     := 0;
eval_IN.er_read_primrows  := 0;
;
_e               := e_ok;
_in_stack     := inv_strat.siir_IN_SUBQ_stpos;
_st_dummy_cnt := 0;
_ix           := 1;
WHILE ( _ix <= inv_strat.siir_inelemcnt ) AND
      ( _e = e_ok )  DO
    BEGIN
    IF  ( acv.a_mblock.mb_st^[ _in_stack + _ix + _st_dummy_cnt ].etype <>
        st_dummy )
    THEN
        (* The current IN value is no DUMMY, so we construct *)
        (* start and stop key and evaluate it's page count.  *)
        BEGIN
&       ifdef trace
        t01stackentry( ak_strat,
              acv.a_mblock.mb_st^[ _in_stack + _ix + _st_dummy_cnt ], _ix );
&       endif
        g04limitinvkeys( acv.a_mblock, inv_strat,
              _startkey, _stopkey, _in_stack, _ix + _st_dummy_cnt );
&       ifdef trace
        (* t01key( ak_strat, 'startkey    ', _startkey ); *)
        (* t01key( ak_strat, 'stopkey     ', _stopkey ); *)
        ;
&       endif
        IF  ( acv.a_mblock.mb_trns^.trError_gg00 = e_move_error )
        THEN
            _e := e_move_error
        ELSE
            BEGIN
            _record_cnt    := -1;
            _all_page_cnt  := 0;
            _scoured_pages := index_pagesize;
            a06eval_page_count( acv, inv_tree,
                  _startkey, _stopkey,
                  c_sample, c_count_recs,
                  _scoured_pages, _all_page_cnt,
                  _record_cnt, _e );
            IF  ( _scoured_pages = 0 )
            THEN
                BEGIN
                (* evaluation of key counts these non-found values as a page access *)
                (* therefore we have to count this as a found page                  *)
&               ifdef trace
                t01name( ak_strat,  'non-found value   ' );
&               endif
                _scoured_pages := 1;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  ( _e <> e_ok )
        THEN
            BEGIN
            IF  ( _e = e_inv_not_found )
            THEN
                a07_b_put_error( acv, e_old_fileversion, 1 )
            ELSE
                a07_b_put_error( acv, _e, 1 );
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            IF  ( _record_cnt < 0 )
            THEN
                eval_IN.er_read_primrows := IS_UNDEFINED_GG07;
            (*ENDIF*) 
            IF  ( _scoured_pages > index_pagesize )
            THEN
                (* leazy propagation of subtree sizes *)
                _scoured_pages := index_pagesize;
            (*ENDIF*) 
            ;
            (* calculate access fraction *)
            _fract := a71stratval_calc( access_info, _scoured_pages,
                  _record_cnt, index_pagesize, (_record_cnt >= 0) );
            END;
        (*ENDIF*) 
&       ifdef TRACE
        t01real( ak_strat, 'fract single', _fract, 3 );
        t01int4( ak_strat, 'min page cnt', _all_page_cnt );
        t01int4( ak_strat, 'scoured page', _scoured_pages );
        t01int4( ak_strat, 'record cnt  ', _record_cnt );
&       endif
        (* Let's add it: eval_IN.er_read_pages and, if wanted, records *)
        eval_IN.er_strat_value := eval_IN.er_strat_value + _fract;
        eval_IN.er_read_pages := eval_IN.er_read_pages + _scoured_pages;
        IF  ( eval_IN.er_read_primrows <> IS_UNDEFINED_GG07 )
        THEN
            eval_IN.er_read_primrows := eval_IN.er_read_primrows + _record_cnt;
&       ifdef TRACE
        (*ENDIF*) 
        t01real( ak_strat, 'SUM stratval', eval_IN.er_strat_value, 3 );
        t01int4( ak_strat, 'SUM pages   ', eval_IN.er_read_pages );
        t01int4( ak_strat, 'SUM primrows', eval_IN.er_read_primrows );
&       endif
        _ix := succ ( _ix );
        ;
        END
    ELSE
        BEGIN
&       ifdef trace
        t01int4( ak_strat, 'st_dummy fnd', _ix );
&       endif
        _st_dummy_cnt := succ( _st_dummy_cnt );
        END;
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
;
eval_IN.er_read_pages := trunc(eval_IN.er_strat_value * index_pagesize);
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        a727trace_eval( acv.a_transinf.tri_trans,
              '----- AK720INDEX_IN_EVAL -----',
              c_count_recs, access_info.srec_primrows,
              eval_IN.er_read_primrows,
              index_pagesize, _all_page_cnt, eval_IN.er_read_pages,
              eval_IN.er_strat_value );
    (*ENDIF*) 
    ;
&   ifdef TRACE
    t01int4( ak_strat, 'prim  rows  ', access_info.srec_primrows );
    t01int4( ak_strat, 'prim  pages ', access_info.srec_primpages );
    t01int4( ak_strat, 'min page cnt', _all_page_cnt );
    t01int4( ak_strat, 'read ipages ', eval_IN.er_read_pages );
    t01int4( ak_strat, 'read prows  ', eval_IN.er_read_primrows );
    t01real( ak_strat, 'strat value ', eval_IN.er_strat_value, 3 );
&   endif
    END;
(*ENDIF*) 
;
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720keyeval (
            VAR acv            : tak_all_command_glob;
            VAR access_info    : tak70_strategy_record;
            VAR keystart       : tgg07_ColPosArr;
            VAR keystop        : tgg07_ColPosArr;
            VAR eval_rec       : t_key_eval_rec;
            VAR config         : tak00_access_configuration;
            VAR strat_props    : tgg07_KeyStratProps);
 
VAR
      _all_page_cnt  : tsp00_Int4;
      _scoured_pages : tsp00_Int4;
      _strat_value   : tsp00_Longreal;
      _startkey      : tgg00_Lkey;
      _stopkey       : tgg00_Lkey;
      _e             : tgg00_BasisError;
      _record_cnt    : tsp00_Int4;
      _use_stopkey   : boolean;
      _count_recs    : boolean;
 
BEGIN
&ifdef trace
a725output_colposarr( ak_strat, 'keystart    ', keystart );
a725output_colposarr( ak_strat, 'keystop     ', keystop );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720KEYEVAL>>              ' );
    END;
(*ENDIF*) 
_count_recs := ( cs_count_records in config.cfg_switches );
;
_strat_value := 1;  (* full range *)
IF  (( access_info.srec_keyaccess.ka_startcnt > 0 ) OR
    ( access_info.srec_keyaccess.ka_stopcnt > 0 ))
THEN
    BEGIN
    _use_stopkey := true;
    g04limitprimkeys( acv.a_mblock, keystart, _startkey,
          keystop, _stopkey, _use_stopkey,
          IS_UNDEFINED_GG07, -1 (* use an IN as range *) );
&   ifdef trace
    t01key( ak_strat, 'startkey    ', _startkey );
    t01key( ak_strat, 'stopkey     ', _stopkey );
    t01bool( ak_strat, 'use stopkey ', _use_stopkey );
&   endif
    END
ELSE
    BEGIN
    (* table scan *)
    _use_stopkey  := false;
    _startkey.len := 0;
    END;
(*ENDIF*) 
;
IF  ( acv.a_mblock.mb_trns^.trError_gg00 = e_move_error )
THEN
    acv.a_returncode :=
          a07_return_code( e_move_error, acv.a_sqlmode );
(*ENDIF*) 
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    _all_page_cnt  := 0;
    IF  (( _use_stopkey ) OR ( _startkey.len > 0 ))
    THEN
        BEGIN
        _scoured_pages := access_info.srec_primpages;
        _record_cnt    := -1;
        _e             := e_ok;
        a06eval_page_count( acv, acv.a_mblock.mb_qual^.mtree,
              _startkey, _stopkey,
              c_sample, _count_recs,
              _scoured_pages, _all_page_cnt, _record_cnt, _e );
        ;
        IF  ( _e <> e_ok )
        THEN
            BEGIN
            IF  ( _e = e_file_not_found )
            THEN
                a07_b_put_error( acv, e_old_fileversion, 1 )
            ELSE
                a07_b_put_error( acv, _e, 1 );
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        _scoured_pages := access_info.srec_primpages;
        IF  ( _count_recs )
        THEN
            _record_cnt := access_info.srec_primrows
        ELSE
            _record_cnt := IS_UNDEFINED_GG07;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _count_recs )
    THEN
        BEGIN
        IF  ( _record_cnt < 0 )
        THEN
            BEGIN
            _record_cnt := IS_UNDEFINED_GG07;
            _count_recs := false;
            END;
        (*ENDIF*) 
        END
    ELSE
        _record_cnt := IS_UNDEFINED_GG07;
    (*ENDIF*) 
    eval_rec.ker_strat_range.er_read_primrows  := _record_cnt;
    eval_rec.ker_strat_range.er_read_pages := _scoured_pages;
    eval_rec.ker_strat_range.er_strat_value :=
          a71stratval_calc( access_info, eval_rec.ker_strat_range.er_read_pages,
          eval_rec.ker_strat_range.er_read_primrows,
          IS_UNDEFINED_GG07, _count_recs );
    END;
(*ENDIF*) 
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        a727trace_eval( acv.a_transinf.tri_trans,
              '-------- AK720KEYEVAL --------',
              _count_recs, access_info.srec_primrows,
              eval_rec.ker_strat_range.er_read_primrows,
              access_info.srec_primpages, _all_page_cnt,
              eval_rec.ker_strat_range.er_read_pages,
              eval_rec.ker_strat_range.er_strat_value );
    (*ENDIF*) 
    ;
&   ifdef trace
    t01bool( ak_strat, 'count record', _count_recs );
    t01int4( ak_strat, 'prim  rows  ', access_info.srec_primrows );
    IF  ( _count_recs )
    THEN
        t01int4( ak_strat, 'found rows  ',
              eval_rec.ker_strat_range.er_read_primrows );
    (*ENDIF*) 
    t01int4( ak_strat, 'prim  pages ', access_info.srec_primpages );
    t01int4( ak_strat, 'min page cnt', _all_page_cnt );
    t01int4( ak_strat, 'read ppages ', eval_rec.ker_strat_range.er_read_pages );
    t01real( ak_strat, 'strat val   ', eval_rec.ker_strat_range.er_strat_value, 3 );
&   endif
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720key_IN_eval (
            VAR acv            : tak_all_command_glob;
            VAR access_info    : tak70_strategy_record;
            VAR keystart       : tgg07_ColPosArr;
            VAR keystop        : tgg07_ColPosArr;
            VAR in_stack       : tsp00_Int2;
            VAR in_cnt         : tsp00_Int2;
            VAR eval_rec       : t_key_eval_rec;
            VAR config         : tak00_access_configuration;
            VAR strat_props    : tgg07_KeyStratProps);
 
VAR
      _iy              : tsp00_Int2;
      _st_dummy_cnt    : tsp00_Int2;
      _all_page_cnt    : tsp00_Int4;
      _max_pages       : tsp00_Int4;
      _scoured_pages   : tsp00_Int4;
      _fract           : tsp00_Longreal;
      _searchkey1      : tgg00_Lkey;
      _searchkey2      : tgg00_Lkey;
      _e               : tgg00_BasisError;
      _record_cnt      : tsp00_Int4;
      _use_stopkey     : boolean;
 
BEGIN
&ifdef trace
a725output_colposarr( ak_strat, 'keystart    ', keystart );
a725output_colposarr( ak_strat, 'keystop     ', keystop );
t01p2int4( ak_strat, 'in stpos    ', in_stack, 'in elemcnt  ', in_cnt );
IF  ( in_stack = 0 )
THEN
    a07ak_system_error( acv, 720, 1 );
&endif
(*ENDIF*) 
_all_page_cnt  := 0;
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720KEY_IN_EVAL>>          ' );
    END;
(*ENDIF*) 
eval_rec.ker_strat_IN_SUBQ.er_strat_value   := 0;
eval_rec.ker_strat_IN_SUBQ.er_read_primrows := 0;
_fract        := 1;  (* full range *)
_st_dummy_cnt := 0;
_iy           := 1;
WHILE ( _iy <= in_cnt ) AND
      ( acv.a_returncode = 0 ) DO
    BEGIN
    IF  ( acv.a_mblock.mb_st^[ in_stack + _iy + _st_dummy_cnt ].etype <>
        st_dummy )
    THEN
        BEGIN
&       ifdef trace
        t01stackentry( ak_strat,
              acv.a_mblock.mb_st^[ in_stack + _iy + _st_dummy_cnt ], _iy );
&       endif
        _use_stopkey := true;
        g04limitprimkeys( acv.a_mblock, keystart, _searchkey1,
              keystop, _searchkey2, _use_stopkey, in_stack,
              _iy + _st_dummy_cnt );
&       ifdef trace
        t01key( ak_strat, 'startkey    ', _searchkey1 );
        t01key( ak_strat, 'stopkey     ', _searchkey2 );
        t01bool( ak_strat, 'use stopkey ', _use_stopkey );
&       endif
        ;
        IF  ( acv.a_mblock.mb_trns^.trError_gg00 = e_move_error )
        THEN
            acv.a_returncode :=
                  a07_return_code( e_move_error, acv.a_sqlmode );
        (*ENDIF*) 
        IF  ( acv.a_returncode = 0 )
        THEN
            BEGIN
            _all_page_cnt  := 0;
            IF  (( _use_stopkey ) OR ( _searchkey1.len > 0 ) OR
                ( cs_IN_strategy in config.cfg_switches ))
            THEN
                BEGIN
                _scoured_pages := access_info.srec_primpages;
                _record_cnt    := -1;
                _e             := e_ok;
                a06eval_page_count( acv, acv.a_mblock.mb_qual^.mtree,
                      _searchkey1, _searchkey2,
                      c_sample, c_count_recs,
                      _scoured_pages, _all_page_cnt, _record_cnt, _e );
                ;
                IF  ( _e <> e_ok )
                THEN
                    BEGIN
                    IF  ( _e = e_file_not_found )
                    THEN
                        a07_b_put_error( acv, e_old_fileversion, 1 )
                    ELSE
                        a07_b_put_error( acv, _e, 1 );
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  ( _record_cnt < 0 )
                    THEN
                        eval_rec.ker_strat_IN_SUBQ.er_read_primrows := IS_UNDEFINED_GG07;
                    (*ENDIF*) 
                    _fract := a71stratval_calc( access_info,
                          _scoured_pages, _record_cnt,
                          IS_UNDEFINED_GG07, (_record_cnt >= 0) );
                    eval_rec.ker_strat_IN_SUBQ.er_strat_value :=
                          eval_rec.ker_strat_IN_SUBQ.er_strat_value + _fract;
                    eval_rec.ker_strat_IN_SUBQ.er_read_pages :=
                          eval_rec.ker_strat_IN_SUBQ.er_read_pages +
                          _scoured_pages;
                    IF  ( eval_rec.ker_strat_IN_SUBQ.er_read_primrows <> IS_UNDEFINED_GG07 )
                    THEN
                        eval_rec.ker_strat_IN_SUBQ.er_read_primrows :=
                              eval_rec.ker_strat_IN_SUBQ.er_read_primrows +
                              _record_cnt;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
&               ifdef trace
                t01int4( ak_strat, 'found rows  ', _record_cnt );
                t01int4( ak_strat, 'min page cnt', _all_page_cnt );
                t01int4( ak_strat, 'found pages ', _scoured_pages );
                t01real( ak_strat, 'single fract', _fract, 3 );
                t01int4( ak_strat, 'IN read page',
                      eval_rec.ker_strat_IN_SUBQ.er_read_pages );
&               endif
                END
            ELSE
                BEGIN
&               ifdef trace
                t01sname( ak_strat, 'full range  ' );
&               endif
                eval_rec.ker_strat_IN_SUBQ.er_read_primrows := IS_UNDEFINED_GG07;
                eval_rec.ker_strat_IN_SUBQ.er_strat_value :=
                      eval_rec.ker_strat_IN_SUBQ.er_strat_value + 1;
                eval_rec.ker_strat_IN_SUBQ.er_read_pages :=
                      eval_rec.ker_strat_IN_SUBQ.er_read_pages +
                      access_info.srec_primpages;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        _iy := succ( _iy );
        ;
        END
    ELSE
        BEGIN
&       ifdef trace
        t01int4( ak_strat, 'st_dummy fnd', _iy );
&       endif
        _st_dummy_cnt := succ( _st_dummy_cnt );
        END;
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
IF  ( eval_rec.ker_strat_IN_SUBQ.er_strat_value = 0 )
THEN
    BEGIN
    eval_rec.ker_strat_IN_SUBQ.er_strat_value := 1;
    eval_rec.ker_strat_IN_SUBQ.er_read_pages  :=
          eval_rec.ker_strat_range.er_read_pages + 1;
    END;
(*ENDIF*) 
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        a727trace_eval( acv.a_transinf.tri_trans,
              '------ AK720KEY_IN_EVAL ------',
              c_count_recs,
              access_info.srec_primrows,
              eval_rec.ker_strat_IN_SUBQ.er_read_primrows,
              access_info.srec_primpages, _all_page_cnt,
              eval_rec.ker_strat_IN_SUBQ.er_read_pages,
              eval_rec.ker_strat_IN_SUBQ.er_strat_value );
&   ifdef trace
    (*ENDIF*) 
    t01int4( ak_strat, 'Prime rows  ', access_info.srec_primrows );
    t01int4( ak_strat, 'found rows  ', eval_rec.ker_strat_IN_SUBQ.er_read_primrows );
    t01int4( ak_strat, 'prim  pages ', access_info.srec_primpages );
    t01int4( ak_strat, 'min page cnt', _all_page_cnt );
    t01int4( ak_strat, 'found pages ', eval_rec.ker_strat_IN_SUBQ.er_read_pages );
    t01real( ak_strat, 'strat val   ', eval_rec.ker_strat_IN_SUBQ.er_strat_value, 3 );
&   endif
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720key_SUBQ_eval (
            VAR acv         : tak_all_command_glob;
            VAR access_info : tak70_strategy_record;
            VAR keystart    : tgg07_ColPosArr;
            VAR keystop     : tgg07_ColPosArr;
            subq_stpos      : tsp00_Int2;
            VAR eval_rec    : t_key_eval_rec;
            VAR config      : tak00_access_configuration;
            VAR strat_props : tgg07_KeyStratProps);
 
VAR
      _subq_rowcnt      : tsp00_Int2;
      _scoured_pages    : tsp00_Int4;
      _all_page_cnt     : tsp00_Int4;
      _record_cnt       : tsp00_Int4;
      _max_pages        : tsp00_Int4;
      _fract            : tsp00_Longreal;
      _startkey         : tgg00_Lkey;
      _stopkey          : tgg00_Lkey;
      _next_key         : tgg00_Lkey;
      _search_id        : tgg00_FileId;
      _subqtree_id      : tgg00_FileId;
      _rec_buf          : tgg00_Rec;
      _aux_error        : tgg00_BasisError;
      _e                : tgg00_BasisError;
      _success          : boolean;
      _use_stopkey      : boolean;
      _count_recs       : boolean;
      _read_limit       : boolean;
 
BEGIN
&ifdef trace
a725output_colposarr( ak_strat, 'keystart    ', keystart );
a725output_colposarr( ak_strat, 'keystop     ', keystop );
&endif
_all_page_cnt := 0;
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720KEY_SUBQ_EVAL>>        ' );
    END;
(*ENDIF*) 
eval_rec.ker_strat_IN_SUBQ.er_strat_value := 0;
_search_id := acv.a_mblock.mb_qual^.mtree;
SAPDB_PascalMove ('VAK720',   2,    
      acv.a_mblock.mb_data_size, sizeof( _subqtree_id ),
      @acv.a_mblock.mb_data^.mbp_buf,
      acv.a_mblock.mb_st^[ subq_stpos + 1 ].epos,
      @_subqtree_id, 1, FILE_ID_MXGG00,
      acv.a_returncode);
&ifdef trace
t01treeid( ak_strat, 'subq treeid ', _subqtree_id );
&endif
_aux_error := acv.a_returncode;
_e         := e_ok;
acv.a_mblock.mb_trns^.trError_gg00 := e_ok;
_subq_rowcnt:= 0;
_next_key.len := 0;
_count_recs := ( cs_count_records in config.cfg_switches );
_read_limit := false;
_max_pages  := eval_rec.ker_strat_range.er_read_pages;
&ifdef trace
t01int4( ak_strat, 'read limit  ', _max_pages );
&endif
;
WHILE ( _e = e_ok ) AND ( _aux_error = e_ok ) AND
      ( acv.a_mblock.mb_trns^.trError_gg00 = e_ok ) AND
      ( NOT _read_limit ) DO
    BEGIN
    g04read_subquery( acv.a_mblock.mb_trns^, _rec_buf,
          _subqtree_id, _next_key, _aux_error, _success );
    IF  ( _success )
    THEN
        BEGIN
        _subq_rowcnt    := succ( _subq_rowcnt );
        IF  ( _subq_rowcnt <= c_max_subq_eval_cnt )
        THEN
            BEGIN
            _use_stopkey := false;
            gg04one_subq_limitprimkey( acv.a_mblock, _rec_buf,
                  keystart, _startkey, _use_stopkey );
            IF  ( acv.a_mblock.mb_trns^.trError_gg00 = e_move_error )
            THEN
                _e := e_move_error
            ELSE
                BEGIN
                _use_stopkey := true;
                gg04one_subq_limitprimkey( acv.a_mblock, _rec_buf,
                      keystop, _stopkey, _use_stopkey );
                IF  ( acv.a_mblock.mb_trns^.trError_gg00 = e_move_error )
                THEN
                    _e := e_move_error
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            _record_cnt    := -1;
            _all_page_cnt  := 0;
            _scoured_pages := access_info.srec_primpages;
            IF  ( _e = e_ok )
            THEN
                a06eval_page_count( acv, _search_id,
                      _startkey, _stopkey,
                      c_sample, _count_recs,
                      _scoured_pages,
                      _all_page_cnt, _record_cnt, _e);
            (*ENDIF*) 
            IF  ( _e <> e_ok )
            THEN
                IF  ( _e = e_file_not_found )
                THEN
                    a07_b_put_error( acv, e_old_fileversion, 1 )
                ELSE
                    a07_b_put_error( acv, _e, 1 )
                (*ENDIF*) 
            ELSE
                BEGIN
                IF  ( _count_recs ) AND ( _record_cnt < 0 )
                THEN
                    BEGIN
                    _record_cnt := IS_UNDEFINED_GG07;
                    _count_recs := false;
                    END;
                (*ENDIF*) 
                _fract := a71stratval_calc( access_info, _scoured_pages,
                      _record_cnt, IS_UNDEFINED_GG07, _count_recs );
                END;
            (*ENDIF*) 
            END
        ELSE
            (* more than c_max_subq_eval_cnt elements *)
            BEGIN
&           ifdef TRACE
            t01sname( ak_strat, 'use avg val ' );
&           endif
            _fract :=
                  eval_rec.ker_strat_IN_SUBQ.er_strat_value /
                  ( _subq_rowcnt - 1 );
            IF  ( _count_recs )
            THEN
                _record_cnt :=
                      trunc(( eval_rec.ker_strat_IN_SUBQ.er_read_primrows /
                      ( _subq_rowcnt - 1 )) + 1 );
            (*ENDIF*) 
            _scoured_pages :=
                  trunc(( eval_rec.ker_strat_IN_SUBQ.er_read_pages /
                  ( _subq_rowcnt - 1 )) + 1 );
            END;
        (*ENDIF*) 
        IF  ( _e = e_ok )
        THEN
            BEGIN
&           ifdef TRACE
            t01real( ak_strat, 'fract single', _fract, 3 );
            t01int4( ak_strat, 'min page cnt', _all_page_cnt );
            t01int4( ak_strat, 'scoured page', _scoured_pages );
            t01int4( ak_strat, 'record cnt  ', _record_cnt );
&           endif
            eval_rec.ker_strat_IN_SUBQ.er_strat_value :=
                  eval_rec.ker_strat_IN_SUBQ.er_strat_value + _fract;
            IF  ( _count_recs )
            THEN
                BEGIN
                (* initialize row count *)
                IF  ( eval_rec.ker_strat_IN_SUBQ.
                    er_read_primrows = IS_UNDEFINED_GG07 )
                THEN
                    eval_rec.ker_strat_IN_SUBQ.er_read_primrows := 0;
                (*ENDIF*) 
                eval_rec.ker_strat_IN_SUBQ.er_read_primrows :=
                      eval_rec.ker_strat_IN_SUBQ.er_read_primrows +
                      _record_cnt;
                END;
            (*ENDIF*) 
            eval_rec.ker_strat_IN_SUBQ.er_read_pages :=
                  eval_rec.ker_strat_IN_SUBQ.er_read_pages +
                  _scoured_pages;
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  ( acv.a_mblock.mb_trns^.trError_gg00 <> e_ok )
        THEN
            a07_b_put_error( acv, acv.a_mblock.mb_trns^.trError_gg00, 1 )
        ELSE
            BEGIN
            IF  ( _aux_error = e_no_next_record ) AND
                ( eval_rec.ker_strat_IN_SUBQ.er_read_pages = 0 )
            THEN
                BEGIN
                eval_rec.ker_strat_IN_SUBQ.er_strat_value :=
                      1 / access_info.srec_primpages;
                IF  ( _count_recs )
                THEN
                    eval_rec.ker_strat_IN_SUBQ.er_read_primrows  := 0;
                (*ENDIF*) 
                eval_rec.ker_strat_IN_SUBQ.er_read_pages  := 1;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    _read_limit :=
          ( eval_rec.ker_strat_IN_SUBQ.er_read_pages >= _max_pages );
    END;
(*ENDWHILE*) 
IF  (( g01vtrace.vtrStrategy_gg00 ) AND _read_limit )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          'exceed strat limit!           ' );
    END;
(*ENDIF*) 
IF  ( eval_rec.ker_strat_IN_SUBQ.er_strat_value = 0 )
THEN
    BEGIN
    eval_rec.ker_strat_IN_SUBQ.er_strat_value := 1;
    eval_rec.ker_strat_IN_SUBQ.er_read_pages  :=
          eval_rec.ker_strat_range.er_read_pages + 1;
    END;
(*ENDIF*) 
IF  ( NOT _count_recs )
THEN
    eval_rec.ker_strat_IN_SUBQ.
          er_read_primrows := IS_UNDEFINED_GG07;
(*ENDIF*) 
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    a727trace_eval( acv.a_transinf.tri_trans,
          '---- AK720KEY_SUBQ_EVAL ------',
          _count_recs,
          access_info.srec_primrows,
          eval_rec.ker_strat_IN_SUBQ.er_read_primrows,
          access_info.srec_primpages, _all_page_cnt,
          eval_rec.ker_strat_IN_SUBQ.er_read_pages,
          eval_rec.ker_strat_IN_SUBQ.er_strat_value );
(*ENDIF*) 
;
&ifdef TRACE
t01bool( ak_strat, 'Count Record', _count_recs );
t01int4( ak_strat, 'prim  rows  ', access_info.srec_primrows );
t01int4( ak_strat, 'prim  pages ', access_info.srec_primpages );
t01int4( ak_strat, 'min page cnt', _all_page_cnt );
t01int4( ak_strat, 'read ppages ', eval_rec.ker_strat_IN_SUBQ.
      er_read_pages );
t01int4( ak_strat, 'read prows  ', eval_rec.ker_strat_IN_SUBQ.
      er_read_primrows );
t01real( ak_strat, 'strat value ', eval_rec.ker_strat_IN_SUBQ.
      er_strat_value, 3 );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720get_invstrat_info (
            VAR acv           : tak_all_command_glob;
            VAR sparr         : tak_syspointerarr;
            VAR gg_strategy   : tgg07_StrategyInfo; (*const*)
            VAR access_info   : tak70_strategy_record;
            VAR inv_strat     : tak70_one_strat;
            VAR index_def     : tak_multindex;
            VAR order_fields  : tak00_ord_fields; (*const*)
            VAR usable        : boolean);
 
VAR
      _ix          : tsp00_Int4;
      _index_tree  : tgg00_FileId;
 
BEGIN
inv_strat.ostr_strategy         := strat_undecided;
inv_strat.ostr_wholeIO_pages    := IS_UNDEFINED_GG07;
inv_strat.ostr_readIO_pages     := IS_UNDEFINED_GG07;
inv_strat.ostr_readIO_primpages := IS_UNDEFINED_GG07;
inv_strat.ostr_readIO_rows      := IS_UNDEFINED_GG07;
inv_strat.ostr_inv_in_range.siir_indexno := index_def.indexno;
&ifdef trace
t01int4( ak_strat, 'indexno     ', inv_strat.ostr_inv_in_range.siir_indexno );
&endif
;
IF  ( access_info.srec_invaccess.ia_inv_root
    [ inv_strat.ostr_inv_in_range.siir_indexno - 1 ] = NIL_PAGE_NO_GG00 )
THEN
    BEGIN
    g04index_tree_build( acv.a_mblock.mb_qual^.mtree, _index_tree,
          inv_strat.ostr_inv_in_range.siir_indexno );
&   ifdef trace
    t01treeid( ak_strat, 'index_tree  ', _index_tree );
&   endif
    ;
    b01filestate( acv.a_transinf.tri_trans, _index_tree );
    IF  ( acv.a_transinf.tri_trans.trError_gg00 = e_ok )
    THEN
        access_info.srec_invaccess.ia_inv_root
              [ inv_strat.ostr_inv_in_range.siir_indexno - 1 ] :=
              _index_tree.fileRoot_gg00;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  ( access_info.srec_invaccess.
    ia_inv_root[ inv_strat.ostr_inv_in_range.siir_indexno - 1 ] <>
    NIL_PAGE_NO_GG00 )
THEN
    BEGIN
    usable := true;
    inv_strat.ostr_inv_in_range.siir_strat_props   := [];
    IF  ( index_def.iunique )
    THEN
        inv_strat.ostr_inv_in_range.siir_strat_props :=
              inv_strat.ostr_inv_in_range.siir_strat_props + [ isp_unique_idx ];
    (*ENDIF*) 
    inv_strat.ostr_inv_in_range.siir_invroot       :=
          access_info.srec_invaccess.
          ia_inv_root[ inv_strat.ostr_inv_in_range.siir_indexno - 1 ];
    inv_strat.ostr_inv_in_range.siir_icount        := a24IndexFieldCount (index_def);
    inv_strat.ostr_inv_in_range.siir_startcnt      := 0;
    inv_strat.ostr_inv_in_range.siir_stopcnt       := 0;
    inv_strat.ostr_inv_in_range.siir_invlen        := 0;
    inv_strat.ostr_inv_in_range.siir_inelemcnt     := 0;
    inv_strat.ostr_inv_in_range.siir_invcoldesc    := [];
    inv_strat.ostr_inv_in_range.siir_out_invseqlen := NOT_SEQUENCED_GG07;
    inv_strat.ostr_inv_in_range.siir_subq_idx      := IS_UNDEFINED_GG07;
    inv_strat.ostr_inv_in_range.siir_IN_SUBQ_stpos := IS_UNDEFINED_GG07;
    inv_strat.ostr_inv_in_range.siir_MIN_recpos    := IS_UNDEFINED_GG07;
    inv_strat.ostr_inv_in_range.siir_MAX_recpos    := IS_UNDEFINED_GG07;
    ;
    FOR _ix := 1 TO a24IndexFieldCount( index_def ) DO
        BEGIN
        inv_strat.ostr_inv_in_range.siir_invstart[ _ix - 1 ] := 0;
        inv_strat.ostr_inv_in_range.siir_invstop[ _ix - 1 ]  := 0;
        IF  ( index_def.icolstack[ _ix ].eop in
            [ op_order_desc, op_unique_desc ] )
        THEN
            inv_strat.ostr_inv_in_range.siir_invcoldesc :=
                  inv_strat.ostr_inv_in_range.siir_invcoldesc + [ _ix ];
        (*ENDIF*) 
        inv_strat.ostr_inv_in_range.siir_invlen :=
              inv_strat.ostr_inv_in_range.siir_invlen +
              index_def.icolstack[ _ix ].elen_var;
        END;
    (*ENDFOR*) 
    ;
    a71create_inv_sequence( acv, access_info, inv_strat, index_def );
    ;
    ak720test_invstrat_props( acv, sparr, gg_strategy, access_info,
          inv_strat, index_def, order_fields );
    ;
    IF  ( qp_missing_value in access_info.srec_query_prop.qps_switches ) OR
        ( qp_no_result_set in access_info.srec_query_prop.qps_switches )
    THEN
        usable := false;
    (*ENDIF*) 
    ;
&   ifdef TRACE
    t01strat_enum( ak_strat, 'index strat ', inv_strat.ostr_strategy );
    a725output_invstrat( ak_strat, 'index strat ', inv_strat.ostr_inv_in_range );
    t01bool( ak_strat, 'usable index', usable );
&   endif
    END
ELSE
    BEGIN
&   ifdef trace
    t01name( ak_strat, 'index inaccessible' );
&   endif
    usable := false;
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        g041c30_to_trace( acv.a_transinf.tri_trans,
              'index not accessible!         ' );
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720test_invstrat_props (
            VAR acv         : tak_all_command_glob;
            VAR sparr       : tak_syspointerarr;
            VAR gg_strategy : tgg07_StrategyInfo; (*const*)
            VAR access_info : tak70_strategy_record;
            VAR inv_strat   : tak70_one_strat;
            VAR index_def   : tak_multindex;
            VAR order_fields: tak00_ord_fields (*const*));
 
VAR
      _ix                 : tsp00_Int2;
      _inv_cnt            : tsp00_Int2;
      _col_index          : tsp00_Int2;
      _dummy_int          : tsp00_Int2;
      _out_invseqlen      : tsp00_Int2;
      _found_const_icols  : SET OF 1..MAX_COL_PER_TAB_GG00;
      _invseq_is_ord_seq  : boolean;
      _all_cols_contained : boolean;
      _inv_processed      : boolean;
      _reverse_seq        : boolean;
      _reverse_poss       : boolean;
      _pure_inv_cols      : boolean;
 
BEGIN
&ifdef trace
t01name( ak_strat, 'ak720test_invstrat' );
&endif
IF  ( sp_exact_match in access_info.srec_invaccess.ia_sequence_props )
THEN
    inv_strat.ostr_inv_in_range.siir_strat_props :=
          inv_strat.ostr_inv_in_range.siir_strat_props + [ isp_exact_match ];
(*ENDIF*) 
IF  ((( sp_IN_usage in access_info.srec_invaccess.ia_sequence_props ) OR
    ( sp_SUBQ_usage in access_info.srec_invaccess.ia_sequence_props )) AND
    ( sp_exact_IN_SUBQ_match in access_info.srec_invaccess.ia_sequence_props ))
THEN
    inv_strat.ostr_inv_in_range.siir_strat_props :=
          inv_strat.ostr_inv_in_range.siir_strat_props +
          [ isp_exact_IN_SUBQ_match ];
(*ENDIF*) 
;
IF  ( qp_check_order_support in access_info.srec_query_prop.qps_switches )
THEN
    (* check order support of this index *)
    BEGIN
&   ifdef trace
    t01name( ak_strat, 'check order supprt' );
&   endif
    _reverse_poss := a01diag_reverse_fetch;
    _reverse_seq  := false;
    IF  a24IsFunctionBasedIndex(index_def)
    THEN
        BEGIN
        _invseq_is_ord_seq := false;
        IF  order_fields.ocntord = 1
        THEN
            BEGIN
            _ix := order_fields.ofield[1].ofstno - 1;
            WHILE (_ix >= acv.a_mblock.mb_qual^.mqual_pos       ) AND
                  (acv.a_mblock.mb_st^[ _ix ].etype <> st_output) DO
                _ix := _ix - 1;
            (*ENDWHILE*) 
            IF  a24IndexMatch (acv, index_def, _ix + 1, order_fields.ofield[1].ofstno -1)
            THEN
                BEGIN
                _reverse_seq :=
                      (( index_def.icolstack[ 1 ].eop in [ op_order_asc, op_unique ] )
                      AND
                      NOT (is_order_asc in order_fields.ofield[ 1 ].ofasc) )
                      OR
                      (( index_def.icolstack[ 1 ].eop in [ op_order_desc, op_unique_desc ] )
                      AND
                      (is_order_asc in order_fields.ofield[ 1 ].ofasc) );
                _invseq_is_ord_seq := NOT _reverse_seq OR _reverse_poss;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        _ix      := 1;
        _inv_cnt := 1;
        _col_index         := 1;
        _found_const_icols := [];
        _inv_processed     := false;
        _invseq_is_ord_seq := ( order_fields.ocntord <= a24IndexFieldCount( index_def ));
        WHILE  ( _ix <= order_fields.ocntord ) AND
              ( _invseq_is_ord_seq ) DO
            BEGIN
&           ifdef trace
            t01p2int4( ak_strat, 'icolseq     ', index_def.icolseq[ _col_index ],
                  'order field ', order_fields.ofield[ _ix ].offno );
&           endif
            BEGIN
            (* if i.inv column is constant this is OK *)
            IF  (( NOT _inv_processed ) AND
                ( inv_strat.ostr_inv_in_range.siir_startcnt >= _inv_cnt ) AND
                ( inv_strat.ostr_inv_in_range.siir_stopcnt   >= _inv_cnt ) AND
                ( inv_strat.ostr_inv_in_range.siir_invstart[_inv_cnt - 1] =
                inv_strat.ostr_inv_in_range.siir_invstop[_inv_cnt - 1] ) AND
                (* it isn't a IN/SUBQ condition *)
                ((( inv_strat.ostr_inv_in_range.siir_IN_SUBQ_stpos <> IS_UNDEFINED_GG07 ) AND
                ( inv_strat.ostr_inv_in_range.siir_IN_SUBQ_stpos <>
                inv_strat.ostr_inv_in_range.siir_invstart[_inv_cnt - 1] )) OR
                ( inv_strat.ostr_inv_in_range.siir_IN_SUBQ_stpos = IS_UNDEFINED_GG07 ))
                )
            THEN
                BEGIN
&               ifdef trace
                t01int4( ak_strat, 'INV is CONST', index_def.icolseq[ _col_index ] );
&               endif
                _found_const_icols := _found_const_icols +
                      [ index_def.icolseq[ _col_index ] ];
                (* step to next key *)
                IF  ( _inv_cnt < index_def.icount )
                THEN
                    BEGIN
                    _col_index  := succ( _col_index );
                    _inv_cnt    := succ( _inv_cnt );
                    END
                ELSE
                    _inv_processed := true;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                IF  ( index_def.icolseq[ _col_index ] =
                    order_fields.ofield[ _ix ].offno )
                THEN
                    BEGIN
                    IF  ( index_def.icolstack[ _inv_cnt ].eop in
                        [ op_order_asc, op_unique ] ) <>
                        ( is_order_asc in order_fields.ofield[ _ix ].ofasc )
                    THEN
                        BEGIN
                        IF  ( _reverse_poss )
                        THEN
                            _reverse_seq := true
                        ELSE
                            BEGIN
                            _invseq_is_ord_seq := false;
                            (* ORDER BY with index access impossible *)
&                           ifdef trace
                            t01name( ak_strat, 'wrong sorting     ' );
&                           endif
                            END;
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        _reverse_poss := false;
                        IF  ( _reverse_seq )
                        THEN
                            _invseq_is_ord_seq := false;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  ( _invseq_is_ord_seq )
                    THEN
                        BEGIN
&                       ifdef trace
                        t01sname( ak_strat, 'INV = ORDER ' );
&                       endif
                        (* step to next order field *)
                        _ix := succ( _ix );
                        (* step to next key *)
                        IF  ( _inv_cnt < index_def.icount )
                        THEN
                            BEGIN
                            _col_index := succ( _col_index );
                            _inv_cnt   := succ( _inv_cnt );
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  ( order_fields.ofield[ _ix ].offno in _found_const_icols )
                    THEN
                        BEGIN
&                       ifdef trace
                        t01name( ak_strat, 'known const field ' );
&                       endif
                        _ix := succ( _ix );
                        END
                    ELSE
                        _invseq_is_ord_seq := false;
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
            END;
        (*ENDWHILE*) 
        END;
    (*ENDIF*) 
    IF  ( _invseq_is_ord_seq )
    THEN
        BEGIN
&       ifdef trace
        t01name( ak_strat, 'inv order support ' );
&       endif
        inv_strat.ostr_inv_in_range.siir_strat_props :=
              inv_strat.ostr_inv_in_range.siir_strat_props +
              [ isp_order_support ];
        IF  ( _reverse_seq )
        THEN
            BEGIN
            inv_strat.ostr_inv_in_range.siir_strat_props :=
                  inv_strat.ostr_inv_in_range.siir_strat_props +
                  [ isp_order_support_reverse ];
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
(* check if all output columns are in icolseq or key *)
ak720content_check(
      access_info.srec_involved_cols.ic_i_outp_cols,
      access_info.srec_involved_cols.ic_i_outp_cnt,
      access_info.srec_involved_cols.ic_k_outp_cols,
      access_info.srec_involved_cols.ic_k_outp_cnt,
      index_def, _all_cols_contained, _pure_inv_cols, _out_invseqlen );
;
IF  ( _pure_inv_cols )
THEN
    inv_strat.ostr_inv_in_range.siir_strat_props :=
          inv_strat.ostr_inv_in_range.siir_strat_props + [ isp_pure_inv_output ];
(*ENDIF*) 
IF  ( _all_cols_contained )
THEN
    BEGIN
&   ifdef trace
    t01name( ak_strat, 'all ocol in index ' );
    t01int4( ak_strat, 'out kseqlen ', gg_strategy.str_out_keyseqlen );
    t01int4( ak_strat, 'out iseqlen ', _out_invseqlen );
&   endif
    (* all output columns in actual index/key          *)
    IF  ( gg_strategy.str_out_keyseqlen <> NOT_SEQUENCED_GG07 )
        (* there are dist optim on key *)
        AND
        ( _out_invseqlen <> IS_UNDEFINED_GG07 )
        AND
        ((( _out_invseqlen < inv_strat.ostr_inv_in_range.siir_invlen ) AND
        ( gg_strategy.str_out_keyseqlen = KEYSEQLEN_OFFSET_GG07 ))
        OR
        (( _out_invseqlen = inv_strat.ostr_inv_in_range.siir_invlen ) AND
        ( gg_strategy.str_out_keyseqlen >= KEYSEQLEN_OFFSET_GG07 )))
    THEN
        BEGIN
        (* we avoid building of result for distinct handling *)
        (* but we have to jump over parts of index file      *)
        inv_strat.ostr_inv_in_range.siir_out_invseqlen := _out_invseqlen;
&       ifdef trace
        t01sname( ak_strat, 'distinct opt' );
&       endif
        END;
    (*ENDIF*) 
    IF  NOT ( qp_inv_only_impossible in access_info.srec_query_prop.qps_switches )
    THEN
        (* check if all qualificated columns in icolseq or key *)
        BEGIN
        ak720content_check(
              access_info.srec_involved_cols.ic_i_qual_cols,
              access_info.srec_involved_cols.ic_i_qual_cnt,
              access_info.srec_involved_cols.ic_k_qual_cols,
              access_info.srec_involved_cols.ic_k_qual_cnt,
              index_def, _all_cols_contained, _pure_inv_cols, _dummy_int );
        ;
        IF  ( _all_cols_contained )
        THEN
            BEGIN
            (* all qualificated columns in actual index/key *)
            (* AND                                          *)
            (* all output columns in actual index/key       *)
            IF  NOT ( cs_disable_inv_only in
                access_info.srec_config.cfg_switches )
            THEN
                inv_strat.ostr_inv_in_range.siir_strat_props :=
                      inv_strat.ostr_inv_in_range.siir_strat_props +
                      [ isp_inv_only ];
&           ifdef trace
            (*ENDIF*) 
            t01name( ak_strat, 'all oqcol in index' );
            t01bool( ak_strat, 'ionly index ', true );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  ( access_info.srec_L1_strategy ) AND
    ( qp_check_inv_MIN_MAX_opt in access_info.srec_query_prop.qps_switches )
THEN
    ak720check_inv_minmax_opt( acv, inv_strat.ostr_inv_in_range, index_def );
(*ENDIF*) 
IF  ( access_info.srec_L1_strategy )
    AND
    ( qp_check_key_inv_MIN_MAX_opt in access_info.srec_query_prop.qps_switches )
THEN
    ak720check_key_inv_minmax_opt( acv, inv_strat.ostr_inv_in_range );
(*ENDIF*) 
;
IF  (( NOT access_info.srec_unusable_L1_pred ) AND
    ( NOT access_info.srec_L23_predicates ))
THEN
    BEGIN
    IF  (( sp_first_row_start in access_info.srec_invaccess.ia_sequence_props )
        AND
        (( inv_strat.ostr_inv_in_range.siir_startcnt =
        access_info.srec_L1_pred_cnt ) OR
        (( sp_first_row_start in access_info.srec_keyaccess.ka_sequence_props ) AND
        ak720all_predicates_used( acv, sparr, access_info,
        inv_strat.ostr_inv_in_range, true ))))
    THEN
        BEGIN
        inv_strat.ostr_inv_in_range.siir_strat_props :=
              inv_strat.ostr_inv_in_range.siir_strat_props +
              [ isp_first_row_start ];
        END;
    (*ENDIF*) 
    IF  (( sp_first_row_stop in access_info.srec_invaccess.ia_sequence_props )
        AND
        (( inv_strat.ostr_inv_in_range.siir_stopcnt =
        access_info.srec_L1_pred_cnt ) OR
        ((( sp_exact_match in access_info.srec_invaccess.ia_sequence_props ) OR
        ( sp_exact_IN_SUBQ_match in access_info.srec_invaccess.ia_sequence_props )) AND
        ( sp_first_row_stop in access_info.srec_keyaccess.ka_sequence_props ) AND
        ak720all_predicates_used( acv, sparr, access_info,
        inv_strat.ostr_inv_in_range, false ))))
    THEN
        BEGIN
        inv_strat.ostr_inv_in_range.siir_strat_props :=
              inv_strat.ostr_inv_in_range.siir_strat_props +
              [ isp_first_row_stop ];
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
IF  ( qp_auto_distinct in access_info.srec_query_prop.qps_switches )
THEN
    inv_strat.ostr_inv_in_range.siir_strat_props :=
          inv_strat.ostr_inv_in_range.siir_strat_props + [ isp_auto_distinct ];
(*ENDIF*) 
IF  ak720IndexIsSubsetOfKey (acv, access_info, inv_strat, sparr.pbasep)
THEN
    inv_strat.ostr_inv_in_range.siir_strat_props :=
          inv_strat.ostr_inv_in_range.siir_strat_props + [ isp_keysubset ];
(*ENDIF*) 
;
&ifdef trace
IF  (( isp_aggr_MIN_opt in inv_strat.ostr_inv_in_range.siir_strat_props ) OR
    (  isp_aggr_MAX_opt in inv_strat.ostr_inv_in_range.siir_strat_props ))
    AND
    (( isp_aggr_key_MIN_opt in inv_strat.ostr_inv_in_range.siir_strat_props ) OR
    (  isp_aggr_key_MAX_opt in inv_strat.ostr_inv_in_range.siir_strat_props ))
THEN
    a07ak_system_error( acv, 720, 2 );
&endif
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720content_check (
            VAR sequence        : tak_colsequence;
            VAR sequencecnt     : tsp00_Int2;
            VAR ref_keyposarr   : tgg07_ColPosArr;
            VAR ref_keyposarrcnt: tsp00_Int2;
            VAR ref_indexdef    : tak_multindex;
            VAR seq_in_ref      : boolean;
            VAR seq_only_in_inv : boolean;
            VAR out_invseqlen   : tsp00_Int2);
 
VAR
      _diff_col_found : boolean;
      _ix             : tsp00_Int4;
      _iy             : tsp00_Int4;
      _iz             : tsp00_Int4;
      _found_icolseq  : tak_colsequence;
 
BEGIN
FOR _ix := 1 TO MAX_COL_SEQUENCE_GG00 DO
    _found_icolseq[ _ix ] := 0;
(*ENDFOR*) 
_ix := 1;
out_invseqlen   := IS_UNDEFINED_GG07;
seq_in_ref      := true;
seq_only_in_inv := false;
IF  ( sequencecnt > 0 )
THEN
    BEGIN
    seq_only_in_inv := true;
    WHILE ( _ix <= sequencecnt ) AND ( seq_in_ref ) DO
        BEGIN
        (* search every sequence column in ref_indexdef.icolseq *)
        _iy        := 1;
        seq_in_ref := false;
        WHILE ( _iy <= a24IndexFieldCount( ref_indexdef )) AND ( NOT seq_in_ref ) DO
            BEGIN
            IF  ( sequence[ _ix ] = ref_indexdef.icolseq[ _iy ] )
            THEN
                BEGIN
                _found_icolseq[ _iy ] := _iy;
                seq_in_ref            := true
                END
            ELSE
                _iy := succ( _iy );
            (*ENDIF*) 
            END;
        (*ENDWHILE*) 
        ;
        (* second chance, search column in ref_keyposarr *)
        IF  ( NOT seq_in_ref ) AND ( ref_keyposarrcnt > 0 )
        THEN
            BEGIN
            seq_only_in_inv := false;
            _iz := 0;
            WHILE ( _iz <= ref_keyposarrcnt - 1 ) AND ( NOT seq_in_ref ) DO
                BEGIN
                IF  ( sequence[ _ix ] = ref_keyposarr[ _iz ] )
                THEN
                    seq_in_ref := true
                ELSE
                    _iz := succ( _iz );
                (*ENDIF*) 
                END;
            (*ENDWHILE*) 
            END;
        (*ENDIF*) 
        _ix := succ( _ix );
        END;
    (*ENDWHILE*) 
    _ix := 0;
    _diff_col_found := true;
    (* look for colno sequence 1, 2, 3, 4, ..... *)
    WHILE ( _diff_col_found ) AND ( _ix < a24IndexFieldCount( ref_indexdef )) DO
        BEGIN
        IF  ( _found_icolseq[ _ix + 1 ] = _ix + 1 )
        THEN
            _ix := succ( _ix )
        ELSE
            _diff_col_found := false;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  ( seq_in_ref ) AND ( _ix = sequencecnt )
    THEN
        BEGIN
        (* all indexed output columns are in sequence *)
        out_invseqlen := 0;
        FOR _iz := 1 TO _ix DO
            BEGIN
            out_invseqlen := out_invseqlen +
                  ref_indexdef.icolstack[ _iz ].elen_var;
            END;
        (*ENDFOR*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a720decide_L2_range(
            VAR acv          : tak_all_command_glob;
            VAR sparr        : tak_syspointerarr;
            VAR access_info  : tak70_strategy_record;
            VAR gg_strategy  : tgg07_StrategyInfo;
            VAR StratInfo_len: tsp00_Int2;
            VAR eval_info    : tak71_page_eval_rec;
            L1_pageIO        : tsp00_Int4;
            VAR L1_stratvalue: tsp00_Longreal;
            VAR key_range    : tgg07_StrKeyInRange);
 
VAR
      _L2range_strat  : tak70_one_strat;
      _L1_strat       : tak70_one_strat;
      _eval_rec       : t_key_eval_rec;
      _decide_strat1  : boolean;
 
BEGIN
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          '>>A720DECIDE_L2_RANGE>>       ' );
    END;
(*ENDIF*) 
_L2range_strat.ostr_strategy        := strat_key_range;
_L2range_strat.ostr_wholeIO_pages   := IS_UNDEFINED_GG07;
_L2range_strat.ostr_readIO_pages    := IS_UNDEFINED_GG07;
_L2range_strat.ostr_readIO_primpages:= IS_UNDEFINED_GG07;
_L2range_strat.ostr_readIO_rows     := IS_UNDEFINED_GG07;
_L2range_strat.ostr_key_in_range    := key_range;
IF  ( gg_strategy.str_key_order_support in [ kos_asc, kos_desc ])
THEN
    BEGIN
    IF  ( gg_strategy.str_key_order_support = kos_asc )
    THEN
        _L2range_strat.ostr_key_in_range.
              skir_strat_props := [ ksp_order_support ]
    ELSE
        _L2range_strat.ostr_key_in_range.
              skir_strat_props := [ ksp_order_support, ksp_order_support_reverse ];
    (*ENDIF*) 
    END
ELSE
    _L2range_strat.ostr_key_in_range.skir_strat_props   := [];
(*ENDIF*) 
;
_eval_rec := a720_strat_eval_rec;
IF  ( acv.a_returncode = 0 ) AND
    (( _L2range_strat.ostr_key_in_range.skir_keystart[ 0 ] > 0 ) OR
    (  _L2range_strat.ostr_key_in_range.skir_keystop [ 0 ] > 0 ))
THEN
    BEGIN
    (* there is key access path *)
    ak720keyeval( acv, access_info,
          _L2range_strat.ostr_key_in_range.skir_keystart,
          _L2range_strat.ostr_key_in_range.skir_keystop,
          _eval_rec, access_info.srec_config,
          _L2range_strat.ostr_key_in_range.skir_strat_props );
    END
ELSE
    BEGIN
    _eval_rec.ker_strat_range.er_read_pages := access_info.srec_primpages;
    IF  ( cs_count_records in access_info.srec_config.cfg_switches )
    THEN
        _eval_rec.ker_strat_range.er_read_primrows :=
              access_info.srec_primrows;
    (*ENDIF*) 
    END;
(*ENDIF*) 
&ifdef trace
t01int4( ak_strat, 'prim pages  ', access_info.srec_primpages );
t01real( ak_strat, 'KEY value   ', _eval_rec.ker_strat_range.er_strat_value, 3 );
&endif
(* if allowed try switching to fetch strategy *)
a71check_fetch_optimization( acv, access_info.srec_config,
      access_info.srec_query_prop, gg_strategy,
      _L2range_strat.ostr_strategy, _L2range_strat.ostr_raw );
;
a71calculate_pageIO( acv, sparr, access_info,
      _L2range_strat,
      _eval_rec.ker_strat_range,
      _eval_rec.ker_strat_range.er_read_pages,
      _eval_rec.ker_strat_range.er_strat_value,
      IS_UNDEFINED_GG07 (* index_pagesize *),
      gg_strategy.str_rec_len );
;
IF  ( cs_count_records in access_info.srec_config.cfg_switches )
THEN
    BEGIN
    a71decide_min_rows( acv, access_info,
          _L2range_strat.ostr_readIO_primpages, _L2range_strat.ostr_readIO_rows );
    END;
(*ENDIF*) 
;
&ifdef trace
t01int4( ak_strat, 'L1 page IO  ', L1_pageIO );
t01int4( ak_strat, 'L2 page IO  ', _L2range_strat.ostr_wholeIO_pages );
&endif
(* build L1 strat *)
_L1_strat.ostr_filler1          := ' ';
_L1_strat.ostr_filler2          := 0;
_L1_strat.ostr_strategy         := gg_strategy.str_strategy;
_L1_strat.ostr_raw              := gg_strategy.str_raw;
_L1_strat.ostr_wholeIO_pages    := L1_pageIO;
_L1_strat.ostr_readIO_pages     := IS_UNDEFINED_GG07;
_L1_strat.ostr_readIO_primpages := IS_UNDEFINED_GG07;
_L1_strat.ostr_readIO_rows      := IS_UNDEFINED_GG07;
_L1_strat.ostr_strat_value      := L1_stratvalue;
;
IF  ( NOT ( cs_L2_strategy in access_info.srec_config.cfg_switches ))
THEN
    BEGIN
    ak720choose_strat( access_info.srec_config,
          _L1_strat, _L2range_strat, _decide_strat1 );
    END
ELSE
    _decide_strat1     := false;
(*ENDIF*) 
acv.a_sample_pages := access_info.srec_primpages;
;
IF  ( NOT _decide_strat1 )
THEN
    BEGIN
    (* =================================== *)
    (* decision : use one key range        *)
    (*            defined by several strats*)
    (* =================================== *)
&   ifdef TRACE
    t01name( ak_strat, 'use one key range ' );
&   endif
    gg_strategy.str_strategy     := _L2range_strat.ostr_strategy;
    gg_strategy.str_key_in_range := _L2range_strat.ostr_key_in_range;
    StratInfo_len := STRATEGY_START_MXGG07 +
          sizeof( gg_strategy.str_key_in_range );
    eval_info.pev_wholeIO_pages     := _L2range_strat.ostr_wholeIO_pages;
    eval_info.pev_readIO_pages := _L2range_strat.ostr_readIO_pages;
    eval_info.pev_readIO_rows  := _L2range_strat.ostr_readIO_rows;
    eval_info.pev_readIO_rows_min   := access_info.srec_readIO_rows_min;
    ;
&   ifdef TRACE
    t01name( ak_strat, 'no several strats ' );
    t01name( ak_strat, 'ONE KEY RANGE     ' );
&   endif
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        g041c30_to_trace( acv.a_transinf.tri_trans,
              'use enclosing key range       ' );
        END;
    (*ENDIF*) 
    END
ELSE
    BEGIN
    (* =================================== *)
    (* decision : use Level1 strategy      *)
    (* =================================== *)
    (* nothing to do, gg_strategy already contains L1-strategy *)
&   ifdef TRACE
    t01name( ak_strat, 'use Level1 strat  ' );
    t01strat_enum( ak_strat, 'strategy is ', gg_strategy.str_strategy );
&   endif
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        g041c30_to_trace( acv.a_transinf.tri_trans,
              'use Level1 strategy           ' );
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a720glob_init_eval_stat;
 
BEGIN
WITH a720_strat_eval_rec DO
    BEGIN
    ker_strat_range.er_strat_value   := 1;
    ker_strat_range.er_read_pages    := 0;
    ker_strat_range.er_read_primrows     := IS_UNDEFINED_GG07;
    ker_subq_strat    := false;
    ker_strat_IN_SUBQ.er_strat_value := 1;
    ker_strat_IN_SUBQ.er_read_pages  := 0;
    ker_strat_IN_SUBQ.er_read_primrows   := IS_UNDEFINED_GG07;
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720get_file_samples(
            VAR acv          : tak_all_command_glob;
            VAR sparr        : tak_syspointerarr;
            VAR file_id      : tgg00_FileId;
            VAR page_count   : tsp00_Int4;
            VAR row_count    : tsp00_Int4;
            VAR access_info  : tak70_strategy_record);
 
VAR
      _all_page_cnt : tsp00_Int4;
      _startkey     : tgg00_Lkey;
      _stopkey      : tgg00_Lkey;
      _e            : tgg00_BasisError;
      _count_records: boolean;
 
BEGIN
IF  ( g04inv_tfn (file_id.fileTfn_gg00) )
THEN
    (* use value from primary table *)
    _count_records := false
ELSE
    _count_records :=
          ( cs_count_records in access_info.srec_config.cfg_switches ) OR
          (* needed for ak71recalculate_eval() *)
          ( qp_ROWNO_limit in access_info.srec_query_prop.qps_switches );
(*ENDIF*) 
IF  ((( file_id.fileTfn_gg00 = tfnTemp_egg00 ) AND
    ( file_id.fileTfnTemp_gg00 <> ttfnTempTable_egg00 ))
    OR
    ( qp_archive_access in access_info.srec_query_prop.qps_switches ))
THEN
    BEGIN
&   ifdef trace
    t01name( ak_strat, 'temp res. OR arch ' );
&   endif
    page_count := cak_initpages;
    row_count  := cak_initrows;
    END
ELSE
    BEGIN
    _startkey.len := 0;
    _stopkey.len  := MAX_KEYLEN_GG00;
    _stopkey.k    := b01fullkey;
    a06eval_page_count( acv, file_id, _startkey, _stopkey,
          c_sample, _count_records, page_count, _all_page_cnt, row_count, _e );
    IF  ( page_count = 0 )
    THEN
        page_count := 1;
    (*ENDIF*) 
    IF  (( _count_records AND ( row_count < 0 ) ) OR
        NOT _count_records )
    THEN
        row_count := a28primrows( acv, sparr.pbasep^.sbase );
    (*ENDIF*) 
    IF  ( _e <> e_ok )
    THEN
        BEGIN
        IF  ( (_e = e_file_not_found)  OR (_e = e_inv_not_found) )
        THEN
            a07_b_put_error( acv, e_old_fileversion, 1 )
        ELSE
            a07_b_put_error( acv, _e, 1 );
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
&ifdef trace
IF  ( g04inv_tfn (file_id.fileTfn_gg00) )
THEN
    t01int4( ak_strat, 'smpl invpage', page_count )
ELSE
    t01int4( ak_strat, 'smpl primpag', page_count );
(*ENDIF*) 
IF  ( _count_records )
THEN
    t01int4( ak_strat, 'smpl primrow', row_count );
&endif
(*ENDIF*) 
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    IF  ( g04inv_tfn (file_id.fileTfn_gg00) )
    THEN
        g041int4_to_trace(acv.a_transinf.tri_trans,
              'sample invpages   ', page_count )
    ELSE
        g041int4_to_trace(acv.a_transinf.tri_trans,
              'sample primpages  ', page_count );
    (*ENDIF*) 
    IF  ( _count_records )
    THEN
        g041int4_to_trace(acv.a_transinf.tri_trans,
              'sample primrows   ', row_count );
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720build_key_range_strat(
            VAR acv          : tak_all_command_glob;
            VAR sparr        : tak_syspointerarr;
            VAR access_info  : tak70_strategy_record;
            VAR gg_strategy  : tgg07_StrategyInfo; (*const*)
            VAR eval_rec     : t_key_eval_rec;
            VAR key_strat     : tak70_one_strat);
 
VAR
      _i  : tsp00_Int2;
 
BEGIN
(* build key range strat *)
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          'AK720BUILD_KEY_RANGE_STRAT    ' );
    END;
(*ENDIF*) 
key_strat.ostr_strategy                        := strat_key_range;
key_strat.ostr_key_in_range.skir_IN_SUBQ_stpos := IS_UNDEFINED_GG07;
key_strat.ostr_key_in_range.skir_inelemcnt     := IS_UNDEFINED_GG07;
;
FOR _i := 0 TO MAX_COLPOSARR_IDX_GG07 DO
    IF  ( _i < access_info.srec_keyaccess.ka_startcnt )
    THEN
        key_strat.ostr_key_in_range.skir_keystart[ _i ] :=
              access_info.srec_keyaccess.ka_startfields[ _i ]
    ELSE
        key_strat.ostr_key_in_range.skir_keystart[ _i ] := 0;
    (*ENDIF*) 
(*ENDFOR*) 
FOR _i := 0 TO MAX_COLPOSARR_IDX_GG07 DO
    IF  ( _i < access_info.srec_keyaccess.ka_stopcnt )
    THEN
        key_strat.ostr_key_in_range.skir_keystop[ _i ] :=
              access_info.srec_keyaccess.ka_stopfields[ _i ]
    ELSE
        key_strat.ostr_key_in_range.skir_keystop[ _i ] := 0;
    (*ENDIF*) 
(*ENDFOR*) 
;
(* if allowed try switching to fetch key_strat *)
a71check_fetch_optimization( acv, access_info.srec_config,
      access_info.srec_query_prop, gg_strategy,
      key_strat.ostr_strategy, key_strat.ostr_raw );
;
(* calculate IO costs *)
(* primary page + page cost for ordering + build costs *)
a71calculate_pageIO( acv, sparr, access_info,
      key_strat,
      eval_rec.ker_strat_range,
      eval_rec.ker_strat_range.er_read_pages,
      eval_rec.ker_strat_range.er_strat_value,
      IS_UNDEFINED_GG07 (* index_pagesize *),
      gg_strategy.str_rec_len );
;
IF  ( access_info.srec_L1_strategy ) AND
    ( cs_count_records in access_info.srec_config.cfg_switches )
THEN
    BEGIN
    a71decide_min_rows( acv, access_info,
          key_strat.ostr_readIO_primpages, key_strat.ostr_readIO_rows );
    END;
(*ENDIF*) 
;
&ifdef trace
a725output_one_strat( ak_strat, key_strat );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    a727trace_one_strat( acv.a_transinf.tri_trans,
          'KEY_RANGE_STRAT   ', key_strat );
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720build_key_INSUBQ_strat(
            VAR acv          : tak_all_command_glob;
            VAR sparr        : tak_syspointerarr;
            VAR access_info  : tak70_strategy_record;
            VAR gg_strategy  : tgg07_StrategyInfo; (*const*)
            VAR eval_rec     : t_key_eval_rec;
            VAR key_insubq     : tak70_one_strat);
 
VAR
      _i  : tsp00_Int2;
 
BEGIN
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          'AK720BUILD_KEY_INSUBQ_STRAT   ' );
    END;
(*ENDIF*) 
;
(* MIN/MAX access only make sense with range strategy *)
key_insubq.ostr_key_in_range.skir_strat_props :=
      key_insubq.ostr_key_in_range.skir_strat_props -
      [ ksp_aggr_MIN_opt, ksp_aggr_MAX_opt ];
IF  ( sp_SUBQ_usage in access_info.srec_keyaccess.ka_sequence_props )
THEN
    BEGIN
    key_insubq.ostr_strategy := strat_key_subq;
    eval_rec.ker_subq_strat := true;
    key_insubq.ostr_key_in_range.skir_IN_SUBQ_stpos :=
          access_info.srec_keyaccess.
          ka_startfields[ access_info.srec_keyaccess.ka_SUBQ_idx ];
    END
ELSE
    BEGIN
    key_insubq.ostr_strategy                        := strat_key_in;
    key_insubq.ostr_key_in_range.skir_IN_SUBQ_stpos :=
          access_info.srec_keyaccess.ka_infield.in_stpos;
    key_insubq.ostr_key_in_range.skir_inelemcnt     :=
          access_info.srec_keyaccess.ka_infield.in_elemcnt;
    END;
(*ENDIF*) 
FOR _i := 0 TO MAX_COLPOSARR_IDX_GG07 DO
    IF  ( _i < access_info.srec_keyaccess.ka_startcnt )
    THEN
        key_insubq.ostr_key_in_range.skir_keystart[ _i ] :=
              access_info.srec_keyaccess.ka_startfields[ _i ]
    ELSE
        key_insubq.ostr_key_in_range.skir_keystart[ _i ] := 0;
    (*ENDIF*) 
(*ENDFOR*) 
FOR _i := 0 TO MAX_COLPOSARR_IDX_GG07 DO
    IF  ( _i < access_info.srec_keyaccess.ka_stopcnt )
    THEN
        key_insubq.ostr_key_in_range.skir_keystop[ _i ] :=
              access_info.srec_keyaccess.ka_stopfields[ _i ]
    ELSE
        key_insubq.ostr_key_in_range.skir_keystop[ _i ] := 0;
    (*ENDIF*) 
(*ENDFOR*) 
;
(* if allowed try switching to fetch key_insubq *)
a71check_fetch_optimization( acv, access_info.srec_config,
      access_info.srec_query_prop, gg_strategy,
      key_insubq.ostr_strategy, key_insubq.ostr_raw );
;
(* calculate IO costs *)
(* primary page + page cost for ordering + build costs *)
a71calculate_pageIO( acv, sparr, access_info,
      key_insubq,
      eval_rec.ker_strat_IN_SUBQ,
      eval_rec.ker_strat_IN_SUBQ.er_read_pages,
      eval_rec.ker_strat_IN_SUBQ.er_strat_value,
      IS_UNDEFINED_GG07 (* index_pagesize *),
      gg_strategy.str_rec_len );
;
IF  ( access_info.srec_L1_strategy ) AND
    ( cs_count_records in access_info.srec_config.cfg_switches )
THEN
    BEGIN
    a71decide_min_rows( acv, access_info,
          key_insubq.ostr_readIO_primpages, key_insubq.ostr_readIO_rows );
    END;
(*ENDIF*) 
;
&ifdef trace
a725output_one_strat( ak_strat, key_insubq );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    a727trace_one_strat( acv.a_transinf.tri_trans,
          'KEY_INSUBQ_STRAT  ', key_insubq );
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720build_key_equal_strat(
            VAR acv          : tak_all_command_glob;
            VAR access_info  : tak70_strategy_record;
            VAR gg_strategy  : tgg07_StrategyInfo; (*const*)
            VAR key_strat    : tak70_one_strat);
 
VAR
      _i                : tsp00_Int2;
 
BEGIN
(* build key equal strat *)
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          'AK720BUILD_KEY_EQUAL_STRAT    ' );
    END;
(*ENDIF*) 
access_info.srec_query_prop.qps_switches :=
      access_info.srec_query_prop.qps_switches - [ qp_missing_value ];
key_strat.ostr_strategy                        := strat_key_equal;
key_strat.ostr_key_in_range.skir_IN_SUBQ_stpos := IS_UNDEFINED_GG07;
key_strat.ostr_key_in_range.skir_inelemcnt     := IS_UNDEFINED_GG07;
key_strat.ostr_key_in_range.skir_strat_props   := [ ksp_exact_match ];
;
FOR _i := 0 TO MAX_COLPOSARR_IDX_GG07 DO
    IF  ( _i < access_info.srec_keyaccess.ka_startcnt )
    THEN
        key_strat.ostr_key_in_range.skir_keystart[ _i ] :=
              access_info.srec_keyaccess.ka_startfields[ _i ]
    ELSE
        key_strat.ostr_key_in_range.skir_keystart[ _i ] := 0;
    (*ENDIF*) 
(*ENDFOR*) 
FOR _i := 0 TO MAX_COLPOSARR_IDX_GG07 DO
    IF  ( _i < access_info.srec_keyaccess.ka_stopcnt )
    THEN
        key_strat.ostr_key_in_range.skir_keystop[ _i ] :=
              access_info.srec_keyaccess.ka_stopfields[ _i ]
    ELSE
        key_strat.ostr_key_in_range.skir_keystop[ _i ] := 0;
    (*ENDIF*) 
(*ENDFOR*) 
;
(* if allowed try switching to fetch key_strat *)
a71check_fetch_optimization( acv, access_info.srec_config,
      access_info.srec_query_prop, gg_strategy,
      key_strat.ostr_strategy, key_strat.ostr_raw );
;
IF  ( gg_strategy.str_distinc <> no_distinct )
THEN
    key_strat.ostr_key_in_range.skir_strat_props :=
          key_strat.ostr_key_in_range.skir_strat_props + [ ksp_auto_distinct ];
(*ENDIF*) 
;
(* calculate IO costs *)
(* primary page + page cost for ordering + build costs *)
(*
      key_strat.ostr_strat_value   := 1 / a28prim_pages( acv, sparr.pbasep^.sbase );
      key_strat.ostr_readIO_rows   := 1;
      IF  ( key_strat.ostr_strategy = strat_key_equal )
      THEN
      BEGIN
      (/* cost KEY BUILD = read P, write E, read E (fetch) */)
      key_strat.ostr_wholeIO_pages    := 3;
      key_strat.ostr_readIO_pages     := 2;
      key_strat.ostr_readIO_primpages := 2;
      END
      ELSE
      BEGIN
      (/* cost KEY FETCH = read P (fetch) */)
      key_strat.ostr_wholeIO_pages    := 1;
      key_strat.ostr_readIO_pages     := 1;
      key_strat.ostr_readIO_primpages := 1;
      END;
      *)
(* fake values for key-equal-strategy *)
key_strat.ostr_strat_value      := 0;
key_strat.ostr_wholeIO_pages    := 1;
key_strat.ostr_readIO_pages     := 1;
key_strat.ostr_readIO_primpages := 1;
key_strat.ostr_readIO_rows      := 1;
;
IF  ( access_info.srec_L1_strategy ) AND
    ( cs_count_records in access_info.srec_config.cfg_switches )
THEN
    BEGIN
    access_info.srec_readIO_rows_min  := 1;
    access_info.srec_readIO_pages_min := 1;
    END;
(*ENDIF*) 
;
&ifdef trace
a725output_one_strat( ak_strat, key_strat );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    a727trace_one_strat( acv.a_transinf.tri_trans,
          'KEY_EQUAL_STRAT   ', key_strat );
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720build_inv_strat(
            VAR acv          : tak_all_command_glob;
            VAR sparr        : tak_syspointerarr;
            VAR access_info  : tak70_strategy_record;
            VAR gg_strategy  : tgg07_StrategyInfo; (*const*)
            VAR key_eval_rec : t_key_eval_rec;
            VAR strategy     : tak70_one_strat;
            index_pagesize   : tsp00_Int4;
            VAR eval_values  : tak70_eval_rec);
 
VAR
      _primkeylen     : tsp00_Int4;
 
BEGIN
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace( acv.a_transinf.tri_trans,
          'AK720BUILD_INV_STRAT          ' );
    a727trace_strategy_text( acv.a_transinf.tri_trans,
          'strat is    ',  strategy.ostr_strategy );
    END;
(*ENDIF*) 
IF  ( strategy.ostr_strategy in [ strat_inv_in, strat_inv_subq ] )
THEN
    BEGIN
    (* MIN/MAX access only make sense with range strategy *)
    strategy.ostr_inv_in_range.siir_strat_props :=
          strategy.ostr_inv_in_range.siir_strat_props -
          [ isp_aggr_MIN_opt, isp_aggr_MAX_opt,
          isp_aggr_MIN_opt_reverse, isp_aggr_MAX_opt_reverse,
          isp_aggr_key_MIN_opt, isp_aggr_key_MAX_opt ];
    END;
(*ENDIF*) 
IF  (( cs_enable_merge in access_info.srec_config.cfg_switches ) OR
    ( eval_values.er_read_pages <= g01max_merge ))
    AND
    (* today DITINCT OPTIM only possible by index access *)
    (* merge list constains only primary keys            *)
    ( NOT a71is_duplicate_avoidance( gg_strategy,
    strategy.ostr_strategy, strategy.ostr_raw, access_info.srec_query_prop ))
THEN
    BEGIN
    IF  ( isp_inv_only in strategy.ostr_inv_in_range.siir_strat_props )
        AND
        ( gg_strategy.str_key_order_support in [ kos_asc, kos_desc ] )
        AND
        ( NOT ( isp_order_support in
        strategy.ostr_inv_in_range.siir_strat_props ))
    THEN
        (* if we have ORDER BY KEY and INDEX ONLY is possible *)
        (* we have 2 possibilities:                           *)
        (* a. INDEX ONLY with build result set                *)
        (* b. merge of keylists and sorted fetch              *)
        (* the decision is given by ratio of out_reclen and   *)
        (* primkey len                                        *)
        BEGIN
        _primkeylen :=  sparr.pbasep^.sbase.
              bcolumn[ sparr.pbasep^.sbase.blastkeyind ]^.ccolstack.epos +
              sparr.pbasep^.sbase.bcolumn[ sparr.pbasep^.sbase.blastkeyind ]^.
              cinoutlen - 1;
        IF  ( _primkeylen <= 0 )
        THEN
            _primkeylen := gg_strategy.str_rec_len;
&       ifdef trace
        (*ENDIF*) 
        t01int4( ak_strat, '_primkeylen ', _primkeylen );
        t01int4( ak_strat, 'output len  ', gg_strategy.str_rec_len );
&       endif
        IF  (( gg_strategy.str_rec_len / _primkeylen ) > 2.0 )
        THEN
            BEGIN
            strategy.ostr_inv_in_range.siir_strat_props :=
                  strategy.ostr_inv_in_range.siir_strat_props +
                  [ isp_listmerge_allowed ];
            strategy.ostr_inv_in_range.siir_strat_props :=
                  strategy.ostr_inv_in_range.siir_strat_props -
                  [ isp_inv_only ];
&           ifdef trace
            t01sname( ak_strat, 'allow MERGE ' );
            t01name( ak_strat,  'disable INV ONLY  ' );
&           endif
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        strategy.ostr_inv_in_range.siir_strat_props :=
              strategy.ostr_inv_in_range.siir_strat_props +
              [ isp_listmerge_allowed ];
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
IF  (( isp_aggr_MIN_opt in strategy.ostr_inv_in_range.siir_strat_props ) OR
    ( isp_aggr_MAX_opt in strategy.ostr_inv_in_range.siir_strat_props ))
THEN
    strategy.ostr_inv_in_range.siir_strat_props :=
          strategy.ostr_inv_in_range.siir_strat_props -
          [ isp_listmerge_allowed ];
(*ENDIF*) 
;
IF  (( NOT ( strategy.ostr_strategy in [ strat_inv_in, strat_inv_subq ])) AND
    ( isp_inv_only in strategy.ostr_inv_in_range.siir_strat_props ) AND
    ( qp_aggr_optim_poss in access_info.srec_query_prop.qps_switches ) AND
    a01aggr_optim AND
    ( isp_pure_inv_output in strategy.ostr_inv_in_range.siir_strat_props ))
THEN
    BEGIN
    (* aggregation optimization only possible with index columns *)
    strategy.ostr_inv_in_range.siir_strat_props :=
          strategy.ostr_inv_in_range.siir_strat_props +
          [ isp_aggr_optim ];
    END;
(*ENDIF*) 
;
(* if allowed try switching to fetch strategy *)
a71check_fetch_optimization( acv, access_info.srec_config,
      access_info.srec_query_prop, gg_strategy,
      strategy.ostr_strategy, strategy.ostr_raw );
;
(* calculate IO costs *)
(* index pages + primary page + page cost for ordering + build costs *)
a71calculate_pageIO( acv, sparr, access_info,
      strategy,
      eval_values,
      key_eval_rec.ker_strat_range.er_read_pages  (* we don't use SUBQ on key ! *),
      key_eval_rec.ker_strat_range.er_strat_value (* we don't use SUBQ on key ! *),
      index_pagesize,
      gg_strategy.str_rec_len );
;
IF  ( access_info.srec_L1_strategy ) AND
    ( cs_count_records in access_info.srec_config.cfg_switches )
THEN
    BEGIN
    a71decide_min_rows( acv, access_info,
          strategy.ostr_readIO_primpages, strategy.ostr_readIO_rows );
    END;
(*ENDIF*) 
;
&ifdef trace
a725output_invstrat( ak_strat, 'act invstrat', strategy.ostr_inv_in_range );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    a727trace_invstrat( acv.a_transinf.tri_trans,
          'INDEX data  ', strategy.ostr_inv_in_range, false );
    a727trace_strat_costs( acv.a_transinf.tri_trans, strategy );
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720choose_strat(
            VAR config    : tak00_access_configuration;
            VAR strat1    : tak70_one_strat;
            VAR strat2    : tak70_one_strat;
            VAR use_strat1: boolean);
 
VAR
      _strat_decided  : boolean;
      _strat1_minmax  : boolean;
      _strat2_minmax  : boolean;
 
BEGIN
(* decide for strat1 if strat2 is strat_undecided and vice versa *)
(* decide for strat1 if strat2 has same costs and strat value    *)
&ifdef trace
a81debug_access_config( ak_strat, config );
t01strat_enum( ak_strat, 'strat1 is   ',    strat1.ostr_strategy );
IF  ( strat1.ostr_strategy <> strat_undecided )
THEN
    BEGIN
    IF  ( strat1.ostr_strategy in a70glob_key_strats )
    THEN
        a725output_keystrat( ak_strat, 'strat1 data ', strat1.ostr_key_in_range )
    ELSE
        a725output_invstrat( ak_strat, 'strat1 data ', strat2.ostr_inv_in_range );
    (*ENDIF*) 
    t01int4( ak_strat, 'whole  pages', strat1.ostr_wholeIO_pages );
    t01int4( ak_strat, 'read   pages', strat1.ostr_readIO_pages );
    t01int4( ak_strat, 'read  ppages', strat1.ostr_readIO_primpages );
    t01int4( ak_strat, 'read   rows ', strat1.ostr_readIO_rows );
    t01real( ak_strat, 'strat  value', strat1.ostr_strat_value, 6 );
    t01name( ak_strat,  '------------------' );
    END;
(*ENDIF*) 
t01strat_enum( ak_strat, 'strat2 is   ',    strat2.ostr_strategy );
IF  ( strat2.ostr_strategy <> strat_undecided )
THEN
    BEGIN
    IF  ( strat2.ostr_strategy in a70glob_key_strats )
    THEN
        a725output_keystrat( ak_strat, 'strat2 data ', strat2.ostr_key_in_range )
    ELSE
        a725output_invstrat( ak_strat, 'strat2 data ', strat2.ostr_inv_in_range );
    (*ENDIF*) 
    t01int4( ak_strat, 'whole  pages', strat2.ostr_wholeIO_pages );
    t01int4( ak_strat, 'read   pages', strat2.ostr_readIO_pages );
    t01int4( ak_strat, 'read  ppages', strat2.ostr_readIO_primpages );
    t01int4( ak_strat, 'read   rows ', strat2.ostr_readIO_rows );
    t01real( ak_strat, 'strat  value', strat2.ostr_strat_value, 6 );
    t01name( ak_strat,  '------------------' );
    END;
&endif
(*ENDIF*) 
IF  (( strat1.ostr_strategy <> strat_undecided ) AND
    ( strat2.ostr_strategy <> strat_undecided ))
THEN
    BEGIN
    _strat_decided := false;
    (* cs_keyaccess/cs_indexaccess are mutually exclusive *)
    IF  ( cs_keyaccess in config.cfg_switches )
    THEN
        BEGIN
        IF  ( strat1.ostr_strategy in a70glob_key_strats ) AND
            ( strat2.ostr_strategy in a70glob_inv_strats )
        THEN
            BEGIN
&           ifdef trace
            t01sname( ak_strat, 'key strat1  ' );
&           endif
            use_strat1      := true;
            _strat_decided  := true;
            END
        ELSE
            BEGIN
            IF  ( strat1.ostr_strategy in a70glob_inv_strats ) AND
                ( strat2.ostr_strategy in a70glob_key_strats )
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_strat, 'key strat2  ' );
&               endif
                use_strat1      := false;
                _strat_decided  := true;
                END
            ELSE
                BEGIN
                (* both strats are key/inv strats, decide as usual *)
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    ;
    IF  ( cs_indexaccess in config.cfg_switches )
    THEN
        BEGIN
        IF  ( strat1.ostr_strategy in a70glob_key_strats ) AND
            ( strat2.ostr_strategy in a70glob_inv_strats )
        THEN
            BEGIN
&           ifdef trace
            t01sname( ak_strat, 'inv strat2  ' );
&           endif
            use_strat1      := false;
            _strat_decided  := true;
            END
        ELSE
            BEGIN
            IF  ( strat1.ostr_strategy in a70glob_inv_strats ) AND
                ( strat2.ostr_strategy in a70glob_key_strats )
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_strat, 'inv strat1  ' );
&               endif
                use_strat1      := true;
                _strat_decided  := true;
                END
            ELSE
                BEGIN
                (* both strats are key/inv strats, decide as usual *)
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    ;
    IF  ( cs_fetch_result in config.cfg_switches )
    THEN
        BEGIN
        IF  (( strat1.ostr_strategy in a70glob_fetch_strats ) AND
            ( strat2.ostr_strategy in a70glob_build_strats ))
        THEN
            BEGIN
&           ifdef trace
            t01sname( ak_strat, 'fetch strat1' );
&           endif
            use_strat1      := true;
            _strat_decided  := true;
            END
        ELSE
            BEGIN
            IF  (( strat1.ostr_strategy in a70glob_build_strats) AND
                ( strat2.ostr_strategy in a70glob_fetch_strats ))
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_strat, 'fetch strat2' );
&               endif
                use_strat1      := false;
                _strat_decided  := true;
                END
            ELSE
                BEGIN
                (* both strats are build/fetch strats, decide as usual *)
                END;
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    ;
    IF  ( cs_operator_join in config.cfg_switches )
    THEN
        BEGIN
        IF  (( strat1.ostr_strategy in a70glob_accessop_known_strats ) AND
            ( strat2.ostr_strategy in a70glob_accessop_uknwn_strats ))
        THEN
            BEGIN
&           ifdef trace
            t01sname( ak_strat, 'opstr strat1' );
&           endif
            use_strat1      := true;
            _strat_decided  := true;
            END
        ELSE
            BEGIN
            IF  (( strat1.ostr_strategy in a70glob_accessop_uknwn_strats) AND
                ( strat2.ostr_strategy in a70glob_accessop_known_strats ))
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_strat, 'opstr strat2' );
&               endif
                use_strat1      := false;
                _strat_decided  := true;
                END
            ELSE
                BEGIN
                (* both strats are build/fetch strats, decide as usual *)
                END;
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    ;
    IF  ( NOT _strat_decided )
    THEN
        IF  ( cs_IN_strategy in config.cfg_switches )
        THEN
            BEGIN
            IF  ( strat1.ostr_strategy in a70glob_in_strats ) AND
                NOT ( strat2.ostr_strategy in a70glob_in_strats )
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_strat, 'IN strat1   ' );
&               endif
                use_strat1      := true;
                _strat_decided  := true;
                END
            ELSE
                IF  NOT ( strat1.ostr_strategy in a70glob_in_strats ) AND
                    ( strat2.ostr_strategy in a70glob_in_strats )
                THEN
                    BEGIN
&                   ifdef trace
                    t01sname( ak_strat, 'IN strat2   ' );
&                   endif
                    use_strat1      := false;
                    _strat_decided  := true;
                    END
                ELSE
                    BEGIN
                    (* both strats are IN/nonIN strats, decide as usual *)
                    (* decide for costs as usual *)
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            END
        ELSE
            IF  ( cs_SUBQ_strategy in config.cfg_switches )
            THEN
                BEGIN
                IF  ( strat1.ostr_strategy in a70glob_subq_strats ) AND
                    NOT ( strat2.ostr_strategy in a70glob_subq_strats )
                THEN
                    BEGIN
&                   ifdef trace
                    t01sname( ak_strat, 'SUBQ strat1 ' );
&                   endif
                    use_strat1      := true;
                    _strat_decided  := true;
                    END
                ELSE
                    IF  NOT ( strat1.ostr_strategy in a70glob_subq_strats ) AND
                        ( strat2.ostr_strategy in a70glob_subq_strats )
                    THEN
                        BEGIN
&                       ifdef trace
                        t01sname( ak_strat, 'SUBQ strat2 ' );
&                       endif
                        use_strat1      := false;
                        _strat_decided  := true;
                        END
                    ELSE
                        BEGIN
                        (* both strats are SUBQ/nonSUBQ strats, decide as usual *)
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    ;
    (* decide for costs *)
    IF  ( NOT _strat_decided )
    THEN
        IF  ( strat1.ostr_wholeIO_pages = strat2.ostr_wholeIO_pages )
        THEN
            BEGIN
&           ifdef trace
            t01name( ak_strat, 'strat1 ~= strat2  ' );
&           endif
            _strat1_minmax := (( strat1.ostr_strategy in a70glob_key_strats ) AND
                  (( ksp_aggr_MIN_opt in strat1.ostr_key_in_range.skir_strat_props ) OR
                  ( ksp_aggr_MAX_opt in strat1.ostr_key_in_range.skir_strat_props )))
                  OR
                  (( strat1.ostr_strategy in a70glob_inv_strats ) AND
                  (( isp_aggr_MIN_opt in strat1.ostr_inv_in_range.siir_strat_props ) OR
                  (  isp_aggr_MAX_opt in strat1.ostr_inv_in_range.siir_strat_props ) OR
                  (  isp_aggr_key_MIN_opt in strat1.ostr_inv_in_range.siir_strat_props ) OR
                  (  isp_aggr_key_MAX_opt in strat1.ostr_inv_in_range.siir_strat_props )));
            _strat2_minmax := (( strat2.ostr_strategy in a70glob_key_strats ) AND
                  (( ksp_aggr_MIN_opt in strat2.ostr_key_in_range.skir_strat_props ) OR
                  ( ksp_aggr_MAX_opt in strat2.ostr_key_in_range.skir_strat_props )))
                  OR
                  (( strat2.ostr_strategy in a70glob_inv_strats ) AND
                  (( isp_aggr_MIN_opt in strat2.ostr_inv_in_range.siir_strat_props ) OR
                  (  isp_aggr_MAX_opt in strat2.ostr_inv_in_range.siir_strat_props ) OR
                  (  isp_aggr_key_MIN_opt in strat2.ostr_inv_in_range.siir_strat_props ) OR
                  (  isp_aggr_key_MAX_opt in strat2.ostr_inv_in_range.siir_strat_props )));
            ;
            IF  (( _strat1_minmax OR _strat2_minmax ) AND
                NOT ( _strat1_minmax AND _strat2_minmax ))
                (* _strat1_minmax XOR _strat2_minmax *)
            THEN
                BEGIN
                IF  ( _strat1_minmax )
                THEN
                    BEGIN
&                   ifdef trace
                    t01name( ak_strat, 'strat1 MIN/MAX    ' );
&                   endif
                    use_strat1 := true;
                    END
                ELSE
                    BEGIN
&                   ifdef trace
                    t01name( ak_strat, 'strat2 MIN/MAX    ' );
&                   endif
                    use_strat1 := false;
                    END;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                IF  (( strat1.ostr_strategy in a70glob_key_strats ) AND
                    (  strat2.ostr_strategy in a70glob_key_strats ))
                    OR
                    (( strat1.ostr_strategy in a70glob_inv_strats ) AND
                    (  strat2.ostr_strategy in a70glob_inv_strats ))
                THEN
                    BEGIN
                    IF  ( strat1.ostr_strat_value <= strat2.ostr_strat_value )
                    THEN
                        BEGIN
&                       ifdef trace
                        t01name( ak_strat, 'strat1 cheaper    ' );
&                       endif
                        use_strat1 := true;
                        END
                    ELSE
                        BEGIN
&                       ifdef trace
                        t01name( ak_strat, 'strat2 cheaper    ' );
&                       endif
                        use_strat1 := false;
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  ( strat1.ostr_strategy in a70glob_key_strats )
                    THEN
                        BEGIN
&                       ifdef trace
                        t01name( ak_strat, 'strat1 cheaper    ' );
&                       endif
                        use_strat1 := true;
                        END
                    ELSE
                        BEGIN
&                       ifdef trace
                        t01name( ak_strat, 'strat2 cheaper    ' );
&                       endif
                        use_strat1 := false;
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END
        ELSE
            IF  ( strat1.ostr_wholeIO_pages < strat2.ostr_wholeIO_pages )
            THEN
                BEGIN
&               ifdef trace
                t01name( ak_strat, 'strat1 cheaper    ' );
&               endif
                use_strat1 := true;
                END
            ELSE
                BEGIN
&               ifdef trace
                t01name( ak_strat, 'strat2 cheaper    ' );
&               endif
                use_strat1 := false;
                END;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    END
ELSE
    IF  ( strat1.ostr_strategy = strat_undecided ) AND
        ( strat2.ostr_strategy <> strat_undecided )
    THEN
        use_strat1 := false
    ELSE
        IF  ( strat1.ostr_strategy <> strat_undecided ) AND
            ( strat2.ostr_strategy = strat_undecided )
        THEN
            use_strat1 := true
        ELSE
            (* same strats are undecided *)
            use_strat1 := true;
        (*ENDIF*) 
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720test_keystrat_props (
            VAR acv             : tak_all_command_glob;
            VAR sparr           : tak_syspointerarr;
            VAR access_info     : tak70_strategy_record;
            VAR key_strat       : tak70_one_strat;
            VAR order_fields    : tak00_ord_fields(*const*));
 
VAR
      _ordcol_ptr       : tak00_colinfo_ptr;
      _ix               : tsp00_Int2;
      _key_cnt          : tsp00_Int2;
      _col_index        : tsp00_Int2;
      _found_const_keys : SET OF 1..MAX_COL_PER_TAB_GG00;
      _keyseq_is_ord_seq: boolean;
      _key_proccesed    : boolean;
      _reverse_seq      : boolean;
      _reverse_poss     : boolean;
 
BEGIN
&ifdef trace
t01name( ak_strat, 'ak720test_keystrat' );
&endif
key_strat.ostr_key_in_range.skir_strat_props := [];
IF  ( sp_exact_match in access_info.srec_keyaccess.ka_sequence_props )
THEN
    key_strat.ostr_key_in_range.skir_strat_props :=
          key_strat.ostr_key_in_range.skir_strat_props + [ ksp_exact_match ];
(*ENDIF*) 
IF  ( sp_exact_IN_SUBQ_match in access_info.srec_keyaccess.ka_sequence_props )
THEN
    key_strat.ostr_key_in_range.skir_strat_props :=
          key_strat.ostr_key_in_range.skir_strat_props +
          [ ksp_exact_IN_SUBQ_match ];
(*ENDIF*) 
;
IF  ( qp_check_order_support in access_info.srec_query_prop.qps_switches )
    AND
    ( order_fields.ofield[ 1 ].offno > 0) (* may be 0 in case of user defined function *)
THEN
    (* check ORDER BY via key *)
    BEGIN
&   ifdef trace
    t01name( ak_strat, 'check order supprt' );
&   endif
    _ix      := 1;
    a06extcolno( sparr.pbasep^.sbase,
          order_fields.ofield[ _ix ].offno, _ordcol_ptr );
    _key_cnt := 1;
    _col_index         := sparr.pbasep^.sbase.bfirstcolind;
    _found_const_keys  := [];
    _key_proccesed     := false;
    _keyseq_is_ord_seq :=
          ( ctkey in sparr.pbasep^.sbase.bcolumn[ _col_index ]^.ccolpropset );
    _reverse_poss := a01diag_reverse_fetch;
    _reverse_seq  := false;
    WHILE ( _col_index <> 0 ) AND ( _ix <= order_fields.ocntord ) AND
          ( _keyseq_is_ord_seq ) DO
        BEGIN
&       ifdef trace
        t01p2int4( ak_strat, 'creccolno   ', sparr.pbasep^.sbase.bcolumn[ _col_index ]^.creccolno,
              'order field ', order_fields.ofield[ _ix ].offno );
&       endif
        IF  ( NOT (ctkey in _ordcol_ptr^.ccolpropset ))
        THEN
            BEGIN
&           ifdef trace
            t01sname( ak_strat, 'no key      ' );
&           endif
            _keyseq_is_ord_seq := false;
            END
        ELSE
            BEGIN
            (* if i.key column is constant this is OK *)
            IF  (( NOT _key_proccesed ) AND
                ( access_info.srec_keyaccess.ka_startcnt >= _key_cnt ) AND
                ( access_info.srec_keyaccess.ka_stopcnt   >= _key_cnt ) AND
                ( access_info.srec_keyaccess.ka_startfields[_key_cnt - 1] =
                access_info.srec_keyaccess.ka_stopfields[_key_cnt - 1] ) AND
                (* it isn't a IN condition *)
                ( access_info.srec_keyaccess.ka_infield.in_stpos <>
                access_info.srec_keyaccess.ka_startfields[_key_cnt - 1] ) AND
                (* it isn't a SUBQ condition *)
                ( access_info.srec_keyaccess.ka_SUBQ_idx <> _key_cnt - 1 )
                )
            THEN
                BEGIN
&               ifdef trace
                t01int4( ak_strat, 'KEY is CONST', sparr.pbasep^.sbase.bcolumn[ _col_index ]^.creccolno );
&               endif
                _found_const_keys := _found_const_keys +
                      [ sparr.pbasep^.sbase.bcolumn[ _col_index ]^.creccolno ];
                (* step to next key *)
                IF  ( _key_cnt < sparr.pbasep^.sbase.bkeycolcount )
                THEN
                    BEGIN
                    _col_index  := sparr.pbasep^.sbase.bcolumn[ _col_index ]^.cnextind;
                    _key_cnt := succ( _key_cnt );
                    END
                ELSE
                    _key_proccesed := true;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                IF  ( sparr.pbasep^.sbase.bcolumn[ _col_index ]^.creccolno =
                    order_fields.ofield[ _ix ].offno )
                THEN
                    BEGIN
                    IF  ( NOT ( is_order_asc in order_fields.ofield[ _ix ].ofasc ))
                    THEN
                        BEGIN
                        IF  ( _reverse_poss )
                        THEN
                            _reverse_seq := true
                        ELSE
                            BEGIN
                            _keyseq_is_ord_seq := false;
                            (* ORDER BY with key access impossible *)
&                           ifdef trace
                            t01name( ak_strat, 'wrong sorting     ' );
&                           endif
                            END;
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        _reverse_poss := false;
                        IF  ( _reverse_seq )
                        THEN
                            _keyseq_is_ord_seq := false;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  ( _keyseq_is_ord_seq )
                    THEN
                        BEGIN
&                       ifdef trace
                        t01sname( ak_strat, 'KEY = ORDER ' );
&                       endif
                        (* step to next order field *)
                        _ix := succ( _ix );
                        IF  ( _ix <= order_fields.ocntord )
                        THEN
                            a06extcolno( sparr.pbasep^.sbase,
                                  order_fields.ofield[ _ix ].offno, _ordcol_ptr );
                        (* step to next key *)
                        (*ENDIF*) 
                        IF  ( _key_cnt < sparr.pbasep^.sbase.bkeycolcount )
                        THEN
                            BEGIN
                            _col_index  := sparr.pbasep^.sbase.bcolumn[ _col_index ]^.cnextind;
                            _key_cnt := succ( _key_cnt );
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  ( order_fields.ofield[ _ix ].offno in _found_const_keys )
                    THEN
                        BEGIN
&                       ifdef trace
                        t01name( ak_strat, 'known const field ' );
&                       endif
                        _ix := succ( _ix );
                        IF  ( _ix <= order_fields.ocntord )
                        THEN
                            a06extcolno( sparr.pbasep^.sbase,
                                  order_fields.ofield[ _ix ].offno, _ordcol_ptr );
                        (*ENDIF*) 
                        END
                    ELSE
                        _keyseq_is_ord_seq := false;
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  ( _keyseq_is_ord_seq )
    THEN
        BEGIN
&       ifdef trace
        t01name( ak_strat, 'key order support ' );
&       endif
        key_strat.ostr_key_in_range.skir_strat_props :=
              key_strat.ostr_key_in_range.skir_strat_props +
              [ ksp_order_support ];
        IF  ( _reverse_seq )
        THEN
            BEGIN
            key_strat.ostr_key_in_range.skir_strat_props :=
                  key_strat.ostr_key_in_range.skir_strat_props +
                  [ ksp_order_support_reverse ];
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  ( access_info.srec_L1_strategy ) AND
    ( qp_check_key_MIN_MAX_opt in access_info.srec_query_prop.qps_switches )
THEN
    ak720check_key_minmax_opt( acv, access_info,
          access_info.srec_keyaccess,
          key_strat.ostr_key_in_range );
(*ENDIF*) 
;
IF  ( NOT
    ( access_info.srec_unusable_L1_pred OR access_info.srec_L23_predicates ))
THEN
    BEGIN
    IF  (( sp_first_row_start in access_info.srec_keyaccess.ka_sequence_props )
        AND
        ( access_info.srec_keyaccess.ka_startcnt =
        access_info.srec_L1_pred_cnt ))
    THEN
        key_strat.ostr_key_in_range.skir_strat_props :=
              key_strat.ostr_key_in_range.skir_strat_props +
              [ ksp_first_row_start ];
    (*ENDIF*) 
    IF  (( sp_first_row_stop in access_info.srec_keyaccess.ka_sequence_props )
        AND
        ( access_info.srec_keyaccess.ka_stopcnt =
        access_info.srec_L1_pred_cnt ))
    THEN
        key_strat.ostr_key_in_range.skir_strat_props :=
              key_strat.ostr_key_in_range.skir_strat_props +
              [ ksp_first_row_stop ];
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
IF  ( qp_auto_distinct in access_info.srec_query_prop.qps_switches )
THEN
    key_strat.ostr_key_in_range.skir_strat_props :=
          key_strat.ostr_key_in_range.skir_strat_props + [ ksp_auto_distinct ];
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720check_key_minmax_opt(
            VAR acv          : tak_all_command_glob;
            VAR access_info  : tak70_strategy_record;
            VAR key_access   : tak70_key_access;
            VAR key_strat    : tgg07_StrKeyInRange);
 
VAR
      _stpos         : tsp00_Int2;
      _stop          : tsp00_Int2;
      _field_pos     : tsp00_Int2;
      _recpos        : tsp00_Int2;
      _ix            : tsp00_Int2;
      _iy            : tsp00_Int2;
      _col_in_keyseq : boolean;
      _valid_sequence: boolean;
 
BEGIN
(* we know we have output columns *)
_stpos := acv.a_mblock.mb_qual^.mqual_pos + 1;
_stop  := _stpos +
      acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mqual_pos ].epos - 1;
_col_in_keyseq := true;
_field_pos := 0;
WHILE (( _stpos < _stop ) AND _col_in_keyseq ) DO
    BEGIN
    CASE acv.a_mblock.mb_st^[ _stpos ].etype OF
        st_fixkey, st_varkey :
            BEGIN
            _field_pos := _stpos;
&           ifdef trace
            t01int4( ak_strat, 'field found ', _stpos );
&           endif
            END;
        st_func :
            BEGIN
            IF  ( acv.a_mblock.mb_st^[ _stpos ].eop_func in [ op_f_min, op_f_max ] ) AND
                ( _field_pos <> 0 )
            THEN
                BEGIN
&               ifdef trace
                t01int4( ak_strat, 'funct found ', _stpos );
&               endif
                (* search field in key start/stop sequence *)
                (* in const part (equal sequence) or one col behind *)
                _col_in_keyseq  := false;
                _valid_sequence := true;
                _ix := -1;
                _iy := -1;
                WHILE ( NOT _col_in_keyseq ) AND ( _valid_sequence ) AND
                      (( _ix + 1 < key_access.ka_startcnt ) OR
                      ( _iy + 1 < key_access.ka_stopcnt )) DO
                    BEGIN
                    IF  ( _ix + 1 < key_access.ka_startcnt )
                    THEN
                        _ix := succ( _ix );
                    (*ENDIF*) 
                    IF  ( _iy + 1 < key_access.ka_stopcnt )
                    THEN
                        _iy := succ( _iy );
                    (*ENDIF*) 
                    IF  ( _ix >= 0 ) AND ( _iy >= 0 )
                    THEN
                        BEGIN
                        IF  ( key_access.ka_startfields[ _ix ] =
                            key_access.ka_stopfields[ _iy ] )
                        THEN
                            BEGIN
                            IF  ( acv.a_mblock.mb_st^[ _field_pos ].etype =
                                acv.a_mblock.mb_st^[ key_access.ka_startfields[ _ix ] ].etype )
                                AND
                                ( acv.a_mblock.mb_st^[ _field_pos ].epos =
                                acv.a_mblock.mb_st^[ key_access.ka_startfields[ _ix ] ].epos )
                            THEN
                                _col_in_keyseq := true;
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            IF  (( acv.a_mblock.mb_st^[ _field_pos ].etype =
                                acv.a_mblock.mb_st^[ key_access.ka_startfields[ _ix ] ].etype )
                                AND
                                ( acv.a_mblock.mb_st^[ _field_pos ].epos =
                                acv.a_mblock.mb_st^[ key_access.ka_startfields[ _ix ] ].epos ))
                                OR
                                (( acv.a_mblock.mb_st^[ _field_pos ].etype =
                                acv.a_mblock.mb_st^
                                [ abs(key_access.ka_stopfields[ _iy ]) ].etype )
                                AND
                                ( acv.a_mblock.mb_st^[ _field_pos ].epos =
                                acv.a_mblock.mb_st^
                                [ abs(key_access.ka_stopfields[ _iy ]) ].epos ))
                            THEN
                                _col_in_keyseq := true
                            ELSE
                                _valid_sequence := false;
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        IF  ( _ix >= 0 )
                        THEN
                            BEGIN
                            IF  (( acv.a_mblock.mb_st^[ _field_pos ].etype =
                                acv.a_mblock.mb_st^[ key_access.ka_startfields[ _ix ] ].etype )
                                AND
                                ( acv.a_mblock.mb_st^[ _field_pos ].epos =
                                acv.a_mblock.mb_st^[ key_access.ka_startfields[ _ix ] ].epos ))
                            THEN
                                _col_in_keyseq := true;
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            IF  ( _iy >= 0 )
                            THEN
                                BEGIN
                                IF  (( acv.a_mblock.mb_st^[ _field_pos ].etype =
                                    acv.a_mblock.mb_st^
                                    [ abs(key_access.ka_stopfields[ _iy ]) ].etype )
                                    AND
                                    ( acv.a_mblock.mb_st^[ _field_pos ].epos =
                                    acv.a_mblock.mb_st^
                                    [ abs(key_access.ka_stopfields[ _iy ]) ].epos ))
                                THEN
                                    _col_in_keyseq := true;
                                (*ENDIF*) 
                                END
                            ELSE
                                (* both values are 0 *)
                                _valid_sequence := false;
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDWHILE*) 
&               ifdef trace
                t01bool( ak_strat, 'col in key  ', _col_in_keyseq );
&               endif
                IF  ( NOT _col_in_keyseq )
                THEN
                    BEGIN
                    (* detect first range operator *)
                    _ix := 0;
                    WHILE ( _ix+1 <= key_access.ka_startcnt ) AND
                          ( _ix+1 <= key_access.ka_stopcnt ) AND
                          ( key_access.ka_startfields[ _ix ] <> 0 ) AND
                          ( key_access.ka_stopfields[ _ix ] <> 0 ) AND
                          ( key_access.ka_startfields[ _ix ] =
                          key_access.ka_stopfields[ _ix ] ) DO
                        _ix := succ( _ix );
                    (*ENDWHILE*) 
                    IF  ( _ix = 0 )
                    THEN
                        _recpos := 1
                    ELSE
                        BEGIN
                        _recpos := acv.a_mblock.mb_st^[ key_access.
                              ka_startfields[ _ix-1 ]].epos +
                              acv.a_mblock.mb_st^[ key_access.
                              ka_startfields[ _ix-1 ]].elen_var;
                        END;
                    (*ENDIF*) 
&                   ifdef trace
                    t01int4( ak_strat, '_ix         ', _ix );
                    t01int4( ak_strat, '_recpos     ', _recpos );
&                   endif
                    IF  ( acv.a_mblock.mb_st^[ _field_pos ].epos = _recpos )
                    THEN
                        _col_in_keyseq := true;
                    (*ENDIF*) 
                    ;
&                   ifdef trace
                    IF  ( _col_in_keyseq )
                    THEN
                        t01name( ak_strat, 'col aftr equal seq');
&                   endif
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  ( _col_in_keyseq )
                THEN
                    BEGIN
                    IF  ( acv.a_mblock.mb_st^[ _stpos ].eop_func = op_f_min )
                    THEN
                        key_strat.skir_strat_props :=
                              key_strat.skir_strat_props + [ ksp_aggr_MIN_opt ]
                    ELSE
                        key_strat.skir_strat_props :=
                              key_strat.skir_strat_props + [ ksp_aggr_MAX_opt ];
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            _field_pos := 0;
            END;
        st_output :
            _field_pos := 0;
        OTHERWISE
            BEGIN
            END;
        END;
    (*ENDCASE*) 
    _stpos := succ( _stpos );
    END;
(*ENDWHILE*) 
IF  ( NOT _col_in_keyseq )
THEN
    BEGIN
    key_strat.skir_strat_props := key_strat.skir_strat_props -
          [ ksp_aggr_MIN_opt, ksp_aggr_MAX_opt ];
    END
ELSE
    BEGIN
    IF  ( a01diag_minmax_optim
        AND
        NOT ( cs_indexscan in access_info.srec_config.cfg_switches ))
    THEN
        access_info.srec_query_prop.qps_switches :=
              access_info.srec_query_prop.qps_switches +
              [ qp_check_key_inv_MIN_MAX_opt ];
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720check_inv_minmax_opt(
            VAR acv          : tak_all_command_glob;
            VAR inv_strat    : tgg07_StrInvInRange;
            VAR index_def    : tak_multindex);
 
VAR
      _stpos         : tsp00_Int2;
      _stop          : tsp00_Int2;
      _field_pos     : tsp00_Int2;
      _ix            : tsp00_Int2;
      _iy            : tsp00_Int2;
      _invfield      : tsp00_Int2;
      _invlen        : tsp00_Int2;
      _col_in_invseq : boolean;
      _valid_sequence: boolean;
      _col_behind_eq : boolean;
 
BEGIN
(* we know we have output columns *)
_stpos := acv.a_mblock.mb_qual^.mqual_pos + 1;
_stop  := _stpos +
      acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mqual_pos ].epos - 1;
_col_in_invseq := true;
_field_pos := 0;
WHILE (( _stpos < _stop ) AND _col_in_invseq ) DO
    BEGIN
    CASE acv.a_mblock.mb_st^[ _stpos ].etype OF
        st_fixkey, st_varkey,
        st_fixcol, st_varcol,
        st_varlongchar:
            BEGIN
            _field_pos := _stpos;
&           ifdef trace
            t01int4( ak_strat, 'field found ', _stpos );
&           endif
            END;
        st_func :
            BEGIN
            IF  ( acv.a_mblock.mb_st^[ _stpos ].eop_func in [ op_f_min, op_f_max ] ) AND
                ( _field_pos <> 0 )
            THEN
                BEGIN
&               ifdef trace
                t01int4( ak_strat, 'funct found ', _stpos );
&               endif
                a71search_thru_index( acv, acv.a_mblock.mb_st^[ _field_pos ],
                      index_def, _invfield );
                IF  ( _invfield <> 0 )
                THEN
                    BEGIN
                    (* search field in inv start/stop sequence *)
                    (* in const part (equal sequence) or one col behind *)
                    _col_in_invseq  := false;
                    _valid_sequence := true;
                    _col_behind_eq  := false;
                    _ix := -1;
                    _iy := -1;
                    WHILE ( NOT _col_in_invseq ) AND ( _valid_sequence ) AND
                          (( _ix + 1 < inv_strat.siir_startcnt ) OR
                          ( _iy + 1 < inv_strat.siir_stopcnt )) DO
                        BEGIN
                        IF  ( _ix + 1 < inv_strat.siir_startcnt )
                        THEN
                            _ix := succ( _ix );
                        (*ENDIF*) 
                        IF  ( _iy + 1 < inv_strat.siir_stopcnt )
                        THEN
                            _iy := succ( _iy );
                        (*ENDIF*) 
                        IF  ( _ix >= 0 ) AND ( _iy >= 0 )
                        THEN
                            BEGIN
                            IF  ( inv_strat.siir_invstart[ _ix ] =
                                inv_strat.siir_invstop[ _iy ] )
                            THEN
                                BEGIN
                                IF  ( acv.a_mblock.mb_st^[ _field_pos ].etype =
                                    acv.a_mblock.mb_st^[ inv_strat.siir_invstart[ _ix ] ].etype )
                                    AND
                                    ( acv.a_mblock.mb_st^[ _field_pos ].epos =
                                    acv.a_mblock.mb_st^[ inv_strat.siir_invstart[ _ix ] ].epos )
                                THEN
                                    _col_in_invseq := true;
                                (*ENDIF*) 
                                END
                            ELSE
                                BEGIN
                                IF  (( acv.a_mblock.mb_st^[ _field_pos ].etype =
                                    acv.a_mblock.mb_st^
                                    [ abs(inv_strat.siir_invstart[ _ix ]) ].etype )
                                    AND
                                    ( acv.a_mblock.mb_st^[ _field_pos ].epos =
                                    acv.a_mblock.mb_st^
                                    [ abs(inv_strat.siir_invstart[ _ix ]) ].epos ))
                                    OR
                                    (( acv.a_mblock.mb_st^[ _field_pos ].etype =
                                    acv.a_mblock.mb_st^
                                    [ abs(inv_strat.siir_invstop[ _iy ]) ].etype )
                                    AND
                                    ( acv.a_mblock.mb_st^[ _field_pos ].epos =
                                    acv.a_mblock.mb_st^
                                    [ abs(inv_strat.siir_invstop[ _iy ]) ].epos ))
                                THEN
                                    _col_in_invseq := true
                                ELSE
                                    _valid_sequence := false;
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            IF  ( _ix >= 0 )
                            THEN
                                BEGIN
                                IF  (( acv.a_mblock.mb_st^[ _field_pos ].etype =
                                    acv.a_mblock.mb_st^
                                    [ abs(inv_strat.siir_invstart[ _ix ]) ].etype )
                                    AND
                                    ( acv.a_mblock.mb_st^[ _field_pos ].epos =
                                    acv.a_mblock.mb_st^
                                    [ abs(inv_strat.siir_invstart[ _ix ]) ].epos ))
                                THEN
                                    _col_in_invseq := true;
                                (*ENDIF*) 
                                END
                            ELSE
                                BEGIN
                                IF  ( _iy >= 0 )
                                THEN
                                    BEGIN
                                    IF  (( acv.a_mblock.mb_st^[ _field_pos ].etype =
                                        acv.a_mblock.mb_st^
                                        [ abs(inv_strat.siir_invstop[ _iy ]) ].etype )
                                        AND
                                        ( acv.a_mblock.mb_st^[ _field_pos ].epos =
                                        acv.a_mblock.mb_st^
                                        [ abs(inv_strat.siir_invstop[ _iy ]) ].epos ))
                                    THEN
                                        _col_in_invseq := true
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    (* both values are 0 *)
                                    _valid_sequence := false;
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDWHILE*) 
                    IF  ( NOT _col_in_invseq )
                    THEN
                        BEGIN
                        _ix := 0;
                        WHILE ( _ix+1 <= inv_strat.siir_startcnt ) AND
                              ( _ix+1 <= inv_strat.siir_stopcnt ) AND
                              ( inv_strat.siir_invstart[ _ix ] <> 0 ) AND
                              ( inv_strat.siir_invstop[ _ix ] <> 0 ) AND
                              ( inv_strat.siir_invstart[ _ix ] =
                              inv_strat.siir_invstop[ _ix ] ) DO
                            _ix := succ( _ix );
                        (*ENDWHILE*) 
                        IF  ( _ix + 1 = _invfield )
                        THEN
                            BEGIN
                            _col_in_invseq := true;
                            _col_behind_eq := true;
                            (* detect record position *)
                            _invlen := 0;
                            FOR _ix := 1 TO _invfield - 1 DO
                                _invlen := _invlen +
                                      acv.a_mblock.mb_st^[
                                      inv_strat.siir_invstart[ _ix - 1 ] ].elen_var;
                            (*ENDFOR*) 
                            END;
                        (*ENDIF*) 
                        ;
&                       ifdef trace
                        IF  ( _col_behind_eq )
                        THEN
                            t01name( ak_strat, 'col aftr equal seq');
&                       endif
                        (*ENDIF*) 
                        END;
&                   ifdef trace
                    (*ENDIF*) 
                    t01bool( ak_strat, 'col in inv  ', _col_in_invseq );
&                   endif
                    IF  ( _col_in_invseq )
                    THEN
                        BEGIN
                        IF  ( acv.a_mblock.mb_st^[ _stpos ].eop_func = op_f_min )
                        THEN
                            BEGIN
                            inv_strat.siir_strat_props :=
                                  inv_strat.siir_strat_props +
                                  [ isp_aggr_MIN_opt ];
                            IF  ( _invfield in inv_strat.siir_invcoldesc )
                            THEN
                                inv_strat.siir_strat_props :=
                                      inv_strat.siir_strat_props +
                                      [ isp_aggr_MIN_opt_reverse ];
                            (*ENDIF*) 
                            IF  ( _col_behind_eq )
                            THEN
                                (* notice that we deal with last field *)
                                inv_strat.siir_MIN_recpos := _invlen + 1;
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            inv_strat.siir_strat_props :=
                                  inv_strat.siir_strat_props +
                                  [ isp_aggr_MAX_opt ];
                            IF  ( _invfield in inv_strat.siir_invcoldesc )
                            THEN
                                inv_strat.siir_strat_props :=
                                      inv_strat.siir_strat_props +
                                      [ isp_aggr_MAX_opt_reverse ];
                            (*ENDIF*) 
                            IF  ( _col_behind_eq )
                            THEN
                                (* notice that we deal with last field *)
                                inv_strat.siir_MAX_recpos := _invlen + 1;
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            _field_pos := 0;
            END;
        st_output :
            _field_pos := 0;
        OTHERWISE
            BEGIN
            END;
        END;
    (*ENDCASE*) 
    _stpos := succ( _stpos );
    END;
(*ENDWHILE*) 
IF  ( NOT _col_in_invseq )
THEN
    BEGIN
    inv_strat.siir_strat_props := inv_strat.siir_strat_props -
          [ isp_aggr_MIN_opt, isp_aggr_MAX_opt ];
    inv_strat.siir_MIN_recpos := IS_UNDEFINED_GG07;
    inv_strat.siir_MAX_recpos := IS_UNDEFINED_GG07;
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720check_key_inv_minmax_opt(
            VAR acv          : tak_all_command_glob;
            VAR inv_strat    : tgg07_StrInvInRange);
 
VAR
      _stpos         : tsp00_Int2;
      _stop          : tsp00_Int2;
 
BEGIN
IF  NOT (
    ( isp_aggr_MIN_opt in inv_strat.siir_strat_props ) OR
    ( isp_aggr_MAX_opt in inv_strat.siir_strat_props ))
    AND
    (( isp_exact_match in inv_strat.siir_strat_props ) OR
    (  isp_exact_IN_SUBQ_match in inv_strat.siir_strat_props ))
THEN
    BEGIN
    (* we know we have output columns *)
    _stpos := acv.a_mblock.mb_qual^.mqual_pos + 1;
    _stop  := _stpos +
          acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mqual_pos ].epos - 1;
    WHILE ( _stpos < _stop ) DO
        BEGIN
        CASE acv.a_mblock.mb_st^[ _stpos ].etype OF
            st_func :
                BEGIN
                (* existence of MIN/MAX could be already tested while *)
                (* setting of qp_check_key_inv_MIN_MAX_opt and split  *)
                (* into qp_check_key_inv_MIN_opt and                  *)
                (* into qp_check_key_inv_MAX_opt                      *)
                (* so what?                                           *)
                IF  ( acv.a_mblock.mb_st^[ _stpos ].eop_func = op_f_min )
                THEN
                    BEGIN
                    inv_strat.siir_strat_props :=
                          inv_strat.siir_strat_props + [ isp_aggr_key_MIN_opt ];
                    END
                ELSE
                    BEGIN
                    IF  ( acv.a_mblock.mb_st^[ _stpos ].eop_func = op_f_max )
                    THEN
                        BEGIN
                        inv_strat.siir_strat_props :=
                              inv_strat.siir_strat_props + [ isp_aggr_key_MAX_opt ];
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            OTHERWISE
                BEGIN
                END;
            END;
        (*ENDCASE*) 
        _stpos := succ( _stpos );
        END;
    (*ENDWHILE*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      ak720all_predicates_used(
            VAR acv             : tak_all_command_glob;
            VAR sparr           : tak_syspointerarr;
            VAR access_info     : tak70_strategy_record;
            VAR inv_strat       : tgg07_StrInvInRange;
            use_startkey        : boolean) : boolean;
 
VAR
      _col_ptr       : tak00_colinfo_ptr;
      _col_array_ptr : ^tgg07_ColPosArr;
      _col_set       : tak_columnset;
      _col_cnt       : tsp00_Int2;
      _sum_col_cnt   : tsp00_Int2;
      _i             : tsp00_Int2;
 
BEGIN
(* access_info.srec_keyaccess contains actual key sequence *)
IF  ( use_startkey )
THEN
    BEGIN
    _col_array_ptr := @inv_strat.siir_invstart;
    _col_cnt       := inv_strat.siir_startcnt;
    _sum_col_cnt   := inv_strat.siir_startcnt;
    END
ELSE
    BEGIN
    _col_array_ptr := @inv_strat.siir_invstop;
    _col_cnt       := inv_strat.siir_stopcnt;
    _sum_col_cnt   := inv_strat.siir_stopcnt;
    END;
(*ENDIF*) 
;
(* add index columns to column set *)
_col_set := [];
_i       := 0;
WHILE ( _i <= _col_cnt - 1 ) AND ( acv.a_returncode = 0 ) DO
    BEGIN
    a06find_colinfo( sparr.pbasep,
          acv.a_mblock.mb_st^[ abs(_col_array_ptr^[ _i ]) ], _col_ptr );
    IF  ( _col_ptr <> NIL )
    THEN
        _col_set := _col_set + [ _col_ptr^.creccolno ]
    ELSE
        BEGIN
&       ifdef trace
        t01stackentry( ak_strat,
              acv.a_mblock.mb_st^[ abs(_col_array_ptr^[ _i ]) ],
              _col_array_ptr^[ _i ] );
&       endif
        a07_b_put_error( acv, e_old_fileversion, 1 );
        END;
    (*ENDIF*) 
    _i := succ(_i);
    END;
(*ENDWHILE*) 
;
(* add distinct key columns to column set *)
_i := 0;
WHILE ( _i <= access_info.srec_keyaccess.ka_startcnt - 1 ) AND
      ( acv.a_returncode = 0 ) DO
    BEGIN
    a06find_colinfo( sparr.pbasep,
          acv.a_mblock.mb_st^[ access_info.srec_keyaccess.ka_startfields[ _i ] ], _col_ptr );
    IF  ( _col_ptr <> NIL )
    THEN
        BEGIN
        IF  NOT ( _col_ptr^.creccolno in _col_set )
        THEN
            BEGIN
            _col_set := _col_set + [ _col_ptr^.creccolno ];
            _sum_col_cnt := succ(_sum_col_cnt);
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
&       ifdef trace
        t01stackentry( ak_strat, acv.a_mblock.
              mb_st^[ access_info.srec_keyaccess.ka_startfields[ _i ] ],
              access_info.srec_keyaccess.ka_startfields[ _i ] );
&       endif
        a07_b_put_error( acv, e_old_fileversion, 1 );
        END;
    (*ENDIF*) 
    _i := succ(_i);
    END;
(*ENDWHILE*) 
&ifdef trace
t01int4( ak_strat, '_sum_col_cnt', _sum_col_cnt );
&endif
ak720all_predicates_used :=
      (_sum_col_cnt >= access_info.srec_L1_pred_cnt);
END;
 
(*------------------------------*) 
 
FUNCTION
      ak720IndexIsSubsetOfKey (
            VAR acv          : tak_all_command_glob;
            VAR access_info  : tak70_strategy_record;
            VAR strategy     : tak70_one_strat;
            base_ptr         : tak_sysbufferaddress) : boolean;
 
VAR
      _colinfo         : tak00_colinfo_ptr;
      _colset          : tak_columnset;
      _idx_pos         : integer;
      _key_pos         : integer;
      _idx_range_col   : integer;
      _key_range_col   : integer;
      _idx_equal       : boolean;
      _key_equal       : boolean;
 
BEGIN
(* this function should check if index strategy is covered by key strategy *)
ak720IndexIsSubsetOfKey := false;
_colinfo   := NIL;
_colset    := [];
_idx_pos   := 0;
_idx_equal := true;
(* fill _colset with columns of index equal conditions *)
WHILE  _idx_equal AND (_idx_pos < MAX_COLPOSARR_IDX_GG07) DO
    BEGIN
    IF  (strategy.ostr_inv_in_range.siir_invstart[_idx_pos] =
        strategy.ostr_inv_in_range.siir_invstop[_idx_pos]) AND
        (strategy.ostr_inv_in_range.siir_invstart[_idx_pos] <> 0)
    THEN
        BEGIN
        a06find_colinfo ( base_ptr,
              acv.a_mblock.mb_st^[ abs(strategy.ostr_inv_in_range.siir_invstart[_idx_pos]) ],
              _colinfo);
        IF  _colinfo <> NIL
        THEN
            _colset := _colset + [_colinfo^.creccolno];
        (*ENDIF*) 
        _idx_pos := succ(_idx_pos);
        END
    ELSE
        _idx_equal := false;
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
_key_pos    := 0;
_key_equal  := true;
(* remove columns from _colset which are covered by key equal conditions *)
WHILE _key_equal AND (_key_pos < MAX_COLPOSARR_IDX_GG07) DO
    BEGIN
    IF  (access_info.srec_keyaccess.ka_startfields[_key_pos] =
        access_info.srec_keyaccess.ka_stopfields[_key_pos]) AND
        (access_info.srec_keyaccess.ka_startfields[_key_pos] <> 0)
    THEN
        BEGIN
        a06find_colinfo ( base_ptr,
              acv.a_mblock.mb_st^[ abs(access_info.srec_keyaccess.ka_stopfields[_key_pos]) ],
              _colinfo);
        IF  _colinfo <> NIL
        THEN
            _colset := _colset - [_colinfo^.creccolno];
        (*ENDIF*) 
        _key_pos := succ(_key_pos);
        END
    ELSE
        _key_equal := false;
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
&ifdef trace
a725output_colposarr_ex( ak_strat, 'key start   ',
      access_info.srec_keyaccess.ka_startfields, MAX_COLPOSARR_IDX_GG07);
a725output_colposarr_ex( ak_strat, 'key stop    ',
      access_info.srec_keyaccess.ka_stopfields, MAX_COLPOSARR_IDX_GG07);
a725output_colposarr_ex( ak_strat, 'index start ',
      strategy.ostr_inv_in_range.siir_invstart, MAX_COLPOSARR_IDX_GG07);
a725output_colposarr_ex( ak_strat, 'index stop  ',
      strategy.ostr_inv_in_range.siir_invstop, MAX_COLPOSARR_IDX_GG07);
t01int4( ak_strat, '_key_pos    ', _key_pos );
t01int4( ak_strat, '_idx_pos    ', _idx_pos );
t01columnset ( ak_strat, '_colset     ', _colset );
&endif
(* if _colset is empty all equal conditions in index strategy are covered by key strategy *)
IF  (_colset = [])
THEN
    BEGIN
    (* now we check the first range condition in both strategies *)
    _idx_range_col := IS_UNDEFINED_GG07;
    _key_range_col := IS_UNDEFINED_GG07;
    (* get colno of first range condition in key strat *)
    IF  (_key_pos  < MAX_COLPOSARR_IDX_GG07) AND
        (access_info.srec_keyaccess.ka_startfields[_key_pos] > 0)
    THEN
        BEGIN
        a06find_colinfo ( base_ptr,
              acv.a_mblock.mb_st^[ abs(access_info.srec_keyaccess.ka_startfields[_key_pos]) ],
              _colinfo);
        IF  _colinfo <> NIL
        THEN
            _key_range_col := _colinfo^.creccolno;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  (_key_pos  < MAX_COLPOSARR_IDX_GG07) AND
            (abs(access_info.srec_keyaccess.ka_stopfields[_key_pos]) > 0)
        THEN
            BEGIN
            a06find_colinfo ( base_ptr,
                  acv.a_mblock.mb_st^[ abs(access_info.srec_keyaccess.ka_stopfields[_key_pos]) ],
                  _colinfo);
            IF  _colinfo <> NIL
            THEN
                _key_range_col := _colinfo^.creccolno;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    (* get colno of first range condition in index strat *)
    IF  (_idx_pos  < MAX_COLPOSARR_IDX_GG07) AND
        (strategy.ostr_inv_in_range.siir_invstart[_idx_pos] > 0)
    THEN
        BEGIN
        a06find_colinfo ( base_ptr,
              acv.a_mblock.mb_st^[ abs(strategy.ostr_inv_in_range.siir_invstart[_idx_pos]) ],
              _colinfo);
        IF  _colinfo <> NIL
        THEN
            _idx_range_col := _colinfo^.creccolno;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  (_idx_pos  < MAX_COLPOSARR_IDX_GG07) AND
            (abs(strategy.ostr_inv_in_range.siir_invstop[_idx_pos]) > 0)
        THEN
            BEGIN
            a06find_colinfo ( base_ptr,
                  acv.a_mblock.mb_st^[ abs(strategy.ostr_inv_in_range.siir_invstop[_idx_pos]) ],
                  _colinfo);
            IF  _colinfo <> NIL
            THEN
                _idx_range_col := _colinfo^.creccolno;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
&   ifdef trace
    t01int4( ak_strat, '_key_pos    ', _key_pos );
    t01int4( ak_strat, '_key_range_c', _key_range_col);
    t01int4( ak_strat, '_idx_pos    ', _idx_pos );
    t01int4( ak_strat, '_idx_range_c', _idx_range_col);
    t01bool( ak_strat, 'idx subset  ', (_idx_range_col = IS_UNDEFINED_GG07)
          OR (_idx_range_col = _key_range_col));
&   endif
    ak720IndexIsSubsetOfKey := (_idx_range_col = IS_UNDEFINED_GG07) OR
          (_idx_range_col = _key_range_col);
    END;
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
