From 9e9f3d42beb78886e58eb6e531e4894ba2308fe9 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Thu, 21 Nov 2024 11:30:10 +0000 Subject: [PATCH 01/18] Fix all int tests. Added TODO for moving utility method decodeBlobHexFromBytesToText() to read hex value from blob field. It would make more sense as decodeBlobHexFromBytesToBytes and then we would read raw data - or not. --- .../morf/jdbc/DatabaseMetaDataProvider.java | 5 +- .../TestDatabaseUpgradeIntegration.java | 2 +- .../morf/integration/TestSqlStatements.java | 52 +++++++++++++------ ...tDatabaseUpgradePathValidationService.java | 2 + .../jdbc/postgresql/PostgreSQLDialect.java | 4 +- .../PostgreSQLMetaDataProvider.java | 34 +++++++++--- 6 files changed, 73 insertions(+), 26 deletions(-) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java index b3c7a9165..ddeac5094 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java @@ -28,10 +28,12 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -116,7 +118,7 @@ public abstract class DatabaseMetaDataProvider implements Schema { private final LoadingCache sequenceCache = CacheBuilder.newBuilder().build(CacheLoader.from(this::loadSequence)); private final Supplier> databaseInformation = Suppliers.memoize(this::loadDatabaseInformation); - + protected Supplier> ignoredTables = Suppliers.memoize(this::getIgnoredTables); /** * @param connection The database connection from which meta data should be provided. @@ -149,6 +151,7 @@ private Map loadDatabaseInformation() { } } + protected Set getIgnoredTables() { return new HashSet<>(); } /** * @see org.alfasoftware.morf.metadata.Schema#isEmptyDatabase() diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestDatabaseUpgradeIntegration.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestDatabaseUpgradeIntegration.java index c569554a0..29cdba1cd 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestDatabaseUpgradeIntegration.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestDatabaseUpgradeIntegration.java @@ -1049,7 +1049,7 @@ private void doAddColumn(Class upgradeStep) throws SQLExc "(?is)(" + "NULL not allowed for column \"ANOTHERVALUE\"" + ".*)" // H2 + "|(" + "Field 'anotherValue' doesn't have a default value" + ".*)" // MySQL + "|(" + "ORA-01400: cannot insert NULL into \\(.*ANOTHERVALUE.*\\)" + ".*)" // Oracle - + "|(" + "ERROR: null value in column \"anothervalue\" violates not-null constraint" + ".*)" // PgSQL + + "|(" + "ERROR: null value in column \"anothervalue\" of relation \"withdefaultvalue\" violates not-null constraint" + ".*)" // PgSQL )); } } diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java index 8e88df0ec..68e6e2883 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java @@ -142,19 +142,13 @@ import org.alfasoftware.morf.sql.SelectStatement; import org.alfasoftware.morf.sql.TruncateStatement; import org.alfasoftware.morf.sql.UpdateStatement; -import org.alfasoftware.morf.sql.element.AliasedField; -import org.alfasoftware.morf.sql.element.CaseStatement; -import org.alfasoftware.morf.sql.element.Cast; -import org.alfasoftware.morf.sql.element.Criterion; -import org.alfasoftware.morf.sql.element.FieldLiteral; -import org.alfasoftware.morf.sql.element.FieldReference; -import org.alfasoftware.morf.sql.element.Function; -import org.alfasoftware.morf.sql.element.SqlParameter; -import org.alfasoftware.morf.sql.element.TableReference; +import org.alfasoftware.morf.sql.element.*; import org.alfasoftware.morf.testing.DatabaseSchemaManager; import org.alfasoftware.morf.testing.DatabaseSchemaManager.TruncationBehavior; import org.alfasoftware.morf.testing.TestingDataSourceModule; import org.alfasoftware.morf.upgrade.LoggingSqlScriptVisitor; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -1655,8 +1649,12 @@ public void testBlobFields() throws SQLException { field("column1").eq(blobLiteral(BLOB1_VALUE.getBytes())), field("column1").eq(blobLiteral(BLOB1_VALUE)) )); + // this update fails to work as an update without a WHERE clause - it strangely inserts a duplicate row on Postgres without a where clause UpdateStatement updateStatement = update(tableRef("BlobTable")) - .set(blobLiteral(BLOB1_VALUE + " Updated").as("column1"), blobLiteral((BLOB2_VALUE + " Updated").getBytes()).as("column2")); + .set(blobLiteral(BLOB1_VALUE + " Updated").as("column1"), blobLiteral((BLOB2_VALUE + " Updated").getBytes()).as("column2")) + .where( + field("column1").eq(blobLiteral((BLOB1_VALUE).getBytes())) + ); SelectStatement selectStatementAfterUpdate = select(field("column1"), field("column2")) .from(tableRef("BlobTable")) .where(or( @@ -1676,13 +1674,13 @@ public Integer process(ResultSet resultSet) throws SQLException { int result = 0; while (resultSet.next()) { result++; - assertEquals("column1 blob value not correctly set/returned after insert", BLOB1_VALUE, new String(resultSet.getBytes(1))); - assertEquals("column2 blob value not correctly set/returned after insert", BLOB2_VALUE, new String(resultSet.getBytes(2))); + assertEquals("column1 blob value not correctly set/returned after insert", BLOB1_VALUE, decodeBlobHexFromBytesToText(resultSet.getBytes(1))); + assertEquals("column2 blob value not correctly set/returned after insert", BLOB2_VALUE, decodeBlobHexFromBytesToText(resultSet.getBytes(2))); } return result; } }); - assertEquals("Should be exactly two records", 2, numberOfRecords.intValue()); + assertEquals("Should be exactly one record", 1, numberOfRecords.intValue()); // Update executor.execute(ImmutableList.of(convertStatementToSQL(updateStatement)), connection); @@ -1696,13 +1694,35 @@ public Integer process(ResultSet resultSet) throws SQLException { int result = 0; while (resultSet.next()) { result++; - assertEquals("column1 blob value not correctly set/returned after update", BLOB1_VALUE + " Updated", new String(resultSet.getBytes(1))); - assertEquals("column2 blob value not correctly set/returned after update", BLOB2_VALUE + " Updated", new String(resultSet.getBytes(2))); + String blob1 = decodeBlobHexFromBytesToText(resultSet.getBytes(1)); + assertEquals("column1 blob value not correctly set/returned after update", BLOB1_VALUE + " Updated", decodeBlobHexFromBytesToText(resultSet.getBytes(1))); + assertEquals("column2 blob value not correctly set/returned after update", BLOB2_VALUE + " Updated", decodeBlobHexFromBytesToText(resultSet.getBytes(2))); } return result; } }); - assertEquals("Should be exactly two records", 2, numberOfRecords.intValue()); + assertEquals("Should be exactly one records", 1, numberOfRecords.intValue()); + } + + // TODO: this utility method or something that returns byte array should probably be exposed as public in mor + // don't know where yet + private static String decodeBlobHexFromBytesToText(byte[] bytSrc) throws SQLException { + String blobStringResult; + Hex hexUtil = new Hex(); + try { + int lenSrc = bytSrc.length; + char[] charBlob = new char[lenSrc]; + byte[] bytBlob = new byte[charBlob.length >> 1]; + for (int i = 0; i < bytSrc.length; i++) { + charBlob[i] = (char) bytSrc[i]; + } + hexUtil.decodeHex(charBlob, bytBlob, 0); + + blobStringResult = new String(bytBlob); + } catch (DecoderException e) { + throw new RuntimeException(e); + } + return blobStringResult; } diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/upgrade/TestDatabaseUpgradePathValidationService.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/upgrade/TestDatabaseUpgradePathValidationService.java index 3794b2771..313fe1cae 100644 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/upgrade/TestDatabaseUpgradePathValidationService.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/upgrade/TestDatabaseUpgradePathValidationService.java @@ -81,6 +81,8 @@ public void setup() { @After public void tearDown() { schemaManager.invalidateCache(); + // to make following test on test suite run clean - org.alfasoftware.morf.upgrade.TestFullDeployment + schemaManager.dropAllTables(); } diff --git a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLDialect.java b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLDialect.java index e906fa4f6..b3a11d3a7 100644 --- a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLDialect.java +++ b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLDialect.java @@ -508,7 +508,9 @@ protected String getSqlFrom(ConcatenatedField concatenatedField) { @Override protected String getSqlFrom(BlobFieldLiteral field) { - return String.format("E'\\x%s'", field.getValue()); + // this format doesn't work with blob fields: String.format("E'\\x%s'", field.getValue()); + // see org.alfasoftware.morf.integration.TestSqlStatements#testBlobFields + return String.format("'%s'", field.getValue()); } @Override diff --git a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java index 5b4edf60a..190e5ba33 100644 --- a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java +++ b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java @@ -3,13 +3,13 @@ import static org.alfasoftware.morf.jdbc.DatabaseMetaDataProviderUtils.getAutoIncrementStartValue; import static org.alfasoftware.morf.jdbc.DatabaseMetaDataProviderUtils.getDataTypeFromColumnComment; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Types; -import java.util.Map; -import java.util.Optional; +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; +import java.sql.Date; +import java.util.*; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -44,6 +44,26 @@ public PostgreSQLMetaDataProvider(Connection connection, String schemaName) { } + @Override + protected Set getIgnoredTables() { + Set ignoredTables = new HashSet<>(); + try(Statement ignoredTablesStmt = connection.createStatement()) { + try (ResultSet ignoredTablesRs = ignoredTablesStmt.executeQuery("select relname from pg_class where relispartition and relkind = 'r'")) { + while (ignoredTablesRs.next()) { + ignoredTables.add(ignoredTablesRs.getString(1).toLowerCase(Locale.ROOT)); + } + } + } catch (SQLException e) { + // ignore exception, if it fails then incompatible Postgres version + } + return ignoredTables; + } + + @Override + protected boolean isIgnoredTable(@SuppressWarnings("unused") RealName tableName) { + return ignoredTables.get().contains(tableName.getDbName().toLowerCase(Locale.ROOT)); + } + @Override protected boolean isPrimaryKeyIndex(RealName indexName) { return indexName.getDbName().endsWith("_pk"); From 30f66d71ea53769adf47903a7ee78a7b5653b2a1 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Wed, 4 Dec 2024 10:07:26 +0000 Subject: [PATCH 02/18] Fix Postgres TestPostgreSQLDialect.expectedBlobLiteral to NOT use E'\\x%s' using instead the plain blobLiteral, which expects an hexadecimal encoded value with morf blobLiteral(value). --- .../morf/jdbc/postgresql/TestPostgreSQLDialect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java index cfbd2533a..4486efd30 100644 --- a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java +++ b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java @@ -567,7 +567,7 @@ protected String expectedBooleanLiteral(boolean value) { */ @Override protected String expectedBlobLiteral(String value) { - return String.format("E'\\x%s'", value); + return String.format("'%s'", value); } From 1422ab2e944a706f47d036f3d23c12cb5944e1fd Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Wed, 4 Dec 2024 16:28:14 +0000 Subject: [PATCH 03/18] Added method DatabaseMetaDataProvider.getPartitionedTables, and on PostgreSQLMetaDataProvider, to read the actual partitioned tables as regular ones. Those tables are represented in a distinct form when Postgres. --- .../morf/jdbc/DatabaseMetaDataProvider.java | 8 ++++ .../PostgreSQLMetaDataProvider.java | 38 +++++++++++++++---- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java index ddeac5094..70b6e6982 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java @@ -119,6 +119,7 @@ public abstract class DatabaseMetaDataProvider implements Schema { private final Supplier> databaseInformation = Suppliers.memoize(this::loadDatabaseInformation); protected Supplier> ignoredTables = Suppliers.memoize(this::getIgnoredTables); + protected Supplier> partitionedTables = Suppliers.memoize(this::getPartitionedTables); /** * @param connection The database connection from which meta data should be provided. @@ -153,6 +154,8 @@ private Map loadDatabaseInformation() { protected Set getIgnoredTables() { return new HashSet<>(); } + protected Set getPartitionedTables() { return new HashSet<>(); } + /** * @see org.alfasoftware.morf.metadata.Schema#isEmptyDatabase() */ @@ -310,6 +313,11 @@ protected Map loadAllTableNames() { throw new RuntimeSqlException("Error reading metadata for table ["+tableName+"]", e); } } + // add partitioned tables to list + partitionedTables.get().forEach(table -> { + RealName partionedTableName = createRealName(table, table); + tableNameMappings.put(partionedTableName, partionedTableName); + }); long end = System.currentTimeMillis(); Map tableNameMap = tableNameMappings.build(); diff --git a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java index 190e5ba33..c4b290154 100644 --- a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java +++ b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java @@ -3,13 +3,16 @@ import static org.alfasoftware.morf.jdbc.DatabaseMetaDataProviderUtils.getAutoIncrementStartValue; import static org.alfasoftware.morf.jdbc.DatabaseMetaDataProviderUtils.getDataTypeFromColumnComment; -import java.io.InputStream; -import java.io.Reader; -import java.math.BigDecimal; -import java.net.URL; -import java.sql.*; -import java.sql.Date; -import java.util.*; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -48,6 +51,8 @@ public PostgreSQLMetaDataProvider(Connection connection, String schemaName) { protected Set getIgnoredTables() { Set ignoredTables = new HashSet<>(); try(Statement ignoredTablesStmt = connection.createStatement()) { + // distinguish partitioned tables from regular ones: relkind = 'p' (partition) or 'r' (regular) also can use boolean col relispartition + // a partition table attached has (r, true) try (ResultSet ignoredTablesRs = ignoredTablesStmt.executeQuery("select relname from pg_class where relispartition and relkind = 'r'")) { while (ignoredTablesRs.next()) { ignoredTables.add(ignoredTablesRs.getString(1).toLowerCase(Locale.ROOT)); @@ -59,6 +64,25 @@ protected Set getIgnoredTables() { return ignoredTables; } + @Override + protected Set getPartitionedTables() { + Set partitionedTables = new HashSet<>(); + try(Statement partitionedTablesStmt = connection.createStatement()) { + // distinguish partitioned tables from regular ones: relkind = 'p' (partition) or 'r' (regular) also can use boolean col relispartition + // a partition table attached has (r, true) + // a partition table has (p, false) + try (ResultSet ignoredTablesRs = partitionedTablesStmt.executeQuery("select relname from pg_class where not relispartition and relkind = 'p'")) { + while (ignoredTablesRs.next()) { + partitionedTables.add(ignoredTablesRs.getString(1).toLowerCase(Locale.ROOT)); + } + } + } catch (SQLException e) { + // ignore exception, if it fails then incompatible Postgres version + } + return partitionedTables; + } + + @Override protected boolean isIgnoredTable(@SuppressWarnings("unused") RealName tableName) { return ignoredTables.get().contains(tableName.getDbName().toLowerCase(Locale.ROOT)); From 178ccbcac50b49e34e55cfaf3a5c4b58560285a7 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Wed, 4 Dec 2024 17:53:21 +0000 Subject: [PATCH 04/18] Fix TestSqlStatements.testBlobFields for H2 and Oracle. Changed comments on PostgreSQLDialect --- .../morf/integration/TestSqlStatements.java | 47 +++++++++++++++---- .../jdbc/postgresql/PostgreSQLDialect.java | 3 +- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java index 68e6e2883..5c7f2b441 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java @@ -116,6 +116,7 @@ import java.util.List; import java.util.Random; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import javax.sql.DataSource; @@ -142,7 +143,15 @@ import org.alfasoftware.morf.sql.SelectStatement; import org.alfasoftware.morf.sql.TruncateStatement; import org.alfasoftware.morf.sql.UpdateStatement; -import org.alfasoftware.morf.sql.element.*; +import org.alfasoftware.morf.sql.element.AliasedField; +import org.alfasoftware.morf.sql.element.CaseStatement; +import org.alfasoftware.morf.sql.element.Cast; +import org.alfasoftware.morf.sql.element.Criterion; +import org.alfasoftware.morf.sql.element.FieldLiteral; +import org.alfasoftware.morf.sql.element.FieldReference; +import org.alfasoftware.morf.sql.element.Function; +import org.alfasoftware.morf.sql.element.SqlParameter; +import org.alfasoftware.morf.sql.element.TableReference; import org.alfasoftware.morf.testing.DatabaseSchemaManager; import org.alfasoftware.morf.testing.DatabaseSchemaManager.TruncationBehavior; import org.alfasoftware.morf.testing.TestingDataSourceModule; @@ -1668,19 +1677,32 @@ public void testBlobFields() throws SQLException { // Check result - note that this is deliberately not tidy - we are making sure that results get // passed back up to this scope correctly. String sql = convertStatementToSQL(selectStatementAfterInsert); + AtomicBoolean isFirstValueHex = new AtomicBoolean(false); Integer numberOfRecords = executor.executeQuery(sql, connection, new ResultSetProcessor() { @Override public Integer process(ResultSet resultSet) throws SQLException { int result = 0; while (resultSet.next()) { result++; - assertEquals("column1 blob value not correctly set/returned after insert", BLOB1_VALUE, decodeBlobHexFromBytesToText(resultSet.getBytes(1))); - assertEquals("column2 blob value not correctly set/returned after insert", BLOB2_VALUE, decodeBlobHexFromBytesToText(resultSet.getBytes(2))); + byte[] bytesFromFirst = resultSet.getBytes("column1"); + + if (bytesFromFirst[1] == 32) { // if second char is a space then it isn't hex encoded + assertEquals("column1 blob value not correctly set/returned after insert", BLOB1_VALUE, new String(resultSet.getBytes(1))); + assertEquals("column2 blob value not correctly set/returned after insert", BLOB2_VALUE, new String(resultSet.getBytes(2))); + } else { + isFirstValueHex.set(true); + assertEquals("column1 blob value not correctly set/returned after insert", BLOB1_VALUE, decodeBlobHexFromBytesToText(resultSet.getBytes(1))); + assertEquals("column2 blob value not correctly set/returned after insert", BLOB2_VALUE, decodeBlobHexFromBytesToText(resultSet.getBytes(2))); + } } return result; } }); - assertEquals("Should be exactly one record", 1, numberOfRecords.intValue()); + if (isFirstValueHex.get()) { + assertEquals("Should be exactly one record", 1, numberOfRecords.intValue()); + } else { + assertEquals("Should be exactly two records", 2, numberOfRecords.intValue()); + } // Update executor.execute(ImmutableList.of(convertStatementToSQL(updateStatement)), connection); @@ -1688,24 +1710,33 @@ public Integer process(ResultSet resultSet) throws SQLException { // Check result- note that this is deliberately not tidy - we are making sure that results get // passed back up to this scope correctly. sql = convertStatementToSQL(selectStatementAfterUpdate); + AtomicBoolean isUpdateFirstValueHex = new AtomicBoolean(false); numberOfRecords = executor.executeQuery(sql, connection, new ResultSetProcessor() { @Override public Integer process(ResultSet resultSet) throws SQLException { int result = 0; while (resultSet.next()) { result++; - String blob1 = decodeBlobHexFromBytesToText(resultSet.getBytes(1)); + byte[] bytesFromFirst = resultSet.getBytes("column1"); + if (bytesFromFirst[1] == 32) { // if second char is a space then it isn't hex encoded + assertEquals("column1 blob value not correctly set/returned after update", BLOB1_VALUE + " Updated", new String(resultSet.getBytes(1))); + assertEquals("column2 blob value not correctly set/returned after update", BLOB2_VALUE + " Updated", new String(resultSet.getBytes(2))); + } else { + isUpdateFirstValueHex.set(true); assertEquals("column1 blob value not correctly set/returned after update", BLOB1_VALUE + " Updated", decodeBlobHexFromBytesToText(resultSet.getBytes(1))); assertEquals("column2 blob value not correctly set/returned after update", BLOB2_VALUE + " Updated", decodeBlobHexFromBytesToText(resultSet.getBytes(2))); + } } return result; } }); - assertEquals("Should be exactly one records", 1, numberOfRecords.intValue()); + if (isUpdateFirstValueHex.get()) { + assertEquals("Should be exactly one records", 1, numberOfRecords.intValue()); + } else { + assertEquals("Should be exactly two records", 2, numberOfRecords.intValue()); + } } - // TODO: this utility method or something that returns byte array should probably be exposed as public in mor - // don't know where yet private static String decodeBlobHexFromBytesToText(byte[] bytSrc) throws SQLException { String blobStringResult; Hex hexUtil = new Hex(); diff --git a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLDialect.java b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLDialect.java index b3a11d3a7..96bb233b8 100644 --- a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLDialect.java +++ b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLDialect.java @@ -508,8 +508,7 @@ protected String getSqlFrom(ConcatenatedField concatenatedField) { @Override protected String getSqlFrom(BlobFieldLiteral field) { - // this format doesn't work with blob fields: String.format("E'\\x%s'", field.getValue()); - // see org.alfasoftware.morf.integration.TestSqlStatements#testBlobFields + // this format doesn't work with blob fields: E'\\x' because it will eat the first value of the string on retrieval return String.format("'%s'", field.getValue()); } From a010d49ed01d0edb0d2f4243694712a0b260358f Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Sat, 7 Dec 2024 22:05:10 +0000 Subject: [PATCH 05/18] Add coverage to partition tables. --- .../jdbc/TestDatabaseMetaDataProvider.java | 55 +++++++++++++++++-- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java index 1bf088389..99ea51f03 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java @@ -16,7 +16,12 @@ package org.alfasoftware.morf.jdbc; import static java.util.stream.Collectors.toList; -import static org.alfasoftware.morf.metadata.SchemaUtils.*; +import static org.alfasoftware.morf.metadata.SchemaUtils.column; +import static org.alfasoftware.morf.metadata.SchemaUtils.index; +import static org.alfasoftware.morf.metadata.SchemaUtils.schema; +import static org.alfasoftware.morf.metadata.SchemaUtils.sequence; +import static org.alfasoftware.morf.metadata.SchemaUtils.table; +import static org.alfasoftware.morf.metadata.SchemaUtils.view; import static org.alfasoftware.morf.sql.SqlUtils.field; import static org.alfasoftware.morf.sql.SqlUtils.select; import static org.alfasoftware.morf.sql.SqlUtils.tableRef; @@ -29,6 +34,7 @@ import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -37,10 +43,16 @@ import java.util.List; import java.util.function.Function; -import net.jcip.annotations.NotThreadSafe; - import org.alfasoftware.morf.guicesupport.InjectMembersRule; -import org.alfasoftware.morf.metadata.*; +import org.alfasoftware.morf.metadata.Column; +import org.alfasoftware.morf.metadata.DataType; +import org.alfasoftware.morf.metadata.Index; +import org.alfasoftware.morf.metadata.Schema; +import org.alfasoftware.morf.metadata.SchemaResource; +import org.alfasoftware.morf.metadata.SchemaUtils; +import org.alfasoftware.morf.metadata.Sequence; +import org.alfasoftware.morf.metadata.Table; +import org.alfasoftware.morf.metadata.View; import org.alfasoftware.morf.sql.SelectStatement; import org.alfasoftware.morf.testing.DatabaseSchemaManager; import org.alfasoftware.morf.testing.DatabaseSchemaManager.TruncationBehavior; @@ -56,8 +68,11 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; +import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.inject.Inject; +import net.jcip.annotations.NotThreadSafe; + /** * Tests for {@link DatabaseMetaDataProvider}. * @@ -117,7 +132,12 @@ public class TestDatabaseMetaDataProvider { column("bigIntegerCol", DataType.BIG_INTEGER).defaultValue("8"), column("booleanCol", DataType.BOOLEAN).defaultValue("1"), column("integerTenCol", DataType.INTEGER).defaultValue("17"), - column("dateCol", DataType.DATE).defaultValue("2020-01-01")) + column("dateCol", DataType.DATE).defaultValue("2020-01-01")), + table("WithPartition") + .columns( + SchemaUtils.idColumn(), + column("stringCol", DataType.STRING, 20) + ) ), schema( view("ViewWithTypes", select(field("primaryStringCol"), field("id")).from("WithTypes").crossJoin(tableRef("WithDefaults"))), @@ -300,6 +320,31 @@ public void testTableWithLobs() throws SQLException { } + @Test + public void testTableWithPartition() throws SQLException { + boolean isPostgres = databaseType.equals("PGSQL"); + // RE-CREATE table with two partitions on table WithPartition + try (Connection connection = database.getDataSource().getConnection()) { + if (isPostgres) { + String schema = Strings.isNullOrEmpty(database.getSchemaName()) ? "" : database.getSchemaName() + "."; + connection.createStatement().executeUpdate("DROP TABLE " + schema + "WithPartition"); + connection.createStatement().executeUpdate("CREATE TABLE " + schema + "WithPartition(id numeric(19) NOT NULL, stringCol VARCHAR(20)) PARTITION BY RANGE (id)"); + connection.createStatement().executeUpdate("CREATE TABLE " + schema + "WithPartition_p0 PARTITION OF " + schema + "WithPartition FOR VALUES FROM (0) TO (10000)"); + connection.createStatement().executeUpdate("CREATE TABLE " + schema + "WithPartition_p1 PARTITION OF " + schema + "WithPartition FOR VALUES FROM (10000) TO (99999)"); + } + } + + try(SchemaResource schemaResource = database.openSchemaResource()) { + assertTrue(schemaResource.tableExists("WithPartition")); + + if (isPostgres) { + UncheckedExecutionException uncheckedExecutionException = assertThrows(UncheckedExecutionException.class, () -> schemaResource.getTable("WithPartition_p0")); + assertTrue("partition must not be found on getTable", uncheckedExecutionException.getMessage().contains("Table [WithPartition_p0/*] not found.")); + } + } + } + + @Test public void testTableWithDefaults() throws SQLException { try(SchemaResource schemaResource = database.openSchemaResource()) { From 862e8a289b2e46c9633df0bb787daa1d711e2cd0 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Sun, 8 Dec 2024 10:48:22 +0000 Subject: [PATCH 06/18] Add methods Schema.partitionedTableNames and Schema.partitionTableNames. Add coverage to changed code. --- .../morf/dataset/SchemaAdapter.java | 10 ++ .../morf/dataset/WithMetaDataAdapter.java | 10 ++ .../morf/jdbc/DatabaseMetaDataProvider.java | 7 + .../morf/metadata/CompositeSchema.java | 11 ++ .../alfasoftware/morf/metadata/Schema.java | 20 +++ .../morf/metadata/SchemaBean.java | 11 ++ .../morf/upgrade/adapt/TableSetSchema.java | 11 ++ .../morf/xml/XmlDataSetProducer.java | 12 +- .../morf/dataset/TestWithMetaDataAdapter.java | 19 ++- .../morf/metadata/TestSchemaBean.java | 18 ++- .../excel/SpreadsheetDataSetProducer.java | 12 +- .../morf/jdbc/h2/H2MetaDataProvider.java | 7 + .../morf/dataset/MockDataSetProducer.java | 11 ++ .../jdbc/TestDatabaseMetaDataProvider.java | 2 + .../jdbc/mysql/MySqlMetaDataProvider.java | 7 + .../jdbc/oracle/OracleMetaDataProvider.java | 10 ++ .../PostgreSQLMetaDataProvider.java | 6 + .../TestPostgreSqlMetaDataProvider.java | 140 ++++++++++++++++-- .../sqlserver/SqlServerMetaDataProvider.java | 7 + 19 files changed, 317 insertions(+), 14 deletions(-) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/dataset/SchemaAdapter.java b/morf-core/src/main/java/org/alfasoftware/morf/dataset/SchemaAdapter.java index 470aedb14..86a417f86 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/dataset/SchemaAdapter.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/dataset/SchemaAdapter.java @@ -78,6 +78,16 @@ public Collection tableNames() { return delegate.tableNames(); } + @Override + public Collection partitionedTableNames() { + return delegate.partitionedTableNames(); + } + + @Override + public Collection partitionTableNames() { + return delegate.partitionTableNames(); + } + /** * @see org.alfasoftware.morf.metadata.Schema#tables() diff --git a/morf-core/src/main/java/org/alfasoftware/morf/dataset/WithMetaDataAdapter.java b/morf-core/src/main/java/org/alfasoftware/morf/dataset/WithMetaDataAdapter.java index 61b964393..2faeb4236 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/dataset/WithMetaDataAdapter.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/dataset/WithMetaDataAdapter.java @@ -99,6 +99,16 @@ public Collection tableNames() { return sourceSchema.tableNames(); } + @Override + public Collection partitionedTableNames() { + return sourceSchema.partitionedTableNames(); + } + + @Override + public Collection partitionTableNames() { + return sourceSchema.partitionTableNames(); + } + @Override public Collection tables() { Set
tables = new HashSet<>(); diff --git a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java index 70b6e6982..6c029f150 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java @@ -191,6 +191,13 @@ public Collection tableNames() { return tableNames.get().values().stream().map(RealName::getRealName).collect(Collectors.toList()); } + /** + * @see org.alfasoftware.morf.metadata.Schema#tableNames() + */ + @Override + public Collection partitionedTableNames() { + return new ArrayList<>(partitionedTables.get()); + } /** * @see org.alfasoftware.morf.metadata.Schema#tables() diff --git a/morf-core/src/main/java/org/alfasoftware/morf/metadata/CompositeSchema.java b/morf-core/src/main/java/org/alfasoftware/morf/metadata/CompositeSchema.java index f5e9ca1d9..f8afe5eee 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/metadata/CompositeSchema.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/metadata/CompositeSchema.java @@ -16,6 +16,7 @@ package org.alfasoftware.morf.metadata; import java.util.Collection; +import java.util.List; import java.util.Set; import com.google.common.collect.Sets; @@ -99,6 +100,16 @@ public Collection tableNames() { return result; } + @Override + public Collection partitionedTableNames() { + return List.of(); + } + + @Override + public Collection partitionTableNames() { + return List.of(); + } + /** * @see org.alfasoftware.morf.metadata.Schema#tables() diff --git a/morf-core/src/main/java/org/alfasoftware/morf/metadata/Schema.java b/morf-core/src/main/java/org/alfasoftware/morf/metadata/Schema.java index 3568f69cc..a58c46492 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/metadata/Schema.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/metadata/Schema.java @@ -61,6 +61,26 @@ public interface Schema { */ public Collection tableNames(); + /** + * Provides the names of all partition tables in the database. This applies for now for postgres. Note that the order of + * the tables in the result is not specified. The case of the + * table names may be preserved when logging progress, but should not be relied on for schema + * processing. + * + * @return A collection of all partitioned table names available in the database. + */ + Collection partitionedTableNames(); + + /** + * Provides the names of all partition tables in the database. This applies for now for postgres. Note that the order of + * the tables in the result is not specified. The case of the + * table names may be preserved when logging progress, but should not be relied on for schema + * processing. + * + * @return A collection of all partition table names available in the database. + */ + Collection partitionTableNames(); + /** * @return the tables in in the schema represented by this metadata */ diff --git a/morf-core/src/main/java/org/alfasoftware/morf/metadata/SchemaBean.java b/morf-core/src/main/java/org/alfasoftware/morf/metadata/SchemaBean.java index fc8de400b..0f1b0202a 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/metadata/SchemaBean.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/metadata/SchemaBean.java @@ -21,6 +21,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -194,6 +195,16 @@ public Collection tableNames() { return names; } + @Override + public Collection partitionedTableNames() { + return List.of(); + } + + @Override + public Collection partitionTableNames() { + return List.of(); + } + /** * {@inheritDoc} diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/adapt/TableSetSchema.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/adapt/TableSetSchema.java index 9e141a837..8fba85c51 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/adapt/TableSetSchema.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/adapt/TableSetSchema.java @@ -19,6 +19,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.alfasoftware.morf.metadata.Schema; @@ -107,6 +108,16 @@ public Collection tableNames() { return names; } + @Override + public Collection partitionedTableNames() { + return List.of(); + } + + @Override + public Collection partitionTableNames() { + return List.of(); + } + /** * @see org.alfasoftware.morf.metadata.Schema#viewExists(java.lang.String) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/xml/XmlDataSetProducer.java b/morf-core/src/main/java/org/alfasoftware/morf/xml/XmlDataSetProducer.java index 6752b9179..f4fcfb491 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/xml/XmlDataSetProducer.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/xml/XmlDataSetProducer.java @@ -43,13 +43,13 @@ import org.alfasoftware.morf.dataset.Record; import org.alfasoftware.morf.metadata.Column; import org.alfasoftware.morf.metadata.DataSetUtils; +import org.alfasoftware.morf.metadata.DataSetUtils.RecordBuilder; import org.alfasoftware.morf.metadata.DataType; import org.alfasoftware.morf.metadata.Index; import org.alfasoftware.morf.metadata.Schema; import org.alfasoftware.morf.metadata.SchemaUtils; import org.alfasoftware.morf.metadata.Sequence; import org.alfasoftware.morf.metadata.Table; -import org.alfasoftware.morf.metadata.DataSetUtils.RecordBuilder; import org.alfasoftware.morf.metadata.View; import org.alfasoftware.morf.xml.XmlStreamProvider.XmlInputStreamProvider; import org.apache.commons.lang3.StringUtils; @@ -318,6 +318,16 @@ public Collection tableNames() { return xmlStreamProvider.availableStreamNames(); } + @Override + public Collection partitionedTableNames() { + return List.of(); + } + + @Override + public Collection partitionTableNames() { + return List.of(); + } + /** * @see org.alfasoftware.morf.metadata.Schema#tables() diff --git a/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java b/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java index 244f29854..389e20cf7 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java @@ -23,9 +23,16 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; -import org.alfasoftware.morf.metadata.*; +import org.alfasoftware.morf.metadata.Column; +import org.alfasoftware.morf.metadata.DataSetUtils; +import org.alfasoftware.morf.metadata.Index; +import org.alfasoftware.morf.metadata.Schema; +import org.alfasoftware.morf.metadata.Sequence; +import org.alfasoftware.morf.metadata.Table; +import org.alfasoftware.morf.metadata.View; import org.junit.Test; /** @@ -206,6 +213,16 @@ public Collection tableNames() { return Arrays.asList(MockProducer.this.getClass().getSimpleName()); } + @Override + public Collection partitionedTableNames() { + return List.of(); + } + + @Override + public Collection partitionTableNames() { + return List.of(); + } + @Override public boolean viewExists(String name) { return false; diff --git a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java index d111b2b0c..91fd7951b 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java @@ -28,10 +28,10 @@ import java.util.Collection; import java.util.List; -import org.junit.Test; - import org.alfasoftware.morf.sql.SelectStatement; import org.alfasoftware.morf.sql.element.TableReference; +import org.junit.Test; + import com.google.common.collect.ImmutableList; /** @@ -91,6 +91,8 @@ private class MockSchema implements Schema { private boolean tableNamesCalled; private boolean viewNamesCalled; private boolean sequenceNamesCalled; + private boolean partitionedTableNamesCalled; + private boolean partitionTableNamesCalled; /** * Table for our mock schema. @@ -246,6 +248,18 @@ public Collection tableNames() { return Arrays.asList(table.getName()); } + @Override + public Collection partitionedTableNames() { + this.partitionedTableNamesCalled = true; + return List.of("PartitionedTable1"); + } + + @Override + public Collection partitionTableNames() { + partitionTableNamesCalled = true; + return List.of("Partition_p0"); + } + /** * {@inheritDoc} diff --git a/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java b/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java index 6e8cff643..a394a956b 100755 --- a/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java +++ b/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java @@ -31,10 +31,10 @@ import org.alfasoftware.morf.dataset.DataSetProducer; import org.alfasoftware.morf.dataset.Record; import org.alfasoftware.morf.metadata.DataSetUtils; +import org.alfasoftware.morf.metadata.DataSetUtils.RecordBuilder; import org.alfasoftware.morf.metadata.Schema; import org.alfasoftware.morf.metadata.Sequence; import org.alfasoftware.morf.metadata.Table; -import org.alfasoftware.morf.metadata.DataSetUtils.RecordBuilder; import org.alfasoftware.morf.metadata.View; import org.apache.commons.lang3.StringUtils; @@ -418,6 +418,16 @@ public Collection tableNames() { return tables.keySet(); } + @Override + public Collection partitionedTableNames() { + return List.of(); + } + + @Override + public Collection partitionTableNames() { + return List.of(); + } + @Override public Collection
tables() { throw new UnsupportedOperationException("Cannot get the metadata of a table for a spreadsheet"); diff --git a/morf-h2/src/main/java/org/alfasoftware/morf/jdbc/h2/H2MetaDataProvider.java b/morf-h2/src/main/java/org/alfasoftware/morf/jdbc/h2/H2MetaDataProvider.java index 6dc699a4b..4f9d16153 100755 --- a/morf-h2/src/main/java/org/alfasoftware/morf/jdbc/h2/H2MetaDataProvider.java +++ b/morf-h2/src/main/java/org/alfasoftware/morf/jdbc/h2/H2MetaDataProvider.java @@ -20,6 +20,8 @@ import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Collection; +import java.util.List; import org.alfasoftware.morf.jdbc.DatabaseMetaDataProvider; import org.alfasoftware.morf.metadata.SchemaUtils.ColumnBuilder; @@ -101,4 +103,9 @@ protected String buildSequenceSql(String schemaName) { return sequenceSqlBuilder.toString(); } + + @Override + public Collection partitionTableNames() { + return List.of(); + } } diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/dataset/MockDataSetProducer.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/dataset/MockDataSetProducer.java index 63bdce046..39d4b3f9b 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/dataset/MockDataSetProducer.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/dataset/MockDataSetProducer.java @@ -25,6 +25,7 @@ import org.alfasoftware.morf.metadata.Sequence; import org.alfasoftware.morf.metadata.Table; import org.alfasoftware.morf.metadata.View; + import com.google.common.collect.Maps; /** @@ -155,6 +156,16 @@ public Collection tableNames() { return tables.keySet(); } + @Override + public Collection partitionedTableNames() { + return List.of(); + } + + @Override + public Collection partitionTableNames() { + return List.of(); + } + /** * @see org.alfasoftware.morf.metadata.Schema#tables() */ diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java index 99ea51f03..cb7248783 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java @@ -214,6 +214,7 @@ public void testViewsAndTables() throws SQLException { tableNameEqualTo("WithTypes"), tableNameEqualTo("WithDefaults"), tableNameEqualTo("WithLobs"), + tableNameEqualTo("WithPartition"), equalToIgnoringCase("WithTimestamp") // can read table names even if they contain unsupported columns ))); @@ -222,6 +223,7 @@ public void testViewsAndTables() throws SQLException { tableNameMatcher("WithTypes"), tableNameMatcher("WithDefaults"), tableNameMatcher("WithLobs"), + tableNameMatcher("WithPartition"), propertyMatcher(Table::getName, "name", equalToIgnoringCase("WithTimestamp")) // can read table names even if they contain unsupported columns ))); } diff --git a/morf-mysql/src/main/java/org/alfasoftware/morf/jdbc/mysql/MySqlMetaDataProvider.java b/morf-mysql/src/main/java/org/alfasoftware/morf/jdbc/mysql/MySqlMetaDataProvider.java index cb471aeb0..cbbc30bc9 100755 --- a/morf-mysql/src/main/java/org/alfasoftware/morf/jdbc/mysql/MySqlMetaDataProvider.java +++ b/morf-mysql/src/main/java/org/alfasoftware/morf/jdbc/mysql/MySqlMetaDataProvider.java @@ -21,6 +21,8 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; +import java.util.Collection; +import java.util.List; import org.alfasoftware.morf.jdbc.DatabaseMetaDataProvider; import org.alfasoftware.morf.metadata.DataType; @@ -84,4 +86,9 @@ protected ColumnBuilder setAdditionalColumnMetadata(RealName tableName, ColumnBu protected String buildSequenceSql(String schemaName) { return null; } + + @Override + public Collection partitionTableNames() { + return List.of(); + } } diff --git a/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleMetaDataProvider.java b/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleMetaDataProvider.java index 6a437f116..0ec9c24e6 100755 --- a/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleMetaDataProvider.java +++ b/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleMetaDataProvider.java @@ -828,6 +828,16 @@ public Collection tableNames() { return tableMap().keySet(); } + @Override + public Collection partitionedTableNames() { + return List.of(); + } + + @Override + public Collection partitionTableNames() { + return List.of(); + } + /** * {@inheritDoc} diff --git a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java index c4b290154..e0e5f2447 100644 --- a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java +++ b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java @@ -8,6 +8,7 @@ import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; +import java.util.Collection; import java.util.HashSet; import java.util.Locale; import java.util.Map; @@ -233,4 +234,9 @@ protected String buildSequenceSql(String schemaName) { return sequenceSqlBuilder.toString(); } + + @Override + public Collection partitionTableNames() { + return ignoredTables.get(); + } } diff --git a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java index 83168d8d4..25873873e 100644 --- a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java +++ b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java @@ -15,6 +15,24 @@ package org.alfasoftware.morf.jdbc.postgresql; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.RETURNS_SMART_NULLS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import javax.sql.DataSource; + import org.alfasoftware.morf.jdbc.DatabaseType; import org.alfasoftware.morf.metadata.Schema; import org.alfasoftware.morf.metadata.Sequence; @@ -23,15 +41,6 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.*; - /** * Test class for {@link PostgreSQLMetaDataProvider} @@ -80,6 +89,83 @@ public void testLoadSequences() throws SQLException { } + /** + * Checks the SQL run for retrieving partitioned tables information + * + * @throws SQLException exception + */ + @Test + public void testLoadPartitionedTables() throws SQLException { + // Given + final Statement statement = mock(PreparedStatement.class, RETURNS_SMART_NULLS); + when(connection.createStatement()).thenReturn(statement); + when(statement.executeQuery("select relname from pg_class where not relispartition and relkind = 'p'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition")); + when(statement.executeQuery("select relname from pg_class where relispartition and relkind = 'r'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0")); + + // When + final Schema postgresMetaDataProvider = postgres.openSchema(connection, "TestDatabase", "TestSchema"); + assertEquals("Partition Table name", "[partition]", postgresMetaDataProvider.partitionedTableNames().toString()); + String partitionTable = postgresMetaDataProvider.partitionedTableNames().iterator().next(); + assertEquals("Partition Table name", "partition", partitionTable); + } + + + /** + * Checks the SQL run for retrieving partition table information + * + * @throws SQLException exception + */ + @Test + public void testLoadPartitionTables() throws SQLException { + // Given + final Statement statement = mock(PreparedStatement.class, RETURNS_SMART_NULLS); + when(connection.createStatement()).thenReturn(statement); + when(statement.executeQuery("select relname from pg_class where not relispartition and relkind = 'p'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition")); + when(statement.executeQuery("select relname from pg_class where relispartition and relkind = 'r'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0")); + + // When + final Schema postgresMetaDataProvider = postgres.openSchema(connection, "TestDatabase", "TestSchema"); + assertEquals("Partition Table name", "[partition_p0]", postgresMetaDataProvider.partitionTableNames().toString()); + String partitionTable = postgresMetaDataProvider.partitionTableNames().iterator().next(); + assertEquals("Partition Table name", "partition_p0", partitionTable); + } + + + /** + * Checks the SQL run for retrieving partition table information + * + * @throws SQLException exception + */ + @Test + public void testIgnoredTables() throws SQLException { + // Given + final Statement statement = mock(PreparedStatement.class, RETURNS_SMART_NULLS); + + final PreparedStatement statement1 = mock(PreparedStatement.class, RETURNS_SMART_NULLS); + when(connection.prepareStatement(anyString())).thenReturn(statement1); + + when(connection.createStatement()).thenReturn(statement); + when(statement.executeQuery("select relname from pg_class where not relispartition and relkind = 'p'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition")); + when(statement.executeQuery("select relname from pg_class where relispartition and relkind = 'r'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0")); + DatabaseMetaData postgreSQLMetaDataMock = mock(DatabaseMetaData.class); + when(connection.getMetaData()).thenReturn(postgreSQLMetaDataMock); + when(postgreSQLMetaDataMock.getTables(any(), any(), any(), any())) + .thenAnswer(new ReturnMockResultSetWithSequence(0)); + + // When + final Schema postgresMetaDataProvider = postgres.openSchema(connection, "TestDatabase", "TestSchema"); + // Then + assertEquals("Partition Table name", "[partition]", postgresMetaDataProvider.tableNames().toString()); + assertFalse("Table names", postgresMetaDataProvider.tableNames().toString().contains("partition_p0")); + } + + /** * Mockito {@link Answer} that returns a mock result set with a given number of resultRows. */ @@ -114,4 +200,40 @@ public Boolean answer(InvocationOnMock invocation) throws Throwable { } } + /** + * Mockito {@link Answer} that returns a mock result set with a given number of resultRows for partition tables. + */ + private static final class ReturnMockResultSetWithPartitionTables implements Answer { + + private final int numberOfResultRows; + private final String partitionResult; + + + /** + * @param numberOfResultRows + */ + private ReturnMockResultSetWithPartitionTables(int numberOfResultRows, String partitionResult) { + super(); + this.numberOfResultRows = numberOfResultRows; + // class is rigged for just one value + this.partitionResult = partitionResult; + } + + @Override + public ResultSet answer(final InvocationOnMock invocation) throws Throwable { + final ResultSet resultSet = mock(ResultSet.class, RETURNS_SMART_NULLS); + when(resultSet.next()).thenAnswer(new Answer() { + private int counter; + + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + return counter++ < numberOfResultRows; + } + }); + + when(resultSet.getString(1)).thenReturn(partitionResult); + + return resultSet; + } + } } diff --git a/morf-sqlserver/src/main/java/org/alfasoftware/morf/jdbc/sqlserver/SqlServerMetaDataProvider.java b/morf-sqlserver/src/main/java/org/alfasoftware/morf/jdbc/sqlserver/SqlServerMetaDataProvider.java index c486fba87..c918c8aee 100755 --- a/morf-sqlserver/src/main/java/org/alfasoftware/morf/jdbc/sqlserver/SqlServerMetaDataProvider.java +++ b/morf-sqlserver/src/main/java/org/alfasoftware/morf/jdbc/sqlserver/SqlServerMetaDataProvider.java @@ -20,7 +20,9 @@ import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; +import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.alfasoftware.morf.jdbc.DatabaseMetaDataProvider; @@ -152,4 +154,9 @@ protected String buildSequenceSql(String schemaName) { return sequenceSqlBuilder.toString(); } + + @Override + public Collection partitionTableNames() { + return List.of(); + } } From 4c4ca2f52126891804b869d14ffc5e5e1b463ee0 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Sun, 8 Dec 2024 14:08:06 +0000 Subject: [PATCH 07/18] Add extra coverage to changed code. --- .../morf/dataset/TestWithMetaDataAdapter.java | 5 + .../morf/metadata/TestCompositeSchema.java | 8 +- .../morf/metadata/TestSchemaBean.java | 5 + .../morf/upgrade/TestUpgrade.java | 2 + .../upgrade/adapt/TestTableSetSchema.java | 11 +- .../morf/xml/TestXmlDataSetProducer.java | 5 + .../excel/TestSpreadsheetDataSetProducer.java | 2 + .../morf/jdbc/h2/TestH2MetaDataProvider.java | 39 +++- .../morf/integration/TestSqlStatements.java | 201 ++++++++++++++++-- .../oracle/TestOracleMetaDataProvider.java | 3 + .../TestSqlServerMetaDataProvider.java | 26 ++- 11 files changed, 270 insertions(+), 37 deletions(-) diff --git a/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java b/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java index 389e20cf7..e8f903986 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java @@ -35,6 +35,8 @@ import org.alfasoftware.morf.metadata.View; import org.junit.Test; +import com.google.common.collect.Lists; + /** * Ensure that {@link DataSetProducer}s can be augmented with meta data from * an alternate source. @@ -77,6 +79,9 @@ public void testAddMetadata() { assertEquals("Version of record", 10L, record.getLong("version").longValue()); assertEquals("ID of record", 1L, record.getLong("id").longValue()); assertEquals("Random value from record", "Bob", record.getString("Alan")); + + assertEquals("Partitioned table names", Lists.newArrayList(), schema.partitionedTableNames()); + assertEquals("Partition table names", Lists.newArrayList(), schema.partitionTableNames()); } diff --git a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestCompositeSchema.java b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestCompositeSchema.java index d6a5fb727..2da53b202 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestCompositeSchema.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestCompositeSchema.java @@ -15,7 +15,10 @@ package org.alfasoftware.morf.metadata; -import static org.alfasoftware.morf.metadata.SchemaUtils.*; +import static org.alfasoftware.morf.metadata.SchemaUtils.schema; +import static org.alfasoftware.morf.metadata.SchemaUtils.sequence; +import static org.alfasoftware.morf.metadata.SchemaUtils.table; +import static org.alfasoftware.morf.metadata.SchemaUtils.view; import static org.alfasoftware.morf.sql.SqlUtils.select; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -29,6 +32,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; /** * Test {@link CompositeSchema} works correctly. @@ -70,6 +74,8 @@ public void testNoSchema() { Schema schema = new CompositeSchema(); assertTrue("Empty database", schema.isEmptyDatabase()); assertFalse("Table exists", schema.tableExists("Foo")); + assertEquals("partitionedTableNames not empty", Lists.newArrayList(), schema.partitionedTableNames()); + assertEquals("partitionTableNames not empty", Lists.newArrayList(), schema.partitionTableNames()); } diff --git a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java index 91fd7951b..b4cfe39f8 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java @@ -33,6 +33,7 @@ import org.junit.Test; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; /** * Tests for {@link SchemaBean}. @@ -70,6 +71,10 @@ public void testCaseSensitivity() { // Check this twice to ensure we are not reading the source schema again. assertNotNull("Columns first call", table.columns()); assertNotNull("Columns second call", table.columns()); + + // check that partitioned tables and partition tables are empty + assertEquals("Partitioned table names", Lists.newArrayList(), schema.partitionedTableNames()); + assertEquals("Partition table names", Lists.newArrayList(), schema.partitionTableNames()); } diff --git a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestUpgrade.java b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestUpgrade.java index c62199857..b55f0cc17 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestUpgrade.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestUpgrade.java @@ -239,6 +239,8 @@ public void testUpgradeWithSchemaConsistencyHealing() throws SQLException { assertEquals("Path validation SQL present.", "INIT", sql.get(0)); assertEquals("Healing SQL 1.", "HEALING1", sql.get(1)); assertEquals("Healing SQL 2.", "HEALING2", sql.get(2)); + assertEquals("Partitioned table names", Lists.newArrayList(), schemaResource.partitionedTableNames()); + assertEquals("Partition table names", Lists.newArrayList(), schemaResource.partitionTableNames()); } diff --git a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java index 04c1994cc..8cdf0d109 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java @@ -15,7 +15,9 @@ package org.alfasoftware.morf.upgrade.adapt; -import static org.alfasoftware.morf.metadata.SchemaUtils.*; +import static org.alfasoftware.morf.metadata.SchemaUtils.column; +import static org.alfasoftware.morf.metadata.SchemaUtils.sequence; +import static org.alfasoftware.morf.metadata.SchemaUtils.table; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -24,12 +26,13 @@ import java.util.HashSet; import java.util.Set; +import org.alfasoftware.morf.metadata.DataType; import org.alfasoftware.morf.metadata.Sequence; +import org.alfasoftware.morf.metadata.Table; import org.junit.Before; import org.junit.Test; -import org.alfasoftware.morf.metadata.DataType; -import org.alfasoftware.morf.metadata.Table; +import com.google.common.collect.Lists; /** * Test the functionality provided by {@link TableSetSchema} @@ -95,6 +98,8 @@ public void testGetTable() { // Then... assertNotNull(appleTable); assertEquals(tableName, appleTable.getName()); + assertEquals("Partitioned table names", Lists.newArrayList(), schema.partitionedTableNames()); + assertEquals("Partition table names", Lists.newArrayList(), schema.partitionTableNames()); } diff --git a/morf-core/src/test/java/org/alfasoftware/morf/xml/TestXmlDataSetProducer.java b/morf-core/src/test/java/org/alfasoftware/morf/xml/TestXmlDataSetProducer.java index b3e9308ef..038cbef3c 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/xml/TestXmlDataSetProducer.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/xml/TestXmlDataSetProducer.java @@ -53,6 +53,7 @@ import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; /** * Test cases to check XML can be parsed to a data set consumer. @@ -213,6 +214,10 @@ private void testTableNamesAgainstProducer(XmlDataSetProducer producer) { use(producer.records("eNTITYoNE")); assertFalse("Non existant table", producer.getSchema().tableNames().contains("NotExist")); + + assertEquals("Partitioned table names", Lists.newArrayList(), producer.getSchema().partitionedTableNames()); + assertEquals("Partition table names", Lists.newArrayList(), producer.getSchema().partitionTableNames()); + producer.close(); } diff --git a/morf-excel/src/test/java/org/alfasoftware/morf/excel/TestSpreadsheetDataSetProducer.java b/morf-excel/src/test/java/org/alfasoftware/morf/excel/TestSpreadsheetDataSetProducer.java index fe2d6888e..4726db8fa 100755 --- a/morf-excel/src/test/java/org/alfasoftware/morf/excel/TestSpreadsheetDataSetProducer.java +++ b/morf-excel/src/test/java/org/alfasoftware/morf/excel/TestSpreadsheetDataSetProducer.java @@ -51,6 +51,8 @@ public void testGetSchema() throws URISyntaxException { assertEquals("Number of tables found [" + tableNames + "]", 12, tableNames.size()); assertTrue("Tables correctly populated [" + tableNames + "]", tableNames.contains("AssetType")); assertTrue("Tables correctly populated [" + tableNames + "]", tableNames.contains("Allowance")); + assertEquals("Partitioned table names", Lists.newArrayList(), producer.getSchema().partitionedTableNames()); + assertEquals("Partition table names", Lists.newArrayList(), producer.getSchema().partitionTableNames()); } diff --git a/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2MetaDataProvider.java b/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2MetaDataProvider.java index ea8890ce8..3062c4984 100644 --- a/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2MetaDataProvider.java +++ b/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2MetaDataProvider.java @@ -15,6 +15,20 @@ package org.alfasoftware.morf.jdbc.h2; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.RETURNS_SMART_NULLS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import javax.sql.DataSource; + import org.alfasoftware.morf.jdbc.DatabaseType; import org.alfasoftware.morf.metadata.Schema; import org.alfasoftware.morf.metadata.Sequence; @@ -23,15 +37,7 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.when; +import com.google.common.collect.Lists; /** @@ -57,6 +63,21 @@ public void before() throws SQLException { } + /** + * Checks the SQL run for retrieving sequences information + * + * @throws SQLException exception + */ + @Test + public void testPartitionedTables() throws SQLException { + // Given + + // When + final Schema h2MetaDataProvider = h2.openSchema(connection, "TestDatabase", "TestSchema"); + assertEquals("Partitioned table names", Lists.newArrayList(), h2MetaDataProvider.partitionedTableNames()); + assertEquals("Partition table names", Lists.newArrayList(), h2MetaDataProvider.partitionTableNames()); + } + /** * Checks the SQL run for retrieving sequences information * diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java index 5c7f2b441..7b485111c 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java @@ -208,6 +208,26 @@ public class TestSqlStatements { //CHECKSTYLE:OFF private static final String BLOB1_VALUE = "A Blob named One"; private static final String BLOB2_VALUE = "A Blob named Two"; + private static final byte[] BLOB3_VALUE = new byte[] { + (byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08, (byte)0x09, (byte)0x0A, (byte)0x0B, (byte)0x0C, (byte)0x0D, (byte)0x0E, (byte)0x0F, (byte)0x10, + (byte)0x11, (byte)0x12, (byte)0x13, (byte)0x14, (byte)0x15, (byte)0x16, (byte)0x17, (byte)0x18, (byte)0x19, (byte)0x1A, (byte)0x1B, (byte)0x1C, (byte)0x1D, (byte)0x1E, (byte)0x1F, (byte)0x20, (byte)0x21, + (byte)0x22, (byte)0x23, (byte)0x24, (byte)0x25, (byte)0x26, (byte)0x27, (byte)0x28, (byte)0x29, (byte)0x2A, (byte)0x2B, (byte)0x2C, (byte)0x2D, (byte)0x2E, (byte)0x2F, (byte)0x30, (byte)0x31, (byte)0x32, + (byte)0x33, (byte)0x34, (byte)0x35, (byte)0x36, (byte)0x37, (byte)0x38, (byte)0x39, (byte)0x3A, (byte)0x3B, (byte)0x3C, (byte)0x3D, (byte)0x3E, (byte)0x3F, (byte)0x40, (byte)0x41, (byte)0x42, (byte)0x43, + (byte)0x44, (byte)0x45, (byte)0x46, (byte)0x47, (byte)0x48, (byte)0x49, (byte)0x4A, (byte)0x4B, (byte)0x4C, (byte)0x4D, (byte)0x4E, (byte)0x4F, (byte)0x50, (byte)0x51, (byte)0x52, (byte)0x53, (byte)0x54, + (byte)0x55, (byte)0x56, (byte)0x57, (byte)0x58, (byte)0x59, (byte)0x5A, (byte)0x5B, (byte)0x5C, (byte)0x5D, (byte)0x5E, (byte)0x5F, (byte)0x60, (byte)0x61, (byte)0x62, (byte)0x63, (byte)0x64, (byte)0x65, + (byte)0x66, (byte)0x67, (byte)0x68, (byte)0x69, (byte)0x6A, (byte)0x6B, (byte)0x6C, (byte)0x6D, (byte)0x6E, (byte)0x6F, (byte)0x70, (byte)0x71, (byte)0x72, (byte)0x73, (byte)0x74, (byte)0x75, (byte)0x76, + (byte)0x77, (byte)0x78, (byte)0x79, (byte)0x7A, (byte)0x7B, (byte)0x7C, (byte)0x7D, (byte)0x7E, (byte)0x7F, (byte)0x80, (byte)0x81, (byte)0x82, (byte)0x83, (byte)0x84, (byte)0x85, (byte)0x86, (byte)0x87, + (byte)0x88, (byte)0x89, (byte)0x8A, (byte)0x8B, (byte)0x8C, (byte)0x8D, (byte)0x8E, (byte)0x8F, (byte)0x90, (byte)0x91, (byte)0x92, (byte)0x93, (byte)0x94, (byte)0x95, (byte)0x96, (byte)0x97, (byte)0x98, + (byte)0x99, (byte)0x9A, (byte)0x9B, (byte)0x9C, (byte)0x9D, (byte)0x9E, (byte)0x9F, (byte)0xA0, (byte)0xA1, (byte)0xA2, (byte)0xA3, (byte)0xA4, (byte)0xA5, (byte)0xA6, (byte)0xA7, (byte)0xA8, (byte)0xA9, + (byte)0xAA, (byte)0xAB, (byte)0xAC, (byte)0xAD, (byte)0xAE, (byte)0xAF, (byte)0xB0, (byte)0xB1, (byte)0xB2, (byte)0xB3, (byte)0xB4, (byte)0xB5, (byte)0xB6, (byte)0xB7, (byte)0xB8, (byte)0xB9, (byte)0xBA, + (byte)0xBB, (byte)0xBC, (byte)0xBD, (byte)0xBE, (byte)0xBF, (byte)0xC0, (byte)0xC1, (byte)0xC2, (byte)0xC3, (byte)0xC4, (byte)0xC5, (byte)0xC6, (byte)0xC7, (byte)0xC8, (byte)0xC9, (byte)0xCA, (byte)0xCB, + (byte)0xCC, (byte)0xCD, (byte)0xCE, (byte)0xCF, (byte)0xD0, (byte)0xD1, (byte)0xD2, (byte)0xD3, (byte)0xD4, (byte)0xD5, (byte)0xD6, (byte)0xD7, (byte)0xD8, (byte)0xD9, (byte)0xDA, (byte)0xDB, (byte)0xDC, + (byte)0xDD, (byte)0xDE, (byte)0xDF, (byte)0xE0, (byte)0xE1, (byte)0xE2, (byte)0xE3, (byte)0xE4, (byte)0xE5, (byte)0xE6, (byte)0xE7, (byte)0xE8, (byte)0xE9, (byte)0xEA, (byte)0xEB, (byte)0xEC, (byte)0xED, + (byte)0xEE, (byte)0xEF, (byte)0xF0, (byte)0xF1, (byte)0xF2, (byte)0xF3, (byte)0xF4, (byte)0xF5, (byte)0xF6, (byte)0xF7, (byte)0xF8, (byte)0xF9, (byte)0xFA, (byte)0xFB, (byte)0xFC, (byte)0xFD, (byte)0xFE, + (byte)0xFF + }; + + //private static final byte[] @Rule public InjectMembersRule injectMembersRule = new InjectMembersRule(new TestingDataSourceModule()); @@ -1737,24 +1757,175 @@ public Integer process(ResultSet resultSet) throws SQLException { } } - private static String decodeBlobHexFromBytesToText(byte[] bytSrc) throws SQLException { - String blobStringResult; - Hex hexUtil = new Hex(); - try { - int lenSrc = bytSrc.length; - char[] charBlob = new char[lenSrc]; - byte[] bytBlob = new byte[charBlob.length >> 1]; - for (int i = 0; i < bytSrc.length; i++) { - charBlob[i] = (char) bytSrc[i]; - } - hexUtil.decodeHex(charBlob, bytBlob, 0); - blobStringResult = new String(bytBlob); - } catch (DecoderException e) { - throw new RuntimeException(e); + @Test + public void testGenBlob3() { // throws SQLException + byte[] byteArray = new byte[256]; + boolean[] boolArray = new boolean[256]; + int distinctToGenerate = 256; + int trials = 1000; + int p = 0; + + + int l = 16; + for (int j = 0; j < 256; ++j) { + + //byteArray[p++] =; + byte byt = (byte) j; + /*int iValue = byt < 0 ? 0x100 + byt : byt; + if (!boolArray[iValue]) { + boolArray[iValue] = true; + } else { + // dup value + System.out.println(String.format("DUPLICATE 0x%02X, ", byt)); + break; + } */ + byteArray[p++] = byt; + + if (l == 0) { + System.out.println(String.format("(byte)0x%02X, ", byteArray[j])); + l = 16; + } else { + System.out.print(String.format("(byte)0x%02X, ", byteArray[j])); + l--; + } + } + } + + /** + * Test the behaviour of SELECTs, INSERTs and UPDATEs of blob fields. In the process + * we test a lot of {@link SqlScriptExecutor}'s statement handling capabilities + * + * @throws SQLException if something goes wrong. + */ + @Test + public void testBlobFieldsRealBinary() { // throws SQLException + SqlScriptExecutor executor = sqlScriptExecutorProvider.get(new LoggingSqlScriptVisitor()); + + // Set up queries + InsertStatement insertStatement = insert() + .into(tableRef("BlobTable")) + .fields(field("column1"), field("column2")) + .values(blobLiteral(BLOB3_VALUE).as("column1"), blobLiteral(BLOB3_VALUE).as("column2")); + SelectStatement selectStatementAfterInsert = select(field("column1"), field("column2")) + .from(tableRef("BlobTable")) + .where(or( + field("column1").eq(blobLiteral(BLOB3_VALUE)), + field("column1").eq(blobLiteral(BLOB3_VALUE)) + )); + + byte[] bytUpdated = Arrays.copyOf(BLOB3_VALUE, 256+3); + bytUpdated[256] = 1; + bytUpdated[257] = 2; + bytUpdated[258] = 3; + // this update fails to work as an update without a WHERE clause - it strangely inserts a duplicate row on Postgres without a where clause + UpdateStatement updateStatement = update(tableRef("BlobTable")) + .set(blobLiteral(bytUpdated).as("column1"), blobLiteral(bytUpdated).as("column2")) + .where( + field("column1").eq(blobLiteral(BLOB3_VALUE)) + ); + SelectStatement selectStatementAfterUpdate = select(field("column1"), field("column2")) + .from(tableRef("BlobTable")) + .where(or( + field("column1").eq(blobLiteral(bytUpdated)), + field("column1").eq(blobLiteral(bytUpdated)) + )); + + // Insert + executor.execute(convertStatementToSQL(insertStatement, schema, null), connection); + + // Check result - note that this is deliberately not tidy - we are making sure that results get + // passed back up to this scope correctly. + String sql = convertStatementToSQL(selectStatementAfterInsert); + AtomicBoolean isFirstValueHex = new AtomicBoolean(false); + Integer numberOfRecords = executor.executeQuery(sql, connection, new ResultSetProcessor() { + @Override + public Integer process(ResultSet resultSet) throws SQLException { + int result = 0; + while (resultSet.next()) { + result++; + byte[] bytesFromFirst = resultSet.getBytes("column1"); + + if (bytesFromFirst[3] == 0x03) { // if 4th char is 0x03 then it isn't hex encoded like in Postgres + assertTrue("column1 blob value not correctly set/returned after insert", Arrays.compare(BLOB3_VALUE, resultSet.getBytes(1)) == 0); + assertTrue("column2 blob value not correctly set/returned after insert", Arrays.compare(BLOB3_VALUE, resultSet.getBytes(2)) == 0); + } else { + isFirstValueHex.set(true); + assertTrue("column1 blob value not correctly set/returned after insert", Arrays.compare(BLOB3_VALUE, decodeBlobHexFromBytesToByteArray(resultSet.getBytes(1))) == 0); + assertTrue("column2 blob value not correctly set/returned after insert", Arrays.compare(BLOB3_VALUE, decodeBlobHexFromBytesToByteArray(resultSet.getBytes(2))) == 0); + } } - return blobStringResult; + return result; + } + }); + + assertEquals("Should be exactly one record", 1, numberOfRecords.intValue()); + + + // Update + executor.execute(ImmutableList.of(convertStatementToSQL(updateStatement)), connection); + + // Check result- note that this is deliberately not tidy - we are making sure that results get + // passed back up to this scope correctly. + sql = convertStatementToSQL(selectStatementAfterUpdate); + AtomicBoolean isUpdateFirstValueHex = new AtomicBoolean(false); + numberOfRecords = executor.executeQuery(sql, connection, new ResultSetProcessor() { + @Override + public Integer process(ResultSet resultSet) throws SQLException { + int result = 0; + while (resultSet.next()) { + result++; + byte[] bytesFromFirst = resultSet.getBytes("column1"); + if (bytesFromFirst[3] == 0x03) { // if second char is a space then it isn't hex encoded + assertTrue("column1 blob value not correctly set/returned after update", Arrays.compare(bytUpdated, resultSet.getBytes(1)) == 0); + assertTrue("column2 blob value not correctly set/returned after update", Arrays.compare(bytUpdated, resultSet.getBytes(2)) == 0); + } else { + isUpdateFirstValueHex.set(true); + assertTrue("column1 blob value not correctly set/returned after update", Arrays.compare(bytUpdated, decodeBlobHexFromBytesToByteArray(resultSet.getBytes(1))) == 0); + assertTrue("column2 blob value not correctly set/returned after update", Arrays.compare(bytUpdated, decodeBlobHexFromBytesToByteArray(resultSet.getBytes(2))) == 0); + } + } + return result; + } + }); + assertEquals("Should be exactly one records", 1, numberOfRecords.intValue()); + } + + private static byte[] decodeBlobHexFromBytesToByteArray(byte[] bytSrc) throws SQLException { + String blobStringResult; + Hex hexUtil = new Hex(); + int lenSrc = bytSrc.length; + char[] charBlob = new char[lenSrc]; + byte[] bytBlob = new byte[charBlob.length >> 1]; + try { + for (int i = 0; i < bytSrc.length; i++) { + charBlob[i] = (char) bytSrc[i]; + } + hexUtil.decodeHex(charBlob, bytBlob, 0); + } catch (DecoderException e) { + throw new RuntimeException(e); } + return bytBlob; + } + + private static String decodeBlobHexFromBytesToText(byte[] bytSrc) throws SQLException { + String blobStringResult; + Hex hexUtil = new Hex(); + try { + int lenSrc = bytSrc.length; + char[] charBlob = new char[lenSrc]; + byte[] bytBlob = new byte[charBlob.length >> 1]; + for (int i = 0; i < bytSrc.length; i++) { + charBlob[i] = (char) bytSrc[i]; + } + hexUtil.decodeHex(charBlob, bytBlob, 0); + + blobStringResult = new String(bytBlob); + } catch (DecoderException e) { + throw new RuntimeException(e); + } + return blobStringResult; + } /** diff --git a/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleMetaDataProvider.java b/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleMetaDataProvider.java index 44006da5f..a4ecab7a7 100755 --- a/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleMetaDataProvider.java +++ b/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleMetaDataProvider.java @@ -55,6 +55,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; /** @@ -289,6 +290,8 @@ public void testIgnoreSystemTables() throws SQLException { final Schema oracleMetaDataProvider = oracle.openSchema(connection, "TESTDATABASE", "TESTSCHEMA"); assertEquals("Table names", "[AREALTABLE]", oracleMetaDataProvider.tableNames().toString()); assertFalse("Table names", oracleMetaDataProvider.tableNames().toString().contains("DBMS")); + assertEquals("Partitioned table names", Lists.newArrayList(), oracleMetaDataProvider.partitionedTableNames()); + assertEquals("Partition table names", Lists.newArrayList(), oracleMetaDataProvider.partitionTableNames()); } diff --git a/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java b/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java index bc365c983..5758e56c1 100644 --- a/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java +++ b/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java @@ -15,6 +15,20 @@ package org.alfasoftware.morf.jdbc.sqlserver; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.RETURNS_SMART_NULLS; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import javax.sql.DataSource; + import org.alfasoftware.morf.jdbc.DatabaseType; import org.alfasoftware.morf.metadata.Schema; import org.alfasoftware.morf.metadata.Sequence; @@ -23,15 +37,7 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.when; +import com.google.common.collect.Lists; /** @@ -80,6 +86,8 @@ public void testLoadSequences() throws SQLException { assertEquals("Sequence names", "[Sequence1]", sqlServerMetaDataProvider.sequenceNames().toString()); Sequence sequence = sqlServerMetaDataProvider.sequences().iterator().next(); assertEquals("Sequence name", "Sequence1", sequence.getName()); + assertEquals("Partitioned table names", Lists.newArrayList(), sqlServerMetaDataProvider.partitionedTableNames()); + assertEquals("Partition table names", Lists.newArrayList(), sqlServerMetaDataProvider.partitionTableNames()); verify(statement).setString(1, "TestSchema"); } From 35ab449752ffeecfd6c3beba9f14c28d327b0dd4 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Sun, 8 Dec 2024 15:24:11 +0000 Subject: [PATCH 08/18] Add TestSqlStatements.testBlobFieldsRealBinary to encode and read real binary fields with byte values ranging from 0x00 to 0xFF. --- .../morf/integration/TestSqlStatements.java | 66 ++++++++++++++++--- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java index 7b485111c..848a3a33c 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java @@ -150,6 +150,7 @@ import org.alfasoftware.morf.sql.element.FieldLiteral; import org.alfasoftware.morf.sql.element.FieldReference; import org.alfasoftware.morf.sql.element.Function; +import org.alfasoftware.morf.sql.element.PortableSqlFunction; import org.alfasoftware.morf.sql.element.SqlParameter; import org.alfasoftware.morf.sql.element.TableReference; import org.alfasoftware.morf.testing.DatabaseSchemaManager; @@ -1834,6 +1835,54 @@ public void testBlobFieldsRealBinary() { // throws SQLException // Insert executor.execute(convertStatementToSQL(insertStatement, schema, null), connection); + boolean isOracle = false; + + try { + String databaseProductName = this.dataSource.getConnection().getMetaData().getDatabaseProductName(); + isOracle = databaseProductName.contains("Oracle"); + } catch (SQLException e) { + // ignore SQLException + } + + if (isOracle) { + // for Oracle need to compare BLOB's with DBMS_LOB.INSTR + AliasedField compareFunctionBlob = PortableSqlFunction.builder() + .withFunctionForDatabaseType("ORACLE", + "DBMS_LOB.INSTR", + new FieldReference("column1"), + blobLiteral(BLOB3_VALUE), + new FieldLiteral("1"), + new FieldLiteral("1") + ) + .build(); + + AliasedField compareFunctionUpdated = PortableSqlFunction.builder() + .withFunctionForDatabaseType("ORACLE", + "DBMS_LOB.INSTR", + new FieldReference("column1"), + blobLiteral(bytUpdated), + new FieldLiteral("1"), + new FieldLiteral("1") + ) + .build(); + + selectStatementAfterInsert = select(field("column1"), field("column2")) + .from(tableRef("BlobTable")) + .where( + compareFunctionBlob.greaterThan(0) + ); + updateStatement = update(tableRef("BlobTable")) + .set(blobLiteral(bytUpdated).as("column1"), blobLiteral(bytUpdated).as("column2")) + .where( + compareFunctionBlob.greaterThan(0) + ); + selectStatementAfterUpdate = select(field("column1"), field("column2")) + .from(tableRef("BlobTable")) + .where( + compareFunctionUpdated.greaterThan(0) + ); + } + // Check result - note that this is deliberately not tidy - we are making sure that results get // passed back up to this scope correctly. String sql = convertStatementToSQL(selectStatementAfterInsert); @@ -1847,12 +1896,12 @@ public Integer process(ResultSet resultSet) throws SQLException { byte[] bytesFromFirst = resultSet.getBytes("column1"); if (bytesFromFirst[3] == 0x03) { // if 4th char is 0x03 then it isn't hex encoded like in Postgres - assertTrue("column1 blob value not correctly set/returned after insert", Arrays.compare(BLOB3_VALUE, resultSet.getBytes(1)) == 0); - assertTrue("column2 blob value not correctly set/returned after insert", Arrays.compare(BLOB3_VALUE, resultSet.getBytes(2)) == 0); + assertEquals("column1 blob value not correctly set/returned after insert", 0, Arrays.compare(BLOB3_VALUE, resultSet.getBytes(1))); + assertEquals("column2 blob value not correctly set/returned after insert", 0, Arrays.compare(BLOB3_VALUE, resultSet.getBytes(2))); } else { isFirstValueHex.set(true); - assertTrue("column1 blob value not correctly set/returned after insert", Arrays.compare(BLOB3_VALUE, decodeBlobHexFromBytesToByteArray(resultSet.getBytes(1))) == 0); - assertTrue("column2 blob value not correctly set/returned after insert", Arrays.compare(BLOB3_VALUE, decodeBlobHexFromBytesToByteArray(resultSet.getBytes(2))) == 0); + assertEquals("column1 blob value not correctly set/returned after insert", 0, Arrays.compare(BLOB3_VALUE, decodeBlobHexFromBytesToByteArray(resultSet.getBytes(1)))); + assertEquals("column2 blob value not correctly set/returned after insert", 0, Arrays.compare(BLOB3_VALUE, decodeBlobHexFromBytesToByteArray(resultSet.getBytes(2)))); } } return result; @@ -1861,7 +1910,6 @@ public Integer process(ResultSet resultSet) throws SQLException { assertEquals("Should be exactly one record", 1, numberOfRecords.intValue()); - // Update executor.execute(ImmutableList.of(convertStatementToSQL(updateStatement)), connection); @@ -1877,12 +1925,12 @@ public Integer process(ResultSet resultSet) throws SQLException { result++; byte[] bytesFromFirst = resultSet.getBytes("column1"); if (bytesFromFirst[3] == 0x03) { // if second char is a space then it isn't hex encoded - assertTrue("column1 blob value not correctly set/returned after update", Arrays.compare(bytUpdated, resultSet.getBytes(1)) == 0); - assertTrue("column2 blob value not correctly set/returned after update", Arrays.compare(bytUpdated, resultSet.getBytes(2)) == 0); + assertEquals("column1 blob value not correctly set/returned after update", 0, Arrays.compare(bytUpdated, resultSet.getBytes(1))); + assertEquals("column2 blob value not correctly set/returned after update", 0, Arrays.compare(bytUpdated, resultSet.getBytes(2))); } else { isUpdateFirstValueHex.set(true); - assertTrue("column1 blob value not correctly set/returned after update", Arrays.compare(bytUpdated, decodeBlobHexFromBytesToByteArray(resultSet.getBytes(1))) == 0); - assertTrue("column2 blob value not correctly set/returned after update", Arrays.compare(bytUpdated, decodeBlobHexFromBytesToByteArray(resultSet.getBytes(2))) == 0); + assertEquals("column1 blob value not correctly set/returned after update", 0, Arrays.compare(bytUpdated, decodeBlobHexFromBytesToByteArray(resultSet.getBytes(1)))); + assertEquals("column2 blob value not correctly set/returned after update", 0, Arrays.compare(bytUpdated, decodeBlobHexFromBytesToByteArray(resultSet.getBytes(2)))); } } return result; From bf047dd50f72f214b8cf406259e7e3b0908faa42 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Sun, 8 Dec 2024 15:28:54 +0000 Subject: [PATCH 09/18] Remove extraneous comment. --- .../org/alfasoftware/morf/integration/TestSqlStatements.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java index 848a3a33c..66d4c37e7 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java @@ -228,8 +228,6 @@ public class TestSqlStatements { //CHECKSTYLE:OFF (byte)0xFF }; - //private static final byte[] - @Rule public InjectMembersRule injectMembersRule = new InjectMembersRule(new TestingDataSourceModule()); @Inject From c51e18cf5464e9c9824f32b18906c0164d28625c Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Sun, 8 Dec 2024 20:22:10 +0000 Subject: [PATCH 10/18] Remove unnecessary test method. --- .../morf/integration/TestSqlStatements.java | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java index 66d4c37e7..277dc782e 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java @@ -1757,40 +1757,6 @@ public Integer process(ResultSet resultSet) throws SQLException { } - @Test - public void testGenBlob3() { // throws SQLException - byte[] byteArray = new byte[256]; - boolean[] boolArray = new boolean[256]; - int distinctToGenerate = 256; - int trials = 1000; - int p = 0; - - - int l = 16; - for (int j = 0; j < 256; ++j) { - - //byteArray[p++] =; - byte byt = (byte) j; - /*int iValue = byt < 0 ? 0x100 + byt : byt; - if (!boolArray[iValue]) { - boolArray[iValue] = true; - } else { - // dup value - System.out.println(String.format("DUPLICATE 0x%02X, ", byt)); - break; - } */ - byteArray[p++] = byt; - - if (l == 0) { - System.out.println(String.format("(byte)0x%02X, ", byteArray[j])); - l = 16; - } else { - System.out.print(String.format("(byte)0x%02X, ", byteArray[j])); - l--; - } - } - } - /** * Test the behaviour of SELECTs, INSERTs and UPDATEs of blob fields. In the process * we test a lot of {@link SqlScriptExecutor}'s statement handling capabilities From dc1fa5bdf72b431ceb5f175cb1912a28e62be515 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Sun, 8 Dec 2024 20:28:11 +0000 Subject: [PATCH 11/18] Clear sonar items. --- .../org/alfasoftware/morf/metadata/TestSchemaBean.java | 4 ---- .../morf/integration/TestSqlStatements.java | 5 ++--- .../morf/jdbc/TestDatabaseMetaDataProvider.java | 10 +++++----- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java index b4cfe39f8..51c52b1b4 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java @@ -96,8 +96,6 @@ private class MockSchema implements Schema { private boolean tableNamesCalled; private boolean viewNamesCalled; private boolean sequenceNamesCalled; - private boolean partitionedTableNamesCalled; - private boolean partitionTableNamesCalled; /** * Table for our mock schema. @@ -255,13 +253,11 @@ public Collection tableNames() { @Override public Collection partitionedTableNames() { - this.partitionedTableNamesCalled = true; return List.of("PartitionedTable1"); } @Override public Collection partitionTableNames() { - partitionTableNamesCalled = true; return List.of("Partition_p0"); } diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java index 277dc782e..fc7ed4e51 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java @@ -1903,8 +1903,7 @@ public Integer process(ResultSet resultSet) throws SQLException { assertEquals("Should be exactly one records", 1, numberOfRecords.intValue()); } - private static byte[] decodeBlobHexFromBytesToByteArray(byte[] bytSrc) throws SQLException { - String blobStringResult; + private static byte[] decodeBlobHexFromBytesToByteArray(byte[] bytSrc) { Hex hexUtil = new Hex(); int lenSrc = bytSrc.length; char[] charBlob = new char[lenSrc]; @@ -1920,7 +1919,7 @@ private static byte[] decodeBlobHexFromBytesToByteArray(byte[] bytSrc) throws SQ return bytBlob; } - private static String decodeBlobHexFromBytesToText(byte[] bytSrc) throws SQLException { + private static String decodeBlobHexFromBytesToText(byte[] bytSrc) { String blobStringResult; Hex hexUtil = new Hex(); try { diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java index cb7248783..aa4973403 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java @@ -328,11 +328,11 @@ public void testTableWithPartition() throws SQLException { // RE-CREATE table with two partitions on table WithPartition try (Connection connection = database.getDataSource().getConnection()) { if (isPostgres) { - String schema = Strings.isNullOrEmpty(database.getSchemaName()) ? "" : database.getSchemaName() + "."; - connection.createStatement().executeUpdate("DROP TABLE " + schema + "WithPartition"); - connection.createStatement().executeUpdate("CREATE TABLE " + schema + "WithPartition(id numeric(19) NOT NULL, stringCol VARCHAR(20)) PARTITION BY RANGE (id)"); - connection.createStatement().executeUpdate("CREATE TABLE " + schema + "WithPartition_p0 PARTITION OF " + schema + "WithPartition FOR VALUES FROM (0) TO (10000)"); - connection.createStatement().executeUpdate("CREATE TABLE " + schema + "WithPartition_p1 PARTITION OF " + schema + "WithPartition FOR VALUES FROM (10000) TO (99999)"); + String tableSchema = Strings.isNullOrEmpty(database.getSchemaName()) ? "" : database.getSchemaName() + "."; + connection.createStatement().executeUpdate("DROP TABLE " + tableSchema + "WithPartition"); + connection.createStatement().executeUpdate("CREATE TABLE " + tableSchema + "WithPartition(id numeric(19) NOT NULL, stringCol VARCHAR(20)) PARTITION BY RANGE (id)"); + connection.createStatement().executeUpdate("CREATE TABLE " + tableSchema + "WithPartition_p0 PARTITION OF " + tableSchema + "WithPartition FOR VALUES FROM (0) TO (10000)"); + connection.createStatement().executeUpdate("CREATE TABLE " + tableSchema + "WithPartition_p1 PARTITION OF " + tableSchema + "WithPartition FOR VALUES FROM (10000) TO (99999)"); } } From b0266b96ba1a0030f2ec67126cec40141401e647 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Thu, 27 Feb 2025 15:28:09 +0000 Subject: [PATCH 12/18] WEB-161904 move properties from Schema to AdditionalMetadata. Propagate the impact of that change to other classes. TestDatabaseMetaDataProvider - testTableWithPartition(): extend test to validate that table and column metadata for partition table is still read. --- .../morf/dataset/SchemaAdapter.java | 10 --------- .../morf/dataset/WithMetaDataAdapter.java | 9 -------- .../morf/jdbc/DatabaseMetaDataProvider.java | 7 ------- .../morf/metadata/AdditionalMetadata.java | 21 +++++++++++++++++++ .../morf/metadata/CompositeSchema.java | 11 ---------- .../alfasoftware/morf/metadata/Schema.java | 20 ------------------ .../morf/metadata/SchemaBean.java | 11 ---------- .../morf/upgrade/adapt/TableSetSchema.java | 11 ---------- .../morf/xml/XmlDataSetProducer.java | 10 --------- .../morf/dataset/TestWithMetaDataAdapter.java | 16 -------------- .../morf/metadata/TestCompositeSchema.java | 3 --- .../morf/metadata/TestSchemaBean.java | 15 ------------- .../morf/upgrade/TestUpgrade.java | 2 -- .../upgrade/adapt/TestTableSetSchema.java | 4 ---- .../morf/xml/TestXmlDataSetProducer.java | 4 ---- .../excel/SpreadsheetDataSetProducer.java | 10 --------- .../excel/TestSpreadsheetDataSetProducer.java | 2 -- .../morf/jdbc/h2/H2MetaDataProvider.java | 7 ------- .../morf/jdbc/h2/TestH2MetaDataProvider.java | 17 --------------- .../morf/dataset/MockDataSetProducer.java | 9 -------- .../jdbc/TestDatabaseMetaDataProvider.java | 6 ++++++ .../jdbc/mysql/MySqlMetaDataProvider.java | 6 ------ .../jdbc/oracle/OracleMetaDataProvider.java | 10 --------- .../oracle/TestOracleMetaDataProvider.java | 3 --- .../PostgreSQLMetaDataProvider.java | 8 ++++++- .../TestPostgreSqlMetaDataProvider.java | 6 ++++-- .../sqlserver/SqlServerMetaDataProvider.java | 6 ------ .../TestSqlServerMetaDataProvider.java | 4 ---- 28 files changed, 38 insertions(+), 210 deletions(-) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/dataset/SchemaAdapter.java b/morf-core/src/main/java/org/alfasoftware/morf/dataset/SchemaAdapter.java index 86a417f86..470aedb14 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/dataset/SchemaAdapter.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/dataset/SchemaAdapter.java @@ -78,16 +78,6 @@ public Collection tableNames() { return delegate.tableNames(); } - @Override - public Collection partitionedTableNames() { - return delegate.partitionedTableNames(); - } - - @Override - public Collection partitionTableNames() { - return delegate.partitionTableNames(); - } - /** * @see org.alfasoftware.morf.metadata.Schema#tables() diff --git a/morf-core/src/main/java/org/alfasoftware/morf/dataset/WithMetaDataAdapter.java b/morf-core/src/main/java/org/alfasoftware/morf/dataset/WithMetaDataAdapter.java index 2faeb4236..6ccd67c2d 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/dataset/WithMetaDataAdapter.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/dataset/WithMetaDataAdapter.java @@ -99,15 +99,6 @@ public Collection tableNames() { return sourceSchema.tableNames(); } - @Override - public Collection partitionedTableNames() { - return sourceSchema.partitionedTableNames(); - } - - @Override - public Collection partitionTableNames() { - return sourceSchema.partitionTableNames(); - } @Override public Collection
tables() { diff --git a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java index 6c029f150..70b6e6982 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java @@ -191,13 +191,6 @@ public Collection tableNames() { return tableNames.get().values().stream().map(RealName::getRealName).collect(Collectors.toList()); } - /** - * @see org.alfasoftware.morf.metadata.Schema#tableNames() - */ - @Override - public Collection partitionedTableNames() { - return new ArrayList<>(partitionedTables.get()); - } /** * @see org.alfasoftware.morf.metadata.Schema#tables() diff --git a/morf-core/src/main/java/org/alfasoftware/morf/metadata/AdditionalMetadata.java b/morf-core/src/main/java/org/alfasoftware/morf/metadata/AdditionalMetadata.java index 081b75688..5e813da64 100644 --- a/morf-core/src/main/java/org/alfasoftware/morf/metadata/AdditionalMetadata.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/metadata/AdditionalMetadata.java @@ -1,5 +1,6 @@ package org.alfasoftware.morf.metadata; +import java.util.Collection; import java.util.Map; import org.apache.commons.lang3.NotImplementedException; @@ -16,4 +17,24 @@ public interface AdditionalMetadata extends Schema { default Map primaryKeyIndexNames() { throw new NotImplementedException("Not implemented yet."); } + + /** + * Provides the names of all partition tables in the database. This applies for now for postgres. Note that the order of + * the tables in the result is not specified. The case of the + * table names may be preserved when logging progress, but should not be relied on for schema + * processing. + * + * @return A collection of all partitioned table names available in the database. + */ + default Collection partitionedTableNames() { throw new NotImplementedException("Not implemented yet."); } + + /** + * Provides the names of all partition tables in the database. This applies for now for postgres. Note that the order of + * the tables in the result is not specified. The case of the + * table names may be preserved when logging progress, but should not be relied on for schema + * processing. + * + * @return A collection of all partition table names available in the database. + */ + default Collection partitionTableNames() { throw new NotImplementedException("Not implemented yet."); } } diff --git a/morf-core/src/main/java/org/alfasoftware/morf/metadata/CompositeSchema.java b/morf-core/src/main/java/org/alfasoftware/morf/metadata/CompositeSchema.java index f8afe5eee..f5e9ca1d9 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/metadata/CompositeSchema.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/metadata/CompositeSchema.java @@ -16,7 +16,6 @@ package org.alfasoftware.morf.metadata; import java.util.Collection; -import java.util.List; import java.util.Set; import com.google.common.collect.Sets; @@ -100,16 +99,6 @@ public Collection tableNames() { return result; } - @Override - public Collection partitionedTableNames() { - return List.of(); - } - - @Override - public Collection partitionTableNames() { - return List.of(); - } - /** * @see org.alfasoftware.morf.metadata.Schema#tables() diff --git a/morf-core/src/main/java/org/alfasoftware/morf/metadata/Schema.java b/morf-core/src/main/java/org/alfasoftware/morf/metadata/Schema.java index a58c46492..3568f69cc 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/metadata/Schema.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/metadata/Schema.java @@ -61,26 +61,6 @@ public interface Schema { */ public Collection tableNames(); - /** - * Provides the names of all partition tables in the database. This applies for now for postgres. Note that the order of - * the tables in the result is not specified. The case of the - * table names may be preserved when logging progress, but should not be relied on for schema - * processing. - * - * @return A collection of all partitioned table names available in the database. - */ - Collection partitionedTableNames(); - - /** - * Provides the names of all partition tables in the database. This applies for now for postgres. Note that the order of - * the tables in the result is not specified. The case of the - * table names may be preserved when logging progress, but should not be relied on for schema - * processing. - * - * @return A collection of all partition table names available in the database. - */ - Collection partitionTableNames(); - /** * @return the tables in in the schema represented by this metadata */ diff --git a/morf-core/src/main/java/org/alfasoftware/morf/metadata/SchemaBean.java b/morf-core/src/main/java/org/alfasoftware/morf/metadata/SchemaBean.java index 0f1b0202a..fc8de400b 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/metadata/SchemaBean.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/metadata/SchemaBean.java @@ -21,7 +21,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; @@ -195,16 +194,6 @@ public Collection tableNames() { return names; } - @Override - public Collection partitionedTableNames() { - return List.of(); - } - - @Override - public Collection partitionTableNames() { - return List.of(); - } - /** * {@inheritDoc} diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/adapt/TableSetSchema.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/adapt/TableSetSchema.java index 8fba85c51..9e141a837 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/adapt/TableSetSchema.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/adapt/TableSetSchema.java @@ -19,7 +19,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Set; import org.alfasoftware.morf.metadata.Schema; @@ -108,16 +107,6 @@ public Collection tableNames() { return names; } - @Override - public Collection partitionedTableNames() { - return List.of(); - } - - @Override - public Collection partitionTableNames() { - return List.of(); - } - /** * @see org.alfasoftware.morf.metadata.Schema#viewExists(java.lang.String) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/xml/XmlDataSetProducer.java b/morf-core/src/main/java/org/alfasoftware/morf/xml/XmlDataSetProducer.java index f4fcfb491..b94e15f93 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/xml/XmlDataSetProducer.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/xml/XmlDataSetProducer.java @@ -318,16 +318,6 @@ public Collection tableNames() { return xmlStreamProvider.availableStreamNames(); } - @Override - public Collection partitionedTableNames() { - return List.of(); - } - - @Override - public Collection partitionTableNames() { - return List.of(); - } - /** * @see org.alfasoftware.morf.metadata.Schema#tables() diff --git a/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java b/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java index e8f903986..8ca9d5450 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java @@ -23,7 +23,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Set; import org.alfasoftware.morf.metadata.Column; @@ -35,8 +34,6 @@ import org.alfasoftware.morf.metadata.View; import org.junit.Test; -import com.google.common.collect.Lists; - /** * Ensure that {@link DataSetProducer}s can be augmented with meta data from * an alternate source. @@ -79,9 +76,6 @@ public void testAddMetadata() { assertEquals("Version of record", 10L, record.getLong("version").longValue()); assertEquals("ID of record", 1L, record.getLong("id").longValue()); assertEquals("Random value from record", "Bob", record.getString("Alan")); - - assertEquals("Partitioned table names", Lists.newArrayList(), schema.partitionedTableNames()); - assertEquals("Partition table names", Lists.newArrayList(), schema.partitionTableNames()); } @@ -218,16 +212,6 @@ public Collection tableNames() { return Arrays.asList(MockProducer.this.getClass().getSimpleName()); } - @Override - public Collection partitionedTableNames() { - return List.of(); - } - - @Override - public Collection partitionTableNames() { - return List.of(); - } - @Override public boolean viewExists(String name) { return false; diff --git a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestCompositeSchema.java b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestCompositeSchema.java index 2da53b202..2e2765ad8 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestCompositeSchema.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestCompositeSchema.java @@ -32,7 +32,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; /** * Test {@link CompositeSchema} works correctly. @@ -74,8 +73,6 @@ public void testNoSchema() { Schema schema = new CompositeSchema(); assertTrue("Empty database", schema.isEmptyDatabase()); assertFalse("Table exists", schema.tableExists("Foo")); - assertEquals("partitionedTableNames not empty", Lists.newArrayList(), schema.partitionedTableNames()); - assertEquals("partitionTableNames not empty", Lists.newArrayList(), schema.partitionTableNames()); } diff --git a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java index 51c52b1b4..1473af813 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java @@ -33,7 +33,6 @@ import org.junit.Test; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; /** * Tests for {@link SchemaBean}. @@ -71,10 +70,6 @@ public void testCaseSensitivity() { // Check this twice to ensure we are not reading the source schema again. assertNotNull("Columns first call", table.columns()); assertNotNull("Columns second call", table.columns()); - - // check that partitioned tables and partition tables are empty - assertEquals("Partitioned table names", Lists.newArrayList(), schema.partitionedTableNames()); - assertEquals("Partition table names", Lists.newArrayList(), schema.partitionTableNames()); } @@ -251,16 +246,6 @@ public Collection tableNames() { return Arrays.asList(table.getName()); } - @Override - public Collection partitionedTableNames() { - return List.of("PartitionedTable1"); - } - - @Override - public Collection partitionTableNames() { - return List.of("Partition_p0"); - } - /** * {@inheritDoc} diff --git a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestUpgrade.java b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestUpgrade.java index b55f0cc17..c62199857 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestUpgrade.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestUpgrade.java @@ -239,8 +239,6 @@ public void testUpgradeWithSchemaConsistencyHealing() throws SQLException { assertEquals("Path validation SQL present.", "INIT", sql.get(0)); assertEquals("Healing SQL 1.", "HEALING1", sql.get(1)); assertEquals("Healing SQL 2.", "HEALING2", sql.get(2)); - assertEquals("Partitioned table names", Lists.newArrayList(), schemaResource.partitionedTableNames()); - assertEquals("Partition table names", Lists.newArrayList(), schemaResource.partitionTableNames()); } diff --git a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java index 8cdf0d109..52a257e10 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java @@ -32,8 +32,6 @@ import org.junit.Before; import org.junit.Test; -import com.google.common.collect.Lists; - /** * Test the functionality provided by {@link TableSetSchema} * @@ -98,8 +96,6 @@ public void testGetTable() { // Then... assertNotNull(appleTable); assertEquals(tableName, appleTable.getName()); - assertEquals("Partitioned table names", Lists.newArrayList(), schema.partitionedTableNames()); - assertEquals("Partition table names", Lists.newArrayList(), schema.partitionTableNames()); } diff --git a/morf-core/src/test/java/org/alfasoftware/morf/xml/TestXmlDataSetProducer.java b/morf-core/src/test/java/org/alfasoftware/morf/xml/TestXmlDataSetProducer.java index 038cbef3c..9be7bd10d 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/xml/TestXmlDataSetProducer.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/xml/TestXmlDataSetProducer.java @@ -53,7 +53,6 @@ import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; /** * Test cases to check XML can be parsed to a data set consumer. @@ -215,9 +214,6 @@ private void testTableNamesAgainstProducer(XmlDataSetProducer producer) { use(producer.records("eNTITYoNE")); assertFalse("Non existant table", producer.getSchema().tableNames().contains("NotExist")); - assertEquals("Partitioned table names", Lists.newArrayList(), producer.getSchema().partitionedTableNames()); - assertEquals("Partition table names", Lists.newArrayList(), producer.getSchema().partitionTableNames()); - producer.close(); } diff --git a/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java b/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java index a394a956b..a7352911a 100755 --- a/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java +++ b/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java @@ -418,16 +418,6 @@ public Collection tableNames() { return tables.keySet(); } - @Override - public Collection partitionedTableNames() { - return List.of(); - } - - @Override - public Collection partitionTableNames() { - return List.of(); - } - @Override public Collection
tables() { throw new UnsupportedOperationException("Cannot get the metadata of a table for a spreadsheet"); diff --git a/morf-excel/src/test/java/org/alfasoftware/morf/excel/TestSpreadsheetDataSetProducer.java b/morf-excel/src/test/java/org/alfasoftware/morf/excel/TestSpreadsheetDataSetProducer.java index 4726db8fa..fe2d6888e 100755 --- a/morf-excel/src/test/java/org/alfasoftware/morf/excel/TestSpreadsheetDataSetProducer.java +++ b/morf-excel/src/test/java/org/alfasoftware/morf/excel/TestSpreadsheetDataSetProducer.java @@ -51,8 +51,6 @@ public void testGetSchema() throws URISyntaxException { assertEquals("Number of tables found [" + tableNames + "]", 12, tableNames.size()); assertTrue("Tables correctly populated [" + tableNames + "]", tableNames.contains("AssetType")); assertTrue("Tables correctly populated [" + tableNames + "]", tableNames.contains("Allowance")); - assertEquals("Partitioned table names", Lists.newArrayList(), producer.getSchema().partitionedTableNames()); - assertEquals("Partition table names", Lists.newArrayList(), producer.getSchema().partitionTableNames()); } diff --git a/morf-h2/src/main/java/org/alfasoftware/morf/jdbc/h2/H2MetaDataProvider.java b/morf-h2/src/main/java/org/alfasoftware/morf/jdbc/h2/H2MetaDataProvider.java index 4f9d16153..6dc699a4b 100755 --- a/morf-h2/src/main/java/org/alfasoftware/morf/jdbc/h2/H2MetaDataProvider.java +++ b/morf-h2/src/main/java/org/alfasoftware/morf/jdbc/h2/H2MetaDataProvider.java @@ -20,8 +20,6 @@ import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.Collection; -import java.util.List; import org.alfasoftware.morf.jdbc.DatabaseMetaDataProvider; import org.alfasoftware.morf.metadata.SchemaUtils.ColumnBuilder; @@ -103,9 +101,4 @@ protected String buildSequenceSql(String schemaName) { return sequenceSqlBuilder.toString(); } - - @Override - public Collection partitionTableNames() { - return List.of(); - } } diff --git a/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2MetaDataProvider.java b/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2MetaDataProvider.java index 3062c4984..46c584f21 100644 --- a/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2MetaDataProvider.java +++ b/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2MetaDataProvider.java @@ -37,8 +37,6 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import com.google.common.collect.Lists; - /** * Test class for {@link H2MetaDataProvider} @@ -63,21 +61,6 @@ public void before() throws SQLException { } - /** - * Checks the SQL run for retrieving sequences information - * - * @throws SQLException exception - */ - @Test - public void testPartitionedTables() throws SQLException { - // Given - - // When - final Schema h2MetaDataProvider = h2.openSchema(connection, "TestDatabase", "TestSchema"); - assertEquals("Partitioned table names", Lists.newArrayList(), h2MetaDataProvider.partitionedTableNames()); - assertEquals("Partition table names", Lists.newArrayList(), h2MetaDataProvider.partitionTableNames()); - } - /** * Checks the SQL run for retrieving sequences information * diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/dataset/MockDataSetProducer.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/dataset/MockDataSetProducer.java index 39d4b3f9b..621f2313d 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/dataset/MockDataSetProducer.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/dataset/MockDataSetProducer.java @@ -156,15 +156,6 @@ public Collection tableNames() { return tables.keySet(); } - @Override - public Collection partitionedTableNames() { - return List.of(); - } - - @Override - public Collection partitionTableNames() { - return List.of(); - } /** * @see org.alfasoftware.morf.metadata.Schema#tables() diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java index aa4973403..06f898a3b 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java @@ -32,6 +32,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalToIgnoringCase; import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThrows; @@ -342,6 +343,11 @@ public void testTableWithPartition() throws SQLException { if (isPostgres) { UncheckedExecutionException uncheckedExecutionException = assertThrows(UncheckedExecutionException.class, () -> schemaResource.getTable("WithPartition_p0")); assertTrue("partition must not be found on getTable", uncheckedExecutionException.getMessage().contains("Table [WithPartition_p0/*] not found.")); + + Table table = schemaResource.getTable("WithPartition"); + assertEquals("table must have 2 columns", 2, table.columns().size()); + assertEquals("first column must match", "id", table.columns().get(0).getName()); + assertEquals("second column column must match", "stringcol", table.columns().get(1).getName()); } } } diff --git a/morf-mysql/src/main/java/org/alfasoftware/morf/jdbc/mysql/MySqlMetaDataProvider.java b/morf-mysql/src/main/java/org/alfasoftware/morf/jdbc/mysql/MySqlMetaDataProvider.java index cbbc30bc9..f13db5325 100755 --- a/morf-mysql/src/main/java/org/alfasoftware/morf/jdbc/mysql/MySqlMetaDataProvider.java +++ b/morf-mysql/src/main/java/org/alfasoftware/morf/jdbc/mysql/MySqlMetaDataProvider.java @@ -21,8 +21,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; -import java.util.Collection; -import java.util.List; import org.alfasoftware.morf.jdbc.DatabaseMetaDataProvider; import org.alfasoftware.morf.metadata.DataType; @@ -87,8 +85,4 @@ protected String buildSequenceSql(String schemaName) { return null; } - @Override - public Collection partitionTableNames() { - return List.of(); - } } diff --git a/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleMetaDataProvider.java b/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleMetaDataProvider.java index 0ec9c24e6..6a437f116 100755 --- a/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleMetaDataProvider.java +++ b/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleMetaDataProvider.java @@ -828,16 +828,6 @@ public Collection tableNames() { return tableMap().keySet(); } - @Override - public Collection partitionedTableNames() { - return List.of(); - } - - @Override - public Collection partitionTableNames() { - return List.of(); - } - /** * {@inheritDoc} diff --git a/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleMetaDataProvider.java b/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleMetaDataProvider.java index a4ecab7a7..44006da5f 100755 --- a/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleMetaDataProvider.java +++ b/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleMetaDataProvider.java @@ -55,7 +55,6 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; /** @@ -290,8 +289,6 @@ public void testIgnoreSystemTables() throws SQLException { final Schema oracleMetaDataProvider = oracle.openSchema(connection, "TESTDATABASE", "TESTSCHEMA"); assertEquals("Table names", "[AREALTABLE]", oracleMetaDataProvider.tableNames().toString()); assertFalse("Table names", oracleMetaDataProvider.tableNames().toString().contains("DBMS")); - assertEquals("Partitioned table names", Lists.newArrayList(), oracleMetaDataProvider.partitionedTableNames()); - assertEquals("Partition table names", Lists.newArrayList(), oracleMetaDataProvider.partitionTableNames()); } diff --git a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java index e0e5f2447..8f83a727f 100644 --- a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java +++ b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java @@ -235,8 +235,14 @@ protected String buildSequenceSql(String schemaName) { return sequenceSqlBuilder.toString(); } + + @Override + public Collection partitionedTableNames() { + return super.partitionedTables.get(); + } + @Override public Collection partitionTableNames() { - return ignoredTables.get(); + return super.ignoredTables.get(); } } diff --git a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java index 25873873e..8ce880fda 100644 --- a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java +++ b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java @@ -34,6 +34,7 @@ import javax.sql.DataSource; import org.alfasoftware.morf.jdbc.DatabaseType; +import org.alfasoftware.morf.metadata.AdditionalMetadata; import org.alfasoftware.morf.metadata.Schema; import org.alfasoftware.morf.metadata.Sequence; import org.junit.Before; @@ -105,7 +106,7 @@ public void testLoadPartitionedTables() throws SQLException { .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0")); // When - final Schema postgresMetaDataProvider = postgres.openSchema(connection, "TestDatabase", "TestSchema"); + final AdditionalMetadata postgresMetaDataProvider = (AdditionalMetadata)postgres.openSchema(connection, "TestDatabase", "TestSchema"); assertEquals("Partition Table name", "[partition]", postgresMetaDataProvider.partitionedTableNames().toString()); String partitionTable = postgresMetaDataProvider.partitionedTableNames().iterator().next(); assertEquals("Partition Table name", "partition", partitionTable); @@ -128,7 +129,8 @@ public void testLoadPartitionTables() throws SQLException { .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0")); // When - final Schema postgresMetaDataProvider = postgres.openSchema(connection, "TestDatabase", "TestSchema"); + final AdditionalMetadata postgresMetaDataProvider = (AdditionalMetadata)postgres.openSchema(connection, "TestDatabase", "TestSchema"); + assertEquals("Partition Table name", "[partition_p0]", postgresMetaDataProvider.partitionTableNames().toString()); String partitionTable = postgresMetaDataProvider.partitionTableNames().iterator().next(); assertEquals("Partition Table name", "partition_p0", partitionTable); diff --git a/morf-sqlserver/src/main/java/org/alfasoftware/morf/jdbc/sqlserver/SqlServerMetaDataProvider.java b/morf-sqlserver/src/main/java/org/alfasoftware/morf/jdbc/sqlserver/SqlServerMetaDataProvider.java index c918c8aee..ba524dcbb 100755 --- a/morf-sqlserver/src/main/java/org/alfasoftware/morf/jdbc/sqlserver/SqlServerMetaDataProvider.java +++ b/morf-sqlserver/src/main/java/org/alfasoftware/morf/jdbc/sqlserver/SqlServerMetaDataProvider.java @@ -20,9 +20,7 @@ import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; -import java.util.Collection; import java.util.HashMap; -import java.util.List; import java.util.Map; import org.alfasoftware.morf.jdbc.DatabaseMetaDataProvider; @@ -155,8 +153,4 @@ protected String buildSequenceSql(String schemaName) { return sequenceSqlBuilder.toString(); } - @Override - public Collection partitionTableNames() { - return List.of(); - } } diff --git a/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java b/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java index 5758e56c1..8516862db 100644 --- a/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java +++ b/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java @@ -37,8 +37,6 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import com.google.common.collect.Lists; - /** * Test class for {@link SqlServerMetaDataProvider} @@ -86,8 +84,6 @@ public void testLoadSequences() throws SQLException { assertEquals("Sequence names", "[Sequence1]", sqlServerMetaDataProvider.sequenceNames().toString()); Sequence sequence = sqlServerMetaDataProvider.sequences().iterator().next(); assertEquals("Sequence name", "Sequence1", sequence.getName()); - assertEquals("Partitioned table names", Lists.newArrayList(), sqlServerMetaDataProvider.partitionedTableNames()); - assertEquals("Partition table names", Lists.newArrayList(), sqlServerMetaDataProvider.partitionTableNames()); verify(statement).setString(1, "TestSchema"); } From babd7e3c15ec228fcef3b55de82d1f9e4ed4d6a9 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Wed, 25 Feb 2026 16:46:15 +0000 Subject: [PATCH 13/18] Revert morf.properties change --- morf-testsupport/src/main/resources/morf.properties | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/morf-testsupport/src/main/resources/morf.properties b/morf-testsupport/src/main/resources/morf.properties index 549d5e20a..322c7fd20 100755 --- a/morf-testsupport/src/main/resources/morf.properties +++ b/morf-testsupport/src/main/resources/morf.properties @@ -1,9 +1,6 @@ # Use H2/MY_SQL/PGSQL/ORACLE for tests. -databaseType=ORACLE +databaseType=H2 hostName=localhost -instanceName=ORACLE -databaseName=ORACLE -schemaName=ALFA -userName=ALFA -password=ALFA - +databaseName=test +userName=test +password=test From f33a5a41812866e53cbbffdf11861fd3cf50a777 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Mon, 2 Mar 2026 14:21:21 +0000 Subject: [PATCH 14/18] Remove unnecessary changes --- .../morf/dataset/WithMetaDataAdapter.java | 1 - .../morf/jdbc/DatabaseMetaDataProvider.java | 12 +++++----- .../morf/metadata/AdditionalMetadata.java | 6 ++--- .../morf/xml/XmlDataSetProducer.java | 2 +- .../morf/dataset/TestWithMetaDataAdapter.java | 8 +------ .../morf/metadata/TestCompositeSchema.java | 5 +--- .../morf/metadata/TestSchemaBean.java | 4 ++-- .../upgrade/adapt/TestTableSetSchema.java | 10 ++++---- .../morf/xml/TestXmlDataSetProducer.java | 1 - .../excel/SpreadsheetDataSetProducer.java | 2 +- .../morf/jdbc/h2/TestH2MetaDataProvider.java | 23 ++++++++----------- .../morf/dataset/MockDataSetProducer.java | 2 -- .../morf/integration/TestSqlStatements.java | 1 - .../jdbc/mysql/MySqlMetaDataProvider.java | 1 - .../PostgreSQLMetaDataProvider.java | 17 +++++++------- .../postgresql/TestPostgreSQLDialect.java | 3 --- .../sqlserver/SqlServerMetaDataProvider.java | 1 - .../TestSqlServerMetaDataProvider.java | 23 ++++++++----------- 18 files changed, 47 insertions(+), 75 deletions(-) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/dataset/WithMetaDataAdapter.java b/morf-core/src/main/java/org/alfasoftware/morf/dataset/WithMetaDataAdapter.java index 6ccd67c2d..61b964393 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/dataset/WithMetaDataAdapter.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/dataset/WithMetaDataAdapter.java @@ -99,7 +99,6 @@ public Collection tableNames() { return sourceSchema.tableNames(); } - @Override public Collection
tables() { Set
tables = new HashSet<>(); diff --git a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java index 2f97204e6..fed259b07 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java @@ -15,6 +15,7 @@ package org.alfasoftware.morf.jdbc; +import static com.google.common.collect.ImmutableSet.of; import static org.alfasoftware.morf.util.SchemaValidatorUtil.validateSchemaName; import java.sql.Connection; @@ -28,12 +29,10 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -58,6 +57,7 @@ import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; /** @@ -118,8 +118,8 @@ public abstract class DatabaseMetaDataProvider implements Schema { private final LoadingCache sequenceCache = CacheBuilder.newBuilder().build(CacheLoader.from(this::loadSequence)); private final Supplier> databaseInformation = Suppliers.memoize(this::loadDatabaseInformation); - protected Supplier> ignoredTables = Suppliers.memoize(this::getIgnoredTables); - protected Supplier> partitionedTables = Suppliers.memoize(this::getPartitionedTables); + protected Supplier> ignoredTables = Suppliers.memoize(this::loadIgnoredTables); + protected Supplier> partitionedTables = Suppliers.memoize(this::loadPartitionedTables); /** * @param connection The database connection from which meta data should be provided. @@ -152,9 +152,9 @@ private Map loadDatabaseInformation() { } } - protected Set getIgnoredTables() { return new HashSet<>(); } + protected ImmutableSet loadIgnoredTables() { return ImmutableSet.of(); } - protected Set getPartitionedTables() { return new HashSet<>(); } + protected ImmutableSet loadPartitionedTables() { return ImmutableSet.of(); } /** * @see org.alfasoftware.morf.metadata.Schema#isEmptyDatabase() diff --git a/morf-core/src/main/java/org/alfasoftware/morf/metadata/AdditionalMetadata.java b/morf-core/src/main/java/org/alfasoftware/morf/metadata/AdditionalMetadata.java index f4860de4a..1053670b2 100644 --- a/morf-core/src/main/java/org/alfasoftware/morf/metadata/AdditionalMetadata.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/metadata/AdditionalMetadata.java @@ -20,10 +20,10 @@ default Map primaryKeyIndexNames() { } /** - * Provides the names of all partition tables in the database. This applies for now for postgres. Note that the order of + * Provides the names of all partitioned tables in the database. This applies for now for postgres. Note that the order of * the tables in the result is not specified. The case of the * table names may be preserved when logging progress, but should not be relied on for schema - * processing. + * processing. A partitioned table is a table that has partitions. * * @return A collection of all partitioned table names available in the database. */ @@ -33,7 +33,7 @@ default Map primaryKeyIndexNames() { * Provides the names of all partition tables in the database. This applies for now for postgres. Note that the order of * the tables in the result is not specified. The case of the * table names may be preserved when logging progress, but should not be relied on for schema - * processing. + * processing. A partition table is a table that is a partition of a partitioned table. * * @return A collection of all partition table names available in the database. */ diff --git a/morf-core/src/main/java/org/alfasoftware/morf/xml/XmlDataSetProducer.java b/morf-core/src/main/java/org/alfasoftware/morf/xml/XmlDataSetProducer.java index b94e15f93..6752b9179 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/xml/XmlDataSetProducer.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/xml/XmlDataSetProducer.java @@ -43,13 +43,13 @@ import org.alfasoftware.morf.dataset.Record; import org.alfasoftware.morf.metadata.Column; import org.alfasoftware.morf.metadata.DataSetUtils; -import org.alfasoftware.morf.metadata.DataSetUtils.RecordBuilder; import org.alfasoftware.morf.metadata.DataType; import org.alfasoftware.morf.metadata.Index; import org.alfasoftware.morf.metadata.Schema; import org.alfasoftware.morf.metadata.SchemaUtils; import org.alfasoftware.morf.metadata.Sequence; import org.alfasoftware.morf.metadata.Table; +import org.alfasoftware.morf.metadata.DataSetUtils.RecordBuilder; import org.alfasoftware.morf.metadata.View; import org.alfasoftware.morf.xml.XmlStreamProvider.XmlInputStreamProvider; import org.apache.commons.lang3.StringUtils; diff --git a/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java b/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java index 8ca9d5450..244f29854 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/dataset/TestWithMetaDataAdapter.java @@ -25,13 +25,7 @@ import java.util.HashSet; import java.util.Set; -import org.alfasoftware.morf.metadata.Column; -import org.alfasoftware.morf.metadata.DataSetUtils; -import org.alfasoftware.morf.metadata.Index; -import org.alfasoftware.morf.metadata.Schema; -import org.alfasoftware.morf.metadata.Sequence; -import org.alfasoftware.morf.metadata.Table; -import org.alfasoftware.morf.metadata.View; +import org.alfasoftware.morf.metadata.*; import org.junit.Test; /** diff --git a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestCompositeSchema.java b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestCompositeSchema.java index 2e2765ad8..d6a5fb727 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestCompositeSchema.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestCompositeSchema.java @@ -15,10 +15,7 @@ package org.alfasoftware.morf.metadata; -import static org.alfasoftware.morf.metadata.SchemaUtils.schema; -import static org.alfasoftware.morf.metadata.SchemaUtils.sequence; -import static org.alfasoftware.morf.metadata.SchemaUtils.table; -import static org.alfasoftware.morf.metadata.SchemaUtils.view; +import static org.alfasoftware.morf.metadata.SchemaUtils.*; import static org.alfasoftware.morf.sql.SqlUtils.select; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; diff --git a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java index 1473af813..d111b2b0c 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/metadata/TestSchemaBean.java @@ -28,10 +28,10 @@ import java.util.Collection; import java.util.List; -import org.alfasoftware.morf.sql.SelectStatement; -import org.alfasoftware.morf.sql.element.TableReference; import org.junit.Test; +import org.alfasoftware.morf.sql.SelectStatement; +import org.alfasoftware.morf.sql.element.TableReference; import com.google.common.collect.ImmutableList; /** diff --git a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java index 52a257e10..fa2cddc8b 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java @@ -15,9 +15,7 @@ package org.alfasoftware.morf.upgrade.adapt; -import static org.alfasoftware.morf.metadata.SchemaUtils.column; -import static org.alfasoftware.morf.metadata.SchemaUtils.sequence; -import static org.alfasoftware.morf.metadata.SchemaUtils.table; +import static org.alfasoftware.morf.metadata.SchemaUtils.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -26,12 +24,14 @@ import java.util.HashSet; import java.util.Set; -import org.alfasoftware.morf.metadata.DataType; import org.alfasoftware.morf.metadata.Sequence; -import org.alfasoftware.morf.metadata.Table; + import org.junit.Before; import org.junit.Test; +import org.alfasoftware.morf.metadata.DataType; +import org.alfasoftware.morf.metadata.Table; + /** * Test the functionality provided by {@link TableSetSchema} * diff --git a/morf-core/src/test/java/org/alfasoftware/morf/xml/TestXmlDataSetProducer.java b/morf-core/src/test/java/org/alfasoftware/morf/xml/TestXmlDataSetProducer.java index 9be7bd10d..b3e9308ef 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/xml/TestXmlDataSetProducer.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/xml/TestXmlDataSetProducer.java @@ -213,7 +213,6 @@ private void testTableNamesAgainstProducer(XmlDataSetProducer producer) { use(producer.records("eNTITYoNE")); assertFalse("Non existant table", producer.getSchema().tableNames().contains("NotExist")); - producer.close(); } diff --git a/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java b/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java index a7352911a..97b7be650 100755 --- a/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java +++ b/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java @@ -31,9 +31,9 @@ import org.alfasoftware.morf.dataset.DataSetProducer; import org.alfasoftware.morf.dataset.Record; import org.alfasoftware.morf.metadata.DataSetUtils; -import org.alfasoftware.morf.metadata.DataSetUtils.RecordBuilder; import org.alfasoftware.morf.metadata.Schema; import org.alfasoftware.morf.metadata.Sequence; +import org.alfasoftware.morf.metadata.DataSetUtils.RecordBuilder; import org.alfasoftware.morf.metadata.Table; import org.alfasoftware.morf.metadata.View; import org.apache.commons.lang3.StringUtils; diff --git a/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2MetaDataProvider.java b/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2MetaDataProvider.java index 46c584f21..74da6f61d 100644 --- a/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2MetaDataProvider.java +++ b/morf-h2/src/test/java/org/alfasoftware/morf/jdbc/h2/TestH2MetaDataProvider.java @@ -15,20 +15,6 @@ package org.alfasoftware.morf.jdbc.h2; -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.RETURNS_SMART_NULLS; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -import javax.sql.DataSource; - import org.alfasoftware.morf.jdbc.DatabaseType; import org.alfasoftware.morf.metadata.Schema; import org.alfasoftware.morf.metadata.Sequence; @@ -37,6 +23,15 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.when; /** * Test class for {@link H2MetaDataProvider} diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/dataset/MockDataSetProducer.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/dataset/MockDataSetProducer.java index 621f2313d..63bdce046 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/dataset/MockDataSetProducer.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/dataset/MockDataSetProducer.java @@ -25,7 +25,6 @@ import org.alfasoftware.morf.metadata.Sequence; import org.alfasoftware.morf.metadata.Table; import org.alfasoftware.morf.metadata.View; - import com.google.common.collect.Maps; /** @@ -156,7 +155,6 @@ public Collection tableNames() { return tables.keySet(); } - /** * @see org.alfasoftware.morf.metadata.Schema#tables() */ diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java index 5443e6882..a20f9031e 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/integration/TestSqlStatements.java @@ -121,7 +121,6 @@ import java.util.function.BiConsumer; import java.util.function.UnaryOperator; - import javax.sql.DataSource; import org.alfasoftware.morf.dataset.DataSetConnector; diff --git a/morf-mysql/src/main/java/org/alfasoftware/morf/jdbc/mysql/MySqlMetaDataProvider.java b/morf-mysql/src/main/java/org/alfasoftware/morf/jdbc/mysql/MySqlMetaDataProvider.java index f13db5325..cb471aeb0 100755 --- a/morf-mysql/src/main/java/org/alfasoftware/morf/jdbc/mysql/MySqlMetaDataProvider.java +++ b/morf-mysql/src/main/java/org/alfasoftware/morf/jdbc/mysql/MySqlMetaDataProvider.java @@ -84,5 +84,4 @@ protected ColumnBuilder setAdditionalColumnMetadata(RealName tableName, ColumnBu protected String buildSequenceSql(String schemaName) { return null; } - } diff --git a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java index 2f2b6069f..db9ee90fb 100644 --- a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java +++ b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java @@ -32,6 +32,7 @@ import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; /** * Provides meta data from a PostgreSQL database connection. @@ -54,8 +55,8 @@ public PostgreSQLMetaDataProvider(Connection connection, String schemaName) { @Override - protected Set getIgnoredTables() { - Set ignoredTables = new HashSet<>(); + protected ImmutableSet loadIgnoredTables() { + ImmutableSet.Builder ignoredTables = new ImmutableSet.Builder<>(); try(Statement ignoredTablesStmt = connection.createStatement()) { // distinguish partitioned tables from regular ones: relkind = 'p' (partition) or 'r' (regular) also can use boolean col relispartition // a partition table attached has (r, true) @@ -67,12 +68,12 @@ protected Set getIgnoredTables() { } catch (SQLException e) { // ignore exception, if it fails then incompatible Postgres version } - return ignoredTables; + return ignoredTables.build(); } @Override - protected Set getPartitionedTables() { - Set partitionedTables = new HashSet<>(); + protected ImmutableSet loadPartitionedTables() { + ImmutableSet.Builder partitionedTables = new ImmutableSet.Builder<>(); try(Statement partitionedTablesStmt = connection.createStatement()) { // distinguish partitioned tables from regular ones: relkind = 'p' (partition) or 'r' (regular) also can use boolean col relispartition // a partition table attached has (r, true) @@ -85,13 +86,13 @@ protected Set getPartitionedTables() { } catch (SQLException e) { // ignore exception, if it fails then incompatible Postgres version } - return partitionedTables; + return partitionedTables.build(); } @Override - protected boolean isIgnoredTable(@SuppressWarnings("unused") RealName tableName) { - return ignoredTables.get().contains(tableName.getDbName().toLowerCase(Locale.ROOT)); + protected boolean isIgnoredTable(RealName tableName) { + return ignoredTables.get().contains(tableName.getDbName().toLowerCase(Locale.ROOT)) || super.isIgnoredTable(tableName); } @Override diff --git a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java index f782a753e..b93483e65 100644 --- a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java +++ b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java @@ -1642,7 +1642,6 @@ protected String expectedSelectWithJoinAndLimit() { return "SELECT Test.id, Alternate.stringField FROM " + tableName(TEST_TABLE) + " INNER JOIN " + tableName("Alternate") + " ON (Test.id = Alternate.id) LIMIT 25"; } - /** * @see AbstractSqlDialectTest#expectedPortableSqlExpression() */ @@ -1650,8 +1649,6 @@ protected String expectedSelectWithJoinAndLimit() { protected String expectedPortableSqlExpression() { return "SELECT CONCAT(first_name, ' ', last_name, ' (', params->>'role', ')') FROM testschema.Test"; } - - @Override protected String expectedSelectWithOrderByWhereAndLimit() { return "SELECT id, stringField FROM " + tableName(TEST_TABLE) + " WHERE (stringField IS NOT NULL) ORDER BY id DESC LIMIT 10"; diff --git a/morf-sqlserver/src/main/java/org/alfasoftware/morf/jdbc/sqlserver/SqlServerMetaDataProvider.java b/morf-sqlserver/src/main/java/org/alfasoftware/morf/jdbc/sqlserver/SqlServerMetaDataProvider.java index ba524dcbb..c486fba87 100755 --- a/morf-sqlserver/src/main/java/org/alfasoftware/morf/jdbc/sqlserver/SqlServerMetaDataProvider.java +++ b/morf-sqlserver/src/main/java/org/alfasoftware/morf/jdbc/sqlserver/SqlServerMetaDataProvider.java @@ -152,5 +152,4 @@ protected String buildSequenceSql(String schemaName) { return sequenceSqlBuilder.toString(); } - } diff --git a/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java b/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java index 8516862db..c7268f797 100644 --- a/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java +++ b/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java @@ -15,20 +15,6 @@ package org.alfasoftware.morf.jdbc.sqlserver; -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.RETURNS_SMART_NULLS; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -import javax.sql.DataSource; - import org.alfasoftware.morf.jdbc.DatabaseType; import org.alfasoftware.morf.metadata.Schema; import org.alfasoftware.morf.metadata.Sequence; @@ -37,6 +23,15 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.when; /** * Test class for {@link SqlServerMetaDataProvider} From 2935597778b412ea325959e9cb7de6d71ac764c2 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Mon, 2 Mar 2026 14:26:13 +0000 Subject: [PATCH 15/18] Remove unnecessary changes #2 --- .../alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java | 1 - .../alfasoftware/morf/excel/SpreadsheetDataSetProducer.java | 2 +- .../morf/jdbc/postgresql/TestPostgreSQLDialect.java | 3 +++ .../morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java index fa2cddc8b..04c1994cc 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/adapt/TestTableSetSchema.java @@ -25,7 +25,6 @@ import java.util.Set; import org.alfasoftware.morf.metadata.Sequence; - import org.junit.Before; import org.junit.Test; diff --git a/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java b/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java index 97b7be650..6e8cff643 100755 --- a/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java +++ b/morf-excel/src/main/java/org/alfasoftware/morf/excel/SpreadsheetDataSetProducer.java @@ -33,8 +33,8 @@ import org.alfasoftware.morf.metadata.DataSetUtils; import org.alfasoftware.morf.metadata.Schema; import org.alfasoftware.morf.metadata.Sequence; -import org.alfasoftware.morf.metadata.DataSetUtils.RecordBuilder; import org.alfasoftware.morf.metadata.Table; +import org.alfasoftware.morf.metadata.DataSetUtils.RecordBuilder; import org.alfasoftware.morf.metadata.View; import org.apache.commons.lang3.StringUtils; diff --git a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java index b93483e65..f782a753e 100644 --- a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java +++ b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java @@ -1642,6 +1642,7 @@ protected String expectedSelectWithJoinAndLimit() { return "SELECT Test.id, Alternate.stringField FROM " + tableName(TEST_TABLE) + " INNER JOIN " + tableName("Alternate") + " ON (Test.id = Alternate.id) LIMIT 25"; } + /** * @see AbstractSqlDialectTest#expectedPortableSqlExpression() */ @@ -1649,6 +1650,8 @@ protected String expectedSelectWithJoinAndLimit() { protected String expectedPortableSqlExpression() { return "SELECT CONCAT(first_name, ' ', last_name, ' (', params->>'role', ')') FROM testschema.Test"; } + + @Override protected String expectedSelectWithOrderByWhereAndLimit() { return "SELECT id, stringField FROM " + tableName(TEST_TABLE) + " WHERE (stringField IS NOT NULL) ORDER BY id DESC LIMIT 10"; diff --git a/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java b/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java index c7268f797..bc365c983 100644 --- a/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java +++ b/morf-sqlserver/src/test/java/org/alfasoftware/morf/jdbc/sqlserver/TestSqlServerMetaDataProvider.java @@ -33,6 +33,7 @@ import static org.mockito.Mockito.*; import static org.mockito.Mockito.when; + /** * Test class for {@link SqlServerMetaDataProvider} * From a98fc774c43ddfe0a121460176daf724658bef00 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Mon, 2 Mar 2026 14:44:28 +0000 Subject: [PATCH 16/18] Remove unusable import --- .../org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java | 1 - 1 file changed, 1 deletion(-) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java index fed259b07..22d940c61 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java @@ -15,7 +15,6 @@ package org.alfasoftware.morf.jdbc; -import static com.google.common.collect.ImmutableSet.of; import static org.alfasoftware.morf.util.SchemaValidatorUtil.validateSchemaName; import java.sql.Connection; From 0bef89bb65963c1bc1f8e89ff92847cb84ac5650 Mon Sep 17 00:00:00 2001 From: Bruno Monteiro Date: Tue, 21 Apr 2026 14:42:18 +0100 Subject: [PATCH 17/18] Solve comments from Juraj --- .../morf/jdbc/DatabaseMetaDataProvider.java | 34 +++---- .../morf/metadata/AdditionalMetadata.java | 7 +- .../jdbc/TestDatabaseMetaDataProvider.java | 6 +- ...tDatabaseUpgradePathValidationService.java | 1 - .../jdbc/oracle/OracleMetaDataProvider.java | 15 ++-- .../oracle/TestOracleMetaDataProvider.java | 5 +- .../PostgreSQLMetaDataProvider.java | 46 +++++----- .../TestPostgreSqlMetaDataProvider.java | 88 +++++++++++++------ 8 files changed, 117 insertions(+), 85 deletions(-) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java index 22d940c61..c75b44572 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/jdbc/DatabaseMetaDataProvider.java @@ -32,6 +32,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -117,8 +118,8 @@ public abstract class DatabaseMetaDataProvider implements Schema { private final LoadingCache sequenceCache = CacheBuilder.newBuilder().build(CacheLoader.from(this::loadSequence)); private final Supplier> databaseInformation = Suppliers.memoize(this::loadDatabaseInformation); - protected Supplier> ignoredTables = Suppliers.memoize(this::loadIgnoredTables); - protected Supplier> partitionedTables = Suppliers.memoize(this::loadPartitionedTables); + protected Supplier> ignoredPartitionTables = Suppliers.memoize(this::loadIgnoredPartitionTables); + protected Supplier> partitionedTables = Suppliers.memoize(this::loadPartitionedTables); /** * @param connection The database connection from which meta data should be provided. @@ -151,9 +152,9 @@ private Map loadDatabaseInformation() { } } - protected ImmutableSet loadIgnoredTables() { return ImmutableSet.of(); } + protected Set loadIgnoredPartitionTables() { return ImmutableSet.of(); } - protected ImmutableSet loadPartitionedTables() { return ImmutableSet.of(); } + protected Set loadPartitionedTables() { return ImmutableSet.of(); } /** * @see org.alfasoftware.morf.metadata.Schema#isEmptyDatabase() @@ -314,8 +315,7 @@ protected Map loadAllTableNames() { } // add partitioned tables to list partitionedTables.get().forEach(table -> { - RealName partionedTableName = createRealName(table, table); - tableNameMappings.put(partionedTableName, partionedTableName); + tableNameMappings.put(table, table); }); long end = System.currentTimeMillis(); @@ -400,8 +400,8 @@ protected boolean isSystemSequence(@SuppressWarnings("unused") RealName sequence * @param tableName The table which we are accessing. * @return true if the table should be ignored, false otherwise. */ - protected boolean isIgnoredTable(@SuppressWarnings("unused") RealName tableName) { - return false; + protected boolean isIgnoredTable(RealName tableName) { + return ignoredPartitionTables.get().contains(tableName); } @@ -1140,22 +1140,16 @@ protected static AName named(String name) { protected void runSQL(String sql, String schemaName, ResultSetHandler handler) { if (log.isTraceEnabled()) log.trace("runSQL: " + sql); try { - PreparedStatement statement = connection.prepareStatement(sql); - try { + try (PreparedStatement statement = connection.prepareStatement(sql)) { // pass through the schema name if (schemaName != null && !schemaName.isBlank()) { statement.setString(1, schemaName); } - ResultSet resultSet = statement.executeQuery(); - try { + try (ResultSet resultSet = statement.executeQuery()) { handler.handle(resultSet); - } finally { - resultSet.close(); } - } finally { - statement.close(); } } catch (SQLException sqle) { throw new RuntimeSqlException("Error running SQL: " + sql, sqle); @@ -1207,7 +1201,7 @@ protected interface ResultSetHandler { * @return {@link RealName} instance holding the two name versions. * Can also be used as a key in the lookup maps, like {@link AName}. */ - protected static RealName createRealName(String dbName, String realName) { + public static RealName createRealName(String dbName, String realName) { return new RealName(dbName, realName); } @@ -1221,7 +1215,7 @@ protected static RealName createRealName(String dbName, String realName) { * see {@link DatabaseMetaDataProvider#named(String)} * and {@link DatabaseMetaDataProvider#createRealName(String, String)} */ - protected static class AName { + public static class AName { private final String aName; private final int hashCode; @@ -1266,11 +1260,11 @@ public final boolean equals(Object obj) { // final intentional! * see {@link DatabaseMetaDataProvider#named(String)} * and {@link DatabaseMetaDataProvider#createRealName(String, String)} */ - protected static final class RealName extends AName { + public static final class RealName extends AName { private final String realName; - private RealName(String dbName, String realName) { + public RealName(String dbName, String realName) { super(dbName); this.realName = realName; } diff --git a/morf-core/src/main/java/org/alfasoftware/morf/metadata/AdditionalMetadata.java b/morf-core/src/main/java/org/alfasoftware/morf/metadata/AdditionalMetadata.java index 1053670b2..5a88fcdee 100644 --- a/morf-core/src/main/java/org/alfasoftware/morf/metadata/AdditionalMetadata.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/metadata/AdditionalMetadata.java @@ -1,9 +1,10 @@ package org.alfasoftware.morf.metadata; -import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; +import org.alfasoftware.morf.jdbc.DatabaseMetaDataProvider; import org.apache.commons.lang3.NotImplementedException; /** @@ -27,7 +28,7 @@ default Map primaryKeyIndexNames() { * * @return A collection of all partitioned table names available in the database. */ - default Collection partitionedTableNames() { throw new NotImplementedException("Not implemented yet."); } + default Set partitionedTableNames() { throw new NotImplementedException("Not implemented yet."); } /** * Provides the names of all partition tables in the database. This applies for now for postgres. Note that the order of @@ -37,7 +38,7 @@ default Map primaryKeyIndexNames() { * * @return A collection of all partition table names available in the database. */ - default Collection partitionTableNames() { throw new NotImplementedException("Not implemented yet."); } + default Set partitionTableNames() { throw new NotImplementedException("Not implemented yet."); } default Map> ignoredIndexes() { return Map.of(); diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java index 24af98616..ec06cb008 100755 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/jdbc/TestDatabaseMetaDataProvider.java @@ -181,7 +181,6 @@ public void after() throws SQLException { String schema = Strings.isNullOrEmpty(database.getSchemaName()) ? "" : database.getSchemaName() + "."; connection.createStatement().executeUpdate("DROP TABLE " + schema + "WithTimestamp"); } - schemaManager.invalidateCache(); } @@ -294,7 +293,7 @@ public void testTableWithTypes() throws SQLException { )); schemaResource.getAdditionalMetadata().ifPresent(additionalMetadata -> - assertThat(additionalMetadata.ignoredIndexes().get("WITHTYPES"), containsInAnyOrder(ImmutableList.of( + assertThat(additionalMetadata.ignoredIndexes().get("withtypes"), containsInAnyOrder(ImmutableList.of( indexMatcher(index("WithTypes_PRF1").columns("decimalNineFiveCol", "bigIntegerCol")) )))); } @@ -338,8 +337,11 @@ public void testTableWithPartition() throws SQLException { String tableSchema = Strings.isNullOrEmpty(database.getSchemaName()) ? "" : database.getSchemaName() + "."; connection.createStatement().executeUpdate("DROP TABLE " + tableSchema + "WithPartition"); connection.createStatement().executeUpdate("CREATE TABLE " + tableSchema + "WithPartition(id numeric(19) NOT NULL, stringCol VARCHAR(20)) PARTITION BY RANGE (id)"); + connection.createStatement().executeUpdate("COMMENT ON TABLE "+ tableSchema + "WithPartition IS 'REALNAME:[WithPartition]'"); connection.createStatement().executeUpdate("CREATE TABLE " + tableSchema + "WithPartition_p0 PARTITION OF " + tableSchema + "WithPartition FOR VALUES FROM (0) TO (10000)"); + connection.createStatement().executeUpdate("COMMENT ON TABLE "+ tableSchema + "WithPartition_p0 IS 'REALNAME:[WithPartition_p0]'"); connection.createStatement().executeUpdate("CREATE TABLE " + tableSchema + "WithPartition_p1 PARTITION OF " + tableSchema + "WithPartition FOR VALUES FROM (10000) TO (99999)"); + connection.createStatement().executeUpdate("COMMENT ON TABLE "+ tableSchema + "WithPartition_p1 IS 'REALNAME:[WithPartition_p1]'"); } } diff --git a/morf-integration-test/src/test/java/org/alfasoftware/morf/upgrade/TestDatabaseUpgradePathValidationService.java b/morf-integration-test/src/test/java/org/alfasoftware/morf/upgrade/TestDatabaseUpgradePathValidationService.java index b68a8e73f..1502a9a6a 100644 --- a/morf-integration-test/src/test/java/org/alfasoftware/morf/upgrade/TestDatabaseUpgradePathValidationService.java +++ b/morf-integration-test/src/test/java/org/alfasoftware/morf/upgrade/TestDatabaseUpgradePathValidationService.java @@ -82,7 +82,6 @@ public void setup() { public void tearDown() { dropUpgradeStatusTable(); schemaManager.invalidateCache(); - // to make following test on test suite run clean - org.alfasoftware.morf.upgrade.TestFullDeployment schemaManager.dropAllTables(); } diff --git a/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleMetaDataProvider.java b/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleMetaDataProvider.java index 817145484..d6d7e1ac5 100755 --- a/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleMetaDataProvider.java +++ b/morf-oracle/src/main/java/org/alfasoftware/morf/jdbc/oracle/OracleMetaDataProvider.java @@ -29,6 +29,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -382,7 +383,7 @@ public void handle(ResultSet resultSet) throws SQLException { if (DatabaseMetaDataProviderUtils.shouldIgnoreIndex(indexName)) { Index ignoredIndex = getAssembledIndex(unique, indexNameFinal); - String currentTableName = currentTable.getName().toUpperCase(); + String currentTableName = currentTable.getName().toLowerCase(Locale.ROOT); if (ignoredIndexes.containsKey(currentTableName)) { ignoredIndexes.compute(currentTableName, (k, tableIgnoredIndexes) -> { List newList = tableIgnoredIndexes == null ? new ArrayList<>() : new ArrayList<>(tableIgnoredIndexes); @@ -471,7 +472,7 @@ public void handle(ResultSet resultSet) throws SQLException { if (DatabaseMetaDataProviderUtils.shouldIgnoreIndex(indexName)) { Index lastIndex = null; - for (Index currentIndex : ignoredIndexes.get(currentTable.getName().toUpperCase())) { + for (Index currentIndex : ignoredIndexes.get(currentTable.getName().toLowerCase())) { if (currentIndex.getName().equalsIgnoreCase(indexName)) { lastIndex = currentIndex; break; @@ -788,22 +789,16 @@ private interface ResultSetHandler { */ private void runSQL(String sql, ResultSetHandler handler) { try { - PreparedStatement statement = connection.prepareStatement(sql); - try { + try (PreparedStatement statement = connection.prepareStatement(sql)) { // We'll inevitably need a lot of meta data so may as well get it in big chunks. statement.setFetchSize(100); // pass through the schema name statement.setString(1, schemaName); - ResultSet resultSet = statement.executeQuery(); - try { + try (ResultSet resultSet = statement.executeQuery()){ handler.handle(resultSet); - } finally { - resultSet.close(); } - } finally { - statement.close(); } } catch (SQLException sqle) { throw new RuntimeSqlException("Error running SQL: " + sql, sqle); diff --git a/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleMetaDataProvider.java b/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleMetaDataProvider.java index 4fd59b786..78ea7b0db 100755 --- a/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleMetaDataProvider.java +++ b/morf-oracle/src/test/java/org/alfasoftware/morf/jdbc/oracle/TestOracleMetaDataProvider.java @@ -33,6 +33,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; +import java.util.Locale; import java.util.Map; import javax.sql.DataSource; @@ -155,7 +156,7 @@ public void testPrimaryKeyIndexNames() throws SQLException { /** * Checks the building of the collection of primary key index names. - * @throws SQLException + * @throws SQLException with error */ @Test public void testIgnoredIndexes() throws SQLException { @@ -211,7 +212,7 @@ public void testIgnoredIndexes() throws SQLException { // When final AdditionalMetadata oracleMetaDataProvider = (AdditionalMetadata) oracle.openSchema(connection, "TESTDATABASE", "TESTSCHEMA"); - List actualIgnoredIndexes = oracleMetaDataProvider.ignoredIndexes().get("AREALTABLE"); + List actualIgnoredIndexes = oracleMetaDataProvider.ignoredIndexes().get("AREALTABLE".toLowerCase(Locale.ROOT)); assertEquals("Ignored indexes size.", 2, actualIgnoredIndexes.size()); assertEquals("Ignored AREALTABLE table indexes size.", 2, actualIgnoredIndexes.size()); Index index = actualIgnoredIndexes.get(0); diff --git a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java index db9ee90fb..95a23df64 100644 --- a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java +++ b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLMetaDataProvider.java @@ -9,10 +9,8 @@ import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; -import java.util.Collection; import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -55,46 +53,52 @@ public PostgreSQLMetaDataProvider(Connection connection, String schemaName) { @Override - protected ImmutableSet loadIgnoredTables() { - ImmutableSet.Builder ignoredTables = new ImmutableSet.Builder<>(); + protected Set loadIgnoredPartitionTables() { + ImmutableSet.Builder ignoredTables = new ImmutableSet.Builder<>(); try(Statement ignoredTablesStmt = connection.createStatement()) { // distinguish partitioned tables from regular ones: relkind = 'p' (partition) or 'r' (regular) also can use boolean col relispartition - // a partition table attached has (r, true) - try (ResultSet ignoredTablesRs = ignoredTablesStmt.executeQuery("select relname from pg_class where relispartition and relkind = 'r'")) { + // a partition table attached has (r, true) -- CREATE TABLE MEASURE_P1 (id, a, b) FOR VALUES ('0) TO ('37000'); + // a partitioned table has (p, false) -- CREATE TABLE MEASURE(id, a, b) PARTITION by ID; + try (ResultSet ignoredTablesRs = ignoredTablesStmt.executeQuery("select par.relname, d.description\n" + + "from pg_class par \n" + + "join pg_namespace n on n.oid = par.relnamespace\n" + + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + + " where par.relispartition and par.relkind = 'r'")) { while (ignoredTablesRs.next()) { - ignoredTables.add(ignoredTablesRs.getString(1).toLowerCase(Locale.ROOT)); + ignoredTables.add(createRealName(ignoredTablesRs.getString(1), ignoredTablesRs.getString(2))); } } } catch (SQLException e) { // ignore exception, if it fails then incompatible Postgres version + log.info("The loading of ignored partitions failed, probably because it is a version before 11"); } return ignoredTables.build(); } @Override - protected ImmutableSet loadPartitionedTables() { - ImmutableSet.Builder partitionedTables = new ImmutableSet.Builder<>(); + protected Set loadPartitionedTables() { + ImmutableSet.Builder partitionedTables = new ImmutableSet.Builder<>(); try(Statement partitionedTablesStmt = connection.createStatement()) { // distinguish partitioned tables from regular ones: relkind = 'p' (partition) or 'r' (regular) also can use boolean col relispartition - // a partition table attached has (r, true) - // a partition table has (p, false) - try (ResultSet ignoredTablesRs = partitionedTablesStmt.executeQuery("select relname from pg_class where not relispartition and relkind = 'p'")) { + // a partition table attached has (r, true) -- CREATE TABLE MEASURE_P1 (id, a, b) FOR VALUES ('0) TO ('37000'); + // a partitioned table has (p, false) -- CREATE TABLE MEASURE(id, a, b) PARTITION by ID; + try (ResultSet ignoredTablesRs = partitionedTablesStmt.executeQuery("select par.relname as tableName, d.description\n" + + "from pg_class par \n" + + "join pg_namespace n on n.oid = par.relnamespace \n" + + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + + "where not par.relispartition and par.relkind = 'p'")) { while (ignoredTablesRs.next()) { - partitionedTables.add(ignoredTablesRs.getString(1).toLowerCase(Locale.ROOT)); + partitionedTables.add(createRealName(ignoredTablesRs.getString(1), matchComment(ignoredTablesRs.getString(2)))); } } } catch (SQLException e) { // ignore exception, if it fails then incompatible Postgres version + log.info("The loading of ignored partitions failed, probably because it is a version before 11"); } return partitionedTables.build(); } - @Override - protected boolean isIgnoredTable(RealName tableName) { - return ignoredTables.get().contains(tableName.getDbName().toLowerCase(Locale.ROOT)) || super.isIgnoredTable(tableName); - } - @Override protected boolean isPrimaryKeyIndex(RealName indexName) { return indexName.getDbName().endsWith("_pk"); @@ -280,12 +284,12 @@ protected String buildSequenceSql(String schemaName) { @Override - public Collection partitionedTableNames() { + public Set partitionedTableNames() { return super.partitionedTables.get(); } @Override - public Collection partitionTableNames() { - return super.ignoredTables.get(); + public Set partitionTableNames() { + return super.ignoredPartitionTables.get(); } } diff --git a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java index 740ab4ca2..62a7d881a 100644 --- a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java +++ b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java @@ -38,6 +38,7 @@ import javax.sql.DataSource; +import org.alfasoftware.morf.jdbc.DatabaseMetaDataProvider; import org.alfasoftware.morf.jdbc.DatabaseType; import org.alfasoftware.morf.metadata.AdditionalMetadata; import org.alfasoftware.morf.metadata.Index; @@ -108,10 +109,18 @@ public void testLoadAllIgnoredIndexes() throws SQLException { final Statement statement0 = mock(Statement.class, RETURNS_SMART_NULLS); final Statement statement1 = mock(Statement.class, RETURNS_SMART_NULLS); when(connection.createStatement()).thenReturn(statement0, statement1); - when(statement0.executeQuery("select relname from pg_class where relispartition and relkind = 'r'")) - .thenAnswer(new ReturnMockResultSetWithPartitionTables(0, "")); - when(statement1.executeQuery("select relname from pg_class where not relispartition and relkind = 'p'")) - .thenAnswer(new ReturnMockResultSetWithPartitionTables(0, "")); + when(statement0.executeQuery("select par.relname, d.description\n" + + "from pg_class par \n" + + "join pg_namespace n on n.oid = par.relnamespace\n" + + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + + " where par.relispartition and par.relkind = 'r'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(0, "", "")); + when(statement1.executeQuery("select par.relname as tableName, d.description\n" + + "from pg_class par \n" + + "join pg_namespace n on n.oid = par.relnamespace \n" + + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + + "where not par.relispartition and par.relkind = 'p'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(0, "", "")); Statement statement = mock(Statement.class, RETURNS_SMART_NULLS); when(connection.createStatement(eq(ResultSet.TYPE_FORWARD_ONLY), eq(ResultSet.CONCUR_READ_ONLY))).thenReturn(statement); @@ -201,16 +210,24 @@ public void testLoadPartitionedTables() throws SQLException { // Given final Statement statement = mock(PreparedStatement.class, RETURNS_SMART_NULLS); when(connection.createStatement()).thenReturn(statement); - when(statement.executeQuery("select relname from pg_class where not relispartition and relkind = 'p'")) - .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition")); - when(statement.executeQuery("select relname from pg_class where relispartition and relkind = 'r'")) - .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0")); + when(statement.executeQuery("select par.relname as tableName, d.description\n" + + "from pg_class par \n" + + "join pg_namespace n on n.oid = par.relnamespace \n" + + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + + "where not par.relispartition and par.relkind = 'p'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition", "Partition")); + when(statement.executeQuery("select par.relname, d.description\n" + + "from pg_class par \n" + + "join pg_namespace n on n.oid = par.relnamespace\n" + + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + + " where par.relispartition and par.relkind = 'r'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0", "Partition_p0")); // When final AdditionalMetadata postgresMetaDataProvider = (AdditionalMetadata)postgres.openSchema(connection, "TestDatabase", "TestSchema"); - assertEquals("Partition Table name", "[partition]", postgresMetaDataProvider.partitionedTableNames().toString()); - String partitionTable = postgresMetaDataProvider.partitionedTableNames().iterator().next(); - assertEquals("Partition Table name", "partition", partitionTable); + assertEquals("Partition Table name", "[partition/Partition]", postgresMetaDataProvider.partitionedTableNames().toString()); + DatabaseMetaDataProvider.RealName partitionTable = postgresMetaDataProvider.partitionedTableNames().iterator().next(); + assertEquals("Partition Table name", "partition", partitionTable.getDbName()); } @@ -224,17 +241,25 @@ public void testLoadPartitionTables() throws SQLException { // Given final Statement statement = mock(PreparedStatement.class, RETURNS_SMART_NULLS); when(connection.createStatement()).thenReturn(statement); - when(statement.executeQuery("select relname from pg_class where not relispartition and relkind = 'p'")) - .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition")); - when(statement.executeQuery("select relname from pg_class where relispartition and relkind = 'r'")) - .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0")); + when(statement.executeQuery("select par.relname as tableName, d.description\n" + + "from pg_class par \n" + + "join pg_namespace n on n.oid = par.relnamespace \n" + + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + + "where not par.relispartition and par.relkind = 'p'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition", "Partition")); + when(statement.executeQuery("select par.relname, d.description\n" + + "from pg_class par \n" + + "join pg_namespace n on n.oid = par.relnamespace\n" + + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + + " where par.relispartition and par.relkind = 'r'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0", "Partition_p0")); // When final AdditionalMetadata postgresMetaDataProvider = (AdditionalMetadata)postgres.openSchema(connection, "TestDatabase", "TestSchema"); - assertEquals("Partition Table name", "[partition_p0]", postgresMetaDataProvider.partitionTableNames().toString()); - String partitionTable = postgresMetaDataProvider.partitionTableNames().iterator().next(); - assertEquals("Partition Table name", "partition_p0", partitionTable); + assertEquals("Partition Table name", "[partition_p0/Partition_p0]", postgresMetaDataProvider.partitionTableNames().toString()); + DatabaseMetaDataProvider.RealName partitionTable = postgresMetaDataProvider.partitionTableNames().iterator().next(); + assertEquals("Partition Table name", "partition_p0", partitionTable.getDbName()); } @@ -252,10 +277,18 @@ public void testIgnoredTables() throws SQLException { when(connection.prepareStatement(anyString())).thenReturn(statement1); when(connection.createStatement()).thenReturn(statement); - when(statement.executeQuery("select relname from pg_class where not relispartition and relkind = 'p'")) - .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition")); - when(statement.executeQuery("select relname from pg_class where relispartition and relkind = 'r'")) - .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0")); + when(statement.executeQuery("select par.relname as tableName, d.description\n" + + "from pg_class par \n" + + "join pg_namespace n on n.oid = par.relnamespace \n" + + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + + "where not par.relispartition and par.relkind = 'p'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition", "Partition")); + when(statement.executeQuery("select par.relname, d.description\n" + + "from pg_class par \n" + + "join pg_namespace n on n.oid = par.relnamespace\n" + + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + + " where par.relispartition and par.relkind = 'r'")) + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0", "Partition_p0")); DatabaseMetaData postgreSQLMetaDataMock = mock(DatabaseMetaData.class); when(connection.getMetaData()).thenReturn(postgreSQLMetaDataMock); when(postgreSQLMetaDataMock.getTables(any(), any(), any(), any())) @@ -264,7 +297,7 @@ public void testIgnoredTables() throws SQLException { // When final Schema postgresMetaDataProvider = postgres.openSchema(connection, "TestDatabase", "TestSchema"); // Then - assertEquals("Partition Table name", "[partition]", postgresMetaDataProvider.tableNames().toString()); + assertEquals("Partition Table name", "[Partition]", postgresMetaDataProvider.tableNames().toString()); assertFalse("Table names", postgresMetaDataProvider.tableNames().toString().contains("partition_p0")); } @@ -278,7 +311,7 @@ private static final class ReturnMockResultSetWithSequence implements Answer Date: Tue, 21 Apr 2026 14:59:48 +0100 Subject: [PATCH 18/18] Fix failing tests --- .../jdbc/postgresql/TestPostgreSqlMetaDataProvider.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java index 62a7d881a..7ea6783eb 100644 --- a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java +++ b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSqlMetaDataProvider.java @@ -215,13 +215,13 @@ public void testLoadPartitionedTables() throws SQLException { "join pg_namespace n on n.oid = par.relnamespace \n" + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + "where not par.relispartition and par.relkind = 'p'")) - .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition", "Partition")); + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition", "REALNAME:[Partition]")); when(statement.executeQuery("select par.relname, d.description\n" + "from pg_class par \n" + "join pg_namespace n on n.oid = par.relnamespace\n" + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + " where par.relispartition and par.relkind = 'r'")) - .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0", "Partition_p0")); + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0", "REALNAME:[Partition_p0]")); // When final AdditionalMetadata postgresMetaDataProvider = (AdditionalMetadata)postgres.openSchema(connection, "TestDatabase", "TestSchema"); @@ -282,13 +282,13 @@ public void testIgnoredTables() throws SQLException { "join pg_namespace n on n.oid = par.relnamespace \n" + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + "where not par.relispartition and par.relkind = 'p'")) - .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition", "Partition")); + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition", "REALNAME:[Partition]")); when(statement.executeQuery("select par.relname, d.description\n" + "from pg_class par \n" + "join pg_namespace n on n.oid = par.relnamespace\n" + "join pg_description d ON d.objoid = par.oid and d.objsubid = 0\n" + " where par.relispartition and par.relkind = 'r'")) - .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0", "Partition_p0")); + .thenAnswer(new ReturnMockResultSetWithPartitionTables(1, "partition_p0", "REALNAME:[Partition_p0]")); DatabaseMetaData postgreSQLMetaDataMock = mock(DatabaseMetaData.class); when(connection.getMetaData()).thenReturn(postgreSQLMetaDataMock); when(postgreSQLMetaDataMock.getTables(any(), any(), any(), any()))