Skip to content

Commit

Permalink
Fixed #1109 ORA-65040 error when trying to clean different schema wit…
Browse files Browse the repository at this point in the history
…h system user
  • Loading branch information
Axel Fontaine committed Dec 29, 2015
1 parent 69aaa31 commit 4ebe298
Showing 1 changed file with 54 additions and 42 deletions.
@@ -1,12 +1,12 @@
/**
* Copyright 2010-2015 Axel Fontaine
*
* <p/>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand Down Expand Up @@ -71,29 +71,39 @@ protected void doClean() throws SQLException {
throw new FlywayException("Clean not supported on Oracle for user 'SYSTEM'! You should NEVER add your own objects to the SYSTEM schema!");
}

for (String statement : generateDropStatementsForSpatialExtensions()) {
String user = dbSupport.doGetCurrentSchemaName();
boolean defaultSchemaForUser = user.equalsIgnoreCase(name);

if (!defaultSchemaForUser) {
LOG.warn("Cleaning schema " + name + " by a different user (" + user + "): " +
"spatial extensions, queue tables, flashback tables and scheduled jobs will not be cleaned due to Oracle limitations");
}

for (String statement : generateDropStatementsForSpatialExtensions(defaultSchemaForUser)) {
jdbcTemplate.execute(statement);
}

for (String statement : generateDropStatementsForQueueTables()) {
try {
jdbcTemplate.execute(statement);
} catch (SQLException e) {
if (e.getErrorCode() == 65040) {
//for dropping queue tables, a special grant is required:
//GRANT EXECUTE ON DBMS_AQADM TO flyway;
LOG.error("Missing required grant to clean queue tables: GRANT EXECUTE ON DBMS_AQADM");
if (defaultSchemaForUser) {
for (String statement : generateDropStatementsForQueueTables()) {
try {
jdbcTemplate.execute(statement);
} catch (SQLException e) {
if (e.getErrorCode() == 65040) {
//for dropping queue tables, a special grant is required:
//GRANT EXECUTE ON DBMS_AQADM TO flyway;
LOG.error("Missing required grant to clean queue tables: GRANT EXECUTE ON DBMS_AQADM");
}
throw e;
}
throw e;
}
}

if (flashbackAvailable()) {
executeAlterStatementsForFlashbackTables();
}
if (flashbackAvailable()) {
executeAlterStatementsForFlashbackTables();
}

for (String statement : generateDropStatementsForScheduledJobs()) {
jdbcTemplate.execute(statement);
for (String statement : generateDropStatementsForScheduledJobs()) {
jdbcTemplate.execute(statement);
}
}

for (String statement : generateDropStatementsForObjectType("TRIGGER", "")) {
Expand Down Expand Up @@ -251,10 +261,11 @@ private List<String> generateDropStatementsForObjectType(String objectType, Stri
/**
* Generates the drop statements for Oracle Spatial Extensions-related database objects.
*
* @param defaultSchemaForUser Whether we are currently cleaning the default schema for the logged in user.
* @return The complete drop statements, ready to execute.
* @throws SQLException when the drop statements could not be generated.
*/
private List<String> generateDropStatementsForSpatialExtensions() throws SQLException {
private List<String> generateDropStatementsForSpatialExtensions(boolean defaultSchemaForUser) throws SQLException {
List<String> statements = new ArrayList<String>();

if (!spatialExtensionsAvailable()) {
Expand All @@ -270,12 +281,13 @@ private List<String> generateDropStatementsForSpatialExtensions() throws SQLExce
return statements;
}

if (defaultSchemaForUser) {
statements.add("DELETE FROM mdsys.user_sdo_geom_metadata");

statements.add("DELETE FROM mdsys.user_sdo_geom_metadata");

List<String> indexNames = jdbcTemplate.queryForStringList("select INDEX_NAME from USER_SDO_INDEX_INFO");
for (String indexName : indexNames) {
statements.add("DROP INDEX \"" + indexName + "\"");
List<String> indexNames = jdbcTemplate.queryForStringList("select INDEX_NAME from USER_SDO_INDEX_INFO");
for (String indexName : indexNames) {
statements.add("DROP INDEX \"" + indexName + "\"");
}
}

return statements;
Expand Down Expand Up @@ -331,29 +343,29 @@ protected Table[] doAllTables() throws SQLException {
// For every table this query will count the number of references (including the transitive ones)
// and order the result list using that value.
" SELECT r FROM" +
" (SELECT CONNECT_BY_ROOT t r FROM" +
" (SELECT DISTINCT c1.table_name f, NVL(c2.table_name, at.table_name) t" +
" FROM all_constraints c1" +
" RIGHT JOIN all_constraints c2 ON c2.constraint_name = c1.r_constraint_name" +
" RIGHT JOIN all_tables at ON at.table_name = c2.table_name" +
" WHERE at.owner = ?" +
" (SELECT CONNECT_BY_ROOT t r FROM" +
" (SELECT DISTINCT c1.table_name f, NVL(c2.table_name, at.table_name) t" +
" FROM all_constraints c1" +
" RIGHT JOIN all_constraints c2 ON c2.constraint_name = c1.r_constraint_name" +
" RIGHT JOIN all_tables at ON at.table_name = c2.table_name" +
" WHERE at.owner = ?" +
// Ignore Recycle bin objects
" AND at.table_name NOT LIKE 'BIN$%'" +
" AND at.table_name NOT LIKE 'BIN$%'" +
// Ignore Spatial Index Tables as they get dropped automatically when the index gets dropped.
" AND at.table_name NOT LIKE 'MDRT_%$'" +
" AND at.table_name NOT LIKE 'MDRT_%$'" +
// Ignore Materialized View Logs
" AND at.table_name NOT LIKE 'MLOG$%' AND at.table_name NOT LIKE 'RUPD$%'" +
" AND at.table_name NOT LIKE 'MLOG$%' AND at.table_name NOT LIKE 'RUPD$%'" +
// Ignore Oracle Text Index Tables
" AND at.table_name NOT LIKE 'DR$%'" +
" AND at.table_name NOT LIKE 'DR$%'" +
// Ignore Index Organized Tables
" AND at.table_name NOT LIKE 'SYS_IOT_OVER_%'" +
" AND at.table_name NOT LIKE 'SYS_IOT_OVER_%'" +
// Ignore Nested Tables
" AND at.nested != 'YES'" +
" AND at.nested != 'YES'" +
// Ignore Nested Tables
" AND at.secondary != 'Y')" +
" CONNECT BY NOCYCLE PRIOR f = t)" +
" GROUP BY r" +
" ORDER BY COUNT(*)", name);
" AND at.secondary != 'Y')" +
" CONNECT BY NOCYCLE PRIOR f = t)" +
" GROUP BY r" +
" ORDER BY COUNT(*)", name);

Table[] tables = new Table[tableNames.size()];
for (int i = 0; i < tableNames.size(); i++) {
Expand Down

0 comments on commit 4ebe298

Please sign in to comment.