diff --git a/README.md b/README.md index 4fd35f862..6e8479cfd 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ![Alfa Morf](https://github.com/alfasoftware/morf/wiki/morf.png) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) -[![Build Status](https://travis-ci.org/alfasoftware/morf.svg?branch=master)](https://travis-ci.org/alfasoftware/morf) +[![Build Status](https://travis-ci.com/alfasoftware/morf.svg?branch=master)](https://travis-ci.com/alfasoftware/morf) [![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=org.alfasoftware%3Amorf-parent&metric=alert_status)](https://sonarcloud.io/dashboard/index/org.alfasoftware:morf-parent) Morf is a library for cross-platform evolutionary relational database mechanics, database access and database imaging/cloning. It has been developed over many years at Alfa and is used to manage all of our RDBMS-backed applications. diff --git a/morf-core/pom.xml b/morf-core/pom.xml index 7e162c156..681d75f4b 100755 --- a/morf-core/pom.xml +++ b/morf-core/pom.xml @@ -4,7 +4,7 @@ org.alfasoftware morf-parent - 1.3.5-SNAPSHOT + 1.3.7-SNAPSHOT Morf - Core diff --git a/morf-core/src/main/java/org/alfasoftware/morf/dataset/TableLoader.java b/morf-core/src/main/java/org/alfasoftware/morf/dataset/TableLoader.java index 6d7feefc9..22f86f976 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/dataset/TableLoader.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/dataset/TableLoader.java @@ -21,6 +21,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; +import java.sql.SQLException; import org.alfasoftware.morf.dataset.TableLoaderBuilder.TableLoaderBuilderImpl; import org.alfasoftware.morf.jdbc.RuntimeSqlException; @@ -89,6 +90,13 @@ public static TableLoaderBuilder builder() { this.insertingUnderAutonumLimit = insertingUnderAutonumLimit; this.truncateBeforeLoad = truncateBeforeLoad; this.batchSize = batchSize; + + if (truncateBeforeLoad && !explicitCommit) { + // This is because PostgreSQL needs to be able to commit/rollback, for TRUNCATE fallback to DELETE to work + // It could potentially be relaxed, if the DELETE fallback after a failed TRUNCATE is not needed. + // It also could potentially be relaxed, if running on PostgreSQL is of no concern to the caller. + throw new UnsupportedOperationException("Cannot TRUNCATE before load without permission to commit explicitly"); + } } @@ -100,7 +108,7 @@ public static TableLoaderBuilder builder() { public void load(final Iterable records) { if (truncateBeforeLoad) { - truncate(table, connection); + truncate(table); } insertOrMergeRecords(records); @@ -112,14 +120,16 @@ public void load(final Iterable records) { * * @param table */ - private void truncate(Table table, Connection connection) { + private void truncate(Table table) { // Get our own table definition based on the name to avoid case sensitivity bugs on some database vendors log.debug("Clearing table [" + table.getName() + "]"); // Try to use a truncate try { - sqlExecutor.execute(sqlDialect.truncateTableStatements(table), connection); - } catch (RuntimeSqlException e) { + runRecoverably(() -> + sqlExecutor.execute(sqlDialect.truncateTableStatements(table), connection) + ); + } catch (SQLException | RuntimeSqlException e) { // If that has failed try to use a delete log.debug("Failed to truncate table, attempting a delete", e); sqlExecutor.execute(sqlDialect.deleteAllFromTableStatements(table), connection); @@ -127,6 +137,33 @@ private void truncate(Table table, Connection connection) { } + /** + * PostgreSQL does not like failing commands, and marks connections as "dirty" after errors: + * ERROR: current transaction is aborted, commands ignored until end of transaction block. + * + *

To recover a connection, one has to issue a rollback.

+ * + * @param runnable + */ + private void runRecoverably(Runnable runnable) throws SQLException { + // make sure we commit if we can + if (explicitCommit) { + connection.commit(); + } + + try { + runnable.run(); + } + catch (Exception e) { + // make sure we rollback if we can + if (explicitCommit) { + connection.rollback(); + } + throw e; + } + } + + /** * Insert the records into the database using a {@link PreparedStatement}. * diff --git a/morf-excel/pom.xml b/morf-excel/pom.xml index 43de41fc8..7ba3bf9ee 100755 --- a/morf-excel/pom.xml +++ b/morf-excel/pom.xml @@ -4,7 +4,7 @@ org.alfasoftware morf-parent - 1.3.5-SNAPSHOT + 1.3.7-SNAPSHOT Morf - Excel diff --git a/morf-h2/pom.xml b/morf-h2/pom.xml index 9c9464094..8c3b28ac0 100755 --- a/morf-h2/pom.xml +++ b/morf-h2/pom.xml @@ -4,7 +4,7 @@ org.alfasoftware morf-parent - 1.3.5-SNAPSHOT + 1.3.7-SNAPSHOT Morf - H2 diff --git a/morf-integration-test/pom.xml b/morf-integration-test/pom.xml index 4391c8a60..d8c88d72e 100755 --- a/morf-integration-test/pom.xml +++ b/morf-integration-test/pom.xml @@ -4,7 +4,7 @@ org.alfasoftware morf-parent - 1.3.5-SNAPSHOT + 1.3.7-SNAPSHOT Morf - Integration Test diff --git a/morf-mysql/pom.xml b/morf-mysql/pom.xml index c9f11ef2f..bfabee85d 100755 --- a/morf-mysql/pom.xml +++ b/morf-mysql/pom.xml @@ -4,7 +4,7 @@ org.alfasoftware morf-parent - 1.3.5-SNAPSHOT + 1.3.7-SNAPSHOT Morf - MySQL diff --git a/morf-nuodb/pom.xml b/morf-nuodb/pom.xml index 35d5a5ea5..5a451f7d3 100755 --- a/morf-nuodb/pom.xml +++ b/morf-nuodb/pom.xml @@ -4,7 +4,7 @@ org.alfasoftware morf-parent - 1.3.5-SNAPSHOT + 1.3.7-SNAPSHOT Morf - NuoDB diff --git a/morf-oracle/pom.xml b/morf-oracle/pom.xml index d166fa4e1..760c7ebb7 100755 --- a/morf-oracle/pom.xml +++ b/morf-oracle/pom.xml @@ -4,7 +4,7 @@ org.alfasoftware morf-parent - 1.3.5-SNAPSHOT + 1.3.7-SNAPSHOT Morf - Oracle diff --git a/morf-postgresql/pom.xml b/morf-postgresql/pom.xml index be7241cb0..ae8708722 100644 --- a/morf-postgresql/pom.xml +++ b/morf-postgresql/pom.xml @@ -4,7 +4,7 @@ org.alfasoftware morf-parent - 1.3.5-SNAPSHOT + 1.3.7-SNAPSHOT Morf - PostgreSQL diff --git a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLDialect.java b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLDialect.java index 5c7abb1fb..3b8312631 100644 --- a/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLDialect.java +++ b/morf-postgresql/src/main/java/org/alfasoftware/morf/jdbc/postgresql/PostgreSQLDialect.java @@ -207,14 +207,14 @@ protected Collection internalTableDeploymentStatements(Table table) { return ImmutableList.builder() .addAll(preStatements) .add(createTableStatement.toString()) - .add(addTableComment(table.getName())) + .add(addTableComment(table)) .addAll(postStatements) .build(); } - private String addTableComment(String tableName) { - return "COMMENT ON TABLE " + schemaNamePrefix() + tableName + " IS 'REALNAME:[" + tableName + "]'"; + private String addTableComment(Table table) { + return "COMMENT ON TABLE " + schemaNamePrefix(table) + table.getName() + " IS 'REALNAME:[" + table.getName() + "]'"; } @@ -234,7 +234,7 @@ public Collection renameTableStatements(Table from, Table to) { .addAll(renameTable) .addAll(renamePk) .addAll(renameSeq) - .add(addTableComment(to.getName())) + .add(addTableComment(to)) .build(); } diff --git a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java index d62bd7004..22a2c38f6 100644 --- a/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java +++ b/morf-postgresql/src/test/java/org/alfasoftware/morf/jdbc/postgresql/TestPostgreSQLDialect.java @@ -125,7 +125,7 @@ protected List expectedCreateTemporaryTableStatements() { return Arrays .asList( "CREATE TEMP TABLE TempTest (id NUMERIC(19) NOT NULL, version INTEGER DEFAULT 0, stringField VARCHAR(3) COLLATE \"POSIX\", intField INTEGER, floatField DECIMAL(13,2) NOT NULL, dateField DATE, booleanField BOOLEAN, charField VARCHAR(1) COLLATE \"POSIX\", blobField BYTEA, bigIntegerField NUMERIC(19) DEFAULT 12345, clobField TEXT, CONSTRAINT TempTest_PK PRIMARY KEY(id))", - "COMMENT ON TABLE testschema.TempTest IS 'REALNAME:[TempTest]'", + "COMMENT ON TABLE TempTest IS 'REALNAME:[TempTest]'", "COMMENT ON COLUMN TempTest.id IS 'REALNAME:[id]/TYPE:[BIG_INTEGER]'", "COMMENT ON COLUMN TempTest.version IS 'REALNAME:[version]/TYPE:[INTEGER]'", "COMMENT ON COLUMN TempTest.stringField IS 'REALNAME:[stringField]/TYPE:[STRING]'", @@ -142,14 +142,14 @@ protected List expectedCreateTemporaryTableStatements() { "CREATE INDEX TempTest_1 ON TempTest (intField,floatField)", "COMMENT ON INDEX TempTest_1 IS 'REALNAME:[TempTest_1]'", "CREATE TEMP TABLE TempAlternate (id NUMERIC(19) NOT NULL, version INTEGER DEFAULT 0, stringField VARCHAR(3) COLLATE \"POSIX\", CONSTRAINT TempAlternate_PK PRIMARY KEY(id))", - "COMMENT ON TABLE testschema.TempAlternate IS 'REALNAME:[TempAlternate]'", + "COMMENT ON TABLE TempAlternate IS 'REALNAME:[TempAlternate]'", "COMMENT ON COLUMN TempAlternate.id IS 'REALNAME:[id]/TYPE:[BIG_INTEGER]'", "COMMENT ON COLUMN TempAlternate.version IS 'REALNAME:[version]/TYPE:[INTEGER]'", "COMMENT ON COLUMN TempAlternate.stringField IS 'REALNAME:[stringField]/TYPE:[STRING]'", "CREATE INDEX TempAlternate_1 ON TempAlternate (stringField)", "COMMENT ON INDEX TempAlternate_1 IS 'REALNAME:[TempAlternate_1]'", "CREATE TEMP TABLE TempNonNull (id NUMERIC(19) NOT NULL, version INTEGER DEFAULT 0, stringField VARCHAR(3) COLLATE \"POSIX\" NOT NULL, intField DECIMAL(8,0) NOT NULL, booleanField BOOLEAN NOT NULL, dateField DATE NOT NULL, blobField BYTEA NOT NULL, CONSTRAINT TempNonNull_PK PRIMARY KEY(id))", - "COMMENT ON TABLE testschema.TempNonNull IS 'REALNAME:[TempNonNull]'", + "COMMENT ON TABLE TempNonNull IS 'REALNAME:[TempNonNull]'", "COMMENT ON COLUMN TempNonNull.id IS 'REALNAME:[id]/TYPE:[BIG_INTEGER]'", "COMMENT ON COLUMN TempNonNull.version IS 'REALNAME:[version]/TYPE:[INTEGER]'", "COMMENT ON COLUMN TempNonNull.stringField IS 'REALNAME:[stringField]/TYPE:[STRING]'", diff --git a/morf-sqlserver/pom.xml b/morf-sqlserver/pom.xml index b86d4cc8e..525bee37b 100755 --- a/morf-sqlserver/pom.xml +++ b/morf-sqlserver/pom.xml @@ -4,7 +4,7 @@ org.alfasoftware morf-parent - 1.3.5-SNAPSHOT + 1.3.7-SNAPSHOT Morf - SQL Server diff --git a/morf-testsupport/pom.xml b/morf-testsupport/pom.xml index c3893e180..68fe99d00 100755 --- a/morf-testsupport/pom.xml +++ b/morf-testsupport/pom.xml @@ -4,7 +4,7 @@ org.alfasoftware morf-parent - 1.3.5-SNAPSHOT + 1.3.7-SNAPSHOT Morf - Test Support diff --git a/pom.xml b/pom.xml index 9b3af6588..510505154 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.alfasoftware morf-parent - 1.3.5-SNAPSHOT + 1.3.7-SNAPSHOT pom Morf