package liquibase.sqlgenerator.core;
import static liquibase.statement.core.FindForeignKeyConstraintsStatement.*;
import liquibase.database.Database;
import liquibase.database.core.MSSQLDatabase;
import liquibase.exception.DatabaseException;
import liquibase.exception.ValidationErrors;
import liquibase.sql.Sql;
import liquibase.sql.UnparsedSql;
import liquibase.sqlgenerator.SqlGeneratorChain;
import liquibase.statement.core.FindForeignKeyConstraintsStatement;
import liquibase.structure.core.Column;
public class FindForeignKeyConstraintsGeneratorMSSQL extends AbstractSqlGenerator<FindForeignKeyConstraintsStatement> {
@Override
public int getPriority() {
return PRIORITY_DATABASE;
}
@Override
public boolean supports(FindForeignKeyConstraintsStatement statement, Database database) {
return database instanceof MSSQLDatabase;
}
@Override
public ValidationErrors validate(FindForeignKeyConstraintsStatement findForeignKeyConstraintsStatement, Database database, SqlGeneratorChain sqlGeneratorChain) {
ValidationErrors validationErrors = new ValidationErrors();
validationErrors.checkRequiredField("baseTableName", findForeignKeyConstraintsStatement.getBaseTableName());
return validationErrors;
}
@Override
public Sql[] generateSql(FindForeignKeyConstraintsStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) {
String escapedTableName = database.escapeTableName(statement.getBaseTableCatalogName(), statement.getBaseTableSchemaName(), statement.getBaseTableName());
boolean sql2005OrLater = true;
try {
sql2005OrLater = database.getDatabaseMajorVersion() >= 9;
} catch (DatabaseException e) {
// Assume SQL Server 2005 or later
}
String sql;
if (sql2005OrLater) {
// SQL Server 2005 or later
sql =
"SELECT " +
"OBJECT_NAME([fk].[parent_object_id]) AS " + database.escapeObjectName(RESULT_COLUMN_BASE_TABLE_NAME, Column.class) + ", " +
"COL_NAME([fkc].[parent_object_id], [fkc].[parent_column_id]) AS " + database.escapeObjectName(RESULT_COLUMN_BASE_TABLE_COLUMN_NAME, Column.class) + ", " +
"OBJECT_NAME([fk].[referenced_object_id]) AS " + database.escapeObjectName(RESULT_COLUMN_FOREIGN_TABLE_NAME, Column.class) + ", " +
"COL_NAME([fkc].[referenced_object_id], [fkc].[referenced_column_id]) AS " + database.escapeObjectName(RESULT_COLUMN_FOREIGN_COLUMN_NAME, Column.class) + ", " +
"[fk].[name] AS " + database.escapeObjectName(RESULT_COLUMN_CONSTRAINT_NAME, Column.class) + " " +
"FROM [sys].[foreign_keys] AS [fk] " +
"INNER JOIN [sys].[foreign_key_columns] AS [fkc] " +
"ON [fk].[object_id] = [fkc].[constraint_object_id] " +
"WHERE [fk].[parent_object_id] = OBJECT_ID(N'" + database.escapeStringForDatabase(escapedTableName) + "') " +
"ORDER BY " +
"[fk].[name], " +
"[fkc].[constraint_column_id]";
} else {
// SQL Server 2000
sql =
"SELECT " +
"OBJECT_NAME([fkc].[fkeyid]) AS " + database.escapeObjectName(RESULT_COLUMN_BASE_TABLE_NAME, Column.class) + ", " +
"COL_NAME([fkc].[fkeyid], [fkc].[fkey]) AS " + database.escapeObjectName(RESULT_COLUMN_BASE_TABLE_COLUMN_NAME, Column.class) + ", " +
"OBJECT_NAME([fkc].[rkeyid]) AS " + database.escapeObjectName(RESULT_COLUMN_FOREIGN_TABLE_NAME, Column.class) + ", " +
"COL_NAME([fkc].[rkeyid], [fkc].[rkey]) AS " + database.escapeObjectName(RESULT_COLUMN_FOREIGN_COLUMN_NAME, Column.class) + ", " +
"[fk].[name] AS " + database.escapeObjectName(RESULT_COLUMN_CONSTRAINT_NAME, Column.class) + " " +
"FROM [dbo].[sysobjects] AS [fk] " +
"INNER JOIN [dbo].[sysforeignkeys] AS [fkc] " +
"ON [fkc].[constid] = [fk].[id] " +
"WHERE [fk].[xtype] = 'F' " +
"AND [fk].[parent_obj] = OBJECT_ID(N'" + database.escapeStringForDatabase(escapedTableName) + "') " +
"ORDER BY " +
"[fk].[name], " +
"[fkc].[keyno]";
}
return new Sql[] { new UnparsedSql(sql) };
}
}