.nf
 
 .nf
 
    ========== licence begin  GPL
    Copyright (c) 2000-2005 SAP AG
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
.fo
 
 
.fo
*****************************************************
Copyright (c) 2000-2005 SAP AG
SAP Database Technology
 
Release :      Date : 2000-10-11
*****************************************************
modname : VAK80
changed : 2000-10-11
module  : Hint_Handling
 
Author  : GertG
Created : 1999-10-13
*****************************************************
 
Purpose : syntax and semeantic analysis for hints.
 
Define  :
 
        PROCEDURE
              a80_ahint_statement (
                    VAR acv              : tak_all_command_glob;
                    subproc              : tsp00_Int2;
                    expected_select_node : tsp00_Int2);
 
        PROCEDURE
              a80store_cmd_hint_info(
                    VAR acv     : tak_all_command_glob;
                    VAR dmli    : tak_dml_info;
                    select_node : tsp00_Int4);
 
        PROCEDURE
              a80drop_all_hint_info( VAR acv : tak_all_command_glob );
 
        PROCEDURE
              a80get_access_hint(
                    VAR acv         : tak_all_command_glob;
                    parskey         : tak_parskey;
                    VAR access_hint : tak00_access_configuration );
 
        PROCEDURE
              a80get_access_for_join_hint(
                    VAR acv         : tak_all_command_glob;
                    parskey         : tak_parskey;
                    tableno         : tsp00_Int2;
                    VAR access_hint : tak00_access_configuration);
 
        FUNCTION
              a80is_predefined_join_order(
                    VAR acv : tak_all_command_glob) : boolean;
 
        PROCEDURE
              a80open_hint_info(
                    VAR acv         : tak_all_command_glob;
                    parskey         : tak_parskey;
                    VAR hintinfo    : tak_sysbufferaddress);
 
        PROCEDURE
              a80close_hint_info( VAR hintinfo : tak_sysbufferaddress );
 
        FUNCTION
              a80is_operator_join(
                    VAR acv         : tak_all_command_glob;
                    VAR dmli        : tak_dml_info) : boolean;
 
.CM *-END-* define --------------------------------------
***********************************************************
 
Use     :
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01sysnullkey          : tgg00_SysInfoKey;
              a01_il_b_identifier    : tsp00_KnlIdentifier;
 
        PROCEDURE
              a01_next_symbol (VAR acv : tak_all_command_glob);
 
        PROCEDURE
              a01_call_put (
                    VAR acv  : tak_all_command_glob;
                    proc     : tak_procs;
                    subproc  : tsp00_Int2;
                    VAR curr_n : tsp00_Int2);
 
        PROCEDURE
              a01_put_node (
                    VAR acv    : tak_all_command_glob;
                    VAR curr_n : tsp00_Int2);
 
        FUNCTION
              a01_eqkey (
                    VAR a      : tak_keyword;
                    sqlmode    : tsp00_SqlMode;
                    VAR b      : tsp00_MoveObj;
                    VAR scv    : tak_scanner_glob) : boolean;
 
      ------------------------------ 
 
        FROM
              AK_semantic_scanner_tools : VAK05;
 
        PROCEDURE
              a05_identifier_get (
                    VAR acv     : tak_all_command_glob;
                    tree_index  : integer;
                    obj_len     : integer;
                    VAR moveobj : tsp00_KnlIdentifier);
 
        PROCEDURE
              a05_int4_unsigned_get (
                    VAR acv            : tak_all_command_glob;
                    pos                : integer;
                    l                  : tsp00_Int2;
                    VAR val            : tsp00_Int4);
 
      ------------------------------ 
 
        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;
                    get_all      : boolean;
                    VAR ok       : boolean);
 
      ------------------------------ 
 
        FROM
              Systeminfo_cache : VAK10;
 
        PROCEDURE
              a10_nil_get_sysinfo (
                    VAR acv      : tak_all_command_glob;
                    VAR syskey   : tgg00_SysInfoKey;
                    dstate       : tak_directory_state;
                    syslen       : tsp00_Int4;
                    VAR syspoint : tak_sysbufferaddress;
                    VAR b_err    : tgg00_BasisError);
 
        PROCEDURE
              a10add_sysinfo (
                    VAR acv      : tak_all_command_glob;
                    VAR syspoint : tak_sysbufferaddress;
                    VAR b_err    : tgg00_BasisError);
 
        PROCEDURE
              a10del_sysinfo (
                    VAR acv     : tak_all_command_glob;
                    VAR syskey  : tgg00_SysInfoKey;
                    VAR b_err   : tgg00_BasisError);
 
        PROCEDURE
              a10rel_sysinfo (syspointer : tak_sysbufferaddress);
 
        PROCEDURE
              a10get_sysinfo (
                    VAR acv      : tak_all_command_glob;
                    VAR syskey   : tgg00_SysInfoKey;
                    dstate       : tak_directory_state;
                    VAR syspoint : tak_sysbufferaddress;
                    VAR b_err    : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              AK_Index : VAK24;
 
        PROCEDURE
              a24find_indexname (
                    VAR acv            : tak_all_command_glob;
                    VAR tabid          : tgg00_Surrogate;
                    VAR indexname      : tsp00_KnlIdentifier;
                    VAR index_scan_rec : tak_index_scan_record);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              hint_trace_routines : VAK81;
 
        PROCEDURE
              a81debug_access_config (
                    debug       : tgg00_Debug;
                    VAR config  : tak00_access_configuration);
 
        PROCEDURE
              a81debug_join_config (
                    debug       : tgg00_Debug;
                    VAR config  : tak00_join_configuration_arr;
                    cnt         : tsp00_Int2);
&       endif
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              gg01_operator_join            : boolean;
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalForcedMove (
                    size1    : tsp00_Int4;
                    size2    : tsp00_Int4;
                    val1     : tsp00_MoveObjPtr;
                    p1       : tsp00_Int4;
                    val2     : tsp00_MoveObjPtr;
                    p2       : tsp00_Int4;
                    cnt      : tsp00_Int4);
&       IFDEF TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01knl_identifier (
                    debug      : tgg00_Debug;
                    nam        : tsp00_Sname;
                    identifier : tsp00_KnlIdentifier);
 
        PROCEDURE
              t01execution_kind (
                    debug     : tgg00_Debug;
                    nam       : tsp00_Sname;
                    ex_kind   : tak_execution_kind);
 
        PROCEDURE
              t01name (
                    debug : tgg00_Debug;
                    nam   : tsp00_Name);
 
        PROCEDURE
              t01sname (
                    debug : tgg00_Debug;
                    nam : tsp00_Sname);
 
        PROCEDURE
              t01int4 (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01bool (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    curr_bool: boolean);
 
        PROCEDURE
              t01basis_error (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname;
                    b_err : tgg00_BasisError);
 
        PROCEDURE
              t01set_bool_debug_or_trace;
 
        PROCEDURE
              t01disable_debug_or_trace;
&       ENDIF
 
.CM *-END-* use -----------------------------------------
***********************************************************
 
Synonym :
 
        PROCEDURE
              a05_identifier_get;
 
              tsp00_MoveObj tsp00_KnlIdentifier
 
.CM *-END-* synonym -------------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
TYPE
      t_hint = ( common_hint, join_hint, join_access_hint );
 
 
(*------------------------------*) 
 
PROCEDURE
      a80_ahint_statement (
            VAR acv              : tak_all_command_glob;
            subproc              : tsp00_Int2;
            expected_select_node : tsp00_Int2);
 
VAR
      _hint_n            : tsp00_Int2;
      _last_n            : tsp00_Int2;
      _first_n           : tsp00_Int2;
      _last_a_scv_index  : tsp00_Int2;
      _hint_syn_ok       : boolean;
      _first_hint        : boolean;
 
BEGIN
&ifdef trace
t01int4( ak_sem, 'exp sel node', expected_select_node );
&endif
_last_a_scv_index := acv.a_scv_index;
_first_n          := 0;
a01_call_put( acv, a80, subproc, _hint_n );
(* use n_pos as node number of node for which hints are ! *)
acv.a_ap_tree^[ _hint_n ].n_pos := expected_select_node;
(* tie new hint node *)
IF  ( acv.a_first_hint_node = csp_minint2 )
THEN
    (* this is the first hint node *)
    BEGIN
    _first_hint           := true;
    acv.a_first_hint_node := _hint_n;
    END
ELSE
    (* another hint node exists, tie this node *)
    BEGIN
    _first_hint := false;
    _last_n     := acv.a_first_hint_node;
    WHILE ( acv.a_ap_tree^[ _last_n ].n_sa_level <> 0 ) DO
        _last_n := acv.a_ap_tree^[ _last_n ].n_sa_level;
    (*ENDWHILE*) 
    acv.a_ap_tree^[ _last_n ].n_sa_level := _hint_n;
    END;
(*ENDIF*) 
a01_next_symbol( acv );
(* scan comma seperated hint list *)
ak80access_hint_list( acv, _hint_n, false, _hint_syn_ok );
;
IF  ( NOT _hint_syn_ok )
THEN
    BEGIN
    IF  ( _first_hint )
    THEN
        acv.a_first_hint_node := csp_minint2;
    (*ENDIF*) 
    acv.a_scv_index       := _last_a_scv_index;
    END;
(*ENDIF*) 
a01_next_symbol( acv );
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak80access_hint_list(
            VAR acv         : tak_all_command_glob;
            first_n         : tsp00_Int2;
            join_embeded    : boolean;
            VAR hint_syn_ok : boolean);
 
VAR
      _last_scv          : tak_scanner_glob;
      _tmp_scv           : tak_scanner_glob;
      _last_n            : tsp00_Int2;
      _first_loc_n       : tsp00_Int2;
      _tmp_n             : tsp00_Int2;
      _keyword           : tak_keyword;
      _restore_scv       : boolean;
      _hint_missing      : boolean;
 
BEGIN
hint_syn_ok := true;
_last_scv   := acv.a_scv;
_last_n     := first_n;
&ifdef trace
t01int4( ak_syn, 'first_n     ', first_n );
t01bool( ak_syn, 'embeded list', join_embeded);
&endif
WHILE ( NOT
      (( NOT join_embeded AND
      ( _last_scv.sc_symb = s_asterisk ) AND ( acv.a_scv.sc_symb = s_divide ))
      OR
      ( join_embeded AND ( acv.a_scv.sc_symb in [ s_rightpar, s_semicolon ] )))
      AND
      ( acv.a_scv.sc_symb <> s_eof )
      AND
      hint_syn_ok ) DO
    (* stop at '*/' or ')' or EOF *)
    BEGIN
&   ifdef trace
    t01name( ak_syn, 'search next ahint ' );
&   endif
    _hint_missing := true;
    IF  ( _hint_missing ) AND ( NOT join_embeded )
    THEN
        BEGIN
        _keyword := 'JOIN              ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            (* 'JOIN[(<hint>)]' *)
            a01_call_put( acv, a80, cak_x_join_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'JOIN        ' );
&           endif
            _restore_scv := true;
            _tmp_scv     := acv.a_scv;
            a01_next_symbol( acv );
            IF  ( acv.a_scv.sc_symb = s_leftpar )
            THEN
                BEGIN
                a01_next_symbol( acv );
                ak80join_hint_list( acv, _first_loc_n, hint_syn_ok );
                IF  ( acv.a_scv.sc_symb = s_rightpar )
                THEN
                    _restore_scv := false
                ELSE
                    BEGIN
&                   ifdef trace
                    t01int4( ak_syn, 'wrong syntax', 1 );
&                   endif
                    hint_syn_ok:= false;
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  ( _restore_scv )
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_syn, 'restore scv ' );
&               endif
                acv.a_scv := _tmp_scv;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'KEYACCESS         ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_keyaccess_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'KEYACCESS   ' );
&           endif
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'INDEXACCESS       ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            (* 'INDEXACCESS[(INDEXNAME)]' *)
            a01_call_put( acv, a80, cak_x_indexaccess_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'INDEXACCESS ' );
&           endif
            _restore_scv := true;
            _tmp_scv     := acv.a_scv;
            a01_next_symbol( acv );
            IF  ( acv.a_scv.sc_symb = s_leftpar )
            THEN
                BEGIN
                a01_next_symbol( acv );
                IF  ( acv.a_scv.sc_symb = s_identifier )
                THEN
                    BEGIN
                    a01_put_node( acv, _tmp_n );
&                   ifdef trace
                    t01int4( ak_syn, '_tmp_n      ', _tmp_n );
&                   endif
                    a01_next_symbol( acv );
                    IF  ( acv.a_scv.sc_symb = s_rightpar )
                    THEN
                        (* tie index name node *)
                        BEGIN
                        acv.a_ap_tree^[ _first_loc_n ].n_sa_level := _tmp_n;
                        _restore_scv := false;
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
&                   ifdef trace
                    t01int4( ak_syn, 'wrong syntax', 3 );
&                   endif
                    hint_syn_ok := false;
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  ( _restore_scv )
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_syn, 'restore scv ' );
&               endif
                acv.a_scv := _tmp_scv;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'KEYSCAN           ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_keyscan_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'KEYSCAN     ' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'KEYRANGE          ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_keyrange_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'KEYRANGE    ' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'INDEXSCAN         ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_indexscan_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'INDEXSCAN   ' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'INDEXRANGE        ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_indexrange_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'INDEXRANGE  ' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'BUILDRESULT       ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_buildresult_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'BUILTRESULT ' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'FETCHRESULT       ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_fetchresult_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'FETCHRESULT ' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'ENABLE_MERGE      ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_enablemerge_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'ENABLEMERGE ' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'DISABLE_INVONLY   ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_disableinvonly_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'DISABLE_INVO' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    ;
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'TRACE             ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_trace_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'TRACE       ' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'L1_STRATEGY       ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_L1_strat_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'L1_STRATEGY ' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'L2_STRATEGY       ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_L2_strat_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'L2_STRATEGY ' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'L2_RANGE_STRATEGY ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_L2_range_strat_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'L2_RANGE_STR' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'L2_MORE_STRATEGIES';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_L2_more_strat_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'L2_MORE_STRA' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'L2_STRAT_NO_OPTIM ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_L2_strat_no_optim_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'L2_STR_NO_OP' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'IN_STRATEGY       ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_in_strat_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'IN_STRATEGY ' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'SUBQ_STRATEGY     ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_subq_strat_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'SUBQ_STRAT  ' );
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'ORDERED           ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_ordered_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'ORDERED     ' );
&           endif
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'COORDINATOR_JOIN  ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_coordinator_join_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'COORD_JOIN  ' );
&           endif
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'OPERATOR_JOIN     ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_operator_join_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'OPEERAT_JOIN' );
&           endif
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'PRETEND_PARAMETER ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_pretend_param_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'PRETEND_PARA' );
&           endif
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'SHORT_SUM_VALUES  ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            acv.a_sql_cmd_state :=
                  acv.a_sql_cmd_state + [ csa_short_sum_values ];
&           ifdef trace
            t01sname( ak_syn, 'SUM_VALUES  ' );
&           endif
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'HASHRATIO         ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            (* 'HASHRATION(<unsigned integer>)' *)
            a01_call_put( acv, a80, cak_x_hashratio_hint, _first_loc_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'HASH RATIO  ' );
&           endif
            _restore_scv := true;
            _tmp_scv     := acv.a_scv;
            a01_next_symbol( acv );
            IF  ( acv.a_scv.sc_symb = s_leftpar )
            THEN
                BEGIN
                a01_next_symbol( acv );
                IF  ( acv.a_scv.sc_symb = s_unsigned_integer )
                THEN
                    BEGIN
                    a01_put_node( acv, _tmp_n );
                    a01_next_symbol( acv );
                    IF  ( acv.a_scv.sc_symb = s_rightpar )
                    THEN
                        (* tie server count node *)
                        BEGIN
                        acv.a_ap_tree^[ _first_loc_n ].n_sa_level := _tmp_n;
                        _restore_scv   := false;
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
&                   ifdef trace
                    t01int4( ak_syn, 'wrong syntax', 6 );
&                   endif
                    hint_syn_ok := false;
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  ( _restore_scv )
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_syn, 'restore scv ' );
&               endif
                acv.a_scv := _tmp_scv;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'QUERYREWRITE_NO   ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            acv.a_queryrewrite_mode := No_Rewrite;
&           ifdef trace
            t01sname( ak_syn, 'QRW NO      ' );
&           endif
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'QUERYREWRITE_STMT ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            acv.a_queryrewrite_mode := Statement_Rewrite;
&           ifdef trace
            t01sname( ak_syn, 'QRW STMT    ' );
&           endif
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'QUERYREWRITE_OP   ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            acv.a_queryrewrite_mode := Operator_Rewrite;
&           ifdef trace
            t01sname( ak_syn, 'QRW OPERATOR' );
&           endif
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    ;
    (* tie new hint node *)
    IF  ( NOT _hint_missing )
    THEN
        BEGIN
        acv.a_ap_tree^[ _last_n ].n_lo_level := _first_loc_n;
        _last_n                              := _first_loc_n;
        END;
    (*ENDIF*) 
    _last_scv := acv.a_scv;
    a01_next_symbol( acv );
    IF  ( acv.a_scv.sc_symb = s_comma )
    THEN
        a01_next_symbol( acv );
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
IF  ( hint_syn_ok AND
    (( join_embeded AND NOT ( acv.a_scv.sc_symb in [ s_rightpar, s_semicolon ]))
    OR
    ( NOT join_embeded AND
    NOT (( _last_scv.sc_symb = s_asterisk ) AND ( acv.a_scv.sc_symb = s_divide )))
    ))
THEN
    BEGIN
&   ifdef trace
    t01int4( ak_syn, 'wrong syntax', 4 );
&   endif
    hint_syn_ok := false;
    END;
(*ENDIF*) 
IF  ( join_embeded AND ( acv.a_scv.sc_symb = s_semicolon ))
THEN
    BEGIN
&   ifdef trace
    t01name( ak_syn, 'reset to semicolon' );
&   endif
    acv.a_scv := _last_scv;
    END;
(*ENDIF*) 
;
&ifdef trace
t01bool( ak_syn, 'hint syn ok ', hint_syn_ok );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak80join_hint_list(
            VAR acv         : tak_all_command_glob;
            first_n         : tsp00_Int2;
            VAR hint_syn_ok : boolean);
 
VAR
      _tmp_scv           : tak_scanner_glob;
      _keyword           : tak_keyword;
      _last_n            : tsp00_Int2;
      _last_list_n       : tsp00_Int2;
      _tmp_n             : tsp00_Int2;
      _curr_n            : tsp00_Int2;
      _hint_missing      : boolean;
      _restore_scv       : boolean;
      _put_new_list      : boolean;
      _skip_rightpar     : boolean;
 
BEGIN
hint_syn_ok   := true;
_put_new_list := true;
_last_list_n  := first_n;
(* loop over semicolon seperated list *)
WHILE hint_syn_ok AND
      NOT (
      ( acv.a_scv.sc_symb = s_rightpar ) OR
      ( acv.a_scv.sc_symb = s_eof )) DO
    BEGIN
&   ifdef trace
    t01name( ak_syn, 'search next jhint ' );
&   endif
    _hint_missing := true;
    _skip_rightpar:= false;
    ;
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'KEYACCESS         ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_keyaccess_hint, _curr_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'KEYACCESS   ' );
&           endif
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'INDEXACCESS       ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            (* 'INDEXACCESS[(INDEXNAME)]' *)
            a01_call_put( acv, a80, cak_x_indexaccess_hint, _curr_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'INDEXACCESS ' );
&           endif
            _restore_scv := true;
            _tmp_scv     := acv.a_scv;
            a01_next_symbol( acv );
            IF  ( acv.a_scv.sc_symb = s_leftpar )
            THEN
                BEGIN
                a01_next_symbol( acv );
                IF  ( acv.a_scv.sc_symb = s_identifier )
                THEN
                    BEGIN
                    a01_put_node( acv, _tmp_n );
                    a01_next_symbol( acv );
                    IF  ( acv.a_scv.sc_symb = s_rightpar )
                    THEN
                        (* tie index name node *)
                        BEGIN
                        acv.a_ap_tree^[ _curr_n ].n_sa_level := _tmp_n;
                        _restore_scv   := false;
                        _skip_rightpar := true;
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
&                   ifdef trace
                    t01int4( ak_syn, 'wrong syntax', 5 );
&                   endif
                    hint_syn_ok := false;
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  ( _restore_scv )
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_syn, 'restore scv ' );
&               endif
                acv.a_scv := _tmp_scv;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'NOACCESSPATH      ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_nopath_hint, _curr_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'NOACCESSPATH' );
&           endif
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'ACCESS            ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            a01_call_put( acv, a80, cak_x_access_hint, _curr_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'ACCESS      ' );
&           endif
            _restore_scv := true;
            _tmp_scv     := acv.a_scv;
            a01_next_symbol( acv );
            IF  ( acv.a_scv.sc_symb = s_equal )
            THEN
                BEGIN
                ak80access_hint_list( acv, _curr_n, true, hint_syn_ok );
                _restore_scv := false;
                END;
            (*ENDIF*) 
            IF  ( _restore_scv )
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_syn, 'restore scv ' );
&               endif
                acv.a_scv := _tmp_scv;
                END;
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'BUFFERSIZE        ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            (* 'BUFFERSIZE(<unsigned integer>)' *)
            a01_call_put( acv, a80, cak_x_buffersize_hint, _curr_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'BUFFERSIZE  ' );
&           endif
            _restore_scv := true;
            _tmp_scv     := acv.a_scv;
            a01_next_symbol( acv );
            IF  ( acv.a_scv.sc_symb = s_leftpar )
            THEN
                BEGIN
                a01_next_symbol( acv );
                IF  ( acv.a_scv.sc_symb = s_unsigned_integer )
                THEN
                    BEGIN
                    a01_put_node( acv, _tmp_n );
                    a01_next_symbol( acv );
                    IF  ( acv.a_scv.sc_symb = s_rightpar )
                    THEN
                        (* tie buffer size node *)
                        BEGIN
                        acv.a_ap_tree^[ _curr_n ].n_sa_level := _tmp_n;
                        _restore_scv   := false;
                        _skip_rightpar := true;
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
&                   ifdef trace
                    t01int4( ak_syn, 'wrong syntax', 6 );
&                   endif
                    hint_syn_ok := false;
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  ( _restore_scv )
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_syn, 'restore scv ' );
&               endif
                acv.a_scv := _tmp_scv;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _hint_missing )
    THEN
        BEGIN
        _keyword := 'PARALLEL_SERVER   ';
        IF  a01_eqkey( _keyword, acv.a_sqlmode,
            acv.a_cmd_part^.sp1p_buf, acv.a_scv )
        THEN
            BEGIN
            (* 'PARALLEL_SERVER(<unsigned integer>)' *)
            a01_call_put( acv, a80, cak_x_parallel_serv_hint, _curr_n );
            _hint_missing := false;
&           ifdef trace
            t01sname( ak_syn, 'PARALL SERV ' );
&           endif
            _restore_scv := true;
            _tmp_scv     := acv.a_scv;
            a01_next_symbol( acv );
            IF  ( acv.a_scv.sc_symb = s_leftpar )
            THEN
                BEGIN
                a01_next_symbol( acv );
                IF  ( acv.a_scv.sc_symb = s_unsigned_integer )
                THEN
                    BEGIN
                    a01_put_node( acv, _tmp_n );
                    a01_next_symbol( acv );
                    IF  ( acv.a_scv.sc_symb = s_rightpar )
                    THEN
                        (* tie server count node *)
                        BEGIN
                        acv.a_ap_tree^[ _curr_n ].n_sa_level := _tmp_n;
                        _restore_scv   := false;
                        _skip_rightpar := true;
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
&                   ifdef trace
                    t01int4( ak_syn, 'wrong syntax', 6 );
&                   endif
                    hint_syn_ok := false;
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  ( _restore_scv )
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_syn, 'restore scv ' );
&               endif
                acv.a_scv := _tmp_scv;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (( NOT _hint_missing ) AND hint_syn_ok )
    THEN
        BEGIN
        IF  ( _put_new_list )
        THEN
            BEGIN
&           ifdef trace
            t01sname( ak_syn, 'tie new list' );
&           endif
            (* tie new hint list on same level *)
            a01_call_put( acv, a80, cak_x_join_hint, _tmp_n );
            acv.a_ap_tree^[ _last_list_n ].n_sa_level := _tmp_n;
            acv.a_ap_tree^[ _tmp_n ].n_lo_level       := _curr_n;
            _last_list_n                              := _tmp_n;
            _last_n                                   := _curr_n
            END
        ELSE
            BEGIN
&           ifdef trace
            t01name( ak_syn, 'tie same list     ' );
&           endif
            (* tie new hint list on low level *)
            acv.a_ap_tree^[ _last_n ].n_lo_level := _curr_n;
            _last_n                              := _curr_n;
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    ;
    IF  (( acv.a_scv.sc_symb = s_semicolon ) AND _hint_missing )
    THEN
        (* empty list detected *)
        BEGIN
&       ifdef trace
        t01sname( ak_syn, 'empty list  ' );
&       endif
        a01_call_put( acv, a80, cak_x_join_hint, _curr_n );
        acv.a_ap_tree^[ _last_list_n ].n_sa_level := _curr_n;
        _last_list_n                              := _curr_n;
        _last_n                                   := _curr_n
        END;
    (*ENDIF*) 
    IF  (( acv.a_scv.sc_symb <> s_rightpar ) OR _skip_rightpar )
    THEN
        BEGIN
        a01_next_symbol( acv );
        IF  ( acv.a_scv.sc_symb = s_comma )
        THEN
            BEGIN
            a01_next_symbol( acv );
            IF  ( NOT _hint_missing )
            THEN
                _put_new_list := false;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            IF  (( acv.a_scv.sc_symb = s_semicolon ) AND NOT _hint_missing )
            THEN
                BEGIN
                a01_next_symbol( acv );
                _put_new_list := true;
                END
            ELSE
                IF  (( acv.a_scv.sc_symb = s_rightpar ) AND _hint_missing )
                THEN
                    (* last empty list detected*)
                    BEGIN
                    a01_call_put( acv, a80, cak_x_join_hint, _curr_n );
                    acv.a_ap_tree^[ _last_list_n ].n_sa_level := _curr_n;
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
IF  ( acv.a_scv.sc_symb <> s_rightpar )
THEN
    BEGIN
&   ifdef trace
    t01int4( ak_syn, 'wrong syntax', 7 );
&   endif
    hint_syn_ok := false;
    END;
&ifdef trace
(*ENDIF*) 
t01bool( ak_syn, 'hint syn ok ', hint_syn_ok );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      a80store_cmd_hint_info(
            VAR acv     : tak_all_command_glob;
            VAR dmli    : tak_dml_info;
            select_node : tsp00_Int4);
 
VAR
      _curr_n     : tsp00_Int2;
      _ke         : tgg00_SysInfoKey;
      _hint       : tak_sysbufferaddress;
      _b_err      : tgg00_BasisError;
      _hint_found : boolean;
      _compile_ok : boolean;
 
BEGIN
IF  ( acv.a_first_hint_node <> csp_minint2 )
THEN
    BEGIN
&   ifdef trace
    t01int4( ak_syn, 'first_hint_n', acv.a_first_hint_node );
    t01int4( ak_syn, 'select node ', select_node );
&   endif
    ak80search_snode( acv.a_ap_tree^, select_node, acv.a_scv_index );
    (* we store hint information by means of parskey      *)
    (* to class hints with any query specification we use *)
    (* subselect idendification from n_pos                *)
    _hint_found      := false;
    ak80build_hint_key( acv, _ke );
    _curr_n := acv.a_first_hint_node;
    REPEAT
        (* look for hint node of actual command *)
        IF  ( acv.a_ap_tree^[ _curr_n ].n_pos = select_node )
        THEN
            BEGIN
            _hint_found := true;
            a10_nil_get_sysinfo( acv, _ke, d_fix,
                  sizeof( tak_hintrecord ), _hint, _b_err );
            IF  ( _b_err = e_ok )
            THEN
                BEGIN
                _hint^.shint.hint_joincfg_cnt := 0;
                _hint^.shint.hint_common_config.cfg_indexno  := 0;
                _hint^.shint.hint_common_config.cfg_switches := [];
                _compile_ok := true;
                ak80compile_hint_info( acv, dmli, _hint^.shint,
                      _curr_n, common_hint, 1, _compile_ok );
                IF  ( _compile_ok )
                THEN
                    BEGIN
                    a10add_sysinfo( acv, _hint, _b_err );
                    END
                ELSE
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'comp failed ' );
&                   endif
                    END;
                (*ENDIF*) 
                IF  (( _b_err <> e_ok ) OR ( NOT _compile_ok ))
                THEN
                    BEGIN
&                   ifdef trace
                    t01basis_error( ak_sem, 'add failed  ', _b_err );
&                   endif
                    a10del_sysinfo( acv, _ke, _b_err );
                    END
                ELSE
                    BEGIN
                    acv.a_sql_cmd_state :=
                          acv.a_sql_cmd_state + [ csa_hint_exist ];
                    IF  ( acv.a_ex_kind = only_parsing ) AND
                        ( dmli.d_sparr.pparsp <> NIL )
                    THEN
                        BEGIN
                        dmli.d_sparr.pparsp^.sparsinfo.p_bool_states :=
                              dmli.d_sparr.pparsp^.sparsinfo.p_bool_states +
                              [ pi_hint_exist ];
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                a10rel_sysinfo( _hint );
                END
            ELSE
                BEGIN
&               ifdef trace
                t01basis_error( ak_sem, 'new failed  ', _b_err );
&               endif
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        ;
        (* step to next hint *)
        _curr_n := acv.a_ap_tree^[ _curr_n ].n_sa_level;
    UNTIL
        (( _curr_n = 0 ) OR _hint_found );
    (*ENDREPEAT*) 
&   ifdef trace
    IF  ( NOT _hint_found )
    THEN
        t01name( ak_syn, 'no approp. hint   ' );
&   endif
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a80drop_all_hint_info( VAR acv : tak_all_command_glob );
 
VAR
      _ke           : tgg00_SysInfoKey;
      _parskey      : tak_parskey;
      _curr_n       : tsp00_Int2;
      _aux_return   : tsp00_Int2;
      _aux_errorpos : tsp00_Int4;
      _b_err        : tgg00_BasisError;
 
      _cast         : RECORD
            CASE boolean OF
                true :
                    (c2   : tsp00_C2);
                false :
                    (int2 : tsp00_Int2);
                END;
            (*ENDCASE*) 
 
 
BEGIN
IF  ( acv.a_first_hint_node <> csp_minint2 ) AND
    ( acv.a_init_ex_kind in [ parsing_executing, only_syntax ] )
THEN
    BEGIN
    _aux_return        := acv.a_returncode;
    _aux_errorpos      := acv.a_errorpos;
    acv.a_returncode   := 0;
    _ke                := a01sysnullkey;
    _ke.sentrytyp      := cak_ehint;
    _ke.sauthid[ 1 ]   := cak_tempinfo_byte;
    _parskey           := acv.a_pars_last_key;
    _parskey.p_id[ 1 ] := acv.a_first_parskey;
    SAPDB_PascalForcedMove( sizeof( _parskey ), sizeof( _ke.sauthid ),
          @_parskey, 1, @_ke.sauthid, 2, mxak_parskey );
    _curr_n    := acv.a_first_hint_node;
    _cast.int2 := 0;
    (* walk through all hint nodes and drop information *)
    REPEAT
        _ke.slinkage := _cast.c2;
        a10del_sysinfo( acv, _ke, _b_err );
&       ifdef trace
        IF  ( _b_err <> e_ok )
        THEN
            t01basis_error( ak_sem, 'drop failed ', _b_err );
&       endif
        (*ENDIF*) 
        ;
        (* step to next hint *)
        _curr_n := acv.a_ap_tree^[ _curr_n ].n_sa_level;
        _cast.int2 := succ( _cast.int2 );
    UNTIL
        ( _curr_n = 0 );
    (*ENDREPEAT*) 
    ;
    (* SELECT statements start with a_cmd_id with '1', not with '0' *)
    _ke.slinkage := _cast.c2;
    a10del_sysinfo( acv, _ke, _b_err );
    acv.a_returncode := _aux_return;
    acv.a_errorpos   := _aux_errorpos;
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak80build_hint_key(
            VAR acv     : tak_all_command_glob;
            VAR ke      : tgg00_SysInfoKey);
 
VAR
      _parskey   : tak_parskey;
 
      _cast         : RECORD
            CASE boolean OF
                true :
                    (c2   : tsp00_C2);
                false :
                    (int2 : tsp00_Int2);
                END;
            (*ENDCASE*) 
 
 
BEGIN
ke                := a01sysnullkey;
ke.sentrytyp      := cak_ehint;
ke.sauthid[ 1 ]   := cak_tempinfo_byte;
_parskey          := acv.a_pars_last_key;
_parskey.p_id[ 1 ]:= acv.a_first_parskey;
SAPDB_PascalForcedMove( sizeof( _parskey ), sizeof( ke.sauthid ),
      @_parskey, 1, @ke.sauthid, 2, mxak_parskey );
_cast.int2 := acv.a_cmd_id;
ke.slinkage := _cast.c2;
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak80build_hint_key_exec(
            VAR acv     : tak_all_command_glob;
            VAR parskey : tak_parskey;
            VAR ke      : tgg00_SysInfoKey);
 
VAR
 
      _cast         : RECORD
            CASE boolean OF
                true :
                    (c2   : tsp00_C2);
                false :
                    (int2 : tsp00_Int2);
                END;
            (*ENDCASE*) 
 
 
BEGIN
ke                := a01sysnullkey;
ke.sentrytyp      := cak_ehint;
ke.sauthid[ 1 ]   := cak_tempinfo_byte;
SAPDB_PascalForcedMove( sizeof( parskey ), sizeof( ke.sauthid ),
      @parskey, 1, @ke.sauthid, 2, mxak_parskey );
_cast.int2 := acv.a_cmd_id;
ke.slinkage := _cast.c2;
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak80compile_hint_info(
            VAR acv         : tak_all_command_glob;
            VAR dmli        : tak_dml_info;
            VAR hint        : tak_hintrecord;
            hint_n          : tsp00_Int2;
            hint_type       : t_hint;
            tabno           : tsp00_Int2;
            VAR is_ok       : boolean);
 
VAR
      _indexname        : tsp00_KnlIdentifier;
      _tabid            : tgg00_Surrogate;
      _index_scan_rec   : tak_index_scan_record;
      _tabinfo          : tak_sysbufferaddress;
      _i, _j            : tsp00_Int4;
      _curr_n           : tsp00_Int2;
      _indexno          : tsp00_Int2;
      _access_switch    : tak00_access_config_switch;
      _aux_err          : tgg00_BasisError;
      _put_switch       : boolean;
      _put_index        : boolean;
      _loop             : boolean;
      _ok               : boolean;
 
BEGIN
&ifdef trace
IF  ( hint_type = common_hint )
THEN
    t01sname( ak_sem, 'common hint ' )
ELSE
    IF  ( hint_type = join_hint )
    THEN
        t01sname( ak_sem, 'join hint   ' )
    ELSE
        IF  ( hint_type = join_access_hint )
        THEN
            t01sname( ak_sem, 'join acc hin' )
        ELSE
            BEGIN
            t01int4( ak_sem, '! unkown !  ', ord(hint_type) );
            END;
        (*ENDIF*) 
    (*ENDIF*) 
(*ENDIF*) 
t01int4( ak_sem, 'hint node   ', hint_n );
t01int4( ak_sem, 'tabno       ', tabno );
t01int4( ak_sem, 'd_cntfromtab', dmli.d_cntfromtab );
&endif
IF  ( hint_type = common_hint )
THEN
    (* root entrance *)
    is_ok := true;
(*ENDIF*) 
IF  (( tabno <= dmli.d_cntfromtab ) )
THEN
    BEGIN
    IF  ( dmli.d_tabarr^[ tabno ].oview ) AND
        (* for views we haven't a fullfilled d_tabarr[] *)
        ( hint_type <> common_hint )
    THEN
        BEGIN
        is_ok := false;
        END
    ELSE
        BEGIN
        _loop := true;
        IF  ( hint_type = common_hint )
        THEN
            BEGIN
            hint.hint_common_config.cfg_indexno  := 0;
            hint.hint_common_config.cfg_switches := [];
            END
        ELSE
            IF  ( hint_type = join_hint )
            THEN
                BEGIN
                IF  ( hint.hint_joincfg_cnt < dmli.d_cntfromtab )
                THEN
                    BEGIN
                    hint.hint_joincfg_cnt := succ(hint.hint_joincfg_cnt);
                    hint.hint_join_config[hint.hint_joincfg_cnt].cfg_indexno := 0;
                    hint.hint_join_config[hint.hint_joincfg_cnt].cfg_bufsize := 0;
                    hint.hint_join_config[hint.hint_joincfg_cnt].cfg_parallel_server := cak_is_undefined;
                    hint.hint_join_config[hint.hint_joincfg_cnt].cfg_join_switches   := [];
                    hint.hint_join_config[hint.hint_joincfg_cnt].cfg_access_switches := [];
                    END
                ELSE
                    _loop := false;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        WHILE ( acv.a_ap_tree^[ hint_n ].n_lo_level <> 0 ) AND _loop DO
            BEGIN
            _put_switch := false;
            _put_index  := false;
            hint_n := acv.a_ap_tree^[ hint_n ].n_lo_level;
            CASE  acv.a_ap_tree^[ hint_n ].n_subproc OF
                (* enumerate access hints *)
                cak_x_join_hint      :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'JOIN        ' );
&                   endif
                    IF  (( hint_type = common_hint ) AND
                        ( dmli.d_cntfromtab > 1 ))
                    THEN
                        BEGIN
                        _curr_n := hint_n;
                        _i      := tabno;
                        WHILE ( acv.a_ap_tree^[ _curr_n ].n_sa_level <> 0 ) DO
                            BEGIN
                            _curr_n := acv.a_ap_tree^[ _curr_n ].n_sa_level;
                            (* process one access hint list *)
                            ak80compile_hint_info( acv, dmli, hint,
                                  _curr_n, join_hint, _i, is_ok );
                            _i := succ(_i);
                            END;
                        (*ENDWHILE*) 
                        END;
                    (*ENDIF*) 
                    END;
                cak_x_access_hint      :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'ACCESS      ' );
&                   endif
                    IF  ( hint_type = join_hint )
                    THEN
                        BEGIN
                        IF  ( acv.a_ap_tree^[ hint_n ].n_lo_level <> 0 )
                        THEN
                            BEGIN
                            ak80compile_hint_info( acv, dmli, hint,
                                  hint_n, join_access_hint, tabno, is_ok );
                            _loop := false;
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                cak_x_nopath_hint    :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'NOACCESSPATH' );
&                   endif
                    IF  ( hint_type = join_hint )
                    THEN
                        BEGIN
                        IF  ( NOT ( cj_indexaccess in
                            hint.hint_join_config[ hint.hint_joincfg_cnt ].
                            cfg_join_switches )) AND
                            ( NOT ( cj_keyaccess in
                            hint.hint_join_config[ hint.hint_joincfg_cnt ].
                            cfg_join_switches ))
                        THEN
                            hint.hint_join_config[ hint.hint_joincfg_cnt ].
                                  cfg_join_switches :=
                                  hint.hint_join_config[ hint.hint_joincfg_cnt ].
                                  cfg_join_switches + [ cj_noaccesspath ];
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                cak_x_keyaccess_hint    :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'KEYACCESS   ' );
&                   endif
                    IF  ( hint_type = join_hint )
                    THEN
                        BEGIN
                        IF  ( NOT ( cj_indexaccess in
                            hint.hint_join_config[ hint.hint_joincfg_cnt ].
                            cfg_join_switches ))
                        THEN
                            hint.hint_join_config[ hint.hint_joincfg_cnt ].
                                  cfg_join_switches :=
                                  hint.hint_join_config[ hint.hint_joincfg_cnt ].
                                  cfg_join_switches + [ cj_keyaccess ];
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        _put_switch    := true;
                        _access_switch := cs_keyaccess;
                        END;
                    (*ENDIF*) 
                    END;
                cak_x_indexaccess_hint  :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'INDEXACCESS ' );
&                   endif
                    IF  ( hint_type = join_hint )
                    THEN
                        BEGIN
                        IF  ( NOT ( cj_keyaccess in
                            hint.hint_join_config[ hint.hint_joincfg_cnt ].
                            cfg_join_switches ))
                        THEN
                            hint.hint_join_config[ hint.hint_joincfg_cnt ].
                                  cfg_join_switches :=
                                  hint.hint_join_config[ hint.hint_joincfg_cnt ].
                                  cfg_join_switches + [ cj_indexaccess ];
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        _put_switch    := true;
                        _access_switch := cs_indexaccess;
                        END;
                    (*ENDIF*) 
                    ;
                    (* look for indexname *)
                    IF  ( acv.a_ap_tree^[ hint_n ].n_sa_level <> 0 )
                        AND
                        ( acv.a_ap_tree^[ acv.a_ap_tree^[ hint_n ].n_sa_level ].
                        n_symb = s_identifier  )
                    THEN
                        BEGIN
                        _indexname := a01_il_b_identifier;
                        a05_identifier_get( acv,
                              acv.a_ap_tree^[ hint_n ].n_sa_level,
                              acv.a_ap_tree^[ acv.a_ap_tree^[ hint_n ].
                              n_sa_level ].n_length, _indexname );
&                       ifdef trace
                        t01knl_identifier( ak_sem, 'indexname   ', _indexname );
                        t01disable_debug_or_trace;
&                       endif
                        _tabid := dmli.d_tabarr^[ tabno ].otreeid.fileTabId_gg00;
                        _index_scan_rec.isr_buf := NIL;
                        a06_systable_get( acv, d_release, _tabid, _tabinfo, false, _ok );
                        IF  ( _ok AND _tabinfo^.sbase.bindexexist )
                        THEN
                            a24find_indexname( acv, _tabid, _indexname, _index_scan_rec );
&                       ifdef trace
                        (*ENDIF*) 
                        t01set_bool_debug_or_trace;
&                       endif
                        IF  ( _index_scan_rec.isr_buf <> NIL )
                        THEN
                            BEGIN
                            _put_index := true;
                            _indexno   := _index_scan_rec.isr_buf^.smindex.
                                  indexdef[ _index_scan_rec.isr_index ].indexno;
                            END
                        ELSE
                            BEGIN
                            (* disable hint because of wrong index name *)
                            IF  ( hint_type = join_hint )
                            THEN
                                BEGIN
                                hint.hint_join_config[ hint.hint_joincfg_cnt ].
                                      cfg_join_switches :=
                                      hint.hint_join_config[ hint.hint_joincfg_cnt ].
                                      cfg_join_switches - [ cj_indexaccess ];
                                END
                            ELSE
                                _put_switch := false;
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                cak_x_buffersize_hint   :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'BUFFERSIZE  ' );
&                   endif
                    IF  ( hint_type = join_hint )
                    THEN
                        BEGIN
                        (* look for buffer size *)
                        IF  ( acv.a_ap_tree^[ hint_n ].n_sa_level <> 0 )
                            AND
                            ( acv.a_ap_tree^[ acv.a_ap_tree^[ hint_n ].n_sa_level ].
                            n_symb = s_unsigned_integer  )
                        THEN
                            BEGIN
                            _aux_err := acv.a_returncode;
                            acv.a_returncode := e_ok;
                            _curr_n := acv.a_ap_tree^[ hint_n ].n_sa_level;
                            a05_int4_unsigned_get( acv,
                                  acv.a_ap_tree^[ _curr_n ].n_pos,
                                  acv.a_ap_tree^[ _curr_n ].n_length,
                                  _i );
                            IF  ( acv.a_returncode <> e_invalid_unsign_integer )
                            THEN
                                BEGIN
                                hint.hint_join_config[ hint.hint_joincfg_cnt ].
                                      cfg_join_switches :=
                                      hint.hint_join_config[ hint.hint_joincfg_cnt ].
                                      cfg_join_switches + [ cj_predefined_buffer ];
                                hint.hint_join_config[ hint.hint_joincfg_cnt ].
                                      cfg_bufsize := _i;
                                END
                            ELSE
                                BEGIN
                                acv.a_returncode := _aux_err;
                                END;
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                cak_x_keyscan_hint      :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'KEYSCAN     ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_keyscan;
                    END;
                cak_x_keyrange_hint      :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'KEYRANGE    ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_keyrange;
                    END;
                cak_x_indexscan_hint    :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'INDEXSCAN   ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_indexscan;
                    END;
                cak_x_indexrange_hint    :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'INDEXRANGE  ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_indexrange;
                    END;
                cak_x_enablemerge_hint  :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'ENABLE MERGE' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_enable_merge;
                    END;
                cak_x_disableinvonly_hint:
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'DIS INVONLY ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_disable_inv_only;
                    END;
                cak_x_trace_hint        :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'TRACE       ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_trace;
                    END;
                cak_x_L1_strat_hint     :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'L1 STRAT    ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_L1_strategy;
                    END;
                cak_x_L2_strat_hint     :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'L2 STRAT    ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_L2_strategy;
                    END;
                cak_x_L2_more_strat_hint:
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'L2 MORE     ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_L2_more_strategies;
                    END;
                cak_x_L2_range_strat_hint:
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'L2 RANGE    ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_L2_range_strategy;
                    END;
                cak_x_L2_strat_no_optim_hint:
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'L2 NO OPTIM ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_L2_strat_no_optim;
                    END;
                cak_x_in_strat_hint     :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'IN STRAT    ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_IN_strategy;
                    END;
                cak_x_subq_strat_hint   :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'SUBQ STRAT  ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_SUBQ_strategy;
                    END;
                cak_x_buildresult_hint  :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'BUILDRESULT ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_build_result;
                    END;
                cak_x_fetchresult_hint  :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'FETCHRESULT ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_fetch_result;
                    END;
                cak_x_ordered_hint      :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'ORDERED     ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_ordered_join;
                    END;
                cak_x_coordinator_join_hint      :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'COORD. JOIN ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_coordinator_join;
                    END;
                cak_x_operator_join_hint      :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'OPERAT. JOIN' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_operator_join;
                    END;
                cak_x_pretend_param_hint      :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'PRETEND_PARA' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_pretend_parameter;
                    END;
                cak_x_parallel_serv_hint   :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'PARALL SERV ' );
&                   endif
                    IF  ( hint_type = join_hint )
                    THEN
                        BEGIN
                        (* look for server count *)
                        IF  ( acv.a_ap_tree^[ hint_n ].n_sa_level <> 0 )
                            AND
                            ( acv.a_ap_tree^[ acv.a_ap_tree^[ hint_n ].n_sa_level ].
                            n_symb = s_unsigned_integer  )
                        THEN
                            BEGIN
                            _aux_err := acv.a_returncode;
                            acv.a_returncode := e_ok;
                            _curr_n := acv.a_ap_tree^[ hint_n ].n_sa_level;
                            a05_int4_unsigned_get( acv,
                                  acv.a_ap_tree^[ _curr_n ].n_pos,
                                  acv.a_ap_tree^[ _curr_n ].n_length,
                                  _i );
                            IF  ( acv.a_returncode <> e_invalid_unsign_integer )
                            THEN
                                BEGIN
                                hint.hint_join_config[ hint.hint_joincfg_cnt ].
                                      cfg_parallel_server := _i;
                                END
                            ELSE
                                BEGIN
                                acv.a_returncode := _aux_err;
                                END;
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                cak_x_hashratio_hint   :
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'HASH RATIO  ' );
&                   endif
                    _put_switch    := true;
                    _access_switch := cs_hashjoin_ratio;
                    (* look for indexname *)
                    IF  ( acv.a_ap_tree^[ hint_n ].n_sa_level <> 0 )
                        AND
                        ( acv.a_ap_tree^[ acv.a_ap_tree^[ hint_n ].n_sa_level ].
                        n_symb = s_unsigned_integer  )
                    THEN
                        BEGIN
                        _aux_err := acv.a_returncode;
                        acv.a_returncode := e_ok;
                        _curr_n := acv.a_ap_tree^[ hint_n ].n_sa_level;
                        a05_int4_unsigned_get( acv,
                              acv.a_ap_tree^[ _curr_n ].n_pos,
                              acv.a_ap_tree^[ _curr_n ].n_length,
                              _i );
                        IF  ( acv.a_returncode <> e_invalid_unsign_integer ) AND
                            ( _i <= MAX_INT2_SP00 )
                        THEN
                            BEGIN
                            hint.hint_common_config.cfg_hashratio := _i;
                            END
                        ELSE
                            BEGIN
                            acv.a_returncode := _aux_err;
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                OTHERWISE:
                    BEGIN
&                   ifdef trace
                    t01sname( ak_sem, 'unknown hint' );
&                   endif
                    END;
                END;
            (*ENDCASE*) 
            IF  ( _put_switch )
            THEN
                BEGIN
                IF  ( hint_type = common_hint )
                THEN
                    BEGIN
                    hint.hint_common_config.cfg_switches :=
                          hint.hint_common_config.cfg_switches + [ _access_switch ];
                    END
                ELSE
                    (* join_access_hint *)
                    BEGIN
                    hint.hint_join_config[ hint.hint_joincfg_cnt ].
                          cfg_access_switches :=
                          hint.hint_join_config[ hint.hint_joincfg_cnt ].
                          cfg_access_switches + [ _access_switch ];
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  ( _put_index )
            THEN
                BEGIN
                IF  ( hint_type = common_hint )
                THEN
                    BEGIN
                    hint.hint_common_config.cfg_indexno := _indexno;
                    END
                ELSE
                    BEGIN
                    hint.hint_join_config[ hint.hint_joincfg_cnt ].cfg_indexno := _indexno;
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDWHILE*) 
        ;
&       ifdef trace
        IF  ( hint_type = common_hint )
        THEN
            BEGIN
            t01name( ak_sem, 'common config :   ' );
            a81debug_access_config( ak_sem, hint.hint_common_config );
            t01int4( ak_sem, 'join config ', hint.hint_joincfg_cnt );
            a81debug_join_config( ak_sem, hint.hint_join_config, hint.hint_joincfg_cnt );
            END;
&       endif
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      a80is_predefined_join_order(
            VAR acv : tak_all_command_glob) : boolean;
 
VAR
      _ke         : tgg00_SysInfoKey;
      _hint       : tak_sysbufferaddress;
      _b_err      : tgg00_BasisError;
 
BEGIN
a80is_predefined_join_order := false;
IF  ( csa_hint_exist in acv.a_sql_cmd_state )
THEN
    BEGIN
    ak80build_hint_key( acv, _ke );
    a10get_sysinfo( acv, _ke, d_release, _hint, _b_err );
    END
ELSE
    _b_err := e_file_not_found; (* any error *)
(*ENDIF*) 
IF  ( _b_err = e_ok )
THEN
    BEGIN
    IF  ( cs_ordered_join in _hint^.shint.hint_common_config.cfg_switches )
    THEN
        a80is_predefined_join_order := true;
    (*ENDIF*) 
    END
ELSE
    BEGIN
&   ifdef trace
    t01name( ak_sem, 'no hint available ' );
&   endif
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a80get_access_hint(
            VAR acv         : tak_all_command_glob;
            parskey         : tak_parskey;
            VAR access_hint : tak00_access_configuration );
 
VAR
      _ke         : tgg00_SysInfoKey;
      _hint       : tak_sysbufferaddress;
      _b_err      : tgg00_BasisError;
 
BEGIN
IF  ( csa_hint_exist in acv.a_sql_cmd_state )
THEN
    BEGIN
&   ifdef trace
    t01execution_kind( ak_sem, 'init_ex_kind', acv.a_init_ex_kind );
    t01execution_kind( ak_sem, 'ex_kind     ', acv.a_ex_kind );
&   endif
    parskey.p_id[1] := acv.a_first_parskey;
    ak80build_hint_key_exec( acv, parskey, _ke );
    a10get_sysinfo( acv, _ke, d_release, _hint, _b_err );
    END
ELSE
    BEGIN
&   ifdef trace
    t01sname( ak_sem, 'no parsinfo ' );
&   endif
    _b_err := e_file_not_found; (* any error *)
    END;
(*ENDIF*) 
IF  ( _b_err = e_ok )
THEN
    BEGIN
    access_hint := _hint^.shint.hint_common_config;
&   ifdef trace
    a81debug_access_config( ak_sem, access_hint );
&   endif
    END
ELSE
    BEGIN
&   ifdef trace
    t01name( ak_sem, 'no hint available ' );
&   endif
    access_hint.cfg_indexno  := 0;
    access_hint.cfg_switches := [];
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a80get_access_for_join_hint(
            VAR acv         : tak_all_command_glob;
            parskey         : tak_parskey;
            tableno         : tsp00_Int2;
            VAR access_hint : tak00_access_configuration);
 
VAR
      _ke         : tgg00_SysInfoKey;
      _hint       : tak_sysbufferaddress;
      _b_err      : tgg00_BasisError;
      _no_hint    : boolean;
 
BEGIN
IF  ( acv.a_returncode = 0 )
THEN
    BEGIN
    _no_hint := true;
    IF  ( csa_hint_exist in acv.a_sql_cmd_state )
    THEN
        BEGIN
&       ifdef trace
        t01execution_kind( ak_sem, 'init_ex_kind', acv.a_init_ex_kind );
        t01execution_kind( ak_sem, 'ex_kind     ', acv.a_ex_kind );
&       endif
        parskey.p_id[1] := acv.a_first_parskey;
        ak80build_hint_key_exec( acv, parskey, _ke );
        a10get_sysinfo( acv, _ke, d_release, _hint, _b_err );
        IF  ( _b_err = e_ok )
        THEN
            BEGIN
            IF  ( tableno <= _hint^.shint.hint_joincfg_cnt )
            THEN
                BEGIN
                _no_hint  := false;
                access_hint.cfg_switches :=
                      _hint^.shint.hint_join_config[ tableno ].cfg_access_switches;
                access_hint.cfg_indexno :=
                      _hint^.shint.hint_join_config[ tableno ].cfg_indexno;
&               ifdef trace
                a81debug_access_config( ak_sem, access_hint );
&               endif
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  ( _no_hint )
    THEN
        BEGIN
&       ifdef trace
        t01name( ak_sem, 'no hint available ' );
&       endif
        access_hint.cfg_indexno    := 0;
        access_hint.cfg_switches   := [];
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a80open_hint_info(
            VAR acv         : tak_all_command_glob;
            parskey         : tak_parskey;
            VAR hintinfo    : tak_sysbufferaddress);
 
VAR
      _ke         : tgg00_SysInfoKey;
      _b_err      : tgg00_BasisError;
 
BEGIN
parskey.p_id[1] := acv.a_first_parskey;
ak80build_hint_key_exec( acv, parskey, _ke );
a10get_sysinfo( acv, _ke, d_fix, hintinfo, _b_err );
IF  ( _b_err = e_ok )
THEN
    BEGIN
&   ifdef trace
    a81debug_access_config( ak_sem, hintinfo^.shint.hint_common_config );
    a81debug_join_config( ak_sem, hintinfo^.shint.hint_join_config,
          hintinfo^.shint.hint_joincfg_cnt );
&   endif
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a80close_hint_info( VAR hintinfo : tak_sysbufferaddress );
 
BEGIN
a10rel_sysinfo( hintinfo );
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak80search_snode(
            VAR ap_tree     : tak_ap_max_tree;
            VAR select_node : tsp00_Int4;
            max_node        : tsp00_Int4 );
 
VAR
      _i         : tsp00_Int4;
      _sel_found : boolean;
      _null      : tsp00_Int4;
 
BEGIN
_null := 0;
_i := select_node;
_sel_found := false;
WHILE (( _i < max_node) AND ( NOT _sel_found )) DO
    BEGIN
    IF  (
        (( ap_tree[ _i ].n_proc = a63 ) AND
        ( ap_tree[ _i ].n_subproc in [cak_x_mass_select,cak_x_decl_cursor,cak_x_start_union] ))
        OR
        ( ap_tree[ _i ].n_proc = a63query_spec )
        OR
        (( ap_tree[ _i ].n_proc = a56 ) AND
        ( ap_tree[ _i ].n_subproc in [ cak_x_normal_insert, cak_x_minsert, cak_x_insert_select ] ))
        OR
        (( ap_tree[ _i ].n_proc = a57 ) AND
        ( ap_tree[ _i ].n_subproc in [ cak_x_update, cak_x_mupdate ] ))
        OR
        (( ap_tree[ _i ].n_proc = a58 ) AND
        ( ap_tree[ _i ].n_subproc in [ cak_x_delete, cak_x_mdelete ] ))
        )
    THEN
        BEGIN
        _sel_found  := true;
        select_node := _i;
&       ifdef trace
        t01int4( ak_sem, 'node found  ', _i );
&       endif
        END
    ELSE
        BEGIN
        IF  (( ap_tree[ _i ].n_proc = a66 ) AND
            ( ap_tree[ _i ].n_subproc = cak_x_select_in_from_part ))
        THEN
            BEGIN
            _sel_found  := true;
            select_node := ap_tree[ _i ].n_lo_level;
&           ifdef trace
            t01int4( ak_sem, 'node found  ', _i );
&           endif
            END
        ELSE
            BEGIN
            IF  ( ap_tree[ _i ].n_proc = a92fromsel )
            THEN
                BEGIN
                _sel_found  := true;
                select_node := ap_tree[ _i ].n_pos;
&               ifdef trace
                t01int4( ak_sem, 'node found  ', _i );
&               endif
                END
            ELSE
                BEGIN
&               ifdef trace
                (* D.T. : crash in order to find those situations where select_node is not the correct node *)
                t01int4( ak_sem, 'ak80search  ', _i );
                _i := trunc(_i/_null);
&               endif
                _i := succ( _i );
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      a80is_operator_join(
            VAR acv         : tak_all_command_glob;
            VAR dmli        : tak_dml_info) : boolean;
 
VAR
      _ke         : tgg00_SysInfoKey;
      _hint       : tak_sysbufferaddress;
      _b_err      : tgg00_BasisError;
 
BEGIN
a80is_operator_join := false;
_hint := NIL;
IF  ( csa_hint_exist in acv.a_sql_cmd_state )
THEN
    BEGIN
        ak80build_hint_key( acv, _ke );
        a10get_sysinfo( acv, _ke, d_release, _hint, _b_err );
        END
ELSE
        _b_err := e_file_not_found; (* any error *)
(*ENDIF*) 
IF  ( _b_err = e_ok )
THEN
        BEGIN
        IF  ( cs_operator_join in
            _hint^.shint.hint_common_config.cfg_switches )
        THEN
            a80is_operator_join := true
        ELSE
            a80is_operator_join := gg01_operator_join;
        (*ENDIF*) 
        END
ELSE
        BEGIN
&       ifdef trace
        t01name( ak_sem, 'no hint available ' );
&       endif
        a80is_operator_join := gg01_operator_join;
        END;
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
