.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 : VAK503
changed : 2000-09-11
module  : Executing_union
 
Author  : ElkeZ
Created : 1985-10-16
*****************************************************
 
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         : tgg00_SysInfoKey;
              a01_il_b_identifier   : tsp00_KnlIdentifier;
              a01_union_fill_resname: tsp00_KnlIdentifier;
              a01_zero_res_name     : tsp00_KnlIdentifier;
 
      ------------------------------ 
 
        FROM
              AK_universal_semantic_tools : VAK06;
 
        PROCEDURE
              a06dml_send_mess_buf (
                    VAR acv    : tak_all_command_glob;
                    VAR mblock : tgg00_MessBlock;
                    VAR dmli   : tak_dml_info;
                    VAR b_err  : tgg00_BasisError);
 
        PROCEDURE
              a06drop_fieldlist_references (VAR fieldlists : tgg00_FieldLists);
 
        PROCEDURE
              a06a_mblock_init (
                    VAR acv      : tak_all_command_glob;
                    mtype        : tgg00_MessType;
                    m2type       : tgg00_MessType2;
                    VAR tree     : tgg00_FileId);
 
        PROCEDURE
              a06move_file_content (
                    VAR acv    : tak_all_command_glob;
                    VAR old_id : tgg00_FileId;
                    VAR new_id : tgg00_FileId;
                    VAR b_err  : tgg00_BasisError);
 
        PROCEDURE
              a06rsend_mess_buf (
                    VAR acv      : tak_all_command_glob;
                    VAR mblock   : tgg00_MessBlock;
                    result_req   : boolean;
                    VAR e        : tgg00_BasisError);
 
        PROCEDURE
              a06tempfile_empty (
                    VAR acv     : tak_all_command_glob;
                    VAR temp_id : tgg00_FileId;
                    VAR b_err   : tgg00_BasisError);
 
        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   : tgg00_BasisError;
                    err_code : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK071;
 
        FUNCTION
              a071_return_code (
                    b_err   : tgg00_BasisError;
                    sqlmode : tsp00_SqlMode) : tsp00_Int2;
 
      ------------------------------ 
 
        FROM
              Systeminfo_cache : VAK10;
 
        PROCEDURE
              a10_copy_catalog_rec (
                    VAR acv         : tak_all_command_glob;
                    VAR old_key     : tgg00_SysInfoKey;
                    del_old_rec     : boolean;
                    VAR new_key     : tgg00_SysInfoKey;
                    new_segment_id  : tsp00_C2;
                    add_new_rec     : boolean;
                    VAR b_err       : tgg00_BasisError);
 
        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
              a10rel_sysinfo (syspointer : tak_sysbufferaddress);
 
      ------------------------------ 
 
        FROM
              SQLManager : vak101;
 
        FUNCTION
              a101_IsExtendedTempFile(
                    VAR acv    : tak_all_command_glob;
                    VAR fileId : tgg00_FileId(*ptocConst*)) : boolean;
 
        FUNCTION
              a101_GetExtendedTempFileType(
                    VAR acv        : tak_all_command_glob;
                    VAR tempFileId : tgg00_FileId(*ptocConst*)) : tgg00_TfnTemp;
 
        PROCEDURE
              a101_SetTempFileLevel(
                    VAR acv        : tak_all_command_glob;
                    VAR tempFileId : tgg00_FileId;
                    level          : tsp00_Int2(*ptocConst*));
 
        PROCEDURE
              a101_DestroyGroupedTempFile(
                    VAR trans      : tgg00_TransContext;
                    VAR tempFileId : tgg00_FileId);
 
      ------------------------------ 
 
        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    : tak71_select_strat_rec);
 
      ------------------------------ 
 
        FROM
              Select_Syntax : VAK60;
 
        PROCEDURE
              a60rescount (
                    VAR acv  : tak_all_command_glob;
                    rescount : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              Resultname_handling : VAK663;
 
        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
              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);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-20 : VSP20;
 
        PROCEDURE
              s20int4_to_buf (
                    val      : tsp00_Int4;
                    VAR dest : tsp00_Buf;
                    di       : tsp00_Int4);
 
      ------------------------------ 
 
        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
              t01command_kind (
                    debug        : tgg00_Debug;
                    nam          : tsp00_Sname;
                    command_kind : tak_commandkind);
 
        PROCEDURE
              t01union_kind (
                    debug   : tgg00_Debug;
                    nam     : tsp00_Sname;
                    ukind   : tak_union_kind;
                    uis_all : boolean);
 
        PROCEDURE
              t01messtype (
                    debug        : tgg00_Debug;
                    nam          : tsp00_Sname;
                    mess_type    : tgg00_MessType);
 
        PROCEDURE
              t01sname (
                    debug   : tgg00_Debug;
                    nam     : tsp00_Sname);
 
        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
              s20int4_to_buf;
 
              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 -------------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
CONST
      c_del_old_rec      = true (* a10_copy_catalog_rec *);
      c_add_new_rec      = true (* a10_copy_catalog_rec *);
      c_first            = true (* ak503one_union_part *);
      c_make_new_res     = true (* a663_get_result_info *);
 
 
(*------------------------------*) 
 
PROCEDURE
      a503build_union_buffer (
            VAR acv : tak_all_command_glob;
            in_join : boolean);
 
VAR
      _gg_strategy_ptr : ^tgg07_StrategyInfo;
 
BEGIN
_gg_strategy_ptr := @acv.a_mblock.
      mb_strat^[ acv.a_mblock.mb_st^[ acv.a_mblock.mb_qual^.mstrat_pos ].epos ];
_gg_strategy_ptr^.str_union_kind := acv.a_union_kind;
&ifdef trace
t01int4( ak_sem, 'str_union_ki', _gg_strategy_ptr^.str_union_kind );
&endif
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            : tgg00_BasisError;
      _res              : tsp00_NumError;
      _i                : integer;
      _pos              : integer;
      _key_cnt_offs     : tsp00_Int4;
      _res_cnt          : tsp00_Int4;
      _ke               : tgg00_SysInfoKey;
      _dummybuf         : tak_sysbufferaddress;
      _munionbuf        : tak_sysbufferaddress;
      _union_id         : tgg00_FileId;
      _is_insert_select : boolean;
      _f_ok             : boolean;
      _resname          : tsp00_KnlIdentifier;
      _modul_name       : tsp00_KnlIdentifier;
      _rep_res          : boolean;
      _ssr_rec          : tak71_select_strat_rec;
      _sub_del_help_tree: tgg00_FileId;
 
BEGIN
&IFDEF TRACE
t01int4 (ak_sem,  'parsk.p_id  ', ord(parsk.p_id[ 1 ]));
t01messtype (ak_sem,  'parsk.p_kind', parsk.p_kind);
t01int4 (ak_sem,  'parsk.p_no  ', ord(parsk.p_no));
&ENDIF
_pos            := cak_intern_pos;
_munionbuf      := acv.a_unionrec_ptr;
_ke             := a01sysnullkey;
_ke.sauthid[ 1 ] := cak_tempinfo_byte;
_is_insert_select:= false;
_res_cnt         := 0;
SAPDB_PascalForcedMove (sizeof(parsk), sizeof(_ke.sauthid), @parsk, 1,
      @_ke.sauthid, 2, mxak_parskey );
_ke.sentrytyp := cak_eunionrec;
a10get_sysinfo ( acv, _ke, d_fix, acv.a_unionrec_ptr, _b_err);
IF  _b_err <> e_ok
THEN
    a07_b_put_error (acv, _b_err, 1)
ELSE
    BEGIN
&   IFDEF TRACE
    t01name( ak_sem, 'UNION EXECUTION   ');
    WITH acv.a_unionrec_ptr^.sunionrec DO
        FOR _i := 1 TO uselect_cnt - 1 DO
            BEGIN
            t01int4 (ak_sem, 'index       ', _i);
            t01union_kind (ak_sem, 'uis_kind    ', uselect_arr [ _i ].uis_kind,
                  uselect_arr [ _i ].uis_all);
            t01int4 (ak_sem, 'ufirstsel   ', uselect_arr [ _i ].ufirstsel);
            t01int4 (ak_sem, 'usecondsel  ', uselect_arr [ _i ].usecondsel);
            t01sname( ak_sem, '+----------+' );
            END;
        (*ENDFOR*) 
    (*ENDWITH*) 
&   ENDIF
    acv.a_union_cnt  := 0;
    acv.a_next_upos  := cak_is_undefined; (* Sequence of unions *)
&   IFDEF TRACE
    t01int4 (ak_sem, 'max_intern_s', acv.a_max_intern_select);
    t01int4 (ak_sem, 'intern_selec', acv.a_intern_select_cnt);
    t01command_kind (ak_sem, 'command_kind', acv.a_command_kind);
    t01lidentifier (ak_syn, acv.a_modul_name);
    t01lidentifier (ak_syn, acv.a_unionrec_ptr^.sunionrec.umodul_name);
&   ENDIF
    IF  acv.a_unionrec_ptr^.sunionrec.ures_name <> a01_union_fill_resname
    THEN
        BEGIN
        WITH acv.a_unionrec_ptr^.sunionrec.ures_tree DO
            IF  a101_IsExtendedTempFile (acv, acv.a_unionrec_ptr^.sunionrec.ures_tree)
                AND (a101_GetExtendedTempFileType (acv,
                acv.a_unionrec_ptr^.sunionrec.ures_tree)
                = ttfnUserResult_egg00)
            THEN
                BEGIN
                IF  dmli.d_resname <> a01_zero_res_name
                THEN
                    IF  (acv.a_unionrec_ptr^.sunionrec.ures_name <>
                        a01_il_b_identifier) AND
                        (acv.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 := acv.a_unionrec_ptr^.
                              sunionrec.umodul_name;
                        END
                    (*ENDIF*) 
                ELSE
                    BEGIN
                    _resname    := acv.a_unionrec_ptr^.sunionrec.ures_name;
                    _modul_name := acv.a_unionrec_ptr^.sunionrec.umodul_name;
                    END;
                (*ENDIF*) 
                _pos := cak_extern_pos
                END
            ELSE
                BEGIN
                _resname    := acv.a_unionrec_ptr^.sunionrec.ures_name;
                _modul_name := acv.a_unionrec_ptr^.sunionrec.umodul_name;
                _pos        := cak_intern_pos
                END;
            (*ENDIF*) 
        (*ENDWITH*) 
        a663_get_result_info (acv, _resname, _modul_name,
              acv.a_resname_addr[ _pos ], c_make_new_res,
              a101_GetExtendedTempFileType (acv, acv.a_unionrec_ptr^.sunionrec.ures_tree),
              d_fix, _f_ok);
        END;
    (*ENDIF*) 
    _union_id         := acv.a_unionrec_ptr^.sunionrec.ures_tree;
    _is_insert_select := acv.a_unionrec_ptr^.sunionrec.uinsertselect;
    _key_cnt_offs     := 0;
    ak503one_union_part (acv, dmli, change_rec, 1(*top*), output_during_execution,
          c_first, _union_id, _res_cnt, _key_cnt_offs);
&   IFDEF TRACE
    t01int4(ak_sem, '_res_cnt    ', _res_cnt);
    t01int4(ak_sem, '_key_cnt_off', _key_cnt_offs);
    t01int4 (ak_sem, ' return_code', acv.a_returncode);
    t01command_kind (ak_sem, 'command_kind', acv.a_command_kind);
&   ENDIF
    END;
(*ENDIF*) 
IF  ( acv.a_returncode = 0 )
    AND
    ( acv.a_max_intern_select = acv.a_intern_select_cnt )
    AND
    (( acv.a_command_kind = single_command ) OR
    ( acv.a_command_kind = last_command ))
    AND
    (NOT _is_insert_select)
THEN
    BEGIN
    _dummybuf := NIL;
    IF  (_pos = cak_extern_pos)
    THEN
        BEGIN
        (* PTS 1119981 E.Z. *)
        IF  (dmli.d_resname_found AND
            (dmli.d_resname <> a01_zero_res_name) AND
            (dmli.d_resname <> acv.a_resname_addr[ _pos ]^.sresname.reskey_name))
        THEN
            BEGIN
            _ke := acv.a_resname_addr[ _pos ]^.syskey;
            _ke.srestablen := dmli.d_resname;
            a10_copy_catalog_rec (acv, acv.a_resname_addr[ _pos ]^.syskey,
                  c_del_old_rec, _ke, cak00_local_segment_id,
                  NOT c_add_new_rec, _b_err);
            IF  _b_err <> e_ok
            THEN
                a07_b_put_error (acv, _b_err, 1)
            ELSE
                a10get_sysinfo ( acv, _ke, d_fix, acv.a_resname_addr[ _pos ], _b_err);
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        _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;
        (* PTS 1001532 E.Z. *)
        acv.a_mblock.mb_qual^.mr_resnum[1] := csp_defined_byte;
        s41p4int (acv.a_mblock.mb_qual^.mr_resnum, 2, _res_cnt, _res);
        a507select_part( acv, _pos, _dummybuf, parsk, dmli, _ssr_rec);
        dmli.d_repl_reskey := _rep_res;
        END;
    (*ENDIF*) 
    acv.a_union_cnt   := 0;
    acv.a_result_name := _resname;
    IF  _res_cnt = 0
    THEN
        BEGIN
        a07_b_put_error (acv, e_row_not_found, 1)
        END
    ELSE
        IF  acv.a_sqlmode = sqlm_oracle
        THEN
            a60rescount (acv, 0)
        ELSE
            a60rescount (acv, _res_cnt)
        (*ENDIF*) 
    (*ENDIF*) 
    END
ELSE
    acv.a_union_cnt := 0;
(*ENDIF*) 
IF  _b_err <> e_ok
THEN
    a07_b_put_error (acv, _b_err, 1);
(*ENDIF*) 
IF  (acv.a_returncode = 0)  OR
    (acv.a_returncode = 100)
THEN
    a10rel_sysinfo (acv.a_unionrec_ptr)
ELSE
    BEGIN
    g04build_temp_tree_id (_sub_del_help_tree, acv.a_transinf.tri_trans);
    _sub_del_help_tree.fileTfnTemp_gg00 := ttfnSubquery_egg00;
    a06subquery_del_result (acv, dmli,
          _sub_del_help_tree, TEMP_PREFIX_MXGG00+2);
    END;
(*ENDIF*) 
acv.a_unionrec_ptr := _munionbuf;
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           : tsp00_Int4;
            VAR key_cnt_offs      : tsp00_Int4;
            second_res_cnt        : tsp00_Int4;
            first                 : boolean);
 
VAR
      _do_set_operation  : boolean;
      _union_kind        : tsp00_Uint1;
      _e                 : tgg00_BasisError;
      _res               : tsp00_NumError;
      _uinv1_id          : tgg00_FileId;
      _uinv2_id          : tgg00_FileId;
      _sub_del_help_tree : tgg00_FileId;
      _strat_len         : integer;
      _strat             : tgg07_StrategyInfo;
 
      _ic4               : RECORD
            CASE boolean OF
                TRUE  :
                    (map_int : tsp00_Int4);
                FALSE :
                    (map_c4  : tsp00_C4)
                END;
            (*ENDCASE*) 
 
 
BEGIN
&IFDEF TRACE
t01bool (ak_sem, 'TOP operator', first);
t01int4 (ak_sem, 'res_cnt 1   ', 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
IF  acv.a_unionrec_ptr^.sunionrec.usubcount > 0
THEN
    BEGIN
    g04build_temp_tree_id (_sub_del_help_tree, acv.a_transinf.tri_trans);
    _sub_del_help_tree.fileTfnTemp_gg00 := ttfnSubquery_egg00;
    a101_SetTempFileLevel (acv, _sub_del_help_tree,
          acv.a_unionrec_ptr^.sunionrec.usubcount);
&   ifdef trace
    t01treeid (ak_sem, 'sub_del_help', _sub_del_help_tree);
&   endif
    a06subquery_del_result (acv,
          dmli, _sub_del_help_tree, TEMP_PREFIX_MXGG00 + 3);
    END;
(*ENDIF*) 
_e := e_ok;
_do_set_operation := true;
IF  first AND
    ((acv.a_unionrec_ptr^.sunionrec.urowno = cgg04_at_least_one_record) OR
    (acv.a_unionrec_ptr^.sunionrec.urowno = cgg04_subquery_one_record)) AND
    ((acv.a_union_kind = cgg04_union_byte) OR
    (acv.a_union_kind = cgg04_union_byte + 3))
THEN
    BEGIN
&   ifdef trace
    t01int4 (ak_sem, '$urowno     ', acv.a_unionrec_ptr^.sunionrec.urowno);
&   endif
    CASE acv.a_unionrec_ptr^.sunionrec.urowno OF
        cgg04_at_least_one_record :
            IF  (res_cnt = 0) AND (second_res_cnt <> 0)
            THEN
                BEGIN
                res_cnt       := second_res_cnt;
                _do_set_operation := false;
                a06move_file_content (acv, second_tree, first_tree, _e);
                IF  _e <> e_ok
                THEN
                    a07_b_put_error (acv, _e, 1)
                ELSE
                    BEGIN
                    acv.a_mblock.mb_qual^.mr_resnum[ 1 ] := csp_defined_byte;
                    acv.a_mblock.mb_qual^.mr_restree     := first_tree;
                    acv.a_mblock.mb_qual_len  := MB_PART1_HEAD_MXGG00 +
                          sizeof(tsp00_ResNum) + 1 + FILE_ID_MXGG00;
                    acv.a_mblock.mb_data_len := 0;
                    acv.a_mblock.mb_type     := m_return_result;
                    acv.a_mblock.mb_type2    := mm_file
                    END;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                _do_set_operation := false;
                a101_DestroyGroupedTempFile (acv.a_transinf.tri_trans,
                      second_tree);
                _e := acv.a_transinf.tri_trans.trError_gg00;
                END;
            (*ENDIF*) 
        cgg04_subquery_one_record :
            IF  (acv.a_max_intern_select = acv.a_intern_select_cnt) AND
                ((acv.a_union_kind = cgg04_union_byte + 3) AND
                (res_cnt + second_res_cnt >= 2)) OR
                ((acv.a_union_kind = cgg04_union_byte) AND (res_cnt >= 2))
            THEN
                BEGIN
                _do_set_operation := false;
                a101_DestroyGroupedTempFile (acv.a_transinf.tri_trans,
                      first_tree);
                a101_DestroyGroupedTempFile (acv.a_transinf.tri_trans,
                      second_tree);
                a07_b_put_error (acv, e_too_many_resultsets, 1);
                END;
            (*ENDIF*) 
        OTHERWISE : ;
        END;
    (*ENDCASE*) 
    END;
(*ENDIF*) 
IF  (( res_cnt = 0 ) OR ( second_res_cnt = 0 ) AND _do_set_operation )
THEN
    BEGIN
    (* handling for special cases with empty sets *)
&   ifdef trace
    t01name( ak_sem, 'special set hndlng');
&   endif
    CASE acv.a_union_kind OF
        cgg04_union_byte, cgg04_union_byte + 3 : (* 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) AND _do_set_operation
                THEN
                    BEGIN
                    a101_DestroyGroupedTempFile (acv.a_transinf.tri_trans,
                          second_tree);
                    _e := acv.a_transinf.tri_trans.trError_gg00;
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
        cgg04_except_byte, cgg04_except_byte + 3 : (* except, except all *)
            BEGIN
            (* <empty set> EXCEPT <set> = <empty set>*)
            (* <set> EXCEPT <empty set> = <set>      *)
            (* therefore result is first_tree !!!!   *)
            a101_DestroyGroupedTempFile (acv.a_transinf.tri_trans, second_tree);
            _e := acv.a_transinf.tri_trans.trError_gg00;
            END;
        cgg04_intersect_byte, cgg04_intersect_byte + 3 : (* 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*) 
            a101_DestroyGroupedTempFile (acv.a_transinf.tri_trans, second_tree);
            _e := acv.a_transinf.tri_trans.trError_gg00;
            END;
        END;
    (*ENDCASE*) 
    acv.a_mblock.mb_qual^.mr_resnum[ 1 ] := csp_defined_byte;
    acv.a_mblock.mb_qual^.mr_restree     := first_tree;
    acv.a_mblock.mb_qual_len  := MB_PART1_HEAD_MXGG00 +
          sizeof(tsp00_ResNum) + 1 + FILE_ID_MXGG00;
    acv.a_mblock.mb_data_len           := 0;
    acv.a_mblock.mb_type    := m_return_result;
    acv.a_mblock.mb_type2              := mm_file;
    _do_set_operation := false;
    END;
(*ENDIF*) 
IF  _e <> e_ok
THEN
    a07_b_put_error (acv, _e, 1);
(*ENDIF*) 
IF  _do_set_operation AND ( acv.a_returncode = 0 )
THEN
    BEGIN
    (* first_tree becomes result file *)
    a06a_mblock_init (acv, m_union, mm_nil, first_tree);
    SAPDB_PascalMove ('VAK503',   1,    
          sizeof(second_tree), acv.a_mblock.mb_qual_size,
          @second_tree, 1, @acv.a_mblock.mb_qual^.buf, MB_PART1_HEAD_MXGG00 + 1,
          sizeof(second_tree), acv.a_returncode);
    (* neccessary i.e. SELECT DISTINCT or ORDER BY *)
    _union_kind := acv.a_union_kind;
&   ifdef trace
    t01int4 (ak_sem, '_union_kind ', _union_kind);
&   endif
    acv.a_mblock.mb_qual^.buf [ MB_PART1_HEAD_MXGG00 + FILE_ID_MXGG00 + 1 ] :=
          chr (_union_kind);
    s20int4_to_buf (res_cnt, acv.a_mblock.mb_qual^.buf,
          MB_PART1_HEAD_MXGG00 + FILE_ID_MXGG00 + 2);
    s20int4_to_buf (key_cnt_offs, acv.a_mblock.mb_qual^.buf,
          MB_PART1_HEAD_MXGG00 + FILE_ID_MXGG00 + 6);
    acv.a_mblock.mb_qual_len  := acv.a_mblock.mb_qual_len  + FILE_ID_MXGG00 + 9;
    IF  first
    THEN
        _ic4.map_int := acv.a_unionrec_ptr^.sunionrec.urowno
    ELSE
        _ic4.map_int := cgg04_no_rowno_predicate;
    (*ENDIF*) 
    acv.a_mblock.mb_qual^.buf[ acv.a_mblock.mb_qual_len  + 1 ] := _ic4.map_c4[ 1 ];
    acv.a_mblock.mb_qual^.buf[ acv.a_mblock.mb_qual_len  + 2 ] := _ic4.map_c4[ 2 ];
    acv.a_mblock.mb_qual^.buf[ acv.a_mblock.mb_qual_len  + 3 ] := _ic4.map_c4[ 3 ];
    acv.a_mblock.mb_qual^.buf[ acv.a_mblock.mb_qual_len  + 4 ] := _ic4.map_c4[ 4 ];
    acv.a_mblock.mb_qual_len  := acv.a_mblock.mb_qual_len + 4;
    a06rsend_mess_buf (acv, acv.a_mblock, cak_return_req, _e);
    IF  ( _e <> e_ok )
    THEN
        a07_b_put_error (acv, _e, 1);
    (*ENDIF*) 
    IF  ( acv.a_returncode = 0 )
    THEN
        s40g4int (acv.a_mblock.mb_qual^.mr_resnum, 2, res_cnt, _res);
    (*ENDIF*) 
    IF  (acv.a_returncode = 0) OR
        (acv.a_returncode =
        a071_return_code(e_row_not_found, acv.a_sqlmode))
    THEN
        s40g4int (acv.a_mblock.mb_qual^.mr_keycnt, 2, key_cnt_offs, _res);
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak503one_union_part (
            VAR acv                : tak_all_command_glob;
            VAR dmli                : tak_dml_info;
            VAR change_rec          : tak_changerecord;
            upos                    : tsp00_Int2;
            output_during_execution : boolean;
            first                   : boolean;
            VAR res_tree            : tgg00_FileId;
            VAR res_cnt             : tsp00_Int4;
            VAR key_cnt_offs        : tsp00_Int4);
 
VAR
      _second_tree           : tgg00_FileId;
      _second_res_cnt        : tsp00_Int4;
      _saved_set_kind        : tsp00_Int4;
      _res                   : tsp00_NumError;
 
BEGIN
&ifdef trace
t01int4 (ak_sem, 'upos        ', upos);
t01int4 (ak_sem, 'ufirstsel   ', acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].ufirstsel);
t01int4 (ak_sem, 'usecondsel  ', acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].usecondsel);
t01union_kind (ak_sem, 'uis_kind    ',
      acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_kind,
      acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_all);
t01int4 (ak_sem, 'res_cnt     ', res_cnt);
t01int4 (ak_sem, 'key_cnt_offs', key_cnt_offs);
&endif
IF  ( acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_kind <> uis_none )
THEN
    BEGIN
    CASE  acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_kind OF
        uis_union     :
            acv.a_union_kind := cgg04_union_byte;
        uis_except    :
            acv.a_union_kind := cgg04_except_byte;
        uis_intersect :
            acv.a_union_kind := cgg04_intersect_byte;
        END;
    (*ENDCASE*) 
    IF  acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_all
    THEN
        acv.a_union_kind := acv.a_union_kind + 3;
    (*ENDIF*) 
    _saved_set_kind := acv.a_union_kind;
&   ifdef trace
    t01name( ak_sem, 'first select !    ');
&   endif
    (* create first select *)
    ak503one_union_part (acv, dmli, change_rec,
          acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].ufirstsel,
          output_during_execution, NOT c_first, res_tree,
          res_cnt(*out*), key_cnt_offs(*out*));
    acv.a_union_kind := _saved_set_kind;
&   ifdef trace
    t01int4 (ak_sem, 'res_cnt     ', res_cnt );
    t01int4 (ak_sem, 'key_cnt_offs', key_cnt_offs);
    t01int4 (ak_sem, ' return_code', acv.a_returncode);
&   endif
    IF  acv.a_returncode = 0
    THEN
        BEGIN
        _second_res_cnt  := 0;
&       ifdef trace
        t01union_kind (ak_sem, 'select for  ',
              acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_kind,
              acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_all);
        t01name( ak_sem, 'second select !   ');
&       endif
        (* create second select *)
        ak503one_union_part (acv, dmli, change_rec,
              acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].usecondsel,
              output_during_execution, NOT c_first, _second_tree,
              _second_res_cnt, key_cnt_offs);
        acv.a_union_kind := _saved_set_kind;
        ;
&       ifdef trace
        t01bool (ak_sem, 'TOP union op', first);
        t01int4 (ak_sem, 'a_union_cnt ', acv.a_union_cnt);
        t01int4 (ak_sem, 'uselect_cnt ', acv.a_unionrec_ptr^.sunionrec.uselect_cnt);
        t01int4 (ak_sem, 'upos        ', upos);
        t01union_kind (ak_sem, '[u].uis_kind',
              acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_kind,
              acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uis_all);
        t01int4 (ak_sem, '[u].secondse',
              acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].usecondsel );
&       endif
        IF  acv.a_returncode = 0
        THEN
            (* create result of set operator *)
            ak503build_union_result( acv, dmli, res_tree,
                  _second_tree, res_cnt, key_cnt_offs,
                  _second_res_cnt, first );
&       IFDEF TRACE
        (*ENDIF*) 
        t01int4 (ak_sem, '_second_res_', _second_res_cnt);
        t01int4 (ak_sem, ' return_code', acv.a_returncode);
&       ENDIF
        END
    (*ENDIF*) 
    END
ELSE
    BEGIN
&   ifdef trace
    t01int4 (ak_sem, 'upos        ', upos);
    t01int4 (ak_sem, 'a_next_upos ', acv.a_next_upos);
&   endif
    acv.a_next_upos   := succ (upos);
    acv.a_union_cnt   := succ (acv.a_union_cnt);
    a501exec_with_change_rec (acv, dmli,
          acv.a_unionrec_ptr^.sunionrec.uselect_arr[ upos ].uparsid,
          change_rec, output_during_execution);
    IF  ( acv.a_returncode = 0 )
    THEN
        BEGIN
        s40g4int (acv.a_mblock.mb_qual^.mr_resnum, 2, res_cnt, _res);
        res_tree     := acv.a_mblock.mb_qual^.mr_restree;
        key_cnt_offs := key_cnt_offs + res_cnt;
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
&ifdef trace
t01int4 (ak_sem, 'res_cnt     ', res_cnt);
t01int4 (ak_sem, 'key_cnt_offs', key_cnt_offs);
t01int4 (ak_sem, ' return_code', acv.a_returncode);
t01int4 (ak_sem, 'upos        ', upos);
&endif
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
