diff --git a/src/main/java/cz/startnet/utils/pgdiff/PgDiff.java b/src/main/java/cz/startnet/utils/pgdiff/PgDiff.java index 1c079862..ac8aba5f 100755 --- a/src/main/java/cz/startnet/utils/pgdiff/PgDiff.java +++ b/src/main/java/cz/startnet/utils/pgdiff/PgDiff.java @@ -277,10 +277,10 @@ private static void updateSchemas(final PrintWriter writer, writer, arguments, oldSchema, newSchema, searchPathHelper); PgDiffViews.dropViews( writer, oldSchema, newSchema, searchPathHelper); - PgDiffConstraints.dropConstraints( - writer, oldSchema, newSchema, true, searchPathHelper); PgDiffConstraints.dropConstraints( writer, oldSchema, newSchema, false, searchPathHelper); + PgDiffConstraints.dropConstraints( + writer, oldSchema, newSchema, true, searchPathHelper); PgDiffIndexes.dropIndexes( writer, oldSchema, newSchema, searchPathHelper); PgDiffTables.dropClusters( @@ -289,8 +289,9 @@ private static void updateSchemas(final PrintWriter writer, writer, oldSchema, newSchema, searchPathHelper); PgDiffSequences.dropSequences( writer, oldSchema, newSchema, searchPathHelper); - PgDiffPolicies.dropPolicies( - writer, oldSchema, newSchema, searchPathHelper); + if(!PgDiffUtils.isNoPolicies()) + PgDiffPolicies.dropPolicies( + writer, oldSchema, newSchema, searchPathHelper); PgDiffSequences.createSequences( writer, oldSchema, newSchema, searchPathHelper); PgDiffSequences.alterSequences( @@ -320,10 +321,12 @@ private static void updateSchemas(final PrintWriter writer, writer, oldSchema, newSchema, searchPathHelper); PgDiffViews.alterViews( writer, oldSchema, newSchema, searchPathHelper); - PgDiffPolicies.createPolicies( - writer, oldSchema, newSchema, searchPathHelper); - PgDiffPolicies.alterPolicies( + if(!PgDiffUtils.isNoPolicies()){ + PgDiffPolicies.createPolicies( + writer, oldSchema, newSchema, searchPathHelper); + PgDiffPolicies.alterPolicies( writer, oldSchema, newSchema, searchPathHelper); + } PgDiffFunctions.alterComments( writer, oldSchema, newSchema, searchPathHelper); PgDiffConstraints.alterComments( diff --git a/src/main/java/cz/startnet/utils/pgdiff/PgDiffArguments.java b/src/main/java/cz/startnet/utils/pgdiff/PgDiffArguments.java index ed2ac2a0..4bd6e6f6 100755 --- a/src/main/java/cz/startnet/utils/pgdiff/PgDiffArguments.java +++ b/src/main/java/cz/startnet/utils/pgdiff/PgDiffArguments.java @@ -267,6 +267,10 @@ public boolean parse(final PrintWriter writer, final String[] args) { setVersion(true); } else if ("--drop-if-exists".equals(args[i])) { PgDiffUtils.setUseExists(true); + } else if ("--no-policies".equals(args[i])) { + PgDiffUtils.setNoPolicies(true); + } else if ("--no-alter-row-level-security".equals(args[i])) { + PgDiffUtils.setNoAlterRLS(true); } else { writer.print(Resources.getString("ErrorUnknownOption")); writer.print(": "); diff --git a/src/main/java/cz/startnet/utils/pgdiff/PgDiffConstraints.java b/src/main/java/cz/startnet/utils/pgdiff/PgDiffConstraints.java index d64cab28..9c2305e7 100755 --- a/src/main/java/cz/startnet/utils/pgdiff/PgDiffConstraints.java +++ b/src/main/java/cz/startnet/utils/pgdiff/PgDiffConstraints.java @@ -85,6 +85,20 @@ public static void dropConstraints(final PrintWriter writer, writer.println(constraint.getDropSQL()); } } + if(oldSchema!=null){ + for (final PgTable oldTable : oldSchema.getTables()) { + //oldTable doesn't exit any more -> delete all her constraints + if(newSchema.getTable(oldTable.getName())==null){ + // Drop constraints that no more exist + for (final PgConstraint constraint : + getDropConstraints(oldTable, null, primaryKey)) { + searchPathHelper.outputSearchPath(writer); + writer.println(); + writer.println(constraint.getDropSQL()); + } + } + } + } } /** @@ -105,10 +119,11 @@ private static List getDropConstraints(final PgTable oldTable, @SuppressWarnings("CollectionWithoutInitialCapacity") final List list = new ArrayList(); - if (newTable != null && oldTable != null) { + if (oldTable != null) { for (final PgConstraint constraint : oldTable.getConstraints()) { if (constraint.isPrimaryKeyConstraint() == primaryKey - && (!newTable.containsConstraint(constraint.getName()) + && (newTable==null + || !newTable.containsConstraint(constraint.getName()) || !newTable.getConstraint(constraint.getName()).equals( constraint))) { list.add(constraint); diff --git a/src/main/java/cz/startnet/utils/pgdiff/PgDiffTables.java b/src/main/java/cz/startnet/utils/pgdiff/PgDiffTables.java index bca06eee..fadcf61c 100755 --- a/src/main/java/cz/startnet/utils/pgdiff/PgDiffTables.java +++ b/src/main/java/cz/startnet/utils/pgdiff/PgDiffTables.java @@ -142,7 +142,8 @@ public static void alterTables(final PrintWriter writer, alterOwnerTo(writer, oldTable, newTable, searchPathHelper); alterPrivileges(writer, oldTable, newTable, searchPathHelper); alterPrivilegesColumns(writer, oldTable, newTable, searchPathHelper); - alterRLS(writer, oldTable, newTable, searchPathHelper); + if(!PgDiffUtils.isNoAlterRLS()) + alterRLS(writer, oldTable, newTable, searchPathHelper); } } diff --git a/src/main/java/cz/startnet/utils/pgdiff/PgDiffTriggers.java b/src/main/java/cz/startnet/utils/pgdiff/PgDiffTriggers.java index 523dccbd..0bdef414 100755 --- a/src/main/java/cz/startnet/utils/pgdiff/PgDiffTriggers.java +++ b/src/main/java/cz/startnet/utils/pgdiff/PgDiffTriggers.java @@ -77,6 +77,18 @@ public static void dropTriggers(final PrintWriter writer, writer.println(trigger.getDropSQL()); } } + if(oldSchema!=null){ + for (final PgRelation oldRelation : oldSchema.getRels()) { + //oldRelation doesn't exit any more -> delete all her triggers + if(newSchema.getRelation(oldRelation.getName())==null){ + for(final PgTrigger trigger : oldRelation.getTriggers()){ + searchPathHelper.outputSearchPath(writer); + writer.println(); + writer.println(trigger.getDropSQL()); + } + } + } + } } /** diff --git a/src/main/java/cz/startnet/utils/pgdiff/PgDiffUtils.java b/src/main/java/cz/startnet/utils/pgdiff/PgDiffUtils.java index b4554952..3f1186f6 100755 --- a/src/main/java/cz/startnet/utils/pgdiff/PgDiffUtils.java +++ b/src/main/java/cz/startnet/utils/pgdiff/PgDiffUtils.java @@ -480,6 +480,18 @@ public class PgDiffUtils { * Determine if use CREATE IF NOT EXISTS OR DROP IF EXISTS where is possible */ private static boolean useIfExists; + + + /** + * Determine if no create policies statements + */ + private static boolean noUsePolicies; + + + /** + * Determine if no create RLS statements in alter + */ + private static boolean noAlterRLS; /** * If name contains only lower case characters and digits and is not @@ -565,6 +577,27 @@ public static void setUseExists(final boolean useExists) { useIfExists = useExists; } + + public static void setNoPolicies(final boolean noPolicies) { + + noUsePolicies = noPolicies; + } + + public static void setNoAlterRLS(final boolean noRLS) { + + noAlterRLS = noRLS; + } + + + public static boolean isNoPolicies() { + + return noUsePolicies; + } + + public static boolean isNoAlterRLS() { + + return noAlterRLS; + } /** * Creates a new PgDiffUtils object. diff --git a/src/main/java/cz/startnet/utils/pgdiff/loader/PgDumpLoader.java b/src/main/java/cz/startnet/utils/pgdiff/loader/PgDumpLoader.java index 57a0cbd4..94d6c453 100644 --- a/src/main/java/cz/startnet/utils/pgdiff/loader/PgDumpLoader.java +++ b/src/main/java/cz/startnet/utils/pgdiff/loader/PgDumpLoader.java @@ -114,7 +114,7 @@ public class PgDumpLoader { //NOPMD * Pattern for testing whether it is CREATE TRIGGER statement. */ private static final Pattern PATTERN_CREATE_TRIGGER = Pattern.compile( - "^CREATE[\\s]+TRIGGER[\\s]+.*$", + "^CREATE[\\s]+(CONSTRAINT){0,1}[\\s]*TRIGGER[\\s]+.*$", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); /** * Pattern for testing whether it is CREATE FUNCTION or CREATE OR REPLACE diff --git a/src/main/java/cz/startnet/utils/pgdiff/parsers/CreateTriggerParser.java b/src/main/java/cz/startnet/utils/pgdiff/parsers/CreateTriggerParser.java index 3b5a9953..887ed8b1 100644 --- a/src/main/java/cz/startnet/utils/pgdiff/parsers/CreateTriggerParser.java +++ b/src/main/java/cz/startnet/utils/pgdiff/parsers/CreateTriggerParser.java @@ -17,29 +17,39 @@ public class CreateTriggerParser { /** - * Parses CREATE TRIGGER statement. + * Parses CREATE [CONSTRAINT] TRIGGER statement. * * @param database database - * @param statement CREATE TRIGGER statement + * @param statement CREATE [CONSTRAINT] TRIGGER statement * @param ignoreSlonyTriggers whether Slony triggers should be ignored */ public static void parse(final PgDatabase database, final String statement, final boolean ignoreSlonyTriggers) { - final Parser parser = new Parser(statement); - parser.expect("CREATE", "TRIGGER"); + final PgTrigger trigger = new PgTrigger(); + final Parser parser = new Parser(statement); + + parser.expect("CREATE"); + if(parser.expectOptional("CONSTRAINT")) + trigger.setConstraint(true); + parser.expect("TRIGGER"); + final String triggerName = parser.parseIdentifier(); final String objectName = ParserUtils.getObjectName(triggerName); - final PgTrigger trigger = new PgTrigger(); trigger.setName(objectName); - - if (parser.expectOptional("BEFORE")) { - trigger.setEventTimeQualification(PgTrigger.EventTimeQualification.before); - } else if (parser.expectOptional("AFTER")) { - trigger.setEventTimeQualification(PgTrigger.EventTimeQualification.after); - } else if (parser.expectOptional("INSTEAD OF")) { - trigger.setEventTimeQualification(PgTrigger.EventTimeQualification.instead_of); + + if(trigger.isConstraint()){ + parser.expect("AFTER"); + trigger.setEventTimeQualification(PgTrigger.EventTimeQualification.after); + } else { + if (parser.expectOptional("BEFORE")) { + trigger.setEventTimeQualification(PgTrigger.EventTimeQualification.before); + } else if (parser.expectOptional("AFTER")) { + trigger.setEventTimeQualification(PgTrigger.EventTimeQualification.after); + } else if (parser.expectOptional("INSTEAD OF")) { + trigger.setEventTimeQualification(PgTrigger.EventTimeQualification.instead_of); + } } boolean first = true; @@ -75,6 +85,23 @@ public static void parse(final PgDatabase database, final String relationName = parser.parseIdentifier(); trigger.setRelationName(ParserUtils.getObjectName(relationName)); + + if(trigger.isConstraint()){ + if(parser.expectOptional("DEFERRABLE")){ + trigger.setDeferrable(true); + if(parser.expectOptional("INITIALLY","DEFERRED")){ + trigger.setDeferred(true); + }else if(parser.expectOptional("INITIALLY","IMMEDIATE")){ + trigger.setDeferred(false); + }else{ + trigger.setDeferred(false); + } + }else if(parser.expectOptional("NOT","DEFERRABLE")){ + trigger.setDeferrable(false); + }else { + trigger.setDeferrable(false); + } + } if (parser.expectOptional("FOR")) { parser.expectOptional("EACH"); diff --git a/src/main/java/cz/startnet/utils/pgdiff/schema/PgConstraint.java b/src/main/java/cz/startnet/utils/pgdiff/schema/PgConstraint.java index 6cefafa0..ed370bda 100755 --- a/src/main/java/cz/startnet/utils/pgdiff/schema/PgConstraint.java +++ b/src/main/java/cz/startnet/utils/pgdiff/schema/PgConstraint.java @@ -56,7 +56,6 @@ public String getCreationSQL() { sbSQL.append(PgDiffUtils.getQuotedName(getTableName())); sbSQL.append(System.getProperty("line.separator")); sbSQL.append("\tADD CONSTRAINT "); - sbSQL.append(PgDiffUtils.getCreateIfNotExists()); sbSQL.append(PgDiffUtils.getQuotedName(getName())); sbSQL.append(' '); sbSQL.append(getDefinition()); diff --git a/src/main/java/cz/startnet/utils/pgdiff/schema/PgTrigger.java b/src/main/java/cz/startnet/utils/pgdiff/schema/PgTrigger.java index 9928925b..052f6709 100755 --- a/src/main/java/cz/startnet/utils/pgdiff/schema/PgTrigger.java +++ b/src/main/java/cz/startnet/utils/pgdiff/schema/PgTrigger.java @@ -43,6 +43,27 @@ public static String toString(EventTimeQualification eventTimeQualification) { return stringRepresentation.get(eventTimeQualification); } } + + /** + * Whether the trigger is contraint. + */ + private boolean constraint; + + /** + * This controls whether the constraint can be deferred. + * A constraint that is not deferrable will be checked immediately after every command. + * Checking of constraints that are deferrable can be postponed until the end of the transaction. + */ + + private boolean deferrable; + + /** + * If a constraint is deferrable, this clause specifies the default time to check the constraint. + * If the constraint is INITIALLY IMMEDIATE, it is checked after each statement. + * This is the default. If the constraint is INITIALLY DEFERRED, it is checked only at the end of the transaction. + */ + + private boolean deferred; /** * Function name and arguments that should be fired on the trigger. @@ -139,14 +160,17 @@ public void setComment(final String comment) { */ public String getCreationSQL() { final StringBuilder sbSQL = new StringBuilder(100); - sbSQL.append("CREATE TRIGGER "); + sbSQL.append("CREATE"); + if(isConstraint()) + sbSQL.append(" CONSTRAINT"); + sbSQL.append(" TRIGGER "); sbSQL.append(PgDiffUtils.getQuotedName(getName())); sbSQL.append(System.getProperty("line.separator")); sbSQL.append("\t"); sbSQL.append(EventTimeQualification.toString(getEventTimeQualification())); boolean firstEvent = true; - + if (isOnInsert()) { sbSQL.append(" INSERT"); firstEvent = false; @@ -197,6 +221,20 @@ public String getCreationSQL() { sbSQL.append(" ON "); sbSQL.append(PgDiffUtils.getQuotedName(getRelationName())); + if(isConstraint()){ + sbSQL.append(System.getProperty("line.separator")); + sbSQL.append("\t"); + if(isDeferrable()){ + sbSQL.append(" DEFERRABLE "); + if(isDeferred()){ + sbSQL.append(" INITIALLY DEFERRED "); + }else{ + sbSQL.append(" INITIALLY IMMEDIATE "); + } + }else { + sbSQL.append(" NOT DEFERRABLE "); + } + } sbSQL.append(System.getProperty("line.separator")); sbSQL.append("\tFOR EACH "); sbSQL.append(isForEachRow() ? "ROW" : "STATEMENT"); @@ -237,6 +275,60 @@ public String getDropSQL() { return "DROP TRIGGER " + PgDiffUtils.getDropIfExists() + PgDiffUtils.getQuotedName(getName()) + " ON " + PgDiffUtils.getQuotedName(getRelationName()) + ";"; } + + /** + * Setter for {@link #constraint}. + * + * @param constraint {@link #constraint} + */ + public void setConstraint(final boolean constraint) { + this.constraint = constraint; + } + + /** + * Getter for {@link #constraint}. + * + * @return {@link #constraint} + */ + public boolean isConstraint() { + return constraint; + } + + /** + * Setter for {@link #deferrable}. + * + * @param deferrable {@link #deferrable} + */ + public void setDeferrable(final boolean deferrable) { + this.deferrable = deferrable; + } + + /** + * Getter for {@link #deferrable}. + * + * @return {@link #deferrable} + */ + public boolean isDeferrable() { + return deferrable; + } + + /** + * Setter for {@link #deferred}. + * + * @param deferred {@link #deferred} + */ + public void setDeferred(final boolean deferred) { + this.deferred = deferred; + } + + /** + * Getter for {@link #deferred}. + * + * @return {@link #deferred} + */ + public boolean isDeferred() { + return deferred; + } /** * Setter for {@link #forEachRow}. @@ -434,7 +526,10 @@ public boolean equals(final Object object) { && (onInsert == trigger.isOnInsert()) && (onUpdate == trigger.isOnUpdate()) && (onTruncate == trigger.isOnTruncate()) - && relationName.equals(trigger.getRelationName()); + && relationName.equals(trigger.getRelationName()) + && constraint == trigger.isConstraint() + && deferrable == trigger.isDeferrable() + && deferred == trigger.isDeferred(); if (equals) { final List sorted1 = diff --git a/src/test/resources/cz/startnet/utils/pgdiff/add_constraint_diff.sql b/src/test/resources/cz/startnet/utils/pgdiff/add_constraint_diff.sql index cf526329..1399b967 100644 --- a/src/test/resources/cz/startnet/utils/pgdiff/add_constraint_diff.sql +++ b/src/test/resources/cz/startnet/utils/pgdiff/add_constraint_diff.sql @@ -1,3 +1,3 @@ ALTER TABLE testtable - ADD CONSTRAINT IF NOT EXISTS field4check CHECK (((field4 > (-5.0)::double precision) AND (field4 < (5.0)::double precision))); + ADD CONSTRAINT field4check CHECK (((field4 > (-5.0)::double precision) AND (field4 < (5.0)::double precision))); diff --git a/src/test/resources/cz/startnet/utils/pgdiff/add_table_bug102_diff.sql b/src/test/resources/cz/startnet/utils/pgdiff/add_table_bug102_diff.sql index 43c2d3bb..4c0354fb 100644 --- a/src/test/resources/cz/startnet/utils/pgdiff/add_table_bug102_diff.sql +++ b/src/test/resources/cz/startnet/utils/pgdiff/add_table_bug102_diff.sql @@ -7,4 +7,4 @@ CREATE TABLE IF NOT EXISTS "procedureresult$Operation" ( ALTER TABLE "procedureresult$Operation" OWNER TO fordfrog; ALTER TABLE "procedureresult$Operation" - ADD CONSTRAINT IF NOT EXISTS $1 FOREIGN KEY (result_id) REFERENCES testtable(field1) ON UPDATE RESTRICT ON DELETE RESTRICT; + ADD CONSTRAINT $1 FOREIGN KEY (result_id) REFERENCES testtable(field1) ON UPDATE RESTRICT ON DELETE RESTRICT; diff --git a/src/test/resources/cz/startnet/utils/pgdiff/add_unique_constraint_diff.sql b/src/test/resources/cz/startnet/utils/pgdiff/add_unique_constraint_diff.sql index ce282b33..4b2f8461 100644 --- a/src/test/resources/cz/startnet/utils/pgdiff/add_unique_constraint_diff.sql +++ b/src/test/resources/cz/startnet/utils/pgdiff/add_unique_constraint_diff.sql @@ -1,6 +1,6 @@ ALTER TABLE inventoryitemsupplier - ADD CONSTRAINT IF NOT EXISTS inventoryitemsupplier_pkey PRIMARY KEY (id); + ADD CONSTRAINT inventoryitemsupplier_pkey PRIMARY KEY (id); ALTER TABLE inventoryitemsupplier - ADD CONSTRAINT IF NOT EXISTS inventoryitemsupplier_5a808b9c_key UNIQUE (inventoryitemid, partneridentificationid); + ADD CONSTRAINT inventoryitemsupplier_5a808b9c_key UNIQUE (inventoryitemid, partneridentificationid); diff --git a/src/test/resources/cz/startnet/utils/pgdiff/modify_constraint_diff.sql b/src/test/resources/cz/startnet/utils/pgdiff/modify_constraint_diff.sql index a13f3633..039a2b29 100644 --- a/src/test/resources/cz/startnet/utils/pgdiff/modify_constraint_diff.sql +++ b/src/test/resources/cz/startnet/utils/pgdiff/modify_constraint_diff.sql @@ -3,4 +3,4 @@ ALTER TABLE testtable DROP CONSTRAINT IF EXISTS field4check; ALTER TABLE testtable - ADD CONSTRAINT IF NOT EXISTS field4check CHECK ((field4 > (0.0)::double precision)); + ADD CONSTRAINT field4check CHECK ((field4 > (0.0)::double precision));