.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 : 2004-22-07
*****************************************************
modname : VAK728
changed : 2000-11-17
module  : Strategy_Explain
 
Author  : GertG / HolgerB
Created : 2004-22-07
*****************************************************
 
Purpose : module for "EXPLAIN" output
 
Define  :
 
        PROCEDURE
              a728_init_strat_texts;
 
        PROCEDURE
              a728_explain (
                    VAR acv          : tak_all_command_glob;
                    VAR dmli         : tak_dml_info;
                    VAR gg_strategy  : tgg07_StrategyInfo;
                    joininfo_ptr     : tak68_join_ptr;
                    VAR morestratbuf : tsp00_MoveObj;
                    morestratbufsize : tsp00_Int4;
                    morestratpos     : tsp00_Int4);
 
        PROCEDURE
              a728explain_no_join_strat_now( VAR acv : tak_all_command_glob);
 
.CM *-END-* define --------------------------------------
Use     :
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01_i_internal       : tsp00_KnlIdentifier;
              a01_i_tmpresult      : tsp00_KnlIdentifier;
              a01_il_b_identifier  : tsp00_KnlIdentifier;
 
      ------------------------------ 
 
        FROM
              AK_universal_semantic_tools : VAK06;
 
        PROCEDURE
              a06_systable_get (
                    VAR acv      : tak_all_command_glob;
                    dstate       : tak_directory_state;
                    VAR tableid  : tgg00_Surrogate;
                    VAR base_ptr : tak_sysbufferaddress;
                    all          : boolean;
                    VAR ok       : boolean);
 
        PROCEDURE
              a06determine_username (
                    VAR acv       : tak_all_command_glob;
                    VAR userid    : tgg00_Surrogate;
                    VAR user_name : tsp00_KnlIdentifier);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK07;
 
        PROCEDURE
              a07ak_system_error (
                    VAR acv  : tak_all_command_glob;
                    modul_no : integer;
                    id       : integer);
 
        PROCEDURE
              a07_nb_put_error (
                    VAR acv  : tak_all_command_glob;
                    b_err    : tgg00_BasisError;
                    err_code : tsp00_Int4;
                    VAR n    : tsp00_KnlIdentifier);
 
      ------------------------------ 
 
        FROM
              AK_Identifier_Handling : VAK061;
 
        PROCEDURE
              a061get_colname (
                    VAR col_info : tak00_columninfo;
                    VAR colname  : tsp00_KnlIdentifier);
 
      ------------------------------ 
 
        FROM
              Systeminfo_cache : VAK10;
 
        PROCEDURE
              a10rel_sysinfo (syspointer : tak_sysbufferaddress);
 
      ------------------------------ 
 
        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);
 
        PROCEDURE
              a24get_indexname (
                    VAR acv        : tak_all_command_glob;
                    indexbuf       : tak_sysbufferaddress;
                    index          : integer;
                    VAR index_name : tsp00_KnlIdentifier);
 
        FUNCTION
              a24IndexFieldCount (
                    VAR index_def : tak_multindex) : integer;
 
      ------------------------------ 
 
        FROM
              AK_update_statistics : VAK28;
 
        FUNCTION
              a28prim_pages (
                    VAR acv     : tak_all_command_glob;
                    VAR baserec : tak_baserecord) : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              AK_universal_show_tools : VAK40;
 
        PROCEDURE
              a40add_explain_record (
                    VAR acv  : tak_all_command_glob;
                    VAR expl : tak70_explain_rec);
 
      ------------------------------ 
 
        FROM
              Build_Strategy : VAK70;
 
        VAR
              a70glob_inv_strats        : tgg07_StratEnumSet;
              a70glob_join_strats       : tgg07_StratEnumSet;
              a70glob_key_strats        : tgg07_StratEnumSet;
              a70glob_join_key_strats   : tgg07_StratEnumSet;
              a70glob_join_inv_strats   : tgg07_StratEnumSet;
 
      ------------------------------ 
 
        FROM
              Build_Strategy_2 : VAK71;
 
        FUNCTION
              a71code_distinct_optim (
                    VAR gg_strategy : tgg07_StrategyInfo) : tsp00_Int2;
 
      ------------------------------ 
 
        FROM
              Catalog_Select_Optimizer : VAK722;
 
        FUNCTION
              a722full_one_level_id (VAR strat : tgg07_StrategyInfo) : boolean;
 
        FUNCTION
              a722full_two_level_id (VAR strat : tgg07_StrategyInfo) : boolean;
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Trace_Strategy_1 : VAK725;
 
        PROCEDURE
              a725output_explain(
                    debug    : tgg00_Debug;
                    VAR expl : tak70_explain_rec);
 
        PROCEDURE
              a725output_gg_strat (
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    VAR gg_strat  : tgg07_StrategyInfo);
&       endif
 
      ------------------------------ 
 
        FROM
              RTE-Extension-20 : VSP20;
 
        FUNCTION
              s20or4b (
                    VAR source : tsp00_MoveObj;
                    source_pos : tsp00_Int4) : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalMove (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    source_upb  : tsp00_Int4;
                    dest_upb    : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    src_pos     : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    dest_pos    : tsp00_Int4;
                    length      : tsp00_Int4;
                    VAR e       : tgg00_BasisError);
&       IFDEF TRACE
 
      ------------------------------ 
 
        FROM
              join_trace_routines : VAK683;
 
        PROCEDURE
              a683trace_joininfo (
                    debug       : tgg00_Debug;
                    VAR joins   : tak_joinrec;
                    VAR joininfo: tak68_join);
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01knl_identifier (
                    debug      : tgg00_Debug;
                    nam        : tsp00_Sname;
                    identifier : tsp00_KnlIdentifier);
 
        PROCEDURE
              t01sname (
                    debug   : tgg00_Debug;
                    nam     : tsp00_Sname);
 
        PROCEDURE
              t01bool (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    curr_bool: boolean);
 
        PROCEDURE
              t01int4 (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01lidentifier (
                    level      : tgg00_Debug;
                    identifier : tsp00_KnlIdentifier);
 
        PROCEDURE
              t01strat_enum (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname;
                    strat : tgg07_StratEnum);
&       ENDIF
 
.CM *-END-* use -----------------------------------------
Synonym :
 
.CM *-END-* synonym -------------------------------------
***********************************************************
 
Description:
 
 
.CM *-END-* description ---------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
CONST
      c_all              = true (* a06_systable_get *);
      (* --------------------------------------------------- *)
      c_str_empty        =  0;
      c_str_no_result    =  1;
      c_str_table_scan   =  2;
      c_str_inv_scan     =  3;
      (**)
      c_str_key_rang     =  4;
      c_str_key_eq       =  5;
      c_str_key_in       =  6;
      c_str_key_subq     =  7;
      (**)
      c_str_inv_rang     =  8;
      c_str_inv_eq       =  9;
      c_str_inv_in       = 10;
      c_str_inv_subq     = 11;
      (**)
      c_str_different    = 12;
      c_str_catscan      = 13;
      c_str_catscan_user = 14;
      c_str_catkey       = 15;
      c_str_not_now      = 16;
      c_str_j_all_invs   = 17;
      c_str_j_start_invs = 18;
      c_str_j_inv        = 19;
      c_str_j_start_keys = 20;
      c_str_j_keynext    = 21;
      c_str_j_all_keys_eq= 22;
      c_str_j_keyeq      = 23;
      (* This shouldn't happen, so it appears in no section at all. *)
      c_str_unknown      = 24;
      (* part of strategies *)
      c_strat_index      = 25;
      c_strat_key        = 26;
      c_strat_sortcol    = 27;
      c_max              = 27;
 
TYPE
      tak728_strat_texts = ARRAY [ 0..c_max ] OF tsp00_C40;
 
VAR
      a728_strat_texts : tak728_strat_texts;
 
 
(*------------------------------*) 
 
PROCEDURE
      a728_explain (
            VAR acv          : tak_all_command_glob;
            VAR dmli         : tak_dml_info;
            VAR gg_strategy  : tgg07_StrategyInfo;
            joininfo_ptr     : tak68_join_ptr;
            VAR morestratbuf : tsp00_MoveObj;
            morestratbufsize : tsp00_Int4;
            morestratpos     : tsp00_Int4);
 
VAR
      _expl     : tak70_explain_rec;
      _base_ptr : tak_sysbufferaddress;
      _f_ok     : boolean;
 
BEGIN
IF  ( NOT acv.a_pars_explain )
THEN
    BEGIN
    IF  ( oisreference in dmli.d_tabarr[ dmli.d_acttabindex ].ospecialname )
    THEN
        BEGIN
        _expl.exp_user  := a01_il_b_identifier;
        _expl.exp_table := dmli.d_tabarr[ dmli.d_acttabindex ].oreference;
        END
    ELSE
        BEGIN
        IF  (( oispartjoinview in dmli.d_tabarr[ dmli.d_acttabindex ].ospecialname )
            AND
            acv.a_explain_view )
        THEN
            BEGIN
            a06_systable_get( acv, d_release,
                  dmli.d_tabarr[ dmli.d_acttabindex ].otreeid.fileTabId_gg00,
                  _base_ptr, c_all, _f_ok );
            IF  ( _f_ok )
            THEN
                BEGIN
                _expl.exp_table := _base_ptr^.sbase.btablen^;
                a06determine_username( acv,
                      _base_ptr^.sbase.bauthid, _expl.exp_user );
                END
            ELSE
                a07_nb_put_error( acv, e_unknown_tablename,
                      1, dmli.d_tabarr[ dmli.d_acttabindex ].otable );
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            _expl.exp_user  := dmli.d_tabarr[ dmli.d_acttabindex ].ouser;
            _expl.exp_table := dmli.d_tabarr[ dmli.d_acttabindex ].otable;
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( dmli.d_join )
    THEN
        _expl.exp_pagecount := a28prim_pages (acv, dmli.d_sparr.pbasep^.sbase)
    ELSE
        _expl.exp_pagecount := acv.a_sample_pages;
    (*ENDIF*) 
    IF  (( acv.a_mblock.mb_qual^.mtree.fileTfn_gg00 = tfnTemp_egg00 )
        AND
        ( acv.a_mblock.mb_qual^.mtree.fileTfnTemp_gg00 <>
        ttfnUserResult_egg00 )
        AND
        ( acv.a_mblock.mb_qual^.mtree.fileTfnTemp_gg00 <>
        ttfnPars_egg00 )
        AND
        ( acv.a_mblock.mb_qual^.mtree.fileTfnTemp_gg00 <>
        ttfnTempTable_egg00 )
        AND
        ( acv.a_mblock.mb_qual^.mtree.fileTfnTemp_gg00 <>
        ttfnRecursive_egg00 )
        )
    THEN
        BEGIN
        _expl.exp_user      := a01_i_internal;
        _expl.exp_table     := a01_i_tmpresult;
        _expl.exp_pagecount := cak_initpages;
        END;
    (*ENDIF*) 
    ak728strat_and_column( acv, dmli, gg_strategy, joininfo_ptr,
          morestratbuf, morestratbufsize, morestratpos, _expl );
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak728pseudo_multinv_check (
            VAR acv            : tak_all_command_glob;
            VAR dmli           : tak_dml_info;
            fno                : integer;
            VAR index_scan_rec : tak_index_scan_record;
            used_strat         : tsp00_Int2;
            VAR expl           : tak70_explain_rec);
 
VAR
      _tabid  : tgg00_Surrogate;
 
BEGIN
_tabid  := dmli.d_sparr.pbasep^.sbase.btreeid.fileTabId_gg00;
(* *** get index name *** *)
a24fnd_indexno( acv, _tabid, fno, index_scan_rec );
IF  ( acv.a_returncode = 0 )
THEN
    IF  ( index_scan_rec.isr_buf <> NIL )
    THEN
        BEGIN
        IF  ( index_scan_rec.isr_buf^.smindex.
            indexdef[ index_scan_rec.isr_index ].icount = 1 ) (* PTS 1108287 *)
        THEN
            BEGIN
            CASE used_strat OF
                c_str_j_all_invs,
                c_str_j_start_invs :
                    used_strat := c_str_j_inv;
                OTHERWISE
                    BEGIN
                    END
                END;
            (*ENDCASE*) 
            expl.exp_strat := a728_strat_texts[ used_strat ];
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak728column_name_get (
            VAR acv             : tak_all_command_glob;
            VAR dmli            : tak_dml_info;
            VAR gg_strategy     : tgg07_StrategyInfo;
            joininfo_ptr        : tak68_join_ptr;
            used_strat          : tsp00_Int2;
            VAR expl            : tak70_explain_rec);
 
VAR
      _f_ok             : boolean;
      _first            : boolean;
      _multi            : boolean;
      _key_strat        : boolean;
      _exit_while       : boolean;
      _col_cnt          : tsp00_Int2;
      _j                : tsp00_Int2;
      _fno              : tsp00_Int2;
      _col_ind          : tsp00_Int2;
      _mecode           : integer;
      _mrcode           : integer;
      _index_scan_rec   : tak_index_scan_record;
 
BEGIN
_j               := 1;
_mrcode          := acv.a_returncode;
_mecode          := acv.a_errorpos;
acv.a_returncode := 0;
acv.a_errorpos   := 0;
_first           := true;
(*
      _multi := ( gg_strategy.str_strategy in
      [ strat_join_all_inv_equal, strat_join_inv_range ] ) OR
      ( gg_strategy.str_strategy in a70glob_inv_strats );
      *)
_multi := ( gg_strategy.str_strategy in a70glob_join_inv_strats ) OR
      ( gg_strategy.str_strategy in a70glob_inv_strats );
;
IF  ( gg_strategy.str_strategy in a70glob_join_key_strats ) OR
    ( gg_strategy.str_strategy in a70glob_key_strats )
THEN
    BEGIN
    _key_strat := true;
    _fno := 1;
    IF  ( strmod_sorted in gg_strategy.str_access_mod ) AND
        ( joininfo_ptr = NIL )
    THEN
        a07ak_system_error( acv, 728, 2 );
    (*ENDIF*) 
    END
ELSE
    BEGIN
    _key_strat := false;
    IF  ( gg_strategy.str_strategy in a70glob_join_inv_strats )
    THEN
        _fno := gg_strategy.str_join_multfields.sjmf_index_no
    ELSE
        _fno := gg_strategy.str_inv_in_range.siir_indexno;
    (*ENDIF*) 
    END;
(*ENDIF*) 
_col_cnt := 0;
&ifdef trace
t01int4( ak_strat, 'first _fno  ', _fno );
&endif
IF  ( gg_strategy.str_strategy in a70glob_join_strats )
THEN
    BEGIN
    _col_cnt := gg_strategy.str_join_multfields.sjmf_cntfields;
    END
ELSE
    BEGIN
    IF  ( gg_strategy.str_strategy in a70glob_key_strats )
    THEN
        BEGIN
        WHILE ( _col_cnt < MAX_STRATEGY_KEYS_GG04 )
              AND
              (( gg_strategy.str_key_in_range.skir_keystart[ _col_cnt ] <> 0 ) OR
              ( gg_strategy.str_key_in_range.skir_keystop[ _col_cnt ] <> 0 )) DO
            _col_cnt := succ( _col_cnt );
        (*ENDWHILE*) 
        END
    ELSE
        BEGIN
        IF  ( gg_strategy.str_strategy in a70glob_inv_strats )
        THEN
            BEGIN
            IF  ( gg_strategy.str_inv_in_range.siir_startcnt >
                gg_strategy.str_inv_in_range.siir_stopcnt )
            THEN
                _col_cnt := gg_strategy.str_inv_in_range.siir_startcnt
            ELSE
                _col_cnt := gg_strategy.str_inv_in_range.siir_stopcnt;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
&IFDEF TRACE
t01int4( ak_strat, '_fno        ', _fno );
t01int4( ak_strat, '_col_cnt    ', _col_cnt );
t01bool( ak_strat, '_multi      ', _multi );
t01bool( ak_strat, '_key_strat  ', _key_strat );
&ENDIF
IF  ( _multi )
THEN
    BEGIN
    ak728pseudo_multinv_check( acv, dmli, _fno, _index_scan_rec,
          used_strat, expl );
    IF  ( acv.a_returncode = 0 )
    THEN
        IF  ( _index_scan_rec.isr_buf <> NIL )
        THEN
            BEGIN
            WITH _index_scan_rec.isr_buf^.smindex.
                 indexdef[ _index_scan_rec.isr_index ] DO
                BEGIN
                a24get_indexname( acv, _index_scan_rec.isr_buf,
                      _index_scan_rec.isr_index, expl.exp_column );
&               IFDEF TRACE
                a725output_explain( ak_strat, expl );
&               ENDIF
                a40add_explain_record( acv, expl );
                IF  ( 1 = a24IndexFieldCount( _index_scan_rec.isr_buf^.smindex.
                    indexdef[ _index_scan_rec.isr_index ] ) )
                THEN
                    BEGIN
                    _col_cnt := 0;
&                   ifdef trace
                    t01int4( ak_strat, '_col_cnt = 0', _col_cnt );
&                   endif
                    END
                ELSE
                    BEGIN
                    expl.exp_strat     := a728_strat_texts[ c_strat_index ];
                    expl.exp_user      := a01_il_b_identifier;
                    expl.exp_table     := a01_il_b_identifier;
                    expl.exp_pagecount := -1;
                    expl.exp_flags     := [];
                    END;
                (*ENDIF*) 
                END
            (*ENDWITH*) 
            END
        ELSE
            a07ak_system_error( acv, 728, 1 );
        (*ENDIF*) 
    (*ENDIF*) 
    END
ELSE
    BEGIN
    IF  ( _key_strat AND
        ( NOT ( gg_strategy.str_strategy in
        [ strat_join_key_equal, strat_join_key_next ] )) OR
        (( gg_strategy.str_strategy = strat_join_key_next ) AND
        ( strmod_sorted in gg_strategy.str_access_mod )))
    THEN
        BEGIN
        a40add_explain_record( acv, expl );
        IF  ( strmod_sorted in gg_strategy.str_access_mod )
        THEN
            expl.exp_strat := a728_strat_texts[ c_strat_sortcol ]
        ELSE
            expl.exp_strat := a728_strat_texts[ c_strat_key ];
        (*ENDIF*) 
        expl.exp_user      := a01_il_b_identifier;
        expl.exp_table     := a01_il_b_identifier;
        expl.exp_pagecount := -1;
        expl.exp_flags     := [];
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
&ifdef trace
a725output_explain( ak_strat, expl );
&endif
_col_ind := 1;
WHILE ( acv.a_returncode = 0 ) AND ( _col_cnt > 0 ) DO
    BEGIN
&   ifdef trace
    t01int4( ak_strat, '_col_cnt    ', _col_cnt );
&   endif
    expl.exp_column := a01_il_b_identifier;
    WITH dmli.d_tabarr[ dmli.d_acttabindex ] DO
        BEGIN
        IF  ( oall_priv OR ( _fno in osetallpriv ))
        THEN
            BEGIN
            IF  ( oview AND
                ( dmli.d_sparr.pbasep^.syskey.stableid <> ofromtableid ))
            THEN
                BEGIN
                a10rel_sysinfo( dmli.d_sparr.pbasep );
                a06_systable_get( acv, d_fix, ofromtableid,
                      dmli.d_sparr.pbasep, c_all, _f_ok );
                IF  NOT _f_ok
                THEN
                    a07_nb_put_error( acv, e_unknown_tablename, 1, otable )
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  ( strmod_sorted in gg_strategy.str_access_mod )
            THEN
                BEGIN
                (* get next field for join transition *)
                _fno := dmli.d_joins.jrc_joinarr[ joininfo_ptr^.jn_jarr[ _j ] ].
                      jo_recs[ dmli.d_joins.jrc_joinarr[ joininfo_ptr^.
                      jn_jarr[ _j ] ].jo_partno ].jop_fieldno;
&               ifdef trace
                t01int4( ak_strat, 'jo_partno   ', dmli.d_joins.jrc_joinarr[ joininfo_ptr^.
                      jn_jarr[ _j ] ].jo_partno );
                t01int4( ak_strat, '_fno        ', _fno );
                t01bool( ak_strat, 'oview       ', oview );
&               endif
                ak728colno_get( dmli, _fno, _col_ind, false, _index_scan_rec );
                IF  ( dmli.d_joins.jrc_joinarr[ joininfo_ptr^.jn_jarr[ _j ] ].
                    jo_recs[ dmli.d_joins.jrc_joinarr[ joininfo_ptr^.
                    jn_jarr[ _j ] ].jo_partno ].jop_cntstack > 1 )
                    AND
                    (( NOT oview ) OR
                    ( dmli.d_colbuf^.ccolstack.etype <> st_func (* viewcol isn't an expression*)
                    ))
                THEN
                    BEGIN
                    expl.exp_column :=
                          'EXPRESSION WITH                                                 ';
                    a40add_explain_record( acv, expl );
                    END;
                (*ENDIF*) 
                a061get_colname( dmli.d_colbuf^, expl.exp_column );
                _j := succ( _j );
                END
            ELSE
                BEGIN
                IF  ( _key_strat )
                THEN
                    BEGIN
                    ak728key_colno_get( dmli, _first );
                    a061get_colname( dmli.d_colbuf^, expl.exp_column );
                    END
                ELSE
                    BEGIN
                    IF  ( _multi )
                    THEN
                        BEGIN
                        ak728colno_get( dmli, _fno, _col_ind, _multi, _index_scan_rec );
                        a061get_colname( dmli.d_colbuf^, expl.exp_column );
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            ;
&           IFDEF TRACE
            a725output_explain( ak_sem, expl );
&           ENDIF
            a40add_explain_record( acv, expl );
            expl.exp_user         := a01_il_b_identifier;
            expl.exp_table        := a01_il_b_identifier;
            expl.exp_pagecount    :=  -1;
            expl.exp_flags        := [];
            _first                := false;
            END;
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
    _col_cnt := pred ( _col_cnt );
    END;
(*ENDWHILE*) 
acv.a_returncode := _mrcode;
acv.a_errorpos   := _mecode;
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak728key_colno_get (
            VAR dmli : tak_dml_info;
            first : boolean);
&     ifdef trace
 
VAR
      colname : tsp00_KnlIdentifier;
&     endif
 
BEGIN
IF  first
THEN
    dmli.d_colbuf := dmli.d_sparr.pbasep^.sbase.
          bcolumn[ dmli.d_sparr.pbasep^.sbase.bfirstcolind ]
ELSE
    dmli.d_colbuf := dmli.d_sparr.pbasep^.sbase.
          bcolumn[dmli.d_colbuf^.cnextind];
(*ENDIF*) 
&ifdef TRACE
t01int4 (ak_join, 'd_index     ', dmli.d_index);
a061get_colname (dmli.d_colbuf^, colname);
t01lidentifier (ak_join, colname);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak728colno_get (
            VAR dmli            : tak_dml_info;
            fno                 : integer;
            VAR col_ind         : tsp00_Int2;
            multi               : boolean;
            VAR index_scan_rec  : tak_index_scan_record);
 
VAR
      _exit_loop : boolean;
 
BEGIN
(* set dmli.d_colbuf with column info of fno *)
(* or column index in index definition       *)
IF  ( multi )
THEN (* evaluate next columnnumber *)
    BEGIN
    fno := index_scan_rec.isr_buf^.smindex.
          indexdef[ index_scan_rec.isr_index ].icolseq[ col_ind ];
    col_ind := succ( col_ind );
    END;
(*ENDIF*) 
dmli.d_colbuf := dmli.d_sparr.pbasep^.sbase.
      bcolumn[ dmli.d_sparr.pbasep^.sbase.bfirstcolind ];
_exit_loop  := false;
WHILE NOT _exit_loop DO
    BEGIN
    IF  ( dmli.d_colbuf^.creccolno = fno )
    THEN
        _exit_loop := true
    ELSE
        IF  ( dmli.d_colbuf^.cnextind > 0 )
        THEN
            dmli.d_colbuf := dmli.d_sparr.pbasep^.sbase.
                  bcolumn[ dmli.d_colbuf^.cnextind ]
        ELSE
            _exit_loop := true;
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak728strat_and_column (
            VAR acv          : tak_all_command_glob;
            VAR dmli         : tak_dml_info;
            VAR gg_strategy  : tgg07_StrategyInfo;
            joininfo_ptr     : tak68_join_ptr;
            VAR morestratbuf : tsp00_MoveObj;
            morestratbufsize : tsp00_Int4;
            morestratpos     : tsp00_Int4;
            VAR expl         : tak70_explain_rec);
 
VAR
      _ix                  : tsp00_Int2;
      _len                 : tsp00_Int2;
      _pos                 : tsp00_Int4;
      _loc_gg_strategy     : tgg07_StrategyInfo;
      _used_strat          : tsp00_Int2;
      _index_scan_rec      : tak_index_scan_record;
 
      _str                 : RECORD
            CASE boolean OF
                true  :
                    (strat_char : tsp00_C1);
                false :
                    (strat_enum : tgg07_StratEnum);
                END;
            (*ENDCASE*) 
 
 
BEGIN
&ifdef trace
a725output_gg_strat( ak_sem, 'STRATEGY    ', gg_strategy );
IF  ( joininfo_ptr <> NIL )
THEN
    a683trace_joininfo( ak_sem, dmli.d_joins, joininfo_ptr^ );
(*ENDIF*) 
;
&endif
_used_strat           := c_str_unknown;
expl.exp_flags        := [];
;
IF  ( gg_strategy.str_strategy in a70glob_key_strats )
THEN
    BEGIN
    IF  ( ksp_aggr_MIN_opt in gg_strategy.str_key_in_range.skir_strat_props ) OR
        ( ksp_aggr_MAX_opt in gg_strategy.str_key_in_range.skir_strat_props )
    THEN
        expl.exp_flags := expl.exp_flags + [ exp_MIN_MAX_opt ];
    (*ENDIF*) 
    IF  ( gg_strategy.str_out_keyseqlen <> NOT_SEQUENCED_GG07 )
    THEN
        BEGIN
        (* could be distinct optimized *)
        _ix := a71code_distinct_optim( gg_strategy );
        CASE _ix OF
            NO_DISTINCT_OPTIM_GG07 :
                (* do nothing *)
                ;
            AUTO_DISTINCT_OPTIM_GG07 :
                expl.exp_flags := expl.exp_flags + [ exp_distinct_A ];
            OTHERWISE
                BEGIN
                expl.exp_flags := expl.exp_flags + [ exp_distinct_P ];
                END;
            END;
        (*ENDCASE*) 
        END;
    (*ENDIF*) 
    CASE gg_strategy.str_strategy OF
        strat_key_equal_fetch,
        strat_key_equal :
            _used_strat := c_str_key_eq;
        strat_key_in :
            _used_strat := c_str_key_in;
        strat_key_subq :
            _used_strat := c_str_key_subq;
        strat_key_range,
        strat_key_range_fetch :
            IF  ( gg_strategy.str_key_in_range.skir_keystart[ 0 ] = 0 )
                AND
                ( gg_strategy.str_key_in_range.skir_keystop[ 0 ]  = 0 )
            THEN
                BEGIN
                _used_strat := c_str_table_scan;
                END
            ELSE
                BEGIN
                _used_strat := c_str_key_rang;
                END;
            (*ENDIF*) 
        END;
    (*ENDCASE*) 
    END
ELSE
    BEGIN
    IF  ( gg_strategy.str_strategy in a70glob_inv_strats )
    THEN
        BEGIN
        _ix := a71code_distinct_optim( gg_strategy );
        CASE _ix OF
            NO_DISTINCT_OPTIM_GG07 :
                (* do nothing *)
                ;
            AUTO_DISTINCT_OPTIM_GG07 :
                expl.exp_flags := expl.exp_flags + [ exp_distinct_A ];
            INV_DISTINCT_OPTIM_GG07 :
                expl.exp_flags := expl.exp_flags + [ exp_distinct_C ];
            OTHERWISE
                BEGIN
                IF  ( _ix > KEYSEQLEN_OFFSET_GG07 )
                THEN
                    expl.exp_flags := expl.exp_flags + [ exp_distinct_K ]
                ELSE
                    expl.exp_flags := expl.exp_flags + [ exp_distinct_P ];
                (*ENDIF*) 
                END;
            END;
        (*ENDCASE*) 
        IF  ( isp_aggr_MIN_opt in gg_strategy.str_inv_in_range.siir_strat_props ) OR
            ( isp_aggr_MAX_opt in gg_strategy.str_inv_in_range.siir_strat_props )
        THEN
            expl.exp_flags := expl.exp_flags + [ exp_MIN_MAX_opt ];
        (*ENDIF*) 
        IF  ( gg_strategy.str_qual_kind = inv_and_primary )
        THEN
            expl.exp_flags := expl.exp_flags + [ exp_qual_on_inv ];
        (*ENDIF*) 
        IF  ( isp_inv_only in gg_strategy.str_inv_in_range.siir_strat_props )
        THEN
            expl.exp_flags := expl.exp_flags + [ exp_only_inv ];
        (*ENDIF*) 
        IF  ( gg_strategy.str_strategy = strat_inv_range_merge_fetch )
        THEN
            expl.exp_flags := expl.exp_flags + [ exp_temp_inv ];
        (*ENDIF*) 
        CASE gg_strategy.str_strategy OF
            strat_inv_range,
            strat_inv_range_fetch,
            strat_inv_range_merge_fetch :
                BEGIN
                IF  ( isp_exact_match in gg_strategy.str_inv_in_range.
                    siir_strat_props )
                THEN
                    BEGIN
                    _used_strat := c_str_inv_eq;
                    END
                ELSE
                    IF  ( gg_strategy.str_inv_in_range.siir_startcnt = 0 )
                        AND
                        ( gg_strategy.str_inv_in_range.siir_stopcnt = 0 )
                    THEN
                        _used_strat := c_str_inv_scan
                    ELSE
                        _used_strat := c_str_inv_rang;
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            strat_inv_in :
                BEGIN
                _used_strat := c_str_inv_in;
                END;
            strat_inv_subq :
                BEGIN
                _used_strat := c_str_inv_subq;
                END;
            END;
        (*ENDCASE*) 
        END
    ELSE
        (* not key/inv strat *)
        BEGIN
        IF  (( gg_strategy.str_strategy in a70glob_join_inv_strats ) AND
            ( gg_strategy.str_qual_kind = inv_and_primary ))
        THEN
            expl.exp_flags := expl.exp_flags + [ exp_qual_on_inv ];
        (*ENDIF*) 
        CASE gg_strategy.str_strategy OF
            strat_more_than_one :
                _used_strat := c_str_different;
            strat_join_all_inv_equal :
                _used_strat := c_str_j_all_invs;
            strat_join_inv_range :
                _used_strat := c_str_j_start_invs;
            strat_join_inv :
                _used_strat := c_str_j_inv;
            strat_join_key_range :
                _used_strat := c_str_j_start_keys;
            strat_join_key_next :
                _used_strat := c_str_j_keynext;
            strat_join_all_keys_equal :
                _used_strat := c_str_j_all_keys_eq;
            strat_join_key_equal :
                _used_strat := c_str_j_keyeq;
            strat_catalog :
                BEGIN
                IF  a722full_one_level_id( gg_strategy ) OR
                    a722full_two_level_id( gg_strategy )
                THEN
                    _used_strat := c_str_catkey
                ELSE
                    IF  ( gg_strategy.str_catalog.scat_authname <>
                        cak_is_undefined )
                    THEN
                        _used_strat := c_str_catscan_user
                    ELSE
                        _used_strat := c_str_catscan;
                    (*ENDIF*) 
                (*ENDIF*) 
                expl.exp_strat  := a728_strat_texts [ _used_strat ];
                expl.exp_column := a01_il_b_identifier;
                a40add_explain_record (acv, expl);
                END;
            strat_undecided, strat_no_result :
                BEGIN
                IF  gg_strategy.str_strategy = strat_undecided
                THEN
                    _used_strat        := c_str_not_now
                ELSE
                    _used_strat        := c_str_no_result;
                (*ENDIF*) 
                expl.exp_strat     := a728_strat_texts [ _used_strat ];
                expl.exp_column    := a01_il_b_identifier;
                expl.exp_pagecount := cak_is_undefined;
&               IFDEF TRACE
                a725output_explain( ak_strat, expl );
&               ENDIF
                a40add_explain_record( acv, expl );
                END;
            OTHERWISE
                _used_strat := c_str_unknown
            END;
        (*ENDCASE*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  ( NOT ( gg_strategy.str_strategy in
    [ strat_no_result, strat_undecided, strat_catalog, strat_viewkey ] ))
THEN
    BEGIN
    expl.exp_strat  := a728_strat_texts [ _used_strat ];
    expl.exp_column := a01_il_b_identifier;
    (* PTS 1127791 M.Ki. *)
    IF  strmod_hash in gg_strategy.str_access_mod
    THEN
        expl.exp_flags := expl.exp_flags + [ exp_hash_join ];
    (*ENDIF*) 
    IF  strmod_parallel in gg_strategy.str_access_mod
    THEN
        expl.exp_flags := expl.exp_flags + [ exp_parallel_index ];
    (*ENDIF*) 
    IF  strmod_sorted in gg_strategy.str_access_mod
    THEN
        expl.exp_flags := expl.exp_flags + [ exp_sorted_access ];
    (*ENDIF*) 
    ;
&   IFDEF TRACE
    a725output_explain( ak_strat, expl );
&   ENDIF
    IF  (( oispartjoinview in dmli.d_tabarr[ dmli.d_acttabindex ].ospecialname )
        AND
        NOT acv.a_explain_view )
    THEN
        BEGIN
        (* NOT EXPLAIN VIEW and oispartjoinview *)
        CASE gg_strategy.str_strategy OF
            strat_join_all_inv_equal,
            strat_join_inv_range :
                BEGIN
                ak728pseudo_multinv_check( acv, dmli,
                      gg_strategy.str_join_multfields.sjmf_index_no,
                      _index_scan_rec, _used_strat, expl  );
                END;
            strat_inv_range_fetch, strat_inv_range_merge_fetch, strat_inv_range,
            strat_inv_subq, strat_inv_in :
                BEGIN
                ak728pseudo_multinv_check( acv, dmli,
                      gg_strategy.str_inv_in_range.siir_indexno,
                      _index_scan_rec, _used_strat, expl );
                END;
            OTHERWISE
                BEGIN
                END
            END;
        (*ENDCASE*) 
&       IFDEF TRACE
        a725output_explain( ak_strat, expl );
&       ENDIF
        a40add_explain_record( acv, expl );
        END
    ELSE
        BEGIN
&       ifdef trace
        t01sname ( ak_strat, '############' );
&       endif
        IF  ( gg_strategy.str_strategy = strat_more_than_one )
        THEN
            BEGIN
&           IFDEF TRACE
            a725output_explain( ak_strat, expl );
&           ENDIF
            a40add_explain_record( acv, expl );
            expl.exp_user      := a01_il_b_identifier;
            expl.exp_table     := a01_il_b_identifier;
            expl.exp_pagecount :=  - 1;
            _pos           := morestratpos + STRATEGY_START_MXGG07;
            SAPDB_PascalMove ('VAK728',   1,    
                  sizeof( gg_strategy ), sizeof( _loc_gg_strategy ),
                  @gg_strategy, 1,
                  @_loc_gg_strategy, 1,
                  STRATEGY_START_MXGG07,
                  acv.a_returncode);
            FOR _ix := 1 TO gg_strategy.str_cnt_strat DO
                BEGIN
                _str.strat_char[ 1 ] := morestratbuf[ _pos ];
                _loc_gg_strategy.str_strategy := _str.strat_enum;
                _len := s20or4b( morestratbuf, _pos + 4 );
&               ifdef TRACE
                t01strat_enum( ak_strat, 'next strat  ', _loc_gg_strategy.str_strategy );
                t01int4( ak_strat, 'strat len   ', _len );
&               endif
                SAPDB_PascalMove ('VAK728',   2,    
                      morestratbufsize,
                      sizeof( _loc_gg_strategy.str_raw ),
                      @morestratbuf, _pos + cgg07_stratpos_offs,
                      @_loc_gg_strategy.str_raw, 1,
                      _len,
                      acv.a_returncode);
                _pos := _pos + cgg07_stratpos_offs + _len;
                IF  ( acv.a_returncode = 0 )
                THEN
                    ak728strat_and_column( acv, dmli, _loc_gg_strategy,
                          NIL, morestratbuf, morestratbufsize,
                          morestratpos, expl );
                (*ENDIF*) 
                END
            (*ENDFOR*) 
            END
        ELSE
            BEGIN
            ak728column_name_get( acv, dmli, gg_strategy,
                  joininfo_ptr, _used_strat, expl );
&           IFDEF TRACE
            a725output_explain( ak_strat, expl );
&           ENDIF
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a728explain_no_join_strat_now( VAR acv : tak_all_command_glob);
 
VAR
      _expl     : tak70_explain_rec;
 
BEGIN
_expl.exp_user         := a01_il_b_identifier;
_expl.exp_column       := a01_il_b_identifier;
_expl.exp_table        := a01_il_b_identifier;
_expl.exp_flags        := [];
_expl.exp_pagecount    := cak_is_undefined;
_expl.exp_strat        := a728_strat_texts[ c_str_not_now ];
IF  ( NOT acv.a_pars_explain )
THEN
    a40add_explain_record( acv, _expl );
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a728_init_strat_texts;
 
BEGIN
a728_strat_texts[ c_str_empty         ] := '                                        ';
a728_strat_texts[ c_str_no_result     ] := 'NO RESULT SET POSSIBLE                  ';
a728_strat_texts[ c_str_table_scan    ] := 'TABLE SCAN                              ';
a728_strat_texts[ c_str_inv_scan      ] := 'INDEX SCAN                              ';
(**)
a728_strat_texts[ c_str_key_rang      ] := 'RANGE CONDITION FOR KEY                 ';
a728_strat_texts[ c_str_key_eq        ] := 'EQUAL CONDITION FOR KEY                 ';
a728_strat_texts[ c_str_key_in        ] := 'IN CONDITION FOR KEY                    ';
a728_strat_texts[ c_str_key_subq      ] := 'SUBQ CONDITION FOR KEY                  ';
(**)
a728_strat_texts[ c_str_inv_rang      ] := 'RANGE CONDITION FOR INDEX               ';
a728_strat_texts[ c_str_inv_eq        ] := 'EQUAL CONDITION FOR INDEX               ';
a728_strat_texts[ c_str_inv_in        ] := 'IN CONDITION FOR INDEX                  ';
a728_strat_texts[ c_str_inv_subq      ] := 'SUBQ CONDITION FOR INDEX                ';
(**)
a728_strat_texts[ c_str_different     ] := 'DIFFERENT STRATEGIES FOR OR-TERMS       ';
a728_strat_texts[ c_str_not_now       ] := 'NO STRATEGY NOW (ONLY AT EXECUTION TIME)';
(**)
a728_strat_texts[ c_str_j_all_invs    ] := 'JOIN VIA MULTIPLE INDEXED COLUMNS       ';
a728_strat_texts[ c_str_j_start_invs  ] := 'JOIN VIA RANGE OF MULTIPLE INDEXED COL. ';
a728_strat_texts[ c_str_j_inv         ] := 'JOIN VIA INDEXED COLUMN                 ';
a728_strat_texts[ c_str_j_start_keys  ] := 'JOIN VIA RANGE OF MULTIPLE KEY COLUMNS  ';
a728_strat_texts[ c_str_j_keynext     ] := 'JOIN VIA KEY RANGE                      ';
a728_strat_texts[ c_str_j_all_keys_eq ] := 'JOIN VIA MULTIPLE KEY COLUMNS           ';
a728_strat_texts[ c_str_j_keyeq       ] := 'JOIN VIA KEY COLUMN                     ';
(**)
a728_strat_texts[ c_str_catscan       ] := 'CATALOG SCAN                            ';
a728_strat_texts[ c_str_catscan_user  ] := 'CATALOG SCAN USING USER EQUAL CONDITION ';
a728_strat_texts[ c_str_catkey        ] := 'CATALOG KEY ACCESS                      ';
(**)
a728_strat_texts[ c_str_unknown       ] := 'UNKNOWN STRATEGY ?!                     ';
(**)
a728_strat_texts[ c_strat_index       ] := '     (USED INDEX COLUMN)                ';
a728_strat_texts[ c_strat_key         ] := '     (USED KEY COLUMN)                  ';
a728_strat_texts[ c_strat_sortcol     ] := '     (USED SORT COLUMN)                 ';
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
