.nf
 
 
    ========== licence begin  GPL
    Copyright (C) 2000 SAP AG
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
 
.fo
*****************************************************
Copyright by SAP AG, 2000
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
Pretty  : 2002-10-29
*****************************************************
 
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    : tsp_int2);
 
        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: tsp_int2;
                    VAR eval_info    : tak70_page_eval_rec;
                    L1_pageIO        : tsp_int4;
                    VAR keystart     : tgg07_ColPosArr;
                    VAR keystop      : tgg07_ColPosArr);
 
        PROCEDURE
              a720glob_init_eval_stat;
 
.CM *-END-* define --------------------------------------
 
Use     :
 
        FROM
              AK_universal_semantic_tools : VAK06;
 
        PROCEDURE
              a06eval_page_count (
                    VAR acv          : tak_all_command_glob;
                    VAR file_id      : tgg00_FileId;
                    VAR startkey     : tgg_lkey;
                    VAR stopkey      : tgg_lkey;
                    do_sample        : boolean;
                    count_records    : boolean;
                    VAR page_count   : tsp_int4;
                    VAR min_page_cnt : tsp_int4;
                    VAR record_cnt   : tsp_int4;
                    VAR b_err        : tgg_basis_error);
 
      ------------------------------ 
 
        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    : tgg_basis_error;
                    err_code : tsp_int4);
 
        FUNCTION
              a07_return_code (
                    b_err   : tgg_basis_error;
                    sqlmode : tsp_sqlmode) : tsp_int2;
 
      ------------------------------ 
 
        FROM
              AK_Index : VAK24;
 
        PROCEDURE
              a24fnd_indexno (
                    VAR acv            : tak_all_command_glob;
                    VAR tabid          : tgg_surrogate;
                    indexno            : integer;
                    VAR index_scan_rec : tak_index_scan_record);
 
        PROCEDURE
              a24init_index_scan (
                    VAR acv            : tak_all_command_glob;
                    VAR tabid          : tgg_surrogate;
                    VAR index_scan_rec : tak_index_scan_record);
 
        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;
 
      ------------------------------ 
 
        FROM
              Build_Strategy_2 : VAK71;
 
        FUNCTION
              a71is_duplicate_avoidance (
                    VAR gg_strategy  : tgg07_StrategyInfo;
                    stratenum        : tgg07_StratEnum;
                    VAR strat_data   : tgg07_StrRaw) : boolean;
 
        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);
 
        PROCEDURE
              a71check_fetch_optimization (
                    VAR acv         : tak_all_command_glob;
                    VAR config      : tak70_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;
                    read_primpages      : tsp_int4;
                    read_primrows       : tsp_int4;
                    VAR key_strat_value : tsp_longreal;
                    read_invpages       : tsp_int4;
                    VAR inv_strat_value : tsp_longreal;
                    outrec_len          : tsp_int2);
 
      ------------------------------ 
 
        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    : tgg_vtrace_state;
 
        FUNCTION
              g01max_merge : tsp_int4;
 
      ------------------------------ 
 
        FROM
              Select_Help_Procedures : VGG04;
 
        PROCEDURE
              g04int4_to_trace (
                    VAR t  : tgg00_TransContext;
                    name   : tsp_name;
                    intval : tsp_int4);
 
        PROCEDURE
              g04c30_to_trace (
                    VAR t  : tgg00_TransContext;
                    msg    : tsp_c30);
 
        PROCEDURE
              g04name_to_trace (
                    VAR t  : tgg00_TransContext;
                    name   : tsp_name);
 
        PROCEDURE
              g04limitprimkeys (
                    VAR mblock      : tgg_mess_block;
                    VAR startkeyarr : tgg07_ColPosArr;
                    VAR start_key   : tgg_lkey;
                    VAR stopkeyarr  : tgg07_ColPosArr;
                    VAR stop_key    : tgg_lkey;
                    VAR use_stopkey : boolean;
                    in_stack        : tsp_int2;
                    in_cnt          : tsp_int2);
 
        PROCEDURE
              g04minv_key (
                    VAR mblock     : tgg_mess_block;
                    VAR subq_buf   : tgg_rec_buf;
                    VAR inv_strat  : tgg07_StrInvInRange;
                    VAR startkey   : tgg_lkey;
                    VAR stopkey    : tgg_lkey;
                    first_index    : tsp_int2);
 
        PROCEDURE
              g04read_subquery (
                    VAR mblock      : tgg_mess_block;
                    VAR result      : tgg_rec_buf;
                    VAR subqtree_id : tgg00_FileId;
                    VAR m_key       : tgg_lkey;
                    VAR aux_error   : tgg_basis_error;
                    VAR ok          : boolean);
 
        PROCEDURE
              gg04subq_limitkey (
                    VAR mblock      : tgg_mess_block;
                    VAR subq_buf    : tgg_rec_buf;
                    VAR keyarr      : tgg07_ColPosArr;
                    VAR one_key     : tgg_lkey;
                    VAR use_stopkey : boolean);
 
        PROCEDURE
              g04index_tree_build (
                    VAR file_id    : tgg00_FileId;
                    VAR index_tree : tgg00_FileId;
                    index_no       : tsp_int2);
 
        PROCEDURE
              g04find_in_stack (
                    VAR mblock      : tgg_mess_block;
                    VAR keyarr      : tgg07_ColPosArr;
                    VAR in_stack    : tsp_int2;
                    VAR in_cnt      : tsp_int2);
 
        FUNCTION
              g04inv_tfn (tfn : tgg00_Tfn) : boolean;
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG10;
 
        PROCEDURE
              g10mv4  (
                    mod_id         : tsp_c6;
                    mod_intern_num : tsp_int4;
                    source_upb     : tsp_int4;
                    destin_upb     : tsp_int4;
                    VAR source     : tsp_moveobj;
                    source_pos     : tsp_int4;
                    VAR destin     : tgg00_FileId;
                    destin_pos     : tsp_int4;
                    length         : tsp_int4;
                    VAR e          : tgg_basis_error);
&       ifdef TRACE
 
      ------------------------------ 
 
        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
              t01set_bool_debug_or_trace;
 
        PROCEDURE
              t01disable_debug_or_trace;
 
      ------------------------------ 
 
        FROM
              Trace_Strategy_1 : VAK725;
 
        PROCEDURE
              a725output_invstrat(
                    debug         : tgg_debug;
                    nam           : tsp00_Sname;
                    VAR inv_strat : tgg07_StrInvInRange);
 
        PROCEDURE
              a725output_one_strat (
                    layer           : tgg_debug;
                    VAR one_strat   : tak70_one_strat);
 
        PROCEDURE
              a725output_colposarr (
                    debug       : tgg_debug;
                    nam         : tsp00_Sname;
                    VAR keypos  : tgg07_ColPosArr);
 
        PROCEDURE
              a725output_query_prop (
                    debug   : tgg00_Debug;
                    qprop   : tak70_query_properties);
&       endif
 
      ------------------------------ 
 
        FROM
              Trace_Strategy_2 : VAK727;
 
        PROCEDURE
              a727trace_costs (
                    VAR transid  : tgg00_TransContext;
                    cost_pages   : tsp_int4;
                    result_pages : tsp_int4;
                    result_rows  : tsp_int4);
 
        PROCEDURE
              a727trace_one_strat (
                    VAR transid     : tgg00_TransContext;
                    proc_name       : tsp_name;
                    VAR one_strat   : tak70_one_strat);
 
        PROCEDURE
              a727trace_eval (
                    VAR transid : tgg00_TransContext;
                    txt        : tsp_c30;
                    cnt_rec    : boolean;
                    all_rows   : tsp_int4;
                    act_rows   : tsp_int4;
                    all_pages  : tsp_int4;
                    min_pages  : tsp_int4;
                    act_pages  : tsp_int4;
                    fraction   : tsp_longreal);
 
        PROCEDURE
              a727trace_invstrat(
                    VAR transid   : tgg00_TransContext;
                    name          : tsp00_Sname;
                    VAR inv_strat : tgg07_StrInvInRange;
                    trace_keyarr  : boolean);
 
.CM *-END-* use -----------------------------------------
 
Synonym :
 
        PROCEDURE
              g10mv4;
 
              tsp_moveobj tgg00_FileId
 
.CM *-END-* synonym -------------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
CONST
      (* strategy-constants for parse-execute separation: *)
      c_almost_zero         = 0.0000001;
      c_max_subq_eval_cnt   = 50; (* maximum number of values to
      evaluate in SUBQ conditions *)
      c_sample              = true;
 
TYPE
 
      t_key_in_subq_info = RECORD
            kisi_strat_value : tsp_longreal;
            kisi_read_pages  : tsp_int4;
            kisi_read_rows   : tsp_int4;
      END;
 
 
      t_key_info = RECORD
            ki_strat_value   : tsp_longreal;
            ki_read_pages    : tsp_int4;
            ki_read_rows     : tsp_int4;
            ki_subq_strat    : boolean;
            ki_stat_in_subq  : t_key_in_subq_info;
      END;
 
 
      t_eval_rec = RECORD
            er_keyinfo        : t_key_info;
            er_primpages      : tsp_int4;
            er_primrows       : tsp_int4;
      END;
 
 
      t_subquery_read_info = RECORD
            sri_pos        : tsp_int4;
            sri_len        : tsp_int4;
            sri_error      : tgg_basis_error;
            sri_tree       : tgg00_FileId;
            sri_key        : tgg_lkey;
            sri_buf        : tgg_rec_buf;
      END;
 
 
VAR
      a720_strat_eval_rec : t_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;
            VAR chosen_strat     : tak70_one_strat; (*INOUT*)
            VAR order_fields     : tak00_ord_fields;
            VAR StratInfo_len    : tsp_int2);
 
VAR
      _index_strategy       : tak70_one_strat;
      _key_strategy         : tak70_one_strat;
      _eval_rec             : t_eval_rec;
      _ix                   : tsp_int2;
 
BEGIN
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    g04c30_to_trace ( acv.a_transinf.tri_trans,
          '>>A720STRATEGY_DECISION>>     ' );
(*ENDIF*) 
;
_index_strategy.ostr_strategy     := strat_undecided;
_index_strategy.ostr_cost_pages   := IS_UNDEFINED_GG07;
_index_strategy.ostr_result_pages := IS_UNDEFINED_GG07;
_index_strategy.ostr_result_rows  := IS_UNDEFINED_GG07;
_index_strategy.ostr_filler1      := ' ';
_index_strategy.ostr_filler2      := 0;
;
_key_strategy.ostr_strategy     := strat_undecided;
_key_strategy.ostr_cost_pages   := IS_UNDEFINED_GG07;
_key_strategy.ostr_result_pages := IS_UNDEFINED_GG07;
_key_strategy.ostr_result_rows  := IS_UNDEFINED_GG07;
_key_strategy.ostr_filler1      := ' ';
_key_strategy.ostr_filler2      := 0;
;
_eval_rec                       := a720_strat_eval_rec;
IF  NOT ( qp_missing_value in access_info.srec_query_prop.qps_switches )
THEN
    BEGIN
    ak720get_file_samples( acv, sparr, acv.a_mblock.mb_qual^.mtree,
          _eval_rec.er_primpages, _eval_rec.er_primrows,
          access_info.srec_config);
    ;
    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
        _key_strategy.ostr_strategy := strat_undecided;
    END
ELSE
    BEGIN
    (* last a71create_key_sequence() exposes broken access *)
    END;
(*ENDIF*) 
;
&ifdef TRACE
t01int4( ak_strat, 'stat ppages ', _eval_rec.er_primpages );
t01int4( ak_strat, 'stat prows  ', _eval_rec.er_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, 'cost   pages', _key_strategy.ostr_cost_pages );
t01int4( ak_strat, 'result pages', _key_strategy.ostr_result_pages );
t01strat_enum( ak_strat, 'best inv str', _index_strategy.ostr_strategy );
t01int4( ak_strat, 'cost   pages', _index_strategy.ostr_cost_pages );
t01int4( ak_strat, 'result pages', _index_strategy.ostr_result_pages );
&endif
(* decide for strategy *)
IF  ( _index_strategy.ostr_strategy = strat_undecided ) AND
    ( _key_strategy.ostr_strategy = strat_undecided )
THEN
    BEGIN
    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;
    chosen_strat.ostr_cost_pages    := IS_UNDEFINED_GG07;
    chosen_strat.ostr_result_pages  := IS_UNDEFINED_GG07;
    chosen_strat.ostr_result_rows   := IS_UNDEFINED_GG07;
    END
ELSE
    IF  ( _index_strategy.ostr_strategy = strat_undecided )
        OR
        (( _index_strategy.ostr_strategy <> strat_undecided ) AND
        ( _key_strategy.ostr_cost_pages <= _index_strategy.ostr_cost_pages ) AND
        NOT ( cs_indexaccess in access_info.srec_config.cfg_switches ))
        OR
        ( cs_keyaccess in access_info.srec_config.cfg_switches )
    THEN
        (* make key strategy *)
        BEGIN
        (* key information already in chosen strat *)
        IF  ( _key_strategy.ostr_strategy = strat_key_in )
        THEN
            BEGIN
            StratInfo_len := STRATEGY_START_MXGG07 +
                  sizeof( chosen_strat.ostr_key_in_range );
            END
        ELSE
            BEGIN
            StratInfo_len := STRATEGY_START_MXGG07 +
                  sizeof( chosen_strat.ostr_key_in_range );
            END;
        (*ENDIF*) 
        chosen_strat       := _key_strategy;
        acv.a_sample_pages := _eval_rec.er_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*) 
(*ENDIF*) 
&ifdef trace
t01strat_enum( ak_strat, 'choosen stra', chosen_strat.ostr_strategy );
&endif
;
IF  ( acv.a_mblock.mb_type = m_delete ) AND
    ( acv.a_mblock.mb_type2 = mm_qual ) AND
    (( _eval_rec.er_primpages = 1 ) OR
    ( _eval_rec.er_keyinfo.ki_read_pages = 1 ))
THEN
    (* an optimized delete work on file directory   *)
    (* for small tables e assume that a page delete *)
    (* was cheaper than file directory handling     *)
    acv.a_mblock.mb_type2 := mm_qual_no_opt;
(*ENDIF*) 
;
&ifdef TRACE
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;
            VAR eval_rec       : t_eval_rec;
            VAR best_key_strat : tak70_one_strat);
 
VAR
      _inv_strat_val   : tsp_longreal;
      _inv_pages       : tsp_int2;
      _in_subq_stpos   : tsp_int2;
      _i               : tsp_int2;
      _startcnt        : tsp_int2;
      _stopcnt         : tsp_int2;
      _in_stpos        : tsp_int2;
      _in_elemcnt      : tsp_int2;
 
BEGIN
&ifdef trace
a725output_query_prop( ak_strat, access_info.srec_query_prop );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g04c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720KEY_DECISION>>         ' );
    END;
(*ENDIF*) 
IF  ( acv.a_return_segm^.sp1r_returncode = 0 )
    AND
    (( access_info.srec_keyaccess.ka_startcnt > 0 ) OR
    ( access_info.srec_keyaccess.ka_stopcnt > 0 ))
THEN
    BEGIN
    IF  ( qp_IN_usage_start in access_info.srec_query_prop.qps_switches ) OR
        ( qp_IN_usage_stop in access_info.srec_query_prop.qps_switches )
    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*) 
    IF  ( qp_SUBQ_usage in access_info.srec_query_prop.qps_switches )
    THEN
        BEGIN
        (* don't use SUBQ as range operator *)
        _in_subq_stpos :=
              access_info.srec_keyaccess.
              ka_startfields[ access_info.srec_keyaccess.ka_SUBQ_idx ];
        access_info.srec_keyaccess.
              ka_startfields[ access_info.srec_keyaccess.ka_SUBQ_idx ] := 0;
        access_info.srec_keyaccess.
              ka_stopfields[ access_info.srec_keyaccess.ka_SUBQ_idx ]  := 0;
        END;
    (*ENDIF*) 
    ;
    ak720keyeval( acv, sparr,
          access_info.srec_keyaccess.ka_startfields,
          access_info.srec_keyaccess.ka_stopfields,
          _in_stpos, _in_elemcnt,
          eval_rec, access_info.srec_config );
    ;
    IF  ( qp_SUBQ_usage in access_info.srec_query_prop.qps_switches )
    THEN
        BEGIN
        (* insert needed information *)
        access_info.srec_keyaccess.
              ka_startfields[ access_info.srec_keyaccess.ka_SUBQ_idx ] :=
              _in_subq_stpos;
        access_info.srec_keyaccess.
              ka_stopfields[ access_info.srec_keyaccess.ka_SUBQ_idx ]  :=
              _in_subq_stpos;
        END;
    (*ENDIF*) 
    ;
    IF  ( qp_SUBQ_usage in access_info.srec_query_prop.qps_switches ) AND
        ( acv.a_return_segm^.sp1r_returncode = 0 )
    THEN
        BEGIN
        (* evaluate witht SUBQ *)
        ak720key_subq_eval( acv, sparr,
              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 );
        END
    ELSE
        IF  ( qp_IN_usage in access_info.srec_query_prop.qps_switches ) AND
            ( acv.a_return_segm^.sp1r_returncode = 0 )
        THEN
            BEGIN
            (* evaluate with IN *)
            ak720key_in_eval( acv, sparr,
                  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 );
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    END
ELSE
    BEGIN
    (* table scan *)
    eval_rec.er_keyinfo.ki_read_pages := eval_rec.er_primpages;
    IF  ( cs_count_records in access_info.srec_config.cfg_switches )
    THEN
        eval_rec.er_keyinfo.ki_read_rows := eval_rec.er_primrows;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
&ifdef trace
t01int4( ak_strat, 'prim pages  ', eval_rec.er_primpages );
t01real( ak_strat, 'KEY value   ', eval_rec.er_keyinfo.ki_strat_value, 3 );
t01int4( ak_strat, 'KEY pages   ', eval_rec.er_keyinfo.ki_read_pages );
t01real( ak_strat, 'SUBQ/IN valu',
      eval_rec.er_keyinfo.ki_stat_in_subq.kisi_strat_value, 3 );
t01int4( ak_strat, 'IN/SUBQ page', eval_rec.er_keyinfo.
      ki_stat_in_subq.kisi_read_pages );
&endif
(* decide for key strategy *)
IF  ( qp_IN_usage in access_info.srec_query_prop.qps_switches ) OR
    ( qp_SUBQ_usage in access_info.srec_query_prop.qps_switches )
THEN
    BEGIN
    IF  ( eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages >=
        eval_rec.er_keyinfo.ki_read_pages ) AND
        ( NOT ( cs_IN_strategy in access_info.srec_config.cfg_switches ) OR
        ( cs_SUBQ_strategy in access_info.srec_config.cfg_switches ))
    THEN
        BEGIN
        best_key_strat.ostr_strategy                        := strat_key_range;
        best_key_strat.ostr_key_in_range.skir_IN_SUBQ_stpos := IS_UNDEFINED_GG07;
        best_key_strat.ostr_key_in_range.skir_inelemcnt     := IS_UNDEFINED_GG07;
        ;
        IF  ( qp_SUBQ_usage in access_info.srec_query_prop.qps_switches )
        THEN
            BEGIN
            (* don't use SUBQ as range operator *)
            _startcnt := access_info.srec_keyaccess.ka_SUBQ_idx;
            _stopcnt  := access_info.srec_keyaccess.ka_SUBQ_idx;
            END
        ELSE
            BEGIN
            _startcnt := access_info.srec_keyaccess.ka_startcnt;
            _stopcnt  := access_info.srec_keyaccess.ka_stopcnt;
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        (* chose IN/SUBQ condition *)
        IF  ( qp_SUBQ_usage in access_info.srec_query_prop.qps_switches )
        THEN
            BEGIN
            IF  ( qp_exact_IN_SUBQ_match in
                access_info.srec_query_prop.qps_switches )
            THEN
                best_key_strat.ostr_strategy := strat_key_equal_sub
            ELSE
                best_key_strat.ostr_strategy := strat_key_range_sub;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            best_key_strat.ostr_strategy                        := strat_key_in;
            best_key_strat.ostr_key_in_range.skir_IN_SUBQ_stpos :=
                  access_info.srec_keyaccess.ka_infield.in_stpos;
            best_key_strat.ostr_key_in_range.skir_inelemcnt     :=
                  access_info.srec_keyaccess.ka_infield.in_elemcnt;
            END;
        (*ENDIF*) 
        _startcnt := access_info.srec_keyaccess.ka_startcnt;
        _stopcnt  := access_info.srec_keyaccess.ka_stopcnt;
        END;
    (*ENDIF*) 
    END
ELSE
    BEGIN
    best_key_strat.ostr_strategy                        := strat_key_range;
    best_key_strat.ostr_key_in_range.skir_IN_SUBQ_stpos := IS_UNDEFINED_GG07;
    best_key_strat.ostr_key_in_range.skir_inelemcnt     := IS_UNDEFINED_GG07;
    ;
    _startcnt := access_info.srec_keyaccess.ka_startcnt;
    _stopcnt  := access_info.srec_keyaccess.ka_stopcnt;
    END;
(*ENDIF*) 
FOR _i := 0 TO MAX_COLPOSARR_IDX_GG07 DO
    IF  ( _i < _startcnt )
    THEN
        best_key_strat.ostr_key_in_range.skir_keystart[ _i ] :=
              access_info.srec_keyaccess.ka_startfields[ _i ]
    ELSE
        best_key_strat.ostr_key_in_range.skir_keystart[ _i ] := 0;
    (*ENDIF*) 
(*ENDFOR*) 
;
FOR _i := 0 TO MAX_COLPOSARR_IDX_GG07 DO
    IF  ( _i < _stopcnt )
    THEN
        best_key_strat.ostr_key_in_range.skir_keystop[ _i ] :=
              access_info.srec_keyaccess.ka_stopfields[ _i ]
    ELSE
        best_key_strat.ostr_key_in_range.skir_keystop[ _i ] := 0;
    (*ENDIF*) 
(*ENDFOR*) 
;
(* if allowed try switching to fetch strategy *)
a71check_fetch_optimization( acv, access_info.srec_config,
      access_info.srec_query_prop, gg_strategy,
      best_key_strat.ostr_strategy, best_key_strat.ostr_raw );
;
(* calculate IO costs *)
(* primary page + page cost for ordering + build costs *)
_inv_strat_val := 0;
_inv_pages     := 0;
IF  ( best_key_strat.ostr_strategy in [ strat_key_range, strat_key_range_fetch ] )
THEN
    BEGIN
    a71calculate_pageIO( acv, sparr, access_info,
          best_key_strat,
          eval_rec.er_keyinfo.ki_read_pages,
          eval_rec.er_keyinfo.ki_read_rows,
          eval_rec.er_keyinfo.ki_strat_value,
          _inv_pages, _inv_strat_val, gg_strategy.str_rec_len );
    END
ELSE
    BEGIN
    a71calculate_pageIO( acv, sparr, access_info,
          best_key_strat,
          eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages,
          eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_rows,
          eval_rec.er_keyinfo.ki_stat_in_subq.kisi_strat_value,
          _inv_pages, _inv_strat_val, gg_strategy.str_rec_len );
    END;
(*ENDIF*) 
;
&ifdef trace
a725output_one_strat( ak_strat, best_key_strat );
&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;
            VAR order_fields   : tak00_ord_fields;
            VAR eval_rec       : t_eval_rec;
            VAR best_inv_strat : tak70_one_strat);
 
VAR
      _usable          : boolean;
      _i               : tsp_int2;
      _startcnt        : tsp_int2;
      _stopcnt         : tsp_int2;
      _inv_strat       : tak70_one_strat;
      _inv_tabid       : tgg_surrogate;
      _index_scan_rec  : tak_index_scan_record;
 
BEGIN
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g04c30_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
        g04c30_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
        (* fill _inv_strat but without key access path *)
        ak720get_invstrat_info( acv, access_info,
              gg_strategy.str_out_keyseqlen,
              _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
        g04name_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_return_segm^.sp1r_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
            (* fill _inv_strat but without key access path *)
            ak720get_invstrat_info( acv, access_info,
                  gg_strategy.str_out_keyseqlen,
                  _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
    (* get correct key access path *)
&   ifdef trace
    t01int4( ak_strat, 'get key accp',
          access_info.srec_keyaccess.ka_SUBQ_idx );
&   endif
    IF  ( eval_rec.er_keyinfo.ki_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;
        END
    ELSE
        BEGIN
        _startcnt := access_info.srec_keyaccess.ka_startcnt;
        _stopcnt  := access_info.srec_keyaccess.ka_stopcnt;
        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
        g04c30_to_trace( acv.a_transinf.tri_trans,
              'all indices inaccessible !    ' );
        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;
            VAR act_inv_strat  : tak70_one_strat;
            VAR key_eval_rec   : t_eval_rec;
            VAR best_inv_strat : tak70_one_strat);
 
CONST
      dont_count_records = false;
 
VAR
      _in_subq_stpos         : tsp_int2;
      _startcnt              : tsp_int2;
      _stopcnt               : tsp_int2;
      _primkeylen            : tsp_int2;
      _dummy_cnt             : tsp_int4;
      _invpages              : tsp_int4;
      _scoured_pages         : tsp_int4;
      _scoured_pages_range   : tsp_int4;
      _scoured_pages_IN_SUBQ : tsp_int4;
      _primrow_cnt           : tsp_int4;
      _primrow_cnt_range     : tsp_int4;
      _primrow_cnt_IN_SUBQ   : tsp_int4;
      _act_strat_value       : tsp_longreal;
      _strat_value_range     : tsp_longreal;
      _strat_value_IN_SUBQ   : tsp_longreal;
      _inv_file              : tgg00_FileId;
 
BEGIN
_act_strat_value := 1;
&ifdef trace
t01sname( ak_strat, 'History:    ' );
t01int4 ( ak_strat, 'best IO page', best_inv_strat.ostr_cost_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, _invpages,
      _dummy_cnt (* use value from primary table *), access_info.srec_config );
;
IF  ( act_inv_strat.ostr_inv_in_range.siir_startcnt > 0 ) OR
    ( act_inv_strat.ostr_inv_in_range.siir_stopcnt > 0 )
THEN
    BEGIN
    IF  ( qp_SUBQ_usage in access_info.srec_query_prop.qps_switches )
    THEN
        BEGIN
        (* don't use SUBQ as range operator *)
        _in_subq_stpos :=
              act_inv_strat.ostr_inv_in_range.siir_invstart
              [ act_inv_strat.ostr_inv_in_range.siir_subq_idx ];
        act_inv_strat.ostr_inv_in_range.siir_invstart
              [ act_inv_strat.ostr_inv_in_range.siir_subq_idx ] := 0;
        act_inv_strat.ostr_inv_in_range.siir_invstop
              [ act_inv_strat.ostr_inv_in_range.siir_subq_idx ] := 0;
        _startcnt := act_inv_strat.ostr_inv_in_range.siir_startcnt;
        _stopcnt  := act_inv_strat.ostr_inv_in_range.siir_stopcnt;
        act_inv_strat.ostr_inv_in_range.siir_startcnt :=
              act_inv_strat.ostr_inv_in_range.siir_subq_idx;
        act_inv_strat.ostr_inv_in_range.siir_stopcnt :=
              act_inv_strat.ostr_inv_in_range.siir_subq_idx;
        END;
    (*ENDIF*) 
    ;
    ak720indexeval( acv, act_inv_strat.ostr_inv_in_range,
          _inv_file, key_eval_rec, _invpages,
          access_info.srec_config,
          _strat_value_range,
          _scoured_pages_range,
          _primrow_cnt_range );
    ;
    IF  ( qp_SUBQ_usage in access_info.srec_query_prop.qps_switches )
    THEN
        BEGIN
        (* insert needed information *)
        act_inv_strat.ostr_inv_in_range.siir_invstart
              [ act_inv_strat.ostr_inv_in_range.siir_subq_idx ] := _in_subq_stpos;
        act_inv_strat.ostr_inv_in_range.siir_invstop
              [ act_inv_strat.ostr_inv_in_range.siir_subq_idx ] := _in_subq_stpos;
        act_inv_strat.ostr_inv_in_range.siir_startcnt := _startcnt;
        act_inv_strat.ostr_inv_in_range.siir_stopcnt  := _stopcnt;
        END;
    (*ENDIF*) 
    ;
    IF  ( qp_SUBQ_usage in access_info.srec_query_prop.qps_switches ) AND
        ( acv.a_return_segm^.sp1r_returncode = 0 )
    THEN
        BEGIN
        (* evaluate witht SUBQ *)
        ak720index_subq_eval( acv, sparr, act_inv_strat.ostr_inv_in_range,
              _inv_file, _scoured_pages_range,
              key_eval_rec, _invpages, access_info.srec_config,
              _strat_value_IN_SUBQ,
              _scoured_pages_IN_SUBQ,
              _primrow_cnt_IN_SUBQ );
        END
    ELSE
        IF  ( qp_IN_usage in access_info.srec_query_prop.qps_switches ) AND
            ( acv.a_return_segm^.sp1r_returncode = 0 )
        THEN
            BEGIN
            (* evaluate with IN *)
            ak720index_in_eval( acv, sparr, act_inv_strat.ostr_inv_in_range,
                  _inv_file, _scoured_pages_range,
                  key_eval_rec, _invpages, access_info.srec_config,
                  _strat_value_IN_SUBQ,
                  _scoured_pages_IN_SUBQ,
                  _primrow_cnt_IN_SUBQ );
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    END
ELSE
    BEGIN
    (* index scan *)
    _strat_value_range   := 1;
    _scoured_pages_range := _invpages;
    IF  ( cs_count_records in access_info.srec_config.cfg_switches )
    THEN
        _primrow_cnt_range := key_eval_rec.er_primrows
    ELSE
        _primrow_cnt_range := IS_UNDEFINED_GG07;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
&ifdef trace
t01real( ak_strat, 'INV value   ', _strat_value_range, 3 );
t01int4( ak_strat, 'INV pages   ', _scoured_pages_range );
IF  ( qp_IN_usage in access_info.srec_query_prop.qps_switches ) OR
    ( qp_SUBQ_usage in access_info.srec_query_prop.qps_switches )
THEN
    BEGIN
    t01real( ak_strat, 'SUBQ/IN valu', _strat_value_IN_SUBQ, 3 );
    t01int4( ak_strat, 'IN/SUBQ page', _scoured_pages_IN_SUBQ );
    END;
&endif
(*ENDIF*) 
;
(* decide for key strategy *)
IF  ( qp_IN_usage in access_info.srec_query_prop.qps_switches ) OR
    ( qp_SUBQ_usage in access_info.srec_query_prop.qps_switches )
THEN
    BEGIN
    IF  ( _scoured_pages_IN_SUBQ >= _scoured_pages_range ) AND
        ( NOT ( cs_IN_strategy in access_info.srec_config.cfg_switches ) OR
        ( cs_SUBQ_strategy in access_info.srec_config.cfg_switches ))
    THEN
        BEGIN
        act_inv_strat.ostr_strategy := strat_inv_range;
        _act_strat_value            := _strat_value_range;
        _scoured_pages              := _scoured_pages_range;
        _primrow_cnt                := _primrow_cnt_range;
        IF  ( qp_SUBQ_usage in access_info.srec_query_prop.qps_switches )
        THEN
            BEGIN
            (* don't use SUBQ as range operator *)
            act_inv_strat.ostr_inv_in_range.siir_invstart
                  [ act_inv_strat.ostr_inv_in_range.siir_subq_idx ] := 0;
            act_inv_strat.ostr_inv_in_range.siir_invstop
                  [ act_inv_strat.ostr_inv_in_range.siir_subq_idx ] := 0;
            act_inv_strat.ostr_inv_in_range.siir_startcnt :=
                  act_inv_strat.ostr_inv_in_range.siir_subq_idx;
            act_inv_strat.ostr_inv_in_range.siir_stopcnt :=
                  act_inv_strat.ostr_inv_in_range.siir_subq_idx;
            act_inv_strat.ostr_inv_in_range.siir_subq_idx      :=
                  IS_UNDEFINED_GG07;
            act_inv_strat.ostr_inv_in_range.siir_IN_SUBQ_stpos :=
                  IS_UNDEFINED_GG07;
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        (* chose IN/SUBQ condition *)
        IF  ( qp_SUBQ_usage in access_info.srec_query_prop.qps_switches )
        THEN
            act_inv_strat.ostr_strategy := strat_inv_range_sub
        ELSE
            act_inv_strat.ostr_strategy := strat_inv_in;
        (*ENDIF*) 
        _act_strat_value := _strat_value_IN_SUBQ;
        _scoured_pages   := _scoured_pages_IN_SUBQ;
        _primrow_cnt     := _primrow_cnt_IN_SUBQ;
        END;
    (*ENDIF*) 
    END
ELSE
    BEGIN
    act_inv_strat.ostr_strategy := strat_inv_range;
    _act_strat_value            := _strat_value_range;
    _scoured_pages              := _scoured_pages_range;
    _primrow_cnt                := _primrow_cnt_range;
    END;
(*ENDIF*) 
;
IF  (( cs_enable_merge in access_info.srec_config.cfg_switches ) OR
    ( _scoured_pages <= g01max_merge ))
    AND
    (* today DITINCT OPTIM only possible by index access *)
    (* merge list constains only primary keys            *)
    ( NOT a71is_duplicate_avoidance( gg_strategy,
    act_inv_strat.ostr_strategy, act_inv_strat.ostr_raw ))
THEN
    BEGIN
    IF  ( isp_inv_only in act_inv_strat.ostr_inv_in_range.siir_strat_props )
        AND
        ( gg_strategy.str_key_order_support )
        AND
        ( NOT ( isp_order_support in
        act_inv_strat.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
            act_inv_strat.ostr_inv_in_range.siir_strat_props :=
                  act_inv_strat.ostr_inv_in_range.siir_strat_props +
                  [ isp_listmerge_allowed ];
            act_inv_strat.ostr_inv_in_range.siir_strat_props :=
                  act_inv_strat.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
        act_inv_strat.ostr_inv_in_range.siir_strat_props :=
              act_inv_strat.ostr_inv_in_range.siir_strat_props +
              [ isp_listmerge_allowed ];
    (*ENDIF*) 
    END;
(* if allowed try switching to fetch strategy *)
(*ENDIF*) 
a71check_fetch_optimization( acv, access_info.srec_config,
      access_info.srec_query_prop, gg_strategy,
      act_inv_strat.ostr_strategy, act_inv_strat.ostr_raw );
;
&ifdef trace
t01int4( ak_strat, 'act result r', act_inv_strat.ostr_result_rows );
&endif
(* calculate IO costs *)
(* index pages + primary page + page cost for ordering + build costs *)
a71calculate_pageIO( acv, sparr, access_info,
      act_inv_strat,
      key_eval_rec.er_keyinfo.ki_read_pages  (* we don't use SUBQ on key ! *),
      _primrow_cnt,
      key_eval_rec.er_keyinfo.ki_strat_value (* we don't use SUBQ on key ! *),
      _scoured_pages,
      _act_strat_value,
      gg_strategy.str_rec_len );
;
&ifdef trace
t01real( ak_strat, 'inv stratval', _act_strat_value, 3 );
a725output_invstrat( ak_strat, 'act invstrat', act_inv_strat.ostr_inv_in_range );
t01int4( ak_strat, 'act IO pages', act_inv_strat.ostr_cost_pages );
t01int4( ak_strat, 'act result p', act_inv_strat.ostr_result_pages );
t01int4( ak_strat, 'act result r', act_inv_strat.ostr_result_rows );
&endif
;
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    a727trace_invstrat( acv.a_transinf.tri_trans,
          'index data  ', act_inv_strat.ostr_inv_in_range, false );
    a727trace_costs( acv.a_transinf.tri_trans, act_inv_strat.ostr_cost_pages,
          act_inv_strat.ostr_result_pages, act_inv_strat.ostr_result_rows );
    END;
(*ENDIF*) 
;
(* remark better index access *)
IF  ( best_inv_strat.ostr_cost_pages <> IS_UNDEFINED_GG07 )
THEN
    BEGIN
    IF  ( act_inv_strat.ostr_cost_pages < best_inv_strat.ostr_cost_pages )
    THEN
        (* catch the better strategy *)
        BEGIN
&       ifdef trace
        t01sname( ak_strat, 'better inv  ' );
&       endif
        best_inv_strat     := act_inv_strat;
        acv.a_sample_pages := _invpages; (* remark best index size *)
        END;
    (*ENDIF*) 
    END
ELSE
    BEGIN
&   ifdef trace
    t01sname( ak_strat, 'init bestqul' );
&   endif
    (* initialize *)
    best_inv_strat     := act_inv_strat;
    acv.a_sample_pages := _invpages; (* remark initial index size *)
    END;
(*ENDIF*) 
&ifdef TRACE
t01int4( ak_strat, 'best IO cost', best_inv_strat.ostr_cost_pages );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720indexeval(
            VAR acv             : tak_all_command_glob;
            VAR inv_strat       : tgg07_StrInvInRange;
            VAR inv_file        : tgg00_FileId;
            VAR key_eval_rec    : t_eval_rec;
            invpages            : tsp_int4;
            VAR config          : tak70_configuration;
            VAR strat_value     : tsp_longreal; (* OUT *)
            VAR scoured_pages   : tsp_int4;     (* OUT *)
            VAR primrow_cnt     : tsp_int4);    (* OUT *)
 
VAR
      _all_invpages    : tsp_int4;
      _dummy_buf       : tgg_rec_buf;
      _startkey        : tgg_lkey;
      _stopkey         : tgg_lkey;
      _b_err           : tgg_basis_error;
 
BEGIN
&ifdef trace
a725output_colposarr( ak_strat, 'invstart    ', inv_strat.siir_invstart );
a725output_colposarr( ak_strat, 'invstop     ', inv_strat.siir_invstop );
t01sname( ak_strat, 'index eval  ' );
_dummy_buf.recLen_gg00    := 0;
_dummy_buf.recKeyLen_gg00 := 0;
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g04c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720INDEXEVAL>>            ' );
    END;
(* evaluate index access *)
(*ENDIF*) 
_b_err         := e_ok;
scoured_pages  := invpages;
strat_value    := 1;
primrow_cnt    := -1;
;
g04minv_key( acv.a_mblock, _dummy_buf, inv_strat, _startkey, _stopkey, 0 );
&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
    _b_err := e_move_error
ELSE
    BEGIN
    a06eval_page_count( acv, inv_file,
          _startkey, _stopkey,
          c_sample,
          ( cs_count_records in config.cfg_switches ),
          scoured_pages,
          _all_invpages, primrow_cnt, _b_err );
    END;
(*ENDIF*) 
IF  ( primrow_cnt < 0 )
THEN
    primrow_cnt := IS_UNDEFINED_GG07;
(*ENDIF*) 
;
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
ELSE
    BEGIN
    (* calculate access fraction *)
    IF  ( cs_count_records in config.cfg_switches ) AND
        ( primrow_cnt >= 0 )
    THEN
        (* we are in a join *)
        BEGIN
        IF  ( key_eval_rec.er_primrows = 0 ) OR ( primrow_cnt = 0 )
        THEN
            strat_value := 0
        ELSE
            IF  ( primrow_cnt > key_eval_rec.er_primrows )
            THEN
                strat_value := 1
            ELSE
                strat_value := primrow_cnt / key_eval_rec.er_primrows;
            (*ENDIF*) 
        (*ENDIF*) 
        END
    ELSE
        (* page count *)
        BEGIN
        strat_value := scoured_pages / invpages;
        END;
    (*ENDIF*) 
    ;
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        a727trace_eval( acv.a_transinf.tri_trans,
              '------- AK720INDEXEVAL -------',
              ( cs_count_records in config.cfg_switches ),
              key_eval_rec.er_primrows,
              primrow_cnt, invpages,
              _all_invpages, scoured_pages,
              strat_value );
    (*ENDIF*) 
    ;
&   ifdef trace
    t01bool( ak_strat, 'Count Record', ( cs_count_records in config.cfg_switches ));
    t01int4( ak_strat, 'all  ipages ', _all_invpages );
    t01real( ak_strat, 'strat val   ', strat_value, 3 );
    t01int4( ak_strat, 'read ipages ', scoured_pages );
    IF  ( cs_count_records in config.cfg_switches )
    THEN
        t01int4( ak_strat, 'read primrow', primrow_cnt );
&   endif
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720index_subq_eval (
            VAR acv           : tak_all_command_glob;
            VAR sparr         : tak_syspointerarr;
            VAR inv_strat     : tgg07_StrInvInRange;
            VAR inv_tree      : tgg00_FileId;
            range_pages       : tsp_int4;
            VAR key_eval_rec  : t_eval_rec;
            invpages          : tsp_int4;
            VAR config        : tak70_configuration;
            VAR strat_value   : tsp_longreal; (* OUT *)
            VAR scoured_pages : tsp_int4;     (* OUT *)
            VAR primrow_cnt   : tsp_int4);    (* OUT *)
 
VAR
      _success          : boolean;
      _scoured_pages    : tsp_int4;
      _record_cnt       : tsp_int4;
      _all_page_cnt     : tsp_int4;
      _startkey         : tgg_lkey;
      _stopkey          : tgg_lkey;
      _fract            : tsp_longreal;
      _subqtree_id      : tgg00_FileId;
      _read_info        : t_subquery_read_info;
      _subq_rowcnt      : tsp_int2;
      _aux_error        : tgg_basis_error;
      _e                : tgg_basis_error;
 
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
    g04c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720INDEX_SUBQ_EVAL>>      ' );
    END;
(*ENDIF*) 
strat_value   := 0;
scoured_pages := 0;
primrow_cnt   := IS_UNDEFINED_GG07;
;
g10mv4 ('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,
      mxgg_treeid,
      acv.a_return_segm^.sp1r_returncode);
&ifdef trace
t01treeid( ak_strat, 'subq treeid ', _subqtree_id );
t01int4( ak_strat, 'read limit  ', range_pages );
&endif
_aux_error := acv.a_return_segm^.sp1r_returncode;
_e         := e_ok;
acv.a_mblock.mb_trns^.trError_gg00 := e_ok;
_subq_rowcnt     := 0;
ak720init_read_info( _read_info, _subqtree_id );
WHILE ( _e = e_ok ) AND ( _aux_error = e_ok ) AND
      ( acv.a_mblock.mb_trns^.trError_gg00 = e_ok ) AND
      ( scoured_pages < range_pages ) DO
    BEGIN
    ak720read_subquery( acv, _read_info, _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 *)
            g04minv_key( acv.a_mblock, _read_info.sri_buf,
                  inv_strat, _startkey, _stopkey, IS_UNDEFINED_GG07 );
            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 := invpages;
                a06eval_page_count( acv, inv_tree,
                      _startkey, _stopkey,
                      c_sample,
                      ( cs_count_records in config.cfg_switches ),
                      _scoured_pages,
                      _all_page_cnt, _record_cnt, _e );
                END;
            (*ENDIF*) 
            IF  ( cs_count_records in config.cfg_switches ) AND
                ( _record_cnt < 0 )
            THEN
                _record_cnt :=
                      ak720calc_rowcnt(acv, sparr, config, _scoured_pages);
            (*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
                (* calculate access fraction *)
                IF  ( cs_count_records in config.cfg_switches )
                THEN
                    (* we are in a join *)
                    BEGIN
                    IF  ( key_eval_rec.er_primrows = 0 ) OR ( _record_cnt = 0 )
                    THEN
                        _fract := 0
                    ELSE
                        IF  ( _record_cnt > key_eval_rec.er_primrows )
                        THEN
                            _fract := 1
                        ELSE
                            _fract := _record_cnt / key_eval_rec.er_primrows;
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END
                ELSE
                    (* page count *)
                    BEGIN
                    _fract := _scoured_pages / invpages;
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            (* more than c_max_subq_eval_cnt elements *)
&           ifdef TRACE
            t01sname( ak_strat, 'use avg val ' );
&           endif
            _fract := strat_value / ( _subq_rowcnt - 1 );
            IF  ( cs_count_records in config.cfg_switches )
            THEN
                _record_cnt :=
                      trunc(( primrow_cnt / ( _subq_rowcnt - 1 )) + 1 );
            (*ENDIF*) 
            _scoured_pages :=
                  trunc(( scoured_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: scoured_pages and, if wanted, records *)
        strat_value := strat_value + _fract;
        IF  ( cs_count_records in config.cfg_switches )
        THEN
            BEGIN
            (* initialize row count *)
            IF  ( primrow_cnt = IS_UNDEFINED_GG07 )
            THEN
                primrow_cnt := 0;
            (*ENDIF*) 
            primrow_cnt := primrow_cnt + _record_cnt;
            END;
        (*ENDIF*) 
        scoured_pages := scoured_pages + _scoured_pages;
&       ifdef TRACE
        t01real( ak_strat, 'SUM stratval', strat_value, 3 );
        t01int4( ak_strat, 'SUM pages   ', scoured_pages );
        t01int4( ak_strat, 'SUM records ', primrow_cnt );
&       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 ( scoured_pages = 0 )
            THEN
                BEGIN
                strat_value := 1 / key_eval_rec.er_primpages;
                IF  ( cs_count_records in config.cfg_switches )
                THEN
                    primrow_cnt := 0;
                (*ENDIF*) 
                scoured_pages := 1;
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
IF  ( g01vtrace.vtrStrategy_gg00 ) AND ( _scoured_pages >= range_pages )
THEN
    BEGIN
    g04c30_to_trace( acv.a_transinf.tri_trans,
          'exceed strat limit!           ' );
    END;
(*ENDIF*) 
IF  ( strat_value = 0 )
THEN
    BEGIN
    strat_value    := 1;
    scoured_pages  := range_pages + 1;
    END;
(*ENDIF*) 
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    a727trace_eval( acv.a_transinf.tri_trans,
          '--- AK720INDEX_SUBQ_EVAL -----',
          ( cs_count_records in config.cfg_switches ),
          key_eval_rec.er_primrows,
          primrow_cnt, invpages,
          _all_page_cnt, scoured_pages,
          strat_value );
(*ENDIF*) 
;
&ifdef TRACE
t01bool( ak_strat, 'Count Record', ( cs_count_records in config.cfg_switches ));
t01int4( ak_strat, 'prim  rows  ', key_eval_rec.er_primrows );
t01int4( ak_strat, 'prim  pages ', key_eval_rec.er_primpages );
t01int4( ak_strat, 'min page cnt', _all_page_cnt );
t01int4( ak_strat, 'read ipages ', scoured_pages );
t01int4( ak_strat, 'read prows  ', primrow_cnt );
t01real( ak_strat, 'strat value ', strat_value, 3 );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720index_in_eval (
            VAR acv           : tak_all_command_glob;
            VAR sparr         : tak_syspointerarr;
            VAR inv_strat     : tgg07_StrInvInRange;
            VAR inv_tree      : tgg00_FileId;
            range_pages       : tsp_int4;
            VAR key_eval_rec  : t_eval_rec;
            invpages          : tsp_int4;
            VAR config        : tak70_configuration;
            VAR strat_value   : tsp_longreal;
            VAR scoured_pages : tsp_int4;
            VAR primrow_cnt   : tsp_int4);
 
VAR
      _ix               : tsp_int2;
      _st_dummy_cnt     : tsp_int2;
      _in_stack         : tsp_int2;
      _scoured_pages    : tsp_int4;
      _record_cnt       : tsp_int4;
      _all_page_cnt     : tsp_int4;
      _startkey         : tgg_lkey;
      _stopkey          : tgg_lkey;
      _fract            : tsp_longreal;
      _dummy_buf        : tgg_rec_buf;
      _e                : tgg_basis_error;
 
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*) 
_dummy_buf.recLen_gg00    := 0;
_dummy_buf.recKeyLen_gg00 := 0;
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g04c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720INDEX_IN_EVAL>>        ' );
    END;
(*ENDIF*) 
strat_value   := 0;
scoured_pages := 0;
primrow_cnt   := IS_UNDEFINED_GG07;
;
_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 ) AND
      (( scoured_pages < range_pages ) OR (cs_IN_strategy in config.cfg_switches )) 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
        g04minv_key( acv.a_mblock, _dummy_buf, inv_strat,
              _startkey, _stopkey,
              _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 := invpages;
            a06eval_page_count( acv, inv_tree,
                  _startkey, _stopkey,
                  c_sample,
                  ( cs_count_records in config.cfg_switches ),
                  _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  ( cs_count_records in config.cfg_switches ) AND
            ( _record_cnt < 0 )
        THEN
            _record_cnt :=
                  ak720calc_rowcnt(acv, sparr, config, _scoured_pages);
        (*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
            (* calculate access fraction *)
            IF  ( cs_count_records in config.cfg_switches )
            THEN
                (* we are in a join *)
                BEGIN
                IF  ( key_eval_rec.er_primrows = 0 ) OR ( _record_cnt = 0 )
                THEN
                    _fract := 0
                ELSE
                    IF  ( _record_cnt > key_eval_rec.er_primrows )
                    THEN
                        _fract := 1
                    ELSE
                        _fract := _record_cnt / key_eval_rec.er_primrows;
                    (*ENDIF*) 
                (*ENDIF*) 
                END
            ELSE
                (* page count *)
                BEGIN
                _fract := _scoured_pages / invpages;
                END;
            (*ENDIF*) 
            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: scoured_pages and, if wanted, records *)
        strat_value := strat_value + _fract;
        IF  ( cs_count_records in config.cfg_switches )
        THEN
            BEGIN
            (* initialize row count *)
            IF  ( primrow_cnt = IS_UNDEFINED_GG07 )
            THEN
                primrow_cnt := 0;
            (*ENDIF*) 
            primrow_cnt := primrow_cnt + _record_cnt;
            END;
        (*ENDIF*) 
        scoured_pages := scoured_pages + _scoured_pages;
&       ifdef TRACE
        t01real( ak_strat, 'SUM stratval', strat_value, 3 );
        t01int4( ak_strat, 'SUM pages   ', scoured_pages );
        t01int4( ak_strat, 'SUM primrows', primrow_cnt );
&       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*) 
;
IF  ( g01vtrace.vtrStrategy_gg00 ) AND ( _scoured_pages >= range_pages )
THEN
    BEGIN
    g04c30_to_trace( acv.a_transinf.tri_trans,
          'exceed strat limit!           ' );
    END;
(*ENDIF*) 
IF  ( strat_value = 0 )
THEN
    BEGIN
    strat_value := 1;
    scoured_pages  := range_pages + 1;
    END;
(*ENDIF*) 
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    a727trace_eval( acv.a_transinf.tri_trans,
          '----- AK720INDEX_IN_EVAL -----',
          ( cs_count_records in config.cfg_switches ),
          key_eval_rec.er_primrows,
          primrow_cnt, invpages,
          _all_page_cnt, scoured_pages,
          strat_value );
(*ENDIF*) 
;
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720keyeval (
            VAR acv            : tak_all_command_glob;
            VAR sparr          : tak_syspointerarr;
            VAR keystart       : tgg07_ColPosArr;
            VAR keystop        : tgg07_ColPosArr;
            in_stack           : tsp_int2;
            in_elemcnt         : tsp_int2;
            VAR eval_rec       : t_eval_rec;
            VAR config         : tak70_configuration);
 
VAR
      _use_stopkey   : boolean;
      _all_page_cnt  : tsp_int4;
      _scoured_pages : tsp_int4;
      _strat_value   : tsp_longreal;
      _startkey      : tgg_lkey;
      _stopkey       : tgg_lkey;
      _e             : tgg_basis_error;
      _record_cnt    : tsp_int4;
 
BEGIN
&ifdef trace
a725output_colposarr( ak_strat, 'keystart    ', keystart );
a725output_colposarr( ak_strat, 'keystop     ', keystop );
t01int4( ak_strat, 'IN stack    ', in_stack );
t01int4( ak_strat, 'IN elemcnt  ', in_elemcnt );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g04c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720KEYEVAL>>              ' );
    END;
(*ENDIF*) 
_strat_value := 1;  (* full range *)
_use_stopkey := true;
g04limitprimkeys( acv.a_mblock, keystart, _startkey,
      keystop, _stopkey, _use_stopkey, in_stack, -in_elemcnt );
&ifdef trace
t01key( ak_strat, 'startkey    ', _startkey );
t01key( ak_strat, 'stopkey     ', _stopkey );
t01bool( ak_strat, 'use stopkey ', _use_stopkey );
&endif
IF  ( acv.a_mblock.mb_trns^.trError_gg00 = e_move_error )
THEN
    acv.a_return_segm^.sp1r_returncode :=
          a07_return_code( e_move_error, acv.a_sqlmode );
(*ENDIF*) 
IF  ( acv.a_return_segm^.sp1r_returncode = 0 )
THEN
    BEGIN
    _all_page_cnt  := 0;
    IF  (( _use_stopkey ) OR ( _startkey.len > 0 ))
    THEN
        BEGIN
        _scoured_pages := eval_rec.er_primpages;
        _record_cnt    := -1;
        _e             := e_ok;
        a06eval_page_count( acv, acv.a_mblock.mb_qual^.mtree,
              _startkey, _stopkey,
              c_sample,
              ( cs_count_records in config.cfg_switches ),
              _scoured_pages, _all_page_cnt, _record_cnt, _e );
        ;
        IF  ( cs_count_records in config.cfg_switches ) AND
            ( _record_cnt < 0 )
        THEN
            _record_cnt :=
                  ak720calc_rowcnt(acv, sparr, config, _scoured_pages);
        (*ENDIF*) 
        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  ( cs_count_records in config.cfg_switches )
            THEN
                (* record count *)
                BEGIN
                IF  (( eval_rec.er_primrows = 0 ) OR ( _record_cnt = 0 ))
                THEN
                    _strat_value := c_almost_zero
                ELSE
                    IF  ( _record_cnt > eval_rec.er_primrows )
                    THEN
                        _strat_value := 1
                    ELSE
                        _strat_value := _record_cnt / eval_rec.er_primrows;
                    (*ENDIF*) 
                (*ENDIF*) 
                END
            ELSE
                (* page count *)
                BEGIN
                _strat_value :=
                      _scoured_pages / eval_rec.er_primpages;
                END;
            (*ENDIF*) 
            eval_rec.er_keyinfo.ki_strat_value := _strat_value;
            IF  ( cs_count_records in config.cfg_switches )
            THEN
                eval_rec.er_keyinfo.ki_read_rows  := _record_cnt;
            (*ENDIF*) 
            eval_rec.er_keyinfo.ki_read_pages := _scoured_pages;
            ;
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        eval_rec.er_keyinfo.ki_read_pages := eval_rec.er_primpages;
        IF  ( cs_count_records in config.cfg_switches )
        THEN
            eval_rec.er_keyinfo.ki_read_rows := eval_rec.er_primrows;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        a727trace_eval( acv.a_transinf.tri_trans,
              '-------- AK720KEYEVAL --------',
              ( cs_count_records in config.cfg_switches ),
              eval_rec.er_primrows,
              eval_rec.er_keyinfo.ki_read_rows, eval_rec.er_primpages,
              _all_page_cnt, eval_rec.er_keyinfo.ki_read_pages,
              eval_rec.er_keyinfo.ki_strat_value );
    (*ENDIF*) 
    ;
&   ifdef trace
    t01bool( ak_strat, 'Count Record', ( cs_count_records in
          config.cfg_switches ));
    t01int4( ak_strat, 'Prime rows  ', eval_rec.er_primrows );
    IF  ( cs_count_records in config.cfg_switches )
    THEN
        t01int4( ak_strat, 'found rows  ', eval_rec.er_keyinfo.ki_read_rows );
    (*ENDIF*) 
    t01int4( ak_strat, 'prim  pages ', eval_rec.er_primpages );
    t01int4( ak_strat, 'min page cnt', _all_page_cnt );
    t01int4( ak_strat, 'found pages ', eval_rec.er_keyinfo.ki_read_pages );
    t01real( ak_strat, 'strat val   ', eval_rec.er_keyinfo.ki_strat_value, 3 );
&   endif
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720key_in_eval (
            VAR acv            : tak_all_command_glob;
            VAR sparr          : tak_syspointerarr;
            VAR keystart       : tgg07_ColPosArr;
            VAR keystop        : tgg07_ColPosArr;
            VAR in_stack       : tsp_int2;
            VAR in_cnt         : tsp_int2;
            VAR eval_rec       : t_eval_rec;
            VAR config         : tak70_configuration);
 
VAR
      _use_stopkey     : boolean;
      _iy              : tsp_int2;
      _st_dummy_cnt    : tsp_int2;
      _all_page_cnt    : tsp_int4;
      _scoured_pages   : tsp_int4;
      _strat_value     : tsp_longreal;
      _searchkey1      : tgg_lkey;
      _searchkey2      : tgg_lkey;
      _e               : tgg_basis_error;
      _record_cnt      : tsp_int4;
 
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*) 
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g04c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720KEY_IN_EVAL>>          ' );
    END;
(*ENDIF*) 
eval_rec.er_keyinfo.ki_stat_in_subq.kisi_strat_value := 0;
_strat_value  := 1;  (* full range *)
_st_dummy_cnt := 0;
_iy           := 1;
WHILE ( _iy <= in_cnt ) AND ( acv.a_return_segm^.sp1r_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_return_segm^.sp1r_returncode :=
                  a07_return_code( e_move_error, acv.a_sqlmode );
        (*ENDIF*) 
        IF  ( acv.a_return_segm^.sp1r_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 := eval_rec.er_primpages;
                _record_cnt    := -1;
                _e             := e_ok;
                a06eval_page_count( acv, acv.a_mblock.mb_qual^.mtree,
                      _searchkey1, _searchkey2,
                      c_sample,
                      ( cs_count_records in config.cfg_switches ),
                      _scoured_pages, _all_page_cnt, _record_cnt, _e );
                ;
                IF  ( cs_count_records in config.cfg_switches ) AND
                    ( _record_cnt < 0 )
                THEN
                    _record_cnt :=
                          ak720calc_rowcnt(acv, sparr, config, _scoured_pages);
                (*ENDIF*) 
                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  ( cs_count_records in config.cfg_switches )
                    THEN
                        (* record count *)
                        BEGIN
                        IF  (( eval_rec.er_primrows = 0 ) OR
                            ( _record_cnt = 0 ))
                        THEN
                            _strat_value := c_almost_zero
                        ELSE
                            IF  ( _record_cnt > eval_rec.er_primrows )
                            THEN
                                _strat_value := 1
                            ELSE
                                _strat_value :=
                                      _record_cnt / eval_rec.er_primrows;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END
                    ELSE
                        (* page count *)
                        BEGIN
                        _strat_value :=
                              _scoured_pages / eval_rec.er_primpages;
                        END;
                    (*ENDIF*) 
                    eval_rec.er_keyinfo.ki_stat_in_subq.kisi_strat_value :=
                          eval_rec.er_keyinfo.ki_stat_in_subq.kisi_strat_value +
                          _strat_value;
                    IF  ( cs_count_records in config.cfg_switches )
                    THEN
                        BEGIN
                        (* initialize row count *)
                        IF  ( eval_rec.er_keyinfo.ki_stat_in_subq.
                            kisi_read_rows = IS_UNDEFINED_GG07 )
                        THEN
                            eval_rec.er_keyinfo.ki_stat_in_subq.
                                  kisi_read_rows := 0;
                        (*ENDIF*) 
                        eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_rows :=
                              eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_rows +
                              _record_cnt;
                        END;
                    (*ENDIF*) 
                    eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages :=
                          eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages +
                          _scoured_pages;
                    IF  ( eval_rec.er_keyinfo.ki_stat_in_subq.
                        kisi_read_pages >= eval_rec.er_keyinfo.ki_read_pages )
                    THEN
                        IF  NOT ( cs_IN_strategy in config.cfg_switches )
                        THEN
                            BEGIN
&                           ifdef trace
                            t01name( ak_strat, 'exceed strat limit' );
                            t01int4( ak_strat, 'IN read page',
                                  eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages );
                            t01int4( ak_strat, 'key read pag',
                                  eval_rec.er_keyinfo.ki_read_pages );
&                           endif
                            _iy := in_cnt; (* break through REPEAT *)
                            eval_rec.er_keyinfo.ki_stat_in_subq.
                                  kisi_strat_value := 1;
                            eval_rec.er_keyinfo.ki_stat_in_subq.
                                  kisi_read_pages := eval_rec.
                                  er_keyinfo.ki_read_pages + 1;
                            IF  ( g01vtrace.vtrStrategy_gg00 )
                            THEN
                                BEGIN
                                g04c30_to_trace( acv.a_transinf.tri_trans,
                                      'exceed strat limit!           ' );
                                END;
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
&               ifdef trace
                t01bool( ak_strat, 'Count Record', ( cs_count_records in
                      config.cfg_switches ));
                t01int4( ak_strat, 'Prime rows  ', eval_rec.er_primrows );
                t01int4( ak_strat, 'found rows  ', _record_cnt );
                t01int4( ak_strat, 'prim  pages ', eval_rec.er_primpages );
                t01int4( ak_strat, 'min page cnt', _all_page_cnt );
                t01int4( ak_strat, 'found pages ', _scoured_pages );
                t01real( ak_strat, 'single fract', _strat_value, 3 );
                t01int4( ak_strat, 'IN read page',
                      eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages );
&               endif
                END
            ELSE
                BEGIN
&               ifdef trace
                t01name( ak_strat, 'exceed strat limit' );
&               endif
                _iy := in_cnt; (* break through REPEAT *)
                eval_rec.er_keyinfo.ki_stat_in_subq.
                      kisi_strat_value := 1;
                eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages :=
                      eval_rec.er_keyinfo.ki_read_pages + 1;
                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.er_keyinfo.ki_stat_in_subq.kisi_strat_value = 0 )
THEN
    BEGIN
    eval_rec.er_keyinfo.ki_stat_in_subq.kisi_strat_value := 1;
    eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages  :=
          eval_rec.er_keyinfo.ki_read_pages + 1;
    END;
(*ENDIF*) 
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    a727trace_eval( acv.a_transinf.tri_trans,
          '------ AK720KEY_IN_EVAL ------',
          ( cs_count_records in config.cfg_switches ),
          eval_rec.er_primrows,
          eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_rows,
          eval_rec.er_primpages, _all_page_cnt,
          eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages,
          eval_rec.er_keyinfo.ki_stat_in_subq.kisi_strat_value );
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720key_subq_eval (
            VAR acv         : tak_all_command_glob;
            VAR sparr       : tak_syspointerarr;
            VAR keystart    : tgg07_ColPosArr;
            VAR keystop     : tgg07_ColPosArr;
            subq_stpos      : tsp_int2;
            VAR eval_rec    : t_eval_rec;
            VAR config      : tak70_configuration);
 
VAR
      _success          : boolean;
      _use_stopkey      : boolean;
      _subq_rowcnt      : tsp_int2;
      _scoured_pages    : tsp_int4;
      _all_page_cnt     : tsp_int4;
      _record_cnt       : tsp_int4;
      _fract            : tsp_longreal;
      _startkey         : tgg_lkey;
      _stopkey          : tgg_lkey;
      _search_id        : tgg00_FileId;
      _subqtree_id      : tgg00_FileId;
      _read_info        : t_subquery_read_info;
      _aux_error        : tgg_basis_error;
      _e                : tgg_basis_error;
 
BEGIN
&ifdef trace
a725output_colposarr( ak_strat, 'keystart    ', keystart );
a725output_colposarr( ak_strat, 'keystop     ', keystop );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g04c30_to_trace( acv.a_transinf.tri_trans,
          '>>AK720KEY_SUBQ_EVAL>>        ' );
    END;
(*ENDIF*) 
eval_rec.er_keyinfo.ki_subq_strat := true; (* we have SUBQ stackentries *)
eval_rec.er_keyinfo.ki_stat_in_subq.kisi_strat_value := 0;
_search_id := acv.a_mblock.mb_qual^.mtree;
g10mv4 ('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, mxgg_treeid,
      acv.a_return_segm^.sp1r_returncode);
&ifdef trace
t01treeid( ak_strat, 'subq treeid ', _subqtree_id );
t01int4( ak_strat, 'read limit  ', eval_rec.er_keyinfo.ki_read_pages );
&endif
_aux_error := acv.a_return_segm^.sp1r_returncode;
_e         := e_ok;
acv.a_mblock.mb_trns^.trError_gg00 := e_ok;
_subq_rowcnt := 0;
ak720init_read_info( _read_info, _subqtree_id );
WHILE ( _e = e_ok ) AND ( _aux_error = e_ok ) AND
      ( acv.a_mblock.mb_trns^.trError_gg00 = e_ok ) AND
      ( eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages <
      eval_rec.er_keyinfo.ki_read_pages ) DO
    BEGIN
    ak720read_subquery( acv, _read_info, _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;
            gg04subq_limitkey( acv.a_mblock, _read_info.sri_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;
                gg04subq_limitkey( acv.a_mblock, _read_info.sri_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 := eval_rec.er_primpages;
            IF  ( _e = e_ok )
            THEN
                a06eval_page_count( acv, _search_id,
                      _startkey, _stopkey,
                      c_sample,
                      ( cs_count_records in config.cfg_switches ),
                      _scoured_pages,
                      _all_page_cnt, _record_cnt, _e);
            (*ENDIF*) 
            IF  ( cs_count_records in config.cfg_switches ) AND
                ( _record_cnt < 0 )
            THEN
                _record_cnt :=
                      ak720calc_rowcnt(acv, sparr, config, _scoured_pages);
            (*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  ( cs_count_records in config.cfg_switches )
                THEN
                    (* record count *)
                    BEGIN
                    IF  ( eval_rec.er_primrows = 0 ) OR
                        ( _record_cnt = 0 )
                    THEN
                        _fract := c_almost_zero
                    ELSE
                        IF  ( _record_cnt > eval_rec.er_primrows )
                        THEN
                            _fract := 1
                        ELSE
                            _fract := _record_cnt / eval_rec.er_primrows;
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END
                ELSE
                    (* page count *)
                    BEGIN
                    _fract := _scoured_pages / eval_rec.er_primpages;
                    END;
                (*ENDIF*) 
                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.er_keyinfo.ki_stat_in_subq.kisi_strat_value /
                  ( _subq_rowcnt - 1 );
            IF  ( cs_count_records in config.cfg_switches )
            THEN
                _record_cnt :=
                      trunc(( eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_rows /
                      ( _subq_rowcnt - 1 )) + 1 );
            (*ENDIF*) 
            _scoured_pages :=
                  trunc(( eval_rec.er_keyinfo.ki_stat_in_subq.kisi_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.er_keyinfo.ki_stat_in_subq.kisi_strat_value :=
                  eval_rec.er_keyinfo.ki_stat_in_subq.kisi_strat_value + _fract;
            IF  ( cs_count_records in config.cfg_switches )
            THEN
                BEGIN
                (* initialize row count *)
                IF  ( eval_rec.er_keyinfo.ki_stat_in_subq.
                    kisi_read_rows = IS_UNDEFINED_GG07 )
                THEN
                    eval_rec.er_keyinfo.ki_stat_in_subq.
                          kisi_read_rows := 0;
                (*ENDIF*) 
                eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_rows :=
                      eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_rows +
                      _record_cnt;
                END;
            (*ENDIF*) 
            eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages :=
                  eval_rec.er_keyinfo.ki_stat_in_subq.kisi_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.er_keyinfo.ki_stat_in_subq.kisi_read_pages = 0 )
            THEN
                BEGIN
                eval_rec.er_keyinfo.ki_stat_in_subq.kisi_strat_value :=
                      1 / eval_rec.er_primpages;
                IF  ( cs_count_records in config.cfg_switches )
                THEN
                    eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_rows  := 0;
                (*ENDIF*) 
                eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages  := 1;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
IF  ( eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages <
    eval_rec.er_keyinfo.ki_read_pages )
THEN
    BEGIN
    g04c30_to_trace( acv.a_transinf.tri_trans,
          'exceed strat limit!           ' );
    END;
(*ENDIF*) 
IF  ( eval_rec.er_keyinfo.ki_stat_in_subq.kisi_strat_value = 0 )
THEN
    BEGIN
    eval_rec.er_keyinfo.ki_stat_in_subq.kisi_strat_value := 1;
    eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages  :=
          eval_rec.er_keyinfo.ki_read_pages + 1;
    END;
(*ENDIF*) 
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    a727trace_eval( acv.a_transinf.tri_trans,
          '---- AK720KEY_SUBQ_EVAL ------',
          ( cs_count_records in config.cfg_switches ),
          eval_rec.er_primrows,
          eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_rows,
          eval_rec.er_primpages, _all_page_cnt,
          eval_rec.er_keyinfo.ki_stat_in_subq.kisi_read_pages,
          eval_rec.er_keyinfo.ki_stat_in_subq.kisi_strat_value );
(*ENDIF*) 
;
&ifdef TRACE
t01bool( ak_strat, 'Count Record', ( cs_count_records in config.cfg_switches ));
t01int4( ak_strat, 'prim  rows  ', eval_rec.er_primrows );
t01int4( ak_strat, 'prim  pages ', eval_rec.er_primpages );
t01int4( ak_strat, 'min page cnt', _all_page_cnt );
t01int4( ak_strat, 'read ppages ', eval_rec.er_keyinfo.ki_stat_in_subq.
      kisi_read_pages );
t01int4( ak_strat, 'read prows  ', eval_rec.er_keyinfo.ki_stat_in_subq.
      kisi_read_rows );
t01real( ak_strat, 'strat value ', eval_rec.er_keyinfo.ki_stat_in_subq.
      kisi_strat_value, 3 );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720init_read_info (
            VAR read_info : t_subquery_read_info;
            VAR subq_tree : tgg00_FileId);
 
BEGIN
read_info.sri_pos       := 1;
read_info.sri_len       := 0;
read_info.sri_tree      := subq_tree;
read_info.sri_error     := e_buffer_limit;
read_info.sri_key.len   := 0
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720read_subquery (
            VAR acv         : tak_all_command_glob;
            VAR read_info   : t_subquery_read_info;
            VAR aux_error   : tgg_basis_error;
            VAR ok          : boolean);
 
BEGIN
&ifdef trace
t01int4( ak_strat, 'sri_pos     ', read_info.sri_pos );
&endif
g04read_subquery( acv.a_mblock, read_info.sri_buf,
      read_info.sri_tree, read_info.sri_key, aux_error, ok );
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720get_invstrat_info (
            VAR acv           : tak_all_command_glob;
            VAR access_info   : tak70_strategy_record;
            out_keyseqlen     : tsp_int2;
            VAR inv_strat     : tak70_one_strat;
            VAR index_def     : tak_multindex;
            VAR order_fields  : tak00_ord_fields;
            VAR usable        : boolean);
 
VAR
      _msg         : tsp_c30;
      _ix          : tsp_int4;
      _index_tree  : tgg00_FileId;
 
BEGIN
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    _msg := '------- INDEXSTRATEGY --------';
    g04c30_to_trace( acv.a_transinf.tri_trans, _msg );
    g04name_to_trace( acv.a_transinf.tri_trans, index_def.indexn_prefix );
    END;
(*ENDIF*) 
inv_strat.ostr_strategy     := strat_undecided;
inv_strat.ostr_cost_pages   := IS_UNDEFINED_GG07;
inv_strat.ostr_result_pages := IS_UNDEFINED_GG07;
inv_strat.ostr_result_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_filler        := '   ';
    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        := index_def.icount;
    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;
    ;
    FOR _ix := 1 TO index_def.icount 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*) 
    ;
    ak720test_invstrat_props( access_info, out_keyseqlen,
          inv_strat, index_def, order_fields );
    ;
    a71create_inv_sequence( acv, access_info, inv_strat, index_def );
    ;
    IF  ( qp_missing_value 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
        g04c30_to_trace( acv.a_transinf.tri_trans,
              'index not accessible!         ' );
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720test_invstrat_props (
            VAR access_info : tak70_strategy_record;
            out_keyseqlen   : tsp_int2;
            VAR inv_strat   : tak70_one_strat;
            VAR index_def   : tak_multindex;
            VAR order_fields: tak00_ord_fields);
 
VAR
      _iseq_is_oseq       : boolean;
      _all_cols_contained : boolean;
      _const_icol         : boolean;
      _ix                 : tsp_int2;
      _index_cnt          : tsp_int2;
      _dummy_int          : tsp_int2;
      _out_invseqlen      : tsp_int2;
      _found_const_icols  : SET OF 1..MAX_COL_PER_TAB_GG00;
 
BEGIN
IF  ( cs_check_order in access_info.srec_config.cfg_switches )
THEN
    (* check order support of this index *)
    BEGIN
&   ifdef trace
    t01name( ak_strat, 'check order supprt' );
&   endif
    _ix := 1;
    _index_cnt := 1;
    _found_const_icols := [];
    _iseq_is_oseq  := ( order_fields.ocntord <= index_def.icount );
    WHILE ( _iseq_is_oseq AND ( _ix <= order_fields.ocntord ) ) DO
        BEGIN
        _const_icol := false;
        IF  ( index_def.icolstack[ _ix ].eop in [ op_order_asc, op_unique ] )
            <>
            ( is_order_asc in order_fields.ofield[ _ix ].ofasc )
        THEN
            (* ORDER BY with index access impossible *)
            _iseq_is_oseq := false
        ELSE
            BEGIN
&           ifdef trace
            t01int4( ak_strat, 'offno       ', order_fields.ofield[ _ix ].offno );
&           endif
            (* compare with _index_cnt. key column *)
            IF  ( index_def.icolseq[ _ix ] <> order_fields.ofield[ _ix ].offno )
            THEN
                BEGIN
                (* if i.key column has an equal condition this is OK *)
                IF  (( inv_strat.ostr_inv_in_range.siir_startcnt >= _index_cnt ) AND
                    ( inv_strat.ostr_inv_in_range.siir_stopcnt   >= _index_cnt ) AND
                    ( inv_strat.ostr_inv_in_range.siir_invstart[_index_cnt - 1] =
                    inv_strat.ostr_inv_in_range.siir_invstop[_index_cnt - 1] ) AND
                    (* it isn't a IN condition *)
                    ( inv_strat.ostr_inv_in_range.siir_IN_SUBQ_stpos <>
                    inv_strat.ostr_inv_in_range.siir_invstart[_index_cnt - 1] ))
                    OR
                    ( order_fields.ofield[ _ix ].offno in _found_const_icols )
                THEN
                    BEGIN
                    (* there's an equal condition on the _key_cnt. key column *)
                    (* we hope further more that order column is key column*)
&                   ifdef trace
                    IF  ( order_fields.ofield[ _ix ].offno in _found_const_icols )
                    THEN
                        t01name( ak_strat, 'ocol already found' )
                    ELSE
                        t01name( ak_strat, 'equal cond on idx ' );
                    (*ENDIF*) 
&                   endif
                    _found_const_icols := _found_const_icols +
                          [ index_def.icolseq[ _ix ] ];
                    _const_icol := true;
                    END
                ELSE
                    BEGIN
&                   ifdef trace
                    t01name( ak_strat, 'no equal key cond ' );
&                   endif
                    _iseq_is_oseq := false;
                    END;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                (* i. order column is _const_ind + i. index column --> OK *)
&               ifdef trace
                t01name( ak_strat, 'i. ord  in idx seq' );
&               endif
                END ;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        _index_cnt := succ( _index_cnt );
        IF  NOT _const_icol
        THEN
            _ix := succ( _ix );
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  ( _iseq_is_oseq )
    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 ];
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
(* check if qualification columns are in icolseq or key *)
(* all output columns are indexed 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, _out_invseqlen );
;
IF  ( _all_cols_contained )
THEN
    BEGIN
&   ifdef trace
    t01name( ak_strat, 'all ocol in index ' );
    t01int4( ak_strat, 'out kseqlen ', out_keyseqlen );
    t01int4( ak_strat, 'out iseqlen ', _out_invseqlen );
&   endif
    (* all output columns in actual index/key          *)
    IF  ( out_keyseqlen <> NOT_SEQUENCED_GG07 )
        (* there are dist optim on key *)
        AND
        ((( _out_invseqlen < inv_strat.ostr_inv_in_range.siir_invlen ) AND
        ( out_keyseqlen = KEYSEQLEN_OFFSET_GG07 ))
        OR
        (( _out_invseqlen = inv_strat.ostr_inv_in_range.siir_invlen ) AND
        ( 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 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, _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*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak720content_check (
            VAR sequence        : tak_colsequence;
            VAR sequencecnt     : tsp_int1;
            VAR ref_keyposarr   : tgg07_ColPosArr;
            VAR ref_keyposarrcnt: tsp_int1;
            VAR ref_indexdef    : tak_multindex;
            VAR seq_in_ref      : boolean;
            VAR out_invseqlen   : tsp_int2);
 
VAR
      _diff_col_found : boolean;
      _ix             : tsp_int4;
      _iy             : tsp_int4;
      _iz             : tsp_int4;
      _found_icolseq  : tak_colsequence;
 
BEGIN
FOR _ix := 1 TO MAX_COL_SEQUENCE_GG00 DO
    _found_icolseq[ _ix ] := 0;
(*ENDFOR*) 
out_invseqlen := IS_UNDEFINED_GG07;
_ix         := 1;
seq_in_ref  := true;
IF  ( sequencecnt > 0 )
THEN
    BEGIN
    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 <= ref_indexdef.icount ) 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
            _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 < ref_indexdef.icount ) 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: tsp_int2;
            VAR eval_info    : tak70_page_eval_rec;
            L1_pageIO        : tsp_int4;
            VAR keystart     : tgg07_ColPosArr;
            VAR keystop      : tgg07_ColPosArr);
 
VAR
      _inv_strat_val  : tsp_longreal;
      _inv_pages      : tsp_int2;
      _key_strat      : tak70_one_strat;
      _eval_rec       : t_eval_rec;
 
BEGIN
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g04c30_to_trace( acv.a_transinf.tri_trans,
          '>>A720DECIDE_L2_RANGE>>       ' );
    END;
(*ENDIF*) 
_key_strat.ostr_strategy     := strat_key_range;
_key_strat.ostr_cost_pages   := IS_UNDEFINED_GG07;
_key_strat.ostr_result_pages := IS_UNDEFINED_GG07;
_key_strat.ostr_result_rows  := IS_UNDEFINED_GG07;
_key_strat.ostr_key_in_range.skir_keystart := keystart;
_key_strat.ostr_key_in_range.skir_keystop  := keystop;
_key_strat.ostr_key_in_range.skir_IN_SUBQ_stpos := 0;
_key_strat.ostr_key_in_range.skir_inelemcnt     := 0;
;
g04find_in_stack( acv.a_mblock, keystart,
      _key_strat.ostr_key_in_range.skir_IN_SUBQ_stpos,
      _key_strat.ostr_key_in_range.skir_inelemcnt );
IF  ( _key_strat.ostr_key_in_range.skir_IN_SUBQ_stpos = 0 )
THEN
    g04find_in_stack( acv.a_mblock, keystop,
          _key_strat.ostr_key_in_range.skir_IN_SUBQ_stpos,
          _key_strat.ostr_key_in_range.skir_inelemcnt );
(*ENDIF*) 
;
_eval_rec := a720_strat_eval_rec;
ak720get_file_samples( acv, sparr, acv.a_mblock.mb_qual^.mtree,
      _eval_rec.er_primpages, _eval_rec.er_primrows,
      access_info.srec_config);
;
IF  ( acv.a_return_segm^.sp1r_returncode = 0 ) AND
    (( keystart[ 0 ] > 0 ) OR ( keystop [ 0 ] > 0 ))
THEN
    BEGIN
    (* there is key access path *)
    ak720keyeval( acv, sparr, keystart, keystop,
          _key_strat.ostr_key_in_range.skir_IN_SUBQ_stpos,
          _key_strat.ostr_key_in_range.skir_inelemcnt,
          _eval_rec, access_info.srec_config );
    END
ELSE
    BEGIN
    _eval_rec.er_keyinfo.ki_read_pages := _eval_rec.er_primpages;
    IF  ( cs_count_records in access_info.srec_config.cfg_switches )
    THEN
        _eval_rec.er_keyinfo.ki_read_rows := _eval_rec.er_primrows;
    (*ENDIF*) 
    END;
(*ENDIF*) 
&ifdef trace
t01int4( ak_strat, 'prim pages  ', _eval_rec.er_primpages );
t01real( ak_strat, 'KEY value   ', _eval_rec.er_keyinfo.ki_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,
      _key_strat.ostr_strategy, _key_strat.ostr_raw );
;
(* calculate IO costs *)
(* primary page + page cost for ordering + build costs *)
_inv_strat_val := 0;
_inv_pages     := 0;
;
a71calculate_pageIO( acv, sparr, access_info,
      _key_strat,
      _eval_rec.er_keyinfo.ki_read_pages,
      _eval_rec.er_keyinfo.ki_read_rows,
      _eval_rec.er_keyinfo.ki_strat_value,
      _inv_pages, _inv_strat_val, gg_strategy.str_rec_len );
;
&ifdef trace
t01int4( ak_strat, 'L1 page IO  ', L1_pageIO );
t01int4( ak_strat, 'L2 page IO  ', _key_strat.ostr_cost_pages );
&endif
IF  ( _key_strat.ostr_cost_pages < L1_pageIO )
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     := strat_key_range;
    gg_strategy.str_key_in_range := _key_strat.ostr_key_in_range;
    StratInfo_len := STRATEGY_START_MXGG07 +
          sizeof( gg_strategy.str_key_in_range );
    IF  ( cs_costcheck in access_info.srec_config.cfg_switches )
    THEN
        BEGIN
        eval_info.pev_cost_pages   := _key_strat.ostr_cost_pages;
        eval_info.pev_result_pages := _key_strat.ostr_result_pages;
        eval_info.pev_result_rows  := _key_strat.ostr_result_rows;
        END;
    (*ENDIF*) 
    ;
&   ifdef TRACE
    t01name( ak_strat, 'no several strats ' );
    t01name( ak_strat, 'ONE KEY RANGE     ' );
&   endif
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        g04c30_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
        g04c30_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
    er_keyinfo.ki_strat_value   := 1;
    er_keyinfo.ki_read_pages    := 0;
    er_keyinfo.ki_read_rows     := IS_UNDEFINED_GG07;
    er_keyinfo.ki_subq_strat    := false;
    er_keyinfo.ki_stat_in_subq.kisi_strat_value := 1;
    er_keyinfo.ki_stat_in_subq.kisi_read_pages  := 0;
    er_keyinfo.ki_stat_in_subq.kisi_read_rows   := IS_UNDEFINED_GG07;
    (**)
    er_primpages  := 1;
    er_primrows   := 0;
    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   : tsp_int4;
            VAR row_count    : tsp_int4;
            VAR config       : tak70_configuration);
 
VAR
      _all_page_cnt : tsp_int4;
      _startkey     : tgg_lkey;
      _stopkey      : tgg_lkey;
      _e            : tgg_basis_error;
      _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 config.cfg_switches);
(*ENDIF*) 
IF  (file_id.fileTfn_gg00 = tfnTemp_egg00) AND
    (file_id.fileTfnTemp_gg00 <> ttfnTempTable_egg00)
THEN
    BEGIN
&   ifdef trace
    t01sname( ak_strat, 'temp result ' );
&   endif
    page_count := cak_initpages;
    row_count  := cak_initrows;
    END
ELSE
    BEGIN
    _startkey.len := 0;
    _stopkey.len  := mxsp_key - 1;
    _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) )
    THEN
        row_count := ak720calc_rowcnt(acv, sparr, config, page_count);
    (*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
        g04int4_to_trace(acv.a_transinf.tri_trans,
              'sample invpages   ', page_count )
    ELSE
        g04int4_to_trace(acv.a_transinf.tri_trans,
              'sample primpages  ', page_count );
    (*ENDIF*) 
    IF  ( _count_records )
    THEN
        g04int4_to_trace(acv.a_transinf.tri_trans,
              'sample primrows   ', row_count );
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      ak720calc_rowcnt(
            VAR acv        : tak_all_command_glob;
            VAR sparr      : tak_syspointerarr;
            VAR config     : tak70_configuration;
            VAR page_count : tsp_int4) : tsp_int4;
 
VAR
      _recs_per_page : tsp_int4;
 
BEGIN
_recs_per_page :=
      trunc(( cak_page80percent/sparr.pbasep^.sbase.bavgrowlen ) + 0.5 );
IF  ( _recs_per_page = 0 )
THEN
    _recs_per_page := 1;
(*ENDIF*) 
;
IF  ( page_count < MAX_INT4_SP00 / _recs_per_page )
THEN
    (* there's no MAX_INT4_SP00 overflow *)
    BEGIN
    ak720calc_rowcnt := page_count * _recs_per_page;
    END
ELSE
    BEGIN
&   ifdef trace
    t01name( ak_strat, 'overflow: reccount' );
&   endif
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        g04name_to_trace( acv.a_transinf.tri_trans, 'overflow: reccount' );
        END;
    (*ENDIF*) 
    config.cfg_switches := config.cfg_switches - [cs_count_records];
    ak720calc_rowcnt    := IS_UNDEFINED_GG07;
    END;
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
*-PRETTY-*  statements    :        948
*-PRETTY-*  lines of code :       2983        PRETTYX 3.10 
*-PRETTY-*  lines in file :       3444         1997-12-10 
.PA 
