MIGRATION_WORKBENCH.MD_META

Specification
AS
FUNCTION get_next_id RETURN NUMBER;
-- Following code taken directly from wwv_flow_random from APEX
--
-- seed random function
procedure srand( new_seed in number );

function rand return number;
pragma restrict_references( rand, WNDS );

procedure get_rand( r OUT number );

function rand_max( n IN number ) return number;
pragma restrict_references( rand_max, WNDS);

procedure get_rand_max( r OUT number, n IN number );

END;
Body Definition
AS

multiplier constant number := 22695477;
increment constant number := 1;
"2^32" constant number := 2 ** 32;
"2^16" constant number := 2 ** 16;
"0x7fff" constant number := 32767;
Seed number := 1;
g_curr_val NUMBER DEFAULT NULL;
/*
* Get the next available id for objectids.
* @return the next id that can be used in objectid fields
* This code is taken from wwv_flows
*/
FUNCTION get_next_id RETURN NUMBER
IS
BEGIN
/*
select to_number(
to_char(dbobjectid_sequence.nextval) ||
lpad( substr( abs(rand), 1, 5 ),5, '0' ) ||
ltrim(to_char(mod(abs(hsecs),1000000),'000000')))
into g_curr_val
from sys.v_$timer;

select to_number(
to_char(dbobjectid_sequence.nextval) ||
lpad( substr( abs(rand), 1, 5 ), 5, '0') ||
ltrim(to_char(mod(dbms_random.value(100000000000, 999999999999),1000000),'000000')))
into g_curr_val
from dual;
*/
select dbobjectid_sequence.nextval
into g_curr_val
from dual;
return g_curr_val;
END get_next_id;
-- Following code taken from wwv_flows_random
procedure srand( new_seed in number ) is
begin
Seed := new_seed;
end srand;
--
function rand return number is
s number;
begin
seed := mod( multiplier * seed + increment, "2^32" );
begin
return bitand( seed/"2^16", "0x7fff" );
--mhichwa
exception when others then
select dbobjectid_sequence.nextval into s from dual;
return s||to_char(sysdate,'HH24MISS');
end;
end rand;
--
procedure get_rand( r OUT number ) is
begin
r := rand;
end get_rand;
--
function rand_max( n IN number ) return number is
begin
return mod( rand, n ) + 1;
end rand_max;
--
procedure get_rand_max( r OUT number, n IN number ) is
begin
r := rand_max( n );
end get_rand_max;
--
-- One time initialisation
begin
select to_char(sysdate,'JSSSSS')
into seed
from dual;
end;

 

MIGRATION_WORKBENCH.MIGRATION

Specification
AS

-- Public functions
FUNCTION copy_connection_cascade(p_connectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL,p_scratchModel BOOLEAN := FALSE) RETURN NUMBER;
FUNCTION transform_all_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE, p_prefixName VARCHAR2, p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_ARRAY;
FUNCTION transform_datatypes(p_connectionid MD_CONNECTIONS.ID%TYPE, p_mapid MIGR_DATATYPE_TRANSFORM_MAP.ID%TYPE, p_numbytesperchar INTEGER) RETURN NUMBER;
FUNCTION transform_identity_columns(p_connectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER;
FUNCTION transform_rewrite_trigger(p_connectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER;
FUNCTION gatherConnectionStats(p_connectionId MD_CONNECTIONS.ID%TYPE,p_comments MD_CONNECTIONS.COMMENTS%TYPE) RETURN NUMBER;
PROCEDURE transform_clashes(p_connectionid MD_CONNECTIONS.ID%TYPE, p_scratchModel BOOLEAN := FALSE);
PROCEDURE populate_derivatives_table(p_connectionid MD_CONNECTIONS.ID%TYPE);
PROCEDURE revert_derivatives_table(p_connectionid MD_CONNECTIONS.ID%TYPE);
END;
Body Definition
AS
/**
* The migration package contains all of the PL/SQL Procedures and functions required by the migration
* system.
* @author Barry McGillin
* @author Dermot Daly.
*/
--a.id schema_id, A.name schema_name, b.id catalog_id, B.CATALOG_NAME,
--B.DUMMY_FLAG, A.type, A.character_set, A.version_tag
TYPE DERIVATIVE_REC IS RECORD (
schema_id NUMBER,
schema_name VARCHAR2(4000 BYTE),
catalog_id NUMBER,
catalog_name VARCHAR2(4000 BYTE),
dummy_flag CHAR(1 BYTE),
cap_type CHAR(1 BYTE),
character_set VARCHAR2(4000 BYTE),
version_tag VARCHAR2(40 BYTE)
);

TYPE DERIVATIVE_REC2 IS RECORD (
schemaid NUMBER,
newid NUMBER
);

v_prefixName VARCHAR2(4) :=''; --text to prefix objects with ,set using transform_all_identifiers
-- Constants that are used throughout the package body.
C_CONNECTIONTYPE_CONVERTED CONSTANT MD_CONNECTIONS.TYPE%TYPE := 'CONVERTED';
C_CONNECTIONTYPE_SCRATCH CONSTANT MD_CONNECTIONS.TYPE%TYPE := 'SCRATCH'; -- enterprise capture/convert
-- Supported object types.
C_OBJECTTYPE_CONNECTIONS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_CONNECTIONS';
C_OBJECTTYPE_CATALOGS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_CATALOGS';
C_OBJECTTYPE_SCHEMAS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_SCHEMAS';
C_OBJECTTYPE_TABLES CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_TABLES';
C_OBJECTTYPE_COLUMNS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_COLUMNS';
C_OBJECTTYPE_CNSTRNT_DETAILS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_CONSTRAINT_DETAILS';
C_OBJECTTYPE_CONSTRAINTS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_CONSTRAINTS';
C_OBJECTTYPE_INDEX_DETAILS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_INDEX_DETAILS';
C_OBJECTTYPE_INDEXES CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_INDEXES';
C_OBJECTTYPE_TRIGGERS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_TRIGGERS';
C_OBJECTTYPE_VIEWS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_VIEWS';
C_OBJECTTYPE_USERS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_USERS';
C_OBJECTTYPE_GROUP_MEMBERS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_GROUPMEMBERS';
C_OBJECTTYPE_GROUPS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_GROUPS';
C_OBJECTTYPE_OTHER_OBJECTS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_OTHER_OBJECTS';
C_OBJECTTYPE_TABLESPACES CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_TABLESPACES';
C_OBJECTTYPE_UDDT CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_USER_DEFINED_DATA_TYPES';
C_OBJECTTYPE_STORED_PROGRAMS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_STORED_PROGRAMS';
C_OBJECTTYPE_PACKAGES CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_PACKAGES';
C_OBJECTTYPE_SYNONYMS CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_SYNONYMS';
C_OBJECTTYPE_SEQUENCES CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_SEQUENCES';
C_OBJECTTYPE_PRIVILEGES CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_PRIVILEGES';
C_OBJECTTYPE_USER_PRIVILEGES CONSTANT MD_DERIVATIVES.SRC_TYPE%TYPE := 'MD_USER_PRIVILEGES';
-- Dummy flag for a dummy catalog.
C_DUMMYFLAG_TRUE CONSTANT MD_CATALOGS.DUMMY_FLAG%TYPE := 'Y';
-- Flag in MD_DERIVATIVES to show if something has been transformed
C_TRANSFORMED_TRUE CONSTANT MD_DERIVATIVES.TRANSFORMED%TYPE := 'Y';
-- Flag in MD_SYNONYMS.PRIVATE_VISIBILITY to highlight that a synonym is marked as private
C_SYNONYM_PRIVATE CONSTANT MD_SYNONYMS.PRIVATE_VISIBILITY%TYPE := 'Y';
-- Flag in MD_GROUPS.GROUP_FLAG to show this is a role
C_ROLE_FLAG CONSTANT MD_GROUPS.GROUP_FLAG%TYPE := 'R';
-- Flag in MD_COLUMNS TO SHOW A COLUMN IS NULLABLE
C_NULLABLE_YES CONSTANT MD_COLUMNS.NULLABLE%TYPE := 'Y';
-- Special defined additional properties.
C_PROPKEY_SEEDVALUE CONSTANT MD_ADDITIONAL_PROPERTIES.PROP_KEY%TYPE := 'SEEDVALUE';
C_PROPKEY_INCREMENT CONSTANT MD_ADDITIONAL_PROPERTIES.PROP_KEY%TYPE := 'INCREMENT';
C_PROPKEY_LASTVALUE CONSTANT MD_ADDITIONAL_PROPERTIES.PROP_KEY%TYPE := 'LASTVALUE';
C_PROPKEY_EXTENDEDINDEXTYPE CONSTANT MD_ADDITIONAL_PROPERTIES.PROP_KEY%TYPE := 'EXTENDEDINDEXTYPE';
C_PROPKEY_SEQUENCEID CONSTANT MD_ADDITIONAL_PROPERTIES.PROP_KEY%TYPE := 'SEQUENCEID';
C_PROPKEY_TRIGGER_REWRITE CONSTANT MD_ADDITIONAL_PROPERTIES.PROP_KEY%TYPE := 'TRIGGER_REWRITE';
-- Name spaces for identifiers
C_NS_SCHEMA_OBJS CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_SCHEMAOBJS';
C_NS_INDEXES CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_INDEXES';
C_NS_CONSTRAINTS CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_CONSTRAINTS';
C_NS_CLUSTERS CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_CLUSTERS';
C_NS_DB_TRIGGERS CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_DB_TRIGGERS';
C_NS_PRIVATE_DBLINKS CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_PRIVATEDBLINKS';
C_NS_DIMENSIONS CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_DIMENSIONS';
C_NS_USER_ROLES CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_USERROLES';
C_NS_PUBLIC_SYNONYMS CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_PUB_SYNONYMS';
C_NS_PUBLIC_DBLINKS CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_PUBLICDBLINKS';
C_NS_TABLESPACES CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_TABLESPACES';
C_NS_PROFILES CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_PROFILES';
C_NS_DATABASE CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_DATABASE';
C_NS_USERS CONSTANT MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := 'NS_USERS';
-- Constants for Filter Types
-- Filter Types are 0-> ALL, 1->NAMELIST, 2->WHERE CLAUSE, 3->OBJECTID LIST
C_FILTERTYPE_ALL CONSTANT INTEGER := 0;
C_FILTERTYPE_NAMELIST CONSTANT INTEGER := 1;
C_FILTERTYPE_WHERECLAUSE CONSTANT INTEGER := 2;
C_FILTERTYPE_OBJECTIDLIST CONSTANT INTEGER := 3;
-- Constatns for TEXT INDEX TYPES
-- see http://download-west.oracle.com/docs/cd/B10501_01/text.920/a96518/csql.htm#19446
-- Use this index type when there is one CLOB or BLOB column in the index only
C_INDEXTYPE_CONTEXT CONSTANT MD_ADDITIONAL_PROPERTIES.VALUE%TYPE := 'ctxsys.context';
-- Use this index type when the index containst a CLOB or BLOB column.
C_INDEXTYPE_CTXCAT CONSTANT MD_ADDITIONAL_PROPERTIES.VALUE%TYPE := 'ctxsys.ctxcat';
-- Constant for LANGUAGE - Used in MD_TRIGGERS, MD_PACKAGES, MD_STORED_PROGRAMS, MD_VIEWS, and MD_CONSTRAINTS
C_LANGUAGEID_ORACLE CONSTANT MD_TRIGGERS.LANGUAGE%TYPE := 'OracleSQL';
-- Type for a generic REF CURSOR
TYPE REF_CURSOR IS REF CURSOR;
/**
* Find a filter element from a filter list
*/
FUNCTION find_filter_for_type(p_filterSet MIGR_FILTER_SET, p_objtype MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE) RETURN MIGR_FILTER
IS
BEGIN
IF p_filterset is NULL OR p_objtype is NULL then
return NULL;
END IF;
FOR indx in p_filterset.FIRST .. p_filterset.LAST
LOOP
if p_filterset(indx).OBJTYPE = p_objtype THEN
return p_filterset(indx);
end if;
END LOOP;
return NULL;
END find_filter_for_type;

/**
* Convert a name list from a filter into a condition for use in a where clause.
* @param p_nameList the set of names that form part of the filter
* @param p_nameField the name of the field to be compared against.
* @return A condition that can be used in a where clause.
*/
FUNCTION namelist_to_where_clause(p_nameList NAMELIST, p_nameField VARCHAR2) RETURN VARCHAR2
IS
v_ret VARCHAR2(4000);
BEGIN
v_ret := p_nameField || ' IN (';
FOR indx IN p_nameList.FIRST .. p_nameList.LAST
LOOP
v_ret := v_ret || '''' || p_nameList(indx) || '''';
IF indx != p_nameList.LAST THEN
v_ret := v_ret || ', ';
END IF;
END LOOP;
v_ret := v_ret || ')';
return v_ret;
END namelist_to_where_clause;

/**
* Convert an object id list from a filter into a condition for use in a where clause.
* @param p_oidList The list of object ids taken from the filter.
* @param p_idFIeld The field to be tested against.
* @return A condition that can be used in a where clause.
*/
FUNCTION objectIdList_to_where_clause(p_oidList OBJECTIDLIST, p_idField VARCHAR2) RETURN VARCHAR2
IS
v_ret VARCHAR2(4000);
BEGIN
V_RET := p_idField || ' IN (';
FOR indx IN p_oidList.FIRST .. p_oidList.LAST
LOOP
v_ret := v_ret || TO_CHAR(p_oidList(indx));
IF indx != p_oidList.LAST THEN
v_ret := v_ret || ', ';
END IF;
END LOOP;
v_ret := v_ret || ')';
return v_ret;
END objectIdList_to_where_clause;

/**
* Convert a filter to a condition for use in a where clause.
* @param p_filter The filter
* @param p_nameFileld The name field that will be used in the names list or where clause.
* @param p_idField The id field that will be used if the filter is an objectid list.
* @return A condition that could be used in a where clause. NULL if no additional filtering is required.
*/
FUNCTION where_clause_from_filter(p_filter MIGR_FILTER, p_nameField VARCHAR2, p_idField VARCHAR2) RETURN VARCHAR2
IS
BEGIN
IF p_filter.FILTER_TYPE = C_FILTERTYPE_ALL THEN
RETURN NULL;
ELSIF p_filter.FILTER_TYPE = C_FILTERTYPE_NAMELIST THEN
RETURN namelist_to_where_clause(p_filter.NAMES, p_nameField);
ELSIF p_filter.FILTER_TYPE = C_FILTERTYPE_WHERECLAUSE THEN
RETURN p_nameField || ' ' || p_filter.WHERECLAUSE;
ELSE
RETURN objectidlist_to_where_clause(p_filter.OBJECTIDS, p_idField);
END IF;
END where_clause_from_filter;

/**
* Apply a filter to an existing select statement
* @param p_filter_set The filter set.
* @param p_filter_type The type of the object, for finding in the filter set.
* @param p_name_field The name field of the table being filtered
* @param p_id_field The id field of the table being filtered.
* @param p_select_stmt The select statment to tag the new condition on to
* @return The select statement with the new condition added to it (or the original statement if
* there is no applicable filter for this object type.
*/
FUNCTION apply_filter(p_filter_set MIGR_FILTER_SET,
p_filter_type MD_DERIVATIVES.SRC_TYPE%TYPE,
p_name_field VARCHAR2,
p_id_field VARCHAR2,
p_select_stmt VARCHAR2) RETURN VARCHAR2
IS
v_filt MIGR_FILTER;
v_condition VARCHAR2(4000);
BEGIN
v_filt := find_filter_for_type(p_filter_set, p_filter_type);
--if the filter is null, then we need to set a value that will fail always so nothing is moved.
-- ie 1=2
IF v_filt IS NOT NULL THEN
v_condition := where_clause_from_filter(v_filt, p_name_field, p_id_field);
IF v_condition IS NOT NULL THEN
RETURN p_select_stmt || ' AND ' || v_condition;
ELSE
RETURN p_select_stmt;
END IF;
END IF;
RETURN p_select_stmt || ' AND 1=2';
END apply_filter;


/**
* Find the copy of a particular object. This function checks for a copied object of a particular
* type by searching the MD_DERIVATIVES table.
* @param p_objectid The id of the object to search for.
* @param p_objecttype The type of the object to search for.
* @return the id of the copy object if it is present, or NULL if it is not.
*/
FUNCTION find_object_copy(p_objectid md_projects.id%TYPE, p_objecttype MD_DERIVATIVES.SRC_TYPE%TYPE, p_derivedconnectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
v_ret MD_DERIVATIVES.DERIVED_ID%TYPE;
BEGIN
SELECT derived_id INTO v_ret FROM MD_DERIVATIVES
WHERE src_id = p_objectid
AND src_type = p_objecttype
AND derived_type = p_objecttype
AND derived_connection_id_fk = p_derivedconnectionid;
RETURN v_ret;
EXCEPTION
WHEN NO_DATA_FOUND then
-- Should we raise an error?
RETURN NULL;
END find_object_copy;

/**
* Copy additional properties. function copies the additional properties for an object.
* @param p_refobjectid The object id whose additional properties have to be copied
* @param p_newrefobject The id of the copied object the new properties should refer to
* @return number of additional properties copied
*/
FUNCTION copy_additional_properties(p_refobjectid MD_ADDITIONAL_PROPERTIES.REF_ID_FK%TYPE, p_newrefobject MD_PROJECTS.ID%TYPE, p_newconnectionid MD_ADDITIONAL_PROPERTIES.CONNECTION_ID_FK%TYPE) RETURN NUMBER
IS
CURSOR ORIGINAL_RECS IS SELECT PROPERTY_ORDER, PROP_KEY, REF_TYPE, VALUE FROM MD_ADDITIONAL_PROPERTIES WHERE REF_ID_FK=p_refobjectid;
v_numcopied NUMBER := 0;
BEGIN
for newrec in ORIGINAL_RECS LOOP
INSERT INTO MD_ADDITIONAL_PROPERTIES (ref_id_fk, ref_type, property_order, prop_key, value, connection_id_fk)
VALUES (p_newrefobject, newrec.ref_type, newrec.property_order, newrec.prop_key, newrec.value, p_newconnectionid);
v_numcopied := v_numcopied + 1;
END LOOP;
commit;
return v_numcopied;
END copy_additional_properties;

FUNCTION copy_connection(p_connectionid MD_CONNECTIONS.ID%TYPE, p_scratchModel BOOLEAN := FALSE) RETURN NUMBER
IS
newrec MD_CONNECTIONS%ROWTYPE;
newid MD_CONNECTIONS.ID%TYPE;
origName MD_CONNECTIONS.NAME%TYPE;
BEGIN
SELECT * INTO newrec from MD_CONNECTIONS WHERE id = p_connectionid;

newrec.HOST := NULL;
newrec.PORT := NULL;
newrec.USERNAME := NULL;
newrec.DBURL := NULL;
-- TODO. Need to do this in a more i18n friendly manner.
origName := newrec.NAME;

IF p_scratchModel = FALSE
THEN
newrec.TYPE :=C_CONNECTIONTYPE_CONVERTED;
newrec.NAME := 'Converted:' || newrec.NAME;
ELSE
newrec.TYPE :=C_CONNECTIONTYPE_SCRATCH;
newrec.NAME := 'Scratch:' || newrec.NAME;
END IF;
-- Let the trigger create the new ID
newrec.ID := NULL;
INSERT INTO MD_CONNECTIONS VALUES newrec
RETURNING id into newid;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, derived_connection_id_fk, original_identifier, new_identifier)
VALUES (p_connectionid, C_OBJECTTYPE_CONNECTIONS, newid, C_OBJECTTYPE_CONNECTIONS, newid, origName, newrec.NAME);
commit;
return newid;
END copy_connection;


FUNCTION create_dummy_catalog(p_connectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
newid MD_CATALOGS.ID%TYPE;
BEGIN
INSERT INTO MD_CATALOGS (CONNECTION_ID_FK, CATALOG_NAME, DUMMY_FLAG, NATIVE_SQL, NATIVE_KEY)
VALUES (p_connectionid, ' ', C_DUMMYFLAG_TRUE, NULL, NULL)
RETURNING ID INTO newid;
RETURN newid;
END create_dummy_catalog;

FUNCTION find_or_create_dummy_catalog(p_connectionid MD_CONNECTIONS.ID%TYPE, p_catalogid MD_CATALOGS.ID%TYPE) RETURN NUMBER
IS
newrec MD_CATALOGS%ROWTYPE;
newid MD_CATALOGS.ID%TYPE;
BEGIN
SELECT * INTO newrec from MD_CATALOGS where connection_id_fk = p_connectionid and "ID" = p_catalogid;
return newrec.id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO MD_CATALOGS (CONNECTION_ID_FK, CATALOG_NAME, DUMMY_FLAG, NATIVE_SQL, NATIVE_KEY)
VALUES (p_connectionid, ' ', C_DUMMYFLAG_TRUE, NULL, NULL)
RETURNING ID INTO newid;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, derived_connection_id_fk, DERIVED_OBJECT_NAMESPACE)
VALUES (p_catalogid, C_OBJECTTYPE_CATALOGS, newid, C_OBJECTTYPE_CATALOGS, p_connectionid, C_NS_DATABASE);
commit;
return newid;
END find_or_create_dummy_catalog;

-- Enterprise convert may have 1 catalog belonging to a given connection id
PROCEDURE create_dummy_catalogs(p_connectionid MD_CONNECTIONS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_scratchModel BOOLEAN)
IS
CURSOR curcats(connId MD_CONNECTIONS.ID%TYPE) IS select * from MD_CATALOGS where connection_id_fk = connId;
cat_row MD_CATALOGS%ROWTYPE;
newid MD_CATALOGS."ID"%TYPE;
v_sql VARCHAR2(300);
BEGIN
OPEN curcats(p_connectionid);
FETCH curcats INTO cat_row;
LOOP
EXIT WHEN curcats%NOTFOUND;
newid := find_or_create_dummy_catalog(p_newconnectionid, cat_row."ID");
v_sql := 'UPDATE MD_CATALOGS SET CATALOG_NAME = ''' || cat_row."CATALOG_NAME" || ''' WHERE ID = ' || TO_CHAR(newid);
EXECUTE IMMEDIATE v_sql;
FETCH curcats INTO cat_row;
END LOOP;
CLOSE curcats;
COMMIT;
END create_dummy_catalogs;


FUNCTION copy_individual_catalog(p_catalogid MD_CATALOGS.ID%TYPE) RETURN NUMBER
IS
newrec MD_CATALOGS%ROWTYPE;
newconnectionid MD_CATALOGS.CONNECTION_ID_FK%TYPE;
dummycatalogid MD_CATALOGS.ID%TYPE;
originalconnectionid MD_CATALOGS.CONNECTION_ID_FK%TYPE;
BEGIN
-- Catalogs aren't copied as such. Instead, we make a single DUMMY catalog
-- Within the new connection
-- So..first see if one exists for the copied connection
SELECT CONNECTION_ID_FK INTO originalconnectionid FROM MD_CATALOGS WHERE ID = p_catalogid;
-- For connections, we have a special case. We can't store the new connection, but 0 is ok.
newconnectionid := find_object_copy(originalconnectionid, C_OBJECTTYPE_CONNECTIONS, 0);
IF newconnectionid IS NULL THEN
newconnectionid := copy_connection(originalconnectionid);
END IF;
dummycatalogid := find_or_create_dummy_catalog(newconnectionid, p_catalogid);
RETURN dummycatalogid;
END copy_individual_catalog;

FUNCTION copy_individual_schema(p_schemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
newid MD_SCHEMAS.ID%TYPE;
newrec MD_SCHEMAS%ROWTYPE;
newcatalogid MD_CATALOGS.ID%TYPE;
originalcatalogname MD_CATALOGS.CATALOG_NAME%TYPE;
originalcatalogid MD_SCHEMAS.CATALOG_ID_FK%TYPE;
originalschemaname MD_SCHEMAS.NAME%TYPE;
originalisdummy CHAR;
BEGIN
SELECT * INTO newrec FROM md_schemas WHERE id = p_schemaid;
newcatalogid := find_object_copy(newrec.catalog_id_fk, C_OBJECTTYPE_CATALOGS, p_newconnectionid);
originalcatalogid := newrec.catalog_id_fk;
originalschemaname := newrec.NAME;
select CATALOG_NAME, DUMMY_FLAG into originalcatalogname, originalisdummy from MD_CATALOGS WHERE ID = originalcatalogid;
IF newcatalogid IS NULL THEN
newcatalogid := copy_individual_catalog(newrec.catalog_id_fk);
END IF;

newrec.catalog_id_fk := newcatalogid;
if originalisdummy <> C_DUMMYFLAG_TRUE THEN
newrec.name := originalcatalogname || '_' || newrec.name;
end if;
-- Let the trigger work out the new id
newrec.ID := NULL;
INSERT INTO MD_SCHEMAS VALUES newrec RETURNING ID INTO newid;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, original_identifier, new_identifier, DERIVED_OBJECT_NAMESPACE)
VALUES (p_schemaid, C_OBJECTTYPE_SCHEMAS, newid, C_OBJECTTYPE_SCHEMAS, originalschemaname, newrec.name, C_NS_DATABASE);
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type)
VALUES (originalcatalogid, C_OBJECTTYPE_CATALOGS, newid, C_OBJECTTYPE_SCHEMAS);
COMMIT;
return newid;
END copy_individual_schema;

FUNCTION copy_individual_table(p_tableid MD_TABLES.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
newrec MD_TABLES%rowtype;
newid MD_TABLES.ID%TYPE;
newschemaid MD_SCHEMAS.ID%TYPE;
BEGIN
SELECT * INTO newrec FROM MD_tables WHERE id = p_tableid;
newschemaid := find_object_copy(newrec.schema_id_fk, C_OBJECTTYPE_SCHEMAS, p_newconnectionid);
IF newschemaid IS NULL THEN
newschemaid := copy_individual_schema(newrec.schema_id_fk, p_newconnectionid);
END IF;

newrec.schema_id_fk := newschemaid;
-- Let the trigger work out the new id
newrec.ID := NULL;
INSERT INTO MD_TABLES VALUES newrec RETURNING ID INTO newid;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, derived_connection_id_fk, original_identifier, new_identifier, DERIVED_OBJECT_NAMESPACE)
VALUES(p_tableid, C_OBJECTTYPE_TABLES, newid, C_OBJECTTYPE_TABLES, p_newconnectionid, newrec.table_name, newrec.table_name, C_NS_SCHEMA_OBJS || TO_CHAR(newschemaid));
COMMIT;
RETURN newid;
END copy_individual_table;

FUNCTION copy_individual_column(p_columnid MD_COLUMNS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
newid MD_COLUMNS.ID%TYPE;
newrec MD_COLUMNS%rowtype;
newtableid MD_TABLES.ID%TYPE;
BEGIN
SELECT * INTO newrec FROM md_columns WHERE id = p_columnid;
-- TODO: How do I check if this worked?
-- OK. We need to fix up table id
newtableid := find_object_copy(newrec.table_id_fk, C_OBJECTTYPE_TABLES, p_newconnectionid);

IF newtableid IS NULL THEN
newtableid := copy_individual_table(newrec.table_id_fk, p_newconnectionid);
END IF;

newrec.table_id_fk := newtableid;
-- Let the trigger work out the new id
newrec.ID := NULL;
INSERT INTO md_columns VALUES newrec RETURNING ID INTO newid;
-- Columns have their own namespace. They must be unique within the given table. So..we'll use the table id as the namespace
INSERT INTO md_derivatives(src_id, src_type, derived_id, derived_type, derived_connection_id_fk, original_identifier, new_identifier, DERIVED_OBJECT_NAMESPACE)
VALUES(p_columnid, C_OBJECTTYPE_COLUMNS, newid, C_OBJECTTYPE_COLUMNS, p_newconnectionid, newrec.column_name, newrec.column_name, C_OBJECTTYPE_COLUMNS || TO_CHAR(newtableid));
COMMIT;
RETURN newid;
END copy_individual_column;

FUNCTION copy_all_tables(p_connectionid MD_CONNECTIONS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
CURSOR all_tables_cursor is select table_id from mgv_all_tables where connection_id = p_connectionid;
v_count NUMBER := 0;
newid MD_TABLES.ID%TYPE;
BEGIN
FOR v_tableid IN all_tables_cursor LOOP
newid := copy_individual_table(v_tableid.table_id, p_newconnectionid);
v_count := v_count + 1;
END LOOP;
RETURN v_count;
END copy_all_tables;

FUNCTION copy_all_columns(p_connectionid MD_CONNECTIONS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
CURSOR all_columns_cursor is select id from MD_COLUMNS where table_id_fk in
(select table_id from MGV_ALL_TABLES where connection_id = p_connectionid);
v_count NUMBER :=0;
newid MD_COLUMNS.ID%TYPE;
BEGIN
FOR v_columnid IN all_columns_cursor LOOP
newid := copy_individual_column(v_columnid.id, p_newconnectionid);
v_count := v_count + 1;
END LOOP;
return v_count;
END copy_all_columns;

FUNCTION copy_constraint_details(p_oldconsid MD_CONSTRAINTS.ID%TYPE, p_newconsid MD_CONSTRAINTS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
CURSOR curs is SELECT * FROM MD_CONSTRAINT_DETAILS WHERE CONSTRAINT_ID_FK = p_oldconsid;
v_newid MD_CONSTRAINT_DETAILS.ID%TYPE;
v_count NUMBER := 0;
v_originalid MD_CONSTRAINT_DETAILS.ID%TYPE;
v_ret NUMBER;
BEGIN
FOR v_row IN curs LOOP
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.COLUMN_ID_FK := find_object_copy(v_row.COLUMN_ID_FK , C_OBJECTTYPE_COLUMNS, p_newconnectionid);
v_row.CONSTRAINT_ID_FK := p_newconsid;
INSERT INTO MD_CONSTRAINT_DETAILS values v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
-- Constraint details don't have an identifier, so don't need a namespace.
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK)
VALUES(v_originalid, C_OBJECTTYPE_CNSTRNT_DETAILS, v_newid, C_OBJECTTYPE_CNSTRNT_DETAILS, p_newconnectionid);
END LOOP;
return v_count;
END copy_constraint_details;

FUNCTION copy_all_constraints_cascade(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) :=
'SELECT * FROM MD_CONSTRAINTS WHERE TABLE_ID_FK IN
(SELECT SRC_ID FROM MD_DERIVATIVES WHERE SRC_TYPE = ''' || C_OBJECTTYPE_TABLES ||''' AND DERIVED_TYPE = '''
|| C_OBJECTTYPE_TABLES || ''' AND DERIVED_ID IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE SCHEMA_ID = ' || p_newschemaid || '))';
v_count NUMBER := 0;
v_newid MD_CONSTRAINTS.ID%TYPE;
v_originalid MD_CONSTRAINTS.ID%TYPE;
v_ret NUMBER;
v_row MD_CONSTRAINTS%ROWTYPE;
v_storeRefTableId MD_TABLES.ID%TYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_CONSTRAINTS, 'NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.TABLE_ID_FK := find_object_copy(v_row.TABLE_ID_FK , C_OBJECTTYPE_TABLES, p_newconnectionid);
if v_row.REFTABLE_ID_FK IS NOT NULL THEN
v_storeRefTableId := v_row.REFTABLE_ID_FK;
v_row.REFTABLE_ID_FK := find_object_copy(v_row.REFTABLE_ID_FK , C_OBJECTTYPE_TABLES, p_newconnectionid);
END IF;
INSERT INTO MD_CONSTRAINTS values v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_CONSTRAINTS, v_newid, C_OBJECTTYPE_CONSTRAINTS, p_newconnectionid, v_row.NAME, v_row.NAME, C_NS_CONSTRAINTS|| TO_CHAR(p_newschemaid));
v_ret := copy_constraint_details(v_originalid, v_newid, p_newconnectionid);
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_constraints_cascade;

FUNCTION copy_all_columns_cascade(p_oldtableid MD_TABLES.ID%TYPE, p_newtableid MD_TABLES.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_COLUMNS WHERE TABLE_ID_FK = ' || p_oldtableid;
v_originalId MD_COLUMNS.ID%TYPE;
v_newid MD_COLUMNS.ID%TYPE;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_COLUMNS%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_COLUMNS, 'COLUMN_NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.TABLE_ID_FK := p_newtableid;
INSERT INTO MD_COLUMNS values v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
-- Columns don't need a namespace as such, they must not clash within the table. We'll handle this
-- As a special case.
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, original_identifier, new_identifier, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_COLUMNS, v_newid, C_OBJECTTYPE_COLUMNS, p_newconnectionid, v_row.column_name, v_row.column_name, C_OBJECTTYPE_COLUMNS || TO_CHAR(p_newtableid));
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_columns_cascade;

FUNCTION copy_index_details(p_oldindexid MD_INDEXES.ID%TYPE, p_newindexid MD_INDEXES.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
CURSOR curs is SELECT * FROM MD_INDEX_DETAILS WHERE MD_INDEX_DETAILS.INDEX_ID_FK = p_oldindexid;
v_originalid MD_INDEX_DETAILS.ID%TYPE;
v_newid MD_INDEX_DETAILS.ID%TYPE;
v_count NUMBER := 0;
v_ret NUMBER;
BEGIN
FOR v_row IN CURS LOOP
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.INDEX_ID_FK := p_newindexid;
v_row.COLUMN_ID_FK := find_object_copy(v_row.COLUMN_ID_FK, C_OBJECTTYPE_COLUMNS, p_newconnectionid);
INSERT INTO MD_INDEX_DETAILS VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
-- Index details don't have identifiers, so don't need a namespace.
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK)
VALUES(v_originalid, C_OBJECTTYPE_INDEX_DETAILS, v_newid, C_OBJECTTYPE_INDEX_DETAILS, p_newconnectionid);
END LOOP;
RETURN v_count;
END copy_index_details;

FUNCTION copy_all_indexes(p_oldtableid MD_TABLES.ID%TYPE, p_newtableid MD_TABLES.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_filter_set MIGR_FILTER_SET) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_INDEXES WHERE MD_INDEXES.TABLE_ID_FK = ' || p_oldtableid;
v_originalid MD_INDEXES.ID%TYPE;
v_newid MD_INDEXES.ID%TYPE;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_INDEXES%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_INDEXES, 'INDEX_NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;

v_row.ID := NULL;
v_row.TABLE_ID_FK := p_newtableid;
INSERT INTO MD_INDEXES values v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_INDEXES, v_newid, C_OBJECTTYPE_INDEXES, p_newconnectionid, v_row.INDEX_NAME, v_row.INDEX_NAME, C_NS_INDEXES || p_newschemaid);
v_ret := copy_index_details(v_originalid, v_newid, p_newconnectionid);
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_indexes;

FUNCTION copy_all_table_triggers(p_oldtableid MD_TABLES.ID%TYPE, p_newtableid MD_TABLES.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_TRIGGERS WHERE MD_TRIGGERS.TABLE_OR_VIEW_ID_FK = ' || p_oldtableid;
v_originalid MD_TRIGGERS.ID%TYPE;
v_newid MD_TRIGGERS.ID%TYPE;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_TRIGGERS%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_TRIGGERS, 'TRIGGER_NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.TABLE_OR_VIEW_ID_FK := p_newtableid;
INSERT INTO MD_TRIGGERS VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_TRIGGERS, v_newid, C_OBJECTTYPE_TRIGGERS, p_newconnectionid, v_row.TRIGGER_NAME, v_row.TRIGGER_NAME, C_NS_DB_TRIGGERS);
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_table_triggers;

FUNCTION copy_all_tables_cascade(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET :=NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
/*CURSOR curs IS SELECT * FROM MD_TABLES where SCHEMA_ID_FK = p_oldschemaid; */
v_newid MD_TABLES.ID%TYPE := NULL;
v_originalid MD_TABLES.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_TABLES%ROWTYPE;
v_filt MIGR_FILTER;
v_condition VARCHAR2(4000);
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_TABLES where SCHEMA_ID_FK = ' || p_oldschemaid;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_TABLES, 'TABLE_NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.SCHEMA_ID_FK := p_newschemaid;
INSERT INTO MD_TABLES values v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_TABLES, v_newid, C_OBJECTTYPE_TABLES, p_newconnectionid, v_row.TABLE_NAME, v_row.TABLE_NAME, C_NS_SCHEMA_OBJS || TO_CHAR(p_newschemaid));
v_ret := copy_all_columns_cascade(v_originalid, v_newid, p_newconnectionid, p_filter_set);
v_ret := copy_all_indexes(v_originalid, v_newid, p_newconnectionid, p_newschemaid, p_filter_set);
v_ret := copy_all_table_triggers(v_originalid, v_newid, p_newconnectionid, p_filter_set);
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_tables_cascade;

FUNCTION copy_all_view_triggers(p_oldviewid MD_VIEWS.ID%TYPE, p_newviewid MD_VIEWS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
CURSOR curs IS SELECT * FROM MD_TRIGGERS WHERE MD_TRIGGERS.TABLE_OR_VIEW_ID_FK = p_oldviewid;
v_originalid MD_TRIGGERS.ID%TYPE;
v_newid MD_TRIGGERS.ID%TYPE;
v_count NUMBER := 0;
v_ret NUMBER;
BEGIN
FOR v_row IN curs LOOP
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.TABLE_OR_VIEW_ID_FK := p_newviewid;
INSERT INTO MD_TRIGGERS VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_TRIGGERS, v_newid, C_OBJECTTYPE_TRIGGERS, p_newconnectionid, v_row.TRIGGER_NAME, v_row.TRIGGER_NAME, C_NS_DB_TRIGGERS);
END LOOP;
return v_count;
END copy_all_view_triggers;

FUNCTION copy_all_views_cascade(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_VIEWS WHERE SCHEMA_ID_FK = ' || p_oldschemaid;
v_newid MD_VIEWS.ID%TYPE := NULL;
v_originalid MD_VIEWS.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_VIEWS%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_VIEWS, 'VIEW_NAME' ,'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs into v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.SCHEMA_ID_FK := p_newschemaid;
INSERT INTO MD_VIEWS VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_VIEWS, v_newid, C_OBJECTTYPE_VIEWS, p_newconnectionid, v_row.VIEW_NAME, v_row.VIEW_NAME, C_NS_SCHEMA_OBJS || TO_CHAR(p_newschemaid));
v_ret := copy_all_view_triggers(v_originalid, v_newid, p_newconnectionid);
END LOOP;
CLOSE cv_curs;
RETURN v_count;
END copy_all_views_cascade;

FUNCTION copy_group_members(p_oldgroupid MD_GROUPS.ID%TYPE, p_newgroupid MD_GROUPS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
CURSOR curs IS SELECT * FROM MD_GROUP_MEMBERS WHERE GROUP_ID_FK = p_oldgroupid;
v_newid MD_GROUP_MEMBERS.ID%TYPE := NULL;
v_originalid MD_GROUP_MEMBERS.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
BEGIN
FOR v_row IN curs LOOP
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.GROUP_ID_FK := p_newgroupid;
v_row.USER_ID_FK := find_object_copy(v_row.USER_ID_FK, C_OBJECTTYPE_USERS, p_newconnectionid);
INSERT INTO MD_GROUP_MEMBERS VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
-- Group members do not have identifiers, so don't need a namespace
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK)
VALUES(v_originalid, C_OBJECTTYPE_GROUP_MEMBERS, v_newid, C_OBJECTTYPE_GROUP_MEMBERS, p_newconnectionid);
END LOOP;
return v_count;
END copy_group_members;

FUNCTION copy_all_groups_cascade(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_GROUPS WHERE SCHEMA_ID_FK = ' || p_oldschemaid;
v_newid MD_GROUPS.ID%TYPE := NULL;
v_originalid MD_GROUPS.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
v_namespace MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE := NULL;
v_row MD_GROUPS%ROWTYPE;
v_catalogname MD_CATALOGS.CATALOG_NAME%TYPE;
v_catalogdummy MD_CATALOGS.DUMMY_FLAG%TYPE;
v_oldname MD_GROUPS.GROUP_NAME%TYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_GROUPS, 'GROUP_NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.SCHEMA_ID_FK := p_newschemaid;
SELECT CATALOG_NAME, DUMMY_FLAG INTO v_catalogname, v_catalogdummy
FROM MD_CATALOGS, MD_SCHEMAS WHERE MD_CATALOGS.ID = MD_SCHEMAS.CATALOG_ID_FK
AND MD_SCHEMAS.ID = p_oldschemaid;
v_oldname := v_row.GROUP_NAME;
if v_catalogdummy <> C_DUMMYFLAG_TRUE then
v_row.GROUP_NAME := v_row.GROUP_NAME || '_' || v_catalogname;
END IF;
INSERT INTO MD_GROUPS values v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
IF v_row.GROUP_FLAG = C_ROLE_FLAG THEN
v_namespace := C_NS_USER_ROLES;
ELSE
v_namespace := C_NS_DATABASE;
END IF;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_GROUPS, v_newid, C_OBJECTTYPE_GROUPS, p_newconnectionid, v_oldname, v_row.GROUP_NAME, v_namespace);
v_ret := copy_group_members(v_originalid, v_newid, p_newconnectionid);
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_groups_cascade;

FUNCTION copy_all_users_cascade(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_USERS WHERE SCHEMA_ID_FK = ' || p_oldschemaid;
v_newid MD_USERS.ID%TYPE := NULL;
v_originalid MD_USERS.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_USERS%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_USERS, 'USERNAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.SCHEMA_ID_FK := p_newschemaid;
INSERT INTO MD_USERS VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_USERS, v_newid, C_OBJECTTYPE_USERS, p_newconnectionid, v_row.USERNAME, v_row.USERNAME, C_NS_USERS);
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_users_cascade;

FUNCTION copy_all_other_objects_cascade(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_OTHER_OBJECTS WHERE SCHEMA_ID_FK = ' || p_oldschemaid;
v_newid MD_OTHER_OBJECTS.ID%TYPE := NULL;
v_originalid MD_OTHER_OBJECTS.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_OTHER_OBJECTS%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_OTHER_OBJECTS, 'NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.SCHEMA_ID_FK := p_newschemaid;
INSERT INTO MD_OTHER_OBJECTS VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_OTHER_OBJECTS, v_newid, C_OBJECTTYPE_OTHER_OBJECTS, p_newconnectionid, v_row.NAME, v_row.NAME, C_NS_SCHEMA_OBJS || TO_CHAR(p_newschemaid));
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_other_objects_cascade;

FUNCTION copy_all_tablespaces_cascade(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_TABLESPACES WHERE SCHEMA_ID_FK = ' || p_oldschemaid;
v_newid MD_TABLESPACES.ID%TYPE := NULL;
v_originalid MD_TABLESPACES.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_TABLESPACES%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_TABLESPACES, 'TABLESPACE_NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.SCHEMA_ID_FK := p_newschemaid;
INSERT INTO MD_TABLESPACES VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_TABLESPACES, v_newid, C_OBJECTTYPE_TABLESPACES, p_newconnectionid, v_row.TABLESPACE_NAME, v_row.TABLESPACE_NAME, C_NS_TABLESPACES);
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_tablespaces_cascade;

FUNCTION copy_all_udds_cascade(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_USER_DEFINED_DATA_TYPES WHERE SCHEMA_ID_FK = ' || p_oldschemaid;
v_newid MD_USER_DEFINED_DATA_TYPES.ID%TYPE := NULL;
v_originalid MD_USER_DEFINED_DATA_TYPES.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_USER_DEFINED_DATA_TYPES%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_UDDT, 'DATA_TYPE_NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.SCHEMA_ID_FK := p_newschemaid;
INSERT INTO MD_USER_DEFINED_DATA_TYPES VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_UDDT, v_newid, C_OBJECTTYPE_UDDT, p_newconnectionid, v_row.DATA_TYPE_NAME, v_row.DATA_TYPE_NAME, C_NS_SCHEMA_OBJS || TO_CHAR(p_newschemaid));
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_udds_cascade;

FUNCTION copy_child_procedures(p_oldpackageid MD_PACKAGES.ID%TYPE, p_newpackageid MD_PACKAGES.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_STORED_PROGRAMS WHERE PACKAGE_ID_FK = ' || p_oldpackageid;
v_newid MD_STORED_PROGRAMS.ID%TYPE := NULL;
v_originalid MD_STORED_PROGRAMS.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_STORED_PROGRAMS%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_STORED_PROGRAMS, 'NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.PACKAGE_ID_FK := p_newpackageid;
v_row.SCHEMA_ID_FK := p_newschemaid;
INSERT INTO MD_STORED_PROGRAMS VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
-- No need for namespace here, the namespace is the package itself.
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER)
VALUES(v_originalid, C_OBJECTTYPE_STORED_PROGRAMS, v_newid, C_OBJECTTYPE_STORED_PROGRAMS, p_newconnectionid, v_row.NAME, v_row.NAME);
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_child_procedures;

FUNCTION copy_all_packages_cascade(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_PACKAGES WHERE SCHEMA_ID_FK = ' || p_oldschemaid;
v_newid MD_PACKAGES.ID%TYPE := NULL;
v_originalid MD_PACKAGES.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_PACKAGES%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_PACKAGES, 'NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.SCHEMA_ID_FK := p_newschemaid;
INSERT INTO MD_PACKAGES VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_PACKAGES, v_newid, C_OBJECTTYPE_PACKAGES, p_newconnectionid, v_row.NAME, v_row.NAME, C_NS_SCHEMA_OBJS || TO_CHAR(p_newschemaid));
v_ret := copy_child_procedures(v_originalid, v_newid, p_newschemaid, p_newconnectionid, p_filter_set);
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_packages_cascade;

FUNCTION copy_all_unpackaged_sps(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_STORED_PROGRAMS WHERE SCHEMA_ID_FK = ' || p_oldschemaid ||' AND PACKAGE_ID_FK IS NULL';
v_newid MD_STORED_PROGRAMS.ID%TYPE := NULL;
v_originalid MD_STORED_PROGRAMS.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_STORED_PROGRAMS%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_STORED_PROGRAMS, 'NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.schema_id_fk := p_newschemaid;
INSERT INTO MD_STORED_PROGRAMS VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
-- Non-packaged procedures belong in the schema objects namespace.
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_STORED_PROGRAMS, v_newid, C_OBJECTTYPE_STORED_PROGRAMS, p_newconnectionid, v_row.NAME, v_row.NAME, C_NS_SCHEMA_OBJS || TO_CHAR(p_newschemaid));
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_unpackaged_sps;

FUNCTION copy_all_synonyms_cascade(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_SYNONYMS WHERE SCHEMA_ID_FK = ' || p_oldschemaid;
v_newid MD_SYNONYMS.ID%TYPE := NULL;
v_originalid MD_SYNONYMS.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
v_namespace MD_DERIVATIVES.DERIVED_OBJECT_NAMESPACE%TYPE;
v_row MD_SYNONYMS%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_SYNONYMS, 'NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.SYNONYM_FOR_ID := find_object_copy(v_row.SYNONYM_FOR_ID, v_row.FOR_OBJECT_TYPE, p_newconnectionid);
INSERT INTO MD_SYNONYMS VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
-- Synonyms have two potential name spaces: Private synonyms belong in the schema objects, while public
-- synonyms belong in their own namespace.
IF v_row.PRIVATE_VISIBILITY = C_SYNONYM_PRIVATE THEN
v_namespace := C_NS_SCHEMA_OBJS || TO_CHAR(p_newschemaid);
ELSE
v_namespace := C_NS_PUBLIC_SYNONYMS;
END IF;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_SYNONYMS, v_newid, C_OBJECTTYPE_SYNONYMS, p_newconnectionid, v_row.NAME, v_row.NAME, v_namespace);
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_synonyms_cascade;

FUNCTION copy_all_sequences_cascade(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_SEQUENCES WHERE SCHEMA_ID_FK = ' || p_oldschemaid;
v_newid MD_SEQUENCES.ID%TYPE := NULL;
v_originalid MD_SEQUENCES.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_SEQUENCES%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_SEQUENCES, 'NAME', 'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
INSERT INTO MD_SEQUENCES VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, derived_connection_id_fk, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_SEQUENCES, v_newid, C_OBJECTTYPE_SEQUENCES, p_newconnectionid, v_row.NAME, v_row.NAME, C_NS_SCHEMA_OBJS || TO_CHAR(p_newschemaid));
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_all_sequences_cascade;

FUNCTION copy_user_privileges(p_olduserid MD_PRIVILEGES.ID%TYPE, p_newuserid MD_PRIVILEGES.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
CURSOR curs is SELECT * FROM MD_USER_PRIVILEGES WHERE PRIVILEGE_ID_FK = p_olduserid;
v_newid MD_USER_PRIVILEGES.ID%TYPE;
v_count NUMBER := 0;
v_originalid MD_USER_PRIVILEGES.ID%TYPE;
v_ret NUMBER;
BEGIN
FOR v_row IN curs LOOP
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.USER_ID_FK := find_object_copy(v_row.USER_ID_FK , C_OBJECTTYPE_USERS, p_newconnectionid);
v_row.PRIVILEGE_ID_FK := p_newuserid;
INSERT INTO MD_USER_PRIVILEGES values v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK)
VALUES(v_originalid, C_OBJECTTYPE_USER_PRIVILEGES, v_newid, C_OBJECTTYPE_USER_PRIVILEGES, p_newconnectionid);
END LOOP;
return v_count;
END copy_user_privileges;

FUNCTION copy_all_privileges_cascade(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_PRIVILEGES WHERE SCHEMA_ID_FK = ' || p_oldschemaid;
v_newid MD_PRIVILEGES.ID%TYPE := NULL;
v_originalid MD_PRIVILEGES.ID%TYPE := NULL;
v_count NUMBER := 0;
v_ret NUMBER;
v_row MD_PRIVILEGES%ROWTYPE;
BEGIN
v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_PRIVILEGES, 'PRIVILEGE_NAME' ,'ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs into v_row;
EXIT WHEN cv_curs%NOTFOUND;
v_originalid := v_row.ID;
v_row.ID := NULL;
v_row.PRIVELEGE_OBJECT_ID := find_object_copy(v_row.PRIVELEGE_OBJECT_ID , v_row.PRIVELEGEOBJECTTYPE, p_newconnectionid);
v_row.SCHEMA_ID_FK := p_newschemaid;
INSERT INTO MD_PRIVILEGES VALUES v_row RETURNING ID INTO v_newid;
v_ret := copy_additional_properties(v_originalid, v_newid, p_newconnectionid);
v_count := v_count + 1;
-- No need to pass on the identifiers to the derivatives as no need to worry about the clashes for the same.
INSERT INTO MD_DERIVATIVES(src_id, src_type, derived_id, derived_type, DERIVED_CONNECTION_ID_FK, DERIVED_OBJECT_NAMESPACE)
VALUES(v_originalid, C_OBJECTTYPE_PRIVILEGES, v_newid, C_OBJECTTYPE_PRIVILEGES, p_newconnectionid, C_NS_SCHEMA_OBJS || TO_CHAR(p_newschemaid));
v_ret := copy_user_privileges(v_originalid, v_newid, p_newconnectionid);
END LOOP;
CLOSE cv_curs;
RETURN v_count;
END copy_all_privileges_cascade;

FUNCTION copy_all_cross_schema_objects(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
v_ret NUMBER;
BEGIN
-- DD; Can't do this until all schema tables are done
-- There may be foreign keys between schema
v_ret := copy_all_constraints_cascade(p_oldschemaid, p_newschemaid, p_newconnectionid, p_filter_set);
v_ret := copy_all_groups_cascade(p_oldschemaid, p_newschemaid, p_newconnectionid, p_filter_set);
v_ret := copy_all_other_objects_cascade(p_oldschemaid, p_newschemaid, p_newconnectionid, p_filter_set);
v_ret := copy_all_privileges_cascade(p_oldschemaid, p_newschemaid, p_newconnectionid, p_filter_set);
-- Do synonyms last: This way, we can be sure that the oject for which it is a synonym
-- has already been copied.
v_ret := copy_all_synonyms_cascade(p_oldschemaid, p_newschemaid, p_newconnectionid, p_filter_set);
return v_ret;
END copy_all_cross_schema_objects;

FUNCTION copy_all_schema_objects(p_oldschemaid MD_SCHEMAS.ID%TYPE, p_newschemaid MD_SCHEMAS.ID%TYPE, p_newconnectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL) RETURN NUMBER
IS
v_ret NUMBER;
BEGIN
v_ret := copy_all_tables_cascade(p_oldschemaid, p_newschemaid, p_newconnectionid, p_filter_set);
v_ret := copy_all_views_cascade(p_oldschemaid, p_newschemaid, p_newconnectionid, p_filter_set);
v_ret := copy_all_users_cascade(p_oldschemaid, p_newschemaid, p_newconnectionid, p_filter_set);
v_ret := copy_all_tablespaces_cascade(p_oldschemaid, p_newschemaid, p_newconnectionid, p_filter_set);
v_ret := copy_all_udds_cascade(p_oldschemaid, p_newschemaid, p_newconnectionid, p_filter_set);
v_ret := copy_all_packages_cascade(p_oldschemaid, p_newschemaid, p_newconnectionid, p_filter_set);
v_ret := copy_all_unpackaged_sps(p_oldschemaid, p_newschemaid, p_newconnectionid, p_filter_set);
v_ret := copy_all_sequences_cascade(p_oldschemaid, p_newschemaid, p_newconnectionid, p_filter_set);
-- TODO: Roles are wrong in the model right now. I need to fix these up.
--v_ret := copy_all_roles_cascade(p_oldschemaid, p_newschemaid);
return v_ret;
END copy_all_schema_objects;

FUNCTION copy_catalogs_cascade(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_catalogid MD_CATALOGS.ID%TYPE,
p_newcatalogid MD_CATALOGS.ID%TYPE,
p_newconnectionid MD_CONNECTIONS.ID%TYPE,
p_filter_set MIGR_FILTER_SET :=NULL) RETURN NUMBER
IS
cv_curs REF_CURSOR;
v_newid NUMBER;
v_count NUMBER := 0;
v_ret NUMBER;
v_newName MD_SCHEMAS.NAME%TYPE;
v_filt MIGR_FILTER;
v_selectStmt VARCHAR2(4000) := 'SELECT a.id schema_id, A.name schema_name, b.id catalog_id, B.CATALOG_NAME, B.DUMMY_FLAG, A.type, A.character_set, A.version_tag
FROM MD_SCHEMAS A, MD_CATALOGS B
WHERE
A.CATALOG_ID_FK = B.ID
AND B.ID =' || p_catalogid ||
' AND CONNECTION_ID_FK = ' || p_connectionid ;
-- v_schemaid MD_SCHEMAS.ID%TYPE;
-- v_schemaname MD_SCHEMAS.NAME%TYPE;
-- v_catalogid MD_CATALOGS.ID%TYPE;
-- v_catalogname MD_CATALOGS.CATALOG_NAME%TYPE;
-- v_catalogdummy MD_CATALOGS.DUMMY_FLAG%TYPE;
-- v_schematype MD_SCHEMAS.TYPE%TYPE;
-- v_schemacharset MD_SCHEMAS.CHARACTER_SET%TYPE;
-- v_schemaversiontag MD_SCHEMAS.VERSION_TAG%TYPE;

v_derivedRec DERIVATIVE_REC;
v_derivedRec2 DERIVATIVE_REC2;
BEGIN
--v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_CATALOGS, 'B.CATALOG_NAME', 'B.ID', v_selectStmt);
-- NOTE: May need to apply a schema filter here too
--v_selectStmt := apply_filter(p_filter_set, C_OBJECTTYPE_SCHEMAS, 'A.NAME', 'A.ID', v_selectStmt);
OPEN cv_curs FOR v_selectStmt;
LOOP
--FETCH cv_curs INTO v_schemaid, v_schemaname, v_catalogid, v_catalogname, v_catalogdummy, v_schematype, v_schemacharset, v_schemaversiontag;
FETCH cv_curs INTO v_derivedRec;
EXIT WHEN cv_curs%NOTFOUND;

/*
schema_id NUMBER,
schema_name VARCHAR2(4000 BYTE),
catalog_id NUMBER,
catalog_name VARCHAR2(4000 BYTE),
dummy_flag CHAR(1 BYTE),
character_set VARCHAR2(4000 BYTE),
version_tag VARCHAR2(40 BYTE)

*/
-- TODO: Handle wrapping here.
if v_derivedRec.dummy_flag <> C_DUMMYFLAG_TRUE then
v_newName := v_derivedRec.schema_name || '_' || v_derivedRec.catalog_name;
else
v_newName := v_derivedRec.schema_name;
end if;
INSERT INTO MD_SCHEMAS(CATALOG_ID_FK, NAME, TYPE, CHARACTER_SET, VERSION_TAG)
VALUES (p_newcatalogid, v_newName, v_derivedRec.cap_type, v_derivedRec.character_set, v_derivedRec.version_tag)
RETURNING ID INTO v_newid;
-- Here's and interesting situation. What will we do with the additional properties?
-- I can coalesce them such that they are in the condensed catalog/schema pair
-- But their order could (will) contain duplicates.....
v_ret := copy_additional_properties(p_catalogid, v_newid, p_newconnectionid);
v_ret := copy_additional_properties(v_derivedRec.schema_id, v_newid, p_newconnectionid);
-- No Need for namespace stuff for catalogs.
INSERT INTO MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER)
VALUES (v_derivedRec.schema_id, C_OBJECTTYPE_SCHEMAS, v_newid, C_OBJECTTYPE_SCHEMAS, p_newconnectionid, v_derivedRec.schema_name, v_newName);
INSERT INTO MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER)
VALUES (v_derivedRec.catalog_id, C_OBJECTTYPE_CATALOGS, v_newid, C_OBJECTTYPE_SCHEMAS, p_newconnectionid, v_derivedRec.catalog_name, v_newName);
-- TODO: ADD THE FILTER TO THE PARAMETERS BELOW
v_ret := copy_all_schema_objects(v_derivedRec.schema_id, v_newid, p_newconnectionid, p_filter_set);
v_count := v_count + 1;
v_newName :='';
END LOOP;
CLOSE cv_curs;
-- Now...Once all of the schema objects have been done, we have to copy all of those objects that could cross
-- schema boundaries. So we need to loop through them again
v_selectStmt := 'SELECT SRC_ID, DERIVED_ID FROM MD_DERIVATIVES WHERE SRC_TYPE = '
|| '''' || C_OBJECTTYPE_SCHEMAS || ''' AND DERIVED_TYPE = ''' || C_OBJECTTYPE_SCHEMAS ||''''
--|| ' AND DERIVED_CONNECTION_ID_FK = ' || p_newconnectionid
|| ' AND DERIVED_ID IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CATALOG_ID = ' || p_newcatalogid || ' AND CONNECTION_ID = ' || p_newconnectionid || ')';
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs into v_derivedRec2;
EXIT when cv_curs%NOTFOUND;
v_ret := copy_all_cross_schema_objects(v_derivedRec2.schemaid, v_derivedRec2.newid, p_newconnectionid, p_filter_set);
END LOOP;
CLOSE cv_curs;
return v_count;
END copy_catalogs_cascade;

FUNCTION remove_duplicate_indexes(p_connectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
CURSOR v_curs IS select index_id_fk, sum(md_index_details.column_id_fk * md_index_details.detail_order) simplehash from md_index_details
where index_id_fk in (select id from md_indexes where table_id_fk in (select table_id from mgv_all_tables where connection_id = p_connectionid))
group by index_id_fk
order by simplehash, index_id_fk;
v_lasthash NUMBER :=0;
v_currenthash NUMBER :=0;
v_currentid MD_INDEX_DETAILS.INDEX_ID_FK%TYPE;
v_lastid MD_INDEX_DETAILS.INDEX_ID_FK%TYPE;
v_count NUMBER := 0;
v_sql VARCHAR(255);
BEGIN
OPEN v_curs;
LOOP
FETCH v_curs into v_currentid, v_currenthash;
EXIT WHEN v_curs%NOTFOUND;
if v_currenthash = v_lasthash THEN
-- dbms_output.put_line('Index ' || TO_CHAR(v_currentid) || ' is a duplicate');
v_sql := 'DELETE FROM MD_INDEXES WHERE ID = ' || v_currentid;
EXECUTE IMMEDIATE v_sql;
--dbms_output.put_line('DELETE FROM MD_INDEXES WHERE ID = ' || v_currentid);
v_sql := 'UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = ''DUPIND'', DERIVED_ID = ' || TO_CHAR(v_lastid) || ' WHERE DERIVED_ID = ' || TO_CHAR(v_currentid);
EXECUTE IMMEDIATE v_sql;
-- dbms_output.put_line('UPDATE MD_DERIVATIVES SET DERIVED_ID = ' || TO_CHAR(v_lastid) || ' WHERE DERIVED_ID = ' || TO_CHAR(v_currentid));
v_count := v_count + 1;
else
v_lasthash := v_currenthash;
v_lastid := v_currentid;
end if;
END LOOP;
CLOSE v_curs;
return v_count;
END remove_duplicate_indexes;

FUNCTION remove_indexes_used_elsewhere(p_connectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
CURSOR v_curs IS
select INDEX_ID_FK from
(select index_id_fk, sum(md_index_details.column_id_fk * md_index_details.detail_order) simplehash from md_index_details
where index_id_fk in (select id from md_indexes where table_id_fk in (select table_id from mgv_all_tables where connection_id = p_connectionid))
group by index_id_fk
order by simplehash) a
WHERE A.SIMPLEHASH
IN
(
SELECT b.simplehash FROM
(
SELECT SUM(MD_CONSTRAINT_DETAILS.COLUMN_ID_FK * MD_CONSTRAINT_DETAILS.DETAIL_ORDER) simplehash from md_constraint_details
where constraint_id_fk in (select id from md_constraints where table_id_fk in (select table_id from mgv_all_tables where connection_id = p_connectionid))
group by constraint_id_fk
order by simplehash
) b
);
v_currentId MD_INDEX_DETAILS.INDEX_ID_FK%TYPE;
v_sql VARCHAR2(255);
v_count NUMBER := 0;
BEGIN
OPEN v_curs;
LOOP
FETCH v_curs into v_currentid;
EXIT WHEN v_curs%NOTFOUND;
v_sql := 'DELETE FROM MD_INDEXES WHERE ID = ' || v_currentid;
EXECUTE IMMEDIATE v_sql;
--dbms_output.put_line('DELETE FROM MD_INDEXES WHERE ID = ' || v_currentid);
v_sql := 'DELETE FROM MD_DERIVATIVES WHERE DERIVED_ID = ' || TO_CHAR(v_currentid);
EXECUTE IMMEDIATE v_sql;
-- dbms_output.put_line('UPDATE MD_DERIVATIVES SET DERIVED_ID = ' || TO_CHAR(v_lastid) || ' WHERE DERIVED_ID = ' || TO_CHAR(v_currentid));
v_count := v_count + 1;
END LOOP;
CLOSE v_curs;
RETURN v_count;
END remove_indexes_used_elsewhere;

PROCEDURE cut_lob_indexes_to_25(p_connectionId MD_CONNECTIONS.ID%TYPE)
IS
CURSOR v_curs (context MD_ADDITIONAL_PROPERTIES.VALUE%TYPE, ctxcat MD_ADDITIONAL_PROPERTIES.VALUE%TYPE) is
SELECT * FROM MD_INDEXES WHERE
TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid)
AND LENGTH(INDEX_NAME) > 25 AND
( EXISTS (SELECT 1 FROM MD_ADDITIONAL_PROPERTIES WHERE ( VALUE = context
OR VALUE = ctxcat ) AND REF_ID_FK = MD_INDEXES.ID ) )
FOR UPDATE OF INDEX_NAME;
v_numIndexCount INTEGER := 1;
v_newName MD_INDEXES.INDEX_NAME%TYPE;
v_row MD_INDEXES%ROWTYPE;
BEGIN
-- totierne: for each lob index cut to 23 or 22 or 21 to put _XXX up to 25 chars (should be bytes)
OPEN v_curs (C_INDEXTYPE_CONTEXT, C_INDEXTYPE_CTXCAT);
LOOP
FETCH v_curs INTO v_row;
EXIT WHEN v_curs%NOTFOUND;
v_newName := MIGRATION_TRANSFORMER.add_suffix(v_row.INDEX_NAME, '_' || TO_CHAR(v_numIndexCount), 25);
update MD_INDEXES SET index_name = v_newName where current of v_curs;
v_numIndexCount := v_numIndexCount + 1;
END LOOP;
CLOSE v_curs;
commit;
END cut_lob_indexes_to_25;

FUNCTION fixupTextIndexes(p_connectionId MD_CONNECTIONS.ID%TYPE) return NUMBER
IS
CURSOR v_curs is
select index_id_fk, count(*) numcols from md_index_details where
index_id_fk in (
select c.id
from md_columns a, md_index_details b, md_indexes c
where b.column_id_fk = a.id
and column_type in ('BLOB', 'CLOB')
and b.index_id_fk = c.id
and c.table_id_fk in (select table_id from mgv_all_tables where connection_id = p_connectionid)
) group by index_id_fk;
v_indexId MD_INDEXES.ID%TYPE;
v_numCols INTEGER;
v_extendedIndexType MD_ADDITIONAL_PROPERTIES.VALUE%TYPE;
BEGIN
OPEN v_curs;
LOOP
FETCH v_curs into v_indexId, v_numCols;
EXIT WHEN v_curs%NOTFOUND;
IF v_numCols = 1 THEN
v_extendedIndexType := C_INDEXTYPE_CONTEXT;
ELSE
v_extendedIndexType := C_INDEXTYPE_CTXCAT;
END IF;
INSERT INTO MD_ADDITIONAL_PROPERTIES(CONNECTION_ID_FK ,REF_ID_FK, REF_TYPE, PROP_KEY, VALUE)
VALUES (p_connectionId, v_indexId, C_OBJECTTYPE_INDEXES, C_PROPKEY_EXTENDEDINDEXTYPE, v_extendedIndexType);
COMMIT;
END LOOP;
-- NCLOBs cannot be indexed. They aren't allowed in normal indexes, and they aren't allowed in TEXT
-- indexes. The only thing to do here is to remove it.
-- TODO: We can't just do this silently.
-- Mark THE derivative RECORD AS DELETEd.
UPDATE md_derivatives SET DERIVATIVE_REASON = 'NCLOBIND' WHERE DERIVED_TYPE = 'MD_INDEXES' AND DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_ID IN
(SELECT C.ID FROM MD_COLUMNS A, MD_INDEX_DETAILS B, MD_INDEXES C, MGV_ALL_TABLES D
WHERE B.COLUMN_ID_FK = A.ID AND COLUMN_TYPE ='NCLOB' AND B.INDEX_ID_FK = C.ID
AND C.TABLE_ID_FK = D.TABLE_ID AND D.CONNECTION_ID = p_connectionid);
DELETE FROM MD_INDEXES WHERE ID IN
(SELECT C.ID FROM MD_COLUMNS A, MD_INDEX_DETAILS B, MD_INDEXES C, MGV_ALL_TABLES D
WHERE B.COLUMN_ID_FK = A.ID AND COLUMN_TYPE ='NCLOB' AND B.INDEX_ID_FK = C.ID
AND C.TABLE_ID_FK = D.TABLE_ID AND D.CONNECTION_ID = p_connectionid);
-- cut blob/clob index string to 25 characters with _nn incrementing marker
cut_lob_indexes_to_25(p_connectionId);
CLOSE v_curs;
return 0;
END fixupTextIndexes;

PROCEDURE createDummyScrTblPerSchema_ee(schemaId MD_SCHEMAS."ID"%TYPE,
new_schemaId MD_SCHEMAS."ID"%TYPE,
p_scratchConn MD_CONNECTIONS."ID"%TYPE)
IS
v_qualified_native_name VARCHAR2(300);
n_newtblid NUMBER;
tbltrigRec MD_TRIGGERS%ROWTYPE;
n_newtrigId MD_TRIGGERS."ID"%TYPE;
origtrigId MD_TRIGGERS."ID"%TYPE;
CURSOR curtblTrig(schId MD_SCHEMAS."ID"%TYPE) IS SELECT * FROM MD_TRIGGERS
WHERE TRIGGER_ON_FLAG = 'T'
AND TABLE_OR_VIEW_ID_FK IN (
SELECT "ID"
FROM MD_TABLES
WHERE SCHEMA_ID_FK = schId);

BEGIN
SELECT A.catalog_name || '.' || B."NAME" || 'DUMMY' INTO v_qualified_native_name
FROM MD_CATALOGS A, MD_SCHEMAS B
WHERE A."ID" = B.catalog_id_fk
AND B."ID" = schemaId;

-- insert 1 DUMMY table per schema. We don't want to create peer records in md_tables for each table entry
INSERT INTO MD_TABLES(schema_id_fk, table_name, qualified_native_name)
VALUES(new_schemaId, 'DUMMY', v_qualified_native_name)
RETURNING "ID" INTO n_newtblid;
-- There is no additional property to copy as this is a dummy table with no src peer
-- This table is used to attached all the translated triggers

-- insert corresponding row into md_derivatives
INSERT INTO MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER)
VALUES (n_newtblid, C_OBJECTTYPE_TABLES, n_newtblId, C_OBJECTTYPE_TABLES, p_scratchConn, 'DUMMY', 'DUMMY');

--copy_all_tbl_trigs_ee
OPEN curtblTrig(schemaId);
FETCH curtblTrig INTO tbltrigRec;
LOOP
EXIT WHEN curtblTrig%NOTFOUND;
origtrigId := tbltrigRec."ID";
tbltrigRec."ID" := NULL;
tbltrigRec.table_or_view_id_fk := n_newtblid;
INSERT INTO MD_TRIGGERS VALUES tbltrigRec RETURNING "ID" INTO n_newtrigId;

-- insert corresponding row into md_derivatives
INSERT INTO MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER)
VALUES (origtrigId, C_OBJECTTYPE_TRIGGERS, n_newtrigId, C_OBJECTTYPE_TRIGGERS, p_scratchConn, tbltrigRec.TRIGGER_NAME, tbltrigRec.TRIGGER_NAME);


FETCH curtblTrig INTO tbltrigRec;
END LOOP;
CLOSE curtblTrig;

END createDummyScrTblPerSchema_ee;

PROCEDURE copy_all_views_ee(schemaId MD_SCHEMAS."ID"%TYPE,
new_schemaId MD_SCHEMAS."ID"%TYPE,
p_scratchConn MD_CONNECTIONS."ID"%TYPE)
IS
CURSOR curViews(schId MD_SCHEMAS."ID"%TYPE) IS SELECT * FROM MD_VIEWS WHERE SCHEMA_ID_FK = schId;
viewRec MD_VIEWS%ROWTYPE;
n_newVwid MD_VIEWS."ID"%TYPE;
norigVwid MD_VIEWS."ID"%TYPE;
n_ret NUMBER;

vwtrigRec MD_TRIGGERS%ROWTYPE;
n_newtrigId MD_TRIGGERS."ID"%TYPE;
origtrigId MD_TRIGGERS."ID"%TYPE;
CURSOR curvwTrig(schId MD_SCHEMAS."ID"%TYPE) IS SELECT * FROM MD_TRIGGERS
WHERE TRIGGER_ON_FLAG = 'V'
AND TABLE_OR_VIEW_ID_FK IN (
SELECT "ID"
FROM MD_TABLES
WHERE SCHEMA_ID_FK = schId);
BEGIN
OPEN curViews(schemaId);
FETCH curViews INTO viewRec;
LOOP
EXIT WHEN curViews%NOTFOUND;
norigVwid := viewRec."ID";
viewRec."ID" := NULL;
viewRec.SCHEMA_ID_FK := new_schemaId;
INSERT INTO MD_VIEWS VALUES viewRec RETURNING "ID" INTO n_newVwId;
n_ret := copy_additional_properties(viewRec."ID", n_newVwId, p_scratchConn);

INSERT INTO MD_DERIVATIVES(src_id,
src_type,
derived_id,
derived_type,
DERIVED_CONNECTION_ID_FK,
ORIGINAL_IDENTIFIER,
NEW_IDENTIFIER,
DERIVED_OBJECT_NAMESPACE)
VALUES(norigVwid,
C_OBJECTTYPE_VIEWS,
n_newVwId,
C_OBJECTTYPE_VIEWS,
p_scratchConn, viewRec.VIEW_NAME, viewRec.VIEW_NAME, C_NS_SCHEMA_OBJS || TO_CHAR(new_schemaId));

-- Handle view triggers
OPEN curvwTrig(schemaId);
FETCH curvwTrig INTO vwtrigRec;
LOOP
EXIT WHEN curvwTrig%NOTFOUND;
origtrigId := vwtrigRec."ID";
vwtrigRec."ID" := NULL;
vwtrigRec.table_or_view_id_fk := n_newVwId;

INSERT INTO MD_TRIGGERS VALUES vwtrigRec RETURNING "ID" INTO n_newtrigId;

INSERT INTO MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER)
VALUES (origtrigId, C_OBJECTTYPE_TRIGGERS, n_newtrigId, C_OBJECTTYPE_TRIGGERS, p_scratchConn, vwtrigRec.TRIGGER_NAME, vwtrigRec.TRIGGER_NAME);

FETCH curvwTrig INTO vwtrigRec;
END LOOP; -- end vw trigger loop
CLOSE curvwTrig;

FETCH curViews INTO viewRec;
--copy_all_tbl_trigs_ee
END LOOP; -- end vw loop
CLOSE curViews;
END copy_all_views_ee;

PROCEDURE copy_all_unpackaged_sps_ee(schemaId MD_SCHEMAS."ID"%TYPE,
new_schemaId MD_SCHEMAS."ID"%TYPE,
p_scratchConn MD_CONNECTIONS."ID"%TYPE)
IS
CURSOR curSps(schId MD_SCHEMAS."ID"%TYPE) IS SELECT * FROM MD_STORED_PROGRAMS WHERE SCHEMA_ID_FK = schId;
spRec MD_STORED_PROGRAMS%ROWTYPE;
n_newSpid MD_STORED_PROGRAMS."ID"%TYPE;
norigSpid MD_STORED_PROGRAMS."ID"%TYPE;
n_ret NUMBER;
BEGIN
OPEN curSps(schemaId);
FETCH curSps INTO spRec;
LOOP
EXIT WHEN curSps%NOTFOUND;
norigSpid := spRec."ID";
spRec."ID" := NULL;
spRec.schema_id_fk := new_schemaId;

INSERT INTO MD_STORED_PROGRAMS VALUES spRec RETURNING "ID" INTO n_newSpid;
n_ret := copy_additional_properties(spRec."ID", n_newSpid, p_scratchConn);

INSERT INTO MD_DERIVATIVES(src_id,
src_type,
derived_id,
derived_type,
DERIVED_CONNECTION_ID_FK,
ORIGINAL_IDENTIFIER,
NEW_IDENTIFIER,
DERIVED_OBJECT_NAMESPACE)
VALUES(norigSpid,
C_OBJECTTYPE_STORED_PROGRAMS,
n_newSpid,
C_OBJECTTYPE_STORED_PROGRAMS,
p_scratchConn, spRec."NAME", spRec."NAME", C_NS_SCHEMA_OBJS || TO_CHAR(new_schemaId));
FETCH curSps INTO spRec;
END LOOP;
CLOSE curSps;
END copy_all_unpackaged_sps_ee;

PROCEDURE copy_all_tbl_trigs_ee(schemaId MD_SCHEMAS."ID"%TYPE,
new_schemaId MD_SCHEMAS."ID"%TYPE,
p_scratchConn MD_CONNECTIONS."ID"%TYPE)
IS
BEGIN
NULL;
END copy_all_tbl_trigs_ee;

PROCEDURE copy_all_vw_trigs_ee(schemaId MD_SCHEMAS."ID"%TYPE,
new_schemaId MD_SCHEMAS."ID"%TYPE,
p_scratchConn MD_CONNECTIONS."ID"%TYPE)
IS
BEGIN
NULL;
END copy_all_vw_trigs_ee;

PROCEDURE createIndexEntry(tableId MD_TABLES."ID"%TYPE,
p_scratchConn MD_CONNECTIONS."ID"%TYPE)
IS
CURSOR curIndexes(tableId MD_TABLES."ID"%TYPE) IS SELECT * FROM md_indexes WHERE table_id_fk = tableId;
idxRow MD_INDEXES%ROWTYPE;

BEGIN
OPEN curIndexes(tableId);
FETCH curIndexes INTO idxRow;

LOOP
EXIT WHEN curIndexes%NOTFOUND;

INSERT INTO MD_DERIVATIVES(src_id,
src_type,
derived_id,
derived_type,
DERIVED_CONNECTION_ID_FK,
ORIGINAL_IDENTIFIER,
NEW_IDENTIFIER,
DERIVED_OBJECT_NAMESPACE)
VALUES
(
idxRow."ID",
C_OBJECTTYPE_INDEXES,
idxRow."ID",
'MD_INDEXES',
p_scratchConn,
idxRow.index_name,
idxRow.index_name,
C_OBJECTTYPE_INDEXES || TO_CHAR(tableId)
);
FETCH curIndexes INTO idxRow;
END LOOP;
CLOSE curIndexes;

END;

PROCEDURE createColumnEntry(tableId MD_TABLES."ID"%TYPE,
p_scratchConn MD_CONNECTIONS."ID"%TYPE)
IS
CURSOR curColumns(tableId MD_TABLES."ID"%TYPE) IS SELECT * FROM md_columns WHERE table_id_fk = tableId;
colRow MD_COLUMNS%ROWTYPE;
BEGIN
OPEN curColumns(tableId);
FETCH curColumns INTO colRow;

LOOP
EXIT WHEN curColumns%NOTFOUND;

INSERT INTO MD_DERIVATIVES(src_id,
src_type,
derived_id,
derived_type,
DERIVED_CONNECTION_ID_FK,
ORIGINAL_IDENTIFIER,
NEW_IDENTIFIER,
DERIVED_OBJECT_NAMESPACE)
VALUES
(
colRow."ID",
C_OBJECTTYPE_COLUMNS,
colRow."ID",
'MD_COLUMNS',
p_scratchConn,
colRow.column_name,
colRow.column_name,
C_OBJECTTYPE_COLUMNS || TO_CHAR(tableId)
);
FETCH curColumns INTO colRow;
END LOOP;
CLOSE curColumns;
END;


PROCEDURE createTableEntry(schemaId MD_SCHEMAS."ID"%TYPE,
new_schemaId MD_SCHEMAS."ID"%TYPE,
p_scratchConn MD_CONNECTIONS."ID"%TYPE)
IS
CURSOR curTables(schemaId MD_SCHEMAS."ID"%TYPE) IS SELECT * FROM md_tables WHERE schema_id_fk = schemaId;
tblRow MD_TABLES%ROWTYPE;
BEGIN
OPEN curTables(schemaId);
FETCH curTables INTO tblRow;

LOOP
EXIT WHEN curTables%NOTFOUND;

INSERT INTO MD_DERIVATIVES(src_id,
src_type,
derived_id,
derived_type,
DERIVED_CONNECTION_ID_FK,
ORIGINAL_IDENTIFIER,
NEW_IDENTIFIER,
DERIVED_OBJECT_NAMESPACE)
VALUES
(
tblRow."ID",
C_OBJECTTYPE_TABLES,
tblRow."ID",
'MD_TABLES',
p_scratchConn,
tblRow.table_name,
tblRow.table_name,
C_NS_SCHEMA_OBJS || TO_CHAR(new_schemaid)
);
createColumnEntry(tblRow."ID", p_scratchConn);
createIndexEntry(tblRow."ID", p_scratchConn);
FETCH curTables INTO tblRow;
END LOOP;
CLOSE curTables;
END;


PROCEDURE createConstraintEntry(schemaId MD_SCHEMAS."ID"%TYPE,
new_schemaId MD_SCHEMAS."ID"%TYPE,
p_scratchConn MD_CONNECTIONS."ID"%TYPE)
IS
BEGIN
NULL;
END;


PROCEDURE copy_schema_objects_ee(schemaId MD_SCHEMAS."ID"%TYPE,
new_schemaId MD_SCHEMAS."ID"%TYPE,
p_scratchConn MD_CONNECTIONS."ID"%TYPE)
IS
BEGIN
--This create scratch model for table triggers as well
createDummyScrTblPerSchema_ee(schemaId,
new_schemaId,
p_scratchConn);
-- Make md_derivatives entry only for the following objects -- begin
createTableEntry(schemaId, new_schemaId, p_scratchConn);
createConstraintEntry(schemaId, new_schemaId, p_scratchConn);
-- Make md_derivatives entry only for the following objects -- end

--This create scratch model for view triggers as well
copy_all_views_ee(schemaId,
new_schemaId,
p_scratchConn);

copy_all_unpackaged_sps_ee(schemaId,
new_schemaId,
p_scratchConn);
END copy_schema_objects_ee;

-- p_connectionid -- scratch model connection id
PROCEDURE copy_catalogs_cascade_ee(p_connectionid MD_CONNECTIONS.ID%TYPE)
IS
CURSOR curDerivatives(conId MD_CONNECTIONS."ID"%TYPE) IS
SELECT *
FROM MD_DERIVATIVES
WHERE DERIVED_CONNECTION_ID_FK = conId
AND SRC_TYPE = C_OBJECTTYPE_CATALOGS;
recDerived MD_DERIVATIVES%ROWTYPE;

CURSOR curSchemas(catId MD_SCHEMAS.CATALOG_ID_FK%TYPE) IS
SELECT * FROM MD_SCHEMAS WHERE CATALOG_ID_FK = catId;
recSchema MD_SCHEMAS%ROWTYPE;

ncatId MD_SCHEMAS.CATALOG_ID_FK%TYPE;
n_newschId MD_SCHEMAS."ID"%TYPE;
v_ret NUMBER;
v_catalogdummy MD_CATALOGS.DUMMY_FLAG%TYPE;
v_catalogname VARCHAR2(300);
v_newName VARCHAR2(300);
BEGIN
OPEN curDerivatives(p_connectionid);
FETCH curDerivatives INTO recDerived;
LOOP -- for each of the catalog process its schemas
EXIT WHEN curDerivatives%NOTFOUND;
SELECT dummy_flag, catalog_name INTO v_catalogdummy, v_catalogname FROM MD_CATALOGS WHERE "ID" = recDerived.src_id;
ncatId := recDerived.src_id;
OPEN curSchemas(ncatId);
FETCH curSchemas INTO recSchema;
LOOP
EXIT WHEN curSchemas%NOTFOUND;

v_newName := recSchema."NAME" || '_' || v_catalogname;

INSERT INTO MD_SCHEMAS(CATALOG_ID_FK, "NAME", "TYPE", CHARACTER_SET, VERSION_TAG)
VALUES (recDerived.derived_id,
v_newName,
recSchema."TYPE",
recSchema.CHARACTER_SET,
recSchema.VERSION_TAG)
RETURNING "ID" INTO n_newschId;
v_ret := copy_additional_properties(ncatId, n_newschId, p_connectionid);
v_ret := copy_additional_properties(recSchema."ID", n_newschId, p_connectionid);

-- No Need for namespace stuff for catalogs.
INSERT INTO MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER)
VALUES (recSchema."ID", C_OBJECTTYPE_SCHEMAS, n_newschId, C_OBJECTTYPE_SCHEMAS, p_connectionid, recSchema."NAME", v_newName);

INSERT INTO MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER)
VALUES (recDerived.src_id, C_OBJECTTYPE_CATALOGS, n_newschId, C_OBJECTTYPE_SCHEMAS, p_connectionid, v_catalogname, v_newName);

copy_schema_objects_ee(recSchema."ID", n_newschId, p_connectionId);
FETCH curSchemas INTO recSchema;
END LOOP; -- end schema loop
CLOSE curSchemas;

FETCH curDerivatives INTO recDerived;
END LOOP; -- end catalog loop
CLOSE curDerivatives;
END copy_catalogs_cascade_ee;

FUNCTION copy_connection_cascade(p_connectionid MD_CONNECTIONS.ID%TYPE, p_filter_set MIGR_FILTER_SET := NULL, p_scratchModel BOOLEAN := FALSE) RETURN NUMBER
IS
v_newConnectionId MD_CONNECTIONS.ID%TYPE;
v_numProps NUMBER;
v_catalogId MD_CATALOGS.ID%TYPE;
v_catalogName MD_CATALOGS.CATALOG_NAME%TYPE;
v_numCatalogs NUMBER;
v_numDuplicateIndexes NUMBER;
v_sql VARCHAR(255);

CURSOR curDerivatives(conId MD_CONNECTIONS."ID"%TYPE) IS
SELECT distinct
id,
src_id,
src_type,
derived_id,
derived_type,
derived_connection_id_fk,
transformed,
original_identifier,
new_identifier,
derived_object_namespace,
derivative_reason,
security_group_id,
created_on,
created_by,
last_updated_on,
last_updated_by
FROM MD_DERIVATIVES
WHERE DERIVED_CONNECTION_ID_FK = conId
AND SRC_TYPE = C_OBJECTTYPE_CATALOGS;

recDerived MD_DERIVATIVES%ROWTYPE;


BEGIN

--DROP ANY EXISTING CONVERTED MODEL, AS WE ONLY HAVE A ONE TO ONE RELATIONSHIP WITH CAPTURED AND CONVERTED MODELS NOW
DELETE FROM Md_Connections C
WHERE C.Type = 'CONVERTED' --only want to delete CONVERTED MODELS
AND C.Id IN ( -- delete all converted models associated with this captured model
SELECT d.derived_id FROM md_derivatives d WHERE d.src_id = p_connectionid
);

-- The connection doesn't use the filter, because it is called for a single connection.
v_newConnectionId := copy_connection(p_connectionid, p_scratchModel);
-- Don't forget its additional props
v_numProps := copy_additional_properties(p_connectionid, v_newConnectionId, v_newConnectionId);
-- OK - Next coalesce the schema/catalogs

IF p_scratchModel = FALSE
THEN
--v_catalogId := create_dummy_catalog(v_newConnectionId);
--select CATALOG_NAME INTO v_catalogName FROM MD_CATALOGS WHERE CONNECTION_ID_FK = p_connectionid;
--v_sql := 'UPDATE MD_CATALOGS SET CATALOG_NAME = ''' || v_catalogName || ''' WHERE ID = ' || TO_CHAR(v_catalogId);
--EXECUTE IMMEDIATE v_sql;
create_dummy_catalogs(p_connectionid, v_newConnectionId, FALSE);

OPEN curDerivatives(v_newConnectionId);

LOOP
FETCH curDerivatives INTO recDerived;
EXIT WHEN curDerivatives%NOTFOUND;
--v_numCatalogs := copy_catalogs_cascade(p_connectionid, v_catalogid, v_newConnectionId, p_filter_set);
v_numCatalogs := copy_catalogs_cascade(p_connectionid, recDerived.src_id, recDerived.derived_id, v_newConnectionId, p_filter_set);
--FETCH curDerivatives INTO recDerived;
END LOOP;
CLOSE curDerivatives;
v_numDuplicateIndexes := remove_duplicate_indexes(v_newConnectionId);
v_numDuplicateIndexes := v_numDuplicateIndexes + remove_indexes_used_elsewhere(v_newConnectionId);
ELSE -- enterprise capture
create_dummy_catalogs(p_connectionid, v_newConnectionId, TRUE);
copy_catalogs_cascade_ee(v_newConnectionId);
END IF;
COMMIT;
return v_newConnectionId;
END copy_connection_cascade;

PROCEDURE update_derivative_record(p_orig VARCHAR2, p_new VARCHAR2, p_derivedid MD_DERIVATIVES.DERIVED_ID%TYPE,
p_derivedtype MD_DERIVATIVES.DERIVED_TYPE%TYPE, p_connectionid MD_DERIVATIVES.DERIVED_CONNECTION_ID_FK%TYPE)
IS
BEGIN
UPDATE MD_DERIVATIVES SET TRANSFORMED = C_TRANSFORMED_TRUE, ORIGINAL_IDENTIFIER = p_orig, NEW_IDENTIFIER = p_new
WHERE DERIVED_ID = p_derivedid
AND DERIVED_TYPE = p_derivedtype
AND DERIVED_CONNECTION_ID_FK = p_connectionid;
END update_derivative_record;

/*
* This procedure is like update_derivative_record except it should be used at name clash stage
* basically, this will work the same as update_derivative_record except in those cases where
* there is already a derivative record. In this latter case, we want ORIGINAL_IDENTIFIER preserved
* (this is called when there is a possiblity that we've carried out a second transformation
*/
PROCEDURE second_update_derivative(p_orig VARCHAR2, p_new VARCHAR2, p_derivedid MD_DERIVATIVES.DERIVED_ID%TYPE,
p_derivedtype MD_DERIVATIVES.DERIVED_TYPE%TYPE, p_connectionid MD_DERIVATIVES.DERIVED_CONNECTION_ID_FK%TYPE)
IS
v_firstOriginal MD_DERIVATIVES.ORIGINAL_IDENTIFIER%TYPE;
BEGIN
-- see if p_orig is already the new identifier
select ORIGINAL_IDENTIFIER INTO v_firstOriginal FROM MD_DERIVATIVES
WHERE DERIVED_ID = p_derivedid
AND DERIVED_TYPE = p_derivedtype
AND NEW_IDENTIFIER = p_orig
AND DERIVED_CONNECTION_ID_FK = p_connectionid;
if v_firstOriginal IS NULL then
update_derivative_record(p_orig, p_new, p_derivedid, p_derivedtype, p_connectionid);
else
update_derivative_record(v_firstOriginal, p_new, p_derivedid, p_derivedtype, p_connectionid);
end if;
EXCEPTION
when NO_DATA_FOUND THEN
update_derivative_record(p_orig, p_new, p_derivedid, p_derivedtype, p_connectionid);
WHEN TOO_MANY_ROWS THEN
dbms_output.put_line(TO_CHAR(p_derivedid) || ' ' || TO_CHAR(p_derivedtype) || ' '|| TO_CHAR(p_connectionid));

END second_update_derivative;

FUNCTION transform_column_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_COLUMNS
WHERE TABLE_ID_FK IN
(SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = connid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(COLUMN_NAME) != COLUMN_NAME
FOR UPDATE OF COLUMN_NAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT c.*, d.NEW_IDENTIFIER FROM MD_COLUMNS c, MD_DERIVATIVES d
WHERE (c.ID, d.SRC_ID) IN
(SELECT DERIVED_ID, SRC_ID FROM MD_DERIVATIVES
WHERE SRC_TYPE= C_OBJECTTYPE_COLUMNS AND DERIVED_CONNECTION_ID_FK = connid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(d.NEW_IDENTIFIER) != COLUMN_NAME
AND d.DERIVATIVE_REASON = C_CONNECTIONTYPE_SCRATCH
FOR UPDATE OF COLUMN_NAME;
v_rec v_curs%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_rec.NEW_IDENTIFIER);

update_derivative_record(v_rec.COLUMN_NAME, v_newName, v_rec.ID, C_OBJECTTYPE_COLUMNS, p_connectionid);
IF p_scratchModel = FALSE -- Update md_columns only for non migration estimation models
THEN
UPDATE MD_COLUMNS SET COLUMN_NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_COLUMNS, v_count);
--return v_count;
END transform_column_identifiers;

FUNCTION transform_constraint_idents(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_CONSTRAINTS
WHERE TABLE_ID_FK IN
(SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = connid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(NAME) != NAME
FOR UPDATE OF NAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT c.*, d.NEW_IDENTIFIER FROM MD_CONSTRAINTS c, MD_DERIVATIVES d
WHERE (c.ID, d.SRC_ID) IN
(SELECT DERIVED_ID, SRC_ID FROM MD_DERIVATIVES
WHERE SRC_TYPE = C_OBJECTTYPE_CONSTRAINTS AND DERIVED_CONNECTION_ID_FK = connid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(d.NEW_IDENTIFIER) != c.NAME
AND d.DERIVATIVE_REASON = C_CONNECTIONTYPE_SCRATCH
FOR UPDATE OF NAME;
v_rec v_curs%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_rec.NEW_IDENTIFIER);

update_derivative_record(v_rec.NAME, v_newName, v_rec.ID, C_OBJECTTYPE_CONSTRAINTS, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_CONSTRAINTS SET NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_CONSTRAINTS, v_count);
END transform_constraint_idents;

FUNCTION transform_group_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_GROUPS WHERE
SCHEMA_ID_FK IN
(SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(GROUP_NAME) != GROUP_NAME
FOR UPDATE OF GROUP_NAME;
*/

CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_GROUPS WHERE
ID IN
(SELECT DERIVED_ID FROM MD_DERIVATIVES
WHERE SRC_TYPE = C_OBJECTTYPE_GROUPS AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(GROUP_NAME) != GROUP_NAME
FOR UPDATE OF GROUP_NAME;
v_rec MD_GROUPS%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_rec.GROUP_NAME);

update_derivative_record(v_rec.GROUP_NAME, v_newName, v_rec.ID, C_OBJECTTYPE_GROUPS, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_GROUPS SET GROUP_NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_GROUPS, v_count);
END transform_group_identifiers;

FUNCTION transform_index_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_INDEXES WHERE TABLE_ID_FK IN
(SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||INDEX_NAME) != INDEX_NAME
FOR UPDATE OF INDEX_NAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT i.*, d.NEW_IDENTIFIER FROM MD_INDEXES i, MD_DERIVATIVES d WHERE (i.ID, d.SRC_ID) IN
(SELECT DERIVED_ID, SRC_ID FROM MD_DERIVATIVES
WHERE SRC_TYPE = C_OBJECTTYPE_INDEXES AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||d.NEW_IDENTIFIER) != i.INDEX_NAME
AND d.DERIVATIVE_REASON = C_CONNECTIONTYPE_SCRATCH
FOR UPDATE OF INDEX_NAME;
v_rec v_curs%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||v_rec.NEW_IDENTIFIER);

update_derivative_record(v_rec.INDEX_NAME, v_newName, v_rec.ID, C_OBJECTTYPE_INDEXES, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_INDEXES SET INDEX_NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
commit;
CLOSE v_curs;
return NAME_AND_COUNT_T(C_OBJECTTYPE_INDEXES, v_count);
END transform_index_identifiers;

FUNCTION transform_othobj_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_OTHER_OBJECTS WHERE SCHEMA_ID_FK IN
(SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||NAME) != NAME
FOR UPDATE OF NAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_OTHER_OBJECTS WHERE ID IN
(SELECT DERIVED_ID FROM MD_DERIVATIVES
WHERE SRC_TYPE = C_OBJECTTYPE_OTHER_OBJECTS AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||NAME) != NAME
FOR UPDATE OF NAME;
v_rec MD_OTHER_OBJECTS%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||v_rec.NAME);

update_derivative_record(v_rec.NAME, v_newName, v_rec.ID, C_OBJECTTYPE_OTHER_OBJECTS, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_OTHER_OBJECTS SET NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_OTHER_OBJECTS, v_count);
END transform_othobj_identifiers;

FUNCTION transform_package_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_PACKAGES WHERE SCHEMA_ID_FK IN
(SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||NAME) != NAME
FOR UPDATE OF NAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_PACKAGES WHERE ID IN
(SELECT DERIVED_ID FROM MD_DERIVATIVES
WHERE SRC_TYPE = C_OBJECTTYPE_PACKAGES AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||NAME) != NAME
FOR UPDATE OF NAME;
v_rec MD_PACKAGES%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||v_rec.NAME);

update_derivative_record(v_rec.NAME, v_newName, v_rec.ID, C_OBJECTTYPE_PACKAGES, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_PACKAGES SET NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_PACKAGES, v_count);
END transform_package_identifiers;

FUNCTION transform_schema_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_SCHEMAS WHERE ID IN
(SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(NAME) != NAME
FOR UPDATE OF NAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT s.*, d.NEW_IDENTIFIER FROM MD_SCHEMAS s, MD_DERIVATIVES d WHERE (s.ID, d.SRC_ID) IN
(SELECT DERIVED_ID, SRC_ID FROM MD_DERIVATIVES
WHERE SRC_TYPE = C_OBJECTTYPE_SCHEMAS AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(d.NEW_IDENTIFIER) != NAME
AND d.DERIVATIVE_REASON = C_CONNECTIONTYPE_SCRATCH
FOR UPDATE OF NAME;
v_rec v_curs%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName:= MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_rec.NEW_IDENTIFIER);

update_derivative_record(v_rec.NAME, v_newName, v_rec.ID, C_OBJECTTYPE_SCHEMAS, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_SCHEMAS SET NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_SCHEMAS, v_count);
END transform_schema_identifiers;

FUNCTION transform_sequence_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_SEQUENCES WHERE SCHEMA_ID_FK IN
(SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||NAME) != NAME
FOR UPDATE OF NAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT s.*, d.NEW_IDENTIFIER FROM MD_SEQUENCES s, MD_DERIVATIVES d WHERE (s.ID, d.SRC_ID) IN
(SELECT DERIVED_ID, SRC_ID FROM MD_DERIVATIVES
WHERE SRC_TYPE = C_OBJECTTYPE_SEQUENCES AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||d.NEW_IDENTIFIER) != NAME
AND d.DERIVATIVE_REASON = C_CONNECTIONTYPE_SCRATCH
FOR UPDATE OF NAME;
v_rec v_curs%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||v_rec.NEW_IDENTIFIER);

update_derivative_record(v_rec.NAME, v_newName, v_rec.ID, C_OBJECTTYPE_SEQUENCES, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_SEQUENCES SET NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_SEQUENCES, v_count);
END transform_sequence_identifiers;

FUNCTION transform_sproc_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_STORED_PROGRAMS WHERE SCHEMA_ID_FK IN
(SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||NAME) != NAME
FOR UPDATE OF NAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT sp.*, d.NEW_IDENTIFIER FROM MD_STORED_PROGRAMS sp, MD_DERIVATIVES d WHERE (sp.ID, d.SRC_ID) IN
(SELECT DERIVED_ID, SRC_ID FROM MD_DERIVATIVES WHERE SRC_TYPE = C_OBJECTTYPE_STORED_PROGRAMS AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||d.NEW_IDENTIFIER) != sp.NAME
AND d.DERIVATIVE_REASON = C_CONNECTIONTYPE_SCRATCH
FOR UPDATE OF NAME;
v_rec v_curs%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||v_rec.NEW_IDENTIFIER);

update_derivative_record(v_rec.NAME, v_newName, v_rec.ID, C_OBJECTTYPE_STORED_PROGRAMS, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_STORED_PROGRAMS SET NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_STORED_PROGRAMS, v_count);
END transform_sproc_identifiers;

FUNCTION transform_synonym_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_SYNONYMS WHERE SCHEMA_ID_FK IN
(SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||NAME) != NAME
FOR UPDATE OF NAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_SYNONYMS WHERE ID IN
(SELECT DERIVED_ID FROM MD_DERIVATIVES
WHERE SRC_TYPE = C_OBJECTTYPE_SYNONYMS AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||NAME) != NAME
FOR UPDATE OF NAME;
v_rec MD_SYNONYMS%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||v_rec.NAME);

update_derivative_record(v_rec.NAME, v_newName, v_rec.ID, C_OBJECTTYPE_SYNONYMS, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_SYNONYMS SET NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_SYNONYMS, v_count);
END transform_synonym_identifiers;

FUNCTION transform_table_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_TABLES WHERE SCHEMA_ID_FK IN
(SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||TABLE_NAME) != TABLE_NAME
FOR UPDATE OF TABLE_NAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT t.*, d.NEW_IDENTIFIER FROM MD_TABLES t, MD_DERIVATIVES d WHERE (t.ID, d.SRC_ID) IN
(SELECT DERIVED_ID, SRC_ID FROM MD_DERIVATIVES
WHERE SRC_TYPE = C_OBJECTTYPE_TABLES AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||d.NEW_IDENTIFIER) != TABLE_NAME
AND d.DERIVATIVE_REASON = C_CONNECTIONTYPE_SCRATCH
FOR UPDATE OF TABLE_NAME;
v_rec v_curs%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||v_rec.NEW_IDENTIFIER);

update_derivative_record(v_rec.TABLE_NAME, v_newName, v_rec.ID, C_OBJECTTYPE_TABLES, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_TABLES SET TABLE_NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_TABLES, v_count);
END transform_table_identifiers;

FUNCTION transform_view_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_VIEWS WHERE SCHEMA_ID_FK IN
(SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||VIEW_NAME) != VIEW_NAME
FOR UPDATE OF VIEW_NAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT v.*, d.NEW_IDENTIFIER FROM MD_VIEWS v, MD_DERIVATIVES d WHERE (v.ID, d.SRC_ID) IN
(SELECT DERIVED_ID, SRC_ID FROM MD_DERIVATIVES WHERE SRC_TYPE = C_OBJECTTYPE_VIEWS AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||d.NEW_IDENTIFIER) != VIEW_NAME
AND d.DERIVATIVE_REASON = C_CONNECTIONTYPE_SCRATCH
FOR UPDATE OF VIEW_NAME;
v_rec v_curs%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||v_rec.NEW_IDENTIFIER);

update_derivative_record(v_rec.VIEW_NAME, v_newName, v_rec.ID, C_OBJECTTYPE_VIEWS, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_VIEWS SET VIEW_NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_VIEWS, v_count);
END transform_view_identifiers;

FUNCTION transform_tablespace_idents(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_TABLESPACES WHERE SCHEMA_ID_FK IN
(SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(TABLESPACE_NAME) != TABLESPACE_NAME
FOR UPDATE OF TABLESPACE_NAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_TABLESPACES WHERE ID IN
(SELECT DERIVED_ID FROM MD_DERIVATIVES
WHERE SRC_TYPE = C_OBJECTTYPE_TABLESPACES AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(TABLESPACE_NAME) != TABLESPACE_NAME
FOR UPDATE OF TABLESPACE_NAME;
v_rec MD_TABLESPACES%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_rec.TABLESPACE_NAME);

update_derivative_record(v_rec.TABLESPACE_NAME, v_newName, v_rec.ID, C_OBJECTTYPE_TABLESPACES, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_TABLESPACES SET TABLESPACE_NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_TABLESPACES, v_count);
END transform_tablespace_idents;

FUNCTION transform_trigger_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs IS
SELECT * FROM MD_TRIGGERS WHERE TABLE_OR_VIEW_ID_FK IN
(SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||TRIGGER_NAME) != TRIGGER_NAME
FOR UPDATE OF TRIGGER_NAME;
CURSOR v_view_trigger_curs IS
SELECT * FROM MD_TRIGGERS WHERE TABLE_OR_VIEW_ID_FK IN
(SELECT VIEW_ID FROM MGV_ALL_VIEWS WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||TRIGGER_NAME) != TRIGGER_NAME
FOR UPDATE OF TRIGGER_NAME;
*/
CURSOR v_curs IS
SELECT t.*, d.NEW_IDENTIFIER FROM MD_TRIGGERS t, MD_DERIVATIVES d WHERE (t.ID, d.SRC_ID) IN
(SELECT DERIVED_ID, SRC_ID FROM MD_DERIVATIVES
WHERE SRC_TYPE = C_OBJECTTYPE_TRIGGERS AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||d.NEW_IDENTIFIER) != t.TRIGGER_NAME
AND d.DERIVATIVE_REASON = C_CONNECTIONTYPE_SCRATCH
FOR UPDATE OF TRIGGER_NAME;

v_rec v_curs%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs;
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||v_rec.NEW_IDENTIFIER);

update_derivative_record(v_rec.TRIGGER_NAME, v_newName, v_rec.ID, C_OBJECTTYPE_TRIGGERS, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_TRIGGERS SET TRIGGER_NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
/*
OPEN v_view_trigger_curs;
LOOP
FETCH v_view_trigger_curs INTO v_rec;
EXIT WHEN v_view_trigger_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||v_rec.TRIGGER_NAME);

IF p_scratchModel = FALSE
THEN
UPDATE MD_TRIGGERS SET TRIGGER_NAME = v_newName WHERE CURRENT OF v_view_trigger_curs;
END IF;

update_derivative_record(v_rec.TRIGGER_NAME, v_newName, v_rec.ID, C_OBJECTTYPE_TRIGGERS, p_connectionid);
END LOOP;
CLOSE v_view_trigger_curs;
*/
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_TRIGGERS, v_count);
END transform_trigger_identifiers;

FUNCTION transform_uddt_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_USER_DEFINED_DATA_TYPES WHERE SCHEMA_ID_FK IN
(SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||DATA_TYPE_NAME) != DATA_TYPE_NAME
FOR UPDATE OF DATA_TYPE_NAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_USER_DEFINED_DATA_TYPES WHERE ID IN
(SELECT DERIVED_ID FROM MD_DERIVATIVES WHERE SRC_TYPE = C_OBJECTTYPE_UDDT AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||DATA_TYPE_NAME) != DATA_TYPE_NAME
FOR UPDATE OF DATA_TYPE_NAME;
v_rec MD_USER_DEFINED_DATA_TYPES%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_prefixName||v_rec.DATA_TYPE_NAME);

update_derivative_record(v_rec.DATA_TYPE_NAME, v_newName, v_rec.ID, C_OBJECTTYPE_UDDT, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_USER_DEFINED_DATA_TYPES SET DATA_TYPE_NAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_UDDT, v_count);
END transform_uddt_identifiers;

FUNCTION transform_user_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_T
IS
/*
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_USERS WHERE SCHEMA_ID_FK IN
(SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(USERNAME) != USERNAME
FOR UPDATE OF USERNAME;
*/
CURSOR v_curs(connid MD_CONNECTIONS.ID%TYPE) IS
SELECT * FROM MD_USERS WHERE ID IN
(SELECT DERIVED_ID FROM MD_DERIVATIVES WHERE SRC_TYPE = C_OBJECTTYPE_USERS AND DERIVED_CONNECTION_ID_FK = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(USERNAME) != USERNAME
FOR UPDATE OF USERNAME;
v_rec MD_USERS%ROWTYPE;
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_T;
v_newName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
BEGIN
OPEN v_curs(p_connectionid);
LOOP
FETCH v_curs INTO v_rec;
EXIT WHEN v_curs%NOTFOUND;
v_count := v_count + 1;
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_rec.USERNAME);

update_derivative_record(v_rec.USERNAME, v_newName, v_rec.ID, C_OBJECTTYPE_USERS, p_connectionid);
IF p_scratchModel = FALSE
THEN
UPDATE MD_USERS SET USERNAME = v_newName WHERE CURRENT OF v_curs;
END IF;

END LOOP;
CLOSE v_curs;
commit;
return NAME_AND_COUNT_T(C_OBJECTTYPE_USERS, v_count);
END transform_user_identifiers;

PROCEDURE rename_duplicate_index_names(p_connectionid MD_CONNECTIONS.ID%TYPE, p_scratchModel BOOLEAN := FALSE)
IS
CURSOR v_curs IS
select * from md_derivatives a
where a.derived_connection_id_fk = p_connectionid
and 1 < (select count(*)
from md_derivatives b
where a.new_identifier = b.new_identifier
and a.derived_type='MD_INDEXES'
and a.derived_connection_id_fk = b.derived_connection_id_fk)
order by new_identifier;

v_row MD_DERIVATIVES%ROWTYPE;
v_newName MD_INDEXES.INDEX_NAME%TYPE;

v_id MD_DERIVATIVES.DERIVED_ID%TYPE;

v_curName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
v_count NUMBER := 1;
BEGIN
v_curName := 'dsa;lkjsd;alskj;';
OPEN v_curs;
LOOP
FETCH v_curs INTO v_row;
EXIT WHEN v_curs%NOTFOUND;


IF UPPER(v_row.NEW_IDENTIFIER) = UPPER(v_curName) THEN
v_newName := MIGRATION_TRANSFORMER.ADD_SUFFIX(v_row.NEW_IDENTIFIER, '_' || TO_CHAR(v_count), 30);
v_count := v_count + 1;

if p_scratchModel = FALSE
THEN
update MD_INDEXES SET index_name = v_newName where id = v_row.DERIVED_ID;
END IF;
second_update_derivative(v_row.NEW_IDENTIFIER, v_newName, v_row.DERIVED_ID, C_OBJECTTYPE_INDEXES, p_connectionid);
else
v_curName := v_row.NEW_IDENTIFIER;
v_count := 1;
END IF;
END LOOP;
CLOSE v_curs;
commit;
END rename_duplicate_index_names;

PROCEDURE fixup_duplicate_identifier(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_mdrec_id MD_DERIVATIVES.ID%TYPE,
p_derived_type MD_DERIVATIVES.DERIVED_TYPE%TYPE,
p_derived_id MD_DERIVATIVES.DERIVED_ID%TYPE,
p_new_identifier MD_DERIVATIVES.NEW_IDENTIFIER%TYPE,
p_suffix INTEGER,
p_scratchModel BOOLEAN := FALSE)
IS
v_transform_identifier MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
v_did_a_transform CHAR(1) := 'Y';
--v_underscoresuffixsize NUMBER;
--v_underscoresuffix VARCHAR2(100);
--v_sizebeforeprefix NUMBER;
BEGIN
--v_underscoresuffix := '_' || TO_CHAR(p_suffix);
--v_underscoresuffixsize := LENGTH(v_underscoresuffix);
--v_sizebeforeprefix := 30 - v_underscoresuffixsize;
v_transform_identifier := MIGRATION_TRANSFORMER.ADD_SUFFIX(p_new_identifier, '_' || TO_CHAR(p_suffix) ,30);

IF p_scratchModel = FALSE
THEN
CASE p_derived_type
WHEN C_OBJECTTYPE_CONNECTIONS THEN
UPDATE MD_CONNECTIONS SET NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_CATALOGS THEN
UPDATE MD_CATALOGS SET CATALOG_NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_SCHEMAS THEN
UPDATE MD_SCHEMAS SET NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_TABLES THEN
UPDATE MD_TABLES SET TABLE_NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_CONSTRAINTS THEN
UPDATE MD_CONSTRAINTS SET NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_INDEXES THEN
UPDATE MD_INDEXES SET INDEX_NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_TRIGGERS THEN
UPDATE MD_TRIGGERS SET TRIGGER_NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_VIEWS THEN
UPDATE MD_VIEWS SET VIEW_NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_USERS THEN
UPDATE MD_USERS SET USERNAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_GROUPS THEN
UPDATE MD_GROUPS SET GROUP_NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_OTHER_OBJECTS THEN
UPDATE MD_OTHER_OBJECTS SET NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_TABLESPACES THEN
UPDATE MD_TABLESPACES SET TABLESPACE_NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_UDDT THEN
UPDATE MD_USER_DEFINED_DATA_TYPES SET DATA_TYPE_NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_STORED_PROGRAMS THEN
UPDATE MD_STORED_PROGRAMS SET NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_PACKAGES THEN
UPDATE MD_PACKAGES SET NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_SYNONYMS THEN
UPDATE MD_SYNONYMS SET NAME = v_transform_identifier WHERE ID = p_derived_id;
WHEN C_OBJECTTYPE_SEQUENCES THEN
UPDATE MD_SEQUENCES SET NAME = v_transform_identifier WHERE ID = p_derived_id;
ELSE
-- Handle column namespace here.
IF SUBSTR(P_DERIVED_TYPE,1, LENGTH(C_OBJECTTYPE_COLUMNS)) = C_OBJECTTYPE_COLUMNS THEN
UPDATE MD_COLUMNS SET COLUMN_NAME = v_transform_identifier WHERE ID = p_derived_id;
ELSE
v_did_a_transform := 'N';
END IF;
END CASE;
END IF; -- end if scratch model

IF v_did_a_transform = 'Y' THEN
UPDATE MD_DERIVATIVES SET NEW_IDENTIFIER = v_transform_identifier WHERE ID = p_mdrec_id;
commit;
END IF;
commit;
END fixup_duplicate_identifier;

FUNCTION getClashCount(p_connectionid MD_CONNECTIONS.ID%TYPE) RETURN INTEGER
IS
v_clashCount INTEGER;
BEGIN
SELECT COUNT(*) INTO v_clashCount FROM md_derivatives a
where rowid > (
select min(rowid) from md_derivatives b
where
b.derived_connection_id_fk = p_connectionid
AND b.derived_connection_id_fk = a.derived_connection_id_fk
AND UPPER(b.new_identifier) = UPPER(a.new_identifier)-- Uppercasing the name so that case sensitve names are caught (see bug 6922052)
AND b.derived_object_namespace = a.derived_object_namespace);
RETURN v_clashCount;
END getClashCount;

PROCEDURE transform_clashes(p_connectionid MD_CONNECTIONS.ID%TYPE, p_scratchModel BOOLEAN := FALSE)
IS
CURSOR v_curs IS
select id,derived_type, derived_id, UPPER(new_identifier) -- Uppercasing the name so that case sensitve names are caught (see bug 6922052)
from md_derivatives a
where rowid > (
select min(rowid) from md_derivatives b
where
b.derived_connection_id_fk = p_connectionid
AND b.derived_connection_id_fk = a.derived_connection_id_fk
AND UPPER(b.new_identifier) = UPPER(a.new_identifier) -- Uppercasing the name so that case sensitve names are caught (see bug 6922052)
AND b.derived_object_namespace = a.derived_object_namespace)
ORDER BY new_identifier, derived_type;
v_derived_type MD_DERIVATIVES.DERIVED_TYPE%TYPE;
v_curr_type v_derived_type%TYPE := '~~dasdddfl;';
v_derived_id MD_DERIVATIVES.DERIVED_ID%TYPE;
v_new_identifier MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
v_curr_identifier v_new_identifier%TYPE := '~~~~asdasnc';
v_suffix INTEGER := 0;
v_innerSuffix INTEGER;
v_clashCount INTEGER;
v_mdrec_id MD_DERIVATIVES.ID%TYPE;
BEGIN

rename_duplicate_index_names(p_connectionid, p_scratchModel);

v_clashCount := getClashCount(p_connectionid);
WHILE v_clashCount > 0
LOOP
v_suffix := v_suffix + 1;
v_innerSuffix := v_suffix;
-- Now lets see if there are any identifier clashes
OPEN v_curs;
LOOP
FETCH v_curs into v_mdrec_id, v_derived_type, v_derived_id, v_new_identifier;
EXIT WHEN v_curs%NOTFOUND;
IF v_derived_type = v_curr_type AND v_new_identifier = v_curr_identifier THEN
v_innerSuffix := v_innerSuffix + 1;
else
v_curr_type := v_derived_type;
v_curr_identifier := v_new_identifier;
END IF;
-- We have to fix up all of these identifiers
fixup_duplicate_identifier(p_connectionid, v_mdrec_id, v_derived_type, v_derived_id, v_new_identifier, v_innerSuffix, p_scratchModel);
END LOOP;
CLOSE v_curs;
v_clashCount := getClashCount(p_connectionid);
END LOOP;
END transform_clashes;

FUNCTION transform_all_identifiers_x(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_ARRAY
IS
v_count INTEGER := 0;
v_ret NAME_AND_COUNT_ARRAY;
v_rec NAME_AND_COUNT_T;
BEGIN
v_ret := NAME_AND_COUNT_ARRAY();
-- We need to update identifiers on pretty much the whole schema
-- MD_COLUMNS
v_rec := transform_column_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');

-- MD_CONSTRAINTS
v_rec := transform_constraint_idents(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
-- MD_GROUPS
v_rec := transform_group_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
-- MD_INDEXES
v_rec := transform_index_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
-- MD_OTHER_OBJECTS
v_rec := transform_othobj_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
-- MD_PACKAGES
v_rec := transform_package_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
-- MD_SCHEMAS
v_rec := transform_schema_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
-- MD_SEQUENCES
v_rec := transform_sequence_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
-- MD_STORED_PROGRAMS
v_rec := transform_sproc_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
-- MD_SYNONYMS
v_rec := transform_synonym_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
-- MD_TABLES
v_rec := transform_table_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
-- MD_TABLESPACES
v_rec := transform_tablespace_idents(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
-- MD_TRIGGERS
v_rec := transform_trigger_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
-- MD_USER_DEFINED_DATA_TYPES
v_rec := transform_uddt_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
-- MD_USERS
v_rec := transform_user_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
/*
UPDATE MD_USERS SET USERNAME = MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(USERNAME) WHERE SCHEMA_ID_FK IN
(SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionid)
AND MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(USERNAME) != USERNAME;
dbms_output.put_line(SQL%ROWCOUNT || ' USER names updated');
*/
-- MD_VIEWS
v_rec := transform_view_identifiers(p_connectionid, p_scratchModel);
v_ret.EXTEND;
v_ret(v_ret.count) := v_rec;
dbms_output.put_line(v_rec.UPDATE_COUNT || v_rec.OBJECT_NAME || ' names udpates');
transform_clashes(p_connectionid, p_scratchModel);
-- TODO: Something meaningful if all goes wrong
return v_ret;
COMMIT;
END transform_all_identifiers_x;

FUNCTION transform_all_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE, p_prefixName VARCHAR2, p_scratchModel BOOLEAN := FALSE) RETURN NAME_AND_COUNT_ARRAY
IS
BEGIN
v_prefixName := p_prefixName;
RETURN transform_all_identifiers_x(p_connectionid, p_scratchModel);
END transform_all_identifiers;

FUNCTION rule_specificity(p_precision MIGR_DATATYPE_TRANSFORM_RULE.SOURCE_PRECISION%TYPE, p_scale MIGR_DATATYPE_TRANSFORM_RULE.SOURCE_SCALE%TYPE) RETURN INTEGER
IS
BEGIN
IF p_precision is NULL then
return 1;
END IF;
IF p_scale is NULL then
return 2;
END IF;
return 3;
END rule_specificity;

FUNCTION addToWhereClause(p_whereclause VARCHAR2, p_toAdd VARCHAR2) return VARCHAR2
IS
BEGIN
IF p_whereclause is NULL then
return p_toAdd;
else
return p_whereclause || ' AND ' || p_toAdd;
END IF;
END addToWhereClause;

FUNCTION precision_val(p_srcPrecision MD_COLUMNS.PRECISION%TYPE, p_newDataType VARCHAR2) RETURN VARCHAR2
IS
v_newDataType VARCHAR2(255);
v_ret VARCHAR2(255);
BEGIN
v_newDataType := UPPER(to_char(p_newDataType));
-- Assume that no precision should be present
v_ret := 'NULL';
-- No see what the new data type is and ensure that a precision is required
IF v_newDataType = 'VARCHAR2' OR
v_newDataType = 'NVARCHAR2' OR
v_newDataType = 'NUMBER' OR
v_newDataType = 'TIMESTAMP' OR
v_newDataType = 'INTERVAL YEAR' OR
v_newDataType = 'INTERVAL DAY' OR
v_newDataType = 'UROWID' OR
v_newDataType = 'CHAR' OR
v_newDataType = 'RAW' OR
v_newDataType = 'NCHAR' THEN
v_ret := p_srcPrecision;
END IF;
return v_ret;
END precision_val;

FUNCTION scale_val(p_srcPrecision MD_COLUMNS.SCALE%TYPE, p_newDataType VARCHAR2) RETURN VARCHAR2
IS
v_newDataType VARCHAR2(255);
v_ret VARCHAR2(255);
BEGIN
v_newDataType := UPPER(to_char(p_newDataType));
v_ret := 'NULL';
IF v_newDataType = 'NUMBER' THEN
v_ret := p_srcPrecision;
END IF;
return v_ret;
END scale_val;


FUNCTION check_for_invalid_data_types(p_connectionid MD_CONNECTIONS.ID%TYPE, p_numbytesperchar INTEGER) RETURN NUMBER
IS
BEGIN
-- First, for char(n) columns, drop back to varchar2 - this could go up to 4k.
-- If its even greater than this, it will be caught later on and made into a CLOB.
UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'CHAR' AND PRECISION > 2000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET COLUMN_TYPE = 'VARCHAR2' WHERE COLUMN_TYPE = 'CHAR' AND PRECISION > 2000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);
-- We'll do something similar for NCHARs
IF p_numbytesperchar = 1 THEN
UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'NCHAR' AND PRECISION > 2000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET COLUMN_TYPE = 'NVARCHAR2' WHERE COLUMN_TYPE = 'NCHAR' AND PRECISION > 2000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);
ELSE
-- 2 bytes per char - max is actually 1k
UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'NCHAR' AND PRECISION > 1000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET COLUMN_TYPE = 'NVARCHAR2' WHERE COLUMN_TYPE = 'NCHAR' AND PRECISION > 1000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);
END IF;
-- VARCHAR or VARCHAR2 can't go above 4000. If they do, they need to fallback to a CLOB
UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'VARCHAR' AND PRECISION > 4000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET COLUMN_TYPE = 'CLOB', PRECISION = NULL, SCALE = NULL WHERE COLUMN_TYPE = 'VARCHAR' AND PRECISION > 4000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);

UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'VARCHAR2' AND PRECISION > 4000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET COLUMN_TYPE = 'CLOB', PRECISION = NULL, SCALE = NULL WHERE COLUMN_TYPE = 'VARCHAR2' AND PRECISION > 4000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);
-- NUMBER has a max precision of 38, and scale must be between -84 and 127
-- We can only narrow this.

UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'NUMBER' AND PRECISION > 38
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET PRECISION = 38 WHERE COLUMN_TYPE = 'NUMBER' AND PRECISION > 38
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);

UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'NUMBER' AND SCALE < -84
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET SCALE = -84 WHERE COLUMN_TYPE = 'NUMBER' AND SCALE < -84
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);

UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'NUMBER' AND SCALE > 127
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET SCALE = 127 WHERE COLUMN_TYPE = 'NUMBER' AND SCALE > 127
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);
-- NVARCHAR has a max of 4000 bytes. But its definition depends on the character set in use.
IF p_numbytesperchar = 1 THEN
UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'NVARCHAR2' AND PRECISION > 4000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET COLUMN_TYPE = 'NCLOB', PRECISION = NULL, SCALE = NULL WHERE COLUMN_TYPE = 'NVARCHAR2' AND PRECISION > 4000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);
ELSE
UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'NVARCHAR2' AND PRECISION > 2000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET COLUMN_TYPE = 'NCLOB', PRECISION = NULL, SCALE = NULL WHERE COLUMN_TYPE = 'NVARCHAR2' AND PRECISION > 2000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);
END IF;
-- TIMESTAMP has a max size of 9

UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'TIMESTAMP' AND PRECISION > 9
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET PRECISION = 9 WHERE COLUMN_TYPE = 'TIMESTAMP' AND PRECISION > 9
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);

UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'INTERVAL YEAR' AND PRECISION > 9
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET PRECISION = 9 WHERE COLUMN_TYPE = 'INTERVAL YEAR' AND PRECISION > 9
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);

UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'INTERVAL DAY' AND PRECISION > 9
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET PRECISION = 9 WHERE COLUMN_TYPE = 'INTERVAL DAY' AND PRECISION > 9
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);

UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'INTERVAL DAY' AND SCALE > 9
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET SCALE = 9 WHERE COLUMN_TYPE = 'INTERVAL DAY' AND SCALE > 9
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);

UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'UROWID' AND PRECISION > 4000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET PRECISION = 4000 WHERE COLUMN_TYPE = 'UROWID' AND PRECISION > 4000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);
-- Too large RAW? Make it a CLOB

UPDATE MD_DERIVATIVES SET DERIVATIVE_REASON = 'INVDTTYPE' WHERE DERIVED_CONNECTION_ID_FK = p_connectionid
AND DERIVED_TYPE = 'MD_COLUMNS' AND DERIVED_ID IN (SELECT ID FROM MD_COLUMNS WHERE COLUMN_TYPE = 'RAW' AND PRECISION > 2000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid));
UPDATE MD_COLUMNS SET COLUMN_TYPE = 'BLOB', PRECISION = NULL WHERE COLUMN_TYPE = 'RAW' AND PRECISION > 2000
AND TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionid);
commit;
RETURN 0;
END check_for_invalid_data_types;

FUNCTION transform_datatypes(p_connectionid MD_CONNECTIONS.ID%TYPE, p_mapid MIGR_DATATYPE_TRANSFORM_MAP.ID%TYPE, p_numbytesperchar INTEGER) RETURN NUMBER
IS
v_projectid MD_PROJECTS.ID%TYPE;
v_mapProjectid MD_PROJECTS.ID%TYPE;
CURSOR v_curs(mapid MIGR_DATATYPE_TRANSFORM_MAP.ID%TYPE) IS
SELECT * FROM MIGR_DATATYPE_TRANSFORM_RULE WHERE map_ID_fk = mapid
ORDER BY DECODE(source_precision,
NULL, 0,
1) +
DECODE(source_scale,
NULL, 0,
1) DESC;
v_rule MIGR_DATATYPE_TRANSFORM_RULE%ROWTYPE;
v_whereClause VARCHAR2(4000);
v_updateClause VARCHAR2(4000);
v_count NUMBER := 0;
v_ret NUMBER;
BEGIN
-- We should only work with our "own" maps. I.e. The map should be part of this project.
SELECT project_id_fk into v_projectid from MD_CONNECTIONS where id = p_connectionid;
SELECT project_id_fk into v_mapProjectid from MIGR_DATATYPE_TRANSFORM_MAP where id = p_mapid;
IF v_projectid != v_mapProjectid then
-- TODO. Some nice RAISE_APPLICATION_ERROR stuff here.
return 0;
END IF;
-- OK We can work with our map
OPEN v_curs(p_mapid);
LOOP
fetch v_curs INTO v_rule;
EXIT WHEN v_curs%NOTFOUND;
v_whereClause := 'UPPER(COLUMN_TYPE) = ''' || UPPER(v_rule.SOURCE_DATA_TYPE_NAME) || '''';
if v_rule.SOURCE_PRECISION is not NULL then
v_whereClause := addToWhereClause(v_whereClause, 'PRECISION = ' || to_char(v_rule.source_precision));
IF v_rule.SOURCE_SCALE is not NULL then
v_whereClause := addToWhereClause(v_whereClause, 'SCALE = ' || to_char(v_rule.source_scale));
end IF;
END IF;
v_whereClause := addToWhereClause(v_whereClause, 'table_id_fk in (SELECT table_id from MGV_ALL_TABLES WHERE connection_id = ' || to_char(p_connectionid) || ')');
v_whereClause := addTowhereclause(v_whereClause, 'DATATYPE_TRANSFORMED_FLAG IS NULL');
v_updateClause := 'UPDATE MD_COLUMNS SET COLUMN_TYPE = ''' || v_rule.TARGET_DATA_TYPE_NAME || ''', DATATYPE_TRANSFORMED_FLAG=''Y''';
IF v_rule.TARGET_PRECISION is not NULL then
v_updateClause := v_updateClause || ', PRECISION = ' || precision_val(v_rule.TARGET_PRECISION, v_rule.TARGET_DATA_TYPE_NAME);
IF v_rule.TARGET_SCALE is not NULL then
-- The rule says change it to a specific scale, but we may override this is the data type shouldn't have a scale
v_updateClause := v_updateClause || ', SCALE = ' || scale_val(v_rule.TARGET_SCALE, v_rule.TARGET_DATA_TYPE_NAME);
ELSE
-- There was no mention on the rule to touch the scale, so we should leave it alone...
-- ..unless of course the data type forbids having it.
IF scale_val(1, v_rule.TARGET_DATA_TYPE_NAME) = 'NULL' THEN
v_updateClause := v_updateClause || ', SCALE = NULL';
END IF;
END IF;
ELSE
-- There was no metion on the rul to touch the precision, so we should leave it alone...
-- ..unless of course the data type forbids having it.
IF precision_val(1, v_rule.TARGET_DATA_TYPE_NAME) = 'NULL' THEN
v_updateClause := v_updateClause || ', PRECISION = NULL';
END IF;
IF scale_val(1, v_rule.TARGET_DATA_TYPE_NAME) = 'NULL' THEN
v_updateClause := v_updateClause || ', SCALE = NULL';
END IF;
END IF;
v_updateClause := v_updateClause || ' WHERE ' || v_whereClause;
dbms_output.put_line(v_updateClause);
EXECUTE IMMEDIATE v_updateClause;
v_count := v_count + SQL%ROWCOUNT;
END LOOP;
CLOSE v_curs;
COMMIT;
-- OK. Lets see if we've made any columns invalid.
v_ret := check_for_invalid_data_types(p_connectionid, p_numbytesperchar);
-- Now that we know the data types of the index columns, we may have flag some of the indexes
-- as text indexes.
v_ret := fixupTextIndexes(p_connectionid);

RETURN v_count;
END transform_datatypes;

FUNCTION GET_IDENTITY_TRIGGER(v_triggerName VARCHAR2 , v_tableName VARCHAR2 ,
v_ColumnName VARCHAR2 ,v_seqName VARCHAR2 ,v_emulationPkgNamePrefix VARCHAR2 ) RETURN VARCHAR2
as
v_identityClause VARCHAR2(200);
BEGIN

IF v_emulationpkgnameprefix = 'mysql_utilities.' THEN
v_identityclause := ' --used to emulate LAST_INSERT_ID()'|| chr(10) || ' --'||v_emulationpkgnameprefix || 'identity := v_newVal; '|| chr(10) ;
ELSE
v_identityclause := ' -- save this to emulate @@identity'|| chr(10) || ' '||v_emulationpkgnameprefix || 'identity := v_newVal; '|| chr(10) ;
END IF;

return 'CREATE OR REPLACE TRIGGER ' || v_triggerName || ' BEFORE INSERT OR UPDATE ON ' || v_tableName || CHR(10) ||
'FOR EACH ROW' || CHR(10) ||
'DECLARE ' || CHR(10)||
'v_newVal NUMBER(12) := 0;' ||CHR(10) ||
'v_incval NUMBER(12) := 0;'||CHR(10) ||
'BEGIN' || CHR(10) ||
' IF INSERTING AND :new.' || v_ColumnName || ' IS NULL THEN' || CHR(10) ||
' SELECT ' || v_seqName || '.NEXTVAL INTO v_newVal FROM DUAL;' || CHR(10) ||
' -- If this is the first time this table have been inserted into (sequence == 1)' || CHR(10) ||
' IF v_newVal = 1 THEN ' || CHR(10) ||
' --get the max indentity value from the table' || CHR(10) ||
' SELECT NVL(max(' || v_ColumnName || '),0) INTO v_newVal FROM ' || v_tableName || ';'|| CHR(10) ||
' v_newVal := v_newVal + 1;' || CHR(10) ||
' --set the sequence to that value'|| CHR(10) ||
' LOOP'|| CHR(10) ||
' EXIT WHEN v_incval>=v_newVal;'|| CHR(10) ||
' SELECT ' || v_seqName || '.nextval INTO v_incval FROM dual;'|| CHR(10) ||
' END LOOP;'|| CHR(10) ||
' END IF;'|| chr(10) ||
v_identityClause
||
' -- assign the value from the sequence to emulate the identity column'|| CHR(10) ||
' :new.' || v_ColumnName || ' := v_newVal;'|| CHR(10) ||
' END IF;' || CHR(10) ||
'END;' || CHR(10);
END GET_IDENTITY_TRIGGER;

FUNCTION get_plugin_name(p_connectionid MD_CONNECTIONS.ID%TYPE) RETURN VARCHAR2
IS
CURSOR v_pluginNameCur IS SELECT value FROM MD_ADDITIONAL_PROPERTIES WHERE prop_key='PLUGIN_ID' AND connection_id_fk = p_connectionid;
v_pluginName MD_ADDITIONAL_PROPERTIES.VALUE%TYPE;
BEGIN
OPEN v_pluginNameCur;
FETCH v_pluginNameCur INTO v_pluginName;
CLOSE v_pluginNameCur;
RETURN v_pluginName;
END get_plugin_name;

FUNCTION get_emulation_pkg_name(p_connectionid MD_CONNECTIONS.ID%TYPE) RETURN VARCHAR2
AS
v_pkgName VARCHAR2(1000);
v_pluginName MD_ADDITIONAL_PROPERTIES.VALUE%TYPE;
BEGIN
v_pluginName := get_plugin_name(p_connectionid);
IF LOWER(v_pluginName) LIKE '%sqlserver%'THEN
v_pkgName := 'sqlserver_utilities.';
ELSIF LOWER(v_pluginName) LIKE '%access%'THEN
v_pkgName := 'msaccess_utilities.';
ELSIF LOWER(v_pluginName) LIKE '%sybase%'THEN
v_pkgName := 'sybase_utilities.';
ELSIF LOWER(v_pluginName) LIKE '%mysql%' THEN
v_pkgName := 'mysql_utilities.';
END IF;
RETURN v_pkgName;
END get_emulation_pkg_name;

FUNCTION transform_identity_columns(p_connectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
CURSOR v_curs IS SELECT a.schema_id_fk, a.id tableid, a.TABLE_NAME, b.id, b.column_name
FROM md_tables a, md_columns b WHERE b.id IN
(SELECT ref_id_fk FROM md_additional_properties WHERE prop_key = C_PROPKEY_SEEDVALUE)
AND table_id_fk IN (SELECT table_id FROM mgv_all_tables WHERE connection_id = p_connectionid)
AND a.id = b.table_id_fk
AND b.id NOT IN (SELECT SRC_ID FROM MD_DERIVATIVES WHERE SRC_TYPE = C_OBJECTTYPE_COLUMNS AND DERIVED_TYPE = C_OBJECTTYPE_SEQUENCES AND
DERIVED_CONNECTION_ID_FK = p_connectionid);
v_schemaId MD_SCHEMAS.ID%TYPE;
v_tableId MD_TABLES.ID%TYPE;
v_tableName MD_TABLES.TABLE_NAME%TYPE;
v_columnId MD_COLUMNS.ID%TYPE;
v_columnName MD_COLUMNS.COLUMN_NAME%TYPE;
v_row MD_ADDITIONAL_PROPERTIES%ROWTYPE;
v_seedValue NUMBER;
-- Default the increment to 1 if it is not supplied.
v_increment NUMBER := 1;
v_lastVal NUMBER := NULL;
v_retId MD_SEQUENCES.ID%TYPE;
v_retSeqId MD_SEQUENCES.ID%TYPE;
v_seqName MD_SEQUENCES.NAME%TYPE;
v_trgName MD_TRIGGERS.TRIGGER_NAME%TYPE;
v_triggerText VARCHAR2(4000);
v_lob CLOB;
v_transRet NAME_AND_COUNT_T;
v_dbTypeCurs VARCHAR2(1000);
v_emulationPkgNamePrefix VARCHAR2(100) := '';
BEGIN
-- Auxillary, get the emulation package name
v_emulationPkgNamePrefix := get_emulation_pkg_name(p_connectionid);

OPEN v_curs;
LOOP
FETCH v_curs into v_schemaId, v_tableId, v_tableName, v_columnId, v_columnName;
EXIT WHEN v_curs%NOTFOUND;
-- The above query excludes already created sequences, so we should be ok.
-- create the sequence:
-- 1. Get the seedvalue, increment, lastvalue if present
FOR v_row in (SELECT * FROM MD_ADDITIONAL_PROPERTIES WHERE REF_ID_FK = v_columnId)
LOOP
IF v_row.PROP_KEY = C_PROPKEY_SEEDVALUE THEN
v_seedValue := TO_NUMBER(v_row.VALUE);
END IF;
IF v_row.PROP_KEY = C_PROPKEY_INCREMENT THEN
v_increment := TO_NUMBER(v_row.VALUE);
END IF;
IF v_row.PROP_KEY = C_PROPKEY_LASTVALUE THEN
v_lastVal := TO_NUMBER(v_row.VALUE);
END IF;
END LOOP;
-- Note: We'll start our sequence where the source left off.
IF v_lastVal IS NOT NULL THEN
v_seedValue := v_lastVal;
END IF;

-- 2. Create the sequence
-- Note: I'm adding _SEQ to the column name for now. We'll have to use the collision manager in the
-- future.
v_seqName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_tableName || '_' || v_columnName || '_SEQ');
INSERT INTO MD_SEQUENCES(SCHEMA_ID_FK, NAME, SEQ_START, INCR)
VALUES (v_schemaId, v_seqName, v_seedValue, v_increment)
RETURNING ID INTO v_retId;
v_retSeqId := v_retId;
-- And of course a new derivative record
INSERT INTO MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, TRANSFORMED, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_columnId, C_OBJECTTYPE_COLUMNS, v_retId, C_OBJECTTYPE_SEQUENCES, p_connectionId, C_TRANSFORMED_TRUE, NULL, v_seqName, C_NS_SCHEMA_OBJS || TO_CHAR(v_schemaId));
-- Create the trigger
v_trgName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_tableName || '_' || v_columnName || '_TRG');
v_triggerText := GET_IDENTITY_TRIGGER(v_trgName, v_tableName , v_ColumnName ,v_seqName ,v_emulationPkgNamePrefix);
-- Note: I'm adding _TRG to the column name for now.We'll have to use the collsion manager in the futre.
INSERT INTO MD_TRIGGERS(TABLE_OR_VIEW_ID_FK, TRIGGER_ON_FLAG, TRIGGER_NAME, TRIGGER_TIMING, TRIGGER_OPERATION, NATIVE_SQL, LANGUAGE)
VALUES(v_tableId, 'T', v_trgName, 'BEFORE', 'INSERT OR UPDATE', EMPTY_CLOB(), C_LANGUAGEID_ORACLE)
RETURNING ID INTO v_retId;
INSERT INTO MD_ADDITIONAL_PROPERTIES ( CONNECTION_ID_FK, REF_ID_FK, REF_TYPE, PROP_KEY, VALUE )
VALUES (p_connectionid, v_retId, C_OBJECTTYPE_TRIGGERS, C_PROPKEY_TRIGGER_REWRITE, '');
INSERT INTO MD_ADDITIONAL_PROPERTIES ( CONNECTION_ID_FK, REF_ID_FK, REF_TYPE, PROP_KEY, VALUE )
VALUES (p_connectionid, v_retId, C_OBJECTTYPE_TRIGGERS, C_PROPKEY_SEQUENCEID, TO_CHAR(v_retSeqId));
INSERT INTO MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, TRANSFORMED, ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE)
VALUES(v_columnId, C_OBJECTTYPE_COLUMNS, v_retId, C_OBJECTTYPE_TRIGGERS, p_connectionId, C_TRANSFORMED_TRUE, NULL, v_trgName, C_NS_SCHEMA_OBJS || TO_CHAR(v_schemaId));
SELECT NATIVE_SQL INTO v_lob FROM MD_TRIGGERS WHERE ID = v_retId;
DBMS_LOB.OPEN(v_lob, DBMS_LOB.LOB_READWRITE);
DBMS_LOB.WRITE(v_lob, LENGTH(v_triggerText), 1, v_triggerText);
DBMS_LOB.CLOSE(v_lob);
END LOOP;
COMMIT;
CLOSE v_curs;
RETURN 0;
END transform_identity_columns;




FUNCTION transform_rewrite_trigger(p_connectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
CURSOR v_curs is SELECT ID, TABLE_OR_VIEW_ID_FK, TRIGGER_ON_FLAG, TRIGGER_NAME,
TRIGGER_TIMING, TRIGGER_OPERATION, TRIGGER_EVENT, NATIVE_SQL, NATIVE_KEY,
LANGUAGE, COMMENTS from MD_TRIGGERS where ID in
(SELECT REF_ID_FK from MD_ADDITIONAL_PROPERTIES
WHERE CONNECTION_ID_FK = p_connectionid and PROP_KEY = C_PROPKEY_TRIGGER_REWRITE);

v_rowTriggers MD_TRIGGERS%ROWTYPE;
v_tableName MD_TABLES.TABLE_NAME%TYPE;
v_columnName MD_COLUMNS.COLUMN_NAME%TYPE;
v_retId MD_SEQUENCES.ID%TYPE;
v_retSeqId MD_SEQUENCES.ID%TYPE;
v_seqName MD_SEQUENCES.NAME%TYPE;
v_seqName2 MD_SEQUENCES.NAME%TYPE;
v_triggerText VARCHAR2(4000);
v_lob CLOB;
v_projectName VARCHAR2(100);
v_emulationPkgNamePrefix VARCHAR2(100) := '';
BEGIN
-- Auxillary, get the emulation package name
v_emulationPkgNamePrefix := get_emulation_pkg_name(p_connectionid);

open v_curs;
loop
fetch v_curs into v_rowTriggers.ID, v_rowTriggers.TABLE_OR_VIEW_ID_FK, v_rowTriggers.TRIGGER_ON_FLAG, v_rowTriggers.TRIGGER_NAME,
v_rowTriggers.TRIGGER_TIMING, v_rowTriggers.TRIGGER_OPERATION, v_rowTriggers.TRIGGER_EVENT, v_rowTriggers.NATIVE_SQL, v_rowTriggers.NATIVE_KEY,
v_rowTriggers.LANGUAGE, v_rowTriggers.COMMENTS ;
EXIT WHEN v_curs%NOTFOUND;
update MD_TRIGGERS set native_sql = empty_clob() where id = v_rowTriggers.ID;

-- get table and column name from the derivative of this trigger
select T.TABLE_NAME, C.COLUMN_NAME into v_tableName, v_columnName from MD_TABLES T,
MD_COLUMNS C where C.TABLE_ID_FK = T.ID and C.ID =
(select SRC_ID from MD_DERIVATIVES where DERIVED_ID = v_rowTriggers.ID and SRC_TYPE =
C_OBJECTTYPE_COLUMNS and DERIVED_CONNECTION_ID_FK = p_connectionid);
-- get sequence name from id got from additional property
select s.NAME into v_seqName from MD_SEQUENCES s where s.ID =
(select TO_NUMBER(VALUE) from MD_ADDITIONAL_PROPERTIES where CONNECTION_ID_FK = p_connectionid
AND REF_ID_FK = v_rowTriggers.ID and PROP_KEY = C_PROPKEY_SEQUENCEID);
v_triggerText := GET_IDENTITY_TRIGGER(v_rowTriggers.TRIGGER_NAME, v_tableName , v_ColumnName ,v_seqName ,v_emulationPkgNamePrefix);
SELECT NATIVE_SQL INTO v_lob FROM MD_TRIGGERS WHERE ID = v_rowTriggers.ID;
DBMS_LOB.OPEN(v_lob, DBMS_LOB.LOB_READWRITE);
DBMS_LOB.WRITE(v_lob, LENGTH(v_triggerText), 1, v_triggerText);
DBMS_LOB.CLOSE(v_lob);
END LOOP;
COMMIT;
CLOSE v_curs;
return 0;
END transform_rewrite_trigger;

PROCEDURE RefreshLineCountViews(p_connectionId MD_CONNECTIONS.ID%TYPE DEFAULT NULL)
IS
BEGIN
UPDATE (select s.*, ltrim(rtrim(s.native_sql,' ' ||' '|| chr(10)||chr(13)),' ' ||' '|| chr(10)||chr(13)) trimmed from md_stored_programs s) x
SET LINECOUNT = LENGTH(trimmed) - LENGTH(replace(trimmed,chr(10))) +1
WHERE linecount IS NULL;

UPDATE (select s.*, ltrim(rtrim(s.native_sql,' ' ||' '|| chr(10)||chr(13)),' ' ||' '|| chr(10)||chr(13)) trimmed from md_views s) x
SET LINECOUNT = LENGTH(trimmed) - LENGTH(replace(trimmed,chr(10))) +1
WHERE linecount IS NULL;

UPDATE (select s.*, ltrim(rtrim(s.native_sql,' ' ||' '|| chr(10)||chr(13)),' ' ||' '|| chr(10)||chr(13)) trimmed from md_triggers s) x
SET LINECOUNT = LENGTH(trimmed) - LENGTH(replace(trimmed,chr(10))) +1
WHERE linecount IS NULL;
END;

FUNCTION gatherConnectionStats(p_connectionId MD_CONNECTIONS.ID%TYPE,p_comments MD_CONNECTIONS.COMMENTS%TYPE) RETURN NUMBER
IS
v_numCatalogs INTEGER := 0;
v_numColumns INTEGER := 0;
v_numConstraints INTEGER := 0;
v_numGroups INTEGER := 0;
v_numRoles INTEGER := 0;
v_numIndexes INTEGER := 0;
v_numOtherObjects INTEGER := 0;
v_numPackages INTEGER := 0;
v_numPrivileges INTEGER := 0;
v_numSchemas INTEGER := 0;
v_numSequences INTEGER := 0;
v_numStoredPrograms INTEGER := 0;
v_numSynonyms INTEGER := 0;
v_numTables INTEGER := 0;
v_numTableSpaces INTEGER := 0;
v_numTriggers INTEGER := 0;
v_numUserDefinedDataTypes INTEGER := 0;
v_numUsers INTEGER := 0;
v_numViews INTEGER := 0;
BEGIN
SELECT COUNT(*) INTO v_numCatalogs FROM MD_CATALOGS WHERE CONNECTION_ID_FK = p_connectionId;
SELECT COUNT(*) INTO v_numColumns FROM MD_COLUMNS WHERE TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numConstraints FROM MD_CONSTRAINTS WHERE TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numGroups FROM MD_GROUPS WHERE GROUP_FLAG = 'G' AND SCHEMA_ID_FK IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numRoles FROM MD_GROUPS WHERE GROUP_FLAG = 'R' AND SCHEMA_ID_FK IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numIndexes FROM MD_INDEXES WHERE TABLE_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numOtherObjects FROM MD_OTHER_OBJECTS WHERE SCHEMA_ID_FK IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numPackages FROM MD_PACKAGES WHERE SCHEMA_ID_FK IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numPrivileges FROM MD_PRIVILEGES WHERE SCHEMA_ID_FK IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numSchemas FROM MD_SCHEMAS WHERE CATALOG_ID_FK IN (SELECT CATALOG_ID FROM MGV_ALL_CATALOGS WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numSequences FROM MD_SEQUENCES WHERE SCHEMA_ID_FK IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numStoredPrograms FROM MD_STORED_PROGRAMS WHERE SCHEMA_ID_FK IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numSynonyms FROM MD_SYNONYMS WHERE SCHEMA_ID_FK IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numTables FROM MD_TABLES WHERE SCHEMA_ID_FK IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numTableSpaces FROM MD_TABLESPACES WHERE SCHEMA_ID_FK IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numTriggers FROM MD_TRIGGERS WHERE TABLE_OR_VIEW_ID_FK IN (SELECT TABLE_ID FROM MGV_ALL_TABLES WHERE CONNECTION_ID = p_connectionId
UNION SELECT VIEW_ID FROM MGV_ALL_VIEWS WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numUserDefinedDataTypes FROM MD_USER_DEFINED_DATA_TYPES WHERE SCHEMA_ID_FK IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numUsers FROM MD_USERS WHERE SCHEMA_ID_FK IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionId);
SELECT COUNT(*) INTO v_numViews FROM MD_VIEWS WHERE SCHEMA_ID_FK IN (SELECT SCHEMA_ID FROM MGV_ALL_SCHEMA WHERE CONNECTION_ID = p_connectionId);
UPDATE MD_CONNECTIONS SET
NUM_CATALOGS = v_numCatalogs,
NUM_COLUMNS = v_numColumns,
NUM_CONSTRAINTS = v_numConstraints,
NUM_GROUPS = v_numGroups,
NUM_ROLES = v_numRoles,
NUM_INDEXES = v_numIndexes,
NUM_OTHER_OBJECTS = v_numOtherObjects,
NUM_PACKAGES = v_numPackages,
NUM_PRIVILEGES = v_numPrivileges,
NUM_SCHEMAS = v_numSchemas,
NUM_SEQUENCES = v_numSequences,
NUM_STORED_PROGRAMS = v_numStoredPrograms,
NUM_SYNONYMS = v_numSynonyms,
NUM_TABLES = v_numTables,
NUM_TABLESPACES = v_numTableSpaces,
NUM_TRIGGERS = v_numTriggers,
NUM_USER_DEFINED_DATA_TYPES = v_numUserDefinedDataTypes,
num_users = v_numusers,
num_views = v_numviews,
COMMENTS = COMMENTS || p_comments
WHERE ID = p_connectionId;
COMMIT;
RefreshLineCountViews(p_connectionId);
COMMIT;
RETURN 0;
END gatherConnectionStats;

--
-- Procedures that start with "insert_*" insert a copy of MD_* values into MD_DERIVATIVES table.
-- MD_* are MD_COLUMNS, MD_CONSTRAINTS, MD_TABLES, MD_TRIGGERS, MD_INDEXES, MD_SEQUENCES, MD_STORED_PROGRAMS
-- AND MD_VIEWS
--
PROCEDURE insert_all_columns(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_tableid MD_TABLES.ID%TYPE)
IS
cv_curs REF_CURSOR;
v_row MD_COLUMNS%ROWTYPE;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_COLUMNS WHERE TABLE_ID_FK = ' || p_tableid;
v_newName MD_COLUMNS.COLUMN_NAME%TYPE;
v_transformed MD_DERIVATIVES.TRANSFORMED%TYPE := NULL;
BEGIN
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;

v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_row.COLUMN_NAME);
if v_row.COLUMN_NAME <> v_newName then
v_transformed := C_TRANSFORMED_TRUE;
end if;

INSERT INTO
MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, TRANSFORMED,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE, DERIVATIVE_REASON)
VALUES(v_row.id, C_OBJECTTYPE_COLUMNS, v_row.id, C_OBJECTTYPE_COLUMNS, p_connectionid, v_transformed,
v_row.COLUMN_NAME, v_newName, C_OBJECTTYPE_COLUMNS || TO_CHAR(p_tableid), C_CONNECTIONTYPE_SCRATCH);

END LOOP;
close cv_curs;
END insert_all_columns;

PROCEDURE insert_all_indexes(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_tableid MD_TABLES.ID%TYPE)
IS
cv_curs REF_CURSOR;
v_row MD_INDEXES%ROWTYPE;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_INDEXES WHERE MD_INDEXES.TABLE_ID_FK = ' || p_tableid;
v_newName MD_INDEXES.INDEX_NAME%TYPE;
v_transformed MD_DERIVATIVES.TRANSFORMED%TYPE := NULL;
BEGIN
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;

v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_row.INDEX_NAME);
if v_row.INDEX_NAME <> v_newName then
v_transformed := C_TRANSFORMED_TRUE;
end if;

INSERT INTO
MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, TRANSFORMED,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE, DERIVATIVE_REASON)
VALUES(v_row.id, C_OBJECTTYPE_INDEXES, v_row.id, C_OBJECTTYPE_INDEXES, p_connectionid, v_transformed,
v_row.INDEX_NAME, v_newName, C_OBJECTTYPE_INDEXES || TO_CHAR(p_tableid), C_CONNECTIONTYPE_SCRATCH);

END LOOP;
close cv_curs;
END insert_all_indexes;

PROCEDURE insert_all_table_triggers(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_tableid MD_TABLES.ID%TYPE)
IS
cv_curs REF_CURSOR;
v_row MD_TRIGGERS%ROWTYPE;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_TRIGGERS WHERE MD_TRIGGERS.TABLE_OR_VIEW_ID_FK = ' || p_tableid;
v_newName MD_TRIGGERS.TRIGGER_NAME%TYPE;
v_transformed MD_DERIVATIVES.TRANSFORMED%TYPE := NULL;
BEGIN
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;

v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_row.TRIGGER_NAME);
if v_row.TRIGGER_NAME <> v_newName then
v_transformed := C_TRANSFORMED_TRUE;
end if;

INSERT INTO
MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, TRANSFORMED,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE, DERIVATIVE_REASON)
VALUES(v_row.id, C_OBJECTTYPE_TRIGGERS, v_row.id, C_OBJECTTYPE_TRIGGERS, p_connectionid, v_transformed,
v_row.TRIGGER_NAME, v_newName, C_NS_DB_TRIGGERS || TO_CHAR(p_tableid), C_CONNECTIONTYPE_SCRATCH);

END LOOP;
close cv_curs;
END insert_all_table_triggers;

PROCEDURE insert_all_constraints(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_tableid MD_TABLES.ID%TYPE)
IS
cv_curs REF_CURSOR;
v_row MD_CONSTRAINTS%ROWTYPE;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_CONSTRAINTS WHERE MD_CONSTRAINTS.TABLE_ID_FK = ' || p_tableid;
v_newName MD_CONSTRAINTS.NAME%TYPE;
v_transformed MD_DERIVATIVES.TRANSFORMED%TYPE := NULL;
BEGIN
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;

v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_row.NAME);
if v_row.NAME <> v_newName then
v_transformed := C_TRANSFORMED_TRUE;
end if;

INSERT INTO
MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, TRANSFORMED,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE, DERIVATIVE_REASON)
VALUES(v_row.id, C_OBJECTTYPE_CONSTRAINTS, v_row.id, C_OBJECTTYPE_CONSTRAINTS, p_connectionid, v_transformed,
v_row.NAME, v_newName, C_NS_CONSTRAINTS || TO_CHAR(p_tableid), C_CONNECTIONTYPE_SCRATCH);

END LOOP;
close cv_curs;
END insert_all_constraints;


PROCEDURE insert_all_tables_cascade(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_schemaid MD_SCHEMAS.ID%TYPE)
IS
cv_curs REF_CURSOR;
v_row MD_TABLES%ROWTYPE;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_TABLES where SCHEMA_ID_FK = ' || p_schemaid;
v_newName MD_TABLES.TABLE_NAME%TYPE;
v_transformed MD_DERIVATIVES.TRANSFORMED%TYPE := NULL;

BEGIN
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;

v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_row.TABLE_NAME);
if v_row.TABLE_NAME <> v_newName then
v_transformed := C_TRANSFORMED_TRUE;
end if;

INSERT INTO
MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, TRANSFORMED,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE, DERIVATIVE_REASON)
VALUES(v_row.id, C_OBJECTTYPE_TABLES, v_row.id, C_OBJECTTYPE_TABLES, p_connectionid, v_transformed,
v_row.TABLE_NAME, v_newName, C_NS_SCHEMA_OBJS || TO_CHAR(p_schemaid), C_CONNECTIONTYPE_SCRATCH);

insert_all_columns(p_connectionid, v_row.id);
insert_all_indexes(p_connectionid, v_row.id);
insert_all_table_triggers(p_connectionid, v_row.id);
insert_all_constraints(p_connectionid, v_row.id);

END LOOP;
close cv_curs;
END insert_all_tables_cascade;

PROCEDURE insert_all_views(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_schemaid MD_SCHEMAS.ID%TYPE)
IS
cv_curs REF_CURSOR;
v_row MD_VIEWS%ROWTYPE;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_VIEWS WHERE SCHEMA_ID_FK = ' || p_schemaid;
v_newName MD_VIEWS.VIEW_NAME%TYPE;
v_transformed MD_DERIVATIVES.TRANSFORMED%TYPE := NULL;

BEGIN
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;

v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_row.VIEW_NAME);
if v_row.VIEW_NAME <> v_newName then
v_transformed := C_TRANSFORMED_TRUE;
end if;

INSERT INTO
MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, TRANSFORMED,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE, DERIVATIVE_REASON)
VALUES(v_row.id, C_OBJECTTYPE_VIEWS, v_row.id, C_OBJECTTYPE_VIEWS, p_connectionid, v_transformed,
v_row.VIEW_NAME, v_newName, C_NS_SCHEMA_OBJS || TO_CHAR(p_schemaid), C_CONNECTIONTYPE_SCRATCH);

END LOOP;
close cv_curs;
END insert_all_views;

PROCEDURE insert_all_sequences(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_schemaid MD_SCHEMAS.ID%TYPE)
IS
cv_curs REF_CURSOR;
v_row MD_SEQUENCES%ROWTYPE;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_SEQUENCES WHERE SCHEMA_ID_FK = ' || p_schemaid;
v_newName MD_SEQUENCES.NAME%TYPE;
v_transformed MD_DERIVATIVES.TRANSFORMED%TYPE := NULL;

BEGIN
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;

v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_row.NAME);
if v_row.NAME <> v_newName then
v_transformed := C_TRANSFORMED_TRUE;
end if;

INSERT INTO
MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, TRANSFORMED,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE, DERIVATIVE_REASON)
VALUES(v_row.id, C_OBJECTTYPE_SEQUENCES, v_row.id, C_OBJECTTYPE_SEQUENCES, p_connectionid, v_transformed,
v_row.NAME, v_newName, C_NS_SCHEMA_OBJS || TO_CHAR(p_schemaid), C_CONNECTIONTYPE_SCRATCH);

END LOOP;
close cv_curs;
END insert_all_sequences;

PROCEDURE insert_all_unpackaged_sps(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_schemaid MD_SCHEMAS.ID%TYPE)
IS
cv_curs REF_CURSOR;
v_row MD_STORED_PROGRAMS%ROWTYPE;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_STORED_PROGRAMS WHERE SCHEMA_ID_FK = ' || p_schemaid || ' AND PACKAGE_ID_FK IS NULL';
v_newName MD_STORED_PROGRAMS.NAME%TYPE;
v_transformed MD_DERIVATIVES.TRANSFORMED%TYPE := NULL;

BEGIN
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;

v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_row.NAME);
if v_row.NAME <> v_newName then
v_transformed := C_TRANSFORMED_TRUE;
end if;

INSERT INTO
MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, TRANSFORMED,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE, DERIVATIVE_REASON)
VALUES(v_row.id, C_OBJECTTYPE_STORED_PROGRAMS, v_row.id, C_OBJECTTYPE_STORED_PROGRAMS, p_connectionid, v_transformed,
v_row.NAME, v_newName, C_NS_SCHEMA_OBJS || TO_CHAR(p_schemaid), C_CONNECTIONTYPE_SCRATCH);

END LOOP;
close cv_curs;
END insert_all_unpackaged_sps;


PROCEDURE insert_all_schobjs_cascade(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_schemaid MD_SCHEMAS.ID%TYPE)
IS
BEGIN
insert_all_tables_cascade(p_connectionid, p_schemaid);
insert_all_views(p_connectionid, p_schemaid);
insert_all_sequences(p_connectionid, p_schemaid);
insert_all_unpackaged_sps(p_connectionid, p_schemaid);
END insert_all_schobjs_cascade;


PROCEDURE insert_catalogs_cascade(p_connectionid MD_CONNECTIONS.ID%TYPE,
p_catalogid MD_CATALOGS.ID%TYPE)
IS
cv_curs REF_CURSOR;
v_selectStmt VARCHAR2(4000) := 'SELECT a.id schema_id, A.name schema_name, b.id catalog_id, B.CATALOG_NAME, B.DUMMY_FLAG, A.type, A.character_set, A.version_tag
FROM MD_SCHEMAS A, MD_CATALOGS B
WHERE
A.CATALOG_ID_FK = B.ID
AND B.ID =' || p_catalogid ||
' AND CONNECTION_ID_FK = ' || p_connectionid ;
v_derivedRec DERIVATIVE_REC;
v_newName MD_SCHEMAS.NAME%TYPE;
v_transformed MD_DERIVATIVES.TRANSFORMED%TYPE := NULL;
BEGIN
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_derivedRec;
EXIT WHEN cv_curs%NOTFOUND;

if v_derivedRec.dummy_flag <> C_DUMMYFLAG_TRUE then
v_newName := v_derivedRec.schema_name || '_' || v_derivedRec.catalog_name;
v_transformed := C_TRANSFORMED_TRUE;
else
v_newName := v_derivedRec.schema_name;
end if;

if v_newName <> MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_newName) then
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_newName);
v_transformed := C_TRANSFORMED_TRUE;
end if;

INSERT INTO
MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, TRANSFORMED,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE, DERIVATIVE_REASON)
VALUES (v_derivedRec.schema_id, C_OBJECTTYPE_SCHEMAS, v_derivedRec.schema_id, C_OBJECTTYPE_SCHEMAS, p_connectionid, v_transformed,
v_derivedRec.schema_name, v_newName, C_NS_DATABASE, C_CONNECTIONTYPE_SCRATCH);

INSERT INTO
MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, TRANSFORMED,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE, DERIVATIVE_REASON)
VALUES(v_derivedRec.catalog_id, C_OBJECTTYPE_CATALOGS, v_derivedRec.catalog_id, C_OBJECTTYPE_SCHEMAS, p_connectionid, v_transformed,
v_derivedRec.catalog_name, v_newName, NULL, C_CONNECTIONTYPE_SCRATCH);

insert_all_schobjs_cascade(p_connectionid, v_derivedRec.schema_id);

END LOOP;
close cv_curs;
END insert_catalogs_cascade;


PROCEDURE insert_connection_cascade(p_connectionid MD_CONNECTIONS.ID%TYPE)
IS
v_connectionsRow MD_CONNECTIONS%ROWTYPE;
v_origName MD_CONNECTIONS.NAME%TYPE;
v_newName MD_CONNECTIONS.NAME%TYPE;
v_id MD_CONNECTIONS.ID%TYPE;
v_catid MD_CATALOGS.ID%TYPE;
v_transformed MD_DERIVATIVES.TRANSFORMED%TYPE := NULL;
cv_curs REF_CURSOR;

BEGIN
SELECT * INTO v_connectionsRow from MD_CONNECTIONS WHERE "ID" = p_connectionid;
v_origName := v_connectionsRow.NAME;
v_newName := v_origName;
v_id := v_connectionsRow.ID;

if v_newName <> MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_newName) then
v_newName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_newName);
v_transformed := C_TRANSFORMED_TRUE;
end if;

INSERT INTO
MD_DERIVATIVES(SRC_ID, SRC_TYPE, DERIVED_ID, DERIVED_TYPE, DERIVED_CONNECTION_ID_FK, TRANSFORMED,
ORIGINAL_IDENTIFIER, NEW_IDENTIFIER, DERIVED_OBJECT_NAMESPACE, DERIVATIVE_REASON)
VALUES(v_id , C_OBJECTTYPE_CONNECTIONS, v_id, C_OBJECTTYPE_CONNECTIONS, v_id, v_transformed,
v_origName, v_newName, '', C_CONNECTIONTYPE_SCRATCH);

OPEN cv_curs FOR 'SELECT id from MD_CATALOGS where connection_id_fk ='|| v_connectionsRow.id;
LOOP
FETCH cv_curs INTO v_catid;
EXIT WHEN cv_curs%NOTFOUND;

insert_catalogs_cascade(v_id, v_catid);
END LOOP;
END insert_connection_cascade;

PROCEDURE populate_derivatives_table(p_connectionid MD_CONNECTIONS.ID%TYPE)
IS
BEGIN
insert_connection_cascade(p_connectionid);
END populate_derivatives_table;

--
-- reverts NEW_IDENTIFIER values back to their default(derived) values in MD_DERIVATIVES table.
--
PROCEDURE revert_derivatives_table(p_connectionid MD_CONNECTIONS.ID%TYPE)
IS
cv_curs REF_CURSOR;
v_row MD_DERIVATIVES%ROWTYPE;
v_origName MD_DERIVATIVES.ORIGINAL_IDENTIFIER%TYPE;
v_derivedName MD_DERIVATIVES.NEW_IDENTIFIER%TYPE;
v_transformed MD_DERIVATIVES.TRANSFORMED%TYPE;
v_selectStmt VARCHAR2(4000) := 'SELECT * FROM MD_DERIVATIVES
WHERE DERIVED_CONNECTION_ID_FK = ' || p_connectionid ;
BEGIN
OPEN cv_curs FOR v_selectStmt;
LOOP
FETCH cv_curs INTO v_row;
EXIT WHEN cv_curs%NOTFOUND;

v_transformed := NULL;
v_derivedName := MIGRATION_TRANSFORMER.TRANSFORM_IDENTIFIER(v_row.ORIGINAL_IDENTIFIER);
if v_row.NEW_IDENTIFIER <> v_derivedName then
if v_row.ORIGINAL_IDENTIFIER <> v_derivedName then
v_transformed := C_TRANSFORMED_TRUE;
end if;

UPDATE MD_DERIVATIVES SET TRANSFORMED = v_transformed, NEW_IDENTIFIER = v_derivedName WHERE
SRC_ID = v_row.SRC_ID and DERIVED_CONNECTION_ID_FK = p_connectionid ;
end if;
END LOOP;
CLOSE cv_curs;
END revert_derivatives_table;


-- One time initialisation
begin
NULL;
end;

 

MIGRATION_WORKBENCH.MIGRATION_REPORT

Specification
AS 
--get status
FUNCTION getCaptureStatus(srcid IN NUMBER) RETURN VARCHAR2;
FUNCTION getConvertStatus(srcid IN NUMBER,convert_conn_id IN NUMBER) RETURN VARCHAR2;
FUNCTION getGenerateStatus(srcid IN NUMBER,convert_conn_id IN NUMBER) RETURN VARCHAR2;
--migration details
FUNCTION getDetails(capture_conn_id IN NUMBER,convert_conn_id IN NUMBER) RETURN MIGR_REPORT_DETAIL_TABLE PIPELINED;
--migration summary
FUNCTION getSum(capture_conn_id IN NUMBER,convert_conn_id IN NUMBER) RETURN MIGR_REPORT_SUM_TABLE PIPELINED;
END MIGRATION_REPORT;
Body Definition
AS
--Function getCaptureStatus
FUNCTION getCaptureStatus(srcid IN NUMBER) RETURN VARCHAR2 IS
status VARCHAR(20) default ' ';
BEGIN
select decode((select count(*) from migrlog where ref_object_id=srcid and severity>800),0,'Passed','Failed') into status from dual;
return status;
END getCaptureStatus;
--Function getConvertStatus
FUNCTION getConvertStatus(srcid IN NUMBER,convert_conn_id IN NUMBER) RETURN VARCHAR2 IS
status VARCHAR(20) default ' ';
ifconvert NUMBER default 0;
BEGIN
SELECT count(*) into ifconvert FROM md_derivatives WHERE src_id=srcid and derived_connection_id_fk=convert_conn_id;
IF ifconvert=0 THEN
RETURN 'NotConverted';
ELSIF getCaptureStatus(srcid)='Failed' THEN
RETURN 'Failed';
ELSE
BEGIN
SELECT
decode((SELECT DISTINCT severity from migrlog
WHERE ref_object_id IN (SELECT derived_id FROM md_derivatives WHERE src_id=srcid and derived_connection_id_fk= convert_conn_id)
and severity=1000
UNION
SELECT DISTINCT severity from migrlog
WHERE ref_object_id IN (SELECT derived_id FROM md_derivatives where src_id=srcid and derived_connection_id_fk=convert_conn_id)
AND severity=900
AND logtext like '%limitation%'),
null,'Passed',1000,'Failed',900,'Limitation',' ')
into status from dual;
return status;
END;
END IF;
END getConvertStatus;
--Function getGenerateStatus
FUNCTION getGenerateStatus(srcid IN number,convert_conn_id IN NUMBER) RETURN VARCHAR2 IS
status VARCHAR(20) default ' ';

BEGIN
status:=getConvertStatus(srcid,convert_conn_id);
IF status='NotConverted' THEN
RETURN 'NotGenerated';
ELSIF status='Failed' THEN
RETURN 'Failed';
ELSE
BEGIN
SELECT
decode((SELECT count(*) FROM migrlog
WHERE ref_object_id IN (SELECT derived_id FROM md_derivatives WHERE src_id=srcid and derived_connection_id_fk=convert_conn_id)
AND phase='Generate'
AND severity>800),
0,'Passed','Failed')
INTO status FROM dual;
RETURN status;
END;
END IF;
END getGenerateStatus;
--migration details for each objects
FUNCTION getDetails(capture_conn_id IN NUMBER,convert_conn_id IN NUMBER) RETURN migr_report_detail_table PIPELINED IS
BEGIN
FOR cur IN (
select allobjs.ObjID captured_id,
allobjs.ObjName captured_name,
md.new_identifier converted_name,
allobjs.ObjType captured_type,
decode(md.derived_type,'MD_INDEXES', substr(md.derived_type,4, length(md.derived_type)-5),substr(md.derived_type,4, length(md.derived_type)-4)) converted_type,
allobjs.CaptureStatus capture_status,
allobjs.ConvertStatus convert_status,
allobjs.GenerateStatus generate_status,
decode(mlog.logtext,null,' ',mlog.logtext) logtext from (
--schema
SELECT md_schemas.id ObjID,md_schemas.name ObjName,'SCHEMA' ObjType,
MIGRATION_REPORT.getCaptureStatus(md_schemas.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_schemas.id,convert_conn_id) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_schemas.id,convert_conn_id) GenerateStatus
FROM md_schemas,md_catalogs
WHERE md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=capture_conn_id
--table
UNION ALL
SELECT md_tables.id ObjID,md_tables.table_name ObjName,'TABLE' ObjType,
MIGRATION_REPORT.getCaptureStatus(md_tables.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_tables.id,convert_conn_id) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_tables.id,convert_conn_id) GenerateStatus
FROM md_tables,md_schemas,md_catalogs
WHERE md_tables.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=capture_conn_id
--view
UNION ALL
SELECT md_views.id ObjID,md_views.view_name ObjName,'View' ObjType,
MIGRATION_REPORT.getCaptureStatus(md_views.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_views.id,convert_conn_id) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_views.id,convert_conn_id) GenerateStatus
FROM md_views,md_schemas,md_catalogs
WHERE md_views.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=capture_conn_id
--storedprogram
UNION ALL
SELECT md_stored_programs.id ObjID,md_stored_programs.name ObjName,'STORED_PROGRAM' ObjType,
MIGRATION_REPORT.getCaptureStatus(md_stored_programs.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_stored_programs.id,convert_conn_id) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_stored_programs.id,convert_conn_id) GenerateStatus
FROM md_stored_programs,md_schemas,md_catalogs
WHERE md_stored_programs.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=capture_conn_id
--index
UNION ALL
SELECT md_indexes.id ObjID,md_indexes.index_name ObjName,'INDEX' ObjType,
MIGRATION_REPORT.getCaptureStatus(md_indexes.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_indexes.id,convert_conn_id) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_indexes.id,convert_conn_id) GenerateStatus
FROM md_indexes, md_tables,md_schemas,md_catalogs
WHERE md_indexes.table_id_fk= md_tables.id
AND md_tables.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=capture_conn_id
UNION ALL
SELECT md_constraints.id ObjID,md_constraints.name ObjName,'CONSTRAINT' ObjType,
MIGRATION_REPORT.getCaptureStatus(md_constraints.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_constraints.id,convert_conn_id) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_constraints.id,convert_conn_id) GenerateStatus
FROM md_constraints, md_tables,md_schemas,md_catalogs
WHERE md_constraints.table_id_fk= md_tables.id
AND md_tables.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=capture_conn_id
UNION ALL
SELECT md_triggers.id ObjID,md_triggers.trigger_name ObjName,'TRIGGER' ObjType,
MIGRATION_REPORT.getCaptureStatus(md_triggers.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_triggers.id,convert_conn_id) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_triggers.id,convert_conn_id) GenerateStatus
FROM md_triggers, md_tables,md_schemas,md_catalogs
WHERE md_triggers.table_or_view_id_fk=md_tables.id
AND md_tables.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=capture_conn_id
UNION ALL
SELECT md_triggers.id ObjID,md_triggers.trigger_name ObjName,'TRIGGER' ObjType,
MIGRATION_REPORT.getCaptureStatus(md_triggers.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_triggers.id,convert_conn_id) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_triggers.id,convert_conn_id) GenerateStatus
FROM md_triggers, md_views,md_schemas,md_catalogs
WHERE md_triggers.table_or_view_id_fk=md_views.id
AND md_views.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=capture_conn_id
) allobjs left join (select md_derivatives.src_id,migrlog.logtext
from migrlog,md_derivatives
where migrlog.ref_object_id = md_derivatives.derived_id or migrlog.ref_object_id=md_derivatives.src_id) mlog
on allobjs.objid=mlog.src_id left join md_derivatives md on allobjs.objid=md.src_id
)
LOOP
PIPE ROW(MIGR_REPORT_DETAIL_ROW(cur.captured_id,
cur.captured_name,
cur.converted_name,
cur.captured_type,
cur.converted_type,
cur.capture_status,
cur.convert_status,
cur.generate_status,
cur.logtext
));

END LOOP;
RETURN;
END getDetails;

--migration summary
FUNCTION getSum(capture_conn_id IN NUMBER,convert_conn_id IN NUMBER) RETURN migr_report_sum_table PIPELINED IS
--
capture_passed_schema number default 0;
capture_passed_table number default 0;
capture_passed_view number default 0;
capture_passed_sp number default 0;
capture_passed_index number default 0;
capture_passed_constraint number default 0;
capture_passed_trigger number default 0;
--
capture_failed_schema number default 0;
capture_failed_table number default 0;
capture_failed_view number default 0;
capture_failed_sp number default 0;
capture_failed_index number default 0;
capture_failed_constraint number default 0;
capture_failed_trigger number default 0;
--
convert_passed_schema number default 0;
convert_passed_table number default 0;
convert_passed_view number default 0;
convert_passed_sp number default 0;
convert_passed_index number default 0;
convert_passed_constraint number default 0;
convert_passed_trigger number default 0;
--
convert_limit_schema number default 0;
convert_limit_table number default 0;
convert_limit_view number default 0;
convert_limit_sp number default 0;
convert_limit_index number default 0;
convert_limit_constraint number default 0;
convert_limit_trigger number default 0;
--
convert_failed_schema number default 0;
convert_failed_table number default 0;
convert_failed_view number default 0;
convert_failed_sp number default 0;
convert_failed_index number default 0;
convert_failed_constraint number default 0;
convert_failed_trigger number default 0;
--
convert_not_schema number default 0;
convert_not_table number default 0;
convert_not_view number default 0;
convert_not_sp number default 0;
convert_not_index number default 0;
convert_not_constraint number default 0;
convert_not_trigger number default 0;
--
generate_passed_schema number default 0;
generate_passed_table number default 0;
generate_passed_view number default 0;
generate_passed_sp number default 0;
generate_passed_index number default 0;
generate_passed_constraint number default 0;
generate_passed_trigger number default 0;
--
generate_failed_schema number default 0;
generate_failed_table number default 0;
generate_failed_view number default 0;
generate_failed_sp number default 0;
generate_failed_index number default 0;
generate_failed_constraint number default 0;
generate_failed_trigger number default 0;
--
generate_not_schema number default 0;
generate_not_table number default 0;
generate_not_view number default 0;
generate_not_sp number default 0;
generate_not_index number default 0;
generate_not_constraint number default 0;
generate_not_trigger number default 0;
--CURSORS
--SCHEMAS CURSOR
CURSOR schema_status(cid IN NUMBER,did IN NUMBER) IS
SELECT
MIGRATION_REPORT.getCaptureStatus(md_schemas.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_schemas.id,did) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_schemas.id,did) GenerateStatus
FROM md_schemas,md_catalogs
WHERE md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=cid;
--TABLES CURSOR
CURSOR table_status(cid IN NUMBER,did IN NUMBER) IS
SELECT
MIGRATION_REPORT.getCaptureStatus(md_tables.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_tables.id,did) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_tables.id,did) GenerateStatus
FROM md_tables,md_schemas,md_catalogs
WHERE md_tables.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=cid;
--VIEWS CURSOR
CURSOR view_status(cid IN NUMBER,did IN NUMBER) IS
SELECT
MIGRATION_REPORT.getCaptureStatus(md_views.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_views.id,did) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_views.id,did) GenerateStatus
FROM md_views,md_schemas,md_catalogs
WHERE md_views.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=cid;
--STORED_PROGRAMS CURSOR
CURSOR sp_status(cid IN NUMBER,did IN NUMBER) IS
SELECT
MIGRATION_REPORT.getCaptureStatus(md_stored_programs.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_stored_programs.id,did) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_stored_programs.id,did) GenerateStatus
FROM md_stored_programs,md_schemas,md_catalogs
WHERE md_stored_programs.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=cid;
--INDEXES CURSOR
CURSOR index_status(cid IN NUMBER,did IN NUMBER) IS
SELECT
MIGRATION_REPORT.getCaptureStatus(md_indexes.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_indexes.id,did) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_indexes.id,did) GenerateStatus
FROM md_indexes, md_tables,md_schemas,md_catalogs
WHERE md_indexes.table_id_fk= md_tables.id
AND md_tables.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=cid;
--CONSTRAINTS CURSOR
CURSOR constraint_status(cid IN NUMBER,did IN NUMBER) IS
SELECT
MIGRATION_REPORT.getCaptureStatus(md_constraints.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_constraints.id,did) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_constraints.id,did) GenerateStatus
FROM md_constraints, md_tables,md_schemas,md_catalogs
WHERE md_constraints.table_id_fk= md_tables.id
AND md_tables.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=cid;
--TRIGGERS CURSOR
CURSOR trigger_status(cid IN NUMBER,did IN NUMBER) IS
SELECT
MIGRATION_REPORT.getCaptureStatus(md_triggers.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_triggers.id,did) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_triggers.id,did) GenerateStatus
FROM md_triggers, md_tables,md_schemas,md_catalogs
WHERE md_triggers.table_or_view_id_fk=md_tables.id
AND md_tables.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=cid
UNION ALL
SELECT
MIGRATION_REPORT.getCaptureStatus(md_triggers.id) CaptureStatus,
MIGRATION_REPORT.getConvertStatus(md_triggers.id,did) ConvertStatus,
MIGRATION_REPORT.getGenerateStatus(md_triggers.id,did) GenerateStatus
FROM md_triggers, md_views,md_schemas,md_catalogs
WHERE md_triggers.table_or_view_id_fk=md_views.id
AND md_views.schema_id_fk=md_schemas.id
AND md_schemas.catalog_id_fk= md_catalogs.id
AND md_catalogs.connection_id_fk=cid;
BEGIN
--count
--schemas
FOR cur IN schema_status(capture_conn_id,convert_conn_id)
LOOP
IF cur.capturestatus='Failed'
THEN capture_failed_schema:=capture_failed_schema+1;
ELSE capture_passed_schema:=capture_passed_schema+1;
END IF;

IF cur.convertstatus='Failed'
THEN convert_failed_schema:=convert_failed_schema+1;
ELSIF cur.convertstatus='Limitation'
THEN convert_limit_schema:=convert_limit_schema+1;
ELSIF cur.convertstatus='Passed'
THEN convert_passed_schema:=convert_passed_schema+1;
ELSE convert_not_schema:=convert_not_schema+1;
END IF;

IF cur.generatestatus='Failed'
THEN generate_failed_schema:=generate_failed_schema+1;
ELSIF cur.generatestatus='Passed'
THEN generate_passed_schema:=generate_passed_schema+1;
ELSE generate_not_schema:=generate_not_schema+1;
END IF;
END LOOP;
--tables
FOR cur IN table_status(capture_conn_id,convert_conn_id)
LOOP
IF cur.capturestatus='Failed'
THEN capture_failed_table:=capture_failed_table+1;
ELSE capture_passed_table:=capture_passed_table+1;
END IF;

IF cur.convertstatus='Failed'
THEN convert_failed_table:=convert_failed_table+1;
ELSIF cur.convertstatus='Limitation'
THEN convert_limit_table:=convert_limit_table+1;
ELSIF cur.convertstatus='Passed'
THEN convert_passed_table:=convert_passed_table+1;
ELSE convert_not_table:=convert_not_table+1;
END IF;

IF cur.generatestatus='Failed'
THEN generate_failed_table:=generate_failed_table+1;
ELSIF cur.generatestatus='Passed'
THEN generate_passed_table:=generate_passed_table+1;
ELSE generate_not_table:=generate_not_table+1;
END IF;
END LOOP;
--views
FOR cur IN view_status(capture_conn_id,convert_conn_id)
LOOP
IF cur.capturestatus='Failed'
THEN capture_failed_view:=capture_failed_view+1;
ELSE capture_passed_view:=capture_passed_view+1;
END IF;

IF cur.convertstatus='Failed'
THEN convert_failed_view:=convert_failed_view+1;
ELSIF cur.convertstatus='Limitation'
THEN convert_limit_view:=convert_limit_view+1;
ELSIF cur.convertstatus='Passed'
THEN convert_passed_view:=convert_passed_view+1;
ELSE convert_not_view:=convert_not_view+1;
END IF;

IF cur.generatestatus='Failed'
THEN generate_failed_view:=generate_failed_view+1;
ELSIF cur.generatestatus='Passed'
THEN generate_passed_view:=generate_passed_view+1;
ELSE generate_not_view:=generate_not_view+1;
END IF;
END LOOP;
--stored programs
FOR cur IN sp_status(capture_conn_id,convert_conn_id)
LOOP
IF cur.capturestatus='Failed'
THEN capture_failed_sp:=capture_failed_sp+1;
ELSE capture_passed_sp:=capture_passed_sp+1;
END IF;

IF cur.convertstatus='Failed'
THEN convert_failed_sp:=convert_failed_sp+1;
ELSIF cur.convertstatus='Limitation'
THEN convert_limit_sp:=convert_limit_sp+1;
ELSIF cur.convertstatus='Passed'
THEN convert_passed_sp:=convert_passed_sp+1;
ELSE convert_not_sp:=convert_not_sp+1;
END IF;

IF cur.generatestatus='Failed'
THEN generate_failed_sp:=generate_failed_sp+1;
ELSIF cur.generatestatus='Passed'
THEN generate_passed_sp:=generate_passed_sp+1;
ELSE generate_not_sp:=generate_not_sp+1;
END IF;
END LOOP;
--index
FOR cur IN index_status(capture_conn_id,convert_conn_id)
LOOP
IF cur.capturestatus='Failed'
THEN capture_failed_index:=capture_failed_index+1;
ELSE capture_passed_index:=capture_passed_index+1;
END IF;

IF cur.convertstatus='Failed'
THEN convert_failed_index:=convert_failed_index+1;
ELSIF cur.convertstatus='Limitation'
THEN convert_limit_index:=convert_limit_index+1;
ELSIF cur.convertstatus='Passed'
THEN convert_passed_index:=convert_passed_index+1;
ELSE convert_not_index:=convert_not_index+1;
END IF;

IF cur.generatestatus='Failed'
THEN generate_failed_index:=generate_failed_index+1;
ELSIF cur.generatestatus='Passed'
THEN generate_passed_index:=generate_passed_index+1;
ELSE generate_not_index:=generate_not_index+1;
END IF;
END LOOP;
--constraints
FOR cur IN constraint_status(capture_conn_id,convert_conn_id)
LOOP
IF cur.capturestatus='Failed'
THEN capture_failed_constraint:=capture_failed_constraint+1;
ELSE capture_passed_constraint:=capture_passed_constraint+1;
END IF;

IF cur.convertstatus='Failed'
THEN convert_failed_constraint:=convert_failed_constraint+1;
ELSIF cur.convertstatus='Limitation'
THEN convert_limit_constraint:=convert_limit_constraint+1;
ELSIF cur.convertstatus='Passed'
THEN convert_passed_constraint:=convert_passed_constraint+1;
ELSE convert_not_constraint:=convert_not_constraint+1;
END IF;

IF cur.generatestatus='Failed'
THEN generate_failed_constraint:=generate_failed_constraint+1;
ELSIF cur.generatestatus='Passed'
THEN generate_passed_constraint:=generate_passed_constraint+1;
ELSE generate_not_constraint:=generate_not_constraint+1;
END IF;
END LOOP;
--triggers
FOR cur IN trigger_status(capture_conn_id,convert_conn_id)
LOOP
IF cur.capturestatus='Failed'
THEN capture_failed_trigger:=capture_failed_trigger+1;
ELSE capture_passed_trigger:=capture_passed_trigger+1;
END IF;

IF cur.convertstatus='Failed'
THEN convert_failed_trigger:=convert_failed_trigger+1;
ELSIF cur.convertstatus='Limitation'
THEN convert_limit_trigger:=convert_limit_trigger+1;
ELSIF cur.convertstatus='Passed'
THEN convert_passed_trigger:=convert_passed_trigger+1;
ELSE convert_not_trigger:=convert_not_trigger+1;
END IF;

IF cur.generatestatus='Failed'
THEN generate_failed_trigger:=generate_failed_trigger+1;
ELSIF cur.generatestatus='Passed'
THEN generate_passed_trigger:=generate_passed_trigger+1;
ELSE generate_not_trigger:=generate_not_trigger+1;
END IF;
END LOOP;
--source exists row
FOR cur IN (
SELECT
'Source Exists' Label,
num_schemas,
num_tables,
num_indexes,
num_constraints,
num_views,
num_stored_programs,
num_triggers
FROM md_connections
WHERE type IS NULL and id=capture_conn_id
)
LOOP
PIPE ROW(MIGR_REPORT_SUM_ROW(
cur.Label,
cur.num_schemas,
cur.num_tables,
cur.num_indexes,
cur.num_constraints,
cur.num_views,
cur.num_triggers,
cur.num_stored_programs
));
END LOOP;
PIPE ROW(MIGR_REPORT_SUM_ROW(
'Capture Passed',
capture_passed_schema,
capture_passed_table,
capture_passed_index,
capture_passed_constraint,
capture_passed_view,
capture_passed_trigger,
capture_passed_sp
));
PIPE ROW(MIGR_REPORT_SUM_ROW(
'Capture Failed',
capture_failed_schema,
capture_failed_table,
capture_failed_index,
capture_failed_constraint,
capture_failed_view,
capture_failed_trigger,
capture_failed_sp
));

PIPE ROW(MIGR_REPORT_SUM_ROW(
'Convert Passed',
convert_passed_schema,
convert_passed_table,
convert_passed_index,
convert_passed_constraint,
convert_passed_view,
convert_passed_trigger,
convert_passed_sp
));
PIPE ROW(MIGR_REPORT_SUM_ROW(
'Convert Limitation',
convert_limit_schema,
convert_limit_table,
convert_limit_index,
convert_limit_constraint,
convert_limit_view,
convert_limit_trigger,
convert_limit_sp
));
PIPE ROW(MIGR_REPORT_SUM_ROW(
'Convert Failed',
convert_failed_schema,
convert_failed_table,
convert_failed_index,
convert_failed_constraint,
convert_failed_view,
convert_failed_trigger,
convert_failed_sp
));

PIPE ROW(MIGR_REPORT_SUM_ROW(
'Generate Passed',
generate_passed_schema,
generate_passed_table,
generate_passed_index,
generate_passed_constraint,
generate_passed_view,
generate_passed_trigger,
generate_passed_sp
));
PIPE ROW(MIGR_REPORT_SUM_ROW(
'Generate Failed',
generate_failed_schema,
generate_failed_table,
generate_failed_index,
generate_failed_constraint,
generate_failed_view,
generate_failed_trigger,
generate_failed_sp
));
RETURN;
END getSum;
END MIGRATION_REPORT;

 

MIGRATION_WORKBENCH.MIGRATION_TRANSFORMER

Specification
AS
FUNCTION check_identifier_length(p_ident VARCHAR2) RETURN VARCHAR2;
FUNCTION add_suffix(p_work VARCHAR2, p_suffix VARCHAR2, p_maxlen NUMBER) RETURN VARCHAR2;
FUNCTION check_reserved_word(p_work VARCHAR2) RETURN VARCHAR2;
FUNCTION sys_check(p_work VARCHAR2) RETURN VARCHAR2;
FUNCTION check_allowed_chars(p_work NVARCHAR2) RETURN NVARCHAR2;
FUNCTION transform_identifier(p_identifier NVARCHAR2) RETURN NVARCHAR2;
FUNCTION getDisallowedCharsNames(p_work NVARCHAR2) RETURN VARCHAR2;
FUNCTION getNameForNullCase(p_work NVARCHAR2) RETURN NVARCHAR2;
END;
Body Definition
AS
-- Maximum length of an identifier
MAX_IDENTIFIER_LEN NUMBER:=30;
C_DISALLOWED_CHARS CONSTANT NVARCHAR2(100) := ' .@`!"%^&*()-+=[]{};:,.<>?/~'''||UNISTR('\00A3');

--PRIVATE FUNCTION
FUNCTION truncateStringByteSize(p_work VARCHAR2, p_bsize NUMBER) RETURN VARCHAR2
IS
v_work VARCHAR2(4000);
v_bsize NUMBER(10);
BEGIN
IF LENGTHB(p_work) <= p_bsize THEN
return p_work;
END IF;
v_work := p_work;
v_work := SUBSTRB(v_work, 1, p_bsize);
WHILE INSTRC(p_work, v_work , 1, 1) <> 1 LOOP -- a character has been cut in half or in 2/3 or 3/4 by substrb (multibyte can have up to 4 bytes)
--note each left over corrupt byte can be a single character
BEGIN
v_bsize := LENGTHB(v_work);
v_work := SUBSTRB(v_work, 1, v_bsize-1);
END;
END LOOP;
return v_work;
END;

FUNCTION add_suffix(p_work VARCHAR2, p_suffix VARCHAR2, p_maxlen NUMBER) RETURN VARCHAR2
IS
v_suflen NUMBER := LENGTHB(p_suffix);
v_truncamount NUMBER;
BEGIN
IF LENGTHB(p_work) < p_maxlen - v_suflen THEN
RETURN p_work || p_suffix;
END IF;
v_truncamount := LENGTHB(p_work) + v_suflen - p_maxlen;
RETURN truncateStringByteSize(p_work, LENGTHB(p_work)-v_truncamount) || p_suffix;
END add_suffix;


FUNCTION check_identifier_length(p_ident VARCHAR2) RETURN VARCHAR2
IS
v_work VARCHAR2(4000);
BEGIN
return truncateStringByteSize(p_ident, MAX_IDENTIFIER_LEN);
END;

FUNCTION check_reserved_word(p_work VARCHAR2) RETURN VARCHAR2
IS
v_count NUMBER := 0;
BEGIN
SELECT COUNT(*) INTO v_count FROM MIGRATION_RESERVED_WORDS WHERE KEYWORD = UPPER(p_work);
IF v_count > 0 THEN
-- It is a reserved word
RETURN add_suffix(p_work, '_', MAX_IDENTIFIER_LEN);
END IF;
RETURN p_work;
END check_reserved_word;

FUNCTION sys_check(p_work VARCHAR2) RETURN VARCHAR2
IS
BEGIN
IF LENGTH(p_work) < 4 THEN
return p_work;
END IF;
IF SUBSTR(p_work, 1, 4) <> 'SYS_' THEN
return p_work;
END IF;
RETURN 'SIS_' || SUBSTR(p_work, 5);
END sys_check;

FUNCTION first_char_check(p_work NVARCHAR2) RETURN NVARCHAR2
/**
* Never want to start with anything but AlphaNumeri
*/
IS
v_firstChar NCHAR(1);
v_allowed NCHAR(200);
BEGIN
v_allowed := C_DISALLOWED_CHARS || '0123456789_$#';
v_firstChar := SUBSTR(p_work,1,1);
if INSTR(v_allowed, v_firstChar) > 0 THEN
return 'A' ||p_work;
END IF;
return p_work;
END first_char_check;



FUNCTION lTrimNonAlphaNumeric(p_work NVARCHAR2) RETURN NVARCHAR2
/**
*Remove all non alphanumeric characters from the start
*/
IS
v_testChar VARCHAR2(2000);
v_index NUMBER;
v_work NVARCHAR2(4000):=p_work;
v_forbiddenChars VARCHAR2(100);
v_firstgoodchar NUMBER;
BEGIN
v_forbiddenChars := C_DISALLOWED_CHARS ||'_$#';
FOR v_index in 1..LENGTH(v_work) LOOP
v_testChar := SUBSTR(p_work, v_index, 1);
IF INSTR(v_forbiddenChars, v_testChar) <= 0 THEN
v_firstgoodchar := v_index;
EXIT;--make sure to leave loop now as first real char reached
END IF;
END LOOP;
return substr(p_work,v_firstgoodchar);
END lTrimNonAlphaNumeric;

FUNCTION removeQuotes(p_work NVARCHAR2) RETURN NVARCHAR2
/**
* Removed Quotes around a identifier name
*/
IS
v_firstChar NCHAR(1);
v_lastChar NCHAR(1);
v_quote NCHAR(200):= '"[]'; -- strip these from start and end;
v_work NVARCHAR2(4000) := p_work;
BEGIN
v_firstChar := SUBSTR(v_work,1,1);
v_lastChar := SUBSTR(v_work,LENGTH(v_work),1);
if INSTR(v_quote, v_firstChar) > 0 THEN
v_work := SUBSTR(v_work, 2);
if INSTR(v_quote, v_lastChar) > 0 THEN
v_work := SUBSTR(v_work,0,LENGTH(v_work)-1);
return v_work;
END IF;
return v_work;
END IF;
return v_work;
END removeQuotes;


FUNCTION check_allowed_chars(p_work NVARCHAR2) RETURN NVARCHAR2
/* The documentation states
* "Nonquoted identifiers can contain only alphanumeric characters from your database character set and the
* underscore (_), dollar sign ($), and pound sign (#). Database links can also contain periods (.) and "at" signs (@).
* Oracle strongly discourages you from using $ and # in nonquoted identifiers."
* Heres a couple of gotchas
* 1) We don't know where we will be generated to, so dunno what that database character set will be
* 2) We've now way of knowing if a character is alphanumeric on the character set.
* So... Here's what we'll do
* 1) given that its come from a database, we'll assume with was alphanumeric
* 2) We'll remove any "regular" symbol characters (i.e. one's on my keyboard!)
* 3) We'll be storing in NVARCHAR2 in the hope that this will preserve everything.
*
*/
IS
v_testChar VARCHAR2(2000);
v_index NUMBER;
-- Folowing syntax is a workaround for a problem with wrap. Do not change it.
v_forbiddenChars NVARCHAR2(100) := C_DISALLOWED_CHARS;
v_work VARCHAR2(4000) := p_work;
v_endswithunderscore boolean := FALSE;
BEGIN
IF INSTR('_',SUBSTR(p_work, LENGTH(p_work))) >0 THEN
v_endswithunderscore := TRUE;
END IF;


FOR v_index in 1..LENGTH(v_work) LOOP
v_testChar := SUBSTR(p_work, v_index, 1);

--check for existing underscores.these existed in the original and should be preserved as later we remove multiple underscores
--bug:10405027
IF v_testChar = '_' THEN
v_work :=SUBSTR(v_work,1,v_index-1)||'!' || SUBSTR(v_work,v_index+1);
ELSIF INSTR(v_forbiddenChars, v_testChar) > 0 THEN
v_work := SUBSTR(v_work, 1, v_index-1) || '_' || SUBSTR(v_work, v_index+1);
END IF;
END LOOP;

--NOW REMOVE DOUBLE UNDERSCORES see bug 6647397
v_work := replace(replace (replace (v_work,'__','_'),'__','_'),'__','_');--replace 2 underscores with 1 underscore

--bug:10405027 , original underscore and a new one
v_work := replace(v_work,'!_','_');
v_work := replace(v_work,'_!','_');

--NOW ADD BACK IN EXISTING ORGINAL UNDERSCORES bug:10405027
v_work := replace(v_work,'!','_');

--REMOVE THE LT CHAR IF IT IS AN UNDERSCORE
IF v_endswithunderscore=false AND INSTR('_',SUBSTR(v_Work,LENGTH(v_work))) > 0 THEN
v_work := SUBSTR(v_work,0,LENGTH(v_work)-1);
END IF;
return v_work;
END check_allowed_chars;

FUNCTION transform_identifier(p_identifier NVARCHAR2) RETURN NVARCHAR2
IS
v_work VARCHAR2(4000);
BEGIN
v_work := p_identifier;

-- There are 10 rules defined for identifier naming:
-- See http://st-doc.us.oracle.com/10/102/server.102/b14200/sql_elements008.htm#i27570

v_work := removeQuotes(v_work);
v_work := lTrimNonAlphaNumeric(v_work);
IF v_work is null THEN
v_work := getNameForNullCase(p_identifier); ---bug no. 8904200
END IF;

--moving this to first as we can shrink the size of the name if they have more than 1 invalid char in a row.
--see bug 6647397
-- 5. Must begin withan alpha character from your character set
v_work := first_char_check(v_work);
-- 6. Alphanumeric characters from your database charset plus '_', '$', '#' only
v_work := check_allowed_chars(v_work);
-- 1. Length
v_work := check_identifier_length(v_work);
-- 2. Reserved words
v_work := check_reserved_word(v_work);
-- 3. "Special words" -I've handled these in reserved words, but still have to check if it starts with SYS
v_work := sys_check(v_work);
-- 4. "You should use ASCII characters in database names, global database names, and database link names,
-- because ASCII characters provide optimal compatibility across different platforms and operating systems."
-- This doesn't apply as we are not doing anything with DB names
-- 7. Name collisions; we'll handle this at a higher level.
-- 8. Nonquoted identifiers are case insensitive. This is a doubl edged sword: If we use quoted, we can possible
-- Keep it similar to the source platform. However this is not how it is typically done in Oracle.
-- 9. Columns in the same table. See point 7. above.
-- 10. All about overloading for functions and parameters. We don't have to handle this here either, at this
-- Should all be done by parsing technology.
return v_work;
END transform_identifier;
FUNCTION fix_all_schema_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
v_ret NUMBER;
BEGIN
v_ret := 0;
-- First, we transform all identifiers to meet our rules
-- Then, we need to see if we've caused any collisions in the process
-- And if so, fix them
-- Right now, this is a dummy stub.
return v_ret;
END fix_all_schema_identifiers;

FUNCTION fix_all_identifiers(p_connectionid MD_CONNECTIONS.ID%TYPE) RETURN NUMBER
IS
v_ret NUMBER;
BEGIN
v_ret := fix_all_schema_identifiers(p_connectionid);
return v_ret;
END fix_all_identifiers;

FUNCTION getNameForNullCase(p_work NVARCHAR2) RETURN NVARCHAR2
IS
v_work VARCHAR2(4000);
v_testChar VARCHAR2(2000);
v_index NUMBER;
BEGIN
FOR v_index in 1..LENGTH(p_work) LOOP
v_testchar := SUBSTR(p_work,v_index,1);
v_work := v_work || getDisallowedCharsNames(v_testchar);
END LOOP;
return v_work;
END;

FUNCTION getDisallowedCharsNames(p_work NVARCHAR2) RETURN VARCHAR2
IS
v_work VARCHAR2(4000) := p_work;
BEGIN
----' .@`!"%^&*()-+=[]{};:,.<>?/~'''
v_work := ( CASE p_work
WHEN '.' THEN 'DOT'
WHEN '@' THEN 'AT'
WHEN '`' THEN 'APOSTROPHE'
WHEN '!' THEN 'EXCLAMATION'
WHEN '"' THEN 'D_QUOTE'
WHEN '%' THEN 'PERCENT'
WHEN '^' THEN 'CARET'
WHEN '&' THEN 'AMPERSAND'
WHEN '*' THEN 'STAR'
WHEN '(' THEN 'LEFTPARENTHESIS'
WHEN ')' THEN 'RIGHTPARANTHESIS'
WHEN '-' THEN 'MINUS'
WHEN '+' THEN 'PLUS'
WHEN '=' THEN 'EQUAL'
WHEN '[' THEN 'LEFTSQUARE_B'
WHEN ']' THEN 'RIGHTSQUARE_B'
WHEN '{' THEN 'LEFTCURLY_B'
WHEN '}' THEN 'RIGHTCURLY_B'
WHEN ';' THEN 'COLON'
WHEN ':' THEN 'SEMICOLON'
WHEN ',' THEN 'COMMA'
WHEN '<' THEN 'LESSTHAN'
WHEN '>' THEN 'GREATERTHAN'
WHEN '?' THEN 'QUESTIONMARK'
WHEN '~' THEN 'TILDE'
WHEN '/' THEN 'BACKSLASH'
WHEN '''' THEN 'S_QUOTE'
WHEN '$' THEN 'DOLLAR'
ELSE 'UNKNOWN'
END);
return v_work;
END;

END;