Uploaded image for project: 'Liquibase Core'
  1. CORE-3080

NPE while running diff against a table where primary key has PK_SEQ=2

    Details

    • Type: Bug
    • Status: Open
    • Priority: Critical
    • Resolution: Unresolved
    • Affects Version/s: 4.0.0, 3.5.3, 3.6.0
    • Fix Version/s: None
    • Environment:

      Database server: MySQL 5.7.18 on Ubuntu 16.04.1 LTS and CentOS 6
      jdbc driver: mariadb-java-client-1.1.1

      Description

      I am trying to run diffChangeLog against a database that has a table that looks like this:

      mysql> show create table areas_views;
      +-------------+---------------------------------------------------------------------------------
      | Table       | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                  |
      +-------------+---------------------------------------------------------------------------------
      | areas_views | CREATE TABLE `areas_views` (
        `areas_id` int(11) NOT NULL,
        `views_id` int(11) NOT NULL,
        UNIQUE KEY `UK_kkive47ql74yxypnqsbpy9odd` (`views_id`),
        KEY `FK_6i05a4cfhkfvfjxh46awjrofi` (`areas_id`),
        CONSTRAINT `FK_6i05a4cfhkfvfjxh46awjrofi` FOREIGN KEY (`areas_id`) REFERENCES `areas` (`id`),
        CONSTRAINT `FK_kkive47ql74yxypnqsbpy9odd` FOREIGN KEY (`views_id`) REFERENCES `views` (`id`)
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
      +-------------+---------------------------------------------------------------------------------
      1 row in set (0.00 sec)
      
      

      This table has been created by hibernate 4.x and is a "connector" table used to implement a many-to-many relation between two models.

      Runninng liquibase against this database ends with the following exception:

      11:45:47.042 [main] DEBUG liquibase - Executing QUERY database command: select const.CONSTRAINT_NAME, COLUMN_NAME from information_schema.table_constraints const join information_schema.key_column_usage col on const.constraint_schema=col.constraint_schema and const.table_name=col.table_name and const.constraint_name=col.constraint_name where const.constraint_schema='nw2v20' and const.table_name='areas_views' and const.constraint_name='UK_kkive47ql74yxypnqsbpy9odd'order by ordinal_position
      Unexpected error running Liquibase: java.lang.NullPointerException
      
      Disconnected from the target VM, address: '127.0.0.1:63156', transport: 'socket'
      
      
      For more information, use the --logLevel flag
      11:45:47.120 [main] ERROR liquibase - java.lang.NullPointerException
      liquibase.exception.LiquibaseException: liquibase.command.CommandExecutionException: java.lang.NullPointerException
      	at liquibase.integration.commandline.CommandLineUtils.doDiffToChangeLog(CommandLineUtils.java:160) ~[classes/:na]
      	at liquibase.integration.commandline.Main.doMigration(Main.java:961) [classes/:na]
      	at liquibase.integration.commandline.Main.run(Main.java:178) [classes/:na]
      	at liquibase.integration.commandline.Main.main(Main.java:97) [classes/:na]
      Caused by: liquibase.command.CommandExecutionException: java.lang.NullPointerException
      	at liquibase.command.AbstractCommand.execute(AbstractCommand.java:13) ~[classes/:na]
      	at liquibase.integration.commandline.CommandLineUtils.doDiffToChangeLog(CommandLineUtils.java:158) ~[classes/:na]
      	... 3 common frames omitted
      Caused by: java.lang.NullPointerException: null
      	at liquibase.structure.core.Index.setColumns(Index.java:100) ~[classes/:na]
      	at liquibase.snapshot.jvm.PrimaryKeySnapshotGenerator.snapshotObject(PrimaryKeySnapshotGenerator.java:64) ~[classes/:na]
      	at liquibase.snapshot.jvm.JdbcSnapshotGenerator.snapshot(JdbcSnapshotGenerator.java:60) ~[classes/:na]
      	at liquibase.snapshot.SnapshotGeneratorChain.snapshot(SnapshotGeneratorChain.java:50) ~[classes/:na]
      	at liquibase.snapshot.DatabaseSnapshot.include(DatabaseSnapshot.java:196) ~[classes/:na]
      	at liquibase.snapshot.DatabaseSnapshot.replaceObject(DatabaseSnapshot.java:263) ~[classes/:na]
      	at liquibase.snapshot.DatabaseSnapshot.includeNestedObjects(DatabaseSnapshot.java:228) ~[classes/:na]
      	at liquibase.snapshot.DatabaseSnapshot.include(DatabaseSnapshot.java:210) ~[classes/:na]
      	at liquibase.snapshot.DatabaseSnapshot.replaceObject(DatabaseSnapshot.java:283) ~[classes/:na]
      	at liquibase.snapshot.DatabaseSnapshot.replaceObject(DatabaseSnapshot.java:305) ~[classes/:na]
      	at liquibase.snapshot.DatabaseSnapshot.includeNestedObjects(DatabaseSnapshot.java:228) ~[classes/:na]
      	at liquibase.snapshot.DatabaseSnapshot.include(DatabaseSnapshot.java:210) ~[classes/:na]
      	at liquibase.snapshot.DatabaseSnapshot.init(DatabaseSnapshot.java:73) ~[classes/:na]
      	at liquibase.snapshot.DatabaseSnapshot.<init>(DatabaseSnapshot.java:47) ~[classes/:na]
      	at liquibase.snapshot.JdbcDatabaseSnapshot.<init>(JdbcDatabaseSnapshot.java:25) ~[classes/:na]
      	at liquibase.snapshot.SnapshotGeneratorFactory.createSnapshot(SnapshotGeneratorFactory.java:134) ~[classes/:na]
      	at liquibase.snapshot.SnapshotGeneratorFactory.createSnapshot(SnapshotGeneratorFactory.java:123) ~[classes/:na]
      	at liquibase.command.DiffCommand.createTargetSnapshot(DiffCommand.java:166) ~[classes/:na]
      	at liquibase.command.DiffCommand.createDiffResult(DiffCommand.java:141) ~[classes/:na]
      	at liquibase.command.DiffToChangeLogCommand.run(DiffToChangeLogCommand.java:51) ~[classes/:na]
      	at liquibase.command.AbstractCommand.execute(AbstractCommand.java:8) ~[classes/:na]
      	... 4 common frames omitted
      
      
      

      it crashes in Index.java, but interersting stuff actually happens in
      PrimaryKeySnapshotGenerator.snapshotObject() when it reads the schema and gets the following:

      rs = {ArrayList@1806}  size = 1
       0 = {CachedRow@1842} 
        row = {LinkedHashMap@1843}  size = 6
         0 = {LinkedHashMap$Entry@1846} "TABLE_CAT" -> "nw2v20"
         1 = {LinkedHashMap$Entry@1847} "TABLE_SCHEM" -> "null"
         2 = {LinkedHashMap$Entry@1848} "TABLE_NAME" -> "areas_views"
         3 = {LinkedHashMap$Entry@1849} "COLUMN_NAME" -> "views_id"
         4 = {LinkedHashMap$Entry@1850} "KEY_SEQ" -> "2"
         5 = {LinkedHashMap$Entry@1851} "PK_NAME" -> "null"
      

      as you can see, there is only one key and its KEY_SEQ=2. When it makes the call

      returnKey.addColumn(position - 1, new Column(columnName).setRelation(((PrimaryKey) example).getTable()));
      

      it has position=2, so it inserts the column as an item with index 1 into the list. It never has a chance to insert an item with index 0 to this list, which means it ends up with the list that has a "hole". Subsequent call to exampleIndex.setColumns(returnKey.getColumns()); causes NPE because of that.

        Attachments

          Activity

            People

            • Reporter:
              vadim Vadim Kurland
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated: