.nf
 
 
    ========== licence begin  GPL
    Copyright (c) 2000-2004 SAP AG
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
 
.fo
*****************************************************
Copyright (c) 2000-2004 SAP AG
SAP Database Technology
 
Release :      Date : 2000-11-28
*****************************************************
modname : VAK71
changed : 2000-11-28
module  : Build_Strategy_2
 
Author  : GertG / HolgerB
Created : 1985-10-16
*****************************************************
 
Purpose : Auxiliary module for strategy determination in a table
 
Define  :
 
        VAR
              a71blankline         : tsp00_Line;
 
        PROCEDURE
              a71glob_init_accesspath_info;
 
        PROCEDURE
              a71add_default_strat (VAR mblock : tgg00_MessBlock);
 
        PROCEDURE
              a71del_sysinfo_strategy (
                    keylen     : tsp00_Int4;
                    VAR mblock : tgg00_MessBlock);
 
        PROCEDURE
              a71default_strat (VAR gg_strategy : tgg07_StrategyInfo);
 
        PROCEDURE
              a71key_strat (
                    VAR acv         : tak_all_command_glob;
                    VAR access_info : tak70_strategy_record;
                    start           : tsp00_Int2;
                    stop            : tsp00_Int2);
 
        PROCEDURE
              a71index_strat (
                    VAR acv         : tak_all_command_glob;
                    VAR access_info : tak70_strategy_record;
                    start           : tsp00_Int2;
                    stop            : tsp00_Int2);
 
        PROCEDURE
              a71create_key_sequence (
                    VAR acv            : tak_all_command_glob;
                    VAR sparr          : tak_syspointerarr;
                    VAR access_info    : tak70_strategy_record);
 
        PROCEDURE
              a71create_inv_sequence(
                    VAR acv            : tak_all_command_glob;
                    VAR access_info    : tak70_strategy_record;
                    VAR inv_strat      : tak70_one_strat;
                    VAR index_def      : tak_multindex);
 
        PROCEDURE
              a71search_thru_index (
                    VAR acv        : tak_all_command_glob;
                    VAR column     : tgg00_StackEntry;
                    VAR index_def  : tak_multindex;
                    VAR invfield   : tsp00_Int2);
 
        PROCEDURE
              a71prepare_qual_on_index (
                    VAR acv         : tak_all_command_glob;
                    VAR qual_kind   : tgg00_QualKind);
 
        PROCEDURE
              a71check_fetch_optimization (
                    VAR acv         : tak_all_command_glob;
                    VAR config      : tak00_access_configuration;
                    VAR qprop       : tak70_query_properties;
                    VAR gg_strategy : tgg07_StrategyInfo;
                    VAR strategy    : tgg07_StratEnum;
                    VAR strat_data  : tgg07_StrRaw);
 
        PROCEDURE
              a71calculate_pageIO (
                    VAR acv             : tak_all_command_glob;
                    VAR sparr           : tak_syspointerarr;
                    VAR access_info     : tak70_strategy_record;
                    VAR strategy        : tak70_one_strat;
                    read_primpages      : tsp00_Int4;
                    read_primrows       : tsp00_Int4;
                    VAR key_strat_value : tsp00_Longreal;
                    read_invpages       : tsp00_Int4;
                    outrec_len          : tsp00_Int2);
 
        FUNCTION
              a71is_duplicate_avoidance (
                    VAR gg_strategy  : tgg07_StrategyInfo;
                    stratenum        : tgg07_StratEnum;
                    VAR strat_data   : tgg07_StrRaw;
                    VAR qprop        : tak70_query_properties) : boolean;
 
        FUNCTION
              a71code_distinct_optim (
                    VAR gg_strategy : tgg07_StrategyInfo) : tsp00_Int2;
 
        PROCEDURE
              a71turn_into_build_strat (
                    VAR acv      : tak_all_command_glob;
                    VAR strategy : tgg07_StratEnum);
 
        PROCEDURE
              a71set_rescnt(
                    VAR acv         : tak_all_command_glob;
                    VAR sparr       : tak_syspointerarr;
                    datapos         : tsp00_Int2;
                    VAR qprop       : tak70_query_properties);
 
        FUNCTION
              a71GetKeyFromKeystrat (
                    VAR mblock      : tgg00_MessBlock;
                    VAR key         : tgg00_Lkey;
                    VAR b_err       : tgg00_BasisError) : boolean;
 
        PROCEDURE
              a71adjust_configuration (
                    VAR dmli        : tak_dml_info;
                    VAR config_qprop : tak70_strategy_record);
 
        FUNCTION
              a71MatchingFunctionBasedIndex (
                    VAR acv        : tak_all_command_glob;
                    columnIndex    : integer;
                    VAR index_def  : tak_multindex;
                    VAR invfield   : tsp00_Int2) : boolean;
 
.CM *-END-* define --------------------------------------
***********************************************************
 
Use     :
 
        FROM
              AK_semantic_scanner_tools : VAK05;
 
        PROCEDURE
              a05luc_space (
                    acv          : tsp00_Addr;
                    VAR buf1     : tsp00_MoveObj;
                    fieldpos1    : tsp00_Int4;
                    fieldlength1 : tsp00_Int4;
                    VAR buf2     : tsp00_MoveObj;
                    fieldpos2    : tsp00_Int4;
                    fieldlength2 : tsp00_Int4;
                    VAR l_result : tsp00_LcompResult);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK07;
 
        PROCEDURE
              a07_b_put_error (
                    VAR acv  : tak_all_command_glob;
                    b_err    : tgg00_BasisError;
                    err_code : tsp00_Int4);
 
        PROCEDURE
              a07ak_system_error (
                    VAR acv  : tak_all_command_glob;
                    modul_no : integer;
                    id       : integer);
 
      ------------------------------ 
 
        FROM
              AK_Index : VAK24;
 
        PROCEDURE
              a24fnd_indexno (
                    VAR acv            : tak_all_command_glob;
                    VAR tabid          : tgg00_Surrogate;
                    indexno            : integer;
                    VAR index_scan_rec : tak_index_scan_record);
 
        FUNCTION
              a24IndexFieldCount(VAR index_def : tak_multindex) : integer;
 
        FUNCTION
              a24IsFunctionBasedIndex(VAR index_def : tak_multindex) : boolean;
 
      ------------------------------ 
 
        FROM
              Systeminfo_cache   : VAK10;
 
        PROCEDURE
              a10new (
                    VAR acv  : tak_all_command_glob;
                    obj_size : tsp00_Int4;
                    VAR p    : tgg00_StackListPtr);
 
        PROCEDURE
              a10dispose (
                    VAR acv : tak_all_command_glob;
                    VAR p : tgg00_StackListPtr);
 
      ------------------------------ 
 
        FROM
              Build_Strategy   : VAK70;
 
        VAR
              a70_glob_zstrat_rec               : tak70_strategy_record;
              a70glob_build_strats              : tgg07_StratEnumSet;
              a70glob_fetch_strats              : tgg07_StratEnumSet;
              a70glob_join_strats               : tgg07_StratEnumSet;
              a70glob_join_key_strats           : tgg07_StratEnumSet;
              a70glob_join_inv_strats           : tgg07_StratEnumSet;
              a70glob_key_strats                : tgg07_StratEnumSet;
              a70glob_key_fetch_strats          : tgg07_StratEnumSet;
              a70glob_key_build_strats          : tgg07_StratEnumSet;
              a70glob_inv_strats                : tgg07_StratEnumSet;
              a70glob_inv_fetch_strats          : tgg07_StratEnumSet;
              a70glob_inv_build_strats          : tgg07_StratEnumSet;
              a70glob_in_strats                 : tgg07_StratEnumSet;
              a70glob_subq_strats               : tgg07_StratEnumSet;
              a70glob_accessop_uknwn_strats     : tgg07_StratEnumSet;
              a70glob_accessop_known_strats     : tgg07_StratEnumSet;
              a70glob_accessop_key_build_strats : tgg07_StratEnumSet;
              a70glob_accessop_inv_build_strats : tgg07_StratEnumSet;
              a70glob_accessop_key_fetch_strats : tgg07_StratEnumSet;
              a70glob_accessop_inv_fetch_strats : tgg07_StratEnumSet;
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01vtrace    : tgg00_VtraceState;
 
        FUNCTION
              g01optim_inv_only : boolean;
 
      ------------------------------ 
 
        FROM
              Select_Help_Procedures : VGG04;
 
        PROCEDURE
              g04check_betw (
                    VAR mblock       : tgg00_MessBlock;
                    stpos            : tsp00_Int2;
                    VAR res_possible : boolean;
                    VAR stack_changed: boolean);
 
        PROCEDURE
              g04check_like (
                    VAR mblock       : tgg00_MessBlock;
                    stpos            : tsp00_Int2;
                    VAR to_eq_changed: boolean);
 
        PROCEDURE
              g04incheck (
                    VAR mblock : tgg00_MessBlock;
                    stpos : integer);
 
        PROCEDURE
              g04limitprimkeys (
                    VAR mblock      : tgg00_MessBlock;
                    VAR startkeyarr : tgg07_ColPosArr;
                    VAR start_key   : tgg00_Lkey;
                    VAR stopkeyarr  : tgg07_ColPosArr;
                    VAR stop_key    : tgg00_Lkey;
                    VAR use_stopkey : boolean;
                    in_stpos_hint   : tsp00_Int2;
                    in_value_idx    : tsp00_Int2);
 
      ------------------------------ 
 
        FROM
              Trace_Help_Procedures : VGG041;
 
        PROCEDURE
              g041c30_to_trace (
                    VAR t : tgg00_TransContext;
                    msg : tsp00_C30);
 
        PROCEDURE
              g041int4_to_trace (
                    VAR t  : tgg00_TransContext;
                    name   : tsp00_Name;
                    intval : tsp00_Int4);
 
        PROCEDURE
              g041longreal_to_trace (
                    VAR t  : tgg00_TransContext;
                    name   : tsp00_Name;
                    realval: tsp00_Longreal);
 
        PROCEDURE
              g041name_to_trace (
                    VAR t  : tgg00_TransContext;
                    name   : tsp00_Name);
 
      ------------------------------ 
 
        FROM
              Record_Encapsulate_Procedures : VGG09;
 
        PROCEDURE
              g09StratStackentry (
                    VAR NewStackEntry : tgg00_StackEntry;
                    inp_startpos : tsp00_Int2;
                    inp_len      : tsp00_Int2);
 
        PROCEDURE
              g09OpStackentry (
                    VAR NewStackEntry : tgg00_StackEntry;
                    inp_eop           : tgg00_StackOpType);
 
        PROCEDURE
              g09ColStackentry (
                    VAR NewStackEntry : tgg00_StackEntry;
                    inp_etype         : tgg00_StackEntryType;
                    inp_epos          : tsp00_Int2;
                    inp_elen_var      : tsp00_Int2;
                    inp_tableno       : tsp00_Uint1);
 
        PROCEDURE
              g09IndexColStackentry (
                    VAR NewStackEntry : tgg00_StackEntry;
                    inp_etype         : tgg00_StackEntryType;
                    inp_epos          : tsp00_Int2;
                    inp_eop           : tgg00_StackOpType;
                    inp_elen_var      : tsp00_Int2;
                    inp_tableno       : tsp00_Uint1);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalMove  (
                    mod_id         : tsp00_C6;
                    mod_intern_num : tsp00_Int4;
                    source_upb     : tsp00_Int4;
                    destin_upb     : tsp00_Int4;
                    source         : tsp00_MoveObjPtr;
                    source_pos     : tsp00_Int4;
                    destin         : tsp00_MoveObjPtr;
                    destin_pos     : tsp00_Int4;
                    length         : tsp00_Int4;
                    VAR e          : tgg00_BasisError);
 
        PROCEDURE
              SAPDB_PascalForcedFill (
                    size     : tsp00_Int4;
                    m        : tsp00_MoveObjPtr;
                    pos      : tsp00_Int4;
                    len      : tsp00_Int4;
                    fillchar : char);
 
        PROCEDURE
              SAPDB_PascalForcedMove  (
                    size1    : tsp00_Int4;
                    size2    : tsp00_Int4;
                    val1     : tsp00_MoveObjPtr;
                    p1       : tsp00_Int4;
                    val2     : tsp00_MoveObjPtr;
                    p2       : tsp00_Int4;
                    cnt      : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01niltree_id : tgg00_FileId;
 
        PROCEDURE
              b01filestate (
                    VAR t       : tgg00_TransContext;
                    VAR file_id : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              Single_Select : VKB720;
 
        PROCEDURE
              k720_maxresult_get (
                    VAR data           : tsp00_MoveObj;
                    strat_maxcnt       : tsp00_Int2;
                    VAR maxresult      : tsp00_Int4;
                    VAR b_err          : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              Trace_Strategy_2 : VAK727;
 
        PROCEDURE
              a727trace_col_cluster (
                    VAR transid     : tgg00_TransContext;
                    nam             : tsp00_Sname;
                    VAR col_cluster : tak70_sort_col_arr;
                    array_len       : tsp00_Int2);
 
        PROCEDURE
              a727trace_colposarr_ex (
                    VAR transid : tgg00_TransContext;
                    nam         : tsp00_Sname;
                    VAR keypos  : tgg07_ColPosArr;
                    length      : tsp00_Int2);
 
        PROCEDURE
              a727trace_query_prop (
                    VAR transid     : tgg00_TransContext;
                    VAR qprop       : tak70_query_properties);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              hint_trace_routines   : VAK81;
 
        PROCEDURE
              a81debug_access_config (
                    debug       : tgg00_Debug;
                    VAR config  : tak00_access_configuration);
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01moveobj (
                    debug       : tgg00_Debug;
                    VAR moveobj : tsp00_MoveObj;
                    startpos    : tsp00_Int4;
                    endpos      : tsp00_Int4);
 
        PROCEDURE
              t01treeid (
                    debug      : tgg00_Debug;
                    nam        : tsp00_Sname;
                    VAR treeid : tgg00_FileId);
 
        PROCEDURE
              t01stackdesc (
                    debug          : tgg00_Debug;
                    nam            : tsp00_Sname;
                    stack_addr     : tgg00_StackListPtr;
                    VAR stack_desc : tgg00_StackDesc);
 
        PROCEDURE
              t01qual_kind (
                    debug     : tgg00_Debug;
                    nam       : tsp00_Sname;
                    qual_kind : tgg00_QualKind);
 
        PROCEDURE
              t01real (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    re       : tsp00_Longreal;
                    digits   : integer);
 
        PROCEDURE
              t01strat_enum (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname;
                    strat : tgg07_StratEnum);
 
        PROCEDURE
              t01int4 (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01name (
                    level : tgg00_Debug;
                    nam : tsp00_Name);
 
        PROCEDURE
              t01sname (debug : tgg00_Debug; nam : tsp00_Sname);
 
        FUNCTION
              t01trace (layer : tgg00_Debug) : boolean;
 
        PROCEDURE
              t01c30 (debug : tgg00_Debug; msg : tsp00_C30);
 
        PROCEDURE
              t01comp_result (
                    debug     : tgg00_Debug;
                    nam       : tsp00_Sname;
                    comp_res  : tsp00_LcompResult);
 
        PROCEDURE
              t01bool (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    curr_bool: boolean);
 
        PROCEDURE
              t01messblock (
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    VAR m         : tgg00_MessBlock);
 
      ------------------------------ 
 
        FROM
              Trace_Strategy_1 : VAK725;
 
        PROCEDURE
              a725output_colposarr_ex (
                    debug       : tgg00_Debug;
                    nam         : tsp00_Sname;
                    VAR keypos  : tgg07_ColPosArr;
                    length      : tsp00_Int2);
 
        PROCEDURE
              a725output_query_prop (
                    debug   : tgg00_Debug;
                    qprop   : tak70_query_properties);
 
        PROCEDURE
              a725output_col_cluster (
                    debug           : tgg00_Debug;
                    nam             : tsp00_Sname;
                    VAR col_cluster : tak70_sort_col_arr;
                    array_len       : tsp00_Int2);
 
        PROCEDURE
              a725output_gg_strat (
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    VAR gg_strat  : tgg07_StrategyInfo);
 
        PROCEDURE
              a725output_sequence_prop (
                    debug   : tgg00_Debug;
                    sprop   : tak70_sequence_properties);
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vdebug_break (debug_break_pos : tsp00_Int4);
&       endif
 
.CM *-END-* use -----------------------------------------
***********************************************************
 
Synonym :
 
        PROCEDURE
              a05luc_space;
 
              tak_acv_address tsp00_Addr
 
        PROCEDURE
              a10new;
 
              tak_sysbufferaddress tgg00_StackListPtr
 
        PROCEDURE
              a10dispose;
 
              tak_sysbufferaddress tgg00_StackListPtr
 
.CM *-END-* synonym -------------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
CONST
      c_in_better_than_rg   = 10;
      c_max_in_index_qual   = 30;
      c_startsequence       = true;
      c_stopsequence        = false;
 
 
(*------------------------------*) 
 
PROCEDURE
      a71create_key_sequence (
            VAR acv            : tak_all_command_glob;
            VAR sparr          : tak_syspointerarr;
            VAR access_info    : tak70_strategy_record);
 
VAR
      _sortcol_IN_SUBQ_idx      : tsp00_Int2;
      _colseq_start_IN_SUBQ_idx : tsp00_Int2;
      _colseq_stop_IN_SUBQ_idx  : tsp00_Int2;
      _ix                       : tsp00_Int2;
      _stackpos                 : tsp00_Int2;
      _sorted_keycnt            : tsp00_Int2;
      _sorted_keys              : tak70_sort_col_arr;
 
BEGIN
(* goal of this function :                  *)
(* sorted_cols will be contain all columns  *)
(* clustered by column sequence             *)
(* same columns are sorted by operators on  *)
(* the column :                             *)
(* 1. op_eq                                 *)
(* 2. op_ge, op_le, op_between, op_like     *)
(* 3. op_in                                 *)
(* 4. op_eq --> SUBQUERY                    *)
(* 5. op_gt, op_lt                          *)
(*                                          *)
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace ( acv.a_transinf.tri_trans,
          'A71CREATE_KEY_SEQUENCE        ' );
    END;
(*ENDIF*) 
;
access_info.srec_sequence_props:= [];
;
IF  ( access_info.srec_keyaccess.ka_startcnt > 0 ) OR
    ( access_info.srec_keyaccess.ka_stopcnt  > 0 )
THEN
    BEGIN
    (* ------------- START SEQUENCE ----------------- *)
    _sorted_keycnt := 0;
&   ifdef TRACE
    t01int4( ak_strat, 'keycol count', sparr.pbasep^.sbase.bkeycolcount );
    a725output_colposarr_ex( ak_strat, 'unsort start',
          access_info.srec_keyaccess.ka_startfields,
          access_info.srec_keyaccess.ka_startcnt );
&   endif
    ;
    (* copy info about stackentry in _sorted_keys *)
    FOR _ix := 0 TO access_info.srec_keyaccess.ka_startcnt - 1 DO
        BEGIN
        _stackpos := access_info.srec_keyaccess.ka_startfields[ _ix ];
        IF  ( _stackpos > 0 )
        THEN
            BEGIN
            ak71put_col_pos( acv.a_mblock, access_info,
                  _sorted_keys, _sorted_keycnt,
                  acv.a_mblock.mb_st^[ _stackpos ].epos,
                  acv.a_mblock.mb_st^[ _stackpos ].elen_var,
                  _stackpos, false );
            END;
        (*ENDIF*) 
        END;
    (*ENDFOR*) 
    ;
&   ifdef TRACE
    a725output_col_cluster( ak_strat, 'clust start ', _sorted_keys, _sorted_keycnt );
&   endif
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        a727trace_col_cluster( acv.a_transinf.tri_trans,
              'clust start ', _sorted_keys, _sorted_keycnt );
        END;
    (*ENDIF*) 
    ;
    ak71filter_col_cluster( acv,
          _sorted_keys, _sorted_keycnt,
          access_info.srec_keyaccess.ka_startfields,
          access_info.srec_keyaccess.ka_startcnt,
          sparr.pbasep^.sbase.bkeycolcount,
          _sortcol_IN_SUBQ_idx,
          _colseq_start_IN_SUBQ_idx,
          c_startsequence,
          access_info.srec_query_prop, access_info.srec_sequence_props );
    ;
&   ifdef TRACE
    a725output_sequence_prop( ak_strat, access_info.srec_sequence_props );
    a725output_colposarr_ex( ak_strat, 'sorted start',
          access_info.srec_keyaccess.ka_startfields,
          access_info.srec_keyaccess.ka_startcnt );
&   endif
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        a727trace_colposarr_ex( acv.a_transinf.tri_trans,
              'sorted start', access_info.srec_keyaccess.ka_startfields,
              access_info.srec_keyaccess.ka_startcnt );
        END;
    (*ENDIF*) 
    ;
    (* ------------- STOP SEQUENCE ----------------- *)
    _sorted_keycnt := 0;
&   ifdef TRACE
    a725output_colposarr_ex( ak_strat, 'unsort stop ',
          access_info.srec_keyaccess.ka_stopfields,
          access_info.srec_keyaccess.ka_stopcnt );
&   endif
    ;
    (* copy info about stackentry in _sorted_keys *)
    FOR _ix := 0 TO access_info.srec_keyaccess.ka_stopcnt - 1 DO
        BEGIN
        _stackpos := abs( access_info.srec_keyaccess.ka_stopfields[ _ix ] );
        IF  ( _stackpos > 0 )
        THEN
            BEGIN
            ak71put_col_pos( acv.a_mblock, access_info,
                  _sorted_keys, _sorted_keycnt,
                  acv.a_mblock.mb_st^[ _stackpos ].epos,
                  acv.a_mblock.mb_st^[ _stackpos ].elen_var,
                  access_info.srec_keyaccess.ka_stopfields[ _ix ], false );
            END;
        (*ENDIF*) 
        END;
    (*ENDFOR*) 
    ;
&   ifdef TRACE
    a725output_col_cluster( ak_strat, 'clust stop  ', _sorted_keys, _sorted_keycnt );
&   endif
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        a727trace_col_cluster( acv.a_transinf.tri_trans,
              'clust stop  ', _sorted_keys, _sorted_keycnt );
        END;
    (*ENDIF*) 
    ;
    ak71filter_col_cluster( acv,
          _sorted_keys, _sorted_keycnt,
          access_info.srec_keyaccess.ka_stopfields,
          access_info.srec_keyaccess.ka_stopcnt,
          sparr.pbasep^.sbase.bkeycolcount,
          _sortcol_IN_SUBQ_idx,
          _colseq_stop_IN_SUBQ_idx,
          c_stopsequence,
          access_info.srec_query_prop, access_info.srec_sequence_props );
    ;
&   ifdef TRACE
    a725output_sequence_prop( ak_strat, access_info.srec_sequence_props );
    a725output_colposarr_ex( ak_strat, 'sorted stop ',
          access_info.srec_keyaccess.ka_stopfields,
          access_info.srec_keyaccess.ka_stopcnt );
&   endif
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        a727trace_colposarr_ex( acv.a_transinf.tri_trans,
              'sorted stop ', access_info.srec_keyaccess.ka_stopfields,
              access_info.srec_keyaccess.ka_stopcnt );
        END;
    (*ENDIF*) 
    ;
    IF  (( sp_IN_usage_start in access_info.srec_sequence_props ) AND
        (  sp_IN_usage_stop  in access_info.srec_sequence_props ))
    THEN
        (* hence -> no SUBQ usage *)
        BEGIN
        access_info.srec_sequence_props :=
              access_info.srec_sequence_props + [ sp_IN_usage ];
        access_info.srec_keyaccess.ka_infield.in_elemcnt :=
              _sorted_keys[ _sortcol_IN_SUBQ_idx ].col_in_valcnt;
        END
    ELSE
        BEGIN
        IF  (( sp_SUBQ_usage_start in access_info.srec_sequence_props ) AND
            (  sp_SUBQ_usage_stop  in access_info.srec_sequence_props ))
        THEN
            BEGIN
            access_info.srec_sequence_props :=
                  access_info.srec_sequence_props + [ sp_SUBQ_usage ];
            access_info.srec_keyaccess.ka_SUBQ_idx   := _colseq_start_IN_SUBQ_idx;
            END
        ELSE
            BEGIN
            IF  ( sp_SUBQ_usage_start in  access_info.srec_sequence_props )
            THEN
                (* don't use SUBQ as range operator *)
                BEGIN
                access_info.srec_keyaccess.
                      ka_startfields[ _colseq_start_IN_SUBQ_idx ] := 0;
                access_info.srec_keyaccess.ka_startcnt := _colseq_start_IN_SUBQ_idx;
                access_info.srec_sequence_props :=
                      access_info.srec_sequence_props - [ sp_SUBQ_usage_start ];
                END;
            (*ENDIF*) 
            IF  ( sp_SUBQ_usage_stop in  access_info.srec_sequence_props )
            THEN
                (* don't use SUBQ as range operator *)
                BEGIN
                access_info.srec_keyaccess.
                      ka_stopfields[ _colseq_stop_IN_SUBQ_idx ] := 0;
                access_info.srec_keyaccess.ka_stopcnt := _colseq_stop_IN_SUBQ_idx;
                access_info.srec_sequence_props :=
                      access_info.srec_sequence_props - [ sp_SUBQ_usage_stop ];
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
&ifdef trace
a725output_query_prop( ak_strat, access_info.srec_query_prop );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    a727trace_query_prop( acv.a_transinf.tri_trans,
          access_info.srec_query_prop );
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
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);
 
VAR
      _sortcol_IN_SUBQ_idx      : tsp00_Int2;
      _colseq_start_IN_SUBQ_idx : tsp00_Int2;
      _colseq_stop_IN_SUBQ_idx  : tsp00_Int2;
      _mpos                     : tsp00_Int2;
      _stackpos                 : tsp00_Int2;
      _invfield                 : tsp00_Int2;
      _sorted_istartcnt         : tsp00_Int2;
      _sorted_istopcnt          : tsp00_Int2;
      _sorted_istart            : tak70_sort_col_arr;
      _sorted_istop             : tak70_sort_col_arr;
 
BEGIN
(* goal of this function :                  *)
(* sorted_cols will be contain all columns  *)
(* clustered by column sequence             *)
(* same columns are sorted by operators on  *)
(* the column :                             *)
(* 1. op_eq                                 *)
(* 2. op_ge, op_le, op_between, op_like     *)
(* 3. op_in                                 *)
(* 4. op_eq --> SUBQUERY                    *)
(* 5. op_gt, op_lt                          *)
(*                                          *)
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace ( acv.a_transinf.tri_trans,
          'A71CREATE_INV_SEQUENCE        ' );
    END;
(*ENDIF*) 
access_info.srec_sequence_props:= [];
;
IF  ( access_info.srec_invaccess.ia_startcnt > 0 ) OR
    ( access_info.srec_invaccess.ia_stopcnt  > 0 ) OR
    ( access_info.srec_invaccess.ia_incnt    > 0 )
THEN
    BEGIN
    _sorted_istartcnt := 0;
    _sorted_istopcnt  := 0;
&   ifdef trace
    t01name( ak_strat, 'analyse GT, GE    ' );
&   endif
    (* *)
    (* --- analyse GT, GE conditions ( ia_startfields ) --- *)
    (* *)
    _mpos := 0;
    WHILE ( _mpos < access_info.srec_invaccess.ia_startcnt ) DO
        BEGIN
        _stackpos := access_info.srec_invaccess.ia_startfields[ _mpos ];
&       ifdef TRACE
        t01int4 (ak_strat, 'start inv   ', _stackpos);
&       endif
        IF  NOT a71MatchingFunctionBasedIndex ( acv, _stackpos, index_def, _invfield )
        THEN
            a71search_thru_index( acv, acv.a_mblock.mb_st^[ _stackpos ],
                  index_def, _invfield );
        (*ENDIF*) 
        IF  ( _invfield > 0 )
        THEN
            BEGIN
            IF  NOT( _invfield in inv_strat.ostr_inv_in_range.siir_invcoldesc )
            THEN
                (* ascending order of index field *)
                BEGIN
                ak71put_col_pos( acv.a_mblock, access_info,
                      _sorted_istart, _sorted_istartcnt,
                      _invfield, 1,
                      access_info.srec_invaccess.ia_startfields[ _mpos ], false );
                END
            ELSE
                (* descending order of index field *)
                BEGIN
&               ifdef trace
                t01sname( ak_strat, 'desc ifield ' );
&               endif
                ak71put_col_pos( acv.a_mblock, access_info,
                      _sorted_istop, _sorted_istopcnt,
                      _invfield, 1,
                      access_info.srec_invaccess.ia_startfields[ _mpos ], true );
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        _mpos := succ( _mpos );
        END;
    (*ENDWHILE*) 
    ;
&   ifdef trace
    t01name( ak_strat, 'analyse LT, LE    ' );
&   endif
    (* *)
    (* --- analyse LT, LE conditions ( ia_stopfields ) --- *)
    (* *)
    _mpos := 0;
    WHILE (_mpos < access_info.srec_invaccess.ia_stopcnt ) DO
        BEGIN
        _stackpos := abs( access_info.srec_invaccess.ia_stopfields[ _mpos ] );
&       ifdef TRACE
        t01int4 (ak_strat, 'stop inv    ', _stackpos);
&       endif
        IF  NOT a71MatchingFunctionBasedIndex ( acv, _stackpos, index_def, _invfield )
        THEN
            a71search_thru_index( acv, acv.a_mblock.mb_st^[ _stackpos ],
                  index_def, _invfield );
        (*ENDIF*) 
        IF  ( _invfield > 0 )
        THEN
            BEGIN
            (* single indices don't contain NULL values *)
            IF  NOT( _invfield in inv_strat.ostr_inv_in_range.siir_invcoldesc )
            THEN
                (* ascending order of index field *)
                BEGIN
                ak71put_col_pos( acv.a_mblock, access_info,
                      _sorted_istop, _sorted_istopcnt,
                      _invfield, 1,
                      access_info.srec_invaccess.ia_stopfields[ _mpos ], false );
                END
            ELSE
                (* descending order of index field *)
                BEGIN
&               ifdef trace
                t01sname( ak_strat, 'desc ifield ' );
&               endif
                ak71put_col_pos( acv.a_mblock, access_info,
                      _sorted_istart, _sorted_istartcnt,
                      _invfield, 1,
                      access_info.srec_invaccess.ia_stopfields[ _mpos ], true );
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        _mpos := succ( _mpos );
        END;
    (*ENDWHILE*) 
    ;
&   ifdef trace
    t01name( ak_strat, 'analyse IN condit ' );
&   endif
    (* *)
    (* --- analyse IN conditions ( ia_infields ) --- *)
    (* *)
    _mpos     := 0;
    WHILE ( _mpos < access_info.srec_invaccess.ia_incnt ) DO
        BEGIN
        _stackpos := access_info.srec_invaccess.ia_infields[ _mpos ].in_stpos;
&       ifdef trace
        t01int4( ak_strat, 'fieldpos in ', _stackpos );
&       endif
        IF  NOT a71MatchingFunctionBasedIndex ( acv, _stackpos, index_def, _invfield )
        THEN
            a71search_thru_index ( acv, acv.a_mblock.mb_st^[ _stackpos ],
                  index_def, _invfield );
        (*ENDIF*) 
        IF  ( _invfield > 0 )
        THEN
            BEGIN
&           ifdef trace
            t01name( ak_strat, 'append IN         ' );
&           endif
            IF  NOT( _invfield in inv_strat.ostr_inv_in_range.siir_invcoldesc )
            THEN
                (* ascending order of index field *)
                BEGIN
                ak71put_col_pos( acv.a_mblock, access_info,
                      _sorted_istart, _sorted_istartcnt,
                      _invfield, 1, _stackpos, false );
                ak71put_col_pos( acv.a_mblock, access_info,
                      _sorted_istop, _sorted_istopcnt,
                      _invfield, 1, _stackpos, false );
                END
            ELSE
                BEGIN
                ak71put_col_pos( acv.a_mblock, access_info,
                      _sorted_istart, _sorted_istartcnt,
                      _invfield, 1, _stackpos, true );
                ak71put_col_pos( acv.a_mblock, access_info,
                      _sorted_istop, _sorted_istopcnt,
                      _invfield, 1, _stackpos, true );
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        _mpos := succ( _mpos );
        END;
    (*ENDWHILE*) 
    ;
&   ifdef TRACE
    a725output_col_cluster( ak_strat, 'cclust start', _sorted_istart, _sorted_istartcnt );
    a725output_col_cluster( ak_strat, 'cclust stop ', _sorted_istop, _sorted_istopcnt );
&   endif
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        a727trace_col_cluster( acv.a_transinf.tri_trans,
              'cclust start', _sorted_istart, _sorted_istartcnt );
        a727trace_col_cluster( acv.a_transinf.tri_trans,
              'cclust stop ', _sorted_istop, _sorted_istopcnt );
        END;
    (*ENDIF*) 
    ;
&   ifdef trace
    t01name( ak_strat, 'filter inv start  ' );
&   endif
    ak71filter_col_cluster( acv,
          _sorted_istart, _sorted_istartcnt,
          inv_strat.ostr_inv_in_range.siir_invstart,
          inv_strat.ostr_inv_in_range.siir_startcnt,
          a24IndexFieldCount(index_def),
          _sortcol_IN_SUBQ_idx,
          _colseq_start_IN_SUBQ_idx,
          c_startsequence,
          access_info.srec_query_prop, access_info.srec_sequence_props );
&   ifdef trace
    a725output_sequence_prop( ak_strat, access_info.srec_sequence_props );
&   endif
    ;
    IF  ( sp_IN_usage_start in access_info.srec_sequence_props ) OR
        ( sp_SUBQ_usage_start in access_info.srec_sequence_props )
    THEN
        BEGIN
        inv_strat.ostr_inv_in_range.siir_IN_SUBQ_stpos :=
              _sorted_istart[ _sortcol_IN_SUBQ_idx ].col_stpos;
&       ifdef trace
        t01int4( ak_strat, 'IN_SUBQ_stpo', inv_strat.ostr_inv_in_range.siir_IN_SUBQ_stpos );
&       endif
        IF  ( sp_IN_usage_start in access_info.srec_sequence_props )
        THEN
            inv_strat.ostr_inv_in_range.siir_inelemcnt :=
                  _sorted_istart[ _sortcol_IN_SUBQ_idx ].col_in_valcnt;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    ;
&   ifdef trace
    t01name( ak_strat, 'filter inv stop   ' );
&   endif
    ak71filter_col_cluster( acv,
          _sorted_istop, _sorted_istopcnt,
          inv_strat.ostr_inv_in_range.siir_invstop,
          inv_strat.ostr_inv_in_range.siir_stopcnt,
          a24IndexFieldCount(index_def),
          _sortcol_IN_SUBQ_idx,
          _colseq_stop_IN_SUBQ_idx,
          c_stopsequence,
          access_info.srec_query_prop, access_info.srec_sequence_props );
&   ifdef trace
    a725output_sequence_prop( ak_strat, access_info.srec_sequence_props );
&   endif
    ;
    IF  ( sp_IN_usage_stop in access_info.srec_sequence_props ) OR
        ( sp_SUBQ_usage_stop in access_info.srec_sequence_props )
    THEN
        BEGIN
        inv_strat.ostr_inv_in_range.siir_IN_SUBQ_stpos :=
              _sorted_istop[ _sortcol_IN_SUBQ_idx ].col_stpos;
&       ifdef trace
        t01int4( ak_strat, 'IN_SUBQ_stpo', inv_strat.ostr_inv_in_range.siir_IN_SUBQ_stpos );
&       endif
        IF  ( sp_IN_usage_stop in access_info.srec_sequence_props )
        THEN
            inv_strat.ostr_inv_in_range.siir_inelemcnt :=
                  _sorted_istop[ _sortcol_IN_SUBQ_idx ].col_in_valcnt;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    ;
    IF  (( sp_IN_usage_start in access_info.srec_sequence_props ) AND
        (  sp_IN_usage_stop  in access_info.srec_sequence_props ))
    THEN
        BEGIN
        access_info.srec_sequence_props :=
              access_info.srec_sequence_props + [ sp_IN_usage ];
        END
    ELSE
        IF  (( sp_SUBQ_usage_start in access_info.srec_sequence_props ) AND
            (  sp_SUBQ_usage_stop  in access_info.srec_sequence_props ))
        THEN
            BEGIN
            access_info.srec_sequence_props :=
                  access_info.srec_sequence_props + [ sp_SUBQ_usage ];
            (* _colseq_stop_IN_SUBQ_idx perhaps with IS_UNDEFINED_GG07 !!! *)
            inv_strat.ostr_inv_in_range.siir_subq_idx := _colseq_start_IN_SUBQ_idx;
            END
        ELSE
            BEGIN
            IF  ( sp_SUBQ_usage_start in  access_info.srec_sequence_props )
            THEN
                (* don't use SUBQ as range operator *)
                BEGIN
                inv_strat.ostr_inv_in_range.siir_IN_SUBQ_stpos := IS_UNDEFINED_GG07;
                inv_strat.ostr_inv_in_range.
                      siir_invstart[ _colseq_start_IN_SUBQ_idx ] := 0;
                inv_strat.ostr_inv_in_range.siir_startcnt  := _colseq_start_IN_SUBQ_idx;
                access_info.srec_sequence_props :=
                      access_info.srec_sequence_props - [ sp_SUBQ_usage_start ];
                END;
            (*ENDIF*) 
            IF  ( sp_SUBQ_usage_stop in  access_info.srec_sequence_props )
            THEN
                (* don't use SUBQ as range operator *)
                BEGIN
                inv_strat.ostr_inv_in_range.siir_IN_SUBQ_stpos := IS_UNDEFINED_GG07;
                inv_strat.ostr_inv_in_range.
                      siir_invstop[ _colseq_stop_IN_SUBQ_idx ] := 0;
                inv_strat.ostr_inv_in_range.siir_stopcnt  := _colseq_stop_IN_SUBQ_idx;
                access_info.srec_sequence_props  :=
                      access_info.srec_sequence_props - [ sp_SUBQ_usage_stop ];
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
&ifdef trace
a725output_colposarr_ex( ak_strat, 'sorted start',
      inv_strat.ostr_inv_in_range.siir_invstart,
      inv_strat.ostr_inv_in_range.siir_startcnt );
a725output_colposarr_ex( ak_strat, 'sorted stop ',
      inv_strat.ostr_inv_in_range.siir_invstop,
      inv_strat.ostr_inv_in_range.siir_stopcnt );
a725output_query_prop( ak_strat, access_info.srec_query_prop );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    a727trace_colposarr_ex( acv.a_transinf.tri_trans,
          'sorted start', inv_strat.ostr_inv_in_range.siir_invstart,
          inv_strat.ostr_inv_in_range.siir_startcnt );
    a727trace_colposarr_ex( acv.a_transinf.tri_trans,
          'sorted stop ', inv_strat.ostr_inv_in_range.siir_invstop,
          inv_strat.ostr_inv_in_range.siir_stopcnt );
    a727trace_query_prop( acv.a_transinf.tri_trans,
          access_info.srec_query_prop );
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak71filter_col_cluster (
            VAR acv                 : tak_all_command_glob;(*  IN   *)
            VAR sorted_cols         : tak70_sort_col_arr;  (*  IN   *)
            sorted_colcnt           : tsp00_Int2;            (*  IN   *)
            VAR col_sequence        : tgg07_ColPosArr;     (*  OUT  *)
            VAR col_cnt             : tsp00_Int2;            (*  OUT  *)
            max_sequence_len        : tsp00_Int2;            (*  IN   *)
            VAR sortcol_IN_SUBQ_idx : tsp00_Int2;            (*  OUT  *)
            VAR colseq_IN_SUBQ_idx  : tsp00_Int2;            (*  OUT  *)
            is_startsequence        : boolean;             (*  IN   *)
            VAR qprop               : tak70_query_properties;(*  OUT  *)
            VAR sequence_props      : tak70_sequence_properties); (* OUT *)
 
VAR
      _subq_or_in      : boolean; (* any previous column has in/subq *)
      _equal_sequence  : boolean; (* all previous columns have equal conditions *)
      _eq_found        : boolean;
      _eq_range_found  : boolean;
      _in_found        : boolean;
      _eq_subq_found   : boolean;
      _useable_op_found: boolean;
      _exact_match     : boolean;
      _last_col_cluster: boolean;
      _ix              : tsp00_Int2;
      _keycnt          : tsp00_Int2;
      _sequence_cnt    : tsp00_Int2;
      _col_id          : tsp00_Int2;
      _valpos1         : tsp00_Int2;
      _valpos2         : tsp00_Int2;
      _htree_id        : tgg00_FileId;
 
BEGIN
(* goal of this function :                  *)
(* sorted_cols contains all columns         *)
(* clustered by column sequence             *)
(* same columns are sorted by operators on  *)
(* the column :                             *)
(* 1. op_eq                                 *)
(* 2. op_ge, op_le, op_between, op_like     *)
(* 3. op_in                                 *)
(* 4. op_eq --> SUBQUERY                    *)
(* 5. op_gt, op_lt                          *)
(*                                          *)
(* if we found conditions on column, worse  *)
(* conditions on same columns are eleminated*)
;
(* now we have clustered sorted_cols array by columns *)
(* each cluster is sorted by operator precedence       *)
IF  ( sorted_colcnt > 0 )
THEN
    _col_id := sorted_cols[ 1 ].col_id;
(*ENDIF*) 
_ix                 := 1;
_exact_match        := true;
_subq_or_in         := false;
_equal_sequence     := true;
_last_col_cluster   := NOT ( sorted_colcnt > 0 );
sortcol_IN_SUBQ_idx := IS_UNDEFINED_GG07;
colseq_IN_SUBQ_idx  := IS_UNDEFINED_GG07;
_sequence_cnt       := IS_UNDEFINED_GG07;
;
&ifdef trace
t01int4( ak_strat, 'sorted_colcn', sorted_colcnt );
&endif
WHILE NOT _last_col_cluster DO
    BEGIN
&   ifdef trace
    t01name( ak_strat, 'optim one column  ' );
    t01int4( ak_strat, '_col_id     ', _col_id );
    t01int4( ak_strat, '[ix].col_id ', sorted_cols[ _ix ].col_id );
&   endif
    _eq_found       := false;
    _eq_range_found := false;
    _in_found       := false;
    _eq_subq_found  := false;
    IF  (( _ix = 1 ) AND ( _col_id <> 1 ))
    THEN
        BEGIN
&       ifdef trace
        t01name( ak_strat, 'no start sequence ' );
        t01name( ak_strat, 'look for qp_no_res' );
&       endif
        _sequence_cnt := 0;
        END;
    (*ENDIF*) 
    ;
    (* find the best condition for one key/index-column *)
    (* eleminate worse conditions                       *)
    (* loop over one column cluster                     *)
    WHILE ( _ix <= sorted_colcnt ) AND ( _col_id = sorted_cols[ _ix ].col_id ) DO
        BEGIN
        CASE sorted_cols[ _ix ].col_eop OF
            op_eq, op_null :
                IF  ( NOT sorted_cols[ _ix ].col_subq )
                THEN
                    BEGIN
                    IF  ( _eq_found )
                    THEN
                        BEGIN
                        _valpos1 := sorted_cols[ _ix - 1 ].col_stpos + 1;
                        _valpos2 := sorted_cols[ _ix ].col_stpos + 1;
                        IF  ( ak71luc( acv.a_mblock.mb_trns^.trAcvPtr_gg00,
                            acv.a_mblock.mb_data^.mbp_buf,
                            acv.a_mblock.mb_st^[ _valpos1 ].epos,
                            acv.a_mblock.mb_st^[ _valpos1 ].elen_var,
                            acv.a_mblock.mb_data^.mbp_buf,
                            acv.a_mblock.mb_st^[ _valpos2 ].epos,
                            acv.a_mblock.mb_st^[ _valpos2 ].elen_var ) in
                            [ l_greater, l_less ] )
                        THEN
                            BEGIN
                            qprop.qps_switches := qprop.qps_switches +
                                  [ qp_no_result_set ];
&                           ifdef trace
                            t01sname( ak_strat, '= NO RESULT ' );
&                           endif
                            END;
                        (*ENDIF*) 
                        sorted_cols[ _ix - 1 ].col_stpos := 0;
                        END
                    ELSE
                        BEGIN
&                       ifdef trace
                        t01name( ak_strat, 'first ( = | NULL) ' );
&                       endif
                        _eq_found := true;
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    (* subq IN/=ANY found *)
                    BEGIN
                    IF  _eq_found OR _eq_range_found OR _in_found OR
                        _eq_subq_found OR _subq_or_in OR NOT _equal_sequence
                    THEN
                        sorted_cols[ _ix ].col_stpos := 0
                    ELSE
                        BEGIN
&                       ifdef trace
                        t01sname( ak_strat, 'first SUBQ  ' );
&                       endif
                        _eq_subq_found := true;
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            op_eq_all:
                BEGIN
&               ifdef trace
                t01sname( ak_strat, 'EQ_ALL      ' );
&               endif
                _eq_found          := true;
                sequence_props := sequence_props + [ sp_exact_match ];
                (* we have whole key for correlated subquery *)
                (* further columns aren't interesting        *)
                _ix := sorted_colcnt; (* break loop *)
                END;
            op_ge, op_le, op_gt, op_lt,
            op_like, op_between :
                IF  _eq_found OR _eq_range_found
                THEN
                    BEGIN
                    IF  _eq_found
                    THEN
                        sorted_cols[ _ix ].col_stpos := 0
                    ELSE
                        BEGIN
                        (* choose better limit *)
                        ak71get_better_limit( acv.a_mblock, sorted_cols,
                              _ix, is_startsequence );
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    (* keep all this operators *)
                    BEGIN
&                   ifdef trace
                    t01sname( ak_strat, 'first RANGE ' );
&                   endif
                    _eq_range_found := true;
                    END;
                (*ENDIF*) 
            op_in :
                IF  _eq_found OR _in_found OR
                    _subq_or_in OR NOT _equal_sequence
                THEN
                    sorted_cols[ _ix ].col_stpos := 0
                ELSE
                    BEGIN
                    IF  _eq_range_found
                    THEN
                        BEGIN
                        IF  ak71in_is_better(acv.a_mblock, sorted_cols, _ix, is_startsequence)
                        THEN
                            BEGIN
                            sorted_cols[ _ix - 1].col_stpos := 0;
                            _in_found       := true;
                            _eq_range_found := false;
                            END
                        ELSE
                            BEGIN
                            sorted_cols[ _ix ].col_stpos :=
                                  sorted_cols[ _ix - 1].col_stpos;
                            sorted_cols[ _ix ].col_eop   :=
                                  sorted_cols[ _ix - 1].col_eop;
                            sorted_cols[ _ix ].col_in_valcnt   :=
                                  sorted_cols[ _ix - 1].col_in_valcnt;
                            sorted_cols[ _ix ].col_subq   :=
                                  sorted_cols[ _ix - 1].col_subq;
                            sorted_cols[ _ix - 1].col_stpos := 0
                            END
                        (*ENDIF*) 
                        END
                    ELSE
                        _in_found := true;
                    (*ENDIF*) 
&                   ifdef trace
                    IF  _in_found
                    THEN
                        t01sname( ak_strat, 'first IN    ' );
&                   endif
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            op_false :
                BEGIN
                (* we have found empty subquery -> no result set *)
                qprop.qps_switches := qprop.qps_switches + [ qp_no_result_set ];
&               ifdef trace
                t01name( ak_strat, 'false NO RESULT   ' );
&               endif
                _ix := sorted_colcnt; (* break loop *)
                END;
            OTHERWISE
                BEGIN
                END;
            END;
        (*ENDCASE*) 
        _ix := succ( _ix );
        END;
    (*ENDWHILE*) 
    ;
    (* steped through all operations on one column *)
    _useable_op_found :=
          ( _eq_found OR _eq_range_found OR _in_found OR _eq_subq_found )
          AND ( _ix <= sorted_colcnt );
    IF  ( _useable_op_found )
    THEN
        BEGIN
&       ifdef trace
        IF  ( _sequence_cnt = IS_UNDEFINED_GG07 )
        THEN
            t01name( ak_strat, 'useable op found  ' );
&       endif
        (*ENDIF*) 
        IF  ( _ix > sorted_colcnt ) AND ( _sequence_cnt = IS_UNDEFINED_GG07 )
        THEN
            BEGIN
            _sequence_cnt := sorted_colcnt;
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  ( _sequence_cnt = IS_UNDEFINED_GG07 )
        THEN
            (* first unusable op found, usable sequence stops *)
            _sequence_cnt := pred( _ix ); (* set correct end of sort area *)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _exact_match )
    THEN
        _exact_match := _eq_found;
    (*ENDIF*) 
    IF  ( _equal_sequence )
    THEN
        (* bring history up to date *)
        (* _equal_sequence := just we found '=' OR for the first time we *)
        (*               find 'IN' or subquery *)
        _equal_sequence := _eq_found OR ( NOT _subq_or_in AND
              ( _eq_subq_found OR _in_found ));
    (*ENDIF*) 
    IF  ( NOT _subq_or_in )
    THEN
        (* bring history up to date *)
        _subq_or_in := _eq_subq_found OR _in_found;
    (*ENDIF*) 
    ;
&   ifdef trace
    IF  ( _exact_match )
    THEN
        t01sname( ak_strat, 'exact match ' );
    (*ENDIF*) 
    IF  ( _equal_sequence )
    THEN
        t01sname( ak_strat, 'equal seque ' );
    (*ENDIF*) 
    IF  ( _subq_or_in )
    THEN
        t01sname( ak_strat, 'subq or in  ' );
    (*ENDIF*) 
    t01int4( ak_strat, 'new col on  ', _ix );
    t01int4( ak_strat, 'sequence cnt', _sequence_cnt );
&   endif
    ;
    (* get next column *)
    IF  ( _ix <= sorted_colcnt )
    THEN
        BEGIN
&       ifdef trace
        t01name( ak_strat, 'switch to next col' );
&       endif
        (* is next column in sequence ?? *)
        IF  ( _col_id + sorted_cols[ _ix - 1 ].col_next_id_offset <>
            sorted_cols[ _ix ].col_id )
        THEN
            (* next column not sequenced *)
            BEGIN
            IF  ( _sequence_cnt = IS_UNDEFINED_GG07 )
            THEN
                BEGIN
&               ifdef trace
                t01name( ak_strat, 'no col sequence   ' );
                t01name( ak_strat, 'look for qp_no_res' );
&               endif
                _sequence_cnt := pred( _ix );
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        ;
        (* get next column *)
        _col_id := sorted_cols[ _ix ].col_id;
        END
    ELSE
        BEGIN
&       ifdef trace
        t01name( ak_strat, 'no more ccluster  ' );
&       endif
        _last_col_cluster := true;
        END;
    (*ENDIF*) 
    ;
    END;
(*ENDWHILE*) 
;
&ifdef TRACE
(* sorted_colcnt is count of useful columns *)
a725output_col_cluster( ak_strat, 'used col clu', sorted_cols, _sequence_cnt );
&endif
;
_keycnt := 0;
_ix     := 1;
(* update unsorted input-array *)
WHILE ( _ix <= _sequence_cnt ) AND
      ( NOT ( qp_no_result_set in qprop.qps_switches )) DO
    BEGIN
    (* col_stpos = 0 : there was worse operation *)
    IF  ( sorted_cols[ _ix ].col_stpos <> 0 )
    THEN
        BEGIN
        (* useable entry in sorted_cols found, i.e. *)
        (* best operation for a column found         *)
        col_sequence[ _keycnt ] := sorted_cols[ _ix ].col_stpos;
        IF  ( sorted_cols[ _ix ].col_eop = op_eq ) AND
            ( sorted_cols[ _ix ].col_subq )
        THEN
            BEGIN
            IF  ( is_startsequence )
            THEN
                sequence_props := sequence_props + [ sp_SUBQ_usage_start ]
            ELSE
                sequence_props := sequence_props + [ sp_SUBQ_usage_stop ];
            (*ENDIF*) 
            ;
            (* SUBQ found *)
            sortcol_IN_SUBQ_idx := _ix;
            colseq_IN_SUBQ_idx  := _keycnt;
            END
        ELSE
            BEGIN
            IF  ( sorted_cols[ _ix ].col_eop = op_in )
            THEN
                BEGIN
                IF  ( is_startsequence )
                THEN
                    sequence_props := sequence_props + [ sp_IN_usage_start ]
                ELSE
                    sequence_props := sequence_props + [ sp_IN_usage_stop ];
                (*ENDIF*) 
                ;
                (* IN found *)
                sortcol_IN_SUBQ_idx := _ix;
                colseq_IN_SUBQ_idx  := _keycnt;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  ( sorted_cols[ _ix ].col_subq )
        THEN
            BEGIN
            (* get subquery BD-file *)
            SAPDB_PascalMove ('VAK71 ',   1,    
                  acv.a_mblock.mb_data_size, sizeof( _htree_id ),
                  @acv.a_mblock.mb_data^.mbp_buf,
                  acv.a_mblock.mb_st^[ abs(col_sequence[ _keycnt ]) + 1 ].epos,
                  @_htree_id, 1,
                  FILE_ID_MXGG00,
                  acv.a_returncode);
            b01filestate( acv.a_transinf.tri_trans, _htree_id );
&           IFDEF TRACE
            t01treeid (ak_strat, 'htree_id    ', _htree_id);
&           ENDIF
            IF  ( acv.a_transinf.tri_trans.trError_gg00 <> e_ok )
            THEN (* subquery not yet executed *)
                BEGIN
&               ifdef TRACE
                t01name(ak_strat, 'subq->srec_paramet');
&               endif
                qprop.qps_switches := qprop.qps_switches + [ qp_missing_value ];
                END;
            (*ENDIF*) 
            END
        ELSE
            IF  ( acv.a_mblock.mb_data^.mbp_buf[
                acv.a_mblock.mb_st^[ abs(col_sequence[ _keycnt ]) + 1 ].epos ] =
                csp_default_byte )
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_strat, 'colval found' );
&               endif
                qprop.qps_switches := qprop.qps_switches + [ qp_missing_value ];
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        ;
        _keycnt := succ( _keycnt );
        END;
    (*ENDIF*) 
    _ix := succ( _ix );
    END;
(*ENDWHILE*) 
FOR _ix := _keycnt TO MAX_COLPOSARR_IDX_GG07 DO
    col_sequence[ _ix ] := 0;
(*ENDFOR*) 
;
&ifdef trace
t01int4( ak_strat, '_keycnt     ', _keycnt );
t01int4( ak_strat, 'max_sequence', max_sequence_len );
&endif
col_cnt := _keycnt;
IF  ( col_cnt = max_sequence_len ) AND ( col_cnt > 0 )
THEN
    BEGIN
    IF  ( _exact_match )
    THEN
        sequence_props := sequence_props + [ sp_exact_match ]
    ELSE
        BEGIN
        IF  ( _equal_sequence )
        THEN
            sequence_props := sequence_props + [ sp_exact_IN_SUBQ_match ];
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
&ifdef trace
(*ENDIF*) 
a725output_query_prop( ak_strat, qprop );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak71right_col_pos (
            VAR all_sorted_cols : tak70_sort_col_arr;
            act_index           : tsp00_Int2);
 
VAR
      _ix         : tsp00_Int2;
      _iy         : tsp00_Int2;
      _act_col_id : tsp00_Int2;
      _tmp_col    : tak70_col_sort_record;
 
BEGIN
(* For one KEY-column sort in following order : *)
(* 1. op_eq                                     *)
(* 2. op_ge, op_le, op_between, op_like         *)
(* 3. op_in                                     *)
(* 4. op_eq --> SUBQUERY                        *)
(* 5. op_gt, op_lt                              *)
_iy       := 1;
(* all_sorted_cols[ act_index ] contains unsorted element *)
_act_col_id := all_sorted_cols[ act_index ].col_id;
WHILE ( _iy < act_index ) DO
    BEGIN
    IF  ( _act_col_id = all_sorted_cols[ _iy ].col_id )
    THEN
        BEGIN
        (* there's the same column *)
&       ifdef TRACE
        t01name(ak_strat, 'insert op ordered ');
&       endif
        CASE all_sorted_cols[ act_index ].col_eop OF
            op_eq :
                IF  ( NOT all_sorted_cols[ act_index ].col_subq )
                THEN
                    BEGIN
&                   ifdef TRACE
                    t01sname(ak_strat, 'order =     ');
&                   endif
                    _tmp_col := all_sorted_cols[ act_index ];
                    FOR _ix := act_index DOWNTO _iy + 1 DO
                        all_sorted_cols[ _ix ] := all_sorted_cols[ _ix - 1 ];
                    (*ENDFOR*) 
                    all_sorted_cols[ _iy ] := _tmp_col;
                    _iy := act_index; (* break through while *)
                    END
                ELSE
                    BEGIN
                    (* with next loop append key column *)
&                   ifdef TRACE
                    t01sname(ak_strat, 'append SUBQ ');
&                   endif
                    END;
                (*ENDIF*) 
            op_ge, op_gt, op_le, op_lt,
            op_like, op_between :
                IF  ( all_sorted_cols[ _iy ].col_eop <> op_eq ) OR
                    ( all_sorted_cols[ _iy ].col_subq )
                THEN
                    BEGIN
&                   ifdef TRACE
                    t01c30 (ak_strat, 'order <=,>=,bw,like           ');
&                   endif
                    _tmp_col := all_sorted_cols[ act_index ];
                    FOR _ix := act_index DOWNTO _iy + 1 DO
                        all_sorted_cols[ _ix ] := all_sorted_cols[ _ix - 1 ];
                    (*ENDFOR*) 
                    all_sorted_cols[ _iy ] := _tmp_col;
                    _iy := act_index; (* break through while *)
                    END
                ELSE
                    BEGIN
                    (* with next loop append key column *)
&                   ifdef TRACE
                    t01c30 (ak_strat, 'append <=,>=,bw,like          ');
&                   endif
                    END;
                (*ENDIF*) 
            op_in :
                IF  (* insert before KEY = <subquery> *)
                    (( all_sorted_cols[ _iy ].col_eop = op_eq ) AND
                    ( all_sorted_cols[ _iy ].col_subq ))
                    (*
                          OR
                          * insert before KEY <,> *
                          ( all_sorted_cols[ _iy ].col_eop in [ op_gt, op_lt ] )
                          *)
                THEN
                    BEGIN
&                   ifdef TRACE
                    t01sname(ak_strat, 'order IN    ');
&                   endif
                    _tmp_col := all_sorted_cols[ act_index ];
                    FOR _ix := act_index DOWNTO _iy + 1 DO
                        all_sorted_cols[ _ix ] := all_sorted_cols[ _ix - 1 ];
                    (*ENDFOR*) 
                    all_sorted_cols[ _iy ] := _tmp_col;
                    _iy := act_index; (* break through while *)
                    END
                ELSE
                    BEGIN
                    (* with next loop append key column *)
&                   ifdef TRACE
                    t01sname(ak_strat, 'append IN   ');
&                   endif
                    END;
                (*ENDIF*) 
            op_false : (* empty subquery file *)
                BEGIN
&               ifdef TRACE
                t01sname(ak_strat, 'order FALSE ');
&               endif
                _tmp_col := all_sorted_cols[ act_index ];
                FOR _ix := act_index DOWNTO _iy + 1 DO
                    all_sorted_cols[ _ix ] := all_sorted_cols[ _ix - 1 ];
                (*ENDFOR*) 
                all_sorted_cols[ _iy ] := _tmp_col;
                _iy := act_index; (* break through while *)
                END;
            OTHERWISE
                BEGIN
                END;
            END
        (*ENDCASE*) 
        END
    ELSE
        (* there's a other colunm *)
        IF  ( _act_col_id < all_sorted_cols[ _iy ].col_id )
        THEN
            BEGIN
&           ifdef TRACE
            t01name( ak_strat, 'insert col ordered' );
&           endif
            (* insert entry in correctly order *)
            _tmp_col := all_sorted_cols[ act_index ];
            FOR _ix := act_index DOWNTO _iy + 1 DO
                all_sorted_cols[ _ix ] := all_sorted_cols[ _ix - 1 ];
            (*ENDFOR*) 
            all_sorted_cols[ _iy ] := _tmp_col;
            _iy := act_index; (* break through while loop *)
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    _iy := succ( _iy );
    END;
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      a71MatchingFunctionBasedIndex (
            VAR acv        : tak_all_command_glob;
            columnIndex    : integer;
            VAR index_def  : tak_multindex;
            VAR invfield   : tsp00_Int2) : boolean;
 
BEGIN
&ifdef trace
t01int4 (ak_strat, 'columnIndex ', columnIndex);
&endif
a71MatchingFunctionBasedIndex := false;
IF  (acv.a_mblock.mb_st^[columnIndex].etype        = st_build_in_func) AND
    (acv.a_mblock.mb_st^[columnIndex].eop_build_in = op_b_user_def_func)
THEN
    IF  acv.a_mblock.mb_st^[columnIndex-1].esurrogate = index_def.icolstack[2].esurrogate
    THEN
        BEGIN
        invfield := 1;
        a71MatchingFunctionBasedIndex := true;
        END;
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a71search_thru_index (
            VAR acv        : tak_all_command_glob;
            VAR column     : tgg00_StackEntry; (* IN : Stackentry             *)
            VAR index_def  : tak_multindex;       (* IN : AK-Descr. of 1 index   *)
            VAR invfield   : tsp00_Int2);     (* OUT: 0 or ColumnNo in Index *)
 
VAR
      _indexfield : tsp00_Int2;
      _indexlen   : tsp00_Int2;
 
BEGIN
_indexlen   := 1;
invfield    := 0;
_indexfield := 1;
(* step over index fields *)
WHILE ( _indexfield <= a24IndexFieldCount( index_def ) ) AND ( invfield = 0 ) DO
    BEGIN
    IF  ( column.etype in [ st_fixinv, st_varinv ] )
    THEN
        BEGIN
        (* index stack entry *)
        IF  ( column.etype = st_fixinv )
        THEN
            BEGIN
            _indexlen := _indexlen + index_def.icolstack[ _indexfield ].elen_var;
            IF  ( column.epos = 1 )
            THEN
                invfield := 1
            ELSE
                BEGIN
                IF  ( column.epos = _indexlen )
                THEN
                    BEGIN
                    invfield := _indexfield + 1;
                    IF  ( invfield > a24IndexFieldCount( index_def ))
                    THEN
                        a07ak_system_error( acv, 71, 1 );
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        ELSE
            invfield := a24IndexFieldCount( index_def );
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  ( column.etype = index_def.icolstack[ _indexfield ].etype ) AND
            ( column.epos  = index_def.icolstack[ _indexfield ].epos )
        THEN
            invfield := _indexfield;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    _indexfield := succ( _indexfield );
    END;
(*ENDWHILE*) 
&ifdef TRACE
IF  invfield <> 0
THEN
    BEGIN
    t01int4( ak_strat, 'invfield    ', invfield );
    t01int4( ak_strat, 'length      ', index_def.icolstack[ invfield ].elen_var );
    END
ELSE
    t01name (ak_strat, 'field not in index' );
(*ENDIF*) 
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      a71index_strat (
            VAR acv         : tak_all_command_glob;
            VAR access_info : tak70_strategy_record;
            start           : tsp00_Int2;
            stop            : tsp00_Int2);
 
VAR
      _ix          : tsp00_Int2;
      _htree_id    : tgg00_FileId;
 
BEGIN
WITH access_info.srec_invaccess DO
    BEGIN
    IF  NOT ( qp_missing_value in access_info.srec_query_prop.qps_switches )
    THEN
        (* host variables which are relevant for strategy search not found *)
        FOR _ix := start + 1 TO stop DO
            IF  ( acv.a_mblock.mb_st^[ _ix ].etype = st_subquery )
            THEN
                BEGIN
                (* get subquery BD-file *)
                SAPDB_PascalMove ('VAK71 ',   2,    
                      acv.a_mblock.mb_data_size, sizeof( _htree_id ),
                      @acv.a_mblock.mb_data^.mbp_buf,
                      acv.a_mblock.mb_st^[ _ix ].epos,
                      @_htree_id, 1,
                      FILE_ID_MXGG00,
                      acv.a_returncode);
                b01filestate( acv.a_transinf.tri_trans, _htree_id );
                IF  ( acv.a_transinf.tri_trans.trError_gg00 <> e_ok )
                THEN (* subquery not yet executed *)
                    BEGIN
&                   ifdef TRACE
                    t01name(ak_strat, 'subq->srec_paramet');
&                   endif
                    access_info.srec_query_prop.qps_switches  :=
                          access_info.srec_query_prop.qps_switches +
                          [ qp_missing_value ];
                    END;
                (*ENDIF*) 
                END
            ELSE
                IF  ( acv.a_mblock.mb_st^[ _ix ].etype = st_value )
                THEN
                    IF  ( acv.a_mblock.mb_data^.
                        mbp_buf[ acv.a_mblock.mb_st^[_ix].epos ] =
                        csp_default_byte ) (* pointer to data part *)
                        OR
                        (( acv.a_mblock.mb_st^[ _ix ].ecol_tab[ 1 ] in
                        [ cgg04_param_in_between_expr, cgg04_param_in_in_expr] )
                        OR
                        (( acv.a_mblock.mb_st^[ _ix ].ecol_tab[ 1 ] = chr(0) ) AND
                        ( acv.a_mblock.mb_st^[ _ix ].ecol_tab[ 2 ] <> chr(0) )))
                        (* const val expr *)
                    THEN
                        BEGIN
&                       ifdef TRACE
                        t01name(ak_strat, 'broken access     ');
&                       endif
                        access_info.srec_query_prop.qps_switches  :=
                              access_info.srec_query_prop.qps_switches +
                              [ qp_missing_value ];
                        END;
&                   ifdef TRACE
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDFOR*) 
    (*ENDIF*) 
    t01int4 (ak_strat, 'ecol_tab[1] ',
          ord(acv.a_mblock.mb_st^[ start ].ecol_tab[ 1 ]));
    t01int4 (ak_strat, 'ecol_tab[2] ',
          ord(acv.a_mblock.mb_st^[ start ].ecol_tab[ 2 ]));
&   endif
    IF  ( ord( acv.a_mblock.mb_st^[ start ].ecol_tab[ 2 ] ) > 100 )
    THEN
        (* field with index *)
        (* Note: if the comparison of the counts with cgg_maxqual-  *)
        (*       ifications should ever yield true, the constant is *)
        (*       choosen badly, because it should be the top limit  *)
        (*       of possible qualifications.                        *)
        CASE acv.a_mblock.mb_st^[ stop ].eop OF
            op_eq, op_null :
                BEGIN
                IF  ia_startcnt <= MAX_INVPOSARR_IDX_AK70
                THEN
                    BEGIN
&                   ifdef trace
                    t01int4( ak_strat, '   =, NULL  ', start );
&                   endif
                    ia_startfields[ ia_startcnt ] := start;
                    ia_startcnt                   := succ( ia_startcnt );
                    END;
                (*ENDIF*) 
                IF  ia_stopcnt <= MAX_INVPOSARR_IDX_AK70
                THEN
                    BEGIN
&                   ifdef trace
                    t01int4( ak_strat, '   =, NULL  ', start );
&                   endif
                    ia_stopfields[ ia_stopcnt ] := start;
                    ia_stopcnt                  := succ ( ia_stopcnt );
                    END;
                (*ENDIF*) 
                END;
            op_gt, op_ge :
                IF  ia_startcnt <= MAX_INVPOSARR_IDX_AK70
                THEN
                    BEGIN
&                   ifdef trace
                    t01int4( ak_strat, '    >, >=   ', start );
&                   endif
                    ia_startfields[ ia_startcnt ] := start;
                    ia_startcnt                   := succ( ia_startcnt );
                    END;
                (*ENDIF*) 
            op_lt, op_le :
                IF  ia_stopcnt <= MAX_INVPOSARR_IDX_AK70
                THEN
                    BEGIN
&                   ifdef trace
                    t01int4( ak_strat, '    <, <=   ', start );
&                   endif
                    ia_stopfields[ ia_stopcnt ] := start;
                    ia_stopcnt                  := succ ( ia_stopcnt );
                    END;
                (*ENDIF*) 
            op_between, op_like   :
                IF  ( ia_startcnt <= MAX_INVPOSARR_IDX_AK70 ) AND
                    ( ia_stopcnt  <= MAX_INVPOSARR_IDX_AK70 )
                THEN
                    BEGIN
&                   ifdef trace
                    t01int4( ak_strat, 'betw, like  ', start );
&                   endif
                    ia_startfields[ ia_startcnt ] := start;
                    ia_stopfields[ ia_stopcnt ]   := -start;
                    ia_startcnt := succ( ia_startcnt );
                    ia_stopcnt  := succ( ia_stopcnt );
                    END;
                (*ENDIF*) 
            op_in :
                BEGIN
                IF  ( acv.a_mblock.mb_st^[ stop ].ecol_tab[ 1 ] <> chr( 1 ))
                THEN
                    BEGIN
&                   ifdef trace
                    t01sname( ak_strat, 'analyze IN  ' );
&                   endif
                    g04incheck( acv.a_mblock, stop );
                    IF  acv.a_mblock.mb_st^[ stop ].ecol_tab[ 1 ] <> chr( 1 )
                    THEN
                        BEGIN
                        access_info.srec_query_prop.qps_switches  :=
                              access_info.srec_query_prop.qps_switches +
                              [ qp_missing_value ];
&                       ifdef trace
                        t01sname( ak_strat, 'param found ' );
&                       endif
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  ( acv.a_mblock.mb_st^[ stop ].elen_var = 0 ) OR
                    (( acv.a_mblock.mb_st^[ stop ].elen_var = 1 ) AND
                    ( acv.a_mblock.mb_data^.
                    mbp_buf[ acv.a_mblock.mb_st^[ stop - 1 ].epos ] = csp_undef_byte ))
                THEN
                    BEGIN
                    access_info.srec_query_prop.qps_switches :=
                          access_info.srec_query_prop.qps_switches +
                          [ qp_no_result_set ];
&                   ifdef trace
                    t01sname( ak_strat, 'IN no result' );
&                   endif
                    END
                ELSE
                    BEGIN
                    IF  ia_incnt <= MAX_INVINPOSARR_IDX_AK70
                    THEN
                        BEGIN
&                       ifdef trace
                        t01int4( ak_strat, '     in     ', start );
                        t01int4( ak_strat, '     in cnt ',
                              acv.a_mblock.mb_st^[stop].elen_var );
&                       endif
                        ia_infields[ ia_incnt ].in_stpos   := start;
                        ia_infields[ ia_incnt ].in_elemcnt :=
                              acv.a_mblock.mb_st^[ stop ].elen_var;
                        ia_incnt := succ( ia_incnt );
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            OTHERWISE;
            END
        (*ENDCASE*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak71put_keyinfo (
            VAR acv      : tak_all_command_glob;
            VAR keyarray : tgg07_ColPosArr;
            VAR keycnt   : tsp00_Int2;
            stpos        : tsp00_Int2);
 
VAR
      _ix         : tsp00_Int2;
      _maxepos    : tsp00_Int2;
      _abs_aux1   : tsp00_Int2;
      _abs_aux2   : tsp00_Int2;
 
BEGIN
IF  keycnt < MAX_STRATEGY_KEYS_GG04
THEN
    BEGIN
    keyarray[ keycnt ] := stpos;
    keycnt := succ( keycnt );
    END
ELSE
    BEGIN
    (* replace key field with greatest record position with   *)
    (* one with smaller record position                       *)
    _maxepos := 0;
    FOR _ix := 1 TO MAX_COLPOSARR_IDX_GG07 DO
        BEGIN
        (* LIKE and BETWEEN !!! *)
        _abs_aux1 := abs( keyarray[ _maxepos ] );
        _abs_aux2 := abs( keyarray[ _ix ] );
        IF  (acv.a_mblock.mb_st^[ _abs_aux1 ].epos <
            acv.a_mblock.mb_st^[ _abs_aux2 ].epos)
        THEN
            _maxepos := _ix;
        (*ENDIF*) 
        END;
    (*ENDFOR*) 
    IF  (acv.a_mblock.mb_st^[ abs( keyarray[ _maxepos ] ) ].epos >
        acv.a_mblock.mb_st^[ stpos ].epos)
    THEN
        BEGIN
&       ifdef trace
        t01int4( ak_strat, 'remove index', _maxepos);
&       endif
        keyarray[ _maxepos ] := stpos;
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a71key_strat (
            VAR acv         : tak_all_command_glob;
            VAR access_info : tak70_strategy_record;
            start           : tsp00_Int2;
            stop            : tsp00_Int2);
 
VAR
      _ix          : tsp00_Int2;
      _subqtree_id : tgg00_FileId;
 
BEGIN
IF  NOT ( qp_missing_value in access_info.srec_query_prop.qps_switches )
THEN
    (* host variables which are relevant for strategy search not found *)
    FOR _ix := start + 1 TO stop DO
        IF  ( acv.a_mblock.mb_st^[ _ix ].etype = st_subquery )
        THEN
            BEGIN
            (* get subquery BD-file *)
            SAPDB_PascalMove ('VAK71 ',   3,    
                  acv.a_mblock.mb_data_size, sizeof( _subqtree_id ),
                  @acv.a_mblock.mb_data^.mbp_buf,
                  acv.a_mblock.mb_st^[ _ix ].epos,
                  @_subqtree_id, 1, FILE_ID_MXGG00,
                  acv.a_returncode);
            b01filestate( acv.a_transinf.tri_trans, _subqtree_id );
            IF  ( acv.a_transinf.tri_trans.trError_gg00 <> e_ok )
            THEN (* subquery not yet executed *)
                BEGIN
&               ifdef TRACE
                t01name(ak_strat, 'missing subq file ');
&               endif
                access_info.srec_query_prop.qps_switches  :=
                      access_info.srec_query_prop.qps_switches +
                      [ qp_missing_value ];
                END;
            (*ENDIF*) 
            END
        ELSE
            IF  ( acv.a_mblock.mb_st^[ _ix ].etype = st_value )
            THEN
                IF  ( acv.a_mblock.mb_data^.
                    mbp_buf[ acv.a_mblock.mb_st^[ _ix ].epos ] =
                    csp_default_byte ) (* pointer in data part to parameter *)
                    OR
                    (( acv.a_mblock.mb_st^[ _ix ].ecol_tab[ 1 ] in
                    [ cgg04_param_in_between_expr, cgg04_param_in_in_expr] )
                    OR
                    (( acv.a_mblock.mb_st^[ _ix ].ecol_tab[ 1 ] = chr( 0 ) ) AND
                    ( acv.a_mblock.mb_st^[ _ix ].ecol_tab[ 2 ] <> chr( 0 ) )) (* const val expr *)
                    )
                THEN
                    BEGIN
&                   ifdef TRACE
                    t01name(ak_strat, 'broken access     ');
&                   endif
                    access_info.srec_query_prop.qps_switches  :=
                          access_info.srec_query_prop.qps_switches +
                          [ qp_missing_value ];
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDFOR*) 
(*ENDIF*) 
IF  NOT (qp_correlation_key in access_info.srec_query_prop.qps_switches)
THEN
    BEGIN
    CASE acv.a_mblock.mb_st^[ stop ].eop OF
        op_null :
            BEGIN
            access_info.srec_query_prop.qps_switches  :=
                  access_info.srec_query_prop.qps_switches + [ qp_no_result_set ];
&           ifdef trace
            t01name( ak_strat, 'KEY IS NULL       ' );
&           endif
            END;
        op_eq_all :
            BEGIN
&           ifdef TRACE
            t01int4( ak_strat, '   eq_all   ', start );
&           endif
            (* special correlation handling to qualify whole key *)
            IF  ( acv.a_mblock.mb_st^[ start ].etype = st_varkey ) AND
                ( acv.a_mblock.mb_st^[ start ].epos = 1 ) AND
                ( acv.a_mblock.mb_st^[ start + 1 ].etype <> st_subquery)
            THEN
                BEGIN
                access_info.srec_keyaccess.ka_startfields[ 0 ] := start;
                access_info.srec_keyaccess.ka_stopfields [ 0 ] := start;
                access_info.srec_keyaccess.ka_startcnt         := 1;
                access_info.srec_query_prop.qps_switches :=
                      access_info.srec_query_prop.qps_switches + [ qp_correlation_key ];
                END;
            (*ENDIF*) 
            END;
        op_eq :
            BEGIN
&           ifdef trace
            t01int4( ak_strat, '      =     ', start );
&           endif
            ak71put_keyinfo( acv, access_info.srec_keyaccess.ka_startfields,
                  access_info.srec_keyaccess.ka_startcnt, start );
            ak71put_keyinfo( acv, access_info.srec_keyaccess.ka_stopfields,
                  access_info.srec_keyaccess.ka_stopcnt, start );
            END;
        op_gt, op_ge :
            BEGIN
&           ifdef trace
            t01int4( ak_strat, '    >, >=   ', start );
&           endif
            IF  ( access_info.srec_keyaccess.ka_startcnt <
                MAX_STRATEGY_KEYS_GG04 )
            THEN
                BEGIN
                access_info.srec_keyaccess.ka_startfields
                      [ access_info.srec_keyaccess.ka_startcnt ] := start;
                access_info.srec_keyaccess.ka_startcnt :=
                      succ( access_info.srec_keyaccess.ka_startcnt );
                END;
            (*ENDIF*) 
            END;
        op_lt, op_le :
            BEGIN
&           ifdef trace
            t01int4( ak_strat, '    <, <=   ', start );
&           endif
            IF  ( access_info.srec_keyaccess.ka_stopcnt <
                MAX_STRATEGY_KEYS_GG04 )
            THEN
                BEGIN
                access_info.srec_keyaccess.ka_stopfields
                      [ access_info.srec_keyaccess.ka_stopcnt ] := start;
                access_info.srec_keyaccess.ka_stopcnt :=
                      succ( access_info.srec_keyaccess.ka_stopcnt );
                END;
            (*ENDIF*) 
            END;
        op_between, op_like :
            BEGIN
&           ifdef trace
            t01int4( ak_strat, 'betw, like  ', start );
&           endif
            IF  ( access_info.srec_keyaccess.ka_startcnt <
                MAX_STRATEGY_KEYS_GG04 )
            THEN
                BEGIN
                access_info.srec_keyaccess.ka_startfields
                      [ access_info.srec_keyaccess.ka_startcnt ] := start;
                access_info.srec_keyaccess.ka_startcnt :=
                      succ( access_info.srec_keyaccess.ka_startcnt );
                END;
            (*ENDIF*) 
            IF  ( access_info.srec_keyaccess.ka_stopcnt <
                MAX_STRATEGY_KEYS_GG04 )
            THEN
                BEGIN
                access_info.srec_keyaccess.ka_stopfields
                      [ access_info.srec_keyaccess.ka_stopcnt ] := -start;
                access_info.srec_keyaccess.ka_stopcnt :=
                      succ( access_info.srec_keyaccess.ka_stopcnt );
                END
            (*ENDIF*) 
            END;
        op_in :
            BEGIN
            IF  ( acv.a_mblock.mb_st^[ stop ].ecol_tab[ 1 ] <> chr( 1 ) )
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_strat, 'analyze IN  ' );
&               endif
                g04incheck( acv.a_mblock, stop );
                IF  ( acv.a_mblock.mb_st^[ stop ].ecol_tab[ 1 ] <> chr( 1 ))
                THEN
                    BEGIN
                    access_info.srec_query_prop.qps_switches  :=
                          access_info.srec_query_prop.qps_switches +
                          [ qp_missing_value ];
&                   ifdef trace
                    t01sname( ak_strat, 'param found ' );
&                   endif
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  ( acv.a_mblock.mb_st^[ stop ].elen_var = 0 ) OR
                (( acv.a_mblock.mb_st^[ stop ].elen_var = 1 ) AND
                ( acv.a_mblock.mb_data^.
                mbp_buf[ acv.a_mblock.mb_st^[ stop - 1 ].epos ] = csp_undef_byte ))
            THEN
                BEGIN
                access_info.srec_query_prop.qps_switches  :=
                      access_info.srec_query_prop.qps_switches + [ qp_no_result_set ];
&               ifdef trace
                t01sname( ak_strat, 'IN no result' );
&               endif
                END
            ELSE
                BEGIN
                IF  ( acv.a_mblock.mb_st^[ stop ].elen_var = 1 )
                THEN
                    BEGIN
&                   ifdef trace
                    t01int4( ak_strat, '     in     ', start );
                    t01sname( ak_strat, 'in to equal ' );
&                   endif
                    ak71put_keyinfo( acv, access_info.srec_keyaccess.ka_startfields,
                          access_info.srec_keyaccess.ka_startcnt, start );
                    ak71put_keyinfo( acv, access_info.srec_keyaccess.ka_stopfields,
                          access_info.srec_keyaccess.ka_stopcnt, start );
                    END
                ELSE
                    BEGIN
                    IF  ( access_info.srec_keyaccess.ka_infield.in_elemcnt = 0 )
                    THEN
                        BEGIN
                        (* never found a IN *)
                        IF  ( access_info.srec_keyaccess.ka_startcnt <
                            MAX_STRATEGY_KEYS_GG04 ) AND
                            ( access_info.srec_keyaccess.ka_stopcnt  <
                            MAX_STRATEGY_KEYS_GG04 )
                        THEN
                            BEGIN
&                           ifdef trace
                            t01int4( ak_strat, '     in     ', start );
                            t01int4( ak_strat, '     in cnt ',
                                  acv.a_mblock.mb_st^[ stop ].elen_var );
&                           endif
                            access_info.srec_keyaccess.ka_startfields
                                  [ access_info.srec_keyaccess.ka_startcnt ] := start;
                            access_info.srec_keyaccess.ka_stopfields
                                  [ access_info.srec_keyaccess.ka_stopcnt ]  := start;
                            access_info.srec_keyaccess.ka_startcnt :=
                                  succ( access_info.srec_keyaccess.ka_startcnt );
                            access_info.srec_keyaccess.ka_stopcnt  :=
                                  succ( access_info.srec_keyaccess.ka_stopcnt );
                            access_info.srec_keyaccess.ka_infield.in_stpos   := start;
                            access_info.srec_keyaccess.ka_infield.in_elemcnt :=
                                  acv.a_mblock.mb_st^[ stop ].elen_var
                            END
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        IF  ( acv.a_mblock.mb_st^[ start ].epos <
                            acv.a_mblock.mb_st^[ access_info.srec_keyaccess.
                            ka_infield.in_stpos ].epos )
                        THEN
                            BEGIN
                            (* use the first IN in key sequence *)
                            FOR _ix := 0 TO MAX_COLPOSARR_IDX_GG07 DO
                                BEGIN
                                IF  ( access_info.srec_keyaccess.
                                    ka_startfields[ _ix ] =
                                    access_info.srec_keyaccess.ka_infield.in_stpos )
                                THEN
                                    access_info.srec_keyaccess.
                                          ka_startfields[ _ix ] := start;
                                (*ENDIF*) 
                                IF  ( access_info.srec_keyaccess.
                                    ka_stopfields[ _ix ] =
                                    access_info.srec_keyaccess.ka_infield.in_stpos )
                                THEN
                                    access_info.srec_keyaccess.
                                          ka_stopfields[ _ix ] := start;
                                (*ENDIF*) 
                                END;
                            (*ENDFOR*) 
                            access_info.srec_keyaccess.
                                  ka_infield.in_stpos   := start;
                            access_info.srec_keyaccess.
                                  ka_infield.in_elemcnt :=
                                  acv.a_mblock.mb_st^[ stop ].elen_var;
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        OTHERWISE
            BEGIN
&           ifdef TRACE
            t01name(ak_strat, 'uninteresting eop ');
&           endif
            END
        END;
    (*ENDCASE*) 
    END
ELSE
    BEGIN
    (* a71key_strat() has found op_eq_all *)
    (* special case for correlation       *)
&   ifdef trace
    t01sname( ak_strat, 'no insert   ' );
&   endif
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a71prepare_qual_on_index (
            VAR acv         : tak_all_command_glob;
            VAR qual_kind   : tgg00_QualKind );
 
VAR
      _new_op_entry    : boolean;
      _no_in_copy      : boolean;
      _change_ok       : boolean;
      _found           : boolean;
      _start_copy      : boolean;
      _eq_cond         : boolean;
      _ok              : boolean;
      _col_found       : boolean;
      _str_qual_kind   : tgg00_QualKind;
      _epos            : tsp00_Int2;
      _eop             : tgg00_StackOpType;
      _etype           : tgg00_StackEntryType;
      _ix              : tsp00_Int2;
      _iz              : tsp00_Int2;
      _jump_stack      : tsp00_Int2;
      _start           : tsp00_Int2;
      _stop            : tsp00_Int2;
      _index_no        : tsp00_Int2;
      _stpos1          : tsp00_Int2;
      _stpos2          : tsp00_Int2;
      _foundfield      : tsp00_Int2;
      _start_copy_st   : tsp00_Int2;
      _str_stpos       : tsp00_Int2;
      _idx_order       : tgg00_StackOpType;
      _st_order        : tgg00_StackOpType;
      _st_help         : tgg00_StackListPtr;
      _gg_strategy_ptr : ^tgg07_StrategyInfo;
      _only_qual_desc  : tgg00_StackDesc;
      _tabid           : tgg00_Surrogate;
      _index_scan_rec  : tak_index_scan_record;
      _join_strat      : boolean;
 
BEGIN
(* precondition: index strategy and no index only strategy *)
&ifdef TRACE
IF  ( t01trace( ak_strat ) OR t01trace( ak_join ) )
THEN
    BEGIN
    t01qual_kind( td_always, 'in qkind    ', qual_kind );
    t01stackdesc (td_always, 'MBUFFSTACK 1',
          acv.a_mblock.mb_qual^.mst_addr, acv.a_mblock.mb_qual^.mstack_desc);
    END;
&endif
(*ENDIF*) 
_start := acv.a_mblock.mb_qual^.mqual_pos;
_stop  := acv.a_mblock.mb_qual^.mqual_pos + acv.a_mblock.mb_qual^.mqual_cnt;
IF  ( _start < _stop ) AND
    ( acv.a_mblock.mb_st^[ _start ].etype = st_jump_output )
THEN
    _start := _start + acv.a_mblock.mb_st^[ _start ].epos - 1;
(*ENDIF*) 
IF  ( acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mstrat_pos ].elen_var >
    sizeof( tgg07_StrategyInfo ))
    OR
    ( acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mstrat_pos ].elen_var <=
    STRATEGY_START_MXGG07 )
    OR
    ( _start >= _stop )
THEN
    _change_ok := false
ELSE
    BEGIN
    _gg_strategy_ptr :=
          @acv.a_mblock.mb_strat^[ acv.a_mblock.
          mb_st^[ acv.a_mblock.mb_qual^.mstrat_pos ].epos ];
    _str_qual_kind := _gg_strategy_ptr^.str_qual_kind;
    _join_strat    := ( _gg_strategy_ptr^.str_strategy in a70glob_join_inv_strats );
    _change_ok     := (( _gg_strategy_ptr^.str_strategy in a70glob_inv_strats )
          OR _join_strat )
          AND ( _gg_strategy_ptr^.str_qual_kind <> inv_only );
&   ifdef trace
    IF  ( t01trace( ak_strat ) OR t01trace( ak_join ) )
    THEN
        a725output_gg_strat( td_always, 'strategy    ', _gg_strategy_ptr^ );
&   endif
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  ( _start < _stop ) AND _change_ok
THEN
    BEGIN
    _index_no   := 0;
    _jump_stack := 0;
    _str_stpos  := 0;
    _tabid := acv.a_mblock.mb_qual^.mtree.fileTabId_gg00;
    IF  ( _join_strat )
    THEN
        a24fnd_indexno( acv, _tabid,
              _gg_strategy_ptr^.str_join_multfields.sjmf_index_no, _index_scan_rec )
    ELSE
        a24fnd_indexno( acv, _tabid,
              _gg_strategy_ptr^.str_inv_in_range.siir_indexno, _index_scan_rec );
    (*ENDIF*) 
    IF  _index_scan_rec.isr_buf = NIL
    THEN
        _change_ok := false
    ELSE
        IF  a24IsFunctionBasedIndex(_index_scan_rec.isr_buf^.smindex.
            indexdef[ _index_scan_rec.isr_index ])
        THEN
            _change_ok := false;
        (*ENDIF*) 
    (*ENDIF*) 
    _only_qual_desc := acv.a_mblock.mb_qual^.mstack_desc;
    _st_help := NIL;
    IF  ( acv.a_mblock.mb_qual^.mfirst_free >= acv.a_mblock.mb_st_max )
    THEN
        _change_ok := false;
    (*ENDIF*) 
    IF  _change_ok
    THEN
        BEGIN
        a10new( acv, ( acv.a_mblock.mb_qual^.mfirst_free - 1 ) *
              STACK_ENTRY_MXGG00, _st_help );
        _change_ok := ( _st_help <> NIL );
        END;
    (*ENDIF*) 
    IF  _change_ok
    THEN
        BEGIN
        (* backup stackentries *)
        SAPDB_PascalMove('VAK71 ',   4,    
              acv.a_mblock.mb_st_size,
              ( acv.a_mblock.mb_qual^.mfirst_free - 1 ) * STACK_ENTRY_MXGG00,
              @acv.a_mblock.mb_st^, 1, @_st_help^, 1,
              ( acv.a_mblock.mb_qual^.mfirst_free - 1 ) * STACK_ENTRY_MXGG00,
              acv.a_returncode );
        IF  ( acv.a_returncode = 0 ) (* PTS 1113355 *)
        THEN
            BEGIN
            _start_copy    := true;
            _col_found     := false;
            acv.a_mblock.mb_qual^.minvqual_pos := acv.a_mblock.mb_qual^.mfirst_free;
            _start_copy_st := acv.a_mblock.mb_qual^.mfirst_free;
            _ix            := _start;
&           ifdef TRACE
            t01int4( ak_strat, 'start       ', _start );
            t01int4( ak_strat, 'stop        ', _stop );
&           endif
            WHILE ( _ix < _stop ) AND _change_ok DO
                BEGIN
&               ifdef TRACE
                t01int4( ak_strat, 'ix          ', _ix );
                t01bool( ak_strat, 'start_copy  ', _start_copy );
                t01bool( ak_strat, 'col_found   ', _col_found );
                t01int4( ak_strat, 'mfirst_fre  ',
                      acv.a_mblock.mb_qual^.mfirst_free );
&               endif
                CASE acv.a_mblock.mb_st^[ _ix ].etype OF
                    st_jump_false :
                        BEGIN
&                       ifdef trace
                        t01sname( ak_strat, 'jump false  ' );
&                       endif
                        IF  ( acv.a_mblock.mb_st^[ _ix ].eop = op_none )
                        THEN
                            BEGIN
                            IF  ( _start_copy )
                            THEN
                                BEGIN
                                IF  ( _col_found )
                                THEN
                                    BEGIN
                                    IF  ( acv.a_mblock.mb_qual^.mfirst_free <=
                                        acv.a_mblock.mb_st_max )
                                    THEN
                                        BEGIN
                                        (* copy stack entry *)
                                        acv.a_mblock.mb_st^[ acv.a_mblock.
                                              mb_qual^.mfirst_free ] :=
                                              acv.a_mblock.mb_st^[ _ix ];
                                        acv.a_mblock.mb_qual^.mfirst_free :=
                                              succ( acv.a_mblock.mb_qual^.mfirst_free );
                                        _start_copy_st :=
                                              acv.a_mblock.mb_qual^.mfirst_free;
                                        _jump_stack    := succ( _jump_stack );
                                        _col_found     := false;
                                        END
                                    ELSE
                                        _change_ok := false;
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    acv.a_mblock.mb_qual^.mfirst_free :=
                                          _start_copy_st
                                (*ENDIF*) 
                                END
                            ELSE
                                BEGIN
                                (* new predicate starts *)
                                _col_found  := false;
                                _start_copy := true;
                                END;
                            (*ENDIF*) 
                            END
                        ELSE
                            (* SHOW command *)
                            _change_ok := false;
                        (*ENDIF*) 
                        END;
                    st_jump_true :
                        BEGIN
&                       ifdef trace
                        t01sname( ak_strat, 'jump true   ' );
&                       endif
                        (* knock out *)
                        (* don't handle OR on index *)
                        _change_ok := false;
                        END;
                    st_jump_absolute :
                        BEGIN
&                       ifdef trace
                        t01sname( ak_strat, 'jump absolut' );
&                       endif
                        _ix := _ix + acv.a_mblock.mb_st^[ _ix ].epos;
                        END;
                    st_fixcol,
                    st_varcol,
                    st_varlongchar:
                        BEGIN
&                       ifdef trace
                        t01sname( ak_strat, 'f/v/vl col  ' );
&                       endif
                        (* index *)
                        IF  ( acv.a_mblock.mb_st^[ _ix ].ecol_tab[ 2 ] <> chr(0) )
                        THEN
                            a71search_thru_index ( acv, acv.a_mblock.mb_st^[ _ix ],
                                  _index_scan_rec.isr_buf^.smindex.
                                  indexdef[ _index_scan_rec.isr_index ],
                                  _foundfield )
                        ELSE
                            _foundfield := 0;
                        (*ENDIF*) 
                        IF  ( _foundfield > 0 )
                        THEN
                            BEGIN
                            IF  ( _join_strat )
                            THEN
                                BEGIN
                                (* calc position in index record *)
                                _epos := 1;
                                FOR _iz := 1 TO ( _foundfield - 1 ) DO
                                    _epos := _epos +
                                          _index_scan_rec.isr_buf^.
                                          smindex.indexdef[ _index_scan_rec.
                                          isr_index ].icolstack[ _iz ].elen_var;
                                (*ENDFOR*) 
                                IF  ( _epos < _gg_strategy_ptr^.str_key_len )
                                THEN
                                    _foundfield := 0;
                                (*ENDIF*) 
                                END
                            ELSE
                                IF  ak71is_stpos_in_invseq( _ix, _gg_strategy_ptr^.str_inv_in_range )
                                THEN
                                    _foundfield := 0;
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        IF  ( _foundfield > 0 )
                        THEN
                            BEGIN
                            (* stack position not in index sequence found *)
                            IF  ( acv.a_mblock.mb_qual^.mfirst_free <=
                                acv.a_mblock.mb_st_max )
                            THEN
                                BEGIN
                                (* qualification on index without *)
                                (* meaning for strategy           *)
                                _new_op_entry := false;
                                _epos         := 1;
                                IF  ( _foundfield > 1 )
                                THEN
                                    FOR _iz := 1 TO ( _foundfield - 1 ) DO
                                        _epos := _epos +
                                              _index_scan_rec.isr_buf^.smindex.
                                              indexdef[ _index_scan_rec.isr_index ].
                                              icolstack[ _iz ].elen_var;
                                    (*ENDFOR*) 
                                (*ENDIF*) 
                                _eop          := acv.a_mblock.mb_st^[ _ix ].eop;
                                _st_order     := _eop;
                                _idx_order    := _index_scan_rec.isr_buf^.smindex.
                                      indexdef[ _index_scan_rec.isr_index ].
                                      icolstack[ _foundfield ].eop;
                                (* check for correct _eop *)
                                IF  ( _idx_order in [ op_order_desc, op_unique_desc ] )
                                THEN
                                    BEGIN
                                    IF  NOT ( _st_order = _idx_order )
                                    THEN
                                        IF  acv.a_mblock.mb_st^[ _ix ].eop in
                                            [ op_none, op_order_asc, op_unique ]
                                        THEN
                                            _eop := _idx_order
                                        ELSE
                                            BEGIN
                                            _new_op_entry := true;
                                            _eop          := _idx_order;
                                            END
                                        (*ENDIF*) 
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    BEGIN
                                    (* ascending index *)
                                    IF  ( _st_order in [ op_order_desc, op_unique_desc ] )
                                    THEN
                                        _eop := op_none;
                                    (*ENDIF*) 
                                    END;
                                (*ENDIF*) 
                                IF  ( _foundfield <>
                                    a24IndexFieldCount( _index_scan_rec.isr_buf^.smindex.
                                    indexdef[ _index_scan_rec.isr_index ] ) )
                                THEN
                                    _etype := st_fixinv
                                ELSE
                                    _etype := st_varinv;
                                (*ENDIF*) 
                                g09IndexColStackentry( acv.a_mblock.
                                      mb_st^[ acv.a_mblock.mb_qual^.mfirst_free ],
                                      _etype,
                                      _epos,
                                      _eop,
                                      _index_scan_rec.isr_buf^.smindex.
                                      indexdef[ _index_scan_rec.isr_index ].
                                      icolstack[ _foundfield ].elen_var,
                                      0 (* tableno *));
                                acv.a_mblock.mb_qual^.mfirst_free  :=
                                      succ( acv.a_mblock.mb_qual^.mfirst_free );
                                IF  ( _new_op_entry )
                                THEN
                                    BEGIN
                                    g09OpStackentry( acv.a_mblock.
                                          mb_st^[ acv.a_mblock.mb_qual^.mfirst_free ],
                                          acv.a_mblock.mb_st^[ _ix ].eop );
                                    acv.a_mblock.mb_qual^.mfirst_free  :=
                                          succ( acv.a_mblock.mb_qual^.mfirst_free );
                                    END;
                                (*ENDIF*) 
                                END
                            ELSE
                                _change_ok := false;
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN (* PTS 1114232 *)
                            (* column for strategy found *)
                            _start_copy := false;
                            acv.a_mblock.mb_qual^.mfirst_free
                                  := _start_copy_st;
                            END;
                        (*ENDIF*) 
                        IF  ( NOT _change_ok ) OR ( NOT _start_copy )
                        THEN
                            _col_found  := false
                        ELSE
                            IF  ( NOT _col_found )
                            THEN
                                _col_found  := true;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END;
                    st_fixkey,
                    st_varkey :
                        BEGIN
&                       ifdef trace
                        t01sname( ak_strat, 'f/v key     ' );
&                       endif
                        _found   := false;
                        _eq_cond := true;
                        _iz      := 0;
                        WHILE ( _iz <= MAX_COLPOSARR_IDX_GG07 ) AND
                              ( NOT _found ) AND _eq_cond DO
                            BEGIN
                            _stpos1 := abs( _gg_strategy_ptr^.
                                  str_key_in_range.skir_keystart[ _iz ] );
                            _stpos2 := abs( _gg_strategy_ptr^.
                                  str_key_in_range.skir_keystop[ _iz ] );
                            IF  ( _stpos1 = 0 ) AND ( _stpos2 = 0 )
                            THEN
                                _iz := MAX_COLPOSARR_IDX_GG07
                            ELSE
                                BEGIN
                                _found := _eq_cond AND
                                      (( _stpos1 = _ix ) OR ( _stpos2 = _ix ));
                                _eq_cond := (_gg_strategy_ptr^.
                                      str_key_in_range.skir_keystart[ _iz ] =
                                      _gg_strategy_ptr^.
                                      str_key_in_range.skir_keystop[ _iz ]);
                                END;
                            (*ENDIF*) 
                            _iz := succ( _iz );
                            END;
                        (*ENDWHILE*) 
                        IF  ( NOT _found ) AND
                            ( acv.a_mblock.mb_st^[ _ix ].ecol_tab[ 2 ] <> chr(0) )
                        THEN
                            BEGIN
                            IF  ( _join_strat )
                            THEN
                                BEGIN
                                a71search_thru_index ( acv, acv.a_mblock.mb_st^[ _ix ],
                                      _index_scan_rec.isr_buf^.smindex.
                                      indexdef[ _index_scan_rec.isr_index ],
                                      _foundfield );
                                IF  ( _foundfield > 0 )
                                THEN
                                    BEGIN
                                    (* calc position in index record *)
                                    _epos := 1;
                                    FOR _iz := 1 TO ( _foundfield - 1 ) DO
                                        _epos := _epos +
                                              _index_scan_rec.isr_buf^.
                                              smindex.indexdef[ _index_scan_rec.
                                              isr_index ].icolstack[ _iz ].elen_var;
                                    (*ENDFOR*) 
                                    IF  ( _epos < _gg_strategy_ptr^.str_key_len )
                                    THEN
                                        _found := true
                                    ELSE
                                        _found := false;
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    _found := false;
                                (*ENDIF*) 
                                END
                            ELSE
                                _found := ak71is_stpos_in_invseq( _ix,
                                      _gg_strategy_ptr^.str_inv_in_range );
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        IF  ( NOT _found )
                        THEN
                            BEGIN
                            IF  ( acv.a_mblock.mb_qual^.mfirst_free <=
                                acv.a_mblock.mb_st_max )
                            THEN
                                BEGIN
                                acv.a_mblock.
                                      mb_st^[ acv.a_mblock.mb_qual^.mfirst_free ] :=
                                      acv.a_mblock.mb_st^[ _ix ];
                                IF  ( acv.a_mblock.
                                    mb_st^[ acv.a_mblock.mb_qual^.mfirst_free ].
                                    etype = st_fixkey )
                                THEN
                                    _etype := st_fixprimkey
                                ELSE
                                    _etype := st_varprimkey;
                                (*ENDIF*) 
                                g09ColStackentry( acv.a_mblock.
                                      mb_st^[ acv.a_mblock.mb_qual^.mfirst_free ],
                                      _etype,
                                      acv.a_mblock.mb_st^[ _ix ].epos,
                                      acv.a_mblock.mb_st^[ _ix ].elen_var,
                                      ord( acv.a_mblock.mb_st^[ _ix ].ecol_tab[ 2 ]) );
                                acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mfirst_free ].eop
                                      := acv.a_mblock.mb_st^[ _ix ].eop;
                                acv.a_mblock.mb_qual^.mfirst_free :=
                                      succ( acv.a_mblock.mb_qual^.mfirst_free );
                                END
                            ELSE
                                _change_ok := false;
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN (* PTS 1114232 *)
                            _start_copy := false;
                            acv.a_mblock.mb_qual^.mfirst_free
                                  := _start_copy_st;
                            END;
                        (*ENDIF*) 
                        IF  ( NOT _change_ok ) OR ( NOT _start_copy )
                        THEN
                            _col_found  := false
                        ELSE
                            IF  ( NOT _col_found )
                            THEN
                                _col_found  := true;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END;
                    st_old_fixkey,
                    st_old_varkey,
                    st_old_fixcol,
                    st_old_varcol,
                    st_old_varlongchar,
                    st_subquery,
                    st_get_subquery,
                    st_short_scol,
                    st_bool,
                    st_long_scol :
                        BEGIN
&                       ifdef trace
                        t01sname( ak_strat, 'other cols  ' );
&                       endif
                        _start_copy := false;
                        _col_found  := false;
                        acv.a_mblock.mb_qual^.mfirst_free
                              := _start_copy_st;
                        END;
                    OTHERWISE
                        BEGIN
&                       ifdef trace
                        t01sname( ak_strat, 'otherwise   ' );
                        t01bool( ak_strat, '_change_ok  ', _change_ok );
                        t01bool( ak_strat, '_start_copy ', _start_copy );
                        t01int4( ak_strat, '_jump_stack ', _jump_stack );
&                       endif
                        _no_in_copy := ( acv.a_mblock.mb_st^[ _ix ].eop = op_in ) AND
                              ( acv.a_mblock.mb_st^[ _ix ].elen_var > c_max_in_index_qual );
                        _change_ok := NOT ( acv.a_mblock.mb_st^[ _ix ].eop in
                              [ op_or, op_upd_view_and ] );
                        IF  ( _change_ok )
                        THEN
                            BEGIN
                            IF  ( acv.a_mblock.mb_st^[ _ix ].etype = st_value ) AND
                                ( acv.a_mblock.mb_st^[ _ix ].eop   = op_not_null )
                            THEN
                                BEGIN
                                _start_copy := false;
                                _col_found  := false;
                                acv.a_mblock.mb_qual^.mfirst_free := _start_copy_st;
                                END;
                            (*ENDIF*) 
                            IF  ( acv.a_mblock.mb_st^[ _ix ].eop = op_and )
                            THEN
                                BEGIN
                                IF  ( _start_copy AND ( NOT _col_found ))
                                THEN
                                    acv.a_mblock.mb_qual^.mfirst_free := _start_copy_st
                                ELSE
                                    _col_found   := true;
                                (*ENDIF*) 
                                IF  ( acv.a_mblock.
                                    mb_st^[ acv.a_mblock.mb_qual^.mfirst_free - 1 ].
                                    etype = st_jump_false )
                                THEN
                                    BEGIN
                                    acv.a_mblock.mb_qual^.mfirst_free :=
                                          pred( acv.a_mblock.mb_qual^.mfirst_free );
                                    _jump_stack  := pred( _jump_stack );
                                    END;
                                (*ENDIF*) 
                                IF  ( _jump_stack > 0 )
                                THEN
                                    BEGIN
                                    _start_copy := true;
                                    _jump_stack := pred( _jump_stack )
                                    END
                                ELSE
                                    _start_copy := false;
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                            IF  ( _start_copy )
                            THEN
                                IF  ( _no_in_copy )
                                THEN
                                    _change_ok := false
                                ELSE
                                    IF  ( acv.a_mblock.mb_qual^.mfirst_free <=
                                        acv.a_mblock.mb_st_max )
                                    THEN
                                        BEGIN
                                        (* copy stack entry *)
                                        acv.a_mblock.
                                              mb_st^[ acv.a_mblock.mb_qual^.mfirst_free ] :=
                                              acv.a_mblock.mb_st^[ _ix ];
                                        acv.a_mblock.mb_qual^.mfirst_free  :=
                                              succ( acv.a_mblock.mb_qual^.mfirst_free );
                                        END
                                    ELSE
                                        _change_ok := false;
                                    (*ENDIF*) 
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END;
                    END;
                (*ENDCASE*) 
&               ifdef TRACE
                t01int4( ak_strat, 'mfirst_free ', acv.a_mblock.mb_qual^.mfirst_free );
                t01bool( ak_strat, '_change_ok  ', _change_ok );
                t01bool( ak_strat, '_start_copy ', _start_copy );
                t01name( ak_strat, '------------------');
&               endif
                IF  ( _change_ok )
                THEN
                    IF  ( _start_copy )
                    THEN
                        _ix := succ( _ix )
                    ELSE
                        BEGIN
                        _ix := succ( _ix );
                        _ok := true;
                        WHILE ( _ix < _stop ) AND _ok DO
                            (* h.b. PTS 1000917 *)
                            BEGIN
                            IF  ( acv.a_mblock.mb_st^[ _ix ].eop = op_or ) OR
                                ( acv.a_mblock.mb_st^[ _ix ].etype = st_jump_true )
                            THEN
                                BEGIN
                                _ix := _stop;
                                _change_ok := false;
                                END
                            ELSE
                                BEGIN
&                               ifdef TRACE
                                t01int4( ak_strat, '_ix         ', _ix );
&                               endif
                                IF  ( acv.a_mblock.mb_st^[ _ix ].etype = st_jump_false )
                                    OR
                                    (( acv.a_mblock.mb_st^[ _ix ].eop = op_and ) AND
                                    ( acv.a_mblock.mb_st^[ _ix - 1 ].eop <> op_and ))
                                THEN
                                    BEGIN
                                    acv.a_mblock.mb_qual^.mfirst_free
                                          := _start_copy_st;
                                    _ok   := false;
                                    END
                                ELSE
                                    _ix := succ( _ix );
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                            END;
                        (*ENDWHILE*) 
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDWHILE*) 
            acv.a_mblock.mb_qual^.minvqual_cnt :=
                  acv.a_mblock.mb_qual^.mfirst_free -
                  acv.a_mblock.mb_qual^.minvqual_pos;
&           ifdef trace
            t01int4( ak_strat, 'minvqual_cnt', acv.a_mblock.mb_qual^.minvqual_cnt );
            t01bool( ak_strat, '_change_ok  ', _change_ok );
&           endif
            IF  ( acv.a_mblock.mb_qual^.minvqual_cnt > 0 )
            THEN
                _gg_strategy_ptr^.str_qual_kind := inv_and_primary;
            (*ENDIF*) 
            IF  _change_ok AND ( _gg_strategy_ptr^.str_qual_kind = inv_and_primary )
            THEN
                BEGIN
                _start := acv.a_mblock.mb_qual^.minvqual_pos;
                _stop  := acv.a_mblock.mb_qual^.minvqual_pos +
                      acv.a_mblock.mb_qual^.minvqual_cnt;
                _ix    := acv.a_mblock.mb_qual^.mfirst_free;
                WHILE ( _start < _stop ) AND _change_ok DO
                    BEGIN
                    IF  ( acv.a_mblock.mb_st^[ _start ].etype = st_jump_false )
                    THEN
                        IF  ( acv.a_mblock.mb_st^[ _ix - 1 ].eop = op_and )
                        THEN
                            BEGIN
                            acv.a_mblock.mb_st^[ _start ].epos := _ix - _start;
                            _ix := pred( _ix );
                            END
                        ELSE
                            _change_ok := false;
                        (*ENDIF*) 
                    (*ENDIF*) 
                    _start := succ( _start );
                    END;
                (*ENDWHILE*) 
                END;
            (*ENDIF*) 
            IF  ( _change_ok )
            THEN
                qual_kind := _gg_strategy_ptr^.str_qual_kind;
            (*ENDIF*) 
            IF  ( NOT _change_ok OR
                ( _gg_strategy_ptr^.str_qual_kind <> inv_and_primary ))
            THEN
                BEGIN
                (* restore original stack entries *)
                _gg_strategy_ptr^.str_qual_kind := _str_qual_kind;
                acv.a_mblock.mb_qual^.mstack_desc := _only_qual_desc;
                SAPDB_PascalMove ('VAK71 ',   5,    
                      ( acv.a_mblock.mb_qual^.mfirst_free - 1 ) * STACK_ENTRY_MXGG00,
                      acv.a_mblock.mb_st_size, @_st_help^, 1,
                      @acv.a_mblock.mb_st^, 1,
                      ( acv.a_mblock.mb_qual^.mfirst_free - 1 ) * STACK_ENTRY_MXGG00,
                      acv.a_returncode);
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  _st_help <> NIL
    THEN
        a10dispose ( acv, _st_help );
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
&ifdef TRACE
IF  ( t01trace( ak_strat ) OR t01trace( ak_join ) )
THEN
    BEGIN
    t01stackdesc (td_always, 'MBUFFSTACK 2',
          acv.a_mblock.mb_qual^.mst_addr, acv.a_mblock.mb_qual^.mstack_desc);
    t01qual_kind( td_always, 'out qkind   ', qual_kind );
    END;
&endif
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      ak71is_stpos_in_invseq(
            stpos           : tsp00_Int2;
            VAR invstrat    : tgg07_StrInvInRange) : boolean;
 
VAR
      _iz       : tsp00_Int2;
      _found    : boolean;
 
BEGIN
_iz    := 0;
_found := false;
WHILE ( _iz < invstrat.siir_startcnt ) AND NOT _found DO
    IF  ( abs( invstrat.siir_invstart[ _iz ] ) = stpos )
    THEN
        _found := true
    ELSE
        _iz := succ( _iz );
    (*ENDIF*) 
(*ENDWHILE*) 
_iz    := 0;
WHILE ( _iz < invstrat.siir_stopcnt ) AND NOT _found DO
    IF  ( abs( invstrat.siir_invstop[ _iz ] ) = stpos )
    THEN
        _found := true
    ELSE
        _iz := succ( _iz );
    (*ENDIF*) 
(*ENDWHILE*) 
ak71is_stpos_in_invseq := _found;
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak71check_build_requirements (
            VAR acv            : tak_all_command_glob;
            VAR config         : tak00_access_configuration;
            VAR qprop          : tak70_query_properties;
            VAR gg_strategy    : tgg07_StrategyInfo (*const*);
            stratenum          : tgg07_StratEnum;
            VAR strat_data     : tgg07_StrRaw;
            VAR write_needings : tak70_write_needings);
 
VAR
      _inv_strat_ptr  : ^tgg07_StrInvInRange;
      _key_strat_ptr  : ^tgg07_StrKeyInRange;
 
BEGIN
(* input strats are always non fetch (initial) strategies *)
&ifdef TRACE
t01bool( ak_strat, 'build_result', gg_strategy.str_build_result );
t01int4( ak_strat, 'rowno       ', gg_strategy.str_rowno );
t01bool( ak_strat, 'use_rowno   ', gg_strategy.str_use_rowno );
t01int4( ak_strat, 'key ord sppt', ord(gg_strategy.str_key_order_support));
t01bool( ak_strat, 'from select ', acv.a_from_select );
t01bool( ak_strat, 'gvn rescnt  ', qp_given_rescnt in qprop.qps_switches );
t01bool( ak_strat, 'build qprop ', qp_build_result in qprop.qps_switches );
t01bool( ak_strat, 'build config', cs_build_result in config.cfg_switches );
&endif
write_needings := write_nothing;
IF  ( cs_build_result in config.cfg_switches )
    OR
    ( qp_build_result in qprop.qps_switches )
THEN
    write_needings := write_result;
(*ENDIF*) 
;
(* furhter tests *)
;
IF  ( stratenum in a70glob_key_strats )
THEN
    BEGIN
    _key_strat_ptr := @strat_data;
    IF  ( ksp_aggr_MIN_opt in _key_strat_ptr^.skir_strat_props ) OR
        ( ksp_aggr_MAX_opt in _key_strat_ptr^.skir_strat_props )
    THEN
        write_needings := write_result;
    (*ENDIF*) 
    IF  (( NOT ( cs_operator_join in config.cfg_switches )) AND
        ( stratenum in [ strat_key_in, strat_key_subq ] ))
    THEN
        (* up to now we have to build a result set for these strategies *)
        write_needings := write_result;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
IF  ( stratenum in a70glob_inv_strats )
THEN
    BEGIN
    _inv_strat_ptr := @strat_data;
    IF  ( isp_aggr_MIN_opt in _inv_strat_ptr^.siir_strat_props ) OR
        ( isp_aggr_MAX_opt in _inv_strat_ptr^.siir_strat_props )
    THEN
        write_needings := write_result;
    (*ENDIF*) 
    IF  (( NOT ( cs_operator_join in config.cfg_switches ))
        AND
        ( stratenum in [ strat_inv_in, strat_inv_subq ] ))
    THEN
        (* up to now we have to build a result set for these strategies *)
        write_needings := write_result;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
&ifdef trace
(* test preconditions *)
IF  ((( gg_strategy.str_distinc <> no_distinct ) OR ( gg_strategy.str_use_order ))
    AND
    ( cs_operator_join in config.cfg_switches ))
THEN
    a07ak_system_error(acv, 70, 3 );
(*ENDIF*) 
;
&endif
IF  ( write_needings = write_nothing ) AND
    ( gg_strategy.str_distinc <> no_distinct ) AND
    ( NOT a71is_duplicate_avoidance( gg_strategy, stratenum,
    strat_data, qprop ))
THEN
    (* check for DISTINCT optim *)
    BEGIN
    write_needings := write_result;
&   ifdef trace
    t01name( ak_strat, 'dist optim imposs ' );
&   endif
    END;
(*ENDIF*) 
;
IF  ( stratenum <> strat_key_equal )
THEN
    BEGIN
    IF  ( write_needings = write_nothing ) AND
        ( gg_strategy.str_use_order )
    THEN
        (* check for ORDER BY optim *)
        BEGIN
        IF  ( stratenum in a70glob_key_strats )
        THEN
            BEGIN
            IF  ( gg_strategy.str_key_order_support = kos_no_support )
            THEN
                BEGIN
                write_needings := write_result;
&               ifdef trace
                t01sname( ak_strat, 'no key order' );
&               endif
                END;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            IF  ( stratenum in a70glob_inv_strats )
            THEN
                BEGIN
                IF  NOT ( isp_order_support in _inv_strat_ptr^.siir_strat_props )
                THEN
                    BEGIN
&                   ifdef trace
                    t01sname( ak_strat, 'no inv order' );
&                   endif
                    IF  ( gg_strategy.str_key_order_support = kos_asc )
                    THEN
                        BEGIN
                        IF  ( isp_exact_match in
                            _inv_strat_ptr^.siir_strat_props )
                        THEN
                            BEGIN
                            (* nothing to do, because there is only one *)
                            (* list of primary keys and this list is    *)
                            (* ascending sorted by primary key          *)
                            END
                        ELSE
                            BEGIN
                            IF  ( isp_listmerge_allowed in
                                _inv_strat_ptr^.siir_strat_props )
                            THEN
                                BEGIN
                                write_needings := write_keylist;
&                               ifdef trace
                                t01sname( ak_strat, 'merge key   ' );
&                               endif
                                END
                            ELSE
                                write_needings := write_result;
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END
                    ELSE
                        write_needings := write_result;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END
ELSE
    BEGIN
    (* only one result row --> nothing to do *)
    END;
(*ENDIF*) 
;
&ifdef trace
CASE write_needings OF
    write_nothing :
        t01sname( ak_strat, 'write_nothin' );
    write_keylist :
        t01sname( ak_strat, 'write_keylis' );
    write_result  :
        t01sname( ak_strat, 'write_result' );
    OTHERWISE
        a07ak_system_error( acv, 71, 2 );
    END;
(*ENDCASE*) 
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    CASE write_needings OF
        write_nothing :
            g041name_to_trace( acv.a_transinf.tri_trans, 'write nothing     ' );
        write_keylist :
            g041name_to_trace( acv.a_transinf.tri_trans, 'write keylist     ' );
        write_result  :
            g041name_to_trace( acv.a_transinf.tri_trans, 'write result      ' );
        OTHERWISE
            ;
        END;
    (*ENDCASE*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a71check_fetch_optimization (
            VAR acv         : tak_all_command_glob;
            VAR config      : tak00_access_configuration;
            VAR qprop       : tak70_query_properties;
            VAR gg_strategy : tgg07_StrategyInfo (*const*);
            VAR strategy    : tgg07_StratEnum;
            VAR strat_data  : tgg07_StrRaw);
 
VAR
      _inv_strat_ptr    : ^tgg07_StrInvInRange;
      _write_needings   : tak70_write_needings;
 
BEGIN
&ifdef TRACE
t01strat_enum( ak_strat, 'input  strat', strategy );
&endif
ak71check_build_requirements( acv, config, qprop, gg_strategy,
      strategy, strat_data, _write_needings );
;
IF  ( _write_needings in [ write_nothing, write_keylist ] )
THEN
    BEGIN
    (* build fetch strategy *)
    IF  ( strategy in a70glob_key_strats )
    THEN
        (* key strategy *)
        BEGIN
        IF  ( strategy = strat_key_equal )
        THEN
            strategy := strat_key_equal_fetch
        ELSE
            IF  ( strategy = strat_key_range )
            THEN
                strategy := strat_key_range_fetch
            ELSE
                BEGIN
                IF  NOT
                    (( cs_operator_join in config.cfg_switches ) AND
                    (( strategy in a70glob_accessop_known_strats )) )
                THEN
                    (* up to now we have to build a result set for these strategies *)
                    a07ak_system_error( acv, 71, 5 );
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  ( strategy in a70glob_inv_strats )
        THEN
            (* index strategy *)
            BEGIN
            IF  ( strategy = strat_inv_range )
            THEN
                BEGIN
                _inv_strat_ptr := @strat_data;
                IF  ( _write_needings = write_keylist )
                THEN
                    BEGIN
                    IF  ( isp_listmerge_allowed in _inv_strat_ptr^.siir_strat_props )
                    THEN
                        strategy := strat_inv_range_merge_fetch
                    ELSE
                        BEGIN
                        (* build of result set necessary *)
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    strategy := strat_inv_range_fetch;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                IF  NOT
                    (( cs_operator_join in config.cfg_switches ) AND
                    (( strategy in a70glob_accessop_known_strats )) )
                THEN
                    (* up to now we have to build a result set for these strategies *)
                    a07ak_system_error( acv, 71, 6 );
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
&ifdef TRACE
t01strat_enum( ak_strat, 'output strat', strategy );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      a71calculate_pageIO (
            VAR acv             : tak_all_command_glob;
            VAR sparr           : tak_syspointerarr;
            VAR access_info     : tak70_strategy_record (*const*);
            VAR strategy        : tak70_one_strat;
            read_primpages      : tsp00_Int4;
            read_primrows       : tsp00_Int4;
            VAR key_strat_value : tsp00_Longreal(*const, needed for inv strats*);
            read_invpages       : tsp00_Int4;
            outrec_len          : tsp00_Int2);
 
VAR
      _pageIO               : tsp00_Int4;
      _InvReadIO            : tsp00_Int4;
      _PrimReadIO           : tsp00_Int4;
      _writeIO              : tsp00_Int4;
      _readIO               : tsp00_Int4;
      _mergeIO              : tsp00_Int4;
      _recs_per_respage     : tsp00_Int4;
      _baserec_len          : tsp00_Int2;
      _primkeylen           : tsp00_Int2;
      _rescnt               : tsp00_Int4;
      _act_key_build_strats : ^tgg07_StratEnumSet;
      _act_inv_build_strats : ^tgg07_StratEnumSet;
 
BEGIN
(* designations: *)
(* P  - search range on primary table given by key range          *)
(* PI - search range on primary table limited by index access     *)
(* E  - result set                                                *)
(* I  - search area on index limited by index range and key range *)
(* M - merged list consists of primary keys of individual primary *)
(*     key lists                                                  *)
_pageIO        := IS_UNDEFINED_GG07;
_writeIO       := IS_UNDEFINED_GG07;
_readIO        := IS_UNDEFINED_GG07;
_baserec_len   := sparr.pbasep^.sbase.bavgrowlen;
&ifdef trace
t01strat_enum( ak_strat, 'calc strat  ', strategy.ostr_strategy );
t01int4( ak_strat, 'read ppages ', read_primpages );
t01int4( ak_strat, 'read ipages ', read_invpages );
IF  ( strategy.ostr_strategy in a70glob_inv_strats )
THEN
    t01real( ak_strat, 'key stratval', key_strat_value, 6 );
(*ENDIF*) 
t01real( ak_strat, 'strat value ', strategy.ostr_strat_value, 6 );
t01int4( ak_strat, 'outrec_len  ', outrec_len );
t01int4( ak_strat, 'baserec_len ', _baserec_len );
IF  ( outrec_len < 0 ) OR ( _baserec_len < 0 )
THEN
    a07ak_system_error( acv, 71, 3 );
&endif
(*ENDIF*) 
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace ( acv.a_transinf.tri_trans,
          'A71CALCULATE_PAGEIO           ' );
    g041longreal_to_trace( acv.a_transinf.tri_trans,
          'strat value       ', strategy.ostr_strat_value );
    g041int4_to_trace( acv.a_transinf.tri_trans,
          'read ppages       ', read_primpages );
    IF  ( strategy.ostr_strategy in a70glob_inv_strats )
    THEN
        BEGIN
        g041int4_to_trace( acv.a_transinf.tri_trans,
              'read ipages       ', read_invpages );
        g041longreal_to_trace( acv.a_transinf.tri_trans,
              'key strat value   ', key_strat_value );
        END;
    (*ENDIF*) 
    g041int4_to_trace( acv.a_transinf.tri_trans,
          'output reclen     ', outrec_len );
    g041int4_to_trace( acv.a_transinf.tri_trans,
          'base reclen       ', _baserec_len );
    END;
(*ENDIF*) 
IF  ( outrec_len = 0 )
THEN
    IF  ( _baserec_len <> 0 )
    THEN
        outrec_len := _baserec_len
    ELSE
        (* _baserec_len=0 AND outrec_len=0 *)
        BEGIN
        (* outrec_len / _baserec_len = 1 *)
        outrec_len   := IS_UNDEFINED_GG07;
        _baserec_len := IS_UNDEFINED_GG07;
&       ifdef trace
        t01sname( ak_strat, 'reclen init1' );
&       endif
        END;
    (*ENDIF*) 
(*ENDIF*) 
IF  ( _baserec_len = 0 )
THEN
    (* hence outrec_len <> 0 *)
    BEGIN
    _baserec_len := outrec_len;
&   ifdef trace
    t01sname( ak_strat, 'reclen init2' );
&   endif
    END;
(*ENDIF*) 
;
IF  ( cs_operator_join in access_info.srec_config.cfg_switches )
THEN
    BEGIN
    _act_key_build_strats := @a70glob_accessop_key_build_strats;
    _act_inv_build_strats := @a70glob_accessop_inv_build_strats;
    END
ELSE
    BEGIN
    _act_key_build_strats := @a70glob_key_build_strats;
    _act_inv_build_strats := @a70glob_inv_build_strats;
    END;
(*ENDIF*) 
;
(* calculate IO costs *)
IF  ( strategy.ostr_strategy in a70glob_key_strats )
THEN
    BEGIN
&   ifdef trace
    t01sname( ak_strat, 'primpages   ' );
&   endif
    ;
    IF  ( g01vtrace.vtrStrategy_gg00 )
    THEN
        BEGIN
        g041c30_to_trace ( acv.a_transinf.tri_trans,
              'calc primpages                ' );
        END;
    (*ENDIF*) 
    ;
    (* calculate read IO *)
    (* read primary page *)
    _PrimReadIO := read_primpages;
    ;
    (* calculate write IO    *)
    (* calculate result size *)
    IF  ( outrec_len <> IS_UNDEFINED_GG07 )
        AND
        (( qp_given_rescnt in access_info.srec_query_prop.qps_switches )
        OR
        (( strategy.ostr_strategy = strat_key_in ) AND
        ( ksp_exact_IN_SUBQ_match in
        strategy.ostr_key_in_range.skir_strat_props )))
    THEN
        BEGIN
        _recs_per_respage := trunc(( cak_page80percent/outrec_len ) + 0.5 );
        IF  ( _recs_per_respage = 0 )
        THEN
            _recs_per_respage := 1;
        (*ENDIF*) 
        ;
&       ifdef trace
        t01int4( ak_strat, 'recs p rpage', _recs_per_respage );
&       endif
        IF  ( access_info.srec_query_prop.qps_rescnt <> IS_UNDEFINED_GG07 ) AND
            ( strategy.ostr_key_in_range.skir_inelemcnt = IS_UNDEFINED_GG07 )
        THEN
            _rescnt := access_info.srec_query_prop.qps_rescnt
        ELSE
            BEGIN
            IF  ( access_info.srec_query_prop.qps_rescnt = IS_UNDEFINED_GG07 ) AND
                ( strategy.ostr_key_in_range.skir_inelemcnt <> IS_UNDEFINED_GG07 )
            THEN
                _rescnt := strategy.ostr_key_in_range.skir_inelemcnt
            ELSE
                (* both values are defined *)
                BEGIN
                IF  ( access_info.srec_query_prop.qps_rescnt <
                    strategy.ostr_key_in_range.skir_inelemcnt )
                THEN
                    _rescnt := access_info.srec_query_prop.qps_rescnt
                ELSE
                    _rescnt := strategy.ostr_key_in_range.skir_inelemcnt;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        _writeIO      := _rescnt DIV _recs_per_respage;
        read_primrows := _rescnt;
        END
    ELSE
        BEGIN
        (* outrec_len == IS_UNDEFINED_GG07 --> _baserec_len == IS_UNDEFINED_GG07 *)
        (* calculate write IO as fraction between base record length *)
        (* and output record length                                  *)
        _writeIO := trunc((_PrimReadIO*(outrec_len/_baserec_len) ) + 0.5 );
        END;
    (*ENDIF*) 
    IF  ( _writeIO = 0 )
    THEN
        _writeIO := 1;
    (*ENDIF*) 
    ;
    (* calculate IO costs *)
    (* primary page + page cost for ordering + build costs *)
    IF  ( strategy.ostr_strategy in _act_key_build_strats^ )
    THEN
        BEGIN
        (* cost KEY BUILD = read P, write E, read E (fetch) *)
        _pageIO := _PrimReadIO  + _writeIO  + _writeIO;
        END
    ELSE
        BEGIN
        (* cost KEY FETCH = read P (fetch) *)
        _pageIO := _PrimReadIO;
        END;
    (*ENDIF*) 
    _readIO := _PrimReadIO;
&   ifdef trace
    t01int4( ak_strat, 'read ppages ', _PrimReadIO );
    t01int4( ak_strat, 'read I/O    ', _readIO );
&   endif
    END
ELSE
    BEGIN
    (* calculate read IO with index strategy *)
    IF  ( strategy.ostr_strategy in a70glob_inv_strats )
    THEN
        BEGIN
        _InvReadIO := read_invpages;
        IF  _InvReadIO = 0
        THEN
            _InvReadIO := 1;
        (*ENDIF*) 
        ;
        IF  ( isp_inv_only in strategy.ostr_inv_in_range.siir_strat_props )
        THEN
            BEGIN
&           ifdef trace
            t01sname( ak_strat, 'ipages only ' );
&           endif
            IF  ( g01vtrace.vtrStrategy_gg00 )
            THEN
                BEGIN
                g041c30_to_trace ( acv.a_transinf.tri_trans,
                      'calc ipages only              ' );
                END;
            (*ENDIF*) 
            ;
            (* calculate read IO    *)
            (* read only indexpages *)
            ;
            IF  ( outrec_len <> IS_UNDEFINED_GG07 )
                AND
                (( qp_given_rescnt in access_info.srec_query_prop.qps_switches )
                OR
                (( strategy.ostr_strategy = strat_inv_in ) AND
                ( isp_exact_IN_SUBQ_match in
                strategy.ostr_inv_in_range.siir_strat_props ) AND
                ( isp_unique_idx in
                strategy.ostr_inv_in_range.siir_strat_props )))
            THEN
                BEGIN
                _recs_per_respage := trunc(( cak_page80percent / outrec_len ) + 0.5 );
                IF  ( _recs_per_respage = 0 )
                THEN
                    _recs_per_respage := 1;
                (*ENDIF*) 
                ;
&               ifdef trace
                t01int4( ak_strat, 'recs p rpage', _recs_per_respage );
&               endif
                IF  ( access_info.srec_query_prop.qps_rescnt <> IS_UNDEFINED_GG07 ) AND
                    ( strategy.ostr_inv_in_range.siir_inelemcnt = IS_UNDEFINED_GG07 )
                THEN
                    _rescnt := access_info.srec_query_prop.qps_rescnt
                ELSE
                    BEGIN
                    IF  ( access_info.srec_query_prop.qps_rescnt = IS_UNDEFINED_GG07 ) AND
                        ( strategy.ostr_inv_in_range.siir_inelemcnt <> IS_UNDEFINED_GG07 )
                    THEN
                        _rescnt := strategy.ostr_inv_in_range.siir_inelemcnt
                    ELSE
                        (* both values are defined *)
                        BEGIN
                        IF  ( access_info.srec_query_prop.qps_rescnt <
                            strategy.ostr_inv_in_range.siir_inelemcnt )
                        THEN
                            _rescnt := access_info.srec_query_prop.qps_rescnt
                        ELSE
                            _rescnt := strategy.ostr_inv_in_range.siir_inelemcnt;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                _writeIO      := _rescnt DIV _recs_per_respage;
                read_primrows := _rescnt;
                END
            ELSE
                BEGIN
                IF  ( isp_unique_idx in strategy.ostr_inv_in_range.
                    siir_strat_props )
                THEN
                    (* defined index-record length *)
                    BEGIN
&                   ifdef trace
                    t01sname( ak_strat, 'estim supprt' );
&                   endif
                    _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 := outrec_len -
                              strategy.ostr_inv_in_range.siir_invlen;
                    (*ENDIF*) 
                    _writeIO := trunc(( _InvReadIO *
                          (outrec_len /
                          ( strategy.ostr_inv_in_range.siir_invlen +
                          _primkeylen ))) + 0.5 );
                    END
                ELSE
                    (* we can't create ratio outrec_len/_rec_len for *)
                    (* index-keylist record                          *)
                    _writeIO := _InvReadIO;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  ( _writeIO = 0 )
            THEN
                _writeIO := 1;
            (*ENDIF*) 
            ;
            (* calculate IO costs ( only index pages ) *)
            IF  ( strategy.ostr_strategy in _act_inv_build_strats^ )
            THEN
                (* build costs (includes 'order by' costs) *)
                BEGIN
                (* cost ONLY INDEX BUILD = read I, write E, read E (fetch) *)
                _pageIO := _InvReadIO  + _writeIO + _writeIO;
                END
            ELSE
                BEGIN
                (* FETCH strategies *)
                IF  ( strategy.ostr_strategy = strat_inv_range_merge_fetch )
                THEN
                    BEGIN
                    (* merged list isn't a full fledged index *)
                    (* it consists only primary keys          *)
                    a07ak_system_error( acv, 71, 4 );
                    END
                ELSE
                    BEGIN
                    (* cost ONLY INDEX FETCH = read I (fetch) *)
                    _pageIO := _InvReadIO;
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            _readIO := _InvReadIO;
&           ifdef trace
            t01int4( ak_strat, 'read ipages ', _InvReadIO );
            t01int4( ak_strat, 'read I/O    ', _readIO );
&           endif
            END
        ELSE
            BEGIN
&           ifdef trace
            t01name( ak_strat, 'ipages + primpages' );
&           endif
            IF  ( g01vtrace.vtrStrategy_gg00 )
            THEN
                BEGIN
                g041c30_to_trace ( acv.a_transinf.tri_trans,
                      'calc ipages + primpages       ' );
                END;
            (*ENDIF*) 
            ;
            (* calculate read IO    *)
            (* index pages + primary page *)
            ;
            _PrimReadIO := trunc( read_primpages * strategy.ostr_strat_value );
            IF  _PrimReadIO = 0
            THEN
                _PrimReadIO := 1;
            (*ENDIF*) 
            ;
            IF  ( outrec_len <> IS_UNDEFINED_GG07 )
                AND
                (( qp_given_rescnt in access_info.srec_query_prop.qps_switches )
                OR
                (( strategy.ostr_strategy = strat_inv_in ) AND
                ( isp_exact_IN_SUBQ_match in
                strategy.ostr_inv_in_range.siir_strat_props ) AND
                ( isp_unique_idx in
                strategy.ostr_inv_in_range.siir_strat_props )))
            THEN
                BEGIN
                _recs_per_respage := trunc(( cak_page80percent / outrec_len ) + 0.5 );
                IF  ( _recs_per_respage = 0 )
                THEN
                    _recs_per_respage := 1;
                (*ENDIF*) 
                ;
&               ifdef trace
                t01int4( ak_strat, 'recs p rpage', _recs_per_respage );
&               endif
                IF  ( access_info.srec_query_prop.qps_rescnt <> IS_UNDEFINED_GG07 ) AND
                    ( strategy.ostr_inv_in_range.siir_inelemcnt = IS_UNDEFINED_GG07 )
                THEN
                    _rescnt := access_info.srec_query_prop.qps_rescnt
                ELSE
                    BEGIN
                    IF  ( access_info.srec_query_prop.qps_rescnt = IS_UNDEFINED_GG07 ) AND
                        ( strategy.ostr_inv_in_range.siir_inelemcnt <> IS_UNDEFINED_GG07 )
                    THEN
                        _rescnt := strategy.ostr_inv_in_range.siir_inelemcnt
                    ELSE
                        (* both values are defined *)
                        BEGIN
                        IF  ( access_info.srec_query_prop.qps_rescnt <
                            strategy.ostr_inv_in_range.siir_inelemcnt )
                        THEN
                            _rescnt := access_info.srec_query_prop.qps_rescnt
                        ELSE
                            _rescnt := strategy.ostr_inv_in_range.siir_inelemcnt;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                _writeIO      := _rescnt DIV _recs_per_respage;
                read_primrows := _rescnt;
                END
            ELSE
                BEGIN
                _writeIO := trunc( read_primpages * strategy.ostr_strat_value );
                (* calculate write IO as fraction between base record length *)
                (* and output record length                                  *)
                _writeIO := trunc(( _writeIO*(outrec_len/_baserec_len) ) + 0.5 );
                END;
            (*ENDIF*) 
            IF  ( _writeIO = 0 )
            THEN
                _writeIO := 1;
            (*ENDIF*) 
            ;
            (* calculate IO costs *)
            IF  ( strategy.ostr_strategy in _act_inv_build_strats^ )
            THEN
                (* build costs (includes 'order by' costs) *)
                BEGIN
                (* cost INDEX BUILD = read I, read PI, write E, read E (fetch) *)
                _pageIO := _InvReadIO  + _PrimReadIO + _writeIO + _writeIO;
                _readIO := _InvReadIO  + _PrimReadIO;
                END
            ELSE
                BEGIN
                (* FETCH strategie *)
                IF  ( strategy.ostr_strategy = strat_inv_range_merge_fetch )
                THEN
                    (* build costs: 'ORDER BY' via key *)
                    BEGIN
                    (* cost INDEX MERGE FETCH =                         *)
                    (* read I, write M, read M (fetch), read PI (fetch) *)
                    (**)
                    (* merge IO estimated as pagecount of index   *)
                    (* better estimated value desirable !         *)
                    _mergeIO := trunc( read_invpages * key_strat_value );
                    IF  _mergeIO = 0
                    THEN
                        _mergeIO := 1;
                    (*ENDIF*) 
                    _pageIO  := _InvReadIO + _mergeIO + _mergeIO + _PrimReadIO;
&                   ifdef trace
                    t01int4( ak_strat, 'merge pages ', _mergeIO );
&                   endif
                    _readIO := _InvReadIO             + _mergeIO + _PrimReadIO;
                    END
                ELSE
                    BEGIN
                    (* cost INDEX FETCH = read I (fetch), read PI (fetch) *)
                    _pageIO := _InvReadIO + _PrimReadIO;
                    _readIO := _pageIO;
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
&           ifdef trace
            t01int4( ak_strat, 'read ipages ', _InvReadIO );
            t01int4( ak_strat, 'read ppages ', _PrimReadIO );
            t01int4( ak_strat, 'read I/O    ', _readIO );
&           endif
            END;
        (*ENDIF*) 
        ;
        (* common part for all index strategies *)
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
(* valid for all strategies *)
strategy.ostr_readIO_pages := _readIO;
IF  ( cs_count_records in access_info.srec_config.cfg_switches )
THEN
    strategy.ostr_readIO_rows  := read_primrows;
(*ENDIF*) 
strategy.ostr_wholeIO_pages := _pageIO;
;
&ifdef trace
t01int4( ak_strat, 'write pages ', _writeIO );
t01int4( ak_strat, 'read  pages ', _readIO );
IF  ( cs_count_records in access_info.srec_config.cfg_switches )
THEN
    t01int4( ak_strat, 'read  rows  ', read_primrows );
(*ENDIF*) 
t01int4( ak_strat, 'whole IO    ', _pageIO );
&endif
END;
 
(*------------------------------*) 
 
FUNCTION
      a71is_duplicate_avoidance (
            VAR gg_strategy  : tgg07_StrategyInfo; (*const*)
            stratenum        : tgg07_StratEnum;
            VAR strat_data   : tgg07_StrRaw;
            VAR qprop        : tak70_query_properties) : boolean;
 
VAR
      _inv_strat_ptr  : ^tgg07_StrInvInRange;
 
BEGIN
a71is_duplicate_avoidance := false;
IF  ( gg_strategy.str_distinc <> no_distinct )
THEN
    BEGIN
    IF  ( stratenum in a70glob_key_strats )
    THEN
        BEGIN
        IF  ( gg_strategy.str_out_keyseqlen <> NOT_SEQUENCED_GG07 )
        THEN
            BEGIN
            IF  ( gg_strategy.str_out_keyseqlen < KEYSEQLEN_OFFSET_GG07 )
            THEN
                BEGIN
&               ifdef trace
                t01name( ak_strat, 'avoid duplicates 1' );
&               endif
                a71is_duplicate_avoidance := true;
                END
            ELSE
                BEGIN
                (* test if key columns in output *)
                IF  ( qp_only_keyseq_in_output in qprop.qps_switches )
                THEN
                    BEGIN
&                   ifdef trace
                    t01name( ak_strat, 'avoid duplicates 2' );
&                   endif
                    a71is_duplicate_avoidance := true;
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  ( stratenum in a70glob_inv_strats )
        THEN
            BEGIN
            _inv_strat_ptr := @strat_data;
            IF  ( isp_auto_distinct in _inv_strat_ptr^.siir_strat_props )
            THEN
                BEGIN
&               ifdef trace
                t01name( ak_strat, 'avoid duplicates 5' );
&               endif
                a71is_duplicate_avoidance := true;
                END
            ELSE
                IF  ( _inv_strat_ptr^.siir_out_invseqlen <> NOT_SEQUENCED_GG07 )
                THEN
                    BEGIN
                    (* distinct optim *)
                    (* jump over non-distinct parts of index file *)
&                   ifdef trace
                    t01name( ak_strat, 'avoid duplicates 6' );
&                   endif
                    a71is_duplicate_avoidance := true;
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      a71code_distinct_optim (
            VAR gg_strategy : tgg07_StrategyInfo (*const*)) : tsp00_Int2;
 
VAR
      _coding : tsp00_Int2;
 
BEGIN
(* meaning of _coding :                               *)
(*                                                    *)
(*  NO_DISTINCT_OPTIM_GG07 :                          *)
(*      distinct optimization not possible :(         *)
(**)
(*  AUTO_DISTINCT_OPTIM_GG07 -                        *)
(*      distinct optimization for nothing :)          *)
(**)
(* INV_DISTINCT_OPTIM_GG07 -                          *)
(*      distinct optimization possible                *)
(*      all columns of index in output                *)
(**)
(* 1 < a71code_distinct_optim < KEYSEQLEN_OFFSET_GG07 *)
(*      distinct optimization possible                *)
(*      columns sequence of index/key in output       *)
(*      code = len of sequenced index/key columns     *)
(*             in output                              *)
(**)
(* a71code_distinct_optim > KEYSEQLEN_OFFSET_GG07     *)
(*      distinct optimization possible                *)
(*      all columns of index and start sequence of    *)
(*      key columns in output                         *)
(*      code = len of sequenced key columns in output *)
(**)
_coding := NO_DISTINCT_OPTIM_GG07;
;
IF  ( gg_strategy.str_strategy in a70glob_key_fetch_strats )
THEN
    BEGIN
    IF  ( gg_strategy.str_out_keyseqlen <> NOT_SEQUENCED_GG07 )
    THEN
        BEGIN
        IF  ( ksp_auto_distinct in gg_strategy.str_key_in_range.skir_strat_props )
        THEN
            _coding := AUTO_DISTINCT_OPTIM_GG07
        ELSE
            _coding := gg_strategy.str_out_keyseqlen;
        (*ENDIF*) 
        END
    ELSE
        (* there are other (indexed) columns in output *)
        (* distinct optim not possible                 *)
        BEGIN
        END;
    (*ENDIF*) 
    END
ELSE
    BEGIN
    IF  ( gg_strategy.str_strategy in a70glob_inv_fetch_strats )
    THEN
        BEGIN
        IF  ( isp_auto_distinct in gg_strategy.str_inv_in_range.siir_strat_props )
        THEN
            _coding := AUTO_DISTINCT_OPTIM_GG07
        ELSE
            BEGIN
            IF  ( gg_strategy.str_inv_in_range.siir_out_invseqlen <> NOT_SEQUENCED_GG07 )
            THEN
                BEGIN
                IF  ( gg_strategy.str_inv_in_range.siir_out_invseqlen =
                    gg_strategy.str_inv_in_range.siir_invlen ) AND
                    ( gg_strategy.str_out_keyseqlen >= KEYSEQLEN_OFFSET_GG07 )
                THEN
                    BEGIN
                    IF  NOT ( isp_unique_idx in gg_strategy.str_inv_in_range.
                        siir_strat_props )
                    THEN
                        BEGIN
                        IF  ( gg_strategy.str_out_keyseqlen = KEYSEQLEN_OFFSET_GG07 )
                        THEN
                            BEGIN
                            _coding := INV_DISTINCT_OPTIM_GG07;
                            (* distinctness is asuranced if we *)
                            (* have only complete index        *)
                            END
                        ELSE
                            BEGIN
                            (* complete index and useable key *)
                            (* sequence in output list        *)
                            _coding := gg_strategy.str_out_keyseqlen;
                            END;
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        (* key list has only one key *)
                        _coding := AUTO_DISTINCT_OPTIM_GG07;
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  ( gg_strategy.str_out_keyseqlen = KEYSEQLEN_OFFSET_GG07 )
                    THEN
                        BEGIN
                        (* not all index column in output, but we have *)
                        (* only start sequence of index in output cols *)
                        _coding := gg_strategy.str_inv_in_range.siir_out_invseqlen;
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
a71code_distinct_optim := _coding;
&ifdef trace
IF  t01trace( ak_strat ) OR t01trace( kb )
THEN
    CASE _coding OF
        NO_DISTINCT_OPTIM_GG07 :
            t01sname( td_always, 'NO DISTOPT  ' );
        AUTO_DISTINCT_OPTIM_GG07 :
            t01sname( td_always, 'AUTO DISTOPT' );
        INV_DISTINCT_OPTIM_GG07 :
            t01sname( td_always, 'INV DISTOPT ' );
        OTHERWISE
            t01int4( td_always, 'len coding  ', _coding );
        END;
    (*ENDCASE*) 
&endif
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a71turn_into_build_strat (
            VAR acv      : tak_all_command_glob;
            VAR strategy : tgg07_StratEnum);
 
BEGIN
IF  ( strategy in a70glob_fetch_strats )
THEN
    BEGIN
    CASE strategy OF
        strat_key_equal_fetch:
            strategy := strat_key_equal;
        strat_key_range_fetch :
            strategy := strat_key_range;
        strat_inv_range_merge_fetch,
        strat_inv_range_fetch :
            strategy := strat_inv_range;
        OTHERWISE
            BEGIN
            a07_b_put_error (acv, e_unknown_strategy, 1)
            END;
        END;
    (*ENDCASE*) 
    END
ELSE
    BEGIN
    (* do nothing *)
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a71glob_init_accesspath_info;
 
VAR
      _ix : tsp00_Int2;
 
BEGIN
SAPDB_PascalForcedFill (sizeof(a71blankline), @a71blankline, 1,
      sizeof(a71blankline), bsp_c1);
WITH a70_glob_zstrat_rec DO
    BEGIN
    srec_query_prop.qps_switches:= [];
    srec_query_prop.qps_rescnt  := IS_UNDEFINED_GG07;
    srec_query_prop.qps_filler  := '  ';
    ;
    srec_config.cfg_indexno     := 0;
    srec_config.cfg_switches    := [];
    srec_config.cfg_filler      := 0;
    ;
    srec_keyaccess.ka_SUBQ_idx           := IS_UNDEFINED_GG07;
    srec_keyaccess.ka_infield.in_stpos   := 0;
    srec_keyaccess.ka_infield.in_elemcnt := 0;
    srec_keyaccess.ka_startcnt           := 0;
    srec_keyaccess.ka_stopcnt            := 0;
    FOR _ix := 0 TO MAX_COLPOSARR_IDX_GG07 DO
        BEGIN
        srec_keyaccess.ka_startfields[ _ix ]      := 0;
        srec_keyaccess.ka_stopfields [ _ix ]      := 0;
        END;
    (*ENDFOR*) 
    srec_keyaccess.ka_filler   := 0;
    srec_invaccess.ia_startcnt := 0;
    srec_invaccess.ia_stopcnt  := 0;
    srec_invaccess.ia_incnt    := 0;
    FOR _ix := 0 TO MAX_INVPOSARR_IDX_AK70 DO
        BEGIN
        srec_invaccess.ia_startfields[ _ix ] := 0;
        srec_invaccess.ia_stopfields[ _ix ]  := 0;
        END;
    (*ENDFOR*) 
    FOR _ix := 0 TO MAX_INVINPOSARR_IDX_AK70 DO
        BEGIN
        srec_invaccess.ia_infields[ _ix ].in_stpos   := 0;
        srec_invaccess.ia_infields[ _ix ].in_elemcnt := 0
        END;
    (*ENDFOR*) 
    FOR _ix := 0 TO MAX_INVROOT_IDX_AK70 DO
        srec_invaccess.ia_inv_root[ _ix ] := NIL_PAGE_NO_GG00;
    (*ENDFOR*) 
    srec_involved_cols.ic_i_outp_cnt := 0; (* output list        *)
    srec_involved_cols.ic_i_qual_cnt := 0; (* qualification list *)
    srec_involved_cols.ic_k_outp_cnt := 0;
    srec_involved_cols.ic_k_qual_cnt := 0;
    FOR _ix := 1 TO MAX_COL_SEQUENCE_GG00 DO
        BEGIN
        srec_involved_cols.ic_i_outp_cols[ _ix ] := 0;
        srec_involved_cols.ic_i_qual_cols[ _ix ] := 0;
        END;
    (*ENDFOR*) 
    FOR _ix := 0 TO MAX_COLPOSARR_IDX_GG07 DO
        BEGIN
        srec_involved_cols.ic_k_outp_cols[ _ix ] := 0;
        srec_involved_cols.ic_k_qual_cols[ _ix ] := 0;
        END;
    (*ENDFOR*) 
    srec_primpages := IS_UNDEFINED_GG07;
    srec_primrows  := IS_UNDEFINED_GG07;
    END;
(*ENDWITH*) 
;
(* build strategy sets *)
a70glob_join_strats   := [
      strat_join_key_equal,
      strat_join_key_next,
      strat_join_all_keys_equal,
      strat_join_key_range,
      strat_join_viewkey,
      strat_join_inv,
      strat_join_all_inv_equal,
      strat_join_inv_range ];
;
a70glob_join_key_strats   := [
      strat_join_key_equal,
      strat_join_key_next,
      strat_join_all_keys_equal,
      strat_join_key_range,
      strat_join_viewkey ];
;
a70glob_join_inv_strats   := [
      strat_join_inv,
      strat_join_all_inv_equal,
      strat_join_inv_range ];
;
a70glob_key_strats   := [
      strat_key_equal,
      strat_key_in,
      strat_key_subq,
      strat_key_range,
      strat_viewkey,
      (* fetch *)
      strat_key_equal_fetch,
      strat_key_range_fetch ];
;
a70glob_inv_strats   := [
      strat_inv_range,
      strat_inv_in,
      strat_inv_subq,
      (* fetch *)
      strat_inv_range_fetch,
      strat_inv_range_merge_fetch ];
;
a70glob_fetch_strats := [
      strat_key_equal_fetch,
      strat_key_range_fetch,
      (* inv *)
      strat_inv_range_fetch,
      strat_inv_range_merge_fetch ];
;
a70glob_build_strats := [
      strat_key_equal,
      strat_key_in,
      strat_key_subq,
      strat_key_range,
      strat_viewkey,
      (* inv *)
      strat_inv_range,
      strat_inv_in,
      strat_inv_subq,
      (**)
      strat_more_than_one,
      strat_catalog,
      strat_no_result ];
;
a70glob_subq_strats := [
      strat_key_subq,
      (* inv *)
      strat_inv_subq ];
;
a70glob_in_strats := [
      strat_key_in,
      (* inv *)
      strat_inv_in ];
;
a70glob_key_fetch_strats := a70glob_fetch_strats - a70glob_inv_strats;
a70glob_inv_fetch_strats := a70glob_fetch_strats - a70glob_key_strats;
;
a70glob_accessop_known_strats := a70glob_fetch_strats +
      a70glob_in_strats + a70glob_subq_strats +
      [ strat_viewkey, strat_no_result, strat_more_than_one ];
a70glob_accessop_uknwn_strats := a70glob_build_strats -
      a70glob_in_strats - a70glob_subq_strats -
      [ strat_viewkey, strat_no_result, strat_more_than_one ];
;
a70glob_accessop_key_fetch_strats :=
      a70glob_accessop_known_strats - a70glob_inv_strats -
      [ strat_no_result, strat_more_than_one ];
a70glob_accessop_inv_fetch_strats :=
      a70glob_accessop_known_strats - a70glob_key_strats -
      [ strat_no_result, strat_more_than_one ];
;
a70glob_accessop_key_build_strats :=
      a70glob_accessop_uknwn_strats - a70glob_inv_strats -
      [ strat_no_result, strat_more_than_one ];
a70glob_accessop_inv_build_strats :=
      a70glob_accessop_uknwn_strats - a70glob_key_strats -
      [ strat_no_result, strat_more_than_one ];
;
a70glob_key_build_strats := a70glob_build_strats - a70glob_inv_strats -
      [ strat_more_than_one, strat_catalog ];
a70glob_inv_build_strats := a70glob_build_strats - a70glob_key_strats -
      [ strat_more_than_one, strat_catalog ];
END;
 
(*------------------------------*) 
 
PROCEDURE
      a71add_default_strat (VAR mblock : tgg00_MessBlock);
 
VAR
      _gg_strategy : tgg07_StrategyInfo;
 
BEGIN
a71default_strat( _gg_strategy );
SAPDB_PascalForcedMove( sizeof( _gg_strategy ), mblock.mb_strat_size,
      @_gg_strategy, 1, @mblock.mb_strat^, 1, STRATEGY_START_MXGG07 );
mblock.mb_qual^.mstrat_pos  := mblock.mb_qual^.mfirst_free;
mblock.mb_qual^.mstrat_cnt  := 1;
mblock.mb_qual^.mfirst_free := mblock.mb_qual^.mfirst_free + 1;
g09StratStackentry( mblock.mb_st^[ mblock.mb_qual^.mstrat_pos ],
      mblock.mb_strat_len + 1, STRATEGY_START_MXGG07 );
mblock.mb_strat_len := mblock.mb_strat_len + STRATEGY_START_MXGG07;
END;
 
(*------------------------------*) 
 
PROCEDURE
      a71del_sysinfo_strategy (
            keylen     : tsp00_Int4;
            VAR mblock : tgg00_MessBlock);
 
VAR
      _StratInfo_len : tsp00_Int4;
      _gg_strategy   : tgg07_StrategyInfo;
 
BEGIN
a71default_strat( _gg_strategy );
_gg_strategy.str_key_len        := keylen;
_gg_strategy.str_rec_len        := _gg_strategy.str_key_len;
_gg_strategy.str_key_in_range.skir_keystart [ 0 ] := 1;
_gg_strategy.str_key_in_range.skir_keystop  [ 0 ] := 1;
_StratInfo_len := STRATEGY_START_MXGG07 + sizeof( _gg_strategy.str_key_in_range );
SAPDB_PascalForcedMove( sizeof( _gg_strategy ), mblock.mb_strat_size,
      @_gg_strategy, 1, @mblock.mb_strat^, 1, _StratInfo_len );
mblock.mb_qual^.mstrat_pos   := mblock.mb_qual^.mfirst_free;
mblock.mb_qual^.mstrat_cnt   := 1;
mblock.mb_qual^.mfirst_free  := mblock.mb_qual^.mfirst_free + 1;
g09StratStackentry( mblock.mb_st^[ mblock.mb_qual^.mstrat_pos ],
      mblock.mb_strat_len + 1, _StratInfo_len );
mblock.mb_strat_len  := mblock.mb_strat_len  + _StratInfo_len;
END;
 
(*------------------------------*) 
 
PROCEDURE
      a71default_strat (VAR gg_strategy : tgg07_StrategyInfo);
 
VAR
      ix : tsp00_Int2;
 
BEGIN
gg_strategy.str_result_id     := b01niltree_id;
gg_strategy.str_strategy      := strat_key_range;
gg_strategy.str_build_result  := true;
gg_strategy.str_distinc       := no_distinct;
gg_strategy.str_ordering      := false;
gg_strategy.str_use_rowno     := false;
gg_strategy.str_filler1       := false;
gg_strategy.str_corr_single   := false;
gg_strategy.str_union_kind    := 0;
gg_strategy.str_res_possible  := true;
gg_strategy.str_use_order     := false;
gg_strategy.str_out_keyseqlen := NOT_SEQUENCED_GG07;
(* no Index-strategy *)
gg_strategy.str_qual_kind     := primary_only;
gg_strategy.str_cnt_strat     := 1;
gg_strategy.str_rowno         := cgg04_no_rowno_predicate;
gg_strategy.str_foundresults  := 0;
gg_strategy.str_key_len       := 0;
gg_strategy.str_rec_len       := 0;
gg_strategy.str_union_key_cnt_offs := 0;
(* str_stack_output_offs used as              *)
(* stackoffset , set by ak680only_inv_prepare *)
gg_strategy.str_stack_output_offs  := 0;
gg_strategy.str_search_first       := true;
gg_strategy.str_all_files          := false;
gg_strategy.str_key_order_support  := kos_no_support;
gg_strategy.str_selinto            := false;
gg_strategy.str_access_mod         := []; (* PTS 1127791 M.Ki. *)
gg_strategy.str_filler             := '    ';
FOR ix := 0 TO MAX_COLPOSARR_IDX_GG07 DO
    BEGIN
    gg_strategy.str_key_in_range.skir_keystart[ ix ] := 0;
    gg_strategy.str_key_in_range.skir_keystop [ ix ] := 0;
    END;
(*ENDFOR*) 
gg_strategy.str_key_in_range.skir_inelemcnt     := IS_UNDEFINED_GG07;
gg_strategy.str_key_in_range.skir_IN_SUBQ_stpos := IS_UNDEFINED_GG07;
gg_strategy.str_key_in_range.skir_strat_props   := [];
gg_strategy.str_key_in_range.skir_filler        := '   ';
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak71put_col_pos (
            VAR mblock        : tgg00_MessBlock;
            VAR access_info   : tak70_strategy_record;
            VAR sorted_col    : tak70_sort_col_arr;
            VAR sorted_colcnt : tsp00_Int2;
            col_id            : tsp00_Int2;
            col_next_id_offset: tsp00_Int2;
            col_stpos         : tsp00_Int2;
            is_desc           : boolean);
 
VAR
      _start        : tsp00_Int2;
      _subq_found   : boolean;
 
BEGIN
_start      := abs( col_stpos ) + 1;
_subq_found := false;
(* step to operator *)
WHILE ( NOT (( mblock.mb_st^[ _start ].eop in [ op_eq, op_eq_all,
      op_gt, op_ge, op_lt, op_le, op_between, op_like, op_in, op_null ] ) OR
      (( mblock.mb_st^[ _start ].etype = st_bool ) AND
      (* empty subquery *)
      ( mblock.mb_st^[ _start ].epos = cgg04_is_false ))))
      AND
      ( _start <= mblock.mb_qual^.mqual_pos + mblock.mb_qual^.mqual_cnt - 1 ) DO
    BEGIN
    IF  ( mblock.mb_st^[ _start ].etype = st_subquery ) AND
        ( mblock.mb_st^[ _start ].eop <> op_get_sub_value )
    THEN
        _subq_found := true;
    (*ENDIF*) 
    _start := succ( _start );
    END;
(*ENDWHILE*) 
IF  ( _start <= mblock.mb_qual^.mqual_pos + mblock.mb_qual^.mqual_cnt - 1 ) AND
    ( sorted_colcnt <= MAX_COLPOSARR_IDX_GG07 )
THEN
    BEGIN
&   ifdef trace
    t01int4( ak_strat, '_start      ', _start );
&   endif
    IF  ( mblock.mb_st^[ _start ].eop = op_between )
    THEN
        ak71check_between( mblock, access_info, col_stpos, _start );
    (*ENDIF*) 
    IF  ( mblock.mb_st^[ _start ].eop = op_like )
    THEN
        ak71check_like( mblock, access_info, col_stpos, _start );
    (*ENDIF*) 
    sorted_colcnt := succ( sorted_colcnt );
    (* append found condition *)
    ;
    sorted_col[ sorted_colcnt ].col_stpos          := col_stpos;
    sorted_col[ sorted_colcnt ].col_id             := col_id;
    sorted_col[ sorted_colcnt ].col_next_id_offset := col_next_id_offset;
    sorted_col[ sorted_colcnt ].col_eop            :=
          mblock.mb_st^[ _start ].eop;
    sorted_col[ sorted_colcnt ].col_isdesc         := is_desc;
    IF  ( sorted_col[ sorted_colcnt ].col_eop = op_in )
    THEN
        BEGIN
        IF  ( mblock.mb_st^[ _start ].ecol_tab[ 1 ] <> chr( 1 ))
        THEN
            g04incheck( mblock, _start );
        (*ENDIF*) 
        IF  ( mblock.mb_st^[ _start ].elen_var = 1 )
        THEN
            BEGIN
            sorted_col[ sorted_colcnt ].col_eop := op_eq;
&           ifdef TRACE
            t01sname(ak_strat, 'IN as EQUAL ');
&           endif
            END
        ELSE
            sorted_col[ sorted_colcnt ].col_in_valcnt :=
                  mblock.mb_st^[ _start ].elen_var;
        (*ENDIF*) 
        END
    ELSE
        sorted_col[ sorted_colcnt ].col_in_valcnt := 0;
    (*ENDIF*) 
    IF  ((( mblock.mb_st^[ _start ].etype = st_subquery ) AND
        ( mblock.mb_st^[ _start ].eop <> op_get_sub_value ))
        OR _subq_found )
    THEN
        BEGIN
&       ifdef trace
        t01sname(ak_strat, 'col_subq    ');
&       endif
        sorted_col[ sorted_colcnt ].col_subq := true;
        END
    ELSE
        sorted_col[ sorted_colcnt ].col_subq := false;
    (*ENDIF*) 
    ;
    IF  ( mblock.mb_st^[ _start ].etype = st_bool ) AND
        ( mblock.mb_st^[ _start ].epos = cgg04_is_false )
    THEN
        BEGIN
        sorted_col[ sorted_colcnt ].col_eop  := op_false;
        sorted_col[ sorted_colcnt ].col_subq := true;
        END;
    (*ENDIF*) 
    ;
&   ifdef TRACE
    t01int4( ak_strat, 'append stpos', sorted_col[ sorted_colcnt ].col_stpos );
&   endif
    IF  ( sorted_colcnt > 1 )
    THEN
        (* insert in correct sequence *)
        ak71right_col_pos( sorted_col, sorted_colcnt );
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a71set_rescnt(
            VAR acv         : tak_all_command_glob;
            VAR sparr       : tak_syspointerarr;
            datapos         : tsp00_Int2;
            VAR qprop       : tak70_query_properties);
 
VAR
      _b_err          : tgg00_BasisError;
 
BEGIN
_b_err := e_ok;
qprop.qps_switches  := qprop.qps_switches + [ qp_given_rescnt_param ];
;
k720_maxresult_get( acv.a_mblock.mb_data^.mbp_buf,
      datapos, qprop.qps_rescnt, _b_err );
IF  ( _b_err = e_ok )
THEN
    BEGIN
&   ifdef trace
    t01int4( ak_strat, 'result cnt  ', qprop.qps_rescnt );
&   endif
    qprop.qps_switches  := qprop.qps_switches + [ qp_given_rescnt ];
    qprop.qps_switches  := qprop.qps_switches - [ qp_given_rescnt_param ];
    IF  ( qprop.qps_rescnt = 0 )
    THEN
        qprop.qps_switches := qprop.qps_switches + [ qp_no_result_set ];
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      ak71luc(
            acv_addr     : tsp00_Addr;
            VAR buf1     : tsp00_MoveObj;
            fieldpos1    : tsp00_Int4;
            fieldlength1 : tsp00_Int4;
            VAR buf2     : tsp00_MoveObj;
            fieldpos2    : tsp00_Int4;
            fieldlength2 : tsp00_Int4) : tsp00_LcompResult;
 
VAR
      _lc_result       : tsp00_LcompResult;
 
BEGIN
&ifdef trace
t01moveobj( ak_strat, buf1, fieldpos1, fieldpos1 + fieldlength1 - 1 );
t01moveobj( ak_strat, buf2, fieldpos2, fieldpos2 + fieldlength2 - 1 );
&endif
a05luc_space( acv_addr, buf1, fieldpos1, fieldlength1,
      buf2, fieldpos2, fieldlength2,
      _lc_result );
&ifdef TRACE
t01comp_result( gg, 'lc_result   ', _lc_result );
&endif
ak71luc := _lc_result;
END;
 
(*------------------------------*) 
 
FUNCTION
      ak71in_is_better (
            VAR mblock         : tgg00_MessBlock;
            VAR sorted_cols    : tak70_sort_col_arr;
            IN_pos             : tsp00_Int2;
            is_startsequence   : boolean) : boolean;
 
VAR
      _IN_better_if    : tsp00_LcompResult;
      _range_valpos    : tsp00_Int2;
      _instart_valpos  : tsp00_Int2;
      _instop_valpos   : tsp00_Int2;
      _in_valpos       : tsp00_Int2;
      _inelement_cnt   : tsp00_Int2;
 
BEGIN
IF  ( is_startsequence )
THEN
    BEGIN
    IF  ( sorted_cols[ IN_pos ].col_isdesc )
    THEN
        _IN_better_if := l_less
    ELSE
        (* IN val > RANGE val *)
        _IN_better_if := l_greater;
    (*ENDIF*) 
    END
ELSE
    BEGIN
    IF  ( sorted_cols[ IN_pos ].col_isdesc )
    THEN
        _IN_better_if := l_greater
    ELSE
        (* IN val < RANGE val *)
        _IN_better_if := l_less;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  ( sorted_cols[ IN_pos - 1 ].col_stpos < 0 )
THEN
    BEGIN
    IF  is_startsequence
    THEN
        _range_valpos := abs( sorted_cols[ IN_pos - 1 ].col_stpos ) + 1
    ELSE
        _range_valpos := abs( sorted_cols[ IN_pos - 1 ].col_stpos ) + 2;
    (*ENDIF*) 
    END
ELSE
    _range_valpos := sorted_cols[ IN_pos - 1 ].col_stpos + 1;
(*ENDIF*) 
_instart_valpos := sorted_cols[ IN_pos ].col_stpos + 1;
WHILE ( mblock.mb_st^[ _instart_valpos ].etype <> st_value ) AND
      ( mblock.mb_st^[ _instart_valpos + 1 ].etype <> st_op ) DO
    _instart_valpos := succ( _instart_valpos );
(*ENDWHILE*) 
_inelement_cnt := 1;
_instop_valpos := sorted_cols[ IN_pos ].col_stpos + 1;
WHILE ( mblock.mb_st^[ _instop_valpos + 1 ].etype <> st_op ) DO
    BEGIN
    IF  (( mblock.mb_st^[ _instop_valpos ].etype <> st_dummy ) AND
        ( mblock.mb_data^.mbp_buf[ mblock.mb_st^[ _instop_valpos ].epos ] <> csp_undef_byte ))
    THEN
        _inelement_cnt := succ( _inelement_cnt );
    (*ENDIF*) 
    _instop_valpos := succ( _instop_valpos );
    END;
(*ENDWHILE*) 
WHILE (( mblock.mb_st^[ _instop_valpos ].etype = st_dummy ) OR
      ( mblock.mb_data^.mbp_buf[ mblock.mb_st^[ _instop_valpos ].epos ] = csp_undef_byte ))
      AND
      ( _instop_valpos > sorted_cols[ IN_pos ].col_stpos + 1 ) DO
    _instop_valpos := pred( _instop_valpos );
(*ENDWHILE*) 
IF  ( is_startsequence )
THEN
    _in_valpos := _instart_valpos
ELSE
    _in_valpos := _instop_valpos;
(*ENDIF*) 
&ifdef trace
t01bool( ak_strat, 'is_startsequ', is_startsequence );
t01bool( ak_strat, 'IN col desc ', sorted_cols[ IN_pos ].col_isdesc );
t01int4( ak_strat, '_instart_val',  _instart_valpos);
t01int4( ak_strat, '_instop_val ',  _instop_valpos);
t01int4( ak_strat, '_in_valpos  ',  _in_valpos);
t01int4( ak_strat, '_inelement_c',  _inelement_cnt);
t01int4( ak_strat, '_range_valpo',  _range_valpos);
t01comp_result( ak_strat, 'IN better if',  _IN_better_if);
&endif
IF  (_inelement_cnt < c_in_better_than_rg) OR
    ( ak71luc( mblock.mb_trns^.trAcvPtr_gg00,
    mblock.mb_data^.mbp_buf,
    mblock.mb_st^[ _in_valpos ].epos,
    mblock.mb_st^[ _in_valpos ].elen_var,
    mblock.mb_data^.mbp_buf,
    mblock.mb_st^[ _range_valpos ].epos,
    mblock.mb_st^[ _range_valpos ].elen_var ) = _IN_better_if )
THEN
    ak71in_is_better := true
ELSE
    ak71in_is_better := false;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak71get_better_limit (
            VAR mblock              : tgg00_MessBlock;
            VAR sorted_cols         : tak70_sort_col_arr;
            arr_pos                 : tsp00_Int2;
            is_startsequence        : boolean);
 
VAR
      _comp_res    : tsp00_LcompResult;
      _valpos1   : tsp00_Int2;
      _valpos2   : tsp00_Int2;
 
BEGIN
IF  ( is_startsequence )
THEN
    BEGIN
    IF  ( sorted_cols[ arr_pos ].col_isdesc )
    THEN
        _comp_res := l_less
    ELSE
        _comp_res := l_greater;
    (*ENDIF*) 
    END
ELSE
    BEGIN
    IF  ( sorted_cols[ arr_pos ].col_isdesc )
    THEN
        _comp_res := l_greater
    ELSE
        _comp_res := l_less;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  ( sorted_cols[ arr_pos - 1 ].col_stpos < 0 )
THEN
    BEGIN
    IF  is_startsequence
    THEN
        _valpos1 := abs( sorted_cols[ arr_pos - 1 ].col_stpos ) + 1
    ELSE
        _valpos1 := abs( sorted_cols[ arr_pos - 1 ].col_stpos ) + 2;
    (*ENDIF*) 
    END
ELSE
    _valpos1 := sorted_cols[ arr_pos - 1 ].col_stpos + 1;
(*ENDIF*) 
IF  ( sorted_cols[ arr_pos ].col_stpos < 0 )
THEN
    BEGIN
    IF  is_startsequence
    THEN
        _valpos2 := abs( sorted_cols[ arr_pos ].col_stpos ) + 1
    ELSE
        _valpos2 := abs( sorted_cols[ arr_pos ].col_stpos ) + 2;
    (*ENDIF*) 
    END
ELSE
    _valpos2 := sorted_cols[ arr_pos ].col_stpos + 1;
(*ENDIF*) 
IF  ( ak71luc( mblock.mb_trns^.trAcvPtr_gg00,
    mblock.mb_data^.mbp_buf,
    mblock.mb_st^[ _valpos1 ].epos,
    mblock.mb_st^[ _valpos1 ].elen_var,
    mblock.mb_data^.mbp_buf,
    mblock.mb_st^[ _valpos2 ].epos,
    mblock.mb_st^[ _valpos2 ].elen_var ) = _comp_res )
THEN
    BEGIN
    sorted_cols[ arr_pos ].col_stpos := sorted_cols[ arr_pos - 1 ].col_stpos;
    sorted_cols[ arr_pos ].col_eop   := sorted_cols[ arr_pos - 1].col_eop;
    sorted_cols[ arr_pos ].col_subq  := sorted_cols[ arr_pos - 1].col_subq;
    sorted_cols[ arr_pos ].col_in_valcnt := sorted_cols[ arr_pos - 1].col_in_valcnt;
    END;
(*ENDIF*) 
sorted_cols[ arr_pos - 1 ].col_stpos := 0;
END;
 
(* h.b. PTS 1118666 *)
(*------------------------------*) 
 
FUNCTION
      a71GetKeyFromKeystrat (
            VAR mblock      : tgg00_MessBlock;
            VAR key         : tgg00_Lkey;
            VAR b_err       : tgg00_BasisError) : boolean;
 
VAR
      _gg_strategy_ptr : ^tgg07_StrategyInfo;
      _stopkey         : tgg00_Lkey;
      _use_stopkey     : boolean;
      _is_key_strat    : boolean;
 
BEGIN
_is_key_strat := false;
IF  b_err = e_ok
THEN
    BEGIN
    _gg_strategy_ptr :=
          @mblock.mb_strat^[ mblock.mb_st^[ mblock.mb_qual^.mstrat_pos ].epos ];
    _is_key_strat := (_gg_strategy_ptr^.str_strategy in
          [ strat_key_equal, strat_key_equal_fetch ]);
    IF  _is_key_strat
    THEN
        BEGIN
        _use_stopkey := false;
        g04limitprimkeys (mblock,
              _gg_strategy_ptr^.str_key_in_range.skir_keystart, key,
              _gg_strategy_ptr^.str_key_in_range.skir_keystop, _stopkey,
              _use_stopkey,
              IS_UNDEFINED_GG07, -1 (* usa an IN as range *) );
        IF  (mblock.mb_trns^.trError_gg00 <> e_ok)
        THEN
            BEGIN
            _is_key_strat := false;
            b_err := mblock.mb_trns^.trError_gg00;
            mblock.mb_trns^.trError_gg00 := e_ok;
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
a71GetKeyFromKeystrat := _is_key_strat;
END;
 
(*------------------------------*) 
 
PROCEDURE
      a71adjust_configuration (
            VAR dmli         : tak_dml_info;
            VAR config_qprop : tak70_strategy_record);
 
BEGIN
IF  (( cs_build_result in config_qprop.srec_config.cfg_switches ) AND
    ( cs_fetch_result in config_qprop.srec_config.cfg_switches ))
THEN
    BEGIN
    config_qprop.srec_config.cfg_switches  :=
          config_qprop.srec_config.cfg_switches - [ cs_build_result ];
    config_qprop.srec_config.cfg_switches  :=
          config_qprop.srec_config.cfg_switches - [ cs_fetch_result ];
    END;
(*ENDIF*) 
;
(* L2_KEYRANGE --> KEYACCESS *)
IF  ( cs_keyrange in config_qprop.srec_config.cfg_switches )
THEN
    config_qprop.srec_config.cfg_switches  :=
          config_qprop.srec_config.cfg_switches + [ cs_keyaccess ];
(*ENDIF*) 
;
(* L2_INDEXRANGE --> INDEXACCESS *)
IF  ( cs_indexrange in config_qprop.srec_config.cfg_switches )
THEN
    config_qprop.srec_config.cfg_switches  :=
          config_qprop.srec_config.cfg_switches + [ cs_indexaccess ];
(*ENDIF*) 
IF  ((( cs_IN_strategy in config_qprop.srec_config.cfg_switches ) OR
    ( cs_SUBQ_strategy in config_qprop.srec_config.cfg_switches ))
    AND
    (( cs_indexrange in config_qprop.srec_config.cfg_switches ) OR
    ( cs_indexscan in config_qprop.srec_config.cfg_switches ) OR
    ( cs_keyrange in config_qprop.srec_config.cfg_switches ) OR
    ( cs_keyscan in config_qprop.srec_config.cfg_switches )))
THEN
    config_qprop.srec_config.cfg_switches  :=
          config_qprop.srec_config.cfg_switches -
          [ cs_keyscan, cs_keyrange, cs_indexscan, cs_indexrange ];
(*ENDIF*) 
IF  (( cs_keyaccess in config_qprop.srec_config.cfg_switches ) AND
    ( cs_indexaccess in config_qprop.srec_config.cfg_switches ))
THEN
    BEGIN
    config_qprop.srec_config.cfg_switches  :=
          config_qprop.srec_config.cfg_switches - [ cs_keyaccess, cs_keyrange ];
    config_qprop.srec_config.cfg_switches  :=
          config_qprop.srec_config.cfg_switches - [ cs_indexaccess, cs_indexrange ];
    config_qprop.srec_config.cfg_indexno   := 0;
    END;
(*ENDIF*) 
;
(* L2_MORE_STRATEGIES, L2_RANGE_STRATEGY, L2_STRAT_NO_OPTIM --> L2_STRATEGY *)
IF  (( cs_L2_more_strategies in config_qprop.srec_config.cfg_switches ) OR
    ( cs_L2_range_strategy in config_qprop.srec_config.cfg_switches ) OR
    ( cs_L2_strat_no_optim in config_qprop.srec_config.cfg_switches ))
THEN
    config_qprop.srec_config.cfg_switches := config_qprop.srec_config.cfg_switches + [ cs_L2_strategy ];
(*ENDIF*) 
IF  ( dmli.d_join )
THEN
    config_qprop.srec_config.cfg_switches  :=
          config_qprop.srec_config.cfg_switches + [ cs_count_records ];
(*ENDIF*) 
IF  ( NOT g01optim_inv_only)
THEN
    config_qprop.srec_config.cfg_switches :=
          config_qprop.srec_config.cfg_switches + [ cs_disable_inv_only ];
(*ENDIF*) 
;
(* ARCHIVE TABLE --> INDEXACCESS *)
IF  ( qp_archive_access in config_qprop.srec_query_prop.qps_switches )
THEN
    config_qprop.srec_config.cfg_switches := config_qprop.srec_config.cfg_switches + [ cs_indexaccess ];
(*ENDIF*) 
;
&ifdef trace
a81debug_access_config( ak_strat, config_qprop.srec_config );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak71check_between(
            VAR mblock      : tgg00_MessBlock;
            VAR access_info : tak70_strategy_record;
            col_stpos       : tsp00_Int2;
            stpos           : tsp00_Int2);
 
VAR
      _ix            : tsp00_Int2;
      _res_poss      : boolean;
      _to_eq_changed : boolean;
 
BEGIN
g04check_betw( mblock, stpos, _res_poss, _to_eq_changed );
IF  ( NOT _res_poss )
THEN
    BEGIN
&   ifdef trace
    t01sname(ak_strat, 'no result ! ');
&   endif
    access_info.srec_query_prop.qps_switches :=
          access_info.srec_query_prop.qps_switches + [ qp_no_result_set ];
    END
ELSE
    BEGIN
    IF  ( _to_eq_changed )
    THEN
        BEGIN
        (* update strategy information *)
        _ix := 0;
        WHILE ( _ix < access_info.srec_keyaccess.ka_stopcnt ) DO
            BEGIN
            IF  ( abs( access_info.srec_keyaccess.ka_stopfields[ _ix ] ) =
                abs(col_stpos))
            THEN
                BEGIN
                access_info.srec_keyaccess.ka_stopfields[ _ix ] := abs(col_stpos);
                _ix := access_info.srec_keyaccess.ka_stopcnt;
                END;
            (*ENDIF*) 
            _ix := succ(_ix);
            END;
        (*ENDWHILE*) 
        _ix := 0;
        WHILE ( _ix < access_info.srec_invaccess.ia_stopcnt ) DO
            BEGIN
            IF  ( abs( access_info.srec_invaccess.ia_stopfields[ _ix ] ) =
                abs(col_stpos))
            THEN
                BEGIN
                access_info.srec_invaccess.ia_stopfields[ _ix ] := abs(col_stpos);
                _ix := access_info.srec_invaccess.ia_stopcnt;
                END;
            (*ENDIF*) 
            _ix := succ(_ix);
            END;
        (*ENDWHILE*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak71check_like(
            VAR mblock      : tgg00_MessBlock;
            VAR access_info : tak70_strategy_record;
            col_stpos       : tsp00_Int2;
            stpos           : tsp00_Int2);
 
VAR
      _ix            : tsp00_Int2;
      _to_eq_changed : boolean;
 
BEGIN
&ifdef trace
t01sname(ak_strat, 'like check  ');
&endif
g04check_like( mblock, stpos, _to_eq_changed );
IF  ( _to_eq_changed )
THEN
    BEGIN
&   ifdef trace
    t01bool( ak_strat, '_to_eq_chang', _to_eq_changed);
&   endif
    (* update strategy information *)
    _ix := 0;
    WHILE ( _ix < access_info.srec_keyaccess.ka_stopcnt ) DO
        BEGIN
        IF  ( abs( access_info.srec_keyaccess.ka_stopfields[ _ix ] ) =
            abs(col_stpos))
        THEN
            BEGIN
            access_info.srec_keyaccess.ka_stopfields[ _ix ] := abs(col_stpos);
            _ix := access_info.srec_keyaccess.ka_stopcnt;
            END;
        (*ENDIF*) 
        _ix := succ(_ix);
        END;
    (*ENDWHILE*) 
    _ix := 0;
    WHILE ( _ix < access_info.srec_invaccess.ia_stopcnt ) DO
        BEGIN
        IF  ( abs( access_info.srec_invaccess.ia_stopfields[ _ix ] ) =
            abs(col_stpos))
        THEN
            BEGIN
            access_info.srec_invaccess.ia_stopfields[ _ix ] := abs(col_stpos);
            _ix := access_info.srec_invaccess.ia_stopcnt;
            END;
        (*ENDIF*) 
        _ix := succ(_ix);
        END;
    (*ENDWHILE*) 
    END;
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
