use of liquibase.database.core.PostgresDatabase in project liquibase by liquibase.
the class BooleanTypeTest method postgresqlBitStringError.
@Test(expected = UnexpectedLiquibaseException.class)
public void postgresqlBitStringError() {
BooleanType bt = new BooleanType();
bt.finishInitialization("bit(12)");
assertNotEquals("b'1'", bt.objectToSql("'12'", new PostgresDatabase()));
}
use of liquibase.database.core.PostgresDatabase in project liquibase by liquibase.
the class AbstractIntegrationTest method wipeDatabase.
/**
* Wipes all Liquibase schemas in the database before testing starts. This includes the DATABASECHANGELOG/LOCK
* tables.
*/
protected void wipeDatabase() {
emptySchemas.clear();
try {
// TODO the cleaner solution would be to have a noCachingHasObject() Method in SnapshotGeneratorFactory
try {
if (database.getConnection() != null) {
String sql = "DROP TABLE " + database.getDatabaseChangeLogLockTableName();
for (SqlListener listener : Scope.getCurrentScope().getListeners(SqlListener.class)) {
listener.writeSqlWillRun(sql);
}
((JdbcConnection) database.getConnection()).getUnderlyingConnection().createStatement().executeUpdate(sql);
database.commit();
}
} catch (SQLException e) {
if (database instanceof PostgresDatabase) {
// throws "current transaction is aborted" unless we roll back the connection
database.rollback();
}
}
SnapshotGeneratorFactory.resetAll();
LockService lockService = LockServiceFactory.getInstance().getLockService(database);
emptyTestSchema(CatalogAndSchema.DEFAULT.getCatalogName(), CatalogAndSchema.DEFAULT.getSchemaName(), database);
SnapshotGeneratorFactory factory = SnapshotGeneratorFactory.getInstance();
if (database.supportsSchemas()) {
emptyTestSchema(null, ALT_SCHEMA, database);
}
if (supportsAltCatalogTests()) {
if (database.supportsSchemas() && database.supportsCatalogs()) {
emptyTestSchema(ALT_CATALOG, ALT_SCHEMA, database);
}
}
/*
* There is a special treatment for identifiers in the case when (a) the RDBMS does NOT support
* schemas AND (b) the RDBMS DOES support catalogs AND (c) someone uses "schemaName=..." in a
* Liquibase ChangeSet. In this case, AbstractJdbcDatabase.escapeObjectName assumes the author
* was intending to write "catalog=..." and transparently rewrites the expression.
* For us, this means that we have to wipe both ALT_SCHEMA and ALT_CATALOG to be sure we
* are doing a thorough cleanup.
*/
CatalogAndSchema[] alternativeLocations = new CatalogAndSchema[] { new CatalogAndSchema(ALT_CATALOG, null), new CatalogAndSchema(null, ALT_SCHEMA), new CatalogAndSchema("LBCAT2", database.getDefaultSchemaName()), new CatalogAndSchema(null, "LBCAT2"), new CatalogAndSchema("lbcat2", database.getDefaultSchemaName()), new CatalogAndSchema(null, "lbcat2") };
for (CatalogAndSchema location : alternativeLocations) {
emptyTestSchema(location.getCatalogName(), location.getSchemaName(), database);
}
database.commit();
SnapshotGeneratorFactory.resetAll();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of liquibase.database.core.PostgresDatabase in project liquibase by liquibase.
the class AbstractIntegrationTest method testRerunDiffChangeLog.
@Test
public void testRerunDiffChangeLog() throws Exception {
assumeNotNull(this.getDatabase());
for (int run = 0; run < 2; run++) {
// run once outputting data as insert, once as csv
boolean outputCsv = run == 1;
runCompleteChangeLog();
SnapshotControl snapshotControl = new SnapshotControl(database);
DatabaseSnapshot originalSnapshot = SnapshotGeneratorFactory.getInstance().createSnapshot(database.getDefaultSchema(), database, snapshotControl);
CompareControl compareControl = new CompareControl();
// database returns different data even if the same
compareControl.addSuppressedField(Column.class, "defaultValue");
// database returns different data even if the same
compareControl.addSuppressedField(Column.class, "autoIncrementInformation");
if (database instanceof OracleDatabase) {
// database returns different nvarchar2 info even though they are the same
compareControl.addSuppressedField(Column.class, "type");
// database returns different nullable on views, e.g. v_person.id
compareControl.addSuppressedField(Column.class, "nullable");
}
if (database instanceof PostgresDatabase) {
// database returns different nvarchar2 info even though they are the same
compareControl.addSuppressedField(Column.class, "type");
}
DiffOutputControl diffOutputControl = new DiffOutputControl();
File tempFile = tempDirectory.getRoot().createTempFile("liquibase-test", ".xml");
if (outputCsv) {
diffOutputControl.setDataDir(new File(tempFile.getParentFile(), "liquibase-data").getCanonicalPath().replaceFirst("\\w:", ""));
}
DiffResult diffResult = DiffGeneratorFactory.getInstance().compare(database, null, compareControl);
FileOutputStream output = new FileOutputStream(tempFile);
try {
new DiffToChangeLog(diffResult, new DiffOutputControl()).print(new PrintStream(output));
output.flush();
} finally {
output.close();
}
Liquibase liquibase = createLiquibase(tempFile.getName());
clearDatabase();
DatabaseSnapshot emptySnapshot = SnapshotGeneratorFactory.getInstance().createSnapshot(database.getDefaultSchema(), database, new SnapshotControl(database));
// run again to test changelog testing logic
liquibase = createLiquibase(tempFile.getName());
try {
liquibase.update(this.contexts);
} catch (ValidationFailedException e) {
e.printDescriptiveError(System.out);
throw e;
}
DatabaseSnapshot migratedSnapshot = SnapshotGeneratorFactory.getInstance().createSnapshot(database.getDefaultSchema(), database, new SnapshotControl(database));
DiffResult finalDiffResult = DiffGeneratorFactory.getInstance().compare(originalSnapshot, migratedSnapshot, compareControl);
try {
assertTrue("recreating the database from the generated change log should cause both 'before' and " + "'after' snapshots to be equal.", finalDiffResult.areEqual());
} catch (AssertionError e) {
new DiffToReport(finalDiffResult, System.err).print();
throw e;
}
// diff to empty and drop all
DiffResult emptyDiffResult = DiffGeneratorFactory.getInstance().compare(emptySnapshot, migratedSnapshot, compareControl);
output = new FileOutputStream(tempFile);
try {
new DiffToChangeLog(emptyDiffResult, new DiffOutputControl(true, true, true, null)).print(new PrintStream(output));
output.flush();
} finally {
output.close();
}
liquibase = createLiquibase(tempFile.getName());
Scope.getCurrentScope().getLog(getClass()).info("updating from " + tempFile.getCanonicalPath());
try {
liquibase.update(this.contexts);
} catch (LiquibaseException e) {
throw e;
}
DatabaseSnapshot emptyAgainSnapshot = SnapshotGeneratorFactory.getInstance().createSnapshot(database.getDefaultSchema(), database, new SnapshotControl(database));
assertEquals("a database that was 'updated' to an empty snapshot should only have 2 tables left: " + "the database change log table and the lock table.", 2, emptyAgainSnapshot.get(Table.class).size());
assertEquals("a database that was 'updated' to an empty snapshot should not contain any views.", 0, emptyAgainSnapshot.get(View.class).size());
}
}
use of liquibase.database.core.PostgresDatabase in project liquibase by liquibase.
the class ChangedSequenceChangeGenerator method fixChanged.
@Override
public Change[] fixChanged(DatabaseObject changedObject, ObjectDifferences differences, DiffOutputControl control, Database referenceDatabase, Database comparisonDatabase, ChangeGeneratorChain chain) {
Sequence sequence = (Sequence) changedObject;
List<Change> changes = new ArrayList<>();
AlterSequenceChange accumulatedChange = createAlterSequenceChange(sequence, control);
if (differences.isDifferent("incrementBy")) {
AlterSequenceChange change = createAlterSequenceChange(sequence, control);
change.setIncrementBy(sequence.getIncrementBy());
accumulatedChange.setIncrementBy(sequence.getIncrementBy());
changes.add(change);
}
if (differences.isDifferent("maxValue")) {
AlterSequenceChange change = createAlterSequenceChange(sequence, control);
change.setMaxValue(sequence.getMaxValue());
accumulatedChange.setMaxValue(sequence.getMaxValue());
changes.add(change);
}
if (differences.isDifferent("minValue")) {
AlterSequenceChange change = createAlterSequenceChange(sequence, control);
change.setMinValue(sequence.getMinValue());
accumulatedChange.setMinValue(sequence.getMinValue());
changes.add(change);
changes.add(change);
}
if (differences.isDifferent("ordered")) {
AlterSequenceChange change = createAlterSequenceChange(sequence, control);
change.setOrdered(sequence.getOrdered());
accumulatedChange.setOrdered(sequence.getOrdered());
changes.add(change);
}
if (differences.isDifferent("cacheSize")) {
AlterSequenceChange change = createAlterSequenceChange(sequence, control);
change.setCacheSize(sequence.getCacheSize());
accumulatedChange.setCacheSize(sequence.getCacheSize());
changes.add(change);
}
if (differences.isDifferent("willCycle")) {
AlterSequenceChange change = createAlterSequenceChange(sequence, control);
change.setCycle(sequence.getWillCycle());
accumulatedChange.setCycle(sequence.getWillCycle());
changes.add(change);
}
if (differences.isDifferent("dataType")) {
AlterSequenceChange change = createAlterSequenceChange(sequence, control);
change.setDataType(sequence.getDataType());
accumulatedChange.setDataType(sequence.getDataType());
changes.add(change);
}
if (changes.isEmpty()) {
return null;
} else if (comparisonDatabase instanceof PostgresDatabase) {
return new Change[] { accumulatedChange };
} else {
return changes.toArray(new Change[changes.size()]);
}
}
use of liquibase.database.core.PostgresDatabase in project liquibase by liquibase.
the class MissingTableChangeGenerator method fixMissing.
@Override
public Change[] fixMissing(DatabaseObject missingObject, DiffOutputControl control, Database referenceDatabase, Database comparisonDatabase, ChangeGeneratorChain chain) {
Table missingTable = (Table) missingObject;
PrimaryKey primaryKey = missingTable.getPrimaryKey();
List<String> pkColumnList = ((primaryKey != null) ? primaryKey.getColumnNamesAsList() : null);
Map<Column, UniqueConstraint> singleUniqueConstraints = getSingleColumnUniqueConstraints(missingTable);
CreateTableChange change = createCreateTableChange();
change.setTableName(missingTable.getName());
if (control.getIncludeCatalog()) {
change.setCatalogName(missingTable.getSchema().getCatalogName());
}
if (control.getIncludeSchema()) {
change.setSchemaName(missingTable.getSchema().getName());
}
if (missingTable.getRemarks() != null) {
change.setRemarks(missingTable.getRemarks());
}
if (control.getIncludeTablespace() && (missingTable.getTablespace() != null) && comparisonDatabase.supportsTablespaces()) {
change.setTablespace(missingTable.getTablespace());
}
for (Column column : missingTable.getColumns()) {
ColumnConfig columnConfig = new ColumnConfig();
columnConfig.setName(column.getName());
LiquibaseDataType ldt = DataTypeFactory.getInstance().from(column.getType(), referenceDatabase);
DatabaseDataType ddt = ldt.toDatabaseDataType(comparisonDatabase);
String typeString = ddt.toString();
if (comparisonDatabase instanceof MSSQLDatabase) {
typeString = comparisonDatabase.unescapeDataTypeString(typeString);
}
columnConfig.setType(typeString);
if (column.isAutoIncrement()) {
columnConfig.setAutoIncrement(true);
}
boolean primaryKeyOrderMatchesTableOrder = checkPrimaryKeyOrderMatchesTableOrder(missingTable, pkColumnList);
ConstraintsConfig constraintsConfig = null;
// In MySQL, the primary key must be specified at creation for an autoincrement column
if ((pkColumnList != null) && primaryKeyOrderMatchesTableOrder && pkColumnList.contains(column.getName())) {
if ((referenceDatabase instanceof MSSQLDatabase) && (primaryKey.getBackingIndex() != null) && (primaryKey.getBackingIndex().getClustered() != null) && !primaryKey.getBackingIndex().getClustered()) {
// have to handle PK as a separate statement
} else if ((referenceDatabase instanceof PostgresDatabase) && (primaryKey.getBackingIndex() != null) && (primaryKey.getBackingIndex().getClustered() != null) && primaryKey.getBackingIndex().getClustered()) {
// have to handle PK as a separate statement
} else {
constraintsConfig = new ConstraintsConfig();
if (shouldAddPrimarykeyToConstraints(missingObject, control, referenceDatabase, comparisonDatabase)) {
constraintsConfig.setPrimaryKey(true);
constraintsConfig.setPrimaryKeyTablespace(primaryKey.getTablespace());
// MySQL sets some primary key names as PRIMARY which is invalid
if ((comparisonDatabase instanceof MySQLDatabase) && "PRIMARY".equals(primaryKey.getName())) {
constraintsConfig.setPrimaryKeyName(null);
} else {
constraintsConfig.setPrimaryKeyName(primaryKey.getName());
}
control.setAlreadyHandledMissing(primaryKey);
control.setAlreadyHandledMissing(primaryKey.getBackingIndex());
} else {
constraintsConfig.setNullable(false);
}
}
}
if ((column.isNullable() != null) && !column.isNullable()) {
if (constraintsConfig == null) {
constraintsConfig = new ConstraintsConfig();
}
constraintsConfig.setNullable(false);
if (!column.getValidateNullable()) {
constraintsConfig.setValidateNullable(false);
}
constraintsConfig.setNotNullConstraintName(column.getAttribute("notNullConstraintName", String.class));
}
if (referenceDatabase instanceof MySQLDatabase) {
UniqueConstraint uniqueConstraint = singleUniqueConstraints.get(column);
if (uniqueConstraint != null) {
if (!control.alreadyHandledMissing(uniqueConstraint, referenceDatabase)) {
if (constraintsConfig == null) {
constraintsConfig = new ConstraintsConfig();
}
constraintsConfig.setUnique(true);
control.setAlreadyHandledMissing(uniqueConstraint);
control.setAlreadyHandledMissing(uniqueConstraint.getBackingIndex());
}
}
}
if (constraintsConfig != null) {
columnConfig.setConstraints(constraintsConfig);
}
setDefaultValue(columnConfig, column, referenceDatabase);
if (column.getRemarks() != null) {
columnConfig.setRemarks(column.getRemarks());
}
Column.AutoIncrementInformation autoIncrementInfo = column.getAutoIncrementInformation();
if (autoIncrementInfo != null) {
BigInteger startWith = autoIncrementInfo.getStartWith();
BigInteger incrementBy = autoIncrementInfo.getIncrementBy();
String generationType = autoIncrementInfo.getGenerationType();
Boolean defaultOnNull = autoIncrementInfo.getDefaultOnNull();
if ((startWith != null) && !startWith.equals(BigInteger.ONE)) {
columnConfig.setStartWith(startWith);
}
if ((incrementBy != null) && !incrementBy.equals(BigInteger.ONE)) {
columnConfig.setIncrementBy(incrementBy);
}
if (StringUtil.isNotEmpty(generationType)) {
columnConfig.setGenerationType(generationType);
if (defaultOnNull != null) {
columnConfig.setDefaultOnNull(defaultOnNull);
}
}
}
//
if (column.getComputed() != null) {
columnConfig.setComputed(column.getComputed());
}
change.addColumn(columnConfig);
control.setAlreadyHandledMissing(column);
}
return new Change[] { change };
}
Aggregations