diff --git a/CHANGELOG.md b/CHANGELOG.md index 64a0b2ab..47ace9a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Change Log +## 7.1.1 + +### Functionality Improvements + +### Technical Improvements + +### Bug Fixes +Oracle Reverse Engineering can still generate output even if a single object DDL cannot be generated. + + ## 7.1.0 ### Functionality Improvements diff --git a/obevo-db-impls/obevo-db-oracle/pom.xml b/obevo-db-impls/obevo-db-oracle/pom.xml index 53722362..bac9f395 100644 --- a/obevo-db-impls/obevo-db-oracle/pom.xml +++ b/obevo-db-impls/obevo-db-oracle/pom.xml @@ -28,7 +28,7 @@ ${project.artifactId} - 0.40 + 0.34 diff --git a/obevo-db-impls/obevo-db-oracle/src/main/java/com/gs/obevo/db/impl/platforms/oracle/OracleReveng.kt b/obevo-db-impls/obevo-db-oracle/src/main/java/com/gs/obevo/db/impl/platforms/oracle/OracleReveng.kt index 1a60380f..50503015 100644 --- a/obevo-db-impls/obevo-db-oracle/src/main/java/com/gs/obevo/db/impl/platforms/oracle/OracleReveng.kt +++ b/obevo-db-impls/obevo-db-oracle/src/main/java/com/gs/obevo/db/impl/platforms/oracle/OracleReveng.kt @@ -19,11 +19,14 @@ import com.gs.obevo.api.platform.ChangeType import com.gs.obevo.db.apps.reveng.AbstractDdlReveng import com.gs.obevo.db.apps.reveng.AquaRevengArgs import com.gs.obevo.db.impl.core.jdbc.JdbcHelper +import com.gs.obevo.impl.changetypes.UnclassifiedChangeType import com.gs.obevo.impl.util.MultiLineStringSplitter import com.gs.obevo.util.inputreader.Credential import org.apache.commons.io.IOUtils +import org.apache.commons.lang3.exception.ExceptionUtils import org.eclipse.collections.api.block.function.Function import org.eclipse.collections.api.list.ImmutableList +import org.eclipse.collections.api.list.MutableList import org.eclipse.collections.impl.block.factory.StringPredicates import org.eclipse.collections.impl.factory.Lists import org.slf4j.LoggerFactory @@ -33,6 +36,7 @@ import java.io.StringWriter import java.nio.charset.Charset import java.nio.file.Files import java.sql.Clob +import java.sql.Connection import java.util.regex.Pattern internal class OracleReveng @@ -73,63 +77,15 @@ internal class OracleReveng jdbc.update(conn, "begin DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'STORAGE',false); end;") jdbc.update(conn, "begin DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'SQLTERMINATOR',true); end;") - // we exclude: - // PACKAGE BODY as those are generated via package anyway - // DATABASE LINK as the get_ddl function doesn't work with it. We may support this later on - val sql = """ -select CASE WHEN obj.OBJECT_TYPE = 'INDEX' THEN 2 ELSE 1 END SORT_ORDER1 - , obj.OBJECT_NAME - , 1 AS SORT_ORDER2 - , obj.OBJECT_TYPE - , dbms_metadata.get_ddl(REPLACE(obj.OBJECT_TYPE,' ','_'), obj.OBJECT_NAME, obj.owner) || ';' AS object_ddl -FROM DBA_OBJECTS obj -LEFT JOIN DBA_TABLES tab ON obj.OBJECT_TYPE = 'TABLE' AND obj.OWNER = tab.OWNER and obj.OBJECT_NAME = tab.TABLE_NAME -WHERE obj.OWNER = '${args.dbSchema}' - AND obj.OBJECT_TYPE NOT IN ('PACKAGE BODY', 'LOB', 'TABLE PARTITION', 'DATABASE LINK') - AND obj.OBJECT_NAME NOT LIKE 'MLOG${'$'}%' AND obj.OBJECT_NAME NOT LIKE 'RUPD${'$'}%' -- exclude the helper tables for materialized views - AND obj.OBJECT_NAME NOT LIKE 'SYS_%' -- exclude other system tables - AND (tab.NESTED is null OR tab.NESTED = 'NO') -""" - - val commentSql = """ -SELECT 1 SORT_ORDER1 -- group comment ordering with tables and other objects, and ahead of indices - , obj.OBJECT_NAME - , 2 AS SORT_ORDER2 -- sort comments last compared to other table changes - , 'COMMENT' as OBJECT_TYPE - , dbms_metadata.get_dependent_ddl('COMMENT', obj.OBJECT_NAME, obj.OWNER) || ';' AS object_ddl -FROM ( - -- inner table is needed to extract all the object names that have comments (we cannot determine this solely from DBA_OBJECTS) - -- use DISTINCT as DBA_COL_COMMENTS may have multiple rows for a single table - SELECT DISTINCT obj.OWNER, obj.OBJECT_NAME, obj.OBJECT_TYPE - FROM DBA_OBJECTS obj - LEFT JOIN DBA_TAB_COMMENTS tabcom ON obj.OWNER = tabcom.OWNER and obj.OBJECT_NAME = tabcom.TABLE_NAME and tabcom.COMMENTS IS NOT NULL - LEFT JOIN DBA_COL_COMMENTS colcom ON obj.OWNER = colcom.OWNER and obj.OBJECT_NAME = colcom.TABLE_NAME and colcom.COMMENTS IS NOT NULL - WHERE obj.OWNER = '${args.dbSchema}' - and (tabcom.OWNER is not null OR colcom.OWNER is not null) -) obj -ORDER BY 1, 2 -""" - - // note - need comments grouped in order with tables, but indexes - /* keeping this for the future as we support more object types with comments - LEFT JOIN DBA_OPERATOR_COMMENTS opcom ON obj.OWNER = opcom.OWNER and obj.OBJECT_NAME = opcom.OPERATOR_NAME and opcom.COMMENTS IS NOT NULL - LEFT JOIN DBA_INDEXTYPE_COMMENTS indexcom ON obj.OWNER = indexcom.OWNER and obj.OBJECT_NAME = indexcom.INDEXTYPE_NAME and indexcom.COMMENTS IS NOT NULL - LEFT JOIN DBA_MVIEW_COMMENTS mviewcom ON obj.OWNER = mviewcom.OWNER and obj.OBJECT_NAME = mviewcom.MVIEW_NAME and mviewcom.COMMENTS IS NOT NULL - LEFT JOIN DBA_EDITION_COMMENTS edcom ON obj.OBJECT_NAME = edcom.EDITION_NAME and edcom.COMMENTS IS NOT NULL -- note - no OWNER supported here - */ - - // Sorting algorithm: // - We use SORT_ORDER1 to split between table and index changes, as we want index changes to come after tables, // but the SQL query only gives the object name as the index name; hence, we can't group easily. // - We use SORT_ORDER2 for having comments come after regular table changes. - val queryResults = listOf(sql, commentSql) - .flatMap { jdbc.queryForList(conn, it) } + val queryResults = queryObjects(jdbc, conn, args.dbSchema).plus(queryComments(jdbc, conn, args.dbSchema)) .sortedWith(compareBy({ it["SORT_ORDER1"] as Comparable<*> }, { it["OBJECT_NAME"] as String }, { it["SORT_ORDER2"] as Comparable<*> })) queryResults.forEach { map -> val objectType = map["OBJECT_TYPE"] as String - val clobObject = map["OBJECT_DDL"] as Clob - var clobAsString = clobToString(clobObject) + var clobAsString = clobToString(map["OBJECT_DDL"]!!) // TODO all parsing like this should move into the core AbstractReveng logic so that we can do more unit-test logic around this parsing clobAsString = clobAsString.trimEnd() @@ -160,11 +116,107 @@ ORDER BY 1, 2 return true } - private fun clobToString(clobObject: Clob): String { - clobObject.characterStream.use { - val w = StringWriter() - IOUtils.copy(it, w) - return w.toString() + private fun queryObjects(jdbc: JdbcHelper, conn: Connection, schema: String): List> { + try { + return jdbc.queryForList(conn, getObjectQuery(schema, true, null)) + } catch (_: Exception) { + // the bulk query may fail if one of the objects cannot be rendered. Hence, we fall back to individual queries + LOG.info("Failed executing bulk query for all objects; falling back to individual queries") + + // First get the objects + val objects = jdbc.queryForList(conn, getObjectQuery(schema, false, null)) + + // Now query each individually + return objects.flatMap { + try { + jdbc.queryForList(conn, getObjectQuery(schema, true, it["OBJECT_NAME"] as String)) + } catch (e2: Exception) { + // in case of failures, write the object out for the reverse-engineering to process + val exceptionText = """OBEVO EXCEPTION ${it["OBJECT_NAME"]!!} of type ${it["OBJECT_TYPE"]!!} +/* +Please report this as an Issue on the Obevo Github page so that we can improve the reverse-engineering logic. +For now, resolve this on your side. +${ExceptionUtils.getStackTrace(e2)} +*/ +end +""" + listOf(mapOf( + "SORT_ORDER1" to it["SORT_ORDER1"]!!, + "OBJECT_NAME" to it["OBJECT_NAME"]!!, + "SORT_ORDER2" to it["SORT_ORDER2"]!!, + "OBJECT_TYPE" to it["OBJECT_TYPE"]!!, + "OBJECT_DDL" to exceptionText + )) + } + }.toSet().toList() + } + } + + private fun getObjectQuery(schema: String, retrieveDefinitions: Boolean, objectName: String?): String { + val objectDefSql = if (retrieveDefinitions) "dbms_metadata.get_ddl(REPLACE(obj.OBJECT_TYPE,' ','_'), obj.OBJECT_NAME, obj.owner) || ';'" else " 'blank'"; + val objectClause = objectName?.let { " AND obj.OBJECT_NAME = '${it}'"} ?: "" + + // we exclude: + // PACKAGE BODY as those are generated via package anyway + // DATABASE LINK as the get_ddl function doesn't work with it. We may support this later on + return """ +select CASE WHEN obj.OBJECT_TYPE = 'INDEX' THEN 2 ELSE 1 END SORT_ORDER1 + , obj.OBJECT_NAME + , 1 AS SORT_ORDER2 + , obj.OBJECT_TYPE + , ${objectDefSql} AS OBJECT_DDL +FROM DBA_OBJECTS obj +LEFT JOIN DBA_TABLES tab ON obj.OBJECT_TYPE = 'TABLE' AND obj.OWNER = tab.OWNER and obj.OBJECT_NAME = tab.TABLE_NAME +WHERE obj.OWNER = '${schema}' + AND obj.OBJECT_TYPE NOT IN ('PACKAGE BODY', 'LOB', 'TABLE PARTITION', 'DATABASE LINK') + AND obj.OBJECT_NAME NOT LIKE 'MLOG${'$'}%' AND obj.OBJECT_NAME NOT LIKE 'RUPD${'$'}%' -- exclude the helper tables for materialized views + AND obj.OBJECT_NAME NOT LIKE 'SYS_%' -- exclude other system tables + AND (tab.NESTED is null OR tab.NESTED = 'NO') + ${objectClause} +""" + } + + private fun queryComments(jdbc: JdbcHelper, conn: Connection, schema: String): MutableList> { + val commentSql = """ +SELECT 1 SORT_ORDER1 -- group comment ordering with tables and other objects, and ahead of indices + , obj.OBJECT_NAME + , 2 AS SORT_ORDER2 -- sort comments last compared to other table changes + , 'COMMENT' as OBJECT_TYPE + , dbms_metadata.get_dependent_ddl('COMMENT', obj.OBJECT_NAME, obj.OWNER) || ';' AS OBJECT_DDL +FROM ( + -- inner table is needed to extract all the object names that have comments (we cannot determine this solely from DBA_OBJECTS) + -- use DISTINCT as DBA_COL_COMMENTS may have multiple rows for a single table + SELECT DISTINCT obj.OWNER, obj.OBJECT_NAME, obj.OBJECT_TYPE + FROM DBA_OBJECTS obj + LEFT JOIN DBA_TAB_COMMENTS tabcom ON obj.OWNER = tabcom.OWNER and obj.OBJECT_NAME = tabcom.TABLE_NAME and tabcom.COMMENTS IS NOT NULL + LEFT JOIN DBA_COL_COMMENTS colcom ON obj.OWNER = colcom.OWNER and obj.OBJECT_NAME = colcom.TABLE_NAME and colcom.COMMENTS IS NOT NULL + WHERE obj.OWNER = '${schema}' + and (tabcom.OWNER is not null OR colcom.OWNER is not null) +) obj +ORDER BY 1, 2 +""" + + // note - need comments grouped in order with tables, but indexes + /* keeping this for the future as we support more object types with comments + LEFT JOIN DBA_OPERATOR_COMMENTS opcom ON obj.OWNER = opcom.OWNER and obj.OBJECT_NAME = opcom.OPERATOR_NAME and opcom.COMMENTS IS NOT NULL + LEFT JOIN DBA_INDEXTYPE_COMMENTS indexcom ON obj.OWNER = indexcom.OWNER and obj.OBJECT_NAME = indexcom.INDEXTYPE_NAME and indexcom.COMMENTS IS NOT NULL + LEFT JOIN DBA_MVIEW_COMMENTS mviewcom ON obj.OWNER = mviewcom.OWNER and obj.OBJECT_NAME = mviewcom.MVIEW_NAME and mviewcom.COMMENTS IS NOT NULL + LEFT JOIN DBA_EDITION_COMMENTS edcom ON obj.OBJECT_NAME = edcom.EDITION_NAME and edcom.COMMENTS IS NOT NULL -- note - no OWNER supported here + */ + return jdbc.queryForList(conn, commentSql) + } + + private fun clobToString(clobObject: Any): String { + if (clobObject is String) { + return clobObject + } else if (clobObject is Clob) { + clobObject.characterStream.use { + val w = StringWriter() + IOUtils.copy(it, w) + return w.toString() + } + } else { + throw RuntimeException("Unexpected type " + clobObject.javaClass + "; expecting String or Clob") } } @@ -191,6 +243,7 @@ ORDER BY 1, 2 } } return Lists.immutable.with( + AbstractDdlReveng.RevengPattern(UnclassifiedChangeType.INSTANCE.name, namePatternType, "(?i)obevo\\s+exception\\s+$schemaNameSubPattern"), AbstractDdlReveng.RevengPattern(ChangeType.SEQUENCE_STR, namePatternType, "(?i)create\\s+(?:or\\s+replace\\s+)?sequence\\s+$schemaNameSubPattern").withPostProcessSql(AbstractDdlReveng.REPLACE_TABLESPACE).withPostProcessSql(AbstractDdlReveng.REMOVE_QUOTES), AbstractDdlReveng.RevengPattern(ChangeType.TABLE_STR, namePatternType, "(?i)create\\s+table\\s+$schemaNameSubPattern").withPostProcessSql(AbstractDdlReveng.REPLACE_TABLESPACE).withPostProcessSql(AbstractDdlReveng.REMOVE_QUOTES), AbstractDdlReveng.RevengPattern(ChangeType.TABLE_STR, namePatternType, "(?i)alter\\s+table\\s+$schemaNameSubPattern").withPostProcessSql(AbstractDdlReveng.REMOVE_QUOTES), diff --git a/obevo-db-impls/obevo-db-oracle/src/test/resources/platforms/oracle/example1/step2/schema1/view/COMMENT_VIEW.sql b/obevo-db-impls/obevo-db-oracle/src/test/resources/platforms/oracle/example1/step2/schema1/view/COMMENT_VIEW.sql index 485145a5..1dea0aa9 100644 --- a/obevo-db-impls/obevo-db-oracle/src/test/resources/platforms/oracle/example1/step2/schema1/view/COMMENT_VIEW.sql +++ b/obevo-db-impls/obevo-db-oracle/src/test/resources/platforms/oracle/example1/step2/schema1/view/COMMENT_VIEW.sql @@ -15,7 +15,8 @@ -- CREATE OR REPLACE VIEW COMMENT_VIEW AS SELECT A_ID, STRING_FIELD FROM TABLE_A WHERE A_ID = 3 -; +GO COMMENT ON COLUMN COMMENT_VIEW.A_ID -IS 'comment VIEW COL A_ID' -; +IS 'comment VIEW COL A_ID 2' +GO + diff --git a/obevo-db-impls/obevo-db-oracle/src/test/resources/reveng/oracle/expected/DBDEPLOY01/unableToClassify-pleaseAnalyze/MY_ERROR_OBJECT.sql b/obevo-db-impls/obevo-db-oracle/src/test/resources/reveng/oracle/expected/DBDEPLOY01/unableToClassify-pleaseAnalyze/MY_ERROR_OBJECT.sql new file mode 100644 index 00000000..27cd515b --- /dev/null +++ b/obevo-db-impls/obevo-db-oracle/src/test/resources/reveng/oracle/expected/DBDEPLOY01/unableToClassify-pleaseAnalyze/MY_ERROR_OBJECT.sql @@ -0,0 +1,131 @@ +OBEVO EXCEPTION MY_ERROR_OBJECT of type TABLE +/* +Please report this as an Issue on the Obevo Github page so that we can improve the reverse-engineering logic. +For now, resolve this on your side. +java.sql.SQLException: ORA-31603: object "COL1_TAB" of type TABLE not found in schema "DBDEPLOY01" +ORA-06512: at "SYS.DBMS_METADATA", line 6478 +ORA-06512: at "SYS.DBMS_SYS_ERROR", line 105 +ORA-06512: at "SYS.DBMS_METADATA", line 6465 +ORA-06512: at "SYS.DBMS_METADATA", line 9202 +ORA-06512: at line 1 + + at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450) + at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399) + at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059) + at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522) + at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257) + at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587) + at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:210) + at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:30) + at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:931) + at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:957) + at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1111) + at oracle.jdbc.driver.OracleStatement.executeQuery(OracleStatement.java:1309) + at oracle.jdbc.driver.OracleStatementWrapper.executeQuery(OracleStatementWrapper.java:422) + at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:208) + at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:208) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryAndLeaveStatementOpenInternal(JdbcHelper.java:203) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryAndLeaveStatementOpen(JdbcHelper.java:193) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.query(JdbcHelper.java:172) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryForList(JdbcHelper.java:225) + at com.gs.obevo.db.impl.platforms.oracle.OracleReveng.queryObjects(OracleReveng.kt:132) + at com.gs.obevo.db.impl.platforms.oracle.OracleReveng.doRevengOrInstructions(OracleReveng.kt:84) + at com.gs.obevo.db.apps.reveng.AbstractDdlReveng.reveng(AbstractDdlReveng.java:165) + at com.gs.obevo.db.impl.platforms.oracle.OracleRevengIT.testReveng(OracleRevengIT.java:82) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) + at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) + at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) + at org.junit.runners.ParentRunner.run(ParentRunner.java:309) + at org.junit.runners.Suite.runChild(Suite.java:127) + at org.junit.runners.Suite.runChild(Suite.java:26) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) + at org.junit.runners.ParentRunner.run(ParentRunner.java:309) + at org.junit.runner.JUnitCore.run(JUnitCore.java:160) + at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) + at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) + at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) + at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) + + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryAndLeaveStatementOpenInternal(JdbcHelper.java:206) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryAndLeaveStatementOpen(JdbcHelper.java:193) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.query(JdbcHelper.java:172) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryForList(JdbcHelper.java:225) + at com.gs.obevo.db.impl.platforms.oracle.OracleReveng.queryObjects(OracleReveng.kt:132) + at com.gs.obevo.db.impl.platforms.oracle.OracleReveng.doRevengOrInstructions(OracleReveng.kt:84) + at com.gs.obevo.db.apps.reveng.AbstractDdlReveng.reveng(AbstractDdlReveng.java:165) + at com.gs.obevo.db.impl.platforms.oracle.OracleRevengIT.testReveng(OracleRevengIT.java:82) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) + at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) + at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) + at org.junit.runners.ParentRunner.run(ParentRunner.java:309) + at org.junit.runners.Suite.runChild(Suite.java:127) + at org.junit.runners.Suite.runChild(Suite.java:26) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) + at org.junit.runners.ParentRunner.run(ParentRunner.java:309) + at org.junit.runner.JUnitCore.run(JUnitCore.java:160) + at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) + at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) + at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) + at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) +Caused by: java.sql.SQLException: ORA-31603: object "COL1_TAB" of type TABLE not found in schema "DBDEPLOY01" +ORA-06512: at "SYS.DBMS_METADATA", line 6478 +ORA-06512: at "SYS.DBMS_SYS_ERROR", line 105 +ORA-06512: at "SYS.DBMS_METADATA", line 6465 +ORA-06512: at "SYS.DBMS_METADATA", line 9202 +ORA-06512: at line 1 + + at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450) + at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399) + at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059) + at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522) + at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257) + at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587) + at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:210) + at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:30) + at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:931) + at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:957) + at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1111) + at oracle.jdbc.driver.OracleStatement.executeQuery(OracleStatement.java:1309) + at oracle.jdbc.driver.OracleStatementWrapper.executeQuery(OracleStatementWrapper.java:422) + at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:208) + at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:208) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryAndLeaveStatementOpenInternal(JdbcHelper.java:203) + ... 37 more + +*/ +end +GO \ No newline at end of file diff --git a/obevo-db-impls/obevo-db-oracle/src/test/resources/reveng/oracle/input.sql b/obevo-db-impls/obevo-db-oracle/src/test/resources/reveng/oracle/input.sql index dbf8267b..fadad205 100644 --- a/obevo-db-impls/obevo-db-oracle/src/test/resources/reveng/oracle/input.sql +++ b/obevo-db-impls/obevo-db-oracle/src/test/resources/reveng/oracle/input.sql @@ -101,7 +101,137 @@ $$ LANGUAGE plpgsql; CREATE SEQUENCE "DBDEPLOY01"."MYSEQ2" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE GLOBAL ~ - + OBEVO EXCEPTION MY_ERROR_OBJECT of type TABLE +/* +Please report this as an Issue on the Obevo Github page so that we can improve the reverse-engineering logic. +For now, resolve this on your side. +java.sql.SQLException: ORA-31603: object "COL1_TAB" of type TABLE not found in schema "DBDEPLOY01" +ORA-06512: at "SYS.DBMS_METADATA", line 6478 +ORA-06512: at "SYS.DBMS_SYS_ERROR", line 105 +ORA-06512: at "SYS.DBMS_METADATA", line 6465 +ORA-06512: at "SYS.DBMS_METADATA", line 9202 +ORA-06512: at line 1 + + at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450) + at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399) + at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059) + at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522) + at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257) + at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587) + at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:210) + at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:30) + at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:931) + at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:957) + at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1111) + at oracle.jdbc.driver.OracleStatement.executeQuery(OracleStatement.java:1309) + at oracle.jdbc.driver.OracleStatementWrapper.executeQuery(OracleStatementWrapper.java:422) + at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:208) + at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:208) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryAndLeaveStatementOpenInternal(JdbcHelper.java:203) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryAndLeaveStatementOpen(JdbcHelper.java:193) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.query(JdbcHelper.java:172) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryForList(JdbcHelper.java:225) + at com.gs.obevo.db.impl.platforms.oracle.OracleReveng.queryObjects(OracleReveng.kt:132) + at com.gs.obevo.db.impl.platforms.oracle.OracleReveng.doRevengOrInstructions(OracleReveng.kt:84) + at com.gs.obevo.db.apps.reveng.AbstractDdlReveng.reveng(AbstractDdlReveng.java:165) + at com.gs.obevo.db.impl.platforms.oracle.OracleRevengIT.testReveng(OracleRevengIT.java:82) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) + at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) + at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) + at org.junit.runners.ParentRunner.run(ParentRunner.java:309) + at org.junit.runners.Suite.runChild(Suite.java:127) + at org.junit.runners.Suite.runChild(Suite.java:26) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) + at org.junit.runners.ParentRunner.run(ParentRunner.java:309) + at org.junit.runner.JUnitCore.run(JUnitCore.java:160) + at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) + at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) + at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) + at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) + + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryAndLeaveStatementOpenInternal(JdbcHelper.java:206) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryAndLeaveStatementOpen(JdbcHelper.java:193) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.query(JdbcHelper.java:172) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryForList(JdbcHelper.java:225) + at com.gs.obevo.db.impl.platforms.oracle.OracleReveng.queryObjects(OracleReveng.kt:132) + at com.gs.obevo.db.impl.platforms.oracle.OracleReveng.doRevengOrInstructions(OracleReveng.kt:84) + at com.gs.obevo.db.apps.reveng.AbstractDdlReveng.reveng(AbstractDdlReveng.java:165) + at com.gs.obevo.db.impl.platforms.oracle.OracleRevengIT.testReveng(OracleRevengIT.java:82) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:498) + at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) + at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) + at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) + at org.junit.runners.ParentRunner.run(ParentRunner.java:309) + at org.junit.runners.Suite.runChild(Suite.java:127) + at org.junit.runners.Suite.runChild(Suite.java:26) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) + at org.junit.runners.ParentRunner.run(ParentRunner.java:309) + at org.junit.runner.JUnitCore.run(JUnitCore.java:160) + at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) + at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) + at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) + at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) +Caused by: java.sql.SQLException: ORA-31603: object "COL1_TAB" of type TABLE not found in schema "DBDEPLOY01" +ORA-06512: at "SYS.DBMS_METADATA", line 6478 +ORA-06512: at "SYS.DBMS_SYS_ERROR", line 105 +ORA-06512: at "SYS.DBMS_METADATA", line 6465 +ORA-06512: at "SYS.DBMS_METADATA", line 9202 +ORA-06512: at line 1 + + at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450) + at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399) + at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059) + at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522) + at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257) + at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587) + at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:210) + at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:30) + at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:931) + at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:957) + at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1111) + at oracle.jdbc.driver.OracleStatement.executeQuery(OracleStatement.java:1309) + at oracle.jdbc.driver.OracleStatementWrapper.executeQuery(OracleStatementWrapper.java:422) + at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:208) + at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:208) + at com.gs.obevo.db.impl.core.jdbc.JdbcHelper.queryAndLeaveStatementOpenInternal(JdbcHelper.java:203) + ... 37 more + +*/ +end +~ CREATE TABLE "DBDEPLOY01"."NESTED_TABLE" ( "ID" NUMBER, "COL1" "DBDEPLOY01"."NESTED_TABLE_TYPE" diff --git a/obevo-db/src/main/java/com/gs/obevo/db/apps/reveng/AbstractDdlReveng.java b/obevo-db/src/main/java/com/gs/obevo/db/apps/reveng/AbstractDdlReveng.java index ceacfd39..39e8e502 100644 --- a/obevo-db/src/main/java/com/gs/obevo/db/apps/reveng/AbstractDdlReveng.java +++ b/obevo-db/src/main/java/com/gs/obevo/db/apps/reveng/AbstractDdlReveng.java @@ -339,7 +339,11 @@ private MutableList revengFile(SchemaObjectReplacer schemaObjectRep if (patternMatch.getSecondaryName() != null) { secondaryName = patternMatch.getSecondaryName(); } - candidateObjectType = platform.getChangeType(patternMatch.getRevengPattern().getChangeType()); + if (patternMatch.getRevengPattern().getChangeType().equalsIgnoreCase(UnclassifiedChangeType.INSTANCE.getName())) { + candidateObjectType = UnclassifiedChangeType.INSTANCE; + } else { + candidateObjectType = platform.getChangeType(patternMatch.getRevengPattern().getChangeType()); + } } }