use of liquibase.snapshot.JdbcDatabaseSnapshot in project liquibase by liquibase.
the class ForeignKeySnapshotGenerator method addTo.
// public Boolean has(DatabaseObject example, DatabaseSnapshot snapshot, SnapshotGeneratorChain chain) throws DatabaseException {
// if (example instanceof ForeignKey) {
// Database database = snapshot.getDatabase();
// String searchCatalog = database.getJdbcCatalogName(example.getSchema());
// String searchSchema = database.getJdbcSchemaName(example.getSchema());
// String searchTableName = null;
// if (((ForeignKey) example).getForeignKeyTable() != null) {
// searchTableName = ((ForeignKey) example).getForeignKeyTable().getName();
// }
// String fkName = example.getName();
//
// ResultSet rs = null;
// try {
// rs = getMetaData(database).getForeignKeys(searchCatalog, searchSchema, searchTableName);
// while (rs.next()) {
// if (fkName.equals(rs.getString("FK_NAME"))) {
// return true;
// }
// }
// return false;
// } catch (SQLException e) {
// throw new DatabaseException(e);
// } finally {
// if (rs != null) {
// try {
// rs.close();
// } catch (SQLException ignored) { }
// }
// }
// } else {
// return chain.has(example, snapshot);
// }
// }
@Override
protected void addTo(DatabaseObject foundObject, DatabaseSnapshot snapshot) throws DatabaseException, InvalidExampleException {
if (!snapshot.getSnapshotControl().shouldInclude(ForeignKey.class)) {
return;
}
if (foundObject instanceof Table) {
Table table = (Table) foundObject;
Database database = snapshot.getDatabase();
Schema schema;
schema = table.getSchema();
Set<String> seenFks = new HashSet<String>();
List<CachedRow> importedKeyMetadataResultSet;
try {
importedKeyMetadataResultSet = ((JdbcDatabaseSnapshot) snapshot).getMetaData().getForeignKeys(((AbstractJdbcDatabase) database).getJdbcCatalogName(schema), ((AbstractJdbcDatabase) database).getJdbcSchemaName(schema), database.correctObjectName(table.getName(), Table.class), null);
for (CachedRow row : importedKeyMetadataResultSet) {
ForeignKey fk = new ForeignKey().setName(row.getString("FK_NAME")).setForeignKeyTable(table);
if (seenFks.add(fk.getName())) {
table.getOutgoingForeignKeys().add(fk);
}
}
} catch (Exception e) {
throw new DatabaseException(e);
}
}
}
use of liquibase.snapshot.JdbcDatabaseSnapshot in project liquibase by liquibase.
the class ForeignKeySnapshotGenerator method snapshotObject.
@Override
protected DatabaseObject snapshotObject(DatabaseObject example, DatabaseSnapshot snapshot) throws DatabaseException, InvalidExampleException {
Database database = snapshot.getDatabase();
List<CachedRow> importedKeyMetadataResultSet;
try {
Table fkTable = ((ForeignKey) example).getForeignKeyTable();
String searchCatalog = ((AbstractJdbcDatabase) database).getJdbcCatalogName(fkTable.getSchema());
String searchSchema = ((AbstractJdbcDatabase) database).getJdbcSchemaName(fkTable.getSchema());
String searchTableName = database.correctObjectName(fkTable.getName(), Table.class);
importedKeyMetadataResultSet = ((JdbcDatabaseSnapshot) snapshot).getMetaData().getForeignKeys(searchCatalog, searchSchema, searchTableName, example.getName());
ForeignKey foreignKey = null;
for (CachedRow row : importedKeyMetadataResultSet) {
String fk_name = cleanNameFromDatabase(row.getString("FK_NAME"), database);
if (snapshot.getDatabase().isCaseSensitive()) {
if (!fk_name.equals(example.getName())) {
continue;
} else if (!fk_name.equalsIgnoreCase(example.getName())) {
continue;
}
}
if (foreignKey == null) {
foreignKey = new ForeignKey();
}
foreignKey.setName(fk_name);
String fkTableCatalog = cleanNameFromDatabase(row.getString("FKTABLE_CAT"), database);
String fkTableSchema = cleanNameFromDatabase(row.getString("FKTABLE_SCHEM"), database);
String fkTableName = cleanNameFromDatabase(row.getString("FKTABLE_NAME"), database);
Table foreignKeyTable = new Table().setName(fkTableName);
foreignKeyTable.setSchema(new Schema(new Catalog(fkTableCatalog), fkTableSchema));
foreignKey.setForeignKeyTable(foreignKeyTable);
Column fkColumn = new Column(cleanNameFromDatabase(row.getString("FKCOLUMN_NAME"), database)).setRelation(foreignKeyTable);
boolean alreadyAdded = false;
for (Column existing : foreignKey.getForeignKeyColumns()) {
if (DatabaseObjectComparatorFactory.getInstance().isSameObject(existing, fkColumn, snapshot.getSchemaComparisons(), database)) {
//already added. One is probably an alias
alreadyAdded = true;
}
}
if (alreadyAdded) {
break;
}
CatalogAndSchema pkTableSchema = ((AbstractJdbcDatabase) database).getSchemaFromJdbcInfo(row.getString("PKTABLE_CAT"), row.getString("PKTABLE_SCHEM"));
Table tempPkTable = (Table) new Table().setName(row.getString("PKTABLE_NAME")).setSchema(new Schema(pkTableSchema.getCatalogName(), pkTableSchema.getSchemaName()));
foreignKey.setPrimaryKeyTable(tempPkTable);
Column pkColumn = new Column(cleanNameFromDatabase(row.getString("PKCOLUMN_NAME"), database)).setRelation(tempPkTable);
foreignKey.addForeignKeyColumn(fkColumn);
foreignKey.addPrimaryKeyColumn(pkColumn);
//todo foreignKey.setKeySeq(importedKeyMetadataResultSet.getInt("KEY_SEQ"));
ForeignKeyConstraintType updateRule = convertToForeignKeyConstraintType(row.getInt("UPDATE_RULE"), database);
foreignKey.setUpdateRule(updateRule);
ForeignKeyConstraintType deleteRule = convertToForeignKeyConstraintType(row.getInt("DELETE_RULE"), database);
foreignKey.setDeleteRule(deleteRule);
short deferrability = row.getShort("DEFERRABILITY");
// it should be set to DatabaseMetaData.importedKeyNotDeferrable(7)
if (deferrability == 0 || deferrability == DatabaseMetaData.importedKeyNotDeferrable) {
foreignKey.setDeferrable(false);
foreignKey.setInitiallyDeferred(false);
} else if (deferrability == DatabaseMetaData.importedKeyInitiallyDeferred) {
foreignKey.setDeferrable(true);
foreignKey.setInitiallyDeferred(true);
} else if (deferrability == DatabaseMetaData.importedKeyInitiallyImmediate) {
foreignKey.setDeferrable(true);
foreignKey.setInitiallyDeferred(false);
} else {
throw new RuntimeException("Unknown deferrability result: " + deferrability);
}
if (database.createsIndexesForForeignKeys()) {
Index exampleIndex = new Index().setTable(foreignKey.getForeignKeyTable());
exampleIndex.getColumns().addAll(foreignKey.getForeignKeyColumns());
foreignKey.setBackingIndex(exampleIndex);
}
}
if (snapshot.get(ForeignKey.class).contains(foreignKey)) {
return null;
}
return foreignKey;
} catch (Exception e) {
throw new DatabaseException(e);
}
}
use of liquibase.snapshot.JdbcDatabaseSnapshot in project liquibase by liquibase.
the class IndexSnapshotGenerator method snapshotObject.
@Override
protected DatabaseObject snapshotObject(DatabaseObject example, DatabaseSnapshot snapshot) throws DatabaseException, InvalidExampleException {
Database database = snapshot.getDatabase();
Table exampleTable = ((Index) example).getTable();
String tableName = null;
Schema schema = null;
if (exampleTable != null) {
tableName = exampleTable.getName();
schema = exampleTable.getSchema();
}
if (schema == null) {
schema = new Schema(database.getDefaultCatalogName(), database.getDefaultSchemaName());
}
for (int i = 0; i < ((Index) example).getColumns().size(); i++) {
((Index) example).getColumns().set(i, ((Index) example).getColumns().get(i));
}
String exampleName = example.getName();
if (exampleName != null) {
exampleName = database.correctObjectName(exampleName, Index.class);
}
Map<String, Index> foundIndexes = new HashMap<String, Index>();
JdbcDatabaseSnapshot.CachingDatabaseMetaData databaseMetaData = null;
List<CachedRow> rs = null;
try {
databaseMetaData = ((JdbcDatabaseSnapshot) snapshot).getMetaData();
rs = databaseMetaData.getIndexInfo(((AbstractJdbcDatabase) database).getJdbcCatalogName(schema), ((AbstractJdbcDatabase) database).getJdbcSchemaName(schema), tableName, exampleName);
for (CachedRow row : rs) {
String rawIndexName = row.getString("INDEX_NAME");
String indexName = cleanNameFromDatabase(rawIndexName, database);
String correctedIndexName = database.correctObjectName(indexName, Index.class);
if (indexName == null) {
continue;
}
if (exampleName != null && !exampleName.equals(correctedIndexName)) {
continue;
}
/*
* TODO Informix generates indexnames with a leading blank if no name given.
* An identifier with a leading blank is not allowed.
* So here is it replaced.
*/
if (database instanceof InformixDatabase && indexName.startsWith(" ")) {
// suppress creation of generated_index records
continue;
}
short type = row.getShort("TYPE");
// String tableName = rs.getString("TABLE_NAME");
Boolean nonUnique = row.getBoolean("NON_UNIQUE");
if (nonUnique == null) {
nonUnique = true;
}
String columnName = cleanNameFromDatabase(row.getString("COLUMN_NAME"), database);
short position = row.getShort("ORDINAL_POSITION");
/*
* TODO maybe bug in jdbc driver? Need to investigate.
* If this "if" is commented out ArrayOutOfBoundsException is thrown
* because it tries to access an element -1 of a List (position-1)
*/
if (database instanceof InformixDatabase && type != DatabaseMetaData.tableIndexStatistic && position == 0) {
System.out.println(this.getClass().getName() + ": corrected position to " + ++position);
}
String definition = StringUtils.trimToNull(row.getString("FILTER_CONDITION"));
if (definition != null) {
if (!(database instanceof OracleDatabase)) {
//TODO: this replaceAll code has been there for a long time but we don't know why. Investigate when it is ever needed and modify it to be smarter
definition = definition.replaceAll("\"", "");
}
}
if (type == DatabaseMetaData.tableIndexStatistic) {
continue;
}
if (columnName == null && definition == null) {
//nothing to index, not sure why these come through sometimes
continue;
}
Index returnIndex = foundIndexes.get(correctedIndexName);
if (returnIndex == null) {
returnIndex = new Index();
returnIndex.setTable((Table) new Table().setName(row.getString("TABLE_NAME")).setSchema(schema));
returnIndex.setName(indexName);
returnIndex.setUnique(!nonUnique);
if (type == DatabaseMetaData.tableIndexClustered) {
returnIndex.setClustered(true);
} else if (database instanceof MSSQLDatabase) {
returnIndex.setClustered(false);
}
if (database instanceof MSSQLDatabase) {
Boolean recompute = (Boolean) row.get("NO_RECOMPUTE");
if (recompute != null) {
recompute = !recompute;
}
returnIndex.setAttribute("padIndex", row.get("IS_PADDED"));
returnIndex.setAttribute("fillFactor", row.get("FILL_FACTOR"));
returnIndex.setAttribute("ignoreDuplicateKeys", row.get("IGNORE_DUP_KEY"));
returnIndex.setAttribute("recomputeStatistics", recompute);
returnIndex.setAttribute("incrementalStatistics", row.get("IS_INCREMENTAL"));
returnIndex.setAttribute("allowRowLocks", row.get("ALLOW_ROW_LOCKS"));
returnIndex.setAttribute("allowPageLocks", row.get("ALLOW_PAGE_LOCKS"));
}
foundIndexes.put(correctedIndexName, returnIndex);
}
if (database instanceof MSSQLDatabase && (Boolean) row.get("IS_INCLUDED_COLUMN")) {
List<String> includedColumns = returnIndex.getAttribute("includedColumns", List.class);
if (includedColumns == null) {
includedColumns = new ArrayList<String>();
returnIndex.setAttribute("includedColumns", includedColumns);
}
includedColumns.add(columnName);
} else {
if (position != 0) {
//if really a column, position is 1-based.
for (int i = returnIndex.getColumns().size(); i < position; i++) {
returnIndex.getColumns().add(null);
}
if (definition == null) {
String ascOrDesc = row.getString("ASC_OR_DESC");
Boolean descending = "D".equals(ascOrDesc) ? Boolean.TRUE : "A".equals(ascOrDesc) ? Boolean.FALSE : null;
returnIndex.getColumns().set(position - 1, new Column(columnName).setDescending(descending).setRelation(returnIndex.getTable()));
} else {
returnIndex.getColumns().set(position - 1, new Column().setRelation(returnIndex.getTable()).setName(definition, true));
}
}
}
}
} catch (Exception e) {
throw new DatabaseException(e);
}
if (exampleName != null) {
Index index = null;
// Wont get here now though due to the continue for generated indexes above
if (database instanceof InformixDatabase) {
index = foundIndexes.get("_generated_index_" + exampleName.substring(1));
} else {
index = foundIndexes.get(exampleName);
}
return index;
} else {
//prefer clustered version of the index
List<Index> nonClusteredIndexes = new ArrayList<Index>();
for (Index index : foundIndexes.values()) {
if (DatabaseObjectComparatorFactory.getInstance().isSameObject(index.getTable(), exampleTable, snapshot.getSchemaComparisons(), database)) {
boolean actuallyMatches = false;
if (database.isCaseSensitive()) {
if (index.getColumnNames().equals(((Index) example).getColumnNames())) {
actuallyMatches = true;
}
} else {
if (index.getColumnNames().equalsIgnoreCase(((Index) example).getColumnNames())) {
actuallyMatches = true;
}
}
if (actuallyMatches) {
if (index.getClustered() != null && index.getClustered()) {
return finalizeIndex(schema, tableName, index, snapshot);
} else {
nonClusteredIndexes.add(index);
}
}
}
}
if (nonClusteredIndexes.size() > 0) {
return finalizeIndex(schema, tableName, nonClusteredIndexes.get(0), snapshot);
}
return null;
}
//todo?
// Set<Index> indexesToRemove = new HashSet<Index>();
/*
* marks indexes as "associated with" instead of "remove it"
* Index should have associations with:
* foreignKey, primaryKey or uniqueConstraint
* */
// for (Index index : snapshot.getDatabaseObjects(schema, Index.class)) {
// for (PrimaryKey pk : snapshot.getDatabaseObjects(schema, PrimaryKey.class)) {
// if (index.getTable().equals(pk.getTable().getName(), database) && columnNamesAreEqual(index.getColumnNames(), pk.getColumnNames(), database)) {
// index.addAssociatedWith(Index.MARK_PRIMARY_KEY);
// }
// }
// for (ForeignKey fk : snapshot.getDatabaseObjects(schema, ForeignKey.class)) {
// if (index.getTable().equals(fk.getForeignKeyTable().getName(), database) && columnNamesAreEqual(index.getColumnNames(), fk.getForeignKeyColumns(), database)) {
// index.addAssociatedWith(Index.MARK_FOREIGN_KEY);
// }
// }
// for (UniqueConstraint uc : snapshot.getDatabaseObjects(schema, UniqueConstraint.class)) {
// if (index.getTable().equals(uc.getTable()) && columnNamesAreEqual(index.getColumnNames(), uc.getColumnNames(), database)) {
// index.addAssociatedWith(Index.MARK_UNIQUE_CONSTRAINT);
// }
// }
//
// }
// snapshot.removeDatabaseObjects(schema, indexesToRemove.toArray(new Index[indexesToRemove.size()]));
}
use of liquibase.snapshot.JdbcDatabaseSnapshot in project liquibase by liquibase.
the class ViewSnapshotGenerator method snapshotObject.
// public Boolean has(DatabaseObject example, DatabaseSnapshot snapshot, SnapshotGeneratorChain chain) throws DatabaseException {
// Database database = snapshot.getDatabase();
// if (!(example instanceof View)) {
// return chain.has(example, snapshot);
// }
// String viewName = example.getName();
// Schema schema = example.getSchema();
// try {
// ResultSet rs = getMetaData(database).getTables(database.getJdbcCatalogName(schema), database.getJdbcSchemaName(schema), database.correctObjectName(viewName, View.class), new String[]{"VIEW"});
// try {
// return rs.next();
// } finally {
// try {
// rs.close();
// } catch (SQLException ignore) {
// }
// }
// } catch (SQLException e) {
// throw new DatabaseException(e);
// }
// }
@Override
protected DatabaseObject snapshotObject(DatabaseObject example, DatabaseSnapshot snapshot) throws DatabaseException {
if (((View) example).getDefinition() != null) {
return example;
}
Database database = snapshot.getDatabase();
Schema schema = example.getSchema();
List<CachedRow> viewsMetadataRs = null;
try {
viewsMetadataRs = ((JdbcDatabaseSnapshot) snapshot).getMetaData().getViews(((AbstractJdbcDatabase) database).getJdbcCatalogName(schema), ((AbstractJdbcDatabase) database).getJdbcSchemaName(schema), example.getName());
if (viewsMetadataRs.size() > 0) {
CachedRow row = viewsMetadataRs.get(0);
String rawViewName = row.getString("TABLE_NAME");
String rawSchemaName = StringUtils.trimToNull(row.getString("TABLE_SCHEM"));
String rawCatalogName = StringUtils.trimToNull(row.getString("TABLE_CAT"));
String remarks = row.getString("REMARKS");
if (remarks != null) {
//come back escaped sometimes
remarks = remarks.replace("''", "'");
}
View view = new View().setName(cleanNameFromDatabase(rawViewName, database));
view.setRemarks(remarks);
CatalogAndSchema schemaFromJdbcInfo = ((AbstractJdbcDatabase) database).getSchemaFromJdbcInfo(rawCatalogName, rawSchemaName);
view.setSchema(new Schema(schemaFromJdbcInfo.getCatalogName(), schemaFromJdbcInfo.getSchemaName()));
try {
String definition = database.getViewDefinition(schemaFromJdbcInfo, view.getName());
if (definition.startsWith("FULL_DEFINITION: ")) {
definition = definition.replaceFirst("^FULL_DEFINITION: ", "");
view.setContainsFullDefinition(true);
}
// remove strange zero-termination seen on some Oracle view definitions
int length = definition.length();
if (definition.charAt(length - 1) == 0) {
definition = definition.substring(0, length - 1);
}
if (database instanceof InformixDatabase) {
// Cleanup
definition = definition.trim();
definition = definition.replaceAll("\\s*,\\s*", ", ");
definition = definition.replaceAll("\\s*;", "");
// Strip the schema definition because it can optionally be included in the tag attribute
definition = definition.replaceAll("(?i)\"" + view.getSchema().getName() + "\"\\.", "");
}
view.setDefinition(definition);
} catch (DatabaseException e) {
throw new DatabaseException("Error getting " + database.getConnection().getURL() + " view with " + new GetViewDefinitionStatement(view.getSchema().getCatalogName(), view.getSchema().getName(), rawViewName), e);
}
return view;
} else {
return null;
}
} catch (SQLException e) {
throw new DatabaseException(e);
}
}
use of liquibase.snapshot.JdbcDatabaseSnapshot in project liquibase by liquibase.
the class ViewSnapshotGenerator method addTo.
@Override
protected void addTo(DatabaseObject foundObject, DatabaseSnapshot snapshot) throws DatabaseException, InvalidExampleException {
if (!snapshot.getSnapshotControl().shouldInclude(View.class)) {
return;
}
if (foundObject instanceof Schema) {
Schema schema = (Schema) foundObject;
Database database = snapshot.getDatabase();
List<CachedRow> viewsMetadataRs = null;
try {
viewsMetadataRs = ((JdbcDatabaseSnapshot) snapshot).getMetaData().getViews(((AbstractJdbcDatabase) database).getJdbcCatalogName(schema), ((AbstractJdbcDatabase) database).getJdbcSchemaName(schema), null);
for (CachedRow row : viewsMetadataRs) {
View view = new View();
view.setName(row.getString("TABLE_NAME"));
view.setSchema(schema);
view.setRemarks(row.getString("REMARKS"));
view.setDefinition(row.getString("OBJECT_BODY"));
if (database instanceof OracleDatabase) {
view.setAttribute("editioning", "Y".equals(row.getString("EDITIONING_VIEW")));
}
schema.addDatabaseObject(view);
}
} catch (SQLException e) {
throw new DatabaseException(e);
}
}
}
Aggregations