.nf
 
 
    ========== licence begin  GPL
    Copyright (C) 2000 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 by SAP AG, 1999
SAP Database Technology
 
Release :      Date : 2000-11-22
*****************************************************
modname : VAK681
changed : 2000-11-22
module  : Join_Select_help_routines
 
Author  : ElkeZ
Created : 1985-10-16
Pretty  : 2002-08-01
*****************************************************
 
Purpose : The module determines the most favourable order for
          table processing and sends the Mess-Buffers that have
          been built by VAK69 to KB
 
Define  :
 
        PROCEDURE
              a681jnew_seq (
                    VAR acv                 : tak_all_command_glob;
                    VAR dmli                : tak_dml_info;
                    VAR table_stats         : tak68_table_stats;
                    VAR jtrans              : tak68_join_transitions;
                    VAR sequence_info       : tak68_sequence_info;
                    VAR jinfos              : tak68_joininfos;
                    VAR res_info            : tak68_result_info;
                    VAR mul_tabs            : tak68_mult_tabs;
                    VAR lastsuccession      : tak68_lastsuccession);
 
        FUNCTION
              a681tmp_table_length (
                    VAR dmli    : tak_dml_info;
                    VAR jinfos  : tak68_joininfos;
                    tabno       : integer) : integer;
 
        PROCEDURE
              a681opt_conditions (
                    VAR acv    : tak_all_command_glob;
                    VAR dmli   : tak_dml_info;
                    VAR series : tak68_sequence;
                    VAR jinfos : tak68_joininfos;
                    VAR eq_rec : tak68_eq_record);
 
        FUNCTION
              a681keval_key_kind (
                    VAR acv       : tak_all_command_glob;
                    VAR dmli      : tak_dml_info;
                    VAR mul_tabs  : tak68_mult_tabs;
                    pos_jarr      : integer;
                    pos_jrec      : integer;
                    is_join_value : boolean) : tak68_one_jointype;
 
        PROCEDURE
              a681key_sort_joinarr (
                    VAR acv      : tak_all_command_glob;
                    VAR dmli     : tak_dml_info;
                    VAR series   : tak68_sequence;
                    ser_pos      : integer;
                    VAR sort_pos : integer;
                    VAR mul_tabs : tak68_mult_tabs);
 
        PROCEDURE
              a681lowest_multiple_strat (
                    VAR jtrans          : tak68_join_transitions;
                    VAR succession      : tak68_succession;
                    VAR mul_tabs        : tak68_mult_tabs;
                    src_table           : tsp00_Int2;
                    dst_table           : tsp00_Int2;
                    VAR best_srctab     : tsp00_Int2;
                    VAR best_jtype      : tak68_one_jointype;
                    VAR best_multiplier : tsp_int4;
                    VAR best_fieldcnt   : tsp_int4;
                    processed_table_cnt : tsp00_Int2;
                    update_jtrans       : boolean);
 
        FUNCTION
              a681ieval_inv_kind (
                    VAR acv          : tak_all_command_glob;
                    VAR dmli         : tak_dml_info;
                    VAR mul_tabs     : tak68_mult_tabs;
                    pos_jarr         : integer;
                    pos_jrec         : integer;
                    is_join_value    : boolean) : tak68_one_jointype;
 
        PROCEDURE
              a681inv_sort_joinarr (
                    VAR acv      : tak_all_command_glob;
                    VAR dmli     : tak_dml_info;
                    VAR jinfos   : tak68_joininfos;
                    VAR series   : tak68_sequence;
                    ser_pos      : integer;
                    VAR sort_pos : integer;
                    VAR mul_tabs : tak68_mult_tabs);
 
        PROCEDURE
              a681sort_conditions (
                    VAR acv    : tak_all_command_glob;
                    VAR dmli   : tak_dml_info;
                    VAR series : tak68_sequence);
 
        PROCEDURE
              a681test_outer_qualification (
                    VAR acv     : tak_all_command_glob;
                    VAR dmli    : tak_dml_info;
                    VAR jinfos  : tak68_joininfos);
 
        FUNCTION
              a681_outer_join_error_found (
                    VAR acv  : tak_all_command_glob;
                    VAR dmli : tak_dml_info) : boolean;
 
        FUNCTION
              a681outer_join_tab_is_curr_tab (
                    VAR dmli : tak_dml_info;
                    curr_tab : integer) : boolean;
 
        PROCEDURE
              a681check_outer_join (
                    VAR acv  : tak_all_command_glob;
                    VAR dmli : tak_dml_info);
 
        PROCEDURE
              a681tr_multabs (
                    VAR acv      : tak_all_command_glob;
                    VAR mul_tabs : tak68_mult_tabs;
                    cntfrom      : integer);
 
        PROCEDURE
              a681tr_tabstats (
                    VAR acv           : tak_all_command_glob;
                    VAR dmli          : tak_dml_info;
                    VAR table_stats   : tak68_table_stats;
                    VAR res_info      : tak68_result_info;
                    cntfrom           : integer;
                    debug             : boolean);
 
        PROCEDURE
              a681tr_joinvals (
                    VAR acv      : tak_all_command_glob;
                    VAR jtrans   : tak68_join_transitions;
                    starttab     : integer;
                    stoptab      : integer;
                    table_cnt    : integer);
 
.CM *-END-* define --------------------------------------
***********************************************************
 
Use     :
 
        FROM
              AK_Identifier_Handling : VAK061;
 
        PROCEDURE
              a061get_colname (VAR col_info : tak00_columninfo;
                    VAR colname  : tsp_knl_identifier);
 
      ------------------------------ 
 
        FROM
              AK_semantic_scanner_tools : VAK05;
 
        PROCEDURE
              a05qualification_test (VAR acv : tak_all_command_glob;
                    VAR m          : tgg_mess_block;
                    result_wanted  : boolean;
                    check_new_rec  : boolean;
                    error_pos      : integer;
                    VAR rec        : tgg_rec_buf;
                    VAR result_buf : tsp_buf;
                    resultBufSize  : tsp00_Int4;
                    VAR result_len : integer);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK07;
 
        PROCEDURE
              a07ak_system_error (VAR acv : tak_all_command_glob;
                    modul_no : integer;
                    id       : integer);
 
        PROCEDURE
              a07_b_put_error (VAR acv : tak_all_command_glob;
                    b_err   : tgg_basis_error;
                    err_code : tsp_int4);
 
      ------------------------------ 
 
        FROM
              AK_Index : VAK24;
 
        PROCEDURE
              a24init_index_scan (VAR acv : tak_all_command_glob;
                    VAR tabid          : tgg_surrogate;
                    VAR index_scan_rec : tak_index_scan_record);
 
        PROCEDURE
              a24finish_index_scan (VAR acv : tak_all_command_glob;
                    VAR index_scan_rec : tak_index_scan_record);
 
        FUNCTION
              a24next_named_index (VAR acv : tak_all_command_glob;
                    VAR index_scan_rec : tak_index_scan_record) : boolean;
 
      ------------------------------ 
 
        FROM
              AK_universal_show_tools : VAK40;
 
        PROCEDURE
              a40sequence_expl_row (VAR acv : tak_all_command_glob;
                    VAR line : tsp_line;
                    change_to_unicode : boolean);
 
      ------------------------------ 
 
        FROM
              Select_List : VAK61;
 
        PROCEDURE
              a61_rel_old_table (VAR acv : tak_all_command_glob;
                    VAR dmli : tak_dml_info;
                    i        : integer);
 
      ------------------------------ 
 
        FROM
              Join_Select: VAK680;
 
        PROCEDURE
              a680_first_table_cost (
                    VAR sequence_info : tak68_sequence_info;
                    VAR table_stats   : tak68_table_stats;
                    first_table       : integer;
                    VAR res_info      : tak68_result_info);
 
        PROCEDURE
              a680standard_cost (
                    VAR acv            : tak_all_command_glob;
                    VAR dmli           : tak_dml_info;
                    VAR table_stats    : tak68_table_stats;
                    VAR jtrans         : tak68_join_transitions;
                    VAR jinfos         : tak68_joininfos;
                    VAR res_info       : tak68_result_info;
                    VAR mul_tabs       : tak68_mult_tabs;
                    VAR lastsuccession : tak68_lastsuccession;
                    VAR lowest_costs   : tsp_longreal;
                    VAR sequence_info  : tak68_sequence_info;
                    succ_length        : tsp00_Int2;
                    update_jtrans      : boolean);
 
        PROCEDURE
              a680next_join_eval (
                    VAR jtrans             : tak68_join_transition;
                    VAR table_stat         : tak68_one_table_stat;
                    VAR counted_multiplier : tsp_longreal;
                    VAR reverse_multiplier : tsp_longreal;
                    VAR newsum             : tsp_longreal;
                    VAR newpages           : tsp_longreal;
                    old_recs_per_respage   : integer;
                    recs_per_respage       : integer;
                    is_distinct            : boolean);
 
      ------------------------------ 
 
        FROM
              join_trace_routines : VAK683;
 
        PROCEDURE
              a683trans_to_line (
                    VAR acv         : tak_all_command_glob;
                    VAR dmli        : tak_dml_info;
                    tableno         : tsp_int2;
                    colno           : tsp_int2;
                    VAR line        : tsp_dataline;
                    maxlen          : tsp_int2;
                    VAR res_state   : boolean);
&       ifdef TRACE
 
        PROCEDURE
              a683trace_jointype (
                    debug : tgg00_Debug;
                    desc  : tsp_sname;
                    jtype : tak68_one_jointype);
 
        PROCEDURE
              a683_output (
                    debug    : tgg00_Debug;
                    VAR dmli : tak_dml_info);
 
        PROCEDURE
              a683multabs_trace (
                    debug        : tgg00_Debug;
                    VAR mul_tabs : tak68_mult_tabs;
                    size_multabs : integer;
                    position     : integer;
                    table_cnt    : integer);
 
        PROCEDURE
              a683tr_newsucc (
                    debug          : tgg00_Debug;
                    VAR succession : tak68_succession;
                    start          : integer;
                    stop           : integer;
                    dst_table      : boolean);
 
        PROCEDURE
              a683tr_tableset (
                    debug           : tgg00_Debug;
                    nam             : tsp_sname;
                    VAR table_set   : tak_joinset);
&       endif
 
      ------------------------------ 
 
        FROM
              RTE-Extension-10 : VSP10;
 
        PROCEDURE
              s10fil (size : tsp_int4;
                    VAR m    : tsp_line;
                    pos      : tsp_int4;
                    len      : tsp_int4;
                    fillchar : char);
 
        PROCEDURE
              s10mv2 (size1  : tsp_int4;
                    size2    : tsp_int4;
                    VAR val1 : tsp_sname;
                    p1       : tsp_int4;
                    VAR val2 : tsp_line;
                    p2       : tsp_int4;
                    cnt      : tsp_int4);
 
        PROCEDURE
              s10mv3 (size1  : tsp_int4;
                    size2    : tsp_int4;
                    VAR val1 : tsp_c42;
                    p1       : tsp_int4;
                    VAR val2 : tsp_line;
                    p2       : tsp_int4;
                    cnt      : tsp_int4);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01vtrace        : tgg_vtrace_state;
              g01unicode       : boolean;
 
        FUNCTION
              g01userstackoverflow : boolean;
 
        FUNCTION
              g01join_search_level : tgg00_JoinSearchLevel;
 
        FUNCTION
              g01join_maxtab_level4 : tsp_int2;
 
        FUNCTION
              g01join_maxtab_level9 : tsp_int2;
 
      ------------------------------ 
 
        FROM
              Unicode-Utilities : VGG20;
 
        PROCEDURE
              g20unifill (
                    size      : tsp_int4;
                    m         : tsp_moveobj_ptr;
                    pos       : tsp_int4;
                    len       : tsp_int4;
                    filluchar : tsp_c2);
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vsleep (
                    pid   : tsp_process_id;
                    limit : tsp_int2);
 
&       ifdef TRACE
        PROCEDURE
              vabort (write_core : boolean);
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01line (debug : tgg00_Debug; VAR ln : tsp00_Line);
 
        PROCEDURE
              t01name (level : tgg00_Debug;
                    nam : tsp00_Name);
 
        PROCEDURE
              t01sname (level : tgg00_Debug;
                    nam : tsp00_Sname);
 
        PROCEDURE
              t01messblock (debug : tgg00_Debug;
                    nam           : tsp00_Sname;
                    VAR m         : tgg00_MessBlock);
 
        PROCEDURE
              t01stackdesc (debug  : tgg00_Debug;
                    nam            : tsp00_Sname;
                    stack_addr     : tgg00_StackListPtr;
                    VAR stack_desc : tgg00_StackDesc);
 
        PROCEDURE
              t01real (debug : tgg00_Debug;
                    nam      : tsp00_Sname;
                    r        : tsp00_Longreal;
                    digits   : integer);
 
        PROCEDURE
              t01stackentry (level : tgg00_Debug;
                    VAR st      : tgg00_StackEntry;
                    entry_index : integer);
 
        PROCEDURE
              t01lidentifier (level : tgg00_Debug;
                    identifier : tsp00_KnlIdentifier);
 
        PROCEDURE
              t01qual (level : tgg00_Debug;
                    VAR q_buf : tgg00_QualBuf);
 
        PROCEDURE
              t01int4 (debug : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01p2int4 (debug : tgg00_Debug;
                    nam_1 : tsp00_Sname;
                    int_1 : tsp00_Int4;
                    nam_2 : tsp00_Sname;
                    int_2 : tsp00_Int4);
 
        PROCEDURE
              t01bool (debug : tgg00_Debug;
                    nam      : tsp00_Sname ;
                    curr_bool: boolean);
 
        PROCEDURE
              t01c30 (debug : tgg00_Debug;
                    msg : tsp00_C30 );
&       endif
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG10;
 
        PROCEDURE
              g10mv (mod_id        : tsp_c6;
                    mod_intern_num : tsp_int4;
                    size1          : tsp_int4;
                    size2          : tsp_int4;
                    VAR val1       : tgg_stack_list;
                    p1             : tsp_int4;
                    VAR val2       : tgg_stack_list;
                    p2             : tsp_int4;
                    cnt            : tsp_int4;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10mv1 (mod_id       : tsp_c6;
                    mod_intern_num : tsp_int4;
                    size1          : tsp_int4;
                    size2          : tsp_int4;
                    VAR val1       : tak_joinarr;
                    p1             : tsp_int4;
                    VAR val2       : tak_joinarr;
                    p2             : tsp_int4;
                    cnt            : tsp_int4;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10mvb (mod_id       : tsp_c6;
                    mod_intern_num : tsp_int4;
                    size1          : tsp_int4;
                    size2          : tsp_int4;
                    VAR val1       : tak_joinarr;
                    p1             : tsp_int4;
                    VAR val2       : tak_joinarr;
                    p2             : tsp_int4;
                    cnt            : tsp_int4;
                    VAR e          : tgg_basis_error);
 
      ------------------------------ 
 
        FROM
              GG_edit_routines: VGG17;
 
        PROCEDURE
              g17longreal_to_line (r : tsp00_Longreal;
                    digits    : integer;
                    pos       : integer;
                    VAR ln    : tsp00_Line);
 
        PROCEDURE
              g17int4to_line (int : tsp00_Int4;
                    with_zero : boolean;
                    int_len   : integer;
                    ln_pos    : integer;
                    VAR ln    : tsp00_Line);
 
        PROCEDURE
              g17stratenum_to_line (strat : tgg07_StratEnum;
                    VAR ln_len : integer;
                    VAR ln     : tsp_line);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1  : VBD01;
 
        PROCEDURE
              b01filestate (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              Trace : VBD120;
 
        PROCEDURE
              b120InsertTrace (VAR t   : tgg00_TransContext;
                    trace_layer  : tgg00_Debug;
                    trace_object : tgg00_VtraceType;
                    body_len     : tsp00_Int2;
                    trace_body   : tsp00_Addr);
 
.CM *-END-* use -----------------------------------------
***********************************************************
 
Synonym :
 
        PROCEDURE
              b120InsertTrace;
 
              tgg11_VtraceBodyPtr tsp00_Addr
 
        PROCEDURE
              g10mv;
 
              tsp_moveobj tgg_stack_list
 
        PROCEDURE
              g10mv1;
 
              tsp_moveobj tak_joinarr
 
        PROCEDURE
              g10mvb;
 
              tsp_page tak_joinarr
 
        PROCEDURE
              s10fil;
 
              tsp_moveobj tsp_line
 
        PROCEDURE
              s10mv2;
 
              tsp_moveobj tsp_sname
              tsp_moveobj tsp_line
 
        PROCEDURE
              s10mv3;
 
              tsp_moveobj tsp_c42
              tsp_moveobj tsp_line
 
.CM *-END-* synonym -------------------------------------
***********************************************************
Specification:
.CM *-END-* specification -------------------------------
***********************************************************
Description:
 
A681OPT_CONDITIONS
 
This procedure eliminates all unnecessary (transitive) join conditions,
which were added by GET_ALL_EQ_CONDITIONS or which were given by the
user.
At first all tables with special strategies (jos_joinno differs to
CARTESIAN_PRODUCT) were transfered into EQ_REC in order of the
processing sequence. The second step is to transfer all join conditions
into EQ_REC which weren't found in EQ_REC (determined by function
FOUND_IN_EQ_REC) and which coressponding tablenumber is equal to the next
tablenumber. The sequence of tablenumbers is stored in SERIES.
The current tablenumber is series[ j ].jos_source.
The next tablenumber is series[ j + offset ].jos_source. In a loop all
conditions of current tables and its next tables (offset is constant).
Then offset is increased and it starts with the first table again. This
will be repeated until offset is is equal to ATCNT.
As a join condition is transfered into EQ_REC the position of
joinarr-element is added to the set USED_REC_SET.
At last all unused join conditions (position not contained in
USED_REC_SET) were eliminated by AK681PACK_JOIN_COND.
 
FOUND_IN_EQ_REC
 
This function returns whether the given join condition is contained
in EQ_REC or whether it is possible to derive the join condition.
 
AK681PACK_JOIN_COND
 
This procedure deletes the element of jrc_joinarr on DEL_POS, all following
elements will be moved one place before.
The SJOINNUMs, which points to elements of jrc_joinarr and which are
greater than DEL_POS were decresed by one.
 
A681KEVAL_KEY_KIND
 
This functions determs if a better strategy than TO_FIRST_KEY_FIELD
between two tables can be used. If all keyfields of a multiple key
were found it returns TO_KEY, else TO_KEYPART for more than one field or
if only the first keyfield is found TO_FIRST_KEY_FIELD.
 
A681KEY_SORT_JOINARR
 
This procedure sorts the jrc_joinarr depended on the two tables, which
gives the connection between the two tables via multipekeycolumns.
 The sort is started at START_POS. The conditions for the
multiplekey-strategy will be moved to START_POS in order of the
multiplekey.
After sort is finished the fieldcount (jos_FIELDCNT) is updated to
the number of detached multiple key columns which were used for the
strategy.
Finally A681UPDATE_SEQUENCE is called for correcting the pointers
(jos_joinno) of jrc_joinarr for used strategy.
 
A681IEVAL_INV_KIND
 
This function determs if a better strategy than TO_EQ_FIELD
between two tables can be used. It calls the procdure
A681EVAL_ONE_MINV until no more multiple_index is found or a full
multiple_index is found. The number of multiple_index is returned in
the current joinarry_element in jo_recs[ 2 ].jop_outpos.
 
A681MEVAL_ONE_MINV
 
This procedure determines if a multiple_index between the two
tables can be used.
 
A681INV_SORT_JOINARR
 
This procedure sorts the jrc_joinarr depended on the two tables, which
gives the connection between the two tables via multipe-indexcolumns.
 The sort is started at START_POS. The conditions for the multiple
index strategy will be moved to START_POS in order of the multiple index.
After sort is finished the fieldcount (jos_FIELDCNT) is updated to
the number of detached multiple key columns which were used for the
strategy.
Finally A681UPDATE_SEQUENCE is called for correcting the pointers
(jos_joinno) of jrc_joinarr for used strategy.
 
A681UPDATE_SEQUENCE
 
This procedure dates the SJOINNUMS up. This is nessaisary after sorting
the joinarry, because the SJOINNUMS will points to the old positions.
 Before the joinarry is sorted the sequence of joinarry_elements
is stored by puting the positionnumber into each joinarry-element in
jo_recs[ 1 ].jop_outpos. If a jos_joinno is equal to jo_recs[ 1 ].jop_outpos,
jos_joinno is updated to the position.
 
.CM *-END-* description ---------------------------------
***********************************************************
Structure :
 
.CM *-END-* structure -----------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
CONST
      c_update_jtrans       = true; (* a681lowest_multiple_strat *)
      c_write_core          = true; (* vabort                    *)
      c_result_wanted       = true; (* a05qualification_test     *)
      c_check_new_rec       = true; (* a05qualification_test     *)
      c_no_error_pos        = 0;    (* a05qualification_test     *)
      c_debug_output        = true;
      c_change_to_unicode   = true; (* h.b. PTS 1105127 *)
      c_find_start_table    = true;
 
TYPE
      tak681_used_jrc_set_type   =  PACKED SET OF 0..MAX_JOINS_GG00;
 
      tak681_unknown_table_rec = RECORD
            ut_tableno     : tsp00_Uint1;
            ut_filler      : tsp00_Uint1;
            ut_joinno      : tak68_joinarr_index;
      END;
 
      tak681_unknown_table_arr = ARRAY [ 1 .. MAX_JOINS_GG00 ] OF tak681_unknown_table_rec;
 
      tak681_best_jstrat_rec = RECORD
            bjr_jmultipl    : tsp_int4;
            bjr_costs       : tsp_longreal;
            bjr_srctab      : tsp_int2;
            bjr_mtab_ind    : tsp_int2;
            bjr_is_mt_join  : boolean;
            bjr_jtype       : tak68_one_jointype;
            bjr_fieldcnt    : tsp_int2;  (* h.b. PTS 1106353 *)
      END;
 
      tak681_best_jstrat_rec_arr = ARRAY [ 1..cak_maxsources ]
            OF tak681_best_jstrat_rec;
 
      tak681_jseq_info_record = RECORD
            jir_sequenced_tables    : tak_joinset;
            jir_best_jstrat         : tak681_best_jstrat_rec_arr;
            jir_comp_sequences      : tsp00_Int4;
            jir_i                   : tsp00_Int2;
            jir_non_best_trans      : tsp00_Int2;
            jir_swap_cnt            : tsp00_Int2;
            jir_last_swap_pos       : tsp00_Int2;
            jir_beststratcnt        : tsp00_Int2;
            jir_max_tables          : tsp00_Int2;
            jir_stop_sequence       : boolean;
            jir_better_seq_exists   : boolean;
            jir_lowest_cost         : tsp_longreal;
            jir_lowest_succession   : tak68_succession;
            jir_start_succession    : tak68_succession;
      END;
 
      tak681_join_groups  = ARRAY [1..cak_maxsources] OF tak_joinset;
 
 
(*------------------------------*) 
 
FUNCTION
      a681tmp_table_length (
            VAR dmli    : tak_dml_info;
            VAR jinfos  : tak68_joininfos;
            tabno       : integer) : integer;
 
VAR
      _i         : integer;
      _j         : integer;
      _len       : integer;
      _stop      : integer;
      _used_cols : tak_columnset;
 
BEGIN
(* precondition: first stack entry is st_jump_out *)
_stop := jinfos.ji_stack_desc.mqual_pos +
      jinfos.ji_st_addr^[ jinfos.ji_stack_desc.mqual_pos ].epos - 1;
_i    := succ (jinfos.ji_stack_desc.mqual_pos);
_len  := cgg_rec_key_offset (* reclen + keylen + varcolcount + varcoloffset *)
      + mxgg_rescnt (* resultcount counter *);
&ifdef TRACE
t01int4 (ak_join, '_stop       ', _stop);
t01stackdesc (ak_join, 'j_stack_desc', jinfos.ji_st_addr, jinfos.ji_stack_desc);
&endif
WHILE (_i < _stop) DO
    BEGIN
    (* loop while not column stackentry *)
    WHILE ((_i < _stop) AND (NOT (jinfos.ji_st_addr^[ _i ].etype IN
          [ st_fixkey, st_varkey, st_fixcol, st_varcol,
          st_varlongchar ]))) DO
        _i := succ (_i);
    (*ENDWHILE*) 
    IF  ((_i < _stop) AND
        ((ord(jinfos.ji_st_addr^[ _i ].ecol_tab[ 2 ]) MOD 100) = tabno))
    THEN
        BEGIN
        (* loop to OUTPUT description *)
        WHILE ((_i < _stop) AND
              (jinfos.ji_st_addr^[ _i ].etype <> st_output)) DO
            _i := succ (_i);
        (*ENDWHILE*) 
&       ifdef TRACE
        t01stackentry (ak_join, jinfos.ji_st_addr^[ _i ], _i);
&       endif
        IF  (_i < _stop)
        THEN
            _len := _len + jinfos.ji_st_addr^[ _i ].elen_var;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    _i := succ (_i);
    END;
(*ENDWHILE*) 
_used_cols := [ ];
IF  dmli.d_join
THEN
    FOR _i := 0 TO dmli.d_joins.jrc_cnt - 1 DO
        (* add key columns (join predicates for EQ-joins)  *)
        (* worst case: all join columns are output colunms *)
        (* i.e. all columns must be written twice          *)
        FOR _j :=  1 TO 2 DO
            WITH dmli.d_joins.jrc_joinarr[ _i ] DO
                IF  (jo_recs[ _j ].jop_tableno = tabno)
                    AND NOT (jo_recs[ _j ].jop_fieldno in _used_cols)
                THEN
                    BEGIN
                    _used_cols := _used_cols + [ jo_recs[ _j ].jop_fieldno ];
                    _len       := _len + ord(jo_recs[ _j ].jop_inoutlen);
                    END;
&               ifdef TRACE
                (*ENDIF*) 
            (*ENDWITH*) 
        (*ENDFOR*) 
    (*ENDFOR*) 
(*ENDIF*) 
t01int4 (ak_join, 'tableno     ', tabno);
t01int4 (ak_join, 'table_length', _len);
&endif
a681tmp_table_length := _len;
END;
 
(*------------------------------*) 
 
PROCEDURE
      a681opt_conditions (
            VAR acv    : tak_all_command_glob;
            VAR dmli   : tak_dml_info;
            VAR series : tak68_sequence;
            VAR jinfos : tak68_joininfos;
            VAR eq_rec : tak68_eq_record);
 
VAR
      _end_pos      : integer;
      _i            : integer;
      _j            : integer;
      _curr_tab     : tsp00_Uint1;
      _nxt_tab      : tsp00_Uint1;
      _offset       : integer;
      _used_jrc_set : tak681_used_jrc_set_type;
 
BEGIN
eq_rec.eqr_cnt        := 0;
_used_jrc_set  := [  ];
_end_pos       := pred (dmli.d_joins.jrc_cnt);
FOR _j := 0 TO _end_pos DO
    IF  ((dmli.d_joins.jrc_joinarr[ _j ].jo_recs [ 1 ].jop_cntstack > 1) OR
        (dmli.d_joins.jrc_joinarr[ _j ].jo_recs [ 2 ].jop_cntstack > 1 )    ) OR
        (dmli.d_joins.jrc_joinarr[ _j ].jo_recs [ 1 ].jop_outer_join OR
        dmli.d_joins.jrc_joinarr[ _j ].jo_recs [ 2 ].jop_outer_join    )
    THEN
        _used_jrc_set  := _used_jrc_set + [ _j ];
    (* evaluate the number of equal-joininfos *)
    (*ENDIF*) 
(*ENDFOR*) 
;
&ifdef TRACE
FOR _i := 0 TO dmli.d_joins.jrc_cnt DO
    IF  (_i in _used_jrc_set)
    THEN
        t01int4 (ak_join, 'cnt > 0 ==> ', _i);
    (*ENDIF*) 
(*ENDFOR*) 
;
&endif
(* evaluate the number of equal-joininfos *)
WHILE (_end_pos > 0) AND ((dmli.d_joins.jrc_joinarr[ _end_pos ].jo_op <> op_eq)  OR
      (dmli.d_joins.jrc_joinarr[ _end_pos ].jo_recs [ 1 ].jop_cntstack <> 1) OR
      (dmli.d_joins.jrc_joinarr[ _end_pos ].jo_recs [ 2 ].jop_cntstack <> 1)   ) DO
    _end_pos := pred (_end_pos);
(*ENDWHILE*) 
&ifdef TRACE
t01int4 (ak_join, 'end_pos     ', _end_pos);
&endif
IF  (_end_pos > 0)
THEN
    BEGIN
    FOR _j := 1 TO dmli.d_cntfromtab DO
        WITH series[ _j ] DO
            IF  (jos_joinno <> cak68_cartesian_product)
            THEN
                FOR _i := jos_joinno TO (jos_joinno + jos_fieldcnt - 1) DO
                    WITH dmli.d_joins.jrc_joinarr[ _i ] DO
                        BEGIN
&                       ifdef TRACE
                        t01int4 (ak_join, 'i jos_joinnu', _i);
                        t01int4 (ak_join, 'used_jrc_set', _i);
                        t01int4 (ak_join, 'eqr_cnt     ', eq_rec.eqr_cnt);
&                       endif
                        IF  (NOT (_i in _used_jrc_set))
                        THEN
                            BEGIN
                            _used_jrc_set := _used_jrc_set + [ _i ];
                            IF  (jo_recs[ 1 ].jop_cntstack = 1) AND
                                (jo_recs[ 2 ].jop_cntstack = 1)
                            THEN
                                BEGIN
                                eq_rec.eqr_cnt := succ (eq_rec.eqr_cnt);
                                WITH eq_rec.eqr_left[ eq_rec.eqr_cnt ], jo_recs[ 1 ] DO
                                    BEGIN
                                    IF  NOT jop_outer_join
                                    THEN
                                        eqi_fieldid.eqt_tabno := jop_tableno
                                    ELSE
                                        eqi_fieldid.eqt_tabno :=
                                              jop_tableno + 20;
                                    (*ENDIF*) 
                                    eqi_fieldid.eqt_colno  := jop_fieldno;
                                    eqi_stackpos       := jop_startstack;
                                    eqi_joinno         := _i;
                                    eqi_jrecs          := 1;
                                    IF  jop_datatyp in [ dcha, ddate, dtime ]
                                    THEN
                                        eqi_codetype := csp_ascii
                                    ELSE
                                        IF  ((jop_datatyp = dche) OR
                                            (jop_datatyp = ddbyteebcdic))
                                        THEN
                                            eqi_codetype := csp_ebcdic
                                        ELSE
                                            eqi_codetype :=
                                                  csp_codeneutral;
                                        (*ENDIF*) 
                                    (*ENDIF*) 
                                    END;
                                (*ENDWITH*) 
                                WITH eq_rec.eqr_right[ eq_rec.eqr_cnt ], jo_recs[ 2 ] DO
                                    BEGIN
                                    IF  NOT jop_outer_join
                                    THEN
                                        eqi_fieldid.eqt_tabno := jop_tableno
                                    ELSE
                                        eqi_fieldid.eqt_tabno :=
                                              jop_tableno + 20;
                                    (*ENDIF*) 
                                    eqi_fieldid.eqt_colno  := jop_fieldno;
                                    eqi_stackpos       := jop_startstack;
                                    eqi_joinno         := _i;
                                    eqi_jrecs          := 2;
&                                   ifdef TRACE
                                    t01int4 (ak_join, 'i           ', _i);
                                    t01int4 (ak_join, 'jop_startsta', jop_startstack);
&                                   endif
                                    CASE jinfos.ji_st_addr^[ jop_startstack ].eop OF
                                        op_ascii :
                                            eqi_codetype := csp_ebcdic;
                                        op_ebcdic :
                                            eqi_codetype := csp_ascii;
                                        OTHERWISE
                                            eqi_codetype := eq_rec.eqr_left[ eq_rec.eqr_cnt ].
                                                  eqi_codetype;
                                        END;
                                    (*ENDCASE*) 
                                    END;
                                (*ENDWITH*) 
                                END;
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDWITH*) 
                (*ENDFOR*) 
&           ifdef TRACE
            (*ENDIF*) 
        (*ENDWITH*) 
    (*ENDFOR*) 
    FOR _i := 0 TO _end_pos DO
        IF  (_i in _used_jrc_set)
        THEN
            t01int4 (ak_join, 'eq used ==> ', _i);
        (*ENDIF*) 
    (*ENDFOR*) 
    FOR _j := 1 TO eq_rec.eqr_cnt DO
        BEGIN
        t01int4 (ak_join, 'j           ', _j);
        t01int4 (ak_join, 'left.tabno  ', eq_rec.eqr_left[ _j ].eqi_fieldid.eqt_tabno);
        t01int4 (ak_join, 'left.colno  ', eq_rec.eqr_left[ _j ].eqi_fieldid.eqt_colno);
        t01int4 (ak_join, 'right.tabno ', eq_rec.eqr_right[ _j ].eqi_fieldid.eqt_tabno);
        t01int4 (ak_join, 'right.colno ', eq_rec.eqr_right[ _j ].eqi_fieldid.eqt_colno);
        END;
    (*ENDFOR*) 
&   endif
    FOR _offset := 1 TO (dmli.d_cntfromtab - 1) DO
        FOR _j := 1 TO (dmli.d_cntfromtab - _offset) DO
            WITH series[ _j ] DO
                BEGIN
                _curr_tab := jos_source;
                _nxt_tab  := series[ _j + _offset ].jos_source;
&               ifdef TRACE
                t01int4 (ak_join, 'offset      ', _offset);
                t01int4 (ak_join, 'j           ', _j);
                t01int4 (ak_join, 'curr_tab    ', _curr_tab);
                t01int4 (ak_join, 'nxt_tab     ', _nxt_tab);
&               endif
                FOR _i := 0 TO _end_pos DO
                    WITH dmli.d_joins.jrc_joinarr[ _i ] DO
                        BEGIN
                        IF  (NOT (_i in _used_jrc_set))
                        THEN
                            IF  (((jo_recs[ 1 ].jop_tableno = _curr_tab) AND
                                (jo_recs[ 2 ].jop_tableno = _nxt_tab)       ) OR
                                ((jo_recs[ 2 ].jop_tableno = _curr_tab) AND
                                (jo_recs[ 1 ].jop_tableno = _nxt_tab)      )    )
                            THEN
                                BEGIN
                                IF  (jo_recs[ 1 ].jop_cntstack = 1) AND
                                    (jo_recs[ 2 ].jop_cntstack = 1)
                                THEN
                                    BEGIN
&                                   ifdef TRACE
                                    t01int4 (ak_join, 'i <> sjoinum', _i);
&                                   endif
                                    WITH eq_rec.eqr_left[ eq_rec.eqr_cnt + 1 ], jo_recs[ 1 ] DO
                                        BEGIN
                                        IF  NOT jop_outer_join
                                        THEN
                                            eqi_fieldid.eqt_tabno := jop_tableno
                                        ELSE
                                            eqi_fieldid.eqt_tabno :=
                                                  jop_tableno + 20;
                                        (*ENDIF*) 
                                        eqi_fieldid.eqt_colno  := jop_fieldno;
                                        eqi_stackpos       := jop_startstack;
                                        eqi_joinno         := _i;
                                        eqi_jrecs          := 1;
                                        IF  jop_datatyp in [ dcha, ddate, dtime ]
                                        THEN
                                            eqi_codetype := csp_ascii
                                        ELSE
                                            IF  ((jop_datatyp = dche) OR
                                                (jop_datatyp = ddbyteebcdic))
                                            THEN
                                                eqi_codetype := csp_ebcdic
                                            ELSE
                                                eqi_codetype := csp_codeneutral;
                                            (*ENDIF*) 
                                        (*ENDIF*) 
                                        END;
                                    (*ENDWITH*) 
                                    WITH eq_rec.eqr_right[ eq_rec.eqr_cnt + 1 ],jo_recs[ 2 ] DO
                                        BEGIN
                                        IF  NOT jop_outer_join
                                        THEN
                                            eqi_fieldid.eqt_tabno := jop_tableno
                                        ELSE
                                            eqi_fieldid.eqt_tabno :=
                                                  jop_tableno + 20;
                                        (*ENDIF*) 
                                        eqi_fieldid.eqt_colno  := jop_fieldno;
                                        eqi_stackpos       := jop_startstack;
                                        eqi_joinno         := _i;
                                        eqi_jrecs          := 2;
                                        CASE jinfos.ji_st_addr^[ jop_startstack ].eop OF
                                            op_ascii :
                                                eqi_codetype := csp_ebcdic;
                                            op_ebcdic :
                                                eqi_codetype := csp_ascii;
                                            OTHERWISE
                                                eqi_codetype :=
                                                      eq_rec.eqr_left[ eq_rec.eqr_cnt + 1 ].
                                                      eqi_codetype;
                                            END;
                                        (*ENDCASE*) 
                                        END;
                                    (*ENDWITH*) 
                                    IF  NOT ak681found_in_eq_rec (eq_rec,
                                        eq_rec.eqr_cnt + 1)
                                    THEN
                                        BEGIN
                                        _used_jrc_set := _used_jrc_set + [ _i ];
                                        eq_rec.eqr_cnt       := succ (eq_rec.eqr_cnt);
&                                       ifdef TRACE
                                        t01int4 (ak_join, 'used_jrc_set', _i);
                                        t01int4 (ak_join, 'eqr_cnt     ', eq_rec.eqr_cnt);
&                                       endif
                                        END;
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    _used_jrc_set := _used_jrc_set + [ _i ];
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END;
                    (*ENDWITH*) 
                (*ENDFOR*) 
                END;
            (*ENDWITH*) 
        (*ENDFOR*) 
    (*ENDFOR*) 
    (* make shure that stackentries be used only one time *)
&   ifdef TRACE
    FOR _i := 0 TO _end_pos DO
        IF  (_i in _used_jrc_set)
        THEN
            t01int4 (ak_join, 'eq used ==> ', _i);
        (*ENDIF*) 
    (*ENDFOR*) 
    a683_output (ak_join, dmli);
&   endif
    ak681elim_duplicate_st_pos (acv, jinfos, dmli, eq_rec, _used_jrc_set);
    FOR _i := _end_pos DOWNTO 0 DO
        IF  NOT (_i in _used_jrc_set) AND
            (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ 1 ].jop_cntstack = 1) AND
            (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ 2 ].jop_cntstack = 1)
        THEN
            BEGIN
&           ifdef TRACE
            t01int4  (ak_join, 'i before    ', _i);
&           endif
            ak681pack_join_cond (dmli, series, _i);
&           ifdef TRACE
            t01int4  (ak_join, 'i after     ', _i);
&           endif
            END;
        (*ENDIF*) 
    (*ENDFOR*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      ak681found_in_eq_rec (
            VAR eq_rec  : tak68_eq_record;
            pos         : integer) : boolean;
 
VAR
      _found    : boolean;
      _i        : integer;
      _j        : integer;
      _eq_start : tak68_eqfieldinfo;
      _eq_dest  : tak68_eqfieldinfo;
 
BEGIN
_eq_start := eq_rec.eqr_left[ pos ];
_eq_dest  := eq_rec.eqr_right[ pos ];
_found    := false;
_i        := 1;
&ifdef TRACE
t01int4  (ak_join, 'eqr_cnt     ', eq_rec.eqr_cnt);
t01int4  (ak_join, 'pos         ', pos);
t01int4 (ak_join, 'start.tabno ', _eq_start.eqi_fieldid.eqt_tabno);
t01int4 (ak_join, 'start.colno ', _eq_start.eqi_fieldid.eqt_colno);
t01int4 (ak_join, 'dest.tabno  ', _eq_dest.eqi_fieldid.eqt_tabno);
t01int4 (ak_join, 'dest.colno  ', _eq_dest.eqi_fieldid.eqt_colno);
&endif
WHILE ((_i <= eq_rec.eqr_cnt) AND (NOT _found)) DO
    BEGIN
&   ifdef TRACE
    t01int4  (ak_join, 'i           ', _i);
&   endif
    _j := 1;
    WHILE ((_j <= eq_rec.eqr_cnt) AND (NOT _found)) DO
        BEGIN
        IF  (_j <> pos)
        THEN
            BEGIN
&           ifdef TRACE
            t01int4 (ak_join, 'j           ', _j);
            t01int4 (ak_join, 'left.tabno  ', eq_rec.eqr_left[ _j ].eqi_fieldid.eqt_tabno);
            t01int4 (ak_join, 'left.colno  ', eq_rec.eqr_left[ _j ].eqi_fieldid.eqt_colno);
            t01int4 (ak_join, 'right.tabno ', eq_rec.eqr_right[ _j ].eqi_fieldid.eqt_tabno);
            t01int4 (ak_join, 'right.colno ', eq_rec.eqr_right[ _j ].eqi_fieldid.eqt_colno);
&           endif
            IF  (eq_rec.eqr_left[ _j ].eqi_fieldid.eqt_whole = _eq_start.eqi_fieldid.eqt_whole)
            THEN
                _eq_start := eq_rec.eqr_right[ _j ]
            ELSE
                IF  (eq_rec.eqr_right[ _j ].eqi_fieldid.eqt_whole = _eq_start.eqi_fieldid.eqt_whole)
                THEN
                    _eq_start := eq_rec.eqr_left[ _j ];
                (*ENDIF*) 
            (*ENDIF*) 
            IF  (_eq_start.eqi_fieldid.eqt_whole = _eq_dest.eqi_fieldid.eqt_whole)
            THEN
                _found := true;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        _j := succ (_j);
        END;
    (*ENDWHILE*) 
    _i := succ (_i);
    END;
(*ENDWHILE*) 
&ifdef TRACE
t01int4  (ak_join, 'j ende      ', _j);
t01int4 (ak_join, 'start.tabno ', _eq_start.eqi_fieldid.eqt_tabno);
t01int4 (ak_join, 'start.colno ', _eq_start.eqi_fieldid.eqt_colno);
t01int4 (ak_join, 'dest.tabno  ', _eq_dest.eqi_fieldid.eqt_tabno);
t01int4 (ak_join, 'dest.colno  ', _eq_dest.eqi_fieldid.eqt_colno);
IF  _found
THEN
    t01int4  (ak_join, 'found       ', ord (_found))
ELSE
    t01int4  (ak_join, 'not found   ', ord (_found));
(*ENDIF*) 
&endif
ak681found_in_eq_rec := _found;
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681pack_join_cond (
            VAR dmli   : tak_dml_info;
            VAR series : tak68_sequence;
            del_pos    : integer);
 
VAR
      _i : integer;
 
BEGIN
dmli.d_joins.jrc_cnt := pred (dmli.d_joins.jrc_cnt);
_i    := del_pos;
WHILE (_i < dmli.d_joins.jrc_cnt) DO
    BEGIN
    dmli.d_joins.jrc_joinarr[ _i ] := dmli.d_joins.jrc_joinarr[ _i + 1 ];
    _i            := succ (_i);
    END;
(*ENDWHILE*) 
FOR _i := 1 TO dmli.d_cntfromtab DO
    IF  ((series[ _i ].jos_joinno > del_pos) AND
        (series[ _i ].jos_joinno <> cak68_cartesian_product))
    THEN
        series[ _i ].jos_joinno := pred (series[ _i ].jos_joinno);
    (*ENDIF*) 
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      a681keval_key_kind (
            VAR acv       : tak_all_command_glob;
            VAR dmli      : tak_dml_info;
            VAR mul_tabs  : tak68_mult_tabs;
            pos_jarr      : integer;
            pos_jrec      : integer;
            is_join_value : boolean) : tak68_one_jointype;
 
CONST
      c_max_keycount = (MAX_COL_PER_TAB_GG00 + 1) DIV 2;
 
VAR
      _ix                : integer;
      _unknown_table_idx : integer;(* index in jrc_joinarr *)
      _dst               : integer;
      _src               : integer;
      _keycol_cnt        : integer;
      _col_buf           : tak00_colinfo_ptr;
      _nxt_fieldno       : tsp_int2;
      _start_ut_cnt      : tsp_int2;
      _start_mt_cnt      : tsp_int2;
      _virt_mt_cnt       : tsp_int2;
      _unknown_table_pos : tsp_int2;
      _unknown_table_cnt : tsp_int2;
      _unknown_table_arr : tak681_unknown_table_arr;
      _keyextcol_arr     : PACKED ARRAY [ 1 .. c_max_keycount ] OF tsp_int2;
      _new_tables        : tak_joinset;
      _jointype          : tak68_one_jointype;
      _curr_tab          : tsp00_Uint1;
      _f_ok              : boolean;
      _known_table       : boolean;
      _reset_loop        : boolean;
 
BEGIN
&ifdef TRACE
t01int4(ak_join, 'joinarr pos ', pos_jarr );
IF  pos_jrec = 1
THEN
    t01sname(ak_join, 'left site   ')
ELSE
    t01sname(ak_join, 'right site  ');
(*ENDIF*) 
&endif
(* join transition to key column found            *)
(* look for more key transitions for actual table *)
_jointype       := to_first_keyfield;
_f_ok           := false;
(* try to insert into mul.tabs.mt_arr        *)
(* insertion is done if we increase mt_cnt ! *)
mul_tabs.mt_pos := succ (mul_tabs.mt_cnt);
IF  mul_tabs.mt_pos <= mxak68_mt_arr
THEN
    BEGIN
    _virt_mt_cnt   := mul_tabs.mt_pos;
    _start_mt_cnt  := mul_tabs.mt_pos;
    _start_ut_cnt  := 0; (* initial unknown table count *)
    _keycol_cnt    := 0;
    _new_tables    := [ ];
    CASE pos_jrec OF
        1 :
            _src := 2;
        2 :
            _src := 1;
        END;
    (*ENDCASE*) 
    (* fill new entry in mul_tabs.mt_arr *)
    _curr_tab := dmli.d_joins.jrc_joinarr[ pos_jarr ].jo_recs[ pos_jrec ].jop_tableno;
    mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_dst_table:= _curr_tab;
    mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_jointype := _jointype;
    mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_multipl  := dmli.d_joins.
          jrc_joinarr[ pos_jarr ].jo_recs[ pos_jrec ].jop_multiplier;
    mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_joinno   := pos_jarr;
    mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_filler   := 0;
    IF  (NOT is_join_value)
    THEN
        BEGIN
        (* S.column <op> D.column *)
        mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tab_seq :=
              [ dmli.d_joins.jrc_joinarr[ pos_jarr ].
              jo_recs[ _src ].jop_tableno ];
        mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tablecnt  := 1;
        END
    ELSE
        BEGIN
        (* S.column <op> <constant> *)
        mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tab_seq   := [ ];
        mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tablecnt  := 0;
        END;
    (*ENDIF*) 
    mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_fieldcnt := 1;
    mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_indexno  := 0;
    (* first column is key column because jtfirstkey in tak_jcolpropset         *)
    (* get second column, we know that second column is key column (jtfirstkey) *)
    IF  (dmli.d_joins.jrc_joinarr[ pos_jarr ].
        jo_recs[ _src ].jop_inoutlen <= dmli.d_joins.jrc_joinarr[ pos_jarr ].
        jo_recs[ pos_jrec ].jop_inoutlen)
    THEN
        BEGIN
        (* get first external key field no *)
        ak681first_keyfield_no(acv, dmli, _col_buf, _curr_tab, _nxt_fieldno, _f_ok);
        IF  _f_ok
        THEN
            BEGIN
            (* remark field no *)
            _keycol_cnt := 1;
            _keyextcol_arr[ _keycol_cnt ] := _nxt_fieldno;
            (* get second external field no *)
            ak681next_keyfield_no (dmli, _col_buf, _nxt_fieldno);
            (* remark field no *)
            _keycol_cnt := succ (_keycol_cnt);
            _keyextcol_arr[ _keycol_cnt ] := _nxt_fieldno;
            END;
        (*ENDIF*) 
        END;
&   ifdef TRACE
    (*ENDIF*) 
    t01name(ak_join, '--start  mul_tabs-');
    a683multabs_trace (ak_join, mul_tabs, _virt_mt_cnt, 0, dmli.d_cntfromtab);
&   endif
    _unknown_table_pos := 1;
    _unknown_table_cnt := 0;
    REPEAT
        (* UNTIL (_unknown_table_pos > _unknown_table_cnt)   *)
        (* i.e. UNTIL no input into _unknown_table_arr *)
        IF  (_unknown_table_pos <= _unknown_table_cnt)
        THEN
            (* earlier insert into _unknown_table_arr *)
            BEGIN
            _start_ut_cnt  := _unknown_table_cnt;
            _start_mt_cnt  := _virt_mt_cnt;
            _new_tables    := [ ];
            (* just switch the first unknown table to known table *)
            _ix := _unknown_table_arr[ _unknown_table_pos ].ut_joinno;
            IF  mul_tabs.mt_pos < mxak68_mt_arr
            THEN
                BEGIN
                (* there are X entries in mul_tabs *)
                (* save the first entry            *)
                mul_tabs.mt_pos := succ (mul_tabs.mt_pos);
                _virt_mt_cnt    := mul_tabs.mt_pos;
&               ifdef TRACE
                t01int4 (ak_join, 'act mt_pos  ', mul_tabs.mt_pos);
&               endif
                END;
&           ifdef TRACE
            (*ENDIF*) 
            t01name(ak_join, '-- upd mul_tabs --');
&           endif
            mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tab_seq  :=
                  mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tab_seq +
                  [ _unknown_table_arr[ _unknown_table_pos ].ut_tableno ];
            mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tablecnt :=
                  succ (mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tablecnt);
            _nxt_fieldno :=
                  _keyextcol_arr[ mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                  mtr_fieldcnt + 1 ];
            (* update _unknown_table_pos concerning new entry *)
            _unknown_table_pos   := succ (_unknown_table_pos);
            END
        ELSE
            _ix := 0;
        (*ENDIF*) 
&       ifdef TRACE
        a683multabs_trace (ak_join, mul_tabs, _virt_mt_cnt, 0,
              dmli.d_cntfromtab);
        t01int4(ak_join, '-act keycol-', _nxt_fieldno);
&       endif
        _unknown_table_idx := _ix;
        _reset_loop := false;
        WHILE (_ix < dmli.d_joins.jrc_cnt) AND _f_ok DO
            BEGIN
            IF  ((_ix <> pos_jarr)
                AND
                (dmli.d_joins.jrc_joinarr[ _ix ].jo_op = op_eq))
            THEN
                (* walk through join conditions 'S.col = D.col' *)
                (* until complete key for _curr_tab found       *)
                WITH dmli.d_joins.jrc_joinarr[ _ix ] DO
                    BEGIN
&                   ifdef TRACE
                    IF  _unknown_table_idx = _ix
                    THEN
                        t01int4(ak_join, 're-run pos  ', _ix)
                    ELSE
                        t01int4(ak_join, 'act jarr pos', _ix);
                    (*ENDIF*) 
&                   endif
                    _dst := 1;
                    _src := 2;
                    WHILE (_dst <= 2) DO
                        BEGIN
&                       ifdef TRACE
                        IF  _src = 1
                        THEN
                            t01sname(ak_join, 'left site   ')
                        ELSE
                            t01sname(ak_join, 'right site  ');
                        (*ENDIF*) 
&                       endif
                        (* inspect join condition *)
                        IF  ((jo_recs[ _dst ].jop_tableno = _curr_tab)
                            AND
                            (* field successor *)
                            (jo_recs[ _dst ].jop_fieldno = _nxt_fieldno)
                            AND
                            (jo_recs[ _src ].jop_inoutlen <=
                            jo_recs[ _dst ].jop_inoutlen)
                            AND
                            (* no function code *)
                            (jo_recs[ _dst ].jop_cntstack = 1)
                            AND
                            (jtkey in jo_recs[ _dst ].jop_propset))
                        THEN
                            (* we found transition to actual *)
                            (* table with next key column    *)
                            BEGIN
                            (* check state of involved table *)
                            IF  (jo_recs[ _src ].jop_tableno =
                                cak68_join_value)
                            THEN
                                (* S.column <op> <constant> *)
                                _known_table := true
                            ELSE
                                _known_table :=
                                      jo_recs[ _src ].jop_tableno in
                                      mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                                      mtr_tab_seq;
                            (*ENDIF*) 
                            IF  _known_table
                            THEN
                                BEGIN
&                               ifdef TRACE
                                t01int4(ak_join, 'known table ',
                                      jo_recs[ _src ].jop_tableno);
&                               endif
                                (* we found 'wider' transition to current table *)
                                (* D.column1 -> S.keycol1 and D.column2 -> S.keycol2 *)
                                (* reject useless transition combination  *)
                                (* A.col -> S.keycol1, B.col -> S.keycol2 *)
                                (* reject earlier insert into _unknown_table_arr *)
                                _unknown_table_cnt := _start_ut_cnt;
                                (* reject earlier insert into mult_tabs  *)
                                _virt_mt_cnt := _start_mt_cnt;
                                (* remark new key transition      *)
                                (* count new key field transition *)
                                mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                                      mtr_fieldcnt := succ (mul_tabs.
                                      mt_arr[ mul_tabs.mt_pos ].
                                      mtr_fieldcnt);
&                               ifdef trace
                                a683multabs_trace (ak_join, mul_tabs,
                                      _virt_mt_cnt, 0, dmli.d_cntfromtab);
&                               endif
                                _new_tables  := [ ];
                                (* get better multiplier *)
                                IF  (mul_tabs.
                                    mt_arr[ mul_tabs.mt_pos ].mtr_multipl >
                                    jo_recs[ _dst ].jop_multiplier)
                                THEN
                                    mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                                          mtr_multipl :=
                                          jo_recs[ _dst ].jop_multiplier;
                                (*ENDIF*) 
                                IF  mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                                    mtr_fieldcnt <
                                    dmli.d_sparr.pbasep^.sbase.bkeycolcount
                                THEN
                                    (* there are other key columns *)
                                    BEGIN
                                    (* get next considered key column *)
                                    IF  (mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                                        mtr_fieldcnt < _keycol_cnt)
                                    THEN
                                        _nxt_fieldno :=
                                              _keyextcol_arr[
                                              mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                                              mtr_fieldcnt + 1 ]
                                    ELSE
                                        BEGIN
                                        ak681next_keyfield_no (dmli,
                                              _col_buf, _nxt_fieldno);
                                        _keycol_cnt
                                              := succ (_keycol_cnt);
                                        _keyextcol_arr[ _keycol_cnt ]
                                              := _nxt_fieldno;
                                        END;
                                    (*ENDIF*) 
&                                   ifdef TRACE
                                    t01int4(ak_join, '-nxt keycol-', _nxt_fieldno);
&                                   endif
                                    (* more than one key transition found *)
                                    mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                                          mtr_jointype := to_keypart;
                                    _reset_loop := true;
                                    END
                                ELSE
                                    BEGIN
                                    (* we found complete key   *)
                                    (* there are no other keys *)
&                                   ifdef TRACE
                                    t01name(ak_join, '-  complete key  -');
&                                   endif
                                    mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                                          mtr_jointype := to_key;
                                    mul_tabs.mt_arr [ mul_tabs.mt_pos ].
                                          mtr_multipl :=
                                          cak68_only_field_multiplier;
                                    (* exit while*)
                                    _ix := dmli.d_joins.jrc_cnt;
                                    END;
                                (*ENDIF*) 
                                END
                            ELSE
                                (* NOT _known_table *)
                                IF  (_unknown_table_cnt < MAX_JOINS_GG00)
                                    AND
                                    (_virt_mt_cnt < mxak68_mt_arr)
                                    AND
                                    (NOT (jo_recs[ _src ].jop_tableno
                                    in _new_tables))
                                THEN
                                    BEGIN
                                    (* insert unknown table into _unknown_table_arr *)
                                    _unknown_table_cnt :=
                                          succ (_unknown_table_cnt);
                                    _unknown_table_arr [ _unknown_table_cnt ].
                                          ut_tableno   := jo_recs[ _src ].jop_tableno;
                                    (* remark index of join condition *)
                                    _unknown_table_arr [ _unknown_table_cnt ].
                                          ut_joinno   := _ix;
                                    _virt_mt_cnt    :=
                                          succ (_virt_mt_cnt);
                                    (* create new entry in mult_tabs *)
                                    (* copy content from origin      *)
                                    mul_tabs.mt_arr[ _virt_mt_cnt ] :=
                                          mul_tabs.mt_arr[ mul_tabs.mt_pos ];
                                    (* remark found new table in new table set *)
                                    _new_tables := _new_tables +
                                          [ _unknown_table_arr [ _unknown_table_cnt ].
                                          ut_tableno ];
&                                   ifdef TRACE
                                    t01int4(ak_join, 'uknown table',
                                          jo_recs[ _src ].jop_tableno);
                                    t01int4(ak_join, 'uknwn tabcnt',
                                          _unknown_table_cnt);
                                    a683multabs_trace (ak_join, mul_tabs,
                                          _virt_mt_cnt, 0, dmli.d_cntfromtab);
&                                   endif
                                    END;
                                (* exit work for parts      *)
                                (*ENDIF*) 
                            (*ENDIF*) 
                            _dst := 3;
                            END;
                        (* swap considered direction of join transition *)
                        (*ENDIF*) 
                        _dst := succ (_dst);
                        _src := pred (_src);
                        END;
                    (*ENDWHILE*) 
                    END;
                (*ENDWITH*) 
            (*ENDIF*) 
            IF  (mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_jointype = to_key)
                AND
                (NOT is_join_value)
                AND
                (mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tablecnt = 1)
            THEN
                (* best join transition found *)
                BEGIN
                (* exit while *)
                _ix := dmli.d_joins.jrc_cnt;
                END
            ELSE
                IF  (_unknown_table_idx > 0)
                    (* we found already a unknown table        *)
                    (* in a first walk through join conditions *)
                    AND
                    (_ix = _unknown_table_idx)
                THEN
                    BEGIN
                    (* now we have inserted unknown table into      *)
                    (* mtr_tab_seq loop with this this start table  *)
                    (* sequence through join conditions             *)
                    _ix                 := 0;
                    _unknown_table_idx  := 0;
                    END
                ELSE
                    (* get next join condition *)
                    IF  NOT _reset_loop
                    THEN
                        _ix := succ (_ix)
                    ELSE
                        BEGIN
                        _reset_loop := false;
                        _ix         := 0;
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDWHILE*) 
    UNTIL
        (_unknown_table_pos > _unknown_table_cnt);
    (*ENDREPEAT*) 
    IF  (mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_fieldcnt = 1)      AND
        (mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_jointype = to_key)
    THEN
        (* *** all other join conditions of key are 'S.col <op> <CONST>' *** *)
        BEGIN
        _jointype := to_key;
        dmli.d_joins.jrc_joinarr[ pos_jarr ].jo_recs[ pos_jrec ].
              jop_multiplier := cak68_only_field_multiplier;
        END
    ELSE
        BEGIN
        _jointype := to_mt_join;
        FOR _ix := mul_tabs.mt_cnt + 1 TO mul_tabs.mt_pos DO
            BEGIN
            (* h.b. PTS 1106028 *)
            IF  mul_tabs.mt_arr[ _ix ].mtr_multipl
                < cak68_only_field_multiplier
            THEN
                mul_tabs.mt_arr[ _ix ].mtr_multipl := cak68_only_field_multiplier;
            (*ENDIF*) 
            END;
        (*ENDFOR*) 
        mul_tabs.mt_cnt := mul_tabs.mt_pos;
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
a681keval_key_kind := _jointype;
&ifdef TRACE
a683multabs_trace (ak_join, mul_tabs, mul_tabs.mt_cnt, 0, dmli.d_cntfromtab);
a683trace_jointype(ak_join, 'return      ', _jointype);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      a681key_sort_joinarr (
            VAR acv      : tak_all_command_glob;
            VAR dmli     : tak_dml_info;
            VAR series   : tak68_sequence;
            ser_pos      : integer;
            VAR sort_pos : integer;
            VAR mul_tabs : tak68_mult_tabs);
 
VAR
      _mj             : tak_one_join;
      _i              : integer;
      _j              : integer;
      _k              : integer;
      _l              : integer;
      _m              : integer;
      _old_sfieldcnt  : integer;
      _end_found      : boolean;
      _f_ok           : boolean;
      _use_table      : boolean;
      _curr_tab       : tsp00_Uint1;
      _nxt_fieldno    : tsp_int2;
      _tab_sequence   : tak_joinset;
      _col_buf        : tak00_colinfo_ptr;
 
BEGIN
_end_found := false;
_f_ok      := false;
_m         := 0;
FOR _i := 0 TO dmli.d_joins.jrc_cnt - 1 DO
    dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ 1 ].jop_outpos := _i;
(*ENDFOR*) 
_old_sfieldcnt := series[ ser_pos ].jos_fieldcnt;
series[ ser_pos ].jos_fieldcnt := 0;
_curr_tab := series[ ser_pos ].jos_source;
IF  (dmli.d_joins.jrc_joinarr
    [ series[ ser_pos ].jos_joinno ].jo_recs[ 1 ].jop_tableno = _curr_tab)
THEN
    BEGIN
    IF  (dmli.d_joins.jrc_joinarr[ series[ ser_pos ].jos_joinno ].
        jo_recs[ 2 ].jop_tableno = cak68_join_value)
    THEN
        _tab_sequence := [ ]
    ELSE
        _tab_sequence := [ dmli.d_joins.jrc_joinarr[ series[ ser_pos ].
              jos_joinno ].jo_recs[ 2 ].jop_tableno ];
    (*ENDIF*) 
    END
ELSE
    _tab_sequence := [ dmli.d_joins.jrc_joinarr
          [ series[ ser_pos ].jos_joinno ].jo_recs[ 1 ].jop_tableno ];
(*ENDIF*) 
IF  mul_tabs.mt_pos <> 0
THEN
    BEGIN
    _tab_sequence := mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tab_seq;
    _curr_tab     := mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_dst_table;
    END;
&ifdef TRACE
(*ENDIF*) 
t01int4 (ak_join, 'ser_pos     ', ser_pos);
t01int4 (ak_join, 'sort_pos    ', sort_pos);
t01int4 (ak_join, 'mt_pos      ', mul_tabs.mt_pos);
t01int4 (ak_join, 'jcnt        ', dmli.d_joins.jrc_cnt);
&endif
ak681first_keyfield_no (acv, dmli, _col_buf, _curr_tab, _nxt_fieldno, _f_ok);
_l := sort_pos;
_i := series[ ser_pos ].jos_joinno;
WHILE ((_l < dmli.d_joins.jrc_cnt) AND _f_ok AND (NOT _end_found)) DO
    BEGIN
&   ifdef TRACE
    t01int4 (ak_join, 'l           ', _l);
&   endif
    WHILE ((_i < dmli.d_joins.jrc_cnt) AND (NOT _end_found)) DO
        BEGIN
&       ifdef TRACE
        t01int4 (ak_join, 'i           ', _i);
&       endif
        IF  (dmli.d_joins.jrc_joinarr[ _i ].jo_op = op_eq)
        THEN
            BEGIN
            _j := 1;
            _k := 2;
            WHILE (_j <= 2) DO
                BEGIN
                IF  (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].jop_tableno = cak68_join_value)
                THEN
                    _use_table := true
                ELSE
                    BEGIN
                    _use_table := dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].jop_tableno
                          in _tab_sequence;
                    IF  (_tab_sequence = [ ])
                    THEN
                        BEGIN
                        _m := ser_pos;
                        WHILE (NOT _use_table) AND (_m > 1) DO
                            BEGIN
                            _m := pred (_m);
                            _use_table := series [ _m ].jos_source =
                                  dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].jop_tableno;
                            END;
                        (*ENDWHILE*) 
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
&               ifdef TRACE
                t01int4 (ak_join, 'jop_fieldno ',
                      dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].jop_fieldno);
                t01int4 (ak_join, 'curr_tab    ', _curr_tab);
                t01int4 (ak_join, 'jop_tableno ',
                      dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].jop_tableno);
                t01int4 (ak_join, 'use_table   ', ord (_use_table));
&               endif
                IF  ((dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].jop_tableno = _curr_tab)
                    AND
                    (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].jop_fieldno = _nxt_fieldno)
                    AND
                    (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].jop_cntstack = 1)
                    AND
                    (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].jop_inoutlen <=
                    dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].jop_inoutlen)
                    AND
                    (jtkey in dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].jop_propset)
                    AND
                    _use_table)
                THEN
                    BEGIN
                    series[ ser_pos ].jos_fieldcnt :=
                          succ (series[ ser_pos ].jos_fieldcnt);
&                   ifdef TRACE
                    t01int4 (ak_join, 'jos_fieldcnt',
                          series[ ser_pos ].jos_fieldcnt);
&                   endif
                    IF  series[ ser_pos ].jos_fieldcnt <
                        dmli.d_sparr.pbasep^.sbase.bkeycolcount
                    THEN
                        BEGIN
                        ak681next_keyfield_no (dmli,
                              _col_buf, _nxt_fieldno);
                        IF  (_m > 0)
                        THEN
                            _tab_sequence :=
                                  [ series[ _m ].jos_source ];
                        (*ENDIF*) 
                        IF  (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].
                            jop_inoutlen > dmli.d_joins.jrc_joinarr[ _i ].
                            jo_recs[ _k ].jop_inoutlen)
                        THEN
                            BEGIN
                            dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].
                                  jop_inoutlen := dmli.d_joins.jrc_joinarr[ _i ].
                                  jo_recs[ _j ].jop_inoutlen;
                            dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].
                                  jop_datalen  := dmli.d_joins.jrc_joinarr[ _i ].
                                  jo_recs[ _j ].jop_datalen;
                            END
                        ELSE
                            BEGIN
                            dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].
                                  jop_inoutlen := dmli.d_joins.jrc_joinarr[ _i ].
                                  jo_recs[ _k ].jop_inoutlen;
                            dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].
                                  jop_datalen  := dmli.d_joins.jrc_joinarr[ _i ].
                                  jo_recs[ _k ].jop_datalen;
                            END;
                        (*ENDIF*) 
                        END
                    ELSE
                        _end_found := true;
                    (*ENDIF*) 
                    IF  (_l < _i + 1)
                    THEN
                        BEGIN
                        _mj           := dmli.d_joins.jrc_joinarr[ _l ];
                        dmli.d_joins.jrc_joinarr[ _l ] :=
                              dmli.d_joins.jrc_joinarr[ _i ];
                        dmli.d_joins.jrc_joinarr[ _i ] := _mj;
                        _i            := dmli.d_joins.jrc_cnt; (* exit while *)
                        END;
                    (*ENDIF*) 
                    _j := 3; (* exit while *)
                    END;
                (*ENDIF*) 
                _j := succ (_j);
                _k := pred (_k);
                END;
            (*ENDWHILE*) 
            END;
        (*ENDIF*) 
        _i := succ (_i);
        END;
    (*ENDWHILE*) 
    _l := succ (_l);
    IF  (_l = series[ ser_pos ].jos_joinno)
    THEN
        _i := sort_pos
    ELSE
        _i := _l;
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
dmli.d_joins.jrc_joinarr[ sort_pos ].jo_recs[ 2 ].jop_outpos :=
      series[ ser_pos ].jos_fieldcnt;
sort_pos := sort_pos + series[ ser_pos ].jos_fieldcnt;
&ifdef TRACE
t01int4 (ak_join, 'end_found   ', ord (_end_found));
t01int4 (ak_join, 'i           ', _i);
t01int4 (ak_join, 'l           ', _l);
t01int4 (ak_join, 'field_cnt   ', series[ ser_pos ].jos_fieldcnt);
a683_output (ak_join, dmli);
IF  (series[ ser_pos ].jos_fieldcnt <> _old_sfieldcnt)
THEN
    vabort (c_write_core);
&endif
(*ENDIF*) 
ak681update_sequence (dmli, series, ser_pos, mul_tabs);
END;
 
(*------------------------------*) 
 
FUNCTION
      a681ieval_inv_kind (
            VAR acv          : tak_all_command_glob;
            VAR dmli         : tak_dml_info;
            VAR mul_tabs     : tak68_mult_tabs;
            pos_jarr         : integer;
            pos_jrec         : integer;
            is_join_value    : boolean) : tak68_one_jointype;
 
VAR
      _src               : integer;
      _curr_tabid        : tgg_surrogate;
      _index_scan_rec    : tak_index_scan_record;
      _index_tree        : tgg00_FileId;
      _jointype          : tak68_one_jointype;
      _curr_tab          : tsp00_Uint1;
 
BEGIN
_jointype := to_eq_field;
(* set correct mt_pos *)
mul_tabs.mt_pos := mul_tabs.mt_cnt;
IF  mul_tabs.mt_pos < mxak68_mt_arr
THEN
    BEGIN
&   ifdef TRACE
    t01int4 (ak_join, 'pos_jarr    ', pos_jarr);
    t01int4 (ak_join, 'pos_jrec    ', pos_jrec);
&   endif
    _curr_tab   := dmli.d_joins.jrc_joinarr[ pos_jarr ].
          jo_recs[ pos_jrec ].jop_tableno;
    _curr_tabid := dmli.d_tabarr[ _curr_tab ].otreeid.fileTabId_gg00;
    CASE pos_jrec OF
        1 :
            _src := 2;
        2 :
            _src := 1;
        END;
    (*ENDCASE*) 
    a24init_index_scan (acv, _curr_tabid, _index_scan_rec);
    WHILE a24next_named_index (acv, _index_scan_rec) AND
          (mul_tabs.mt_pos < mxak68_mt_arr) DO
        BEGIN
        (* create 'virtual' entry in mul_tabs *)
        mul_tabs.mt_pos := succ (mul_tabs.mt_cnt);
        IF  NOT _index_scan_rec.isr_buf^.smindex.
            indexdef[_index_scan_rec.isr_index].idisabled
        THEN
            BEGIN
            _index_tree := dmli.d_tabarr[ _curr_tab ].otreeid;
            (* set mindex file type *)
            _index_tree.fileTfn_gg00         := tfnMulti_egg00;
            _index_tree.fileTfnNo_gg00 [ 1 ] :=
                  chr(_index_scan_rec.isr_buf^.smindex.
                  indexdef[_index_scan_rec.isr_index].indexno);
            _index_tree.fileRoot_gg00 := NIL_PAGE_NO_GG00;
            b01filestate (acv.a_transinf.tri_trans, _index_tree);
            IF  (acv.a_transinf.tri_trans.trError_gg00 <>
                e_file_not_accessible)
            THEN
                IF  (dmli.d_joins.jrc_joinarr[ pos_jarr ].
                    jo_recs[ pos_jrec ].jop_fieldno = _index_scan_rec.
                    isr_buf^.smindex.indexdef[_index_scan_rec.isr_index].
                    icolseq[ 1 ]) AND NOT
                    (* h.b. PTS 1105999 *)
                    (* descending index doesn't support join strategy *)
                    (_index_scan_rec.isr_buf^.smindex.
                    indexdef[_index_scan_rec.isr_index].
                    icolstack[ 1 ].eop in [op_order_desc, op_unique_desc])
                THEN
                    BEGIN
                    (* we found first indexed column *)
                    _curr_tab := dmli.d_joins.jrc_joinarr[ pos_jarr ].
                          jo_recs[ pos_jrec ].jop_tableno;
                    (* initialize mul_tab entry *)
                    mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                          mtr_dst_table   := _curr_tab;
                    mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                          mtr_jointype  := _jointype;
                    mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                          mtr_fieldcnt  := 1;
                    mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                          mtr_indexno   := _index_scan_rec.isr_buf^.
                          smindex.indexdef[_index_scan_rec.isr_index].
                          indexno;
                    IF  (NOT is_join_value)
                    THEN
                        BEGIN
                        mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                              mtr_tab_seq  := [ dmli.d_joins.
                              jrc_joinarr[ pos_jarr ].jo_recs[ _src ].
                              jop_tableno ];
                        mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                              mtr_tablecnt := 1;
                        END
                    ELSE
                        BEGIN
                        mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                              mtr_tab_seq  := [ ];
                        mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                              mtr_tablecnt := 0;
                        END;
                    (*ENDIF*) 
                    mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                          mtr_multipl := dmli.d_joins.
                          jrc_joinarr[ pos_jarr ].jo_recs[ pos_jrec ].
                          jop_multiplier;
                    mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                          mtr_joinno  := pos_jarr;
                    ak681meval_one_minv(dmli, mul_tabs, pos_jarr, pos_jrec,
                          _index_scan_rec.isr_buf^.
                          smindex.indexdef[_index_scan_rec.isr_index],
                          _jointype, _curr_tab, is_join_value)
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    a24finish_index_scan (acv, _index_scan_rec);
    END;
(*ENDIF*) 
a681ieval_inv_kind := _jointype;
&ifdef TRACE
a683trace_jointype(ak_join, 'return      ', _jointype);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681meval_one_minv(
            VAR dmli      : tak_dml_info;
            VAR mul_tabs  : tak68_mult_tabs;
            pos_jarr      : integer;
            pos_jrec      : integer;
            VAR m_inddef  : tak_multindex;
            VAR jointype  : tak68_one_jointype;
            curr_tab      : tsp00_Uint1;
            is_join_value : boolean);
 
VAR
      _ix                : integer;
      (* index in jrc_joinarr *)
      _unknown_table_idx : integer;
      _dst               : integer;
      _src               : integer;
      _nxt_fieldno       : integer;
      _start_ut_cnt      : tsp_int2;
      _start_mt_cnt      : tsp_int2;
      _virt_mt_cnt       : tsp_int2;
      _unknown_table_pos : tsp_int2;
      _unknown_table_cnt : tsp_int2;
      _unknown_table_arr : tak681_unknown_table_arr;
      _new_tables        : tak_joinset;
      _f_ok              : boolean;
      _known_table       : boolean;
      _reset_loop        : boolean;
 
BEGIN
_f_ok := true;
CASE pos_jrec OF
    1:
        _src := 2;
    2:
        _src := 1;
    END;
(*ENDCASE*) 
IF  m_inddef.icount = 1
THEN
    BEGIN
    IF  m_inddef.iunique
    THEN
        BEGIN
        mul_tabs.mt_arr [ mul_tabs.mt_pos ].mtr_jointype := to_unique_field;
        mul_tabs.mt_arr [ mul_tabs.mt_pos ].mtr_multipl  := cak68_only_field_multiplier;
        END
    ELSE
        mul_tabs.mt_arr [ mul_tabs.mt_pos ].mtr_jointype := to_all_invfields;
    (*ENDIF*) 
    jointype        := to_mt_join;
    (* ensure new entry *)
    mul_tabs.mt_cnt := mul_tabs.mt_pos;
    END
ELSE
    (* multiple index *)
    BEGIN
    IF  (dmli.d_joins.jrc_joinarr[ pos_jarr ].jo_recs[ _src ].jop_inoutlen >
        dmli.d_joins.jrc_joinarr[ pos_jarr ].jo_recs[ pos_jrec ].jop_inoutlen)
    THEN
        (* ensure non complete join transition *)
        _f_ok := false;
    (*ENDIF*) 
    jointype := to_invpart;
    mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_jointype := jointype;
    (* get second index field number *)
    _nxt_fieldno   := m_inddef.
          icolseq [ mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_fieldcnt + 1 ];
    _virt_mt_cnt   := mul_tabs.mt_pos;
    _start_mt_cnt  := mul_tabs.mt_pos;
    _start_ut_cnt  := 0;
    _new_tables    := [ ];
    _unknown_table_cnt := 0;
    _unknown_table_pos := 1;
    REPEAT
        (* UNTIL (_unknown_table_pos > _unknown_table_cnt)   *)
        (* i.e. UNTIL no input into _unknown_table_arr *)
        IF  (_unknown_table_pos <= _unknown_table_cnt)
        THEN
            (* earlier insert into _unknown_table_arr *)
            BEGIN
            _start_ut_cnt := _unknown_table_cnt;
            _start_mt_cnt := _virt_mt_cnt;
            _new_tables   := [ ];
            (* just switch the first unknown table to known table *)
            _ix := _unknown_table_arr [ _unknown_table_pos ].ut_joinno;
            IF  mul_tabs.mt_pos < mxak68_mt_arr
            THEN
                BEGIN
                (* there are X entries in mul_tabs *)
                (* save the first entry            *)
                mul_tabs.mt_pos := succ (mul_tabs.mt_pos);
                _virt_mt_cnt    := mul_tabs.mt_pos;
                END;
            (*ENDIF*) 
            mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tab_seq  :=
                  mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tab_seq +
                  [ _unknown_table_arr [ _unknown_table_pos ].ut_tableno ];
            mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tablecnt :=
                  succ (mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tablecnt);
            _nxt_fieldno :=
                  m_inddef.icolseq[ mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_fieldcnt + 1 ];
            (* update _unknown_table_pos concerning new entry *)
            _unknown_table_pos   := succ (_unknown_table_pos);
            END
        ELSE
            _ix := 0;
        (*ENDIF*) 
        _unknown_table_idx := _ix;
        _reset_loop := false;
        WHILE (mul_tabs.mt_arr [ mul_tabs.mt_pos ].mtr_fieldcnt <
              m_inddef.icount) AND (_ix < dmli.d_joins.jrc_cnt) AND _f_ok DO
            BEGIN
            IF  ((_ix <> pos_jarr)
                AND
                (dmli.d_joins.jrc_joinarr[ _ix ].jo_op = op_eq))
            THEN
                (* walk through join conditions 'S.col = D.col' *)
                (* until complete key for _curr_tab found       *)
                WITH dmli.d_joins.jrc_joinarr[ _ix ] DO
                    BEGIN
                    _dst := 1;
                    _src := 2;
                    WHILE (_dst <= 2) DO
                        BEGIN
                        (* inspect join condition *)
                        IF  ((jo_recs[ _dst ].jop_tableno = curr_tab)
                            AND
                            (* field successor *)
                            (jo_recs[ _dst ].jop_fieldno = _nxt_fieldno)
                            AND
                            (jo_recs[ _src ].jop_inoutlen <=
                            jo_recs[ _dst ].jop_inoutlen)
                            AND
                            (* no function code *)
                            (jo_recs[ _dst ].jop_cntstack = 1)
                            AND
                            (jtmulti in jo_recs[ _dst ].jop_propset))
                        THEN
                            (* we found transition to actual *)
                            (* table with next key column    *)
                            BEGIN
                            (* check state of involved table *)
                            IF  (jo_recs[ _src ].jop_tableno =
                                cak68_join_value)
                            THEN
                                _known_table := true
                            ELSE
                                _known_table := jo_recs[ _src ].
                                      jop_tableno in
                                      mul_tabs.mt_arr [ mul_tabs.mt_pos ].
                                      mtr_tab_seq;
                            (*ENDIF*) 
                            IF  _known_table
                            THEN
                                BEGIN
                                (* we found 'wider' transition to current table *)
                                (* D.column1 -> S.invcol1 and D.column2 -> S.invcol2 *)
                                (* reject useless transition combination  *)
                                (* A.col -> S.invcol1, B.col -> S.invcol2 *)
                                (* reject earlier insert into _unknown_table_arr *)
                                _unknown_table_cnt := _start_ut_cnt;
                                (* reject earlier insert into mult_tabs  *)
                                _virt_mt_cnt       := _start_mt_cnt;
                                (* remark new minv transition      *)
                                (* count new minv field transition *)
                                mul_tabs.mt_arr [ mul_tabs.mt_pos ].
                                      mtr_fieldcnt := succ (mul_tabs.
                                      mt_arr [ mul_tabs.mt_pos ].mtr_fieldcnt);
                                _new_tables  := [ ];
                                (* get better multiplier *)
                                IF  (mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                                    mtr_multipl > jo_recs[ _dst ].jop_multiplier)
                                THEN
                                    mul_tabs.mt_arr[ mul_tabs.mt_pos ].
                                          mtr_multipl :=
                                          jo_recs[ _dst ].jop_multiplier;
                                (*ENDIF*) 
                                IF  (mul_tabs.mt_arr [ mul_tabs.mt_pos ].
                                    mtr_fieldcnt < m_inddef.icount)
                                THEN
                                    BEGIN
                                    (* there are other indexed columns *)
                                    (* get next considered indexed column *)
                                    (* *)
                                    (* h.b. PTS 1105999 *)
                                    (* descending index doesn't support join strategy *)
                                    IF  m_inddef.icolstack[mul_tabs.mt_arr[mul_tabs.mt_pos].
                                        mtr_fieldcnt + 1].eop in [op_order_desc, op_unique_desc]
                                    THEN
                                        BEGIN
                                        (* exit while*)
                                        _ix := dmli.d_joins.jrc_cnt;
                                        END
                                    ELSE
                                        BEGIN
                                        _nxt_fieldno := m_inddef.icolseq
                                              [ mul_tabs.mt_arr [ mul_tabs.mt_pos ].
                                              mtr_fieldcnt + 1 ];
                                        _reset_loop := true;
                                        END;
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    (* we found complete index *)
                                    BEGIN
                                    IF  m_inddef.iunique
                                    THEN
                                        BEGIN
                                        mul_tabs.mt_arr [ mul_tabs.mt_pos ].
                                              mtr_jointype := to_unique_field;
                                        mul_tabs.mt_arr [ mul_tabs.mt_pos ].
                                              mtr_multipl  :=
                                              cak68_only_field_multiplier;
                                        END
                                    ELSE
                                        mul_tabs.mt_arr [ mul_tabs.mt_pos ].
                                              mtr_jointype := to_all_invfields;
                                    (*ENDIF*) 
                                    (* exit while*)
                                    _ix := dmli.d_joins.jrc_cnt;
                                    END;
                                (*ENDIF*) 
                                END
                            ELSE
                                (* NOT _known_table *)
                                IF  (_unknown_table_cnt < MAX_JOINS_GG00)
                                    AND
                                    (_virt_mt_cnt < mxak68_mt_arr)
                                    AND
                                    (NOT (jo_recs[ _src ].jop_tableno in
                                    _new_tables))
                                THEN
                                    BEGIN
                                    (* insert unknown table into _unknown_table_arr *)
                                    _unknown_table_cnt :=
                                          succ (_unknown_table_cnt);
                                    _unknown_table_arr [ _unknown_table_cnt ].
                                          ut_tableno := jo_recs[ _src ].jop_tableno;
                                    (* remark index of join condition *)
                                    _unknown_table_arr [ _unknown_table_cnt ].
                                          ut_joinno := _ix;
                                    _virt_mt_cnt := succ (_virt_mt_cnt);
                                    (* create new entry in mult_tabs *)
                                    (* copy content from predecessor *)
                                    mul_tabs.mt_arr[ _virt_mt_cnt ] :=
                                          mul_tabs.mt_arr[ mul_tabs.mt_pos ];
                                    (* remark found new table in new table set *)
                                    _new_tables := _new_tables +
                                          [ _unknown_table_arr [ _unknown_table_cnt ].
                                          ut_tableno ];
                                    END;
                                (* exit work for parts      *)
                                (*ENDIF*) 
                            (*ENDIF*) 
                            _dst := 3;
                            END;
                        (* swap considered direction of join transition *)
                        (*ENDIF*) 
                        _dst := succ (_dst);
                        _src := pred (_src);
                        END;
                    (*ENDWHILE*) 
                    END;
                (*ENDWITH*) 
            (*ENDIF*) 
            IF  (mul_tabs.mt_arr [ mul_tabs.mt_pos ].mtr_jointype = to_all_invfields)
                AND
                (NOT is_join_value)
                AND
                (mul_tabs.mt_arr [ mul_tabs.mt_pos ].mtr_tablecnt = 1)
            THEN
                (* best join transition found *)
                BEGIN
                (* exit inner while *)
                _ix       := dmli.d_joins.jrc_cnt;
                END
            ELSE
                IF  (_unknown_table_idx > 0)
                    (* we found already a unknown table        *)
                    (* in a first walk through join conditions *)
                    AND
                    (_ix = _unknown_table_idx)
                THEN
                    BEGIN
                    (* now we have inserted unknown table mtr_tab_seq *)
                    (* loop with this this start table sequence       *)
                    (* through join conditions                        *)
                    _ix       := 0;
                    _unknown_table_idx := 0;
                    END
                ELSE
                    (* get next join condition *)
                    IF  NOT _reset_loop
                    THEN
                        _ix := succ (_ix)
                    ELSE
                        BEGIN
                        _reset_loop := false;
                        _ix         := 0;
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDWHILE*) 
    UNTIL
        (_unknown_table_pos > _unknown_table_cnt);
    (*ENDREPEAT*) 
    IF  (mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_fieldcnt > 0)
    THEN
        BEGIN
        jointype := to_mt_join;
        (* *** Multiplier update *** *)
        FOR _ix := mul_tabs.mt_cnt + 1 TO mul_tabs.mt_pos DO
            BEGIN
            (* h.b. PTS 1106028 *)
            IF  mul_tabs.mt_arr[ _ix ].mtr_multipl
                < cak68_only_field_multiplier
            THEN
                mul_tabs.mt_arr[ _ix ].mtr_multipl :=
                      cak68_only_field_multiplier;
            (*ENDIF*) 
            END;
        (*ENDFOR*) 
        (* ensure new entries *)
        mul_tabs.mt_cnt := mul_tabs.mt_pos;
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
&ifdef TRACE
a683multabs_trace (ak_join, mul_tabs, mul_tabs.mt_cnt, 0, dmli.d_cntfromtab);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      a681inv_sort_joinarr (
            VAR acv      : tak_all_command_glob;
            VAR dmli     : tak_dml_info;
            VAR jinfos   : tak68_joininfos;
            VAR series   : tak68_sequence;
            ser_pos      : integer;
            VAR sort_pos : integer;
            VAR mul_tabs : tak68_mult_tabs);
 
VAR
      _index_found    : boolean;
      _end_found      : boolean;
      _use_table      : boolean;
      _curr_tab       : tsp00_Uint1;
      _index_no       : integer;
      _old_sfieldcnt  : integer;
      _i              : integer;
      _j              : integer;
      _k              : integer;
      _l              : integer;
      _m              : integer;
      _nxt_fieldno    : integer;
      _mj             : tak_one_join;
      _index_scan_rec : tak_index_scan_record;
      _tab_sequence   : tak_joinset;
      _inv_tabid      : tgg_surrogate;
 
BEGIN
_end_found := false;
_m         := 0;
FOR _i := 0 TO dmli.d_joins.jrc_cnt - 1 DO
    dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ 1 ].jop_outpos := _i;
(*ENDFOR*) 
_old_sfieldcnt := series[ ser_pos ].jos_fieldcnt;
series[ ser_pos ].jos_fieldcnt     := 0;
_curr_tab      := series[ ser_pos ].jos_source;
&ifdef TRACE
t01int4 (ak_join, 'sort_pos    ', sort_pos);
t01int4 (ak_join, 'jcnt        ', dmli.d_joins.jrc_cnt);
a683_output (ak_join, dmli);
&endif
WITH dmli.d_joins.jrc_joinarr[ series[ ser_pos ].jos_joinno ] DO
    BEGIN
    IF  (jo_recs[ 1 ].jop_tableno = _curr_tab)
    THEN
        BEGIN
        IF  (jo_recs[ 2 ].jop_tableno = cak68_join_value)
        THEN
            _tab_sequence := [ ]
        ELSE
            _tab_sequence := [ jo_recs[ 2 ].jop_tableno ];
        (*ENDIF*) 
        _nxt_fieldno  := jo_recs[ 1 ].jop_fieldno;
        END
    ELSE
        BEGIN
        _tab_sequence := [ jo_recs[ 1 ].jop_tableno ];
        _nxt_fieldno  := jo_recs[ 2 ].jop_fieldno;
        END;
    (*ENDIF*) 
    IF  mul_tabs.mt_pos <> 0
    THEN
        BEGIN
        _tab_sequence := mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_tab_seq;
        _index_no     := mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_indexno;  (* used multiple indexno *)
        _curr_tab     := mul_tabs.mt_arr[ mul_tabs.mt_pos ].mtr_dst_table;
        END
    ELSE
        _index_no := series[ ser_pos ].jos_indexno; (* used multiple indexno *)
    (*ENDIF*) 
&   ifdef TRACE
    t01int4 (ak_join, 'mt_pos      ', mul_tabs.mt_pos);
    t01int4 (ak_join, 'jcnt        ', dmli.d_joins.jrc_cnt);
&   endif
    END;
(*ENDWITH*) 
&ifdef TRACE
t01int4 (ak_join, 'curr_tab    ', _curr_tab);
t01int4 (ak_join, 'jos_indexno ', series[ ser_pos ].jos_indexno);
t01int4 (ak_join, 'index_no    ', ord (_index_no));
&endif
BEGIN
_inv_tabid := dmli.d_tabarr[ series[ ser_pos ].jos_source ].otreeid.fileTabId_gg00;
a24init_index_scan (acv, _inv_tabid, _index_scan_rec);
END;
_index_found := false;
REPEAT
    IF  a24next_named_index (acv, _index_scan_rec)
    THEN
        _index_found := (_index_no = _index_scan_rec.isr_buf^.
              smindex.indexdef[_index_scan_rec.isr_index].indexno)
    ELSE
        a07ak_system_error (acv, 681, 1);
    (*ENDIF*) 
UNTIL
    _index_found OR (acv.a_return_segm^.sp1r_returncode <> 0);
(*ENDREPEAT*) 
a24finish_index_scan (acv, _index_scan_rec);
IF  _index_found
THEN
    BEGIN
    _l           := sort_pos;
    _i           := series[ ser_pos ].jos_joinno;
    _nxt_fieldno := _index_scan_rec.isr_buf^.smindex.
          indexdef[_index_scan_rec.isr_index].icolseq[ series[ ser_pos ].jos_fieldcnt + 1 ];
    WHILE ((_l < dmli.d_joins.jrc_cnt) AND (NOT _end_found)) DO
        BEGIN
&       ifdef TRACE
        t01int4 (ak_join, 'l           ', _l);
&       endif
        WHILE ((_i < dmli.d_joins.jrc_cnt) AND (NOT _end_found)) DO
            BEGIN
&           ifdef TRACE
            t01int4 (ak_join, 'i           ', _i);
            t01int4 (ak_join, 'nxt_fieldno ', _nxt_fieldno);
&           endif
            IF  (dmli.d_joins.jrc_joinarr[ _i ].jo_op = op_eq)
            THEN
                WITH dmli.d_joins.jrc_joinarr[ _i ] DO
                    BEGIN
                    _j := 1;
                    _k := 2;
                    WHILE (_j <= 2) DO
                        BEGIN
                        IF  (jo_recs[ _k ].jop_tableno = cak68_join_value)
                        THEN
                            _use_table := true
                        ELSE
                            BEGIN
                            _use_table :=
                                  jo_recs[ _k ].jop_tableno
                                  in _tab_sequence;
                            IF  (_tab_sequence = [ ])
                            THEN
                                BEGIN
                                _m := ser_pos;
                                WHILE (NOT _use_table) AND (_m > 1) DO
                                    BEGIN
                                    _m := pred (_m);
                                    _use_table := series [ _m ].jos_source =
                                          jo_recs[ _k ].jop_tableno;
                                    END;
                                (*ENDWHILE*) 
                                END;
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        WITH jo_recs[ _j ] DO
                            BEGIN
                            IF  ((jop_tableno = _curr_tab)        AND
                                (jop_fieldno = _nxt_fieldno)      AND
                                (jop_cntstack = 1)               AND
                                (jtmulti in jop_propset)         AND
                                _use_table)
                            THEN
                                BEGIN
                                IF  (_m > 0)
                                THEN
                                    _tab_sequence :=
                                          [ series[ _m ].jos_source ];
&                               ifdef TRACE
                                (*ENDIF*) 
                                t01int4 (ak_join, 'jop_startsta', jop_startstack);
                                t01stackentry (ak_join, jinfos.ji_st_addr^[ jop_startstack ],
                                      jop_startstack);
&                               endif
                                series[ ser_pos ].jos_fieldcnt := succ (series[ ser_pos ].jos_fieldcnt);
                                _nxt_fieldno := _index_scan_rec.isr_buf^.
                                      smindex.indexdef[_index_scan_rec.isr_index].
                                      icolseq [ series[ ser_pos ].jos_fieldcnt + 1 ];
                                IF  _index_scan_rec.isr_buf^.smindex.
                                    indexdef[_index_scan_rec.isr_index].
                                    icolstack[ series[ ser_pos ].jos_fieldcnt ].eop in
                                    [ op_order_desc, op_unique_desc ]
                                THEN
                                    WITH jinfos.ji_st_addr^[ jop_startstack ] DO
                                        CASE eop OF
                                            op_ascii :
                                                IF  (_index_scan_rec.isr_buf^.smindex.
                                                    indexdef[_index_scan_rec.isr_index].
                                                    icolstack[ series[ ser_pos ].jos_fieldcnt ].eop =
                                                    op_order_desc)
                                                THEN
                                                    eop := op_order_desc_ascii
                                                ELSE
                                                    eop := op_unique_desc_ascii;
                                                (*ENDIF*) 
                                            op_ebcdic :
                                                IF  (_index_scan_rec.isr_buf^.smindex.
                                                    indexdef[_index_scan_rec.isr_index].
                                                    icolstack[ series[ ser_pos ].jos_fieldcnt ].eop =
                                                    op_order_desc)
                                                THEN
                                                    eop := op_order_desc_ebcdic
                                                ELSE
                                                    eop := op_unique_desc_ebcdic;
                                                (*ENDIF*) 
                                            OTHERWISE
                                                jinfos.ji_st_addr^[ jop_startstack ].eop :=
                                                      _index_scan_rec.isr_buf^.smindex.
                                                      indexdef[_index_scan_rec.isr_index].
                                                      icolstack[ series[ ser_pos ].jos_fieldcnt ].eop;
                                            END;
                                        (*ENDCASE*) 
                                    (*ENDWITH*) 
&                               ifdef TRACE
                                (*ENDIF*) 
                                t01stackentry (ak_join,
                                      jinfos.ji_st_addr^[ jop_startstack ],
                                      jop_startstack);
&                               endif
                                IF  (series[ ser_pos ].jos_fieldcnt >= _old_sfieldcnt)
                                THEN
                                    _end_found := true;
                                (*ENDIF*) 
                                IF  (series[ ser_pos ].jos_fieldcnt <= _old_sfieldcnt) AND
                                    (jo_recs[ _k ].jop_inoutlen < jop_inoutlen)
                                THEN
                                    BEGIN
                                    IF  (jop_inoutlen > jo_recs[ _k ].jop_inoutlen)
                                    THEN
                                        BEGIN
                                        jo_recs[ _k ].jop_inoutlen := jop_inoutlen;
                                        jo_recs[ _k ].jop_datalen  := jop_datalen;
                                        END
                                    ELSE
                                        BEGIN
                                        jop_inoutlen := jo_recs[ _k ].jop_inoutlen;
                                        jop_datalen  := jo_recs[ _k ].jop_datalen;
                                        END;
                                    (*ENDIF*) 
                                    END;
                                (*ENDIF*) 
                                IF  (_l < _i + 1)
                                THEN
                                    BEGIN
                                    _mj := dmli.d_joins.jrc_joinarr[ _l ];
                                    dmli.d_joins.jrc_joinarr[ _l ] :=
                                          dmli.d_joins.jrc_joinarr[ _i ];
                                    dmli.d_joins.jrc_joinarr[ _i ] := _mj;
                                    _i := dmli.d_joins.jrc_cnt; (* exit while *)
                                    END;
                                (*ENDIF*) 
                                _j := 3; (* exit while *)
                                END;
                            (*ENDIF*) 
                            _j := succ (_j);
                            _k := pred (_k);
                            END;
                        (*ENDWITH*) 
                        END;
                    (*ENDWHILE*) 
                    END;
                (*ENDWITH*) 
            (*ENDIF*) 
            _i := succ (_i);
            END;
        (*ENDWHILE*) 
        _l := succ (_l);
        IF  (_l = series[ ser_pos ].jos_joinno)
        THEN
            _i := sort_pos
        ELSE
            _i := _l;
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    dmli.d_joins.jrc_joinarr[ sort_pos ].jo_recs[ 2 ].jop_outpos :=
          series[ ser_pos ].jos_fieldcnt;
    sort_pos := sort_pos + series[ ser_pos ].jos_fieldcnt;
&   ifdef TRACE
    t01int4 (ak_join, 'end_found   ', ord (_end_found));
    t01int4 (ak_join, 'i           ', _i);
    t01int4 (ak_join, 'l           ', _l);
    t01int4 (ak_join, 'jos_fieldcnt', series[ ser_pos ].jos_fieldcnt);
    IF  (series[ ser_pos ].jos_fieldcnt <> _old_sfieldcnt)
    THEN
        vabort (c_write_core);
&   endif
    (*ENDIF*) 
    END;
(*ENDIF*) 
ak681update_sequence (dmli, series, ser_pos, mul_tabs);
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681update_sequence (
            VAR dmli     : tak_dml_info;
            VAR series   : tak68_sequence;
            ser_pos      : integer;
            VAR mul_tabs : tak68_mult_tabs);
 
VAR
      _i : integer;
      _j : integer;
 
BEGIN
&ifdef TRACE
t01int4 (ak_join, 'ser_pos     ', ser_pos);
&endif
FOR _i := 1 TO dmli.d_cntfromtab DO
    BEGIN
    _j := 0;
    WHILE (_j < dmli.d_joins.jrc_cnt) DO
        BEGIN
        IF  (series[ _i ].jos_joinno = dmli.d_joins.jrc_joinarr[ _j ].
            jo_recs[ 1 ].jop_outpos)
        THEN
            BEGIN
            series[ _i ].jos_joinno  := _j;
&           ifdef TRACE
            t01int4 (ak_join, 'i -->series ', _i);
            t01int4 (ak_join, 'j -->joinarr', _j);
            t01int4 (ak_join, 'jos_joinno  ', series[ _i ].jos_joinno);
            t01int4 (ak_join, 'jos_fieldcnt', series[ _i ].jos_fieldcnt);
&           endif
            _j := dmli.d_joins.jrc_cnt; (* exit while *)
            END;
        (*ENDIF*) 
        _j := succ (_j);
        END;
    (*ENDWHILE*) 
    END;
(*ENDFOR*) 
FOR _i := 1 TO mul_tabs.mt_cnt DO
    BEGIN
    _j := 0;
    WHILE (_j < dmli.d_joins.jrc_cnt) DO
        BEGIN
        IF  (mul_tabs.mt_arr [ _i ].mtr_joinno =
            dmli.d_joins.jrc_joinarr[ _j ].jo_recs[ 1 ].jop_outpos)
        THEN
            BEGIN
            mul_tabs.mt_arr [ _i ].mtr_joinno  := _j;
&           ifdef TRACE
            t01int4 (ak_join, 'i -->mt-jno ', _i);
            t01int4 (ak_join, 'j -->joinarr', _j);
&           endif
            _j := dmli.d_joins.jrc_cnt; (* exit while *)
            END;
        (*ENDIF*) 
        _j := succ (_j);
        END;
    (*ENDWHILE*) 
    END;
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681elim_duplicate_st_pos (
            VAR acv      : tak_all_command_glob;
            VAR jinfos   : tak68_joininfos;
            VAR dmli     : tak_dml_info;
            VAR eq_rec   : tak68_eq_record;
            VAR used_set : tak681_used_jrc_set_type);
 
VAR
      _i           : integer;
      _k           : integer;
      _cnt         : integer;
      _free_st_pos : integer;
 
BEGIN
&ifdef TRACE
t01int4 (ak_join, 'eqr_cnt     ', eq_rec.eqr_cnt);
FOR _i := 1 TO eq_rec.eqr_cnt DO
    BEGIN
    t01int4 (ak_join, 'eq used ==>l', eq_rec.eqr_left[ _i ].eqi_joinno);
    t01int4 (ak_join, 'eq used ==>r', eq_rec.eqr_right[ _i ].eqi_joinno);
    END;
(*ENDFOR*) 
&endif
_k := 0;
FOR _i := eq_rec.eqr_cnt DOWNTO 1 DO
    BEGIN
&   ifdef TRACE
    t01int4 (ak_join, 'eqr_left i  ', _i);
    t01int4 (ak_join, 'eq stpos==>l', eq_rec.eqr_left[ _i ].eqi_stackpos);
    t01int4 (ak_join, 'eq stpos==>r', eq_rec.eqr_right[ _i ].eqi_stackpos);
&   endif
    _cnt := ak681cnt_st_entry_in_use (eq_rec, eq_rec.eqr_left[ _i ].eqi_stackpos);
    IF  (_cnt > 1) AND (_k < dmli.d_joins.jrc_cnt)
    THEN
        BEGIN
&       ifdef TRACE
        t01int4 (ak_join, 'eqi_stackpos', eq_rec.eqr_left[ _i ].eqi_stackpos);
&       endif
        _free_st_pos := -1;
        WHILE (_free_st_pos < 1) AND (_k < dmli.d_joins.jrc_cnt) DO
            IF  NOT (_k in used_set)
            THEN
                WITH dmli.d_joins.jrc_joinarr[ _k ] DO
                    BEGIN
                    IF  (ak681cnt_st_entry_in_use (eq_rec,
                        jo_recs[ 1 ].jop_startstack) = 0)
                    THEN
                        _free_st_pos := jo_recs[ 1 ].jop_startstack
                    ELSE
                        IF  (ak681cnt_st_entry_in_use (eq_rec,
                            jo_recs[ 2 ].jop_startstack) = 0)
                        THEN
                            _free_st_pos := jo_recs[ 2 ].jop_startstack
                        ELSE
                            _k := succ (_k);
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END
                (*ENDWITH*) 
            ELSE
                _k := succ (_k);
            (*ENDIF*) 
        (*ENDWHILE*) 
&       ifdef TRACE
        t01int4 (ak_join, 'k  left     ', _k);
&       endif
        IF  _free_st_pos > 0
        THEN
            BEGIN
            WITH jinfos.ji_stack_desc, eq_rec.eqr_left[ _i ] DO
                BEGIN
&               ifdef TRACE
                t01int4 (ak_join, 'k found  l  ', _k);
                t01int4 (ak_join, 'eqi_joinno  ', eqi_joinno);
                t01int4 (ak_join, 'eqi_jrecs   ', eqi_jrecs);
                t01int4 (ak_join, 'free_st_pos ', _free_st_pos);
&               endif
                g10mv ('VAK681',   1,    
                      (mst_max * mxgg_stack_entry),
                      (mst_max * mxgg_stack_entry),
                      jinfos.ji_st_addr^, (eqi_stackpos - 1) * mxgg_stack_entry + 1,
                      jinfos.ji_st_addr^, (_free_st_pos - 1) * mxgg_stack_entry + 1,
                      mxgg_stack_entry, acv.a_return_segm^.sp1r_returncode);
                dmli.d_joins.jrc_joinarr[ eqi_joinno ].jo_recs[ eqi_jrecs ].jop_startstack :=
                      _free_st_pos;
                eqi_stackpos := _free_st_pos;
                _cnt        := pred (_cnt);
                END;
            (*ENDWITH*) 
            END;
        (*ENDIF*) 
        END;
&   ifdef TRACE
    (*ENDIF*) 
    t01int4 (ak_join, 'eqr_right i ', _i);
    t01int4 (ak_join, 'eq stpos==>l', eq_rec.eqr_left[ _i ].eqi_stackpos);
    t01int4 (ak_join, 'eq stpos==>r', eq_rec.eqr_right[ _i ].eqi_stackpos);
&   endif
    _cnt := ak681cnt_st_entry_in_use (eq_rec, eq_rec.eqr_right[ _i ].eqi_stackpos);
    IF  (_cnt > 1) AND (_k < dmli.d_joins.jrc_cnt)
    THEN
        BEGIN
&       ifdef TRACE
        t01int4 (ak_join, 'eqi_stackpos', eq_rec.eqr_right[ _i ].eqi_stackpos);
&       endif
        _free_st_pos := -1;
        WHILE (_free_st_pos < 1) AND (_k < dmli.d_joins.jrc_cnt) DO
            IF  NOT (_k in used_set)
            THEN
                WITH dmli.d_joins.jrc_joinarr[ _k ] DO
                    BEGIN
                    IF  (ak681cnt_st_entry_in_use (eq_rec,
                        jo_recs[ 1 ].jop_startstack) = 0)
                    THEN
                        _free_st_pos := jo_recs[ 1 ].jop_startstack
                    ELSE
                        IF  (ak681cnt_st_entry_in_use (eq_rec,
                            jo_recs[ 2 ].jop_startstack) = 0)
                        THEN
                            _free_st_pos := jo_recs[ 2 ].jop_startstack
                        ELSE
                            _k := succ (_k);
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END
                (*ENDWITH*) 
            ELSE
                _k := succ (_k);
            (*ENDIF*) 
        (*ENDWHILE*) 
&       ifdef TRACE
        t01int4 (ak_join, 'k right     ', _k);
&       endif
        IF  _free_st_pos > 0
        THEN
            BEGIN
            WITH jinfos.ji_stack_desc, eq_rec.eqr_right[ _i ] DO
                BEGIN
&               ifdef TRACE
                t01int4 (ak_join, 'k found  r  ', _k);
                t01int4 (ak_join, 'eqi_joinno  ', eqi_joinno);
                t01int4 (ak_join, 'eqi_jrecs   ', eqi_jrecs);
                t01int4 (ak_join, 'free_st_pos ', _free_st_pos);
&               endif
                g10mv ('VAK681',   2,    
                      (mst_max * mxgg_stack_entry),
                      (mst_max * mxgg_stack_entry),
                      jinfos.ji_st_addr^, (eqi_stackpos - 1) * mxgg_stack_entry + 1,
                      jinfos.ji_st_addr^, (_free_st_pos - 1) * mxgg_stack_entry + 1,
                      mxgg_stack_entry, acv.a_return_segm^.sp1r_returncode);
                dmli.d_joins.jrc_joinarr[ eqi_joinno ].jo_recs[ eqi_jrecs ].jop_startstack :=
                      _free_st_pos;
                eqi_stackpos := _free_st_pos;
                _cnt        := pred (_cnt);
                END;
            (*ENDWITH*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      ak681cnt_st_entry_in_use (
            VAR eq_rec  : tak68_eq_record;
            st_pos      : integer) : integer;
 
VAR
      _i   : integer;
      _cnt : integer;
 
BEGIN
_cnt := 0;
FOR _i := 1 TO eq_rec.eqr_cnt DO
    IF  ((eq_rec.eqr_left[ _i ].eqi_stackpos = st_pos) OR
        ( eq_rec.eqr_right[ _i ].eqi_stackpos = st_pos))
    THEN
        _cnt := succ (_cnt);
&   ifdef TRACE
    (*ENDIF*) 
(*ENDFOR*) 
t01int4 (ak_join, 'st_pos      ', st_pos);
t01int4 (ak_join, 'cnt         ', _cnt);
&endif
ak681cnt_st_entry_in_use := _cnt;
END;
 
(*------------------------------*) 
 
PROCEDURE
      a681sort_conditions (
            VAR acv    : tak_all_command_glob;
            VAR dmli   : tak_dml_info;
            VAR series : tak68_sequence);
 
VAR
      _i         : integer;
      _j         : integer;
      _end_pos   : integer;
      _sort_pos  : integer;
 
BEGIN
(* **** sort in order of special-strategies give by jos_joinno *** *)
_sort_pos := 0;
series[ 1 ].jos_joinno := cak68_cartesian_product;
FOR _i := 2 TO dmli.d_cntfromtab DO
    IF  (series[ _i ].jos_joinno <> cak68_cartesian_product)
    THEN
        BEGIN
&       ifdef TRACE
        t01int4 (ak_join, 'join_num    ', series[ _i ].jos_joinno);
        t01int4 (ak_join, 'sort_pos    ', _sort_pos);
        t01int4 (ak_join, 'i           ', _i);
&       endif
        IF  (_sort_pos <> series[ _i ].jos_joinno)
        THEN
            BEGIN
            ak681move_in_front (acv, dmli, series[ _i ].jos_joinno, _sort_pos, series[ _i ].jos_fieldcnt);
            FOR _j := (_i + 1) TO dmli.d_cntfromtab DO
                IF  series[ _j ].jos_joinno = series[ _i ].jos_joinno
                THEN
                    BEGIN
                    _sort_pos := _sort_pos + series[ _j ].jos_fieldcnt -
                          series[ _i ].jos_fieldcnt;
                    series[ _j ].jos_joinno := cak68_cartesian_product;
                    END
                ELSE
                    IF  series[ _j ].jos_joinno < series[ _i ].jos_joinno
                    THEN
                        series[ _j ].jos_joinno :=
                              series[ _j ].jos_joinno + series[ _i ].jos_fieldcnt;
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDFOR*) 
            END
        ELSE
            FOR _j := (_i + 1) TO dmli.d_cntfromtab DO
                IF  series[ _j ].jos_joinno = series[ _i ].jos_joinno
                THEN
                    BEGIN
                    _sort_pos := _sort_pos + series[ _j ].jos_fieldcnt -
                          series[ _i ].jos_fieldcnt;
                    series[ _j ].jos_joinno := cak68_cartesian_product;
                    END;
                (*ENDIF*) 
            (*ENDFOR*) 
        (*ENDIF*) 
        _sort_pos := _sort_pos + series[ _i ].jos_fieldcnt;
        series[ _i ].jos_joinno := cak68_cartesian_product;
        END;
&   ifdef TRACE
    (*ENDIF*) 
(*ENDFOR*) 
FOR _i := 1 TO dmli.d_cntfromtab DO
    BEGIN
    t01int4 (ak_join, 'table_no    ', series[ _i ].jos_source);
    t01int4 (ak_join, 'join_strat  ', ord(series[ _i ].jos_joinstrat));
    t01int4 (ak_join, 'join_invinde', series[ _i ].jos_indexno);
    t01int4 (ak_join, 'join_num    ', ord(series[ _i ].jos_joinno));
    t01int4 (ak_join, 'jos_fieldcnt', ord(series[ _i ].jos_fieldcnt));
    END;
(*ENDFOR*) 
t01int4  (ak_join, 'sort_pos    ', _sort_pos);
&endif
_end_pos := pred (dmli.d_joins.jrc_cnt);
(* evaluate the number of equal-joininfos *)
WHILE (_end_pos > _sort_pos) AND (dmli.d_joins.jrc_joinarr[ _end_pos ].jo_op <> op_eq) DO
    _end_pos := pred (_end_pos);
(*ENDWHILE*) 
_i := _end_pos;
&ifdef TRACE
t01int4  (ak_join, 'end_pos     ', _i);
&endif
WHILE (_i >= 0) DO
    BEGIN
    IF  (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ 2 ].jop_tableno  = cak68_join_value) AND
        (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ 2 ].jop_cntstack = 1)               AND
        (NOT dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ 1 ].jop_outer_join)
    THEN
        (* *** try to eliminate value-join-condition *** *)
        BEGIN
&       ifdef TRACE
        t01int4  (ak_join, 'JOIN_VALUE  ', _i);
&       endif
        IF  _i >= _sort_pos
        THEN
            (* *** join_value not used by join-strategies *** *)
            BEGIN
&           ifdef TRACE
            t01int4  (ak_join, 'i before    ', _i);
&           endif
            ak681pack_join_cond (dmli, series, _i);
            _end_pos := pred (_end_pos);
            END
        ELSE
            BEGIN
            _j := _end_pos;
&           ifdef TRACE
            t01int4  (ak_join, 'JOIN_VALUE 2', _j);
&           endif
            WHILE (_j >= _sort_pos) DO
                BEGIN
                WITH dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ 1 ], dmli.d_joins.jrc_joinarr[ _j ] DO
                    BEGIN
                    IF  (((jo_recs[ 1 ].jop_tableno  = jop_tableno ) AND
                        (  jo_recs[ 1 ].jop_fieldno  = jop_fieldno ) AND
                        (  jo_recs[ 1 ].jop_cntstack = 1   )    ) OR
                        ( (jo_recs[ 2 ].jop_tableno  = jop_tableno ) AND
                        (  jo_recs[ 2 ].jop_fieldno  = jop_fieldno ) AND
                        (  jo_recs[ 2 ].jop_cntstack = 1   )    )   ) AND
                        (NOT jo_recs[ 1 ].jop_outer_join) AND
                        (NOT jo_recs[ 2 ].jop_outer_join)
                    THEN
                        BEGIN
&                       ifdef TRACE
                        t01int4  (ak_join, 'j before    ', _j);
&                       endif
                        ak681pack_join_cond (dmli, series, _j);
                        _end_pos := pred (_end_pos);
                        _j       := -3; (* exit while *)
                        END
                    ELSE
                        _j := pred (_j);
                    (*ENDIF*) 
                    END;
                (*ENDWITH*) 
                END;
            (*ENDWHILE*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    _i := pred (_i);
    END;
(*ENDWHILE*) 
&ifdef TRACE
FOR _i := 1 TO dmli.d_cntfromtab DO
    BEGIN
    t01int4 (ak_join, 'table_no    ', series[ _i ].jos_source);
    t01int4 (ak_join, 'join_strat  ', ord(series[ _i ].jos_joinstrat));
    t01int4 (ak_join, 'join_invinde', series[ _i ].jos_indexno);
    t01int4 (ak_join, 'join_num    ', ord(series[ _i ].jos_joinno));
    t01int4 (ak_join, 'jos_fieldcnt', ord(series[ _i ].jos_fieldcnt));
    END;
(*ENDFOR*) 
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681move_in_front (
            VAR acv  : tak_all_command_glob;
            VAR dmli : tak_dml_info;
            from_pos : integer;
            to_pos   : integer;
            cnt      : integer);
 
VAR
      _i          : integer;
      _j          : integer;
      _m_one_join : tak_one_join;
 
BEGIN
IF  (cnt > 0)
THEN
    IF  ((dmli.d_joins.jrc_cnt + from_pos - to_pos) > MAX_JOINS_GG00)
    THEN
        FOR _i := 0 TO (cnt - 1) DO
            BEGIN
            _m_one_join := dmli.d_joins.jrc_joinarr[ from_pos + _i ];
            FOR _j := (from_pos + _i) DOWNTO (to_pos + _i + 1) DO
                dmli.d_joins.jrc_joinarr[ _j ] := dmli.d_joins.jrc_joinarr[ _j - 1 ];
            (*ENDFOR*) 
            dmli.d_joins.jrc_joinarr[ to_pos + _i ] := _m_one_join;
            END
        (*ENDFOR*) 
    ELSE
        BEGIN
        g10mvb ('VAK681',   3,    
              sizeof(dmli.d_joins.jrc_joinarr), sizeof(dmli.d_joins.jrc_joinarr),
              dmli.d_joins.jrc_joinarr, to_pos * mxak_one_join + 1,
              dmli.d_joins.jrc_joinarr, dmli.d_joins.jrc_cnt * mxak_one_join + 1,
              (from_pos - to_pos) * mxak_one_join,
              acv.a_return_segm^.sp1r_returncode);
        g10mv1 ('VAK681',   4,    
              sizeof(dmli.d_joins.jrc_joinarr), sizeof(dmli.d_joins.jrc_joinarr),
              dmli.d_joins.jrc_joinarr, from_pos * mxak_one_join + 1,
              dmli.d_joins.jrc_joinarr, to_pos * mxak_one_join + 1,
              cnt * mxak_one_join,
              acv.a_return_segm^.sp1r_returncode);
        g10mv1 ('VAK681',   5,    
              sizeof(dmli.d_joins.jrc_joinarr), sizeof(dmli.d_joins.jrc_joinarr),
              dmli.d_joins.jrc_joinarr, dmli.d_joins.jrc_cnt * mxak_one_join + 1,
              dmli.d_joins.jrc_joinarr, (to_pos + cnt) * mxak_one_join + 1,
              (from_pos - to_pos) * mxak_one_join,
              acv.a_return_segm^.sp1r_returncode);
        END;
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      ak681all_multabs_in_succ (
            VAR mul_tab         : tak68_mul_tab_rec;
            VAR newsuccession   : tak68_succession;
            processed_table_cnt : integer) : boolean;
 
VAR
      _xi         : integer;
      _found_tabs : integer;
 
BEGIN
_found_tabs := 0;
FOR _xi := 1 TO processed_table_cnt DO
    IF  (newsuccession[ _xi ].s_tableno in mul_tab.mtr_tab_seq)
    THEN
        _found_tabs := succ (_found_tabs);
    (*ENDIF*) 
(*ENDFOR*) 
ak681all_multabs_in_succ := (_found_tabs = mul_tab.mtr_tablecnt);
END;
 
(*------------------------------*) 
 
PROCEDURE
      a681test_outer_qualification (
            VAR acv     : tak_all_command_glob;
            VAR dmli    : tak_dml_info;
            VAR jinfos  : tak68_joininfos);
 
VAR
      _xi               : integer;
      _xj               : integer;
      _table_qual_found : boolean;
      _pack_joinarr     : boolean;
 
BEGIN
_table_qual_found := false;
_pack_joinarr     := false;
_xi := 0;
_xj := 0;
WHILE (_xi < dmli.d_joins.jrc_cnt) DO
    BEGIN
    IF  (dmli.d_joins.jrc_joinarr[ _xi ].jo_recs[ 1 ].jop_tableno MOD 100 =
        jinfos.ji_acttabno)
    THEN
        (* actual table T found on left side of join *)
        BEGIN
        IF  ( NOT dmli.d_joins.jrc_joinarr[ _xi ].jo_recs[ 1 ].jop_outer_join )
        THEN
            (* actual table T isn't an outer join table *)
            BEGIN
            _table_qual_found := true;
            IF  (dmli.d_joins.jrc_joinarr[ _xi ].jo_recs[ 2 ].jop_tableno =
                cak68_join_value)
            THEN
                (* T.column <op> <constant>          *)
                (* realize local non-equal predicate *)
                _pack_joinarr := _pack_joinarr OR
                      (dmli.d_joins.jrc_joinarr[ _xi ].jo_op <> op_eq);
            (*ENDIF*) 
            END
        ELSE
            (* actual table T is an outer join part *)
            IF  (dmli.d_joins.jrc_joinarr[ _xi ].jo_recs[ 2 ].jop_tableno =
                cak68_join_value)
            THEN
                (* T.column (+) <op> <constant>                     *)
                (* mean to evaluate condition before evaluation     *)
                (* of other outer join on the table T               *)
                (* important only in case of 'T.column (+) IS NULL' *)
                _pack_joinarr     := true;
            (*ENDIF*) 
        (*ENDIF*) 
        END
    ELSE
        IF  (dmli.d_joins.jrc_joinarr[ _xi ].jo_recs[ 2 ].jop_tableno MOD 100 =
            jinfos.ji_acttabno)
        THEN
            (* actual table T found on right side of join *)
            BEGIN
            IF  (dmli.d_joins.jrc_joinarr[ _xi ].jo_recs[ 1 ].jop_tableno =
                dmli.d_joins.jrc_joinarr[ _xi ].jo_recs[ 2 ].jop_tableno)
            THEN
                _pack_joinarr := true;
            (*ENDIF*) 
            IF  ( NOT dmli.d_joins.jrc_joinarr[ _xi ].jo_recs[ 2 ].jop_outer_join )
            THEN
                _table_qual_found := true;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    _xi := succ (_xi);
    END;
(*ENDWHILE*) 
IF  _pack_joinarr
THEN
    (* delete all 'X.column <non-equalop> <constant>' entries *)
    (* from d_joinarr                                         *)
    BEGIN
    _xi := 0;
    WHILE (_xi < dmli.d_joins.jrc_cnt) DO
        IF  (dmli.d_joins.jrc_joinarr[ _xi ].jo_op <> op_eq)
            AND
            (dmli.d_joins.jrc_joinarr[ _xi ].jo_recs[ 2 ].
            jop_tableno = cak68_join_value)
            OR
            (dmli.d_joins.jrc_joinarr[ _xi ].jo_recs[ 1 ].jop_tableno =
            dmli.d_joins.jrc_joinarr[ _xi ].jo_recs[ 2 ].jop_tableno)
        THEN
            (* delete this entry *)
            BEGIN
            dmli.d_joins.jrc_cnt := pred (dmli.d_joins.jrc_cnt);
            _xj     := _xi;
            WHILE (_xj < dmli.d_joins.jrc_cnt) DO
                BEGIN
                dmli.d_joins.jrc_joinarr[ _xj ] :=
                      dmli.d_joins.jrc_joinarr[ _xj + 1 ];
                _xj := succ (_xj);
                END;
            (*ENDWHILE*) 
            END
        ELSE
            _xi := succ (_xi);
        (*ENDIF*) 
    (*ENDWHILE*) 
    END;
(*ENDIF*) 
IF  _table_qual_found
THEN
    (* we don't need an outer join *)
    BEGIN
    acv.a_mblock.mb_trns^.trError_gg00 := e_ok;
    FOR _xi := 0 TO dmli.d_joins.jrc_cnt - 1 DO
        BEGIN
        _xj := 1;
        REPEAT
            (* work for left and right join part *)
            IF  (dmli.d_joins.jrc_joinarr[ _xi ].jo_recs[ _xj ].
                jop_tableno = jinfos.ji_acttabno)
            THEN
                BEGIN
                dmli.d_oj_tables := dmli.d_oj_tables -
                      [ dmli.d_joins.jrc_joinarr[ _xi ].
                      jo_recs[ _xj ].jop_tableno ];
                dmli.d_joins.jrc_joinarr[ _xi ].jo_recs[ _xj ].
                      jop_outer_join := false;
                _xj := 3;  (* exit repeat *)
                END;
            (*ENDIF*) 
            _xj := succ (_xj);
        UNTIL
            (_xj > 2);
        (*ENDREPEAT*) 
        END;
    (*ENDFOR*) 
    acv.a_outer_join := false;
    (* search for other outer joins *)
    FOR _xi := 1 TO dmli.d_cntfromtab DO
        IF  (_xi <> jinfos.ji_acttabno)
        THEN
            IF  a681outer_join_tab_is_curr_tab (dmli, _xi)
            THEN
                acv.a_outer_join := true;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDFOR*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      a681_outer_join_error_found (
            VAR acv     : tak_all_command_glob;
            VAR dmli    : tak_dml_info) : boolean;
 
VAR
      _i            : integer;
      _j            : integer;
      _k            : integer;
      _oj_table_cnt : integer;
      _used_tab_cnt : integer;
      _used_tables  : tak_joinset;
      _error_found  : boolean;
 
BEGIN
dmli.d_oj_tables   := [ ];
_oj_table_cnt := 0;
_used_tables  := [ ];
_used_tab_cnt := 0;
_i            := 0;
WHILE (_i < dmli.d_joins.jrc_cnt) DO
    BEGIN
    _j := 1;
    _k := 2;
    REPEAT
        (* work for part 1 and 2 *)
        IF  dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].jop_outer_join
        THEN
            BEGIN
            (* adjustment of jop_tableno because *)
            (* of different start indexes        *)
            IF  (NOT (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].
                jop_tableno in dmli.d_oj_tables))
            THEN
                BEGIN
                _oj_table_cnt := succ (_oj_table_cnt);
                dmli.d_oj_tables  := dmli.d_oj_tables +
                      [ dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].jop_tableno ];
                END;
            (*ENDIF*) 
            IF  (NOT (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].
                jop_tableno in _used_tables))
                AND
                (* real join: column != <const> *)
                (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].
                jop_tableno <> cak68_join_value)
            THEN
                BEGIN
                _used_tab_cnt := succ (_used_tab_cnt);
                _used_tables  := _used_tables +
                      [ dmli.d_joins.jrc_joinarr[ _i ].
                      jo_recs[ _k ].jop_tableno  ];
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        _j := succ (_j);
        _k := pred (_k);
    UNTIL
        (_j > 2);
    (*ENDREPEAT*) 
    _i := succ (_i);
    END;
(*ENDWHILE*) 
(* h.b. PTS 1000984 *)
(* get given sequence for any outer join *)
IF  (_oj_table_cnt  >= 1)
THEN
    BEGIN
    (* join sequence must be preserved *)
    (* because of wrong join processing with several outer joins *)
    (* precondition: join sequence is well defined *)
    (* example in OUTERJ3.punix, line 545 ff *)
    dmli.d_standard := true;
&   ifdef TRACE
    t01int4  (ak_join, 'sapr3 from<>', 681);
&   endif
    END;
(* h.b. PTS 1104163 *)
(*ENDIF*) 
_error_found := (dmli.d_cntfromtab < 2);
_i := 0;
IF  (NOT _error_found)
THEN
    WHILE (_i < dmli.d_joins.jrc_cnt) DO
        BEGIN
        _j := 1;
        _k := 2;
        REPEAT
            IF  ((dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].
                jop_tableno) in _used_tables)
                AND
                ((dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].jop_tableno
                in dmli.d_oj_tables) OR
                (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].jop_tableno = cak68_join_value))
            THEN
                dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].jop_propset := [ ];
            (*ENDIF*) 
            _j := succ (_j);
            _k := pred (_k);
        UNTIL
            (_j > 2);
        (*ENDREPEAT*) 
        _i := succ (_i);
        END;
    (*ENDWHILE*) 
&ifdef TRACE
(*ENDIF*) 
FOR _i := 1 TO dmli.d_cntfromtab DO
    IF  _i in dmli.d_oj_tables
    THEN
        t01int4 (ak_join, '   oj_table ', _i + 1);
    (*ENDIF*) 
(*ENDFOR*) 
FOR _i := 1 TO dmli.d_cntfromtab DO
    IF  _i in _used_tables
    THEN
        t01int4 (ak_join, 'used_table  ', _i );
    (*ENDIF*) 
(*ENDFOR*) 
t01int4 (ak_join, 'oj_table_cnt', _oj_table_cnt);
t01int4 (ak_join, 'used_tab_cnt', _used_tab_cnt);
t01int4 (ak_join, 'd_cntfromtab', dmli.d_cntfromtab);
t01int4 (ak_join, 'd_maxcountta', dmli.d_maxcounttabs);
&endif
IF  _error_found
THEN
    a07_b_put_error (acv, e_outer_join_def_error, 1);
(*ENDIF*) 
a681_outer_join_error_found := _error_found;
END;
 
(*------------------------------*) 
 
FUNCTION
      a681outer_join_tab_is_curr_tab (
            VAR dmli : tak_dml_info;
            curr_tab : integer) : boolean;
 
VAR
      _i            : integer;
      _j            : integer;
      _is_outer_tab : boolean;
 
BEGIN
_is_outer_tab := false;
_i            := 0;
WHILE (_i < dmli.d_joins.jrc_cnt) AND (NOT _is_outer_tab) DO
    BEGIN
    _j := 1;
    REPEAT
        (* work twice, left and right join part *)
        IF  (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].jop_tableno =
            curr_tab) AND
            dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _j ].jop_outer_join
        THEN
            BEGIN
            _is_outer_tab := true;
            _j            := 3;  (* exit repeat *)
            END;
        (*ENDIF*) 
        _j := succ (_j);
    UNTIL
        (_j > 2);
    (*ENDREPEAT*) 
    _i := succ (_i);
    END;
(*ENDWHILE*) 
a681outer_join_tab_is_curr_tab := _is_outer_tab;
END;
 
(*------------------------------*) 
 
PROCEDURE
      a681check_outer_join (
            VAR acv : tak_all_command_glob;
            VAR dmli : tak_dml_info);
 
VAR
      _i : integer;
      _j : integer;
      _k : integer;
 
BEGIN
IF  NOT a681_outer_join_error_found (acv, dmli)
THEN
    BEGIN
    dmli.d_oj_tables := [  ];
    FOR _i := 0 TO (dmli.d_joins.jrc_cnt - 1) DO
        FOR _k := 1 TO 2 DO
            IF  dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].jop_outer_join
            THEN
                BEGIN
                IF  dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].jop_tableno = 1
                THEN
                    _j := 2
                ELSE
                    _j := 1;
                (*ENDIF*) 
                dmli.d_oj_tables := dmli.d_oj_tables +
                      [ dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].jop_tableno ];
                _j := dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].jop_startstack;
                WHILE (_j <
                      (dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].
                      jop_startstack + dmli.d_joins.jrc_joinarr[ _i ].
                      jo_recs[ _k ].jop_cntstack)) DO
                    BEGIN
                    IF  (acv.a_mblock.mb_st^[ _j ].etype in [ st_varkey,
                        st_varcol, st_fixkey, st_fixcol, st_varlongchar ])
                    THEN
                        BEGIN
                        acv.a_mblock.mb_st^[ _j ].eop := op_outer_join;
                        _j := _j + dmli.d_joins.jrc_joinarr[ _i ].jo_recs[ _k ].jop_cntstack;
                        END;
                    (*ENDIF*) 
                    _j := succ (_j);
                    END;
                (*ENDWHILE*) 
                END;
&           ifdef TRACE
            (*ENDIF*) 
        (*ENDFOR*) 
    (*ENDFOR*) 
    FOR _i := 1 TO dmli.d_cntfromtab DO
        IF  _i in dmli.d_oj_tables
        THEN
            t01int4 (ak_join, '   oj_table ', _i + 1);
        (*ENDIF*) 
    (*ENDFOR*) 
    t01qual (ak_join, acv.a_mblock.mb_qual^);
&   endif
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681first_keyfield_no (
            VAR acv         : tak_all_command_glob;
            VAR dmli        : tak_dml_info;
            VAR col_buf     : tak00_colinfo_ptr;
            curr_tab        : tsp00_Uint1;
            VAR nxt_fieldno : tsp_int2;
            VAR f_ok        : boolean);
&     ifdef trace
 
VAR
      _colname : tsp_knl_identifier;
&     endif
 
BEGIN
f_ok := false;
a61_rel_old_table (acv, dmli, curr_tab);
IF  acv.a_return_segm^.sp1r_returncode = 0
THEN
    BEGIN
    f_ok    := true;
    col_buf := dmli.d_sparr.pbasep^.sbase.
          bcolumn[ dmli.d_sparr.pbasep^.sbase.bfirstcolind ];
    nxt_fieldno := col_buf^.cextcolno;
&   ifdef TRACE
    a061get_colname (col_buf^, _colname);
    t01lidentifier (ak_join, _colname);
&   endif
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681next_keyfield_no (
            VAR dmli        : tak_dml_info;
            VAR col_buf     : tak00_colinfo_ptr;
            VAR nxt_fieldno : tsp_int2);
&     ifdef trace
 
VAR
      _colname : tsp_knl_identifier;
&     endif
 
BEGIN
col_buf     := dmli.d_sparr.pbasep^.sbase.bcolumn[col_buf^.cnextind];
nxt_fieldno := col_buf^.cextcolno;
&ifdef TRACE
a061get_colname (col_buf^, _colname);
t01lidentifier (ak_join, _colname);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      a681lowest_multiple_strat (
            VAR jtrans          : tak68_join_transitions;
            VAR succession      : tak68_succession;
            VAR mul_tabs        : tak68_mult_tabs;
            src_table           : tsp00_Int2;
            dst_table           : tsp00_Int2;
            VAR best_srctab     : tsp00_Int2;
            VAR best_jtype      : tak68_one_jointype;
            VAR best_multiplier : tsp_int4;
            VAR best_fieldcnt   : tsp_int4; (* h.b. PTS 1106353 *)
            processed_table_cnt : tsp00_Int2;
            update_jtrans       : boolean);
 
VAR
      _l                    : tsp00_Int2;
      _sequenced_table_cnt  : tsp00_Int2;
 
BEGIN
(* if possible, return better transition than best_jtype/best_multiplier   *)
(* to dst_tab, if better trans is found, grab best_jtype, best_multiplier, *)
(* best_srctab = src_table *)
_sequenced_table_cnt := 0;
FOR _l := 1 TO processed_table_cnt DO
    IF  (succession[ _l ].s_tableno <> 0)
    THEN
        _sequenced_table_cnt := succ (_sequenced_table_cnt);
&   ifdef TRACE
    (*ENDIF*) 
(*ENDFOR*) 
t01p2int4(ak_join, 'src_table   ', src_table
      , 'dst_table   ', dst_table);
t01p2int4(ak_join, 'proc tab cnt', processed_table_cnt
      , 'seq tab cnt ', _sequenced_table_cnt);
a683tr_newsucc (ak_join, succession, 1, processed_table_cnt, true);
&endif
_l := 1;
WHILE (_l <= mul_tabs.mt_cnt) DO
    (* loop over mul_tabs.mt_arr *)
    BEGIN
    IF  (dst_table = mul_tabs.mt_arr[ _l ].mtr_dst_table)
        AND
        (_sequenced_table_cnt >= mul_tabs.mt_arr[ _l ].mtr_tablecnt)
        AND
        ak681all_multabs_in_succ (mul_tabs.mt_arr[ _l ],
        succession, processed_table_cnt)
    THEN
        BEGIN
&       ifdef TRACE
        a683trace_jointype(ak_join, 'jtype in mul', mul_tabs.mt_arr [ _l ].mtr_jointype);
&       endif
        IF  (mul_tabs.mt_arr[ _l ].mtr_jointype = to_key)
        THEN
            (* key transition is best join transition *)
            BEGIN
            best_srctab     := src_table;
            best_jtype      := mul_tabs.mt_arr[ _l ].mtr_jointype;
            best_multiplier := mul_tabs.mt_arr [ _l ].mtr_multipl;
            (* h.b. PTS 1106353 *)
            best_fieldcnt   := mul_tabs.mt_arr [ _l ].mtr_fieldcnt;
            mul_tabs.mt_pos := _l;
            IF  update_jtrans
            THEN
                BEGIN
                jtrans[ src_table, dst_table ].jt_indexno  := 0;
                jtrans[ src_table, dst_table ].jt_joinno   :=
                      mul_tabs.mt_arr[ _l ].mtr_joinno;
                jtrans[ src_table, dst_table ].jt_multipl  :=
                      mul_tabs.mt_arr[ _l ].mtr_multipl;
                END;
            (*ENDIF*) 
            _l := mul_tabs.mt_cnt; (* exit while *)
            END
        ELSE
            (* mtr_jointype <> to_key *)
            IF  ak681_is_lower_strat(best_jtype, best_multiplier,
                best_fieldcnt, (* h.b. PTS 1106353 *)
                mul_tabs.mt_arr [ _l ].mtr_jointype,
                mul_tabs.mt_arr [ _l ].mtr_multipl,
                mul_tabs.mt_arr [ _l ].mtr_fieldcnt)
            THEN
                (* transition in mul_tabs is better than input *)
                BEGIN
                best_srctab     := src_table;
                best_multiplier := mul_tabs.mt_arr[ _l ].mtr_multipl;
                (* h.b. PTS 1106353 *)
                best_fieldcnt   := mul_tabs.mt_arr[ _l ].mtr_fieldcnt;
                IF  (mul_tabs.mt_arr[ _l ].mtr_jointype = to_unique_field)
                THEN
                    best_jtype := to_all_invfields
                ELSE
                    best_jtype := mul_tabs.mt_arr[ _l ].mtr_jointype;
                (*ENDIF*) 
                mul_tabs.mt_pos := _l;
                IF  update_jtrans
                THEN
                    BEGIN
                    jtrans[ src_table, dst_table ].jt_indexno  :=
                          mul_tabs.mt_arr[ _l ].mtr_indexno;
                    jtrans[ src_table, dst_table ].jt_joinno   :=
                          mul_tabs.mt_arr[ _l ].mtr_joinno;
                    jtrans[ src_table, dst_table ].jt_multipl  :=
                          mul_tabs.mt_arr[ _l ].mtr_multipl;
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    _l := succ (_l)
    END;
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      ak681_is_lower_strat (
            best_jtype        : tak68_one_jointype;
            best_multiplier   : tsp_int4;
            best_fieldcnt     : tsp_int4; (* h.b. PTS 1106353 *)
            new_jointype      : tak68_one_jointype;
            new_multiplier    : tsp_int4;
            new_fieldcnt      : tsp_int4) : boolean;
 
CONST
      c_inv_factor = 1.3;
 
VAR
      _best        : tsp_longreal;
      _new         : tsp_longreal;
 
BEGIN (* h.b. PTS 1106353 *)
_best := best_multiplier;
IF  best_jtype in [to_unique_field, to_all_invfields,
    to_invpart, to_invfield]
THEN
    _best := _best * c_inv_factor;
(*ENDIF*) 
_new := new_multiplier;
IF  new_jointype in [to_unique_field, to_all_invfields,
    to_invpart, to_invfield]
THEN
    _new := _new * c_inv_factor;
&ifdef trace
(*ENDIF*) 
t01real (ak_join, 'old mult    ', _best, 6);
t01real (ak_join, 'new_mult    ', _new, 6);
t01bool (ak_join, 'ist lower   ', (best_jtype > to_mt_join) OR
      (_new < _best) OR ((_new = _best) AND (new_fieldcnt > best_fieldcnt)));
&endif
ak681_is_lower_strat := (best_jtype > to_mt_join) OR (_new < _best) OR
      ((_new = _best) AND (new_fieldcnt > best_fieldcnt));
END;
 
(*------------------------------*) 
 
PROCEDURE
      a681jnew_seq (
            VAR acv            : tak_all_command_glob;
            VAR dmli           : tak_dml_info;
            VAR table_stats    : tak68_table_stats;
            VAR jtrans         : tak68_join_transitions;
            VAR sequence_info  : tak68_sequence_info;
            VAR jinfos         : tak68_joininfos;
            VAR res_info       : tak68_result_info;
            VAR mul_tabs       : tak68_mult_tabs;
            VAR lastsuccession : tak68_lastsuccession);
 
VAR
      _i               : tsp00_Int2;
      _start_table     : tsp00_Int2;
      _start_table_idx : tsp00_Int2;
      _reschedule_cnt  : tsp00_Int2;
      _context         : tak681_jseq_info_record;
      _ln              : tsp_line;
      _searchkind      : tsp_c42;
      _ready           : boolean;
 
BEGIN
s10fil (sizeof (_ln), _ln, 1, sizeof (_ln), bsp_c1);
_context.jir_beststratcnt      := 0;
_context.jir_comp_sequences    := 0;
_context.jir_lowest_cost       := cak68_max_real;
_context.jir_better_seq_exists := false;
(* *** find best strategy to each table *** *)
ak681best_join_strat (acv, dmli, table_stats, jtrans, sequence_info, res_info,
      mul_tabs, _context.jir_best_jstrat);
IF  NOT dmli.d_standard
THEN
    (* search best join transition *)
    BEGIN
    _context.jir_max_tables := dmli.d_cntfromtab;
    IF  (dmli.d_joins.jrc_cnt = 0) AND
        (g01join_search_level = jsLevel0_egg00)
    THEN
        BEGIN
&       ifdef TRACE
        t01sname (ak_join, '>> JSS CART ');
&       endif
        IF  acv.a_intern_explain OR g01vtrace.vtrStrategy_gg00
        THEN
            BEGIN
            _searchkind := 'JOIN SEQUENCE SEARCH = AUTOMATIC - CARTES ';
            s10mv3 (sizeof(_searchkind), sizeof(_ln),
                  _searchkind, 1, _ln, 1, sizeof(_searchkind));
            a40sequence_expl_row (acv, _ln, c_change_to_unicode);
            END;
        (* take sorted sequence, if join conditions *)
        (* wasn't found in WHERE clause             *)
        (*ENDIF*) 
        ak681sort_by_costs (dmli, sequence_info, _context.jir_best_jstrat,
              table_stats);
        END
    ELSE
        IF  ( g01join_search_level = jsLevel9_egg00 ) OR
            ( (g01join_search_level = jsLevel0_egg00)
            AND (dmli.d_cntfromtab <= g01join_maxtab_level9) )
        THEN
            BEGIN
&           ifdef TRACE
            t01sname (ak_join, '>> JSS PERMU');
&           endif
            IF  acv.a_intern_explain OR g01vtrace.vtrStrategy_gg00
            THEN
                BEGIN
                IF  g01join_search_level = jsLevel9_egg00
                THEN
                    BEGIN
                    _searchkind :=
                          'JOIN SEQUENCE SEARCH = LEVEL 9            ';
                    s10mv3 (sizeof(_searchkind), sizeof(_ln),
                          _searchkind, 1, _ln, 1, 30);
                    a40sequence_expl_row (acv, _ln, c_change_to_unicode);
                    END
                ELSE
                    BEGIN
                    _searchkind :=
                          'JOIN SEQUENCE SEARCH = AUTOMATIC - LEVEL 9';
                    s10mv3 (sizeof(_searchkind), sizeof(_ln),
                          _searchkind, 1, _ln, 1, sizeof(_searchkind));
                    a40sequence_expl_row (acv, _ln, c_change_to_unicode);
                    END
                (*ENDIF*) 
                END;
            (* build optimized permutation *)
            (*ENDIF*) 
            _context.jir_i := 1;
            _context.jir_sequenced_tables := [];
            _reschedule_cnt := 0;
            ak681permut_sequence(acv, dmli, table_stats, jtrans, sequence_info,
                  jinfos, res_info, mul_tabs, lastsuccession, _context, _reschedule_cnt);
            END
        ELSE
            IF  ( g01join_search_level = jsLevel4_egg00 ) OR
                ( (g01join_search_level = jsLevel0_egg00)
                AND (dmli.d_cntfromtab <= g01join_maxtab_level4) )
            THEN
                BEGIN
&               ifdef TRACE
                t01sname (ak_join, '>> JSS HEUR ');
&               endif
                IF  acv.a_intern_explain OR g01vtrace.vtrStrategy_gg00
                THEN
                    BEGIN
                    IF  g01join_search_level = jsLevel4_egg00
                    THEN
                        BEGIN
                        _searchkind :=
                              'JOIN SEQUENCE SEARCH = LEVEL 4            ';
                        s10mv3 (sizeof(_searchkind), sizeof(_ln),
                              _searchkind, 1, _ln, 1, 30);
                        a40sequence_expl_row (acv, _ln, c_change_to_unicode);
                        END
                    ELSE
                        BEGIN
                        _searchkind :=
                              'JOIN SEQUENCE SEARCH = AUTOMATIC - LEVEL 4';
                        s10mv3 (sizeof(_searchkind), sizeof(_ln),
                              _searchkind, 1, _ln, 1, sizeof(_searchkind));
                        a40sequence_expl_row (acv, _ln, c_change_to_unicode);
                        END
                    (*ENDIF*) 
                    END;
                (* save start sequence *)
                (* PTS 1112102 *)
                (*ENDIF*) 
                _context.jir_start_succession := sequence_info.si_sequence;
                _start_table_idx := 1;
                _ready := false;
                WHILE (NOT _ready) AND
                      (acv.a_return_segm^.sp1r_returncode = 0) DO
                    BEGIN
                    (* restore start sequence *)
                    sequence_info.si_sequence :=
                          _context.jir_start_succession;
                    (*  enqueue first table *)
                    _start_table := sequence_info.
                          si_sequence[ _start_table_idx ].s_tableno;
                    FOR _i := _start_table_idx DOWNTO 2 DO
                        sequence_info.si_sequence[ _i ].s_tableno :=
                              sequence_info.si_sequence[ _i - 1 ].s_tableno;
                    (*ENDFOR*) 
                    sequence_info.si_sequence[ 1 ].s_tableno := _start_table;
                    (* PTS 1112102 *)
                    ak681greedy (jtrans, mul_tabs, table_stats,
                          sequence_info, _context.jir_max_tables,
                          NOT c_find_start_table);
&                   ifdef TRACE
                    t01int4 (ak_join, '1. TABLE ==>',
                          sequence_info.si_sequence[ 1 ].s_tableno);
                    a683tr_newsucc (ak_join, sequence_info.si_sequence,
                          1, dmli.d_cntfromtab, true);
&                   endif
                    (* put start table in used table set *)
                    _context.jir_sequenced_tables    :=
                          [ sequence_info.si_sequence[ 1 ].s_tableno ];
                    _context.jir_stop_sequence := false;
                    (* contains jir_i if no transition from sequence found *)
                    _context.jir_last_swap_pos := 0;
                    _context.jir_i  := 2;
                    (* there are (jir_max_tables - 1) - (jir_i - 1) join strategies *)
                    (* between predecessor table and successor table, jir_i is      *)
                    (* position of one table in sequecen                            *)
                    (* ((jir_max_tables - 1) - jir_i) join strategies are eligible  *)
                    (* for election                                                 *)
                    (* we have to decide for join strategy to table jir_i, hence    *)
                    (* there are ((jir_max_tables - 1) - jir_i + 1 =                *)
                    (* jir_max_tables - jir_i decisions for join transition         *)
                    _context.jir_beststratcnt :=
                          _context.jir_max_tables - _context.jir_i;
                    ak681one_sequence (acv, dmli, table_stats, jtrans,
                          sequence_info, jinfos, res_info, mul_tabs,
                          lastsuccession, _context);
                    _ready := (_start_table_idx >= _context.jir_max_tables);
                    _start_table_idx := succ(_start_table_idx);
                    END;
                (*ENDWHILE*) 
                END
            ELSE
                BEGIN
&               ifdef TRACE
                t01sname (ak_join, '>> JSS GRDY ');
&               endif
                IF  acv.a_intern_explain OR g01vtrace.vtrStrategy_gg00
                THEN
                    BEGIN
                    IF  g01join_search_level = jsLevel1_egg00
                    THEN
                        BEGIN
                        _searchkind :=
                              'JOIN SEQUENCE SEARCH = LEVEL 1            ';
                        s10mv3 (sizeof(_searchkind), sizeof(_ln),
                              _searchkind, 1, _ln, 1, 30);
                        a40sequence_expl_row (acv, _ln, c_change_to_unicode);
                        END
                    ELSE
                        BEGIN
                        _searchkind :=
                              'JOIN SEQUENCE SEARCH = AUTOMATIC - LEVEL 1';
                        s10mv3 (sizeof(_searchkind), sizeof(_ln),
                              _searchkind, 1, _ln, 1, sizeof(_searchkind));
                        a40sequence_expl_row (acv, _ln, c_change_to_unicode);
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                ak681greedy (jtrans, mul_tabs, table_stats,
                      sequence_info, _context.jir_max_tables, c_find_start_table);
                END;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    IF  (_context.jir_lowest_cost < cak68_max_real) OR
        (_context.jir_comp_sequences = 1)
    THEN
        sequence_info.si_sequence := _context.jir_lowest_succession;
    (*ENDIF*) 
    END
ELSE
    IF  acv.a_intern_explain OR g01vtrace.vtrStrategy_gg00
    THEN
        BEGIN
        _searchkind := 'JOIN SEQUENCE SEARCH = PREDEFINED         ';
        s10mv3 (sizeof(_searchkind), sizeof(_ln),
              _searchkind, 1, _ln, 1, sizeof(_searchkind));
        a40sequence_expl_row (acv, _ln, c_change_to_unicode);
        END;
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681one_sequence (
            VAR acv            : tak_all_command_glob;
            VAR dmli           : tak_dml_info;
            VAR table_stats    : tak68_table_stats;
            VAR jtrans         : tak68_join_transitions;
            VAR sequence_info  : tak68_sequence_info;
            VAR jinfos         : tak68_joininfos;
            VAR res_info       : tak68_result_info;
            VAR mul_tabs       : tak68_mult_tabs;
            VAR lastsuccession : tak68_lastsuccession;
            VAR context        : tak681_jseq_info_record);
 
VAR
      _best_multipl        : tsp_int4;
      _best_fieldcnt       : tsp_int4;
      _aux_multiplier1     : tsp_int4;
      _actual_table        : tsp00_Int2;
      _i                   : tsp00_Int2;
      _seq_table           : tsp00_Int2;
      _nonseq_table        : tsp00_Int2;
      _l                   : tsp00_Int2;
      _n                   : tsp00_Int2;
      _best_srctab         : tsp00_Int2;
      _next_table          : tsp00_Int2;
      _best_jtype          : tak68_one_jointype;
      _join_other_table    : boolean;
      _aux_c               : tak681_jseq_info_record;
      _aux_l               : tak68_sequence_info;
      _mt_jtrans_check     : boolean;
 
BEGIN
&ifdef trace
t01name(ak_join, 'unprocessed sequen');
t01int4(ak_join, 'length      ', context.jir_max_tables - context.jir_i + 1);
&endif
context.jir_better_seq_exists := false;
_best_srctab := cak_is_undefined;
REPEAT
    (* UNTIL context.jir_stop_sequence *)
    BEGIN
&   ifdef trace
    t01sname(ak_join, 'repeat loop ');
&   endif
    FOR _i := 1 TO context.jir_max_tables DO
        sequence_info.si_sequence[ _i ].s_backup :=
              sequence_info.si_sequence[ _i ].s_tableno;
    (*ENDFOR*) 
    context.jir_swap_cnt       := 0;
    context.jir_non_best_trans := context.jir_i;
    (* si_sequence[1 .. jir_i - 1] forms found sequence !!!! *)
    WHILE (context.jir_i < context.jir_max_tables)
          AND
          (context.jir_i + context.jir_swap_cnt <= context.jir_max_tables)
          AND
          (acv.a_return_segm^.sp1r_returncode = 0) DO
        BEGIN
        (* check if join transition to _actual_table *)
        (* is possible from sequence                 *)
        _actual_table := sequence_info.si_sequence[ context.jir_i ].s_tableno;
        context.jir_better_seq_exists := false;
&       ifdef trace
        t01p2int4(ak_join, 'while loop i', context.jir_i,
              'actual table', _actual_table );
&       endif
        IF  context.jir_best_jstrat[ _actual_table ].
            bjr_jtype < to_cartesian_prod
        THEN
            BEGIN
&           ifdef TRACE
            ak681tr_context( sequence_info, context );
&           endif
            (* there is a join transition to considered table *)
            _join_other_table := false;
            _aux_c            := context;
            _aux_l            := sequence_info;
            (* check transitions from already sequenced tables  *)
            (* to considered table                              *)
            IF  context.jir_best_jstrat[ _actual_table ].bjr_is_mt_join
            THEN
                ak681mtj_check (dmli, jtrans, sequence_info, context, table_stats,
                      res_info, mul_tabs, _join_other_table)
            ELSE
                ak681j_check (dmli, jtrans, sequence_info,
                      context, _join_other_table);
            (*ENDIF*) 
&           ifdef trace
            t01sname( ak_join, 'sequence1   ');
            a683tr_newsucc (ak_join, sequence_info.si_sequence, 1, context.jir_i, true);
&           endif
            IF  _join_other_table
            THEN
                BEGIN
                _best_jtype     := to_cartesian_prod;
                _best_multipl   := csp_maxint4;
                _best_srctab    := cak_is_undefined;
                _best_fieldcnt  := 1;
                _n              := _aux_c.jir_i;
                _next_table     :=
                      _aux_l.si_sequence[ _aux_c.jir_i ].s_tableno;
                FOR _l := _aux_c.jir_i + 1 TO _aux_c.jir_max_tables DO
                    BEGIN
                    _mt_jtrans_check := true;
                    _nonseq_table :=
                          _aux_l.si_sequence[ _l ].s_tableno;
                    FOR _i := 1 TO _aux_c.jir_i - 1 DO
                        BEGIN
                        _seq_table :=
                              _aux_l.si_sequence[ _i ].s_tableno;
                        (* look for best join transitions to remaining tables *)
                        IF  jtrans[ _seq_table, _nonseq_table ].
                            jt_jointype = to_mt_join
                        THEN
                            BEGIN
                            IF  _mt_jtrans_check
                            THEN
                                BEGIN
                                _mt_jtrans_check := false;
                                _aux_multiplier1 := _best_multipl;
                                a681lowest_multiple_strat (jtrans,
                                      sequence_info.si_sequence, mul_tabs,
                                      _seq_table, _nonseq_table,
                                      _best_srctab, _best_jtype,
                                      (* h.b. PTS 1106353 *)
                                      _best_multipl, _best_fieldcnt,
                                      _aux_c.jir_i, NOT c_update_jtrans);
                                IF  _aux_multiplier1 > _best_multipl
                                THEN
                                    BEGIN
                                    (* all other data was set in *)
                                    (* a681lowest_multiple_strat *)
                                    _next_table := _nonseq_table;
                                    _n          := _l;
                                    END;
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                            END
                        ELSE
                            (* single table transition *)
                            IF  (_best_jtype >
                                jtrans[ _seq_table, _nonseq_table ].jt_jointype)
                                OR
                                ((_best_jtype =
                                jtrans[ _seq_table, _nonseq_table ].
                                jt_jointype)
                                AND
                                (_best_multipl >
                                jtrans[ _seq_table, _nonseq_table ].
                                jt_multipl))
                            THEN
                                BEGIN
                                _best_jtype       :=
                                      jtrans[ _seq_table, _nonseq_table ].
                                      jt_jointype;
                                _best_multipl :=
                                      jtrans[ _seq_table, _nonseq_table ].
                                      jt_multipl;
                                _best_fieldcnt := 1;
                                _best_srctab   := _seq_table;
                                _next_table    := _nonseq_table;
                                _n             := _l;
                                END;
                            (* all multiple table transition from sequence *)
                            (* to non-sequenced tables checked             *)
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END;
                    (*ENDFOR*) 
                    END;
                (*ENDFOR*) 
                IF  (_next_table <>
                    _aux_l.si_sequence[ _aux_c.jir_i ].s_tableno)
                    AND
                    (_best_srctab <> cak_is_undefined)
                THEN
                    BEGIN
&                   ifdef trace
                    t01p2int4(ak_join, 'recursive ca', context.jir_i ,
                          'get table   ',  _next_table);
&                   endif
                    (* there is a join transition to one remaining table *)
                    (* move this table on sequence end *)
                    FOR _l := _n DOWNTO _aux_c.jir_i + 1 DO
                        _aux_l.si_sequence[ _l ].s_tableno :=
                              _aux_l.si_sequence[ _l - 1 ].s_tableno;
                    (*ENDFOR*) 
                    _aux_l.si_sequence[ _aux_c.jir_i ].s_tableno :=
                          _next_table;
                    _aux_c.jir_sequenced_tables   :=
                          _aux_c.jir_sequenced_tables + [ _next_table ];
                    _aux_c.jir_beststratcnt   := pred (_aux_c.jir_beststratcnt);
                    _aux_c.jir_stop_sequence  := false;
                    _aux_c.jir_i              := succ (_aux_c.jir_i);
                    _aux_c.jir_non_best_trans := _aux_c.jir_i;
                    IF  g01userstackoverflow
                    THEN
                        (* stack usage too high to call kb layer *)
                        a07_b_put_error (acv, e_program_stack_overflow, 9)
                    ELSE
                        ak681one_sequence (acv, dmli, table_stats, jtrans,
                              _aux_l, jinfos, res_info, mul_tabs,
                              lastsuccession, _aux_c);
                    (*ENDIF*) 
&                   ifdef TRACE
                    t01int4 (ak_join, 'come up recu', context.jir_i);
                    t01int4 (ak_join, 'stop sequenc',
                          ord (context.jir_stop_sequence));
                    t01int4 (ak_join, 'beststratcnt', context.jir_beststratcnt);
                    a683tr_newsucc (ak_join, sequence_info.si_sequence, 1,
                          context.jir_i, true);
                    a683tr_newsucc (ak_join, sequence_info.si_sequence, context.jir_i + 1,
                          context.jir_max_tables, true);
                    t01int4 (ak_join, '$$$$$$$$$$$>', _aux_c.jir_i);
                    t01int4 (ak_join, 'beststratcnt', _aux_c.jir_beststratcnt);
                    a683tr_newsucc (ak_join, _aux_l.si_sequence,
                          1, context.jir_max_tables, true);
&                   endif
                    context.jir_stop_sequence :=
                          context.jir_stop_sequence
                          OR
                          ((NOT context.jir_better_seq_exists)
                          (**) AND
                          (context.jir_comp_sequences <
                          _aux_c.jir_comp_sequences));
                    context.jir_lowest_cost := _aux_c.jir_lowest_cost;
                    context.jir_lowest_succession :=
                          _aux_c.jir_lowest_succession;
                    context.jir_comp_sequences := _aux_c.jir_comp_sequences;
                    _n := 0;
                    FOR _l := 1 TO context.jir_i DO
                        IF  (_aux_l.si_sequence[ _l ].s_tableno =
                            sequence_info.si_sequence[ _l ].s_tableno)
                        THEN
                            _n := succ (_n);
                        (*ENDIF*) 
                    (*ENDFOR*) 
                    IF  (_n = context.jir_i)
                    THEN
                        BEGIN
                        (* no new start sequence computed *)
                        (* *** exit while without costcheck *** *)
                        context.jir_swap_cnt     :=
                              context.jir_max_tables - context.jir_i + 1;
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            (* there isn't a join transition to considered table *)
            context.jir_beststratcnt   := pred (context.jir_beststratcnt);
            (* cartesian product tables could be sequenced any time *)
            context.jir_sequenced_tables := context.jir_sequenced_tables +
                  [ _actual_table ];
            END;
        (*ENDIF*) 
        context.jir_i := succ (context.jir_i);
        END;
    (*ENDWHILE*) 
&   ifdef TRACE
    ak681tr_context( sequence_info, context );
&   endif
    context.jir_stop_sequence :=
          context.jir_stop_sequence
          OR
          (context.jir_i + 1 >= context.jir_max_tables)
          AND
          (
          (context.jir_beststratcnt <= 0)
          (**) OR
          (* initial value *)
          (context.jir_beststratcnt = context.jir_max_tables - 2)
          (**) OR
          (* mt join trans:                                              *)
          (* jir_i wasn't best transition and jir_i + 1 < jir_max_tables *)
          (* single join trans :                                         *)
          (* jir_i wasn't best transition                                *)
          (context.jir_better_seq_exists)
          )
          OR
          (* not a transition from first table to second table *)
          (* therefore try other start table                 *)
          (context.jir_i = 2);
&   ifdef TRACE
    t01bool (ak_join, 'stop sequenc', context.jir_stop_sequence);
    t01bool (ak_join, 'better_seq_e', context.jir_better_seq_exists);
&   endif
    IF  (NOT context.jir_stop_sequence) AND
        (acv.a_return_segm^.sp1r_returncode = 0)
    THEN
        BEGIN
        _aux_l := sequence_info;
        ak681get_other_transition (jtrans, sequence_info, context, mul_tabs,
              table_stats, res_info);
        _n := 0;
        FOR _l := 1 TO context.jir_i DO
            IF  (_aux_l.si_sequence[ _l ].s_tableno =
                sequence_info.si_sequence[ _l ].s_tableno)
            THEN
                _n := succ (_n);
            (*ENDIF*) 
        (*ENDFOR*) 
        context.jir_stop_sequence :=
              context.jir_stop_sequence OR ( _n = context.jir_i );
        END;
    (*ENDIF*) 
    END;
UNTIL
    context.jir_stop_sequence OR (acv.a_return_segm^.sp1r_returncode <> 0);
(*ENDREPEAT*) 
&ifdef trace
t01sname( ak_join, 'full seq2   ');
a683tr_newsucc (ak_join, sequence_info.si_sequence, 1, dmli.d_cntfromtab, true);
&endif
IF  (context.jir_beststratcnt <= 0) AND
    (acv.a_return_segm^.sp1r_returncode = 0)
THEN
    ak681sequence_eval(acv, dmli, table_stats, jtrans, sequence_info, jinfos,
          res_info, mul_tabs, lastsuccession, context);
&ifdef trace
(*ENDIF*) 
ak681tr_context( sequence_info, context );
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681get_other_transition (
            VAR jtrans         : tak68_join_transitions;
            VAR sequence_info  : tak68_sequence_info;
            VAR context        : tak681_jseq_info_record;
            VAR mul_tabs       : tak68_mult_tabs;
            VAR table_stats    : tak68_table_stats;
            VAR res_info       : tak68_result_info);
 
VAR
      _xsum                : tsp_longreal;
      _aux_costs           : tsp_longreal;
      _best_multiplier     : tsp_int4;
      _best_fieldcnt       : tsp_int4;
      _next_table          : tsp00_Int2;
      _j                   : tsp00_Int2;
      _k                   : tsp00_Int2;
      _actual_table        : tsp00_Int2;
      _nonseq_table        : tsp00_Int2;
      _seq_table           : tsp00_Int2;
      _n                   : tsp00_Int2;
      _best_srctab         : tsp00_Int2;
      _best_jointype       : tak68_one_jointype;
      _mt_jtrans_check     : boolean;
 
BEGIN
context.jir_beststratcnt := context.jir_max_tables - context.jir_i;
(* *** restore sequenced table set from si_sequence *** *)
context.jir_sequenced_tables := [ ];
FOR _j := 1 TO context.jir_i - 1 DO
    context.jir_sequenced_tables := context.jir_sequenced_tables +
          [ sequence_info.si_sequence[ _j ].s_tableno ];
(*ENDFOR*) 
_k := 1;
(* from jir_i on save non sequenced tables from start succession *)
FOR _j := context.jir_i TO context.jir_max_tables DO
    BEGIN
    IF  _k < context.jir_max_tables
    THEN
        WHILE (context.jir_start_succession[ _k ].s_tableno
              in context.jir_sequenced_tables) DO
            _k := succ (_k);
        (*ENDWHILE*) 
    (*ENDIF*) 
    sequence_info.si_sequence[ _j ].s_tableno :=
          context.jir_start_succession[ _k ].s_tableno;
    sequence_info.si_sequence[ _j ].s_backup :=
          context.jir_start_succession[ _k ].s_tableno;
    _k := succ (_k);
    END;
(*ENDFOR*) 
_actual_table := sequence_info.si_sequence[ context.jir_i ].s_tableno;
&ifdef TRACE
t01int4 (ak_join, 'other_wayi->', context.jir_i);
t01int4 (ak_join, 'beststratcnt', context.jir_beststratcnt);
a683tr_newsucc (ak_join, sequence_info.si_sequence, 1, context.jir_i, true);
a683tr_newsucc (ak_join, sequence_info.si_sequence, context.jir_i + 1,
      context.jir_max_tables,true);
a683tr_tableset(ak_join, 'seq_table_se', context.jir_sequenced_tables);
&endif
context.jir_stop_sequence := true;
_xsum       := cak68_max_real;
_next_table := 0;
_n := 0;
_mt_jtrans_check := true;
FOR _j := 1 TO context.jir_i - 1 DO
    BEGIN
    (* check for transitions from sequence *)
    _seq_table := sequence_info.si_sequence[ _j ].s_tableno;
    _k := succ (context.jir_i);
    WHILE (_k <= context.jir_max_tables) DO
        BEGIN
        _nonseq_table := sequence_info.si_sequence[ _k ].s_tableno;
        IF  context.jir_best_jstrat[ _nonseq_table ].bjr_is_mt_join
        THEN
            (* multiple table join transition to non-sequenced table *)
            BEGIN
            IF  _mt_jtrans_check
            THEN
                BEGIN
                (* all multiple table transition from sequence *)
                (* to non-sequenced tables checked             *)
                _mt_jtrans_check := false;
                _best_multiplier := csp_maxint4;
                _best_srctab     := 1;
                _best_jointype   := to_cartesian_prod;
                _best_fieldcnt   := 1;
                a681lowest_multiple_strat (jtrans,
                      sequence_info.si_sequence, mul_tabs, _seq_table,
                      _nonseq_table(*dst table*),
                      _best_srctab, _best_jointype,
                      _best_multiplier, _best_fieldcnt, (* h.b. PTS 1106353 *)
                      context.jir_i - 1,
                      NOT c_update_jtrans);
                _aux_costs := ak681jtable_cost (table_stats,
                      _nonseq_table,
                      _best_jointype, _best_multiplier, res_info);
                IF   (_aux_costs < _xsum)
                THEN
                    BEGIN
                    context.jir_stop_sequence := false;
                    _xsum       := _aux_costs;
                    _next_table := _nonseq_table;
                    _n          := _k;
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END
        ELSE
            (* join transition with single table to non-sequenced table *)
            IF  (context.jir_best_jstrat[ _nonseq_table ].
                bjr_jtype <= to_eq_field)
                AND
                (* best transition comes from sequence *)
                (jtrans[ _seq_table, _nonseq_table ].
                jt_jointype = context.jir_best_jstrat[ _nonseq_table ].
                bjr_jtype)
                AND
                (context.jir_best_jstrat[ _nonseq_table ].
                bjr_costs < _xsum)
            THEN
                BEGIN
                _xsum := context.jir_best_jstrat[ _nonseq_table ].
                      bjr_costs;
                _next_table := _nonseq_table;
                context.jir_stop_sequence := false;
                _n          := _k;
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        _k := succ (_k);
        END;
    (*ENDWHILE*) 
    END;
(*ENDFOR*) 
IF  (_next_table = 0)
THEN
    (* no transition from sequence to non-sequenced tables *)
    (* check for transitions from actual considered table  *)
    (* to non_sequenced table                              *)
    IF  context.jir_best_jstrat[ _actual_table ].bjr_is_mt_join
    THEN
        (* best join transition to considered table is multiple table transition *)
        BEGIN
        _k := succ (context.jir_i);
        WHILE (_k <= context.jir_max_tables) DO
            BEGIN
            _nonseq_table := sequence_info.si_sequence[ _k ].s_tableno;
            IF  (_nonseq_table
                in mul_tabs.mt_arr [ context.jir_best_jstrat[ _actual_table ].
                bjr_mtab_ind ].mtr_tab_seq)
            THEN
                BEGIN
                (* table from non-sequence has transition *)
                (* to actual considered table             *)
                _next_table := _nonseq_table;
                context.jir_stop_sequence := false;
                _n  := _k;
                (* exit while *)
                _k  := context.jir_max_tables;
                END;
            (*ENDIF*) 
            _k := succ (_k);
            END;
        (*ENDWHILE*) 
        END
    ELSE
        (* best join transition to considered table is single table transition *)
        (* table transition from sequence or non-sequence *)
        BEGIN
        IF  (context.jir_i >= context.jir_non_best_trans)
        THEN
            BEGIN
            (* sequence actual table *)
            context.jir_beststratcnt     := pred (context.jir_beststratcnt);
            context.jir_sequenced_tables := context.jir_sequenced_tables +
                  [ _actual_table ];
&           ifdef TRACE
            t01sname( ak_join, 'set nonbest5' );
&           endif
            context.jir_non_best_trans    := context.jir_i;
            context.jir_i                 := succ (context.jir_i);
            context.jir_stop_sequence     := false;
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
(*ENDIF*) 
IF  (_next_table > 0)
THEN
    (* best single table transition from sequence *)
    (* OR *)
    (* good mult. table transition from sequence  *)
    (* OR *)
    (* mult. transition to actual considered table *)
    (* from non-sequenced tables                   *)
    BEGIN
    (* move transition table in front of actual considered table  *)
    FOR _k := _n DOWNTO context.jir_i + 1 DO
        sequence_info.si_sequence[ _k ].s_tableno :=
              sequence_info.si_sequence[ _k - 1 ].s_tableno;
    (*ENDFOR*) 
    sequence_info.si_sequence[ context.jir_i ].s_tableno := _next_table;
    context.jir_beststratcnt     := pred (context.jir_beststratcnt);
    context.jir_sequenced_tables := context.jir_sequenced_tables +
          [ sequence_info.si_sequence[ context.jir_i ].s_tableno ];
&   ifdef TRACE
    t01sname( ak_join, 'set nonbest6' );
&   endif
    context.jir_non_best_trans := context.jir_i;
    context.jir_i              := succ (context.jir_i);
    END;
&ifdef TRACE
(*ENDIF*) 
t01int4 (ak_join, '.........i->', context.jir_i);
t01int4 (ak_join, 'beststratcnt', context.jir_beststratcnt);
t01bool (ak_join, 'stop sequenc', context.jir_stop_sequence);
a683tr_newsucc (ak_join, sequence_info.si_sequence, 2, context.jir_i, true);
a683tr_newsucc (ak_join, sequence_info.si_sequence, context.jir_i + 1,
      context.jir_max_tables, true);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681best_join_strat (
            VAR acv           : tak_all_command_glob;
            VAR dmli          : tak_dml_info;
            VAR table_stats   : tak68_table_stats;
            VAR jtrans        : tak68_join_transitions;
            VAR sequence_info : tak68_sequence_info;
            VAR res_info      : tak68_result_info;
            VAR mul_tabs      : tak68_mult_tabs;
            VAR best_jstrat   : tak681_best_jstrat_rec_arr);
 
VAR
      _aux_multiplier       : tsp_int4;
      _aux_fieldcnt         : tsp_int4;
      _best_srctab          : tsp00_Int2;
      _src_tab              : tsp00_Int2;
      _src_tab_idx          : tsp00_Int2;
      _dst_tab              : tsp00_Int2;
      _dst_tab_idx          : tsp00_Int2;
      _used_tablecnt        : tsp00_Int2;
      _aux_bestjoin         : tak68_one_jointype;
 
BEGIN
_used_tablecnt       := dmli.d_cntfromtab;
FOR _dst_tab_idx := 1 TO dmli.d_cntfromtab DO
    BEGIN
    _dst_tab := sequence_info.si_sequence[ _dst_tab_idx ].s_tableno;
    (* initialize best join record *)
    best_jstrat[ _dst_tab ].bjr_jmultipl    := csp_maxint4;
    best_jstrat[ _dst_tab ].bjr_srctab      := 0;
    best_jstrat[ _dst_tab ].bjr_mtab_ind    := 0;
    best_jstrat[ _dst_tab ].bjr_is_mt_join  := false;
    best_jstrat[ _dst_tab ].bjr_jtype       := to_cartesian_prod;
    best_jstrat[ _dst_tab ].bjr_fieldcnt    := 1; (* h.b. PTS 1106353 *)
    (* work for all possible join transitions *)
    FOR _src_tab_idx := 1 TO dmli.d_cntfromtab DO
        BEGIN
        _src_tab := sequence_info.si_sequence[ _src_tab_idx ].s_tableno;
        IF  _src_tab <> _dst_tab
        THEN
            (* consider every possible join transition *)
            (* decide for best join strategy           *)
            IF  jtrans[ _src_tab, _dst_tab ].jt_jointype = to_mt_join
            THEN
                (* there is information in mul_tabs *)
                BEGIN
                _aux_multiplier := best_jstrat[ _dst_tab ].bjr_jmultipl;
                _aux_bestjoin   := best_jstrat[ _dst_tab ].bjr_jtype;
                (* h.b. PTS 1106353 *)
                _aux_fieldcnt   := best_jstrat[ _dst_tab ].bjr_fieldcnt;
                a681lowest_multiple_strat (jtrans, sequence_info.si_sequence,
                      mul_tabs, _src_tab, _dst_tab, _best_srctab,
                      (* h.b. PTS 1106353 *)
                      _aux_bestjoin, _aux_multiplier, _aux_fieldcnt,
                      _used_tablecnt, NOT c_update_jtrans);
                IF  (_aux_multiplier < best_jstrat[ _dst_tab ].bjr_jmultipl)
                THEN
                    BEGIN
                    (* get better join transition *)
                    best_jstrat[ _dst_tab ].bjr_jmultipl    := _aux_multiplier;
                    best_jstrat[ _dst_tab ].bjr_jtype       := _aux_bestjoin;
                    (* h.b. PTS 1106353 *)
                    best_jstrat[ _dst_tab ].bjr_fieldcnt    := _aux_fieldcnt;
                    best_jstrat[ _dst_tab ].bjr_srctab      := _best_srctab;
                    best_jstrat[ _dst_tab ].bjr_mtab_ind    := mul_tabs.mt_pos;
                    best_jstrat[ _dst_tab ].bjr_is_mt_join  := true;
                    END;
                (*ENDIF*) 
                END
            ELSE
                IF  ( best_jstrat[ _dst_tab ].bjr_jtype    >
                    jtrans[ _src_tab, _dst_tab ].jt_jointype)
                    OR
                    (
                    (best_jstrat[ _dst_tab ].bjr_jtype    =
                    jtrans[ _src_tab, _dst_tab ].jt_jointype)
                    AND
                    ( best_jstrat[ _dst_tab ].bjr_jmultipl >
                    jtrans[ _src_tab, _dst_tab ].jt_multipl)
                    )
                THEN
                    BEGIN
                    (* get better join transition *)
                    best_jstrat[ _dst_tab ].bjr_jtype    :=
                          jtrans[ _src_tab, _dst_tab ].jt_jointype;
                    best_jstrat[ _dst_tab ].bjr_jmultipl :=
                          jtrans[ _src_tab, _dst_tab ].jt_multipl;
                    (* h.b. PTS 1106353 *)
                    best_jstrat[ _dst_tab ].bjr_fieldcnt    := 1;
                    best_jstrat[ _dst_tab ].bjr_srctab      := _src_tab;
                    best_jstrat[ _dst_tab ].bjr_mtab_ind    := 0;
                    best_jstrat[ _dst_tab ].bjr_is_mt_join  := false;
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDFOR*) 
    a680_first_table_cost (sequence_info, table_stats, _dst_tab, res_info);
    best_jstrat[ _dst_tab ].bjr_costs :=
          ak681jtable_cost (table_stats, _dst_tab,
          best_jstrat[ _dst_tab ].bjr_jtype (*in*), best_jstrat[ _dst_tab ].
          bjr_jmultipl(*in*), res_info);
    END;
(*ENDFOR*) 
IF  acv.a_intern_explain OR g01vtrace.vtrStrategy_gg00
THEN
    ak681tr_best_joinstrat (acv, dmli, best_jstrat, sequence_info,
          NOT c_debug_output);
&ifdef trace
(*ENDIF*) 
ak681tr_best_joinstrat (acv, dmli, best_jstrat, sequence_info, c_debug_output);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681sort_by_costs (
            VAR dmli          : tak_dml_info;
            VAR sequence_info : tak68_sequence_info;
            VAR best_jstrat   : tak681_best_jstrat_rec_arr;
            VAR table_stats   : tak68_table_stats);
 
VAR
      _i           : tsp00_Int2;
      _j           : tsp00_Int2;
      _k           : tsp00_Int2;
      _first_table : tsp00_Int2;
 
BEGIN
&ifdef TRACE
a683tr_newsucc (ak_join, sequence_info.si_sequence, 1, dmli.d_cntfromtab, true);
&endif
(***************************************************************)
(* *** searching for the smallest table for joining first,     *)
(*     which offers not a very good joinstrategy           *** *)
(***************************************************************)
(* first table is table with lowest one table access costs *)
_first_table := sequence_info.si_sequence[ 1 ].s_tableno;
FOR _i := 2 TO dmli.d_cntfromtab DO
    IF  table_stats[ _i ].ts_cost < table_stats[ _first_table ].ts_cost
    THEN
        _first_table := _i;
    (* get first table *)
    (*ENDIF*) 
(*ENDFOR*) 
_k := sequence_info.si_sequence[ 1 ].s_tableno;
sequence_info.si_sequence[ 1 ].s_tableno :=
      sequence_info.si_sequence[ _first_table ].s_tableno;
sequence_info.si_sequence[ _first_table ].s_tableno := _k;
(* now sort remaining tables with costs for joining *)
FOR _i := 2 TO dmli.d_cntfromtab - 1 DO
    FOR _j := _i + 1 TO dmli.d_cntfromtab DO
        BEGIN
        IF  ( best_jstrat[ sequence_info.si_sequence[ _j ].s_tableno ].
            bjr_costs <
            best_jstrat[ sequence_info.si_sequence[ _i ].s_tableno ].
            bjr_costs   )
        THEN
            BEGIN
            (* swap destination tables *)
            _k := sequence_info.si_sequence[ _j ].s_tableno;
            sequence_info.si_sequence[ _j ].s_tableno :=
                  sequence_info.si_sequence[ _i ].s_tableno;
            sequence_info.si_sequence[ _i ].s_tableno := _k;
            END;
        (*ENDIF*) 
        END;
    (*ENDFOR*) 
(*ENDFOR*) 
&ifdef TRACE
t01sname(ak_join, 'sorted seq  ');
a683tr_newsucc (ak_join, sequence_info.si_sequence, 1, dmli.d_cntfromtab, true);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681greedy (
            VAR jtrans        : tak68_join_transitions;
            VAR mul_tabs      : tak68_mult_tabs;
            VAR table_stats   : tak68_table_stats;
            VAR sequence_info : tak68_sequence_info;
            last_table        : tsp_int2;
            find_start_table  : boolean);
 
VAR
      _best_multipl        : tsp_int4;
      _best_fieldcnt       : tsp_int4;
      _aux_multiplier      : tsp_int4;
      _act_table_pos       : tsp00_Int2;
      _seq_table           : tsp00_Int2;
      _nonseq_table        : tsp00_Int2;
      _l                   : tsp00_Int2;
      _i                   : tsp00_Int2;
      _k                   : tsp00_Int2;
      _first_table         : tsp00_Int2;
      _best_srctab         : tsp00_Int2;
      _next_table_pos      : tsp00_Int2;
      _best_jtype          : tak68_one_jointype;
      _mt_jtrans_check     : boolean;
 
BEGIN
&ifdef TRACE
a683tr_newsucc (ak_join,
      sequence_info.si_sequence, 1, last_table, true);
&endif
IF  find_start_table
THEN
    BEGIN
    _first_table :=  1;
    FOR _i := 2 TO last_table DO
        BEGIN (* PTS 1112102 *)
        IF  table_stats[sequence_info.si_sequence[_i].s_tableno].ts_pages_searched <
            table_stats[sequence_info.si_sequence[_first_table].s_tableno].
            ts_pages_searched
        THEN
            _first_table :=  _i;
        (*ENDIF*) 
        END;
    (*ENDFOR*) 
    _k := sequence_info.si_sequence[ 1 ].s_tableno;
    sequence_info.si_sequence[ 1 ].s_tableno :=
          sequence_info.si_sequence[ _first_table ].s_tableno;
    sequence_info.si_sequence[ _first_table ].s_tableno := _k;
    END;
(*ENDIF*) 
FOR _act_table_pos := 2 TO last_table DO
    BEGIN
    _next_table_pos := _act_table_pos; (* PTS 1112102 *)
    _best_multipl   := csp_maxint4;
    _best_srctab    := 1;
    _best_jtype     := to_cartesian_prod;
    _best_fieldcnt  := 1;
    FOR _l := _act_table_pos TO last_table DO
        BEGIN
        _mt_jtrans_check := true;
        _nonseq_table :=
              sequence_info.si_sequence[ _l ].s_tableno;
        FOR _i := 1 TO _act_table_pos - 1 DO
            BEGIN
            _seq_table :=
                  sequence_info.si_sequence[ _i ].s_tableno;
            IF  jtrans[ _seq_table, _nonseq_table ].
                jt_jointype = to_mt_join
            THEN
                BEGIN
                IF  _mt_jtrans_check
                THEN
                    BEGIN
                    _mt_jtrans_check := false;
                    _aux_multiplier := _best_multipl;
                    a681lowest_multiple_strat (jtrans,
                          sequence_info.si_sequence, mul_tabs,
                          _seq_table, _nonseq_table,
                          _best_srctab, _best_jtype,
                          _best_multipl, _best_fieldcnt, (* h.b. PTS 1106353 *)
                          _act_table_pos - 1, NOT c_update_jtrans);
                    IF  _aux_multiplier > _best_multipl
                    THEN
                        _next_table_pos := _l;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            ELSE
                IF  (_best_jtype >
                    jtrans[ _seq_table, _nonseq_table ].jt_jointype)
                    OR
                    ((_best_jtype =
                    jtrans[ _seq_table, _nonseq_table ].
                    jt_jointype)
                    AND
                    (_best_multipl >
                    jtrans[ _seq_table, _nonseq_table ].
                    jt_multipl))
                THEN
                    BEGIN
                    _best_jtype       :=
                          jtrans[ _seq_table, _nonseq_table ].
                          jt_jointype;
                    _best_multipl     :=
                          jtrans[ _seq_table, _nonseq_table ].
                          jt_multipl;
                    _best_fieldcnt    := 1;
                    _best_srctab      := _seq_table;
                    _next_table_pos   := _l;
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDFOR*) 
        END;
    (*ENDFOR*) 
    _k := sequence_info.si_sequence[ _act_table_pos ].s_tableno;
    sequence_info.si_sequence[ _act_table_pos ].s_tableno :=
          sequence_info.si_sequence[ _next_table_pos ].s_tableno;
    sequence_info.si_sequence[ _next_table_pos ].s_tableno := _k;
    END;
(*ENDFOR*) 
&ifdef TRACE
t01sname(ak_join, 'greedy seq  ');
a683tr_newsucc (ak_join, sequence_info.si_sequence, 1, last_table, true);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681mtj_check (
            VAR dmli              : tak_dml_info;
            VAR jtrans            : tak68_join_transitions;
            VAR sequence_info     : tak68_sequence_info;
            VAR context           : tak681_jseq_info_record;
            VAR table_stats       : tak68_table_stats;
            VAR res_info          : tak68_result_info;
            VAR mul_tabs          : tak68_mult_tabs;
            VAR join_other_table  : boolean);
 
VAR
      _best_multiplier     : tsp_int4;
      _best_fieldcnt       : tsp_int4;
      _best_srctab         : tsp00_Int2;
      _actual_table        : tsp00_Int2;
      _n                   : tsp00_Int2;
      _xi                  : tsp00_Int2;
      _best_jtype          : tak68_one_jointype;
      _join_table          : boolean;
 
BEGIN
join_other_table  := false;
_actual_table     := sequence_info.si_sequence[ context.jir_i ].s_tableno;
_best_multiplier  := csp_maxint4;
_best_fieldcnt    := 1;
_best_srctab      := 1;
_best_jtype       := to_cartesian_prod;
(* are all needed tables for mult table join in sequence ? *)
(* test for best transition from sequence *)
_join_table :=
      context.jir_sequenced_tables >= mul_tabs.mt_arr[ context.jir_best_jstrat
      [ _actual_table ].bjr_mtab_ind ].mtr_tab_seq;
IF  (NOT _join_table)
THEN
    BEGIN
    a681lowest_multiple_strat (jtrans, sequence_info.si_sequence, mul_tabs,
          sequence_info.si_sequence[ 1 ].s_tableno, _actual_table,
          (* h.b. PTS 1106353 *)
          _best_srctab, _best_jtype, _best_multiplier, _best_fieldcnt,
          context.jir_i - 1, NOT c_update_jtrans);
    (* test for best transition from sequence *)
    _join_table :=
          (* TRUE, if mt join transition to _actual_table with  *)
          (* same quality found; all tables in si_sequence *)
          (context.jir_best_jstrat[ _actual_table ].
          bjr_jtype = _best_jtype)
          AND
          (context.jir_best_jstrat[ _actual_table ].
          bjr_jmultipl >= _best_multiplier);
    IF  NOT _join_table
    THEN
        BEGIN
        IF  _best_jtype = to_cartesian_prod
        THEN
            (* don't found multiple table transition from sequence *)
            (* *** no index- or keystratgey found ! *** *)
            BEGIN
            (* find best join transition to dst_table *)
            (* from tables in sequence                *)
            _xi := 1;
            WHILE (_xi <= dmli.d_cntfromtab) DO
                BEGIN
                IF  (_xi in context.jir_sequenced_tables)
                THEN
                    IF  ( _best_jtype > jtrans[ _xi, _actual_table ].jt_jointype)
                        OR
                        (
                        (_best_jtype = jtrans[ _xi, _actual_table ].jt_jointype)
                        AND
                        ( _best_multiplier > jtrans[ _xi, _actual_table ].jt_multipl)
                        )
                    THEN
                        BEGIN
                        _best_jtype      :=
                              jtrans[ _xi, _actual_table ].jt_jointype;
                        _best_multiplier :=
                              jtrans[ _xi, _actual_table ].jt_multipl;
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
                _xi := succ (_xi);
                END;
            (*ENDWHILE*) 
            END;
        (*ENDIF*) 
        _join_table :=
              (* there is a possible transition from sequence *)
              (_best_jtype <> to_cartesian_prod)
              AND
              (
              (
              (ak681jtable_cost (table_stats, _actual_table, _best_jtype,
              _best_multiplier, res_info) <
              (context.jir_best_jstrat
              [ sequence_info.si_sequence[ context.jir_i + 1 ].s_tableno ].
              bjr_costs))
              (**) AND
              (context.jir_best_jstrat
              [ sequence_info.si_sequence[ context.jir_i + 1 ].s_tableno ].
              bjr_jtype < to_eq_field)
              )
              OR
              (* good transition to next table *)
              (context.jir_best_jstrat
              [ sequence_info.si_sequence[ context.jir_i + 1 ].s_tableno ].
              bjr_jtype = to_single_keyfield)
              );
        join_other_table :=
              ( _join_table AND (context.jir_i + 1 < context.jir_max_tables))
              OR
              (
              (NOT _join_table)
              (* no transition from first table to second table *)
              (**) AND
              (context.jir_i = 2)
              (**) AND
              (dmli.d_cntfromtab > 2)
              (**) AND
              (table_stats[ sequence_info.si_sequence[ 1 ].s_tableno ].
              ts_strat_value < 0.98)
              );
        (* note: there isn't a key or index transition from sequence *)
        context.jir_better_seq_exists :=
              (context.jir_i + 1 < context.jir_max_tables);
&       ifdef trace
        t01sname( ak_join, 'set nonbest1' );
&       endif
        context.jir_non_best_trans := context.jir_i;
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  _join_table
THEN
    BEGIN
    (* trace found sequence from mtr_tab_seq *)
    context.jir_beststratcnt     := pred (context.jir_beststratcnt);
    context.jir_sequenced_tables := context.jir_sequenced_tables +
          [ _actual_table ];
    _best_jtype := context.jir_best_jstrat[ _actual_table ].bjr_jtype;
    context.jir_swap_cnt     := 0;
    END
ELSE
    (* no transition from sequence *)
    IF  NOT join_other_table
    THEN
        BEGIN
        (* *** change tables *** *)
        FOR _n := 1 TO context.jir_max_tables DO
            sequence_info.si_sequence[ _n ].s_backup :=
                  sequence_info.si_sequence[ _n ].s_tableno;
        (*ENDFOR*) 
        context.jir_last_swap_pos := context.jir_i;
        IF  (context.jir_i + 1 = context.jir_max_tables)
        THEN
            BEGIN
            sequence_info.si_sequence[ context.jir_i ].s_tableno :=
                  sequence_info.si_sequence[ context.jir_i + 1 ].s_tableno;
            sequence_info.si_sequence[ context.jir_i + 1 ].
                  s_tableno := _actual_table;
            _join_table := true;
            END
        ELSE
            BEGIN
            ak681mt_next_table (dmli, sequence_info, jtrans, mul_tabs, context,
                  table_stats, res_info, _join_table);
            join_other_table :=
                  (* at least 2 tables remaining *)
                  (context.jir_i + 1 < context.jir_max_tables);
            context.jir_better_seq_exists :=
                  (context.jir_i + 1 < context.jir_max_tables);
&           ifdef trace
            t01sname( ak_join, 'set nonbest2' );
&           endif
            context.jir_non_best_trans    := context.jir_i;
            IF  (NOT _join_table)
            THEN
                BEGIN
                (* ** no good join-condition    *)
                (*    from first table       ** *)
                (* ** leave loop             ** *)
                context.jir_stop_sequence := true;
                context.jir_swap_cnt      :=
                      context.jir_max_tables - context.jir_i + 1;
                context.jir_i             := context.jir_max_tables;
                context.jir_beststratcnt  := context.jir_max_tables;
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  _join_table
        THEN
            BEGIN
            (* tables swaped *)
            context.jir_beststratcnt   := pred (context.jir_beststratcnt);
            context.jir_sequenced_tables := context.jir_sequenced_tables +
                  [sequence_info.si_sequence[ context.jir_i ].s_tableno ];
            END;
        (*ENDIF*) 
        context.jir_swap_cnt := 0;
        END;
    (*ENDIF*) 
(*ENDIF*) 
IF  (_best_jtype > to_eq_field)
THEN
    (* we need cartesian product join transition *)
    join_other_table := true;
(*ENDIF*) 
;
(* *** one_to_n check *** *)
IF  (NOT join_other_table)
    AND
    (* we are in first half the sequence *)
    (context.jir_i + 1 <= context.jir_max_tables DIV 2)
    AND
    (* NOT one join result row *)
    (NOT (_best_jtype in [ to_single_keyfield, to_key, to_unique_field ]))
THEN
    BEGIN
    _xi := context.jir_i + 1;
    WHILE ((_xi <= context.jir_max_tables) AND (NOT join_other_table)) DO
        BEGIN
        join_other_table := (context.jir_best_jstrat
              [ sequence_info.si_sequence[ _xi ].s_tableno ].bjr_jtype in
              [ to_single_keyfield, to_key, to_unique_field ]);
        _xi := succ (_xi);
        END;
    (*ENDWHILE*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681mt_next_table (
            VAR dmli           : tak_dml_info;
            VAR sequence_info  : tak68_sequence_info;
            VAR jtrans         : tak68_join_transitions;
            VAR mul_tabs       : tak68_mult_tabs;
            VAR context        : tak681_jseq_info_record;
            VAR table_stats    : tak68_table_stats;
            VAR res_info       : tak68_result_info;
            VAR table_swaped   : boolean);
 
VAR
      _jmultipl_to_nonseq   : tsp_int4;
      _jfieldcnt_to_nonseq  : tsp_int4;
      _jmultipl_to_next     : tsp_int4;
      _n                    : tsp00_Int2;
      _i                    : tsp00_Int2;
      _j                    : tsp00_Int2;
      _seq_table            : tsp00_Int2;
      _actual_table         : tsp00_Int2;
      _nonseq_table         : tsp00_Int2;
      _best_srctab          : tsp00_Int2;
      _next_table           : tsp00_Int2;
      _mt_index             : tsp00_Int2;
      _best_jtype_to_next   : tak68_one_jointype;
      _best_jtype_to_nonseq : tak68_one_jointype;
      _cost_to_nonseqtab    : tsp_longreal;
      _cost_to_nexttab      : tsp_longreal;
      _processed_table_set  : tak_joinset;
      _mt_jtrans_check      : boolean;
 
BEGIN
_actual_table := sequence_info.si_sequence[ context.jir_i ].s_tableno;
_next_table   := 0;
_n  := 0;
_i  := context.jir_best_jstrat[ _actual_table ].bjr_mtab_ind;
IF  ((mul_tabs.mt_arr[ _i ].mtr_tab_seq - context.jir_sequenced_tables) =
    mul_tabs.mt_arr[ _i ].mtr_tab_seq)
THEN
    (* sets are disjunct, i.e. there is no transition from sequence *)
    (* to considered table *)
    BEGIN
    (* *** try to find same joinstrategy via other tablesequence *** *)
    _i := mul_tabs.mt_cnt;
    END;
(*ENDIF*) 
WHILE (_i >= context.jir_best_jstrat[ _actual_table ].bjr_mtab_ind) DO
    BEGIN
    IF  (mul_tabs.mt_arr [ _i ].mtr_dst_table = _actual_table)
        AND
        (* there is the same best join transition *)
        (mul_tabs.mt_arr [ _i ].mtr_jointype =
        context.jir_best_jstrat[ _actual_table ].bjr_jtype)
        AND
        (* we found best join transition *)
        ((_i = context.jir_best_jstrat[ _actual_table ].bjr_mtab_ind)
        OR
        (* we found join without transition from sequence *)
        ((mul_tabs.mt_arr [ _i ].mtr_tab_seq - context.jir_sequenced_tables) =
        mul_tabs.mt_arr [ _i ].mtr_tab_seq))
    THEN
        BEGIN
        (* look for non-sequenced table with multiple  *)
        (* transition to considered table              *)
        (* all participated tables are not in sequence *)
        _j := succ (context.jir_i);
        WHILE (_j <= context.jir_max_tables) DO
            BEGIN
            IF  (sequence_info.si_sequence[ _j ].s_tableno in
                mul_tabs.mt_arr [ _i ].mtr_tab_seq) AND
                NOT (sequence_info.si_sequence[ _j ].s_tableno in
                context.jir_sequenced_tables)
            THEN
                BEGIN
                (* _next_table is participant in multiple join transition *)
                _next_table := sequence_info.si_sequence[ _j ].s_tableno;
                _n          := _j;
                _mt_index   := _i;
                _j          := context.jir_max_tables;
                END;
            (*ENDIF*) 
            _j := succ (_j);
            END;
        (*ENDWHILE*) 
        END;
    (*ENDIF*) 
    _i := pred (_i);
    END;
(*ENDWHILE*) 
IF  (_next_table <> 0)
THEN
    BEGIN
    table_swaped := true;
    (* *** try to find a cheaper table for next joinstep *** *)
    _processed_table_set := [ ];
    _best_srctab        := 1;
    _jmultipl_to_next   := csp_maxint4;
    _best_jtype_to_next := to_cartesian_prod;
    _cost_to_nexttab    := ak681jtable_cost (table_stats, _next_table(*dst_tab*),
          _best_jtype_to_next(*in*), _jmultipl_to_next(*in*), res_info);
    FOR _i := context.jir_i + 1 TO context.jir_max_tables DO
        BEGIN
        _mt_jtrans_check := true;
        _nonseq_table := sequence_info.si_sequence[ _i ].s_tableno;
        IF  (NOT (_nonseq_table in _processed_table_set))
            AND
            (_nonseq_table in mul_tabs.mt_arr[ _mt_index ].mtr_tab_seq )
        THEN
            FOR _j := 1 TO context.jir_i - 1 DO
                BEGIN
                _seq_table := sequence_info.si_sequence[ _j ].s_tableno;
                IF  jtrans[ _seq_table, _nonseq_table ].
                    jt_jointype = to_mt_join
                THEN
                    BEGIN
                    (* multiple join transition *)
                    IF  _mt_jtrans_check
                    THEN
                        BEGIN
                        (* better transition from sequence to choosen table *)
                        (* than transition from sequence to _next_table ?   *)
                        _mt_jtrans_check      := false;
                        _jmultipl_to_nonseq   := csp_maxint4;
                        _jfieldcnt_to_nonseq  := 1;
                        _best_jtype_to_nonseq := to_cartesian_prod;
                        a681lowest_multiple_strat (jtrans,
                              sequence_info.si_sequence, mul_tabs,
                              _seq_table, _nonseq_table(*dst tab*),
                              _best_srctab(*inout*),
                              _best_jtype_to_nonseq(*inout*),
                              _jmultipl_to_nonseq(*inout*),
                              (* h.b. PTS 1106353 *)
                              _jfieldcnt_to_nonseq(*inout*),
                              context.jir_i - 1,
                              NOT c_update_jtrans);
                        _cost_to_nonseqtab := ak681jtable_cost (table_stats,
                              _nonseq_table(*dst table*),
                              _best_jtype_to_nonseq(*in*),
                              _jmultipl_to_nonseq(*in*),
                              res_info);
                        IF  (_cost_to_nonseqtab = context.jir_best_jstrat
                            [ _nonseq_table ].bjr_costs)
                            OR
                            ((_cost_to_nonseqtab / context.jir_best_jstrat
                            [ _nonseq_table ].bjr_costs) <
                            (_cost_to_nexttab / context.jir_best_jstrat
                            [ _next_table ].bjr_costs))
                        THEN
                            BEGIN
                            IF  (NOT (context.jir_best_jstrat
                                [ _nonseq_table ].bjr_jtype in
                                [ to_key, to_all_invfields ]))
                                (* NOT multi table transitions *)
                            THEN
                                BEGIN
                                _next_table := _nonseq_table;
                                _n          := _i;
                                _jmultipl_to_next   := _jmultipl_to_nonseq;
                                _best_jtype_to_next := _best_jtype_to_nonseq;
                                _cost_to_nexttab    := _cost_to_nonseqtab;
                                _processed_table_set := _processed_table_set +
                                      [ _nonseq_table ];
                                END;
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    (* single join transition to non-sequenced table *)
                    (* which is participant in multiple join         *)
                    IF  (_best_jtype_to_next  >
                        jtrans[ _seq_table, _nonseq_table ].jt_jointype)
                        AND
                        (context.
                        jir_best_jstrat[ _nonseq_table ].bjr_jtype =
                        jtrans[ _seq_table, _nonseq_table ].jt_jointype)
                    THEN
                        BEGIN
                        (* best transition from sequenced *)
                        (* to non-sequenced table found   *)
                        _cost_to_nonseqtab :=
                              ak681jtable_cost (table_stats,
                              _nonseq_table(*dst tab*),
                              jtrans[ _seq_table, _nonseq_table ].
                              jt_jointype(*in*),
                              jtrans[ _seq_table, _nonseq_table ].
                              jt_multipl(*in*),
                              res_info);
                        IF  (_cost_to_nonseqtab  / context.jir_best_jstrat
                            [ _nonseq_table ].bjr_costs) <
                            (_cost_to_nexttab / context.jir_best_jstrat
                            [ _next_table ].bjr_costs)
                        THEN
                            BEGIN
                            _next_table := _nonseq_table;
                            _n          := _i;
                            _jmultipl_to_next   := _jmultipl_to_nonseq;
                            _cost_to_nexttab    := _cost_to_nonseqtab;
                            _best_jtype_to_next :=
                                  jtrans[ _seq_table, _nonseq_table ].
                                  jt_jointype;
                            _processed_table_set := [ _nonseq_table ] +
                                  _processed_table_set;
                            END;
                        (*ENDIF*) 
                        END;
                    (* all multiple table transition from sequence *)
                    (* to non-sequenced tables checked             *)
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDFOR*) 
        (*ENDIF*) 
        END;
    (*ENDFOR*) 
    (* move found table in front of sequence *)
&   ifdef trace
    t01int4( ak_join, 'next table  ', _next_table );
&   endif
    FOR _j := _n DOWNTO context.jir_i + 1 DO
        sequence_info.si_sequence[ _j ].s_tableno :=
              sequence_info.si_sequence[ _j - 1 ].s_tableno;
    (*ENDFOR*) 
    sequence_info.si_sequence[ context.jir_i ].s_tableno := _next_table;
&   ifdef trace
    a683tr_newsucc (ak_join, sequence_info.si_sequence, 1, dmli.d_cntfromtab, true);
&   endif
    END
ELSE
    table_swaped := false;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681j_check (
            VAR dmli              : tak_dml_info;
            VAR jtrans            : tak68_join_transitions;
            VAR sequence_info     : tak68_sequence_info;
            VAR context           : tak681_jseq_info_record;
            VAR join_other_table  : boolean);
 
VAR
      _j            : tsp00_Int2;
      _xi           : tsp00_Int2;
      _seq_table    : tsp00_Int2;
      _actual_table : tsp00_Int2;
      _join_table   : boolean;
 
BEGIN
(* there is a transition to _actual_table *)
_actual_table := sequence_info.si_sequence[ context.jir_i ].s_tableno;
_j          := 1;
_join_table := false;
WHILE (_j <= context.jir_i - 1) DO
    BEGIN
    (* consider all transitions to _actual_table *)
    _seq_table := sequence_info.si_sequence[ _j ].s_tableno;
    IF  (_seq_table <> _actual_table)
        AND
        (jtrans[ _seq_table, _actual_table ].jt_jointype < to_cartesian_prod)
        AND
        (_seq_table in context.jir_sequenced_tables)
    THEN
        (* there is a possible transition to dst_table  *)
        (* from already sequenced table                 *)
        BEGIN
        IF  (context.jir_best_jstrat[ _actual_table ].bjr_jtype =
            jtrans[ _seq_table, _actual_table ].jt_jointype)
            AND
            (jtrans[ _seq_table, _actual_table ].jt_multipl =
            context.jir_best_jstrat[ _actual_table ].bjr_jmultipl)
        THEN
            BEGIN
            (* best join transition to dst_table  *)
            (* from already sequenced table       *)
            context.jir_best_jstrat[ _actual_table ].bjr_srctab :=
                  _seq_table;
            context.jir_beststratcnt := pred (context.jir_beststratcnt);
            context.jir_sequenced_tables := context.jir_sequenced_tables +
                  [ _actual_table ];
            _j := context.jir_max_tables + 2; (* exit while *)
            context.jir_swap_cnt     := 0;
            (* *** cak68_join_value can offer a     *)
            (*     cartesianproduct strategy  *** *)
            join_other_table :=
                  (context.jir_i < context.jir_max_tables)
                  AND
                  (* join transition carriers cartesian product *)
                  (
                  (jtrans[ _seq_table, _actual_table ].jt_jointype > to_eq_field)
                  (* transition without access path and non-equal conditions *)
                  OR
                  (dmli.d_joins.jrc_joinarr
                  [ jtrans[ _seq_table, _actual_table ].jt_joinno ].
                  jo_recs[ 2 ].jop_tableno = cak68_join_value)
                  (* transition to constant value *)
                  );
            IF  join_other_table
            THEN
                BEGIN
&               ifdef trace
                t01sname( ak_join, 'set nonbest3' );
&               endif
                context.jir_non_best_trans := context.jir_i
                END
            ELSE
                (* *** one_to_n check *** *)
                IF  (context.jir_i + 2 <= context.jir_max_tables DIV 2)
                    (* we are in first half the sequence *)
                    AND
                    (NOT (jtrans[ _seq_table, _actual_table ].jt_jointype
                    in [ to_single_keyfield, to_key, to_unique_field ]))
                    (* NOT one join result row *)
                THEN
                    BEGIN
                    _xi := context.jir_i + 1;
                    WHILE ((_xi <= context.jir_max_tables) AND
                          (NOT join_other_table)) DO
                        BEGIN
                        join_other_table := (context.jir_best_jstrat
                              [ sequence_info.si_sequence[ _xi ].s_tableno ].
                              bjr_jtype in
                              [ to_single_keyfield, to_key, to_unique_field ]);
                        _xi := succ (_xi);
                        END;
                    (*ENDWHILE*) 
                    END;
                (* *** *** *)
                (*ENDIF*) 
            (*ENDIF*) 
            END
        ELSE
            (* this isn't the best join transition to dst_table *)
            (* from already sequenced table                     *)
            BEGIN
            IF  jtrans[ _seq_table, _actual_table ].jt_jointype < to_eq_field
            THEN
                (* we have an access path to column from sequenced tables *)
                _join_table := true;
            (*ENDIF*) 
            context.jir_better_seq_exists := true;
&           ifdef TRACE
            a683trace_jointype (ak_join, 'better_seq  ',
                  jtrans[ _seq_table, _actual_table ].jt_jointype);
            a683trace_jointype (ak_join, 'bjr_bestjoin',
                  context.jir_best_jstrat[ _actual_table ].bjr_jtype);
&           endif
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    _j := succ (_j);
    END;
(*ENDWHILE*) 
IF  (_j < (context.jir_max_tables + 2))
THEN
    (* we don't found best join transition from sequence to _actual_table *)
    BEGIN
    join_other_table := join_other_table OR
          (* at least 1 tables remaining *)
          (context.jir_i < context.jir_max_tables);
    IF  join_other_table
    THEN
        BEGIN
&       ifdef trace
        t01sname( ak_join, 'set nonbest4' );
&       endif
        context.jir_non_best_trans := context.jir_i;
        context.jir_stop_sequence  := false;
        END;
    (*ENDIF*) 
    IF  (_join_table)
    THEN
        (* there was any join transition to _actual_table  *)
        (* with access path from sequenced tables       *)
        BEGIN
        context.jir_beststratcnt     := pred (context.jir_beststratcnt);
        context.jir_sequenced_tables := context.jir_sequenced_tables +
              [ _actual_table ];
        END
    ELSE
        (* there wasn't any join transition to _actual_table with access path *)
        BEGIN
&       ifdef trace
        t01sname(ak_join, 'swap tables ');
&       endif
        IF  (context.jir_last_swap_pos = context.jir_i)
        THEN
            BEGIN
            (* prior table hasn't join transition from sequence *)
            (* *** restore sequence *** *)
            FOR _j := context.jir_i TO context.jir_max_tables DO
                sequence_info.si_sequence[ _j ].s_tableno := sequence_info.
                      si_sequence[ _j ].s_backup;
            (*ENDFOR*) 
            END
        ELSE
            (* prior table has join transition from sequence *)
            FOR _j := context.jir_i TO context.jir_max_tables DO
                sequence_info.si_sequence[ _j ].s_backup := sequence_info.
                      si_sequence[ _j ].s_tableno;
            (*ENDFOR*) 
        (*ENDIF*) 
        context.jir_swap_cnt      := succ (context.jir_swap_cnt);
        context.jir_last_swap_pos := context.jir_i;
        IF  (context.jir_i + context.jir_swap_cnt <= context.jir_max_tables)
        THEN
            BEGIN
            _actual_table := sequence_info.si_sequence
                  [ context.jir_i + context.jir_swap_cnt ].s_tableno;
            (* restore old sequence *)
            FOR _j := context.jir_i + context.jir_swap_cnt DOWNTO
                  context.jir_i + 1 DO
                sequence_info.si_sequence[ _j ].s_tableno :=
                      sequence_info.si_sequence[ _j - 1 ].s_tableno;
            (*ENDFOR*) 
            sequence_info.si_sequence[ context.jir_i ].
                  s_tableno := _actual_table;
            (* try swaped table *)
            context.jir_i := pred (context.jir_i);
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a681tr_tabstats (
            VAR acv           : tak_all_command_glob;
            VAR dmli          : tak_dml_info;
            VAR table_stats   : tak68_table_stats;
            VAR res_info      : tak68_result_info;
            cntfrom           : integer;
            debug             : boolean);
 
CONST
      c_no_column = 0;
 
VAR
      _i    : integer;
      _pos  : integer;
      _ln   : tsp_dataline;
      _nam  : tsp_sname;
      _res  : boolean;
 
BEGIN
IF  acv.a_intern_explain OR debug
THEN
    FOR _i := 1 TO cntfrom DO
        BEGIN
        WITH table_stats [ _i ], res_info DO
            BEGIN
            s10fil (sizeof (_ln.text), _ln.text, 1, sizeof (_ln.text), bsp_c1);
            _ln.pos := 1;
            _nam    := 'TABLE No.   ';
            s10mv2 (sizeof(_nam), sizeof(_ln.text),
                  _nam, 1, _ln.text, _ln.pos, sizeof(_nam));
            _ln.pos := _ln.pos + sizeof(_nam);
            g17int4to_line (_i, false, 2, _ln.pos - 2, _ln.text);
&           ifdef trace
            IF  debug
            THEN
                t01line(ak_join, _ln.text)
            ELSE
&               endif
                (* h.b. PTS 1105127 *)
                a40sequence_expl_row (acv, _ln.text, c_change_to_unicode);
            (*ENDIF*) 
            IF  g01unicode
            THEN
                g20unifill (sizeof(_ln.text), @_ln.text, 1,
                      sizeof (_ln.text), csp_unicode_blank)
            ELSE
                s10fil (sizeof (_ln.text), _ln.text, 1,
                      sizeof (_ln.text), bsp_c1);
            (*ENDIF*) 
            _ln.pos := 1;
            a683trans_to_line( acv, dmli, _i, c_no_column, _ln,
                  sizeof(_ln.text), _res );
&           ifdef trace
            IF  debug
            THEN
                t01line(ak_join, _ln.text)
            ELSE
&               endif
                (* h.b. PTS 1105127 *)
                a40sequence_expl_row (acv, _ln.text, NOT c_change_to_unicode);
            (*ENDIF*) 
            s10fil (sizeof (_ln.text), _ln.text, 1, sizeof (_ln.text), bsp_c1);
            (* solve parameter develivery problems *)
            _pos := 2;
            g17stratenum_to_line (ri_single_strat[ _i ], _pos, _ln.text);
            _ln.pos := _pos;
            _ln.pos := _ln.pos + 2;
            IF  ri_inv_only_strat [ _i ]
            THEN
                BEGIN
                _nam  := '(Index Only)';
                s10mv2 (sizeof(_nam), sizeof(_ln.text),
                      _nam, 1, _ln.text, _ln.pos, sizeof(_nam));
                END;
&           ifdef trace
            (*ENDIF*) 
            IF  debug
            THEN
                t01line(ak_join, _ln.text)
            ELSE
&               endif
                (* h.b. PTS 1105127 *)
                a40sequence_expl_row (acv, _ln.text, c_change_to_unicode);
            (*ENDIF*) 
            s10fil (sizeof (_ln.text), _ln.text, 1, sizeof (_ln.text), bsp_c1);
            _ln.pos := 1;
            _nam    := ' pages_found';
            s10mv2 (sizeof(_nam), sizeof(_ln.text),
                  _nam, 1, _ln.text, _ln.pos, sizeof(_nam));
            _ln.pos := _ln.pos + sizeof(_nam);
            g17longreal_to_line (ts_pages_found, 3, _ln.pos, _ln.text);
&           ifdef trace
            IF  debug
            THEN
                t01line(ak_join, _ln.text)
            ELSE
&               endif
                (* h.b. PTS 1105127 *)
                a40sequence_expl_row (acv, _ln.text, c_change_to_unicode);
            (*ENDIF*) 
            s10fil (sizeof (_ln.text), _ln.text, 1, sizeof (_ln.text), bsp_c1);
            _ln.pos := 1;
            _nam    := ' strat      ';
            s10mv2 (sizeof(_nam), sizeof(_ln.text),
                  _nam, 1, _ln.text, _ln.pos, sizeof(_nam));
            _ln.pos := _ln.pos + sizeof(_nam);
            g17longreal_to_line (ts_strat_value, 3, _ln.pos, _ln.text);
&           ifdef trace
            IF  debug
            THEN
                t01line(ak_join, _ln.text)
            ELSE
&               endif
                (* h.b. PTS 1105127 *)
                a40sequence_expl_row (acv, _ln.text, c_change_to_unicode);
            (*ENDIF*) 
            s10fil (sizeof (_ln.text), _ln.text, 1, sizeof (_ln.text), bsp_c1);
            _ln.pos := 1;
            _nam    := ' all_pages  ';
            s10mv2 (sizeof(_nam), sizeof(_ln.text),
                  _nam, 1, _ln.text, _ln.pos, sizeof(_nam));
            _ln.pos := _ln.pos + sizeof(_nam);
            g17int4to_line (ts_all_pages, false, 7, _ln.pos, _ln.text);
&           ifdef trace
            IF  debug
            THEN
                t01line(ak_join, _ln.text)
            ELSE
&               endif
                (* h.b. PTS 1105127 *)
                a40sequence_expl_row (acv, _ln.text, c_change_to_unicode);
            (*ENDIF*) 
            s10fil (sizeof (_ln.text), _ln.text, 1, sizeof (_ln.text), bsp_c1);
            _ln.pos := 1;
            _nam    := ' cost       ';
            s10mv2 (sizeof(_nam), sizeof(_ln.text),
                  _nam, 1, _ln.text, _ln.pos, sizeof(_nam));
            _ln.pos := _ln.pos + sizeof(_nam);
            g17int4to_line (ts_cost, false, 7, _ln.pos, _ln.text);
&           ifdef trace
            IF  debug
            THEN
                t01line(ak_join, _ln.text)
            ELSE
&               endif
                (* h.b. PTS 1105127 *)
                a40sequence_expl_row (acv, _ln.text, c_change_to_unicode);
            (*ENDIF*) 
            s10fil (sizeof (_ln.text), _ln.text, 1, sizeof (_ln.text), bsp_c1);
            _ln.pos := 1;
            _nam    := ' recs_per_p ';
            s10mv2 (sizeof(_nam), sizeof(_ln.text),
                  _nam, 1, _ln.text, _ln.pos, sizeof(_nam));
            _ln.pos := _ln.pos + sizeof(_nam);
            g17int4to_line (ts_recs_per_page, false, 7, _ln.pos, _ln.text);
&           ifdef trace
            IF  debug
            THEN
                t01line(ak_join, _ln.text)
            ELSE
&               endif
                (* h.b. PTS 1105127 *)
                a40sequence_expl_row (acv, _ln.text, c_change_to_unicode);
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
        END;
    (*ENDFOR*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a681tr_multabs (
            VAR acv      : tak_all_command_glob;
            VAR mul_tabs : tak68_mult_tabs;
            cntfrom      : integer);
 
VAR
      _i              : integer;
      _j              : integer;
      _pos            : integer;
      _oldpos         : integer;
      _ln             : tsp_line;
      _nam            : tsp_sname;
      _dummy          : tsp_longreal;
 
BEGIN
WITH mul_tabs DO
    IF  mt_cnt > 0
    THEN
        BEGIN
        s10fil (sizeof (_ln), _ln, 1, sizeof (_ln), bsp_c1);
        _pos     := 1;
        _ln [ _pos ]     := 'T';
        _ln [ _pos + 1 ] := 'O';
        _pos    := _pos + 4;
        _nam    := 'via         ';
        s10mv2 (sizeof(_nam), sizeof(_ln), _nam, 1, _ln, _pos, sizeof(_nam));
        _pos    := _pos + sizeof (_nam) + 2;
        _nam    := 'multiplier  ';
        s10mv2 (sizeof(_nam), sizeof(_ln), _nam, 1, _ln, _pos, sizeof(_nam));
        _pos    := _pos + sizeof (_nam) + 1;
        _ln [ _pos ]     := 'T';
        _pos            := _pos + 3;
        _ln [ _pos ]     := 'F';
        _pos            := _pos + 3;
        _ln [ _pos ]     := 'J';
        _pos            := _pos + 3;
        _ln [ _pos ]     := 'I';
        _pos            := _pos + 3;
        _nam    := 'Used tables ';
        s10mv2 (sizeof(_nam), sizeof(_ln), _nam, 1, _ln, _pos, sizeof(_nam));
        _pos    := _pos + sizeof(_nam);
        IF  g01vtrace.vtrStrategy_gg00
        THEN
            b120InsertTrace (acv.a_mblock.mb_trns^,
                  ak_strat, ak_join_strat, _pos, @_ln);
        (*ENDIF*) 
        IF  acv.a_intern_explain
        THEN
            (* h.b. PTS 1105127 *)
            a40sequence_expl_row (acv, _ln, c_change_to_unicode);
        (*ENDIF*) 
        FOR _j := 1 TO mt_cnt DO
            WITH mt_arr[ _j ] DO
                BEGIN
                s10fil (sizeof (_ln), _ln, 1, sizeof (_ln), bsp_c1);
                _pos     := 1;
                g17int4to_line (mtr_dst_table, false, 2, _pos, _ln);
                _pos    := _pos + 4;
                CASE mtr_jointype OF
                    to_single_keyfield :
                        _nam := 'SINGLE KEY  ';
                    to_unique_field    :
                        _nam := 'UNIQUE INDE ';
                    to_keypart  :
                        _nam := 'KEY PART    ';
                    to_key      :
                        _nam := 'KEY         ';
                    to_first_keyfield  :
                        _nam := 'FIRST KEY   ';
                    to_invfield :
                        _nam := 'INDEX       ';
                    to_all_invfields :
                        _nam := 'INDEXCOLUMNS';
                    to_invpart :
                        _nam := 'INDEX PART  ';
                    to_eq_field :
                        _nam := 'EQUAL COLUMN';
                    to_lt_gt_field :
                        _nam := '>, <, ......';
                    to_ne_field,
                    to_cartesian_prod :
                        _nam := '<>, none    ';
                    to_illegal :
                        _nam := '  ILLEGAL   ';
                    OTHERWISE
                        _nam := 'unknown cond';
                    END;
                (*ENDCASE*) 
                s10mv2 (sizeof(_nam), sizeof(_ln), _nam, 1, _ln, _pos,
                      sizeof(_nam));
                _pos    := _pos + sizeof (_nam) + 2;
                _dummy := mt_arr[ _j ].mtr_multipl;
                g17longreal_to_line (_dummy, 3, _pos, _ln);
                _pos    := _pos + 11;
                g17int4to_line (mtr_tablecnt, false, 3, _pos, _ln);
                _pos    := _pos + 3;
                g17int4to_line (mtr_fieldcnt, false, 3, _pos, _ln);
                _pos    := _pos + 3;
                g17int4to_line (mtr_joinno, false, 3, _pos, _ln);
                _pos    := _pos + 3;
                g17int4to_line (mtr_indexno, false, 3, _pos, _ln);
                _pos    := _pos + 5;
                _ln [ _pos ] := '[';
                _pos    := _pos + 1;
                _oldpos := _pos;
                FOR _i := 1 TO cntfrom DO
                    BEGIN
                    IF  _i in mtr_tab_seq
                    THEN
                        BEGIN
                        g17int4to_line (_i, false, 3, _pos, _ln);
                        _pos := _pos + 3;
                        END;
                    (*ENDIF*) 
                    IF  (_pos >= 80) AND (_i < cntfrom)
                    THEN
                        BEGIN
                        IF  g01vtrace.vtrStrategy_gg00
                        THEN
                            b120InsertTrace (acv.a_mblock.mb_trns^,
                                  ak_strat, ak_join_strat, _pos, @_ln);
                        (*ENDIF*) 
                        IF  acv.a_intern_explain
                        THEN
                            a40sequence_expl_row (acv, _ln,
                                  c_change_to_unicode); (* h.b. PTS 1105127 *)
                        (*ENDIF*) 
                        s10fil (sizeof (_ln), _ln, 1, sizeof (_ln), bsp_c1);
                        _pos := _oldpos;
                        END
                    (*ENDIF*) 
                    END;
                (*ENDFOR*) 
                _pos := succ (_pos);
                _ln [ _pos ] := ']';
                IF  g01vtrace.vtrStrategy_gg00
                THEN
                    b120InsertTrace (acv.a_mblock.mb_trns^,
                          ak_strat, ak_join_strat, _pos, @_ln);
                (*ENDIF*) 
                IF  acv.a_intern_explain
                THEN
                    (* h.b. PTS 1105127 *)
                    a40sequence_expl_row (acv, _ln, c_change_to_unicode)
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
        (*ENDFOR*) 
        END;
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681tr_best_joinstrat (
            VAR acv           : tak_all_command_glob;
            VAR dmli          : tak_dml_info;
            VAR bjra          : tak681_best_jstrat_rec_arr;
            VAR sequence_info : tak68_sequence_info;
            debug             : boolean);
 
VAR
      _pos            : integer;
      _to_tab         : integer;
      _to_tab_index   : integer;
      _ln             : tsp_line;
      _nam            : tsp_sname;
      _dummy          : tsp_longreal;
 
BEGIN
s10fil (sizeof (_ln), _ln, 1, sizeof (_ln), bsp_c1);
_pos     := 1;
_ln [ _pos ]     := 'T';
_ln [ _pos + 1 ] := 'O';
_pos    := _pos + 4;
_nam    := 'via         ';
s10mv2 (sizeof(_nam), sizeof(_ln), _nam, 1, _ln, _pos, sizeof(_nam));
_pos    := _pos + sizeof (_nam) + 2;
_nam    := 'multiplier  ';
s10mv2 (sizeof(_nam), sizeof(_ln), _nam, 1, _ln, _pos, sizeof(_nam));
_pos    := _pos + sizeof (_nam) + 2;
_nam    := 'costs       ';
s10mv2 (sizeof(_nam), sizeof(_ln), _nam, 1, _ln, _pos, sizeof(_nam));
_pos    := _pos + sizeof (_nam) + 2;
_ln [ _pos ]     := 'j';
_ln [ _pos + 1 ] := 'i';
_pos            := _pos + 4;
_ln [ _pos ]     := 'm';
_pos            := _pos + 1;
_ln [ _pos ]     := 'i';
&ifdef trace
IF  debug
THEN
    t01line(ak_join, _ln)
ELSE
    BEGIN
&   endif
    IF  g01vtrace.vtrStrategy_gg00
    THEN
        b120InsertTrace (acv.a_mblock.mb_trns^,
              ak_strat, ak_join_strat, _pos, @_ln);
    (*ENDIF*) 
    IF  acv.a_intern_explain
    THEN
        (* h.b. PTS 1105127 *)
        a40sequence_expl_row (acv, _ln, c_change_to_unicode);
&   ifdef trace
    (*ENDIF*) 
    END;
(*ENDIF*) 
&endif
FOR _to_tab := 1 TO dmli.d_cntfromtab DO
    BEGIN
    _to_tab_index := 1;
    WHILE (sequence_info.si_sequence[ _to_tab_index ].s_tableno <> _to_tab) DO
        _to_tab_index := succ (_to_tab_index);
    (*ENDWHILE*) 
    s10fil (sizeof (_ln), _ln, 1, sizeof (_ln), bsp_c1);
    _pos     := 1;
    g17int4to_line (_to_tab, false, 2, _pos, _ln);
    _pos    := _pos + 4;
    CASE bjra[ _to_tab_index ].bjr_jtype OF
        to_single_keyfield :
            _nam := 'SINGLE KEY  ';
        to_unique_field    :
            _nam := 'UNIQUE INDE ';
        to_keypart  :
            _nam := 'KEY PART    ';
        to_key      :
            _nam := 'KEY         ';
        to_first_keyfield  :
            _nam := 'FIRST KEY   ';
        to_invfield :
            _nam := 'INDEX       ';
        to_all_invfields :
            _nam := 'INDEX-FIELDS';
        to_invpart :
            _nam := 'INDEX PART  ';
        to_eq_field :
            _nam := 'EQUAL FIELD ';
        to_lt_gt_field :
            _nam := '>, <, ......';
        to_ne_field,
        to_cartesian_prod :
            _nam := '<>, none    ';
        to_illegal :
            _nam := '  ILLEGAL   ';
        OTHERWISE
            _nam := 'unknown cond';
        END;
    (*ENDCASE*) 
    s10mv2 (sizeof(_nam), sizeof(_ln), _nam, 1, _ln, _pos, sizeof(_nam));
    _pos    := _pos + sizeof (_nam) + 2;
    _dummy  := bjra[ _to_tab_index ].bjr_jmultipl;
    g17longreal_to_line (_dummy, 3, _pos, _ln);
    _pos    := _pos + sizeof (_nam) + 2;
    g17longreal_to_line (bjra[ _to_tab_index ].bjr_costs, 6, _pos, _ln);
    _pos    := _pos + sizeof (_nam) + 2;
    g17int4to_line (bjra[ _to_tab_index ].bjr_srctab, false, 2, _pos, _ln);
    _pos    := _pos + 4;
    g17int4to_line (bjra[ _to_tab_index ].bjr_mtab_ind, false, 2, _pos, _ln);
    _pos    := _pos + 4;
    IF  bjra[ _to_tab_index ].bjr_is_mt_join
    THEN
        BEGIN
        _nam    := 'multiplejoin';
        s10mv2 (sizeof(_nam), sizeof(_ln), _nam, 1, _ln, _pos, sizeof(_nam));
        _pos    := _pos + sizeof (_nam);
        END;
&   ifdef trace
    (*ENDIF*) 
    IF  debug
    THEN
        t01line(ak_join, _ln)
    ELSE
        BEGIN
&       endif
        IF  g01vtrace.vtrStrategy_gg00
        THEN
            b120InsertTrace (acv.a_mblock.mb_trns^,
                  ak_strat, ak_join_strat, _pos, @_ln);
        (*ENDIF*) 
        IF  acv.a_intern_explain
        THEN
            (* h.b. PTS 1105127 *)
            a40sequence_expl_row (acv, _ln, c_change_to_unicode);
&       ifdef trace
        (*ENDIF*) 
        END;
    (*ENDIF*) 
&   endif
    END;
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681tr_report_succ (
            VAR acv        : tak_all_command_glob;
            r              : tsp_longreal;
            VAR succession : tak68_succession;
            start          : integer;
            stop           : integer;
            is_lower       : boolean);
 
VAR
      _i              : integer;
      _pos            : integer;
      _oldpos         : integer;
      _ln             : tsp_line;
      _nam            : tsp_sname;
 
BEGIN
s10fil (sizeof (_ln), _ln, 1, sizeof (_ln), bsp_c1);
_pos    := 1;
IF  is_lower
THEN
    _nam := '< COSTVALUE '
ELSE
    _nam := '> COSTVALUE ';
(*ENDIF*) 
s10mv2 (sizeof(_nam), sizeof(_ln), _nam, 1, _ln, _pos, sizeof(_nam));
_pos      := _pos + sizeof (_nam);
_ln [_pos] := ':';
_pos      := _pos + 1;
g17longreal_to_line (r, 6, _pos, _ln);
_pos       := _pos + 14;
_ln[ _pos ] := '[';
_pos       := _pos + 1;
_oldpos    := _pos;
(* succession *)
FOR _i := start TO stop DO
    BEGIN
    g17int4to_line (succession[ _i ].s_tableno, false, 3, _pos, _ln);
    _pos := _pos + 3;
    IF  ((_i+1-start) MOD 16 = 0) AND (_i < stop)
    THEN
        BEGIN
        IF  g01vtrace.vtrStrategy_gg00
        THEN
            b120InsertTrace (acv.a_mblock.mb_trns^,
                  ak_strat, ak_join_strat, _pos, @_ln);
        (*ENDIF*) 
        IF  acv.a_intern_explain
        THEN
            (* h.b. PTS 1105127 *)
            a40sequence_expl_row (acv, _ln, c_change_to_unicode);
        (*ENDIF*) 
        s10fil (sizeof (_ln), _ln, 1, sizeof (_ln), bsp_c1);
        _pos := _oldpos
        END
    (*ENDIF*) 
    END;
(*ENDFOR*) 
_pos := succ (_pos);
_ln[ _pos ] := ']';
IF  g01vtrace.vtrStrategy_gg00
THEN
    b120InsertTrace (acv.a_mblock.mb_trns^,
          ak_strat, ak_join_strat, _pos, @_ln);
(*ENDIF*) 
IF  acv.a_intern_explain
THEN
    (* h.b. PTS 1105127 *)
    a40sequence_expl_row (acv, _ln, c_change_to_unicode)
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a681tr_joinvals (
            VAR acv      : tak_all_command_glob;
            VAR jtrans   : tak68_join_transitions;
            starttab     : integer;
            stoptab      : integer;
            table_cnt    : integer);
 
VAR
      _i              : integer;
      _j              : integer;
      _pos            : integer;
      _ln             : tsp_line;
      _nam            : tsp_sname;
 
BEGIN
s10fil (sizeof (_ln), _ln, 1, sizeof (_ln), bsp_c1);
_pos := 1;
_nam := ' | FROM     ';
s10mv2 (sizeof(_nam), sizeof(_ln), _nam, 1, _ln, _pos, sizeof(_nam));
_pos := _pos + sizeof (_nam) - 9;
FOR _i (* *** fromrec *** *) := starttab TO stoptab DO
    g17int4to_line (_i, false, 3, (_i-starttab+1) * 4 + _pos, _ln);
(*ENDFOR*) 
_pos := _pos + (stoptab-starttab+1 + 1) * 4;
IF  g01vtrace.vtrStrategy_gg00
THEN
    b120InsertTrace (acv.a_mblock.mb_trns^,
          ak_strat, ak_join_strat, _pos, @_ln);
(*ENDIF*) 
IF  acv.a_intern_explain
THEN
    (* h.b. PTS 1105127 *)
    a40sequence_expl_row (acv, _ln, c_change_to_unicode);
(*ENDIF*) 
s10fil (sizeof (_ln), _ln, 1, sizeof (_ln), bsp_c1);
_pos := 1;
_nam := 'TO          ';
s10mv2 (sizeof(_nam), sizeof(_ln), _nam, 1, _ln, _pos, sizeof(_nam));
_pos := _pos + sizeof(_nam);
IF  g01vtrace.vtrStrategy_gg00
THEN
    b120InsertTrace (acv.a_mblock.mb_trns^,
          ak_strat, ak_join_strat, _pos, @_ln);
(*ENDIF*) 
IF  acv.a_intern_explain
THEN
    (* h.b. PTS 1105127 *)
    a40sequence_expl_row (acv, _ln, c_change_to_unicode);
(*ENDIF*) 
FOR _j (* *** torec *** *) := 1 TO table_cnt DO
    BEGIN
    s10fil (sizeof (_ln), _ln, 1, sizeof (_ln), bsp_c1);
    _pos := 1;
    g17int4to_line (_j, false, 2, _pos, _ln);
    _pos := _pos + sizeof (_nam) - 4;
    FOR _i := starttab TO stoptab DO
        BEGIN
        CASE jtrans[ _i, _j ].jt_jointype OF
            to_single_keyfield :
                BEGIN
                _ln [ _pos ]     := 'S';
                _ln [ _pos + 1 ] := 'K';
                END;
            to_unique_field    :
                BEGIN
                _ln [ _pos ]     := 'U';
                _ln [ _pos + 1 ] := 'I';
                END;
            to_keypart  :
                BEGIN
                _ln [ _pos ]     := 'K';
                _ln [ _pos + 1 ] := 'P';
                END;
            to_key      :
                BEGIN
                _ln [ _pos ]     := 'M';
                _ln [ _pos + 1 ] := 'K';
                END;
            to_first_keyfield  :
                BEGIN
                _ln [ _pos ]     := 'F';
                _ln [ _pos + 1 ] := 'K';
                END;
            to_invfield :
                BEGIN
                _ln [ _pos ]     := 'I';
                END;
            to_all_invfields :
                BEGIN
                _ln [ _pos ]     := 'M';
                _ln [ _pos + 1 ] := 'I';
                END;
            to_invpart :
                BEGIN
                _ln [ _pos ]     := 'I';
                _ln [ _pos + 1 ] := 'P';
                END;
            to_mt_join :
                BEGIN
                _ln [ _pos ]     := 'M';
                _ln [ _pos + 1 ] := 'J';
                END;
            to_eq_field :
                BEGIN
                _ln [ _pos ]     := '=';
                END;
            to_lt_gt_field :
                BEGIN
                _ln [ _pos ]     := '>';
                _ln [ _pos + 1 ] := '<';
                END;
            to_ne_field,
            to_cartesian_prod :
                BEGIN
                _ln [ _pos ]     := '?';
                _ln [ _pos + 1 ] := '?';
                END;
            to_illegal :
                BEGIN
                _ln [ _pos ]     := '-';
                _ln [ _pos + 1 ] := '-';
                END;
            OTHERWISE
                BEGIN
                _ln [ _pos ]     := '.';
                _ln [ _pos + 1 ] := '.';
                END;
            END;
        (*ENDCASE*) 
        _pos := _pos + 4;
        END;
    (*ENDFOR*) 
    IF  g01vtrace.vtrStrategy_gg00
    THEN
        b120InsertTrace (acv.a_mblock.mb_trns^,
              ak_strat, ak_join_strat, _pos, @_ln);
    (*ENDIF*) 
    IF  acv.a_intern_explain
    THEN
        (* h.b. PTS 1105127 *)
        a40sequence_expl_row (acv, _ln, c_change_to_unicode)
    (*ENDIF*) 
    END;
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      ak681jtable_cost (
            VAR table_stats  : tak68_table_stats;
            curr_tab         : integer;
            best_jtype       : tak68_one_jointype;
            best_jmultipl    : tsp_int4;
            VAR res_info     : tak68_result_info) : tsp_longreal;
 
CONST
      _c_not_distinct = false;
 
VAR
      _counted_multiplier    : tsp_longreal;
      _reverse_multiplier    : tsp_longreal;
      _costs                 : tsp_longreal;
      _newpages              : tsp_longreal;
      _local_jtrans          : tak68_join_transition;
      _local_table_stat      : tak68_one_table_stat;
 
BEGIN
_local_jtrans.jt_joinno       := 0;
_local_jtrans.jt_indexno      := 0;
_local_jtrans.jt_jointype     := best_jtype;
_local_jtrans.jt_multipl      := best_jmultipl;
_local_table_stat             := table_stats [ curr_tab ];
_costs                        := 100;
_newpages                     := 10;
res_info.ri_old_recs_per_page := 50;
_counted_multiplier           := best_jmultipl;
_reverse_multiplier           := csp_maxint4;
a680next_join_eval (_local_jtrans, _local_table_stat,
      _counted_multiplier, _reverse_multiplier,
      _costs (* inout *), _newpages (* inout *),
      res_info.ri_old_recs_per_page (* in *),
      res_info.ri_recs_per_page (* in *),
      _c_not_distinct);
_costs := _costs * _counted_multiplier * _local_table_stat.ts_strat_value;
IF  _costs = 0
THEN
    _costs := 1;
&ifdef TRACE
(*ENDIF*) 
t01real (ak_join,'costs       ', _costs, 3);
&endif
ak681jtable_cost := _costs;
END;
 
&ifdef TRACE
(*------------------------------*) 
 
PROCEDURE
      ak681tr_context(
            VAR sequence_info : tak68_sequence_info;
            VAR context       : tak681_jseq_info_record );
 
BEGIN
t01int4(ak_join, 'jir_max_tabl', context.jir_max_tables);
t01c30 (ak_join, 'succ 1 ... context.jir_i - 1  ');
a683tr_newsucc (ak_join, sequence_info.si_sequence, 1, context.jir_i - 1, true);
t01c30 (ak_join, 'newsucc context.jir_i ... last');
a683tr_newsucc (ak_join, sequence_info.si_sequence, context.jir_i,
      context.jir_max_tables, true);
t01bool (ak_join, 'stop sequenc', context.jir_stop_sequence);
t01bool (ak_join, 'better seq  ', context.jir_better_seq_exists);
t01p2int4(ak_join, 'strat cnt   ', context.jir_beststratcnt
      , 'comp sequenc', context.jir_comp_sequences);
t01int4(ak_join, 'swap count  ', context.jir_swap_cnt);
t01p2int4(ak_join, 'non best tra', context.jir_non_best_trans
      , 'i           ', context.jir_i);
t01int4(ak_join, 'last_swap_po', context.jir_last_swap_pos);
t01real(ak_join, 'lowest_cost ', context.jir_lowest_cost, 6);
a683tr_tableset(ak_join, 'jir_seq_set ', context.jir_sequenced_tables);
END;
 
&endif
(*------------------------------*) 
 
PROCEDURE
      ak681permut_sequence(
            VAR acv             : tak_all_command_glob;
            VAR dmli            : tak_dml_info;
            VAR table_stats     : tak68_table_stats;
            VAR jtrans          : tak68_join_transitions;
            VAR sequence_info   : tak68_sequence_info;
            VAR jinfos          : tak68_joininfos;
            VAR res_info        : tak68_result_info;
            VAR mult_tabs       : tak68_mult_tabs;
            VAR lastsuccession  : tak68_lastsuccession;
            VAR context         : tak681_jseq_info_record;
            VAR reschedule_cnt  : tsp_int2);
 
VAR
      _i  : tsp00_Int2;
 
BEGIN
reschedule_cnt := succ(reschedule_cnt);
IF  acv.a_transinf.tri_trans.trRteCommPtr_gg00^.to_cancel
THEN
    a07_b_put_error (acv, e_cancelled, 0);
(*ENDIF*) 
IF  (reschedule_cnt = MAX_RESCHEDULE_CNT_AK68)
THEN
    BEGIN
&   ifdef trace
    t01sname(ak_join, 'reschedule !');
&   endif
    (* give CPU time to other tasks; reschedule *)
    reschedule_cnt := 0;
    vsleep(acv.a_transinf.tri_trans.trTaskId_gg00, 0);
    END;
(*ENDIF*) 
IF  (acv.a_return_segm^.sp1r_returncode = 0)
THEN
    BEGIN
    FOR _i := 1 TO context.jir_max_tables DO
        BEGIN
        IF  (acv.a_return_segm^.sp1r_returncode = 0) AND
            NOT (_i in context.jir_sequenced_tables)
        THEN
            BEGIN
            sequence_info.si_sequence[ context.jir_i ].s_tableno := _i;
            IF   ( context.jir_i < context.jir_max_tables )
            THEN
                BEGIN
                a680standard_cost (acv, dmli, table_stats, jtrans, jinfos, res_info,
                      mult_tabs, lastsuccession, context.jir_lowest_cost,
                      sequence_info, context.jir_i, NOT c_update_jtrans);
&               ifdef trace
                t01real(ak_join, 'comp costs  ', sequence_info.si_sum, 6);
&               endif
                IF  ( sequence_info.si_sum < context.jir_lowest_cost )
                THEN
                    BEGIN
&                   ifdef trace
                    t01int4(ak_join, 'better costs', context.jir_i);
                    t01real(ak_join, 'best costs  ', context.jir_lowest_cost, 6);
&                   endif
                    context.jir_sequenced_tables :=
                          context.jir_sequenced_tables + [ _i ];
                    context.jir_i := succ(context.jir_i);
                    ak681permut_sequence(acv, dmli, table_stats, jtrans,
                          sequence_info, jinfos, res_info, mult_tabs,
                          lastsuccession, context, reschedule_cnt);
                    context.jir_i := pred(context.jir_i);
                    context.jir_sequenced_tables :=
                          context.jir_sequenced_tables - [ _i ];
                    END;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                (* there is a complete sequence *)
                ak681sequence_eval(acv, dmli, table_stats, jtrans, sequence_info,
                      jinfos, res_info, mult_tabs, lastsuccession, context);
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  acv.a_transinf.tri_trans.trRteCommPtr_gg00^.to_cancel
        THEN
            a07_b_put_error (acv, e_cancelled, 0);
        (*ENDIF*) 
        END;
    (*ENDFOR*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak681sequence_eval(
            VAR acv             : tak_all_command_glob;
            VAR dmli            : tak_dml_info;
            VAR table_stats     : tak68_table_stats;
            VAR jtrans          : tak68_join_transitions;
            VAR sequence_info   : tak68_sequence_info;
            VAR jinfos          : tak68_joininfos;
            VAR res_info        : tak68_result_info;
            VAR mult_tabs       : tak68_mult_tabs;
            VAR lastsuccession  : tak68_lastsuccession;
            VAR context         : tak681_jseq_info_record);
 
VAR
      _xi : tsp00_Int2;
 
BEGIN
&ifdef TRACE
t01sname (ak_join, '-<STANDARD>-');
a683tr_newsucc (ak_join, sequence_info.si_sequence, 1, context.jir_max_tables, true);
&endif
_xi := 0;
WHILE (_xi <= context.jir_max_tables - 1) AND
      (sequence_info.si_sequence[ _xi + 1 ].s_tableno =
      lastsuccession.ls_sequence[ _xi + 1 ].s_tableno) DO
    _xi := succ (_xi);
(*ENDWHILE*) 
IF  (_xi < context.jir_max_tables)
THEN
    (* computed sequence is a new sequence or  *)
    (* last sequence was worse than one before *)
    BEGIN
    a680standard_cost (acv, dmli,
          table_stats, jtrans, jinfos, res_info, mult_tabs,
          lastsuccession, context.jir_lowest_cost, sequence_info,
          dmli.d_cntfromtab, NOT c_update_jtrans);
    IF  acv.a_intern_explain OR g01vtrace.vtrStrategy_gg00
    THEN
        ak681tr_report_succ (acv, sequence_info.si_sum,
              sequence_info.si_sequence, 1, context.jir_max_tables,
              context.jir_lowest_cost > sequence_info.si_sum);
    (*ENDIF*) 
    context.jir_comp_sequences := succ (context.jir_comp_sequences);
&   ifdef TRACE
    t01int4 (ak_join, 'check_cnt   ', context.jir_comp_sequences);
    t01int4 (ak_join, '============', context.jir_comp_sequences);
&   endif
    END;
(*ENDIF*) 
IF  sequence_info.si_sum < context.jir_lowest_cost
THEN
    BEGIN
    context.jir_lowest_cost       := sequence_info.si_sum;
    context.jir_lowest_succession := sequence_info.si_sequence;
    END;
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
*-PRETTY-*  statements    :       1911
*-PRETTY-*  lines of code :       5848        PRETTYX 3.10 
*-PRETTY-*  lines in file :       6579         1997-12-10 
.PA 
