.nf
 
 .nf
 
    ========== licence begin  GPL
    Copyright (c) 1999-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) 1999-2005 SAP AG
SAP Database Technology
 
Release :      Date : 2000-08-25
*****************************************************
modname : VAK52
changed : 2000-08-25
module  : AK_Lock_Commit_Rollback
 
Author  : ElkeZ
Created : 1985-02-01
*****************************************************
 
Purpose : Syntax analysis and processing of the commands:
          LOCK, UNLOCK, COMMIT, ROLLBACK, BEGIN SUBTRANS, END SUBTRANS
 
Define  :
 
        PROCEDURE
              a52_alock_statement (
                    VAR acv          : tak_all_command_glob;
                    VAR put_node     : tsp00_Int2);
 
        PROCEDURE
              a52_aunlock_statement (
                    VAR acv      : tak_all_command_glob;
                    VAR put_node : tsp00_Int2);
 
        PROCEDURE
              a52_acommit_rollback_statement
                    (VAR acv     : tak_all_command_glob;
                    VAR put_node : tsp00_Int2;
                    commit       : boolean);
 
        PROCEDURE
              a52_aforce_statement (
                    VAR acv      : tak_all_command_glob;
                    VAR put_node : tsp00_Int2);
 
        PROCEDURE
              a52_asavepoint (
                    VAR acv      : tak_all_command_glob;
                    VAR put_node : tsp00_Int2);
 
        PROCEDURE
              a52asubtrans_statement (
                    VAR acv      : tak_all_command_glob;
                    VAR put_node : tsp00_Int2);
 
        PROCEDURE
              a52_call_semantik (
                    VAR acv : tak_all_command_glob;
                    subproc : tsp00_Int2);
 
        PROCEDURE
              a52_lock_statement (
                    VAR acv    : tak_all_command_glob;
                    start_node : tsp00_Int2);
 
        PROCEDURE
              a52_ex_commit_rollback (
                    VAR acv        : tak_all_command_glob;
                    m_type         : tgg00_MessType;
                    n_rel          : boolean;
                    normal_release : boolean);
 
        PROCEDURE
              a52_rest_lock_statement (
                    VAR acv       : tak_all_command_glob;
                    VAR isparr    : tak_syspointerarr;
                    VAR back_lock : tak_ak_all_locks;
                    return_result : boolean;
                    complicate    : boolean);
 
        PROCEDURE
              a52free_caches (VAR acv : tak_all_command_glob);
 
        PROCEDURE
              a52new_subtrans (
                    VAR acv           : tak_all_command_glob;
                    VAR subtrans_name : tsp00_KnlIdentifier);
 
        PROCEDURE
              a52internal_subtrans (VAR acv : tak_all_command_glob);
 
        PROCEDURE
              a52end_rollback_subtrans (
                    VAR acv           : tak_all_command_glob;
                    VAR subtrans_name : tsp00_KnlIdentifier;
                    m_type : tgg00_MessType);
 
        PROCEDURE
              a52release_session (
                    VAR acv        : tak_all_command_glob;
                    normal_release : boolean);
 
        PROCEDURE
              a52init_subtrans_of_new_trans (VAR acv : tak_all_command_glob);
 
.CM *-END-* define --------------------------------------
***********************************************************
 
Use     :
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01kw                : tak_keywordtab;
              a01sysnullkey        : tgg00_SysInfoKey;
              a01defaultkey        : tgg00_SysInfoKey;
              a01_il_b_identifier   : tsp00_KnlIdentifier;
 
        PROCEDURE
              a01_next_symbol (VAR acv : tak_all_command_glob);
 
        PROCEDURE
              a01_is_end_symbol (VAR acv : tak_all_command_glob);
 
        PROCEDURE
              a01_call_put (
                    VAR acv    : tak_all_command_glob;
                    proc       : tak_procs;
                    subproc    : tsp00_Int2;
                    VAR curr_n : tsp00_Int2);
 
        FUNCTION
              a01_eqkey (
                    VAR a      : tak_keyword;
                    sqlmode    : tsp00_SqlMode;
                    VAR b      : tsp00_MoveObj;
                    VAR scv    : tak_scanner_glob) : boolean;
 
        FUNCTION
              a01mandatory_keyword (
                    VAR acv          : tak_all_command_glob;
                    required_keyword : integer) : boolean;
 
        PROCEDURE
              a01_force_symbol (
                    VAR acv         : tak_all_command_glob;
                    expected_symbol : tak_sc_symbol;
                    VAR node1       : tsp00_Int2;
                    VAR node2       : tsp00_Int2);
 
      ------------------------------ 
 
        FROM
              AK_syntax_tools : VAK02;
 
        PROCEDURE
              a02_put_identifier (
                    VAR acv       : tak_all_command_glob;
                    VAR put_node  : tsp00_Int2;
                    VAR last_node : tsp00_Int2);
 
        PROCEDURE
              a02_atablename (
                    VAR acv       : tak_all_command_glob;
                    VAR put_node  : tsp00_Int2;
                    VAR last_node : tsp00_Int2);
 
        PROCEDURE
              a02_l_atablename_list (
                    VAR acv       : tak_all_command_glob;
                    VAR put_node  : tsp00_Int2;
                    VAR last_node : tsp00_Int2);
 
      ------------------------------ 
 
        FROM
              AK_semantic_scanner_tools : VAK05;
 
        PROCEDURE
              a05identifier_get (
                    VAR acv     : tak_all_command_glob;
                    tree_index  : integer;
                    obj_len     : integer;
                    VAR moveobj : tsp00_KnlIdentifier);
 
      ------------------------------ 
 
        FROM
              AK_universal_semantic_tools : VAK06;
 
        PROCEDURE
              a06_systable_get (
                    VAR acv      : tak_all_command_glob;
                    dstate       : tak_directory_state;
                    VAR tableid  : tgg00_Surrogate;
                    VAR base_ptr : tak_sysbufferaddress;
                    get_all      : boolean;
                    VAR ok       : boolean);
 
        PROCEDURE
              a06a_mblock_init (
                    VAR acv      : tak_all_command_glob;
                    mtype        : tgg00_MessType;
                    m2type       : tgg00_MessType2;
                    VAR tree     : tgg00_FileId);
 
        PROCEDURE
              a06lsend_mess_buf (
                    VAR acv         : tak_all_command_glob;
                    VAR mbuf        : tgg00_MessBlock;
                    call_from_rsend : boolean;
                    VAR b_err       : tgg00_BasisError);
 
        PROCEDURE
              a06remove_locked_state (VAR acv : tak_all_command_glob);
 
        PROCEDURE
              a06rsend_mess_buf (
                    VAR acv       : tak_all_command_glob;
                    VAR mbuf      : tgg00_MessBlock;
                    result_req    : boolean;
                    VAR b_err     : tgg00_BasisError);
 
        PROCEDURE
              a06init_curr_retpart (VAR acv : tak_all_command_glob);
 
        PROCEDURE
              a06retpart_move (
                    VAR acv     : tak_all_command_glob;
                    moveobj_ptr : tsp00_MoveObjPtr;
                    move_len    : tsp00_Int4);
 
        PROCEDURE
              a06finish_curr_retpart (
                    VAR acv   : tak_all_command_glob;
                    part_kind : tsp1_part_kind;
                    arg_count : tsp00_Int2);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK07;
 
        PROCEDURE
              a07ak_system_error (
                    VAR acv  : tak_all_command_glob;
                    modul_no : integer;
                    id       : integer);
 
        PROCEDURE
              a07_error (
                    VAR acv  : tak_all_command_glob;
                    err      : tgg00_BasisError;
                    VAR nod1 : tsp00_Int2;
                    VAR nod2 : tsp00_Int2);
 
        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
              a10add_sysinfo (
                    VAR acv      : tak_all_command_glob;
                    VAR syspoint : tak_sysbufferaddress;
                    VAR b_err    : tgg00_BasisError);
 
        PROCEDURE
              a10rel_sysinfo (syspointer : tak_sysbufferaddress);
 
        PROCEDURE
              a10del_sysinfo (
                    VAR acv     : tak_all_command_glob;
                    VAR syskey  : tgg00_SysInfoKey;
                    VAR b_err   : tgg00_BasisError);
 
        PROCEDURE
              a10_key_del  (
                    VAR acv    : tak_all_command_glob;
                    VAR syskey : tgg00_SysInfoKey);
 
        PROCEDURE
              a10_add_repl_sysinfo (
                    VAR acv      : tak_all_command_glob;
                    VAR syspoint : tak_sysbufferaddress;
                    add_sysinfo  : boolean;
                    VAR b_err    : tgg00_BasisError);
 
        PROCEDURE
              a10_fix_len_get_sysinfo (
                    VAR acv      : tak_all_command_glob;
                    VAR syskey   : tgg00_SysInfoKey;
                    dstate       : tak_directory_state;
                    required_len : integer;
                    plus         : integer;
                    VAR syspoint : tak_sysbufferaddress;
                    VAR b_err    : tgg00_BasisError);
 
        PROCEDURE
              a10free_cache (VAR acv : tak_all_command_glob);
 
        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_cache_delete  (
                    VAR acv     : tak_all_command_glob;
                    is_rollback : boolean);
 
        PROCEDURE
              a10cmd_rollback  (VAR acv : tak_all_command_glob);
 
      ------------------------------ 
 
        FROM
              AK_Link : VAK25;
 
        FUNCTION
              a25lnk_pending (VAR acv : tak_all_command_glob) : boolean;
 
      ------------------------------ 
 
        FROM
              AK_dialog_tools : VAK260;
 
        PROCEDURE
              a260end_session (VAR acv : tak_all_command_glob);
 
        PROCEDURE
              a260session_frame_release (VAR acv : tak_all_command_glob);
 
        PROCEDURE
              a260TransEnd (
                    VAR acv  : tak_all_command_glob;
                    messType : tgg00_MessType;
                    release  : boolean;
                    VAR e    : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              AK_Connect : VAK51;
 
        PROCEDURE
              a51release_cache_size_info (VAR acv : tak_all_command_glob);
 
      ------------------------------ 
 
        FROM
              DML_Help_Procedures : VAK54;
 
        PROCEDURE
              a54_dml_init (
                    VAR dmli : tak_dml_info;
                    in_union : boolean);
 
        PROCEDURE
              a54_get_pparsp_pinfop (
                    VAR acv   : tak_all_command_glob;
                    VAR sparr : tak_syspointerarr;
                    mtype     : tgg00_MessType);
 
        PROCEDURE
              a54_shortinfo_to_varpart (
                    VAR acv   : tak_all_command_glob;
                    store_cmd : boolean;
                    VAR infop : tak_sysbufferaddress);
 
        PROCEDURE
              a54_store_parsinfo (
                    VAR acv   : tak_all_command_glob;
                    VAR sparr : tak_syspointerarr);
 
        PROCEDURE
              a54set_complex_entry (
                    VAR acv     : tak_all_command_glob;
                    call_reason : tak_complex_call_reason);
 
        PROCEDURE
              a54_fixedpos (
                    VAR acv  : tak_all_command_glob;
                    VAR dmli : tak_dml_info);
 
        PROCEDURE
              a54largechunk_parsinfo (
                    VAR acv          : tak_all_command_glob;
                    VAR sparr        : tak_syspointerarr;
                    VAR movebefore   : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              diagnose monitor : VAK545;
 
        PROCEDURE
              a545diag_parse_info (
                    VAR acv        : tak_all_command_glob;
                    VAR parsid     : tak_parsid;
                    VAR sel_parsid : tak_parsid);
 
      ------------------------------ 
 
        FROM
              DML_Parts : VAK55;
 
        PROCEDURE
              a55_akey_spec_list (
                    VAR acv       : tak_all_command_glob;
                    VAR put_node  : tsp00_Int2;
                    VAR last_node : tsp00_Int2);
 
        PROCEDURE
              a55_build_key (
                    VAR acv  : tak_all_command_glob;
                    VAR dmli : tak_dml_info;
                    VAR dfa  : tak_dfarr;
                    keynode  : integer);
 
        PROCEDURE
              a55_current_or_pos_of_resname (
                    VAR acv                    : tak_all_command_glob;
                    VAR current_or_pos_allowed : tak_allow_type;
                    VAR put_node               : tsp00_Int2;
                    VAR last_node              : tsp00_Int2);
 
        PROCEDURE
              a55realloc_parsinfo (
                    VAR acv          : tak_all_command_glob;
                    VAR parsinfo_ptr : tak_sysbufferaddress);
 
      ------------------------------ 
 
        FROM
              AK_Delete : VAK58;
 
        PROCEDURE
              a58_current_of (
                    VAR acv  : tak_all_command_glob;
                    VAR dmli : tak_dml_info;
                    curr_n   : integer);
 
      ------------------------------ 
 
        FROM
              Execute_Select_Expression : VAK660;
 
        PROCEDURE
              a660_search_one_table (
                    VAR acv        : tak_all_command_glob;
                    VAR dmli       : tak_dml_info;
                    table_node     : integer;
                    all            : boolean;
                    check_teresult : boolean;
                    lockspec       : tak_lockenum;
                    wanted_priv    : tak00_PrivR);
 
        PROCEDURE
              a660_new_pparsp (
                    VAR acv        : tak_all_command_glob;
                    VAR sparr      : tak_syspointerarr;
                    first_parsinfo : boolean;
                    complicate     : boolean);
 
      ------------------------------ 
 
        FROM
              Resultname_handling : VAK663;
 
        PROCEDURE
              a663commit_rollback
                    (VAR acv : tak_all_command_glob;
                    m_type   : tgg00_MessType;
                    release  : boolean;
                    subtrans : tgg00_SubtransNo);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01niltree_id : tgg00_FileId;
 
        PROCEDURE
              b01trelease_temp_cache (VAR t : tgg00_TransContext);
 
      ------------------------------ 
 
        FROM
              KB_locklist : VKB51;
 
        FUNCTION
              k51is_locklist_generated (taskid : tsp00_TaskId) : boolean;
 
      ------------------------------ 
 
        FROM
              KB_Logging : VKB560;
 
        PROCEDURE
              kb560DeleteLogTransaction (VAR Trans : tgg00_TransContext);
 
        PROCEDURE
              kb560BeginSubtransLogTransaction (VAR Trans : tgg00_TransContext);
 
        PROCEDURE
              kb560EndSubtransLogTransaction (VAR Trans : tgg00_TransContext);
 
        PROCEDURE
              kb560RollbackLogTransAction (VAR Trans : tgg00_TransContext;
                    RollbackKind : tgg00_MessType2;
                    SubTransNo   : tgg00_SubtransNo);
 
        PROCEDURE
              kb560StartSavepointAndWait (VAR Trans : tgg00_TransContext;
                    MessType2 : tgg00_MessType2);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01diag_moni_parse_on : boolean;
 
      ------------------------------ 
 
        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
              KernelAdministration_Interface : VGG999;
 
        FUNCTION
              gg999KernelStateIsAdmin : boolean;
 
        FUNCTION
              gg999KernelStateIsRestart : boolean;
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vmfree (p : tsp1_packet_ptr);
 
      ------------------------------ 
 
        FROM
              SQLManager : VAK101;
 
        PROCEDURE
              a101_DestroyContextMembers(
                    VAR acv : tak_all_command_glob);
 
        PROCEDURE
              a101_RemoveFromSessionList(
                    VAR acv       : tak_all_command_glob);
 
        FUNCTION
              a101_SharedSQL_GetStatusParameter : boolean;
 
        PROCEDURE
              a101_InvalidateAll (
                    VAR acv        : tak_all_command_glob);
&       IFDEF TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01int4 (
                    debug    : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
 
        PROCEDURE
              t01lock (
                    layer : tgg00_Debug;
                    nam   : tsp00_Sname;
                    VAR l : tgg00_Lock);
 
        PROCEDURE
              t01messblock (
                    debug         : tgg00_Debug;
                    nam           : tsp00_Sname;
                    VAR m         : tgg00_MessBlock);
&       ENDIF
 
.CM *-END-* use -----------------------------------------
***********************************************************
 
Synonym :
 
        PROCEDURE
              a05identifier_get;
 
              tsp00_MoveObj tsp00_KnlIdentifier
 
        PROCEDURE
              vmfree;
 
              tsp00_ObjAddr tsp1_packet_ptr
 
.CM *-END-* synonym -------------------------------------
***********************************************************
 
Description:
 
.sp 2;A52_ALOCK_STATEMENT
.sp
The syntax for the LOCK command is analyzed.
The syntax analysis of the actual lock specifications is performed in
AK52LOCK_SPEC.
.br;ALOCK is called in order to determine the lock mode for the specified
tables or rows (EXCLUSIVE or SHARE).
.br;If SHARE has been specified, a part with EXCLUSIVE specifications for
tables and rows may still follow.
.sp 2;A52_AUNLOCK_STATEMENT
.sp
The syntax of the UNLOCK command is analyzed with the aid of AKLOCK_SPEC.
.sp 2;AK52ALOCK
.sp
When this procedure is called, the specifications on parts that are to be
locked have already been syntactically analyzed. 'IN EXCLUSIVE MODE' or 'IN
SHARE MODE' must follow. In the case of SHARE, a branch is made to AK52SHARE_PART,
since the SHARE specifications may still be followed by specifications on
EXCLUSIVE parts that are to be locked.
.sp 2;AK52SHARE_PART
.sp
A search is made for 'SHARE MODE' and then, with the aid of AK52LOCK_SPEC, the list
of parts to be locked is again analyzed. 'IN EXCLUSIVE MODE' must come at the
end; the repeated specification of 'IN SHARE MODE' is illegal.
.sp 2;AK52LOCK_SPEC
.sp
If entire tables are to be locked, the keyword TABLE need appear only once in
front of a list of table names. If rows are to be locked, the keyword ROW must
be specified for each row. The procedure AK52ROW_SPEC is called each time a row is
specified.
.br;The table locks must come before the row locks.
.sp 2;AK52ROW_SPEC
.sp
This procedure syntactically analyzes the specification of a row that is to be
locked. The specification of the key by 'KEY ...' or by 'CURRENT OF ...' is
possible.
.sp 2;A52_LOCK_STATEMENT
.sp
This procedure forms the main part of the processing of the LOCK and UNLOCK
commands. It makes entries only in the message types for the Mess_Buffer and
calls AK52BUILD_LOCK_STRING and REST_LOCK_STATEMENT.
.sp 2;REST_LOCK_STATEMENT
.sp
The created Mess_Buffer of the LOCK, UNLOCK, COMMIT or ROLLBACK command is
either sent directly to KB or is entered as parse info in the parse file. If
only parsing is to be performed, the parse id and the parameter descriptions
are given to the user in the SQL_PACKET.
.sp 2;AK52BUILD_LOCK_STRING
.sp
The Mess_Buffer is initialized with the transferred message types. Preliminary
entries are made in some variables in DMLI that are necessary for data input
(fetched from the command or specified only as parameters).
.br;Two buffers are taken from the Cache
(A54_GET_PPARSP_PINFOP), in which, in the case of
parsing, the parameter descriptions are stored for the user and for internal
use.
.br;AK52LOCKALL is called for one lock mode,to process all parts that are
to be locked.
.br;If both SHARE and also EXCLUSIVE locks have been requested, AK52LOCKALL is
called a second time (the second time relates in all cases to EXCLUSIVE locks).
.sp 2;AK52LOCKALL
.sp
If entire tables are to be locked, AK52LOCK_TABLES is called; if rows are also
being locked, AK52LOCK_KEYS is used.
.sp
40 lock entries each of 92 bytes are available.
.sp 2;AK52LOCK_TABLES
.sp
In a loop via the table list, the table description is fetched with the aid of
AK52GET_TABLE, the privileges are checked etc. If everything is O.K., the next lock
entry (entries) is (are) filled in the Mess_Buffer. In the case of Join-Views,
this is done by AK52JOINVIEW_TABLELOCK. In all other cases it is done directly.
The key length of the entry to be locked is set to 0; the mode is
set to table-read/-write lock.
.sp 2;AK52JOINVIEW_TABLELOCK
.sp
In the case of a Join-View, each base table must be locked. For this purpose,
the system information is fetched in which the names of the base tables have
been recorded for this view. A separate lock entry is filled for each of these
base tables.
.sp 2;AK52LOCK_KEYS
.sp
In a loop via the row entries, the table description is fetched with the aid of
AK52GET_TABLE, the privileges are checked etc. If everything is O.K., the next lock
entry (entries) is (are) filled in the Mess_Buffer.
.br;In the case of Join-Views, this is done by A59_JOIN_VIEW. Afterwards the
lock mode must be set.
.br;For other tables, the trunc_key is pre-initialized with chr(0) and is then,
by means of A55_BUILD_KEY (Specification 'KEY ...') or A58_CURRENT_OF
(Specification 'CURRENT OF ...'), entirely or partially overwritten or left
unchanged if, in the case of parsing, the parameter values are not yet known.
.br;L_KLENGTH
contains the length of the entire key. The key itself is truncated after the
30th byte (trunc_keysize). This means that all records that are identical up to
the 30th byte and that have the same length are locked with one lock entry
although this is perhaps not what the user wanted.
.br;It is recorded in the internal parameter information that the parameters up
to this point form one key, i.e. an entry must now be made in k_length, and
that the further parameters belong to the next key.
.sp 2;AK52GET_TABLE
.sp
The user id and the table name are fetched from the SQL_PACKET; a search
is made for the associated system information (A06_TABLE_EXIST). Privilege
checks are performed, with the following applying: for read locks, only
the Select privilege is necessary, but for write locks, the Insert,
Update or Delete privilege is necessary.
.br;DM_PRIVCHECK specifies whether privilege checks must still be made for
individual fields. DM_ALLPRIVS contains as a set all the fields for which at
least one privilege exists,
i.e. that are known to the user. DM_ACT_SET contains
as a set all the fields that have the desired privilege.
.br;If necessary, an entry is made in the Sysusage table.
.sp 2;A52_ACOMMIT_ROLLBACK_STATEMENT
.sp
The syntax of COMMIT and ROLLBACK is analyzed.
.sp 2;A52_CALL_SEMANTIC
.sp
This is the distributor for the processing of all VAK52 commands.
.sp 2;AK52COMMIT_ROLLBACK
.sp
Everything can be done by A52_EX_COMMIT_ROLLBACK.
.br;If only parsing was requested, only the parse id is formed, in which p_no =
maxint1 specifies that 'RELEASE' has been requested.
.br;No parse information is stored for the commands COMMIT and ROLLBACK.
The parse id is put into the SQL_PACKET.
.sp 2;A52_EX_COMMIT_ROLLBACK
.sp
.br;For ROLLBACK, the cache is deleted, so that modified system information
cannot be used in the next transaction by DDL commands.
.br;A Mess_Buffer is sent to KB with this leading to a Log entry and releasing
the locks that are still held.
.br;If RELEASE has been specified, the string file, the result files, the file
for the parse information and the system information for result sets, the file
for the unnamed result set, the file in which results can, if necessary, be
stored intermediately for SELECT ... INTO, and the Schema Unloading and
Reloading file are deleted (see
VAK51).
.br;An entry is made in the Return_Code in order to inform VAK9x that a release
has been performed (there, the Return_Code is then reset to 0).
.br;The user is removed from the list of currently connected users;
current_auth_id is reset to blank in order to show that no user is connected.
.br;In all cases, the transaction number is increased by one.
.sp 2;.fo
A52_COL_FILE_NOLOG
.sp
If necessary, the file for string fields is deleted.
.CM *-END-* description ---------------------------------
***********************************************************
.CM -lll-
Code    :
 
 
CONST
      c_return_result   = true (* a52_rest_lock_statement *);
      c_complicate      = true (* a52_rest_lock_statement *);
      (*                          a660_new_pparsp *)
      c_normal_release  = true (* a52_ex_commit_rollback  *);
      (*                          a52release_session *)
      c_all             = true (* ak52get_table *);
      c_check_one_to_one= true (* ak52joinview_tablelock *);
      c_release         = true (* ak52return_parsid *);
      (*                          a663commit_rollback *)
      c_call_from_rsend = true (* a06lsend_mess_buf *);
      c_add_sysinfo     = true (* a10_add_repl_sysinfo *);
      c_in_union        = true (* a54_dml_init *);
      c_check_teresult  = true (* a660_search_one_table *);
      c_first_parsinfo  = true (* a660_new_pparsp *);
      c_is_rollback     = true;
 
TYPE
      (* pop_stack_type = (pop, delete_top, read_top); *)
 
      tak52trans_end_info = RECORD
            tei_m_type         : tgg00_MessType;
            tei_m2_type        : tgg00_MessType2;
            tei_release        : boolean;
            tei_normal_release : boolean;
            tei_drda_access    : boolean;
            tei_two_phase      : boolean;
            tei_rolled_back    : boolean;
            tei_b_err          : tgg00_BasisError;
      END;
 
      (* PTS 1115978 E.Z. *)
 
 
(*------------------------------*) 
 
PROCEDURE
      ak52end_rollback_subtrans (
            VAR acv : tak_all_command_glob;
            m_type : tgg00_MessType);
 
VAR
      subtrans_name : tsp00_KnlIdentifier;
 
BEGIN
WITH acv DO
    BEGIN
    IF  a_ap_tree^[ a_ap_tree^[ 0 ].n_lo_level ].n_sa_level <> 0
    THEN
        a05identifier_get (acv,
              a_ap_tree^[ a_ap_tree^[ 0 ].n_lo_level ].n_sa_level,
              sizeof(subtrans_name), subtrans_name)
    ELSE
        subtrans_name := a01_il_b_identifier;
    (*ENDIF*) 
    a52end_rollback_subtrans (acv, subtrans_name, m_type)
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52force_savepoint (VAR acv : tak_all_command_glob);
 
VAR
      b_err        : tgg00_BasisError;
      sparr        : tak_syspointerarr;
      parsid       : tak_parsid;
      dummy_parsid : tak_parsid;
 
BEGIN
WITH acv DO
    IF  a_ex_kind = only_parsing
    THEN
        BEGIN
        a54_get_pparsp_pinfop (acv, sparr, m_flush);
        a_return_segm^.sp1r_function_code := csp1_set_fc;
        IF  acv.a_returncode = 0
        THEN
            BEGIN
            IF  sparr.pinfop <> NIL
            THEN
                BEGIN
                a10_key_del (acv, sparr.pinfop^.syskey);
&               ifdef trace
                sparr.pinfop := NIL;
&               endif
                a_shortinfo_key := cgg_zero_id;
                END;
            (*ENDIF*) 
            WITH sparr.pparsp^.sparsinfo DO
                BEGIN
                p_mtyp     := m_flush;
                p_mtyp2    := mm_with_functions; (* force savepoint*)
                p_select   := false;
                p_prepare  := false;
                END;
            (*ENDWITH*) 
            sparr.pparsp^.b_sl := mxak_pars_header + cak_sysbufferoffset;
            sparr.pparsp^.sparsinfo.p_fullen := sparr.pparsp^.b_sl;
            sparr.pparsp^.b_kl := mxak_standard_sysk;
            a10add_sysinfo (acv, sparr.pparsp, b_err);
            IF  b_err <> e_ok
            THEN
                a07_b_put_error (acv, b_err, 1)
            ELSE
                BEGIN
                WITH a_pars_last_key DO
                    BEGIN
                    p_id[ 1 ] := chr (ord (p_id[ 1 ]) + 1);
                    p_kind    := m_flush;
                    END;
                (*ENDWITH*) 
                parsid.pid_session       := a_transinf.tri_trans.trSessionId_gg00;
                parsid.pid_parsk         := a_pars_last_key;
                parsid.pid_appl_info[1]  := chr (a_precomp_info_byte);
                parsid.pid_dtime_info[1] := chr (ord(dtf_none));
                IF  g01diag_moni_parse_on
                THEN
                    BEGIN
                    dummy_parsid.pid_session.ci4_gg00 := cgg_nil_session;
                    a545diag_parse_info (acv, parsid, dummy_parsid)
                    END;
                (* Now put the parsid into the result part. *)
                (* Building of second return part with parsid. *)
                (*ENDIF*) 
                a06retpart_move (acv, @parsid, sizeof (parsid));
                a06finish_curr_retpart (acv, sp1pk_parsid, 1);
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        a_transinf.tri_trans.trError_gg00 := e_ok;
        kb560StartSavepointAndWait (a_transinf.tri_trans, mm_user);
        IF  a_transinf.tri_trans.trError_gg00 <> e_ok
        THEN
            a07_b_put_error (acv, a_transinf.tri_trans.trError_gg00, 1);
        (*ENDIF*) 
        END
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52free_caches (VAR acv : tak_all_command_glob);
 
BEGIN
IF  acv.a_sysdir.ci_cache_p <> NIL
THEN
    BEGIN
    WITH acv.a_transinf DO
        BEGIN
        IF  tri_trans.trSessionId_gg00.ci4_gg00 <> cgg_nil_session
        THEN
            a51release_cache_size_info (acv);
        (*ENDIF*) 
        IF  tri_trans.trBdTcachePtr_gg00 <> NIL
        THEN
            BEGIN
            b01trelease_temp_cache (tri_trans);
            tri_trans.trBdTcachePtr_gg00 := NIL
            END;
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
    a260session_frame_release  (acv);
    a10free_cache (acv);
    a101_DestroyContextMembers (acv);
    END;
(*ENDIF*) 
IF  acv.a_old_packet_p <> NIL
THEN      (* Here we get rid of the pointer *)
    BEGIN (* to the old - pre612 - packet.  *)
    vmfree (acv.a_old_packet_p);
    acv.a_old_packet_p := NIL
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52alock (
            VAR acv        : tak_all_command_glob;
            may_optimistic : boolean;
            VAR put_node   : tsp00_Int2);
 
VAR
      curr_n : tsp00_Int2;
      last_n : tsp00_Int2;
 
BEGIN
WITH acv, a_scv DO
    BEGIN
    last_n := put_node;
    IF  a_returncode = 0
    THEN
        BEGIN
        IF  NOT a01_eqkey (a01kw[ cak_i_in], a_sqlmode,
            a_cmd_part^.sp1p_buf, a_scv)
        THEN
            IF  ((a_sqlmode = sqlm_internal) AND
                may_optimistic AND
                a01_eqkey (a01kw[ cak_i_optimistic], a_sqlmode,
                a_cmd_part^.sp1p_buf, a_scv))
            THEN
                BEGIN
                a01_call_put (acv, a52, cak_x_optimistic, curr_n);
                a_ap_tree^[ last_n ].n_sa_level := curr_n;
                last_n := curr_n;
                a01_next_symbol (acv);
                END
            ELSE
                a07_error (acv, e_wanted_keyword, put_node, put_node)
            (*ENDIF*) 
        ELSE
            BEGIN
            a01_next_symbol (acv);
            IF  a01_eqkey (a01kw[ cak_i_exclusive], a_sqlmode,
                a_cmd_part^.sp1p_buf, a_scv)
            THEN
                BEGIN
                a01_next_symbol (acv);
                IF  a01mandatory_keyword (acv, cak_i_mode)
                THEN
                    BEGIN
                    a01_call_put (acv, a52, cak_x_exclusive, curr_n);
                    a_ap_tree^[ last_n ].n_sa_level := curr_n;
                    last_n := curr_n;
                    END
                (*ENDIF*) 
                END
            ELSE
                ak52share_part (acv, a_ap_tree^[ last_n ].n_sa_level, curr_n);
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52build_lock_string (
            VAR acv       : tak_all_command_glob;
            VAR isparr    : tak_syspointerarr;
            VAR back_lock : tak_ak_all_locks;
            start_node    : tsp00_Int2;
            start_n       : integer;
            mtype         : tgg00_MessType;
            m2type        : tgg00_MessType2);
 
VAR
      b_err    : tgg00_BasisError;
      curr_n   : integer;
      next_n   : integer;
      lockspec : tak_lockenum;
      parsk    : tak_parskey;
      sysk     : tgg00_SysInfoKey;
      dmli     : tak_dml_info;
 
BEGIN
WITH acv, dmli DO
    BEGIN
    a54_dml_init (dmli, NOT c_in_union);
    curr_n := start_n;
    a06a_mblock_init (acv, mtype, m2type, b01niltree_id);
    a_mblock.mb_qual^.mlock_cnt := 0;
    back_lock.all_lock_count      := 0;
    d_pars_kind  := fp_lock_val;
    d_like       := false;
    d_movebefore := 0;
    d_nullkey    := true;
    d_pargeslen  := 0;
    d_maxlen     := 0;
    IF  a_ex_kind = only_parsing
    THEN
        IF  start_node <> a_ap_tree^[ 0 ].n_lo_level
        THEN
            BEGIN
            a_pars_last_key.p_kind := mtype;
            a660_new_pparsp (acv, dmli.d_sparr,
                  NOT c_first_parsinfo, c_complicate);
            IF  acv.a_returncode = 0
            THEN
                BEGIN
                a54set_complex_entry (acv, c_set_last_pars);
                sysk := a01sysnullkey;
                WITH sysk, parsk DO
                    BEGIN
                    sauthid[ 1 ] := cak_tempinfo_byte;
                    p_count   := acv.a_pars_last_key.p_count;
                    p_id[ 1 ] := acv.a_first_parsid;
                    p_kind    := m_fetch;
                    p_no      := 0;
                    sentrytyp := cak_eshortinfo;
                    s10mv (sizeof(parsk), sizeof(sauthid),
                          @parsk, 1, @sauthid, 2, mxak_parskey);
                    END;
                (*ENDWITH*) 
                a10get_sysinfo (acv, sysk, d_fix, d_sparr.pinfop, b_err);
                IF  b_err <> e_ok
                THEN
                    a07_b_put_error (acv, b_err, 1);
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        ELSE
            a54_get_pparsp_pinfop (acv, d_sparr, mtype);
        (*ENDIF*) 
    (*ENDIF*) 
    next_n := a_ap_tree^[ curr_n ].n_sa_level;
    WITH a_ap_tree^[ next_n ] DO
        IF  n_subproc = cak_x_rows
        THEN
            next_n := n_sa_level;
        (*ENDIF*) 
    (*ENDWITH*) 
    IF  a_ap_tree^[ next_n ].n_subproc = cak_x_share
    THEN
        lockspec := read_lock
    ELSE
        IF  a_ap_tree^[ next_n ].n_subproc = cak_x_optimistic
        THEN
            lockspec := optimistic_lock
        ELSE
            lockspec := write_lock;
        (*ENDIF*) 
    (*ENDIF*) 
    ak52lockall (acv, dmli, curr_n, back_lock, lockspec);
    IF  ((lockspec = read_lock) AND
        (a_returncode = 0))
    THEN
        BEGIN
        WITH a_ap_tree^[ curr_n ] DO
            IF  n_sa_level <> 0
            THEN
                BEGIN
                curr_n := n_sa_level;
                ak52lockall (acv, dmli, curr_n, back_lock, write_lock)
                END
            (*ENDIF*) 
        (*ENDWITH*) 
        END;
    (*ENDIF*) 
    isparr := d_sparr
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52check_pending_fks (
            VAR acv            : tak_all_command_glob;
            VAR trans_end_info : tak52trans_end_info);
 
BEGIN
WITH acv, trans_end_info DO
    BEGIN
    a_link_pending := false;
    IF  a25lnk_pending (acv) AND (tei_m_type = m_commit)
    THEN
        BEGIN
        tei_m_type      := m_rollback;
        tei_rolled_back := true;
        IF  tei_normal_release
        THEN
            BEGIN
            tei_normal_release := false;
            tei_release        := false
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52commit_messbuf (
            VAR acv  : tak_all_command_glob;
            m2type   : tgg00_MessType2);
 
BEGIN
WITH acv DO
    BEGIN
    a06a_mblock_init (acv, m_commit, m2type, b01niltree_id);
    g10mv ('VAK52 ',   1,    
          sizeof(a_acc_user_id), a_mblock.mb_qual_size,
          @a_acc_user_id, SURROGATE_MXGG00 - USERID_MXGG04 + 1,
          @a_mblock.mb_qual^.buf, 1, USERID_MXGG04,
          a_returncode);
    a_mblock.mb_qual_len  := USERID_MXGG04
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52commit_rollback (
            VAR acv : tak_all_command_glob;
            m_type : tgg00_MessType);
 
VAR
      n_rel              : boolean;
      curr_n             : integer;
      subtrans_name      : tsp00_KnlIdentifier;
 
BEGIN
WITH acv DO
    BEGIN
    curr_n       := a_ap_tree^[ a_ap_tree^[ 0 ].n_lo_level ].n_lo_level;
    n_rel        := false;
    IF  curr_n <> 0
    THEN
        IF  a_ap_tree^[ curr_n ].n_subproc = cak_x_release
        THEN
            n_rel := true;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  a_ex_kind <> only_parsing
    THEN
        a52_ex_commit_rollback (acv, m_type, n_rel,
              c_normal_release)
    ELSE
        BEGIN
        subtrans_name := a01_il_b_identifier;
        ak52return_parsid (acv, subtrans_name, m_type, n_rel)
        END;
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52get_table (
            VAR acv    : tak_all_command_glob;
            VAR dmli   : tak_dml_info;
            VAR lock_n : integer;
            all        : boolean;
            lockspec   : tak_lockenum);
 
BEGIN
dmli.d_acttabindex := 1;
dmli.d_cntfromtab  := 1;
dmli.d_view        := false;
IF  lockspec = read_lock
THEN
    a660_search_one_table (acv, dmli, lock_n,
          all, NOT c_check_teresult, lockspec, r_sel)
ELSE
    a660_search_one_table (acv, dmli, lock_n,
          all, NOT c_check_teresult, lockspec, r_upd);
(*ENDIF*) 
IF  acv.a_ap_tree^[ lock_n ].n_symb = s_authid
THEN
    lock_n := acv.a_ap_tree^[ lock_n ].n_sa_level;
(*ENDIF*) 
IF  acv.a_returncode = 0
THEN
    IF  (dmli.d_sparr.pbasep^.sbase.btreeid.fileTfn_gg00 = tfnTemp_egg00)
    THEN
        a07_b_put_error (acv, e_temp_table_not_allowed,
              acv.a_ap_tree^[ lock_n ].n_pos)
    (*ENDIF*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52complicated_view_lock (
            VAR acv       : tak_all_command_glob;
            VAR dmli      : tak_dml_info;
            VAR dfa       : tak_dfarr;
            tablelockn    : integer;
            VAR back_lock : tak_ak_all_locks);
 
VAR
      ok                : boolean;
      b_err             : tgg00_BasisError;
      dummy_node        : integer;
      tabcnt            : integer;
      tabno             : integer;
      viewtextkey       : tgg00_SysInfoKey;
 
BEGIN
WITH acv, dmli DO
    BEGIN
    viewtextkey           := d_sparr.pbasep^.syskey;
    viewtextkey.sentrytyp := cak_eviewtext;
    tabno                 := cak_is_undefined;
    dummy_node := 0;
    REPEAT
        a10get_sysinfo (acv, viewtextkey, d_release,
              d_viewtextbuf, b_err);
        IF  b_err = e_ok
        THEN
            WITH d_viewtextbuf^.sviewtext DO
                BEGIN
                IF  tabno = cak_is_undefined
                THEN
                    IF  va_correlation in d_sparr.pbasep^.sbase.bview_attributes
                    THEN
                        BEGIN
                        tabno  := 1;
                        tabcnt := vtfromtabcnt
                        END
                    ELSE
                        BEGIN
                        tabno  := vttabcount - vtfromtabcnt + 1;
                        tabcnt := vttabcount
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
                WITH vttab[ tabno ] DO
                    a06_systable_get (acv, d_release, vtttableid,
                          d_sparr.pbasep, NOT c_all, ok);
                (*ENDWITH*) 
                IF  ok
                THEN
                    CASE d_sparr.pbasep^.sbase.btablekind OF
                        tcomplexview :
                            ak52complicated_view_lock (acv, dmli,
                                  dfa, tablelockn, back_lock);
                        tonebase :
                            ak52lock_one_table (acv,
                                  d_sparr.pbasep^.sbase.btreeid,
                                  back_lock, read_lock);
                        tview :
                            ak52joinview_tablelock (acv, dmli,
                                  dfa, tablelockn, back_lock,
                                  read_lock,  dummy_node,
                                  NOT c_check_one_to_one);
                        OTHERWISE
                            ak52lock_one_table (acv,
                                  d_sparr.pbasep^.sbase.btreeid,
                                  back_lock, read_lock);
                        END
                    (*ENDCASE*) 
                ELSE
                    a07ak_system_error (acv, 52, 1);
                (*ENDIF*) 
                tabno := succ(tabno);
                END
            (*ENDWITH*) 
        ELSE
            a07_b_put_error (acv, b_err, 1);
        (*ENDIF*) 
    UNTIL
        (tabno > tabcnt) OR (a_returncode <> 0);
    (*ENDREPEAT*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52joinview_tablelock (
            VAR acv          : tak_all_command_glob;
            VAR dmli         : tak_dml_info;
            VAR dfa          : tak_dfarr;
            tablelockn       : integer;
            VAR back_lock    : tak_ak_all_locks;
            lockspec         : tak_lockenum;
            curr_n           : integer;
            check_one_to_one : boolean);
 
VAR
      e       : tgg00_BasisError;
      i       : integer;
      iblcnt  : integer;
      viewp   : tak_sysbufferaddress;
      ke      : tgg00_SysInfoKey;
 
BEGIN
WITH acv, dmli DO
    IF  lockspec = optimistic_lock
    THEN
        a07_b_put_error (acv, e_lock_row_not_allowed, 1)
    ELSE
        BEGIN
        ke           := d_sparr.pbasep^.syskey;
        ke.sentrytyp := cak_eviewqual_basis;
        a10get_sysinfo (acv, ke, d_fix, viewp, e);
        IF  e <> e_ok
        THEN
            a07_b_put_error (acv, e, 1);
        (*ENDIF*) 
        IF  a_returncode = 0
        THEN
            WITH back_lock DO
                BEGIN
                iblcnt := all_lock_count + 1;
                i      := 1;
                WHILE ((i <= viewp^.sviewqual_basis.vbasetabcnt) AND
                      (a_returncode = 0)) DO
                    BEGIN
                    WITH viewp^.sviewqual_basis.vtable[ i ] DO
                        IF  NOT check_one_to_one OR vtone_to_one
                        THEN
                            IF  all_lock_count = MAX_QUALBUF_LOCKS_GG00
                            THEN
                                a07_b_put_error (acv, e_too_many_lockunits_specified,
                                      a_ap_tree^[ tablelockn ].n_pos)
                            ELSE
                                BEGIN
                                all_lock_count := succ(all_lock_count);
                                WITH all_locks[ all_lock_count ] DO
                                    BEGIN
                                    lockTabId_gg00  := vttableid;
                                    lockState_gg00 := [  ];
                                    IF  check_one_to_one
                                    THEN
                                        BEGIN
                                        IF  i > 1
                                        THEN
                                            BEGIN
                                            lockKeyPos_gg00 :=
                                                  a_mblock.mb_data_len -
                                                  cgg_rec_key_offset + 1;
                                            lockKeyLen_gg00 := back_lock.all_locks
                                                  [ iblcnt ].lockKeyLen_gg00;
                                            IF  (a_ap_tree^[ curr_n ].n_proc = a55) AND
                                                (a_ap_tree^[ curr_n ].n_subproc =
                                                cak_x_keyspec_list)
                                            THEN
                                                a55_build_key (acv,
                                                      dmli, dfa, curr_n)
                                            ELSE
                                                (* PTS 1107541 E.Z. *)
                                                BEGIN
                                                IF  (dmli.d_maxlen + a_mblock.mb_data_len) MOD ALIGNMENT_GG00 <> 0
                                                THEN
                                                    BEGIN
                                                    a_mblock.mb_data_len := a_mblock.mb_data_len -
                                                       ((dmli.d_maxlen + a_mblock.mb_data_len) MOD ALIGNMENT_GG00) +
                                                       ALIGNMENT_GG00;
                                                    IF  acv.a_ex_kind = only_parsing
                                                    THEN
                                                     a54_fixedpos (acv, dmli);
                                                    (*ENDIF*) 
                                                    END;
                                                (*ENDIF*) 
                                                lockKeyPos_gg00 :=
                                                      a_mblock.mb_data_len -
                                                      cgg_rec_key_offset + 1;
                                                a58_current_of (acv,
                                                      dmli, curr_n);
                                                END;
                                            (*ENDIF*) 
                                            IF  a_ex_kind = only_parsing
                                            THEN
                                                BEGIN
                                                IF  d_movebefore > MAX_INT2_SP00
                                                THEN
                                                    a54largechunk_parsinfo (acv, d_sparr, d_movebefore);
                                                (*ENDIF*) 
                                                WITH d_sparr.pparsp^.sparsinfo DO
                                                    IF  p_cnt_infos >=
                                                     p_max_infos
                                                    THEN
                                                     a55realloc_parsinfo (acv,
                                                        d_sparr.pparsp);
                                                    (*ENDIF*) 
                                                (*ENDWITH*) 
                                                IF  a_returncode = 0
                                                THEN
                                                    WITH d_sparr.pparsp^.sparsinfo,
                                                     p_pars_infos[ p_cnt_infos+1 ] DO
                                                     BEGIN
                                                     fp_kind := fp_last_lock;
                                                     fp_movebefore_v4 := d_movebefore;
                                                     d_movebefore := 0;
                                                     p_cnt_infos :=
                                                        succ(p_cnt_infos)
                                                     END;
                                                    (*ENDWITH*) 
                                                (*ENDIF*) 
                                                END;
                                            (*ENDIF*) 
                                            END;
                                        (*ENDIF*) 
                                        IF  lockspec = read_lock
                                        THEN
                                            lockMode_gg00 := lckRowShare_egg00
                                        ELSE
                                            BEGIN
                                            lockMode_gg00 := lckRowExcl_egg00;
                                            (*lockState_gg00 := lockState_gg00 +
                                                  [ lrs_intent_excl ]*)
                                            END
                                        (*ENDIF*) 
                                        END
                                    ELSE
                                        BEGIN
                                        lockKeyPos_gg00 := 0;
                                        lockKeyLen_gg00 := 0;
                                        IF  lockspec = read_lock
                                        THEN
                                            lockMode_gg00 := lckTabShare_egg00
                                        ELSE
                                            BEGIN
                                            lockMode_gg00 := lckTabExcl_egg00;
                                            (*lockState_gg00 := lockState_gg00 +
                                                  [ lrs_intent_excl ]*)
                                            END
                                        (*ENDIF*) 
                                        END;
                                    (*ENDIF*) 
&                                   IFDEF TRACE
                                    t01int4 (ak_sem, 'lock_cnt    ', all_lock_count);
                                    t01lock (ak_sem, '============',
                                          all_locks[ all_lock_count ])
&                                         ENDIF
                                    END;
                                (*ENDWITH*) 
                                END;
                            (*ENDIF*) 
                        (*ENDIF*) 
                    (*ENDWITH*) 
                    i := succ(i)
                    END;
                (*ENDWHILE*) 
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        a10rel_sysinfo( viewp );
        END
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52lock_keys (
            VAR acv       : tak_all_command_glob;
            VAR dmli      : tak_dml_info;
            first_n       : integer;
            VAR back_lock : tak_ak_all_locks;
            lockspec      : tak_lockenum);
 
VAR
      curr_n     : integer;
      lock_n     : integer;
      tablelockn : integer;
      dfa        : tak_dfarr;
 
BEGIN
WITH acv, back_lock, dmli DO
    IF  a_returncode = 0
    THEN
        BEGIN
        lock_n := first_n;
        REPEAT
            tablelockn := a_ap_tree^[ lock_n ].n_lo_level;
            ak52get_table (acv, dmli, tablelockn, c_all, lockspec);
            IF  a_returncode = 0
            THEN
                WITH d_sparr.pbasep^.sbase DO
                    IF  (btablekind = tview)        OR
                        (btablekind = tcomplexview) OR
                        (btablekind = tdb2view)
                    THEN
                        IF  ((NOT bv_checkopt) OR
                            (lockspec = optimistic_lock) OR
                            (btablekind = tdb2view))
                        THEN
                            a07_b_put_error (acv, e_lock_row_not_allowed,
                                  a_ap_tree^[ tablelockn ].n_pos);
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDWITH*) 
            (*ENDIF*) 
            IF  a_returncode = 0
            THEN
                BEGIN
                curr_n := a_ap_tree^[ tablelockn ].n_sa_level;
                IF  all_lock_count = MAX_QUALBUF_LOCKS_GG00
                THEN
                    a07_b_put_error (acv, e_too_many_lockunits_specified,
                          a_ap_tree^[ tablelockn ].n_pos)
                ELSE
                    BEGIN
                    all_locks[ all_lock_count+1 ].lockKeyPos_gg00 :=
                          a_mblock.mb_data_len - cgg_rec_key_offset + 1;
                    IF  (a_ap_tree^[ curr_n ].n_proc = a55) AND
                        (a_ap_tree^[ curr_n ].n_subproc = cak_x_keyspec_list)
                    THEN
                        a55_build_key (acv, dmli, dfa, curr_n)
                    ELSE
                        a58_current_of (acv, dmli, curr_n);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
&               IFDEF TRACE
                t01messblock (ak_sem, 'lock_keys ab', a_mblock);
&               ENDIF
                IF  a_returncode = 0
                THEN
                    BEGIN
                    WITH all_locks[ all_lock_count+1 ] DO
                        lockKeyLen_gg00 := a_mblock.mb_data_len -
                              cgg_rec_key_offset - lockKeyPos_gg00 + 1;
                    (*ENDWITH*) 
                    IF  a_ex_kind = only_parsing
                    THEN
                        BEGIN
                        IF  d_movebefore > MAX_INT2_SP00
                        THEN
                            a54largechunk_parsinfo (acv, d_sparr, d_movebefore);
                        (*ENDIF*) 
                        WITH d_sparr.pparsp^.sparsinfo DO
                            IF  p_cnt_infos >= p_max_infos
                            THEN
                                a55realloc_parsinfo (acv, d_sparr.pparsp);
                            (*ENDIF*) 
                        (*ENDWITH*) 
                        IF  a_returncode = 0
                        THEN
                            WITH d_sparr.pparsp^.sparsinfo,
                                 p_pars_infos[ p_cnt_infos+1 ] DO
                                BEGIN
                                fp_kind          := fp_last_lock;
                                fp_movebefore_v4 := d_movebefore;
                                d_movebefore     := 0;
                                p_cnt_infos      := p_cnt_infos + 1
                                END;
                            (*ENDWITH*) 
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  d_sparr.pbasep^.sbase.btablekind <> tview
                    THEN
                        BEGIN
                        all_lock_count := succ(all_lock_count);
                        WITH d_sparr, all_locks[ all_lock_count ] DO
                            BEGIN
                            lockSite_gg00  := cgg_zero_c2;
                            lockTabId_gg00 := pbasep^.sbase.btreeid.fileTabId_gg00;
                            lockState_gg00 := [  ];
                            IF  lockspec = read_lock
                            THEN
                                lockMode_gg00 := lckRowShare_egg00
                            ELSE
                                IF  lockspec = optimistic_lock
                                THEN
                                    lockMode_gg00 := lckRowOptimistic_egg00
                                ELSE
                                    BEGIN
                                    lockMode_gg00 := lckRowExcl_egg00;
                                    (*lockState_gg00 := lockState_gg00 + [ lrs_intent_excl ]*)
                                    END;
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END;
                        (*ENDWITH*) 
                        END
                    ELSE
                        ak52joinview_tablelock (acv, dmli, dfa,
                              tablelockn, back_lock, lockspec,
                              curr_n, c_check_one_to_one);
                    (*ENDIF*) 
                    lock_n := a_ap_tree^[ lock_n ].n_sa_level
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
        UNTIL
            ((lock_n = 0) OR (a_returncode <> 0))
        (*ENDREPEAT*) 
        END
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52lock_spec (
            VAR acv            : tak_all_command_glob;
            VAR may_optimistic : boolean;
            VAR put_node       : tsp00_Int2;
            VAR last_node      : tsp00_Int2);
 
VAR
      curr_n : tsp00_Int2;
 
BEGIN
WITH acv, a_scv DO
    IF  a_returncode = 0
    THEN
        BEGIN
        put_node := 0;
        IF  (a01_eqkey (a01kw[ cak_i_table], a_sqlmode,
            a_cmd_part^.sp1p_buf, a_scv))
            OR
            (* PTS 1107262 E.Z. *)
            (a01_eqkey (a01kw[ cak_i_row], a_sqlmode,
            a_cmd_part^.sp1p_buf, a_scv))
        THEN
            BEGIN
            IF  a01_eqkey (a01kw[ cak_i_table], a_sqlmode,
                a_cmd_part^.sp1p_buf, a_scv)
            THEN
                BEGIN
                may_optimistic := false;
                a01_call_put (acv, a52, cak_x_table, curr_n);
                put_node  := curr_n;
                last_node := curr_n;
                a01_next_symbol (acv);
                IF  a_sqlmode = sqlm_internal
                THEN
                    a02_l_atablename_list (acv,
                          a_ap_tree^[ curr_n ].n_lo_level,
                          curr_n)
                ELSE
                    a02_atablename (acv,
                          a_ap_tree^[ curr_n ].n_lo_level, curr_n);
                (*ENDIF*) 
                END;
            (* PTS 1107262 E.Z. *)
            (*ENDIF*) 
            IF  a01_eqkey (a01kw[ cak_i_row], a_sqlmode,
                a_cmd_part^.sp1p_buf, a_scv)
            THEN
                BEGIN
                a01_call_put (acv, a52, cak_x_rows, curr_n);
                IF  put_node = 0
                THEN
                    BEGIN
                    put_node  := curr_n;
                    last_node := curr_n
                    END
                ELSE
                    BEGIN
                    a_ap_tree^[ last_node ].n_sa_level := curr_n;
                    last_node := curr_n
                    END;
                (*ENDIF*) 
                ak52row_spec (acv, a_ap_tree^[ last_node ].n_lo_level, curr_n);
                WHILE a01_eqkey (a01kw[ cak_i_row], a_sqlmode,
                      a_cmd_part^.sp1p_buf, a_scv)
                      AND (a_returncode = 0) DO
                    ak52row_spec (acv, a_ap_tree^[ curr_n ].n_sa_level, curr_n)
                (*ENDWHILE*) 
                END
            (*ENDIF*) 
            END
        ELSE
            a07_error (acv, e_wanted_keyword, put_node, last_node)
        (*ENDIF*) 
        END
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52_lock_statement (
            VAR acv    : tak_all_command_glob;
            start_node : tsp00_Int2);
 
VAR
      start_n   : integer;
      mtype     : tgg00_MessType;
      m2type    : tgg00_MessType2;
      isparr    : tak_syspointerarr;
      back_lock : tak_ak_all_locks;
 
BEGIN
WITH acv DO
    BEGIN
    start_n := a_ap_tree^[ start_node ].n_lo_level;
    IF  a_ap_tree^[ start_node ].n_subproc = cak_x_unlock
    THEN
        BEGIN
        mtype  := m_unlock;
        m2type := mm_nil
        END
    ELSE
        BEGIN
        mtype := m_lock;
        WITH a_ap_tree^[ start_n ] DO
            IF  n_subproc = cak_x_nowait
            THEN
                BEGIN
                m2type  := mm_test;
                start_n := n_sa_level
                END
            ELSE
                m2type := mm_nil;
            (*ENDIF*) 
        (*ENDWITH*) 
        END;
    (*ENDIF*) 
    ak52build_lock_string (acv, isparr, back_lock,
          start_node, start_n, mtype, m2type);
    a52_rest_lock_statement (acv, isparr, back_lock,
          c_return_result, NOT c_complicate);
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52lock_tables (
            VAR acv       : tak_all_command_glob;
            VAR dmli      : tak_dml_info;
            first_n       : integer;
            VAR back_lock : tak_ak_all_locks;
            lockspec      : tak_lockenum);
 
VAR
      tablelockn : integer;
      dummy_node : integer;
      dummy_dfa  : tak_dfarr;
 
BEGIN
WITH acv, back_lock, dmli DO
    IF  a_returncode = 0
    THEN
        BEGIN
        dummy_node := 0;
        tablelockn := first_n;
        REPEAT
            ak52get_table (acv, dmli, tablelockn, NOT c_all, lockspec);
            IF  a_returncode = 0
            THEN
                WITH d_sparr.pbasep^.sbase DO
                    BEGIN
                    CASE btablekind OF
                        tcomplexview :
                            ak52complicated_view_lock (acv, dmli,
                                  dummy_dfa, tablelockn, back_lock);
                        tonebase :
                            ak52lock_one_table (acv, btreeid,
                                  back_lock, lockspec);
                        tview :
                            ak52joinview_tablelock (acv, dmli,
                                  dummy_dfa, tablelockn, back_lock,
                                  lockspec,  dummy_node,
                                  NOT c_check_one_to_one);
                        OTHERWISE
                            ak52lock_one_table (acv, btreeid,
                                  back_lock, lockspec);
                        END;
                    (*ENDCASE*) 
                    tablelockn := a_ap_tree^[ tablelockn ].n_sa_level
                    END
                (*ENDWITH*) 
            (*ENDIF*) 
        UNTIL
            ((tablelockn = 0) OR (a_returncode <> 0))
        (*ENDREPEAT*) 
        END
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52lock_one_table (
            VAR acv       : tak_all_command_glob;
            VAR tree      : tgg00_FileId;
            VAR back_lock : tak_ak_all_locks;
            lockspec      : tak_lockenum);
 
VAR
      duplicate : boolean;
      i         : integer;
 
BEGIN
WITH acv, back_lock DO
    BEGIN
    duplicate := false;
    i         := 1;
    WHILE (i <= all_lock_count) AND NOT duplicate DO
        WITH all_locks[ i ] DO
            BEGIN
            IF  lockTabId_gg00 = tree.fileTabId_gg00
            THEN
                BEGIN
                IF  lockMode_gg00 = lckTabShare_egg00
                THEN
                    BEGIN
                    duplicate := true;
                    IF  lockspec <> read_lock
                    THEN
                        lockMode_gg00 := lckTabExcl_egg00
                    (*ENDIF*) 
                    END
                ELSE
                    IF  lockMode_gg00 = lckTabExcl_egg00
                    THEN
                        duplicate := true
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            i := i + 1
            END;
        (*ENDWITH*) 
    (*ENDWHILE*) 
    IF  NOT duplicate
    THEN
        IF  all_lock_count = MAX_QUALBUF_LOCKS_GG00
        THEN
            a07_b_put_error (acv, e_too_many_lockunits_specified, 1)
        ELSE
            BEGIN
            all_lock_count := succ(all_lock_count);
            WITH all_locks[ all_lock_count ] DO
                BEGIN
                lockKeyPos_gg00 := 0;
                lockTabId_gg00  := tree.fileTabId_gg00;
                lockKeyLen_gg00 := 0;
                lockState_gg00  := [  ];
                IF  lockspec = read_lock
                THEN
                    lockMode_gg00 := lckTabShare_egg00
                ELSE
                    BEGIN
                    lockMode_gg00 := lckTabExcl_egg00;
                    (*lockState_gg00 := lockState_gg00 + [ lrs_intent_excl ]*)
                    END;
                (*ENDIF*) 
                END
            (*ENDWITH*) 
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52lockall (
            VAR acv       : tak_all_command_glob;
            VAR dmli      : tak_dml_info;
            VAR curr_n    : integer;
            VAR back_lock : tak_ak_all_locks;
            lockspec      : tak_lockenum);
 
BEGIN
WITH acv DO
    IF  a_returncode = 0
    THEN
        BEGIN
        WITH a_ap_tree^[ curr_n ] DO
            IF  n_subproc = cak_x_table
            THEN
                BEGIN
                ak52lock_tables (acv, dmli, n_lo_level, back_lock, lockspec);
                curr_n := n_sa_level
                END;
            (*ENDIF*) 
        (*ENDWITH*) 
        WITH a_ap_tree^[ curr_n ] DO
            IF  n_subproc = cak_x_rows
            THEN
                BEGIN
                ak52lock_keys (acv, dmli, n_lo_level, back_lock, lockspec);
                curr_n := n_sa_level
                END
            (*ENDIF*) 
        (*ENDWITH*) 
        END
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52row_spec (
            VAR acv       : tak_all_command_glob;
            VAR put_node  : tsp00_Int2;
            VAR last_node : tsp00_Int2);
 
VAR
      curr_n                 : tsp00_Int2;
      current_or_pos_allowed : tak_allow_type;
 
BEGIN
WITH acv, a_scv DO
    IF  a_returncode = 0
    THEN
        BEGIN
        a01_call_put (acv, a52, cak_x_row, curr_n);
        put_node  := curr_n;
        last_node := curr_n;
        a01_next_symbol (acv);
        a02_atablename (acv,
              a_ap_tree^[curr_n].n_lo_level, curr_n);
        IF  NOT a01_eqkey (a01kw[ cak_i_key], a_sqlmode,
            a_cmd_part^.sp1p_buf, a_scv)
        THEN
            BEGIN
            current_or_pos_allowed := at_has_to_be_there;
            a55_current_or_pos_of_resname (acv,
                  current_or_pos_allowed,
                  a_ap_tree^[ curr_n ].n_sa_level, curr_n);
            END
        ELSE
            a55_akey_spec_list (acv, a_ap_tree^[ curr_n ].n_sa_level, curr_n)
        (*ENDIF*) 
        END
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52share_part (
            VAR acv       : tak_all_command_glob;
            VAR put_node  : tsp00_Int2;
            VAR last_node : tsp00_Int2);
 
VAR
      may_optimistic : boolean;
      curr_n         : tsp00_Int2;
      last_n         : tsp00_Int2;
      subproc        : tsp00_Int2;
 
BEGIN
WITH acv, a_scv DO
    BEGIN
    IF  a01_eqkey (a01kw[ cak_i_share], a_sqlmode,
        a_cmd_part^.sp1p_buf, a_scv)
    THEN
        BEGIN
        subproc := cak_x_share;
        a01_next_symbol (acv);
        IF  a_sqlmode = sqlm_oracle
        THEN
            BEGIN
            IF  a01_eqkey (a01kw[ cak_i_update], a_sqlmode,
                a_cmd_part^.sp1p_buf, a_scv)
            THEN
                a01_next_symbol (acv)
            ELSE
                IF  a01_eqkey (a01kw[ cak_i_row], a_sqlmode,
                    a_cmd_part^.sp1p_buf, a_scv)
                THEN
                    BEGIN
                    a01_next_symbol (acv);
                    IF  a01mandatory_keyword (acv, cak_i_exclusive)
                    THEN
                        subproc := cak_x_exclusive
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    ELSE
        IF  a_sqlmode <> sqlm_oracle
        THEN
            a07_error (acv, e_wanted_keyword, put_node, last_n)
        ELSE
            IF  a01mandatory_keyword (acv, cak_i_row)
            THEN
                BEGIN
                IF  a01_eqkey (a01kw[ cak_i_share], a_sqlmode,
                    a_cmd_part^.sp1p_buf, a_scv)
                THEN
                    BEGIN
                    a01_next_symbol (acv);
                    subproc := cak_x_share
                    END
                ELSE
                    IF  a01_eqkey (a01kw[ cak_i_exclusive], a_sqlmode,
                        a_cmd_part^.sp1p_buf, a_scv)
                    THEN
                        BEGIN
                        a01_next_symbol (acv);
                        subproc := cak_x_exclusive
                        END
                    ELSE
                        a07_error (acv, e_wanted_keyword, put_node,
                              last_n);
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    IF  a_returncode = 0
    THEN
        BEGIN
        IF  a01mandatory_keyword (acv, cak_i_mode)
        THEN
            BEGIN
            a01_call_put (acv, a52, subproc, curr_n);
            put_node := curr_n;
            last_n := curr_n;
            IF  ((a01_eqkey (a01kw[ cak_i_table], a_sqlmode,
                a_cmd_part^.sp1p_buf, a_scv)) OR
                (a01_eqkey (a01kw[ cak_i_row], a_sqlmode,
                a_cmd_part^.sp1p_buf, a_scv)))
                AND (a_sqlmode = sqlm_internal)
            THEN
                BEGIN
                may_optimistic := false;
                ak52lock_spec (acv, may_optimistic,
                      a_ap_tree^[ last_n ].n_sa_level, curr_n);
                last_n := curr_n;
                IF  a01mandatory_keyword (acv, cak_i_in)
                THEN
                    BEGIN
                    IF  a01mandatory_keyword (acv, cak_i_exclusive)
                    THEN
                        BEGIN
                        IF  a01mandatory_keyword (acv, cak_i_mode)
                        THEN
                            BEGIN
                            a01_call_put (acv, a52, cak_x_exclusive, curr_n);
                            a_ap_tree^[ last_n ].n_sa_level := curr_n;
                            last_n := curr_n;
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    last_node := last_n
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52new_subtrans (VAR acv : tak_all_command_glob);
 
VAR
      subtrans_name : tsp00_KnlIdentifier;
 
BEGIN
WITH acv DO
    BEGIN
    IF  a_ap_tree^[ a_ap_tree^[ 0 ].n_lo_level ].n_lo_level <> 0
    THEN
        a05identifier_get (acv,
              a_ap_tree^[ a_ap_tree^[ 0 ].n_lo_level ].n_lo_level,
              sizeof(subtrans_name), subtrans_name)
    ELSE
        subtrans_name := a01_il_b_identifier;
    (*ENDIF*) 
    a52new_subtrans (acv, subtrans_name)
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52trans_end (
            VAR acv            : tak_all_command_glob;
            VAR trans_end_info : tak52trans_end_info);
 
VAR
      b_err : tgg00_BasisError;
 
BEGIN
WITH acv, trans_end_info DO
    BEGIN
    IF  (tei_m_type = m_commit) AND (acv.a_dbproc_level = 0) (* 1106919 *)
    THEN
        a260TransEnd (acv, tei_m_type, tei_release, tei_b_err);
    (*ENDIF*) 
    IF  (tei_b_err <> e_ok) AND (tei_m_type = m_commit)
    THEN
        BEGIN
        tei_rolled_back  := true;
        (* PTS 1109783 E.Z. *)
        END;
    (*ENDIF*) 
    IF  (tei_m_type = m_commit) AND NOT tei_rolled_back
    THEN
        ak52commit_messbuf (acv, tei_m2_type)
    ELSE
        BEGIN
        a06a_mblock_init (acv, m_rollback, tei_m2_type, b01niltree_id);
        IF  tei_m2_type = mm_destroy_temp
        THEN
            a_mblock.mb_reply := false;
        (*ENDIF*) 
        a_mblock.mb_qual_len  := 0;
        END;
    (*ENDIF*) 
    a06lsend_mess_buf (acv, a_mblock,
          NOT c_call_from_rsend, tei_b_err);
    (* PTS 1109783 E.Z. *)
    IF  (tei_m_type = m_rollback) AND (acv.a_dbproc_level = 0) (* PTS 1106919 *)
    THEN
        BEGIN
        IF  acv.a_purgeAtRollback
        THEN
            a101_InvalidateAll (acv);
        (*ENDIF*) 
        b_err := e_ok;
        a260TransEnd (acv, tei_m_type, tei_release, b_err);
        IF  (tei_b_err = e_ok) AND (b_err <> e_ok)
        THEN
            tei_b_err := b_err;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (acv.a_dbproc_level = 0)
    THEN
        BEGIN
        b_err := e_ok;
        (* PTS 1110315, unlock OmsLockObjects *)
        a260TransEnd (acv, m_unlock, tei_release, b_err);
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
IF  NOT acv.a_createSharedSQL
THEN
    acv.a_createSharedSQL := a101_SharedSQL_GetStatusParameter;
(*ENDIF*) 
acv.a_purgeAtRollback := false;
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52_acommit_rollback_statement (
            VAR acv      : tak_all_command_glob;
            VAR put_node : tsp00_Int2;
            commit       : boolean);
 
VAR
      curr_n : tsp00_Int2;
      last_n : tsp00_Int2;
 
BEGIN
WITH acv, a_scv DO
    BEGIN
    a01_next_symbol (acv);
    IF  commit
    THEN
        a01_call_put (acv, a52, cak_x_commit, curr_n)
    ELSE
        a01_call_put (acv, a52, cak_x_rollback, curr_n);
    (*ENDIF*) 
    put_node := curr_n;
    last_n   := curr_n;
    IF  a01_eqkey (a01kw[ cak_i_work], a_sqlmode,
        a_cmd_part^.sp1p_buf, a_scv)
    THEN
        a01_next_symbol (acv)
    ELSE
        IF  a_sqlmode = sqlm_ansi
        THEN
            a07_error (acv, e_wanted_keyword, last_n, last_n);
        (*ENDIF*) 
    (*ENDIF*) 
    IF  a01_eqkey (a01kw[ cak_i_release], a_sqlmode,
        a_cmd_part^.sp1p_buf, a_scv)
    THEN
        BEGIN
        a_precomp_info_byte := csp1_p_release_found;
        a01_call_put (acv, a52, cak_x_release, curr_n);
        a_ap_tree^[ last_n ].n_lo_level := curr_n;
        a01_next_symbol (acv)
        END
    ELSE
        (* PTS 1120205 E.Z. *)
        IF  NOT (commit) AND
            a01_eqkey (a01kw[ cak_i_to], a_sqlmode,
            a_cmd_part^.sp1p_buf, a_scv) AND
            (a_sqlmode in [sqlm_oracle, sqlm_internal])
        THEN
            BEGIN
            IF  a_statement_kind = irollbacks
            THEN
                a_statement_kind := irollback_subtrans;
            (*ENDIF*) 
            a01_next_symbol (acv);
            IF  a01_eqkey (a01kw[ cak_i_savepoint], a_sqlmode,
                a_cmd_part^.sp1p_buf, a_scv)
            THEN
                a01_next_symbol (acv);
            (*ENDIF*) 
            a_ap_tree^[ put_node ].n_subproc :=
                  cak_x_rollback_subtrans;
            a02_put_identifier (acv,
                  a_ap_tree^[ last_n ].n_sa_level, last_n)
            END;
        (* PTS 1102895 E.Z. *)
        (*ENDIF*) 
    (*ENDIF*) 
    IF  commit
    THEN
        IF  a_precomp_info_byte = csp1_p_release_found
        THEN
            a_return_segm^.sp1r_function_code := csp1_commit_release_fc
        ELSE
            a_return_segm^.sp1r_function_code := csp1_commit_fc
        (*ENDIF*) 
    ELSE
        IF  a_precomp_info_byte = csp1_p_release_found
        THEN
            a_return_segm^.sp1r_function_code := csp1_rollback_release_fc
        ELSE
            a_return_segm^.sp1r_function_code := csp1_rollback_fc;
        (*ENDIF*) 
    (*ENDIF*) 
    a01_is_end_symbol (acv)
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52_aforce_statement (
            VAR acv      : tak_all_command_glob;
            VAR put_node : tsp00_Int2);
 
BEGIN
WITH acv, a_scv DO
    BEGIN
    a01_next_symbol (acv);
    (* PTS 1110053 E.Z. *)
    (*
          IF  ((a_ex_kind = parsing_executing) AND
          (a_comp_type in [at_load, at_control, at_db_manager]))
          OR
          ((a_ex_kind = only_parsing) AND (a_comp_type = at_cpc))
          OR
          (a_initial_segment_header.sp1c_mess_type = sp1m_execute)
          THEN
          *)
    BEGIN
    IF  NOT a01mandatory_keyword (acv, cak_i_savepoint)
    THEN
        put_node := 0
    ELSE
        BEGIN
        IF  a01_eqkey (a01kw[ cak_i_no], a_sqlmode,
            a_cmd_part^.sp1p_buf, a_scv)
        THEN
            BEGIN
            a01_next_symbol (acv);
            IF  NOT a01mandatory_keyword (acv, cak_i_open)
            THEN
                put_node := 0
            ELSE
                IF  NOT a01mandatory_keyword (acv, cak_i_transaction)
                THEN
                    put_node := 0
                ELSE
                    a01_call_put (acv, a52, cak_x_force_checkpoint, put_node);
                (*ENDIF*) 
            (*ENDIF*) 
            END
        ELSE
            a01_call_put (acv, a52, cak_x_force_savepoint, put_node);
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
    (*
          ELSE
          a07_b_put_error (acv, e_invalid_command, 1)
          *)
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52_alock_statement (
            VAR acv          : tak_all_command_glob;
            VAR put_node     : tsp00_Int2);
 
VAR
      may_optimistic : boolean;
      testfound      : boolean;
      curr_n         : tsp00_Int2;
      last_n         : tsp00_Int2;
 
BEGIN
WITH acv, a_scv DO
    BEGIN
    a_return_segm^.sp1r_function_code := csp1_lock_table_fc;
    a01_call_put (acv, a52, cak_x_lock, curr_n);
    put_node := curr_n;
    last_n   := curr_n;
    a01_next_symbol (acv);
    testfound      := false;
    may_optimistic := (a_sqlmode = sqlm_internal);
    (* PTS 1107262 E.Z. *)
    (* PTS 1120205 E.Z. *)
    IF  sc_symb = s_leftpar
    THEN
        BEGIN
        a01_next_symbol (acv);
        IF  a01_eqkey (a01kw[ cak_i_nowait], a_sqlmode,
            a_cmd_part^.sp1p_buf, a_scv)
        THEN
            BEGIN
            a01_call_put (acv, a52, cak_x_nowait, curr_n);
            a_ap_tree^[ last_n ].n_lo_level := curr_n;
            a01_next_symbol (acv);
            testfound := true;
            last_n := curr_n
            END
        ELSE
            IF  a01_eqkey (a01kw[ cak_i_wait], a_sqlmode,
                a_cmd_part^.sp1p_buf, a_scv)
            THEN
                a01_next_symbol (acv)
            ELSE
                a07_error (acv, e_wanted_keyword, put_node, last_n);
            (*ENDIF*) 
        (*ENDIF*) 
        a01_force_symbol (acv, s_rightpar, put_node, last_n)
        END;
    (*ENDIF*) 
    IF  a_returncode = 0
    THEN
        IF  testfound
        THEN
            ak52lock_spec (acv, may_optimistic,
                  a_ap_tree^[ last_n ].n_sa_level, curr_n)
        ELSE
            ak52lock_spec (acv, may_optimistic,
                  a_ap_tree^[ last_n ].n_lo_level, curr_n);
        (*ENDIF*) 
    (*ENDIF*) 
    ak52alock (acv, may_optimistic, curr_n);
    IF  a_sqlmode = sqlm_oracle
    THEN
        IF  a01_eqkey (a01kw[ cak_i_nowait], a_sqlmode,
            a_cmd_part^.sp1p_buf, a_scv)
        THEN
            BEGIN
            a01_call_put (acv, a52, cak_x_nowait, curr_n);
            a_ap_tree^[ curr_n ].n_sa_level :=
                  a_ap_tree^[ last_n ].n_lo_level;
            a_ap_tree^[ last_n ].n_lo_level := curr_n;
            a01_next_symbol (acv);
            last_n := curr_n
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    a01_is_end_symbol (acv);
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52_asavepoint (
            VAR acv      : tak_all_command_glob;
            VAR put_node : tsp00_Int2);
 
VAR
      last_n : tsp00_Int2;
 
BEGIN
WITH acv, a_scv DO
    BEGIN
    a_return_segm^.sp1r_function_code := csp1_savepoint_fc;
    a01_call_put (acv, a52, cak_x_begin_subtrans, put_node);
    a01_next_symbol (acv);
    a02_put_identifier (acv, a_ap_tree^[ put_node ].n_lo_level, last_n);
    a01_is_end_symbol (acv)
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52_aunlock_statement (
            VAR acv      : tak_all_command_glob;
            VAR put_node : tsp00_Int2);
 
VAR
      may_optimistic : boolean;
      curr_n         : tsp00_Int2;
      last_n         : tsp00_Int2;
 
BEGIN
WITH acv, a_scv DO
    BEGIN
    a_return_segm^.sp1r_function_code := csp1_unlock_fc;
    a01_call_put (acv, a52, cak_x_unlock, curr_n);
    put_node       := curr_n;
    last_n         := curr_n;
    may_optimistic := true;
    ak52lock_spec (acv, may_optimistic,
          a_ap_tree^[ last_n ].n_lo_level, curr_n);
    ak52alock (acv, may_optimistic, curr_n);
    a01_is_end_symbol (acv);
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52_call_semantik (
            VAR acv : tak_all_command_glob;
            subproc : tsp00_Int2);
 
BEGIN
CASE subproc OF
    cak_x_commit :
        (* PTS 1127067 E.Z. *)
        IF  (gg999KernelStateIsAdmin      AND
            NOT gg999KernelStateIsRestart AND
            NOT acv.a_internalConnection)
            OR NOT k51is_locklist_generated (acv.a_transinf.tri_trans.trTaskId_gg00)
        THEN
            BEGIN
            END
        ELSE
            ak52commit_rollback (acv, m_commit);
        (*ENDIF*) 
    cak_x_rollback :
        ak52commit_rollback (acv, m_rollback);
    cak_x_begin_subtrans :
        ak52new_subtrans (acv);
    cak_x_end_subtrans :
        ak52end_rollback_subtrans (acv, m_end);
    cak_x_rollback_subtrans :
        ak52end_rollback_subtrans (acv, m_rollback);
    cak_x_force_savepoint,
    cak_x_force_checkpoint :
        (* PTS 1110053 E.Z. *)
        ak52force_savepoint (acv);
    OTHERWISE
        a52_lock_statement (acv, acv.a_ap_tree^[ 0 ].n_lo_level);
    END;
(*ENDCASE*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52_ex_commit_rollback (
            VAR acv        : tak_all_command_glob;
            m_type         : tgg00_MessType;
            n_rel          : boolean;
            normal_release : boolean);
 
VAR
      dummy_err        : tgg00_BasisError;
      sysk             : tgg00_SysInfoKey;
      trans_end_info   : tak52trans_end_info;
 
BEGIN
WITH acv, trans_end_info DO
    BEGIN
    (* PTS 1113190 E.Z. *)
    tei_m_type         := m_type;
    tei_release        := n_rel AND a_is_connected;
    tei_normal_release := normal_release;
    tei_drda_access    := false;
    tei_rolled_back    := false;
    (* required exceptions must not survive transaction end, PTS 1112358 *)
    a_allocatorInfo.ai_badAllocCountDown := -1;
    IF  (a_is_connected AND NOT gg999KernelStateIsAdmin)
    THEN
        BEGIN
        IF  a_link_pending
        THEN
            ak52check_pending_fks (acv, trans_end_info);
        (*ENDIF*) 
        IF  tei_release OR
            ((a_sqlmode <> sqlm_oracle)
            AND
            NOT ((a_sqlmode = sqlm_internal) AND (m_type = m_commit)))
        THEN
            a663commit_rollback (acv,
                  tei_m_type, tei_release, cgg_zero_subtrans);
        (*ENDIF*) 
        IF  a_named_subtrans
        THEN
            BEGIN
            sysk           := a01defaultkey;
            sysk.sentrytyp := cak_esubtrans;
            a10del_sysinfo (acv, sysk, dummy_err);
            a_named_subtrans := false
            END;
        (*ENDIF*) 
        IF  tei_m_type = m_rollback
        THEN
            a10_cache_delete(acv, c_is_rollback);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  tei_release AND a_is_connected
    THEN
        tei_m2_type := mm_destroy_temp
    ELSE
        tei_m2_type := mm_nil;
    (*ENDIF*) 
    tei_b_err     := e_ok;
    tei_two_phase := false;
    ak52trans_end (acv, trans_end_info);
    (* PTS 1113190 E.Z. *)
    IF  tei_release
    THEN
        BEGIN
        (* PTS 1115978 E.Z. *)
        (* PTS 1103938 E.Z. *)
        a52release_session (acv, tei_normal_release);
        IF  tei_b_err = e_ok
        THEN
            a_returncode := cak_e_released
        ELSE
            a_returncode := 0;
        (*ENDIF*) 
        END
    ELSE
        IF  tei_b_err = e_ok
        THEN
            BEGIN
            a52init_subtrans_of_new_trans (acv);
            a06remove_locked_state (acv);
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  tei_rolled_back
    THEN
        tei_b_err := e_work_rolled_back;
    (*ENDIF*) 
    IF  tei_b_err <> e_ok
    THEN
        a07_b_put_error (acv, tei_b_err, 1)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52_rest_lock_statement (
            VAR acv       : tak_all_command_glob;
            VAR isparr    : tak_syspointerarr;
            VAR back_lock : tak_ak_all_locks;
            return_result : boolean;
            complicate    : boolean);
 
VAR
      b_err           : tgg00_BasisError;
      i               : integer;
 
BEGIN
WITH acv, a_mblock, mb_qual^, back_lock DO
    BEGIN
&   IFDEF TRACE
    t01int4 (ak_sem, 'return_resul', ord(return_result));
&   ENDIF
    IF  a_returncode = 0
    THEN
        IF  a_ex_kind <> only_parsing
        THEN
            BEGIN
            mlock_cnt    := 0;
            FOR i := 1 TO all_lock_count DO
                WITH all_locks[ i ] DO
                    BEGIN
                    mlock_cnt           := succ (mlock_cnt);
                    mlock [ mlock_cnt ] := all_locks[ i ];
                    END;
                (*ENDWITH*) 
            (*ENDFOR*) 
            mb_qual_len    := MB_PART1_LOCKHEAD_MXGG04 + mlock_cnt * LOCK_MXGG04;
            IF  (mlock_cnt > 0) AND
                (a_returncode = 0)
            THEN
                BEGIN
                a06rsend_mess_buf (acv, a_mblock,
                      NOT cak_return_req, b_err);
                IF  b_err <> e_ok
                THEN
                    BEGIN
                    a_part_rollback := true;
                    a07_b_put_error (acv, b_err,
                          a_cmd_part^.sp1p_buf_len)
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            isparr.pparsp^.sparsinfo.p_select   := false;
            mlock_cnt := all_lock_count;
            FOR i := 1 TO all_lock_count DO
                mlock[ i ] := all_locks[ i ];
            (*ENDFOR*) 
            mb_qual_len  :=
                  MB_PART1_LOCKHEAD_MXGG04 + mlock_cnt * LOCK_MXGG04;
            a54_store_parsinfo (acv, isparr);
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  ( a_ex_kind = only_parsing ) AND
        ( a_returncode = 0 )
        AND (NOT complicate)
    THEN
        a54_shortinfo_to_varpart (acv, a_initial_segment_header.sp1c_prepare, isparr.pinfop);
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(* PTS 1115978 E.Z. *)
(*------------------------------*) 
 
PROCEDURE
      a52asubtrans_statement (
            VAR acv      : tak_all_command_glob;
            VAR put_node : tsp00_Int2);
 
VAR
      id : integer;
 
BEGIN
WITH acv, a_scv DO
    BEGIN
    a01_next_symbol (acv);
    IF  a01_eqkey (a01kw[ cak_i_begin], a_sqlmode,
        a_cmd_part^.sp1p_buf, a_scv)
    THEN
        BEGIN
        a_return_segm^.sp1r_function_code := csp1_savepoint_fc;
        id := cak_x_begin_subtrans
        END
    ELSE
        IF  a01_eqkey (a01kw[ cak_i_end], a_sqlmode,
            a_cmd_part^.sp1p_buf, a_scv)
        THEN
            BEGIN
            a_return_segm^.sp1r_function_code := csp1_commit_fc;
            id := cak_x_end_subtrans
            END
        ELSE
            IF  a01_eqkey (a01kw[ cak_i_rollback], a_sqlmode,
                a_cmd_part^.sp1p_buf, a_scv)
            THEN
                BEGIN
                a_return_segm^.sp1r_function_code := csp1_rollback_fc;
                id := cak_x_rollback_subtrans
                END
            ELSE
                a07_error (acv, e_wanted_keyword, put_node, put_node);
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    IF  a_returncode = 0
    THEN
        BEGIN
        IF  a_statement_kind = isql_commands
        THEN
            CASE id OF
                cak_x_begin_subtrans :
                    a_statement_kind := ibegin_subtrans;
                cak_x_end_subtrans :
                    a_statement_kind := iend_subtrans;
                cak_x_rollback_subtrans :
                    a_statement_kind := irollback_subtrans;
                END;
            (*ENDCASE*) 
        (*ENDIF*) 
        a01_next_symbol (acv);
        a01_call_put (acv, a52, id, put_node);
        a01_is_end_symbol (acv)
        END;
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(* PTS 1102303 E.Z. *)
(*------------------------------*) 
 
PROCEDURE
      a52end_rollback_subtrans (
            VAR acv           : tak_all_command_glob;
            VAR subtrans_name : tsp00_KnlIdentifier;
            m_type            : tgg00_MessType);
 
VAR
      cmd_rollback   : boolean;
      b_err          : tgg00_BasisError;
      subtrans_id    : tgg00_SubtransNo;
      i              : integer;
      sysk           : tgg00_SysInfoKey;
 
BEGIN
WITH acv DO
    IF  ((a_ex_kind <> only_parsing) AND NOT (a_in_internal_subtr))
        OR
        (
        a_in_internal_subtr AND
        ((a_internal_sql = no_internal_sql) OR a_in_ddl_trigger) AND
        (* PTS 1111044 E.Z. *)
        ((a_long_desc_pos = 0) OR (a_ex_kind = only_parsing))
        )
    THEN
        BEGIN
        a_ptr1               := NIL;
        b_err                := e_ok;
        subtrans_id := a_transinf.tri_trans.trSubtransId_gg00;
        IF  subtrans_name <> a01_il_b_identifier
        THEN
            BEGIN (* rollback of named subtrans *)
            sysk           := a01defaultkey;
            sysk.sentrytyp := cak_esubtrans;
            a10get_sysinfo (acv, sysk,
                  d_release, a_ptr1, b_err);
            IF  b_err = e_ok
            THEN
                WITH a_ptr1^.ssubtrans DO
                    BEGIN
                    subtrans_id := cgg_zero_subtrans;
                    i := str_count;
                    WHILE i > 0 DO
                        WITH str_subtrans[ i ] DO
                            IF  str_name = subtrans_name
                            THEN
                                BEGIN
                                subtrans_id := str_no;
                                str_count   := i;
                                i           := 0
                                END
                            ELSE
                                i := i - 1;
                            (*ENDIF*) 
                        (*ENDWITH*) 
                    (*ENDWHILE*) 
                    IF  subtrans_id = cgg_zero_subtrans
                    THEN
                        a07_b_put_error (acv, e_no_open_subtrans, 1);
                    (*ENDIF*) 
                    END
                (*ENDWITH*) 
            ELSE
                IF  b_err = e_sysinfo_not_found
                THEN
                    a07_b_put_error (acv, e_no_open_subtrans, 1)
                ELSE
                    a07_b_put_error (acv, b_err, 1)
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (* PTS 1123747 E.Z. *)
        (*ENDIF*) 
        IF  (b_err = e_ok) AND
            (a_returncode <> a07_return_code (e_no_open_subtrans, a_sqlmode))
        THEN
            BEGIN
            cmd_rollback    := a_part_rollback AND a_in_internal_subtr;
            IF  NOT a_in_internal_subtr
            THEN
                IF  m_type = m_rollback
                THEN
                    a_return_segm^.sp1r_function_code := csp1_rollback_fc
                ELSE
                    a_return_segm^.sp1r_function_code := csp1_commit_fc;
                (*ENDIF*) 
            (*ENDIF*) 
            a_part_rollback := false;
            IF  cmd_rollback
            THEN
                m_type := m_rollback;
            (*ENDIF*) 
            IF  m_type = m_rollback
            THEN
                BEGIN
                a_transinf.tri_trans.trSubtransId_gg00 := subtrans_id;
                a_transinf.tri_trans.trError_gg00 := e_ok;
                kb560RollbackLogTransAction (a_transinf.tri_trans, mm_subtrans, subtrans_id);
                b_err := a_transinf.tri_trans.trError_gg00;
                IF  b_err <> e_ok
                THEN
                    BEGIN
                    IF  (b_err = e_serverdb_error  ) OR
                        (b_err = e_work_rolled_back) OR
                        (b_err = e_rollb_log_full  ) OR
                        (b_err = e_log_reject      )
                    THEN
                        (* returncode may be <> 0 in case this procedure   *)
                        (* is called by vak93 in case of an error          *)
                        (* those errors seem to be stronger than any other *)
                        a_returncode := 0;
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                a_transinf.tri_trans.trError_gg00 := e_ok;
                kb560EndSubtransLogTransaction (a_transinf.tri_trans);
                b_err := a_transinf.tri_trans.trError_gg00;
                END;
            (*ENDIF*) 
            IF  (b_err <> e_ok)
            THEN
                a07_b_put_error (acv, b_err, 1)
            ELSE
                BEGIN
                IF  a_in_internal_subtr
                THEN
                    a_in_internal_subtr := false
                ELSE
                    BEGIN
                    IF  (a_ptr1 <> NIL) AND (a_returncode = 0)
                    THEN
                        WITH a_ptr1^.ssubtrans DO
                            BEGIN
                            a_transinf.tri_trans.trError_gg00 := e_ok;
                            kb560BeginSubtransLogTransaction (a_transinf.tri_trans);
                            str_subtrans[ str_count ].str_no :=
                                  a_transinf.tri_trans.trSubtransId_gg00;
                            a_ptr1^.b_sl := cak_sysbufferoffset +
                                  4 + sizeof (tak_named_subtrans_info) * str_count;
                            a10_add_repl_sysinfo (acv,
                                  a_ptr1, NOT c_add_sysinfo, b_err);
                            IF  b_err <> e_ok
                            THEN
                                a07_b_put_error (acv, b_err, 1)
                            (*ENDIF*) 
                            END;
                        (*ENDWITH*) 
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  m_type = m_rollback
                THEN
                    IF  cmd_rollback
                    THEN
                        BEGIN
                        a10cmd_rollback (acv);
                        IF  a_isolation_info = temp_lock_rec_get
                        THEN
                            a_isolation_info := temp_lock_rec_needed
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        IF  a_sqlmode = sqlm_internal
                        THEN
                            a663commit_rollback (acv, m_partial_rollback,
                                  NOT c_release, subtrans_id);
                        (*ENDIF*) 
                        a10_cache_delete(acv, c_is_rollback)
                        END;
                    (*ENDIF*) 
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    ELSE
        IF  NOT a_in_internal_subtr
        THEN
            BEGIN
            IF  m_type = m_rollback
            THEN
                m_type := m_partial_rollback;
            (*ENDIF*) 
            ak52return_parsid (acv, subtrans_name, m_type,
                  NOT c_release)
            END;
        (*ENDIF*) 
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52internal_subtrans (VAR acv : tak_all_command_glob);
 
BEGIN
WITH acv DO
    IF  NOT a_in_internal_subtr
    THEN
        BEGIN
        a_in_internal_subtr := true;
        a_transinf.tri_trans.trError_gg00 := e_ok;
        kb560BeginSubtransLogTransaction (a_transinf.tri_trans);
        IF  (a_returncode = 0) AND NOT a_in_ddl_trigger
        THEN
            BEGIN
            WITH a_transinf.tri_trans DO
                trState_gg00 := trState_gg00 - [ tsSubUpdated_egg00 ]
            (*ENDWITH*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52new_subtrans (
            VAR acv           : tak_all_command_glob;
            VAR subtrans_name : tsp00_KnlIdentifier);
 
VAR
      b_err      : tgg00_BasisError;
      i          : integer;
      j          : integer;
      sysk       : tgg00_SysInfoKey;
 
BEGIN
WITH acv DO
    IF  a_ex_kind <> only_parsing
    THEN
        BEGIN
        a_return_segm^.sp1r_function_code := csp1_savepoint_fc;
        a_transinf.tri_trans.trError_gg00 := e_ok;
        kb560BeginSubtransLogTransaction (a_transinf.tri_trans);
        IF  (a_returncode = 0) AND
            (subtrans_name <> a01_il_b_identifier)
        THEN
            BEGIN (* savepoint <savepoint name> *)
            sysk           := a01defaultkey;
            sysk.sentrytyp := cak_esubtrans;
            a10_fix_len_get_sysinfo (acv, sysk, d_release,
                  cak_sysbufferoffset + 4 + sizeof (tak_named_subtrans_info),
                  sizeof (tak_named_subtrans_info), a_ptr1, b_err);
            IF  a_returncode = 0
            THEN
                WITH a_ptr1^.ssubtrans DO
                    BEGIN
                    a_named_subtrans := true;
                    IF  b_err = e_sysinfo_not_found
                    THEN
                        BEGIN
                        a_ptr1^.b_sl := cak_sysbufferoffset + 4;
                        str_count    := 0
                        END;
                    (*ENDIF*) 
                    i := 1;
                    WHILE i <= str_count DO
                        IF  str_subtrans[ i ].str_name = subtrans_name
                        THEN
                            BEGIN (* redefinition of subtrans name *)
                            FOR j := i + 1 TO str_count DO
                                str_subtrans[ j-1 ] := str_subtrans[ j ];
                            (*ENDFOR*) 
                            WITH str_subtrans[ str_count ] DO
                                BEGIN
                                str_name := subtrans_name;
                                str_no   := a_transinf.tri_trans.trSubtransId_gg00
                                END;
                            (*ENDWITH*) 
                            i := csp_maxint2
                            END
                        ELSE
                            i := i + 1;
                        (*ENDIF*) 
                    (*ENDWHILE*) 
                    IF  i < csp_maxint2
                    THEN
                        BEGIN (* new savepoint name *)
                        IF  str_count >= cak_max_named_subtrans
                        THEN
                            a07_b_put_error (acv, e_too_many_named_subtrans, 1)
                        ELSE
                            BEGIN
                            str_count := str_count + 1;
                            WITH str_subtrans[ str_count ] DO
                                BEGIN
                                str_name := subtrans_name;
                                str_no   := a_transinf.tri_trans.trSubtransId_gg00
                                END;
                            (*ENDWITH*) 
                            a_ptr1^.b_sl := a_ptr1^.b_sl +
                                  sizeof (tak_named_subtrans_info)
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    a10_add_repl_sysinfo (acv,
                          a_ptr1, b_err = e_sysinfo_not_found, b_err);
                    IF  b_err <> e_ok
                    THEN
                        a07_b_put_error (acv, b_err, 1)
                    (*ENDIF*) 
                    END;
                (*ENDWITH*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END
    ELSE
        ak52return_parsid (acv, subtrans_name, m_begin, NOT c_release)
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52release_session (
            VAR acv        : tak_all_command_glob;
            normal_release : boolean);
 
VAR
      b_err       : tgg00_BasisError;
      s           : tgg00_ServerdbNo;
 
BEGIN
a101_RemoveFromSessionList (acv); (* PTS 1135218 M.Ki. *)
WITH acv DO
    BEGIN
    a260end_session (acv);
    a_transinf.tri_trans.trError_gg00 := e_ok;
    (* PTS 1103938 E.Z. *)
    IF  normal_release
    THEN
        a06a_mblock_init (acv, m_release, mm_nil, b01niltree_id)
    ELSE
        a06a_mblock_init (acv, m_release, mm_ignore, b01niltree_id);
    (*ENDIF*) 
    s := cgg04_nil_site;
    a_mblock.mb_qual^.buf[ 1 ] := s[ 1 ];
    a_mblock.mb_qual^.buf[ 2 ] := s[ 2 ];
    g10mv ('VAK52 ',   2,    
          sizeof(a_init_user_id), a_mblock.mb_qual_size,
          @a_init_user_id, SURROGATE_MXGG00 - USERID_MXGG04 + 1,
          @a_mblock.mb_qual^.buf, 3, USERID_MXGG04,
          a_returncode);
    a_mblock.mb_qual_len  := 2 + USERID_MXGG04;
    a06lsend_mess_buf (acv, a_mblock,
          NOT c_call_from_rsend, b_err);
    a_transinf.tri_trans.trError_gg00 := e_ok;
    kb560DeleteLogTransaction (a_transinf.tri_trans); (* Logging74 UH *)
    a_curr_user_name    := a01_il_b_identifier;
    a_is_connected      := false;
    a_in_internal_subtr := false;
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak52return_parsid (
            VAR acv           : tak_all_command_glob;
            VAR subtrans_name : tsp00_KnlIdentifier;
            m_type            : tgg00_MessType;
            release           : boolean);
 
VAR
      b_err        : tgg00_BasisError;
      parsid       : tak_parsid;
      dummy_parsid : tak_parsid;
 
BEGIN
WITH acv DO
    BEGIN
    IF  (subtrans_name <> a01_il_b_identifier)
    THEN
        BEGIN
        a54_get_pparsp_pinfop (acv, a_p_arr1, m_type);
        IF  (a_returncode = 0)
        THEN
            WITH a_p_arr1.pparsp^, sparsinfo DO
                BEGIN
                p_resn             := subtrans_name;
                p_statement_kind   := a_statement_kind;
                p_function_code    := a_return_segm^.sp1r_function_code;
                p_sqlmode          := a_sqlmode;
                b_sl := cak_sysbufferoffset + mxak_pars_header;
                p_fullen           := b_sl;
                a10_add_repl_sysinfo (acv,
                      a_p_arr1.pparsp, c_add_sysinfo, b_err)
                END
            (*ENDWITH*) 
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        WITH a_pars_last_key DO
            BEGIN
            p_id[ 1 ] := chr (ord (p_id[ 1 ]) + 1);
            p_kind    := m_type;
            IF  release
            THEN
                p_no := csp_maxint1
            ELSE
                IF  a_sqlmode <> a_session_sqlmode
                THEN
                    BEGIN
                    a54_get_pparsp_pinfop (acv, a_p_arr1, m_type);
                    IF  (a_returncode = 0)
                    THEN
                        WITH a_p_arr1.pparsp^, sparsinfo DO
                            BEGIN
                            p_resn             := subtrans_name;
                            p_statement_kind   := a_statement_kind;
                            p_function_code    := a_return_segm^.sp1r_function_code;
                            p_sqlmode          := a_sqlmode;
                            b_sl := cak_sysbufferoffset + mxak_pars_header;
                            p_fullen           := b_sl;
                            a10_add_repl_sysinfo (acv,
                                  a_p_arr1.pparsp, c_add_sysinfo, b_err);
                            END;
                        (*ENDWITH*) 
                    (*ENDIF*) 
                    p_no := csp_maxint1 - 2;
                    END
                ELSE
                    p_no := csp_maxint1 - 1;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
        END;
    (*ENDIF*) 
    parsid.pid_session       := a_transinf.tri_trans.trSessionId_gg00;
    parsid.pid_parsk         := a_pars_last_key;
    parsid.pid_appl_info[1]  := chr (a_precomp_info_byte);
    parsid.pid_dtime_info[1] := chr (ord(dtf_none));
    IF  g01diag_moni_parse_on
    THEN
        BEGIN
        dummy_parsid.pid_session.ci4_gg00 := cgg_nil_session;
        a545diag_parse_info (acv, parsid, dummy_parsid)
        END;
    (* Now put the parsid into the result part. *)
    (*ENDIF*) 
    a06retpart_move (acv, @parsid,  sizeof (parsid));
    a06finish_curr_retpart (acv, sp1pk_parsid, 1);
    a06init_curr_retpart (acv);
    a06finish_curr_retpart (acv, sp1pk_shortinfo, 0);
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a52init_subtrans_of_new_trans (VAR acv : tak_all_command_glob);
 
BEGIN
(* setting of real subtrans is done in KB *)
acv.a_in_internal_subtr := false;
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
