.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 2000-2005 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.TT 1 $SQL$Project Distributed Database System$VAK22$
.tt 2 $$$
.TT 3 $ThomasA$AK_Grant_Revoke$1999-06-22$
***********************************************************
.nf
 
 .nf

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

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

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

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

 
.fo
.nf
.sp
MODULE  : AK_Grant_Revoke
=========
.sp
Purpose : AK_grant_revoke semantische Routinen.
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              a22_call_semantic  (VAR acv : tak_all_command_glob);
 
        FUNCTION
              a22exist_user  (VAR acv : tak_all_command_glob;
                    VAR user      : tsp00_KnlIdentifier;
                    errorpos      : integer;
                    VAR user_info : tak_user_info) : boolean;
 
        PROCEDURE
              a22add_priv_rec (VAR acv : tak_all_command_glob;
                    base_ptr        : tak_sysbufferaddress;
                    VAR new_priv    : tak_privilege;
                    priv_buf        : tak_sysbufferaddress;
                    add_sysinfo     : boolean;
                    VAR revoke_casc : boolean);
 
        PROCEDURE
              a22new_version_no (VAR acv : tak_all_command_glob;
                    tab_ptr         : tak_sysbufferaddress;
                    VAR version_no  : tgg91_FileVersion;
                    VAR viewscanpar : tak_viewscan_par);
 
        PROCEDURE
              a22pack_priv (privbuf : tak_sysbufferaddress;
                    VAR new_priv    : tak_privilege;
                    VAR packed_priv : tak_privilege);
 
        PROCEDURE
              a22revoke_cascade (VAR acv : tak_all_command_glob;
                    base_ptr        : tak_sysbufferaddress;
                    VAR all_col_set : tak_columnset;
                    rev_user        : tgg00_Surrogate;
                    VAR rev_priv    : tak_privilege);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
&       ifdef TRACE
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01surrogate (layer : tgg00_Debug;
                    nam       : tsp00_Sname;
                    VAR tabid : tgg00_Surrogate);
 
        PROCEDURE
              t01lidentifier (layer : tgg00_Debug;
                    identifier : tsp00_KnlIdentifier);
 
        PROCEDURE
              t01int4 (debug : tgg00_Debug;
                    nam      : tsp00_Sname;
                    int      : tsp00_Int4);
&       endif
 
      ------------------------------ 
 
        FROM
              Scanner : VAK01;
 
        VAR
              a01defaultkey       : tgg00_SysInfoKey;
              a01emptypriv        : tak_privilege;
              a01_i_public        : tsp00_KnlIdentifier;
              a01_i_sys           : tsp00_KnlIdentifier;
              a01_i_sysinfo       : tsp00_KnlIdentifier;
              a01_i_temp          : tsp00_KnlIdentifier;
              a01_i_domain        : tsp00_KnlIdentifier;
              a01_il_b_identifier : tsp00_KnlIdentifier;
 
      ------------------------------ 
 
        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
              a06_get_priv  (VAR acv : tak_all_command_glob;
                    VAR brec   : tak_sysbufferaddress;
                    VAR priv   : tak_privilege);
 
        PROCEDURE
              a06_view_get_basetable (VAR acv : tak_all_command_glob;
                    VAR view_id  : tgg00_Surrogate;
                    tabno        : integer;
                    VAR base_id  : tgg00_Surrogate);
 
        PROCEDURE
              a06determine_username (VAR acv : tak_all_command_glob;
                    VAR userid    : tgg00_Surrogate;
                    VAR user_name : tsp00_KnlIdentifier);
 
        PROCEDURE
              a06get_username (VAR acv : tak_all_command_glob;
                    VAR tree_index : integer;
                    VAR username   : tsp00_KnlIdentifier);
 
        PROCEDURE
              a06inc_linkage (VAR linkage : tsp00_C2);
 
        PROCEDURE
              a06public_priv  (VAR acv : tak_all_command_glob;
                    VAR brec : tak_baserecord;
                    VAR priv : tak_privilege);
 
        FUNCTION
              a06role_exist (VAR acv : tak_all_command_glob;
                    VAR role_name    : tsp00_KnlIdentifier;
                    dstate           : tak_directory_state;
                    VAR role_rec_ptr : tak_sysbufferaddress) : boolean;
 
        PROCEDURE
              a06unpack_priv (VAR packed_priv : tak_privilege;
                    VAR unpacked_priv : tak_privilege);
 
        PROCEDURE
              a06user_get_priv  (
                    VAR acv  : tak_all_command_glob;
                    VAR brec : tak_sysbufferaddress;
                    VAR user : tgg00_Surrogate;
                    VAR priv : tak_privilege);
&       ifdef trace
 
        PROCEDURE
              a06td_priv (p : tak_privilege;
                    id       : tsp00_C18;
                    unpacked : boolean);
&       endif
 
      ------------------------------ 
 
        FROM
              AK_Identifier_Handling : VAK061;
 
        FUNCTION
              a061exist_columnname (VAR base_rec : tak_baserecord;
                    VAR column      : tsp00_KnlIdentifier;
                    VAR colinfo_ptr : tak00_colinfo_ptr) : boolean;
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK07;
 
        PROCEDURE
              a07ak_system_error (VAR acv : tak_all_command_glob;
                    modul_no : integer;
                    id       : integer);
 
        PROCEDURE
              a07_b_put_error (VAR acv : tak_all_command_glob;
                    b_err : tgg00_BasisError;
                    err_code : tsp00_Int4);
 
        PROCEDURE
              a07_const_b_put_error (VAR acv : tak_all_command_glob;
                    b_err      : tgg00_BasisError;
                    err_code   : tsp00_Int4;
                    param_addr : tsp00_MoveObjPtr;
                    const_len  : integer);
 
        PROCEDURE
              a07_kw_put_error (VAR acv : tak_all_command_glob;
                    b_err    : tgg00_BasisError;
                    err_code : tsp00_Int4;
                    kw       : integer);
 
        PROCEDURE
              a07_nb_put_error (VAR acv : tak_all_command_glob;
                    b_err    : tgg00_BasisError;
                    err_code : tsp00_Int4;
                    VAR n    : tsp00_KnlIdentifier);
 
      ------------------------------ 
 
        FROM
              AK_error_handling : VAK071;
 
        FUNCTION
              a071_return_code (
                    b_err   : tgg00_BasisError;
                    sqlmode : tsp00_SqlMode) : tsp00_Int2;
 
      ------------------------------ 
 
        FROM
              Systeminfo_cache   : VAK10;
 
        PROCEDURE
              a10_cache_delete  (VAR acv : tak_all_command_glob;
                    is_rollback : boolean);
 
        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
              a10_key_del  (VAR acv : tak_all_command_glob;
                    VAR syskey : tgg00_SysInfoKey);
 
        PROCEDURE
              a10next_sysinfo (VAR acv : tak_all_command_glob;
                    VAR syskey    : tgg00_SysInfoKey;
                    stop_prefix   : integer;
                    dstate        : tak_directory_state;
                    rec_kind      : tsp00_C2;
                    VAR syspoint  : tak_sysbufferaddress;
                    VAR b_err     : tgg00_BasisError);
 
        PROCEDURE
              a10_rel_sysinfo (VAR acv : tak_all_command_glob;
                    VAR syskey : tgg00_SysInfoKey);
 
        PROCEDURE
              a10rel_sysinfo (syspointer : tak_sysbufferaddress);
 
        PROCEDURE
              a10_version (VAR acv : tak_all_command_glob;
                    VAR base_rec   : tak_baserecord;
                    m_type         : tgg00_MessType;
                    view_scan      : boolean);
 
        PROCEDURE
              a10_all_release (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_add_repl_sysinfo (VAR acv : tak_all_command_glob;
                    VAR syspoint : tak_sysbufferaddress;
                    add_sysinfo  : boolean;
                    VAR b_err    : tgg00_BasisError);
 
        PROCEDURE
              a10del_sysinfo (VAR acv : tak_all_command_glob;
                    VAR syskey   : tgg00_SysInfoKey;
                    VAR b_err    : tgg00_BasisError);
 
        PROCEDURE
              a10repl_sysinfo (VAR acv : tak_all_command_glob;
                    VAR syspoint : tak_sysbufferaddress;
                    VAR b_err    : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              CatalogWrapper : VAK103;
 
        PROCEDURE
              a103GetSchemaName (
                    VAR acv        : tak_all_command_glob;
                    VAR schemaId   : tgg00_Surrogate (* ptocConst *);
                    VAR schemaName : tsp00_KnlIdentifier);
 
        FUNCTION
              a103GrantRevokeSchemaPrivilege (
                    VAR acv        : tak_all_command_glob;
                    isGrant        : boolean;
                    alterIn        : boolean;
                    createIn       : boolean;
                    dropIn         : boolean;
                    cntSchemas     : integer;
                    pSchemas       : tsp00_KnlIdentifierPtr;
                    cntUsers       : integer;
                    pUser          : tsp00_KnlIdentifierPtr) : integer;
 
      ------------------------------ 
 
        FROM
              AK_Table : VAK11;
 
        PROCEDURE
              a11get_check_table (VAR acv : tak_all_command_glob;
                    new_table        : boolean;
                    basetable        : boolean;
                    unload_allowed   : boolean;
                    required_priv    : tak00_PrivilegeSet;
                    any_priv         : boolean;
                    all_base_rec     : boolean;
                    d_state          : tak_directory_state;
                    VAR act_tree_ind : tsp00_Int4;
                    VAR authid       : tsp00_KnlIdentifier;
                    VAR tablen       : tsp00_KnlIdentifier;
                    VAR d_sparr        : tak_syspointerarr);
 
        PROCEDURE
              a11put_date_time (VAR date : tsp00_Int4;
                    VAR time : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              AK_save_scheme : VAK15;
 
        PROCEDURE
              a15restore_catalog (VAR acv  : tak_all_command_glob;
                    VAR treeid      : tgg00_FileId;
                    VAR viewscanpar : tak_viewscan_par);
 
        PROCEDURE
              a15catalog_save (VAR acv : tak_all_command_glob;
                    VAR viewscanpar : tak_viewscan_par);
 
      ------------------------------ 
 
        FROM
              AK_usertab_tools : VAK19;
 
        PROCEDURE
              a19add_usertab  (VAR acv : tak_all_command_glob;
                    VAR user       : tgg00_Surrogate;
                    VAR surrogate  : tgg00_Surrogate;
                    surrogate_desc : tak_usertab_descriptor);
 
        PROCEDURE
              a19addroletab  (VAR acv : tak_all_command_glob;
                    VAR user       : tgg00_Surrogate;
                    VAR role_id    : tgg00_Surrogate);
 
        PROCEDURE
              a19delroletab  (VAR acv : tak_all_command_glob;
                    VAR user       : tgg00_Surrogate;
                    VAR role_id    : tgg00_Surrogate);
 
        PROCEDURE
              a19del_usertab  (VAR acv : tak_all_command_glob;
                    VAR user      : tgg00_Surrogate;
                    VAR surrogate : tgg00_Surrogate);
 
        FUNCTION
              a19IsDefaultRole (VAR acv : tak_all_command_glob;
                    VAR user_id : tgg00_Surrogate;
                    VAR role_id : tgg00_Surrogate) : boolean;
 
      ------------------------------ 
 
        FROM
              AK_Synonym : VAK23;
 
        FUNCTION
              a23exist_sequence (VAR acv : tak_all_command_glob;
                    tree_index      : integer;
                    inclusiveSerial : boolean;
                    VAR seq_buf     : tak_sysbufferaddress;
                    VAR seq_owner   : tsp00_KnlIdentifier;
                    VAR seq_name    : tsp00_KnlIdentifier) : boolean;
 
        PROCEDURE
              a23new_version_no (VAR acv : tak_all_command_glob;
                    syn_base_ptr : tak_sysbufferaddress);
 
      ------------------------------ 
 
        FROM
              AK_Link : VAK25;
 
        PROCEDURE
              a25check_fk_priv (VAR acv : tak_all_command_glob;
                    base_ptr    : tak_sysbufferaddress;
                    VAR priv    : tak_privilege;
                    VAR grantee : tgg00_Surrogate);
 
      ------------------------------ 
 
        FROM
              AK_Trigger : VAK262;
 
        PROCEDURE
              a262DropInternalTriggers (
                    VAR acv  : tak_all_command_glob);
 
      ------------------------------ 
 
        FROM
              AK_VIEW_SCAN   : VAK27;
 
        PROCEDURE
              a27init_viewscanpar (VAR acv : tak_all_command_glob;
                    VAR viewscanpar : tak_viewscan_par;
                    v_type          : tak_viewscantype);
 
        PROCEDURE
              a27view_scan   (VAR acv : tak_all_command_glob;
                    VAR tabid       : tgg00_Surrogate;
                    VAR viewscanpar : tak_viewscan_par);
 
      ------------------------------ 
 
        FROM
              AK_data_dictionary : VAK38;
 
        PROCEDURE
              a38DropSystemTrigger (
                    VAR acv             : tak_all_command_glob;
                    VAR ReplicationUser : tsp00_KnlIdentifier;
                    VAR SchemaName      : tsp00_KnlIdentifier;
                    VAR TableName       : tsp00_KnlIdentifier);
 
      ------------------------------ 
 
        FROM
              AK_Connect : VAK51;
 
        PROCEDURE
              a51build_userkey (VAR user_name : tsp00_KnlIdentifier;
                    VAR userkey : tgg00_SysInfoKey);
 
      ------------------------------ 
 
        FROM
              GG_allocator_interface: VGG941;
 
        FUNCTION
              gg941Allocate(VAR TransContext : tgg00_TransContext;
                    wantedBytes : integer) : tsp00_KnlIdentifierPtr;
 
        PROCEDURE
              gg941Deallocate(VAR TransContext : tgg00_TransContext;
                    VAR p : tsp00_KnlIdentifierPtr);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01niltree_id : tgg00_FileId;
 
      ------------------------------ 
 
        FROM
              RTE-Extension-30 : VSP30;
 
        PROCEDURE
              s30cmp (VAR buf1   : tsp00_MoveObj;
                    fieldpos1    : tsp00_Int4;
                    fieldlength1 : tsp00_Int4;
                    VAR buf2     : tsp00_MoveObj;
                    fieldpos2    : tsp00_Int4;
                    fieldlength2 : tsp00_Int4;
                    VAR l_result : tsp00_LcompResult);
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              a05identifier_get;
 
              tsp00_MoveObj tsp00_KnlIdentifier
 
        PROCEDURE
              a15catalog_save;
 
              tak_save_viewscan_par tak_viewscan_par
 
        PROCEDURE
              a15restore_catalog;
 
              tak_save_viewscan_par tak_viewscan_par
 
        FUNCTION
              gg941Allocate;
 
              tsp00_Addr tsp00_KnlIdentifierPtr
 
        PROCEDURE
              gg941Deallocate;
 
              tsp00_Addr tsp00_KnlIdentifierPtr
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : ThomasA
.sp
.cp 3
Created : 1985-07-09
.sp
.cp 3
.sp
.cp 3
Release :      Date : 1999-06-22
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
.sp
PROCEDURE  A22_CALL_SEMANTIC:
.sp 2
This procedure implements the SQL commands GRANT and REVOKE.
The syntax tree has already been built when the procedure is entered.
When the procedure is exited, the command is checked for semantic
errors and the resulting catalog modifications are carried out if no
error occurred during processing.
.sp 4
FUNCTION  A22_EXIST_USER
.sp 2
The procedure checks whether the specified user is a non-group member
and supplies the user type.
.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.pb '@'
.oc _/1
Description:
.sp
PROCEDURE  A22_CALL_SEMANTIC  (VAR acv : all_command_glob);
.sp;.fo
This procedure is in charge of the semantic processing of the commands
GRANT and REVOKE, i.e. it takes care of the catalog modifications
resulting from these commands.
The catalog records concerned are those records of the type tprivrecord,
which contain the privileges of a user for a table and, in the case of a
GRANT/REVOKE command for the user PUBLIC, the tbaserecords of the
pertinent table, since the privileges granted to PUBLIC are
stored in the first tbaserecord of a table.
.br;As with each DDL command, first the cache is deleted so that each
catalog record that is read is implicitly locked.  The necessary
catalog modifications are carried out via a22_grant_revoke.
If an error occurred during processing and catalog modifications have
already been carried out, these changes must be rollbacked
(a06_partial_rollback).
.sp 2;.nf;.cp 8
PROCEDURE  AK22_GRANT_REVOKE  (VAR acv : all_command_glob;
            VAR a22v : a22_grant_glob;
            grant    : boolean);
.sp;.fo
This procedure is in charge of the catalog modifications that become
necessary as a result of a GRANT (parameter grant = TRUE) or REVOKE
command (grant = FALSE) (creation of the tprivrecords, assignment of
public privileges in the tbaserecord if appropriate, file version,
view updating).  First a check is run via ak22same_grantee to determine
whether a user appears more than once in the list of users for whom
privileges are to be granted or revoked (==> error).  If not,
the repeat loop is run through once for each table specified.
Via ak22table_ex_get, the name of the current table is read from the
SQL-PACKET and a check is run to determine whether the current user
is the owner of this table.  The tbaserecords of the table are loaded
to the cache as non-relocatable (d_fix).
Via ak22build_priv_all_set, the privileges that are being granted
(revoked) for the entire current table are then transferred to the
priv_all_set of g2privileges.
Then the privileges that are being granted (revoked) for specific columns
of the current table only are written to g2privileges.  A check is
run via ak22check_priv to determine whether the current user is
authorized to grant (revoke) the privilege.
.br
In a while loop, the privilege built in g2privileges is now granted
or revoked, as the case may be, for all users in the user list, i.e.
the appropriate catalog modifications are carried out.  Within the while
loop, the current user name is transferred from the SQL-PACKET to
g2usern.  Depending on whether the privilege is to be granted (revoked)
for PUBLIC or for one user, either ak22public_user_priv or
ak22other_user_priv is called.
.br
.sp 4;.nf;.cp 8
PROCEDURE  A22_BUILD_COLUMN_PRIV (VAR acv : all_command_glob;
            VAR a22v : a22_grant_glob);
.sp;.fo
This procedure writes the external column numbers of the columns for which
an update and/or select privilege is being granted/revoked to the
priv_upd_set and priv_sel_set of g2privileges.  For this purpose, the
syntax-tree pointer g2ti is first set to the column descriptions of the
columns for which the update privilege is being granted or revoked.
A check is run via ak22column_ex_get to determine whether the columns exist
and the column numbers are transferred to priv_upd_set.
.br
The same procedure is used for the select privilege record.  If SELUPD
has been specified for individual columns, column_ex is called twice
in order to assign both the priv_sel_set and the priv_upd_set.
.sp 4;.nf;.cp 8
PROCEDURE  AK22PUT_PRIVILEGES (VAR acv : all_command_glob;
            VAR a22v        : a22_grant_glob;
            VAR ppriv       : tprivilege;
            grant           : boolean;
            VAR viewscanpar : viewscan_par);
.sp;.fo
This procedure builds in ppriv the privilege record resulting from the
GRANT/REVOKE command based on the existing privilege record
(ppriv) and the privileges to be added (GRANT) and/or subtracted (REVOKE).
The privileges that are to be granted or revoked are stored in
g2privilege.  In the case of a GRANT command, the appropriate sets
must be added; in the case of REVOKE, the g2privileges must be subtracted
from the existing privileges.  If the SELECT or UPDATE privilege
for individual columns is to be revoked even though the SELECT or
UPDATE privilege has been granted for the whole table, the SELECT or
UPDATE privilege is removed from the set of privileges that are
valid for the entire table (priv_all_set) and the resulting
priv_sel_set or priv_upd_set is formed by subtracting the
appropriate column numbers from the set of all valid column numbers
of the table (g2all_col_privset).
.sp 4;.nf;.cp 8
PROCEDURE  AK22PUBLIC_USER_PRIV (VAR acv : all_command_glob;
            VAR a22v        : a22_grant_glob;
            grant           : boolean;
            VAR viewscanpar : viewscan_par);
.sp;.fo
This procedure is called when PUBLIC privileges for the current table
g2authid.g2tablen are being granted/revoked for the virtual user.
Via ak22put_privileges, the resulting privilege record for PUBLIC is
built and transferred to the component bpriv of the first
tbaserecords of the table.  The owner privilege must not be granted.
The modified tbaserecord is written back to the system file and the
system record of the type tprivrecord of the user PUBLIC
relating to g2authid.g2tablen is loaded to the cache (ak22get_priv_rec).
If no tprivrecord exists and a GRANT command is being processed, i.e.
if no PUBLIC privilege exists, the tprivrecord is built and inserted
in the system file.  In addition, in this case the table must be entered
in the list of tables visible for the user PUBLIC (a19_add_usertab).
.br;
If, however, a tprivrecord does exist, a differentiation must be
made between two cases:
.br;.hi +4
i)@@PUBLIC all privileges for g2authid.g2tablen have been revoked
.hi -4;.in +4
The tprivrecord is deleted in the system file and the table
g2authid.g2tablen is removed from the list of tables visible for the
user PUBLIC (a19del_usertab).
.in -4
ii)@PUBLIC retains privileges for g2authid.g2tablen
.in +4
The resulting privileges are entered in the tprivrecord and the
tprivrecord is written back to the system file.
.in -4
If privileges have been revoked, all g2authid.g2tablen-dependent
views must be examined to find out whether columns of the view must
be deleted or whether the entire view must be deleted.  The analysis
is carried out via a27view_scan.
.sp 4;.nf;.cp 8
PROCEDURE  AK22GET_PRIV_REC (VAR acv : all_command_glob;
            VAR a22v : a22_grant_glob;
            VAR new  : boolean);
.sp;.fo
The catalog record of type tprivrecord, which contains the
privilege record of the user g2usern for the table
g2authid.g2tablen, is loaded to the cache.  If this catalog record
does not exist (new = TRUE), a free cache area is allocated in the
cache for the tprivrecord and is initialized as tprivrecord.
g2privbuf is the pointer to this tprivrecord.
.sp 4;.nf;.cp 8
PROCEDURE  AK22OTHER_USER_PRIV (VAR acv : all_command_glob;
            VAR a22v        : a22_grant_glob;
            grant           : boolean;
            VAR viewscanpar : viewscan_par);
.sp;.fo
This procedure is called when, for a user <> PUBLIC privileges for
the table g2authid.g2tablen are to be granted/revoked.  First it is
determined via a22_exist_user whether the specified user g2usern exists.
If yes, the existing privilege record of g2usern for
g2authid.g2tablen is determined via ak22get_priv_rec.
.br
If g2usern does not yet have any privilege record, an empty tprivrecord is
allocated in the cache via ak22get_priv_rec at the address
g2privbuf.  The privileges to be granted (g2privileges) are entered in
this record and the tprivrecord is inserted in the system file.  In
addition, g2authid.g2tablen is entered in the list of tables visible
for g2usern (a19_add_usertab).
.br
If g2usern already has a tprivrecord for g2authid.g2tablen, the privileges
resulting from the GRANT/REVOKE command are built in the tprivrecord via
ak22put_privileges.  If all privileges for g2usern are to be revoked,
the tprivrecord is deleted and g2authid.g2tablen is removed from the
list of tables visible for g2usern (a19del_usertab).
Otherwise, the modified tprivrecord is written back to the system file
and if g2usern is DBA or SUPERDBA, the owner flag in the list of
tables that are visible for him is updated (a19_repl_usertab).
.br
If g2usern privileges were revoked, all g2authid.g2tablen-dependent
views must be examined to find out whether columns of the view must
be deleted or whether the entire view must be deleted.  The analysis
is carried out via a27view_scan.
.br
.sp 4;.nf;.cp 8
PROCEDURE  AK22SAME_GRANTEE    (VAR acv : all_command_glob;
            VAR a22v : a22_grant_glob);
.sp;.fo
This procedure checks whether at least one user for whom privileges are
to be granted or revoked appears more than once in the user list.
If yes, the error message duplicate_name is sent.  The number of users
specified is returned in g2user_count.
.sp 4;.nf;.cp 8
PROCEDURE  A22_TABLE_EX_GET   (VAR acv : all_command_glob;
            VAR a22v : a22_grant_glob);
.br;.fo
The syntax-tree index of the syntax-tree element that describes the
current table is determined by skipping the elements that describe
privileges.  The catalog information of the type tbaserecord for the
table described by this syntax-tree element is allocated in the
cache via a11get_check_table.  A check is run to determine whether
the current user is owner of the table.  If the table is a synonym, the
command is rejected; otherwise the components g2tablearr1 (pointer
to the first tbaserecord), g2versno (version number of the table) and
g2tabl_locset (location of the table) of the a22_grant_glob are assigned.
The external column numbers for all valid columns of the table are stored
in g2all_col_privset in order to be able to determine the set of
columns to which the select or update privilege applies in the event
that a select or update privilege for individual columns is to be
revoked even though select or update privileges have been granted for
the entire table.
.sp 4;.nf;.cp 8
PROCEDURE  COLUMN_EX_GET   (VAR acv : all_command_glob;
            VAR a22v       : a22_grant_glob;
            VAR extprivset : tcolumnset);
.sp;.fo
This procedure is called if the select or update privilege for individual
columns is being granted/revoked.  When the procedure is entered, g2ti
points to the syntax-tree element that describes the first column name.
Beginning with this column, the procedure now reads the column names
from the SQL-PACKET, checks whether the column in g2authid.g2tablen
exists and writes the external column number of the column to the
extprivset.  A column must not have been specified more than once and
the update privilege must not have been specified for key columns
(update = TRUE).
.sp 4;.nf;.cp 8
FUNCTION  A22_EXIST_USER (VAR acv : all_command_glob;
            VAR user  : user_id;
            errorpos  : integer;
            VAR ukind : usertyp) : boolean;
.sp;.fo
This function checks whether the user specified by 'user' exists
and whether he is a non-group member.  If yes, the function supplies the
value TRUE and the user type is returned in ukind
(BDA, RESOURCE, STANDARD).
.sp 4;.nf;.cp 8
PROCEDURE  A22_BUILD_PRIV_ALL_SET (VAR acv : all_command_glob;
            VAR a22v : a22_grant_glob;
            grant    : boolean);
.sp;.fo
This procedure determines the privileges that are granted (grant = TRUE)
or revoked (GRANT = FALSE) for the entire table g2authid.g2tablen
and enters them in the priv_all_set of g2privileges.  The following
errors can occur:
.br
A user who is not the SUPERDBA attempts to grant the owner privilege.
.br
An attempt is made to grant (revoke) a privilege in the command more
than once.
.br
An attempt is made to grant the update (select) privilege for both the
entire table and for individual columns of the table.
.br
When the procedure is exited, both the priv_all_set and the values
g2tiupd, g2tisel, g2tisup are assigned.  If g2tisup does not equal 0,
this means the the update privilege for individual columns is being
granted (revoked) and that g2tiupd points to the syntax-tree element
that contains the description of the first column for which the
update privilege is being granted (revoked).
(g2tisel points to the list of columns for which the select privilege
is being granted (revoked) and g2tisub points to the list of the columns
for which the selupd privilege is being granted (revoked).
.sp 4;.nf;.cp 8
PROCEDURE  AK22CHECK_PRIV  (VAR acv : all_command_glob;
            VAR a22v : a22_grant_glob);
.sp;.fo
This procedure checks whether the owner of a view is attempting to
grant more privileges for the view than he himself possesses.  If yes,
the error message missing_privilege is generated.
.sp 4;.nf;.cp 8
PROCEDURE  NEW_VERSION_NO (VAR acv : all_command_glob;
            VAR a22v        : a22_grant_glob;
            VAR viewscanpar : viewscan_par);
.sp;.fo
In the case of a revoke, it must be ensured that all users affected
by the revoke command immediately experience the change in privileges,
even if they have the catalog information of the table for which the
privileges have been revoked or catalog information from dependent
views in their cache.  Otherwise it would be possible for these users
to continue to access the table with the old privileges as long
as they have the catalog information in the cache.   In order to prevent
this, the file version of the table is raised so that, the next time
the table is accessed, the error old_file_version is reported, which
causes the cache to be emptied.  However, care should be taken that only
base tables have a file version.  If the table for which the privileges
are being revoked is a view, the file version of one of the base tables upon
which the view is based is raised.  Determination of the base table
upon which the view is based is carried out differently for the different
view types.
.br;.hi +5
i)@@@The view references exactly one base table and is not a complex
view (tonebaseview).
.hi -5;.in +5
In this case, the table name of the base table referenced is located in
the first tbaserecord of the view (bv_authid.bv_tablen).
.in -5;.hi +5
ii)@@The table references more than one base table and is not a complex
view (tview):
.hi -5;.in +5
The base tables referenced are described in the
tviewqualrecord of the view.  The first base table is selected for
raising the file version.
.in -5;.hi +5
iii)@The view is a complex view, i.e. it contains subqueries or
'group by' and 'having' (tcomplexview) :
.hi -5;.in +5
The tviewtextrecord of the view contains all tables in the 'from'
part of the view definition.  A search is carried out here for a
table that is not a complex view.  If such a table is found, either
it is already a base table or it is a view of the type i) or ii).
The search for the suitable base table is then carried out as in
i) or ii).  If the view is composed of complex views only, the
procedure is applied to the first view in the 'from' part.
This continues until a non-complex table is found
.in -5
The file version for the particular base table is raised.  The
change is later updated in the views via a27view_scan for which the
necessary preparations are made in the procedure.  The
tbaserecords of the base table are written back to the system file
if the table is not the one for which the privileges are being revoked.
In this case, more modifications of the bpriv field and the owner field
are to be made for the tbaserecords, if necessary.  The
tbaserecords are then written back at a later stage in processing
via ak22replace_base_records
.sp 4;.nf;.cp 8
PROCEDURE  AK22REPLACE_BASE_RECORDS (VAR acv : all_command_glob;
            VAR a22v : a22_grant_glob);
.sp;.fo
If the table for which the privileges have been revoked is a base
table, the tbaserecords of the table are written back to the system
file with the new version number (g2versno).
.sp 4
.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
 
.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
 
 
CONST
      c_is_rollback = true;
 
TYPE
 
      a22_grant_glob   = RECORD
            g2tablearr1       : tak_sysbufferaddress;
            g2p_arr           : tak_syspointerarr;
            g2authname        : tsp00_KnlIdentifier;
            g2auth_id         : tgg00_Surrogate;
            g2role_id         : tgg00_Surrogate;
            g2tablen          : tsp00_KnlIdentifier;
            g2coln            : tsp00_KnlIdentifier;
            g2username        : tsp00_KnlIdentifier;
            g2user_id         : tgg00_Surrogate;
            g2ci              : integer;
            g2privbuf         : tak_sysbufferaddress;
            g2privkey         : tgg00_SysInfoKey;
            g2userbuf         : tak_sysbufferaddress;
            g2userkey         : tgg00_SysInfoKey;
            g2privileges      : tak_privilege;
            g2grantor_priv    : tak_privilege;
            g2old_user_priv   : tak_privilege;
            g2selreccolno     : tak_columnset;
            g2updreccolno     : tak_columnset;
            g2all_col_privset : tak_columnset;
            g2user_count      : integer;
            g2ti              : tsp00_Int4;
            g2tiuser          : integer;
            g2tispec          : integer;
            g2tiupd           : integer;
            g2tisel           : integer;
            g2tisup           : integer;
            g2tiref           : integer;
            g2sequence        : boolean;
            g2versno          : tgg91_FileVersion;
            g2allprivileges   : boolean;
            g2grant_option    : boolean;
      END;
 
 
 
(*------------------------------*) 
 
PROCEDURE
      ak22CheckReplicationPrivileges (VAR acv : tak_all_command_glob;
            VAR a22v : a22_grant_glob);
 
VAR
      userId          : tgg00_Surrogate;
      priv            : tak_privilege;
      replicationUser : tsp00_KnlIdentifier;
      schemaName       : tsp00_KnlIdentifier;
 
BEGIN
(* does replication user have select privilege ?     *)
userId := cak_replication_user_id;
a06user_get_priv  (acv, a22v.g2p_arr.pbasep, userId, priv);
IF  NOT (r_sel in priv.priv_all_set)
THEN
    BEGIN
    (* no select privilege ==> drop replication triggers *)
    acv.a_p_arr1.pbasep := a22v.g2p_arr.pbasep;
    a262DropInternalTriggers (acv);
    IF  acv.a_returncode = 0
    THEN
        BEGIN
        a06determine_username (acv, userId, replicationUser);
        a103GetSchemaName (acv, a22v.g2p_arr.pbasep^.sbase.bschema, schemaName);
        a38DropSystemTrigger (acv, replicationUser, schemaName, a22v.g2p_arr.pbasep^.sbase.btablen^);
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22column_ex_get   (VAR acv : tak_all_command_glob;
            VAR a22v    : a22_grant_glob;
            grant       : boolean;
            priv_desc   : tak_priv_descriptors);
 
VAR
      error      : tgg00_BasisError;
      grant_desc : tak_priv_descriptors;
      col_ptr    : tak00_colinfo_ptr;
 
BEGIN
WITH acv, a22v, g2privileges DO
    IF  a_returncode = 0
    THEN
        IF  g2sequence
        THEN
            a07_b_put_error (acv, e_invalid_command, g2ti)
        ELSE
            BEGIN
            error := e_ok;
            IF  priv_desc = priv_col_sel
            THEN
                BEGIN
                IF  g2p_arr.pbasep^.sbase.btablekind = tdb2view
                THEN
                    error := e_missing_privilege
                ELSE
                    grant_desc := priv_col_sel_grant
                (*ENDIF*) 
                END
            ELSE
                IF  priv_desc = priv_col_upd
                THEN
                    grant_desc := priv_col_upd_grant
                ELSE
                    grant_desc := priv_col_ref_grant;
                (*ENDIF*) 
            (*ENDIF*) 
            IF  error = e_ok
            THEN
                REPEAT
                    a05identifier_get (acv,
                          g2ti, sizeof (g2coln), g2coln);
                    IF  NOT a061exist_columnname (g2p_arr.pbasep^.sbase,
                        g2coln, col_ptr)
                    THEN
                        error := e_unknown_columnname
                    ELSE
                        WITH col_ptr^ DO
                            BEGIN
                            IF  NOT (cextcolno in
                                g2grantor_priv.priv_col[ grant_desc ])
                            THEN
                                error := e_missing_privilege
                            ELSE
                                IF  cextcolno in
                                    priv_col[priv_desc]
                                THEN
                                    error := e_duplicate_columnname;
                                (*ENDIF*) 
                            (*ENDIF*) 
                            IF  error = e_ok
                            THEN
                                BEGIN
                                priv_col_exist := priv_col_exist +
                                      [ priv_desc ];
                                priv_col[ priv_desc ] :=
                                      priv_col[ priv_desc ] +
                                      [ cextcolno ];
                                IF  g2grant_option OR NOT grant
                                THEN
                                    BEGIN
                                    priv_col_exist := priv_col_exist +
                                          [ grant_desc ];
                                    priv_col[ grant_desc ] :=
                                          priv_col[ grant_desc ] +
                                          [ cextcolno ]
                                    END;
                                (*ENDIF*) 
                                g2ti := a_ap_tree^[ g2ti ].n_sa_level;
                                END;
                            (*ENDIF*) 
                            END;
                        (*ENDWITH*) 
                    (*ENDIF*) 
                UNTIL
                    (g2ti = 0) OR (error <> e_ok);
                (*ENDREPEAT*) 
            (*ENDIF*) 
            IF  error <> e_ok
            THEN
                a07_b_put_error (acv, error, a_ap_tree^[ g2ti ].n_pos);
            (*ENDIF*) 
            END;
        (*ENDIF*) 
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22column_priv (VAR acv : tak_all_command_glob;
            VAR a22v : a22_grant_glob;
            grant    : boolean);
 
BEGIN
WITH acv, a22v, g2privileges DO
    IF  a_returncode = 0
    THEN
        BEGIN
        IF  g2allprivileges
        THEN
            BEGIN
            g2privileges.priv_sel_set :=
                  g2grantor_priv.priv_grant_sel_set;
            g2privileges.priv_upd_set :=
                  g2grantor_priv.priv_grant_upd_set;
            g2privileges.priv_ref_set :=
                  g2grantor_priv.priv_grant_ref_set;
            IF  g2grant_option OR NOT grant
            THEN
                BEGIN
                g2privileges.priv_grant_sel_set :=
                      g2grantor_priv.priv_grant_sel_set;
                g2privileges.priv_grant_upd_set :=
                      g2grantor_priv.priv_grant_upd_set;
                g2privileges.priv_grant_ref_set :=
                      g2grantor_priv.priv_grant_ref_set
                END;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            IF  g2tiupd <> 0
            THEN
                BEGIN
                g2ti := g2tiupd;
                ak22column_ex_get (acv, a22v, grant, priv_col_upd)
                END;
            (*ENDIF*) 
            IF  g2tisel <> 0
            THEN
                BEGIN
                g2ti := g2tisel;
                ak22column_ex_get (acv, a22v, grant, priv_col_sel)
                END;
            (*ENDIF*) 
            IF  g2tiref <> 0
            THEN
                BEGIN
                g2ti := g2tiref;
                ak22column_ex_get (acv, a22v, grant, priv_col_ref)
                END;
            (*ENDIF*) 
            IF  g2tisup <> 0
            THEN
                BEGIN
                g2ti := g2tisup;
                ak22column_ex_get (acv, a22v, grant, priv_col_upd);
                g2ti := g2tisup;
                ak22column_ex_get (acv, a22v, grant, priv_col_sel)
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22get_grantor_priv (VAR acv : tak_all_command_glob;
            VAR a22v : a22_grant_glob);
 
VAR
      j : integer;
 
BEGIN
WITH acv, a22v, g2p_arr.pbasep^.sbase DO
    IF  g2sequence
    THEN
        BEGIN
        g2grantor_priv := a01emptypriv;
        g2grantor_priv.priv_all_set       := [ r_sel ];
        g2grantor_priv.priv_all_grant_set := [ r_sel ]
        END
    ELSE
        BEGIN
        g2tablearr1 := g2p_arr.pbasep;
        g2versno    := btreeid.fileVersion_gg00;
        a06_get_priv (acv, g2tablearr1, g2grantor_priv);
        g2grantor_priv.priv_all_set :=
              g2grantor_priv.priv_all_set - [ r_owner ];
        g2all_col_privset := [  ];
        WITH g2p_arr.pbasep^.sbase DO
            FOR j := bfirstindex TO blastindex DO
                WITH g2p_arr.pbasep^.sbase.bcolumn[ j ]^ DO
                    IF  NOT (ctdropped in ccolpropset) AND
                        NOT (ctinvisible in ccolpropset)
                    THEN
                        g2all_col_privset := g2all_col_privset
                              + [ cextcolno ];
                    (*ENDIF*) 
                (*ENDWITH*) 
            (*ENDFOR*) 
        (*ENDWITH*) 
        WITH g2grantor_priv DO
            BEGIN
            IF  r_upd in priv_all_set
            THEN
                priv_upd_set := g2all_col_privset;
            (*ENDIF*) 
            IF  r_sel in priv_all_set
            THEN
                priv_sel_set := g2all_col_privset;
            (*ENDIF*) 
            IF  r_link in priv_all_set
            THEN
                priv_ref_set := g2all_col_privset;
            (*ENDIF*) 
            IF  r_upd in priv_all_grant_set
            THEN
                priv_grant_upd_set := g2all_col_privset;
            (*ENDIF*) 
            IF  r_sel in priv_all_grant_set
            THEN
                priv_grant_sel_set := g2all_col_privset;
            (*ENDIF*) 
            IF  r_link in priv_all_grant_set
            THEN
                priv_grant_ref_set := g2all_col_privset;
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
        END;
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22get_priv_rec (VAR acv : tak_all_command_glob;
            VAR a22v        : a22_grant_glob;
            procedure_priv  : boolean;
            VAR new_sysinfo : boolean);
 
VAR
      b_err : tgg00_BasisError;
 
BEGIN
WITH acv, a22v DO
    BEGIN
    g2old_user_priv := a01emptypriv;
    g2privkey       := g2tablearr1^.syskey;
    IF  procedure_priv
    THEN
        BEGIN
        g2privkey.sentrytyp  := cak_eprivproc;
        g2privkey.suserid    := a_curr_user_id;
        g2privkey.sgrantuser := g2user_id
        END
    ELSE
        BEGIN
        g2privkey.sentrytyp  := cak_eprivuser;
        g2privkey.suserid    := g2user_id;
        g2privkey.sgrantuser := a_curr_user_id
        END;
    (*ENDIF*) 
    g2privkey.skeylen   := mxak_standard_sysk + 2 * SURROGATE_MXGG00;
    a10_fix_len_get_sysinfo (acv, g2privkey, d_fix,
          sizeof (tak_privuserrecord), 0, g2privbuf, b_err);
    IF  b_err = e_sysinfo_not_found
    THEN
        WITH g2privbuf^, sprivuser DO
            BEGIN
            new_sysinfo   := true;
            pru_segmentid := g2tablearr1^.sbase.bsegmentid;
            pru_filler    := cak00_local_segment_id
            END
        (*ENDWITH*) 
    ELSE
        IF  a_returncode = 0
        THEN
            BEGIN
            new_sysinfo := false;
            a06unpack_priv (g2privbuf^.sprivuser.pru_priv,
                  g2old_user_priv);
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    g2old_user_priv.priv_all_set :=
          g2old_user_priv.priv_all_set - [ r_owner ];
&   ifdef trace
    a06td_priv (g2old_user_priv, 'ret : ak22get_priv', true)
&         endif
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a22new_version_no (VAR acv : tak_all_command_glob;
            tab_ptr         : tak_sysbufferaddress;
            VAR version_no  : tgg91_FileVersion;
            VAR viewscanpar : tak_viewscan_par);
 
VAR
      replace_baserecords : boolean;
      found               : boolean;
      ok                  : boolean;
      b_err               : tgg00_BasisError;
      dstate              : tak_directory_state;
      i                   : integer;
      buf                 : tak_sysbufferaddress;
      base_ptr            : tak_sysbufferaddress;
      tableid             : tgg00_Surrogate;
      sysk                : tgg00_SysInfoKey;
 
BEGIN
(* PTS 1111576 E.Z. *)
IF  tab_ptr^.sbase.btablekind in
    [twithkey, twithoutkey, tonebase, tview, tcomplexview]
THEN
    BEGIN
    viewscanpar.vsc_base_tabid := tab_ptr^.sbase.bsurrogate;
    b_err := e_ok;
    WITH acv, tab_ptr^.sbase DO
        BEGIN
        version_no                  := btreeid.fileVersion_gg00;
        dstate                      := d_release;
        replace_baserecords         := true;
        viewscanpar.vsc_start_tabid := bsurrogate;
        (* PTS 1111576 E.Z. *)
        IF  (btablekind in [twithkey, twithoutkey])
        THEN
            BEGIN
            tableid             := bsurrogate;
            replace_baserecords := false;
            dstate              := d_fix;
            END
        ELSE
            IF  btablekind = tcomplexview
            THEN
                BEGIN
                sysk           := tab_ptr^.syskey;
                sysk.sentrytyp := cak_eviewtext;
                found          := false;
                REPEAT
                    a10get_sysinfo (acv,
                          sysk, d_release, buf, b_err);
                    IF  b_err = e_ok
                    THEN
                        WITH buf^.sviewtext DO
                            BEGIN
                            i := 1;
                            WHILE (i <= vttabcount) AND NOT(found) DO
                                WITH vttab[ i ] DO
                                    IF  vttcomplex_view
                                    THEN
                                        i := succ(i)
                                    ELSE
                                        found := true;
                                    (*ENDIF*) 
                                (*ENDWITH*) 
                            (*ENDWHILE*) 
                            IF  NOT (found)
                            THEN
                                i := 1;
                            (*ENDIF*) 
                            WITH vttab[ i ] DO
                                BEGIN
                                sysk.stableid := vtttableid;
                                END;
                            (*ENDWITH*) 
                            END;
                        (*ENDWITH*) 
                    (*ENDIF*) 
                UNTIL
                    found OR (b_err <> e_ok);
                (*ENDREPEAT*) 
                IF  b_err = e_ok
                THEN
                    BEGIN
                    tableid := sysk.stableid;
                    a06_systable_get (acv, d_release, tableid,
                          buf, true, ok);
                    IF  NOT ok
                    THEN
                        b_err := e_sysinfo_not_found
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END
            ELSE
                buf := tab_ptr;
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
    IF  (replace_baserecords) AND (b_err = e_ok)
    THEN
        WITH buf^, sbase DO
            (* PTS 1111576 E.Z. *)
            IF  (btablekind in [twithkey, twithoutkey])
            THEN
                BEGIN
                tableid := buf^.syskey.stableid;
                END
            ELSE
                IF  btablekind = tonebase
                THEN
                    tableid  := btreeid.fileTabId_gg00
                ELSE
                    IF  btablekind = tview
                    THEN
                        a06_view_get_basetable (acv,
                              buf^.syskey.stableid, 1, tableid);
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDWITH*) 
    (*ENDIF*) 
    IF  (acv.a_returncode = 0) AND (b_err = e_ok)
    THEN
        BEGIN
        a06_systable_get (acv, dstate, tableid, base_ptr, true, ok);
        IF  NOT ok
        THEN
            a07ak_system_error (acv, 22, 1)
        ELSE
            IF  base_ptr^.sbase.btablekind <> tcatalog_table
            THEN
                BEGIN
                WITH base_ptr^.sbase DO
                    BEGIN
                    a10_version (acv, base_ptr^.sbase,
                          m_succ_file_version, false);
                    version_no                 := btreeid.fileVersion_gg00;
                    viewscanpar.vsc_filevers   := version_no;
                    viewscanpar.vsc_base_tabid := btreeid.fileTabId_gg00;
                    END;
                (*ENDWITH*) 
                IF  replace_baserecords
                THEN
                    BEGIN
                    a10repl_sysinfo (acv, base_ptr, b_err);
                    END;
                (*ENDIF*) 
                END
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  b_err <> e_ok
    THEN
        a07_b_put_error (acv, b_err, 1);
    (*ENDIF*) 
    END
ELSE
    WITH tab_ptr^.sbase DO
        BEGIN
        viewscanpar.vsc_filevers   := btreeid.fileVersion_gg00;
        viewscanpar.vsc_base_tabid := btreeid.fileTabId_gg00;
        END;
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22priv_all_set   (VAR acv : tak_all_command_glob;
            VAR a22v : a22_grant_glob;
            grant    : boolean);
 
VAR
      upd   : boolean;
      ref   : boolean;
      sel   : boolean;
      sup   : boolean;
      stop  : boolean;
      p     : tak00_PrivilegeSet;
      error : tgg00_BasisError;
 
BEGIN
WITH acv, a22v, g2privileges DO
    IF  a_returncode = 0
    THEN
        BEGIN
        error           := e_ok;
        g2privileges    := a01emptypriv;
        g2ti            := a_ap_tree^[ g2tispec ].n_lo_level;
        g2tisel         := 0;
        g2tiupd         := 0;
        g2tiref         := 0;
        g2tisup         := 0;
        upd             := false;
        sel             := false;
        ref             := false;
        sup             := false;
        stop            := false;
        g2allprivileges := false;
        REPEAT
            p := [  ];
            CASE a_ap_tree^[ g2ti ].n_symb OF
                s_all_priv :
                    BEGIN
                    g2allprivileges:= true;
                    priv_all_set   := g2grantor_priv.priv_all_grant_set;
                    END;
                s_alter :
                    p := [ r_alter ];
                s_index :
                    p := [ r_index ];
                s_insert :
                    p := [ r_ins ];
                s_delete :
                    p := [ r_del ];
                s_link :
                    IF  ref
                    THEN
                        error := e_duplicate_privilege
                    ELSE
                        BEGIN
                        ref     := true;
                        g2tiref := a_ap_tree^ [ g2ti ].n_lo_level;
                        IF  g2tiref = 0
                        THEN
                            p := [ r_link ]
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                s_update :
                    IF  upd
                    THEN
                        error := e_duplicate_privilege
                    ELSE
                        BEGIN
                        upd     := true;
                        g2tiupd := a_ap_tree^ [ g2ti ].n_lo_level;
                        IF  g2tiupd = 0
                        THEN
                            p := [ r_upd ]
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                s_select :
                    IF  sel
                    THEN
                        error := e_duplicate_privilege
                    ELSE
                        BEGIN
                        sel     := true;
                        g2tisel := a_ap_tree^ [ g2ti ].n_lo_level;
                        IF  g2tisel = 0
                        THEN
                            p := [ r_sel ]
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                s_selupd :
                    IF  sup
                    THEN
                        error := e_duplicate_privilege
                    ELSE
                        BEGIN
                        sup     := true;
                        g2tisup := a_ap_tree^ [ g2ti ].n_lo_level;
                        IF  g2tisup = 0
                        THEN
                            p := [ r_sel, r_upd ]
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                OTHERWISE
                    stop := true;
                END;
            (*ENDCASE*) 
            IF  p <> [  ]
            THEN
                IF  p * priv_all_set <> [  ]
                THEN
                    error := e_duplicate_privilege
                ELSE
                    IF  p - g2grantor_priv.priv_all_grant_set <> [  ]
                    THEN
                        BEGIN
                        IF  r_upd in p (* PTS 1111776 *)
                        THEN
                            BEGIN
                            IF  (priv_col_upd_grant in g2grantor_priv.priv_col_exist) AND
                                (g2grantor_priv.priv_grant_upd_set <> [])
                            THEN
                                BEGIN
                                priv_col_exist := priv_col_exist + [priv_col_upd];
                                priv_upd_set   := priv_upd_set + g2grantor_priv.priv_grant_upd_set;
                                IF  g2grant_option OR NOT (grant)
                                THEN
                                    BEGIN
                                    priv_col_exist := priv_col_exist + [priv_col_upd_grant];
                                    priv_grant_upd_set := priv_grant_upd_set +
                                          g2grantor_priv.priv_grant_upd_set;
                                    END;
                                (*ENDIF*) 
                                END
                            ELSE
                                error := e_missing_privilege
                            (*ENDIF*) 
                            END
                        ELSE
                            error := e_missing_privilege
                        (*ENDIF*) 
                        END
                    ELSE
                        priv_all_set := priv_all_set + p;
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
            g2ti := a_ap_tree^[ g2ti ].n_sa_level;
        UNTIL
            (stop) OR (error <> e_ok);
        (*ENDREPEAT*) 
        IF  error <> e_ok
        THEN
            a07_b_put_error (acv, error, a_ap_tree^[ g2ti ].n_pos)
        ELSE
            IF  g2grant_option OR NOT (grant)
            THEN
                priv_all_grant_set := priv_all_set;
&           ifdef trace
            (*ENDIF*) 
        (*ENDIF*) 
        a06td_priv (g2privileges, 'g2privileges      ', false);
&       endif
        END;
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22put_bprivileges (VAR acv : tak_all_command_glob;
            VAR a22v        : a22_grant_glob);
 
VAR
      b_err : tgg00_BasisError;
      priv  : tak_privilege;
 
BEGIN
IF  acv.a_returncode = 0
THEN
    WITH a22v.g2tablearr1^.sbase DO
        BEGIN
        a06public_priv (acv, a22v.g2tablearr1^.sbase, priv);
        IF  (priv.priv_all_set   <> bpriv_all_set) OR
            (priv.priv_col_exist <> bpriv_col_exist)
        THEN
            BEGIN
            bpriv_all_set   := priv.priv_all_set;
            bpriv_col_exist := priv.priv_col_exist;
            a10repl_sysinfo (acv, a22v.g2tablearr1, b_err);
            IF  b_err <> e_ok
            THEN
                a07_b_put_error (acv, b_err, 1)
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22put_privileges (VAR acv : tak_all_command_glob;
            VAR old_priv    : tak_privilege;
            VAR rev_priv    : tak_privilege;
            VAR new_priv    : tak_privilege;
            VAR all_col_set : tak_columnset;
            grant_option    : boolean;
            grant           : boolean);
 
VAR
      j       : tak_priv_descriptors;
      all_set : tak00_PrivilegeSet;
 
BEGIN
WITH acv, new_priv DO
    IF  a_returncode = 0
    THEN
        BEGIN
&       ifdef trace
        a06td_priv (old_priv    , 'oldpriv           ', true);
        a06td_priv (rev_priv    , 'revpriv           ', true);
&       endif
        new_priv := old_priv;
        IF  grant
        THEN
            BEGIN
            priv_all_set := priv_all_set + rev_priv.priv_all_set;
            IF  grant_option
            THEN
                priv_all_grant_set :=
                      priv_all_grant_set + rev_priv.priv_all_set;
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            IF  r_sel in rev_priv.priv_all_set
            THEN
                BEGIN
                rev_priv.priv_sel_set       := all_col_set;
                rev_priv.priv_grant_sel_set := all_col_set;
                END;
            (*ENDIF*) 
            IF  r_upd in rev_priv.priv_all_set
            THEN
                BEGIN
                rev_priv.priv_upd_set       := all_col_set;
                rev_priv.priv_grant_upd_set := all_col_set
                END;
            (*ENDIF*) 
            IF  r_link in rev_priv.priv_all_set
            THEN
                BEGIN
                rev_priv.priv_ref_set       := all_col_set;
                rev_priv.priv_grant_ref_set := all_col_set
                END;
            (*ENDIF*) 
            priv_all_set       :=
                  priv_all_set - rev_priv.priv_all_set;
            priv_all_grant_set :=
                  priv_all_grant_set - rev_priv.priv_all_set;
            END;
        (*ENDIF*) 
        FOR j := priv_col_sel TO priv_col_ref_grant DO
            IF  grant
            THEN
                priv_col[ j ] := priv_col[ j ] + rev_priv.priv_col[ j ]
            ELSE
                IF  rev_priv.priv_col[ j ] <> [  ]
                THEN
                    BEGIN
                    all_set := priv_all_set;
                    CASE j OF
                        priv_col_sel :
                            IF  r_sel in priv_all_set
                            THEN
                                BEGIN
                                priv_all_set  := priv_all_set - [r_sel];
                                priv_col[ j ] := all_col_set -
                                      rev_priv.priv_col[ j ]
                                END;
                            (*ENDIF*) 
                        priv_col_upd :
                            IF  r_upd in priv_all_set
                            THEN
                                BEGIN
                                priv_all_set  := priv_all_set - [r_upd];
                                priv_col[ j ] := all_col_set -
                                      rev_priv.priv_col[ j ]
                                END;
                            (*ENDIF*) 
                        priv_col_ref :
                            IF  r_link in priv_all_set
                            THEN
                                BEGIN
                                priv_all_set  := priv_all_set -[r_link];
                                priv_col[ j ] := all_col_set -
                                      rev_priv.priv_col[ j ]
                                END;
                            (*ENDIF*) 
                        priv_col_sel_grant :
                            IF  r_sel in priv_all_grant_set
                            THEN
                                BEGIN
                                priv_all_grant_set :=
                                      priv_all_grant_set - [r_sel];
                                priv_col[ j ]      := all_col_set -
                                      rev_priv.priv_col[ j ]
                                END;
                            (*ENDIF*) 
                        priv_col_upd_grant :
                            IF  r_upd in priv_all_grant_set
                            THEN
                                BEGIN
                                priv_all_grant_set :=
                                      priv_all_grant_set - [r_upd];
                                priv_col[ j ]      := all_col_set -
                                      rev_priv.priv_col[ j ]
                                END;
                            (*ENDIF*) 
                        priv_col_ref_grant :
                            IF  r_link in priv_all_grant_set
                            THEN
                                BEGIN
                                priv_all_grant_set :=
                                      priv_all_grant_set - [r_link];
                                priv_col[ j ]      := all_col_set -
                                      rev_priv.priv_col[ j ]
                                END;
                            (*ENDIF*) 
                        END;
                    (*ENDCASE*) 
                    IF  all_set = priv_all_set
                    THEN
                        priv_col[ j ] := priv_col[ j ] -
                              rev_priv.priv_col[ j ];
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDFOR*) 
        IF  r_sel in priv_all_set
        THEN
            priv_sel_set := [  ];
        (*ENDIF*) 
        IF  r_upd in priv_all_set
        THEN
            priv_upd_set := [  ];
        (*ENDIF*) 
        IF  r_link in priv_all_set
        THEN
            priv_ref_set := [  ];
        (*ENDIF*) 
        IF  r_sel in priv_all_grant_set
        THEN
            priv_grant_sel_set := [  ];
        (*ENDIF*) 
        IF  r_upd in priv_all_grant_set
        THEN
            priv_grant_upd_set := [  ];
        (*ENDIF*) 
        IF  r_link in priv_all_grant_set
        THEN
            priv_grant_ref_set := [  ]
        (*ENDIF*) 
        END;
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22replace_base_records (VAR acv : tak_all_command_glob;
            VAR a22v : a22_grant_glob);
 
VAR
      b_err  : tgg00_BasisError;
 
BEGIN
WITH acv, a22v DO
    IF  (a_returncode = 0)
    THEN
        WITH g2p_arr.pbasep^.sbase DO
            IF  (btablekind = twithkey)    OR
                (btablekind = twithoutkey)
            THEN
                BEGIN
                a10repl_sysinfo (acv, g2p_arr.pbasep, b_err);
                IF  b_err <> e_ok
                THEN
                    a07_b_put_error (acv, b_err, 1);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
        (*ENDWITH*) 
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22same_grantee    (VAR acv : tak_all_command_glob;
            VAR a22v : a22_grant_glob);
 
VAR
      tia    : integer;
      tin    : integer;
      p1     : integer;
      p2     : integer;
      l1     : integer;
      l2     : integer;
      result : tsp00_LcompResult;
 
BEGIN
WITH acv, a22v DO
    IF  a_returncode = 0
    THEN
        BEGIN
        tia          := g2tiuser;
        g2user_count := 0;
        REPEAT
            g2user_count := g2user_count + 1;
            tin          := a_ap_tree^[ tia ].n_sa_level;
            p1           := a_ap_tree^[ tia ].n_pos;
            l1           := a_ap_tree^[ tia ].n_length;
            WHILE (tin <> 0) AND (a_returncode = 0) DO
                BEGIN
                p2 :=  a_ap_tree^[ tin ].n_pos;
                l2 :=  a_ap_tree^[ tin ].n_length;
                s30cmp (a_cmd_part^.sp1p_buf, p1, l1,
                      a_cmd_part^.sp1p_buf, p2, l2, result);
                IF  result  = l_equal
                THEN
                    a07_b_put_error (acv, e_duplicate_name,
                          a_ap_tree^[ tin ].n_pos)
                ELSE
                    tin := a_ap_tree^[ tin ].n_sa_level;
                (*ENDIF*) 
                END;
            (*ENDWHILE*) 
            tia := a_ap_tree^[ tia ].n_sa_level;
        UNTIL
            (tia = 0) OR (a_returncode <> 0);
        (*ENDREPEAT*) 
        END;
    (*ENDIF*) 
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22sequence_priv (VAR acv : tak_all_command_glob;
            VAR a22v : a22_grant_glob;
            grant    : boolean);
 
VAR
      b_err   : tgg00_BasisError;
      privbuf : tak_sysbufferaddress;
      priv    : tak_privilege;
 
BEGIN
WITH acv, a22v DO
    BEGIN
    a06_get_priv (acv, g2p_arr.pbasep, priv);
    IF  NOT (r_owner in priv.priv_all_set)
    THEN
        a07_kw_put_error (acv, e_missing_privilege, 1, cak_i_userid)
    ELSE
        BEGIN
        IF  g2username = a01_i_public
        THEN (* Grant/ revoke to/from PUBLIC *)
            BEGIN
            IF  g2p_arr.pbasep^.ssequence.seq_public <> grant
            THEN
                BEGIN
                g2p_arr.pbasep^.ssequence.seq_public := grant;
                a10_add_repl_sysinfo (acv,
                      g2p_arr.pbasep, false, b_err);
                IF  b_err <> e_ok
                THEN
                    a07_b_put_error (acv, b_err, 1)
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        g2privkey           := a01defaultkey;
        g2privkey.sauthid   :=
              g2p_arr.pbasep^.ssequence.seq_surrogate;
        g2privkey.suserid   := g2user_id;
        g2privkey.sentrytyp := cak_esequencepriv;
        g2privkey.skeylen   := mxak_standard_sysk + SURROGATE_MXGG00;
        IF  grant
        THEN
            BEGIN
            a10_fix_len_get_sysinfo (acv, g2privkey, d_release,
                  sizeof (tak_proc_seq_privilege),
                  0, privbuf, b_err);
            IF  b_err = e_sysinfo_not_found
            THEN
                BEGIN
                WITH privbuf^.sprocseqpriv DO
                    BEGIN
                    psp_grantOption := g2grant_option;
                    psp_priv        := [r_sel];
                    a11put_date_time (psp_date, psp_time)
                    END;
                (*ENDWITH*) 
                a10_add_repl_sysinfo (acv,
                      privbuf, true, b_err);
                IF  b_err = e_ok
                THEN
                    a19add_usertab  (acv, g2user_id,
                          g2p_arr.pbasep^.ssequence.seq_surrogate,
                          ut_sequence)
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            a10del_sysinfo (acv, g2privkey, b_err);
            IF  b_err = e_sysinfo_not_found
            THEN
                b_err := e_ok
            ELSE
                a19del_usertab  (acv, g2user_id,
                      g2p_arr.pbasep^.ssequence.seq_surrogate)
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  b_err <> e_ok
        THEN
            a07_b_put_error (acv, b_err, 1)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22table_ex_get   (VAR acv : tak_all_command_glob;
            VAR a22v : a22_grant_glob);
 
CONST
      c_inclusiveSequence = true;
 
BEGIN
WITH acv, a22v DO
    BEGIN
    IF  a_returncode = 0
    THEN
        BEGIN
        g2ti := a_ap_tree^[ g2tispec ].n_lo_level;
        REPEAT
            g2ti := a_ap_tree^[ g2ti ].n_sa_level;
        UNTIL
            (a_ap_tree^[ g2ti ].n_symb = s_authid) OR
            (a_ap_tree^[ g2ti ].n_symb = s_tablename);
        (*ENDREPEAT*) 
        IF  a_sqlmode in [sqlm_oracle, sqlm_internal]
        THEN
            BEGIN
            g2sequence := a23exist_sequence (acv, g2ti,
                  NOT c_inclusiveSequence,
                  g2p_arr.pbasep, g2authname, g2tablen);
            IF  g2authname = a01_i_temp
            THEN
                BEGIN (* a23exist_sequence returned unknown user *)
                a_returncode := 0;
                a_errorpos   := 0
                END
            (*ENDIF*) 
            END
        ELSE
            g2sequence := false;
        (*ENDIF*) 
        IF  NOT g2sequence
        THEN
            a11get_check_table (acv, false, false, true, [  ],
                  true,true, d_fix, g2ti, g2authname, g2tablen, g2p_arr)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  a_returncode = 0
    THEN
        ak22get_grantor_priv (acv, a22v)
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22user_priv (VAR acv : tak_all_command_glob;
            VAR a22v        : a22_grant_glob;
            procedure_priv  : boolean;
            grant           : boolean);
 
VAR
      new_sysinfo  : boolean;
      cascade      : boolean;
      new_priv     : tak_privilege;
      sysk         : tgg00_SysInfoKey;
 
BEGIN
WITH acv, a22v DO
    BEGIN
&   ifdef trace
    t01lidentifier (ak_sem, g2username);
    t01lidentifier (ak_sem, a01_i_public);
&   endif
    IF  g2username = a01_i_public
    THEN (* Grant/ revoke to/from PUBLIC *)
        g2user_id := cak_public_id;
    (*ENDIF*) 
    ak22get_priv_rec (acv, a22v, procedure_priv, new_sysinfo);
    IF  a_returncode = 0
    THEN
        BEGIN
        IF  new_sysinfo AND NOT grant
        THEN (* current user has not granted any privilege  *)
            (* to specified user, release privilege record *)
            a10_key_del (acv, g2privbuf^.syskey)
        ELSE
            BEGIN
            sysk := g2privbuf^.syskey;
            ak22put_privileges (acv, g2old_user_priv, g2privileges,
                  new_priv, g2all_col_privset, g2grant_option, grant);
            a22add_priv_rec (acv, g2p_arr.pbasep,
                  new_priv, g2privbuf, new_sysinfo, cascade);
            IF  cascade AND NOT (grant)
            THEN
                a22revoke_cascade (acv, g2p_arr.pbasep,
                      g2all_col_privset, g2user_id, g2privileges);
            (*ENDIF*) 
            a10_rel_sysinfo (acv, sysk)
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (g2username = a01_i_public) AND
        (a_returncode = 0)
    THEN (* Grant/ revoke to/from PUBLIC *)
        ak22put_bprivileges (acv, a22v);
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a22_call_semantic  (VAR acv : tak_all_command_glob);
 
VAR
      a22v : a22_grant_glob;
 
BEGIN
WITH acv, a22v DO
    BEGIN
    ak22init_glob (a22v);
    a10_cache_delete (acv, NOT c_is_rollback);
    WITH a_ap_tree^[a_ap_tree^[ 0 ].n_lo_level] DO
        CASE n_subproc OF
            cak_i_role :
                ak22grant_revoke_role (acv, a22v);
            cak_i_schema :
                ak22grant_revoke_schema (acv, a22v);
            OTHERWISE
                BEGIN
                g2grant_option :=
                      a_ap_tree^[ a_ap_tree^[ 0 ].n_lo_level ].n_length = cak_i_grant;
                ak22_grant_revoke (acv, a22v,
                      (a_ap_tree^[ a_ap_tree^[ 0 ].n_lo_level ].n_subproc = cak_i_grant))
                END;
            END;
        (*ENDCASE*) 
    (*ENDWITH*) 
    IF  a_returncode <> 0
    THEN
        IF  a_internal_sql <> sql_restore_schema
        THEN
            a_part_rollback := true;
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22grant_revoke_schema (VAR acv : tak_all_command_glob;
            VAR a22v : a22_grant_glob);
 
TYPE
      IdentifierArray = ARRAY[1..32767] OF tsp00_KnlIdentifier;
 
VAR
      isGrant          : boolean;
      alterIn          : boolean;
      createIn         : boolean;
      dropIn           : boolean;
      e                : tgg00_BasisError;
      errorPos         : integer;
      ix               : integer;
      errorIdx         : integer;
      ti               : integer;
      root_ti          : integer;
      cntSchemas       : integer;
      cntUsers         : integer;
      pSchemas         : tsp00_KnlIdentifierPtr;
      pUser            : tsp00_KnlIdentifierPtr;
      pIdentifierArray : ^IdentifierArray;
 
BEGIN
isGrant  := true;
alterIn  := false;
createIn := false;
dropIn   := false;
root_ti  := acv.a_ap_tree^[0].n_lo_level;
ti := acv.a_ap_tree^[root_ti].n_sa_level;
WHILE ti <> 0 DO
    BEGIN
    CASE acv.a_ap_tree^[ti].n_subproc OF
        cak_i_alterin :
            alterIn := true;
        cak_i_createin :
            createIn := true;
        cak_i_dropin :
            dropIn := true;
        END;
    (*ENDCASE*) 
    ti := acv.a_ap_tree^[ti].n_sa_level;
    END;
(*ENDWHILE*) 
ti := acv.a_ap_tree^[root_ti].n_lo_level;
ti := acv.a_ap_tree^[ti].n_sa_level;
(* eval space needed to store schema names *)
cntSchemas := 0;
WHILE ti <> 0 DO
    BEGIN
    cntSchemas := cntSchemas + 1;
    ti := acv.a_ap_tree^[ti].n_sa_level;
    END;
(*ENDWHILE*) 
pSchemas := gg941Allocate(acv.a_transinf.tri_trans, cntSchemas * sizeof(tsp00_KnlIdentifier));
IF  pSchemas <> NIL
THEN
    BEGIN
    pIdentifierArray := @pSchemas^;
    ti := acv.a_ap_tree^[root_ti].n_lo_level;
    ti := acv.a_ap_tree^[ti].n_sa_level;
    ix := 1;
    WHILE ti <> 0 DO
        BEGIN
        a05identifier_get (acv, ti, sizeof (pIdentifierArray^[ix]), pIdentifierArray^[ix]);
        IF  pIdentifierArray^[ix] = acv.a_curr_user_name
        THEN
            BEGIN
            a07_nb_put_error (acv, e_user_not_allowed,
                  acv.a_ap_tree^[ti].n_pos, pIdentifierArray^[ix]);
            ti := 0;
            END
        ELSE
            ti := acv.a_ap_tree^[ti].n_sa_level;
        (*ENDIF*) 
        ix := ix + 1;
        END;
    (*ENDWHILE*) 
    END;
(*ENDIF*) 
ti := acv.a_ap_tree^[root_ti].n_lo_level;
ti := acv.a_ap_tree^[ti].n_lo_level;
(* eval space needed to store user names *)
cntUsers := 0;
WHILE ti <> 0 DO
    BEGIN
    cntUsers := cntUsers + 1;
    ti := acv.a_ap_tree^[ti].n_lo_level;
    END;
(*ENDWHILE*) 
pUser:= gg941Allocate(acv.a_transinf.tri_trans, cntUsers * sizeof(tsp00_KnlIdentifier));
IF  pUser <> NIL
THEN
    BEGIN
    pIdentifierArray := @pUser^;
    ti := acv.a_ap_tree^[root_ti].n_lo_level;
    ti := acv.a_ap_tree^[ti].n_lo_level;
    ix := 1;
    WHILE ti <> 0 DO
        BEGIN
        a05identifier_get (acv, ti, sizeof (pIdentifierArray^[ix]), pIdentifierArray^[ix]);
        IF  pIdentifierArray^[ix] = acv.a_curr_user_name
        THEN
            BEGIN
            a07_nb_put_error (acv, e_user_not_allowed,
                  acv.a_ap_tree^[ti].n_pos, pIdentifierArray^[ix]);
            ti := 0;
            END
        ELSE
            ti := acv.a_ap_tree^[ti].n_lo_level;
        (*ENDIF*) 
        ix := ix + 1;
        END;
    (*ENDWHILE*) 
    END;
(*ENDIF*) 
IF  acv.a_returncode = 0
THEN
    BEGIN
    IF  (pUser <> NIL) AND (pSchemas <> NIL)
    THEN
        BEGIN
        errorIdx := a103GrantRevokeSchemaPrivilege (acv, acv.a_ap_tree^[root_ti].n_length = cak_i_grant,
              alterIn, createIn, dropIn, cntSchemas, pSchemas, cntUsers, pUser);
        IF  acv.a_returncode <> 0
        THEN
            BEGIN (* error analysis, find out error position and error name *)
            ix       := errorIdx;
            errorPos := 1;
            e        := e_ok;
            IF  acv.a_returncode = a071_return_code (e_unknown_user, acv.a_sqlmode)
            THEN
                BEGIN
                e                := e_unknown_user;
                pIdentifierArray := @pUser^;
                ti := acv.a_ap_tree^[root_ti].n_lo_level;
                ti := acv.a_ap_tree^[ti].n_lo_level;
                WHILE (ix > 1) AND (ti > 0) DO
                    BEGIN
                    ix := ix - 1;
                    ti := acv.a_ap_tree^[ti].n_lo_level;
                    END;
                (*ENDWHILE*) 
                IF  ti > 0
                THEN
                    errorPos := acv.a_ap_tree^[ti].n_pos;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                IF  acv.a_returncode = a071_return_code (e_unknown_name, acv.a_sqlmode)
                THEN
                    e := e_unknown_name
                ELSE
                    IF  acv.a_returncode = a071_return_code (e_missing_privilege, acv.a_sqlmode)
                    THEN
                        e := e_missing_privilege;
                    (*ENDIF*) 
                (*ENDIF*) 
                IF  e <> e_ok
                THEN
                    BEGIN
                    pIdentifierArray := @pSchemas^;
                    ti := acv.a_ap_tree^[root_ti].n_lo_level;
                    ti := acv.a_ap_tree^[ti].n_sa_level;
                    WHILE (ix > 1) AND (ti > 0) DO
                        BEGIN
                        ix := ix - 1;
                        ti := acv.a_ap_tree^[ti].n_sa_level;
                        END;
                    (*ENDWHILE*) 
                    IF  ti > 0
                    THEN
                        errorPos := acv.a_ap_tree^[ti].n_pos;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  e <> e_ok
            THEN
                BEGIN
                acv.a_returncode := 0;
                a07_nb_put_error (acv, e, errorPos, pIdentifierArray^[errorIdx]);
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END
    ELSE
        a07_b_put_error (acv, e_no_more_memory, 1);
    (*ENDIF*) 
    END;
(*ENDIF*) 
gg941Deallocate(acv.a_transinf.tri_trans, pSchemas);
gg941Deallocate(acv.a_transinf.tri_trans, pUser);
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22grant_revoke_role (VAR acv : tak_all_command_glob;
            VAR a22v : a22_grant_glob);
 
VAR
      ti_role    : integer;
      role_ptr   : tak_sysbufferaddress;
      role_name  : tsp00_KnlIdentifier;
 
BEGIN
ti_role       :=
      acv.a_ap_tree^[acv.a_ap_tree^[ 0 ].n_lo_level].n_lo_level;
a22v.g2tiuser :=
      acv.a_ap_tree^[acv.a_ap_tree^[ 0 ].n_lo_level].n_sa_level;
ak22same_grantee (acv, a22v);
WHILE ti_role <> 0 DO
    BEGIN
    a05identifier_get (acv, ti_role, sizeof (role_name), role_name);
    IF  a06role_exist (acv, role_name, d_release, role_ptr)
    THEN
        BEGIN
        a22v.g2role_id := role_ptr^.syskey.stableid;
        ak22one_role_grant_revoke (acv, a22v, a22v.g2tiuser);
        ti_role := acv.a_ap_tree^[ti_role].n_lo_level
        END
    ELSE
        BEGIN (* ADIS 1001573, T.A. 15.10.1998 *)
        a07_nb_put_error (acv, e_unknown_name,
              acv.a_ap_tree^[ti_role].n_pos, role_name);
        ti_role := 0
        END;
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22one_role_grant_revoke (VAR acv : tak_all_command_glob;
            VAR a22v      : a22_grant_glob;
            ti_grantee    : integer);
 
VAR
      ok          : boolean;
      user_info   : tak_user_info;
 
BEGIN
WHILE ti_grantee <> 0 DO
    BEGIN
    a05identifier_get (acv, ti_grantee,
          sizeof (a22v.g2username), a22v.g2username);
    IF  a22v.g2username = a01_i_public
    THEN
        BEGIN
        ok                   := true;
        user_info.ui_is_role := false;
        user_info.ui_id      := cak_public_id
        END
    ELSE
        IF  a22v.g2username = acv.a_curr_user_name (* PTS 1113279*)
        THEN
            BEGIN
            ok := false;
            a07_nb_put_error (acv, e_user_not_allowed,
                  acv.a_ap_tree^[ti_grantee].n_pos, a22v.g2username)
            END
        ELSE
            ok := a22exist_user (acv, a22v.g2username,
                  acv.a_ap_tree^[ti_grantee].n_pos, user_info);
        (*ENDIF*) 
    (*ENDIF*) 
    IF  ok
    THEN
        BEGIN
        a22v.g2user_id := user_info.ui_id;
        ak22role_grant_revoke (acv, a22v, user_info.ui_is_role)
        END;
    (*ENDIF*) 
    ti_grantee := acv.a_ap_tree^[ti_grantee].n_sa_level
    END;
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22role_grant_revoke (VAR acv : tak_all_command_glob;
            VAR a22v      : a22_grant_glob;
            grant_to_role : boolean);
 
VAR
      b_err       : tgg00_BasisError;
      is_grant    : boolean;
      privbuf     : tak_sysbufferaddress;
      p           : tak_sysbufferaddress;
      pUser       : tak_sysbufferaddress;
      userKey     : tgg00_SysInfoKey;
 
BEGIN
is_grant :=
      acv.a_ap_tree^[acv.a_ap_tree^[ 0 ].n_lo_level].n_length = cak_i_grant;
a22v.g2privkey            := a01defaultkey;
a22v.g2privkey.sauthid    := a22v.g2role_id;
a22v.g2privkey.sentrytyp  := cak_eprivuser;
a22v.g2privkey.suserid    := a22v.g2user_id;
a22v.g2privkey.sgrantuser := acv.a_curr_user_id;
a22v.g2privkey.skeylen    := mxak_standard_sysk + 2 * SURROGATE_MXGG00;
a10_fix_len_get_sysinfo (acv, a22v.g2privkey, d_fix,
      sizeof (tak_privuserrecord), 0, privbuf, b_err);
IF  ((b_err = e_sysinfo_not_found) AND is_grant)
    OR
    (( b_err = e_ok) AND NOT is_grant)
THEN
    BEGIN
    IF  NOT is_grant
    THEN (* delete privilege *)
        a10del_sysinfo (acv, a22v.g2privkey, b_err)
    ELSE
        b_err := e_ok;
    (*ENDIF*) 
    a22v.g2privkey.skeylen := mxak_standard_sysk + SURROGATE_MXGG00;
    IF  b_err = e_ok
    THEN
        a10next_sysinfo (acv, a22v.g2privkey, 2 * SURROGATE_MXGG00 + 4,
              d_release, cak_eprivuser, p, b_err);
    (*ENDIF*) 
    IF  b_err = e_no_next_record
    THEN
        BEGIN (* first grant to role *)
        b_err := e_ok;
        IF  is_grant
        THEN
            BEGIN
            a19addroletab   (acv, a22v.g2user_id, a22v.g2role_id);
            IF  grant_to_role
            THEN
                ak22cycle_check (acv, a22v.g2user_id, a22v.g2user_id)
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            IF  a19IsDefaultRole (acv, a22v.g2user_id, a22v.g2role_id) (* PTS 1129910 *)
            THEN
                BEGIN
                userKey           := a01defaultkey;
                userKey.sauthid   := a22v.g2user_id;
                userKey.sentrytyp := cak_euser;
                a10get_sysinfo (acv, userKey, d_release, pUser, b_err);
                IF  b_err = e_ok
                THEN
                    BEGIN
                    IF  pUser^.suser.userrolecnt > 0
                    THEN
                        BEGIN
                        pUser^.suser.userrolecnt := pUser^.suser.userrolecnt - 1;
                        IF  pUser^.suser.userrolecnt = 0
                        THEN
                            pUser^.suser.userroleinfo := role_none;
                        (*ENDIF*) 
                        a10repl_sysinfo (acv, pUser, b_err)
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            a19delroletab  (acv, a22v.g2user_id, a22v.g2role_id);
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  b_err = e_ok
    THEN
        IF  is_grant
        THEN
            BEGIN
            privbuf^.sprivuser.pru_segmentid := cak00_public_segment_id;
            a11put_date_time (privbuf^.sprivuser.pru_date,
                  privbuf^.sprivuser.pru_time);
            a22pack_priv (privbuf,
                  a01emptypriv, privbuf^.sprivuser.pru_priv);
            a10_add_repl_sysinfo (acv,
                  privbuf, true, b_err)
            END
        ELSE
            BEGIN
            ak22new_role_tab_version (acv, a22v.g2role_id);
            ak22role_version         (acv, a22v.g2role_id)
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  b_err <> e_ok
    THEN
        a07_b_put_error (acv, b_err, 1)
    (*ENDIF*) 
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22cycle_check (VAR acv : tak_all_command_glob;
            curr_role_id    : tgg00_Surrogate;
            VAR src_role_id : tgg00_Surrogate);
 
VAR
      b_err       : tgg00_BasisError;
      index       : integer;
      roletab_ptr : tak_sysbufferaddress;
      sysk        : tgg00_SysInfoKey;
 
BEGIN
&ifdef trace
t01surrogate (ak_sem, 'curr_role_id', curr_role_id);
t01surrogate (ak_sem, 'src_role_id ', src_role_id );
&endif
sysk           := a01defaultkey;
sysk.sauthid   := curr_role_id;
sysk.sentrytyp := cak_eroletab;
index          := 0;
REPEAT
    index := index + 1;
    a10get_sysinfo (acv, sysk, d_release, roletab_ptr, b_err);
    IF  b_err = e_ok
    THEN
        IF  index > roletab_ptr^.susertab.usertabcount
        THEN
            IF  roletab_ptr^.susertab.usertabnext_exist
            THEN
                a06inc_linkage (sysk.slinkage)
            ELSE
                b_err := e_sysinfo_not_found
            (*ENDIF*) 
        ELSE
            WITH roletab_ptr^.susertab.usertabdef[index] DO
                IF  NOT ut_empty
                THEN
                    BEGIN
                    IF  ut_surrogate = src_role_id
                    THEN
                        b_err := e_role_cycle
                    ELSE
                        ak22cycle_check (acv,
                              ut_surrogate, src_role_id);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDWITH*) 
        (*ENDIF*) 
    (*ENDIF*) 
UNTIL
    b_err <> e_ok;
(*ENDREPEAT*) 
IF  b_err <> e_sysinfo_not_found
THEN
    a07_b_put_error (acv, b_err, 1)
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22role_version (VAR acv : tak_all_command_glob;
            role_id : tgg00_Surrogate);
 
VAR
      b_err       : tgg00_BasisError;
      index       : integer;
      roletab_ptr : tak_sysbufferaddress;
      sysk        : tgg00_SysInfoKey;
 
BEGIN
sysk           := a01defaultkey;
sysk.sauthid   := role_id;
sysk.sentrytyp := cak_eroletab;
index          := 0;
REPEAT
    index := index + 1;
    a10get_sysinfo (acv, sysk, d_fix,
          roletab_ptr, b_err);
    IF  b_err = e_ok
    THEN
        IF  index > roletab_ptr^.susertab.usertabcount
        THEN
            BEGIN
            a10rel_sysinfo (roletab_ptr);
            IF  roletab_ptr^.susertab.usertabnext_exist
            THEN
                a06inc_linkage (sysk.slinkage)
            ELSE
                b_err := e_sysinfo_not_found
            (*ENDIF*) 
            END
        ELSE
            WITH roletab_ptr^.susertab.usertabdef[index] DO
                IF  NOT ut_empty
                THEN
                    BEGIN
                    ak22new_role_tab_version (acv, ut_surrogate);
                    a10rel_sysinfo           (roletab_ptr);
                    ak22role_version         (acv, ut_surrogate)
                    END;
                (*ENDIF*) 
            (*ENDWITH*) 
        (*ENDIF*) 
    (*ENDIF*) 
UNTIL
    b_err <> e_ok;
(*ENDREPEAT*) 
IF  b_err <> e_sysinfo_not_found
THEN
    a07_b_put_error (acv, b_err, 1)
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22new_role_tab_version (VAR acv : tak_all_command_glob;
            VAR role_id : tgg00_Surrogate);
 
VAR
      ok          : boolean;
      b_err       : tgg00_BasisError;
      index       : integer;
      base_ptr    : tak_sysbufferaddress;
      usertab_ptr : tak_sysbufferaddress;
      sysk        : tgg00_SysInfoKey;
 
BEGIN
sysk           := a01defaultkey;
sysk.sauthid   := role_id;
sysk.sentrytyp := cak_eusertab;
index          := 0;
REPEAT
    a10get_sysinfo (acv, sysk, d_fix,
          usertab_ptr, b_err);
    IF  b_err = e_ok
    THEN
        WITH usertab_ptr^.susertab DO
            BEGIN
            index := 1;
            WHILE (index <= usertabcount) AND
                  (acv.a_returncode = 0) DO
                WITH usertabdef[index] DO
                    BEGIN
                    IF  NOT ut_empty AND
                        (ut_kind in [ut_base_table, ut_view])
                    THEN
                        BEGIN
                        a06_systable_get (acv, d_fix,
                              ut_surrogate, base_ptr, true, ok);
                        IF  ok
                        THEN
                            a23new_version_no (acv, base_ptr)
                        ELSE
                            a07ak_system_error (acv, 22, 2);
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    index := index + 1;
                    END;
                (*ENDWITH*) 
            (*ENDWHILE*) 
            a10rel_sysinfo (usertab_ptr);
            IF  usertabnext_exist
            THEN
                a06inc_linkage (sysk.slinkage)
            ELSE
                b_err := e_sysinfo_not_found
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
    (*ENDIF*) 
UNTIL
    b_err <> e_ok;
(*ENDREPEAT*) 
IF  b_err <> e_sysinfo_not_found
THEN
    a07_b_put_error (acv, b_err, 1)
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22_grant_revoke  (VAR acv : tak_all_command_glob;
            VAR a22v : a22_grant_glob;
            grant    : boolean);
 
VAR
      ti          : integer;
      grant_option: tsp00_C12;
      user_info   : tak_user_info;
      viewscanpar : tak_viewscan_par;
 
BEGIN
WITH acv, a22v DO
    BEGIN
    IF  grant
    THEN
        viewscanpar.vsc_type := v_save_scheme
    ELSE
        viewscanpar.vsc_type := v_revoke_priv;
    (*ENDIF*) 
    a27init_viewscanpar (acv, viewscanpar, viewscanpar.vsc_type);
    viewscanpar.vsc_restrict :=
          a_ap_tree^[a_ap_tree^[ 0 ].n_lo_level].n_length = cak_i_restrict;
    g2tispec   := a_ap_tree^[ g2ti ].n_lo_level;
    g2tiuser   := g2tispec;
    WHILE (a_ap_tree^[ g2tiuser ].n_subproc = cak_x_one_grant_spec) DO
        g2tiuser := a_ap_tree^[ g2tiuser ].n_sa_level;
    (*ENDWHILE*) 
    IF  grant
    THEN
        WITH viewscanpar DO
            BEGIN
            vsc_save_into  := false;
            vsc_cmd_cnt    := 0;
            vsc_first_save := true;
            END;
        (*ENDWITH*) 
    (*ENDIF*) 
    ak22same_grantee (acv, a22v);
    REPEAT
        ak22table_ex_get (acv, a22v);
        ak22priv_all_set (acv, a22v, grant);
        ak22column_priv  (acv, a22v, grant);
        IF  a_returncode = 0
        THEN
            IF  g2privileges.priv_c196 = a01emptypriv.priv_c196
            THEN
                a07_b_put_error (acv, e_missing_privilege, 1)
            ELSE
                IF  NOT g2sequence
                THEN
                    IF  NOT grant
                    THEN
                        a22new_version_no (acv,
                              g2p_arr.pbasep, g2versno, viewscanpar)
                    ELSE
                        IF  a_internal_sql = no_internal_sql
                        THEN
                            WITH viewscanpar, g2p_arr.pbasep^ DO
                                BEGIN
                                vsc_base_tabid := syskey.stableid;
                                ti := a_ap_tree^[ g2tispec ].n_sa_level;
                                vsc_last_save :=
                                      a_ap_tree^[ ti ].n_subproc <> cak_x_one_grant_spec;
                                a_p_arr1 := g2p_arr;
                                a15catalog_save (acv, viewscanpar);
                                vsc_first_save := false
                                END;
                            (*ENDWITH*) 
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
        g2ti := g2tiuser;
        WHILE (g2ti <> 0) AND (a_returncode = 0) DO
            BEGIN
            ti := g2ti;
            a06get_username (acv, ti, g2username);
            viewscanpar.vsc_type           := v_revoke_priv;
            viewscanpar.vsc_rp_rt_handling := false;
            viewscanpar.vsc_col_dropped    := false;
            IF  g2username <> a01_i_public
            THEN
                BEGIN
                IF  (g2username = a_curr_user_name) OR
                    (g2username = g2authname)
                THEN
                    a07_b_put_error (acv, e_user_not_allowed,
                          a_ap_tree^[ g2ti ].n_pos)
                ELSE
                    IF  a22exist_user (acv, g2username,
                        a_ap_tree^[ g2ti ].n_pos, user_info)
                    THEN
                        IF  user_info.ui_is_role AND g2grant_option
                        THEN
                            BEGIN
                            grant_option := 'GRANT OPTION';
                            a07_const_b_put_error (acv, e_missing_privilege,
                                  1, @grant_option, sizeof (grant_option))
                            END
                        ELSE
                            g2user_id := user_info.ui_id;
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
                END
            ELSE (* Grant / Revoke to/from PUBLIC *)
                g2user_id := cak_public_id;
            (*ENDIF*) 
            IF  a_returncode = 0
            THEN
                IF  g2sequence
                THEN
                    ak22sequence_priv (acv, a22v, grant)
                ELSE
                    BEGIN
                    IF  NOT grant AND (g2authname = a_curr_user_name)
                    THEN (* owner is allowed to revoke all privileges *)
                        ak22revoke_by_owner (acv, a22v)
                    ELSE (* user is allowed to revoke only privileges *)
                        (* he has granted                            *)
                        ak22user_priv (acv, a22v, false, grant);
                    (*ENDIF*) 
                    IF  (internal_trigger in g2p_arr.pbasep^.sbase.blinkexist) AND
                        NOT grant
                    THEN
                        ak22CheckReplicationPrivileges (acv,  a22v);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            g2ti := a_ap_tree^[ g2ti ].n_sa_level;
            END;
        (*ENDWHILE*) 
        IF  NOT (grant)
            AND (a_returncode = 0)
            AND NOT g2sequence
        THEN
            BEGIN
            ak22replace_base_records (acv, a22v);
            a10_all_release (acv);
            a_p_arr1 := g2p_arr;
            a27view_scan (acv, viewscanpar.vsc_base_tabid,
                  viewscanpar)
            END
        ELSE
            a10_all_release (acv);
        (*ENDIF*) 
        g2tispec := a_ap_tree^[ g2tispec ].n_sa_level;
    UNTIL
        (a_ap_tree^[ g2tispec ].n_subproc <> cak_x_one_grant_spec) OR
        (a_returncode <> 0);
    (*ENDREPEAT*) 
    IF  grant AND NOT g2sequence
    THEN
        BEGIN
        IF  a_internal_sql = no_internal_sql
        THEN
            BEGIN
            a_internal_sql := sql_alter_table;
            a15restore_catalog (acv, b01niltree_id, viewscanpar);
            a_internal_sql := no_internal_sql
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a22add_priv_rec (VAR acv : tak_all_command_glob;
            base_ptr        : tak_sysbufferaddress;
            VAR new_priv    : tak_privilege;
            priv_buf        : tak_sysbufferaddress;
            add_sysinfo     : boolean;
            VAR revoke_casc : boolean);
 
VAR
      new_sysinfo        : boolean;
      in_installation    : boolean;
      ut_tab_kind        : tak_usertab_descriptor;
      b_err              : tgg00_BasisError;
      i                  : tak_priv_descriptors;
      curr_index         : tak_priv_descriptors;
      privbuf            : tak_sysbufferaddress;
      p                  : tak_sysbufferaddress;
      curr_user          : tgg00_Surrogate;
      privkey            : tgg00_SysInfoKey;
      oldpriv            : tak_privilege;
 
BEGIN
in_installation := acv.a_initial_segment_header.sp1c_producer = sp1pr_installation;
WITH acv DO
    BEGIN
    revoke_casc := false;
    b_err       := e_ok;
    privkey     := priv_buf^.syskey;
    new_priv.priv_col_exist := [  ];
    FOR i := priv_col_sel TO priv_col_ref_grant DO
        BEGIN
        IF  new_priv.priv_col[ i ] <> [  ]
        THEN
            new_priv.priv_col_exist :=
                  new_priv.priv_col_exist + [ i ];
        (*ENDIF*) 
        END;
    (*ENDFOR*) 
&   ifdef trace
    a06td_priv(new_priv, 'new_priv          ', true);
&   endif
    IF  new_priv.priv_c196 = a01emptypriv.priv_c196
    THEN
        BEGIN
        IF  NOT (add_sysinfo)
        THEN
            a10del_sysinfo (acv, priv_buf^.syskey, b_err);
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        a11put_date_time (priv_buf^.sprivuser.pru_date,
              priv_buf^.sprivuser.pru_time);
        a22pack_priv (priv_buf,
              new_priv, priv_buf^.sprivuser.pru_priv);
        a10_add_repl_sysinfo (acv,
              priv_buf, add_sysinfo, b_err);
        END;
    (*ENDIF*) 
    IF  b_err <> e_ok
    THEN
        a07_b_put_error (acv, b_err, 1);
    (*ENDIF*) 
    IF  (a_returncode = 0) AND
        (privkey.sentrytyp <> cak_eprivproc)
    THEN
        BEGIN
        curr_user         := privkey.suserid;
        privkey.sentrytyp := cak_epriv;
        privkey.skeylen   := mxak_standard_sysk + SURROGATE_MXGG00;
        a10_fix_len_get_sysinfo (acv, privkey, d_fix,
              sizeof (tak_privrecord), 0, privbuf, b_err);
        oldpriv := a01emptypriv;
        IF  b_err = e_sysinfo_not_found
        THEN
            BEGIN
            privbuf^.spriv.pr_segmentid
                  := base_ptr^.sbase.bsegmentid;
            new_sysinfo := true;
            b_err := e_ok
            END
        ELSE
            BEGIN
            a06unpack_priv (privbuf^.spriv.pr_priv, oldpriv);
&           ifdef trace
            a06td_priv (oldpriv, 'oldpriv           ', true);
&           endif
            new_sysinfo := false
            END;
        (*ENDIF*) 
        IF  b_err = e_ok
        THEN
            WITH new_priv DO
                BEGIN
                new_priv          := a01emptypriv;
                privkey.sentrytyp := cak_eprivuser;
                REPEAT
                    a10next_sysinfo (acv, privkey, 2*SURROGATE_MXGG00 + 4,
                          d_release, cak_eprivuser, p, b_err);
                    IF  b_err = e_ok
                    THEN
                        BEGIN
                        new_priv.priv_all_set :=  priv_all_set +
                              p^.sprivuser.pru_priv.priv_all_set;
                        priv_all_grant_set    := priv_all_grant_set +
                              p^.sprivuser.pru_priv.priv_all_grant_set;
                        curr_index            := priv_col_sel;
                        FOR i := priv_col_sel TO
                              priv_col_ref_grant DO
                            BEGIN
                            IF  i in p^.sprivuser.pru_priv.priv_col_exist
                            THEN
                                BEGIN
                                priv_col[ i ]  := priv_col[ i ] +
                                      p^.sprivuser.
                                      pru_priv.priv_col[curr_index];
                                priv_col_exist :=
                                      priv_col_exist + [ i ];
                                IF  curr_index < priv_col_ref_grant
                                THEN
                                    curr_index := succ(curr_index)
                                (*ENDIF*) 
                                END;
                            (*ENDIF*) 
                            END;
                        (*ENDFOR*) 
                        END
                    ELSE
                        b_err := e_no_next_record;
                    (*ENDIF*) 
                UNTIL
                    (b_err <> e_ok);
                (*ENDREPEAT*) 
                IF  b_err = e_no_next_record
                THEN
                    BEGIN
                    b_err := e_ok;
                    IF  r_upd in priv_all_set
                    THEN
                        priv_col_exist :=
                              priv_col_exist - [ priv_col_upd ];
                    (*ENDIF*) 
                    IF  r_sel in priv_all_set
                    THEN
                        priv_col_exist :=
                              priv_col_exist - [ priv_col_sel ];
                    (*ENDIF*) 
                    IF  r_link in priv_all_set
                    THEN
                        priv_col_exist :=
                              priv_col_exist - [ priv_col_ref ];
                    (*ENDIF*) 
                    IF  r_upd in priv_all_grant_set
                    THEN
                        BEGIN
                        priv_col_exist     :=
                              priv_col_exist - [ priv_col_upd_grant ];
                        priv_grant_upd_set := [  ]
                        END;
                    (*ENDIF*) 
                    IF  r_sel in priv_all_grant_set
                    THEN
                        BEGIN
                        priv_col_exist     :=
                              priv_col_exist - [ priv_col_sel_grant ];
                        priv_grant_sel_set := [  ]
                        END;
                    (*ENDIF*) 
                    IF  r_link in priv_all_grant_set
                    THEN
                        BEGIN
                        priv_col_exist     :=
                              priv_col_exist - [ priv_col_ref_grant ];
                        priv_grant_ref_set := [  ]
                        END;
                    (*ENDIF*) 
                    a22pack_priv (privbuf,
                          new_priv, privbuf^.spriv.pr_priv);
                    revoke_casc :=
                          (oldpriv.priv_all_grant_set -
                          new_priv.priv_all_grant_set <> [  ]) OR
                          (oldpriv.priv_grant_sel_set -
                          new_priv.priv_grant_sel_set <> [  ]) OR
                          (oldpriv.priv_grant_upd_set -
                          new_priv.priv_grant_upd_set <> [  ]) OR
                          (oldpriv.priv_grant_ref_set -
                          new_priv.priv_grant_ref_set <> [  ]);
                    IF  (new_priv.priv_all_set       = [  ]) AND
                        (new_priv.priv_all_grant_set = [  ]) AND
                        (new_priv.priv_col_exist     = [  ])
                    THEN
                        BEGIN
                        IF  NOT new_sysinfo
                        THEN
                            BEGIN
                            a10del_sysinfo (acv,
                                  privbuf^.syskey, b_err);
                            IF  b_err = e_ok
                            THEN
                                WITH base_ptr^.syskey DO
                                    a19del_usertab  (acv, curr_user,
                                          stableid)
                                (*ENDWITH*) 
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        a10_add_repl_sysinfo (acv,
                              privbuf, new_sysinfo, b_err);
                        IF  (b_err = e_ok) AND new_sysinfo
                        THEN
                            WITH base_ptr^, sbase, syskey DO
                                IF  curr_user <> bauthid
                                THEN
                                    BEGIN
                                    ut_tab_kind := ut_table;
                                    CASE btablekind OF
                                        twithkey, twithoutkey,
                                        tonebase, tview, tcomplexview :
                                            BEGIN
                                            IF  btablekind in
                                                [twithkey, twithoutkey]
                                            THEN
                                                ut_tab_kind := ut_base_table
                                            ELSE
                                                ut_tab_kind := ut_view;
                                            (*ENDIF*) 
                                            IF  in_installation
                                                AND
                                                ( acv.a_curr_schema = a01_i_sys )
                                            THEN
                                                ut_tab_kind :=
                                                      ut_oracle_systable
                                            ELSE
                                                IF  in_installation AND
                                                    (a_current_user_kind = usysdba)
                                                THEN
                                                    ut_tab_kind := ut_internal_systable;
                                                (*ENDIF*) 
                                            (*ENDIF*) 
                                            END;
                                        (* PTS 1111576 E.Z. *)
                                        OTHERWISE ;
                                        END;
                                    (*ENDCASE*) 
                                    a19add_usertab  (acv, curr_user,
                                          stableid, ut_tab_kind)
                                    END;
                                (*ENDIF*) 
                            (*ENDWITH*) 
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        IF  b_err <> e_ok
        THEN
            a07_b_put_error (acv, b_err, 1)
        ELSE
            BEGIN
            IF  ((r_link in oldpriv.priv_all_set) AND
                NOT (r_link in new_priv.priv_all_set))
                OR
                (oldpriv.priv_ref_set - new_priv.priv_ref_set <> [])
            THEN (* reference privilege has been revoked *)
                a25check_fk_priv (acv, base_ptr, new_priv, curr_user)
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      a22exist_user  (VAR acv : tak_all_command_glob;
            VAR user      : tsp00_KnlIdentifier;
            errorpos      : integer;
            VAR user_info : tak_user_info) : boolean;
 
VAR
      b_err   : tgg00_BasisError;
      error   : tgg00_BasisError;
      userbuf : tak_sysbufferaddress;
      userkey : tgg00_SysInfoKey;
 
BEGIN
WITH acv DO
    IF  a_returncode = 0
    THEN
        BEGIN
        error   := e_ok;
        a51build_userkey (user, userkey);
        a10get_sysinfo (acv, userkey, d_release,
              userbuf, b_err);
        IF  b_err = e_ok
        THEN
            BEGIN
            userkey           := a01defaultkey;
            user_info.ui_id   := userbuf^.suserref.ru_user_id;
            userkey.sauthid   := user_info.ui_id;
            userkey.sentrytyp := cak_euser;
            a10get_sysinfo (acv, userkey, d_release,
                  userbuf, b_err)
            END;
        (*ENDIF*) 
        IF  b_err <> e_ok
        THEN
            IF  b_err = e_sysinfo_not_found
            THEN
                error := e_unknown_user
            ELSE
                a07_b_put_error (acv, b_err, 1)
            (*ENDIF*) 
        ELSE
            WITH userbuf^.suser DO
                IF  NOT (is_group_rec in urecordtyp) AND
                    NOT (is_role_rec  in urecordtyp)
                THEN
                    error := e_group_user_not_allowed
                ELSE
                    BEGIN
                    user_info.ui_kind    := userkind;
                    user_info.ui_is_role := is_role_rec in urecordtyp;
                    user_info.ui_owner   := userowner_id
                    END;
                (*ENDIF*) 
            (*ENDWITH*) 
        (*ENDIF*) 
        IF  error <> e_ok
        THEN
            a07_b_put_error (acv, error, errorpos)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
(*ENDWITH*) 
a22exist_user := acv.a_returncode = 0
END;
 
(*------------------------------*) 
 
PROCEDURE
      a22pack_priv (privbuf : tak_sysbufferaddress;
            VAR new_priv    : tak_privilege;
            VAR packed_priv : tak_privilege);
 
VAR
      i             : tak_priv_descriptors;
      priv_index    : tak_priv_descriptors;
      columnsetsize : integer;
 
BEGIN
&ifdef trace
a06td_priv(new_priv, 'new privilege     ', true);
&endif
WITH privbuf^, packed_priv DO
    BEGIN
    packed_priv.priv_all_set       := new_priv.priv_all_set;
    packed_priv.priv_all_grant_set := new_priv.priv_all_grant_set;
    packed_priv.priv_col_exist     := [  ];
    packed_priv.priv_filler        := false;
    b_sl := sizeof (privbuf^.sprivuser) -
          sizeof (privbuf^.sprivuser.pru_priv)                    +
          sizeof (privbuf^.sprivuser.pru_priv.priv_all_set)       +
          sizeof (privbuf^.sprivuser.pru_priv.priv_all_grant_set) +
          sizeof (privbuf^.sprivuser.pru_priv.priv_col_exist)     +
          sizeof (privbuf^.sprivuser.pru_priv.priv_filler);
    priv_index    := priv_col_sel;
    columnsetsize := sizeof (tak_columnset);
    FOR i := priv_col_sel TO priv_col_ref_grant DO
        BEGIN
        IF  i in new_priv.priv_col_exist
        THEN
            BEGIN
            packed_priv.priv_col[ priv_index ] := new_priv.priv_col[i];
            packed_priv.priv_col_exist         := priv_col_exist + [i];
            IF  priv_index < priv_col_ref_grant
            THEN
                priv_index := succ(priv_index);
            (*ENDIF*) 
            b_sl := b_sl + columnsetsize
            END;
        (*ENDIF*) 
        END;
    (*ENDFOR*) 
&   ifdef trace
    a06td_priv (packed_priv, 'packed privilege  ', false);
&   endif
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      a22revoke_cascade (VAR acv : tak_all_command_glob;
            base_ptr        : tak_sysbufferaddress;
            VAR all_col_set : tak_columnset;
            rev_user        : tgg00_Surrogate;
            VAR rev_priv    : tak_privilege);
      (* rev_user must not be a var parameter, because rev_user may *)
      (* identify a part of a catalog record, that would be changed *)
      (* by this procedure                                          *)
 
VAR
      cascade    : boolean;
      b_err      : tgg00_BasisError;
      p          : tak_sysbufferaddress;
      grant_user : tgg00_Surrogate;
      curr_user  : tgg00_Surrogate;
      curr_name  : tsp00_KnlIdentifier;
      auth_name  : tsp00_KnlIdentifier;
      sysk       : tgg00_SysInfoKey;
      curr_priv  : tak_privilege;
      new_priv   : tak_privilege;
 
BEGIN
WITH acv DO
    BEGIN
&   ifdef trace
    a06td_priv (rev_priv, 'revoke_priv       ', true);
&   endif
    REPEAT
        sysk           := base_ptr^.syskey;
        sysk.sentrytyp := cak_eprivuser;
        grant_user     := cgg_zero_id;
        REPEAT
            a10next_sysinfo (acv, sysk, SURROGATE_MXGG00+2, d_release,
                  cak_eprivuser, p, b_err);
            IF  b_err = e_ok
            THEN
                a10_fix_len_get_sysinfo (acv, sysk, d_fix,
                      sizeof (tak_privuserrecord),
                      0, p, b_err);
            (*ENDIF*) 
            IF  b_err = e_ok
            THEN
                IF  p^.syskey.sgrantuser = rev_user
                THEN
                    BEGIN
                    curr_user := p^.syskey.suserid;
                    curr_priv := a01emptypriv;
                    a06determine_username (acv,
                          base_ptr^.sbase.bauthid,
                          auth_name);
                    a06determine_username (acv, curr_user,
                          curr_name);
                    a06unpack_priv (p^.sprivuser.pru_priv,
                          curr_priv);
&                   ifdef trace
                    a06td_priv (curr_priv,
                          'curr_priv         ', true);
&                   endif
                    ak22put_privileges (acv, curr_priv, rev_priv,
                          new_priv, all_col_set, false, false);
                    a22add_priv_rec (acv, base_ptr,
                          new_priv, p, false, cascade);
                    IF  cascade
                    THEN
                        grant_user := curr_user;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
        UNTIL
            (b_err <> e_ok) OR (a_returncode <> 0);
        (*ENDREPEAT*) 
        rev_user := grant_user;
    UNTIL
        grant_user = cgg_zero_id;
    (*ENDREPEAT*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22init_glob (VAR a22v : a22_grant_glob);
 
BEGIN
WITH a22v DO
    BEGIN
    g2tablearr1       := NIL;
    g2authname        := a01_il_b_identifier;
    g2auth_id         := cgg_zero_id;
    g2tablen          := a01_il_b_identifier;
    g2coln            := a01_il_b_identifier;
    g2username        := a01_il_b_identifier;
    g2user_id         := cgg_zero_id;
    g2ci              := 0;
    g2privbuf         := NIL;
    g2privkey         := a01defaultkey;
    g2userbuf         := NIL;
    g2userkey         := a01defaultkey;
    g2privileges      := a01emptypriv;
    g2grantor_priv    := a01emptypriv;
    g2old_user_priv   := a01emptypriv;
    g2selreccolno     := [  ];
    g2updreccolno     := [  ];
    g2all_col_privset := [  ];
    g2user_count      := 0;
    g2ti              := 1;
    g2tiuser          := 0;
    g2tispec          := 0;
    g2tiupd           := 0;
    g2tisel           := 0;
    g2tiref           := 0;
    g2tisup           := 0;
    g2sequence        := false;
    g2versno.ci2_gg00 := cgg_dummy_file_version;
    g2allprivileges   := false;
    g2grant_option    := false
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      ak22revoke_by_owner (VAR acv : tak_all_command_glob;
            VAR a22v : a22_grant_glob);
 
VAR
      b_err          : tgg00_BasisError;
      buf            : tak_sysbufferaddress;
      sysk           : tgg00_SysInfoKey;
      init_user_name : tsp00_KnlIdentifier;
      init_user_id   : tgg00_Surrogate;
 
BEGIN
WITH acv, a22v DO
    BEGIN
    (* the owner of the current table revokes privileges from *)
    (* the user g2user_id. He can do this even if has not     *)
    (* granted those privileges                               *)
    init_user_name := a_curr_user_name;
    init_user_id   := a_curr_user_id;
    sysk           := g2tablearr1^.syskey;
    sysk.sentrytyp := cak_eprivuser;
    sysk.suserid   := g2user_id;
    sysk.skeylen   := mxak_standard_sysk + SURROGATE_MXGG00;
    REPEAT
        (* scan all privileges records that descibe a privilege *)
        (* of user g2user_id on the current table               *)
        a10next_sysinfo (acv, sysk, 2 * SURROGATE_MXGG00 + 4,
              d_release, cak_eprivuser, buf, b_err);
        IF  b_err = e_ok
        THEN
            BEGIN
            (* privilege has been granted by sysk.sgrantuser *)
            (* revoke privilege under account of this user   *)
            a06determine_username (acv, sysk.sgrantuser,
                  a_curr_user_name);
            a_curr_user_id := sysk.sgrantuser;
            ak22user_priv  (acv, a22v, false, false)
            END;
        (*ENDIF*) 
    UNTIL
        (b_err <> e_ok) OR (a_returncode <> 0);
    (*ENDREPEAT*) 
    IF  b_err <> e_no_next_record
    THEN
        a07_b_put_error (acv, b_err, 1);
    (*ENDIF*) 
    a_curr_user_name := init_user_name;
    a_curr_user_id   := init_user_id
    END;
(*ENDWITH*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
