From e0c02b9d37d6b0d84db061259efba9a9f3909cf9 Mon Sep 17 00:00:00 2001 From: shantstepanian <17996546+shantstepanian@users.noreply.github.com> Date: Wed, 20 Mar 2019 12:30:24 -0400 Subject: [PATCH 1/5] Additional fixes around Hibernate functionality for kata --- obevo-bom/pom.xml | 20 +++++++++++++++++++ .../hibernate/HibernateDdlRevengAdapter.kt | 2 +- .../obevo/hibernate/HibernateRevengArgs.java | 4 ++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/obevo-bom/pom.xml b/obevo-bom/pom.xml index 6f0eaa3c..ea520580 100644 --- a/obevo-bom/pom.xml +++ b/obevo-bom/pom.xml @@ -240,6 +240,26 @@ obevo-reladomo-util ${project.version} + + com.goldmansachs.obevo + obevo-hibernate-util + ${project.version} + + + com.goldmansachs.obevo + obevo-hibernate3-util + ${project.version} + + + com.goldmansachs.obevo + obevo-hibernate4-util + ${project.version} + + + com.goldmansachs.obevo + obevo-hibernate5-util + ${project.version} + diff --git a/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateDdlRevengAdapter.kt b/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateDdlRevengAdapter.kt index 19003896..f2e7fd3e 100644 --- a/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateDdlRevengAdapter.kt +++ b/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateDdlRevengAdapter.kt @@ -66,7 +66,7 @@ internal class HibernateDdlRevengAdapter( return Lists.immutable.with( RevengPattern(ChangeType.TABLE_STR, namePatternType, "(?i)create\\s+table\\s+$schemaNameSubPattern") - .withPostProcessSql { LineParseOutput(it + revengArgs.postCreateTableSql) } + .withPostProcessSql { LineParseOutput(it + (revengArgs.postCreateTableSql ?: "")) } .withRemapObjectName(remapObjectName), RevengPattern(ChangeType.TABLE_STR, namePatternType, "(?i)create\\s+(?:\\w+\\s+)?index\\s+$schemaNameSubPattern\\s+on\\s+$schemaNameSubPattern", 2, 1, "INDEX") .withRemapObjectName(remapObjectName), diff --git a/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateRevengArgs.java b/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateRevengArgs.java index 8dcb09e5..6ac6f540 100644 --- a/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateRevengArgs.java +++ b/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateRevengArgs.java @@ -18,6 +18,7 @@ import java.io.File; import com.gs.obevo.db.api.platform.DbPlatform; +import org.jetbrains.annotations.Nullable; public class HibernateRevengArgs { private final String schema; @@ -26,6 +27,7 @@ public class HibernateRevengArgs { private final Class hibernateDialectClass; private final T config; private boolean generateBaseline; + @Nullable private String postCreateTableSql; private boolean generateForeignKeys = true; private boolean explicitSchemaRequired; @@ -71,10 +73,12 @@ public HibernateRevengArgs withGenerateBaseline(boolean generateBaseline) { return this; } + @Nullable public String getPostCreateTableSql() { return postCreateTableSql; } + @Nullable public void setPostCreateTableSql(String postCreateTableSql) { this.postCreateTableSql = postCreateTableSql; } From e3124e42aef4cbd3f3f7b476d525874c58e03252 Mon Sep 17 00:00:00 2001 From: shantstepanian <17996546+shantstepanian@users.noreply.github.com> Date: Wed, 20 Mar 2019 12:31:25 -0400 Subject: [PATCH 2/5] checkstyle upgrade to avoid security hole --- .../gs/obevo/db/api/platform/DbPlatform.java | 273 ++++---- .../gs/obevo/db/api/platform/SqlExecutor.java | 134 ++-- .../hibernate/HibernateDdlRevengAdapter.kt | 2 + pom.xml | 2 +- .../checkstyle-import-control.xml | 189 ++--- src/main/build-resources/checkstyle.xml | 650 +++++++++--------- 6 files changed, 627 insertions(+), 623 deletions(-) diff --git a/obevo-db/src/main/java/com/gs/obevo/db/api/platform/DbPlatform.java b/obevo-db/src/main/java/com/gs/obevo/db/api/platform/DbPlatform.java index c6e1c98c..0aa5c57d 100644 --- a/obevo-db/src/main/java/com/gs/obevo/db/api/platform/DbPlatform.java +++ b/obevo-db/src/main/java/com/gs/obevo/db/api/platform/DbPlatform.java @@ -1,137 +1,136 @@ -/** - * Copyright 2017 Goldman Sachs. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package com.gs.obevo.db.api.platform; - -import java.sql.Connection; -import java.sql.Driver; -import java.sql.Timestamp; - -import com.gs.obevo.api.appdata.Change; -import com.gs.obevo.api.appdata.PhysicalSchema; -import com.gs.obevo.api.platform.Platform; -import com.gs.obevo.db.api.appdata.DbEnvironment; -import com.gs.obevo.db.api.appdata.GrantTargetType; -import com.gs.obevo.db.apps.reveng.AbstractDdlReveng; -import com.gs.obevo.db.apps.reveng.ChangeEntry; -import com.gs.obevo.dbmetadata.api.DbMetadataManager; -import org.eclipse.collections.api.set.ImmutableSet; - -public interface DbPlatform extends Platform { - - Class getDriverClass(DbEnvironment env); - - /** - * This is for cases like in Sybase where teams had backed up db objects, and so it was created w/ a different name - * in the object, but the underlying content points to the original name. - * We only fire off this check in case the scan of the content does pick up the object name, as to be conservative - */ - boolean isDuplicateCheckRequiredForReverseEngineering(); - - /** - * Returns the token that separates the schema from the object name. - * - * @since 6.0.0 - * @deprecated No longer used; use {@link #getSchemaPrefix(PhysicalSchema)} instead. - */ - @Deprecated - String getSchemaSeparator(); - - /** - * Determines whether this platform uses catalog + schema, or just a schema. - * - * @since 6.4.0 - */ - boolean isSubschemaSupported(); - - /** - * Returns the schema and subschema (if applicable) for the given schema with the appropriate separators appended. - * - * @since 6.0.0 - */ - String getSchemaPrefix(PhysicalSchema schema); - - /** - * Returns the subschema section of the given PhysicalSchema with the separator appended, or a blank string in case - * the subschema doesn't apply. Used for cases where we don't want to assume the schema is prefixed (for backwards-compatibility - * reasons), while still supporting the subschema use case. - * - * @since 6.4.0 - */ - String getSubschemaPrefix(PhysicalSchema schema); - - String getNullMarkerForCreateTable(); - - String getTimestampType(); - - String getTextType(); - - String getBigIntType(); - - /** - * Returns the grantTargetType intended for the input grant target. Also see See the grant pattern - * in {@link DbChangeType#getGrantObjectQualifier()} - */ - String getGrantTargetTypeStr(GrantTargetType grantTargetType, String grantTarget); - - DbMetadataManager getDbMetadataManager(); - - void doTryBlockForArtifact(Connection conn, SqlExecutor sqlExecutor, Change artifact); - - void doFinallyBlockForArtifact(Connection conn, SqlExecutor sqlExecutor, Change artifact); - - /** - * Do stuff like adding annotations to the reveng file if needed (e.g. adding annotations to handling quoted - * identifiers for sybase) - */ - void postProcessChangeForRevEng(ChangeEntry change, String sql); - - DbTranslationDialect getDbTranslationDialect(DbPlatform targetDialect); - - String getArtifactDeploymentDDLString(final String changeNameColumn, - final String changeTypeColumn, - final String deployUserIdColumn, - final String timeUpdatedColumn, - final String rollbackContentColumn, - final String tablespaceSql, - final DbEnvironment env); - - ImmutableSet getRequiredValidationObjectTypes(); - - /** - * Still in beta... - */ - AbstractDdlReveng getDdlReveng(); - - String getTableSuffixSql(DbEnvironment env); - - /** - * Given an object from the result set returned by the MapListHandler in JdbcHelper, this will return a long value. - * This is simple for most DBMSs, but a few need special handling. - */ - Long getLongValue(Object obj); - - /** - * Given an object from the result set returned by the MapListHandler in JdbcHelper, this will return a timestamp value. - * This is simple for most DBMSs, but a few need special handling. - */ - Timestamp getTimestampValue(Object obj); - - /** - * Given an object from the result set returned by the MapListHandler in JdbcHelper, this will return an integer value. - * This is simple for most DBMSs, but a few need special handling. - */ - Integer getIntegerValue(Object obj); -} +/** + * Copyright 2017 Goldman Sachs. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.gs.obevo.db.api.platform; + +import java.sql.Connection; +import java.sql.Driver; +import java.sql.Timestamp; + +import com.gs.obevo.api.appdata.Change; +import com.gs.obevo.api.appdata.PhysicalSchema; +import com.gs.obevo.api.platform.Platform; +import com.gs.obevo.db.api.appdata.DbEnvironment; +import com.gs.obevo.db.api.appdata.GrantTargetType; +import com.gs.obevo.db.apps.reveng.AbstractDdlReveng; +import com.gs.obevo.db.apps.reveng.ChangeEntry; +import com.gs.obevo.dbmetadata.api.DbMetadataManager; +import org.eclipse.collections.api.set.ImmutableSet; + +public interface DbPlatform extends Platform { + Class getDriverClass(DbEnvironment env); + + /** + * This is for cases like in Sybase where teams had backed up db objects, and so it was created w/ a different name + * in the object, but the underlying content points to the original name. + * We only fire off this check in case the scan of the content does pick up the object name, as to be conservative + */ + boolean isDuplicateCheckRequiredForReverseEngineering(); + + /** + * Returns the token that separates the schema from the object name. + * + * @since 6.0.0 + * @deprecated No longer used; use {@link #getSchemaPrefix(PhysicalSchema)} instead. + */ + @Deprecated + String getSchemaSeparator(); + + /** + * Determines whether this platform uses catalog + schema, or just a schema. + * + * @since 6.4.0 + */ + boolean isSubschemaSupported(); + + /** + * Returns the schema and subschema (if applicable) for the given schema with the appropriate separators appended. + * + * @since 6.0.0 + */ + String getSchemaPrefix(PhysicalSchema schema); + + /** + * Returns the subschema section of the given PhysicalSchema with the separator appended, or a blank string in case + * the subschema doesn't apply. Used for cases where we don't want to assume the schema is prefixed (for backwards-compatibility + * reasons), while still supporting the subschema use case. + * + * @since 6.4.0 + */ + String getSubschemaPrefix(PhysicalSchema schema); + + String getNullMarkerForCreateTable(); + + String getTimestampType(); + + String getTextType(); + + String getBigIntType(); + + /** + * Returns the grantTargetType intended for the input grant target. Also see See the grant pattern + * in {@link DbChangeType#getGrantObjectQualifier()} + */ + String getGrantTargetTypeStr(GrantTargetType grantTargetType, String grantTarget); + + DbMetadataManager getDbMetadataManager(); + + void doTryBlockForArtifact(Connection conn, SqlExecutor sqlExecutor, Change artifact); + + void doFinallyBlockForArtifact(Connection conn, SqlExecutor sqlExecutor, Change artifact); + + /** + * Do stuff like adding annotations to the reveng file if needed (e.g. adding annotations to handling quoted + * identifiers for sybase) + */ + void postProcessChangeForRevEng(ChangeEntry change, String sql); + + DbTranslationDialect getDbTranslationDialect(DbPlatform targetDialect); + + String getArtifactDeploymentDDLString(String changeNameColumn, + String changeTypeColumn, + String deployUserIdColumn, + String timeUpdatedColumn, + String rollbackContentColumn, + String tablespaceSql, + DbEnvironment env); + + ImmutableSet getRequiredValidationObjectTypes(); + + /** + * Still in beta... + */ + AbstractDdlReveng getDdlReveng(); + + String getTableSuffixSql(DbEnvironment env); + + /** + * Given an object from the result set returned by the MapListHandler in JdbcHelper, this will return a long value. + * This is simple for most DBMSs, but a few need special handling. + */ + Long getLongValue(Object obj); + + /** + * Given an object from the result set returned by the MapListHandler in JdbcHelper, this will return a timestamp value. + * This is simple for most DBMSs, but a few need special handling. + */ + Timestamp getTimestampValue(Object obj); + + /** + * Given an object from the result set returned by the MapListHandler in JdbcHelper, this will return an integer value. + * This is simple for most DBMSs, but a few need special handling. + */ + Integer getIntegerValue(Object obj); +} diff --git a/obevo-db/src/main/java/com/gs/obevo/db/api/platform/SqlExecutor.java b/obevo-db/src/main/java/com/gs/obevo/db/api/platform/SqlExecutor.java index 4ac5d16f..f0697cdb 100644 --- a/obevo-db/src/main/java/com/gs/obevo/db/api/platform/SqlExecutor.java +++ b/obevo-db/src/main/java/com/gs/obevo/db/api/platform/SqlExecutor.java @@ -1,67 +1,67 @@ -/** - * Copyright 2017 Goldman Sachs. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package com.gs.obevo.db.api.platform; - -import java.sql.Connection; - -import com.gs.obevo.api.appdata.PhysicalSchema; -import com.gs.obevo.db.impl.core.jdbc.JdbcHelper; -import com.gs.obevo.dbmetadata.api.DbMetadataManager; -import com.gs.obevo.impl.ExecuteChangeCommand; -import org.eclipse.collections.api.block.procedure.Procedure; -import org.eclipse.collections.impl.block.function.checked.ThrowingFunction; - -/** - * The interface through which to access the database for {@link DbPlatform} implementations. - * - * While JdbcHelper does the actual SQL invocation, we must access it from this class due to the complexities around - * accessing the data source, notably that: - * 1) We need to set the schema for the duration of a connection across many API calls - * 2) For Sybase IQ, we must explicitly have a different connection to change schemas as edits are done by connecting - * as that schema user. - * - * Along with that, this class is used to "set the context" of the data source, i.e. assign a single connection of the - * data source to a thread. This is akin to a transaction manager or txn management context in JTA - * - * This class is a bit convoluted now; could be simpler to just resort to passing a connection around. That will be a - * refactor for a later time... - */ -public interface SqlExecutor { - /** - * Returns the JdbcHelper for accessing the database. The "context" methods must be used in conjunction with this. - */ - JdbcHelper getJdbcTemplate(); - - /** - * Convenience method that will execute the given runnable while wrapping the setContext/unsetContext methods in - * a try-finally block. - */ - void executeWithinContext(PhysicalSchema schema, Procedure runnable); - - /** - * Convenience method that will execute the given runnable while wrapping the setContext/unsetContext methods in - * a try-finally block. - */ - T executeWithinContext(PhysicalSchema schema, ThrowingFunction callable); - - /** - * Unused operation. - * - * @deprecated Do not use - */ - @Deprecated - void performExtraCleanOperation(final ExecuteChangeCommand command, final DbMetadataManager metaDataMgr); -} +/** + * Copyright 2017 Goldman Sachs. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.gs.obevo.db.api.platform; + +import java.sql.Connection; + +import com.gs.obevo.api.appdata.PhysicalSchema; +import com.gs.obevo.db.impl.core.jdbc.JdbcHelper; +import com.gs.obevo.dbmetadata.api.DbMetadataManager; +import com.gs.obevo.impl.ExecuteChangeCommand; +import org.eclipse.collections.api.block.procedure.Procedure; +import org.eclipse.collections.impl.block.function.checked.ThrowingFunction; + +/** + * The interface through which to access the database for {@link DbPlatform} implementations. + * + * While JdbcHelper does the actual SQL invocation, we must access it from this class due to the complexities around + * accessing the data source, notably that: + * 1) We need to set the schema for the duration of a connection across many API calls + * 2) For Sybase IQ, we must explicitly have a different connection to change schemas as edits are done by connecting + * as that schema user. + * + * Along with that, this class is used to "set the context" of the data source, i.e. assign a single connection of the + * data source to a thread. This is akin to a transaction manager or txn management context in JTA + * + * This class is a bit convoluted now; could be simpler to just resort to passing a connection around. That will be a + * refactor for a later time... + */ +public interface SqlExecutor { + /** + * Returns the JdbcHelper for accessing the database. The "context" methods must be used in conjunction with this. + */ + JdbcHelper getJdbcTemplate(); + + /** + * Convenience method that will execute the given runnable while wrapping the setContext/unsetContext methods in + * a try-finally block. + */ + void executeWithinContext(PhysicalSchema schema, Procedure runnable); + + /** + * Convenience method that will execute the given runnable while wrapping the setContext/unsetContext methods in + * a try-finally block. + */ + T executeWithinContext(PhysicalSchema schema, ThrowingFunction callable); + + /** + * Unused operation. + * + * @deprecated Do not use + */ + @Deprecated + void performExtraCleanOperation(ExecuteChangeCommand command, DbMetadataManager metaDataMgr); +} diff --git a/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateDdlRevengAdapter.kt b/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateDdlRevengAdapter.kt index f2e7fd3e..82cb2a8e 100644 --- a/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateDdlRevengAdapter.kt +++ b/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateDdlRevengAdapter.kt @@ -71,6 +71,8 @@ internal class HibernateDdlRevengAdapter( RevengPattern(ChangeType.TABLE_STR, namePatternType, "(?i)create\\s+(?:\\w+\\s+)?index\\s+$schemaNameSubPattern\\s+on\\s+$schemaNameSubPattern", 2, 1, "INDEX") .withRemapObjectName(remapObjectName), RevengPattern(ChangeType.TABLE_STR, namePatternType, "(?i)alter\\s+table\\s+$schemaNameSubPattern\\s+add\\s+constraint\\s+$schemaNameSubPattern\\s+foreign\\s+key", 1, 2, "FK").withShouldBeIgnored(!revengArgs.isGenerateForeignKeys) + .withRemapObjectName(remapObjectName), + RevengPattern(ChangeType.SEQUENCE_STR, namePatternType, "(?i)create\\s+sequence\\s+$schemaNameSubPattern\\s+") .withRemapObjectName(remapObjectName) ) } diff --git a/pom.xml b/pom.xml index e1df4149..32fb21ec 100644 --- a/pom.xml +++ b/pom.xml @@ -695,7 +695,7 @@ com.puppycrawl.tools checkstyle - 6.19 + 8.18 diff --git a/src/main/build-resources/checkstyle-import-control.xml b/src/main/build-resources/checkstyle-import-control.xml index 857414b5..b394a34d 100644 --- a/src/main/build-resources/checkstyle-import-control.xml +++ b/src/main/build-resources/checkstyle-import-control.xml @@ -1,94 +1,95 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/build-resources/checkstyle.xml b/src/main/build-resources/checkstyle.xml index e9195b4b..d96b3c24 100644 --- a/src/main/build-resources/checkstyle.xml +++ b/src/main/build-resources/checkstyle.xml @@ -1,324 +1,326 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 7e6296b5162ca59351fef4ccdf1c7db7cb0116c2 Mon Sep 17 00:00:00 2001 From: shantstepanian <17996546+shantstepanian@users.noreply.github.com> Date: Wed, 20 Mar 2019 19:55:23 -0400 Subject: [PATCH 3/5] Postgres view drop use case fixes --- .../java/com/gs/obevo/impl/MainDeployer.kt | 49 ++++- .../impl/text/TextDependencyExtractable.kt | 2 +- .../text/TextDependencyExtractableImpl.kt | 2 +- .../postgresql/PostgreSqlDeployerIT.java | 177 +++++++++--------- .../example1/step1/schema1/view/VIEW1.sql | 34 ++-- .../example1/step1/schema1/view/VIEW4.sql | 17 ++ .../schema1/staticdata/TABLE_SPECIAL_COL.csv | 2 + .../step2/schema1/table/TABLE_SPECIAL_COL.ddl | 7 + .../hibernate/HibernateDdlRevengAdapter.kt | 2 +- 9 files changed, 173 insertions(+), 119 deletions(-) create mode 100644 obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/view/VIEW4.sql create mode 100644 obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/staticdata/TABLE_SPECIAL_COL.csv create mode 100644 obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_SPECIAL_COL.ddl diff --git a/obevo-core/src/main/java/com/gs/obevo/impl/MainDeployer.kt b/obevo-core/src/main/java/com/gs/obevo/impl/MainDeployer.kt index 63d68004..68d438dc 100644 --- a/obevo-core/src/main/java/com/gs/obevo/impl/MainDeployer.kt +++ b/obevo-core/src/main/java/com/gs/obevo/impl/MainDeployer.kt @@ -15,9 +15,25 @@ */ package com.gs.obevo.impl -import com.gs.obevo.api.appdata.* +import com.gs.obevo.api.appdata.Change +import com.gs.obevo.api.appdata.ChangeIncremental +import com.gs.obevo.api.appdata.ChangeKey +import com.gs.obevo.api.appdata.ChangeRerunnable +import com.gs.obevo.api.appdata.DeployExecution +import com.gs.obevo.api.appdata.DeployExecutionImpl +import com.gs.obevo.api.appdata.DeployExecutionStatus +import com.gs.obevo.api.appdata.Environment import com.gs.obevo.api.factory.PlatformConfiguration -import com.gs.obevo.api.platform.* +import com.gs.obevo.api.platform.ChangeAuditDao +import com.gs.obevo.api.platform.ChangeCommand +import com.gs.obevo.api.platform.CommandExecutionContext +import com.gs.obevo.api.platform.DeployExecutionDao +import com.gs.obevo.api.platform.DeployExecutionException +import com.gs.obevo.api.platform.DeployMetrics +import com.gs.obevo.api.platform.FailedChange +import com.gs.obevo.api.platform.GraphExportFormat +import com.gs.obevo.api.platform.MainDeployerArgs +import com.gs.obevo.api.platform.Platform import com.gs.obevo.impl.graph.GraphEnricher import com.gs.obevo.impl.graph.GraphUtil import com.gs.obevo.impl.text.TextDependencyExtractableImpl @@ -35,13 +51,19 @@ import org.eclipse.collections.impl.block.factory.StringFunctions import org.eclipse.collections.impl.factory.Lists import org.eclipse.collections.impl.factory.Sets import org.jgrapht.DirectedGraph -import org.jgrapht.ext.* +import org.jgrapht.ext.DOTExporter +import org.jgrapht.ext.GmlExporter +import org.jgrapht.ext.GraphMLExporter +import org.jgrapht.ext.IntegerEdgeNameProvider +import org.jgrapht.ext.IntegerNameProvider +import org.jgrapht.ext.MatrixExporter +import org.jgrapht.ext.VertexNameProvider import org.jgrapht.graph.DefaultEdge import org.slf4j.LoggerFactory import java.io.FileWriter import java.io.Writer import java.sql.Timestamp -import java.util.* +import java.util.Date import java.util.concurrent.TimeUnit /** @@ -188,23 +210,30 @@ class MainDeployer

>( // TODO refactor into separate method if (env.platform.isDropOrderRequired) { + // In this block, we set the "dependentChanges" field on the drop objects to ensure they can be sorted for dependencies later on val dropsToEnrich = changePairs .filter { it.changeKey.changeType.isRerunnable && it.sourceChange == null && it.deployedChange != null } .map { it.deployedChange!! } - val drops = dropsToEnrich.map {drop -> + val dropsByObjectName = dropsToEnrich.associateBy { env.platform.convertDbObjectName().valueOf(it.objectName) } + + val dropsForTextProcessing = dropsToEnrich.map { drop -> val sql = changeTypeBehaviorRegistry.getChangeTypeBehavior(drop.changeType).getDefinitionFromEnvironment(drop); LOG.debug("Found the sql from the DB for dropping: {}", sql) TextDependencyExtractableImpl(drop.objectName, sql ?: "", drop) } - val dropDependencies = this.textDependencyExtractor.calculateDependencies(drops) - - drops.forEach { it.codeDependencies = Sets.immutable.ofAll(dropDependencies.get(it)) } + val dropDependencies = this.textDependencyExtractor.calculateDependencies(dropsForTextProcessing) - val dependencyGraph = graphEnricher.createDependencyGraph(sourceChanges, deployerArgs.isRollback) + dropsForTextProcessing.forEach { it.codeDependencies = Sets.immutable.ofAll(dropDependencies.get(it)) } - dropsToEnrich.forEach { it.dependentChanges = GraphUtil.getDependencyNodes(dependencyGraph, it) } + for (drop in dropsForTextProcessing) { + drop.codeDependencies?.let { deps -> + if (deps.notEmpty()) { + drop.payload.dependentChanges = Sets.immutable.ofAll(deps.map { dropsByObjectName[it.target] }) + } + } + } } diff --git a/obevo-core/src/main/java/com/gs/obevo/impl/text/TextDependencyExtractable.kt b/obevo-core/src/main/java/com/gs/obevo/impl/text/TextDependencyExtractable.kt index b73e8292..3703cc08 100644 --- a/obevo-core/src/main/java/com/gs/obevo/impl/text/TextDependencyExtractable.kt +++ b/obevo-core/src/main/java/com/gs/obevo/impl/text/TextDependencyExtractable.kt @@ -37,7 +37,7 @@ interface TextDependencyExtractable { * * @since 6.4.0 */ - val codeDependencies: ImmutableSet + val codeDependencies: ImmutableSet? /** * The dependencies to exclude from the text. This is to let the user specify the false-positive dependencies that diff --git a/obevo-core/src/main/java/com/gs/obevo/impl/text/TextDependencyExtractableImpl.kt b/obevo-core/src/main/java/com/gs/obevo/impl/text/TextDependencyExtractableImpl.kt index 0f0fff68..b8b6ef27 100644 --- a/obevo-core/src/main/java/com/gs/obevo/impl/text/TextDependencyExtractableImpl.kt +++ b/obevo-core/src/main/java/com/gs/obevo/impl/text/TextDependencyExtractableImpl.kt @@ -27,7 +27,7 @@ class TextDependencyExtractableImpl ( override val contentForDependencyCalculation: String, val payload: T ) : TextDependencyExtractable { - override var codeDependencies: ImmutableSet = Sets.immutable.empty() + override var codeDependencies: ImmutableSet? = null override val excludeDependencies: ImmutableSet get() = Sets.immutable.empty() diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlDeployerIT.java b/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlDeployerIT.java index bb85f47f..f9de46fd 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlDeployerIT.java +++ b/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlDeployerIT.java @@ -1,89 +1,88 @@ -/** - * Copyright 2017 Goldman Sachs. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package com.gs.obevo.db.impl.platforms.postgresql; - -import java.sql.Connection; -import java.sql.Timestamp; -import java.util.List; -import java.util.Map; - -import javax.sql.DataSource; - -import com.gs.obevo.db.api.platform.DbDeployerAppContext; -import com.gs.obevo.db.impl.core.jdbc.JdbcHelper; -import org.apache.commons.dbutils.DbUtils; -import org.eclipse.collections.api.block.function.primitive.IntToObjectFunction; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import static org.junit.Assert.assertEquals; - -@RunWith(Parameterized.class) -public class PostgreSqlDeployerIT { - @Parameterized.Parameters - public static Iterable params() { - return PostgreSqlParamReader.getParamReader().getAppContextAndJdbcDsParams(); - } - - private final IntToObjectFunction getAppContext; - private final DataSource ds; - - public PostgreSqlDeployerIT(IntToObjectFunction getAppContext, DataSource ds) { - this.getAppContext = getAppContext; - this.ds = ds; - } - - @Test - public void testDeploy() throws Exception { - getAppContext.valueOf(1) - .setupEnvInfra() - .setupEnvInfra() - .cleanEnvironment() - .deploy(); - - // ensuring that we can modify - DbDeployerAppContext dbDeployerAppContext = getAppContext.valueOf(2); - dbDeployerAppContext - .cleanEnvironment() - .setupEnvInfra() - .deploy(); - - JdbcHelper jdbc = new JdbcHelper(); - - Connection conn = ds.getConnection(); - try { - List> results = jdbc.queryForList(conn, "select * from " + dbDeployerAppContext.getEnvironment().getPhysicalSchema("schema1") + ".TABLE_A order by a_id"); - assertEquals(3, results.size()); - this.validateResults(results.get(0), 2, 3, "fasdfasd", "2013-02-02 11:11:11.65432", 9); - this.validateResults(results.get(1), 3, 4, "ABC", null, 9); - this.validateResults(results.get(2), 4, 2, "ABC", "2012-01-01 12:12:12", null); - } finally { - DbUtils.closeQuietly(conn); - } - } - - private void validateResults(Map map, Integer aId, - Integer bId, String stringField, String timestampField, Integer cId) { - - assertEquals(aId, map.get("A_ID")); - assertEquals(bId, map.get("B_ID")); - assertEquals(stringField, map.get("STRING_FIELD")); - Timestamp millis = timestampField == null ? null : Timestamp.valueOf(timestampField); - assertEquals(millis, map.get("TIMESTAMP_FIELD")); - assertEquals(cId, map.get("C_ID")); - } -} +/** + * Copyright 2017 Goldman Sachs. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.gs.obevo.db.impl.platforms.postgresql; + +import java.sql.Connection; +import java.sql.Timestamp; +import java.util.List; +import java.util.Map; + +import javax.sql.DataSource; + +import com.gs.obevo.db.api.platform.DbDeployerAppContext; +import com.gs.obevo.db.impl.core.jdbc.JdbcHelper; +import org.apache.commons.dbutils.DbUtils; +import org.eclipse.collections.api.block.function.primitive.IntToObjectFunction; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) +public class PostgreSqlDeployerIT { + @Parameterized.Parameters + public static Iterable params() { + return PostgreSqlParamReader.getParamReader().getAppContextAndJdbcDsParams(); + } + + private final IntToObjectFunction getAppContext; + private final DataSource ds; + + public PostgreSqlDeployerIT(IntToObjectFunction getAppContext, DataSource ds) { + this.getAppContext = getAppContext; + this.ds = ds; + } + + @Test + public void testDeploy() throws Exception { + getAppContext.valueOf(1) + .setupEnvInfra() + .setupEnvInfra() + .cleanEnvironment() + .deploy(); + + // ensuring that we can modify + DbDeployerAppContext dbDeployerAppContext = getAppContext.valueOf(2); + dbDeployerAppContext + .setupEnvInfra() + .deploy(); + + JdbcHelper jdbc = new JdbcHelper(); + + Connection conn = ds.getConnection(); + try { + List> results = jdbc.queryForList(conn, "select * from " + dbDeployerAppContext.getEnvironment().getPhysicalSchema("schema1") + ".TABLE_A order by a_id"); + assertEquals(3, results.size()); + this.validateResults(results.get(0), 2, 3, "fasdfasd", "2013-02-02 11:11:11.65432", 9); + this.validateResults(results.get(1), 3, 4, "ABC", null, 9); + this.validateResults(results.get(2), 4, 2, "ABC", "2012-01-01 12:12:12", null); + } finally { + DbUtils.closeQuietly(conn); + } + } + + private void validateResults(Map map, Integer aId, + Integer bId, String stringField, String timestampField, Integer cId) { + + assertEquals(aId, map.get("A_ID")); + assertEquals(bId, map.get("B_ID")); + assertEquals(stringField, map.get("STRING_FIELD")); + Timestamp millis = timestampField == null ? null : Timestamp.valueOf(timestampField); + assertEquals(millis, map.get("TIMESTAMP_FIELD")); + assertEquals(cId, map.get("C_ID")); + } +} diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/view/VIEW1.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/view/VIEW1.sql index 6ee34aa5..50edcbcb 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/view/VIEW1.sql +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/view/VIEW1.sql @@ -1,17 +1,17 @@ --- --- Copyright 2017 Goldman Sachs. --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, --- software distributed under the License is distributed on an --- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY --- KIND, either express or implied. See the License for the --- specific language governing permissions and limitations --- under the License. --- - -CREATE OR REPLACE VIEW VIEW1 AS SELECT * FROM VIEW3 +-- +-- Copyright 2017 Goldman Sachs. +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. +-- + +CREATE OR REPLACE VIEW VIEW1 AS SELECT * FROM VIEW2 diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/view/VIEW4.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/view/VIEW4.sql new file mode 100644 index 00000000..f843f561 --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/view/VIEW4.sql @@ -0,0 +1,17 @@ +-- +-- Copyright 2017 Goldman Sachs. +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. +-- + +CREATE OR REPLACE VIEW VIEW4 AS SELECT * FROM VIEW3 diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/staticdata/TABLE_SPECIAL_COL.csv b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/staticdata/TABLE_SPECIAL_COL.csv new file mode 100644 index 00000000..007e6fac --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/staticdata/TABLE_SPECIAL_COL.csv @@ -0,0 +1,2 @@ +"UUID_PK","STR1" +"186FFBB4-9A4D-4572-B89F-0D992BB9EB81","test1" diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_SPECIAL_COL.ddl b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_SPECIAL_COL.ddl new file mode 100644 index 00000000..3114fe83 --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_SPECIAL_COL.ddl @@ -0,0 +1,7 @@ +//// CHANGE name=chng1 +CREATE TABLE TABLE_SPECIAL_COL ( + UUID_PK UUID NOT NULL, + STR1 VARCHAR(30) NULL, + PRIMARY KEY (UUID_PK) +) +GO diff --git a/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateDdlRevengAdapter.kt b/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateDdlRevengAdapter.kt index 82cb2a8e..d2316c6f 100644 --- a/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateDdlRevengAdapter.kt +++ b/obevo-utils/obevo-hibernate-util/src/main/java/com/gs/obevo/hibernate/HibernateDdlRevengAdapter.kt @@ -70,7 +70,7 @@ internal class HibernateDdlRevengAdapter( .withRemapObjectName(remapObjectName), RevengPattern(ChangeType.TABLE_STR, namePatternType, "(?i)create\\s+(?:\\w+\\s+)?index\\s+$schemaNameSubPattern\\s+on\\s+$schemaNameSubPattern", 2, 1, "INDEX") .withRemapObjectName(remapObjectName), - RevengPattern(ChangeType.TABLE_STR, namePatternType, "(?i)alter\\s+table\\s+$schemaNameSubPattern\\s+add\\s+constraint\\s+$schemaNameSubPattern\\s+foreign\\s+key", 1, 2, "FK").withShouldBeIgnored(!revengArgs.isGenerateForeignKeys) + RevengPattern(ChangeType.TABLE_STR, namePatternType, "(?i)alter\\s+table\\s+(?:if\\s+exists\\s+)?$schemaNameSubPattern\\s+add\\s+constraint\\s+$schemaNameSubPattern\\s+foreign\\s+key", 1, 2, "FK").withShouldBeIgnored(!revengArgs.isGenerateForeignKeys) .withRemapObjectName(remapObjectName), RevengPattern(ChangeType.SEQUENCE_STR, namePatternType, "(?i)create\\s+sequence\\s+$schemaNameSubPattern\\s+") .withRemapObjectName(remapObjectName) From bac766aa847c52c48bdf73eab05dcd126f7d5de6 Mon Sep 17 00:00:00 2001 From: shantstepanian <17996546+shantstepanian@users.noreply.github.com> Date: Sat, 23 Mar 2019 10:15:07 -0400 Subject: [PATCH 4/5] Additional postgres reverse engineering fixes --- .../api/factory/PlatformConfigReader.java | 8 +- .../postgresql/PostgreSqlDbPlatform.java | 236 +++++++-------- .../postgresql/PostgreSqlPgDumpReveng.java | 43 ++- .../postgresql/PostgreSqlRevengTest.java | 2 + .../PostgresqlDbMetadataManagerIT.java | 201 +++++++------ .../step1/schema1/usertype/usertype0.sql | 9 + .../step2/schema1/usertype/usertype0.sql | 9 + .../test/resources/postgresql-test-drops.sql | 144 ++++----- .../src/test/resources/postgresql-test.sql | 211 ++++++------- .../pgdump/expected/myschema01/sp/sp1.sql | 7 + .../myschema01/usertype/usertype1.sql | 9 + .../pgdump/input/input-noschemaqualifier.sql | 265 +++++++++++++++++ .../resources/reveng/pgdump/input/input.sql | 65 ++-- .../gs/obevo/db/api/platform/DbPlatform.java | 6 + .../db/apps/reveng/AbstractDdlReveng.java | 11 +- .../dialects/PostgresqlMetadataDialect.java | 278 ++++++++++-------- 16 files changed, 945 insertions(+), 559 deletions(-) create mode 100644 obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/usertype/usertype0.sql create mode 100644 obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/usertype/usertype0.sql create mode 100644 obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/expected/myschema01/sp/sp1.sql create mode 100644 obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/expected/myschema01/usertype/usertype1.sql create mode 100644 obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/input/input-noschemaqualifier.sql diff --git a/obevo-core/src/main/java/com/gs/obevo/api/factory/PlatformConfigReader.java b/obevo-core/src/main/java/com/gs/obevo/api/factory/PlatformConfigReader.java index 4f3c4282..f667f7a3 100644 --- a/obevo-core/src/main/java/com/gs/obevo/api/factory/PlatformConfigReader.java +++ b/obevo-core/src/main/java/com/gs/obevo/api/factory/PlatformConfigReader.java @@ -135,7 +135,7 @@ public String valueOf(PropertyInput propertyInput) { return propertyInput.getFileName(); } }); - final MutableList warnings = Lists.mutable.empty(); + final MutableList debugMessages = Lists.mutable.empty(); final MutableList errors = Lists.mutable.empty(); propertiesByFileName.forEachKeyMultiValues(new Procedure2>() { @@ -157,7 +157,7 @@ public URL valueOf(PropertyInput propertyInput) { } }) + "]. Please ensure that priorities are distinct."); } else if (priorities.size() > 1) { - warnings.add("File name [" + fileName + "] was found in multiple locations [" + propertyInputs.collect(new Function() { + debugMessages.add("File name [" + fileName + "] was found in multiple locations [" + propertyInputs.collect(new Function() { @Override public URL valueOf(PropertyInput propertyInput) { return propertyInput.getPropertyFilePath(); @@ -167,8 +167,8 @@ public URL valueOf(PropertyInput propertyInput) { } }); - if (warnings.notEmpty()) { - LOG.warn("Warnings on platform configuration file setup; please address in the future, but program will proceed:\n{}", warnings.makeString("\n")); + if (debugMessages.notEmpty()) { + LOG.debug("Debug notices on platform configuration file setup:\n{}", debugMessages.makeString("\n")); } if (errors.notEmpty()) { diff --git a/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlDbPlatform.java b/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlDbPlatform.java index f2782aa4..43f290c4 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlDbPlatform.java +++ b/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlDbPlatform.java @@ -1,117 +1,119 @@ -/** - * Copyright 2017 Goldman Sachs. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package com.gs.obevo.db.impl.platforms.postgresql; - -import com.gs.obevo.api.platform.ChangeType; -import com.gs.obevo.api.platform.DeployerAppContext; -import com.gs.obevo.db.api.appdata.GrantTargetType; -import com.gs.obevo.db.api.platform.DbChangeType; -import com.gs.obevo.db.api.platform.DbChangeTypeImpl; -import com.gs.obevo.db.apps.reveng.AbstractDdlReveng; -import com.gs.obevo.db.impl.platforms.AbstractDbPlatform; -import org.eclipse.collections.api.block.function.Function; -import org.eclipse.collections.api.list.ImmutableList; -import org.eclipse.collections.api.list.MutableList; -import org.eclipse.collections.api.set.ImmutableSet; -import org.eclipse.collections.impl.block.factory.Predicates; -import org.eclipse.collections.impl.block.factory.StringFunctions; - -/** - * PostgreSQL DBMS platform implementation. - */ -public class PostgreSqlDbPlatform extends AbstractDbPlatform { - public PostgreSqlDbPlatform() { - super("POSTGRESQL"); - } - - /** - * Protected constructor to allow for the Amazon-based platforms that leverage PostgreSQL as their SQL interface. - */ - protected PostgreSqlDbPlatform(String name) { - super(name); - } - - @Override - public Class initializeAppContextBuilderClass() { - return PostgreSqlAppContext.class; - } - - @Override - protected String initializeDefaultDriverClassName() { - return "org.postgresql.Driver"; - } - - @Override - protected ImmutableList initializeChangeTypes() { - MutableList changeTypes = super.initializeChangeTypes().toList(); - - DbChangeType sequenceType = getChangeType(changeTypes, ChangeType.SEQUENCE_STR); - sequenceType = DbChangeTypeImpl.newDbChangeType(sequenceType).setGrantObjectQualifier("SEQUENCE").build(); - replaceChangeType(changeTypes, sequenceType); - - DbChangeType functionType = getChangeType(changeTypes, ChangeType.FUNCTION_STR); - functionType = DbChangeTypeImpl.newDbChangeType(functionType).setGrantObjectQualifier("FUNCTION").build(); - replaceChangeType(changeTypes, functionType); - - return changeTypes.toImmutable(); - } - - @Override - public boolean isDropOrderRequired() { - return true; - } - - @Override - protected String getGrantTargetTypeStrDbSpecific(GrantTargetType grantTargetType) { - // only user must have the blank defined; GROUP can still be specified - switch (grantTargetType) { - case USER: - return ""; - default: - return grantTargetType.name(); - } - } - - @Override - public Function convertDbObjectName() { - return StringFunctions.toLowerCase(); - } - - @Override - public String getNullMarkerForCreateTable() { - return ""; // for DB2 create statement, a blank implies NULL. Adding NULL explicitly was not allowed prior to - // v9.7, so we leave this here - } - - @Override - public String getTimestampType() { - return "TIMESTAMP"; - } - - @Override - public ImmutableSet getRequiredValidationObjectTypes() { - // there is currently a quirk w/ PostgreSQL where view SQL definitions will not have the objects qualified w/ - // the schema name in the connection that creates the SQL; but in subsequent connections, it will be qualified. - // Until we work out this issue, we will exclude views from PostgreSQL processing. - return super.getRequiredValidationObjectTypes() - .reject(Predicates.equal(ChangeType.VIEW_STR)); - } - - @Override - public AbstractDdlReveng getDdlReveng() { - return new PostgreSqlPgDumpReveng(); - } -} +/** + * Copyright 2017 Goldman Sachs. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.gs.obevo.db.impl.platforms.postgresql; + +import com.gs.obevo.api.platform.ChangeType; +import com.gs.obevo.api.platform.DeployerAppContext; +import com.gs.obevo.db.api.appdata.GrantTargetType; +import com.gs.obevo.db.api.platform.DbChangeType; +import com.gs.obevo.db.api.platform.DbChangeTypeImpl; +import com.gs.obevo.db.apps.reveng.AbstractDdlReveng; +import com.gs.obevo.db.impl.platforms.AbstractDbPlatform; +import org.eclipse.collections.api.block.function.Function; +import org.eclipse.collections.api.list.ImmutableList; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.api.set.ImmutableSet; +import org.eclipse.collections.impl.block.factory.Predicates; +import org.eclipse.collections.impl.block.factory.StringFunctions; + +/** + * PostgreSQL DBMS platform implementation. + */ +public class PostgreSqlDbPlatform extends AbstractDbPlatform { + public PostgreSqlDbPlatform() { + super("POSTGRESQL"); + } + + /** + * Protected constructor to allow for the Amazon-based platforms that leverage PostgreSQL as their SQL interface. + */ + protected PostgreSqlDbPlatform(String name) { + super(name); + } + + @Override + public Class initializeAppContextBuilderClass() { + return PostgreSqlAppContext.class; + } + + @Override + protected String initializeDefaultDriverClassName() { + return "org.postgresql.Driver"; + } + + @Override + protected ImmutableList initializeChangeTypes() { + MutableList changeTypes = super.initializeChangeTypes().toList(); + + DbChangeType sequenceType = getChangeType(changeTypes, ChangeType.SEQUENCE_STR); + sequenceType = DbChangeTypeImpl.newDbChangeType(sequenceType).setGrantObjectQualifier("SEQUENCE").build(); + replaceChangeType(changeTypes, sequenceType); + + DbChangeType functionType = getChangeType(changeTypes, ChangeType.FUNCTION_STR); + functionType = DbChangeTypeImpl.newDbChangeType(functionType).setGrantObjectQualifier("FUNCTION").build(); + replaceChangeType(changeTypes, functionType); + + DbChangeType typeType = DbChangeTypeImpl.newDbChangeType(ChangeType.USERTYPE_STR, true, 1, "TYPE").build(); + changeTypes.add(typeType); + + return changeTypes.toImmutable(); + } + + @Override + public boolean isDropOrderRequired() { + return true; + } + + @Override + protected String getGrantTargetTypeStrDbSpecific(GrantTargetType grantTargetType) { + // only user must have the blank defined; GROUP can still be specified + switch (grantTargetType) { + case USER: + return ""; + default: + return grantTargetType.name(); + } + } + + @Override + public Function convertDbObjectName() { + return StringFunctions.toLowerCase(); + } + + @Override + public String getNullMarkerForCreateTable() { + return ""; + } + + @Override + public String getTimestampType() { + return "TIMESTAMP"; + } + + @Override + public ImmutableSet getRequiredValidationObjectTypes() { + // there is currently a quirk w/ PostgreSQL where view SQL definitions will not have the objects qualified w/ + // the schema name in the connection that creates the SQL; but in subsequent connections, it will be qualified. + // Until we work out this issue, we will exclude views from PostgreSQL processing. + return super.getRequiredValidationObjectTypes() + .reject(Predicates.equal(ChangeType.VIEW_STR)); + } + + @Override + public AbstractDdlReveng getDdlReveng() { + return new PostgreSqlPgDumpReveng(); + } +} diff --git a/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlPgDumpReveng.java b/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlPgDumpReveng.java index bbf7bd2b..59a27338 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlPgDumpReveng.java +++ b/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlPgDumpReveng.java @@ -56,9 +56,10 @@ public class PostgreSqlPgDumpReveng extends AbstractDdlReveng { } private static ImmutableList getRevengPatterns() { - String schemaNameSubPattern = getObjectPattern("", ""); + String schemaNameSubPattern = getSchemaObjectPattern("", ""); + String objectNameSubPattern = getObjectPattern("", ""); - NamePatternType namePatternType = NamePatternType.ONE; + NamePatternType namePatternType = NamePatternType.TWO; return Lists.immutable.with( new RevengPattern(ChangeType.SEQUENCE_STR, namePatternType, "(?i)create\\s+(?:or\\s+replace\\s+)?sequence\\s+" + schemaNameSubPattern).withPostProcessSql(REPLACE_TABLESPACE).withPostProcessSql(REMOVE_QUOTES), new RevengPattern(ChangeType.TABLE_STR, namePatternType, "(?i)create\\s+table\\s+" + schemaNameSubPattern).withPostProcessSql(REPLACE_TABLESPACE).withPostProcessSql(REMOVE_QUOTES), @@ -66,33 +67,51 @@ private static ImmutableList getRevengPatterns() { new RevengPattern(ChangeType.TABLE_STR, namePatternType, "(?i)alter\\s+sequence\\s+" + schemaNameSubPattern + "\\s+owned\\s+by\\s+" + schemaNameSubPattern, 2, 1, null).withPostProcessSql(REMOVE_QUOTES), new RevengPattern(ChangeType.TABLE_STR, namePatternType, "(?i)create\\s+(?:unique\\s+)index\\s+" + schemaNameSubPattern + "\\s+on\\s+" + schemaNameSubPattern, 2, 1, "INDEX").withPostProcessSql(REPLACE_TABLESPACE).withPostProcessSql(REMOVE_QUOTES), new RevengPattern(ChangeType.FUNCTION_STR, namePatternType, "(?i)create\\s+(?:or\\s+replace\\s+)?(?:force\\s+)?(?:editionable\\s+)?function\\s+" + schemaNameSubPattern), + new RevengPattern(ChangeType.SP_STR, namePatternType, "(?i)create\\s+(?:or\\s+replace\\s+)?(?:force\\s+)?(?:editionable\\s+)?procedure\\s+" + schemaNameSubPattern), new RevengPattern(ChangeType.VIEW_STR, namePatternType, "(?i)create\\s+(?:or\\s+replace\\s+)?(?:force\\s+)?(?:editionable\\s+)?view\\s+" + schemaNameSubPattern), new RevengPattern(ChangeType.SP_STR, namePatternType, "(?i)create\\s+(?:or\\s+replace\\s+)(?:editionable\\s+)procedure\\s+" + schemaNameSubPattern), new RevengPattern(ChangeType.PACKAGE_STR, namePatternType, "(?i)create\\s+(?:or\\s+replace\\s+)(?:editionable\\s+)package\\s+" + schemaNameSubPattern), - new RevengPattern(ChangeType.TRIGGER_STR, namePatternType, "(?i)create\\s+or\\s+replace\\s+trigger\\s+" + schemaNameSubPattern) + new RevengPattern(ChangeType.TRIGGER_STR, namePatternType, "(?i)create\\s+or\\s+replace\\s+trigger\\s+" + schemaNameSubPattern), + new RevengPattern(ChangeType.USERTYPE_STR, namePatternType, "(?i)create\\s+(?:or\\s+replace\\s+)?type\\s+" + schemaNameSubPattern) ); } @Override protected boolean doRevengOrInstructions(PrintStream out, AquaRevengArgs args, File interimDir) { - out.println("1) Run the following command to generate the DDL file:"); - out.println(getCommandWithDefaults(args, "", "", "", "", "", "", "")); - out.println(""); + out.println("1) Create the folder for your interim output:"); + out.println(); + out.println("mkdir -p " + interimDir.getAbsolutePath()); + out.println(); + out.println(); + out.println("2) Run the following command to generate the DDL file:"); + out.println(); + out.println("(without Docker)"); + out.println(getCommandWithDefaults(false, args, interimDir, "", "", "", "", "", "", "")); + out.println(); + out.println("(with Docker)"); + out.println(getCommandWithDefaults(true, args, interimDir, "", "", "", "", "", "", "")); + out.println(); out.println("Here is an example command (in case your values are not filled in):"); - out.println(getCommandWithDefaults(args, "myuser", "mypassword", "myhost.myplace.com", "12345", "mydb", "myschema", "H:\\sybase-ddl-output.txt")); - out.println(""); - out.println("The pg_dump command will "); + out.println(); + out.println("(without Docker)"); + out.println(getCommandWithDefaults(false, args, interimDir, "myuser", "mypassword", "myhost.myplace.com", "12345", "mydb", "myschema", "H:\\sybase-ddl-output.txt")); + out.println(); + out.println("(with Docker)"); + out.println(getCommandWithDefaults(true, args, interimDir, "myuser", "mypassword", "myhost.myplace.com", "12345", "mydb", "myschema", "H:\\sybase-ddl-output.txt")); + out.println(); return false; } - private String getCommandWithDefaults(AquaRevengArgs args, String username, String password, String dbHost, String dbPort, String dbName, String dbSchema, String outputDirectory) { - return "pg_dump -O --disable-dollar-quoting -s" + + private String getCommandWithDefaults(boolean container, AquaRevengArgs args, File interimDir, String username, String password, String dbHost, String dbPort, String dbName, String dbSchema, String outputDirectory) { + String prefix = container ? "docker exec $CONTAINER_NAME " : ""; + String fileSuffix = container ? "> " + interimDir.getAbsolutePath() : " -f " + interimDir.getAbsolutePath(); + return prefix + "pg_dump -O -s --no-privileges" + " -h " + ObjectUtils.defaultIfNull(args.getDbHost(), dbHost) + " -p " + ObjectUtils.defaultIfNull(args.getDbPort(), dbPort) + " --username=" + ObjectUtils.defaultIfNull(args.getUsername(), username) + " -d " + ObjectUtils.defaultIfNull(args.getDbServer(), dbName) + " -n " + ObjectUtils.defaultIfNull(args.getDbSchema(), dbSchema) + - " -f " + ObjectUtils.defaultIfNull(args.getOutputPath(), outputDirectory); + " " + fileSuffix; } } diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlRevengTest.java b/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlRevengTest.java index d4f8ae18..41cae661 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlRevengTest.java +++ b/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlRevengTest.java @@ -45,5 +45,7 @@ public void testReverseEngineeringFromFile() throws Exception { new PostgreSqlDbPlatform().getDdlReveng().reveng(args); DirectoryAssert.assertDirectoriesEqual(new File("./src/test/resources/reveng/pgdump/expected"), new File(outputDir, "final")); + + // TODO add test for input-noschemaqualifier.sql for older postgres versions } } diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/dbmetadata/impl/dialects/PostgresqlDbMetadataManagerIT.java b/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/dbmetadata/impl/dialects/PostgresqlDbMetadataManagerIT.java index 55b5a956..1e4aed70 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/dbmetadata/impl/dialects/PostgresqlDbMetadataManagerIT.java +++ b/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/dbmetadata/impl/dialects/PostgresqlDbMetadataManagerIT.java @@ -1,98 +1,103 @@ -/** - * Copyright 2017 Goldman Sachs. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package com.gs.obevo.dbmetadata.impl.dialects; - -import javax.sql.DataSource; - -import com.gs.obevo.api.appdata.PhysicalSchema; -import com.gs.obevo.db.impl.platforms.postgresql.PostgreSqlDbPlatform; -import com.gs.obevo.db.impl.platforms.postgresql.PostgreSqlParamReader; -import com.gs.obevo.dbmetadata.api.DbMetadataManager; -import org.apache.commons.dbutils.QueryRunner; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -@RunWith(Parameterized.class) -public class PostgresqlDbMetadataManagerIT extends AbstractDbMetadataManagerIT { - @Parameterized.Parameters - public static Iterable params() { - return PostgreSqlParamReader.getParamReader().getJdbcDsAndSchemaParams(); - } - - public PostgresqlDbMetadataManagerIT(DataSource dataSource, PhysicalSchema physicalSchema) { - super(dataSource, physicalSchema); - } - - @Override - protected DbMetadataManager createMetadataManager() { - return new PostgreSqlDbPlatform().getDbMetadataManager(); - } - - @Override - protected String convertName(String name) { - return name.toLowerCase(); - } - - @Override - protected String get_FUNC1() { - return "BEGIN -- ensure that func comment remains RETURN 1; END;"; - } - - @Override - protected boolean isInvalidViewPossible() { - return false; // postgresql does not allow invalid views (i.e. views that have dependent tables dropped first) - } - - @Override - protected boolean isStoredProcedureSupported() { - return false; // postgresql only supports functions, not procedures separately - } - - @Override - protected String get_VIEW1() { - return "SELECT metadata_test_table.afield, metadata_test_table.bfield FROM metadata_test_table;"; - } - - @Override - protected void setCurrentSchema(QueryRunner jdbc) throws Exception { - jdbc.update("SET search_path TO " + getSchemaName()); - } - - @Override - protected String getDropSqlFile() { - return "postgresql-test-drops.sql"; - } - - @Override - protected String getAddSqlFile() { - return "postgresql-test.sql"; - } - - @Override - protected String get_FUNC_WITH_OVERLOAD_1() { - return "BEGIN RETURN 1; END;"; - } - - @Override - protected String get_FUNC_WITH_OVERLOAD_2() { - return "BEGIN RETURN 1; END;"; - } - - @Override - protected String get_FUNC_WITH_OVERLOAD_3() { - return "BEGIN RETURN 1; END;"; - } -} +/** + * Copyright 2017 Goldman Sachs. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.gs.obevo.dbmetadata.impl.dialects; + +import javax.sql.DataSource; + +import com.gs.obevo.api.appdata.PhysicalSchema; +import com.gs.obevo.db.impl.platforms.postgresql.PostgreSqlDbPlatform; +import com.gs.obevo.db.impl.platforms.postgresql.PostgreSqlParamReader; +import com.gs.obevo.dbmetadata.api.DbMetadataManager; +import org.apache.commons.dbutils.QueryRunner; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class PostgresqlDbMetadataManagerIT extends AbstractDbMetadataManagerIT { + @Parameterized.Parameters + public static Iterable params() { + return PostgreSqlParamReader.getParamReader().getJdbcDsAndSchemaParams(); + } + + public PostgresqlDbMetadataManagerIT(DataSource dataSource, PhysicalSchema physicalSchema) { + super(dataSource, physicalSchema); + } + + @Override + protected DbMetadataManager createMetadataManager() { + return new PostgreSqlDbPlatform().getDbMetadataManager(); + } + + @Override + protected String convertName(String name) { + return name.toLowerCase(); + } + + @Override + protected String get_FUNC1() { + return "BEGIN -- ensure that func comment remains RETURN 1; END;"; + } + + @Override + protected boolean isInvalidViewPossible() { + return false; // postgresql does not allow invalid views (i.e. views that have dependent tables dropped first) + } + + @Override + boolean isUserTypeSupported() { + return true; + } + + @Override + protected boolean isStoredProcedureSupported() { + return false; // postgresql only supports functions, not procedures separately. Metadata for procedures is stored as functions for now + } + + @Override + protected String get_VIEW1() { + return "SELECT metadata_test_table.afield, metadata_test_table.bfield FROM metadata_test_table;"; + } + + @Override + protected void setCurrentSchema(QueryRunner jdbc) throws Exception { + jdbc.update("SET search_path TO " + getSchemaName()); + } + + @Override + protected String getDropSqlFile() { + return "postgresql-test-drops.sql"; + } + + @Override + protected String getAddSqlFile() { + return "postgresql-test.sql"; + } + + @Override + protected String get_FUNC_WITH_OVERLOAD_1() { + return "BEGIN RETURN 1; END;"; + } + + @Override + protected String get_FUNC_WITH_OVERLOAD_2() { + return "BEGIN RETURN 1; END;"; + } + + @Override + protected String get_FUNC_WITH_OVERLOAD_3() { + return "BEGIN RETURN 1; END;"; + } +} diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/usertype/usertype0.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/usertype/usertype0.sql new file mode 100644 index 00000000..bfe03d74 --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/usertype/usertype0.sql @@ -0,0 +1,9 @@ +CREATE TYPE usertype0 AS ENUM ( + '1', + '2', + '3' +); + + + +GO \ No newline at end of file diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/usertype/usertype0.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/usertype/usertype0.sql new file mode 100644 index 00000000..bfe03d74 --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/usertype/usertype0.sql @@ -0,0 +1,9 @@ +CREATE TYPE usertype0 AS ENUM ( + '1', + '2', + '3' +); + + + +GO \ No newline at end of file diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/postgresql-test-drops.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/postgresql-test-drops.sql index 31138ab0..971386c3 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/postgresql-test-drops.sql +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/postgresql-test-drops.sql @@ -1,70 +1,74 @@ --- --- Copyright 2017 Goldman Sachs. --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, --- software distributed under the License is distributed on an --- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY --- KIND, either express or implied. See the License for the --- specific language governing permissions and limitations --- under the License. --- - -DROP VIEW VIEW1 -GO - - -DROP TABLE METADATA_TEST_TABLE -GO - -DROP TABLE TABLE_B_WITH_FK -GO - -DROP TABLE TABLE_A -GO - -DROP TABLE TABLE_A_ROOT -GO - -DROP TABLE TABLE_B_WITH_MULTICOL_FK -GO - -DROP TABLE TABLE_A_MULTICOL_PK -GO - -DROP TABLE TABLE_GENERATED_ID -GO - - - -DROP TABLE INVALID_TABLE -GO - -DROP VIEW INVALID_VIEW -GO - - -DROP SEQUENCE REGULAR_SEQUENCE -GO - - -DROP PROCEDURE SP_WITH_OVERLOAD (INT, VARCHAR(32)) -GO -DROP PROCEDURE SP_WITH_OVERLOAD (INT) -GO -DROP PROCEDURE SP_WITH_OVERLOAD () -GO -DROP FUNCTION FUNC_WITH_OVERLOAD (INT, VARCHAR(32)) -GO -DROP FUNCTION FUNC_WITH_OVERLOAD (INT) -GO -DROP FUNCTION FUNC_WITH_OVERLOAD () -GO -DROP PROCEDURE SP1 () -GO -DROP FUNCTION FUNC1 () -GO +-- +-- Copyright 2017 Goldman Sachs. +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. +-- + +DROP VIEW VIEW1 +GO + + +DROP TABLE METADATA_TEST_TABLE +GO + +DROP TABLE TABLE_B_WITH_FK +GO + +DROP TABLE TABLE_A +GO + +DROP TABLE TABLE_A_ROOT +GO + +DROP TABLE TABLE_B_WITH_MULTICOL_FK +GO + +DROP TABLE TABLE_A_MULTICOL_PK +GO + +DROP TABLE TABLE_GENERATED_ID +GO + + + +DROP TABLE INVALID_TABLE +GO + +DROP VIEW INVALID_VIEW +GO + + +DROP SEQUENCE REGULAR_SEQUENCE +GO + + +DROP PROCEDURE SP_WITH_OVERLOAD (INT, VARCHAR(32)) +GO +DROP PROCEDURE SP_WITH_OVERLOAD (INT) +GO +DROP PROCEDURE SP_WITH_OVERLOAD () +GO +DROP FUNCTION FUNC_WITH_OVERLOAD (INT, VARCHAR(32)) +GO +DROP FUNCTION FUNC_WITH_OVERLOAD (INT) +GO +DROP FUNCTION FUNC_WITH_OVERLOAD () +GO +DROP PROCEDURE SP1 () +GO +DROP FUNCTION FUNC1 () +GO +DROP TYPE MyType +GO +DROP TYPE MyType2 +GO diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/postgresql-test.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/postgresql-test.sql index b0e7bd45..552eadbf 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/postgresql-test.sql +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/postgresql-test.sql @@ -1,103 +1,108 @@ --- --- Copyright 2017 Goldman Sachs. --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, --- software distributed under the License is distributed on an --- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY --- KIND, either express or implied. See the License for the --- specific language governing permissions and limitations --- under the License. --- - -create table METADATA_TEST_TABLE (afield int, bfield int) -GO - -create table TABLE_A ( - A_ID INT NOT NULL, - A2_ID INT, - PRIMARY KEY (A_ID) -) -GO - - -create table TABLE_A_MULTICOL_PK ( - A1_ID INT NOT NULL, - A2_ID INT NOT NULL, - VAL3 INT, - PRIMARY KEY (A1_ID, A2_ID) -) -GO -create table TABLE_B_WITH_MULTICOL_FK ( - B_ID INT NOT NULL, - OTHER_A1_ID INT, - OTHER_A2_ID INT, - PRIMARY KEY (B_ID) -) -GO -ALTER TABLE TABLE_B_WITH_MULTICOL_FK ADD CONSTRAINT FK_A_MULTICOL FOREIGN KEY (OTHER_A1_ID, OTHER_A2_ID) REFERENCES TABLE_A_MULTICOL_PK(A1_ID, A2_ID) -GO - -create table TABLE_B_WITH_FK ( - B_ID INT NOT NULL, - OTHER_A_ID INT, - PRIMARY KEY (B_ID) -) -GO -ALTER TABLE TABLE_B_WITH_FK ADD CONSTRAINT FK_A FOREIGN KEY (OTHER_A_ID) REFERENCES TABLE_A(A_ID) -GO - -create table TABLE_GENERATED_ID ( - GEN_ID SERIAL, - FIELD1 INT -) -GO - - - -CREATE VIEW VIEW1 AS SELECT * FROM METADATA_TEST_TABLE --- my comment -GO - - --- Postgresql does not allow dropping objects that have dependencies, so the invalid view test is not applicable - - -CREATE SEQUENCE REGULAR_SEQUENCE -GO - - -CREATE OR REPLACE FUNCTION FUNC1 () RETURNS INT AS $$ -BEGIN - -- ensure that func comment remains - RETURN 1; -END; -$$ LANGUAGE plpgsql; -GO - -CREATE FUNCTION FUNC_WITH_OVERLOAD () RETURNS INT AS $$ -BEGIN - RETURN 1; -END; -$$ LANGUAGE plpgsql; -GO - -CREATE FUNCTION FUNC_WITH_OVERLOAD (var1 integer) RETURNS INT AS $$ -BEGIN - RETURN 1; -END; -$$ LANGUAGE plpgsql; -GO - -CREATE FUNCTION FUNC_WITH_OVERLOAD (var1 integer, IN INVALSTR VARCHAR(32)) RETURNS INT AS $$ -BEGIN - RETURN 1; -END; -$$ LANGUAGE plpgsql; -GO - - +-- +-- Copyright 2017 Goldman Sachs. +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. +-- + +CREATE TYPE MyType AS ENUM ('1', '2', '3') +GO +CREATE TYPE MyType2 AS ENUM ('1', '2', '3') +GO + +create table METADATA_TEST_TABLE (afield int, bfield int) +GO + +create table TABLE_A ( + A_ID INT NOT NULL, + A2_ID INT, + PRIMARY KEY (A_ID) +) +GO + + +create table TABLE_A_MULTICOL_PK ( + A1_ID INT NOT NULL, + A2_ID INT NOT NULL, + VAL3 INT, + PRIMARY KEY (A1_ID, A2_ID) +) +GO +create table TABLE_B_WITH_MULTICOL_FK ( + B_ID INT NOT NULL, + OTHER_A1_ID INT, + OTHER_A2_ID INT, + PRIMARY KEY (B_ID) +) +GO +ALTER TABLE TABLE_B_WITH_MULTICOL_FK ADD CONSTRAINT FK_A_MULTICOL FOREIGN KEY (OTHER_A1_ID, OTHER_A2_ID) REFERENCES TABLE_A_MULTICOL_PK(A1_ID, A2_ID) +GO + +create table TABLE_B_WITH_FK ( + B_ID INT NOT NULL, + OTHER_A_ID INT, + PRIMARY KEY (B_ID) +) +GO +ALTER TABLE TABLE_B_WITH_FK ADD CONSTRAINT FK_A FOREIGN KEY (OTHER_A_ID) REFERENCES TABLE_A(A_ID) +GO + +create table TABLE_GENERATED_ID ( + GEN_ID SERIAL, + FIELD1 INT +) +GO + + + +CREATE VIEW VIEW1 AS SELECT * FROM METADATA_TEST_TABLE +-- my comment +GO + + +-- Postgresql does not allow dropping objects that have dependencies, so the invalid view test is not applicable + + +CREATE SEQUENCE REGULAR_SEQUENCE +GO + + +CREATE OR REPLACE FUNCTION FUNC1 () RETURNS INT AS $$ +BEGIN + -- ensure that func comment remains + RETURN 1; +END; +$$ LANGUAGE plpgsql; +GO + +CREATE FUNCTION FUNC_WITH_OVERLOAD () RETURNS INT AS $$ +BEGIN + RETURN 1; +END; +$$ LANGUAGE plpgsql; +GO + +CREATE FUNCTION FUNC_WITH_OVERLOAD (var1 integer) RETURNS INT AS $$ +BEGIN + RETURN 1; +END; +$$ LANGUAGE plpgsql; +GO + +CREATE FUNCTION FUNC_WITH_OVERLOAD (var1 integer, IN INVALSTR VARCHAR(32)) RETURNS INT AS $$ +BEGIN + RETURN 1; +END; +$$ LANGUAGE plpgsql; +GO + + diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/expected/myschema01/sp/sp1.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/expected/myschema01/sp/sp1.sql new file mode 100644 index 00000000..4085efd9 --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/expected/myschema01/sp/sp1.sql @@ -0,0 +1,7 @@ +CREATE PROCEDURE sp1() + LANGUAGE plpgsql + AS $$ DECLARE val INTEGER; END $$; + + + +GO \ No newline at end of file diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/expected/myschema01/usertype/usertype1.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/expected/myschema01/usertype/usertype1.sql new file mode 100644 index 00000000..ccbd3070 --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/expected/myschema01/usertype/usertype1.sql @@ -0,0 +1,9 @@ +CREATE TYPE usertype1 AS ENUM ( + '1', + '2', + '3' +); + + + +GO \ No newline at end of file diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/input/input-noschemaqualifier.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/input/input-noschemaqualifier.sql new file mode 100644 index 00000000..3d27f6a5 --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/input/input-noschemaqualifier.sql @@ -0,0 +1,265 @@ +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 9.6.2 +-- Dumped by pg_dump version 9.6.3 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SET check_function_bodies = false; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- Name: myschema01; Type: SCHEMA; Schema: -; Owner: - +-- + +CREATE SCHEMA myschema01; + + +SET search_path = myschema01, pg_catalog; + + +-- +-- Name: usertype0; Type: TYPE; Schema: mylargeschema; Owner: - +-- + +CREATE TYPE myschema01.usertype1 AS ENUM ( + '1', + '2', + '3' +); + + +-- +-- Name: sp0(); Type: PROCEDURE; Schema: mylargeschema; Owner: - +-- + +CREATE PROCEDURE sp1() + LANGUAGE plpgsql + AS $$ DECLARE val INTEGER; END $$; + + +-- +-- Name: func1(); Type: FUNCTION; Schema: myschema01; Owner: - +-- + +CREATE FUNCTION func1() RETURNS integer + LANGUAGE plpgsql + AS ' +BEGIN + -- ensure that func comment remains + RETURN 1; +END; +'; + + +-- +-- Name: func_with_overload(); Type: FUNCTION; Schema: myschema01; Owner: - +-- + +CREATE FUNCTION func_with_overload() RETURNS integer + LANGUAGE plpgsql + AS ' +BEGIN + RETURN 1; +END; +'; + + +-- +-- Name: func_with_overload(integer); Type: FUNCTION; Schema: myschema01; Owner: - +-- + +CREATE FUNCTION func_with_overload(var1 integer) RETURNS integer + LANGUAGE plpgsql + AS ' +BEGIN + RETURN 1; +END; +'; + + +-- +-- Name: func_with_overload(integer, character varying); Type: FUNCTION; Schema: myschema01; Owner: - +-- + +CREATE FUNCTION func_with_overload(var1 integer, invalstr character varying) RETURNS integer + LANGUAGE plpgsql + AS ' +BEGIN + RETURN 1; +END; +'; + + +SET default_tablespace = ''; + +SET default_with_oids = false; + +-- +-- Name: metadata_test_table; Type: TABLE; Schema: myschema01; Owner: - +-- + +CREATE TABLE metadata_test_table ( + afield integer, + bfield integer +); + + +-- +-- Name: regular_sequence; Type: SEQUENCE; Schema: myschema01; Owner: - +-- + +CREATE SEQUENCE regular_sequence + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: table_a; Type: TABLE; Schema: myschema01; Owner: - +-- + +CREATE TABLE table_a ( + a_id integer NOT NULL, + a2_id integer +); + + +-- +-- Name: table_a_multicol_pk; Type: TABLE; Schema: myschema01; Owner: - +-- + +CREATE TABLE table_a_multicol_pk ( + a1_id integer NOT NULL, + a2_id integer NOT NULL, + val3 integer +); + + +-- +-- Name: table_b_with_fk; Type: TABLE; Schema: myschema01; Owner: - +-- + +CREATE TABLE table_b_with_fk ( + b_id integer NOT NULL, + other_a_id integer +); + + +-- +-- Name: table_b_with_multicol_fk; Type: TABLE; Schema: myschema01; Owner: - +-- + +CREATE TABLE table_b_with_multicol_fk ( + b_id integer NOT NULL, + other_a1_id integer, + other_a2_id integer +); + + +-- +-- Name: table_generated_id; Type: TABLE; Schema: myschema01; Owner: - +-- + +CREATE TABLE table_generated_id ( + gen_id integer NOT NULL, + field1 integer +); + + +-- +-- Name: table_generated_id_gen_id_seq; Type: SEQUENCE; Schema: myschema01; Owner: - +-- + +CREATE SEQUENCE table_generated_id_gen_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: table_generated_id_gen_id_seq; Type: SEQUENCE OWNED BY; Schema: myschema01; Owner: - +-- + +ALTER SEQUENCE myschema01.table_generated_id_gen_id_seq OWNED BY myschema01.table_generated_id.gen_id; + + +-- +-- Name: view1; Type: VIEW; Schema: myschema01; Owner: - +-- + +CREATE VIEW view1 AS + SELECT metadata_test_table.afield, + metadata_test_table.bfield + FROM metadata_test_table; + + +-- +-- Name: table_generated_id gen_id; Type: DEFAULT; Schema: myschema01; Owner: - +-- + +ALTER TABLE ONLY table_generated_id ALTER COLUMN gen_id SET DEFAULT nextval('table_generated_id_gen_id_seq'::regclass); + + +-- +-- Name: table_a_multicol_pk table_a_multicol_pk_pkey; Type: CONSTRAINT; Schema: myschema01; Owner: - +-- + +ALTER TABLE ONLY table_a_multicol_pk + ADD CONSTRAINT table_a_multicol_pk_pkey PRIMARY KEY (a1_id, a2_id); + + +-- +-- Name: table_a table_a_pkey; Type: CONSTRAINT; Schema: myschema01; Owner: - +-- + +ALTER TABLE ONLY table_a + ADD CONSTRAINT table_a_pkey PRIMARY KEY (a_id); + + +-- +-- Name: table_b_with_fk table_b_with_fk_pkey; Type: CONSTRAINT; Schema: myschema01; Owner: - +-- + +ALTER TABLE ONLY table_b_with_fk + ADD CONSTRAINT table_b_with_fk_pkey PRIMARY KEY (b_id); + + +-- +-- Name: table_b_with_multicol_fk table_b_with_multicol_fk_pkey; Type: CONSTRAINT; Schema: myschema01; Owner: - +-- + +ALTER TABLE ONLY table_b_with_multicol_fk + ADD CONSTRAINT table_b_with_multicol_fk_pkey PRIMARY KEY (b_id); + + +-- +-- Name: table_b_with_fk fk_a; Type: FK CONSTRAINT; Schema: myschema01; Owner: - +-- + +ALTER TABLE ONLY table_b_with_fk + ADD CONSTRAINT fk_a FOREIGN KEY (other_a_id) REFERENCES table_a(a_id); + + +-- +-- Name: table_b_with_multicol_fk fk_a_multicol; Type: FK CONSTRAINT; Schema: myschema01; Owner: - +-- + +ALTER TABLE ONLY table_b_with_multicol_fk + ADD CONSTRAINT fk_a_multicol FOREIGN KEY (other_a1_id, other_a2_id) REFERENCES table_a_multicol_pk(a1_id, a2_id); + + +-- +-- PostgreSQL database dump complete +-- + diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/input/input.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/input/input.sql index 01916509..f89b471e 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/input/input.sql +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/reveng/pgdump/input/input.sql @@ -23,11 +23,32 @@ CREATE SCHEMA myschema01; SET search_path = myschema01, pg_catalog; + +-- +-- Name: usertype0; Type: TYPE; Schema: mylargeschema; Owner: - +-- + +CREATE TYPE myschema01.usertype1 AS ENUM ( + '1', + '2', + '3' +); + + +-- +-- Name: sp0(); Type: PROCEDURE; Schema: mylargeschema; Owner: - +-- + +CREATE PROCEDURE myschema01.sp1() + LANGUAGE plpgsql + AS $$ DECLARE val INTEGER; END $$; + + -- -- Name: func1(); Type: FUNCTION; Schema: myschema01; Owner: - -- -CREATE FUNCTION func1() RETURNS integer +CREATE FUNCTION myschema01.func1() RETURNS integer LANGUAGE plpgsql AS ' BEGIN @@ -41,7 +62,7 @@ END; -- Name: func_with_overload(); Type: FUNCTION; Schema: myschema01; Owner: - -- -CREATE FUNCTION func_with_overload() RETURNS integer +CREATE FUNCTION myschema01.func_with_overload() RETURNS integer LANGUAGE plpgsql AS ' BEGIN @@ -54,7 +75,7 @@ END; -- Name: func_with_overload(integer); Type: FUNCTION; Schema: myschema01; Owner: - -- -CREATE FUNCTION func_with_overload(var1 integer) RETURNS integer +CREATE FUNCTION myschema01.func_with_overload(var1 integer) RETURNS integer LANGUAGE plpgsql AS ' BEGIN @@ -67,7 +88,7 @@ END; -- Name: func_with_overload(integer, character varying); Type: FUNCTION; Schema: myschema01; Owner: - -- -CREATE FUNCTION func_with_overload(var1 integer, invalstr character varying) RETURNS integer +CREATE FUNCTION myschema01.func_with_overload(var1 integer, invalstr character varying) RETURNS integer LANGUAGE plpgsql AS ' BEGIN @@ -84,7 +105,7 @@ SET default_with_oids = false; -- Name: metadata_test_table; Type: TABLE; Schema: myschema01; Owner: - -- -CREATE TABLE metadata_test_table ( +CREATE TABLE myschema01.metadata_test_table ( afield integer, bfield integer ); @@ -94,7 +115,7 @@ CREATE TABLE metadata_test_table ( -- Name: regular_sequence; Type: SEQUENCE; Schema: myschema01; Owner: - -- -CREATE SEQUENCE regular_sequence +CREATE SEQUENCE myschema01.regular_sequence START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -106,7 +127,7 @@ CREATE SEQUENCE regular_sequence -- Name: table_a; Type: TABLE; Schema: myschema01; Owner: - -- -CREATE TABLE table_a ( +CREATE TABLE myschema01.table_a ( a_id integer NOT NULL, a2_id integer ); @@ -116,7 +137,7 @@ CREATE TABLE table_a ( -- Name: table_a_multicol_pk; Type: TABLE; Schema: myschema01; Owner: - -- -CREATE TABLE table_a_multicol_pk ( +CREATE TABLE myschema01.table_a_multicol_pk ( a1_id integer NOT NULL, a2_id integer NOT NULL, val3 integer @@ -127,7 +148,7 @@ CREATE TABLE table_a_multicol_pk ( -- Name: table_b_with_fk; Type: TABLE; Schema: myschema01; Owner: - -- -CREATE TABLE table_b_with_fk ( +CREATE TABLE myschema01.table_b_with_fk ( b_id integer NOT NULL, other_a_id integer ); @@ -137,7 +158,7 @@ CREATE TABLE table_b_with_fk ( -- Name: table_b_with_multicol_fk; Type: TABLE; Schema: myschema01; Owner: - -- -CREATE TABLE table_b_with_multicol_fk ( +CREATE TABLE myschema01.table_b_with_multicol_fk ( b_id integer NOT NULL, other_a1_id integer, other_a2_id integer @@ -148,7 +169,7 @@ CREATE TABLE table_b_with_multicol_fk ( -- Name: table_generated_id; Type: TABLE; Schema: myschema01; Owner: - -- -CREATE TABLE table_generated_id ( +CREATE TABLE myschema01.table_generated_id ( gen_id integer NOT NULL, field1 integer ); @@ -158,7 +179,7 @@ CREATE TABLE table_generated_id ( -- Name: table_generated_id_gen_id_seq; Type: SEQUENCE; Schema: myschema01; Owner: - -- -CREATE SEQUENCE table_generated_id_gen_id_seq +CREATE SEQUENCE myschema01.table_generated_id_gen_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -170,31 +191,31 @@ CREATE SEQUENCE table_generated_id_gen_id_seq -- Name: table_generated_id_gen_id_seq; Type: SEQUENCE OWNED BY; Schema: myschema01; Owner: - -- -ALTER SEQUENCE table_generated_id_gen_id_seq OWNED BY table_generated_id.gen_id; +ALTER SEQUENCE myschema01.table_generated_id_gen_id_seq OWNED BY myschema01.table_generated_id.gen_id; -- -- Name: view1; Type: VIEW; Schema: myschema01; Owner: - -- -CREATE VIEW view1 AS +CREATE VIEW myschema01.view1 AS SELECT metadata_test_table.afield, metadata_test_table.bfield - FROM metadata_test_table; + FROM myschema01.metadata_test_table; -- -- Name: table_generated_id gen_id; Type: DEFAULT; Schema: myschema01; Owner: - -- -ALTER TABLE ONLY table_generated_id ALTER COLUMN gen_id SET DEFAULT nextval('table_generated_id_gen_id_seq'::regclass); +ALTER TABLE ONLY myschema01.table_generated_id ALTER COLUMN gen_id SET DEFAULT nextval('table_generated_id_gen_id_seq'::regclass); -- -- Name: table_a_multicol_pk table_a_multicol_pk_pkey; Type: CONSTRAINT; Schema: myschema01; Owner: - -- -ALTER TABLE ONLY table_a_multicol_pk +ALTER TABLE ONLY myschema01.table_a_multicol_pk ADD CONSTRAINT table_a_multicol_pk_pkey PRIMARY KEY (a1_id, a2_id); @@ -202,7 +223,7 @@ ALTER TABLE ONLY table_a_multicol_pk -- Name: table_a table_a_pkey; Type: CONSTRAINT; Schema: myschema01; Owner: - -- -ALTER TABLE ONLY table_a +ALTER TABLE ONLY myschema01.table_a ADD CONSTRAINT table_a_pkey PRIMARY KEY (a_id); @@ -210,7 +231,7 @@ ALTER TABLE ONLY table_a -- Name: table_b_with_fk table_b_with_fk_pkey; Type: CONSTRAINT; Schema: myschema01; Owner: - -- -ALTER TABLE ONLY table_b_with_fk +ALTER TABLE ONLY myschema01.table_b_with_fk ADD CONSTRAINT table_b_with_fk_pkey PRIMARY KEY (b_id); @@ -218,7 +239,7 @@ ALTER TABLE ONLY table_b_with_fk -- Name: table_b_with_multicol_fk table_b_with_multicol_fk_pkey; Type: CONSTRAINT; Schema: myschema01; Owner: - -- -ALTER TABLE ONLY table_b_with_multicol_fk +ALTER TABLE ONLY myschema01.table_b_with_multicol_fk ADD CONSTRAINT table_b_with_multicol_fk_pkey PRIMARY KEY (b_id); @@ -226,7 +247,7 @@ ALTER TABLE ONLY table_b_with_multicol_fk -- Name: table_b_with_fk fk_a; Type: FK CONSTRAINT; Schema: myschema01; Owner: - -- -ALTER TABLE ONLY table_b_with_fk +ALTER TABLE ONLY myschema01.table_b_with_fk ADD CONSTRAINT fk_a FOREIGN KEY (other_a_id) REFERENCES table_a(a_id); @@ -234,7 +255,7 @@ ALTER TABLE ONLY table_b_with_fk -- Name: table_b_with_multicol_fk fk_a_multicol; Type: FK CONSTRAINT; Schema: myschema01; Owner: - -- -ALTER TABLE ONLY table_b_with_multicol_fk +ALTER TABLE ONLY myschema01.table_b_with_multicol_fk ADD CONSTRAINT fk_a_multicol FOREIGN KEY (other_a1_id, other_a2_id) REFERENCES table_a_multicol_pk(a1_id, a2_id); diff --git a/obevo-db/src/main/java/com/gs/obevo/db/api/platform/DbPlatform.java b/obevo-db/src/main/java/com/gs/obevo/db/api/platform/DbPlatform.java index 0aa5c57d..e1c2e545 100644 --- a/obevo-db/src/main/java/com/gs/obevo/db/api/platform/DbPlatform.java +++ b/obevo-db/src/main/java/com/gs/obevo/db/api/platform/DbPlatform.java @@ -71,6 +71,12 @@ public interface DbPlatform extends Platform { */ String getSubschemaPrefix(PhysicalSchema schema); + /** + * The token to use to indicate a null field when creating columns in a table. Some platforms use the NULL keyword, + * and others imply a lack of keyword (e.g. "") as null. + * + * @since 6.0.0 + */ String getNullMarkerForCreateTable(); String getTimestampType(); diff --git a/obevo-db/src/main/java/com/gs/obevo/db/apps/reveng/AbstractDdlReveng.java b/obevo-db/src/main/java/com/gs/obevo/db/apps/reveng/AbstractDdlReveng.java index 5f3bc07b..a8ba9f8b 100644 --- a/obevo-db/src/main/java/com/gs/obevo/db/apps/reveng/AbstractDdlReveng.java +++ b/obevo-db/src/main/java/com/gs/obevo/db/apps/reveng/AbstractDdlReveng.java @@ -161,23 +161,24 @@ private static String nameWithPrefixPattern(String startQuoteStr, String endQuot public void reveng(AquaRevengArgs args) { if (args.getInputPath() == null) { File interimDir = new File(args.getOutputPath(), "interim"); + System.out.println(); boolean proceedWithReveng = doRevengOrInstructions(System.out, args, interimDir); - System.out.println(""); - System.out.println(""); + System.out.println(); + System.out.println(); if (proceedWithReveng) { System.out.println("Interim reverse-engineering from the vendor tool is complete."); System.out.println("Content was written to: " + interimDir); System.out.println("Proceeding with full reverse-engineering: " + interimDir); - System.out.println(""); + System.out.println(); System.out.println("*** In case the interim content had issues when reverse-engineering to the final output, you can update the interim files and restart from there (without going back to the DB) by specifying the following argument:"); System.out.println(" -inputPath " + ObjectUtils.defaultIfNull(args.getOutputPath(), "")); revengMain(interimDir, args); } else { System.out.println("***********"); - System.out.println(""); + System.out.println(); System.out.println("Once those steps are done, rerun the reverse-engineering command you just ran, but add the following argument based on the value passed in above the argument:"); System.out.println(" -inputPath " + ObjectUtils.defaultIfNull(args.getOutputPath(), "")); - System.out.println(""); + System.out.println(); System.out.println("If you need more information on the vendor reverse engineer process, see the doc: https://goldmansachs.github.io/obevo/reverse-engineer-dbmstools.html"); } } else { diff --git a/obevo-dbmetadata-impl/src/main/java/com/gs/obevo/dbmetadata/impl/dialects/PostgresqlMetadataDialect.java b/obevo-dbmetadata-impl/src/main/java/com/gs/obevo/dbmetadata/impl/dialects/PostgresqlMetadataDialect.java index 238d0413..8d7c9830 100644 --- a/obevo-dbmetadata-impl/src/main/java/com/gs/obevo/dbmetadata/impl/dialects/PostgresqlMetadataDialect.java +++ b/obevo-dbmetadata-impl/src/main/java/com/gs/obevo/dbmetadata/impl/dialects/PostgresqlMetadataDialect.java @@ -1,128 +1,150 @@ -/** - * Copyright 2017 Goldman Sachs. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package com.gs.obevo.dbmetadata.impl.dialects; - -import java.sql.Connection; -import java.sql.SQLException; -import java.util.Map; - -import com.gs.obevo.api.appdata.PhysicalSchema; -import com.gs.obevo.dbmetadata.api.DaExtension; -import com.gs.obevo.dbmetadata.api.DaExtensionImpl; -import com.gs.obevo.dbmetadata.api.DaRoutineType; -import org.apache.commons.dbutils.handlers.ColumnListHandler; -import org.apache.commons.dbutils.handlers.MapListHandler; -import org.eclipse.collections.api.block.function.Function; -import org.eclipse.collections.api.list.ImmutableList; -import org.eclipse.collections.api.set.ImmutableSet; -import org.eclipse.collections.impl.block.factory.StringFunctions; -import org.eclipse.collections.impl.factory.Lists; -import org.eclipse.collections.impl.factory.Sets; -import org.eclipse.collections.impl.list.mutable.ListAdapter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import schemacrawler.schema.RoutineType; -import schemacrawler.schemacrawler.DatabaseSpecificOverrideOptionsBuilder; -import schemacrawler.schemacrawler.SchemaCrawlerOptions; - -public class PostgresqlMetadataDialect extends AbstractMetadataDialect { - private static final Logger LOG = LoggerFactory.getLogger(OracleMetadataDialect.class); - - @Override - public void customEdits(SchemaCrawlerOptions options, Connection conn) { - // postgresql only supports FUNCTIONs in its syntax, not PROCEDUREs. However, the metadata still comes - // back as procedure. We override the metadata value using the getRoutineOverrideValue method. - options.setRoutineTypes(Lists.immutable.with(RoutineType.procedure).castToList()); - } - - @Override - public DatabaseSpecificOverrideOptionsBuilder getDbSpecificOptionsBuilder(Connection conn, PhysicalSchema physicalSchema, boolean searchAllTables) { - DatabaseSpecificOverrideOptionsBuilder dbSpecificOptionsBuilder = super.getDbSpecificOptionsBuilder(conn, physicalSchema, searchAllTables); - - String sequenceSql = getSequenceSql(physicalSchema); - if (sequenceSql != null) { - // if null, then setting the sequences object to null won't help either - dbSpecificOptionsBuilder.withInformationSchemaViews().withSequencesSql(sequenceSql); - } - - return dbSpecificOptionsBuilder; - } - - /** - * Gets the sequence SQL for the JDBC metadata. - * Protected visibility as subclasses may need to override. - */ - protected String getSequenceSql(PhysicalSchema physicalSchema) { - return "SELECT\n" + - " NULL AS SEQUENCE_CATALOG,\n" + - " SEQUENCE_SCHEMA,\n" + - " SEQUENCE_NAME,\n" + - " INCREMENT,\n" + - " MINIMUM_VALUE,\n" + - " MAXIMUM_VALUE,\n" + - " CYCLE_OPTION\n" + - "FROM\n" + - " INFORMATION_SCHEMA.SEQUENCES\n" + - "WHERE SEQUENCE_SCHEMA = '" + physicalSchema.getPhysicalName() + "'\n" + - "ORDER BY\n" + - " SEQUENCE_CATALOG,\n" + - " SEQUENCE_SCHEMA,\n" + - " SEQUENCE_NAME\n"; - } - - @Override - public String getSchemaExpression(PhysicalSchema physicalSchema) { - return "(?i)" + physicalSchema.getPhysicalName(); - } - - /** - * PostgreSQL should override the routine type to "function". PostgreSQL only supports functions in its SQL syntax; - * however, the JDBC metadata returns it as a "procedure". For consistency w/ the SQL syntax, we do this override. - */ - @Override - public DaRoutineType getRoutineOverrideValue() { - return DaRoutineType.function; - } - - @Override - public ImmutableSet getExtensionsOptional(Connection conn) throws SQLException { - final String sql = "SELECT DISTINCT EXTNAME FROM PG_EXTENSION"; - LOG.debug("Executing extension metadata query SQL: {}", sql); - - ImmutableList> maps = ListAdapter.adapt(jdbc.query(conn, sql, new MapListHandler())).toImmutable(); - - if (LOG.isDebugEnabled()) { - LOG.debug("Results:"); - for (Map map : maps) { - LOG.debug("ROW: {}", map.toString()); - } - } - - return maps.collect(new Function, DaExtension>() { - @Override - public DaExtension valueOf(Map map) { - return new DaExtensionImpl((String) map.get("EXTNAME")); - } - }).toSet().toImmutable(); - } - - @Override - public ImmutableSet getGroupNamesOptional(Connection conn, PhysicalSchema physicalSchema) throws SQLException { - return Sets.immutable - .withAll(jdbc.query(conn, "select rolname from pg_roles", new ColumnListHandler())) - .collect(StringFunctions.trim()); - } -} +/** + * Copyright 2017 Goldman Sachs. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.gs.obevo.dbmetadata.impl.dialects; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Map; + +import com.gs.obevo.api.appdata.PhysicalSchema; +import com.gs.obevo.dbmetadata.api.DaExtension; +import com.gs.obevo.dbmetadata.api.DaExtensionImpl; +import com.gs.obevo.dbmetadata.api.DaRoutineType; +import com.gs.obevo.dbmetadata.api.DaSchema; +import com.gs.obevo.dbmetadata.api.DaUserType; +import com.gs.obevo.dbmetadata.api.DaUserTypeImpl; +import org.apache.commons.dbutils.handlers.ColumnListHandler; +import org.apache.commons.dbutils.handlers.MapListHandler; +import org.eclipse.collections.api.block.function.Function; +import org.eclipse.collections.api.collection.ImmutableCollection; +import org.eclipse.collections.api.list.ImmutableList; +import org.eclipse.collections.api.set.ImmutableSet; +import org.eclipse.collections.impl.block.factory.StringFunctions; +import org.eclipse.collections.impl.factory.Lists; +import org.eclipse.collections.impl.factory.Sets; +import org.eclipse.collections.impl.list.mutable.ListAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import schemacrawler.schema.RoutineType; +import schemacrawler.schemacrawler.DatabaseSpecificOverrideOptionsBuilder; +import schemacrawler.schemacrawler.SchemaCrawlerOptions; + +public class PostgresqlMetadataDialect extends AbstractMetadataDialect { + private static final Logger LOG = LoggerFactory.getLogger(OracleMetadataDialect.class); + + @Override + public void customEdits(SchemaCrawlerOptions options, Connection conn) { + // postgresql only supports FUNCTIONs in its syntax, not PROCEDUREs. However, the metadata still comes + // back as procedure. We override the metadata value using the getRoutineOverrideValue method. + options.setRoutineTypes(Lists.immutable.with(RoutineType.procedure).castToList()); + } + + @Override + public DatabaseSpecificOverrideOptionsBuilder getDbSpecificOptionsBuilder(Connection conn, PhysicalSchema physicalSchema, boolean searchAllTables) { + DatabaseSpecificOverrideOptionsBuilder dbSpecificOptionsBuilder = super.getDbSpecificOptionsBuilder(conn, physicalSchema, searchAllTables); + + String sequenceSql = getSequenceSql(physicalSchema); + if (sequenceSql != null) { + // if null, then setting the sequences object to null won't help either + dbSpecificOptionsBuilder.withInformationSchemaViews().withSequencesSql(sequenceSql); + } + + return dbSpecificOptionsBuilder; + } + + /** + * Gets the sequence SQL for the JDBC metadata. + * Protected visibility as subclasses may need to override. + */ + protected String getSequenceSql(PhysicalSchema physicalSchema) { + return "SELECT\n" + + " NULL AS SEQUENCE_CATALOG,\n" + + " SEQUENCE_SCHEMA,\n" + + " SEQUENCE_NAME,\n" + + " INCREMENT,\n" + + " MINIMUM_VALUE,\n" + + " MAXIMUM_VALUE,\n" + + " CYCLE_OPTION\n" + + "FROM\n" + + " INFORMATION_SCHEMA.SEQUENCES\n" + + "WHERE SEQUENCE_SCHEMA = '" + physicalSchema.getPhysicalName() + "'\n" + + "ORDER BY\n" + + " SEQUENCE_CATALOG,\n" + + " SEQUENCE_SCHEMA,\n" + + " SEQUENCE_NAME\n"; + } + + @Override + public String getSchemaExpression(PhysicalSchema physicalSchema) { + return "(?i)" + physicalSchema.getPhysicalName(); + } + + /** + * PostgreSQL should override the routine type to "function". PostgreSQL only supports functions in its SQL syntax; + * however, the JDBC metadata returns it as a "procedure". For consistency w/ the SQL syntax, we do this override. + */ + @Override + public DaRoutineType getRoutineOverrideValue() { + return DaRoutineType.function; + } + + @Override + public ImmutableSet getExtensionsOptional(Connection conn) throws SQLException { + final String sql = "SELECT DISTINCT EXTNAME FROM PG_EXTENSION"; + LOG.debug("Executing extension metadata query SQL: {}", sql); + + ImmutableList> maps = ListAdapter.adapt(jdbc.query(conn, sql, new MapListHandler())).toImmutable(); + + if (LOG.isDebugEnabled()) { + LOG.debug("Results:"); + for (Map map : maps) { + LOG.debug("ROW: {}", map.toString()); + } + } + + return maps.collect(new Function, DaExtension>() { + @Override + public DaExtension valueOf(Map map) { + return new DaExtensionImpl((String) map.get("EXTNAME")); + } + }).toSet().toImmutable(); + } + + @Override + public ImmutableCollection searchUserTypes(final DaSchema schema, Connection conn) { + String sql = "SELECT t.typname \n" + + "FROM pg_type t \n" + + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace \n" + + "WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) \n" + + "AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n" + + "AND n.nspname IN ('" + schema.getName() + "')"; + ImmutableList> maps = ListAdapter.adapt(jdbc.query(conn, sql, new MapListHandler())).toImmutable(); + + return maps.collect(new Function, DaUserType>() { + @Override + public DaUserType valueOf(Map map) { + return new DaUserTypeImpl((String) map.get("typname"), schema); + } + }); + } + + @Override + public ImmutableSet getGroupNamesOptional(Connection conn, PhysicalSchema physicalSchema) throws SQLException { + return Sets.immutable + .withAll(jdbc.query(conn, "select rolname from pg_roles", new ColumnListHandler())) + .collect(StringFunctions.trim()); + } +} From 4e78af63b51eafe06ec4ca65577fd4b8179efe5c Mon Sep 17 00:00:00 2001 From: shantstepanian <17996546+shantstepanian@users.noreply.github.com> Date: Sat, 23 Mar 2019 15:49:52 -0400 Subject: [PATCH 5/5] Supporting postgres in-memory db translation for HSQL --- CHANGELOG.md | 3 + .../obevo-db-postgresql.iml | 4 + obevo-db-impls/obevo-db-postgresql/pom.xml | 15 + .../postgresql/PostgreSqlDbPlatform.java | 11 + .../postgresql/PostgreSqlPgDumpReveng.java | 3 +- .../PostgreSqlToH2TranslationDialect.java | 27 + .../PostgreSqlToHsqlTranslationDialect.java | 92 +++ .../PostgreSqlInMemConversionTest.java | 53 ++ .../example1/step1/schema1/table/TABLE_A.ddl | 58 +- .../example1/step1/schema1/table/TABLE_B.ddl | 10 +- .../step1/schema1/table/TABLE_SPECIAL_COL.ddl | 2 +- .../step1/schema1/table/TAB_WITH_SEQ.ddl | 16 +- .../step1/schema1/usertype/usertype0.hsql.sql | 3 + .../step1/schema1/usertype/usertype0.sql | 1 + .../example1/step1/system-config-inmem.xml | 27 + .../example1/step2/schema1/table/TABLE_A.ddl | 64 +- .../example1/step2/schema1/table/TABLE_B.ddl | 10 +- .../step2/schema1/table/TABLE_SPECIAL_COL.ddl | 2 +- .../step2/schema1/table/TAB_WITH_SEQ.ddl | 16 +- .../step2/schema1/usertype/usertype0.hsql.sql | 3 + .../step2/schema1/usertype/usertype0.sql | 1 + .../example1/step2/system-config-inmem.xml | 27 + .../db/apps/reveng/AbstractDdlReveng.java | 2 +- .../PostColumnSqlTranslator.java | 46 +- .../src/main/jjtree/sqlInMemTranslate.jjt | 3 +- .../obevo/db/unittest/UnitTestDbBuilder.java | 583 +++++++++--------- 26 files changed, 679 insertions(+), 403 deletions(-) create mode 100644 obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlToH2TranslationDialect.java create mode 100644 obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlToHsqlTranslationDialect.java create mode 100644 obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlInMemConversionTest.java create mode 100644 obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/usertype/usertype0.hsql.sql create mode 100644 obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/system-config-inmem.xml create mode 100644 obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/usertype/usertype0.hsql.sql create mode 100644 obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/system-config-inmem.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index ce440caf..4df391ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,13 @@ ### Functionality Improvements #182: Adding Hibernate reverse-engineering API. See [ORM Integration docs](https://goldmansachs.github.io/obevo/orm-integration.html) for more details. #221 #223 #225: Oracle reverse-engineering improvements - unicode characters, nested tables, types, comments +#227: PostgreSQL improvements for kata - reverse-engineering, in-memory databases ### Technical Improvements +#227: Upgrading checkstyle version to avoid security prompts at Github site ### Bug Fixes +#227: Fixed drop behavior of PostgreSQL for multiple views that depended on each other ## 7.0.2 diff --git a/obevo-db-impls/obevo-db-postgresql/obevo-db-postgresql.iml b/obevo-db-impls/obevo-db-postgresql/obevo-db-postgresql.iml index 19eb5bfe..78c1e2b2 100644 --- a/obevo-db-impls/obevo-db-postgresql/obevo-db-postgresql.iml +++ b/obevo-db-impls/obevo-db-postgresql/obevo-db-postgresql.iml @@ -78,6 +78,10 @@ + + + + diff --git a/obevo-db-impls/obevo-db-postgresql/pom.xml b/obevo-db-impls/obevo-db-postgresql/pom.xml index 09914838..2b2db99c 100644 --- a/obevo-db-impls/obevo-db-postgresql/pom.xml +++ b/obevo-db-impls/obevo-db-postgresql/pom.xml @@ -49,6 +49,21 @@ postgresql + + com.goldmansachs.obevo + obevo-db-h2 + ${project.version} + true + + + + com.goldmansachs.obevo + obevo-db-hsql + ${project.version} + true + + + com.goldmansachs.obevo obevo-db-internal-test-helper diff --git a/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlDbPlatform.java b/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlDbPlatform.java index 43f290c4..97596992 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlDbPlatform.java +++ b/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlDbPlatform.java @@ -20,6 +20,8 @@ import com.gs.obevo.db.api.appdata.GrantTargetType; import com.gs.obevo.db.api.platform.DbChangeType; import com.gs.obevo.db.api.platform.DbChangeTypeImpl; +import com.gs.obevo.db.api.platform.DbPlatform; +import com.gs.obevo.db.api.platform.DbTranslationDialect; import com.gs.obevo.db.apps.reveng.AbstractDdlReveng; import com.gs.obevo.db.impl.platforms.AbstractDbPlatform; import org.eclipse.collections.api.block.function.Function; @@ -116,4 +118,13 @@ public ImmutableSet getRequiredValidationObjectTypes() { public AbstractDdlReveng getDdlReveng() { return new PostgreSqlPgDumpReveng(); } + + @Override + public DbTranslationDialect getDbTranslationDialect(DbPlatform targetDialect) { + if (targetDialect.getClass().getName().equals("com.gs.obevo.db.impl.platforms.hsql.HsqlDbPlatform")) { + return new PostgreSqlToHsqlTranslationDialect(); + } else { + return super.getDbTranslationDialect(targetDialect); + } + } } diff --git a/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlPgDumpReveng.java b/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlPgDumpReveng.java index 59a27338..f9729559 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlPgDumpReveng.java +++ b/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlPgDumpReveng.java @@ -105,7 +105,8 @@ protected boolean doRevengOrInstructions(PrintStream out, AquaRevengArgs args, F private String getCommandWithDefaults(boolean container, AquaRevengArgs args, File interimDir, String username, String password, String dbHost, String dbPort, String dbName, String dbSchema, String outputDirectory) { String prefix = container ? "docker exec $CONTAINER_NAME " : ""; - String fileSuffix = container ? "> " + interimDir.getAbsolutePath() : " -f " + interimDir.getAbsolutePath(); + String fileSuffix = container ? "> " : " -f "; + fileSuffix += new File(interimDir, "revengoutput.txt").getAbsolutePath(); return prefix + "pg_dump -O -s --no-privileges" + " -h " + ObjectUtils.defaultIfNull(args.getDbHost(), dbHost) + " -p " + ObjectUtils.defaultIfNull(args.getDbPort(), dbPort) + diff --git a/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlToH2TranslationDialect.java b/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlToH2TranslationDialect.java new file mode 100644 index 00000000..d2efcbbd --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlToH2TranslationDialect.java @@ -0,0 +1,27 @@ +/** + * Copyright 2017 Goldman Sachs. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.gs.obevo.db.impl.platforms.postgresql; + +import com.gs.obevo.db.impl.platforms.DefaultDbTranslationDialect; +import org.eclipse.collections.api.list.ImmutableList; +import org.eclipse.collections.impl.factory.Lists; + +public class PostgreSqlToH2TranslationDialect extends DefaultDbTranslationDialect { + @Override + public ImmutableList getInitSqls() { + return Lists.immutable.with("SET MODE PostgreSQL"); + } +} diff --git a/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlToHsqlTranslationDialect.java b/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlToHsqlTranslationDialect.java new file mode 100644 index 00000000..df351769 --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/main/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlToHsqlTranslationDialect.java @@ -0,0 +1,92 @@ +/** + * Copyright 2017 Goldman Sachs. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.gs.obevo.db.impl.platforms.postgresql; + +import java.sql.Connection; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.gs.obevo.api.platform.ChangeType; +import com.gs.obevo.db.impl.core.jdbc.JdbcHelper; +import com.gs.obevo.db.impl.platforms.DefaultDbTranslationDialect; +import com.gs.obevo.db.impl.platforms.sqltranslator.InMemoryTranslator; +import com.gs.obevo.db.impl.platforms.sqltranslator.PostColumnSqlTranslator; +import com.gs.obevo.db.impl.platforms.sqltranslator.PreParsedSqlTranslator; +import com.gs.obevo.db.impl.platforms.sqltranslator.SqlTranslatorConfigHelper; +import com.gs.obevo.db.sqlparser.syntaxparser.CreateTable; +import com.gs.obevo.db.sqlparser.syntaxparser.CreateTableColumn; +import com.gs.obevo.impl.PrepareDbChange; +import org.eclipse.collections.api.list.ImmutableList; +import org.eclipse.collections.api.set.ImmutableSet; +import org.eclipse.collections.impl.factory.Lists; +import org.eclipse.collections.impl.factory.Sets; + +public class PostgreSqlToHsqlTranslationDialect extends DefaultDbTranslationDialect { + private final PostColumnSqlTranslator replaceNextvalWithIdentity = new PostColumnSqlTranslator() { + private final Pattern defaultPattern = Pattern.compile("(?i)default\\s+nextval.*", Pattern.DOTALL); + + @Override + public String handlePostColumnText(String postColumnText, CreateTableColumn column, CreateTable table) { + Matcher defaultMatcher = defaultPattern.matcher(postColumnText); + if (defaultMatcher.find()) { + postColumnText = defaultMatcher.replaceFirst("IDENTITY"); + } + + return postColumnText; + } + }; + + private final PreParsedSqlTranslator substituteCreateOrReplace = new PreParsedSqlTranslator() { + Pattern pattern = Pattern.compile("(?i)^\\s*create\\s+or\\s+replace\\s+", Pattern.DOTALL); + @Override + public String preprocessSql(String sql) { + Matcher matcher = pattern.matcher(sql); + if (matcher.find()) { + sql = matcher.replaceFirst("create "); + } + return sql; + } + }; + + @Override + public ImmutableList getInitSqls() { + return Lists.immutable.with( + "SET DATABASE SQL SYNTAX PGS TRUE" + , "SET DATABASE TRANSACTION CONTROL MVCC" + ); + } + + @Override + public ImmutableList getAdditionalTranslators() { + SqlTranslatorConfigHelper configHelper = SqlTranslatorConfigHelper.createInMemoryDefault(); + + configHelper.getPreParsedSqlTranslators() + .with(substituteCreateOrReplace); + configHelper.getPostColumnSqlTranslators() + .with(replaceNextvalWithIdentity); + return Lists.immutable.with(new InMemoryTranslator(configHelper)); + } + + @Override + public void initSchema(JdbcHelper jdbc, Connection conn) { + updateAndIgnoreException(conn, jdbc, "create type int4 as integer"); + } + + @Override + public ImmutableSet getDisabledChangeTypeNames() { + return Sets.immutable.of(ChangeType.FUNCTION_STR, ChangeType.SP_STR); + } +} diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlInMemConversionTest.java b/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlInMemConversionTest.java new file mode 100644 index 00000000..c6d4380d --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/test/java/com/gs/obevo/db/impl/platforms/postgresql/PostgreSqlInMemConversionTest.java @@ -0,0 +1,53 @@ +/** + * Copyright 2017 Goldman Sachs. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.gs.obevo.db.impl.platforms.postgresql; + +import com.gs.obevo.db.api.platform.DbDeployerAppContext; +import com.gs.obevo.db.impl.platforms.h2.H2DbPlatform; +import com.gs.obevo.db.impl.platforms.hsql.HsqlDbPlatform; +import com.gs.obevo.db.unittest.UnitTestDbBuilder; +import org.junit.Test; + +public class PostgreSqlInMemConversionTest { + @Test + public void testInMemoryHsql() { + DbDeployerAppContext context = UnitTestDbBuilder.newBuilder() + .setSourcePath("platforms/postgresql/example1/step1/system-config-inmem.xml") + .setReferenceEnvName("unittestrefhsql") + .setDbPlatform(new HsqlDbPlatform()) + .setDbServer("mydb2testHsql") + .buildContext(); + context.setupEnvInfra(); + context.cleanAndDeploy(); + + // TODO add assertions + } + + // Implementation for H2 TBD +// @Test +// public void testInMemoryH2() { +// DbDeployerAppContext context = UnitTestDbBuilder.newBuilder() +// .setSourcePath("platforms/postgresql/example1/step1/system-config-inmem.xml") +// .setReferenceEnvName("unittestrefh2") +// .setDbPlatform(new H2DbPlatform()) +// .setDbServer("mydb2testH2") +// .buildContext(); +// context.setupEnvInfra(); +// context.cleanAndDeploy(); +// +// // TODO add assertions +// } +} diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TABLE_A.ddl b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TABLE_A.ddl index effbdcbb..2891013b 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TABLE_A.ddl +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TABLE_A.ddl @@ -1,29 +1,29 @@ -//// CHANGE name=chng1 -CREATE TABLE TABLE_A ( - A_ID INT NOT NULL, - B_ID INT NOT NULL, - STRING_FIELD VARCHAR(30) NULL, - TIMESTAMP_FIELD TIMESTAMP NULL, - PRIMARY KEY (A_ID) -) -GO - -//// CHANGE name=emptychange -//// CHANGE name=emptychange2 - - -//// CHANGE FK name=chng2 -ALTER TABLE TABLE_A ADD FOREIGN KEY (B_ID) REFERENCES TABLE_B(B_ID) -GO -//// CHANGE name=chng3 -ALTER TABLE TABLE_A ADD COLUMN C_ID INT NULL -GO -//// CHANGE name=extra1 -ALTER TABLE TABLE_A ADD COLUMN EXTRA1 INT NULL -GO -//// CHANGE name=extra2 -ALTER TABLE TABLE_A ADD COLUMN EXTRA2 INT NULL -GO -//// CHANGE name=extra3 -ALTER TABLE TABLE_A ADD COLUMN EXTRA3 INT NULL -GO +//// CHANGE name=chng1 +CREATE TABLE TABLE_A ( + A_ID INT NOT NULL, + B_ID INT NOT NULL, + STRING_FIELD VARCHAR(30) NULL, + TIMESTAMP_FIELD TIMESTAMP NULL, + PRIMARY KEY (A_ID) +) WITHOUT OIDS +GO + +//// CHANGE name=emptychange +//// CHANGE name=emptychange2 + + +//// CHANGE FK name=chng2 +ALTER TABLE TABLE_A ADD FOREIGN KEY (B_ID) REFERENCES TABLE_B(B_ID) +GO +//// CHANGE name=chng3 +ALTER TABLE TABLE_A ADD COLUMN C_ID INT NULL +GO +//// CHANGE name=extra1 +ALTER TABLE TABLE_A ADD COLUMN EXTRA1 INT NULL +GO +//// CHANGE name=extra2 +ALTER TABLE TABLE_A ADD COLUMN EXTRA2 INT NULL +GO +//// CHANGE name=extra3 +ALTER TABLE TABLE_A ADD COLUMN EXTRA3 INT NULL +GO diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TABLE_B.ddl b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TABLE_B.ddl index cff127c4..81b93691 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TABLE_B.ddl +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TABLE_B.ddl @@ -1,5 +1,5 @@ -//// CHANGE name=chng1 -CREATE TABLE TABLE_B ( - B_ID INT NOT NULL, - PRIMARY KEY (B_ID) -) +//// CHANGE name=chng1 +CREATE TABLE TABLE_B ( + B_ID INT NOT NULL, + PRIMARY KEY (B_ID) +) WITHOUT OIDS diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TABLE_SPECIAL_COL.ddl b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TABLE_SPECIAL_COL.ddl index 3114fe83..71698aea 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TABLE_SPECIAL_COL.ddl +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TABLE_SPECIAL_COL.ddl @@ -3,5 +3,5 @@ CREATE TABLE TABLE_SPECIAL_COL ( UUID_PK UUID NOT NULL, STR1 VARCHAR(30) NULL, PRIMARY KEY (UUID_PK) -) +) WITHOUT OIDS GO diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TAB_WITH_SEQ.ddl b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TAB_WITH_SEQ.ddl index c6e7ed25..24889b18 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TAB_WITH_SEQ.ddl +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/table/TAB_WITH_SEQ.ddl @@ -1,8 +1,8 @@ -//// METADATA excludePlatforms=REDSHIFT -//// CHANGE name=chng1 -CREATE TABLE TAB_WITH_SEQ ( - ID int4 NOT NULL DEFAULT nextval('MYSEQ1'::regclass), - FIELD1 INT NULL, - PRIMARY KEY (ID) -) -GO +//// METADATA excludePlatforms=REDSHIFT +//// CHANGE name=chng1 +CREATE TABLE TAB_WITH_SEQ ( + ID int4 NOT NULL DEFAULT nextval('MYSEQ1'::regclass), + FIELD1 INT NULL, + PRIMARY KEY (ID) +) WITHOUT OIDS +GO diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/usertype/usertype0.hsql.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/usertype/usertype0.hsql.sql new file mode 100644 index 00000000..93efe056 --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/usertype/usertype0.hsql.sql @@ -0,0 +1,3 @@ +//// METADATA includePlatforms="HSQL" +CREATE TYPE usertype0 AS VARCHAR(1); +GO diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/usertype/usertype0.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/usertype/usertype0.sql index bfe03d74..bf6ab05b 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/usertype/usertype0.sql +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/schema1/usertype/usertype0.sql @@ -1,3 +1,4 @@ +//// METADATA excludePlatforms="HSQL" CREATE TYPE usertype0 AS ENUM ( '1', '2', diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/system-config-inmem.xml b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/system-config-inmem.xml new file mode 100644 index 00000000..2a94b414 --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step1/system-config-inmem.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_A.ddl b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_A.ddl index a8382583..3b88b31f 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_A.ddl +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_A.ddl @@ -1,32 +1,32 @@ -//// CHANGE name=chng1 -CREATE TABLE TABLE_A ( - A_ID INT NOT NULL, - B_ID INT NOT NULL, - STRING_FIELD VARCHAR(30) NULL, - TIMESTAMP_FIELD TIMESTAMP NULL, - PRIMARY KEY (A_ID) -) -GO - -//// CHANGE name=emptychange -//// CHANGE name=emptychange2 - - -//// CHANGE FK name=chng2 -ALTER TABLE TABLE_A ADD FOREIGN KEY (B_ID) REFERENCES TABLE_B(B_ID) -GO -//// CHANGE name=chng3 -ALTER TABLE TABLE_A ADD COLUMN C_ID INT NULL -GO -//// CHANGE name=extra1 -ALTER TABLE TABLE_A ADD COLUMN EXTRA1 INT NULL -GO -//// CHANGE name=extra2 -ALTER TABLE TABLE_A ADD COLUMN EXTRA2 INT NULL -GO -//// CHANGE name=extra3 -ALTER TABLE TABLE_A ADD COLUMN EXTRA3 INT NULL -GO -//// CHANGE name=extra4 -ALTER TABLE TABLE_A ADD COLUMN EXTRA4 INT NULL -GO +//// CHANGE name=chng1 +CREATE TABLE TABLE_A ( + A_ID INT NOT NULL, + B_ID INT NOT NULL, + STRING_FIELD VARCHAR(30) NULL, + TIMESTAMP_FIELD TIMESTAMP NULL, + PRIMARY KEY (A_ID) +) WITHOUT OIDS +GO + +//// CHANGE name=emptychange +//// CHANGE name=emptychange2 + + +//// CHANGE FK name=chng2 +ALTER TABLE TABLE_A ADD FOREIGN KEY (B_ID) REFERENCES TABLE_B(B_ID) +GO +//// CHANGE name=chng3 +ALTER TABLE TABLE_A ADD COLUMN C_ID INT NULL +GO +//// CHANGE name=extra1 +ALTER TABLE TABLE_A ADD COLUMN EXTRA1 INT NULL +GO +//// CHANGE name=extra2 +ALTER TABLE TABLE_A ADD COLUMN EXTRA2 INT NULL +GO +//// CHANGE name=extra3 +ALTER TABLE TABLE_A ADD COLUMN EXTRA3 INT NULL +GO +//// CHANGE name=extra4 +ALTER TABLE TABLE_A ADD COLUMN EXTRA4 INT NULL +GO diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_B.ddl b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_B.ddl index cff127c4..81b93691 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_B.ddl +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_B.ddl @@ -1,5 +1,5 @@ -//// CHANGE name=chng1 -CREATE TABLE TABLE_B ( - B_ID INT NOT NULL, - PRIMARY KEY (B_ID) -) +//// CHANGE name=chng1 +CREATE TABLE TABLE_B ( + B_ID INT NOT NULL, + PRIMARY KEY (B_ID) +) WITHOUT OIDS diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_SPECIAL_COL.ddl b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_SPECIAL_COL.ddl index 3114fe83..71698aea 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_SPECIAL_COL.ddl +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TABLE_SPECIAL_COL.ddl @@ -3,5 +3,5 @@ CREATE TABLE TABLE_SPECIAL_COL ( UUID_PK UUID NOT NULL, STR1 VARCHAR(30) NULL, PRIMARY KEY (UUID_PK) -) +) WITHOUT OIDS GO diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TAB_WITH_SEQ.ddl b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TAB_WITH_SEQ.ddl index c6e7ed25..24889b18 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TAB_WITH_SEQ.ddl +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/table/TAB_WITH_SEQ.ddl @@ -1,8 +1,8 @@ -//// METADATA excludePlatforms=REDSHIFT -//// CHANGE name=chng1 -CREATE TABLE TAB_WITH_SEQ ( - ID int4 NOT NULL DEFAULT nextval('MYSEQ1'::regclass), - FIELD1 INT NULL, - PRIMARY KEY (ID) -) -GO +//// METADATA excludePlatforms=REDSHIFT +//// CHANGE name=chng1 +CREATE TABLE TAB_WITH_SEQ ( + ID int4 NOT NULL DEFAULT nextval('MYSEQ1'::regclass), + FIELD1 INT NULL, + PRIMARY KEY (ID) +) WITHOUT OIDS +GO diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/usertype/usertype0.hsql.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/usertype/usertype0.hsql.sql new file mode 100644 index 00000000..93efe056 --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/usertype/usertype0.hsql.sql @@ -0,0 +1,3 @@ +//// METADATA includePlatforms="HSQL" +CREATE TYPE usertype0 AS VARCHAR(1); +GO diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/usertype/usertype0.sql b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/usertype/usertype0.sql index bfe03d74..bf6ab05b 100644 --- a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/usertype/usertype0.sql +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/schema1/usertype/usertype0.sql @@ -1,3 +1,4 @@ +//// METADATA excludePlatforms="HSQL" CREATE TYPE usertype0 AS ENUM ( '1', '2', diff --git a/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/system-config-inmem.xml b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/system-config-inmem.xml new file mode 100644 index 00000000..2a94b414 --- /dev/null +++ b/obevo-db-impls/obevo-db-postgresql/src/test/resources/platforms/postgresql/example1/step2/system-config-inmem.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + diff --git a/obevo-db/src/main/java/com/gs/obevo/db/apps/reveng/AbstractDdlReveng.java b/obevo-db/src/main/java/com/gs/obevo/db/apps/reveng/AbstractDdlReveng.java index a8ba9f8b..ceacfd39 100644 --- a/obevo-db/src/main/java/com/gs/obevo/db/apps/reveng/AbstractDdlReveng.java +++ b/obevo-db/src/main/java/com/gs/obevo/db/apps/reveng/AbstractDdlReveng.java @@ -177,7 +177,7 @@ public void reveng(AquaRevengArgs args) { System.out.println("***********"); System.out.println(); System.out.println("Once those steps are done, rerun the reverse-engineering command you just ran, but add the following argument based on the value passed in above the argument:"); - System.out.println(" -inputPath " + ObjectUtils.defaultIfNull(args.getOutputPath(), "")); + System.out.println(" -inputPath " + interimDir.getAbsolutePath()); System.out.println(); System.out.println("If you need more information on the vendor reverse engineer process, see the doc: https://goldmansachs.github.io/obevo/reverse-engineer-dbmstools.html"); } diff --git a/obevo-db/src/main/java/com/gs/obevo/db/impl/platforms/sqltranslator/PostColumnSqlTranslator.java b/obevo-db/src/main/java/com/gs/obevo/db/impl/platforms/sqltranslator/PostColumnSqlTranslator.java index 9e50df7c..9ecbd896 100644 --- a/obevo-db/src/main/java/com/gs/obevo/db/impl/platforms/sqltranslator/PostColumnSqlTranslator.java +++ b/obevo-db/src/main/java/com/gs/obevo/db/impl/platforms/sqltranslator/PostColumnSqlTranslator.java @@ -1,23 +1,23 @@ -/** - * Copyright 2017 Goldman Sachs. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package com.gs.obevo.db.impl.platforms.sqltranslator; - -import com.gs.obevo.db.sqlparser.syntaxparser.CreateTable; -import com.gs.obevo.db.sqlparser.syntaxparser.CreateTableColumn; - -public interface PostColumnSqlTranslator { - String handlePostColumnText(String sql, CreateTableColumn column, CreateTable table); -} +/** + * Copyright 2017 Goldman Sachs. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.gs.obevo.db.impl.platforms.sqltranslator; + +import com.gs.obevo.db.sqlparser.syntaxparser.CreateTable; +import com.gs.obevo.db.sqlparser.syntaxparser.CreateTableColumn; + +public interface PostColumnSqlTranslator { + String handlePostColumnText(String postColumnText, CreateTableColumn column, CreateTable table); +} diff --git a/obevo-db/src/main/jjtree/sqlInMemTranslate.jjt b/obevo-db/src/main/jjtree/sqlInMemTranslate.jjt index 5fd2b427..2841294b 100644 --- a/obevo-db/src/main/jjtree/sqlInMemTranslate.jjt +++ b/obevo-db/src/main/jjtree/sqlInMemTranslate.jjt @@ -157,7 +157,7 @@ TOKEN : TOKEN : { - < IDENTIFIER: (||||||)+ > + < IDENTIFIER: (|||||||)+ > | < #LETTER: [ @@ -211,6 +211,7 @@ TOKEN : | < DOLLAR: "$" > | < DOT: "." > | < POUND: "#" > +| < COLON: ":" > } diff --git a/obevo-utils/obevo-db-unittest-util/src/main/java/com/gs/obevo/db/unittest/UnitTestDbBuilder.java b/obevo-utils/obevo-db-unittest-util/src/main/java/com/gs/obevo/db/unittest/UnitTestDbBuilder.java index 0b8aa94b..8fdb046e 100644 --- a/obevo-utils/obevo-db-unittest-util/src/main/java/com/gs/obevo/db/unittest/UnitTestDbBuilder.java +++ b/obevo-utils/obevo-db-unittest-util/src/main/java/com/gs/obevo/db/unittest/UnitTestDbBuilder.java @@ -1,288 +1,295 @@ -/** - * Copyright 2017 Goldman Sachs. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package com.gs.obevo.db.unittest; - -import java.io.File; -import java.util.Set; - -import com.gs.obevo.api.appdata.ChangeKey; -import com.gs.obevo.api.platform.ChangeType; -import com.gs.obevo.api.platform.MainDeployerArgs; -import com.gs.obevo.db.api.appdata.DbEnvironment; -import com.gs.obevo.db.api.appdata.Permission; -import com.gs.obevo.db.api.factory.DbEnvironmentFactory; -import com.gs.obevo.db.api.platform.DbDeployerAppContext; -import com.gs.obevo.db.api.platform.DbPlatform; -import com.gs.obevo.impl.changepredicate.ChangeKeyPredicateBuilder; -import com.gs.obevo.util.inputreader.Credential; -import org.apache.commons.lang3.Validate; -import org.eclipse.collections.api.block.predicate.Predicate; -import org.eclipse.collections.api.list.MutableList; -import org.eclipse.collections.api.map.MutableMap; -import org.eclipse.collections.api.set.ImmutableSet; -import org.eclipse.collections.impl.block.factory.Predicates; -import org.eclipse.collections.impl.factory.Lists; -import org.eclipse.collections.impl.factory.Maps; -import org.eclipse.collections.impl.factory.Sets; - -/** - * Helper class for building unit test db environments and contexts, i.e. to not have to remember details for each unit - * test db type and to easily switch between unit test DBMS's if needed - * - * Ultimately, this will delegate to Environment.getAppContextBuilder() for building the context. This class will mainly - * leverage a client's existing DbEnvironment setup and tweak values accordingly - * - * If an existing environment is referenced, a copy of that DbEnvironment will be made by this class so that any changes - * to that object will not impact anything existing - */ -public class UnitTestDbBuilder { - public static UnitTestDbBuilder newBuilder() { - return new UnitTestDbBuilder(); - } - - /** - * Caching the contexts created so that subsequent operations on this can go quickly (i.e. avoiding the costs of - * reading the contents from the file system). - */ - private static final MutableMap cachedContexts = Maps.mutable.empty(); - - private String sourcePath; - private String envName; - private String referenceEnvName; - private DbPlatform dbPlatform; - private String dbServer = "test"; - private ImmutableSet tables; - private ImmutableSet views; - private boolean persistToFile = false; - private boolean grantsDisabled = true; // disabling grants by default for unit tests as in practice, most teams - private File workDir = new File("./target/unitdb"); - private Credential credential = new Credential("sa", ""); - - /** - * (Required) path to read environment metadata from - */ - public UnitTestDbBuilder setSourcePath(String sourcePath) { - this.sourcePath = sourcePath; - return this; - } - - /** - * Name to give the environment created during this builder - * - * If not specified, will use the name and environment specified by the referenceEnvName parameter - */ - public UnitTestDbBuilder setEnvName(String envName) { - this.envName = envName; - return this; - } - - /** - * Environment to use as a model for the unit test db environment to create - * - * If not specified, then one of the environments read from the source path will be picked arbitrarily. The envName - * parameter must then be specified to give this unit test db environment a known name - */ - public UnitTestDbBuilder setReferenceEnvName(String referenceEnvName) { - this.referenceEnvName = referenceEnvName; - return this; - } - - /** - * dbPlatform to use for the new unit test db - * - * If not specified, will default to the dbPlatform of the reference environment - */ - public UnitTestDbBuilder setDbPlatform(DbPlatform dbPlatform) { - this.dbPlatform = dbPlatform; - return this; - } - - /** - * Name of the in-memory db to be created to be used when creating the URL, e.g. jdbc:h2:mem:<dbServer>:etc. - * This is a convenience for clients to not have to remember the URL convention. The resolved URL can be retrieved - * from the DbEnvironment instance - * - * If not specified, will default to "test" - */ - public UnitTestDbBuilder setDbServer(String dbServer) { - this.dbServer = dbServer; - return this; - } - - /** - * Specify this to restrict the tables deployed to just the ones provided. If not specified, all tables will be deployed. - * - * @deprecated Specify these fields to remove in the {@link DbDeployerAppContext#deploy(MainDeployerArgs)} arguments itself. - */ - @Deprecated - public UnitTestDbBuilder setTables(Set tables) { - this.tables = Sets.immutable.withAll(tables); - return this; - } - - /** - * Specify this to restrict the views deployed to just the ones provided. If not specified, all views will be deployed. - * - * @deprecated Specify these fields to remove in the {@link DbDeployerAppContext#deploy(MainDeployerArgs)} arguments itself. - */ - @Deprecated - public UnitTestDbBuilder setViews(Set views) { - this.views = Sets.immutable.withAll(views); - return this; - } - - /** - * If true, will generate the file-persistent URL for the in-memory database. If false, goes w/ the in-memory URL - * - * Defaults to false (in-memory) - */ - public UnitTestDbBuilder setPersistToFile(boolean persistToFile) { - this.persistToFile = persistToFile; - return this; - } - - private boolean isPersistToFile() { - // We support this system property here to facilitate easy debugging for - // unit tests (i.e. if we don't want to change the code accidentally when running/debugging) - // But we can still set this programatically anyway - if (System.getProperty("debugDbUnit") == null) { - return this.persistToFile; - } else { - return "true".equalsIgnoreCase(System.getProperty("debugDbUnit")); - } - } - - /** - * @deprecated Clients should move off this. Leverage the groups and users sections in your DbEnvironment configuration to have the grants created - */ - @Deprecated - public UnitTestDbBuilder setGrantsDisabled(boolean grantsDisabled) { - this.grantsDisabled = grantsDisabled; - return this; - } - - /** - * The workDir to use for any temporary files used for the db deployment - * - * If not specified, defaults to "./target/unitdb" (i.e. relative to your working directory) - */ - public UnitTestDbBuilder setWorkDir(File workDir) { - this.workDir = workDir; - return this; - } - - /** - * (optional) credential defaults to username==sa and password==<blank>, per the default convention of h2/hsql - */ - public UnitTestDbBuilder setCredential(Credential credential) { - this.credential = credential; - return this; - } - - private void validateBuilder() { - if (envName == null && referenceEnvName == null) { - throw new IllegalArgumentException("One of envName or referenceEnvName must be populated"); - } - Validate.notNull(sourcePath); - Validate.notNull(credential); - } - - public DbDeployerAppContext buildContext() { - validateBuilder(); - - String instanceLookupKey = instanceLookupKey(); - - DbDeployerAppContext baseContext = cachedContexts.get(instanceLookupKey); - - if (baseContext == null) { - baseContext = buildContextUncached(); - cachedContexts.put(instanceLookupKey, baseContext); - } - - // set the arguments that should be used as defined in this builder class, e.g. for limiting by specific tables - return new UnitTestDbDeployerAppContext(baseContext, getMainDeployerArgs()); - } - - /** - * Builds the deployer context. See the class Javadoc for more information - */ - private DbDeployerAppContext buildContextUncached() { - validateBuilder(); - - String[] envsToRequest = this.referenceEnvName != null ? new String[] { this.referenceEnvName } : new String[0]; - DbEnvironment referenceEnv = DbEnvironmentFactory.getInstance().readFromSourcePath(this.sourcePath, envsToRequest) - .getFirst(); - - DbEnvironment env = referenceEnv.createCopy(); - - if (this.envName != null) { - env.setName(this.envName); - } - - env.setDisableAuditTracking(true); - env.setPersistToFile(this.isPersistToFile()); - - if (this.dbPlatform != null) { - env.setPlatform(this.dbPlatform); - } - - if (this.dbServer != null) { - env.setDbServer(this.dbServer); - } - - if (this.grantsDisabled) { - env.setPermissions(Lists.immutable.empty()); - } - - env.setDefaultUserId(credential.getUsername()); - env.setDefaultPassword(credential.getPassword()); - - return env.getAppContextBuilder() - .setWorkDir(workDir) - .build(); - } - - private MainDeployerArgs getMainDeployerArgs() { - MainDeployerArgs args = new MainDeployerArgs(); - - if (this.tables != null || this.views != null) { - MutableList> predicates = Lists.mutable.empty(); - if (this.tables != null) { - predicates.add(ChangeKeyPredicateBuilder.newBuilder() - .setChangeTypes(ChangeType.TABLE_STR, ChangeType.FOREIGN_KEY_STR, ChangeType.TRIGGER_INCREMENTAL_OLD_STR, ChangeType.STATICDATA_STR) - .setObjectNames(Sets.immutable.withAll(this.tables)) - .build()); - } - if (this.views != null) { - predicates.add(ChangeKeyPredicateBuilder.newBuilder() - .setChangeTypes(ChangeType.VIEW_STR) - .setObjectNames(Sets.immutable.withAll(this.views)) - .build()); - } - - args.setChangeInclusionPredicate(Predicates.or(predicates)); - } - - args.setAllChangesets(true); // for unit tests, we always want all changes to deploy - return args; - } - - private String instanceLookupKey() { - String envNameToLookup = envName != null ? envName : referenceEnvName; - - return this.sourcePath + ":" + envNameToLookup; - } -} +/** + * Copyright 2017 Goldman Sachs. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.gs.obevo.db.unittest; + +import java.io.File; +import java.util.Set; + +import com.gs.obevo.api.appdata.ChangeKey; +import com.gs.obevo.api.platform.ChangeType; +import com.gs.obevo.api.platform.MainDeployerArgs; +import com.gs.obevo.db.api.appdata.DbEnvironment; +import com.gs.obevo.db.api.appdata.Permission; +import com.gs.obevo.db.api.factory.DbEnvironmentFactory; +import com.gs.obevo.db.api.platform.DbDeployerAppContext; +import com.gs.obevo.db.api.platform.DbPlatform; +import com.gs.obevo.impl.changepredicate.ChangeKeyPredicateBuilder; +import com.gs.obevo.util.inputreader.Credential; +import org.apache.commons.lang3.Validate; +import org.eclipse.collections.api.block.predicate.Predicate; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.api.map.MutableMap; +import org.eclipse.collections.api.set.ImmutableSet; +import org.eclipse.collections.impl.block.factory.Predicates; +import org.eclipse.collections.impl.factory.Lists; +import org.eclipse.collections.impl.factory.Maps; +import org.eclipse.collections.impl.factory.Sets; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Helper class for building unit test db environments and contexts, i.e. to not have to remember details for each unit + * test db type and to easily switch between unit test DBMS's if needed + * + * Ultimately, this will delegate to Environment.getAppContextBuilder() for building the context. This class will mainly + * leverage a client's existing DbEnvironment setup and tweak values accordingly + * + * If an existing environment is referenced, a copy of that DbEnvironment will be made by this class so that any changes + * to that object will not impact anything existing + */ +public class UnitTestDbBuilder { + private static final Logger LOG = LoggerFactory.getLogger(UnitTestDbBuilder.class); + public static UnitTestDbBuilder newBuilder() { + return new UnitTestDbBuilder(); + } + + /** + * Caching the contexts created so that subsequent operations on this can go quickly (i.e. avoiding the costs of + * reading the contents from the file system). + */ + private static final MutableMap cachedContexts = Maps.mutable.empty(); + + private String sourcePath; + private String envName; + private String referenceEnvName; + private DbPlatform dbPlatform; + private String dbServer = "test"; + private ImmutableSet tables; + private ImmutableSet views; + private boolean persistToFile = false; + private boolean grantsDisabled = true; // disabling grants by default for unit tests as in practice, most teams + private File workDir = new File("./target/unitdb"); + private Credential credential = new Credential("sa", ""); + + /** + * (Required) path to read environment metadata from + */ + public UnitTestDbBuilder setSourcePath(String sourcePath) { + this.sourcePath = sourcePath; + return this; + } + + /** + * Name to give the environment created during this builder + * + * If not specified, will use the name and environment specified by the referenceEnvName parameter + */ + public UnitTestDbBuilder setEnvName(String envName) { + this.envName = envName; + return this; + } + + /** + * Environment to use as a model for the unit test db environment to create + * + * If not specified, then one of the environments read from the source path will be picked arbitrarily. The envName + * parameter must then be specified to give this unit test db environment a known name + */ + public UnitTestDbBuilder setReferenceEnvName(String referenceEnvName) { + this.referenceEnvName = referenceEnvName; + return this; + } + + /** + * dbPlatform to use for the new unit test db + * + * If not specified, will default to the dbPlatform of the reference environment + */ + public UnitTestDbBuilder setDbPlatform(DbPlatform dbPlatform) { + this.dbPlatform = dbPlatform; + return this; + } + + /** + * Name of the in-memory db to be created to be used when creating the URL, e.g. jdbc:h2:mem:<dbServer>:etc. + * This is a convenience for clients to not have to remember the URL convention. The resolved URL can be retrieved + * from the DbEnvironment instance + * + * If not specified, will default to "test" + */ + public UnitTestDbBuilder setDbServer(String dbServer) { + this.dbServer = dbServer; + return this; + } + + /** + * Specify this to restrict the tables deployed to just the ones provided. If not specified, all tables will be deployed. + * + * @deprecated Specify these fields to remove in the {@link DbDeployerAppContext#deploy(MainDeployerArgs)} arguments itself. + */ + @Deprecated + public UnitTestDbBuilder setTables(Set tables) { + this.tables = Sets.immutable.withAll(tables); + return this; + } + + /** + * Specify this to restrict the views deployed to just the ones provided. If not specified, all views will be deployed. + * + * @deprecated Specify these fields to remove in the {@link DbDeployerAppContext#deploy(MainDeployerArgs)} arguments itself. + */ + @Deprecated + public UnitTestDbBuilder setViews(Set views) { + this.views = Sets.immutable.withAll(views); + return this; + } + + /** + * If true, will generate the file-persistent URL for the in-memory database. If false, goes w/ the in-memory URL + * + * Defaults to false (in-memory) + */ + public UnitTestDbBuilder setPersistToFile(boolean persistToFile) { + this.persistToFile = persistToFile; + return this; + } + + private boolean isPersistToFile() { + // We support this system property here to facilitate easy debugging for + // unit tests (i.e. if we don't want to change the code accidentally when running/debugging) + // But we can still set this programatically anyway + if (System.getProperty("debugDbUnit") == null) { + return this.persistToFile; + } else { + return "true".equalsIgnoreCase(System.getProperty("debugDbUnit")); + } + } + + /** + * @deprecated Clients should move off this. Leverage the groups and users sections in your DbEnvironment configuration to have the grants created + */ + @Deprecated + public UnitTestDbBuilder setGrantsDisabled(boolean grantsDisabled) { + this.grantsDisabled = grantsDisabled; + return this; + } + + /** + * The workDir to use for any temporary files used for the db deployment + * + * If not specified, defaults to "./target/unitdb" (i.e. relative to your working directory) + */ + public UnitTestDbBuilder setWorkDir(File workDir) { + this.workDir = workDir; + return this; + } + + /** + * (optional) credential defaults to username==sa and password==<blank>, per the default convention of h2/hsql + */ + public UnitTestDbBuilder setCredential(Credential credential) { + this.credential = credential; + return this; + } + + private void validateBuilder() { + if (envName == null && referenceEnvName == null) { + throw new IllegalArgumentException("One of envName or referenceEnvName must be populated"); + } + Validate.notNull(sourcePath); + Validate.notNull(credential); + } + + public DbDeployerAppContext buildContext() { + validateBuilder(); + + String instanceLookupKey = instanceLookupKey(); + + DbDeployerAppContext baseContext = cachedContexts.get(instanceLookupKey); + + if (baseContext == null) { + baseContext = buildContextUncached(); + cachedContexts.put(instanceLookupKey, baseContext); + } + + // set the arguments that should be used as defined in this builder class, e.g. for limiting by specific tables + return new UnitTestDbDeployerAppContext(baseContext, getMainDeployerArgs()); + } + + /** + * Builds the deployer context. See the class Javadoc for more information + */ + private DbDeployerAppContext buildContextUncached() { + validateBuilder(); + + String[] envsToRequest = this.referenceEnvName != null ? new String[] { this.referenceEnvName } : new String[0]; + DbEnvironment referenceEnv = DbEnvironmentFactory.getInstance().readFromSourcePath(this.sourcePath, envsToRequest) + .getFirst(); + + DbEnvironment env = referenceEnv.createCopy(); + + if (this.envName != null) { + env.setName(this.envName); + } + + env.setDisableAuditTracking(true); + env.setPersistToFile(this.isPersistToFile()); + + if (this.dbPlatform != null) { + env.setPlatform(this.dbPlatform); + } + + if (this.dbServer != null) { + if (env.getJdbcUrl() != null) { + LOG.debug("Unsetting existing JDBC URL value, as we can rely on the in-memory DB value to be set here"); + env.setJdbcUrl(null); + } + env.setDbServer(this.dbServer); + } + + if (this.grantsDisabled) { + env.setPermissions(Lists.immutable.empty()); + } + + env.setDefaultUserId(credential.getUsername()); + env.setDefaultPassword(credential.getPassword()); + + return env.getAppContextBuilder() + .setWorkDir(workDir) + .build(); + } + + private MainDeployerArgs getMainDeployerArgs() { + MainDeployerArgs args = new MainDeployerArgs(); + + if (this.tables != null || this.views != null) { + MutableList> predicates = Lists.mutable.empty(); + if (this.tables != null) { + predicates.add(ChangeKeyPredicateBuilder.newBuilder() + .setChangeTypes(ChangeType.TABLE_STR, ChangeType.FOREIGN_KEY_STR, ChangeType.TRIGGER_INCREMENTAL_OLD_STR, ChangeType.STATICDATA_STR) + .setObjectNames(Sets.immutable.withAll(this.tables)) + .build()); + } + if (this.views != null) { + predicates.add(ChangeKeyPredicateBuilder.newBuilder() + .setChangeTypes(ChangeType.VIEW_STR) + .setObjectNames(Sets.immutable.withAll(this.views)) + .build()); + } + + args.setChangeInclusionPredicate(Predicates.or(predicates)); + } + + args.setAllChangesets(true); // for unit tests, we always want all changes to deploy + return args; + } + + private String instanceLookupKey() { + String envNameToLookup = envName != null ? envName : referenceEnvName; + + return this.sourcePath + ":" + envNameToLookup; + } +}