Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix columnNames snapshot attribute of uniqueConstraints for Snowflake #3123

Merged
merged 2 commits into from Aug 2, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -2,6 +2,7 @@

import liquibase.Scope;
import liquibase.database.Database;
import liquibase.database.core.H2Database;
import liquibase.database.core.SnowflakeDatabase;
import liquibase.exception.DatabaseException;
import liquibase.executor.ExecutorService;
Expand All @@ -10,10 +11,8 @@
import liquibase.snapshot.SnapshotGenerator;
import liquibase.statement.core.RawSqlStatement;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.Relation;
import liquibase.structure.core.Schema;
import liquibase.structure.core.Table;
import liquibase.structure.core.UniqueConstraint;
import liquibase.structure.core.*;
import liquibase.util.StringUtil;

import java.sql.SQLException;
import java.util.List;
Expand All @@ -31,6 +30,32 @@ public int getPriority(Class<? extends DatabaseObject> objectType, Database data
}
}

@Override
protected DatabaseObject snapshotObject(DatabaseObject example, DatabaseSnapshot snapshot) throws DatabaseException {
Database database = snapshot.getDatabase();
UniqueConstraint exampleConstraint = (UniqueConstraint) example;
Relation table = exampleConstraint.getRelation();

List<Map<String, ?>> metadata = listColumns(exampleConstraint, database, snapshot);

if (metadata.isEmpty()) {
return null;
}
UniqueConstraint constraint = new UniqueConstraint();
constraint.setRelation(table);
constraint.setName(example.getName());
constraint.setBackingIndex(exampleConstraint.getBackingIndex());
constraint.setInitiallyDeferred(((UniqueConstraint) example).isInitiallyDeferred());
constraint.setDeferrable(((UniqueConstraint) example).isDeferrable());
constraint.setClustered(((UniqueConstraint) example).isClustered());

for (Map<String, ?> col : metadata) {
constraint.getColumns().add(new Column((String) col.get("COLUMN_NAME")).setRelation(table));
}

return constraint;
}

@Override
public Class<? extends SnapshotGenerator>[] replaces() {
return new Class[] { UniqueConstraintSnapshotGenerator.class };
Expand All @@ -47,25 +72,15 @@ protected List<CachedRow> listConstraints(Table table, DatabaseSnapshot snapshot
protected List<Map<String, ?>> listColumns(UniqueConstraint example, Database database, DatabaseSnapshot snapshot)
throws DatabaseException {
Relation table = example.getRelation();
Schema schema = table.getSchema();
String name = example.getName();
String schemaName = database.correctObjectName(schema.getName(), Schema.class);
String constraintName = database.correctObjectName(name, UniqueConstraint.class);
String tableName = database.correctObjectName(table.getName(), Table.class);
//TODO figure out what to do with COLUMN_NAME
// https://community.snowflake.com/s/question/0D50Z00008Y3VUbSAN/table-details-including-the-constraints
String sql = "select CONSTRAINT_NAME, CONSTRAINT_NAME as COLUMN_NAME " + "from " + database.getSystemSchema() +
".TABLE_CONSTRAINTS "
+ "where CONSTRAINT_TYPE='UNIQUE'";
if (schemaName != null) {
sql += "and CONSTRAINT_SCHEMA='" + schemaName + "' ";
}
if (tableName != null) {
sql += "and TABLE_NAME='" + tableName + "' ";
}
if (constraintName != null) {
sql += "and CONSTRAINT_NAME='" + constraintName + "'";
}
String constraintName = database.correctObjectName(name, UniqueConstraint.class);

String showSql = "SHOW UNIQUE KEYS IN " + tableName;
String sql = "SELECT \"column_name\" AS COLUMN_NAME FROM TABLE(result_scan(last_query_id())) WHERE \"constraint_name\"= '" + constraintName +"'";

Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database)
.queryForList(new RawSqlStatement(showSql));

return Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database)
.queryForList(new RawSqlStatement(sql));
Expand Down