.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-22
*****************************************************
modname : VAK70
changed : 2000-11-22
module  : Build_Strategy
 
Author  : GertG / HolgerB
Created : 1985-10-16
*****************************************************
 
Purpose : Main module for the strategy search in a table
 
Define  :
 
        VAR
              a70_glob_zstrat_rec       : tak70_strategy_record;
              a70glob_key_strats        : tgg07_StratEnumSet;
              a70glob_inv_strats        : tgg07_StratEnumSet;
              a70glob_join_strats       : tgg07_StratEnumSet;
              a70glob_join_key_strats   : tgg07_StratEnumSet;
              a70glob_join_inv_strats   : tgg07_StratEnumSet;
              a70glob_fetch_strats      : tgg07_StratEnumSet;
              a70glob_build_strats      : tgg07_StratEnumSet;
              a70glob_key_build_strats  : tgg07_StratEnumSet;
              a70glob_inv_build_strats  : tgg07_StratEnumSet;
              a70glob_key_fetch_strats  : tgg07_StratEnumSet;
              a70glob_inv_fetch_strats  : tgg07_StratEnumSet;
              a70glob_in_strats         : tgg07_StratEnumSet;
              a70glob_subq_strats       : tgg07_StratEnumSet;
 
        PROCEDURE
              a70_strategy_search (
                    VAR acv       : tak_all_command_glob;
                    VAR dmli      : tak_dml_info;
                    VAR rtree     : tgg00_FileId;
                    VAR strat_rec : tak70_strat_rec);
 
        PROCEDURE
              a70strategy (
                    VAR acv          : tak_all_command_glob;
                    VAR dmli         : tak_dml_info;
                    VAR gg_strategy  : tgg07_StrategyInfo;
                    VAR StratInfo_len: tsp00_Int2;
                    VAR eval_info    : tak70_page_eval_rec;
                    config           : tak00_access_configuration);
 
        PROCEDURE
              a70L1_strat_search (
                    VAR acv          : tak_all_command_glob;
                    VAR sparr        : tak_syspointerarr;
                    VAR access_info  : tak70_strategy_record;
                    VAR gg_strategy  : tgg07_StrategyInfo;
                    VAR StratInfo_len: tsp00_Int2;
                    VAR eval_info    : tak70_page_eval_rec;
                    VAR order_fields : tak00_ord_fields;
                    VAR L1_pageIO    : tsp00_Int4;
                    VAR L1_stratvalue: tsp00_Longreal);
 
        PROCEDURE
              a70L2L3_strat_search (
                    VAR acv          : tak_all_command_glob;
                    VAR dmli         : tak_dml_info;
                    VAR sparr        : tak_syspointerarr;
                    VAR access_info  : tak70_strategy_record;
                    VAR gg_strategy  : tgg07_StrategyInfo;
                    VAR StratInfo_len: tsp00_Int2;
                    morestratpos     : tsp00_Int4;
                    VAR eval_info    : tak70_page_eval_rec;
                    VAR L1_terms     : tak70_term;
                    VAR order_fields : tak00_ord_fields;
                    L1_pageIO        : tsp00_Int4;
                    VAR L1_stratvalue: tsp00_Longreal);
 
.CM *-END-* define --------------------------------------
***********************************************************
 
Use     :
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01sysnullkey        : tgg00_SysInfoKey;
 
      ------------------------------ 
 
        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;
                    vtrAll_gg00  : boolean;
                    VAR ok       : boolean);
 
      ------------------------------ 
 
        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
              Systeminfo_cache : VAK10;
 
        PROCEDURE
              a10rel_sysinfo (p : tak_sysbufferaddress);
 
        PROCEDURE
              a10add_sysinfo (
                    VAR acv      : tak_all_command_glob;
                    VAR syspoint : tak_sysbufferaddress;
                    VAR b_err    : tgg00_BasisError);
 
        PROCEDURE
              a10mblock_into_cache (
                    VAR acv      : tak_all_command_glob;
                    VAR syskey   : tgg00_SysInfoKey;
                    VAR mblock   : tgg00_MessBlock;
                    dstate       : tak_directory_state;
                    VAR syspoint : tak_sysbufferaddress;
                    VAR b_err    : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              DML_Help_Procedures : VAK54;
 
        PROCEDURE
              a54_fixedpos (
                    VAR acv  : tak_all_command_glob;
                    VAR dmli : tak_dml_info);
 
      ------------------------------ 
 
        FROM
              Part2_Select_Expression  : VAK67;
 
        PROCEDURE
              a67_invkeylen (
                    VAR acv         : tak_all_command_glob;
                    VAR gg_strategy : tgg07_StrategyInfo;
                    VAR invkeylen   : tsp00_Int2);
 
        PROCEDURE
              a67_explain (
                    VAR acv          : tak_all_command_glob;
                    VAR dmli         : tak_dml_info;
                    VAR gg_strategy  : tgg07_StrategyInfo;
                    VAR morestratbuf : tsp00_MoveObj;
                    morestratbufsize : tsp00_Int4;
                    morestratpos     : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              Build_Strategy_2 : VAK71;
 
        PROCEDURE
              a71check_fetch_optimization (
                    VAR acv         : tak_all_command_glob;
                    VAR config      : tak00_access_configuration;
                    VAR qprop       : tak70_query_properties;
                    VAR gg_strategy : tgg07_StrategyInfo;
                    VAR strategy    : tgg07_StratEnum;
                    VAR strat_data  : tgg07_StrRaw);
 
        FUNCTION
              a71code_distinct_optim (
                    VAR gg_strategy : tgg07_StrategyInfo) : tsp00_Int2;
 
        PROCEDURE
              a71prepare_qual_on_index (
                    VAR acv       : tak_all_command_glob;
                    VAR qual_kind : tgg00_QualKind);
 
        PROCEDURE
              a71set_rescnt(
                    VAR acv         : tak_all_command_glob;
                    VAR sparr       : tak_syspointerarr;
                    datapos         : tsp00_Int2;
                    VAR qprop       : tak70_query_properties);
 
        PROCEDURE
              a71adjust_configuration (
                    VAR dmli        : tak_dml_info;
                    VAR config_qprop : tak70_strategy_record);
 
        PROCEDURE
              a71default_strat (VAR gg_strategy : tgg07_StrategyInfo);
 
      ------------------------------ 
 
        FROM
              Build_Strategy_Decision : VAK720;
 
        PROCEDURE
              a720strategy_decision (
                    VAR acv              : tak_all_command_glob;
                    VAR sparr            : tak_syspointerarr;
                    VAR access_info      : tak70_strategy_record;
                    VAR gg_strategy      : tgg07_StrategyInfo;
                    VAR chosen_strat     : tak70_one_strat;
                    VAR order_fields     : tak00_ord_fields;
                    VAR StratInfo_len    : tsp00_Int2;
                    call_for_L1          : boolean);
 
        PROCEDURE
              a720decide_L2_range(
                    VAR acv          : tak_all_command_glob;
                    VAR sparr        : tak_syspointerarr;
                    VAR access_info  : tak70_strategy_record;
                    VAR gg_strategy  : tgg07_StrategyInfo;
                    VAR StratInfo_len: tsp00_Int2;
                    VAR eval_info    : tak70_page_eval_rec;
                    L1_pageIO        : tsp00_Int4;
                    VAR L1_stratvalue: tsp00_Longreal;
                    VAR key_range    : tgg07_StrKeyInRange);
 
      ------------------------------ 
 
        FROM
              Build_Strategy_4 : VAK721;
 
        PROCEDURE
              a721transfer_parse_info (
                    VAR acv           : tak_all_command_glob;
                    VAR access_info   : tak70_strategy_record;
                    VAR L1_terms      : tak70_term;
                    VAR order_fields  : tak00_ord_fields;
                    work_kind         : tak70_backup);
 
      ------------------------------ 
 
        FROM
              Catalog_Select_Optimizer : VAK722;
 
        PROCEDURE
              a722strategy (
                    VAR acv        : tak_all_command_glob;
                    VAR dmli       : tak_dml_info;
                    VAR eval_info  : tak70_page_eval_rec;
                    VAR gg_strategy: tgg07_StrategyInfo;
                    VAR strat_len  : tsp00_Int2);
 
      ------------------------------ 
 
        FROM
              Build_Strategy_Index_Only : VAK723;
 
        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);
 
      ------------------------------ 
 
        FROM
              Build_Strategy_Level1_terms : VAK726;
 
        PROCEDURE
              a726combine_terms (
                    VAR acv          : tak_all_command_glob;
                    VAR dmli         : tak_dml_info;
                    VAR sparr        : tak_syspointerarr;
                    VAR access_info  : tak70_strategy_record;
                    VAR gg_strategy  : tgg07_StrategyInfo;
                    VAR astrats      : tak70_all_strat;
                    VAR order_fields : tak00_ord_fields;
                    VAR L1_terms     : tak70_term;
                    VAR nextstratpos : tsp00_Int4;
                    L1term_cnt       : tsp00_Int2;
                    L2pL3t_cnt       : tsp00_Int2;
                    L1_pageIO        : tsp00_Int4;
                    VAR strat_status : tak70_l2l3_strat_status);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Trace_Strategy_1 : VAK725;
 
        PROCEDURE
              a725output_gg_strat (
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    VAR gg_strat  : tgg07_StrategyInfo);
 
        PROCEDURE
              a725L1_terms_output (
                    level        : tgg00_Debug;
                    VAR L1_terms : tak70_term);
 
        PROCEDURE
              a725output_one_strat (
                    layer           : tgg00_Debug;
                    VAR one_strat   : tak70_one_strat);
 
        PROCEDURE
              a725output_end_strat(
                    debug             : tgg00_Debug;
                    nam               : tsp00_Sname;
                    VAR gg_strategy   : tgg07_StrategyInfo;
                    VAR eval_info     : tak70_page_eval_rec;
                    VAR StratInfo_len : tsp00_Int2);
 
        PROCEDURE
              a725output_more_strat(
                    VAR acv         : tak_all_command_glob;
                    debug           : tgg00_Debug;
                    VAR gg_strategy : tgg07_StrategyInfo;
                    VAR all_strats  : tak70_all_strat);
 
        PROCEDURE
              a725output_query_prop (
                    debug   : tgg00_Debug;
                    qprop   : tak70_query_properties);
&       endif
 
      ------------------------------ 
 
        FROM
              Trace_Strategy_2 : VAK727;
 
        PROCEDURE
              a727trace_tablename (
                    VAR transid     : tgg00_TransContext;
                    name            : tsp00_Sname;
                    VAR tabname     :tsp00_KnlIdentifier);
 
        PROCEDURE
              a727trace_one_strat (
                    VAR transid     : tgg00_TransContext;
                    proc_name       : tsp00_Name;
                    VAR one_strat   : tak70_one_strat);
 
        PROCEDURE
              a727trace_strategy_text(
                    VAR transid : tgg00_TransContext;
                    name       : tsp00_Sname;
                    strategy   : tgg07_StratEnum);
 
        PROCEDURE
              a727trace_query_prop (
                    VAR transid     : tgg00_TransContext;
                    VAR qprop       : tak70_query_properties);
 
      ------------------------------ 
 
        FROM
              Build_Strategy_term_structure : VAK724;
 
        PROCEDURE
              a724all_L1_terms (
                    VAR acv         : tak_all_command_glob;
                    VAR dmli        : tak_dml_info;
                    VAR access_info : tak70_strategy_record;
                    VAR L1_terms    : tak70_term;
                    use_subquery    : tgg07_SubqKind);
 
      ------------------------------ 
 
        FROM
              Hint_Handling   : VAK80;
 
        PROCEDURE
              a80get_access_hint(
                    VAR acv         : tak_all_command_glob;
                    parskey         : tak_parskey;
                    VAR access_hint : tak00_access_configuration );
 
      ------------------------------ 
 
        FROM
              hint_trace_routines : VAK81;
 
        PROCEDURE
              a81trace_access_config (
                    VAR transid     : tgg00_TransContext;
                    VAR config      : tak00_access_configuration);
 
      ------------------------------ 
 
        FROM
              Single_Select : VKB720;
 
        PROCEDURE
              k720ref_statistic (
                    VAR m         : tgg00_MessBlock;
                    VAR arr_index : tgg00_RefInfoIndex;
                    VAR strat     : tgg07_StrategyInfo);
 
      ------------------------------ 
 
        FROM
              Trace : VBD120;
 
        PROCEDURE
              b120MessBlockTrace (
                    VAR Trans     : tgg00_TransContext;
                    TraceType     : tgg00_VtraceType;
                    VAR MessBlock : tgg00_MessBlock);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01vtrace    : tgg00_VtraceState;
              g01tabid     : tgg04_TabIdGlobals;
 
      ------------------------------ 
 
        FROM
              Select_Help_Procedures : VGG04;
 
        PROCEDURE
              g04spec_null_check (
                    VAR mblock : tgg00_MessBlock;
                    VAR b_err : tgg00_BasisError);
 
        PROCEDURE
              g04inbetween_change (
                    VAR mblock           : tgg00_MessBlock;
                    VAR finding_possible : boolean);
 
      ------------------------------ 
 
        FROM
              Trace_Help_Procedures : VGG041;
 
        PROCEDURE
              g041c30_to_trace (
                    VAR t : tgg00_TransContext;
                    msg : tsp00_C30);
 
        PROCEDURE
              g041name_to_trace (
                    VAR t  : tgg00_TransContext;
                    name   : tsp00_Name);
 
      ------------------------------ 
 
        FROM
              Record_Encapsulate_Procedures : VGG09;
 
        PROCEDURE
              g09StratStackentry (
                    VAR NewStackEntry : tgg00_StackEntry;
                    inp_startpos      : tsp00_Int2;
                    inp_len           : tsp00_Int2);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalMove (
                    mod_id         : tsp00_C6;
                    mod_intern_num : tsp00_Int4;
                    source_upb     : tsp00_Int4;
                    destin_upb     : tsp00_Int4;
                    source         : tsp00_MoveObjPtr;
                    source_pos     : tsp00_Int4;
                    destin         : tsp00_MoveObjPtr;
                    destin_pos     : tsp00_Int4;
                    length         : tsp00_Int4;
                    VAR e          : tgg00_BasisError);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vdebug_break (debug_break_pos : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01treeid (
                    level      : tgg00_Debug;
                    nam        : tsp00_Sname;
                    VAR treeid : tgg00_FileId);
 
        PROCEDURE
              t01corr_type (
                    debug     : tgg00_Debug;
                    nam       : tsp00_Sname;
                    corr_type : tak_corr_type);
 
        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
              t01bool (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    curr_bool: boolean);
 
        PROCEDURE
              t01int4 (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01messblock (
                    debug       : tgg00_Debug;
                    nam         : tsp00_Sname;
                    VAR mblock  : tgg00_MessBlock);
 
        PROCEDURE
              t01sname (
                    level : tgg00_Debug;
                    nam   : tsp00_Sname);
 
        PROCEDURE
              t01name (
                    level : tgg00_Debug;
                    nam : tsp00_Name);
 
        PROCEDURE
              t01strat_enum (
                    debug : tgg00_Debug;
                    nam   : tsp00_Sname;
                    strat : tgg07_StratEnum);
 
        PROCEDURE
              t01columnset (
                    debug           : tgg00_Debug;
                    nam             : tsp00_Sname;
                    columnset       : tak_columnset);
&       endif
 
.CM *-END-* use -----------------------------------------
***********************************************************
 
Synonym :
 
.CM *-END-* synonym -------------------------------------
***********************************************************
Specification:
 
This module should not be analyzed until you are familiar with the
Internals training with regard to the optimizer. This training explains in
detail which conditions can be used for a good search strategy, which
strategies exist and how they are described for KB. Therefore, not
everything is described in full detail in this module.
 
.CM *-END-* specification -------------------------------
***********************************************************
Description:
 
A70STRATEGY
------------------------
 
This is the main procedure for the strategy search in a table.
The best strategy is to be chosen for the specified table with the aid of
the conditions contained in the Mess-Buffer.
STRAT is, at the end, to contain the strategy and, when the procedure is
called, it has in it information on the source file name (primary table),
result file name etc. It is specified whether the result set has to be built,
whether only a certain number of results is allowed or whether DISTINCT was
specified.
ATORDER contains information on the fields to be used for sorting
(specified by the user in ORDER BY).
UPD_COL_SET is empty for normal Selects. In the case of Select FOR UPDATE,
the set contains the columns that are specified behind 'FOR UPDATE'
and, in the case of
Updates, it contains the columns that are to receive a new value resulting from
an expression. The inversions of the fields contained in the set must not be
used in some strategies, since e.g.
   UPDATE tab
      SET f = f+3
    WHERE f > 9
would lead to an endless loop when one inversion list from field f after
the other is processed.
In eval_info.costcheck, it is specified whether it is to be determined for each
condition how many percent of the records of the primary table will satisfy the
condition. This is necessary in the case of Joins and for the EXPLAIN.
The result of the procedure is the information on:
 
- strategy to be taken for accessing the table (strat.strategy)
 
- parameters of the chosen strategy (e.g. strat.str_key_in_range, str_key_in_range. ]
 
- strategy value (eval_info.strat_value) representing the expected fraction
of pages to be searched for evaluating the qualification.
 
- qualification value (eval_info.qual_value) representing the expected
number of result records (as fraction of base table pages)
 
A98_READ_STRETCHES is used for testing in order to make the strategy search
think it is dealing with a larger database.
If a cost check is required for the user (COSTCHECK), the conditions must
all be evaluated (see also eval_info.costcheck).
All ANDed conditions at the highest level of the Search Condition are
entered in zstrat by A724ALL_L1_TERMS; the conditions on lower levels (ORed) are
entered in L1_TERMS.
The conditions recorded in L1_TERMS are analyzed for their usability for good
search strategies only if the top-level conditions from zstrat have not
resulted in a good strategy.
The analysis of the descriptions of the conditions stored in zstrat takes
place in A70L1_STRAT_SEARCH. The procedure checks whether a good search
strategy can be found using these conditions alone.
If a strategy has been found in which searching need not be sequential,
this strategy is considered good (good_enough). The strategy is likewise <>
sequential (eval_strat), if, because of missing data input (parsing only), the
descriptions of the conditions are stored by A721STORE_ALL_STRATS, but are not
analyzed.
If a cost estimate is to be performed, it must be determined
for the conditions stored in L1_TERMS that are not at the highest level of the
Search Condition how many percent of the records will satisfy these conditions.
This value is shown by qual_value.
Since all conditions that are to be evaluated are in L1_TERMS (if a cost
estimate is to be performed), not only those that can be used for a strategy,
the unusable strategies are removed from L1_TERMS in A70EVAL_WHOLE_TERM_QUAL.
FIRST_COST specifies the search cost in the primary and secondary tables.
INV_OVERHEAD attempts to evaluate the extra cost for the reading and
analyzing of secondary pages.
If it has not been possible to determine a good strategy from the
conditions at the highest level alone, but there are still usable conditions at
lower levels, these are analyzed.
Structures of the following type can be stored in L1_TERMS, with each letter
intended to signify a condition, a predicate:
  (a OR b AND c OR d) AND (e AND f OR g OR h).
Up to 6 Or parts (big brackets) each with up to 6 ORed terms each with up
to 7 conditions for each term can be stored in L1_TERMS.
In A726STRAT_COMBINE, these brackets are transformed :
  (a AND e AND f) OR (a AND g) OR (a AND h) OR
  (b AND c AND e AND f) OR (b AND c AND g) OR ...
For each of these brackets, an attempt is made to choose a good strategy
that can then be executed individually in KB.
Identical strategies are not contained more than once. There may be a
maximum of 36 different strategies. These are entered in astrats.
If each bracket can be processed with a better strategy
than by a sequential search across
the entire primary table (NOT seq), these strategies are used and are sent to
KB (z_strat = more_than_one).
The information on these strategies is stored in a character array, in each
case with strategy, length of the strategy description and the strategy
description itself.
An evaluation of the search cost has been performed within
A726STRAT_COMBINE for each individual strategy. These costs are added up in a
FOR loop and result in the estimated total costs.
If, according to the evaluation, more records satisfy all conditions than
the total number of records that have to be accessed because of the strategies,
the smaller of the two values is taken. This case may occur in that
computations are performed partly with estimated values and partly with values
that have been determined in the database (number of records, pages).
The total costs (accessing of all pages necessary for the strategies,
writing of all records that satisfy the conditions, writing of each primary key
from whose record a result record has been built in order to prevent one
primary record being made into more than one result record within different
strategies) are determined.
If the result set has to be physically built (for Joins, in the case of
subqueries, if ROWNO or DISTINCT was specified, if the other information to be
stored for FETCH will not fit into one parse buffer), the strategy is retained.
If there is still a chance of being able to cut out the costs of physically
building the result set, analysis is continued:
Normally, the result set must be physically built if ORDER BY has been
specified. These costs can be cut out only if a good strategy has not been
found but the ORDER-BY fields form the first part of the key or
an inversion. The corresponding analysis is
performed in ORDER_MULTI.
If the result set need not be built, this is indicated by the strategy
prefix fe_ (fetch_). Such strategies are processed in VKB73, with all others
being processed in VKB720,721.
If the whole strategy would not fit in part2 of the Mess-Buffer, it is
better to search sequentially than not to be able to execute the entire
command.
The strategy is entered in the Mess-Buffer by the calling procedures (VAK67/68).
 
A70L1_STRAT_SEARCH
---------------------------------------
 
This procedure is called by A70_STRATEGY to determine if there is a non-
sequential strategy using only the simple top-level terms of the qualification.
Input :
 
z_strat_rec - contains all parameters of the simple top-level terms (e.g.
              BETWEEN-bounds)
 
Output:
 
strat
1. strategy chosen (strat.strategy)
2. parameters of strategy (e.g. str_sinv_in, str_key_in_range)
3. value describing what fraction of pages will have to be searched using this
   strategy (ostrat_value)
 
z_strat_rec^- z_strat, identical to ostrategy
z_strat_value, identical to ostrat_value
 
Sequence of Actions:
 
1. If z_strat equals 'key_in' (established by all_ands) then any further search
is stopped and ostrat is assigned the key_in- parameters.
 
2. In all other cases (unless separate parse-execute) A720STRATEGY_DECISION is
called to determine the strategy from the information in z_strat_rec. All
parameters of this strategy besides the key-range (which is in z_strat_rec
anyway) are returned via one_strat of type ostrategy. The information in
'one_strat' and the key-range from 'z_strat_rec' are both copied to the
variable 'strat' of type 'strategy_info', which is then returned. (str_inv_in_range is
the longest possible strategy)
 
If, for any data specification that is not a part of the condition IS NULL,
the null value is found in the data part (part2) of the Mess-Buffer, this means
that the initialization of the buffer still exists, i.e. that the value will
not be known until at the time of execution (srec_broken_access). Therefore, it is not
yet possible at this time to decide on the best strategy and it is necessary to
store all available information by means of A721TRANSFER_PARSE_INFO in order,
during execution, to be able to determine the best strategy.
 
A70DEL_SYSINFO_STRATEGY
------------------------
 
This procedure is called from VAK10 if all system information for a table is to
be deleted and a strategy is needed for this. It is in this module so that, in
the case of alterations to the STRAT record, it is not (again and again)
forgotten to alter this procedure.
 
.CM *-END-* description ---------------------------------
***********************************************************
Structure:
 
 
(*------------------------------*) 
 
PROCEDURE
      eval_whole_term_qual;
 
BEGIN
WHILE there_is_another_Or_part DO
    BEGIN
    mark_old_number_of_terms;
    IF  entries_in_this_Or_part_are_still_valid
    THEN
        BEGIN
        WHILE there_is_another_term DO
            BEGIN
            WHILE another_condition_entered DO
                BEGIN
                multiplication_of_evaluation_factors_of_the
                      conditions_of_an_and;
                IF  condition_is_useful_for_strategy
                THEN
                    look_at_the_next_condition
                ELSE
                    forget_this_condition
                (*ENDIF*) 
                END;
            (*ENDWHILE*) 
            Add_up_evaluation_factors_for_the_different
                  terms;
            IF  not_all_conditions_of_a_term_have_been
                forgotten
            THEN
                look_at_the_next_term
            ELSE
                forget_the_whole_term
            (*ENDIF*) 
            END;
        (*ENDWHILE*) 
        multiplication_of_the_evaluation_factors_for_the_or_parts
        END;
    (*ENDIF*) 
    IF  a_term_could_be_forgotten_for_an_Or_part_because
        all_conditions_for_it_could_be_forgotten
    THEN
        the_entire_Or_part_must_be_forgotten,_because,_for_the
              strategy_search,_all_terms_from_each_participating
              Or_part_must_be_contained,_because,_otherwise,
              it_is_possible_that_records_that_would_belong
              to_the_result_set_will_not_be_checked_(because
              no_strategy_specified)
    (*ENDIF*) 
    END
(*ENDWHILE*) 
END;
 
.CM *-END-* structure -----------------------------------
**********************************************************
.CM -lll-
Code    :
 
 
CONST
      (* the following constants should also be *)
      (* defined in VAK71 with the same values: *)
      c_get_all          = true (* a06_systable_get      *);
 
 
(*------------------------------*) 
 
PROCEDURE
      a70_strategy_search (
            VAR acv       : tak_all_command_glob;
            VAR dmli      : tak_dml_info;
            VAR rtree     : tgg00_FileId;
            VAR strat_rec : tak70_strat_rec);
 
VAR
      _e             : tgg00_BasisError;
      _eval_info     : tak70_page_eval_rec;
      _ix            : tsp00_Int2;
      _jx            : tsp00_Int2;
      _prev          : tsp00_Int2;
      _StratInfo_len : tsp00_Int2;
      _h_data_len    : tsp00_Int4;
      _mv_strat_len  : tsp00_Int4;
      _ibuf          : tak_sysbufferaddress;
      _ke            : tgg00_SysInfoKey;
      _gg_strategy   : tgg07_StrategyInfo;
      _config        : tak00_access_configuration;
 
BEGIN
WITH acv.a_mblock DO
    BEGIN
&   IFDEF TRACE
    t01messblock (ak_strat, 'a70_strat_s1', acv.a_mblock);
    t01treeid  (ak_strat, 'resulttreeid', rtree);
    t01bool    (ak_strat, 'use_subquery', strat_rec.sr_use_subquery);
    t01int4    (ak_strat, 'd_pos_result', dmli.d_pos_result);
    t01bool    (ak_strat, 'd_single    ', dmli.d_single);
    t01corr_type(ak_strat, 'd_corr      ', dmli.d_corr);
    t01int4    (ak_strat, 'd_rowno     ', dmli.d_rowno);
    t01int4    (ak_strat, 'd_inoutpos  ', dmli.d_inoutpos);
    t01int4    (ak_strat, 'd_reclen    ', dmli.d_reclen);
&   ENDIF
    _e := e_ok;
    a71default_strat( _gg_strategy );
    _gg_strategy.str_rowno      := dmli.d_rowno;
    _gg_strategy.str_result_id  := rtree;
    _gg_strategy.str_result_id.fileHandling_gg00 :=
          _gg_strategy.str_result_id.fileHandling_gg00 + [ hsCreateFile_egg00 ];
    _gg_strategy.str_build_result := strat_rec.sr_must_result;
    _gg_strategy.str_distinc      := dmli.d_distinct;
    IF  (strat_rec.sr_use_subquery OR mb_qual^.msubquery)
    THEN
        _gg_strategy.str_use_subquery := normal_subquery
    ELSE
        IF  dmli.d_subquery
        THEN
            _gg_strategy.str_use_subquery := query_in_subq
        ELSE
            _gg_strategy.str_use_subquery := no_subquery;
        (*ENDIF*) 
    (*ENDIF*) 
    _gg_strategy.str_use_order    := dmli.d_use_order;
    IF  ( dmli.d_single )
    THEN
        BEGIN
        IF  ( dmli.d_corr = first_correlation )
        THEN
            _gg_strategy.str_corr_single := true;
        (*ENDIF*) 
        _gg_strategy.str_selinto := true;
        END
    ELSE
        BEGIN
        IF  ( dmli.d_corr = first_correlation ) AND ( dmli.d_rowno = cgg04_one_record_at_most_internal )
        THEN
            _gg_strategy.str_corr_single := true;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    _gg_strategy.str_key_len      := dmli.d_keylen;
    (* PTS 1000843 E.Z. *)
    IF  ( dmli.d_inoutpos > 0 )
    THEN
        _gg_strategy.str_rec_len := dmli.d_inoutpos - 1;
    (*ENDIF*) 
    _gg_strategy.str_all_files := ( acv.a_recursive_state = rs_last_select );
    IF  ( mb_data_len MOD ALIGNMENT_GG00 <> 0 )
    THEN
        mb_data_len := mb_data_len -
              ( mb_data_len MOD ALIGNMENT_GG00 ) + ALIGNMENT_GG00;
    (*ENDIF*) 
    IF  (mb_qual^.mtree.fileTfn_gg00     = tfnTemp_egg00) AND
        (mb_qual^.mtree.fileTfnTemp_gg00 = ttfnCorrelation_egg00)
    THEN
        BEGIN
        _ix := mb_qual^.mfirst_free - 1;
        WHILE (mb_st^[ _ix ].etype <> st_varkey) DO
            _ix := pred( _ix );
        (*ENDWHILE*) 
        _gg_strategy.str_strategy                      := strat_key_equal;
        _gg_strategy.str_key_in_range.skir_keystart[ 0 ]   := _ix;
        _gg_strategy.str_key_in_range.skir_keystop[ 0 ]    := _ix;
        _StratInfo_len  := STRATEGY_START_MXGG07 +
              sizeof( _gg_strategy.str_key_in_range );
        _eval_info.pev_wholeIO_pages := 1000;
        END
    ELSE
        IF  (mb_qual^.mtree.fileTfn_gg00     = tfnTemp_egg00)
            AND (mb_qual^.mtree.fileTfnTemp_gg00 <> ttfnTempTable_egg00)
            AND (mb_qual^.mtree.fileTabId_gg00 <>
            g01tabid.sys_diag_parse.fileTabId_gg00)
            (* table SYSPARSEID has a primary key *)
        THEN (* h.b. PTS 1002121 *)
            BEGIN
            IF  ( acv.a_from_select )
                OR
                ( _gg_strategy.str_build_result )
                OR
                (* h.b. PTS 1105126 *)
                ( _gg_strategy.str_use_order )
                OR
                ( _gg_strategy.str_distinc <> no_distinct )
                OR
                ( _gg_strategy.str_selinto )
                OR
                (( abs(_gg_strategy.str_rowno) < cgg04_valid_rowno_pos )
                AND
                ( _gg_strategy.str_rowno <> cgg04_no_rowno_predicate ))
            THEN
                _gg_strategy.str_strategy := strat_key_range
            ELSE
                _gg_strategy.str_strategy := strat_key_range_fetch;
            (*ENDIF*) 
            _StratInfo_len := STRATEGY_START_MXGG07 +
                  sizeof( _gg_strategy.str_key_in_range );
            (* (read + write frac) * page count for temporary result *)
            _eval_info.pev_wholeIO_pages := ( 1 + 1 ) * cak_initpages + 1;
            END
        ELSE
            BEGIN
            _gg_strategy.str_strategy := strat_undecided;
            _StratInfo_len            := STRATEGY_START_MXGG07;
&           ifdef TRACE
            IF  ( dmli.d_sparr.pparsp = NIL )
            THEN
                t01int4( ak_sem, 'sparsp = nil', 1 )
            ELSE
                t01int4( ak_sem, 'sparsp<> nil', 0 );
            (*ENDIF*) 
&           endif
            IF  (( acv.a_ex_kind = only_parsing ) AND
                ( dmli.d_sparr.pparsp <> NIL ))
            THEN
                a54_fixedpos( acv, dmli );
            (*ENDIF*) 
            IF  (dmli.d_sparr.pbasep^.sbase.bv_tablekind = tcatalog_table)
                AND
                (mb_qual^.mtree.fileTfn_gg00 = tfnSys_egg00)
            THEN
                a722strategy( acv, dmli, _eval_info,
                      _gg_strategy, _StratInfo_len )
            ELSE
                BEGIN
                IF  (mb_type = m_select)
                THEN
                    dmli.d_index_strat_poss := ind_init;
                (*ENDIF*) 
                a80get_access_hint( acv, acv.a_pars_last_key, _config );
                a70strategy( acv, dmli, _gg_strategy,
                      _StratInfo_len, _eval_info, _config );
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  ( acv.a_returncode = 0 )
    THEN
        BEGIN
        IF  (mb_type = m_delete) AND (mb_qual^.mqual_cnt = 0) AND
            (mb_qual^.mstring_cnt = 0) AND (mb_qual^.mlink_cnt = 0)
        THEN
            _eval_info.pev_wholeIO_pages := 2;
        (* DELETE_ALL_RECORDS in VKB61 *)
        (*ENDIF*) 
        IF  ( acv.a_costcheck )
        THEN
            BEGIN
            IF  ( csp_maxint4 - acv.a_costsum > _eval_info.pev_wholeIO_pages )
            THEN
                BEGIN
                IF  ( _eval_info.pev_wholeIO_pages = IS_UNDEFINED_GG07 )
                THEN
                    acv.a_costsum := cak_is_undefined
                ELSE
                    acv.a_costsum := acv.a_costsum + _eval_info.pev_wholeIO_pages;
                (*ENDIF*) 
                END
            ELSE
                acv.a_costsum := csp_maxint4;
            (*ENDIF*) 
&           ifdef trace
            t01int4( ak_strat, 'a_costsum   ', acv.a_costsum );
            t01int4( ak_strat, 'a_costwarn_v', acv.a_costlimit_value );
            t01int4( ak_strat, 'a_costwarn_v', acv.a_costwarn_value );
&           endif
            IF  ( NOT acv.a_intern_explain ) (* no EXPLAIN command *)
            THEN
                IF  (acv.a_costsum > acv.a_costlimit_value)
                THEN
                    a07_b_put_error( acv, e_costlimit_overflow, 1 )
                ELSE
                    IF  (acv.a_costsum > acv.a_costwarn_value) AND
                        (acv.a_comp_type <> at_odbc) AND
                        (acv.a_comp_type <> at_jdbc)
                    THEN
                        a07_b_put_error( acv, e_costwarning_overflow, 1 )
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        strat_rec.sr_strategy       := _gg_strategy.str_strategy;
        _gg_strategy.str_use_rowno  := strat_rec.sr_use_rowno;
        _gg_strategy.str_union_kind := 0;
        _gg_strategy.str_ordering   := strat_rec.sr_distinct_bytes;
        (* means that there are 4 bytes available for distinct they *)
        (* are not available only for GROUP BY without set-function *)
        a67_invkeylen( acv, _gg_strategy, strat_rec.sr_invkeylen );
        END;
    (*ENDIF*) 
    IF  ( acv.a_returncode = 0 )
    THEN
        WITH mb_qual^, mb_data^ DO
            BEGIN
            IF  ( mfirst_free > mb_st_max )
            THEN
                a07_b_put_error( acv, e_too_many_mb_stackentries, 1 )
            ELSE
                IF  mb_strat_len + _StratInfo_len > mb_strat_size
                THEN
                    a07_b_put_error( acv, e_too_many_mb_strat, 1 );
                (*ENDIF*) 
            (*ENDIF*) 
            IF  ( acv.a_returncode = 0 )
            THEN
                BEGIN
                IF  ( _gg_strategy.str_use_subquery = normal_subquery )
                THEN
                    msubquery := true;
                (*ENDIF*) 
                IF  ( strat_rec.sr_strategy in a70glob_fetch_strats )
                    AND
                    ( NOT acv.a_intern_explain )
                    AND (* no ... WITH LINK *)
                    ( acv.a_ex_kind <> only_parsing )
                THEN
                    BEGIN
                    g04spec_null_check( acv.a_mblock, _e );
                    IF  _e <> e_ok
                    THEN
                        a07_b_put_error( acv, _e, 1 )
                    ELSE
                        g04inbetween_change( acv.a_mblock,
                              _gg_strategy.str_res_possible );
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  ( acv.a_returncode = 0 )
                THEN
                    BEGIN
                    IF  ( _gg_strategy.str_strategy in
                        [ strat_more_than_one, strat_undecided, strat_no_result ] )
                    THEN
                        _mv_strat_len := STRATEGY_START_MXGG07
                    ELSE
                        _mv_strat_len := _StratInfo_len;
                    (*ENDIF*) 
                    IF  ( _gg_strategy.str_strategy in a70glob_inv_strats ) AND
                        ( isp_inv_only in _gg_strategy.str_inv_in_range.
                        siir_strat_props )
                    THEN
                        dmli.d_index_strat_poss := ind_no_inv;
                    (*ENDIF*) 
                    SAPDB_PascalMove ('VAK70 ',   1,
                          sizeof( _gg_strategy ), mb_strat_size,
                          @_gg_strategy, 1,
                          @acv.a_mblock.mb_strat^, mb_strat_len + 1,
                          _mv_strat_len,
                          acv.a_returncode);
                    mstrat_pos   := mfirst_free;
                    mstrat_cnt   := 1;
                    mfirst_free  := succ( mfirst_free );
                    g09StratStackentry( mb_st^[ mstrat_pos ], mb_strat_len + 1,
                          _mv_strat_len );
&                   IFDEF TRACE
                    t01execution_kind( ak_strat, 'a_ex_kind   ', acv.a_ex_kind );
                    t01bool( ak_strat, 'd_join      ', dmli.d_join );
                    t01bool( ak_strat, 'd_view      ', dmli.d_view );
&                   ENDIF
                    IF  ( dmli.d_qual_kind <> inv_only )
                        AND
                        ( _gg_strategy.str_strategy in a70glob_inv_strats )
                        AND
                        ( NOT ( dmli.d_join OR dmli.d_view ))
                        AND
                        (( acv.a_ex_kind <> only_parsing) OR acv.a_intern_explain )
                        AND
                        ( acv.a_returncode = 0 )
                    THEN
                        a71prepare_qual_on_index( acv, _gg_strategy.str_qual_kind );
                    (*ENDIF*) 
                    dmli.d_qual_kind := _gg_strategy.str_qual_kind;
                    IF  acv.a_intern_explain AND
                        ( acv.a_returncode = 0 )
                    THEN
                        a67_explain( acv, dmli, _gg_strategy,
                              mb_strat^, mb_strat_size,
                              mb_strat_len + 1 );
                    (*ENDIF*) 
                    mb_strat_len  := mb_strat_len  + _StratInfo_len;
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
&   IFDEF TRACE
    (*ENDIF*) 
    t01int4      (ak_strat, 'd_pos_result', dmli.d_pos_result);
    t01messblock (ak_strat, 'a70_strat_s2', acv.a_mblock);
&   ENDIF
    IF  ( acv.a_returncode = 0 )
        AND
        (( strat_rec.sr_strategy in a70glob_fetch_strats ) OR
        (strat_rec.sr_strategy = strat_no_result))
        AND
        NOT dmli.d_single (* no resname record for select into *)
        AND
        ( dmli.d_pos_result <> 0 ) (* no link *)
    THEN
        BEGIN
        WITH acv.a_resname_addr[ dmli.d_pos_result ]^.sresname DO
            BEGIN
            resstate := resstate - [ rs_result ] + [ rs_useinv ];
            CASE strat_rec.sr_strategy OF
                strat_inv_range_fetch :
                    resstate := resstate + [ rs_noresult ];
                strat_inv_range_merge_fetch :
                    resstate := resstate + [ rs_intinvnoresult ];
                strat_key_range_fetch,
                strat_no_result :
                    resstate := resstate - [ rs_useinv ] + [ rs_noresult ];
                OTHERWISE
                    BEGIN
                    END
                END;
            (*ENDCASE*) 
            END;
        (*ENDWITH*) 
        IF  ( NOT acv.a_intern_explain ) AND ( acv.a_ex_kind <> only_parsing )
        THEN
            BEGIN
            _ke := a01sysnullkey;
            _ke.stempid   := acv.a_curr_res_id;
            _ke.sentrytyp := cak_emessblock
                  ;
            mb_qual^.mtree.fileHandling_gg00 := dmli.d_globstate;
            mb_qual_len  := MB_PART1_HEAD_MXGG00;
            _h_data_len  := mb_strat_len;
            mb_strat_len  := mb_st^[ mb_qual^.mstrat_pos ].epos - 1;
            IF  ( mb_qual^.mqual_cnt > 0 ) AND
                ( mb_st^[ mb_qual^.mqual_pos ].etype = st_jump_output)
            THEN
                BEGIN
                _prev := mb_qual^.mqual_pos + 1;
                FOR _ix := mb_qual^.mqual_pos + 1 TO mb_qual^.mqual_pos +
                      mb_st^[ mb_qual^.mqual_pos ].epos - 1 DO
                    IF  ( mb_st^[ _ix ].etype = st_output )
                    THEN
                        BEGIN
                        IF  ( mb_st^[ _ix ].epos <=
                            cgg_rec_key_offset + dmli.d_keylen )
                        THEN
                            FOR _jx := _ix DOWNTO _prev DO
                                mb_st^[ _jx ].etype := st_dummy
                            (*ENDFOR*) 
                        ELSE
                            IF  ( mb_st^[ _ix ].eop_out = op_o_output_hold )
                                AND
                                ( mb_st^[ _ix + 1 ].epos <=
                                cgg_rec_key_offset + dmli.d_keylen )
                            THEN
                                mb_st^[ _ix ].eop_out := op_o_none;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        _prev := _ix + 1;
                        END;
                    (*ENDIF*) 
                (*ENDFOR*) 
                mb_st^[ mb_qual^.mqual_pos ].elen_var :=
                      cgg_rec_key_offset + dmli.d_keylen + 1;
&               ifdef trace
                t01int4( ak_sem, 'output_offse',
                      mb_st^[ mb_qual^.mqual_pos ].elen_var );
&               endif
                END;
            (*ENDIF*) 
            a10mblock_into_cache( acv, _ke, acv.a_mblock, d_release, _ibuf, _e );
            mb_strat_len := _h_data_len;
            IF  ( _e = e_ok )
            THEN
                BEGIN
                WITH _ibuf^.smessblock.mbr_mess_block DO
                    mb_st^[ mb_qual^.mstrat_pos ].etype := st_dummy;
                (*ENDWITH*) 
                a10add_sysinfo( acv, _ibuf, _e );
                END;
            (*ENDIF*) 
            IF  _e <> e_ok
            THEN
                a07_b_put_error( acv, _e, 1 );
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a70L2L3_strat_search (
            VAR acv          : tak_all_command_glob;
            VAR dmli         : tak_dml_info;
            VAR sparr        : tak_syspointerarr;
            VAR access_info  : tak70_strategy_record;
            VAR gg_strategy  : tgg07_StrategyInfo;
            VAR StratInfo_len: tsp00_Int2;
            morestratpos     : tsp00_Int4;
            VAR eval_info    : tak70_page_eval_rec;
            VAR L1_terms     : tak70_term;
            VAR order_fields : tak00_ord_fields;
            L1_pageIO        : tsp00_Int4;
            VAR L1_stratvalue: tsp00_Longreal);
 
VAR
      _actstratlen : tsp00_Int4;
 
BEGIN
&ifdef TRACE
t01strat_enum( ak_strat, 'L1 strategy ', gg_strategy.str_strategy );
t01int4( ak_strat, 'L1 page IO  ', L1_pageIO );
t01int4( ak_strat, 'trm_L1termcn', L1_terms.trm_L1termcnt );
&endif
IF  ( acv.a_returncode = 0 )
    AND
    ( L1_terms.trm_L1termcnt > 0 )
    AND
    (( gg_strategy.str_strategy <> strat_key_equal ) OR
    ( cs_L2_strategy in access_info.srec_config.cfg_switches ))
    AND
    ( NOT ( cs_L1_strategy in access_info.srec_config.cfg_switches ))
THEN
    ak70L2L3_strat_search( acv, dmli, sparr, access_info, gg_strategy,
          StratInfo_len, morestratpos, eval_info, L1_terms,
          order_fields, L1_pageIO, L1_stratvalue );
(*ENDIF*) 
;
IF  ( acv.a_returncode = 0 )
    AND
    ( gg_strategy.str_strategy in a70glob_inv_strats )
THEN
    BEGIN
    dmli.d_dist_optim  := a71code_distinct_optim( gg_strategy );
    IF  ( isp_inv_only in gg_strategy.str_inv_in_range.siir_strat_props )
    THEN
        BEGIN
        (* we have an only index strategy   *)
        gg_strategy.str_qual_kind := inv_only;
        (* manipulate stack                 *)
        a723only_index_stack( acv,
              sparr.pbasep^.sbase.btreeid.fileTabId_gg00, gg_strategy );
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
IF  ( acv.a_mblock.mb_qual^.mstrat_pos > 0 ) AND
    ( acv.a_mblock.mb_qual^.mstrat_cnt = 1 )
THEN
    _actstratlen :=
          acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mstrat_pos ].epos - 1
ELSE
    _actstratlen := acv.a_mblock.mb_strat_len;
(*ENDIF*) 
;
(* error handling *)
IF  ( _actstratlen + StratInfo_len > acv.a_mblock.mb_strat_size )
THEN
    IF  ( _actstratlen + STRATEGY_START_MXGG07 <= acv.a_mblock.mb_strat_size )
    THEN
        BEGIN
        IF  ( g01vtrace.vtrStrategy_gg00 )
        THEN
            g041c30_to_trace ( acv.a_transinf.tri_trans,
                  '!!! LOW SPACE IN MB_STRAT !!! ' );
        (*ENDIF*) 
        gg_strategy.str_strategy  := strat_key_range;
        gg_strategy.str_cnt_strat := 1;
        StratInfo_len             := STRATEGY_START_MXGG07;
        END
    ELSE
        a07_b_put_error( acv, e_too_many_mb_strat, 1 );
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a70strategy (
            VAR acv          : tak_all_command_glob;
            VAR dmli         : tak_dml_info;
            VAR gg_strategy  : tgg07_StrategyInfo;
            VAR StratInfo_len: tsp00_Int2;
            VAR eval_info    : tak70_page_eval_rec;
            config           : tak00_access_configuration);
 
VAR
      _ok             : boolean;
      _L1_pageIO      : tsp00_Int4;
      _L1_stratvalue  : tsp00_Longreal;
      _sparr          : tak_syspointerarr;
      _basetable      : tgg00_Surrogate;
      _L1_terms       : tak70_term;
      _access_info    : tak70_strategy_record;
      _order_fields   : tak00_ord_fields;
 
BEGIN
IF  ( NOT ( g01vtrace.vtrStrategy_gg00 ) AND ( cs_trace in config.cfg_switches ))
THEN
    BEGIN
    g01vtrace.vtrStrategy_gg00 := true;
    g01vtrace.vtrSession_gg00  := acv.a_transinf.tri_trans.trSessionId_gg00;
    END;
(*ENDIF*) 
_order_fields := dmli.d_order_or_group_cols^;
;
gg_strategy.str_key_order_support := false;
gg_strategy.str_out_keyseqlen     := NOT_SEQUENCED_GG07;
;
&ifdef trace
IF  ( dmli.d_sparr.pbasep^.sbase.btablen <> NIL )
THEN
    t01knl_identifier( ak_strat, 'view/table  ',
          dmli.d_sparr.pbasep^.sbase.btablen^ );
(*ENDIF*) 
t01messblock( ak_strat, 'A70STRATEGY ', acv.a_mblock );
a725output_gg_strat( ak_strat, 'gg_strategy ', gg_strategy );
t01execution_kind( ak_strat, 'init ex kind', acv.a_init_ex_kind );
t01execution_kind( ak_strat, 'exec kind   ', acv.a_ex_kind );
t01int4( ak_strat, 'StratInfo_le', StratInfo_len );
t01columnset( ak_strat, 'expr updcols', dmli.d_foundset );
&endif
IF  ( dmli.d_sparr.pbasep^.sbase.btablekind = tonebase )
THEN
    BEGIN
    _basetable := dmli.d_sparr.pbasep^.sbase.btreeid.fileTabId_gg00;
    a10rel_sysinfo( dmli.d_sparr.pbasep );
    a06_systable_get( acv, d_fix, _basetable, dmli.d_sparr.pbasep,
          c_get_all, _ok );
    IF  ( NOT _ok )
    THEN
        a07_b_put_error( acv, e_old_fileversion, 1 )
    ELSE
        BEGIN
&       ifdef trace
        t01knl_identifier( ak_strat, 'base table  ',
              dmli.d_sparr.pbasep^.sbase.btablen^ );
&       endif
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
_sparr := dmli.d_sparr;
IF  ( acv.a_mblock.mb_qual^.mfirst_free > acv.a_mblock.mb_st_max )
THEN
    a07_b_put_error( acv, e_too_many_mb_stackentries, 1 )
ELSE
    IF  ( acv.a_returncode = 0 )
    THEN
        BEGIN
        gg_strategy.str_inv_in_range.siir_invroot := NIL_PAGE_NO_GG00;
        _access_info := a70_glob_zstrat_rec;
        _access_info.srec_config := config;
        ;
        ak70set_given_query_props( acv, dmli, _sparr, gg_strategy,
              _order_fields, _access_info.srec_query_prop );
        ;
        a71adjust_configuration( dmli, _access_info );
        ;
        IF  ( g01vtrace.vtrStrategy_gg00 )
        THEN
            BEGIN
            g041name_to_trace( acv.a_transinf.tri_trans,
                  '>> A70STRATEGY >> ' );
            IF  ( _sparr.pbasep^.sbase.btablen <> NIL )
            THEN
                BEGIN
                a727trace_tablename( acv.a_transinf.tri_trans,
                      'base table  ', _sparr.pbasep^.sbase.btablen^ );
                END;
            (*ENDIF*) 
            b120MessBlockTrace(acv.a_transinf.tri_trans, ak_send, acv.a_mblock);
            a81trace_access_config( acv.a_transinf.tri_trans,
                  _access_info.srec_config );
            a727trace_query_prop( acv.a_transinf.tri_trans,
                  _access_info.srec_query_prop );
            END;
        (*ENDIF*) 
        ;
        (* initialize cost values *)
        eval_info.pev_wholeIO_pages:= IS_UNDEFINED_GG07;
        eval_info.pev_readIO_pages := IS_UNDEFINED_GG07;
        eval_info.pev_readIO_rows  := IS_UNDEFINED_GG07;
        ;
        _L1_terms.trm_L1termcnt   := 0; (* initial value = no strategies  *)
        a724all_L1_terms( acv, dmli, _access_info, _L1_terms,
              gg_strategy.str_use_subquery );
        (* ================================================ *)
        (* ak70all_L1_terms gathers all level-1-predicates  *)
        (* into _access_info, level-1-terms into _L1_terms  *)
        (* ================================================ *)
        IF  NOT ( qp_no_result_set in _access_info.srec_query_prop.qps_switches )
        THEN
            BEGIN
            a723analyse_used_cols( acv, dmli, _access_info, gg_strategy );
&           ifdef trace
            a725output_query_prop( ak_strat, _access_info.srec_query_prop );
&           endif
            IF  ( g01vtrace.vtrStrategy_gg00 )
            THEN
                BEGIN
                a727trace_query_prop( acv.a_transinf.tri_trans,
                      _access_info.srec_query_prop );
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  ( acv.a_returncode = 0 )
        THEN
            BEGIN
            (* ignore qp_missing_value at the moment; we could found *)
            (* strat_key_equal and for this strat parameters are of *)
            (* no interest*)
            a70L1_strat_search( acv, _sparr, _access_info, gg_strategy,
                  StratInfo_len, eval_info, _order_fields, _L1_pageIO, _L1_stratvalue );
            ;
            IF  ( qp_missing_value in _access_info.srec_query_prop.qps_switches )
            THEN
                BEGIN
                (* full stop, store collected access information *)
                a721transfer_parse_info( acv, _access_info, _L1_terms,
                      _order_fields, bckp_save );
                gg_strategy.str_strategy := strat_undecided;
                StratInfo_len            := STRATEGY_START_MXGG07;
                eval_info.pev_wholeIO_pages := IS_UNDEFINED_GG07;
                END
            ELSE
                BEGIN
                a70L2L3_strat_search( acv, dmli, _sparr,
                      _access_info, gg_strategy, StratInfo_len,
                      (* get place for strategy *)
                      acv.a_mblock.mb_strat_len + 1 + STRATEGY_START_MXGG07,
                      eval_info, _L1_terms, _order_fields, _L1_pageIO, _L1_stratvalue );
                END;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
&           ifdef trace
            t01int4( ak_strat, 'returncode  ',
                  acv.a_returncode );
&           endif
            END;
        (*ENDIF*) 
        IF  ( acv.a_returncode = 0 )
            AND
            ( acv.a_ex_kind <> only_executing )
            AND
            (( gg_strategy.str_strategy in a70glob_build_strats ) OR
            (gg_strategy.str_strategy = strat_undecided) AND
            (gg_strategy.str_build_result = true) )
        THEN
            BEGIN
            CASE acv.a_precomp_info_byte OF
                csp1_p_mass_select_found :
                    acv.a_precomp_info_byte := csp1_p_reuse_mass_select_found;
                csp1_p_select_for_update_found :
                    acv.a_precomp_info_byte := csp1_p_reuse_update_sel_found;
                csp1_p_mselect_found :
                    acv.a_precomp_info_byte := csp1_p_reuse_mselect_found;
                csp1_p_for_upd_mselect_found :
                    acv.a_precomp_info_byte := csp1_p_reuse_upd_mselect_found;
                OTHERWISE
                    BEGIN
                    END;
                END;
            (*ENDCASE*) 
            END;
        (*ENDIF*) 
        dmli.d_qual_kind := gg_strategy.str_qual_kind;
        k720ref_statistic( acv.a_mblock, dmli.d_strat_info, gg_strategy );
        (* PTS 1112419 reset inv root for only index strategies
              to avoid problems with invalid roots after
              drop index or unqualified delete *)
        IF  (acv.a_ex_kind = only_parsing) AND
            ( gg_strategy.str_strategy in a70glob_inv_strats ) AND
            ( isp_inv_only in gg_strategy.str_inv_in_range.siir_strat_props )
        THEN
            gg_strategy.str_inv_in_range.siir_invroot := NIL_PAGE_NO_GG00;
        (*ENDIF*) 
        ;
&       ifdef TRACE
        a725output_end_strat( ak_strat, 'ENDSTRAT >>>', gg_strategy,
              eval_info, StratInfo_len );
&       endif
        END;
    (*ENDIF*) 
(*ENDIF*) 
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    a727trace_strategy_text( acv.a_transinf.tri_trans,
          'CHOOSEN     ',  gg_strategy.str_strategy );
    g041name_to_trace( acv.a_transinf.tri_trans,
          '<< A70STRATEGY << ' );
    IF  ( cs_trace in config.cfg_switches )
    THEN
        BEGIN
        g01vtrace.vtrStrategy_gg00         := false;
        g01vtrace.vtrSession_gg00.ci4_gg00 := cgg_nil_session;
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a70L1_strat_search (
            VAR acv          : tak_all_command_glob;
            VAR sparr        : tak_syspointerarr;
            VAR access_info  : tak70_strategy_record;
            VAR gg_strategy  : tgg07_StrategyInfo;
            VAR StratInfo_len: tsp00_Int2;
            VAR eval_info    : tak70_page_eval_rec;
            VAR order_fields : tak00_ord_fields;
            VAR L1_pageIO    : tsp00_Int4; (* out *)
            VAR L1_stratvalue: tsp00_Longreal );
 
VAR
      _chosen_strat   : tak70_one_strat;
      _raw_key_access : tak70_key_access;
 
BEGIN
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    g041c30_to_trace ( acv.a_transinf.tri_trans,
          '>> A70L1_STRAT_SEARCH >>      ' );
(*ENDIF*) 
;
(* save original/raw key access data *)
_raw_key_access := access_info.srec_keyaccess;
;
_chosen_strat.ostr_filler1 := ' ';
_chosen_strat.ostr_filler2 := 0;
;
a720strategy_decision( acv, sparr, access_info, gg_strategy,
      _chosen_strat, order_fields, StratInfo_len, true );
(* initialize Level1 strategy *)
gg_strategy.str_strategy := _chosen_strat.ostr_strategy;
gg_strategy.str_raw      := _chosen_strat.ostr_raw;
;
L1_pageIO     := _chosen_strat.ostr_wholeIO_pages;
L1_stratvalue := _chosen_strat.ostr_strat_value;
eval_info.pev_wholeIO_pages := _chosen_strat.ostr_wholeIO_pages;
eval_info.pev_readIO_pages  := _chosen_strat.ostr_readIO_pages;
eval_info.pev_readIO_rows   := _chosen_strat.ostr_readIO_rows;
;
&ifdef trace
t01name( ak_strat, 'Level-1-strategy  ' );
a725output_one_strat( ak_strat, _chosen_strat );
&endif
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    BEGIN
    a727trace_one_strat( acv.a_transinf.tri_trans,
          'LEVEL-1-STRATEGY  ', _chosen_strat );
    END;
(*ENDIF*) 
;
IF  ( qp_no_result_set in access_info.srec_query_prop.qps_switches )
THEN
    gg_strategy.str_res_possible := false;
(*ENDIF*) 
;
(* restore original/raw key access data *)
(* for L2/L3 strategy search            *)
access_info.srec_keyaccess := _raw_key_access;
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak70L2L3_strat_search (
            VAR acv          : tak_all_command_glob;
            VAR dmli         : tak_dml_info;
            VAR sparr        : tak_syspointerarr;
            VAR access_info  : tak70_strategy_record;
            VAR gg_strategy  : tgg07_StrategyInfo;
            VAR StratInfo_len: tsp00_Int2;
            actstratpos      : tsp00_Int4;
            VAR eval_info    : tak70_page_eval_rec;
            VAR L1_terms     : tak70_term;
            VAR order_fields : tak00_ord_fields;
            L1_pageIO        : tsp00_Int4;
            VAR L1_stratvalue: tsp00_Longreal);
 
VAR
      _build_demand     : boolean;
      _ix               : tsp00_Int2;
      _combination_stat : tak70_l2l3_strat_status;
      _nextstratpos     : tsp00_Int4;
      _used_strats      : tak70_all_strat;
 
BEGIN
IF  ( g01vtrace.vtrStrategy_gg00 )
THEN
    g041c30_to_trace ( acv.a_transinf.tri_trans,
          'AK70L2L3_STRAT_SEARCH         ' );
(*ENDIF*) 
IF  (( L1_terms.trm_L1terms[ 0 ].l1t_is_usable ) AND
    ( L1_terms.trm_L1terms[ 0 ].l1t_L2pL3tcnt > 0 ))
THEN
    BEGIN
&   ifdef TRACE
    a725L1_terms_output( ak_strat, L1_terms );
&   endif
    _used_strats.ast_cntstrats      := 0;
    _used_strats.ast_wholeIO_pages  := 0;
    _used_strats.ast_readIO_pages   := 0;
    _used_strats.ast_readIO_rows    := 0;
    _used_strats.ast_key_range_poss :=
          ( gg_strategy.str_use_subquery in [ no_subquery, query_in_subq ] );
    _used_strats.ast_init_key_range := true;
    FOR _ix := 0 TO MAX_COLPOSARR_IDX_GG07 DO
        BEGIN
        _used_strats.ast_key_range.skir_keystart[ _ix ]  := 0;
        _used_strats.ast_key_range.skir_keystop [ _ix ]  := 0;
        END;
    (*ENDFOR*) 
    _used_strats.ast_key_range.skir_IN_SUBQ_stpos := IS_UNDEFINED_GG07;
    _used_strats.ast_key_range.skir_inelemcnt     := IS_UNDEFINED_GG07;
    _used_strats.ast_key_range.skir_strat_props   := [];
    _nextstratpos := actstratpos;
    ;
    (* set processing instructions *)
    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 ];
    _build_demand :=
          ( qp_build_result in access_info.srec_query_prop.qps_switches );
    access_info.srec_query_prop.qps_switches :=
          access_info.srec_query_prop.qps_switches + [ qp_build_result ];
    access_info.srec_query_prop.qps_switches :=
          access_info.srec_query_prop.qps_switches + [ qp_inv_only_impossible ];
    IF  ( cs_L2_range_strategy in access_info.srec_config.cfg_switches )
    THEN
        _combination_stat := lss_one_key_range
    ELSE
        _combination_stat := lss_several_strats;
    (*ENDIF*) 
    ;
    a726combine_terms( acv, dmli, sparr, access_info, gg_strategy,
          _used_strats, order_fields, L1_terms,
          _nextstratpos, 0, 0,
          L1_pageIO, _combination_stat );
    ;
    (* neutralize build instruction if possible *)
    IF  ( NOT _build_demand )
    THEN
        access_info.srec_query_prop.qps_switches :=
              access_info.srec_query_prop.qps_switches - [ qp_build_result ];
    (*ENDIF*) 
    IF  ( qp_missing_value in access_info.srec_query_prop.qps_switches )
    THEN
        BEGIN
        IF  ( acv.a_ex_kind = only_executing )
        THEN
            BEGIN
            IF  ( dmli.d_corr = no_correlation )
            THEN
                a07ak_system_error(acv, 70, 1 )
            ELSE
                BEGIN
                (* =================================== *)
                (* decision : use Level1 strategy      *)
                (* =================================== *)
                (* nothing to do, gg_strategy already contains L1-strategy *)
&               ifdef TRACE
                t01name( ak_strat, 'use Level1 strat X' );
                t01strat_enum( ak_strat, 'strategy is ',
                      gg_strategy.str_strategy );
&               endif
                END;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            (* parameters on L2/L3 predicates found *)
            a721transfer_parse_info( acv, access_info, L1_terms,
                  order_fields, bckp_save );
            gg_strategy.str_strategy := strat_undecided;
            StratInfo_len            := STRATEGY_START_MXGG07;
            eval_info.pev_wholeIO_pages := IS_UNDEFINED_GG07;
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  ( acv.a_returncode = 0 )
        THEN
            BEGIN
            IF  ( _combination_stat = lss_use_L1_strat )
            THEN
                BEGIN
                (* =================================== *)
                (* decision : use Level1 strategy      *)
                (* =================================== *)
                (* nothing to do, gg_strategy already contains L1-strategy *)
&               ifdef TRACE
                t01name( ak_strat, 'use Level1 strat  ' );
                t01strat_enum( ak_strat, 'strategy is ',
                      gg_strategy.str_strategy );
&               endif
                END;
            (*ENDIF*) 
            IF  ( _combination_stat = lss_one_key_range )
            THEN
                BEGIN
                a720decide_L2_range( acv, sparr, access_info,
                      gg_strategy, StratInfo_len,
                      eval_info, L1_pageIO, L1_stratvalue,
                      _used_strats.ast_key_range);
                END;
            (*ENDIF*) 
            ;
            IF  ( _combination_stat = lss_several_strats )
            THEN
                BEGIN
                IF  ( _used_strats.ast_cntstrats > 0 )
                THEN
                    BEGIN
                    (* =================================== *)
                    (* decision : several strategies       *)
                    (*            will be used             *)
                    (* =================================== *)
                    (* all stategies are build strategies !! *)
                    gg_strategy.str_strategy     := strat_more_than_one;
                    gg_strategy.str_cnt_strat    := _used_strats.ast_cntstrats;
                    StratInfo_len := _nextstratpos - actstratpos +
                          STRATEGY_START_MXGG07;
&                   ifdef TRACE
                    a725output_more_strat( acv, ak_strat, gg_strategy, _used_strats );
&                   endif
                    IF  ( _used_strats.ast_cntstrats = 1 )
                    THEN
                        (* all strategies are nested strategies *)
                        BEGIN
                        gg_strategy.str_strategy :=
                              _used_strats.ast_strats[ 1 ].osr_strategy;
                        SAPDB_PascalMove('VAK70 ',   2,
                              acv.a_mblock.mb_strat_size,
                              sizeof( gg_strategy.str_raw ),
                              @acv.a_mblock.mb_strat^,
                              _used_strats.ast_strats[ 1 ].osr_stratpos + 2,
                              @gg_strategy.str_raw,
                              1,
                              _used_strats.ast_strats[ 1 ].osr_stratlen,
                              acv.a_returncode );
                        StratInfo_len := STRATEGY_START_MXGG07 +
                              _used_strats.ast_strats[ 1 ].osr_stratlen;
                        a71check_fetch_optimization( acv,
                              access_info.srec_config,
                              access_info.srec_query_prop,
                              gg_strategy, gg_strategy.str_strategy,
                              gg_strategy.str_raw );
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
&                   ifdef trace
                    t01name ( ak_strat, 'no poss strats -->' );
                    t01sname( ak_strat, 'no resultset' );
&                   endif
                    gg_strategy.str_strategy     := strat_no_result;
                    gg_strategy.str_res_possible := false;
                    StratInfo_len                := STRATEGY_START_MXGG07;
                    END;
                (*ENDIF*) 
                eval_info.pev_wholeIO_pages:= _used_strats.ast_wholeIO_pages;
                eval_info.pev_readIO_pages := _used_strats.ast_readIO_pages;
                eval_info.pev_readIO_rows  := _used_strats.ast_readIO_rows;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak70set_given_query_props (
            VAR acv         : tak_all_command_glob;
            VAR dmli        : tak_dml_info;
            VAR sparr       : tak_syspointerarr;
            VAR gg_strategy : tgg07_StrategyInfo;
            VAR order_fields: tak00_ord_fields;
            VAR qprop       : tak70_query_properties);
 
VAR
      _check_st_result  : boolean;
      _i                : tsp00_Int2;
 
BEGIN
IF  ( gg_strategy.str_build_result )
    OR
    ((NOT dmli.d_join ) AND ( acv.a_from_select ))
THEN
    (* could be set while executing *)
    qprop.qps_switches := qprop.qps_switches + [ qp_build_result ];
(*ENDIF*) 
;
IF  dmli.d_view (* avoid stack change *)
    OR
    ( acv.a_mblock.mb_qual^.mqual_pos = 0 )
    OR
    ( acv.a_mblock.mb_qual^.mqual_cnt = 0 )
    OR
    ( dmli.d_index_strat_poss = ind_no_inv )
    OR
    ( acv.a_mblock.mb_type = m_update )
THEN
    qprop.qps_switches := qprop.qps_switches + [ qp_inv_only_impossible ];
(*ENDIF*) 
;
IF  NOT dmli.d_join
THEN
    BEGIN
    IF  ( gg_strategy.str_selinto )
        OR
        (( abs(gg_strategy.str_rowno) < cgg04_valid_rowno_pos )
        AND
        ( gg_strategy.str_rowno <> cgg04_no_rowno_predicate ))
        OR
        (( acv.a_mblock.mb_type2 = mm_with_functions ) AND
        ( dmli.d_group_cols.ocntord = 0 ))
    THEN
        BEGIN
        (* i.e. SELECT INTO , COUNT( * ) *)
        qprop.qps_switches := qprop.qps_switches + [ qp_build_result ];
        qprop.qps_switches := qprop.qps_switches + [ qp_given_rescnt ];
        qprop.qps_rescnt   := 1;
        END
    ELSE
        BEGIN
        IF  ( abs(gg_strategy.str_rowno) >= cgg04_valid_rowno_pos )
            (* If a ROWNO predicate in a join is given,         *)
            (* optimizer isn't allowed to take it into account  *)
            (* for cost calculating of single table access      *)
        THEN
            a71set_rescnt( acv, sparr, gg_strategy.str_rowno, qprop );
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
;
IF  ( gg_strategy.str_use_order ) AND ( order_fields.ocntord > 0 ) AND
    (* NOT ( implizit ORDER BY (e.g. subquery ) ) *)
    NOT (( order_fields.ocntord = 1 ) AND ( order_fields.ofield[ 1 ].ofstno = 0 ))
THEN
    BEGIN
    _i := 1;
    qprop.qps_switches := qprop.qps_switches + [ qp_check_order_support ];
    WHILE  (( qp_check_order_support in qprop.qps_switches ) AND
          ( _i <= order_fields.ocntord ) ) DO
        BEGIN
        IF  ( order_fields.ofield[ _i ].offno <= 0 )
            (* offno < 0 => used column but with internal expressions  *)
            (* offno = 0 => column with expression or order by fieldno *)
        THEN
            (* order support by usage of index/key ordering *)
            (* can't be realized                            *)
            (* we have to build result to achieve ordering  *)
            (* without qp_check_order_support no access path support *)
            (* ordering, hence result is written                     *)
            qprop.qps_switches := qprop.qps_switches - [ qp_check_order_support ];
        (*ENDIF*) 
        IF  ( order_fields.ocntord = 1 )
        THEN
            BEGIN
            (* check whether ordering by user defined function is required. *)
            (* in that case there's a chance that a function based index    *)
            (* supports the required ordering                               *)
            ;
            _i := order_fields.ofield[ 1 ].ofstno - 1;
            IF  ( acv.a_mblock.mb_st^[ _i ].etype        = st_build_in_func   ) AND
                ( acv.a_mblock.mb_st^[ _i ].eop_build_in = op_b_user_def_func )
            THEN
                BEGIN
                (* order by user defined function required, check if only    *)
                (* columns of current table are used as function parameters. *)
                (* if this is not true we can exclude  that a function based *)
                (* may used for ordering                                  *)
                ;
                _i               := _i - 2; (* skip st_surrogate *)
                _check_st_result := true;
                qprop.qps_switches := qprop.qps_switches + [ qp_check_order_support ];
                WHILE ( _i >= acv.a_mblock.mb_qual^.mqual_pos ) AND
                      ( acv.a_mblock.mb_st^[_i].etype <> st_output ) DO
                    BEGIN
                    IF  ( _check_st_result AND
                        ( acv.a_mblock.mb_st^[_i].etype <> st_result )) OR
                        ( NOT _check_st_result AND
                        NOT ( acv.a_mblock.mb_st^[_i].etype in
                        [ st_fixkey, st_varkey, st_fixcol, st_varcol ] ))
                    THEN
                        BEGIN
                        qprop.qps_switches := qprop.qps_switches - [ qp_check_order_support ];
                        _i := 0; (* exit loop *)
                        END
                    ELSE
                        BEGIN
                        IF  _check_st_result                                       AND
                            (_i >= acv.a_mblock.mb_qual^.mqual_pos)                AND
                            (acv.a_mblock.mb_st^[_i - 1].etype = st_build_in_func) AND
                            (acv.a_mblock.mb_st^[_i - 1].eop_build_in = op_b_uni_trans)
                        THEN
                            _i := _i - 1;
                        (*ENDIF*) 
                        _check_st_result := NOT _check_st_result;
                        _i               := _i - 1;
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDWHILE*) 
&               ifdef trace
                t01bool (ak_strat, 'fctindex ord', qp_check_order_support in
                      qprop.qps_switches);
&               endif
                _i := order_fields.ocntord; (* exit loop *)
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        _i := succ( _i );
        END;
    (*ENDWHILE*) 
    END;
(*ENDIF*) 
;
IF  ( ftsArchive_egg00 in sparr.pbasep^.sbase.btreeid.fileType_gg00 )
THEN
    BEGIN
    qprop.qps_switches := qprop.qps_switches + [ qp_archive_access ];
    END;
&ifdef trace
(*ENDIF*) 
a725output_query_prop( ak_strat, qprop );
&endif
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
