diff --git a/pom.xml b/pom.xml index 79b22b46..d0ef453b 100644 --- a/pom.xml +++ b/pom.xml @@ -125,6 +125,12 @@ 2.6.38 compile + + org.projectlombok + lombok + 1.18.32 + provided + diff --git a/src/main/java/liquibase/ext/databricks/change/alterTableProperties/AlterTablePropertiesChangeDatabricks.java b/src/main/java/liquibase/ext/databricks/change/alterTableProperties/AlterTablePropertiesChangeDatabricks.java new file mode 100644 index 00000000..15505575 --- /dev/null +++ b/src/main/java/liquibase/ext/databricks/change/alterTableProperties/AlterTablePropertiesChangeDatabricks.java @@ -0,0 +1,89 @@ +package liquibase.ext.databricks.change.alterTableProperties; + +import liquibase.change.AbstractChange; +import liquibase.change.DatabaseChange; +import liquibase.change.DatabaseChangeProperty; +import liquibase.database.Database; +import liquibase.exception.ValidationErrors; +import liquibase.ext.databricks.database.DatabricksDatabase; +import liquibase.servicelocator.PrioritizedService; +import liquibase.statement.SqlStatement; +import lombok.Setter; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; + +import static liquibase.statement.SqlStatement.EMPTY_SQL_STATEMENT; + +@Setter +@DatabaseChange(name = "alterTableProperties", description = "Alter Table Properties", priority = PrioritizedService.PRIORITY_DATABASE + 500) +public class AlterTablePropertiesChangeDatabricks extends AbstractChange { + + private String tableName; + private String catalogName; + private String schemaName; + private SetExtendedTableProperties setExtendedTableProperties; + private UnsetExtendedTableProperties unsetExtendedTableProperties; + + @Override + public boolean supports(Database database) { + return database instanceof DatabricksDatabase; + } + + @Override + public ValidationErrors validate(Database database) { + ValidationErrors validationErrors = new ValidationErrors(); + validationErrors.addAll(super.validate(database)); + + if (setExtendedTableProperties == null && unsetExtendedTableProperties == null) { + validationErrors.addError("Alter Table Properties change require 'setExtendedTableProperties' or 'unsetExtendedTableProperties' element, please add at least one option."); + } + return validationErrors; + } + + @Override + public String getConfirmationMessage() { + return MessageFormat.format("{0}.{1}.{2} successfully altered.", getCatalogName(), getSchemaName(), getTableName()); + } + + @Override + public SqlStatement[] generateStatements(Database database) { + AlterTablePropertiesStatementDatabricks statement = new AlterTablePropertiesStatementDatabricks(getCatalogName(), getSchemaName(), getTableName()); + + if (setExtendedTableProperties != null) { + statement.setSetExtendedTableProperties(setExtendedTableProperties); + } else if (unsetExtendedTableProperties != null) { + statement.setUnsetExtendedTableProperties(unsetExtendedTableProperties); + } + + List statements = new ArrayList<>(); + statements.add(statement); + return statements.toArray(EMPTY_SQL_STATEMENT); + } + + @DatabaseChangeProperty + public String getCatalogName() { + return catalogName; + } + + @DatabaseChangeProperty + public String getSchemaName() { + return schemaName; + } + + @DatabaseChangeProperty + public String getTableName() { + return tableName; + } + + @DatabaseChangeProperty + public SetExtendedTableProperties getSetExtendedTableProperties() { + return setExtendedTableProperties; + } + + @DatabaseChangeProperty + public UnsetExtendedTableProperties getUnsetExtendedTableProperties() { + return unsetExtendedTableProperties; + } +} diff --git a/src/main/java/liquibase/ext/databricks/change/alterTableProperties/AlterTablePropertiesStatementDatabricks.java b/src/main/java/liquibase/ext/databricks/change/alterTableProperties/AlterTablePropertiesStatementDatabricks.java new file mode 100644 index 00000000..b7170eed --- /dev/null +++ b/src/main/java/liquibase/ext/databricks/change/alterTableProperties/AlterTablePropertiesStatementDatabricks.java @@ -0,0 +1,23 @@ +package liquibase.ext.databricks.change.alterTableProperties; + +import liquibase.statement.AbstractSqlStatement; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class AlterTablePropertiesStatementDatabricks extends AbstractSqlStatement { + + private String tableName; + private String catalogName; + private String schemaName; + private SetExtendedTableProperties setExtendedTableProperties; + private UnsetExtendedTableProperties unsetExtendedTableProperties; + + public AlterTablePropertiesStatementDatabricks(String catalogName, String schemaName, String tableName) { + this.tableName = tableName; + this.catalogName = catalogName; + this.schemaName = schemaName; + } + +} diff --git a/src/main/java/liquibase/ext/databricks/change/alterTableProperties/SetExtendedTableProperties.java b/src/main/java/liquibase/ext/databricks/change/alterTableProperties/SetExtendedTableProperties.java new file mode 100644 index 00000000..d7571640 --- /dev/null +++ b/src/main/java/liquibase/ext/databricks/change/alterTableProperties/SetExtendedTableProperties.java @@ -0,0 +1,21 @@ +package liquibase.ext.databricks.change.alterTableProperties; + +import liquibase.serializer.AbstractLiquibaseSerializable; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class SetExtendedTableProperties extends AbstractLiquibaseSerializable { + private String tblProperties; + + @Override + public String getSerializedObjectName() { + return "setExtendedTableProperties"; + } + + @Override + public String getSerializedObjectNamespace() { + return "http://www.liquibase.org/xml/ns/databricks"; + } +} diff --git a/src/main/java/liquibase/ext/databricks/change/alterTableProperties/UnsetExtendedTableProperties.java b/src/main/java/liquibase/ext/databricks/change/alterTableProperties/UnsetExtendedTableProperties.java new file mode 100644 index 00000000..ef1bff71 --- /dev/null +++ b/src/main/java/liquibase/ext/databricks/change/alterTableProperties/UnsetExtendedTableProperties.java @@ -0,0 +1,21 @@ +package liquibase.ext.databricks.change.alterTableProperties; + +import liquibase.serializer.AbstractLiquibaseSerializable; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class UnsetExtendedTableProperties extends AbstractLiquibaseSerializable{ + private String tblProperties; + + @Override + public String getSerializedObjectName() { + return "unsetExtendedTableProperties"; + } + + @Override + public String getSerializedObjectNamespace() { + return "http://www.liquibase.org/xml/ns/databricks"; + } +} diff --git a/src/main/java/liquibase/ext/databricks/sqlgenerator/AlterTablePropertiesGeneratorDatabricks.java b/src/main/java/liquibase/ext/databricks/sqlgenerator/AlterTablePropertiesGeneratorDatabricks.java new file mode 100644 index 00000000..3e52a107 --- /dev/null +++ b/src/main/java/liquibase/ext/databricks/sqlgenerator/AlterTablePropertiesGeneratorDatabricks.java @@ -0,0 +1,52 @@ +package liquibase.ext.databricks.sqlgenerator; + +import liquibase.database.Database; +import liquibase.exception.ValidationErrors; +import liquibase.ext.databricks.change.alterTableProperties.AlterTablePropertiesStatementDatabricks; +import liquibase.ext.databricks.database.DatabricksDatabase; +import liquibase.sql.Sql; +import liquibase.sql.UnparsedSql; +import liquibase.sqlgenerator.SqlGeneratorChain; +import liquibase.sqlgenerator.core.AbstractSqlGenerator; + +public class AlterTablePropertiesGeneratorDatabricks extends AbstractSqlGenerator { + + @Override + public boolean supports(AlterTablePropertiesStatementDatabricks statement, Database database) { + return super.supports(statement, database) && (database instanceof DatabricksDatabase); + } + + @Override + public int getPriority() { + return DatabricksDatabase.DATABRICKS_PRIORITY_DATABASE; + } + + @Override + public ValidationErrors validate(AlterTablePropertiesStatementDatabricks statement, Database database, SqlGeneratorChain sqlGeneratorChain) { + ValidationErrors validationErrors = new ValidationErrors(); + if (statement.getSetExtendedTableProperties() == null && statement.getUnsetExtendedTableProperties() == null){ + validationErrors.addError("WARNING! Alter Table Properties change require 'setExtendedTableProperties' or 'unsetExtendedTableProperties' element, please add at least one option."); + } + return validationErrors; + } + + @Override + public Sql[] generateSql(AlterTablePropertiesStatementDatabricks statement, Database database, SqlGeneratorChain sqlGeneratorChain) { + StringBuilder buffer = new StringBuilder(); + + buffer.append("ALTER TABLE "); + buffer.append(database.escapeTableName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName())); + if (statement.getSetExtendedTableProperties() != null) { + buffer.append(" SET TBLPROPERTIES ("); + buffer.append(statement.getSetExtendedTableProperties().getTblProperties()); + } else if (statement.getUnsetExtendedTableProperties() != null) { + buffer.append(" UNSET TBLPROPERTIES ("); + buffer.append(statement.getUnsetExtendedTableProperties().getTblProperties()); + } + buffer.append(")"); + + return new Sql[]{ + new UnparsedSql(buffer.toString()) + }; + } +} diff --git a/src/main/resources/META-INF/services/liquibase.change.Change b/src/main/resources/META-INF/services/liquibase.change.Change index 129e740c..93aa7f79 100644 --- a/src/main/resources/META-INF/services/liquibase.change.Change +++ b/src/main/resources/META-INF/services/liquibase.change.Change @@ -4,4 +4,5 @@ liquibase.ext.databricks.change.analyzeTable.AnalyzeTableChange liquibase.ext.databricks.change.vacuumTable.VacuumTableChange liquibase.ext.databricks.change.addLookupTable.AddLookupTableChangeDatabricks liquibase.ext.databricks.change.addCheckConstraint.AddCheckConstraintChangeDatabricks -liquibase.ext.databricks.change.dropCheckConstraint.DropCheckConstraintChangeDatabricks \ No newline at end of file +liquibase.ext.databricks.change.dropCheckConstraint.DropCheckConstraintChangeDatabricks +liquibase.ext.databricks.change.alterTableProperties.AlterTablePropertiesChangeDatabricks \ No newline at end of file diff --git a/src/main/resources/META-INF/services/liquibase.sqlgenerator.SqlGenerator b/src/main/resources/META-INF/services/liquibase.sqlgenerator.SqlGenerator index 46fb3529..0af35927 100644 --- a/src/main/resources/META-INF/services/liquibase.sqlgenerator.SqlGenerator +++ b/src/main/resources/META-INF/services/liquibase.sqlgenerator.SqlGenerator @@ -17,4 +17,5 @@ liquibase.ext.databricks.sqlgenerator.AddUniqueConstraintGeneratorDatabricks liquibase.ext.databricks.sqlgenerator.InsertOrUpdateGeneratorDatabricks liquibase.ext.databricks.sqlgenerator.UpdateGeneratorDatabricks liquibase.ext.databricks.change.addCheckConstraint.AddCheckConstraintGeneratorDatabricks -liquibase.ext.databricks.change.dropCheckConstraint.DropCheckConstraintGeneratorDatabricks \ No newline at end of file +liquibase.ext.databricks.change.dropCheckConstraint.DropCheckConstraintGeneratorDatabricks +liquibase.ext.databricks.sqlgenerator.AlterTablePropertiesGeneratorDatabricks \ No newline at end of file diff --git a/src/main/resources/www.liquibase.org/xml/ns/databricks/liquibase-databricks-1.0.xsd b/src/main/resources/www.liquibase.org/xml/ns/databricks/liquibase-databricks-1.0.xsd index 973f4e36..4e61b353 100644 --- a/src/main/resources/www.liquibase.org/xml/ns/databricks/liquibase-databricks-1.0.xsd +++ b/src/main/resources/www.liquibase.org/xml/ns/databricks/liquibase-databricks-1.0.xsd @@ -11,4 +11,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/www.liquibase.org/xml/ns/databricks/liquibase-databricks-latest.xsd b/src/main/resources/www.liquibase.org/xml/ns/databricks/liquibase-databricks-latest.xsd index 973f4e36..4e61b353 100644 --- a/src/main/resources/www.liquibase.org/xml/ns/databricks/liquibase-databricks-latest.xsd +++ b/src/main/resources/www.liquibase.org/xml/ns/databricks/liquibase-databricks-latest.xsd @@ -11,4 +11,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/liquibase/harness/change/changelogs/databricks/alterTableProperties.json b/src/test/resources/liquibase/harness/change/changelogs/databricks/alterTableProperties.json new file mode 100644 index 00000000..c53b746c --- /dev/null +++ b/src/test/resources/liquibase/harness/change/changelogs/databricks/alterTableProperties.json @@ -0,0 +1,51 @@ +{ + "databaseChangeLog": [ + { + "changeSet": { + "id": "1", + "author": "your.name", + "changes": [ + { + "createTable": { + "tableName": "test_alter_table_properties", + "columns": [ + { + "column": { + "name":"test_id", + "type": "int" + } + } + ] + } + } + ] + } + }, + { + "changeSet": { + "id": "2", + "author": "your.name", + "changes": [ + { + "alterTableProperties": { + "tableName": "test_alter_table_properties", + "setExtendedTableProperties": { + "tblProperties": "'external.location'='s3://mybucket/mytable','this.is.my.key'=12,'this.is.my.key2'=true" + } + } + } + ], + "rollback": [ + { + "alterTableProperties": { + "tableName": "test_alter_table_properties", + "unsetExtendedTableProperties": { + "tblProperties": "'external.location', 'this.is.my.key','this.is.my.key2'" + } + } + } + ] + } + } + ] +} diff --git a/src/test/resources/liquibase/harness/change/changelogs/databricks/alterTableProperties.xml b/src/test/resources/liquibase/harness/change/changelogs/databricks/alterTableProperties.xml new file mode 100644 index 00000000..c6e1c94c --- /dev/null +++ b/src/test/resources/liquibase/harness/change/changelogs/databricks/alterTableProperties.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/liquibase/harness/change/changelogs/databricks/alterTableProperties.yaml b/src/test/resources/liquibase/harness/change/changelogs/databricks/alterTableProperties.yaml new file mode 100644 index 00000000..5262b6ef --- /dev/null +++ b/src/test/resources/liquibase/harness/change/changelogs/databricks/alterTableProperties.yaml @@ -0,0 +1,24 @@ +databaseChangeLog: + - changeSet: + id: 1 + author: your.name + changes: + - createTable: + tableName: test_alter_table_properties + columns: + - column: + name: test_id + type: int + - changeSet: + id: 2 + author: your.name + changes: + - alterTableProperties: + tableName: test_alter_table_properties + setExtendedTableProperties: + tblProperties: "'external.location'='s3://mybucket/mytable','this.is.my.key'=12,'this.is.my.key2'=true" + rollback: + - alterTableProperties: + tableName: test_alter_table_properties + unsetExtendedTableProperties: + tblProperties: "'external.location', 'this.is.my.key','this.is.my.key2'" diff --git a/src/test/resources/liquibase/harness/change/expectedSnapshot/databricks/alterTableProperties.json b/src/test/resources/liquibase/harness/change/expectedSnapshot/databricks/alterTableProperties.json new file mode 100644 index 00000000..0e0dcd23 --- /dev/null +++ b/src/test/resources/liquibase/harness/change/expectedSnapshot/databricks/alterTableProperties.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/src/test/resources/liquibase/harness/change/expectedSql/databricks/alterTableProperties.sql b/src/test/resources/liquibase/harness/change/expectedSql/databricks/alterTableProperties.sql new file mode 100644 index 00000000..24b6d1fe --- /dev/null +++ b/src/test/resources/liquibase/harness/change/expectedSql/databricks/alterTableProperties.sql @@ -0,0 +1,2 @@ +CREATE TABLE main.liquibase_harness_test_ds.test_alter_table_properties (test_id INT NOT NULL, test_column VARCHAR(50) NOT NULL, CONSTRAINT PK_TEST_ALTER_TABLE_PROPERTIES PRIMARY KEY (test_id)) USING delta TBLPROPERTIES('delta.feature.allowColumnDefaults' = 'supported', 'delta.columnMapping.mode' = 'name', 'delta.enableDeletionVectors' = true) +ALTER TABLE main.liquibase_harness_test_ds.test_alter_table_properties SET TBLPROPERTIES ('external.location'='s3://mybucket/mytable','this.is.my.key'=12,'this.is.my.key2'=true)