@Override public Sql[] generateSql( final AddAutoIncrementStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) { List<Sql> statements = new ArrayList<Sql>(); // define alter table logic SQLiteDatabase.AlterTableVisitor rename_alter_visitor = new SQLiteDatabase.AlterTableVisitor() { @Override public ColumnConfig[] getColumnsToAdd() { return new ColumnConfig[0]; } @Override public boolean copyThisColumn(ColumnConfig column) { return true; } @Override public boolean createThisColumn(ColumnConfig column) { if (column.getName().equals(statement.getColumnName())) { column.setAutoIncrement(true); column.setType("INTEGER"); } return true; } @Override public boolean createThisIndex(Index index) { return true; } }; try { // alter table for (SqlStatement generatedStatement : SQLiteDatabase.getAlterTableStatements( rename_alter_visitor, database, statement.getCatalogName(), statement.getSchemaName(), statement.getTableName())) { statements.addAll( Arrays.asList( SqlGeneratorFactory.getInstance().generateSql(generatedStatement, database))); } } catch (DatabaseException e) { e.printStackTrace(); } return statements.toArray(new Sql[statements.size()]); }
@Override public boolean acquireLock() { if (hasChangeLogLock) { // We already have a lock return true; } Executor executor = ExecutorService.getInstance().getExecutor(database); try { database.rollback(); // Ensure table created and lock record inserted this.init(); } catch (DatabaseException de) { throw new IllegalStateException("Failed to retrieve lock", de); } try { log.debug("Trying to lock database"); executor.execute(new LockDatabaseChangeLogStatement()); log.debug("Successfully acquired database lock"); hasChangeLogLock = true; database.setCanCacheLiquibaseTableInfo(true); return true; } catch (DatabaseException de) { log.warn( "Lock didn't yet acquired. Will possibly retry to acquire lock. Details: " + de.getMessage()); if (log.isTraceEnabled()) { log.debug(de.getMessage(), de); } return false; } }
@Override public void init() throws DatabaseException { boolean createdTable = false; Executor executor = ExecutorService.getInstance().getExecutor(database); if (!hasDatabaseChangeLogLockTable()) { try { if (log.isTraceEnabled()) { log.trace("Create Database Lock Table"); } executor.execute(new CreateDatabaseChangeLogLockTableStatement()); database.commit(); } catch (DatabaseException de) { log.warn( "Failed to create lock table. Maybe other transaction created in the meantime. Retrying..."); if (log.isTraceEnabled()) { log.trace(de.getMessage(), de); // Log details at trace level } database.rollback(); throw new LockRetryException(de); } log.debugf( "Created database lock table with name: %s", database.escapeTableName( database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), database.getDatabaseChangeLogLockTableName())); try { Field field = Reflections.findDeclaredField( StandardLockService.class, "hasDatabaseChangeLogLockTable"); Reflections.setAccessible(field); field.set(CustomLockService.this, true); } catch (IllegalAccessException iae) { throw new RuntimeException(iae); } createdTable = true; } if (!isDatabaseChangeLogLockTableInitialized(createdTable)) { try { if (log.isTraceEnabled()) { log.trace("Initialize Database Lock Table"); } executor.execute(new InitializeDatabaseChangeLogLockTableStatement()); database.commit(); } catch (DatabaseException de) { log.warn( "Failed to insert first record to the lock table. Maybe other transaction inserted in the meantime. Retrying..."); if (log.isTraceEnabled()) { log.trace(de.getMessage(), de); // Log details at trace level } database.rollback(); throw new LockRetryException(de); } log.debug("Initialized record in the database lock table"); } // repeid doesn't support Derby, but keep it for sure... if (executor.updatesDatabase() && database instanceof DerbyDatabase && ((DerbyDatabase) database) .supportsBooleanDataType()) { // check if the changelog table is of an old smallint vs. // boolean format String lockTable = database.escapeTableName( database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), database.getDatabaseChangeLogLockTableName()); Object obj = executor.queryForObject( new RawSqlStatement( "select min(locked) as test from " + lockTable + " fetch first row only"), Object.class); if (!(obj instanceof Boolean)) { // wrong type, need to recreate table executor.execute( new DropTableStatement( database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), database.getDatabaseChangeLogLockTableName(), false)); executor.execute(new CreateDatabaseChangeLogLockTableStatement()); executor.execute(new InitializeDatabaseChangeLogLockTableStatement()); } } }