From ec3b72f546fb05f03307402d17be596ffa101058 Mon Sep 17 00:00:00 2001 From: vpetrovy Date: Wed, 19 Mar 2025 15:28:10 +0200 Subject: [PATCH 01/10] [DAT-18825] - evaluate regression for "easy fix" --- .../main/java/liquibase/database/AbstractJdbcDatabase.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java b/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java index cf447275d9..1060f4019d 100644 --- a/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java @@ -30,7 +30,8 @@ import liquibase.statement.SequenceCurrentValueFunction; import liquibase.statement.SequenceNextValueFunction; import liquibase.statement.SqlStatement; -import liquibase.statement.core.*; +import liquibase.statement.core.GetViewDefinitionStatement; +import liquibase.statement.core.RawCallStatement; import liquibase.structure.DatabaseObject; import liquibase.structure.core.*; import liquibase.util.ISODateFormat; @@ -763,7 +764,7 @@ public void dropDatabaseObjects(final CatalogAndSchema schemaToDrop) throws Liqu typesToInclude.remove(PrimaryKey.class); typesToInclude.remove(UniqueConstraint.class); - if (supportsForeignKeyDisable() || getShortName().equals("postgresql")) { + if (supportsForeignKeyDisable() || getShortName().equals("postgresql") || getShortName().equals("oracle")) { //We do not remove ForeignKey because they will be disabled and removed as parts of tables. // Postgress is treated as if we can disable foreign keys because we can't drop // the foreign keys of a partitioned table, as discovered in From 358400dad84f996f4ae9e83706da134be9952087 Mon Sep 17 00:00:00 2001 From: vpetrovy Date: Thu, 20 Mar 2025 14:18:47 +0200 Subject: [PATCH 02/10] [DAT-18825] - try to make 'reference' partitions precede all others, and all others order should be unchanged --- .../liquibase/snapshot/JdbcDatabaseSnapshot.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java b/liquibase-core/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java index 03a00fce4b..f7a91f5ca9 100755 --- a/liquibase-core/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java @@ -1047,9 +1047,11 @@ private List queryMssql(CatalogAndSchema catalogAndSchema, String tab private List queryOracle(CatalogAndSchema catalogAndSchema, String tableName) throws DatabaseException, SQLException { String ownerName = database.correctObjectName(catalogAndSchema.getCatalogName(), Schema.class); - String sql = "SELECT null as TABLE_CAT, a.OWNER as TABLE_SCHEM, a.TABLE_NAME as TABLE_NAME, a.TEMPORARY as TEMPORARY, a.DURATION as DURATION, 'TABLE' as TABLE_TYPE, c.COMMENTS as REMARKS " + + String sql = "SELECT null as TABLE_CAT, a.OWNER as TABLE_SCHEM, a.TABLE_NAME as TABLE_NAME, a.TEMPORARY as TEMPORARY, " + + "a.DURATION as DURATION, 'TABLE' as TABLE_TYPE, c.COMMENTS as REMARKS, p.PARTITIONING_TYPE as PARTITION_TYPE " + "from ALL_TABLES a " + - "join ALL_TAB_COMMENTS c on a.TABLE_NAME=c.table_name and a.owner=c.owner "; + "join ALL_TAB_COMMENTS c on a.TABLE_NAME=c.table_name and a.owner=c.owner " + + "left join ALL_PART_TABLES p on a.TABLE_NAME=p.TABLE_NAME and a.OWNER=p.OWNER"; String allCatalogsString = getAllCatalogsStringScratchData(); if (tableName != null || allCatalogsString == null) { sql += "WHERE a.OWNER='" + ownerName + "'"; @@ -1058,6 +1060,12 @@ private List queryOracle(CatalogAndSchema catalogAndSchema, String ta } if (tableName != null) { sql += " AND a.TABLE_NAME='" + tableName + "'"; + } else { + sql += " ORDER BY" + + " CASE" + + " WHEN partitioning_type = 'REFERENCE' THEN 0" + + " ELSE 1" + + " END"; } return executeAndExtract(sql, database); From 9c30215d9a08ae9b557e3e9150de7fd92446cce7 Mon Sep 17 00:00:00 2001 From: vpetrovy Date: Thu, 20 Mar 2025 16:07:19 +0200 Subject: [PATCH 03/10] [DAT-18825] - try to make 'reference' partitions precede all others, and all others order should be unchanged --- .../src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liquibase-core/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java b/liquibase-core/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java index f7a91f5ca9..18e24066e2 100755 --- a/liquibase-core/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java @@ -1051,7 +1051,7 @@ private List queryOracle(CatalogAndSchema catalogAndSchema, String ta "a.DURATION as DURATION, 'TABLE' as TABLE_TYPE, c.COMMENTS as REMARKS, p.PARTITIONING_TYPE as PARTITION_TYPE " + "from ALL_TABLES a " + "join ALL_TAB_COMMENTS c on a.TABLE_NAME=c.table_name and a.owner=c.owner " + - "left join ALL_PART_TABLES p on a.TABLE_NAME=p.TABLE_NAME and a.OWNER=p.OWNER"; + "left join ALL_PART_TABLES p on a.TABLE_NAME=p.TABLE_NAME and a.OWNER=p.OWNER "; String allCatalogsString = getAllCatalogsStringScratchData(); if (tableName != null || allCatalogsString == null) { sql += "WHERE a.OWNER='" + ownerName + "'"; From 7c6b688387e96b24bc81120d0f0ab66d548c7818 Mon Sep 17 00:00:00 2001 From: vpetrovy Date: Fri, 21 Mar 2025 14:56:37 +0200 Subject: [PATCH 04/10] [DAT-18825] - use natural order for unexpected object --- .../java/liquibase/diff/output/changelog/DiffToChangeLog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java index 736f192bf6..d6cc34e47b 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java @@ -216,7 +216,7 @@ public List generateChangeSets() { types = getOrderedOutputTypes(UnexpectedObjectChangeGenerator.class); for (Class type : types) { ObjectQuotingStrategy quotingStrategy = diffOutputControl.getObjectQuotingStrategy(); - for (DatabaseObject object : sortUnexpectedObjects(diffResult.getUnexpectedObjects(type, comparator), diffResult.getReferenceSnapshot().getDatabase())) { + for (DatabaseObject object : sortUnexpectedObjects(diffResult.getUnexpectedObjects(type), diffResult.getReferenceSnapshot().getDatabase())) { if (!diffResult.getComparisonSnapshot().getDatabase().isLiquibaseObject(object) && !diffResult.getComparisonSnapshot().getDatabase().isSystemObject(object)) { Change[] changes = changeGeneratorFactory.fixUnexpected(object, diffOutputControl, diffResult.getReferenceSnapshot().getDatabase(), diffResult.getComparisonSnapshot().getDatabase()); addToChangeSets(changes, deleteChangeSets, quotingStrategy, created); From 6e5e9aecb332afe07ae756cc677a5f2c1c35f34e Mon Sep 17 00:00:00 2001 From: vpetrovy Date: Mon, 31 Mar 2025 13:19:37 +0300 Subject: [PATCH 05/10] [DAT-18825] - undo changes on Snapshot level --- .../diff/output/changelog/DiffToChangeLog.java | 2 +- .../liquibase/snapshot/JdbcDatabaseSnapshot.java | 12 ++---------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java index d6cc34e47b..736f192bf6 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java @@ -216,7 +216,7 @@ public List generateChangeSets() { types = getOrderedOutputTypes(UnexpectedObjectChangeGenerator.class); for (Class type : types) { ObjectQuotingStrategy quotingStrategy = diffOutputControl.getObjectQuotingStrategy(); - for (DatabaseObject object : sortUnexpectedObjects(diffResult.getUnexpectedObjects(type), diffResult.getReferenceSnapshot().getDatabase())) { + for (DatabaseObject object : sortUnexpectedObjects(diffResult.getUnexpectedObjects(type, comparator), diffResult.getReferenceSnapshot().getDatabase())) { if (!diffResult.getComparisonSnapshot().getDatabase().isLiquibaseObject(object) && !diffResult.getComparisonSnapshot().getDatabase().isSystemObject(object)) { Change[] changes = changeGeneratorFactory.fixUnexpected(object, diffOutputControl, diffResult.getReferenceSnapshot().getDatabase(), diffResult.getComparisonSnapshot().getDatabase()); addToChangeSets(changes, deleteChangeSets, quotingStrategy, created); diff --git a/liquibase-core/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java b/liquibase-core/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java index 18e24066e2..03a00fce4b 100755 --- a/liquibase-core/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java @@ -1047,11 +1047,9 @@ private List queryMssql(CatalogAndSchema catalogAndSchema, String tab private List queryOracle(CatalogAndSchema catalogAndSchema, String tableName) throws DatabaseException, SQLException { String ownerName = database.correctObjectName(catalogAndSchema.getCatalogName(), Schema.class); - String sql = "SELECT null as TABLE_CAT, a.OWNER as TABLE_SCHEM, a.TABLE_NAME as TABLE_NAME, a.TEMPORARY as TEMPORARY, " + - "a.DURATION as DURATION, 'TABLE' as TABLE_TYPE, c.COMMENTS as REMARKS, p.PARTITIONING_TYPE as PARTITION_TYPE " + + String sql = "SELECT null as TABLE_CAT, a.OWNER as TABLE_SCHEM, a.TABLE_NAME as TABLE_NAME, a.TEMPORARY as TEMPORARY, a.DURATION as DURATION, 'TABLE' as TABLE_TYPE, c.COMMENTS as REMARKS " + "from ALL_TABLES a " + - "join ALL_TAB_COMMENTS c on a.TABLE_NAME=c.table_name and a.owner=c.owner " + - "left join ALL_PART_TABLES p on a.TABLE_NAME=p.TABLE_NAME and a.OWNER=p.OWNER "; + "join ALL_TAB_COMMENTS c on a.TABLE_NAME=c.table_name and a.owner=c.owner "; String allCatalogsString = getAllCatalogsStringScratchData(); if (tableName != null || allCatalogsString == null) { sql += "WHERE a.OWNER='" + ownerName + "'"; @@ -1060,12 +1058,6 @@ private List queryOracle(CatalogAndSchema catalogAndSchema, String ta } if (tableName != null) { sql += " AND a.TABLE_NAME='" + tableName + "'"; - } else { - sql += " ORDER BY" + - " CASE" + - " WHEN partitioning_type = 'REFERENCE' THEN 0" + - " ELSE 1" + - " END"; } return executeAndExtract(sql, database); From 9e08ed2deb2e4415c5fd6fe4066a3bdccd799cfb Mon Sep 17 00:00:00 2001 From: vpetrovy Date: Mon, 31 Mar 2025 16:11:21 +0300 Subject: [PATCH 06/10] [DAT-18825] - try to apply ref part dependencies on graph --- .../output/changelog/DiffToChangeLog.java | 107 +++++++++++++++--- 1 file changed, 89 insertions(+), 18 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java index 736f192bf6..e5db247671 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java @@ -393,6 +393,71 @@ public String toString(String obj) { return rs; } + private List> queryForReferencePartitionedDependenciesOracle(Executor executor, List schemas) + throws DatabaseException { + List> rs = null; + try { + if (tryDbaDependencies) { + rs = executor.queryForList(new RawSqlStatement("SELECT UNIQUE\n" + + " c1.TABLE_OWNER AS OWNER,\n" + + " c1.TABLE_NAME AS NAME,\n" + + " c2.TABLE_OWNER AS REFERENCED_OWNER,\n" + + " c2.TABLE_NAME AS REFERENCED_NAME\n" + + "FROM dba_tab_partitions c1\n" + + " JOIN dba_constraints c ON c1.TABLE_NAME = c.TABLE_NAME\n" + + " JOIN dba_constraints p ON c.r_constraint_name = p.constraint_name\n" + + " JOIN dba_tab_partitions c2 ON p.TABLE_NAME = c2.TABLE_NAME\n" + + "WHERE c.constraint_type = 'R'\n" + + " AND c2.TABLE_OWNER != 'SYS'\n" + + " AND c1.TABLE_NAME != c2.TABLE_NAME\n" + + " AND c1.partition_name = c2.partition_name AND (" + StringUtils.join(schemas, " OR ", new StringUtils.StringUtilsFormatter() { + @Override + public String toString(String obj) { + return "c1.TABLE_OWNER='" + obj + "'"; + } + } + ) + ")")); + } else { + rs = executor.queryForList(new RawSqlStatement("SELECT UNIQUE\n" + + " c1.TABLE_OWNER AS OWNER,\n" + + " c1.TABLE_NAME AS NAME,\n" + + " c2.TABLE_OWNER AS REFERENCED_OWNER,\n" + + " c2.TABLE_NAME AS REFERENCED_NAME\n" + + "FROM all_tab_partitions c1\n" + + " JOIN all_constraints c ON c1.TABLE_NAME = c.TABLE_NAME\n" + + " JOIN all_constraints p ON c.r_constraint_name = p.constraint_name\n" + + " JOIN all_tab_partitions c2 ON p.TABLE_NAME = c2.TABLE_NAME\n" + + "WHERE c.constraint_type = 'R' -- Foreign Key Relationship\n" + + " AND c2.TABLE_OWNER != 'SYS'\n" + + " AND c1.TABLE_NAME != c2.TABLE_NAME\n" + + " AND c1.partition_name = c2.partition_name AND (" + StringUtils.join(schemas, " OR ", new StringUtils.StringUtilsFormatter() { + @Override + public String toString(String obj) { + return "c2.TABLE_OWNER='" + obj + "'"; + } + } + ) + ")")); + } + } catch (DatabaseException dbe) { + // + // If our exception is for something other than a missing table/view + // then we just re-throw the exception + // else if we can't see USER_DEPENDENCIES then we also re-throw + // to stop the recursion + // + String message = dbe.getMessage(); + if (!message.contains("ORA-00942: table or view does not exist")) { + throw new DatabaseException(dbe); + } else if (!tryDbaDependencies) { + throw new DatabaseException(dbe); + } + logger.warning("Unable to query DBA_DEPENDENCIES table. Switching to USER_DEPENDENCIES"); + tryDbaDependencies = false; + return queryForReferencePartitionedDependenciesOracle(executor, schemas); + } + return rs; + } + /** * Used by {@link #sortMissingObjects(Collection, Database)} to determine whether to go into the sorting logic. */ @@ -436,24 +501,10 @@ public String toString(String obj) { } } else if (database instanceof OracleDatabase) { Executor executor = ExecutorService.getInstance().getExecutor(database); - List> rs = queryForDependenciesOracle(executor, schemas); - for (Map row : rs) { - String tabName = null; - if (tryDbaDependencies) { - tabName = - StringUtils.trimToNull((String) row.get("OWNER")) + "." + - StringUtils.trimToNull((String) row.get("NAME")); - } else { - tabName = - StringUtils.trimToNull((String) row.get("REFERENCED_OWNER")) + "." + - StringUtils.trimToNull((String) row.get("NAME")); - } - String bName = - StringUtils.trimToNull((String) row.get("REFERENCED_OWNER")) + "." + - StringUtils.trimToNull((String) row.get("REFERENCED_NAME")); - - graph.add(bName, tabName); - } + List> declaredDependencies = queryForDependenciesOracle(executor, schemas); + addOracleDependencies(graph, declaredDependencies); + List> referencedPartDependencies = queryForReferencePartitionedDependenciesOracle(executor, schemas); + addOracleDependencies(graph, referencedPartDependencies); } else if (database instanceof MSSQLDatabase && database.getDatabaseMajorVersion() >= 9) { Executor executor = ExecutorService.getInstance().getExecutor(database); String sql = "select object_schema_name(referencing_id) as referencing_schema_name, object_name(referencing_id) as referencing_name, object_name(referenced_id) as referenced_name, object_schema_name(referenced_id) as referenced_schema_name from sys.sql_expression_dependencies depz where (" + StringUtils.join(schemas, " OR ", new StringUtils.StringUtilsFormatter() { @@ -567,6 +618,26 @@ public String toString(String obj) { } } + private void addOracleDependencies(DependencyUtil.DependencyGraph graph, List> dependenciesResultSet) { + for (Map row : dependenciesResultSet) { + String tabName = null; + if (tryDbaDependencies) { + tabName = + StringUtils.trimToNull((String) row.get("OWNER")) + "." + + StringUtils.trimToNull((String) row.get("NAME")); + } else { + tabName = + StringUtils.trimToNull((String) row.get("REFERENCED_OWNER")) + "." + + StringUtils.trimToNull((String) row.get("NAME")); + } + String bName = + StringUtils.trimToNull((String) row.get("REFERENCED_OWNER")) + "." + + StringUtils.trimToNull((String) row.get("REFERENCED_NAME")); + + graph.add(bName, tabName); + } + } + private String queryForDependenciesPostgreSql(List schemas){ //SQL adapted from https://wiki.postgresql.org/wiki/Pg_depend_display return "WITH RECURSIVE preference AS (\n" + From 294ff43a6df9a97f1d0d00f63e48642d321539c5 Mon Sep 17 00:00:00 2001 From: vpetrovy Date: Mon, 31 Mar 2025 16:39:18 +0300 Subject: [PATCH 07/10] [DAT-18825] - minor clean up --- .../java/liquibase/diff/output/changelog/DiffToChangeLog.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java index e5db247671..4ce5f29336 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java @@ -427,7 +427,7 @@ public String toString(String obj) { " JOIN all_constraints c ON c1.TABLE_NAME = c.TABLE_NAME\n" + " JOIN all_constraints p ON c.r_constraint_name = p.constraint_name\n" + " JOIN all_tab_partitions c2 ON p.TABLE_NAME = c2.TABLE_NAME\n" + - "WHERE c.constraint_type = 'R' -- Foreign Key Relationship\n" + + "WHERE c.constraint_type = 'R'\n" + " AND c2.TABLE_OWNER != 'SYS'\n" + " AND c1.TABLE_NAME != c2.TABLE_NAME\n" + " AND c1.partition_name = c2.partition_name AND (" + StringUtils.join(schemas, " OR ", new StringUtils.StringUtilsFormatter() { @@ -451,7 +451,7 @@ public String toString(String obj) { } else if (!tryDbaDependencies) { throw new DatabaseException(dbe); } - logger.warning("Unable to query DBA_DEPENDENCIES table. Switching to USER_DEPENDENCIES"); + logger.warning("Unable to query DBA_TAB_PARTITIONS table. Switching to ALL_TAB_PARTITIONS"); tryDbaDependencies = false; return queryForReferencePartitionedDependenciesOracle(executor, schemas); } From e218f0dea965079d8f6c38ed4e0047695e02bb74 Mon Sep 17 00:00:00 2001 From: vpetrovy Date: Mon, 31 Mar 2025 16:43:38 +0300 Subject: [PATCH 08/10] [DAT-18825] - minor clean up --- .../java/liquibase/diff/output/changelog/DiffToChangeLog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java index 4ce5f29336..a0cf691f12 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java @@ -442,7 +442,7 @@ public String toString(String obj) { // // If our exception is for something other than a missing table/view // then we just re-throw the exception - // else if we can't see USER_DEPENDENCIES then we also re-throw + // else if we can't see ALL_TAB_PARTITIONS then we also re-throw // to stop the recursion // String message = dbe.getMessage(); From 09c5ac7f7dea221ad4c5908d97be2b7c7f4d2d1d Mon Sep 17 00:00:00 2001 From: vpetrovy Date: Mon, 5 May 2025 16:02:16 +0300 Subject: [PATCH 09/10] [DAT-18825] - since referencing partition is possible only by foreign key, thus we can track all tables referencing integrity in Dependency Graph via 'R' constraint instead of drop all constraints in the very beginning of 'dropAll' operation --- .../output/changelog/DiffToChangeLog.java | 60 ++++++++----------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java index a0cf691f12..9bc8813f88 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java @@ -399,43 +399,35 @@ public String toString(String obj) { try { if (tryDbaDependencies) { rs = executor.queryForList(new RawSqlStatement("SELECT UNIQUE\n" + - " c1.TABLE_OWNER AS OWNER,\n" + - " c1.TABLE_NAME AS NAME,\n" + - " c2.TABLE_OWNER AS REFERENCED_OWNER,\n" + - " c2.TABLE_NAME AS REFERENCED_NAME\n" + - "FROM dba_tab_partitions c1\n" + - " JOIN dba_constraints c ON c1.TABLE_NAME = c.TABLE_NAME\n" + - " JOIN dba_constraints p ON c.r_constraint_name = p.constraint_name\n" + - " JOIN dba_tab_partitions c2 ON p.TABLE_NAME = c2.TABLE_NAME\n" + - "WHERE c.constraint_type = 'R'\n" + - " AND c2.TABLE_OWNER != 'SYS'\n" + - " AND c1.TABLE_NAME != c2.TABLE_NAME\n" + - " AND c1.partition_name = c2.partition_name AND (" + StringUtils.join(schemas, " OR ", new StringUtils.StringUtilsFormatter() { - @Override - public String toString(String obj) { - return "c1.TABLE_OWNER='" + obj + "'"; - } - } + " referencer.OWNER AS OWNER,\n" + + " referencer.TABLE_NAME AS NAME,\n" + + " referenced.OWNER AS REFERENCED_OWNER,\n" + + " referenced.TABLE_NAME AS REFERENCED_NAME\n" + + "FROM\n" + + " DBA_CONSTRAINTS referencer\n" + + " JOIN\n" + + " DBA_CONSTRAINTS referenced\n" + + " ON referencer.R_CONSTRAINT_NAME = referenced.CONSTRAINT_NAME\n" + + " AND referencer.R_OWNER = referenced.OWNER\n" + + "WHERE referencer.CONSTRAINT_TYPE = 'R' and referenced.OWNER != 'SYS' " + + "AND (" + StringUtils.join(schemas, " OR ", + (StringUtils.StringUtilsFormatter) obj -> "referencer.TABLE_OWNER='" + obj + "'" ) + ")")); } else { rs = executor.queryForList(new RawSqlStatement("SELECT UNIQUE\n" + - " c1.TABLE_OWNER AS OWNER,\n" + - " c1.TABLE_NAME AS NAME,\n" + - " c2.TABLE_OWNER AS REFERENCED_OWNER,\n" + - " c2.TABLE_NAME AS REFERENCED_NAME\n" + - "FROM all_tab_partitions c1\n" + - " JOIN all_constraints c ON c1.TABLE_NAME = c.TABLE_NAME\n" + - " JOIN all_constraints p ON c.r_constraint_name = p.constraint_name\n" + - " JOIN all_tab_partitions c2 ON p.TABLE_NAME = c2.TABLE_NAME\n" + - "WHERE c.constraint_type = 'R'\n" + - " AND c2.TABLE_OWNER != 'SYS'\n" + - " AND c1.TABLE_NAME != c2.TABLE_NAME\n" + - " AND c1.partition_name = c2.partition_name AND (" + StringUtils.join(schemas, " OR ", new StringUtils.StringUtilsFormatter() { - @Override - public String toString(String obj) { - return "c2.TABLE_OWNER='" + obj + "'"; - } - } + " referencer.OWNER AS OWNER,\n" + + " referencer.TABLE_NAME AS NAME,\n" + + " referenced.OWNER AS REFERENCED_OWNER,\n" + + " referenced.TABLE_NAME AS REFERENCED_NAME\n" + + "FROM\n" + + " ALL_CONSTRAINTS referencer\n" + + " JOIN\n" + + " ALL_CONSTRAINTS referenced\n" + + " ON referencer.R_CONSTRAINT_NAME = referenced.CONSTRAINT_NAME\n" + + " AND referencer.R_OWNER = referenced.OWNER\n" + + "WHERE referencer.CONSTRAINT_TYPE = 'R' and referenced.OWNER != 'SYS' " + + "AND (" + StringUtils.join(schemas, " OR ", + (StringUtils.StringUtilsFormatter) obj -> "referencer.TABLE_OWNER='" + obj + "'" ) + ")")); } } catch (DatabaseException dbe) { From 570c5b558b11f4831418eed3bb357968498458c2 Mon Sep 17 00:00:00 2001 From: vpetrovy Date: Mon, 5 May 2025 17:38:07 +0300 Subject: [PATCH 10/10] [DAT-18825] - woops, syntax error fix --- .../java/liquibase/diff/output/changelog/DiffToChangeLog.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java index 9bc8813f88..1de56cc3be 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java @@ -411,7 +411,7 @@ public String toString(String obj) { " AND referencer.R_OWNER = referenced.OWNER\n" + "WHERE referencer.CONSTRAINT_TYPE = 'R' and referenced.OWNER != 'SYS' " + "AND (" + StringUtils.join(schemas, " OR ", - (StringUtils.StringUtilsFormatter) obj -> "referencer.TABLE_OWNER='" + obj + "'" + (StringUtils.StringUtilsFormatter) obj -> "referencer.OWNER='" + obj + "'" ) + ")")); } else { rs = executor.queryForList(new RawSqlStatement("SELECT UNIQUE\n" + @@ -427,7 +427,7 @@ public String toString(String obj) { " AND referencer.R_OWNER = referenced.OWNER\n" + "WHERE referencer.CONSTRAINT_TYPE = 'R' and referenced.OWNER != 'SYS' " + "AND (" + StringUtils.join(schemas, " OR ", - (StringUtils.StringUtilsFormatter) obj -> "referencer.TABLE_OWNER='" + obj + "'" + (StringUtils.StringUtilsFormatter) obj -> "referencer.OWNER='" + obj + "'" ) + ")")); } } catch (DatabaseException dbe) {