MINI MINI MANI MO
Rem $Header: rdbms/admin/dbmsrmanvpc.sql /st_rdbms_18.0/1 2017/12/21 11:23:51 molagapp Exp $
Rem
Rem dbmsrvpc.sql
Rem
Rem Copyright (c) 2013, 2017, Oracle and/or its affiliates.
Rem All rights reserved.
Rem
Rem NAME
Rem dbmsrmanvpc.sql - upgrade to VPD model.
Rem
Rem DESCRIPTION
Rem A script to upgrade rman VPC user schemas to a new VPD model.
Rem
Rem NOTES
Rem This script has to be executed as SYS user. It detects what RMAN base
Rem catalog schemas are upgraded to a VPD compatible catalog and upgrades
Rem the corresponding VPC schemas as well, performing removal of unneeded
Rem database objects and revoking unnecessary privileges.
Rem
Rem MODIFIED (MM/DD/YY)
Rem molagapp 12/20/17 - Fix 5 digit version interpretation
Rem stanaya 01/24/17 - Bug-25237021 : adding sql metadata
Rem ardrai 12/02/16 - Bug 21849312:ora-1918 create/upgrade catalog
Rem vbegun 01/30/15 - disabling vpd support out of the box
Rem vbegun 10/29/13 - no VPC schema case
Rem vbegun 10/11/13 - Created
Rem
Rem BEGIN SQL_FILE_METADATA
Rem SQL_SOURCE_FILE: rdbms/admin/dbmsrmanvpc.sql
Rem SQL_SHIPPED_FILE: rdbms/admin/dbmsrmanvpc.sql
Rem SQL_PHASE:DBMSRMANVPC
Rem SQL_STARTUP_MODE: NORMAL
Rem SQL_IGNORABLE_ERRORS: NONE
Rem SQL_CALLING_FILE: NONE
Rem END SQL_FILE_METADATA
SET DEFINE "^" TRIMSPOOL ON TAB OFF PAGES 50000 LINES 32767 FEEDBACK OFF
SET VERIFY OFF SERVEROUTPUT ON SIZE UNLIMITED FORMAT TRUNCATED
WHENEVER OSERROR EXIT 1
WHENEVER SQLERROR EXIT 1
SET HEADING OFF
SELECT 'Checking the operating user... '
|| CASE
WHEN USER = 'SYS'
THEN 'Passed'
ELSE 'Failed: the user must be SYS'
END
FROM dual;
PROMPT
SET TERMOUT OFF
SELECT CASE WHEN USER <> 'SYS' THEN 1/0 END FROM dual;
COLUMN script NEW_VALUE script
SELECT COALESCE(
REGEXP_SUBSTR(
TRIM(SYS_CONTEXT('USERENV', 'MODULE'))
, '^[[:digit:]]{2}@[< ](.*(/|\\))*(.*)$'
, 1, 1, 'i', 3
)
, 'dbmsrmanvpc.sql'
) script
FROM dual
/
SET TERMOUT ON HEADING ON
COLUMN 1 NEW_VALUE 1
COLUMN 2 NEW_VALUE 2
COLUMN 3 NEW_VALUE 3
COLUMN 4 NEW_VALUE 4
COLUMN 5 NEW_VALUE 5
COLUMN 6 NEW_VALUE 6
COLUMN 7 NEW_VALUE 7
COLUMN 8 NEW_VALUE 8
COLUMN 9 NEW_VALUE 9
COLUMN 10 NEW_VALUE 10
SELECT '' AS "1", '' AS "2", '' AS "3", '' AS "4", '' AS "5"
, '' AS "6", '' AS "7", '' AS "8", '' AS "9", '' AS "10"
FROM dual
WHERE ROWNUM = 0
/
VAR list_of_owners1 VARCHAR2(4000)
VAR list_of_owners2 VARCHAR2(4000)
VAR scan NUMBER
VAR vpd NUMBER
VAR novpd NUMBER
VAR e NUMBER
DECLARE
TYPE argv_t IS TABLE OF user_users.username%TYPE;
l_argv CONSTANT argv_t := argv_t(
'^^1', '^^2', '^^3', '^^4', '^^5'
, '^^6', '^^7', '^^8', '^^9', '^^10'
);
l_dummy VARCHAR2(1);
l_scan BOOLEAN := FALSE;
l_vpd BOOLEAN := FALSE;
l_novpd BOOLEAN := FALSE;
l_all BOOLEAN := FALSE;
l_owners argv_t := argv_t();
l_user_name user_users.username%TYPE;
PROCEDURE p (
l_message IN VARCHAR2
, l_crlf IN BOOLEAN DEFAULT TRUE
)
IS
BEGIN
IF (l_crlf)
THEN
dbms_output.put_line(l_message);
ELSE
dbms_output.put(l_message);
END IF;
END p;
PROCEDURE el
IS
BEGIN
dbms_output.put_line('');
END el;
PROCEDURE usage
IS
BEGIN
p(q'{Usage: ^^script -vpd <base catalog schema name>
^^script -novpd <base catalog schema name>
^^script -scan [<base catalog schema name>]
^^script <base catalog schema name> [...]
^^script -all
This script performs an upgrade of RMAN base catalog and corresponding
VPC users schemas to a new VPD model.
-vpd command grants required privileges to support VPD protected catalog.
Connect to RMAN base catalog and perform UPGRADE CATALOG after the VPD
privileges are granted.
-novpd command removes VPD support: cleans up the base catalog schema,
revokes grants and removes database objects to disable VPD facilities.
This is only possible when there are no existing VPC users registered
in that catalog.
-scan command performs a scan of RMAN base catalog owner schemas and
reports on granted roles and VPC users status.
After UPGRADE CATALOG is performed for the base catalog schemas a cleanup
of VPC schemas has to take place for that the RMAN base catalog schema
names have to be supplied as command line parameters. Up to 10 schema
names can be supplied per script execution. When -all is specified the
script attempts to detect the RMAN base catalog schemas automatically
and perform the upgrade.
}');
END usage;
BEGIN
:vpd := 0;
:novpd := 0;
:scan := 0;
FOR i IN 1..l_argv.COUNT
LOOP
IF (l_argv(i) IS NOT NULL)
THEN
l_owners.EXTEND;
l_owners(l_owners.COUNT) := UPPER(l_argv(i));
IF (NOT (l_all OR l_vpd OR l_novpd OR l_scan)
AND l_owners.COUNT = 1
)
THEN
IF (l_owners(l_owners.COUNT) = '-ALL')
THEN
l_all := TRUE;
l_owners(l_owners.COUNT) := 'owner';
CONTINUE;
END IF;
IF (l_owners(l_owners.COUNT) = '-VPD')
THEN
l_vpd := TRUE; :vpd := 1;
l_owners.DELETE;
CONTINUE;
END IF;
IF (l_owners(l_owners.COUNT) = '-NOVPD')
THEN
l_novpd := TRUE; :novpd := 1;
l_owners.DELETE;
CONTINUE;
END IF;
IF (l_owners(l_owners.COUNT) = '-SCAN')
THEN
l_scan := TRUE; :scan := 1;
l_owners(l_owners.COUNT) := 'owner';
CONTINUE;
END IF;
END IF;
END IF;
END LOOP;
IF ( (l_owners.COUNT = 0 OR l_all OR l_vpd OR l_novpd)
AND l_owners.COUNT <> 1
)
THEN
usage(); :e := 0; RETURN;
END IF;
IF (l_vpd)
THEN
p( 'Granting VPD privileges to the owner of the base catalog schema '
|| l_owners(l_owners.COUNT)
);
:list_of_owners1 := '''' || l_owners(l_owners.COUNT) || '''';
el();
ELSIF (l_novpd)
THEN
p( 'Removing VPD support in the base catalog schema '
|| l_owners(l_owners.COUNT)
);
:list_of_owners1 := '''' || l_owners(l_owners.COUNT) || '''';
el();
ELSIF (l_scan)
THEN
IF (l_owners.COUNT > 2)
THEN
usage(); :e := 0; RETURN;
END IF;
IF (l_owners(l_owners.COUNT) = 'owner')
THEN
:list_of_owners1 := 'owner';
ELSE
:list_of_owners1 := '''' || l_owners(l_owners.COUNT) || '''';
BEGIN
l_user_name := l_owners(l_owners.COUNT);
SELECT 'x'
INTO l_dummy
FROM dba_users
WHERE username = l_user_name;
EXCEPTION
WHEN NO_DATA_FOUND
THEN p( 'Base catalog owner schema ' || l_owners(l_owners.COUNT)
|| ' does not exist!'
);
:e := 1; RETURN;
END;
END IF;
p( 'RMAN base catalog owners schemas report as of '
|| TO_CHAR(SYSDATE, 'YYYY/MM/DD HH24:MI:SS')
);
el();
p(RPAD('=', 80, '='));
p(q'{Acronyms used:
VPC -- Virtual Private Catalog users
VPD -- RECOVERY_CATALOG_OWNER_VPD role
RCO -- RECOVERY_CATALOG_OWNER role
RCU -- RECOVERY_CATALOG_USER role
}'
);
ELSE
IF (l_owners(l_owners.COUNT) <> 'owner')
THEN
FOR i IN 1..l_owners.COUNT
LOOP
:list_of_owners1 := :list_of_owners1
|| ''''
|| l_owners(i)
|| ''''
|| CASE
WHEN i <> l_owners.COUNT
THEN ', '
END;
:list_of_owners2 := :list_of_owners2
|| l_owners(i)
|| CASE
WHEN i <> l_owners.COUNT
THEN ', '
END;
END LOOP;
p('The VPC user schemas of the following catalogs: ', FALSE);
p(:list_of_owners2, FALSE);
p(' are going to be upgraded to a new VPD model');
el();
ELSE
:list_of_owners1 := 'owner';
END IF;
END IF;
END;
/
SET TERMOUT OFF
COLUMN list_of_owners1 NEW_VALUE list_of_owners1
COLUMN list_of_owners2 NEW_VALUE list_of_owners2
SELECT :list_of_owners1 list_of_owners1
, :list_of_owners2 list_of_owners2
, COALESCE(:list_of_owners1, TO_CHAR(1 / 0))
, 1 / :e
FROM dual;
SET TERMOUT ON
DECLARE
TYPE users_t IS TABLE OF user_users.username%TYPE;
l_debug BOOLEAN := FALSE;
lc_users SYS_REFCURSOR;
l_user_name user_users.username%TYPE;
SUBTYPE short_string_t IS VARCHAR2(32);
gc_vpc_version CONSTANT VARCHAR2(15) := '12.01.00.01.00';
l_version VARCHAR2(15);
TYPE h_t IS TABLE OF short_string_t INDEX BY user_users.username%TYPE;
l_extrainfo h_t;
l_dummy VARCHAR2(1);
l_ddl_error BOOLEAN := FALSE;
l_upgraded_vpc users_t := users_t();
l_successful_vpc users_t := users_t();
l_problematic_vpc users_t;
l_catalogs users_t := users_t();
l_problematic_cat users_t := users_t();
-- a given base catalog had associated VPC users
l_had_vpc_users BOOLEAN;
-- a status of the base catalog owner VPD setup
l_had_vpd_setup BOOLEAN;
PROCEDURE p (
l_message IN VARCHAR2
, l_crlf IN BOOLEAN DEFAULT TRUE
)
IS
BEGIN
IF (l_crlf)
THEN
dbms_output.put_line(l_message);
ELSE
dbms_output.put(l_message);
END IF;
END p;
PROCEDURE el
IS
BEGIN
dbms_output.put_line('');
END el;
PROCEDURE t
IS
BEGIN
p(RPAD('-', 40, '-'));
END t;
PROCEDURE tt
IS
BEGIN
p(RPAD('=', 40, '='));
END tt;
PROCEDURE t2csv (
i_title IN VARCHAR2 DEFAULT NULL
, i_table IN users_t
, i_crlf IN BOOLEAN DEFAULT FALSE
-- extra qualifier
, i_eq IN BOOLEAN DEFAULT FALSE
)
IS
BEGIN
IF (i_title IS NOT NULL AND i_table.COUNT > 0)
THEN
p(i_title, i_crlf);
END IF;
FOR i IN 1..i_table.COUNT
LOOP
p(i_table(i) || CASE
WHEN i_eq AND l_extrainfo.EXISTS(i_table(i))
THEN ' [' || l_extrainfo(i_table(i)) || ']'
END
|| CASE
WHEN i <> i_table.COUNT
THEN ', '
END
, FALSE
);
END LOOP;
p('', i_title IS NOT NULL AND i_table.COUNT > 0);
END t2csv;
PROCEDURE do_ddl (
i_stmt IN VARCHAR2
, i_warning IN BOOLEAN DEFAULT FALSE
, i_show_errors IN BOOLEAN DEFAULT TRUE
)
IS
e_not_granted EXCEPTION;
PRAGMA EXCEPTION_INIT(e_not_granted, -1951);
BEGIN
IF (l_debug)
THEN
p(i_stmt);
END IF;
BEGIN
EXECUTE IMMEDIATE i_stmt;
EXCEPTION
WHEN e_not_granted
THEN NULL;
WHEN OTHERS
THEN IF (i_show_errors)
THEN
p( CASE WHEN i_warning THEN 'Warning: ' ELSE 'Error: ' END
|| 'ORA' || SQLCODE || ': ' || i_stmt
);
END IF;
l_ddl_error := TRUE;
END;
END do_ddl;
PROCEDURE drop_synonym (
i_synonym_name IN user_synonyms.synonym_name%TYPE
, i_user_name IN user_users.username%TYPE
DEFAULT l_user_name
)
IS
BEGIN
do_ddl('DROP SYNONYM ' || i_user_name || '.' || i_synonym_name);
END drop_synonym;
PROCEDURE drop_view (
i_view_name IN user_views.view_name%TYPE
, i_user_name IN user_users.username%TYPE
DEFAULT l_user_name
)
IS
BEGIN
do_ddl('DROP VIEW "' || i_user_name || '"."' || i_view_name || '"');
END drop_view;
PROCEDURE revoke_priv (
i_priv_name IN user_role_privs.granted_role%TYPE
, i_user_name IN user_users.username%TYPE
DEFAULT l_user_name
, i_report_errors IN BOOLEAN DEFAULT FALSE
)
IS
l_prev_ddl_error BOOLEAN;
BEGIN
IF (i_report_errors)
THEN
do_ddl('REVOKE ' || i_priv_name || ' FROM "' || i_user_name || '"');
ELSE
l_prev_ddl_error := l_ddl_error;
do_ddl(
i_stmt => 'REVOKE ' || i_priv_name
|| ' FROM "' || i_user_name || '"'
, i_show_errors => FALSE
);
l_ddl_error := l_prev_ddl_error;
END IF;
END revoke_priv;
PROCEDURE grant_priv (
i_priv_name IN VARCHAR2
, i_user_name IN user_users.username%TYPE
DEFAULT l_user_name
)
IS
BEGIN
do_ddl('GRANT ' || i_priv_name || ' TO "' || i_user_name || '"');
END grant_priv;
PROCEDURE a (
i_table IN OUT NOCOPY users_t
, i_user_name IN user_users.username%TYPE
, i_condition IN BOOLEAN DEFAULT TRUE
)
IS
BEGIN
IF (i_condition)
THEN
i_table.EXTEND;
i_table(i_table.COUNT) := i_user_name;
END IF;
END a;
FUNCTION has_vpc_users (
i_user_name IN user_users.username%TYPE
)
RETURN BOOLEAN
IS
l_catowner VARCHAR2(130);
BEGIN
l_catowner := dbms_assert.enquote_name(i_user_name);
EXECUTE IMMEDIATE
REGEXP_REPLACE (
'SELECT ''x'' FROM %o.vpc_users WHERE ROWNUM = 1 HAVING COUNT(*) = 1'
, '%o'
, l_catowner
)
INTO l_dummy;
RETURN l_dummy IS NOT NULL;
EXCEPTION
WHEN NO_DATA_FOUND
THEN RETURN FALSE;
END has_vpc_users;
BEGIN
IF (:scan = 0)
THEN
BEGIN
SELECT 'x'
INTO l_dummy
FROM dba_roles
WHERE role IN (
'RECOVERY_CATALOG_OWNER'
, 'RECOVERY_CATALOG_OWNER_VPD'
, 'RECOVERY_CATALOG_USER'
)
HAVING COUNT(*) = 3;
EXCEPTION
WHEN NO_DATA_FOUND
THEN NULL;
END;
IF (l_dummy IS NULL)
THEN
p(q'{Required Recovery Manager roles do not exist!
Execute '?/rdbms/admin/dbmsrmansys.sql' after connecting to
a catalog database as SYS to create required roles.
}');
:e := 0; RETURN;
END IF;
END IF;
-- -scan
IF (:scan = 1)
THEN
:e := 0;
RETURN;
END IF;
FOR c IN (
SELECT owner
FROM dba_tables t
WHERE table_name = 'VPC_USERS'
AND owner IN (^^list_of_owners1)
AND (
:vpd = 1
OR :novpd = 1
OR 2 = (
SELECT COUNT(*)
FROM dba_tab_columns c
WHERE c.owner = t.owner
AND c.table_name = t.table_name
AND c.column_name IN ('FILTER_USER', 'FILTER_UID')
)
AND 2 = (
SELECT COUNT(*)
FROM dba_objects o
WHERE o.owner = t.owner
AND o.object_name = 'DBMS_RCVCAT'
AND o.object_type IN ('PACKAGE', 'PACKAGE BODY')
)
AND 2 = (
SELECT COUNT(*)
FROM dba_objects o
WHERE o.owner = t.owner
AND o.object_name = 'DBMS_RCVMAN'
AND o.object_type IN ('PACKAGE', 'PACKAGE BODY')
)
)
ORDER BY
owner
)
LOOP
-- -vpd
IF (:vpd = 1)
THEN
a(l_catalogs, c.owner);
revoke_priv('recovery_catalog_owner', c.owner, FALSE);
grant_priv('recovery_catalog_owner_vpd', c.owner);
CONTINUE;
END IF;
-- -novpd
IF (:novpd = 1)
THEN
a(l_catalogs, c.owner);
IF (has_vpc_users(c.owner))
THEN
a(l_problematic_cat, c.owner);
l_extrainfo(c.owner) := 'Existing VPC users';
ELSE
p('Revoking privileges from RECOVERY_CATALOG_USER role...');
FOR t IN (
SELECT DISTINCT table_name
FROM dba_tab_privs
WHERE grantee = 'RECOVERY_CATALOG_USER'
AND owner = c.owner
ORDER BY
table_name
)
LOOP
revoke_priv(
'ALL ON '
|| dbms_assert.enquote_name(c.owner, FALSE)
|| '.'
|| dbms_assert.enquote_name(t.table_name, FALSE)
, 'RECOVERY_CATALOG_USER'
, FALSE
);
IF (l_ddl_error)
THEN
a(l_problematic_cat, c.owner);
EXIT;
END IF;
END LOOP;
CONTINUE WHEN l_ddl_error;
p('Dropping on-logon trigger...');
FOR t IN (
SELECT trigger_name
FROM dba_triggers
WHERE owner = c.owner
AND trigger_name = 'VPC_CONTEXT_TRG'
)
LOOP
do_ddl (
i_stmt => 'DROP TRIGGER '
|| dbms_assert.enquote_name(c.owner, FALSE)
|| '.'
|| t.trigger_name
, i_show_errors => TRUE
);
a(l_problematic_cat, c.owner, l_ddl_error);
END LOOP;
CONTINUE WHEN l_ddl_error;
p('Dropping VPD policies...');
FOR p IN (
SELECT object_name
, policy_name
FROM dba_policies
WHERE object_owner = c.owner
ORDER BY
object_name
)
LOOP
dbms_rls.drop_policy (
object_schema => dbms_assert.enquote_name(c.owner, FALSE)
, object_name => p.object_name
, policy_name => p.policy_name
);
END LOOP;
p('Granting/revoking roles from/to ' || c.owner || '...');
grant_priv('recovery_catalog_owner', c.owner);
revoke_priv('recovery_catalog_owner_vpd', c.owner, TRUE);
a(l_problematic_cat, c.owner, l_ddl_error);
CONTINUE WHEN l_ddl_error;
END IF;
CONTINUE;
END IF;
-- -all or supplied base catalog schemas
a(l_catalogs, c.owner);
BEGIN
EXECUTE IMMEDIATE
'SELECT version FROM ' || dbms_assert.enquote_name(c.owner, FALSE)
|| '.rcver'
INTO l_version;
-- Append .00 for older version of catalog schema that track only
-- first 4 digits.
IF (LENGTH(l_version) = 12) THEN
l_version := '.00';
END IF;
a(l_problematic_cat, c.owner, (l_version < gc_vpc_version));
l_extrainfo(c.owner) := l_version;
CONTINUE WHEN l_version < gc_vpc_version;
EXCEPTION
WHEN OTHERS
THEN a(l_problematic_cat, c.owner);
CONTINUE;
END;
l_had_vpc_users := FALSE;
OPEN lc_users
FOR 'SELECT filter_user FROM '
|| dbms_assert.enquote_name(c.owner, FALSE)
|| '.vpc_users ORDER BY filter_user';
LOOP
FETCH lc_users INTO l_user_name;
EXIT WHEN lc_users%NOTFOUND;
l_had_vpc_users := TRUE;
l_ddl_error := FALSE;
tt();
p( 'Upgrading the VPC user schemas registered in the base catalog of '
|| c.owner
);
t();
p('Upgrading: ' || l_user_name);
a(l_upgraded_vpc, l_user_name);
p('Synonyms...');
FOR s IN (
SELECT synonym_name
FROM dba_synonyms
WHERE table_owner = c.owner
AND owner = l_user_name
AND synonym_name NOT IN ('DBMS_RCVCAT', 'DBMS_RCVMAN')
ORDER BY
synonym_name
)
LOOP
drop_synonym(s.synonym_name, l_user_name);
END LOOP;
p('Views...');
FOR v IN (
SELECT view_name
FROM dba_views
WHERE owner = l_user_name
AND ( view_name LIKE 'RC~_%' ESCAPE '~'
OR view_name LIKE 'RCI~_%' ESCAPE '~'
OR view_name LIKE '~_RS~_RC~_%' ESCAPE '~'
OR view_name LIKE '~_RS~_RCI~_%' ESCAPE '~'
)
ORDER BY
view_name
)
LOOP
drop_view(v.view_name, l_user_name);
END LOOP;
p('Cleanup of privileges...');
FOR p IN (
SELECT privilege name
FROM dba_sys_privs
WHERE grantee = l_user_name
UNION
SELECT granted_role
FROM dba_role_privs
WHERE grantee = l_user_name
)
LOOP
revoke_priv(p.name, l_user_name);
END LOOP;
p('Grant of privileges...');
grant_priv('create session, recovery_catalog_user', l_user_name);
a(l_successful_vpc, l_user_name, (NOT l_ddl_error));
END LOOP;
CLOSE lc_users;
t();
p('Removing old VPC views in the base catalog of ' || c.owner || '...');
l_ddl_error := FALSE;
FOR v IN (
SELECT view_name
FROM dba_views
WHERE view_name LIKE '%~_V' ESCAPE '~'
AND owner = c.owner
)
LOOP
drop_view(v.view_name, c.owner);
END LOOP;
IF (NOT l_ddl_error)
THEN
-- if a base catalog owner has a VPD trigger setup it means
-- the VPD catalog upgrade already took place and we have to
-- reconcile the privileges
SELECT MIN('x')
INTO l_dummy
FROM dba_triggers
WHERE owner = c.owner
AND trigger_name = 'VPC_CONTEXT_TRG';
l_had_vpd_setup := l_dummy IS NOT NULL;
IF (l_had_vpc_users OR l_had_vpd_setup)
THEN
-- if a base catalog owner had VPC users registered or
-- already had a VPD setup we reconcile the privileges
revoke_priv('recovery_catalog_owner', c.owner);
grant_priv('recovery_catalog_owner_vpd', c.owner);
END IF;
END IF;
a(l_problematic_cat, c.owner, l_ddl_error);
END LOOP;
l_problematic_vpc := l_upgraded_vpc MULTISET EXCEPT l_successful_vpc;
tt();
IF (l_catalogs.COUNT > 0)
THEN
IF (:vpd = 1)
THEN
p('VPD SETUP STATUS:');
IF (l_problematic_cat.COUNT > 0)
THEN
:e := 1;
t2csv(
i_title => 'Unable to grant required privileges to the base catalog '
|| 'owner for VPD upgrade '
, i_table => l_problematic_cat
, i_eq => TRUE
);
ELSE
:e := 0;
p('VPD privileges granted successfully!');
p('Connect to RMAN base catalog and perform UPGRADE CATALOG.');
END IF;
ELSIF (:novpd = 1)
THEN
p('VPD REMOVAL STATUS:');
IF (l_problematic_cat.COUNT > 0)
THEN
:e := 1;
t2csv(
i_title => 'Unable to remove VPD support from to the base catalog '
, i_table => l_problematic_cat
, i_eq => TRUE
);
ELSE
:e := 0;
p('VPD support is removed successfully!');
END IF;
ELSE
p('UPGRADE STATUS:');
t2csv(
i_title => 'The VPC user schemas of these catalogs: '
, i_table => l_catalogs
);
IF ( l_problematic_vpc.COUNT = 0
AND l_successful_vpc.COUNT >= 0
AND l_problematic_cat.COUNT = 0
)
THEN
:e := 0;
p('have been successfully upgraded to the new VPD model!');
ELSE
:e := 1;
p('have NOT been successfully upgraded to the new VPD model!!!');
t2csv(
i_title => 'The problematic VPC user schemas: '
, i_table => l_problematic_vpc
);
t2csv(
i_title => 'The problematic or ineligible for the VPD upgrade '
|| 'base catalog schemas are: '
, i_table => l_problematic_cat
, i_eq => TRUE
);
END IF;
END IF;
ELSE
:e := 1;
p('No eligible RMAN catalogs have been found!');
END IF;
END;
/
DEFINE y = YES
DEFINE n = NO
DEFINE v = "|| dbms_assert.enquote_name(owner) || '.vpc_users'"
DEFINE vpd = RECOVERY_CATALOG_OWNER_VPD
DEFINE rco = RECOVERY_CATALOG_OWNER
DEFINE rcu = RECOVERY_CATALOG_USER
COLUMN owner FORMAT A20 -
HEADING "RMAN Base Catalog|schema owner" WRAP ON
COLUMN vpcuser FORMAT A20 -
HEADING "VPC user" WRAP ON
COLUMN recovery_catalog_owner_vpd FORMAT A4 -
HEADING "VPD|role" JUSTIFY CENTER
COLUMN recovery_catalog_owner FORMAT A4 -
HEADING "RCO|role" JUSTIFY CENTER
COLUMN has_vpc_users FORMAT 99999 -
HEADING "VPC|count" JUSTIFY CENTER
COLUMN non_existing_vpc_users FORMAT 99999 -
HEADING "VPC dropped|from DB" JUSTIFY CENTER
SET HEADSEP "~"
COLUMN s FORMAT A1 HEADING "|~|"
SET HEADSEP "|"
COLUMN vpc_users_with_vpd FORMAT 99999 -
HEADING "VPC with|VPD role" JUSTIFY CENTER
COLUMN vpc_users_with_rco FORMAT 99999 -
HEADING "VPC with|RCO role" JUSTIFY CENTER
COLUMN vpc_users_with_rcu FORMAT 99999 -
HEADING "VPC with|RCU role" JUSTIFY CENTER
WITH bc AS
(
SELECT owner
, (
SELECT COUNT(*)
FROM dba_tab_columns c
WHERE c.owner = t.owner
AND c.table_name = t.table_name
AND c.column_name IN ('FILTER_UID')
) has_filter_uid
, (
SELECT NVL2(MIN(grantee), '^^y', '^^n')
FROM dba_role_privs
WHERE grantee = t.owner
AND granted_role = '^^vpd'
) recovery_catalog_owner_vpd
, (
SELECT NVL2(MIN(grantee), '^^y', '^^n')
FROM dba_role_privs
WHERE grantee = t.owner
AND granted_role = '^^rco'
) recovery_catalog_owner
FROM dba_tables t
WHERE :scan = 1
AND owner IN (^^list_of_owners1)
AND table_name = 'VPC_USERS'
AND 1 = (
SELECT COUNT(*)
FROM dba_tab_columns c
WHERE c.owner = t.owner
AND c.table_name = t.table_name
AND c.column_name IN ('FILTER_USER')
)
AND 2 = (
SELECT COUNT(*)
FROM dba_objects o
WHERE o.owner = t.owner
AND o.object_name = 'DBMS_RCVCAT'
AND o.object_type IN ('PACKAGE', 'PACKAGE BODY')
)
AND 2 = (
SELECT COUNT(*)
FROM dba_objects o
WHERE o.owner = t.owner
AND o.object_name = 'DBMS_RCVMAN'
AND o.object_type IN ('PACKAGE', 'PACKAGE BODY')
)
)
SELECT owner
, recovery_catalog_owner_vpd
, recovery_catalog_owner
, (
dbms_xmlgen.getxmltype (
'SELECT COUNT(*) c FROM ' ^^v
)
).extract('//C/text()').getnumberval() has_vpc_users
, CASE
WHEN has_filter_uid = 0
THEN (
dbms_xmlgen.getxmltype (
'SELECT COUNT(*) c FROM ' ^^v
|| ' WHERE NOT EXISTS (SELECT * FROM dba_users WHERE'
|| ' username = filter_user)'
)
).extract('//C/text()').getnumberval()
ELSE (
dbms_xmlgen.getxmltype (
'SELECT COUNT(*) c FROM ' ^^v
|| ' WHERE NOT EXISTS (SELECT * FROM dba_users WHERE'
|| ' username = filter_user AND user_id = filter_uid)'
)
).extract('//C/text()').getnumberval()
END non_existing_vpc_users
, '|' s
, (
dbms_xmlgen.getxmltype (
'SELECT COUNT(*) c FROM dba_role_privs,' ^^v
|| ' WHERE grantee = filter_user'
|| ' AND granted_role = ''^^vpd'''
)
).extract('//C/text()').getnumberval() vpc_users_with_vpd
, (
dbms_xmlgen.getxmltype (
'SELECT COUNT(*) c FROM dba_role_privs,' ^^v
|| ' WHERE grantee = filter_user'
|| ' AND granted_role = ''^^rco'''
)
).extract('//C/text()').getnumberval() vpc_users_with_rco
, (
dbms_xmlgen.getxmltype (
'SELECT COUNT(*) c FROM dba_role_privs,' ^^v
|| ' WHERE grantee = filter_user'
|| ' AND granted_role = ''^rcu'''
)
).extract('//C/text()').getnumberval() vpc_users_with_rcu
FROM bc
ORDER BY
owner
/
COLUMN vpcuser FORMAT A20 -
HEADING "VPC user" WRAP ON
COLUMN vpc_user_with_vpd FORMAT A4 -
HEADING "VPD|role" JUSTIFY CENTER
COLUMN vpc_user_with_rco FORMAT A4 -
HEADING "RCO|role" JUSTIFY CENTER
COLUMN vpc_user_with_rcu FORMAT A4 -
HEADING "RCU|role" JUSTIFY CENTER
COLUMN non_existing_vpc_user FORMAT A7 -
HEADING "Dropped" JUSTIFY CENTER
BREAK ON OWNER SKIP 1
WITH bc AS
(
SELECT owner
FROM dba_tables t
WHERE :scan = 1
AND owner IN (^^list_of_owners1)
AND table_name = 'VPC_USERS'
AND 1 = (
SELECT COUNT(*)
FROM dba_tab_columns c
WHERE c.owner = t.owner
AND c.table_name = t.table_name
AND c.column_name IN ('FILTER_USER')
)
AND 2 = (
SELECT COUNT(*)
FROM dba_objects o
WHERE o.owner = t.owner
AND o.object_name = 'DBMS_RCVCAT'
AND o.object_type IN ('PACKAGE', 'PACKAGE BODY')
)
AND 2 = (
SELECT COUNT(*)
FROM dba_objects o
WHERE o.owner = t.owner
AND o.object_name = 'DBMS_RCVMAN'
AND o.object_type IN ('PACKAGE', 'PACKAGE BODY')
)
)
SELECT owner
, u vpcuser
, CASE WHEN v = 0 THEN '^^n' ELSE '^^y' END vpc_user_with_vpd
, CASE WHEN co = 0 THEN '^^n' ELSE '^^y' END vpc_user_with_rco
, CASE WHEN cu = 0 THEN '^^n' ELSE '^^y' END vpc_user_with_rcu
, CASE WHEN e = 0 THEN '^^n' ELSE '^^y' END non_existing_vpc_user
FROM (
SELECT owner
, dbms_xmlgen.getxmltype('
SELECT filter_user u
, SUM(CASE WHEN granted_role = ''^^vpd'' THEN 1 ELSE 0 END) v
, SUM(CASE WHEN granted_role = ''^^rco'' THEN 1 ELSE 0 END) co
, SUM(CASE WHEN granted_role = ''^^rcu'' THEN 1 ELSE 0 END) cu
, MAX(NVL2(username, 0, 1)) e
FROM ' ^^v || '
LEFT OUTER JOIN
(
SELECT grantee
, granted_role
FROM dba_role_privs
WHERE granted_role IN (''^^vpd'', ''^^rco'', ''^rcu'')
) dba_role_privs
ON (grantee = filter_user)
LEFT OUTER JOIN
dba_users
ON (filter_user = username)
GROUP BY
filter_user
') x FROM bc
) x
, XMLTABLE(
'/ROWSET/ROW' PASSING x.x
COLUMNS
u VARCHAR2(128) PATH 'U'
, v NUMBER PATH 'V'
, co NUMBER PATH 'CO'
, cu NUMBER PATH 'CU'
, e NUMBER PATH 'E'
)
ORDER BY
owner
, vpcuser
/
PROMPT
EXIT :e
OHA YOOOO