.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 2000-2005 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.TT 1 $SQL$Project Distributed Database System$VAK502$
.tt 2 $$$
.TT 3 $ElkeZ$Executing_complex$1999-03-23$
***********************************************************
.nf
 
 .nf

    ========== licence begin  GPL
    Copyright (c) 2000-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
.fo

 
.fo
*****************************************************
Copyright (c) 2000-2005 SAP AG
SAP Database Technology
 
Release :      Date : 2000-09-11
*****************************************************
modname : VAK502
changed : 2000-09-11
module  : Executing_complex
 
Author  : ElkeZ
Created : 1985-10-16
*****************************************************
 
Purpose : Module where complex commands and correlations are handled.
 
Define  :
 
        PROCEDURE
              a502complex_execution (
                    VAR acv                 : tak_all_command_glob;
                    VAR dmli                : tak_dml_info;
                    VAR change_rec          : tak_changerecord;
                    VAR parsk               : tak_parskey;
                    output_during_execution : boolean );
 
        PROCEDURE
              a502correlation_execute (
                    VAR acv        : tak_all_command_glob;
                    VAR dmli       : tak_dml_info;
                    VAR change_rec : tak_changerecord;
                    VAR erec       : tak_exec_rec;
                    VAR parsk      : tak_parskey;
                    VAR old_cinfo  : tak_corr_infos;
                    inner_loop     : boolean);
 
        PROCEDURE
              a502destroy_file (
                    VAR acv          : tak_all_command_glob;
                    VAR tree         : tgg00_FileId);
 
        PROCEDURE
              a502empty_result (
                    VAR acv      : tak_all_command_glob;
                    VAR dmli     : tak_dml_info;
                    VAR res_tree : tgg00_FileId);
 
.CM *-END-* define --------------------------------------
***********************************************************
 
Use     :
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01sysnullkey        : tgg00_SysInfoKey;
              a01_il_b_identifier  : tsp00_KnlIdentifier;
              a01_zero_res_name    : tsp00_KnlIdentifier;
 
      ------------------------------ 
 
        FROM
              AK_universal_semantic_tools : VAK06;
 
        PROCEDURE
              a06subquery_del_result (
                    VAR acv           : tak_all_command_glob;
                    VAR dmli          : tak_dml_info;
                    VAR subquery_tree : tgg00_FileId;
                    prefix_len        : integer);
 
        PROCEDURE
              a06finish_curr_retpart (
                    VAR acv   : tak_all_command_glob;
                    part_kind : tsp1_part_kind;
                    arg_count : tsp00_Int2);
 
        PROCEDURE
              a06retpart_move (
                    VAR acv     : tak_all_command_glob;
                    moveobj_ptr : tsp00_MoveObjPtr;
                    move_len    : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              AK_Identifier_Handling : VAK061;
 
        PROCEDURE
              a061assign_colname (
                    value       : tsp00_C18;
                    VAR colname : tsp00_KnlIdentifier);
 
      ------------------------------ 
 
        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   : tgg00_BasisError;
                    err_code : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK071;
 
        FUNCTION
              a07_return_code (
                    b_err   : tgg00_BasisError;
                    sqlmode : tsp00_SqlMode) : tsp00_Int2;
 
      ------------------------------ 
 
        FROM
              Systeminfo_cache : VAK10;
 
        PROCEDURE
              a10get_sysinfo (
                    VAR acv      : tak_all_command_glob;
                    VAR syskey   : tgg00_SysInfoKey;
                    dstate       : tak_directory_state;
                    VAR syspoint : tak_sysbufferaddress;
                    VAR b_err    : tgg00_BasisError);
 
        PROCEDURE
              a10_nil_get_sysinfo (
                    VAR acv      : tak_all_command_glob;
                    VAR syskey   : tgg00_SysInfoKey;
                    dstate       : tak_directory_state;
                    syslen       : tsp00_Int2;
                    VAR syspoint : tak_sysbufferaddress;
                    VAR b_err    : tgg00_BasisError);
 
        PROCEDURE
              a10rel_sysinfo (syspointer : tak_sysbufferaddress);
 
        PROCEDURE
              a10new (
                    VAR acv  : tak_all_command_glob;
                    obj_size : tsp00_Int4;
                    VAR p    : tsp00_BufAddr);
 
        PROCEDURE
              a10dispose (
                    VAR acv : tak_all_command_glob;
                    VAR p : tsp00_BufAddr);
 
      ------------------------------ 
 
        FROM
              AK_Data_Type_Options : VAK14;
 
        PROCEDURE
              a14create_tab_as_select (
                    VAR acv     : tak_all_command_glob;
                    VAR tableid : tgg00_Surrogate;
                    parsk       : tak_parskey);
 
      ------------------------------ 
 
        FROM
              Executing_dispatcher : VAK501;
 
        PROCEDURE
              a501exec_with_change_rec (
                    VAR acv                 : tak_all_command_glob;
                    VAR dmli                : tak_dml_info;
                    VAR parsk               : tak_parskey;
                    VAR change_rec          : tak_changerecord;
                    output_during_execution : boolean);
 
      ------------------------------ 
 
        FROM
              Executing_loop_most : VAK505;
 
        PROCEDURE
              a505execute_link (
                    VAR acv   : tak_all_command_glob;
                    VAR parsk : tak_parskey;
                    pno       : integer);
 
        PROCEDURE
              a505fill_mess_buf (
                    VAR acv    : tak_all_command_glob;
                    VAR dmli   : tak_dml_info;
                    VAR erec   : tak_exec_rec;
                    VAR frec   : tak_fill_rec;
                    full_part2 : boolean);
 
        PROCEDURE
              a505get_change_rec (
                    VAR acv            : tak_all_command_glob;
                    VAR sparr          : tak_syspointerarr;
                    VAR change_rec     : tak_changerecord);
 
        PROCEDURE
              a505loop_most_execute (
                    VAR acv        : tak_all_command_glob;
                    VAR dmli       : tak_dml_info;
                    VAR change_rec : tak_changerecord;
                    VAR erec       : tak_exec_rec;
                    VAR parsk      : tak_parskey;
                    viewkeybuf     : tak_sysbufferaddress;
                    VAR series     : tak68_sequence;
                    VAR cinfo      : tak_corr_infos;
                    VAR old_cinfo  : tak_corr_infos;
                    inner_loop     : boolean);
 
        PROCEDURE
              a505next_command (
                    VAR acv       : tak_all_command_glob;
                    VAR sparr     : tak_syspointerarr;
                    VAR old_parsk : tak_parskey;
                    ex_plus       : integer);
 
        PROCEDURE
              a505strategy_search (
                    VAR acv          : tak_all_command_glob;
                    VAR dmli         : tak_dml_info;
                    mtype            : tgg00_MessType;
                    VAR searchname   : tsp00_KnlIdentifier;
                    VAR act_res_tree : tgg00_FileId;
                    VAR ssr_rec      : tak71_select_strat_rec;
                    VAR qbufp        : tak_sysbufferaddress;
                    VAR parsk        : tak_parskey;
                    not_last         : boolean);
 
      ------------------------------ 
 
        FROM
              Executing_values : VAK506;
 
        PROCEDURE
              a506fieldvalues (
                    VAR acv       : tak_all_command_glob;
                    VAR dmli      : tak_dml_info;
                    VAR frec      : tak_fill_rec;
                    viewkeybuf    : tak_sysbufferaddress;
                    VAR result    : tsp00_MoveObj;
                    resultBufSize : tsp00_Int4); (* PTS 1115085 *)
 
      ------------------------------ 
 
        FROM
              Executing_finish : VAK507;
 
        PROCEDURE
              a507select_part (
                    VAR acv        : tak_all_command_glob;
                    pos            : integer;
                    qbufp          : tak_sysbufferaddress;
                    VAR parsk      : tak_parskey;
                    VAR dmli       : tak_dml_info;
                    VAR ssr_rec    : tak71_select_strat_rec);
 
      ------------------------------ 
 
        FROM
              Long-Support-Getval: VAK508;
 
        PROCEDURE
              a508_lget_long_columns (
                    VAR acv             : tak_all_command_glob;
                    VAR change_rec      : tak_changerecord;
                    VAR lcol_lock       : boolean;
                    rec_cnt             : integer;
                    rec_len             : integer;
                    startpos            : integer);
 
        FUNCTION
              a508_lcol_found (
                    VAR acv        : tak_all_command_glob;
                    VAR change_rec : tak_changerecord) : boolean;
 
      ------------------------------ 
 
        FROM
              DML_Help_Procedures : VAK54;
 
        PROCEDURE
              a54_store_parsinfo (
                    VAR acv   : tak_all_command_glob;
                    VAR sparr : tak_syspointerarr);
 
        PROCEDURE
              a54_sel_store_parsinfo (
                    VAR acv        : tak_all_command_glob;
                    VAR sparr      : tak_syspointerarr;
                    VAR change_rec : tak_changerecord;
                    last_pars_part : boolean);
 
      ------------------------------ 
 
        FROM
              DML-Join-View-Procedures : VAK59;
 
        PROCEDURE
              a59qualified_dml (
                    VAR acv   : tak_all_command_glob;
                    VAR parsk : tak_parskey);
 
      ------------------------------ 
 
        FROM
              Select_Syntax : VAK60;
 
        PROCEDURE
              a60_change_results (
                    VAR acv        : tak_all_command_glob;
                    VAR data       : tsp00_MoveObj;
                    VAR change_rec : tak_changerecord;
                    startpos       : integer;
                    curr_resreclen : integer);
 
        PROCEDURE
              a60_put_result (
                    VAR acv    : tak_all_command_glob;
                    VAR mblock : tgg00_MessBlock;
                    spos       : integer);
 
        PROCEDURE
              a60rescount (
                    VAR acv  : tak_all_command_glob;
                    rescount : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              Execute_Select_Expression : VAK660;
 
        PROCEDURE
              a660_prefix_delete (
                    VAR acv       : tak_all_command_glob;
                    VAR parsk     : tak_parskey;
                    VAR del_cnt   : integer;
                    prefix_length : integer);
 
      ------------------------------ 
 
        FROM
              Resultname_handling : VAK663;
 
        PROCEDURE
              a663create_result_file (
                    VAR acv      : tak_all_command_glob;
                    m_type       : tgg00_MessType;
                    VAR res_tree : tgg00_FileId);
 
        PROCEDURE
              a663_get_result_info (
                    VAR acv          : tak_all_command_glob;
                    VAR resname      : tsp00_KnlIdentifier;
                    VAR modul_name   : tsp00_KnlIdentifier;
                    VAR resname_addr : tak_sysbufferaddress;
                    make_new_res     : boolean;
                    ftemptype        : tgg00_TfnTemp;
                    dstate           : tak_directory_state;
                    VAR f_ok         : boolean);
 
      ------------------------------ 
 
        FROM
              Join_Select_execution : VAK682;
 
        PROCEDURE
              a682copy_joinparsinfo (
                    VAR acv   : tak_all_command_glob;
                    VAR parsk : tak_parskey);
 
      ------------------------------ 
 
        FROM
              Deal-With-User-Commands : VAK92;
 
        PROCEDURE
              a92next_pcount (
                    VAR acv   : tak_all_command_glob;
                    VAR parsk : tak_parskey);
 
        PROCEDURE
              a92_add_pcount (
                    VAR acv  : tak_all_command_glob;
                    pcount   : tsp00_C3;
                    parskind : tgg00_MessType);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01niltree_id : tgg00_FileId;
 
        PROCEDURE
              b01destroy_file (
                    VAR t       : tgg00_TransContext;
                    VAR current : tgg00_FileId);
 
        PROCEDURE
              b01prefix_destroy_files (
                    VAR t         : tgg00_TransContext;
                    VAR prefix_fn : tgg00_Filename;
                    prefix_len    : integer);
 
        PROCEDURE
              b01empty_file (
                    VAR t       : tgg00_TransContext;
                    VAR current : tgg00_FileId);
 
        PROCEDURE
              b01tcreate_file (
                    VAR t       : tgg00_TransContext;
                    VAR current : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_2 : VBD07;
 
        PROCEDURE
              b07cnext_record (
                    VAR t          : tgg00_TransContext;
                    VAR curr       : tgg00_FileId;
                    VAR rk         : tgg00_Lkey;
                    VAR set_result : tgg00_BdSetResultRecord;
                    VAR tree_pos   : tgg00_FilePos;
                    VAR b          : tsp00_Buf);
 
      ------------------------------ 
 
        FROM
              Select_Help_Procedures : VGG04;
 
        PROCEDURE
              g04build_temp_tree_id (
                    VAR curr : tgg00_FileId;
                    VAR t : tgg00_TransContext);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalFill (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    obj_upb     : tsp00_Int4;
                    obj         : tsp00_MoveObjPtr;
                    obj_pos     : tsp00_Int4;
                    length      : tsp00_Int4;
                    fillchar    : char;
                    VAR e       : tgg00_BasisError);
 
        PROCEDURE
              SAPDB_PascalUnicodeFill (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    obj_upb     : tsp00_Int4;
                    obj         : tsp00_MoveObjPtr;
                    obj_pos     : tsp00_Int4;
                    length      : tsp00_Int4;
                    fillchar    : tsp00_C2;
                    VAR e       : tgg00_BasisError);
 
        PROCEDURE
              SAPDB_PascalForcedUnicodeFill (
                    obj_upb     : tsp00_Int4;
                    obj         : tsp00_MoveObjPtr;
                    obj_pos     : tsp00_Int4;
                    length      : tsp00_Int4;
                    fillchar    : tsp00_C2 );
 
        PROCEDURE
              SAPDB_PascalMove (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    source_upb  : tsp00_Int4;
                    dest_upb    : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    src_pos     : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    dest_pos    : tsp00_Int4;
                    length      : tsp00_Int4;
                    VAR e       : tgg00_BasisError);
 
        PROCEDURE
              SAPDB_PascalOverlappingMove (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    source_upb  : tsp00_Int4;
                    dest_upb    : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    src_pos     : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    dest_pos    : tsp00_Int4;
                    length      : tsp00_Int4;
                    VAR e       : tgg00_BasisError);
 
        PROCEDURE
              SAPDB_PascalForcedFill (
                    size        : tsp00_Int4;
                    m           : tsp00_MoveObjPtr;
                    pos         : tsp00_Int4;
                    len         : tsp00_Int4;
                    fillchar    : char);
 
        PROCEDURE
              SAPDB_PascalForcedMove (
                    source_upb  : tsp00_Int4;
                    destin_upb  : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    source_pos  : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    destin_pos  : tsp00_Int4;
                    length      : tsp00_Int4);
 
        PROCEDURE
              SAPDB_PascalForcedOverlappingMove (
                    source_upb  : tsp00_Int4;
                    destin_upb  : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    source_pos  : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    destin_pos  : tsp00_Int4;
                    length      : tsp00_Int4);
 
        PROCEDURE
              g10mv (
                    mod_id      : tsp00_C6;
                    mod_num     : tsp00_Int4;
                    source_upb  : tsp00_Int4;
                    dest_upb    : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    src_pos     : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    dest_pos    : tsp00_Int4;
                    length      : tsp00_Int4;
                    VAR e       : tgg00_BasisError);
 
        PROCEDURE
              s10mv (
                    source_upb  : tsp00_Int4;
                    destin_upb  : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    source_pos  : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    destin_pos  : tsp00_Int4;
                    length      : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              GG_allocator_interface : VGG941;
 
        FUNCTION
              gg941Allocate(VAR TransContext : tgg00_TransContext;
                    wantedBytes : integer) : tsp00_Addr;
 
      ------------------------------ 
 
        FROM
              RTE-Extension-30 : VSP30;
 
        PROCEDURE
              s30cmp1 (
                    VAR buf1     : tsp00_Buf;
                    fieldpos1    : tsp00_Int4;
                    fieldlength1 : tsp00_Int4;
                    VAR buf2     : tsp00_Buf;
                    fieldpos2    : tsp00_Int4;
                    fieldlength2 : tsp00_Int4;
                    VAR l_result : tsp00_LcompResult);
 
        PROCEDURE
              s30cmp2 (
                    VAR buf1     : tsp00_MoveObj;
                    fieldpos1    : tsp00_Int4;
                    fieldlength1 : tsp00_Int4;
                    VAR buf2     : tsp00_Buf;
                    fieldpos2    : tsp00_Int4;
                    fieldlength2 : tsp00_Int4;
                    VAR l_result : tsp00_LcompResult);
 
      ------------------------------ 
 
        FROM
              GET-Conversions : VSP40;
 
        PROCEDURE
              s40g4int (
                    VAR buf  : tsp00_ResNum;
                    pos      : tsp00_Int4;
                    VAR dest : tsp00_Int4;
                    VAR res  : tsp00_NumError);
 
      ------------------------------ 
 
        FROM
              PUT-Conversions : VSP41;
 
        PROCEDURE
              s41p4int (
                    VAR buf : tsp00_ResNum;
                    pos     : tsp00_Int4;
                    source  : tsp00_Int4;
                    VAR res : tsp00_NumError);
&       IFDEF TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01int4 (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01buf  (
                    level     : tgg00_Debug;
                    VAR buf   : tak_systembuffer;
                    pos_start : integer;
                    pos_end   : integer);
 
        PROCEDURE
              t01buf1 (
                    level     : tgg00_Debug;
                    VAR buf   : tsp00_Buf;
                    pos_start : integer;
                    pos_end   : integer);
 
        PROCEDURE
              t01name (
                    level : tgg00_Debug;
                    nam : tsp00_Name);
 
        PROCEDURE
              t01lidentifier (
                    level      : tgg00_Debug;
                    identifier : tsp00_KnlIdentifier);
 
        PROCEDURE
              t01treeid (
                    level      : tgg00_Debug;
                    nam        : tsp00_Sname;
                    VAR treeid : tgg00_FileId);
&       ENDIF
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              a10new;
 
              tak_sysbufferaddress tsp00_BufAddr;
 
        PROCEDURE
              a10dispose;
 
              tak_sysbufferaddress tsp00_BufAddr;
 
        PROCEDURE
              b07cnext_record;
 
              tsp00_MoveObj tsp00_Buf
 
        PROCEDURE
              s30cmp1;
 
              tsp00_MoveObj tsp00_Buf
 
        PROCEDURE
              s30cmp2;
 
              tsp00_MoveObj tsp00_Buf
 
        PROCEDURE
              s40g4int;
 
              tsp00_MoveObj tsp00_ResNum
 
        PROCEDURE
              s41p4int;
 
              tsp00_MoveObj tsp00_ResNum
 
        PROCEDURE
              t01buf;
 
              tsp00_Buf tak_systembuffer
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : ElkeZ
.sp
.cp 3
Created : 1985-04-15
.sp
.cp 3
.sp
.cp 3
Release :      Date : 1999-03-23
.sp
***********************************************************
 
Description:
 
A50_CORRELATION_EXECUTE
------------------------------
 
Correlated subqueries are processed in the following manner:
 
  A50DO_EXECUTE
     A53_MOST_EXECUTE
          (the highest SELECT is processed)
     LOOP_MOST_EXECUTE (inner_loop = false)
        A53_MOST_EXECUTE [ .., inner_loop)
               (mess_buf.mess_type = m_fetch is found)
           A50_CORRELATION_EXECUTE ( ....., inner_loop)
                per SELECT result :
                    LOOP_MOST_EXECUTE (inner_loop = true)  *
                          (the subqueries are generated)
                    LOOP_MOST_EXECUTE (inner_loop = true)
                          (checks the one result record against
                           the result of the subqueries)
                if necessary:
                LOOP_MOST_EXECUTE (inner_loop = true)
                          (set functions, etc., are executed)
 
The LOOP_MOST_EXECUTE with the flag * can also have the following
layout:
 
 LOOP_MOST_EXECUTE (inner_loop = true)
    A53_MOST_EXECUTE [ .., inner_loop)
           (mess_buf.mess_type = m_fetch is found)
       A50_CORRELATION_EXECUTE ( ....., inner_loop)
            per SELECT result :
                LOOP_MOST_EXECUTE (inner_loop = true)  *
                      (the subqueries are generated, 1st loop)
                LOOP_MOST_EXECUTE (inner_loop = true)
                      (checks the one result record against
                       the result of the subqueries, 2nd loop)
            if necessary:
            LOOP_MOST_EXECUTE (inner_loop = true)
                  (set functions, etc. are executed, 3rd loop)
 
A result of such a SELECT has the following layout:
 
  2  2    keylen     lcomp_len
 |__|__|___________|____________|________|_______|
  |  |     |             |           |       |
  |  |  as many of      all        output   qual
  |  |  the corr    corr columns  columns  columns
  |  |  columns as
  |  |  possible
  |  |
  |  keylen
  |
one_rec_len
 
Corr columns are those fields that are referenced in other SELECTs
(not the SELECT where this
table stands in the FROM part). They are
divided into those columns whose table is located in the current SELECT
in the FROM part and those that come from upper SELECTs and
must be passed through the current SELECT.
 
If possible, these corr columns are again stored in the key in their
entirety so that the records can be sorted according to them.  This is
advantageous because all the underlying subqueries then do not have to be
executed for each record but, instead, only if the corr-column values
change.
 
Output_columns are the columns that are found in the select list during
the current SELECT.  Qual columns are the columns that are addressed in
the qualification (and whose table is located in the FROM part of
the current SELECT).  These columns are already contained in the results
of the first SELECT although only the corr columns are actually needed to be
able to execute the subqueries.  However, since another access to the base
table(s) should not occur when a result is being checked against its
subqueries (this would require another join), the columns necessary for
this check must, of course, have been assembled beforehand.
 
The file name and the tree description of the last SELECT that was
processed (corrfilename, corr_current) is identified from the message
buffer and the name of the file in which the result of this subquery
step is to be saved is stored in help_res_fn.
 
The entries stored in a somewhat peculiar fashion in the FETCH message
buffer designate the following:
 
one_rec_len Length of a record to be fetched
 
lcomp_len Length of the corr columns
 
startkeyfields Position in the mess-buffer.part2 to which the key
of the result record
must be written when this one record is checked against
its subqueries
 
one_key_len Length of this key
 
last_sel_buf_no Entry indicating the number of parse-information records
that belong to the 3rd loop of this A50_CORRELATION_EXECUTE iteration
 
next_sel_buf_no Entry indicating the number of parse infos that follow
the 1st loop.  In simple cases, last_sel_buf_no = next_sel_buf_no.
In complicated cases (compare CORR_SUB in VAK66) it has the following
layout:
 
  LOOP_MOST_EXECUTE
     MOST_EXECUTE
        A50_CORRELATION_EXECUTE
           LOOP_MOST_EXECUTE (1st loop)
              MOST_EXECUTE
                 A50_CORRELATION_EXECUTE
              MOST_EXECUTE
                 A50_CORRELATION_EXECUTE
              MOST_EXECUTE
                 A50_CORRELATION_EXECUTE
          (*======*)
           LOOP_MOST_EXECUTE (2nd loop)
 
This case occurs if more than one subquery is located on the same level.
The outermost A50_CORRELATION also gives the number that is reached for
(*======*) to the 1st loop as the maximum number of the parse infos
(erec.maxbufs).  Only the final inner A50_CORRELATION_EXECUTE has
last_sel_buf_no = next_sel_buf_no.  The other inner
A50_CORRELATION_EXECUTEs must therefore leave next_sel_buf_no parse infos
for their own 2nd and 3rd loops and for subsequent A50_CORRELATION_EXECUTEs.
 
 
During the processing of a command with correlated subqueries, some
SELECTs must be executed quite often.  Since it must be prevented that
the strategy be reidentifed from the parse infos and from the data passed
during execution for each execution, this strategy must be established
once at the beginning and then be used over and over again.  For this
purpose, PARSINFO_WITH_VALUES is called in the outermost loop
of the SELECT for all parse-information records that still exist within
the command.  The
data are fetched from the SQL_PACKET, strategies are identifed and
the resulting information is again stored as parse information.  In order
to differentiate between the original parse-information records that must be
retained unchanged (for the next execution of the same command) and the
new parse infos, a different parse id is selected for the new parse infos
from that of the original (starting with P_NO = 0).  This
parse id is located in parsk.
 
All_rescnt specifes the number of records already contained in the final
result;  root = 0 indicates that the result file must first be generated.
 
Since, after PARSINFO_WITH_VALUES, the last parse info is located in
sparr[ 1 ] (the outermost that contains the result-set name),
this name can be processed.
 
Dummybuf is used in
LOOP_MOST_EXECUTE/A53_MOST_EXECUTE as substitute for
the viewkeybuf (buffer that contains the primary keys of the
relevant base records for FOR UPDATE applied to join views).
 
For the three loops within A50_CORRELATION_EXECUTE, the start p_nos and
stop p_nos are identified ('rest' stands for the 3rd loop; plus is always
too small by 1 since in LOOP_MOST_EXECUTE, 1 must first of all be counted
to plus).
 
For each result record that can be fetched, the 2 loops are executed.
The 3rd loop is required for set functions, i.e. it must not be
started until all records have been processed.
 
The next result record is identified with NEXT_CORR_RECORD and, at the
same time, it is determined whether the corr columns contained in it
have the same values as in the previous record.  If not, the subquery
(1st loop) must be executed (subquery_needed).
 
Next_record_possible only indicates whether, within NEXT_CORR_RECORD,
e_ok has already been sent or b_buffer_limit is still being sent
for b07CNEXT_RECORD.  It is simply passed on at the time of the next call.
 
If a subquery is required (except for the first time), the old subquery
must first be destroyed (if applicable, several subqueries on the
same level).
 
The entries for the first loop (first.. ] are used and it is determined
that the corr_columns contained in the co_corr_buf are to be used (the
values are to be transferred into the message buffer).
The first loop
(formation of all subqueries on the underlying levels) is activated.
 
It would then be convenient to know whether or not the subquery conditions
can be fulfilled at all (e.g. EXISTS applied to an empty subquery result).
This is currently not possible, for which reason normal_query_useful
is always true.
 
A second loop is prepared (it is not a loop, but simply a quasi SELECT
DIRECT via a set-select mechanism) by using the second... values.
Erec contains the name and root description of the (intermediate)
result.  This file must continue to be filled (root <> 0).  The entries
are transferred back to new_erec (used in the loop).  In addition, it
is determined that the key-field values of the record and not its corr
columns are to be transferred to the message buffer (quasi SELECT DIRECT).
 
After the loop, if only one result is expected (SELECT..INTO), the result
found is transferred to the SQL_PACKET (the input data from there
have already all been processed via PARSINFO_WITH_VALUES).  If there is yet
another result, it is usually an error except when DISTINCT was requested
and the two results (the one that was already found and is contained in
the SQL_PACKET and the one that was newly identified that is in the
mess_buffer in part2) are the same.
 
If several results are expected, the number of results and, again, the
file description are stored in erec (all_rescnt always indicates the total
number of records found and stored in the file, not just those of the
loop that has just been ended).
 
If no record was found in the file from which it was to be fetched
(none_found), the second loop was not executed and help_res_fn was not
generated.  This must now be done since this file is either the end
result of this A50_CORRELATION_EXECUTE call or the input file for
the third loop.
 
 
If a third loop is required (restlast > secondlast), the loop is activated
after the name of the input file has been saved, the root description of
the file to be generated has been preset (unnamed_tree) and the number of
results has been set back to 0.  After the loop, the input file for this
third loop is deleted.
 
If no result file was generated up to this time (can occur even if
none_found is false if normal_query_useful is no longer always true),
this is now done.
 
In the outermost A50_CORRELATION_EXECUTE, A50_SELECT_PART is called
in order to complete the system information belonging to the SELECT
(see that section).
 
Both the subquery results and the file with the records to be fetched
must be deleted.
 
If the outermost A50_CORRELATION_EXECUTE is again reached, the last
parse-information record of the command is fetched (not necessarily
located in sparr, since the last record might not have led to
normal_query_useful).  It contains information on how the result records
are to be converted.  This information is required for
SELECT..INTO.  Either the result in A50_CORRELATION_EXECUTE is transferred
directly to the SQL_PACKET or it is transferred in VAK66 after the
long infos have been formed and transferred.
 
Via A66_PREFIX_DELETE, the parse infos generated via PARSINFO_WITH_VALUES
using a new parse id are deleted.
 
For an inner loop, it must be ensured that the plus value has the
maximum value so that loops that are further out do not start
from a plus value that is too small.
 
PARSINFO_WITH_VALUES
------------------------------
 
The parameter atch is not there to function as an input and/or output
parameter.  Such a (relatively large) record is needed within
PARSINFO_WITH_VALUES.  The atch contained in DMLI is passed so that it
is not necessary to generate a local variable.
 
The last parse-information records to be fetched and processed are
released in order to avoid causing the cache to overflow.  The next block of
several infos is fetched from the parse-information records with NEXT_COMMAND.
 
Currently, only two types of parse-information records can be found :
SELECTs and additional FETCHes.
 
FETCHes have no input data.  The parsed message buffer must only be
transferred to the current message buffer with A53_FILL_MESS_BUF.  In the
case of SELECTs, the input data are still transferred to the message
buffer via A53_FIELDVALUES and the rest of the data that are already known
from parsing are copied (e.g. strategy information).
 
If a SELECT has been found, the best strategy is identified from the
strategy information determined during parsing and the input
data that are now known.  This occurs in the case of joins via
A68_STRATEGIES and, in the case of single-table selects, via
A53_STRATEGY_SEARCH.
 
EXECUTE_PARSINFO is not used to execute a command; instead, an
executable parse-information record is stored using the new parse id.
Atch is also required for this operation since at least the last
parse-information record must have correct information
on conversion at its disposal.
 
NEXT_CORR_RECORD
 
In this procedure, the next record to be fetched is identified for
A50_CORRELATION_EXECUTE.
 
At first, cinfo.act_pos is set to 1 (a value that can no longer be
achieved once at least one record has been fetched).  Beginning with
the first record, a maximum of 200 result records are fetched to
co_corr_buf.  The first two bytes of co_corr_buf contain the length of the part
written; the first record begins at act_pos = 3.  Next_record_possible
retains the error, i.e. is false if no additional call of
b07CNEXT_RECORD would make sense because all records have already been
fetched from the file.  The variable is again specified the next time
NEXT_CORR_RECORD is called.
 
If the last record from co_corr_buf has already been processed (act_pos
points to it), the next co_corr_buf must be filled.  For this purpose, the
key of the last result record in the old co_corr_buf is used as a start
key.  In order to be able to discern whether the subqueries must be
newly built (the corr_columns of the last record to be processed differ
from those of the first to come next), these corr columns are saved in hbuf.
 
b07CNEXT_RECORD is called, next_record_possible is determined (see above)
and the corr columns of the two records are compared.
 
If not all records have been read from co_corr_buf, only act_pos is set
forward and the two records compared in order to be able to assign
subquery_needed.
.CM *-END-* description ---------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
CONST
      c_first            = true (* ak502parsinfo_with_values *);
      c_full_part2       = true (* a505fill_mess_buf *);
      c_inner_loop       = true (* a505loop_most_execute *);
      c_not_last         = true (* a505strategy_search *);
      c_make_new_res     = true (* a663_get_result_info *);
 
TYPE
      found_type = (select_found, fetch_found, nothing_found);
 
 
(*------------------------------*) 
 
PROCEDURE
      a502complex_execution (
            VAR acv                 : tak_all_command_glob;
            VAR dmli                : tak_dml_info;
            VAR change_rec          : tak_changerecord;
            VAR parsk               : tak_parskey;
            output_during_execution : boolean );
 
VAR
      exit_loop         : boolean;
      is_tab_as_select  : boolean;
      finished          : boolean;
      m_recursive_state : tak_recursive_state;
      i                 : integer;
      j                 : integer;
      complex_cnt       : integer;
      mucnt             : tsp00_Int4;
      b_err             : tgg00_BasisError;
      aux_return        : tsp00_Int2;
      aux_errorpos      : tsp00_Int4;
      m_command_kind    : tak_commandkind;
      mparsk            : tak_parskey;
      tableid           : tgg00_Surrogate;
      ke                : tgg00_SysInfoKey;
      curr              : tgg00_FileId;
      complexbuf        : tak_sysbufferaddress;
      mcomplexbuf       : tak_sysbufferaddress;
 
BEGIN
WITH acv DO
    BEGIN
    m_command_kind:= a_command_kind;
    mcomplexbuf   := a_ptr2;
    mucnt         := a_union_cnt;
    a_union_cnt   := 0;
    m_recursive_state := rs_no_recursive_select;
    ke            := a01sysnullkey;
    WITH ke DO
        BEGIN
        sauthid[ 1 ] := cak_tempinfo_byte;
        s10mv (sizeof(parsk), sizeof(sauthid), @parsk, 1,
              @sauthid, 2, mxak_parskey);
        sentrytyp := cak_ecomplex;
        END;
    (*ENDWITH*) 
    a10get_sysinfo ( acv, ke, d_fix, a_ptr2, b_err);
    IF  b_err <> e_ok
    THEN
        IF  b_err = e_sysinfo_not_found
        THEN
            a07_b_put_error (acv, e_old_fileversion, 1)
        ELSE
            a07_b_put_error (acv, b_err, 1)
        (*ENDIF*) 
    ELSE
        BEGIN
        tableid := a_complex_tree.fileTabId_gg00;
        a_complex_tree := b01niltree_id;
        complex_cnt := a_ptr2^.scomplexrec.compcnt;
&       IFDEF TRACE
        t01buf (ak_sem, a_ptr2^, 1, a_ptr2^.b_sl);
        t01int4 (ak_sem, 'max_intern  ', a_max_intern_select);
        t01int4 (ak_sem, 'a_send_mess ', ord (a_send_messbuf));
&       ENDIF
        acv.a_max_intern_select :=
              a_ptr2^.scomplexrec.compmax_sel_cnt;
&       IFDEF TRACE
        t01int4 (ak_sem, 'max_intern  ', a_max_intern_select);
        t01int4 (ak_sem, 'complex_cnt ', complex_cnt);
&       ENDIF
        is_tab_as_select       := false;
        i                      := 1;
        exit_loop              := false;
        WHILE (i <= complex_cnt) AND NOT exit_loop DO
            BEGIN
            IF  ((a_returncode = 0) OR
                (ci_unlock in a_ptr2^.scomplexrec.comparr[ i ].centryinfo))
            THEN
                IF  a_ptr2^.scomplexrec.comparr[ i ].cparsk.p_kind <> m_nil
                THEN
                    BEGIN
                    WITH a_ptr2^.scomplexrec, comparr[ i ] DO
                        BEGIN
&                       IFDEF TRACE
                        IF  ci_lastpars in centryinfo
                        THEN
                            t01int4 (ak_sem, 'clastpars   ', 1);
&                       ENDIF
                        (*ENDIF*) 
                        mparsk := cparsk;
                        (* PTS 1111510 E.Z. *)
                        a_curr_ex_parskey  := mparsk;
                        IF  m_recursive_state = rs_recursive_select
                        THEN
                            BEGIN
                            a_recursive_state := rs_last_select;
                            m_recursive_state := rs_last_select;
                            END;
                        (*ENDIF*) 
                        IF  ci_lastpars in centryinfo
                        THEN
                            BEGIN
                            a_union_cnt    := mucnt;
                            a_command_kind := last_command;
                            END
                        ELSE
                            BEGIN
                            a_command_kind := complex_view_command;
                            IF  ci_recursive in centryinfo
                            THEN
                                BEGIN
                                a_recursive_no   := 1;
                                a_recursive_state := rs_recursive_select;
                                m_recursive_state := rs_recursive_select;
                                END;
                            (*ENDIF*) 
                            IF  i < compcnt
                            THEN
                                IF  ci_unlock in comparr[ i+1 ].centryinfo
                                THEN
                                    BEGIN
                                    a_union_cnt    := mucnt;
                                    a_command_kind := last_command
                                    END
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        acv.a_qualified_jv_upd := cqual_jv_upd;
&                       IFDEF TRACE
                        t01int4 (ak_sem, 'command_kind', ord(a_command_kind));
&                       ENDIF
                        dmli.d_execute_unlock := (ci_unlock in centryinfo);
                        END;
                    (*ENDWITH*) 
                    IF  (a_ptr2^.scomplexrec.
                        comparr[ i ].cparsk.p_kind = m_key)
                        AND
                        (a_ptr2^.scomplexrec.
                        comparr[ i ].cqual_jv_upd <> no_jv_upd)
                    THEN
                        BEGIN
                        a_ex_kind := only_executing;
                        a59qualified_dml (acv, mparsk)
                        END
                    ELSE
                        BEGIN
                        IF  ci_unlock in a_ptr2^.scomplexrec.comparr[ i ].centryinfo
                        THEN
                            BEGIN
                            aux_return   := a_returncode;
                            aux_errorpos := a_errorpos;
                            a_returncode   := 0
                            END;
                        (*ENDIF*) 
                        IF  ((ci_unlock in a_ptr2^.scomplexrec.
                            comparr[ i ].centryinfo) AND
                            (NOT output_during_execution OR
                            (acv.a_qualified_jv_upd <> no_jv_upd)))
                        THEN
                            ak502store_during_unlock (acv, dmli,
                                  mparsk, change_rec,
                                  output_during_execution)
                        ELSE
                            IF  mparsk.p_kind = m_create_table
                            THEN
                                BEGIN
                                tableid := a_ptr2^.scomplexrec.compcreateaseltree.fileTabId_gg00;
                                a_complex_tree.fileTabId_gg00 := tableid;
                                ak502create_tab_as_select (acv,
                                      tableid, mparsk);
                                is_tab_as_select := true;
                                exit_loop        :=
                                      a_returncode <> 0
                                END
                            ELSE
                                BEGIN
&                               ifdef TRACE
                                t01int4 (ak_sem, 'rec_state   ', ord(a_recursive_state));
                                t01int4 (ak_sem, 'recursive_no', a_recursive_no);
&                               endif
                                IF  m_recursive_state = rs_recursive_select
                                THEN
                                    REPEAT
                                        finished := false;
                                        a_recursive_no :=
                                              succ(a_recursive_no);
                                        a501exec_with_change_rec (acv, dmli,
                                              mparsk, change_rec,
                                              output_during_execution);
                                        IF  a_returncode = 0
                                        THEN
                                            IF  a_mblock.mb_qual^.mr_resnum[ 2 ] = cgg04_zero_exponent
                                            THEN
                                                finished := true;
                                            (*ENDIF*) 
                                        (*ENDIF*) 
                                    UNTIL
                                        (a_returncode <> 0) OR
                                        finished
                                    (*ENDREPEAT*) 
                                ELSE
                                    a501exec_with_change_rec (acv, dmli,
                                          mparsk, change_rec,
                                          output_during_execution);
                                (*ENDIF*) 
                                FOR j := 1 TO dmli.d_sparr.pcount DO
                                    a10rel_sysinfo (dmli.d_sparr.px[ j ]);
                                (*ENDFOR*) 
                                (* PTS 1000816 E.Z. *)
                                dmli.d_sparr.pcount := 0;
                                IF  is_tab_as_select AND
                                    (a_returncode <> 0)
                                THEN
                                    IF  a_returncode =
                                        a07_return_code (e_row_not_found,
                                        a_sqlmode)
                                    THEN
                                        a_returncode := 0
                                    ELSE
                                        parsk :=
                                              a_ptr2^.scomplexrec.comparr[1].cparsk
                                    (*ENDIF*) 
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        IF  NOT exit_loop
                        THEN
                            IF  ci_unlock in a_ptr2^.scomplexrec.comparr[ i ].centryinfo
                            THEN
                                IF  aux_return <> 0
                                THEN
                                    BEGIN
                                    a_returncode := aux_return;
                                    a_errorpos   := aux_errorpos;
                                    END;
                                (*ENDIF*) 
                            (*ENDIF*) 
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (* PTS 1121418 E.Z. *)
                (*ENDIF*) 
            (*ENDIF*) 
            IF  (m_recursive_state = rs_last_select)
                OR
                (
                (m_recursive_state = rs_recursive_select) AND
                (a_returncode <> 0) AND (a_returncode <> 100)
                )
            THEN
                BEGIN
                m_recursive_state := rs_no_recursive_select;
                a_recursive_state := rs_no_recursive_select;
                g04build_temp_tree_id (curr, a_transinf.tri_trans);
                WITH curr DO
                    fileTfnTemp_gg00 := ttfnRecursive_egg00;
                (*ENDWITH*) 
                b01prefix_destroy_files (a_transinf.tri_trans,
                      curr.fileName_gg00, TEMP_PREFIX_MXGG00 + 1);
                END;
            (*ENDIF*) 
            i := succ(i)
            END;
        (*ENDWHILE*) 
        IF  a_returncode = 0
        THEN
            a10rel_sysinfo (a_ptr2)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    a_ptr2         := mcomplexbuf;
    a_command_kind := m_command_kind;
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a502correlation_execute (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR change_rec : tak_changerecord;
            VAR erec       : tak_exec_rec;
            VAR parsk      : tak_parskey;
            VAR old_cinfo  : tak_corr_infos;
            inner_loop     : boolean);
 
VAR
      e                    : tgg00_BasisError;
      first                : boolean;
      firstsingle          : boolean;
      next_record_possible : boolean;
      none_found           : boolean;
      normal_query_useful  : boolean;
      single               : boolean;
      subquery_needed      : boolean;
      ex_link              : boolean;
      empty_into_file      : boolean;
      is_not_from_select   : boolean;
      f_ok                 : boolean;
      lcol_found           : boolean;
      lcol_lock            : boolean;
      cinfo                : tak_corr_infos;
      help_cinfo           : tak_corr_infos;
      new_erec             : tak_exec_rec;
      ft                   : found_type;
      firstlast            : integer;
      firstplus            : integer;
      i                    : integer;
      last_sel_buf_no      : integer;
      linkplus             : integer;
      maxresults           : integer;
      next_sel_buf_no      : integer;
      restlast             : integer;
      restplus             : integer;
      resultindexno        : integer;
      secondlast           : integer;
      secondplus           : integer;
      stored_len           : integer;
      resreclen            : integer;
      resinfolen           : integer;
      munion_cnt           : tsp00_Int4;
      lc_result            : tsp00_LcompResult;
      resnam               : tsp00_KnlIdentifier;
      res                  : tsp00_NumError;
      new_parsk            : tak_parskey;
      aux_pars_last_key    : tak_parskey;
      tree_pos             : tgg00_FilePos;
      series               : tak68_sequence;
      old_res_tree         : tgg00_FileId;
      second_loop_res_tree : tgg00_FileId;
      subquery_tree        : tgg00_FileId;
      dummybuf             : tak_sysbufferaddress;
      p                    : tsp00_Addr;
      aux_tfn              : tgg00_TfnTemp;
      rep_res              : boolean;
      ssr_rec              : tak71_select_strat_rec;
      first_selinto_result : tsp00_Buf;
 
BEGIN
IF  NOT inner_loop
THEN
    old_cinfo.co_corr_buf := NIL;
(* allocate storage in cache, where the correlation values *)
(* are to be stored in (save space of 1 buffer)            *)
(*ENDIF*) 
a10new (acv, sizeof (cinfo.co_corr_buf^), cinfo.co_corr_buf);
IF  cinfo.co_corr_buf = NIL
THEN
    a07_b_put_error (acv, e_no_more_memory, 1)
ELSE
    WITH acv, dmli DO
        BEGIN
        f_ok := true;
        WITH a_mblock, mb_qual^, cinfo DO
            BEGIN
            ex_link := false;
            g10mv ('VAK502',   1,    
                  mb_data_size, sizeof(second_loop_res_tree),
                  @mb_data^.mbp_buf, cgg_rec_key_offset+1, @second_loop_res_tree, 1,
                  sizeof(second_loop_res_tree),
                  a_returncode);
            co_corr_current := a_mblock.mb_qual^.mr_restree;
            (* mb_qual^ is as it was in that part although *)
            (* a505fill_mess_buf was called with mtype = m_fetch *)
            co_one_rec_len     := mcol_pos;
            co_lcomp_len       := mcol_cnt;
            co_startkeyfields  := mqual_pos;
            co_one_key_len     := mqual_cnt;
            co_sel_keypos      := mview_pos;
            co_upd_keylen      := mview_cnt; (* = one_key_len during SELECT *)
            co_minkeylen       := mupd_cnt;
            co_varkeyvalstack  := mupd_pos;
            last_sel_buf_no    := mmult_pos;
            maxresults         := mmult_cnt;
            resreclen          := mstrat_pos;
            resinfolen         := mstrat_cnt;
&           ifdef TRACE
            t01int4 (ak_sem, 'resinfolen  ', resinfolen);
            t01int4 (ak_sem, 'resreclen   ', resreclen );
&           endif
            next_sel_buf_no    := dmli.d_sparr.px[ 1 ]^.sparsinfo.p_p_no;
            co_act_pos         := 0;
            co_all_recs_len    := 0;
            tree_pos.tpsPno_gg00     := NIL_PAGE_NO_GG00;
            co_use_cinfo       := true;
            END;
        (*ENDWITH*) 
        single          := false;
        firstsingle     := true;
        empty_into_file := false;
        none_found      := true;
        new_parsk       := parsk;
        linkplus := new_parsk.p_no - next_sel_buf_no + 1;
        IF  NOT inner_loop
        THEN
            (* PTS 1122398 E.Z. *)
            (*                 IF  a_data_length > 0  THEN *)
            BEGIN
            (* parameter are used *)
            dmli.d_corr := correlation;
            ft          := select_found;
            aux_pars_last_key := a_pars_last_key;
            WITH a_pars_last_key DO
                BEGIN
                a92next_pcount (acv, a_pars_last_key);
                p_id   := chr(0);
                p_kind := m_nil;
                p_no   := 0
                END;
            (*ENDWITH*) 
            IF  parsk.p_count = a_pars_last_key.p_count
            THEN
                BEGIN
                a92_add_pcount (acv, a_pars_last_key.p_count, m_select);
                a92next_pcount (acv, a_pars_last_key);
                END;
            (*ENDIF*) 
            ak502parsinfo_with_values (acv, dmli, change_rec, erec,
                  parsk, single, ft, c_first,
                  (erec.ex_plus + 1 = erec.ex_maxbufs));
            WHILE ((a_returncode = 0) AND
                  (erec.ex_plus + 1 <= erec.ex_maxbufs)) DO
                ak502parsinfo_with_values (acv, dmli, change_rec, erec,
                      parsk, single, ft, NOT c_first,
                      (erec.ex_plus + 1 = erec.ex_maxbufs));
            (*ENDWHILE*) 
            dmli.d_corr := no_correlation;
            new_parsk   := a_pars_last_key;
            firstplus   := -1;
            (* PTS 1122398 E.Z. *)
            (*
                  END
                  ELSE
                  BEGIN
                  firstplus := parsk.p_no;
                  a505next_command (acv, dmli.d_sparr, parsk, firstplus);
                  IF  a_returncode = 0
                  THEN
                  single := dmli.d_sparr.px[ 1 ]^.sparsinfo.p_single;
                  firstplus    := erec.ex_plus;
                  erec.ex_plus := erec.ex_maxbufs
                  *)
            END;
        (*ENDIF*) 
        erec.ex_all_rescnt               := 0;
        erec.ex_act_treeid.fileRoot_gg00 := NIL_PAGE_NO_GG00;
        new_erec                         := erec;
        erec.ex_act_treeid               := second_loop_res_tree;
        IF  ( NOT inner_loop AND
            (( a_command_kind = single_command ) OR
            ( a_command_kind = subquery_command )) AND
            ( a_max_intern_select = 0 ))
        THEN
            a_max_intern_select := a_intern_select_cnt;
        (*ENDIF*) 
        IF  a_returncode = 0
        THEN
            IF  (d_sparr.px[ 1 ]^.sparsinfo.p_select AND
                NOT d_sparr.px[ 1 ]^.sparsinfo.p_single AND
                NOT inner_loop) AND
                (a_max_intern_select = a_intern_select_cnt)
            THEN
                WITH d_sparr.px[ 1 ]^.sparsinfo DO
                    BEGIN
                    (* last parsinfo was found *)
                    IF  (d_resname <> a01_zero_res_name) AND
                        (a_union_cnt <= 1)
                    THEN
                        resnam := d_resname
                    ELSE
                        resnam := p_resn;
                    (*ENDIF*) 
                    IF  (resnam = a01_zero_res_name)
                    THEN
                        BEGIN
                        aux_tfn       := ttfnInternResult_egg00;
                        resultindexno := cak_intern_pos;
                        END
                    ELSE
                        BEGIN
                        aux_tfn       := ttfnUserResult_egg00;
                        resultindexno := cak_extern_pos;
                        END;
                    (*ENDIF*) 
                    a663_get_result_info (acv, resnam, p_modul_name,
                          a_resname_addr[ resultindexno ], c_make_new_res,
                          aux_tfn, d_fix, f_ok);
&                   IFDEF TRACE
                    t01lidentifier (ak_sem, resnam);
                    t01lidentifier (ak_sem, p_modul_name);
                    t01int4 (ak_sem, 'resultindexn', resultindexno);
&                   ENDIF
                    END
                (*ENDWITH*) 
            ELSE
                a061assign_colname ('dummy             ', resnam);
            (*ENDIF*) 
        (*ENDIF*) 
        dummybuf := NIL;
        first    := true;
        munion_cnt := a_union_cnt;
        IF  NOT inner_loop
        THEN
            BEGIN
            firstlast  := new_parsk.p_no - next_sel_buf_no;
            secondplus := new_parsk.p_no - next_sel_buf_no;
            secondlast := secondplus + 1;
            restplus   := secondplus + 1;
            restlast   := new_parsk.p_no;
            acv.a_rest_equal_second := ( restlast <= secondlast );
            IF  restlast > secondlast
            THEN
                erec.ex_act_treeid.fileRoot_gg00 := NIL_PAGE_NO_GG00
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            firstplus     := erec.ex_plus;
            firstlast     := erec.ex_maxbufs - next_sel_buf_no;
            secondplus    := erec.ex_maxbufs - next_sel_buf_no;
            secondlast    := secondplus + 1;
            restplus      := secondplus + 1;
            restlast      := firstlast + last_sel_buf_no;
            a_union_cnt := 0;
            END;
        (*ENDIF*) 
&       ifdef TRACE
        t01int4 (ak_sem, 'inner_loop  ', ord(inner_loop));
        t01int4 (ak_sem, ' firstplus  ', firstplus);
        t01int4 (ak_sem, ' ex_maxbufs ', erec.ex_maxbufs);
        t01int4 (ak_sem, ' next_sel_b ', next_sel_buf_no);
        t01int4 (ak_sem, ' firstlast  ', firstlast );
        t01int4 (ak_sem, ' secondplus ', secondplus );
        t01int4 (ak_sem, ' secondlast ', secondlast  );
        t01int4 (ak_sem, ' restplus   ', restplus     );
        t01int4 (ak_sem, ' restlast   ', restlast      );
&       endif
        normal_query_useful  := false;
        next_record_possible := true;
        e                    := e_ok;
        WHILE ((a_returncode = 0) AND ( e = e_ok)) DO
            BEGIN
            ak502next_corr_record (acv, cinfo, tree_pos,
                  subquery_needed, next_record_possible, e);
            IF  e = e_ok
            THEN
                BEGIN
                none_found := false;
                IF  subquery_needed
                THEN
                    BEGIN
                    IF  NOT first
                    THEN
                        a06subquery_del_result (acv,
                              dmli, subquery_tree, TEMP_PREFIX_MXGG00 + 3)
                    ELSE
                        first := false;
                    (*ENDIF*) 
                    IF  a_returncode = 0
                    THEN
                        BEGIN
                        WITH new_erec DO
                            BEGIN
                            ex_act_treeid.fileRoot_gg00 := NIL_PAGE_NO_GG00;
                            ex_plus                     := firstplus;
                            ex_maxbufs                  := firstlast
                            END;
                        (*ENDWITH*) 
                        cinfo.co_use_fields := corr_fields;
                        a505loop_most_execute (acv, dmli, change_rec,
                              new_erec, new_parsk, dummybuf, series,
                              cinfo, old_cinfo, c_inner_loop);
                        END;
                    (*ENDIF*) 
                    subquery_tree := new_erec.ex_act_treeid;
                    normal_query_useful := (a_returncode = 0);
                    END;
&               IFDEF TRACE
                (*ENDIF*) 
                t01name (ak_sem, 'end first         ');
                t01treeid (ak_sem, 'subquerytree', subquery_tree);
                t01int4 (ak_sem, 'returncode  ', a_returncode);
                t01int4 (ak_sem, 'normal_query', ord(normal_query_useful));
&               ENDIF
                IF  ((a_returncode = 0) AND normal_query_useful)
                THEN
                    BEGIN
                    (******************************)
                    (* if this part was not used, *)
                    (* sometimes act_treeid is not*)
                    (* initialized and no file is *)
                    (* there                      *)
                    (******************************)
                    new_erec.ex_all_rescnt := erec.ex_all_rescnt;
                    new_erec.ex_act_treeid := erec.ex_act_treeid;
                    new_erec.ex_plus       := secondplus;
                    new_erec.ex_maxbufs    := secondlast;
                    cinfo.co_use_fields    := keyfields;
                    a505loop_most_execute (acv, dmli, change_rec, new_erec,
                          new_parsk, dummybuf, series,
                          cinfo, old_cinfo, c_inner_loop);
                    ex_link := new_erec.ex_with_link;
&                   IFDEF TRACE
                    t01treeid (ak_sem, 'normalacttre',
                          new_erec.ex_act_treeid);
&                   ENDIF
                    IF  a_returncode = 0
                    THEN
                        IF  (single AND (a_mblock.mb_data_len  > 0)
                            AND (restlast <= secondlast))
                        THEN
                            WITH a_mblock, mb_data^ DO
                                (* one record found *)
                                IF  firstsingle
                                THEN
                                    BEGIN
                                    stored_len := mb_data_len ;
                                    g10mv ('VAK502',   2,    
                                          mb_data_size, sizeof(first_selinto_result),
                                          @mbp_buf, 1,
                                          @first_selinto_result, 1,
                                          stored_len,
                                          a_returncode);
                                    IF  mbp_keylen > RESCNT_MXGG04
                                    THEN (* distinct *)
                                        empty_into_file := true;
                                    (*ENDIF*) 
                                    firstsingle := false;
                                    IF  a_sqlmode = sqlm_oracle
                                    THEN
                                        e := e_no_next_record
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    BEGIN
                                    IF  mbp_keylen = RESCNT_MXGG04 (* no distinct *)
                                    THEN
                                        a07_b_put_error (acv,
                                              e_too_many_resultsets, 1)
                                    ELSE
                                        BEGIN
                                        s30cmp2 (mbp_buf,
                                              mbp_keylen+cgg_rec_key_offset+1,
                                              mb_data_len -mbp_keylen-cgg_rec_key_offset,
                                              first_selinto_result,
                                              cgg_rec_key_offset+1+mbp_keylen,
                                              mb_data_len -mbp_keylen-cgg_rec_key_offset,
                                              lc_result);
                                        IF  lc_result <> l_equal
                                        THEN
                                            a07_b_put_error (acv,
                                                  e_too_many_resultsets, 1)
                                        (*ENDIF*) 
                                        END
                                    (*ENDIF*) 
                                    END
                                (*ENDIF*) 
                            (*ENDWITH*) 
                        ELSE
                            BEGIN
                            s40g4int (a_mblock.mb_qual^.mr_resnum, 2,
                                  erec.ex_all_rescnt, res);
                            erec.ex_act_treeid := a_mblock.mb_qual^.mr_restree;
                            (* PTS 1125033 E.Z. *)
                            IF  (erec.ex_all_rescnt >= 1) AND
                                (restlast <= secondlast)
                            THEN
                                IF  (maxresults = 1) OR
                                    (warn12_rowno_used in a_mblock.mb_trns^.trWarning_gg00)
                                THEN
                                    e := e_no_next_record;
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDWHILE*) 
        IF  ex_link
        THEN
            a505execute_link (acv, parsk, linkplus);
        (*ENDIF*) 
        IF  ((a_returncode = 0) AND none_found AND
            ((parsk.p_kind = m_select) OR inner_loop))
        THEN
            BEGIN
            erec.ex_all_rescnt := 0;
            (* put '0' into mess_buf.mb_qual^ *)
            (* putlint impossible because used for cmh_var_part *)
            a_mblock.mb_qual^.mr_resnum  := csp_rescnt_zero;
            erec.ex_act_treeid           := second_loop_res_tree;
            a502empty_result (acv, dmli, erec.ex_act_treeid);
            a_mblock.mb_qual^.mr_restree := erec.ex_act_treeid;
            END;
        (*ENDIF*) 
        IF  ((a_returncode = 0) AND (restlast > secondlast))
        THEN
            BEGIN
            old_res_tree     := erec.ex_act_treeid;
            IF  NOT old_cinfo.co_use_cinfo
            THEN
                BEGIN
                help_cinfo := cinfo;
                help_cinfo.co_use_fields := no_fields;
                END
            ELSE
                BEGIN
                help_cinfo := old_cinfo;
                help_cinfo.co_use_fields := corr_fields;
                END;
            (*ENDIF*) 
            (* keyfields may not come in the function select *)
            new_erec.ex_act_treeid.fileRoot_gg00 := NIL_PAGE_NO_GG00;
            new_erec.ex_all_rescnt := 0;
            new_erec.ex_plus       := restplus;
            new_erec.ex_maxbufs    := restlast;
            (* PTS 1117747 E.Z. *)
            a505loop_most_execute (acv, dmli, change_rec, new_erec,
                  new_parsk, dummybuf, series, help_cinfo, old_cinfo, c_inner_loop);
            IF  a_returncode = 0
            THEN
                IF  (single AND (a_mblock.mb_data_len  > 0))
                THEN
                    WITH a_mblock DO
                        (* one record found *)
                        BEGIN
                        stored_len := mb_data_len ;
                        g10mv ('VAK502',   3,    
                              mb_data_size,
                              sizeof(first_selinto_result),
                              @mb_data^.mbp_buf, 1, @first_selinto_result, 1,
                              stored_len, a_returncode);
                        IF  mb_data^.mbp_keylen > RESCNT_MXGG04
                        THEN (* distinct *)
                            empty_into_file := true;
                        (*ENDIF*) 
                        erec.ex_all_rescnt := 1;
                        firstsingle := false;
                        IF  a_sqlmode = sqlm_oracle
                        THEN
                            e := e_no_next_record
                        (*ENDIF*) 
                        END
                    (*ENDWITH*) 
                ELSE
                    BEGIN
                    s40g4int (a_mblock.mb_qual^.mr_resnum, 2,
                          erec.ex_all_rescnt, res);
                    erec.ex_act_treeid := a_mblock.mb_qual^.mr_restree;
&                   IFDEF TRACE
                    t01name (bi, 'rest              ');
                    t01treeid (bi, '3.looprestre', erec.ex_act_treeid);
&                   ENDIF
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            a502destroy_file (acv, old_res_tree)
            END;
        (*ENDIF*) 
        IF  ((a_returncode = 0) AND NOT inner_loop)
        THEN
            IF  NOT single
            THEN
                BEGIN
                IF  ((erec.ex_act_treeid.fileRoot_gg00 = NIL_PAGE_NO_GG00) AND
                    (parsk.p_kind = m_select))
                    (* resfile not created *)
                THEN
                    BEGIN
                    erec.ex_all_rescnt := 0;
                    (* put '0' into mess_buf.mb_qual^ *)
                    (* putlint impossible because used for cmh_var_part *)
                    a_mblock.mb_qual^.mr_resnum := csp_rescnt_zero;
                    erec.ex_act_treeid := a_resname_addr[ resultindexno ]^.
                          sresname.restreeid;
                    a502empty_result (acv, dmli, erec.ex_act_treeid);
                    a_mblock.mb_qual^.mr_restree := erec.ex_act_treeid;
                    END;
                (*ENDIF*) 
                WITH erec.ex_act_treeid DO
                    is_not_from_select := (fileTfnTemp_gg00 <> ttfnFromSelect_egg00) OR
                          (fileTfn_gg00 <> tfnTemp_egg00);
                (*ENDWITH*) 
&               IFDEF TRACE
                t01int4 (ak_sem, 'returncode  ', a_returncode);
                t01int4 (ak_sem, 'max_intern  ', a_max_intern_select);
                t01int4 (ak_sem, 'intern_sel  ', a_intern_select_cnt);
                t01int4 (ak_sem, 'command_kind', ord(a_command_kind));
                t01int4 (ak_sem, 'a_union_cnt ', a_union_cnt);
                t01int4 (ak_sem, 'munion_cnt  ', munion_cnt);
                t01int4 (ak_sem, 'p_kind      ', ord(parsk.p_kind));
&               ENDIF
                IF  (a_returncode = 0 )       AND
                    (a_max_intern_select = a_intern_select_cnt) AND
                    ((a_command_kind = single_command ) OR
                    ( a_command_kind = subquery_command))       AND
                    (munion_cnt = 0)                            AND
                    is_not_from_select
                THEN
                    BEGIN
                    IF  (parsk.p_kind = m_select)
                    THEN
                        BEGIN
                        IF  (NOT single)
                        THEN
                            a_result_name := resnam;
                        (*ENDIF*) 
                        WITH a_mblock.mb_qual^ DO
                            BEGIN
                            mr_resnum [ 1 ] := csp_defined_byte;
                            s41p4int (mr_resnum, 2,
                                  erec.ex_all_rescnt, res);
                            END;
                        (*ENDWITH*) 
                        erec.ex_act_treeid.fileTempCnt_gg00       := a_max_res_id;
                        a_mblock.mb_qual^.mr_restree := erec.ex_act_treeid;
                        a_mblock.mb_qual^.mr_res_build := true;
                        dummybuf                       := NIL;
                        rep_res            := dmli.d_repl_reskey;
                        dmli.d_repl_reskey := false;
                        ssr_rec.ssr_old_strategynum := strat_inv_in;
                        ssr_rec.ssr_new_strategynum := strat_inv_in;
                        ssr_rec.ssr_invlen := 0;
                        ssr_rec.ssr_reverse_access := false;
                        ssr_rec.ssr_filler         := false;
                        a507select_part (acv, resultindexno, dummybuf,
                              parsk, dmli, ssr_rec);
                        dmli.d_repl_reskey := rep_res;
                        END;
                    (*ENDIF*) 
                    IF  erec.ex_all_rescnt = 0
                    THEN
                        BEGIN
                        a07_b_put_error (acv, e_row_not_found, 1)
                        END
                    ELSE
                        BEGIN
                        IF  (a_sqlmode = sqlm_oracle) AND
                            (parsk.p_kind = m_select)
                        THEN
                            a60rescount (acv, 0)
                        ELSE
                            a60rescount (acv, erec.ex_all_rescnt)
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  NOT none_found
        THEN
            a06subquery_del_result (acv,
                  dmli, subquery_tree, TEMP_PREFIX_MXGG00 + 3);
        (*ENDIF*) 
        a502destroy_file (acv, cinfo.co_corr_current);
        IF  NOT inner_loop
        THEN
            BEGIN
            IF  a_returncode = 0
            THEN
                BEGIN
                FOR i := 1 TO dmli.d_sparr.pcount DO
                    a10rel_sysinfo (dmli.d_sparr.px[ i ]);
                (*ENDFOR*) 
                (* PTS 1000816 E.Z. *)
                dmli.d_sparr.pcount := 0;
                new_erec.ex_plus := restlast;
                IF  (new_parsk.p_kind <> m_update) AND
                    (new_parsk.p_kind <> m_delete)
                THEN
                    BEGIN
                    a505next_command (acv, dmli.d_sparr, new_parsk, new_erec.ex_plus);
                    IF  a_returncode = 0
                    THEN
                        BEGIN
                        a505get_change_rec (acv, dmli.d_sparr,
                              change_rec);
                        d_pos_in_parsbuf := 1
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  (parsk.p_id[ 1 ] <> new_parsk.p_id[ 1 ])
                OR (parsk.p_count <> new_parsk.p_count)
            THEN
                BEGIN
                a660_prefix_delete (acv, new_parsk, i, cak_intern_prefix);
                a92_add_pcount (acv, new_parsk.p_count, m_select);
                a_pars_last_key := aux_pars_last_key;
                END;
            (*ENDIF*) 
            IF  (single AND (a_returncode = 0))
            THEN
                IF  (firstsingle AND
                    (dmli.d_mselect_loop_cnt = cgg04_first_and_only_of_all) AND
                    (* no MSELECT INTO *)
                    (dmli.d_mselect_rescnt <= 1))
                THEN
                    a07_b_put_error (acv, e_no_next_record, 1)
                ELSE
                    BEGIN
                    IF  firstsingle
                    THEN
                        BEGIN
                        IF  dmli.d_mselect_rescnt = cak_is_undefined
                        THEN
                            dmli.d_mselect_rescnt := 0;
                        (*ENDIF*) 
                        SAPDB_PascalFill ('VAK502',   4,    
                              a_mblock.mb_data_size,
                              @a_mblock.mb_data^.mbp_buf, 1,
                              resreclen, csp_undef_byte,
                              a_returncode);
                        a_mblock.mb_data_len  := resreclen;
                        END
                    ELSE
                        BEGIN
                        IF  dmli.d_mselect_rescnt = cak_is_undefined
                        THEN
                            dmli.d_mselect_rescnt := 1
                        ELSE
                            dmli.d_mselect_rescnt := succ(dmli.d_mselect_rescnt);
                        (*ENDIF*) 
                        a_mblock.mb_data_len  := stored_len;
                        g10mv ('VAK502',   5,    
                              sizeof(first_selinto_result),
                              a_mblock.mb_data_size,
                              @first_selinto_result, 1,
                              @a_mblock.mb_data^.mbp_buf, 1,
                              stored_len,
                              a_returncode);
                        IF  empty_into_file
                        THEN
                            (* only local possible *)
                            b01empty_file (a_transinf.tri_trans, a_into_tree);
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  erec.ex_output_wanted
                    THEN
                        IF  ((dmli.d_mselect_loop_cnt = cgg04_first_and_only_of_all) AND
                            (* no MSELECT INTO *)
                            (dmli.d_mselect_rescnt <= 1))
                        THEN
                            BEGIN
                            lcol_found := false;
                            IF  d_change.cr_colcount > 0
                            THEN
                                lcol_found := a508_lcol_found (acv, d_change);
                            (*ENDIF*) 
                            a60rescount (acv, 1);
                            a60_change_results (acv, a_mblock.mb_data^.mbp_buf,
                                  change_rec, 0, a_mblock.mb_data_len);
                            a60_put_result (acv, a_mblock,
                                  a_mblock.mb_data^.mbp_keylen+
                                  cgg_rec_key_offset);
                            IF  lcol_found AND
                                (a_returncode = 0)
                            THEN
                                BEGIN
                                lcol_lock := true;
                                a508_lget_long_columns (acv, d_change,
                                      lcol_lock, 1,
                                      a_mblock.mb_data^.mbp_reclen,
                                      - (a_mblock.mb_data^.mbp_keylen +
                                      cgg_rec_key_offset))
                                END;
                            (*ENDIF*) 
                            IF  a_returncode = 0
                            THEN
                                a06finish_curr_retpart (acv, sp1pk_data, 1)
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            (* MSELECT INTO *)
                            IF  NOT dmli.d_local_massdata_part AND
                                NOT
                                ((dmli.d_mselect_loop_cnt = cgg04_last_of_this) OR
                                ( dmli.d_mselect_loop_cnt = cgg04_first_and_only_of_all) OR
                                ( dmli.d_mselect_loop_cnt = cgg04_first_and_only_of_this) OR
                                ( dmli.d_mselect_loop_cnt = cgg04_last_of_all))
                            THEN
                                BEGIN
                                p := gg941Allocate (acv.a_transinf.tri_trans,
                                      acv.a_data_length);
                                IF  p = NIL
                                THEN
                                    a07_b_put_error (acv, e_no_more_memory, 1)
                                ELSE
                                    BEGIN
                                    dmli.d_massdata_ptr        := @p^;
                                    g10mv ('VAK502',   6,    
                                          acv.a_data_length, acv.a_data_length,
                                          @acv.a_data_ptr^, 1,
                                          @dmli.d_massdata_ptr^, 1,
                                          acv.a_data_length,
                                          acv.a_returncode);
                                    acv.a_data_ptr := dmli.d_massdata_ptr;
                                    dmli.d_local_massdata_part := true;
                                    END;
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                            IF  a_returncode = 0
                            THEN
                                BEGIN
                                a_long_desc_pos := 0;
                                IF  change_rec.cr_colcount > 0
                                THEN
                                    a60_change_results (acv, a_mblock.mb_data^.mbp_buf,
                                          change_rec, 0, acv.a_mblock.mb_data_len);
                                (*ENDIF*) 
                                stored_len := cgg_rec_key_offset +
                                      acv.a_mblock.mb_data^.mbp_keylen + 1;
                                a06retpart_move (acv, @a_mblock.mb_data^.mbp_buf [ stored_len ],
                                      resinfolen);
                                IF  (a_returncode = 0) AND
                                    ((dmli.d_mselect_loop_cnt = cgg04_last_of_this) OR
                                    ( dmli.d_mselect_loop_cnt = cgg04_first_and_only_of_all) OR
                                    ( dmli.d_mselect_loop_cnt = cgg04_first_and_only_of_this) OR
                                    ( dmli.d_mselect_loop_cnt = cgg04_last_of_all))
                                THEN
                                    a06finish_curr_retpart (acv, sp1pk_data,
                                          a_curr_retpart^.sp1p_buf_len DIV resinfolen);
                                (* do not use dmli.d_mselect_rescnt       *)
                                (* it only counts real (NOT NULL) results *)
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  inner_loop
        THEN
            BEGIN
            erec.ex_plus := restlast;
            a_union_cnt  := munion_cnt
            END;
        (*ENDIF*) 
        a10dispose (acv, cinfo.co_corr_buf)
        END
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a502destroy_file (
            VAR acv          : tak_all_command_glob;
            VAR tree         : tgg00_FileId);
 
BEGIN
b01destroy_file (acv.a_transinf.tri_trans, tree);
IF  acv.a_transinf.tri_trans.trError_gg00 = e_ok
THEN
    tree.fileRoot_gg00 := NIL_PAGE_NO_GG00
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a502empty_result (
            VAR acv      : tak_all_command_glob;
            VAR dmli     : tak_dml_info;
            VAR res_tree : tgg00_FileId);
 
BEGIN
IF  (res_tree.fileTfn_gg00 = tfnTemp_egg00) AND
    (res_tree.fileTfnTemp_gg00 <> ttfnInto_egg00)
THEN
    BEGIN
    IF  res_tree.fileTfnTemp_gg00 = ttfnUserResult_egg00
    THEN
        IF  (dmli.d_mselect_loop_cnt = cgg04_first_and_only_of_all)
            OR
            (((dmli.d_mselect_loop_cnt = cgg04_first_of_all) OR
            (  dmli.d_mselect_loop_cnt = cgg04_first_and_only_of_this)) AND
            NOT dmli.d_repl_reskey)
        THEN
            BEGIN
            res_tree.fileTempCnt_gg00 := acv.a_max_res_id;
            a663create_result_file (acv, m_create_table, res_tree);
            IF  res_tree.fileTfnTemp_gg00 = ttfnUserResult_egg00
            THEN
                IF  acv.a_resname_addr[ cak_extern_pos ] <> NIL
                THEN
                    WITH acv.a_resname_addr[ cak_extern_pos ]^.sresname DO
                        restreeid.fileTempCnt_gg00 := res_tree.fileTempCnt_gg00
                    (*ENDWITH*) 
                ELSE
                    a07ak_system_error (acv, 502, 1)
                (*ENDIF*) 
            (*ENDIF*) 
            END
        ELSE
            acv.a_transinf.tri_trans.trError_gg00 := e_ok
        (*ENDIF*) 
    ELSE
        b01tcreate_file (acv.a_transinf.tri_trans, res_tree);
    (*ENDIF*) 
    IF  acv.a_transinf.tri_trans.trError_gg00 <> e_ok
    THEN
        a07_b_put_error (acv, acv.a_transinf.tri_trans.trError_gg00, 1)
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak502create_tab_as_select (
            VAR acv     : tak_all_command_glob;
            VAR tableid : tgg00_Surrogate;
            VAR parsk   : tak_parskey);
 
VAR
      b_err         : tgg00_BasisError;
      aux_data_part : tsp1_part_ptr;
      aux_data_ptr  : tsp00_MoveObjPtr;
      aux_data_len  : tsp00_Int4;
      sysk          : tgg00_SysInfoKey;
 
BEGIN
WITH acv DO
    BEGIN
    (* execution of create table .. as select *)
    aux_data_part := a_data_part;
    aux_data_ptr  := a_data_ptr;
    aux_data_len  := a_data_length;
    sysk          := a_ptr2^.syskey;
    a14create_tab_as_select (acv, tableid, parsk);
    a10get_sysinfo (acv, sysk, d_fix, a_ptr2, b_err);
    IF  b_err <> e_ok
    THEN
        a07_b_put_error (acv, b_err, 1);
    (*ENDIF*) 
    a_data_part   := aux_data_part;
    a_data_ptr    := aux_data_ptr;
    a_data_length := aux_data_len
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak502execute_parsinfo (
            VAR acv        : tak_all_command_glob;
            VAR sparr      : tak_syspointerarr;
            VAR change_rec : tak_changerecord;
            mtype          : tgg00_MessType;
            ft             : found_type;
            new_p_id       : boolean;
            last           : boolean);
 
VAR
      e  : tgg00_BasisError;
      ke : tgg00_SysInfoKey;
 
BEGIN
WITH acv, sparr DO
    BEGIN
    WITH a_pars_last_key DO
        IF  new_p_id
        THEN
            BEGIN
            IF  a_pars_last_key.p_id[ 1 ] < chr(255)
            THEN
                p_id[ 1 ] := succ (a_pars_last_key.p_id[ 1 ])
            ELSE
                WITH a_pars_last_key DO
                    BEGIN
                    a92next_pcount (acv, a_pars_last_key);
                    p_id   := chr(0);
                    END;
                (*ENDWITH*) 
            (*ENDIF*) 
            p_kind    := mtype;
            p_no      := 0
            END
        ELSE
            IF  a_pars_last_key.p_no + 1 > csp_maxint1
            THEN
                a07_b_put_error (acv, e_too_many_subqueries, 1)
            ELSE
                WITH a_pars_last_key DO
                    p_no := p_no + 1;
                (*ENDWITH*) 
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDWITH*) 
    IF  a_returncode = 0
    THEN
        BEGIN
        ke := a01sysnullkey;
        WITH ke DO
            BEGIN
            sauthid[ 1 ] := cak_tempinfo_byte;
            s10mv (sizeof (a_pars_last_key), sizeof (sauthid),
                  @a_pars_last_key, 1, @sauthid, 2, mxak_parskey);
            sentrytyp := cak_eparsinfo
            END;
        (*ENDWITH*) 
        a10_nil_get_sysinfo (acv, ke, d_release, MAX_RECLEN_GG00,
              pparsp, e);
        IF  e <> e_ok
        THEN
            a07_b_put_error (acv, e, 1)
        ELSE
            BEGIN
            g10mv ('VAK502',   7,    
                  sizeof(tak_parsbuffer), sizeof(tak_parsbuffer),
                  @sparr.px[ 1 ]^.sparsinfo.p_buf, 1,
                  @pparsp^.sparsinfo.p_buf, 1, mxak_pars_header,
                  a_returncode);
            pparsp^.sparsinfo.p_cnt_infos := 0;
            pparsp^.sparsinfo.p_sqlmode   := a_sqlmode;
            IF  ft = select_found
            THEN
                a54_sel_store_parsinfo (acv, sparr, change_rec, last)
            ELSE
                BEGIN
                pparsp^.sparsinfo.p_select := false;
                a54_store_parsinfo (acv, sparr)
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak502next_corr_record (
            VAR acv                  : tak_all_command_glob;
            VAR cinfo                : tak_corr_infos;
            VAR tree_pos             : tgg00_FilePos;
            VAR subquery_needed      : boolean;
            VAR next_record_possible : boolean;
            VAR e                    : tgg00_BasisError);
 
VAR
      first      : boolean;
      lc_result  : tsp00_LcompResult;
      set_result : tgg00_BdSetResultRecord;
      corr_key   : tgg00_Lkey;
      hbuf       : tsp00_Buf;
 
BEGIN
WITH cinfo DO
    BEGIN
    e         := e_ok;
    lc_result := l_equal;
    IF  co_act_pos + co_one_rec_len > co_all_recs_len
    THEN
        IF  next_record_possible
        THEN
            BEGIN
            first := tree_pos.tpsPno_gg00 = NIL_PAGE_NO_GG00;
            IF  first
            THEN
                BEGIN
                lc_result    := l_greater;
                corr_key.len := 0
                END
            ELSE
                g10mv ('VAK502',   8,    
                      sizeof (co_corr_buf^), sizeof(hbuf),
                      @co_corr_buf^, co_act_pos + co_one_key_len+cgg_rec_key_offset,
                      @hbuf, 1, co_lcomp_len,
                      acv.a_returncode);
            (*ENDIF*) 
            WITH set_result DO
                BEGIN
                bd_key_check_len := 0;
                bd_max_rec_cnt   := sizeof (co_corr_buf^) DIV
                      (cgg_rec_key_offset+2);
                bd_max_fill_len  := sizeof (co_corr_buf^);
                bd_next          := false;
                END;
            (*ENDWITH*) 
            b07cnext_record (acv.a_transinf.tri_trans, co_corr_current,
                  corr_key, set_result, tree_pos, co_corr_buf^);
            e := acv.a_transinf.tri_trans.trError_gg00;
            IF  (e = e_ok)           OR
                (e = e_buffer_limit) OR
                (e = e_key_not_found)
            THEN
                BEGIN
                next_record_possible := (e = e_buffer_limit);
                e                    := e_ok;
                co_all_recs_len      := set_result.bd_fill_len;
                IF  co_all_recs_len <= 0
                THEN
                    e := e_no_next_record
                ELSE
                    BEGIN
                    co_act_pos := 1;
                    IF  NOT first
                    THEN
                        s30cmp1 (co_corr_buf^,
                              cgg_rec_key_offset + co_act_pos + co_one_key_len,
                              co_lcomp_len, hbuf, 1, co_lcomp_len, lc_result);
&                   IFDEF TRACE
                    (*ENDIF*) 
                    t01int4 (ak_sem, 'act_pos     ', co_act_pos);
                    t01int4 (ak_sem, 'lcomp_start ', co_one_key_len+cgg_rec_key_offset+1);
                    t01int4 (ak_sem, 'lcomp_len   ', co_lcomp_len);
                    t01int4 (ak_sem, 'one_rec_len ', co_one_rec_len);
                    t01buf1 (ak_sem, co_corr_buf^, co_act_pos,
                          co_act_pos+co_one_rec_len-1);
&                   ENDIF
                    END;
                (*ENDIF*) 
                END
            ELSE
                IF  e <> e_no_next_record
                THEN
                    a07_b_put_error (acv, e, 1)
                (*ENDIF*) 
            (*ENDIF*) 
            END
        ELSE
            e := e_no_next_record
        (*ENDIF*) 
    ELSE
        BEGIN
&       IFDEF TRACE
        t01int4 (ak_sem, 'act_pos     ', co_act_pos);
        t01int4 (ak_sem, 'lcomp_start ', co_one_key_len+cgg_rec_key_offset+1);
        t01int4 (ak_sem, 'lcomp_len   ', co_lcomp_len);
        t01int4 (ak_sem, 'one_rec_len ', co_one_rec_len);
        t01buf1 (ak_sem, co_corr_buf^, co_act_pos+co_one_key_len+cgg_rec_key_offset,
              co_act_pos+co_one_key_len+cgg_rec_key_offset+1+co_lcomp_len-2);
        t01buf1 (ak_sem, co_corr_buf^, co_act_pos+co_one_rec_len+
              co_one_key_len+cgg_rec_key_offset,
              co_act_pos+co_one_rec_len+co_one_key_len+cgg_rec_key_offset+1+co_lcomp_len-2);
        t01treeid (ak_sem, 'corr_current', co_corr_current);
&       ENDIF
        s30cmp1 (co_corr_buf^, co_act_pos+co_one_key_len+cgg_rec_key_offset, co_lcomp_len,
              co_corr_buf^, co_act_pos+co_one_rec_len+co_one_key_len+cgg_rec_key_offset,
              co_lcomp_len, lc_result);
&       IFDEF TRACE
        IF  lc_result = l_equal
        THEN
            t01int4 (ak_sem, 'EQUAL       ', 1)
        ELSE
            t01int4 (ak_sem, 'NOT EQUAL   ', 1);
        (*ENDIF*) 
&       ENDIF
        co_act_pos := co_act_pos + co_one_rec_len
        END;
    (*ENDIF*) 
    subquery_needed := lc_result <> l_equal
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak502parsinfo_with_values (
            VAR acv        : tak_all_command_glob;
            VAR dmli       : tak_dml_info;
            VAR change_rec : tak_changerecord;
            VAR erec       : tak_exec_rec;
            VAR parsk      : tak_parskey;
            VAR single     : boolean;
            VAR ft         : found_type;
            first          : boolean;
            last           : boolean);
 
VAR
      do_ex_parsinfo    : boolean;
      frec              : tak_fill_rec;
      i                 : integer;
      mtype             : tgg00_MessType;
      m2type            : tgg00_MessType2;
      join_help_parsk   : tak_parskey;
      act_res_tree      : tgg00_FileId;
      dummybuf          : tak_sysbufferaddress;
      qbufp             : tak_sysbufferaddress;
      searchname        : tsp00_KnlIdentifier;
      ssr_rec           : tak71_select_strat_rec;
      pmbp              : tgg00_MessBlockPtr;
      pdbp              : tgg00_DataPartPtr;
 
BEGIN
WITH acv, dmli, erec, frec DO
    BEGIN
    FOR i := 1 TO dmli.d_sparr.pcount DO
        a10rel_sysinfo (dmli.d_sparr.px[ i ]);
    (*ENDFOR*) 
    (* PTS 1000816 E.Z. *)
    dmli.d_sparr.pcount := 0;
    dummybuf       := NIL;
    searchname     := a01_il_b_identifier;
    do_ex_parsinfo := true;
    ex_plus        := ex_plus + 1;
    a505next_command (acv, dmli.d_sparr, parsk, ex_plus);
    IF  a_returncode = 0
    THEN
        IF  d_sparr.px[ 1 ]^.sparsinfo.p_mtyp = m_fetch
        THEN
            BEGIN
            ft               := fetch_found;
            d_pos_in_parsbuf := 1;
            a505fill_mess_buf (acv, dmli, erec, frec, c_full_part2)
            END
        ELSE
            BEGIN
            ft          := select_found;
            WITH d_sparr.px[ 1 ]^.sparsinfo DO
                BEGIN
                single       := p_single;
                searchname   := p_searchname;
                a_modul_name := p_modul_name;
                END;
            (*ENDWITH*) 
            a505get_change_rec (acv, dmli.d_sparr,
                  change_rec);
            d_pos_in_parsbuf := 1;
            a505fill_mess_buf (acv, dmli, erec, frec,
                  NOT c_full_part2);
            fr_f_no     := 1;
            fr_last_fno := d_sparr.px[ 1 ]^.sparsinfo.p_cnt_infos;
            a506fieldvalues (acv, dmli,
                  frec, dummybuf, a_mblock.mb_data^.mbp_buf, a_mblock.mb_data_size);
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  ((a_returncode = 0) AND (ft = select_found))
    THEN
        BEGIN
        WITH a_mblock, mb_data^ DO
            BEGIN
            pmbp := @dmli.d_sparr.px[ dmli.d_sparr.pcount ]^.
                  smessblock.mbr_mess_block;
            pdbp := pmbp^.mb_data;
&           IFDEF TRACE
            t01int4 (ak_sem, 'pos_in_parsb', dmli.d_pos_in_parsbuf);
            t01int4 (ak_sem, 'len         ', mb_data_len);
            t01int4 (ak_sem, 'keylen      ', mbp_keylen);
&           ENDIF
            IF  pmbp^.mb_data_len >= dmli.d_pos_in_parsbuf
            THEN
                BEGIN
                fr_leng := pmbp^.mb_data_len - dmli.d_pos_in_parsbuf + 1;
&               IFDEF TRACE
                t01int4 (ak_sem, 'pos_in_parsb', dmli.d_pos_in_parsbuf);
                t01int4 (ak_sem, 'length      ', fr_leng);
                t01int4 (ak_sem, 'len         ', mb_data_len);
                t01int4 (ak_sem, 'keylen      ', mbp_keylen);
&               ENDIF
                g10mv ('VAK502',   9,    
                      pmbp^.mb_data_size, a_mblock.mb_data_size,
                      @pdbp^.mbp_buf, dmli.d_pos_in_parsbuf,
                      @a_mblock.mb_data^.mbp_buf, mb_data_len + 1,
                      fr_leng, a_returncode);
                mb_data_len := mb_data_len + fr_leng;
                dmli.d_pos_in_parsbuf := dmli.d_pos_in_parsbuf +
                      fr_leng;
                END
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
        END;
    (*ENDIF*) 
    IF  ((a_returncode = 0) AND (ft = select_found))
    THEN
        BEGIN
        WITH a_mblock, mb_data^ DO
            BEGIN
            mtype        := mb_type;
            m2type       := mb_type2;
            qbufp        := NIL;
            IF  ((mtype = m_select) AND (m2type = mm_with_join))
            THEN
                BEGIN
                ak502execute_parsinfo (acv, dmli.d_sparr, change_rec,
                      mtype, ft, first, last);
                do_ex_parsinfo       := false;
                join_help_parsk      := parsk;
                join_help_parsk.p_no := ex_plus;
                IF  a_returncode = 0
                THEN
                    a682copy_joinparsinfo (acv, join_help_parsk)
                (*ENDIF*) 
                END
            ELSE
                IF  (mtype = m_select) AND
                    ((m2type = mm_nil) OR (m2type = mm_with_functions))
                THEN
                    BEGIN
                    qbufp := NIL;
                    a505strategy_search (acv, dmli, mtype, searchname,
                          act_res_tree, ssr_rec, qbufp, parsk, c_not_last);
                    END
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
        END;
    (*ENDIF*) 
    IF  ((a_returncode = 0) AND do_ex_parsinfo)
    THEN
        ak502execute_parsinfo (acv, dmli.d_sparr, change_rec,
              parsk.p_kind, ft, first, last)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak502store_during_unlock (
            VAR acv                 : tak_all_command_glob;
            VAR dmli                : tak_dml_info;
            VAR parsk               : tak_parskey;
            VAR change_rec          : tak_changerecord;
            output_during_execution : boolean);
 
VAR
 
      aux_ptr         : RECORD
            CASE boolean OF
                false :
                    (x_data_ptr : tgg00_DataPartPtr);
                true  :
                    (x_ptr      : tsp00_BufAddr)
                END;
            (*ENDCASE*) 
 
      aux_mess_header : tgg00_MessBufHeader;
      aux_change_rec  : tak_changerecord;
      aux_qual_buf    : tgg00_QualBuf;
 
BEGIN
WITH acv, a_mblock DO
    BEGIN
    a10new (acv, mb_data_len , aux_ptr.x_ptr);
    IF  aux_ptr.x_data_ptr = NIL
    THEN
        a07_b_put_error (acv, e_no_more_memory, 1)
    ELSE
        BEGIN
        g10mv ('VAK502',  10,    
              sizeof(change_rec), sizeof(aux_change_rec), @change_rec, 1,
              @aux_change_rec, 1,
              (change_rec.cr_colcount * mxak_change_colinfo) + 4,
              a_returncode);
        aux_mess_header := mb_header;
        g10mv ('VAK502',  11,    
              mb_qual_size, sizeof (aux_qual_buf),
              @mb_qual^, 1, @aux_qual_buf, 1, mb_qual_len,
              a_returncode);
        g10mv ('VAK502',  12,    
              mb_data_size, mb_data_len ,
              @mb_data^.mbp_buf, 1, @aux_ptr.x_data_ptr^.mbp_buf, 1,
              mb_data_len, a_returncode);
        a501exec_with_change_rec (acv, dmli, parsk, change_rec,
              output_during_execution);
        g10mv ('VAK502',  13,    
              sizeof(aux_change_rec), sizeof(change_rec), @aux_change_rec, 1,
              @change_rec, 1,
              (aux_change_rec.cr_colcount * mxak_change_colinfo) + 4,
              a_returncode);
        mb_header := aux_mess_header;
        g10mv ('VAK502',  14,    
              sizeof (aux_qual_buf), mb_qual_size,
              @aux_qual_buf, 1, @mb_qual^, 1, mb_qual_len,
              a_returncode);
        g10mv ('VAK502',  15,    
              mb_data_len , mb_data_size,
              @aux_ptr.x_data_ptr^.mbp_buf, 1, @mb_data^.mbp_buf, 1,
              mb_data_len, a_returncode);
        a10dispose (acv, aux_ptr.x_ptr)
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
