public void check(Database database, DatabaseChangeLog changeLog, ChangeSet changeSet) throws PreconditionFailedException, PreconditionErrorException { try { boolean checkPassed; if (getForeignKeyTableName() == null) { checkPassed = DatabaseSnapshotGeneratorFactory.getInstance() .createSnapshot(database, getSchemaName(), null) .getForeignKey(getForeignKeyName()) != null; } else { // much faster if we can limit to correct table checkPassed = DatabaseSnapshotGeneratorFactory.getInstance() .getGenerator(database) .getForeignKeyByForeignKeyTable( getSchemaName(), getForeignKeyTableName(), getForeignKeyName(), database) != null; } if (!checkPassed) { String message = "Foreign Key " + database.escapeStringForDatabase(getForeignKeyName()); if (getForeignKeyTableName() != null) { message += " on table " + getForeignKeyTableName(); } message += " does not exist"; throw new PreconditionFailedException(message, changeLog, this); } } catch (DatabaseException e) { throw new PreconditionErrorException(e, changeLog, this); } }
@Override public String objectToSql(Object value, Database database) { if (value == null || value.toString().equalsIgnoreCase("null")) { return null; } if (value instanceof DatabaseFunction) { return value.toString(); } String val = String.valueOf(value); // postgres type character varying gets identified as a char type // simple sanity check to avoid double quoting a value if (database instanceof PostgresDatabase && val.startsWith("'") && val.endsWith("'")) { return val; } else { if (database instanceof MSSQLDatabase && !StringUtils.isAscii(val)) { return "N'" + database.escapeStringForDatabase(val) + "'"; } return "'" + database.escapeStringForDatabase(val) + "'"; } }
protected String getWhereClause( InsertOrUpdateStatement insertOrUpdateStatement, Database database) { StringBuffer where = new StringBuffer(); String[] pkColumns = insertOrUpdateStatement.getPrimaryKey().split(","); for (String thisPkColumn : pkColumns) { where .append( database.escapeColumnName( insertOrUpdateStatement.getSchemaName(), insertOrUpdateStatement.getTableName(), thisPkColumn)) .append(" = "); Object newValue = insertOrUpdateStatement.getColumnValues().get(thisPkColumn); if (newValue == null || newValue.toString().equals("NULL")) { where.append("NULL"); } else if (newValue instanceof String && database.shouldQuoteValue(((String) newValue))) { where.append("'").append(database.escapeStringForDatabase((String) newValue)).append("'"); } else if (newValue instanceof Date) { where.append(database.getDateLiteral(((Date) newValue))); } else if (newValue instanceof Boolean) { if (((Boolean) newValue)) { where.append( TypeConverterFactory.getInstance() .findTypeConverter(database) .getBooleanType() .getTrueBooleanValue()); } else { where.append( TypeConverterFactory.getInstance() .findTypeConverter(database) .getBooleanType() .getFalseBooleanValue()); } } else { where.append(newValue); } where.append(" AND "); } where.delete(where.lastIndexOf(" AND "), where.lastIndexOf(" AND ") + " AND ".length()); return where.toString(); }
// Copied from liquibase.sqlgenerator.core.InsertOrUpdateGeneratorMySQL private String convertToString(Object newValue, Database database) { String sqlString; if (newValue == null || newValue.toString().equals("") || newValue.toString().equalsIgnoreCase("NULL")) { sqlString = "NULL"; } else if (newValue instanceof String && !looksLikeFunctionCall(((String) newValue), database)) { sqlString = "'" + database.escapeStringForDatabase(newValue.toString()) + "'"; } else if (newValue instanceof Date) { sqlString = database.getDateLiteral(((Date) newValue)); } else if (newValue instanceof Boolean) { if (((Boolean) newValue)) { sqlString = DataTypeFactory.getInstance().getTrueBooleanValue(database); } else { sqlString = DataTypeFactory.getInstance().getFalseBooleanValue(database); } } else { sqlString = newValue.toString(); } return sqlString; }
@Override public Sql[] generateSql( MarkChangeSetRanStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) { String dateValue = database.getCurrentDateTimeFunction(); ChangeSet changeSet = statement.getChangeSet(); SqlStatement runStatement; try { if (statement.getExecType().equals(ChangeSet.ExecType.FAILED) || statement.getExecType().equals(ChangeSet.ExecType.SKIPPED)) { return new Sql[0]; // don't mark } else if (statement.getExecType().ranBefore) { runStatement = new UpdateStatement( database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), database.getDatabaseChangeLogTableName()) .addNewColumnValue("DATEEXECUTED", new DatabaseFunction(dateValue)) .addNewColumnValue("MD5SUM", changeSet.generateCheckSum().toString()) .addNewColumnValue("EXECTYPE", statement.getExecType().value) .setWhereClause("ID=? AND AUTHOR=? AND FILENAME=?") .addWhereParameters( changeSet.getId(), changeSet.getAuthor(), changeSet.getFilePath()); } else { runStatement = new InsertStatement( database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), database.getDatabaseChangeLogTableName()) .addColumnValue("ID", changeSet.getId()) .addColumnValue("AUTHOR", changeSet.getAuthor()) .addColumnValue("FILENAME", changeSet.getFilePath()) .addColumnValue("DATEEXECUTED", new DatabaseFunction(dateValue)) .addColumnValue( "ORDEREXECUTED", ChangeLogHistoryServiceFactory.getInstance() .getChangeLogService(database) .getNextSequenceValue()) .addColumnValue("MD5SUM", changeSet.generateCheckSum().toString()) .addColumnValue("DESCRIPTION", limitSize(changeSet.getDescription())) .addColumnValue( "COMMENTS", limitSize( database.escapeStringForDatabase( StringUtils.trimToEmpty(changeSet.getComments())))) .addColumnValue("EXECTYPE", statement.getExecType().value) .addColumnValue( "LIQUIBASE", LiquibaseUtil.getBuildVersion().replaceAll("SNAPSHOT", "SNP")); String tag = null; List<Change> changes = changeSet.getChanges(); if (changes != null && changes.size() == 1) { Change change = changes.get(0); if (change instanceof TagDatabaseChange) { TagDatabaseChange tagChange = (TagDatabaseChange) change; tag = tagChange.getTag(); } } if (tag != null) { ((InsertStatement) runStatement).addColumnValue("TAG", tag); } } } catch (LiquibaseException e) { throw new UnexpectedLiquibaseException(e); } return SqlGeneratorFactory.getInstance().generateSql(runStatement, database); }
@Override protected DatabaseObject snapshotObject(DatabaseObject example, DatabaseSnapshot snapshot) throws DatabaseException, InvalidExampleException { Database database = snapshot.getDatabase(); Relation relation = ((Column) example).getRelation(); if (((Column) example).getComputed() != null && ((Column) example).getComputed()) { return example; } Schema schema = relation.getSchema(); List<CachedRow> columnMetadataRs = null; try { JdbcDatabaseSnapshot.CachingDatabaseMetaData databaseMetaData = ((JdbcDatabaseSnapshot) snapshot).getMetaData(); columnMetadataRs = databaseMetaData.getColumns( ((AbstractJdbcDatabase) database).getJdbcCatalogName(schema), ((AbstractJdbcDatabase) database).getJdbcSchemaName(schema), relation.getName(), example.getName()); if (columnMetadataRs.size() > 0) { CachedRow data = columnMetadataRs.get(0); Column column = readColumn(data, relation, database); if (column != null && database instanceof MSSQLDatabase && database.getDatabaseMajorVersion() >= 8) { String sql; if (database.getDatabaseMajorVersion() >= 9) { // SQL Server 2005 or later // https://technet.microsoft.com/en-us/library/ms177541.aspx sql = "SELECT CAST([ep].[value] AS [nvarchar](MAX)) AS [REMARKS] " + "FROM [sys].[extended_properties] AS [ep] " + "WHERE [ep].[class] = 1 " + "AND [ep].[major_id] = OBJECT_ID(N'" + database.escapeStringForDatabase( database.escapeTableName( schema.getCatalogName(), schema.getName(), relation.getName())) + "') " + "AND [ep].[minor_id] = COLUMNPROPERTY([ep].[major_id], N'" + database.escapeStringForDatabase(column.getName()) + "', 'ColumnId') " + "AND [ep].[name] = 'MS_Description'"; } else { // SQL Server 2000 // https://technet.microsoft.com/en-us/library/aa224810%28v=sql.80%29.aspx sql = "SELECT CAST([p].[value] AS [ntext]) AS [REMARKS] " + "FROM [dbo].[sysproperties] AS [p] " + "WHERE [p].[id] = OBJECT_ID(N'" + database.escapeStringForDatabase( database.escapeTableName( schema.getCatalogName(), schema.getName(), relation.getName())) + "') " + "AND [p].[smallid] = COLUMNPROPERTY([p].[id], N'" + database.escapeStringForDatabase(column.getName()) + "', 'ColumnId') " + "AND [p].[type] = 4 " + "AND [p].[name] = 'MS_Description'"; } List<String> remarks = ExecutorService.getInstance() .getExecutor(snapshot.getDatabase()) .queryForList(new RawSqlStatement(sql), String.class); if (remarks != null && remarks.size() > 0) { column.setRemarks(StringUtils.trimToNull(remarks.iterator().next())); } } return column; } else { return null; } } catch (Exception e) { throw new DatabaseException(e); } }