Skip to content

Commit

Permalink
DAT-18897: merged main changes, renamed ChangedTblPropertiesUtil.getE…
Browse files Browse the repository at this point in the history
…xtendedProperties -> getFilteredTblProperties. Removed filtering of table properties in snapshot.
  • Loading branch information
Mykhailo Savchenko committed Nov 6, 2024
2 parents 85efece + 0aa5b10 commit 43e0edc
Show file tree
Hide file tree
Showing 10 changed files with 397 additions and 16 deletions.
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-parent-pom</artifactId>
<version>0.4.5</version> <!-- Replace with the desired version -->
<version>0.5.0</version> <!-- Replace with the desired version -->
</parent>

<groupId>org.liquibase.ext</groupId>
Expand Down Expand Up @@ -53,7 +53,7 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<liquibase.version>4.29.2</liquibase.version>
<liquibase.version>4.30.0</liquibase.version>
<sonar.organization>liquibase</sonar.organization>
<sonar.projectKey>${sonar.organization}_${project.artifactId}</sonar.projectKey>
<sonar.projectName>${project.name}</sonar.projectName>
Expand Down Expand Up @@ -160,7 +160,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.10.1</version>
<version>3.11.1</version>
<configuration>
<attach>true</attach>
<author>false</author>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,9 @@ public SetExtendedTableProperties getSetExtendedTableProperties() {
public UnsetExtendedTableProperties getUnsetExtendedTableProperties() {
return unsetExtendedTableProperties;
}

@Override
public String getSerializedObjectNamespace() {
return "http://www.liquibase.org/xml/ns/databricks";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package liquibase.ext.databricks.diff.output.changelog;

import liquibase.change.Change;
import liquibase.database.Database;
import liquibase.diff.Difference;
import liquibase.diff.ObjectDifferences;
import liquibase.diff.output.DiffOutputControl;
import liquibase.diff.output.changelog.ChangeGeneratorChain;
import liquibase.diff.output.changelog.core.ChangedTableChangeGenerator;
import liquibase.ext.databricks.change.AbstractAlterPropertiesChangeDatabricks;
import liquibase.ext.databricks.database.DatabricksDatabase;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.Table;

import java.util.Arrays;

import static liquibase.ext.databricks.diff.output.changelog.ChangedTblPropertiesUtil.getAlterTablePropertiesChangeDatabricks;

/**
* Custom diff change generator for Databricks
*/
public class ChangedTableChangeGeneratorDatabricks extends ChangedTableChangeGenerator {

@Override
public int getPriority(Class<? extends DatabaseObject> objectType, Database database) {
if (database instanceof DatabricksDatabase && super.getPriority(objectType, database) > PRIORITY_NONE) {
return PRIORITY_DATABASE;
}
return PRIORITY_NONE;
}

@Override
public Change[] fixChanged(DatabaseObject changedObject, ObjectDifferences differences, DiffOutputControl control, Database referenceDatabase, Database comparisonDatabase, ChangeGeneratorChain chain) {
Change[] changes = super.fixChanged(changedObject, differences, control, referenceDatabase, comparisonDatabase, chain);
for (Difference difference : differences.getDifferences()) {
if (difference.getField().equals("tblProperties")) {
AbstractAlterPropertiesChangeDatabricks[] change = getAlterTablePropertiesChangeDatabricks((Table) changedObject, control, difference);

if (changes == null || changes.length == 0) {
changes = change;
} else {
changes = Arrays.copyOf(changes, changes.length + change.length);
System.arraycopy(change, 0, changes, changes.length - change.length, change.length);
}
}
}
return changes;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package liquibase.ext.databricks.diff.output.changelog;

import liquibase.diff.Difference;
import liquibase.diff.output.DiffOutputControl;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.ext.databricks.change.AbstractAlterPropertiesChangeDatabricks;
import liquibase.ext.databricks.change.alterTableProperties.AlterTablePropertiesChangeDatabricks;
import liquibase.ext.databricks.change.alterTableProperties.SetExtendedTableProperties;
import liquibase.ext.databricks.change.alterTableProperties.UnsetExtendedTableProperties;
import liquibase.ext.databricks.change.alterViewProperties.AlterViewPropertiesChangeDatabricks;
import liquibase.structure.AbstractDatabaseObject;
import liquibase.structure.core.Table;
import liquibase.structure.core.View;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* Utility class for changed table properties diff
*/
public class ChangedTblPropertiesUtil {


private static final String SPLIT_ON_COMMAS = ",(?=(?:[^\"]*\"[^\"]*\")*[^\"$])";
private static final String SPLIT_ON_EQUALS = "=(?=(?:[^\"]*\"[^\"]*\")*[^\"$])";

private ChangedTblPropertiesUtil() {
}

/**
* Get the AlterViewPropertiesChangeDatabricks changes
*/
static AbstractAlterPropertiesChangeDatabricks[] getAlterViewPropertiesChangeDatabricks(View changedObject, DiffOutputControl control, Difference difference) {
AbstractAlterPropertiesChangeDatabricks[] change = getAbstractTablePropertiesChangeDatabricks(changedObject, control, difference, AlterViewPropertiesChangeDatabricks.class);
Stream.of(change).forEach(c -> ((AlterViewPropertiesChangeDatabricks)c).setViewName(changedObject.getName()));
return change;
}

/**
* Get the AlterTablePropertiesChangeDatabricks changes
*/
static AbstractAlterPropertiesChangeDatabricks[] getAlterTablePropertiesChangeDatabricks(Table changedObject, DiffOutputControl control, Difference difference) {
AbstractAlterPropertiesChangeDatabricks[] change = getAbstractTablePropertiesChangeDatabricks(changedObject, control, difference, AlterTablePropertiesChangeDatabricks.class);
Stream.of(change).forEach(c -> ((AlterTablePropertiesChangeDatabricks)c).setTableName(changedObject.getName()));
return change;
}

static AbstractAlterPropertiesChangeDatabricks[] getAbstractTablePropertiesChangeDatabricks(AbstractDatabaseObject changedObject, DiffOutputControl control, Difference difference, Class<? extends AbstractAlterPropertiesChangeDatabricks> clazz) {
AbstractAlterPropertiesChangeDatabricks[] changes = new AbstractAlterPropertiesChangeDatabricks[0];
Map<String, String> referencedValuesMap = convertToMapExcludingDeltaParameters(difference.getReferenceValue());
Map<String, String> comparedValuesMap = convertToMapExcludingDeltaParameters(difference.getComparedValue());

Map<String, String> addPropertiesMap = new HashMap<>();
//first we add the missing or changed properties
referencedValuesMap.forEach((key, value) -> {
if (!comparedValuesMap.containsKey(key) || !comparedValuesMap.get(key).equals(value)) {
addPropertiesMap.put(key, value);
}
});
//then we remove the properties that are not in the reference
Map<String, String> removePropertiesMap = comparedValuesMap.entrySet().stream()
.filter(entry -> !referencedValuesMap.containsKey(entry.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

if (!addPropertiesMap.isEmpty()) {
SetExtendedTableProperties setExtendedTableProperties = new SetExtendedTableProperties();
setExtendedTableProperties.setTblProperties(addPropertiesMap.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(",")));
AbstractAlterPropertiesChangeDatabricks change = getAbstractAlterPropertiesChangeDatabricks(changedObject, control, clazz);
change.setSetExtendedTableProperties(setExtendedTableProperties);
changes = new AbstractAlterPropertiesChangeDatabricks[]{change};
}

if (!removePropertiesMap.isEmpty()) {
UnsetExtendedTableProperties unsetExtendedTableProperties = new UnsetExtendedTableProperties();
unsetExtendedTableProperties.setTblProperties(String.join(",", removePropertiesMap.keySet()));
AbstractAlterPropertiesChangeDatabricks change = getAbstractAlterPropertiesChangeDatabricks(changedObject, control, clazz);
change.setUnsetExtendedTableProperties(unsetExtendedTableProperties);
if (changes.length == 0) {
changes = new AbstractAlterPropertiesChangeDatabricks[]{change};
} else {
changes = Arrays.copyOf(changes, changes.length + 1);
changes[changes.length - 1] = change;
}
}

return changes;
}

/**
* Convert the reference value to a map excluding delta parameters
*/
private static Map<String, String> convertToMapExcludingDeltaParameters(Object referenceValueObject) {
String referenceValue = referenceValueObject == null ? "" : referenceValueObject.toString();
return Arrays.stream(referenceValue.split(SPLIT_ON_COMMAS))
.map(s -> s.split(SPLIT_ON_EQUALS))
.filter(a -> a.length > 1)
.map(a -> new String[]{a[0].trim(), a[1].trim()})
.filter(a -> !a[0].replace("'", "").matches("^delta.+"))
.collect(Collectors.toMap(a -> a[0], a -> a[1]));
}

/**
* Get the extended properties excluding delta parameters
*/
public static String getFilteredTblProperties(String tblProperties) {
Map<String, String> properties = convertToMapExcludingDeltaParameters(tblProperties);
return properties.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(","));
}

private static AbstractAlterPropertiesChangeDatabricks getAbstractAlterPropertiesChangeDatabricks(AbstractDatabaseObject changedObject, DiffOutputControl control, Class<? extends AbstractAlterPropertiesChangeDatabricks> clazz) {
AbstractAlterPropertiesChangeDatabricks change;
try {
change = clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new UnexpectedLiquibaseException("Reflection error", e);
}
if (control.getIncludeCatalog()) {
change.setCatalogName(changedObject.getSchema().getCatalogName());
}

if (control.getIncludeSchema()) {
change.setSchemaName(changedObject.getSchema().getName());
}
return change;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package liquibase.ext.databricks.diff.output.changelog;

import liquibase.change.Change;
import liquibase.database.Database;
import liquibase.diff.Difference;
import liquibase.diff.ObjectDifferences;
import liquibase.diff.output.DiffOutputControl;
import liquibase.diff.output.changelog.ChangeGeneratorChain;
import liquibase.diff.output.changelog.core.ChangedViewChangeGenerator;
import liquibase.ext.databricks.change.AbstractAlterPropertiesChangeDatabricks;
import liquibase.ext.databricks.database.DatabricksDatabase;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.View;

import java.util.Arrays;

import static liquibase.ext.databricks.diff.output.changelog.ChangedTblPropertiesUtil.getAlterViewPropertiesChangeDatabricks;


public class ChangedViewChangeGeneratorDatabricks extends ChangedViewChangeGenerator {

@Override
public int getPriority(Class<? extends DatabaseObject> objectType, Database database) {
if (database instanceof DatabricksDatabase && super.getPriority(objectType, database) > PRIORITY_NONE) {
return PRIORITY_DATABASE;
}
return PRIORITY_NONE;
}

@Override
public Change[] fixChanged(DatabaseObject changedObject, ObjectDifferences differences, DiffOutputControl control, Database referenceDatabase, Database comparisonDatabase, ChangeGeneratorChain chain) {
Change[] changes = null;
for (Difference difference : differences.getDifferences()) {
if (difference.getField().equals("tblProperties")) {
AbstractAlterPropertiesChangeDatabricks[] change = getAlterViewPropertiesChangeDatabricks((View) changedObject, control, difference);

if (changes == null) {
changes = change;
} else {
changes = Arrays.copyOf(changes, changes.length + change.length);
System.arraycopy(change, 0, changes, changes.length - change.length, change.length);
}
differences.removeDifference("tblProperties");
}
}

if (differences.hasDifferences()) {
Change[] otherChanges = super.fixChanged(changedObject, differences, control, referenceDatabase, comparisonDatabase, chain);
if (otherChanges != null) {
if (changes == null) {
changes = otherChanges;
} else {
changes = Arrays.copyOf(changes, changes.length + otherChanges.length);
System.arraycopy(otherChanges, 0, changes, changes.length - otherChanges.length, otherChanges.length);
}
}
}

return changes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.Table;

import static liquibase.ext.databricks.diff.output.changelog.ChangedTblPropertiesUtil.getFilteredTblProperties;

public class MissingTableChangeGeneratorDatabricks extends MissingTableChangeGenerator {

@Override
Expand All @@ -35,7 +37,7 @@ public Change[] fixMissing(DatabaseObject missingObject, DiffOutputControl contr
ExtendedTableProperties extendedTableProperties = new ExtendedTableProperties(
null,
null,
missingObject.getAttribute("tblProperties", String.class),
getFilteredTblProperties(missingObject.getAttribute("tblProperties", String.class)),
missingObject.getAttribute("clusteringColumns", String.class),
missingObject.getAttribute("partitionColumns", String.class)
);
Expand Down Expand Up @@ -65,4 +67,4 @@ private CreateTableChangeDatabricks getCreateTableChangeDatabricks(ExtendedTable
protected CreateTableChange createCreateTableChange() {
return new CreateTableChangeDatabricks();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.View;

import static liquibase.ext.databricks.diff.output.changelog.ChangedTblPropertiesUtil.getFilteredTblProperties;

/**
* Custom implementation of {@link MissingViewChangeGenerator} for Databricks.
*/
Expand All @@ -31,7 +33,7 @@ public Change[] fixMissing(DatabaseObject missingObject, DiffOutputControl contr
if (changes == null || changes.length == 0) {
return changes;
}
changes[0] = getCreateViewChangeDatabricks(missingObject.getAttribute("tblProperties", String.class), changes);
changes[0] = getCreateViewChangeDatabricks(getFilteredTblProperties(missingObject.getAttribute("tblProperties", String.class)), changes);
return changes;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.Table;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
Expand All @@ -25,12 +24,6 @@ public class TableSnapshotGeneratorDatabricks extends TableSnapshotGenerator {
private static final String PARTITION_COLUMNS = "partitionColumns";
private static final String DETAILED_TABLE_INFORMATION_NODE = "# Detailed Table Information";
private static final String TABLE_PARTITION_INFORMATION_NODE = "# Partition Information";
private static final List<String> TBL_PROPERTIES_STOP_LIST = Arrays.asList(
"delta.columnMapping.maxColumnId",
"delta.rowTracking.materializedRowCommitVersionColumnName",
"delta.rowTracking.materializedRowIdColumnName",
"delta.feature.clustering"
);

@Override
public int getPriority(Class<? extends DatabaseObject> objectType, Database database) {
Expand Down Expand Up @@ -79,8 +72,6 @@ protected DatabaseObject snapshotObject(DatabaseObject example, DatabaseSnapshot
}
}
Map<String, String> tblProperties = getTblPropertiesMap(database, example.getName());
// removing Databricks system properties which are not allowed in create/alter table statements
TBL_PROPERTIES_STOP_LIST.forEach(tblProperties::remove);
if (tblProperties.containsKey(CLUSTER_COLUMNS)) {
table.setAttribute(CLUSTER_COLUMNS, sanitizeClusterColumns(tblProperties.remove(CLUSTER_COLUMNS)));
}
Expand Down Expand Up @@ -119,4 +110,4 @@ private String sanitizeClusterColumns(String clusterColumnProperty) {
return clusterColumnProperty.replaceAll(pattern.toString(), "");
}

}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
liquibase.ext.databricks.diff.output.changelog.MissingTableChangeGeneratorDatabricks
liquibase.ext.databricks.diff.output.changelog.MissingViewChangeGeneratorDatabricks
liquibase.ext.databricks.diff.output.changelog.ChangedTableChangeGeneratorDatabricks
liquibase.ext.databricks.diff.output.changelog.ChangedViewChangeGeneratorDatabricks
Loading

0 comments on commit 43e0edc

Please sign in to comment.