.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-17
*****************************************************
modname : VAK723
changed : 2000-11-17
module  : Build_Strategy_Index_Only
 
Author  : GertG / HolgerB
Created : 1985-10-16
*****************************************************
 
Purpose : help module for "Index Only" strategy
 
Define  :
 
        PROCEDURE
              a723only_index_stack (
                    VAR acv           : tak_all_command_glob;
                    VAR tabid         : tgg00_Surrogate;
                    VAR gg_strategy   : tgg07_StrategyInfo);
 
        PROCEDURE
              a723analyse_used_cols (
                    VAR acv           : tak_all_command_glob;
                    VAR dmli          : tak_dml_info;
                    VAR access_info   : tak70_strategy_record;
                    VAR gg_strategy   : tgg07_StrategyInfo);
 
.CM *-END-* define --------------------------------------
 
Use     :
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01diag_minmax_optim   : boolean;
 
      ------------------------------ 
 
        FROM
              AK_universal_semantic_tools : VAK06;
 
        PROCEDURE
              a06find_colinfo (
                    base_ptr        : tak_sysbufferaddress;
                    VAR stack_entry : tgg00_StackEntry;
                    VAR colinfo_ptr : tak00_colinfo_ptr);
 
      ------------------------------ 
 
        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;
 
      ------------------------------ 
 
        FROM
              Build_Strategy_2 : VAK71;
 
        PROCEDURE
              a71search_thru_index (
                    VAR acv        : tak_all_command_glob;
                    VAR column     : tgg00_StackEntry;
                    VAR index_def  : tak_multindex;
                    VAR invfield   : tsp00_Int2);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Trace_Strategy_1 : VAK725;
 
        PROCEDURE
              a725output_involved_cols (
                    debug   : tgg00_Debug;
                    nam     : tsp00_Sname;
                    ic_info : tak70_involved_columns);
&       endif
 
      ------------------------------ 
 
        FROM
              Trace_Strategy_2 : VAK727;
 
        PROCEDURE
              a727trace_involved_cols (
                    VAR transid : tgg00_TransContext;
                    proc_name   : tsp00_Name;
                    ic_info     : tak70_involved_columns;
                    distinct    : boolean;
                    inv_only    : boolean);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01vtrace    : tgg00_VtraceState;
 
      ------------------------------ 
 
        FROM
              Trace_Help_Procedures : VGG041;
 
        PROCEDURE
              g041int4_to_trace (
                    VAR t  : tgg00_TransContext;
                    name   : tsp00_Name;
                    intval : tsp00_Int4);
 
        PROCEDURE
              g041c30_to_trace (
                    VAR t  : tgg00_TransContext;
                    msg    : tsp00_C30);
 
      ------------------------------ 
 
        FROM
              Record_Encapsulate_Procedures : VGG09;
 
        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);
 
        PROCEDURE
              g09OutStackentry (
                    VAR NewStackEntry : tgg00_StackEntry;
                    inp_etype         : tgg00_StackEntryType;
                    inp_eop           : tgg00_StackOpOutput;
                    inp_resultpos     : tsp00_Int2;
                    inp_resultlen     : tsp00_Int2);
 
        PROCEDURE
              g09OpStackentry (
                    VAR NewStackEntry : tgg00_StackEntry;
                    inp_eop           : tgg00_StackOpType);
 
        PROCEDURE
              g09JumpStackentry (
                    VAR NewStackEntry : tgg00_StackEntry;
                    inp_etype         : tgg00_StackEntryType;
                    inp_jumpcnt       : tsp00_Int2);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalOverlappingMove (
                    mod_id         : tsp00_C6;
                    mod_intern_num : tsp00_Int4;
                    source_upb     : tsp00_Int4;
                    destin_upb     : tsp00_Int4;
                    source         : tsp00_MoveObjPtr;
                    source_pos     : tsp00_Int4;
                    destin         : tsp00_MoveObjPtr;
                    destin_pos     : tsp00_Int4;
                    length         : tsp00_Int4;
                    VAR e          : tgg00_BasisError);
&       ifdef trace
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01op_func (
                    debug  : tgg00_Debug;
                    nam    : tsp00_Sname;
                    op     : tgg00_StackOpFunc);
         
        PROCEDURE
              t01messblock (
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    VAR m         : tgg00_MessBlock);
 
        PROCEDURE
              t01stackentry (
                    debug          : tgg00_Debug;
                    VAR st         : tgg00_StackEntry;
                    entry_index    : integer);
 
        PROCEDURE
              t01bool (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    curr_bool: boolean);
 
        PROCEDURE
              t01int4 (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01sname (
                    level : tgg00_Debug;
                    nam   : tsp00_Sname);
 
        PROCEDURE
              t01name (
                    level : tgg00_Debug;
                    nam : tsp00_Name);
&       endif
 
.CM *-END-* use -----------------------------------------
 
Synonym :
 
.CM *-END-* synonym -------------------------------------
***********************************************************
 
Description:
 
 
.CM *-END-* description ---------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
(*------------------------------*) 
 
PROCEDURE
      a723only_index_stack (
            VAR acv           : tak_all_command_glob;
            VAR tabid         : tgg00_Surrogate;
            VAR gg_strategy   : tgg07_StrategyInfo);
 
VAR
      _mark_special_flag : boolean;
      _etype             : tgg00_StackEntryType;
      _eop               : tgg00_StackOpType;
      _epos              : tsp00_Int2;
      _elen_var          : tsp00_Int2;
      _ecol_tab          : tsp00_C2;
      _ix                : tsp00_Int2;
      _iz                : tsp00_Int2;
      _jump_stack        : tsp00_Int2;
      _foundfield        : tsp00_Int2;
      _out_pos           : tsp00_Int2;
      _old_mfirst        : tsp00_Int2;
      _end_out           : tsp00_Int2;
      _index_scan_rec    : tak_index_scan_record;
      _index_def         : tak_multindex;
 
BEGIN
&ifdef trace
t01messblock( ak_strat,'ORIG STACK  ', acv.a_mblock );
&endif
a24fnd_indexno( acv, tabid,
      gg_strategy.str_inv_in_range.siir_indexno, _index_scan_rec );
IF  ( _index_scan_rec.isr_buf <> NIL )
THEN
    BEGIN
    _index_def := _index_scan_rec.isr_buf^.
          smindex.indexdef[ _index_scan_rec.isr_index ];
    _jump_stack        := 0;
    _end_out           := 0;
    _old_mfirst        := acv.a_mblock.mb_qual^.mfirst_free;
    _ix                := acv.a_mblock.mb_qual^.mqual_pos;
    WHILE ( _ix <= ( acv.a_mblock.mb_qual^.mqual_pos +
          acv.a_mblock.mb_qual^.mqual_cnt - 1 ) ) AND
          ( acv.a_returncode = 0 ) DO
        BEGIN
&       ifdef trace
        t01stackentry( ak_strat, acv.a_mblock.mb_st^[ _ix ], _ix );
&       endif
        (* step over qualification stack entries *)
        CASE acv.a_mblock.mb_st^[ _ix ].etype OF
            st_fixcol,
            st_varcol,
            st_varlongchar:
                (* this have to be an index column *)
                BEGIN
                _out_pos     := 0;
                a71search_thru_index ( acv, acv.a_mblock.mb_st^[ _ix ],
                      _index_def, _foundfield );
                IF  ( _foundfield = 0 )
                THEN
                    a07_b_put_error( acv, e_old_fileversion, 1 )
                ELSE
                    BEGIN
                    IF  ( acv.a_mblock.mb_st^[ _ix ].elen_var <>
                        _index_def.icolstack[ _foundfield ].elen_var )
                    THEN
                        a07_b_put_error( acv, e_old_fileversion, 1 );
                    (*ENDIF*) 
                    IF  ( _foundfield <> a24IndexFieldCount( _index_def ))
                    THEN
                        _etype := st_fixinv
                    ELSE
                        _etype := st_varinv;
                    (*ENDIF*) 
                    _eop  := acv.a_mblock.mb_st^[ _ix ].eop;
                    _epos := 1;
                    IF  ( _foundfield > 1 )
                    THEN
                        (* calc position in index record *)
                        FOR _iz := 1 TO ( _foundfield - 1 ) DO
                            _epos := _epos + _index_def.icolstack[ _iz ].elen_var;
                        (*ENDFOR*) 
                    (*ENDIF*) 
                    IF  ( _index_def.icolstack[ _foundfield ].eop in
                        [ op_order_desc, op_unique_desc ] )
                    THEN
                        BEGIN
                        IF  ( NOT ( acv.a_mblock.mb_st^[ _ix ].eop in
                            [ op_order_desc, op_unique_desc ] ))
                        THEN
                            BEGIN
                            (* remark descending *)
                            _eop := _index_def.icolstack[ _foundfield ].eop;
                            IF  ( NOT ( acv.a_mblock.mb_st^[ _ix ].eop in
                                [ op_none, op_order_asc, op_unique ] ))
                            THEN
                                ak723desc_change( acv, gg_strategy, _ix );
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END
                    ELSE
                        (* ascending ordered index             *)
                        (* remove disturbing index information *)
                        IF  ( acv.a_mblock.mb_st^[ _ix ].eop in
                            [ op_order_desc, op_unique_desc ] )
                        THEN
                            _eop := op_none;
                        (*ENDIF*) 
                    (*ENDIF*) 
                    g09IndexColStackentry(
                          acv.a_mblock.mb_st^[ _ix ],
                          _etype,
                          _epos,
                          _eop,
                          _index_def.icolstack[ _foundfield ].elen_var,
                          ord( acv.a_mblock.mb_st^[ _ix ].ecol_tab[ 2 ] ));
                    ;
                    IF  ( acv.a_mblock.mb_st^[ _ix + 1 ].etype in
                        [ st_output, st_output_join ] )
                    THEN
                        BEGIN
                        _epos := acv.a_mblock.mb_st^[ _ix + 1 ].epos;
                        IF  ( acv.a_mblock.mb_st^[ _ix + 1 ].epos = 0 )
                        THEN
                            _epos := _out_pos;
                        (*ENDIF*) 
                        _elen_var := acv.a_mblock.mb_st^[ _ix + 1 ].elen_var;
                        IF  ( acv.a_mblock.mb_st^[ _ix + 1 ].elen_var = 0 )
                        THEN
                            _elen_var :=
                                  _index_def.icolstack[ _foundfield ].elen_var;
                        (* for st_output_join ecol_tab contains info *)
                        (*ENDIF*) 
                        _ecol_tab := acv.a_mblock.mb_st^[ _ix + 1 ].ecol_tab;
                        g09OutStackentry(
                              acv.a_mblock.mb_st^[ _ix + 1 ],
                              acv.a_mblock.mb_st^[ _ix + 1 ].etype,
                              acv.a_mblock.mb_st^[ _ix + 1 ].eop_out,
                              _epos,
                              _elen_var );
                        acv.a_mblock.mb_st^[ _ix + 1 ].ecol_tab := _ecol_tab;
                        _out_pos := acv.a_mblock.mb_st^[ _ix + 1 ].epos +
                              acv.a_mblock.mb_st^[ _ix + 1 ].elen_var;
                        _ix := succ( _ix );
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                _ix := succ( _ix );
                END;
            st_fixkey,
            st_varkey :
                BEGIN
                a71search_thru_index ( acv, acv.a_mblock.mb_st^[ _ix ],
                      _index_def, _foundfield );
                IF  ( _foundfield = 0 )
                THEN
                    (* this is a pure key column *)
                    BEGIN
                    IF  ( acv.a_mblock.mb_st^[ _ix ].etype = st_fixkey )
                    THEN
                        _etype := st_fixprimkey
                    ELSE
                        _etype := st_varprimkey;
                    (*ENDIF*) 
                    _eop := acv.a_mblock.mb_st^[ _ix ].eop;
                    ;
                    g09ColStackentry(
                          acv.a_mblock.mb_st^[ _ix ],
                          _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^[ _ix ].eop := _eop;
                    END
                ELSE
                    (* this key column is participant of an index *)
                    BEGIN
                    (* for g04one_limitkey, to find the   *)
                    (* last keyfield, if field is inverted*)
                    (* and is also the last keyfield      *)
                    IF  acv.a_mblock.mb_st^[ _ix ].etype = st_varkey
                    THEN
                        (* mark VARKEY entry *)
                        _mark_special_flag := true
                    ELSE
                        _mark_special_flag := false;
                    (*ENDIF*) 
                    _epos := 1;
                    IF  ( _foundfield > 1 )
                    THEN
                        (* calc position in index record *)
                        FOR _iz := 1 TO ( _foundfield - 1 ) DO
                            BEGIN
&                           ifdef trace
                            t01int4( ak_strat, 'one elen_var',
                                  _index_def.icolstack[ _iz ].elen_var );
&                           endif
                            _epos := _epos +
                                  _index_def.icolstack[ _iz ].elen_var;
                            END;
                        (*ENDFOR*) 
                    (*ENDIF*) 
                    IF  ( _foundfield = a24IndexFieldCount( _index_def ))
                    THEN
                        BEGIN
                        _etype    := st_varinv;
                        _elen_var := _index_def.icolstack[ _foundfield ].elen_var;
                        END
                    ELSE
                        BEGIN
                        _etype    := st_fixinv;
                        _elen_var := _index_def.icolstack[ _foundfield ].elen_var;
                        END;
                    (*ENDIF*) 
                    _eop := acv.a_mblock.mb_st^[ _ix ].eop;
                    IF  ( _index_def.icolstack[ _foundfield ].eop in
                        [ op_order_desc, op_unique_desc ] )
                    THEN
                        BEGIN
                        IF  ( NOT ( acv.a_mblock.mb_st^[ _ix ].eop in
                            [ op_order_desc, op_unique_desc ] ))
                        THEN
                            BEGIN
                            _eop := _index_def.icolstack[ _foundfield ].eop;
                            IF  ( NOT ( acv.a_mblock.mb_st^[ _ix ].eop in
                                [ op_none, op_order_asc, op_unique ] ))
                            THEN
                                ak723desc_change( acv, gg_strategy, _ix );
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END
                    ELSE
                        IF  ( acv.a_mblock.mb_st^[ _ix ].eop in
                            [ op_order_desc, op_unique_desc ] )
                        THEN
                            _eop := op_none;
                        (*ENDIF*) 
                    (*ENDIF*) 
                    g09IndexColStackentry(
                          acv.a_mblock.mb_st^[ _ix ],
                          _etype,
                          _epos,
                          _eop,
                          _elen_var,
                          ord( acv.a_mblock.mb_st^[ _ix ].ecol_tab[ 2 ] ));
                    ;
                    IF  ( _mark_special_flag )
                    THEN
                        acv.a_mblock.mb_st^[ _ix ].ecol_tab[ 1 ] := VARKEY_GG07;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                _ix := succ( _ix );
                END;
            st_jump_output :
                BEGIN
                IF  ( _jump_stack = 0 )
                THEN
                    BEGIN
                    _end_out    := acv.a_mblock.mb_st^[ _ix ].epos;
                    _jump_stack := _ix;
                    END
                ELSE
                    a07ak_system_error( acv, 723, 1 );
                (*ENDIF*) 
                _ix := succ( _ix );
                END;
            OTHERWISE
                BEGIN
                _ix := succ( _ix );
                END
            END;
        (*ENDCASE*) 
        IF  ( _jump_stack > 0 )
        THEN
            IF  ( _ix >= acv.a_mblock.mb_st^[ _jump_stack ].epos +
                ( acv.a_mblock.mb_qual^.mfirst_free - _old_mfirst ))
            THEN
                BEGIN
                g09JumpStackentry(
                      acv.a_mblock.mb_st^[ _jump_stack ],
                      acv.a_mblock.mb_st^[ _jump_stack ].etype,
                      acv.a_mblock.mb_st^[ _jump_stack ].epos +
                      ( acv.a_mblock.mb_qual^.mfirst_free - _old_mfirst ));
                _jump_stack := 0
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
&   ifdef trace
    t01messblock( ak_strat,'ONLY INV STA', acv.a_mblock );
&   endif
    END
ELSE
    a07_b_put_error( acv, e_old_fileversion, 1 );
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak723desc_change (
            VAR acv           : tak_all_command_glob;
            VAR gg_strategy   : tgg07_StrategyInfo;
            stpos             : tsp00_Int2);
 
VAR
      _iz : tsp00_Int2;
 
BEGIN
IF  acv.a_mblock.mb_qual^.mfirst_free < acv.a_mblock.mb_st_max
THEN
    BEGIN
    SAPDB_PascalOverlappingMove('VAK723',   1,    
          acv.a_mblock.mb_st_size, acv.a_mblock.mb_st_size,
          @acv.a_mblock.mb_st^, stpos * STACK_ENTRY_MXGG00 + 1,
          @acv.a_mblock.mb_st^, ( stpos + 1 ) * STACK_ENTRY_MXGG00 + 1,
          ( acv.a_mblock.mb_qual^.mfirst_free - stpos ) * STACK_ENTRY_MXGG00,
          acv.a_returncode );
    g09OpStackentry( acv.a_mblock.mb_st^[ stpos + 1 ],
          acv.a_mblock.mb_st^[ stpos ].eop );
    ak723upd_stack_desc( stpos, 1, acv.a_mblock.mb_qual^.mstack_desc );
    acv.a_mblock.mb_qual^.mqual_cnt :=
          succ( acv.a_mblock.mb_qual^.mqual_cnt );
    ak723increase_keys( gg_strategy, stpos, 1 );
    FOR _iz := 0 TO ( gg_strategy.str_inv_in_range.siir_startcnt - 1 ) DO
        IF  ( stpos <
            abs( gg_strategy.str_inv_in_range.siir_invstart[ _iz ] ) )
        THEN
            IF  ( gg_strategy.str_inv_in_range.siir_invstart[ _iz ] > 0 )
            THEN
                gg_strategy.str_inv_in_range.siir_invstart[ _iz ] :=
                      gg_strategy.str_inv_in_range.siir_invstart[ _iz ] + 1
            ELSE
                gg_strategy.str_inv_in_range.siir_invstart[ _iz ] :=
                      gg_strategy.str_inv_in_range.siir_invstart[ _iz ] - 1;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDFOR*) 
    FOR _iz := 0 TO ( gg_strategy.str_inv_in_range.siir_stopcnt - 1 ) DO
        IF  ( stpos <
            abs( gg_strategy.str_inv_in_range.siir_invstop[ _iz ] ) )
        THEN
            IF  ( gg_strategy.str_inv_in_range.siir_invstop[ _iz ] > 0 )
            THEN
                gg_strategy.str_inv_in_range.siir_invstop[ _iz ] :=
                      gg_strategy.str_inv_in_range.siir_invstop[ _iz ] + 1
            ELSE
                gg_strategy.str_inv_in_range.siir_invstop[ _iz ] :=
                      gg_strategy.str_inv_in_range.siir_invstop[ _iz ] - 1;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDFOR*) 
    END
ELSE
    (* better way: first proove count of free stack entries *)
    a07_b_put_error( acv, e_too_many_mb_stackentries, 1 );
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak723upd_stack_desc (
            stpos           : tsp00_Int2;
            movement        : tsp00_Int2;
            VAR mstack_desc : tgg00_StackDesc);
 
BEGIN
IF  (mstack_desc.mcol_cnt > 0) AND (stpos <= mstack_desc.mcol_pos)
THEN
    mstack_desc.mcol_pos    :=              mstack_desc.mcol_pos + movement;
(*ENDIF*) 
IF  (mstack_desc.mmult_cnt > 0) AND (stpos <= mstack_desc.mmult_pos)
THEN
    mstack_desc.mmult_pos   :=               mstack_desc.mmult_pos + movement;
(*ENDIF*) 
IF  (mstack_desc.mqual_cnt > 0) AND (stpos <= mstack_desc.mqual_pos)
THEN
    mstack_desc.mqual_pos   :=               mstack_desc.mqual_pos + movement;
(*ENDIF*) 
IF  (mstack_desc.mview_cnt > 0) AND (stpos <= mstack_desc.mview_pos)
THEN
    mstack_desc.mview_pos   :=               mstack_desc.mview_pos + movement;
(*ENDIF*) 
IF  (mstack_desc.mupd_cnt > 0) AND (stpos <= mstack_desc.mupd_pos)
THEN
    mstack_desc.mupd_pos    :=              mstack_desc.mupd_pos + movement;
(*ENDIF*) 
IF  (mstack_desc.mlink_cnt > 0) AND (stpos <= mstack_desc.mlink_pos)
THEN
    mstack_desc.mlink_pos   :=               mstack_desc.mlink_pos + movement;
(*ENDIF*) 
IF  (mstack_desc.mstrat_cnt > 0) AND (stpos <= mstack_desc.mstrat_pos)
THEN
    mstack_desc.mstrat_pos  :=                mstack_desc.mstrat_pos + movement;
(*ENDIF*) 
IF  (mstack_desc.mstring_cnt > 0) AND (stpos <= mstack_desc.mstring_pos)
THEN
    mstack_desc.mstring_pos :=                 mstack_desc.mstring_pos + movement;
(*ENDIF*) 
IF  (mstack_desc.mtrigger_cnt > 0) AND (stpos <= mstack_desc.mtrigger_pos)
THEN
    mstack_desc.mtrigger_pos:=                  mstack_desc.mtrigger_pos + movement;
(*ENDIF*) 
IF  (mstack_desc.minvqual_cnt > 0) AND (stpos <= mstack_desc.minvqual_pos)
THEN
    mstack_desc.minvqual_pos:=                  mstack_desc.minvqual_pos + movement;
(*ENDIF*) 
IF  (mstack_desc.mresqual_cnt > 0) AND (stpos <= mstack_desc.mresqual_pos)
THEN
    mstack_desc.mresqual_pos:=                  mstack_desc.mresqual_pos + movement;
(*ENDIF*) 
mstack_desc.mfirst_free := mstack_desc.mfirst_free + movement;
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak723increase_keys (
            VAR gg_strategy : tgg07_StrategyInfo;
            stpos           : tsp00_Int2;
            i_cnt           : tsp00_Int2);
 
VAR
      _iz : tsp00_Int4;
 
BEGIN
_iz := 0;
WHILE ( _iz <= MAX_COLPOSARR_IDX_GG07 ) AND
      ( gg_strategy.str_key_in_range.skir_keystart[ _iz ] <> 0 ) DO
    BEGIN
    IF  ( stpos < abs(gg_strategy.str_key_in_range.skir_keystart[ _iz ] ) )
    THEN
        IF  ( gg_strategy.str_key_in_range.skir_keystart[ _iz ] > 0 )
        THEN
            gg_strategy.str_key_in_range.skir_keystart[ _iz ] :=
                  gg_strategy.str_key_in_range.skir_keystart[ _iz ] + i_cnt
        ELSE
            gg_strategy.str_key_in_range.skir_keystart[ _iz ] :=
                  gg_strategy.str_key_in_range.skir_keystart[ _iz ] - i_cnt;
        (*ENDIF*) 
    (*ENDIF*) 
    _iz := succ(_iz);
    END;
(*ENDWHILE*) 
_iz := 0;
WHILE ( _iz <= MAX_COLPOSARR_IDX_GG07 ) AND
      ( gg_strategy.str_key_in_range.skir_keystop[ _iz ] <> 0 ) DO
    BEGIN
    IF  ( stpos < abs( gg_strategy.str_key_in_range.skir_keystop[ _iz ] ) )
    THEN
        IF  ( gg_strategy.str_key_in_range.skir_keystop[ _iz ] > 0 )
        THEN
            gg_strategy.str_key_in_range.skir_keystop[ _iz ] :=
                  gg_strategy.str_key_in_range.skir_keystop[ _iz ] + i_cnt
        ELSE
            gg_strategy.str_key_in_range.skir_keystop[ _iz ] :=
                  gg_strategy.str_key_in_range.skir_keystop[ _iz ] - i_cnt;
        (*ENDIF*) 
    (*ENDIF*) 
    _iz := succ(_iz);
    END;
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak723analyze_output (
            VAR acv            : tak_all_command_glob;
            VAR dmli           : tak_dml_info;
            VAR access_info    : tak70_strategy_record;
            VAR gg_strategy    : tgg07_StrategyInfo);
 
TYPE
      t_colfound = ( cf_none, cf_key, cf_inv, cf_key_inv );
      t_optim_kind = ( ok_MIN_MAX, ok_aggr_func );
 
VAR
      _iz            : tsp00_Int2;
      _stpos         : tsp00_Int2;
      _stop          : tsp00_Int2;
      _col_no        : tsp00_Int2;
      _keycolcnt     : tsp00_Int2;
      _keyseqcnt     : tsp00_Int2;
      _col_found     : t_colfound;
      _value_found   : boolean;
      _funct_found   : boolean;
      _key_dist_opt  : boolean;
      _funct_cnt     : tsp00_Int2;
      _col_ptr       : tak00_colinfo_ptr;
      _key_pos       : ARRAY [ 1..cak_maxkeyfields ] OF tsp00_Int2;
      _key_len       : ARRAY [ 1..cak_maxkeyfields ] OF tsp00_Int2;
      _check_optim   : SET OF t_optim_kind; (* AGGR OR MIN/MAX optimization possible? *)
 
BEGIN
_check_optim := [];
_col_found   := cf_none;
_value_found := false;
_funct_found := false;
_key_dist_opt:= true;
_funct_cnt   := 0;
_stpos := acv.a_mblock.mb_qual^.mqual_pos;
IF  ( _stpos > 0 )
    AND
    ( acv.a_mblock.mb_qual^.mqual_cnt > 0 ) (* important !!*)
    AND
    ( acv.a_mblock.mb_st^[ _stpos ].etype = st_jump_output )
THEN
    BEGIN
    (* stop on last output column *)
    _stop      := _stpos + acv.a_mblock.mb_st^[ _stpos ].epos - 1;
    _stpos     := succ( _stpos );
    ;
    IF  ( gg_strategy.str_distinc <> no_distinct )
        AND
        (* array commands(means more than one data for one parameter) *)
        (* more than one SELECT in one result set (disticntness)      *)
        NOT ( acv.a_precomp_info_byte in
        [ csp1_p_mselect_found, csp1_p_for_upd_mselect_found,
        csp1_p_reuse_mselect_found, csp1_p_reuse_upd_mselect_found ] )
    THEN
        BEGIN
        (* initialize output key-sequence search *)
        gg_strategy.str_out_keyseqlen := 0 ;
        _keycolcnt := 0;
        FOR _iz := 1 TO cak_maxkeyfields DO
            BEGIN
            _key_pos[ _iz ] := 0;
            _key_len[ _iz ] := 0;
            END;
        (*ENDFOR*) 
        END
    ELSE
        gg_strategy.str_out_keyseqlen := NOT_SEQUENCED_GG07;
    (*ENDIF*) 
    IF  (( acv.a_mblock.mb_type2 = mm_with_functions ) AND ( NOT dmli.d_join )
        AND ( acv.a_recursive_state = rs_no_recursive_select ))
    THEN
        BEGIN
        _check_optim := _check_optim + [ ok_aggr_func ];
        IF  (( NOT dmli.d_group ) AND a01diag_minmax_optim )
        THEN
            _check_optim := _check_optim + [ ok_MIN_MAX ];
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END
ELSE
    BEGIN
    _stop := _stpos;
    (* e.g. DELETE *)
    access_info.srec_query_prop.qps_switches :=
          access_info.srec_query_prop.qps_switches + [ qp_inv_only_impossible ];
    (* distinct optim not possible *)
    gg_strategy.str_out_keyseqlen  := NOT_SEQUENCED_GG07;
    END;
(*ENDIF*) 
WHILE ( _stpos < _stop ) DO
    BEGIN
    (* while looping check posibility of *)
    (* DISTINCT and MIN/MAX optimization *)
&   ifdef trace
    t01stackentry( ak_strat, acv.a_mblock.mb_st^[ _stpos ], _stpos );
&   endif
    CASE acv.a_mblock.mb_st^[ _stpos ].etype  OF
        st_fixkey, st_varkey,
        st_fixcol, st_varcol,
        st_varlongchar:
            BEGIN
            IF  ( _check_optim <> [] )
            THEN
                IF  ((( acv.a_mblock.mb_st^[ _stpos + 1 ].etype <> st_output ) AND
                    ( _col_found <> cf_none )) OR
                    ( acv.a_mblock.mb_st^[ _stpos ].eop <> op_none ))
                THEN
                    (* expression: more than one column per output *)
                    _check_optim := [];
                (*ENDIF*) 
            (*ENDIF*) 
            IF  ( gg_strategy.str_out_keyseqlen = 0 )
                AND
                ( acv.a_mblock.mb_st^[ _stpos ].etype in
                [ st_fixkey, st_varkey ] )
            THEN
                BEGIN
                (* work for SELECT DISTINCT optimization *)
                _keyseqcnt := 1;
                (* count key columns preceding found key column *)
                WHILE ( _keyseqcnt <= _keycolcnt ) AND
                      ( acv.a_mblock.mb_st^[ _stpos ].
                      epos > _key_pos[ _keyseqcnt ] ) DO
                    _keyseqcnt := succ( _keyseqcnt );
                (*ENDWHILE*) 
                (* if none preceding columns found ->   *)
                (* _keyseqcnt = _keycolcnt + 1          *)
                IF  ( _keycolcnt = 0 ) OR
                    (* only count different columns *)
                    ( _key_pos[ _keyseqcnt ] <> acv.a_mblock.
                    mb_st^[ _stpos ].epos )
                THEN
                    BEGIN
                    _keycolcnt := succ( _keycolcnt );
                    _iz        := _keycolcnt;
                    (* right shift for new entry *)
                    WHILE ( _iz >= _keyseqcnt + 1 ) DO
                        BEGIN
                        _key_pos[ _iz ] :=
                              _key_pos[ _iz - 1 ];
                        _key_len[ _iz ] :=
                              _key_len[ _iz - 1 ];
                        _iz             := _iz - 1;
                        END;
                    (*ENDWHILE*) 
                    _key_pos[ _iz ] :=
                          acv.a_mblock.mb_st^[ _stpos ].epos;
                    _key_len[ _iz ] :=
                          acv.a_mblock.mb_st^[ _stpos ].elen_var;
                    END;
                (*ENDIF*) 
                END
            ELSE
                _key_dist_opt := false;
            (*ENDIF*) 
            a06find_colinfo( dmli.d_sparr.pbasep,
                  acv.a_mblock.mb_st^[ _stpos ], _col_ptr );
            IF  ( _col_ptr <> NIL )
            THEN
                BEGIN
                IF  ( ctmulti in _col_ptr^.ccolpropset )
                    OR
                    ( ctkey in _col_ptr^.ccolpropset )
                THEN
                    BEGIN
                    _col_no := _col_ptr^.creccolno;
                    IF  ( ctmulti in _col_ptr^.ccolpropset )
                    THEN
                        BEGIN
                        (* access_info.srec_involved_cols.ic_i_outp_cols *)
                        ak723put_colno( access_info,
                              access_info.srec_involved_cols.ic_i_outp_cnt, _col_no,
                              access_info.srec_involved_cols.ic_all_colbuf,
                              0,
                              MAX_COL_SEQUENCE_GG00 );
                        _col_found := cf_inv;
                        END;
                    (*ENDIF*) 
                    IF  ( ctkey in _col_ptr^.ccolpropset )
                    THEN
                        BEGIN
                        (* access_info.srec_involved_cols.ic_k_outp_cols *)
                        ak723put_colno( access_info,
                              access_info.srec_involved_cols.ic_k_outp_cnt, _col_no,
                              access_info.srec_involved_cols.ic_all_colbuf,
                              MAX_COL_SEQUENCE_GG00 * 2,
                              MAX_COLPOSARR_IDX_GG07 );
                        IF  ( _col_found = cf_inv )
                        THEN
                            BEGIN
                            _col_found := cf_key_inv;
                            END
                        ELSE
                            _col_found := cf_key;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    (* none key/inv column found *)
                    access_info.srec_query_prop.qps_switches :=
                          access_info.srec_query_prop.qps_switches +
                          [ qp_inv_only_impossible ];
                    gg_strategy.str_out_keyseqlen  := NOT_SEQUENCED_GG07;
                    ;
                    _check_optim := [];
                    END;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
&               ifdef trace
                t01stackentry( ak_strat, acv.a_mblock.mb_st^[ _stpos ], _stpos );
&               endif
                a07_b_put_error( acv, e_old_fileversion, 1 );
                END;
            (*ENDIF*) 
            END;
        st_old_fixkey,
        st_old_varkey,
        st_old_fixcol,
        st_old_varcol,
        st_old_varlongchar:
            BEGIN
            (* trigger/scol *)
            access_info.srec_query_prop.qps_switches :=
                  access_info.srec_query_prop.qps_switches + [ qp_inv_only_impossible ];
            ;
            _check_optim := [];
            gg_strategy.str_out_keyseqlen := NOT_SEQUENCED_GG07;
            END;
        st_func :
            BEGIN
&           ifdef trace
            t01op_func( ak_strat, 'func found  ',
                  acv.a_mblock.mb_st^[ _stpos ].eop_func );
            t01bool( ak_strat, '_func_found ', _funct_found );
            IF  ( _col_found = cf_key )
            THEN
                t01sname( ak_strat, 'key found   ' )
            ELSE
                IF  ( _col_found = cf_inv )
                THEN
                    t01sname( ak_strat, 'inv found   ' )
                ELSE
                    IF  ( _col_found = cf_key_inv )
                    THEN
                        t01sname( ak_strat, 'key/inv foun' )
                    ELSE
                        t01sname( ak_strat, 'no col found' );
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
&           endif
            (* distinct optim not possible *)
            gg_strategy.str_out_keyseqlen := NOT_SEQUENCED_GG07;
            ;
            IF  ( acv.a_mblock.mb_st^[ _stpos ].eop_func in
                [ op_f_check_null, op_f_all_count ] )
            THEN
                BEGIN
                IF  (( _col_found = cf_none ) AND NOT _funct_found )
                THEN
                    BEGIN
                    IF  ( acv.a_mblock.mb_st^[ _stpos ].eop_func =
                        op_f_all_count )
                    THEN
                        _check_optim := _check_optim - [ ok_MIN_MAX ];
                    (*ENDIF*) 
                    _funct_found := true;
                    _funct_cnt   := succ(_funct_cnt);
                    IF  ( _funct_cnt > MAX_COL_SEQUENCE_GG00 )
                    THEN
                        _check_optim := _check_optim - [ ok_aggr_func ];
                    (*ENDIF*) 
                    _col_found   := cf_key_inv; (* any value *)
                    END
                ELSE
                    _check_optim := [];
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                IF  (( NOT _funct_found ) AND ( _col_found <> cf_none ))
                THEN
                    BEGIN
                    _funct_found := true;
                    _funct_cnt   := succ(_funct_cnt);
                    IF  ( _funct_cnt > MAX_COL_SEQUENCE_GG00 )
                    THEN
                        _check_optim := _check_optim - [ ok_aggr_func ];
                    (*ENDIF*) 
                    CASE acv.a_mblock.mb_st^[ _stpos ].eop_func OF
                        op_f_min, op_f_max :
                            BEGIN
                            CASE _col_found OF
                                cf_key:
                                    BEGIN
                                    access_info.srec_query_prop.qps_switches :=
                                          access_info.srec_query_prop.qps_switches +
                                          [ qp_check_key_MIN_MAX_opt ];
                                    (* aggregation optimization only possible *)
                                    (* with index columns *)
                                    _check_optim := _check_optim - [ ok_aggr_func ];
                                    END;
                                cf_inv:
                                    access_info.srec_query_prop.qps_switches :=
                                          access_info.srec_query_prop.qps_switches +
                                          [ qp_check_inv_MIN_MAX_opt ];
                                cf_key_inv:
                                    access_info.srec_query_prop.qps_switches :=
                                          access_info.srec_query_prop.qps_switches +
                                          [ qp_check_key_MIN_MAX_opt, qp_check_inv_MIN_MAX_opt ];
                                END;
                            (*ENDCASE*) 
                            END;
                        op_f_sum, op_f_dis_sum,
                        op_f_avg, op_f_dis_avg,
                        op_f_count, op_f_dis_count :
                            BEGIN
                            _check_optim := _check_optim - [ ok_MIN_MAX ];
                            IF  ( _col_found = cf_key )
                            THEN
                                (* aggregation optimization only possible *)
                                (* with index columns *)
                                _check_optim := _check_optim - [ ok_aggr_func ];
                            (*ENDIF*) 
                            END;
                        op_f_none :
                            BEGIN
                            (* 'LASTFUNCTION' *)
                            IF  ( _col_found <> cf_none )
                            THEN
                                _check_optim := [];
                            (*ENDIF*) 
                            END;
                        OTHERWISE
                            _check_optim := [];
                        END;
                    (*ENDCASE*) 
                    END
                ELSE
                    IF  ( acv.a_mblock.mb_st^[ _stpos ].eop_func <> op_f_none )
                    THEN
                        _check_optim := [];
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        st_output :
            BEGIN
            IF  ( _col_found <> cf_none )
            THEN
                BEGIN
                IF  ( _funct_found )
                THEN
                    BEGIN
                    _col_found   := cf_none;
                    _funct_found := false;
                    END
                ELSE
                    (* _col_found NOT _funct_found *)
                    (* i.e. GROUP BY column found        *)
                    _check_optim := _check_optim - [ ok_MIN_MAX ];
                (*ENDIF*) 
                END
            ELSE
                (* NOT _col_found *)
                BEGIN
                IF  ( _value_found )
                THEN
                    _value_found := false
                ELSE
                    IF  ( acv.a_mblock.mb_st^[ _stpos ].eop_out <> op_o_output_later )
                    THEN
                        _check_optim := [];
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        st_value :
            BEGIN
            (* distinct optim not possible *)
            gg_strategy.str_out_keyseqlen := NOT_SEQUENCED_GG07;
            ;
            IF  ( NOT ( acv.a_mblock.mb_st^[ _stpos + 1 ].etype in
                [ st_value, st_result, st_output ] ) )
            THEN
                _check_optim := []
            ELSE
                _value_found := true;
            (*ENDIF*) 
            END;
        st_op,
        st_result :
            BEGIN
            (* distinct optim not possible *)
            gg_strategy.str_out_keyseqlen := NOT_SEQUENCED_GG07;
            (* sktip this entries for setting of _check_optim *)
            END;
        OTHERWISE
            BEGIN
            (* distinct optim not possible *)
            gg_strategy.str_out_keyseqlen := NOT_SEQUENCED_GG07;
            _check_optim := _check_optim - [ ok_MIN_MAX ];
            END;
        END;
    (*ENDCASE*) 
    _stpos := succ( _stpos );
    END;
(*ENDWHILE*) 
IF  ( NOT ( ok_MIN_MAX in _check_optim ))
THEN
    access_info.srec_query_prop.qps_switches :=
          access_info.srec_query_prop.qps_switches -
          [ qp_check_key_MIN_MAX_opt, qp_check_inv_MIN_MAX_opt ];
(*ENDIF*) 
IF  ( ok_aggr_func in _check_optim )
THEN
    access_info.srec_query_prop.qps_switches :=
          access_info.srec_query_prop.qps_switches + [ qp_aggr_optim_poss ];
(*ENDIF*) 
IF  ( gg_strategy.str_out_keyseqlen = 0 ) AND ( _keycolcnt > 0 )
THEN
    BEGIN
&   ifdef trace
    t01int4( ak_strat, 'key col cnt ', _keycolcnt );
    FOR _iz := 1 TO _keycolcnt DO
        BEGIN
        t01int4( ak_strat, 'key_pos[ x ]', _key_pos[ _iz ] );
        t01int4( ak_strat, 'key_len[ x ]', _key_len[ _iz ] );
        END;
    (*ENDFOR*) 
&   endif
    (* work for SELECT DISTINCT optimization *)
    _iz        := 1;
    _keyseqcnt := 1;
    WHILE ( _iz <= _keycolcnt ) AND
          ( gg_strategy.str_out_keyseqlen <> NOT_SEQUENCED_GG07 ) DO
        BEGIN
        IF  ( _key_pos[ _iz ] = _keyseqcnt )
        THEN
            BEGIN
            gg_strategy.str_out_keyseqlen :=
                  gg_strategy.str_out_keyseqlen + _key_len[ _iz ];
            (* length of fields of 1..n Keys *)
            _keyseqcnt := _keyseqcnt + _key_len[ _iz ];
            _iz        := succ( _iz );
            END
        ELSE
            BEGIN
            (* no Optim. of Key-fields *)
            gg_strategy.str_out_keyseqlen := NOT_SEQUENCED_GG07;
&           ifdef trace
            t01sname( ak_strat, 'no key seque' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    ;
    END;
(*ENDIF*) 
IF  ( gg_strategy.str_out_keyseqlen <> NOT_SEQUENCED_GG07 ) 
THEN
    BEGIN
    (* sequenced key columns found *)
    IF  ( _keycolcnt = dmli.d_sparr.pbasep^.sbase.bkeycolcount )
    THEN
        access_info.srec_query_prop.qps_switches :=
              access_info.srec_query_prop.qps_switches + [ qp_auto_distinct ];
    (*ENDIF*) 
    IF  ( _keycolcnt > 0 ) AND ( _key_dist_opt )
    THEN
        access_info.srec_query_prop.qps_switches :=
              access_info.srec_query_prop.qps_switches +
              [ qp_only_keyseq_in_output ];
    (*ENDIF*) 
    IF  ( access_info.srec_involved_cols.ic_i_outp_cnt > 0 ) AND
        NOT ( qp_auto_distinct in access_info.srec_query_prop.qps_switches )
    THEN
        BEGIN
        gg_strategy.str_out_keyseqlen := gg_strategy.str_out_keyseqlen +
              KEYSEQLEN_OFFSET_GG07;
        END;
    (*ENDIF*) 
    END;
(* str_out_keyseqlen contains now length of sequenced key columns *)
(* if there are index columns there will be an offset of          *)
(* KEYSEQLEN_OFFSET_GG07 *)
(* if there are no key columns str_out_keyseqlen                  *)
(* contains 0 ( KEYSEQLEN_OFFSET_GG07 )                           *)
(* if key columns in output not sequenced str_out_keyseqlen       *)
(* is set to NOT_SEQUENCED_GG07                                   *)
(*ENDIF*) 
;
&ifdef TRACE
t01bool( ak_strat, 'inv only pos', NOT ( qp_inv_only_impossible in
      access_info.srec_query_prop.qps_switches ));
t01int4( ak_strat, 'out keyseqln', gg_strategy.str_out_keyseqlen );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    g041c30_to_trace ( acv.a_transinf.tri_trans,
          'AK723ANALYZE_OUTPUT           ' );
    IF  ( NOT ( qp_inv_only_impossible in
        access_info.srec_query_prop.qps_switches ))
    THEN
        g041c30_to_trace ( acv.a_transinf.tri_trans,
              'inv only possible             ' );
    (*ENDIF*) 
    IF  ( gg_strategy.str_out_keyseqlen = NOT_SEQUENCED_GG07 )
    THEN
        g041c30_to_trace ( acv.a_transinf.tri_trans,
              'out keyseqlen     : undef     ' )
    ELSE
        g041int4_to_trace ( acv.a_transinf.tri_trans,
              'out keyseqlen     ', gg_strategy.str_out_keyseqlen );
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a723analyse_used_cols (
            VAR acv           : tak_all_command_glob;
            VAR dmli          : tak_dml_info;
            VAR access_info   : tak70_strategy_record;
            VAR gg_strategy   : tgg07_StrategyInfo);
 
VAR
      _stpos         : tsp00_Int2;
      _stop          : tsp00_Int2;
      _col_no        : tsp00_Int2;
      _col_ptr       : tak00_colinfo_ptr;
 
BEGIN
ak723analyze_output( acv, dmli, access_info, gg_strategy );
IF  NOT ( qp_inv_only_impossible in access_info.srec_query_prop.qps_switches )
THEN
    BEGIN
    (* there are output columns, analyse qualification    *)
    (* stop on last qualification stack entry *)
    _stop := acv.a_mblock.mb_qual^.mqual_pos +
          acv.a_mblock.mb_qual^.mqual_cnt;
    (* because there are output columns, there is an jump_output stack entry *)
    (* start on first qualification *)
    _stpos     := acv.a_mblock.mb_qual^.mqual_pos +
          acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mqual_pos ].epos - 1;
&   ifdef trace
    t01name( ak_strat, 'analyse qualificat' );
    t01int4( ak_strat, 'start       ', _stpos );
    t01int4( ak_strat, 'stop        ', _stop );
&   endif
    ;
    WHILE ( _stpos < _stop ) AND
          ( NOT ( qp_inv_only_impossible in
          access_info.srec_query_prop.qps_switches )) DO
        BEGIN
&       ifdef trace
        t01stackentry( ak_strat, acv.a_mblock.mb_st^[ _stpos ], _stpos );
&       endif
        CASE acv.a_mblock.mb_st^[ _stpos ].etype  OF
            st_fixkey, st_varkey,
            st_fixcol, st_varcol,
            st_varlongchar:
                BEGIN
                a06find_colinfo( dmli.d_sparr.pbasep,
                      acv.a_mblock.mb_st^[ _stpos ], _col_ptr );
                IF  ( _col_ptr <> NIL )
                THEN
                    BEGIN
                    IF  ( ctmulti in _col_ptr^.ccolpropset )
                        OR
                        ( ctkey in _col_ptr^.ccolpropset )
                    THEN
                        BEGIN
                        _col_no := _col_ptr^.creccolno;
                        IF  ( ctmulti in _col_ptr^.ccolpropset )
                        THEN
                            (* access_info.srec_involved_cols.ic_i_qual_cols *)
                            ak723put_colno( access_info,
                                  access_info.srec_involved_cols.ic_i_qual_cnt,
                                  _col_no,
                                  access_info.srec_involved_cols.ic_all_colbuf,
                                  MAX_COL_SEQUENCE_GG00,
                                  MAX_COL_SEQUENCE_GG00 );
                        (*ENDIF*) 
                        IF  ( ctkey in _col_ptr^.ccolpropset )
                        THEN
                            BEGIN
                            (* access_info.srec_involved_cols.ic_k_qual_cols *)
                            ak723put_colno( access_info,
                                  access_info.srec_involved_cols.ic_k_qual_cnt,
                                  _col_no,
                                  access_info.srec_involved_cols.ic_all_colbuf,
                                  MAX_COL_SEQUENCE_GG00 * 2 + MAX_STRATEGY_KEYS_GG04,
                                  MAX_COLPOSARR_IDX_GG07 );
                            END;
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
&                       ifdef trace
                        t01name( ak_strat, 'normal col found  ' );
&                       endif
                        (* non key/inv column found *)
                        access_info.srec_query_prop.qps_switches :=
                              access_info.srec_query_prop.qps_switches +
                              [ qp_inv_only_impossible ];
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
&                   ifdef trace
                    t01stackentry( ak_strat, acv.a_mblock.mb_st^[ _stpos ],
                          _stpos );
&                   endif
                    a07_b_put_error( acv, e_old_fileversion, 1 );
                    END ;
                (*ENDIF*) 
                END;
            st_old_fixkey,
            st_old_varkey,
            st_old_fixcol,
            st_old_varcol,
            st_old_varlongchar:
                BEGIN
&               ifdef trace
                t01sname( ak_strat, 'trigger/scol' );
&               endif
                access_info.srec_query_prop.qps_switches :=
                      access_info.srec_query_prop.qps_switches +
                      [ qp_inv_only_impossible ];
                END;
            OTHERWISE
                IF  ( acv.a_mblock.mb_st^[ _stpos ].eop = op_or )
                THEN
                    BEGIN
                    (*
&                         ifdef trace
                          t01sname( ak_strat, 'L2_term foun' );
&                         endif
                          access_info.srec_query_prop.qps_switches :=
                          access_info.srec_query_prop.qps_switches +
                          [ qp_inv_only_impossible ];
                          *)
                    END;
                (*ENDIF*) 
            END;
        (*ENDCASE*) 
        _stpos := succ( _stpos );
        END;
    (*ENDWHILE*) 
    END;
(*ENDIF*) 
;
&ifdef TRACE
a725output_involved_cols( ak_strat, 'ic_info     ',
      access_info.srec_involved_cols );
t01int4( ak_strat, 'out keyseqln', gg_strategy.str_out_keyseqlen );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    a727trace_involved_cols( acv.a_transinf.tri_trans ,
          'A723ANALYZE_USED_C', access_info.srec_involved_cols,
          ( gg_strategy.str_distinc <> no_distinct ),
          NOT ( qp_inv_only_impossible in
          access_info.srec_query_prop.qps_switches ));
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak723put_colno (
            VAR access_info : tak70_strategy_record;
            VAR colno_cnt   : tsp00_Int2;
            VAR act_colno   : tsp00_Int2;
            VAR colno_arr   : tak70_all_colbuf;
            offset          : tsp00_Int2;
            max_idx         : tsp00_Int2);
 
VAR
      _ix        : tsp00_Int2;
      _fieldfound: boolean;
 
BEGIN
_ix         := 0;
_fieldfound := false;
WHILE ( _ix <= colno_cnt - 1 ) AND ( NOT _fieldfound ) DO
    IF  ( colno_arr[ offset + _ix ] = act_colno )
    THEN
        _fieldfound := true
    ELSE
        _ix         := succ(_ix);
    (*ENDIF*) 
(*ENDWHILE*) 
IF  ( NOT _fieldfound )
THEN
    IF  ( colno_cnt < max_idx )
    THEN
        BEGIN
        colno_cnt                           := succ( colno_cnt );
        colno_arr[ offset + colno_cnt - 1 ] := act_colno;
        END
    ELSE
        BEGIN
&       ifdef trace
        t01name( ak_strat, 'colno_cnt >= mx_id' );
&       endif
        access_info.srec_query_prop.qps_switches :=
              access_info.srec_query_prop.qps_switches + [ qp_inv_only_impossible ];
        END;
    (*ENDIF*) 
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
