Quantcast
Channel: Liquibase Forums
Viewing all articles
Browse latest Browse all 2993

Possible bug in ForeignKeyComparator.isSameObject() introduced by 3.0.3 release.

$
0
0
There appears to be a bug in:
liquibase-core/src/main/java/liquibase/diff/compare/core/ForeignKeyComparator.java

Which was changed on 8/27/2013 for the 3.0.3 release.

If you have a precondition like this:
        <preConditions>
            <not>
                <foreignKeyConstraintExists foreignKeyTableName="some_table" foreignKeyName="fk_some_key"/>
            </not>
        </preConditions>



You will encounter this error since the ForeignKeyColumns and PrimaryKeyColumns aren't set in the change set:

Caused by: liquibase.exception.MigrationFailedException: Migration failed for change set foo.xml::xxx::zzz:
     Reason:
          src/main/resources/db/activFoundation.xml : liquibase.precondition.core.ForeignKeyExistsPrecondition@5f96f335 : java.lang.NullPointerException

    at liquibase.changelog.ChangeSet.execute(ChangeSet.java:310)
    at liquibase.changelog.visitor.UpdateVisitor.visit(UpdateVisitor.java:28)
    at liquibase.changelog.ChangeLogIterator.run(ChangeLogIterator.java:58)
    at liquibase.Liquibase.update(Liquibase.java:135)
    at org.liquibase.maven.plugins.LiquibaseUpdate.doUpdate(LiquibaseUpdate.java:31)
    at org.liquibase.maven.plugins.AbstractLiquibaseUpdateMojo.performLiquibaseTask(AbstractLiquibaseUpdateMojo.java:24)
    at org.liquibase.maven.plugins.AbstractLiquibaseMojo.execute(AbstractLiquibaseMojo.java:375)
    ... 21 more
Caused by: liquibase.exception.PreconditionErrorException: Precondition Error
    at liquibase.precondition.core.ForeignKeyExistsPrecondition.check(ForeignKeyExistsPrecondition.java:76)
    at liquibase.precondition.core.NotPrecondition.check(NotPrecondition.java:30)
    at liquibase.precondition.core.AndPrecondition.check(AndPrecondition.java:34)
    at liquibase.precondition.core.PreconditionContainer.check(PreconditionContainer.java:199)
    at liquibase.changelog.ChangeSet.execute(ChangeSet.java:274)
    ... 27 more



I downloaded and changed the code to this and rebuilt locally and the issue is resolved.  The change is checking the value of getForeignKeyColumns() and getPrimaryKeyColumns() for  null before doing the comparison.

    public boolean isSameObject(DatabaseObject databaseObject1, DatabaseObject databaseObject2, Database accordingTo, DatabaseObjectComparatorChain chain) {
        if (!(databaseObject1 instanceof ForeignKey && databaseObject2 instanceof ForeignKey)) {
            return false;
        }

        ForeignKey thisForeignKey = (ForeignKey) databaseObject1;
        ForeignKey otherForeignKey = (ForeignKey) databaseObject2;

        if (thisForeignKey.getName() != null && otherForeignKey.getName() != null) {
            if (chain.isSameObject(thisForeignKey, otherForeignKey, accordingTo)) {
                return true;
            }
        }

        if (thisForeignKey.getForeignKeyColumns() != null && thisForeignKey.getPrimaryKeyColumns() != null &&
                otherForeignKey.getForeignKeyColumns() != null && otherForeignKey.getPrimaryKeyColumns() != null) {
            boolean columnsTheSame;
            if (accordingTo.isCaseSensitive()) {
                columnsTheSame = StringUtils.trimToEmpty(thisForeignKey.getForeignKeyColumns()).equals(StringUtils.trimToEmpty(otherForeignKey.getForeignKeyColumns())) &&
                        StringUtils.trimToEmpty(thisForeignKey.getPrimaryKeyColumns()).equals(StringUtils.trimToEmpty(otherForeignKey.getPrimaryKeyColumns()));
            } else {
            columnsTheSame = thisForeignKey.getForeignKeyColumns().equalsIgnoreCase(otherForeignKey.getForeignKeyColumns()) &&
                    thisForeignKey.getPrimaryKeyColumns().equalsIgnoreCase(otherForeignKey.getPrimaryKeyColumns());

            return columnsTheSame &&
                    DatabaseObjectComparatorFactory.getInstance().isSameObject(thisForeignKey.getForeignKeyTable(), otherForeignKey.getForeignKeyTable(), accordingTo) &&
                    DatabaseObjectComparatorFactory.getInstance().isSameObject(thisForeignKey.getPrimaryKeyTable(), otherForeignKey.getPrimaryKeyTable(), accordingTo);
            }

        }
        //false by default
        return false;
    }

I'm not sure this is the optimal solution, but certainly works.

Thanks in advance for help with this.

Andy

Viewing all articles
Browse latest Browse all 2993

Trending Articles