package liquibase.sqlgenerator.core;
import liquibase.CatalogAndSchema;
import liquibase.database.Database;
import liquibase.database.core.*;
import liquibase.structure.core.Relation;
import liquibase.exception.ValidationErrors;
import liquibase.sql.Sql;
import liquibase.sql.UnparsedSql;
import liquibase.sqlgenerator.SqlGeneratorChain;
import liquibase.statement.core.CreateViewStatement;
import liquibase.structure.core.View;
import liquibase.util.SqlParser;
import liquibase.util.StringClauses;
import java.util.ArrayList;
import java.util.List;
public class CreateViewGenerator extends AbstractSqlGenerator<CreateViewStatement> {
@Override
public ValidationErrors validate(CreateViewStatement createViewStatement, Database database, SqlGeneratorChain sqlGeneratorChain) {
if (database instanceof InformixDatabase) {
return new CreateViewGeneratorInformix().validate(createViewStatement, database, sqlGeneratorChain);
}
ValidationErrors validationErrors = new ValidationErrors();
validationErrors.checkRequiredField("viewName", createViewStatement.getViewName());
validationErrors.checkRequiredField("selectQuery", createViewStatement.getSelectQuery());
if (createViewStatement.isReplaceIfExists()) {
validationErrors.checkDisallowedField("replaceIfExists", createViewStatement.isReplaceIfExists(), database, HsqlDatabase.class, DB2Database.class, DerbyDatabase.class, SybaseASADatabase.class, InformixDatabase.class);
}
return validationErrors;
}
@Override
public Sql[] generateSql(CreateViewStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) {
if (database instanceof InformixDatabase) {
return new CreateViewGeneratorInformix().generateSql(statement, database, sqlGeneratorChain);
}
List<Sql> sql = new ArrayList<Sql>();
StringClauses viewDefinition = SqlParser.parse(statement.getSelectQuery(), true, true);
if (!statement.isFullDefinition()) {
viewDefinition
.prepend(" ")
.prepend("AS")
.prepend(" ")
.prepend(database.escapeViewName(statement.getCatalogName(), statement.getSchemaName(), statement.getViewName()))
.prepend(" ")
.prepend("VIEW")
.prepend(" ")
.prepend("CREATE");
}
if (statement.isReplaceIfExists()) {
if (database instanceof FirebirdDatabase) {
viewDefinition.replaceIfExists("CREATE", "RECREATE");
} else if (database instanceof SybaseASADatabase && statement.getSelectQuery().toLowerCase().startsWith("create view")) {
// Sybase ASA saves view definitions with header.
} else if (database instanceof MSSQLDatabase) {
//from http://stackoverflow.com/questions/163246/sql-server-equivalent-to-oracles-create-or-replace-view
CatalogAndSchema schema = new CatalogAndSchema(statement.getCatalogName(), statement.getSchemaName()).customize(database);
sql.add(new UnparsedSql("IF NOT EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[" + schema.getSchemaName() + "].[" + statement.getViewName() + "]'))\n" +
" EXEC sp_executesql N'CREATE VIEW [" + schema.getSchemaName() + "].[" + statement.getViewName() + "] AS SELECT ''This is a code stub which will be replaced by an Alter Statement'' as [code_stub]'"));
viewDefinition.replaceIfExists("CREATE", "ALTER");
} else if (database instanceof PostgresDatabase) {
sql.add(new UnparsedSql("DROP VIEW IF EXISTS " + database.escapeViewName(statement.getCatalogName(), statement.getSchemaName(), statement.getViewName())));
} else {
if (!viewDefinition.contains("replace")) {
viewDefinition.replace("CREATE", "CREATE OR REPLACE");
}
}
}
sql.add(new UnparsedSql(viewDefinition.toString(), getAffectedView(statement)));
return sql.toArray(new Sql[sql.size()]);
}
protected Relation getAffectedView(CreateViewStatement statement) {
return new View().setName(statement.getViewName()).setSchema(statement.getCatalogName(), statement.getSchemaName());
}
}