diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/HibernateConfiguration.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/HibernateConfiguration.kt index 9457d75835..9fce23202c 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/HibernateConfiguration.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/HibernateConfiguration.kt @@ -86,7 +86,7 @@ class HibernateConfiguration( config.setProperty("hibernate.hbm2ddl.auto","validate") databaseConfig.schema?.apply { - //preserving case-sensitive schema name for PostgreSQL by wrapping in double quotes, schema without double quotes would be treated as case-insensitive (lower cases) + // Enterprise only - preserving case-sensitive schema name for PostgreSQL by wrapping in double quotes, schema without double quotes would be treated as case-insensitive (lower cases) val schemaName = if (jdbcUrl.contains(":postgresql:", ignoreCase = true) && !databaseConfig.schema.startsWith("\"")) { "\"" + databaseConfig.schema + "\"" } else { @@ -231,4 +231,3 @@ class HibernateConfiguration( /** Allow Oracle database drivers ojdbc7.jar and ojdbc8.jar to deserialize classes from oracle.sql.converter package. */ fun oracleJdbcDriverSerialFilter(clazz: Class<*>): Boolean = clazz.name.startsWith("oracle.sql.converter.") - diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/SchemaMigration.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/SchemaMigration.kt index bb74488434..e574271049 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/SchemaMigration.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/SchemaMigration.kt @@ -17,6 +17,9 @@ import java.io.ByteArrayInputStream import java.io.InputStream import java.io.Writer import javax.sql.DataSource +import liquibase.database.core.PostgresDatabase +import liquibase.structure.DatabaseObject +import liquibase.structure.core.Schema class SchemaMigration( val schemas: Set, @@ -135,6 +138,7 @@ class SchemaMigration( private fun getLiquibaseDatabase(conn: JdbcConnection): Database { + // Enterprise only // The standard MSSQLDatabase in Liquibase does not support sequences for Ms Azure. // this class just overrides that behaviour class AzureDatabase(conn: JdbcConnection) : MSSQLDatabase() { @@ -147,9 +151,33 @@ class SchemaMigration( override fun supportsSequences(): Boolean = true } + // Enterprise only + // Postgres - Wrap schema name into double quotes to preserve case sensitivity + class PostgresDatabaseFixed(conn: JdbcConnection) : PostgresDatabase() { + init { + this.connection = conn + } + + override fun getPriority(): Int { return super.getPriority() + 1 } + + // For PostgreSQL if a schema name has uppercase or lowercase characters only then Liquibase would add it to generated query + // without double quotes and effectively make them lowercase. This is inconsistent with Corda which wraps schema name for PostgreSQL in double quotes. + // The overridden method ensures Liquibase wraps schema name into double quotes. + override fun mustQuoteObjectName(objectName: String, objectType: Class?): Boolean { + return if (objectType == Schema::class.java) + true + else + super.mustQuoteObjectName(objectName, objectType) + } + } + val liquibaseDbImplementation = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(conn) - return if (liquibaseDbImplementation is MSSQLDatabase) AzureDatabase(conn) else liquibaseDbImplementation + return when (liquibaseDbImplementation) { + is PostgresDatabase -> PostgresDatabaseFixed(conn) // Enterprise only + is MSSQLDatabase -> AzureDatabase(conn) // Enterprise only + else -> liquibaseDbImplementation + } } /** For existing database created before verions 4.0 add Liquibase support - creates DATABASECHANGELOG and DATABASECHANGELOGLOCK tables and mark changesets are executed. */ diff --git a/testing/node-driver/src/integration-test/kotlin/net/corda/testing/driver/DriverTests.kt b/testing/node-driver/src/integration-test/kotlin/net/corda/testing/driver/DriverTests.kt index e3686e72c2..d657b7d385 100644 --- a/testing/node-driver/src/integration-test/kotlin/net/corda/testing/driver/DriverTests.kt +++ b/testing/node-driver/src/integration-test/kotlin/net/corda/testing/driver/DriverTests.kt @@ -58,7 +58,7 @@ class DriverTests : IntegrationTest() { @ClassRule @JvmField val databaseSchemas = IntegrationTestSchemas(DUMMY_BANK_A_NAME.toDatabaseSchemaName(), DUMMY_NOTARY_NAME.toDatabaseSchemaName(), - DUMMY_REGULATOR_NAME.toDatabaseSchemaName(), BOB_NAME.toDatabaseSchemaName(), DUMMY_BANK_B_NAME.toDatabaseSchemaName()) + DUMMY_REGULATOR_NAME.toDatabaseSchemaName(), BOB_NAME.toDatabaseSchemaName(), DUMMY_BANK_B_NAME.toDatabaseSchemaName(), "R3CEV") } @Test @@ -157,7 +157,6 @@ class DriverTests : IntegrationTest() { @Test fun `driver rejects multiple nodes with the same organisation name`() { - assumeTrue(!IntegrationTest.isRemoteDatabaseMode()) // Enterprise only - disable test, Liquibase doesn't quote schema name with all uppercase or lowercase letters driver(DriverParameters(startNodesInProcess = true, notarySpecs = emptyList())) { newNode(CordaX500Name(commonName = "Notary", organisation = "R3CEV", locality = "New York", country = "US"))().getOrThrow() assertThatIllegalArgumentException().isThrownBy {