MINI MINI MANI MO
Rem
Rem $Header: rdbms/admin/utl32k.sql /main/21 2017/08/29 12:14:42 geadon Exp $
Rem
Rem utl32k.sql
Rem
Rem Copyright (c) 2011, 2017, Oracle and/or its affiliates.
Rem All rights reserved.
Rem
Rem NAME
Rem utl32k.sql - <one-line expansion of the name>
Rem
Rem DESCRIPTION
Rem <short description of component this file declares/defines>
Rem
Rem NOTES
Rem <other useful comments, qualifications, etc.>
Rem
Rem BEGIN SQL_FILE_METADATA
Rem SQL_SOURCE_FILE: rdbms/admin/utl32k.sql
Rem SQL_SHIPPED_FILE: rdbms/admin/utl32k.sql
Rem SQL_PHASE: UPGRADE
Rem SQL_STARTUP_MODE: UPGRADE
Rem SQL_IGNORABLE_ERRORS: NONE
Rem END SQL_FILE_METADATA
Rem
Rem MODIFIED (MM/DD/YY)
Rem geadon 08/24/17 - bug 26368251: XDB may not be installed
Rem prshanth 06/19/17 - Bug 26285822: invalidate application objects
Rem thbaby 05/18/17 - Bug 26046188: disable redirection in Proxy PDB
Rem aychen 05/17/17 - bug 25812018: unset oracle script at the end
Rem geadon 05/16/17 - bug 25922494: handle BJI virtual columns
Rem geadon 07/21/16 - XbranchMerge geadon_bug-22650793 from main
Rem geadon 03/28/16 - bug 22375145: add ORDER BY for column migration
Rem sjanardh 11/25/15 - Replace dbms_aqadm_syscalls APIs w/ dbms_aqadm_sys APIs
Rem acolunga 11/05/15 - bug 21996904: do not update virtual columns in
Rem xml index path tables.
Rem geadon 09/28/15 - bug 21907429: enable AQ DDL
Rem rafsanto 09/10/15 - Bug 21793725: Let DDL through for csx tokensets
Rem sanagara 08/12/15 - 21615157: use DBMS_SQL.DESCRIBE_COLUMNS3
Rem rafsanto 06/03/15 - Bug 20911289 - Let DML go through for csx
Rem tokenset objects
Rem pjayapal 10/28/14 - bug 19063812: procedure to parse mv defn query
Rem geadon 11/20/13 - bug 16894689: run utlrp.sql in normal mode
Rem geadon 02/26/13 - bug 16237862: long col names for describe_columns
Rem geadon 09/24/12 - bug 13824121: fix PROPS$ property name
Rem geadon 03/14/12 - bug 13332548: enforce utl32k upgrade for
Rem max_sql_string_size
Rem geadon 12/28/11 - script to set MAX_SQL_STRING_SIZE=EXTENDED
Rem geadon 12/28/11 - Created
Rem
Rem Exit immediately if Any failure in this script
WHENEVER SQLERROR EXIT;
Rem Bug 26046188: In a Proxy PDB, all top-level statements are redirected to
Rem the target (PDB) of the Proxy PDB. Set underscore parameter so that
Rem automatic redirection is turned off. This is needed so that utl32k
Rem can be used to migrate varchar2 columns in a Proxy PDB.
Rem
alter session set "_enable_view_pdb"=false;
alter session set current_schema = SYS;
DOC
#######################################################################
#######################################################################
The following statement will cause an "ORA-01722: invalid number"
error if the database has not been opened for UPGRADE.
Perform a "SHUTDOWN ABORT" and
restart using UPGRADE.
#######################################################################
#######################################################################
#
SELECT TO_NUMBER('MUST_BE_OPEN_UPGRADE') FROM v$instance
WHERE status != 'OPEN MIGRATE';
DOC
#######################################################################
#######################################################################
The following statement will cause an "ORA-01722: invalid number"
error if the database does not have compatible >= 12.0.0
Set compatible >= 12.0.0 and retry.
#######################################################################
#######################################################################
#
DECLARE
dummy number;
BEGIN
SELECT CASE WHEN TO_NUMBER(SUBSTR(value,1,2)) < 12
THEN TO_NUMBER('COMPATIBLE_12.1.0_REQUIRED')
ELSE NULL
END INTO dummy
FROM v$parameter WHERE name = 'compatible';
END;
/
alter session set "_oracle_script" = TRUE;
---------------------------------------------------------------------------
-- invalidate views that have VARCHAR or NVARCHAR columns >= 4000 bytes or
-- RAW columns >= 2000 bytes because these columns could change when
-- 32k VARCHAR2, NVARCHAR2, and RAW are enabled.
-- Bug 26285822: invalidate application objects
update obj$ o
set status = 6
where type# IN (4)
and status not in (5, 6)
and (bitand(flags, 196608) = 0 /* not a common object */
or bitand(flags, 134217728) != 0) /* is an application object */
and exists (select * from col$ c
where c.obj# = o.obj#
and ( (c.type# = 1 and c.length >= 4000) or
(c.type# = 23 and c.length >= 2000) ));
commit;
alter system flush shared_pool;
---------------------------------------------------------------------------
-- invalidate views and synonyms that depend on views that have been
-- invalided
-- Bug 26285822: invalidate application objects
begin
loop
update obj$ o_outer set status = 6
where type# in (4, 5)
and status not in (5, 6)
and (bitand(flags, 196608) = 0 /* not a common object */
or bitand(flags, 134217728) != 0) /* is an application object */
and linkname is null
and ((subname is null) or (subname <> 'DBMS_DBUPGRADE_BABY'))
and exists (select o.obj# from obj$ o, dependency$ d
where d.d_obj# = o_outer.obj#
and d.p_obj# = o.obj#
and (bitand(d.property, 1) = 1)
and o.status > 1);
exit when sql%notfound;
end loop;
end;
/
commit;
alter system flush shared_pool;
---------------------------------------------------------------------------
-- Now, update virtual columns if their length has changed as a result
-- of enabling 32k types.
-- Bug 21996904: during selection of candidate columns, we should leave out
-- columns from path tables. Path tables are internal unstructured XML Index
-- (UXI) tables and they should not be changed since:
-- (1) UXI code is not going to be changed in any near future, if required
-- the XMLIndex layer will take care of future changes in utl32k regarding
-- this matter.
-- (2) The column left out from the path table is a virtual column with
-- SYS_ORDERKEY_PARENT("ORDER_KEY") as expression. Such operator does not
-- return a 32 kB type and it is safe to skip during migration.
-- This will be checked by asserting that the candidate columns do not belong
-- to tables specified in path_table_names of dba_xml_indexes
--
-- Bug 26368251: xdb may not be installed, and hence dba_xml_indexes may not
-- exist. So we cannot include dba_xml_indexes in the candidate_columns
-- query. Instead we check dba_xml_indexes inside the candidate_columns loop,
-- if the view exists.
alter session set "_modify_column_index_unusable" = TRUE;
--Turn on csx dml internal event to let internal columns be reloaded
alter session set events '19056 trace name context forever, level 0x10';
create table utl32k_errors(uname varchar2(128),
tname varchar2(128),
cname varchar2(128),
obj# int,
intcol# int,
data_type varchar2(9),
data_len int,
char_used varchar2(4),
virtual varchar2(1),
mv varchar2(1),
error varchar2(4000),
sqlstr clob,
when timestamp);
create table utl32k_warnings(uname varchar2(128),
tname varchar2(128),
warning varchar2(4000),
when timestamp);
-- find all indexes that initially have KQLDINF_TOBE_DROPPED flag set
create table utl32k_ini_tobe_dropped(obj# int);
truncate table utl32k_ini_tobe_dropped;
insert into utl32k_ini_tobe_dropped
select obj# from sys.ind$ where bitand(flags, 536870912) != 0;
variable starttime varchar2(128)
exec :starttime := to_char(systimestamp, 'MM/DD/YYYY HH24:MI:SS.FF');
print starttime
DECLARE
cursor candidate_columns is
select u.name UNAME,
o.name TNAME,
o.obj# OBJ#,
DECODE(c.type#,
1, DECODE(c.charsetform, 2, 'NVARCHAR2', 'VARCHAR2'),
23, 'RAW') DATA_TYPE,
c.spare3 DATA_LEN,
decode(bitand(c.property, 8388608), 0, 'BYTE', 'CHAR') CHAR_USED,
c.name CNAME,
c.intcol# INTCOL#,
decode(c.segcol#, 0, 'Y', 'N') VIRTUAL,
decode(bitand(t.flags, 262144), 0, 'N', 'Y') MV
from sys.tab$ t, sys.obj$ o, sys.user$ u, sys.col$ c
where t.obj# = o.obj# and o.owner# = u.user# and c.obj# = t.obj#
and (bitand(o.flags, 196608) = 0 -- not a common object
or bitand(o.flags, 134217728) != 0) -- is an application object
and (c.segcol# = 0 or -- virtual column
bitand(c.property, 8388608) != 0 or -- CHAR length semantics
bitand(t.flags, 262144) != 0) -- materialized view tbl
and ( (c.type# = 1 and c.length >= 4000) or
(c.type# = 23 and c.length >= 2000) )
order by UNAME, TNAME, VIRTUAL; -- bug 22375145: physical before virtual
schema_table varchar2(512); /* "SCHEMA"."TABLE" for SQL generation */
data_type varchar2(128);
cur integer;
col_cnt integer;
len integer;
off integer;
discard integer;
str varchar2(32767);
strlen integer;
col_desc DBMS_SQL.DESC_TAB2;
col_expr clob;
sqlstr clob;
mv_str clob;
long_chunk_sz constant int := 256;
parse_proc varchar2(32767);
parse_exec varchar2(128);
parse_dele varchar2(128);
tokenset_dml varchar2(30);
mv_objn int;
mv_status int;
mv_owner varchar2(128);
mv_name varchar2(128);
mv_schema_table varchar2(512); /* "SCHEMA"."TABLE" for SQL generation */
doATB boolean; /* ALTER TABLE MODIFY should be done */
exclude_xdb int;
cnt int;
BEGIN
-- Bug 21907429: enable DDL on AQ tables
sys.dbms_aqadm_sys.Mark_Internal_Tables(dbms_aqadm_sys.ENABLE_AQ_DDL);
cur := DBMS_SQL.OPEN_CURSOR;
-- Bug 26285822: Set _skip_app_object_check to TRUE to bypass
-- restrictions on application objects as they cannot be altered outside
-- application begin/end block.
EXECUTE IMMEDIATE 'alter session set "_skip_app_object_check" = TRUE';
-- Bug 26368251: here we check if XDB was installed; we use this to
-- decide if we can query DBA_XML_INDEXES
select count(*) into exclude_xdb from v$parameter
where name='_no_catalog' and
(value = 'XDB' or value like 'XDB,%' or value like '%,XDB' or
value like '%,XDB,%');
for target in candidate_columns loop
BEGIN
-- Bug 26368251: if XDB was installed, we check if this column is
-- in a path table. If so, we skip the column for reasons explained in
-- bug 21996904. If XDB is not install there are no path tables
-- and there is nothing to check here.
IF exclude_xdb = 0 THEN
EXECUTE IMMEDIATE 'select count(*) from dba_xml_indexes '
|| 'where index_owner = :1 and path_table_name = :2'
INTO cnt
USING target.UNAME, target.TNAME;
IF cnt > 0 THEN
CONTINUE;
END IF;
END IF;
doATB := TRUE;
schema_table := DBMS_ASSERT.ENQUOTE_NAME(target.UNAME, FALSE) || '.'
|| DBMS_ASSERT.ENQUOTE_NAME(target.TNAME, FALSE);
IF (target.virtual = 'Y') THEN
DBMS_SQL.PARSE(cur,
'select deflength, default$ from col$ where obj# = :1 and name = :2',
DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(cur, ':1', target.obj#);
DBMS_SQL.BIND_VARIABLE(cur, ':2', target.cname);
DBMS_SQL.DEFINE_COLUMN(cur, 1, len);
DBMS_SQL.DEFINE_COLUMN_LONG(cur, 2);
discard := DBMS_SQL.EXECUTE(cur);
discard := DBMS_SQL.FETCH_ROWS(cur);
DBMS_SQL.COLUMN_VALUE(cur, 1, len);
/* bug 25922494: bitmap join indexes create virtual columns that have
* NULL deflength and default$. In this case there is no migration
* required for the virtual column.
*/
if (len IS NULL) then
doATB := FALSE;
else
col_expr := '';
off := 0;
WHILE len > 0 LOOP
DBMS_SQL.COLUMN_VALUE_LONG(cur, 2, long_chunk_sz, off, str, strlen);
col_expr := col_expr || str;
off := off + strlen;
len := len - strlen;
END LOOP;
/* Bug 20911289: let dml to go through for csx tokenset objects
* This is required for the virtual column in QN index to be aliased*/
tokenset_dml := '/*+ XMLTSET_DML_ENABLE*/ ';
/* Bug 16237862: use an alias for the column to avoid column
* name overflow errors in dbms_sql.describe_columns.
*/
sqlstr := 'SELECT '
|| tokenset_dml || col_expr || ' expr FROM ' || schema_table;
DBMS_SQL.PARSE(cur, sqlstr, DBMS_SQL.NATIVE);
DBMS_SQL.DESCRIBE_COLUMNS2(cur, col_cnt, col_desc);
data_type := target.DATA_TYPE || '(' || col_desc(1).col_max_len || ')';
end if;
ELSIF (target.mv = 'Y') THEN
DBMS_SQL.PARSE(cur,
'select sumtextlen, sumtext, obj# from sys.sum$ ' ||
'where containerobj# = :1',
DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(cur, ':1', target.obj#);
DBMS_SQL.DEFINE_COLUMN(cur, 1, len);
DBMS_SQL.DEFINE_COLUMN_LONG(cur, 2);
DBMS_SQL.DEFINE_COLUMN(cur, 3, mv_objn);
discard := DBMS_SQL.EXECUTE(cur);
discard := DBMS_SQL.FETCH_ROWS(cur);
DBMS_SQL.COLUMN_VALUE(cur, 1, len);
mv_str := '';
off := 0;
WHILE len > 0 LOOP
DBMS_SQL.COLUMN_VALUE_LONG(cur, 2, long_chunk_sz, off, str, strlen);
mv_str := mv_str || str;
off := off + strlen;
len := len - strlen;
END LOOP;
DBMS_SQL.COLUMN_VALUE(cur, 3, mv_objn);
-- check status of the MV
EXECUTE IMMEDIATE
'select u.name, o.name, o.status from sys.obj$ o, sys.user$ u ' ||
'where o.obj# = :1 and o.owner# = u.user#'
into mv_owner, mv_name, mv_status
using mv_objn;
mv_schema_table := DBMS_ASSERT.ENQUOTE_NAME(mv_owner, FALSE) || '.' ||
DBMS_ASSERT.ENQUOTE_NAME(mv_name, FALSE);
IF mv_status != 1 THEN
sqlstr := 'alter materialized view ' || mv_schema_table ||
' compile';
EXECUTE IMMEDIATE sqlstr;
EXECUTE IMMEDIATE
'select u.name, o.name, o.status from sys.obj$ o, sys.user$ u ' ||
'where o.obj# = :1 and o.owner# = u.user#'
into mv_owner, mv_name, mv_status
using mv_objn;
END IF;
IF mv_status != 1 THEN
insert into utl32k_warnings values(target.UNAME, target.TNAME,
'Materialized view container table ' || schema_table
|| 'was not migrated because materialized view '
|| mv_schema_table
|| 'has compilation errors. When compilation errors have been fixed, '
|| 'column length in the container table can be updated manually '
|| 'via ALTER MATERIALIZED VIEW <mview_name> '
|| 'MODIFY(<col> <data type>).',
SYSTIMESTAMP);
ELSE
execute immediate
'alter session set current_schema = '
|| DBMS_ASSERT.ENQUOTE_NAME(target.UNAME, FALSE);
sqlstr := mv_str;
-- Bug 19063812 : Incase of mview definition query,create a procedure
-- as part of the mview owner schema to do the parsing. This is to
-- avoid ORA 2019 when parsing db links which maybe present in the
-- query.
parse_proc := 'create or replace procedure utl32k_parsequery
(
sqlstr IN clob,
col_cnt OUT integer,
col_desc OUT DBMS_SQL.DESC_TAB2
)as
cur integer;
begin
cur := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(cur, sqlstr, DBMS_SQL.NATIVE);
DBMS_SQL.DESCRIBE_COLUMNS2(cur, col_cnt, col_desc);
DBMS_SQL.CLOSE_CURSOR(cur);
EXCEPTION WHEN OTHERS THEN
DBMS_SQL.CLOSE_CURSOR(cur);
RAISE;
end;';
execute immediate parse_proc;
parse_exec := 'BEGIN utl32k_parsequery(:a, :b, :c); END;';
execute immediate parse_exec
USING IN sqlstr,OUT col_cnt,OUT col_desc;
data_type := target.DATA_TYPE
|| '(' || col_desc(target.intcol#).col_max_len || ')';
parse_dele := 'drop procedure utl32k_parsequery';
execute immediate parse_dele;
execute immediate
'alter session set current_schema = SYS';
END IF;
ELSE
IF (target.DATA_TYPE = 'NVARCHAR2') THEN
data_type := target.DATA_TYPE
|| '(' || target.DATA_LEN || ')';
ELSE
data_type := target.DATA_TYPE
|| '(' || target.DATA_LEN || ' ' || target.CHAR_USED || ')';
END IF;
END IF;
if doATB then
sqlstr := 'ALTER TABLE ' || schema_table
|| ' MODIFY (' || DBMS_ASSERT.ENQUOTE_NAME(target.CNAME, FALSE)
|| ' ' || data_type || ')';
dbms_output.put_line(sqlstr);
EXECUTE IMMEDIATE sqlstr;
end if;
EXCEPTION WHEN OTHERS THEN
execute immediate
'insert into utl32k_errors(uname, tname, cname, obj#,
intcol#, data_type, data_len, char_used,
virtual, mv, error, sqlstr,
when)
values (:1, :2, :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, :13)'
using target.uname, target.tname, target.cname, target.obj#,
target.intcol#, target.data_type, target.data_len, target.char_used,
target.virtual, target.mv, sqlerrm, sqlstr,
systimestamp;
END;
end loop;
EXECUTE IMMEDIATE 'alter session set "_skip_app_object_check" = FALSE';
DBMS_SQL.CLOSE_CURSOR(cur);
END;
/
show errors;
-- Bug 21907429: disable DDL on AQ tables since we've finished processing them
BEGIN
sys.dbms_aqadm_sys.Mark_Internal_Tables(dbms_aqadm_sys.DISABLE_AQ_DDL);
END;
/
--Turn off csx dml internal event after finished processing columns
alter session set events '19056 trace name context off';
alter session set "_modify_column_index_unusable" = FALSE;
insert into utl32k_warnings
select tu.name, tobj.name,
CASE WHEN i.type# != 9 THEN
'Index "' || iu.name || '"."' || iobj.name
|| '" must be dropped because it now exceeds maximum key length.'
ELSE
'Domain index "' || iu.name || '"."' || iobj.name
|| '" is now unusable because length of the indexed column '
|| 'has changed. This index must be dropped and recreated.'
END,
systimestamp
from sys.ind$ i, obj$ tobj, obj$ iobj, user$ tu, user$ iu
where bitand(i.flags, 536870912) != 0
and i.bo# = tobj.obj# and i.obj# = iobj.obj#
and tobj.owner# = tu.user# and iobj.owner# = iu.user#
and i.obj# not in (select obj# from utl32k_ini_tobe_dropped);
select uname, tname, warning from utl32k_warnings
where when > TO_TIMESTAMP(:starttime, 'MM/DD/YYYY HH24:MI:SS.FF')
order by when;
select uname, tname, cname, error from utl32k_errors
where when > TO_TIMESTAMP(:starttime, 'MM/DD/YYYY HH24:MI:SS.FF')
order by when;
DOC
#######################################################################
#######################################################################
The following statement will cause an "ORA-01722: invalid number"
error if we encountered an error while modifying a column to
account for data type length change as a result of enabling or
disabling 32k types.
Contact Oracle support for assistance.
#######################################################################
#######################################################################
#
DECLARE
dummy number;
BEGIN
SELECT CASE WHEN COUNT(*) > 0 THEN TO_NUMBER('ERROR IN UTL32K MIGRATION')
ELSE NULL
END INTO dummy
FROM utl32k_errors
where when > TO_TIMESTAMP(:starttime, 'MM/DD/YYYY HH24:MI:SS.FF');
END;
/
-- update PROPS$ to indicate that we've completed migration in this container
DECLARE
mss_typ binary_integer; -- type of max_string_size parameter
mss_len binary_integer; -- length of max_string_size parameter
mss_prm varchar2(80); -- max_string_size parameter
BEGIN
-- get the MAX_STRING_SIZE parameter
mss_typ := SYS.DBMS_UTILITY.GET_PARAMETER_VALUE('MAX_STRING_SIZE',
mss_len, mss_prm);
update props$ set value$ = mss_prm where name = 'MAX_STRING_SIZE';
END;
/
commit;
Rem Continue even if there are SQL errors
WHENEVER SQLERROR CONTINUE;
---------------------------------------------------------------------------
-- bug 16894689: utlrp.sql should be run in normal mode to recompile all
-- invalid objects
alter package SYS.DBMS_INTERNAL_LOGSTDBY compile;
alter package SYS.PRVT_ADVISOR compile;
--bug 25812018: Oracle Script need to be unset
alter session set "_oracle_script" = FALSE;
OHA YOOOO