.nf
 
 
    ========== licence begin  GPL
    Copyright (C) 2000 SAP AG
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
 
.fo
*****************************************************
Copyright by SAP AG, 2000
SAP Database Technology
 
Release :      Date : 2000-09-11
*****************************************************
modname : VAK503
changed : 2000-09-11
module  : Executing_union
 
Author  : ElkeZ
Created : 1985-10-16
Pretty  : 2001-09-04
*****************************************************
 
Purpose : Module to execute union-commands.
 
Define  :
 
        PROCEDURE
              a503build_union_buffer (
                    VAR acv : tak_all_command_glob;
                    in_join : boolean);
 
        PROCEDURE
              a503union_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);
 
.CM *-END-* define --------------------------------------
***********************************************************
 
Use     :
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01sysnullkey         : tgg_sysinfokey;
              a01_il_b_identifier   : tsp_knl_identifier;
              a01_union_fill_resname: tsp_knl_identifier;
              a01_zero_res_name     : tsp_knl_identifier;
 
      ------------------------------ 
 
        FROM
              AK_universal_semantic_tools : VAK06;
 
        PROCEDURE
              a06dml_send_mess_buf (
                    VAR acv    : tak_all_command_glob;
                    VAR mblock : tgg_mess_block;
                    VAR dmli   : tak_dml_info;
                    VAR b_err  : tgg_basis_error);
 
        PROCEDURE
              a06a_mblock_init (
                    VAR acv      : tak_all_command_glob;
                    mtype        : tgg_message_type;
                    m2type       : tgg_message2_type;
                    VAR tree     : tgg00_FileId);
 
        PROCEDURE
              a06destroy_temp (
                    VAR acv     : tak_all_command_glob;
                    VAR temp_id : tgg00_FileId;
                    VAR b_err   : tgg_basis_error);
 
        PROCEDURE
              a06move_file_content (
                    VAR acv    : tak_all_command_glob;
                    VAR old_id : tgg00_FileId;
                    VAR new_id : tgg00_FileId;
                    VAR b_err  : tgg_basis_error);
 
        PROCEDURE
              a06rsend_mess_buf (
                    VAR acv      : tak_all_command_glob;
                    VAR mblock   : tgg_mess_block;
                    result_req   : boolean;
                    VAR e        : tgg_basis_error);
 
        PROCEDURE
              a06tempfile_empty (
                    VAR acv     : tak_all_command_glob;
                    VAR temp_id : tgg00_FileId;
                    VAR b_err   : tgg_basis_error);
 
        PROCEDURE
              a06subquery_del_result (
                    VAR acv           : tak_all_command_glob;
                    VAR dmli          : tak_dml_info;
                    VAR subquery_tree : tgg00_FileId;
                    prefix_len        : integer);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK07;
 
        PROCEDURE
              a07_b_put_error (
                    VAR acv : tak_all_command_glob;
                    b_err   : tgg_basis_error;
                    err_code : tsp_int4);
 
        FUNCTION
              a07_return_code (
                    b_err   : tgg_basis_error;
                    sqlmode : tsp_sqlmode) : tsp_int2;
 
      ------------------------------ 
 
        FROM
              Systeminfo_cache : VAK10;
 
        PROCEDURE
              a10get_sysinfo (
                    VAR acv      : tak_all_command_glob;
                    VAR syskey   : tgg_sysinfokey;
                    dstate       : tak_directory_state;
                    VAR syspoint : tak_sysbufferaddress;
                    VAR b_err    : tgg_basis_error);
 
        PROCEDURE
              a10rel_sysinfo (syspointer : tak_sysbufferaddress);
 
      ------------------------------ 
 
        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_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    : tgg07_selectstrat_rec);
 
      ------------------------------ 
 
        FROM
              Select_Syntax : VAK60;
 
        PROCEDURE
              a60rescount (
                    VAR acv  : tak_all_command_glob;
                    rescount : tsp_int4);
 
      ------------------------------ 
 
        FROM
              Resultname_handling : VAK663;
 
        PROCEDURE
              a663_get_result_info (
                    VAR acv          : tak_all_command_glob;
                    VAR resname      : tsp_knl_identifier;
                    VAR modul_name   : tsp_knl_identifier;
                    VAR resname_addr : tak_sysbufferaddress;
                    make_new_res     : boolean;
                    ftemptype        : tgg00_TfnTemp;
                    dstate           : tak_directory_state;
                    VAR f_ok         : boolean);
 
      ------------------------------ 
 
        FROM
              Select_Help_Procedures : VGG04;
 
        PROCEDURE
              g04build_temp_tree_id (
                    VAR curr : tgg00_FileId;
                    VAR t : tgg00_TransContext);
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG10;
 
        PROCEDURE
              g10mv1  (
                    mod_id         : tsp_c6;
                    mod_intern_num : tsp_int4;
                    size1          : tsp_int4;
                    size2          : tsp_int4;
                    VAR val1       : tgg00_FileId;
                    p1             : tsp_int4;
                    VAR val2       : tsp_buf;
                    p2             : tsp_int4;
                    cnt            : tsp_int4;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10mv2  (
                    mod_id         : tsp_c6;
                    mod_intern_num : tsp_int4;
                    size1          : tsp_int4;
                    size2          : tsp_int4;
                    VAR val1       : tsp_moveobj;
                    p1             : tsp_int4;
                    VAR val2       : tgg07_StrategyInfo;
                    p2             : tsp_int4;
                    cnt            : tsp_int4;
                    VAR e          : tgg_basis_error);
 
        PROCEDURE
              g10mv3  (
                    mod_id         : tsp_c6;
                    mod_intern_num : tsp_int4;
                    size1          : tsp_int4;
                    size2          : tsp_int4;
                    VAR val1       : tgg07_StrategyInfo;
                    p1             : tsp_int4;
                    VAR val2       : tsp_moveobj;
                    p2             : tsp_int4;
                    cnt            : tsp_int4;
                    VAR e          : tgg_basis_error);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-10 : VSP10;
 
        PROCEDURE
              s10mv1 (
                    size1    : tsp_int4;
                    size2    : tsp_int4;
                    VAR val1 : tak_parskey;
                    p1       : tsp_int4;
                    VAR val2 : tgg_surrogate;
                    p2       : tsp_int4;
                    cnt      : tsp_int4);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-20 : VSP20;
 
        PROCEDURE
              s20ch4a (
                    val      : tsp_int4;
                    VAR dest : tsp_buf;
                    di       : tsp_int4);
 
      ------------------------------ 
 
        FROM
              GET-Conversions : VSP40;
 
        PROCEDURE
              s40g4int (
                    VAR buf  : tsp_resnum;
                    pos      : tsp_int4;
                    VAR dest : tsp_int4;
                    VAR res  : tsp_num_error);
 
      ------------------------------ 
 
        FROM
              PUT-Conversions : VSP41;
 
        PROCEDURE
              s41p4int (
                    VAR buf : tsp_resnum;
                    pos     : tsp_int4;
                    source  : tsp_int4;
                    VAR res : tsp_num_error);
&       IFDEF TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01bool (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    curr_bool: boolean);
 
        PROCEDURE
              t01lidentifier (
                    debug      : tgg00_Debug;
                    identifier : tsp00_KnlIdentifier);
 
        PROCEDURE
              t01messblock (
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    VAR m         : tgg00_MessBlock);
 
        PROCEDURE
              t01int4 (
                    level : tgg00_Debug;
                    nam : tsp00_Sname;
                    int : tsp00_Int4);
 
        PROCEDURE
              t01buf  (
                    level     : tgg00_Debug;
                    VAR buf   : tak_systembuffer;
                    pos_start : integer;
                    pos_end   : integer);
 
        PROCEDURE
              t01name (
                    level : tgg00_Debug;
                    nam : tsp00_Name);
 
        PROCEDURE
              t01treeid (
                    level      : tgg00_Debug;
                    nam        : tsp00_Sname;
                    VAR treeid : tgg00_FileId);
&       ENDIF
 
.CM *-END-* use -----------------------------------------
***********************************************************
 
Synonym :
 
        PROCEDURE
              g10mv1;
 
              tsp_moveobj tgg00_FileId
              tsp_moveobj tsp_buf
 
        PROCEDURE
              g10mv2;
 
              tsp_moveobj tgg07_StrategyInfo
 
        PROCEDURE
              g10mv3;
 
              tsp_moveobj tgg07_StrategyInfo
 
        PROCEDURE
              s10mv1;
 
              tsp_moveobj tak_parskey
              tsp_moveobj tgg_surrogate
 
        PROCEDURE
              s20ch4a;
 
              tsp_moveobj tsp_buf
 
        PROCEDURE
              s40g4int;
 
              tsp_moveobj tsp_resnum
 
        PROCEDURE
              s41p4int;
 
              tsp_moveobj tsp_resnum
 
        PROCEDURE
              t01buf;
 
              tsp00_Buf tak_systembuffer
 
.CM *-END-* synonym -------------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
CONST
      c_first            = true (* ak503loop_union *);
      c_make_new_res     = true (* a663_get_result_info *);
 
 
(*------------------------------*) 
 
PROCEDURE
      a503build_union_buffer (
            VAR acv : tak_all_command_glob;
            in_join : boolean);
 
VAR
      keylen     : tsp_int_map_c2;
      reclen     : tsp_int_map_c2;
      i          : integer;
      key_offset : integer;
      strat_pos  : integer;
      keylenpos  : integer;
      reclenpos  : integer;
      dist_offs  : integer;
      gg_strategy_ptr : ^tgg07_StrategyInfo;
      union_kind : tsp00_Uint1;
 
BEGIN
dist_offs := 0;
WITH acv, a_mblock, mb_qual^, mb_data^, a_unionrec_ptr^.sunionrec DO
    BEGIN
    gg_strategy_ptr := @mb_strat^[ mb_st^[ mstrat_pos ].epos ];
    a_union_append := uappend_all;
    strat_pos      := mb_st^[ mstrat_pos ].epos;
    a_send_messbuf := ( a_send_messbuf OR a_first_union );
&   IFDEF TRACE
    t01bool( ak_sem, 'a_send_messb', a_send_messbuf );
&   ENDIF
    IF  in_join
    THEN
        BEGIN
        keylenpos := strat_pos + mb_st^[ mstrat_pos ].elen_var +
              mxgg_treeid + 6;
        reclenpos := strat_pos + mb_st^[ mstrat_pos ].elen_var +
              mxgg_treeid + 4;
        keylen.map_c2[ 1 ] := mb_strat^[ keylenpos ];
        keylen.map_c2[ 2 ] := mb_strat^[ keylenpos + 1 ];
        reclen.map_c2[ 1 ] := mb_strat^[ reclenpos ];
        reclen.map_c2[ 2 ] := mb_strat^[ reclenpos + 1 ];
        END
    ELSE
        BEGIN
        keylen.map_int := gg_strategy_ptr^.str_key_len;
        reclen.map_int := gg_strategy_ptr^.str_rec_len;
        ;
        END;
    (*ENDIF*) 
    IF   a_unionrec_ptr^.sunionrec.uappend_all
    THEN
        BEGIN
        union_kind     := a_union_kind + cgg_union_append;
        a_send_messbuf := a_first_union;
&       IFDEF TRACE
        t01bool( ak_sem, 'a_send_messb', a_send_messbuf );
&       ENDIF
        END
    ELSE
        union_kind := a_union_kind;
    (*ENDIF*) 
    gg_strategy_ptr^.str_union_kind := union_kind;
    IF  ( keylen.map_int < ukeylen )
    THEN
        BEGIN
        key_offset := ukeylen - keylen.map_int - dist_offs;
        IF  ( mb_type2 = mm_with_join ) OR
            ( mb_type2 = mm_join_with_last_tab )
        THEN
            BEGIN
            FOR i := mqual_pos TO ( mfirst_free - 1 ) DO
                WITH mb_st^ [i] DO
                    IF  (( etype = st_output_join ) AND
                        ( ecol_pos > keylen.map_int + cgg_rec_key_offset ))
                    THEN
                        ecol_pos := ecol_pos + key_offset;
                    (*ENDIF*) 
                (*ENDWITH*) 
            (*ENDFOR*) 
            END
        ELSE
            BEGIN
            FOR i := mqual_pos TO mb_st^[ mqual_pos ].epos DO
                WITH mb_st^[ i ] DO
                    IF  (( etype = st_output ) AND
                        ( epos > keylen.map_int + cgg_rec_key_offset ))
                    THEN
                        epos := epos + key_offset;
                    (*ENDIF*) 
                (*ENDWITH*) 
            (*ENDFOR*) 
            END;
        (*ENDIF*) 
        keylen.map_int := ukeylen;
        reclen.map_int := reclen.map_int + key_offset;
        IF  in_join
        THEN
            BEGIN
            mb_strat^[ keylenpos ]     := keylen.map_c2[ 1 ];
            mb_strat^[ keylenpos + 1 ] := keylen.map_c2[ 2 ];
            mb_strat^[ reclenpos ]     := reclen.map_c2[ 1 ];
            mb_strat^[ reclenpos + 1 ] := reclen.map_c2[ 2 ];
            END
        ELSE
            BEGIN
            gg_strategy_ptr^.str_key_len := keylen.map_int;
            gg_strategy_ptr^.str_rec_len := reclen.map_int;
            END;
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a503union_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
      b_err            : tgg_basis_error;
      res              : tsp_num_error;
      i                : integer;
      pos              : integer;
      key_cnt_offs     : tsp_int4;
      ke               : tgg_sysinfokey;
      dummybuf         : tak_sysbufferaddress;
      munionbuf        : tak_sysbufferaddress;
      union_id         : tgg00_FileId;
      is_insert_select : boolean;
      f_ok             : boolean;
      resname          : tsp_knl_identifier;
      modul_name       : tsp_knl_identifier;
      rep_res          : boolean;
      ssr_rec          : tgg07_selectstrat_rec;
 
BEGIN
WITH acv DO
    BEGIN
&   IFDEF TRACE
    t01int4 (ak_sem,  'parsk.p_id  ', ord(parsk.p_id[ 1 ]));
    t01int4 (ak_sem,  'parsk.p_kind', ord(parsk.p_kind));
    t01int4 (ak_sem,  'parsk.p_no  ', ord(parsk.p_no));
&   ENDIF
    pos            := cak_intern_pos;
    munionbuf      := a_unionrec_ptr;
    ke             := a01sysnullkey;
    WITH ke DO
        BEGIN
        sauthid[ 1 ] := cak_tempinfo_byte;
        s10mv1 (sizeof(parsk), sizeof(sauthid), parsk, 1,
              sauthid, 2, mxak_parskey );
        sentrytyp := cak_eunionrec
        END;
    (*ENDWITH*) 
    a10get_sysinfo ( acv, ke, d_fix, a_unionrec_ptr, b_err);
    IF  b_err <> e_ok
    THEN
        a07_b_put_error (acv, b_err, a_cmd_part^.sp1p_buf_len)
    ELSE
        BEGIN
&       IFDEF TRACE
        t01buf (ak_sem, a_unionrec_ptr^, 1, a_unionrec_ptr^.b_sl);
        WITH a_unionrec_ptr^.sunionrec DO
            FOR i := 1 TO uselect_cnt - 1 DO
                WITH uselect_arr [ i ] DO
                    BEGIN
                    t01int4 (ak_sem, 'index       ', i);
                    t01int4 (ak_sem, 'ufirstsel   ', ufirstsel);
                    t01int4 (ak_sem, 'usecondsel  ', usecondsel);
                    t01int4 (ak_sem, 'uis_kind    ', ord(uis_kind));
                    t01int4 (ak_sem, 'uis_all     ', ord(uis_all));
                    END;
                (*ENDWITH*) 
            (*ENDFOR*) 
        (*ENDWITH*) 
&       ENDIF
        a_union_cnt  := 0;
        a_next_upos  := cak_is_undefined; (* Sequence of unions *)
&       IFDEF TRACE
        t01int4 (ak_sem, 'max_intern_s', a_max_intern_select);
        t01int4 (ak_sem, 'intern_selec', a_intern_select_cnt);
        t01int4 (ak_sem, 'command_kind', ord(a_command_kind));
        t01lidentifier (ak_syn, a_modul_name);
        t01lidentifier (ak_syn, a_unionrec_ptr^.sunionrec.umodul_name);
&       ENDIF
        IF  a_unionrec_ptr^.sunionrec.ures_name <> a01_union_fill_resname
        THEN
            BEGIN
            WITH a_unionrec_ptr^.sunionrec.ures_tree DO
                IF  (fileTfnTemp_gg00 = ttfnUserResult_egg00)
                THEN
                    BEGIN
                    IF  dmli.d_resname <> a01_zero_res_name
                    THEN
                        IF  (a_unionrec_ptr^.sunionrec.ures_name <>
                            a01_il_b_identifier) AND
                            (a_unionrec_ptr^.sunionrec.ures_name <>
                            dmli.d_resname)
                        THEN
                            a07_b_put_error (acv,
                                  e_no_resulttable_allowed, 1)
                        ELSE
                            BEGIN
                            resname    := dmli.d_resname;
                            modul_name := a_unionrec_ptr^.
                                  sunionrec.umodul_name;
                            END
                        (*ENDIF*) 
                    ELSE
                        BEGIN
                        resname    := a_unionrec_ptr^.sunionrec.ures_name;
                        modul_name := a_unionrec_ptr^.sunionrec.umodul_name;
                        END;
                    (*ENDIF*) 
                    pos := cak_extern_pos
                    END
                ELSE
                    BEGIN
                    resname    := a_unionrec_ptr^.sunionrec.ures_name;
                    modul_name := a_unionrec_ptr^.sunionrec.umodul_name;
                    pos        := cak_intern_pos
                    END;
                (*ENDIF*) 
            (*ENDWITH*) 
            a663_get_result_info (acv, resname, modul_name,
                  a_resname_addr[ pos ], c_make_new_res,
                  a_unionrec_ptr^.sunionrec.ures_tree.fileTfnTemp_gg00,
                  d_fix, f_ok);
            END;
        (*ENDIF*) 
        a_union_kind     := cgg_union_byte;
        union_id         := a_unionrec_ptr^.sunionrec.ures_tree;
        is_insert_select := a_unionrec_ptr^.sunionrec.uinsertselect;
        key_cnt_offs     := 0;
        ak503loop_union (acv, dmli, change_rec, 1, output_during_execution,
              c_first, union_id, a_unionrec_ptr^.sunionrec.ures_cnt,
              key_cnt_offs);
&       IFDEF TRACE
        t01int4(ak_sem, 'RES_CNT 5031', a_unionrec_ptr^.sunionrec.ures_cnt);
        t01int4(ak_sem, 'KEY_CNT_OFFS', key_cnt_offs);
        t01int4 (ak_sem, ' return_code', a_return_segm^.sp1r_returncode);
        t01int4 (ak_sem, 'command_kind', ord(a_command_kind));
&       ENDIF
        END;
    (*ENDIF*) 
    IF  (a_return_segm^.sp1r_returncode         = 0)                   AND
        (a_max_intern_select = a_intern_select_cnt) AND
        ((a_command_kind     = single_command) OR
        ( a_command_kind     = last_command))       AND
        (NOT is_insert_select)
    THEN
        BEGIN
        dummybuf := NIL;
        IF  (pos = cak_extern_pos)
        THEN
            BEGIN
            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;
            (* PTS 1001532 E.Z. *)
            a_mblock.mb_qual^.mr_resnum[1] := csp_defined_byte;
            s41p4int (a_mblock.mb_qual^.mr_resnum, 2,
                  a_unionrec_ptr^.sunionrec.ures_cnt, res);
            a507select_part( acv, pos, dummybuf, parsk, dmli, ssr_rec);
            dmli.d_repl_reskey := rep_res;
            END;
        (*ENDIF*) 
        a_union_cnt   := 0;
        a_result_name := resname;
        IF  a_unionrec_ptr^.sunionrec.ures_cnt = 0
        THEN
            BEGIN
            a07_b_put_error (acv, e_row_not_found, 1)
            END
        ELSE
            IF  a_sqlmode = sqlm_oracle
            THEN
                a60rescount (acv, 0)
            ELSE
                a60rescount (acv, a_unionrec_ptr^.sunionrec.ures_cnt)
            (*ENDIF*) 
        (*ENDIF*) 
        END
    ELSE
        a_union_cnt := 0;
    (*ENDIF*) 
    IF  b_err <> e_ok
    THEN
        a07_b_put_error (acv, b_err, a_cmd_part^.sp1p_buf_len);
    (*ENDIF*) 
    IF  (a_return_segm^.sp1r_returncode = 0)  OR
        (a_return_segm^.sp1r_returncode = 100)
    THEN
        a10rel_sysinfo (a_unionrec_ptr);
    (*ENDIF*) 
    a_unionrec_ptr := munionbuf;
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak503build_union_result (
            VAR acv              : tak_all_command_glob;
            VAR dmli              : tak_dml_info;
            VAR first_tree        : tgg00_FileId;
            VAR second_tree       : tgg00_FileId;
            VAR res_cnt           : tsp_int4;
            VAR key_cnt_offs      : tsp_int4;
            second_res_cnt        : tsp_int4;
            first                 : boolean;
            one_union_select_call : boolean);
 
VAR
      send_mess_buf     : boolean;
      e                 : tgg_basis_error;
      res               : tsp_num_error;
      ic2               : tsp_int_map_c2;
      uinv1_id          : tgg00_FileId;
      uinv2_id          : tgg00_FileId;
      sub_del_help_tree : tgg00_FileId;
      union_kind        : tsp00_Uint1;
      strat_len         : integer;
 
VAR
      strat            : tgg07_StrategyInfo;
 
BEGIN
WITH acv, a_mblock DO
    BEGIN
&   IFDEF TRACE
    t01int4 (ak_sem, 'one_union_se', ord (one_union_select_call));
    t01int4 (ak_sem, 'first       ', ord (first));
    t01int4 (ak_sem, 'res_cnt     ', res_cnt);
    t01int4 (ak_sem, 'res_cnt 2   ', second_res_cnt);
    t01treeid (ak_sem, 'first_tree  ', first_tree);
    t01treeid (ak_sem, 'second_tree ', second_tree);
&   ENDIF
    g04build_temp_tree_id (sub_del_help_tree, a_transinf.tri_trans);
    sub_del_help_tree.fileTfnTemp_gg00 := ttfnSubquery_egg00;
    WITH a_unionrec_ptr^.sunionrec DO
        BEGIN
        sub_del_help_tree.fileLevel_gg00[ 1 ] := chr(usubcount);
        IF  usubcount > 0
        THEN
            a06subquery_del_result (acv,
                  dmli, sub_del_help_tree, mxgg_tempprefix + 3);
&       IFDEF TRACE
        (*ENDIF*) 
        t01treeid (ak_sem, 'sub_del_help', sub_del_help_tree);
&       ENDIF
        END;
    (*ENDWITH*) 
    e             := e_ok;
    send_mess_buf := true;
&   IFDEF TRACE
    WITH a_unionrec_ptr^.sunionrec DO
        IF  first 
            AND 
            (( urowno = cgg_at_least_one_record ) OR ( urowno = cgg_subquery_one_record )) 
            AND
            (( a_union_kind = 1 ) OR ( a_union_kind = 4 ))
        THEN
            t01int4 (ak_sem, '$urowno     ', urowno);
&       ENDIF
        (*ENDIF*) 
    (*ENDWITH*) 
    IF  first AND
        ((a_unionrec_ptr^.sunionrec.urowno = cgg_at_least_one_record) OR
        (a_unionrec_ptr^.sunionrec.urowno = cgg_subquery_one_record)) AND
        ((a_union_kind = 1) OR (a_union_kind = 4))
    THEN
        CASE a_unionrec_ptr^.sunionrec.urowno OF
            cgg_at_least_one_record :
                IF  (res_cnt = 0) AND (second_res_cnt <> 0)
                THEN
                    BEGIN
                    res_cnt       := second_res_cnt;
                    send_mess_buf := false;
                    a06move_file_content (acv, second_tree,
                          first_tree, e);
                    IF  e <> e_ok
                    THEN
                        a07_b_put_error (acv, e, 1)
                    ELSE
                        BEGIN
                        mb_qual^.mr_resnum[ 1 ] := csp_defined_byte;
                        mb_qual^.mr_restree     := first_tree;
                        mb_qual_len  := mxgg_mb_part1head +
                              sizeof(tsp_resnum) + 1 + mxgg_treeid;
                        mb_data_len           := 0;
                        a_mblock.mb_type    := m_return_result;
                        mb_type2              := mm_file
                        END;
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    send_mess_buf := false;
                    a06destroy_temp (acv, second_tree, e);
                    END;
                (*ENDIF*) 
            cgg_subquery_one_record :
                IF  (a_max_intern_select = a_intern_select_cnt) AND
                    ((a_union_kind = 4) AND (res_cnt + second_res_cnt >= 2)) OR
                    ((a_union_kind = 1) AND (res_cnt >= 2))
                THEN
                    BEGIN
                    send_mess_buf := false;
                    a06destroy_temp (acv, first_tree, e);
                    a06destroy_temp (acv, second_tree, e);
                    a07_b_put_error (acv, e_too_many_resultsets, 1);
                    END;
                (*ENDIF*) 
            OTHERWISE : ;
            END;
        (*ENDCASE*) 
    (*ENDIF*) 
    IF  (( res_cnt = 0 ) OR ( second_res_cnt = 0 ) AND send_mess_buf )
        AND (NOT one_union_select_call)
    THEN
        BEGIN
&       IFDEF TRACE
        t01int4 (ak_sem, '$acv_union_k', a_union_kind);
&       ENDIF
        CASE a_union_kind OF
            1, 4 : (* union, union all *)
                IF  ( res_cnt = 0 ) AND ( second_res_cnt <> 0 )
                THEN
                    BEGIN
                    uinv2_id                  := second_tree;
                    uinv2_id.fileTfnTemp_gg00 := ttfnUnionIndex_egg00;
                    uinv2_id.fileRoot_gg00    := NIL_PAGE_NO_GG00;
                    uinv1_id                  := first_tree;
                    uinv1_id.fileTfnTemp_gg00 := ttfnUnionIndex_egg00;
                    uinv1_id.fileRoot_gg00    := NIL_PAGE_NO_GG00;
&                   IFDEF TRACE
                    t01treeid (ak_sem, '$uinv2_id   ', uinv2_id);
&                   ENDIF
                    res_cnt := second_res_cnt;
                    a06move_file_content(acv, second_tree,
                          first_tree, e);
                    IF  e <> e_ok
                    THEN
                        a07_b_put_error (acv, e, 1)
                    (*ENDIF*) 
                    END
                ELSE
                    IF  second_res_cnt = 0
                    THEN
                        a06destroy_temp (acv, second_tree, e);
                    (*ENDIF*) 
                (*ENDIF*) 
            2, 5 : (* except, except all *)
                a06destroy_temp (acv, second_tree, e);
            3, 6 : (* intersect, intersect all *)
                BEGIN
                IF  res_cnt <> 0
                THEN
                    BEGIN
                    res_cnt := 0;
                    uinv1_id                  := first_tree;
                    uinv1_id.fileTfnTemp_gg00 := ttfnUnionIndex_egg00;
                    uinv1_id.fileRoot_gg00    := NIL_PAGE_NO_GG00;
                    a06tempfile_empty (acv, first_tree, e);
                    a06tempfile_empty (acv, uinv1_id, e);
                    END;
                (*ENDIF*) 
                a06destroy_temp (acv, second_tree, e);
                END;
            END;
        (*ENDCASE*) 
        send_mess_buf           := false;
        mb_qual^.mr_resnum[ 1 ] := csp_defined_byte;
        mb_qual^.mr_restree     := first_tree;
        mb_qual_len  := mxgg_mb_part1head +
              sizeof(tsp_resnum) + 1 + mxgg_treeid;
        mb_data_len           := 0;
        a_mblock.mb_type    := m_return_result;
        mb_type2              := mm_file
        END;
    (*ENDIF*) 
    IF  e <> e_ok
    THEN
        a07_b_put_error (acv, e, 1);
    (*ENDIF*) 
    IF  send_mess_buf AND ( a_return_segm^.sp1r_returncode = 0 )
    THEN
        BEGIN
        IF  one_union_select_call
        THEN
            (* *** kb is called with a combinied union-select-call,         *)
            (*     that means, that union-call and select-call will be      *)
            (*     executed at one time.                                *** *)
            WITH  strat, mb_qual^ DO
                BEGIN
&               IFDEF TRACE
                t01messblock (ak_sem, 'MBLOCK 503bu', a_mblock);
&               ENDIF
                strat_len := mb_st^ [mstrat_pos].elen_var;
                IF  strat_len > sizeof(strat)
                THEN
                    strat_len := sizeof(strat);
                (*ENDIF*) 
                g10mv2 ('VAK503',   1,    
                      mb_strat_size, sizeof( strat ),
                      mb_strat^, mb_st^[ mstrat_pos ].epos,
                      strat, 1, strat_len,
                      a_return_segm^.sp1r_returncode);
                str_foundresults       := res_cnt;
                str_union_key_cnt_offs := key_cnt_offs;
                str_maxresults         := cgg_no_rowno_predicate;
&               IFDEF TRACE
                t01treeid (ak_sem, 'first_tree  ', first_tree);
                t01treeid (ak_sem, 'qual.mtree  ', mb_qual^.mtree);
&               ENDIF
                str_result_id := first_tree;
                str_result_id.fileHandling_gg00 := str_result_id.fileHandling_gg00 -
                      [hsCreateFile_egg00];
                IF  res_cnt > 0
                THEN
                    IF   a_unionrec_ptr^.sunionrec.uappend_all
                    THEN
                        str_union_kind := a_union_kind + cgg_union_select +
                              cgg_union_append
                    ELSE
                        str_union_kind := a_union_kind + cgg_union_select;
                    (*ENDIF*) 
&               IFDEF TRACE
                (*ENDIF*) 
                t01int4 (ak_sem, 'str_union_ki', str_union_kind);
&               ENDIF
                g10mv3 ('VAK503',   2,    
                      sizeof( strat ), mb_strat_size,
                      strat, 1,
                      mb_strat^, mb_st^[ mstrat_pos ].epos,
                      strat_len, a_return_segm^.sp1r_returncode);
                a06dml_send_mess_buf (acv, a_mblock, dmli, e);
                IF  a_sub_found
                THEN
                    WITH a_unionrec_ptr^.sunionrec DO
                        BEGIN
                        a_sub_found := false;
                        g04build_temp_tree_id (sub_del_help_tree,
                              a_transinf.tri_trans);
                        sub_del_help_tree.fileTfnTemp_gg00   := ttfnSubquery_egg00;
                        IF  (dmli.d_sparr.px[ 1 ]^.sparsinfo.p_subcntlevel
                            >= 0)
                        THEN
                            sub_del_help_tree.fileLevel_gg00[ 1 ] :=
                                  chr(dmli.d_sparr.px[ 1 ]^.sparsinfo.p_subcntlevel);
                        (*ENDIF*) 
                        a06subquery_del_result (acv,
                              dmli, sub_del_help_tree,
                              mxgg_tempprefix + 3);
                        END;
                    (*ENDWITH*) 
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        ELSE
            BEGIN
            a06a_mblock_init (acv, m_union, mm_nil, first_tree);
            g10mv1 ('VAK503',   3,    
                  sizeof(second_tree), mb_qual_size,
                  second_tree, 1, mb_qual^.buf, mxgg_mb_part1head + 1,
                  sizeof(second_tree), a_return_segm^.sp1r_returncode);
            IF   a_unionrec_ptr^.sunionrec.uappend_all
            THEN
                union_kind := ord (a_union_kind) + cgg_union_append
            ELSE
                union_kind := a_union_kind;
            (*ENDIF*) 
&           IFDEF TRACE
            t01int4 (ak_sem, 'str_union_ki', union_kind);
&           ENDIF
            mb_qual^.buf [ mxgg_mb_part1head + mxgg_treeid + 1 ] :=
                  chr (union_kind);
            s20ch4a (res_cnt, mb_qual^.buf,
                  mxgg_mb_part1head + mxgg_treeid + 2);
            s20ch4a (key_cnt_offs, mb_qual^.buf,
                  mxgg_mb_part1head + mxgg_treeid + 6);
            mb_qual_len  := mb_qual_len  + mxgg_treeid + 9;
            WITH a_unionrec_ptr^.sunionrec DO
                BEGIN
                IF  first
                THEN
                    ic2.map_int := urowno
                ELSE
                    ic2.map_int := cgg_no_rowno_predicate;
                (*ENDIF*) 
                mb_qual^.buf[ mb_qual_len  + 1 ] := ic2.map_c2[ 1 ];
                mb_qual^.buf[ mb_qual_len  + 2 ] := ic2.map_c2[ 2 ];
                END;
            (*ENDWITH*) 
            mb_qual_len  := mb_qual_len  + 2;
            a06rsend_mess_buf (acv, a_mblock, cak_return_req, e);
            END;
        (*ENDIF*) 
        IF  e <> e_ok
        THEN
            a07_b_put_error (acv, e, a_cmd_part^.sp1p_buf_len);
        (*ENDIF*) 
        IF  a_return_segm^.sp1r_returncode = 0
        THEN
            s40g4int (a_mblock.mb_qual^.mr_resnum, 2,
                  res_cnt, res);
        (*ENDIF*) 
        IF  (a_return_segm^.sp1r_returncode = 0) OR
            (a_return_segm^.sp1r_returncode =
            a07_return_code(e_row_not_found, a_sqlmode))
        THEN
            s40g4int (a_mblock.mb_qual^.mr_keycnt, 2, key_cnt_offs, res);
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak503loop_union (
            VAR acv                : tak_all_command_glob;
            VAR dmli                : tak_dml_info;
            VAR change_rec          : tak_changerecord;
            upos                    : tsp_int2;
            output_during_execution : boolean;
            first                   : boolean;
            VAR res_tree            : tgg00_FileId;
            VAR res_cnt             : tsp_int4;
            VAR key_cnt_offs        : tsp_int4);
 
VAR
      one_union_select_call : boolean;
      res                   : tsp_num_error;
      second_res_cnt        : tsp_int4;
      second_tree           : tgg00_FileId;
      i                     : integer;
 
BEGIN
WITH acv DO
    BEGIN
&   IFDEF TRACE
    WITH a_unionrec_ptr^.sunionrec.uselect_arr[ upos ] DO
        BEGIN
        t01int4 (ak_sem, 'upos        ', upos);
        t01int4 (ak_sem, 'ufirstsel   ', ufirstsel);
        t01int4 (ak_sem, 'usecondsel  ', usecondsel);
        t01int4 (ak_sem, 'uis_all     ', ord(uis_all));
        IF  uis_kind = uis_none
        THEN
            t01name (ak_sem, 'IS NONE           ');
        (*ENDIF*) 
        IF  uis_kind = uis_union
        THEN
            t01name (ak_sem, 'IS UNION          ');
        (*ENDIF*) 
        IF  uis_kind = uis_except
        THEN
            t01name (ak_sem, 'IS EXCEPT         ');
        (*ENDIF*) 
        IF  uis_kind = uis_intersect
        THEN
            t01name (ak_sem, 'IS INTERSECT      ');
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
&   ENDIF
    IF  (a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_kind
        = uis_union)  OR
        (a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_kind
        = uis_except) OR
        (a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_kind
        = uis_intersect)
    THEN
        BEGIN
        a_union_kind := cgg_union_byte;
        ak503loop_union (acv, dmli, change_rec,
              a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].ufirstsel,
              output_during_execution, NOT c_first, res_tree,
              res_cnt, key_cnt_offs);
&       IFDEF TRACE
        t01int4 (ak_sem, 'RES_CNT 5032', res_cnt );
        t01int4 (ak_sem, 'KEY_CNT_OFFS', key_cnt_offs);
        t01int4 (ak_sem, ' return_code', a_return_segm^.sp1r_returncode);
&       ENDIF
        IF  a_return_segm^.sp1r_returncode = 0
        THEN
            BEGIN
            a_union_kind   := 0;
            second_res_cnt := 0;
&           IFDEF TRACE
            t01int4 (ak_sem, 'return_loop:', 1);
&           ENDIF
            ak503loop_union (acv, dmli, change_rec,
                  a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].usecondsel,
                  output_during_execution, NOT c_first, second_tree,
                  second_res_cnt, key_cnt_offs);
            CASE  a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_kind OF
                uis_union     :
                    a_union_kind := cgg_union_byte;
                uis_except    :
                    a_union_kind := cgg_except_byte;
                uis_intersect :
                    a_union_kind := cgg_intersect_byte;
                END;
            (*ENDCASE*) 
            IF  a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_all
            THEN
                a_union_kind := a_union_kind + 3;
            (*ENDIF*) 
            i := a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].usecondsel;
            one_union_select_call := (NOT a_send_messbuf)                 AND
                  (a_union_cnt > 1)                                       AND
                  ((a_unionrec_ptr^.sunionrec.uappend_all AND
                  (NOT a_first_union)             AND
                  (NOT first)                                        ) OR
                  (i > a_unionrec_ptr^.sunionrec.uselect_arr[ i ].usecondsel));
            IF  a_return_segm^.sp1r_returncode = 0
            THEN
                ak503build_union_result (acv, dmli, res_tree,
                      second_tree, res_cnt, key_cnt_offs,
                      second_res_cnt, first, one_union_select_call);
&           IFDEF TRACE
            (*ENDIF*) 
            t01int4 (ak_sem, 'RES_CNT 5033', res_cnt);
            t01int4 (ak_sem, 'SEC_RES_CNT ', second_res_cnt);
            t01int4 (ak_sem, 'KEY_CNT_OFFS', key_cnt_offs);
            t01int4 (ak_sem, ' return_code', a_return_segm^.sp1r_returncode);
&           ENDIF
            END
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        (* *** Paranthesesis may cause executing of an "inner"-            *)
        (*     union-select as first select. In this case it is            *)
        (*     necessary to execute the union and the select with two      *)
        (*     different kb-calls. "a_first_union" indicates that such     *)
        (*     a union exists at this time.                            *** *)
        a_first_union := (upos > a_next_upos);
&       IFDEF TRACE
        t01int4 (ak_sem, 'a_first_unio', ord (a_first_union));
        t01int4 (ak_sem, 'upos        ', upos);
        t01int4 (ak_sem, 'a_next_upos ', a_next_upos);
&       ENDIF
        a_next_upos   := succ (upos);
        a_union_cnt   := succ (a_union_cnt);
        a501exec_with_change_rec (acv, dmli,
              a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uparsid,
              change_rec, output_during_execution);
&       IFDEF TRACE
        t01int4(ak_sem, 'RES_CNT     ', res_cnt);
&       ENDIF
        IF  (a_return_segm^.sp1r_returncode = 0)     AND
            (a_first_union     OR
            (a_union_cnt <= 1) OR
            a_send_messbuf           )
        THEN
            BEGIN
            s40g4int (a_mblock.mb_qual^.mr_resnum, 2,
                  res_cnt, res);
            res_tree     := a_mblock.mb_qual^.mr_restree;
            key_cnt_offs := key_cnt_offs + res_cnt;
            END;
&       IFDEF TRACE
        (*ENDIF*) 
        t01int4 (ak_sem, 'RES_CNT 5034', res_cnt);
        t01int4 (ak_sem, 'KEY_CNT_OFFS', key_cnt_offs);
        t01int4 (ak_sem, ' return_code', a_return_segm^.sp1r_returncode);
&       ENDIF
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
*-PRETTY-*  statements    :        305
*-PRETTY-*  lines of code :        790        PRETTYX 3.10 
*-PRETTY-*  lines in file :       1208         1997-12-10 
.PA 
