Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions lib/src/main/java/io/cloudquery/schema/Table.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package io.cloudquery.schema;

import static io.cloudquery.schema.TableColumnChangeType.ADD;
import static io.cloudquery.schema.TableColumnChangeType.REMOVE;
import static io.cloudquery.schema.TableColumnChangeType.UPDATE;

import io.cloudquery.glob.Glob;
import io.cloudquery.schema.Column.ColumnBuilder;
import io.cloudquery.transformers.TransformerException;
Expand All @@ -18,6 +22,7 @@
@Builder(toBuilder = true)
@Getter
public class Table {

public interface Transform {
void transformTable(Table table) throws TransformerException;
}
Expand Down Expand Up @@ -203,4 +208,39 @@ public Optional<Column> getColumn(String name) {
}
return Optional.empty();
}

public List<TableColumnChange> getChanges(Table old) {
List<TableColumnChange> changes = new ArrayList<>();
for (Column currentColumn : columns) {
Optional<Column> oldColumn = old.getColumn(currentColumn.getName());
if (oldColumn.isEmpty()) {
changes.add(new TableColumnChange(ADD, currentColumn.getName(), currentColumn, null));
continue;
}
if (shouldUpdate(currentColumn, oldColumn.get())) {
changes.add(
new TableColumnChange(UPDATE, currentColumn.getName(), currentColumn, oldColumn.get()));
}
}
for (Column column : old.columns) {
Optional<Column> otherColumn = getColumn(column.getName());
if (otherColumn.isEmpty()) {
changes.add(new TableColumnChange(REMOVE, column.getName(), null, column));
}
}
return changes;
}

private static boolean shouldUpdate(Column currentColumn, Column oldColumn) {
if (!oldColumn.getType().equals(currentColumn.getType())) {
return true;
}
if (oldColumn.isPrimaryKey() != currentColumn.isPrimaryKey()) {
return true;
}
if (oldColumn.isNotNull() != currentColumn.isNotNull()) {
return true;
}
return oldColumn.isUnique() != currentColumn.isUnique();
}
}
13 changes: 13 additions & 0 deletions lib/src/main/java/io/cloudquery/schema/TableColumnChange.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.cloudquery.schema;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class TableColumnChange {
private TableColumnChangeType type;
private String columnName;
private Column current;
private Column previous;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.cloudquery.schema;

public enum TableColumnChangeType {
REMOVE,
UPDATE,
ADD
}
104 changes: 104 additions & 0 deletions lib/src/test/java/io/cloudquery/schema/TableColumnChangeTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package io.cloudquery.schema;

import static org.junit.jupiter.api.Assertions.assertEquals;

import io.cloudquery.schema.Table.TableBuilder;
import java.util.List;
import org.apache.arrow.vector.types.pojo.ArrowType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class TableColumnChangeTest {

private TableBuilder tableBuilder;

@BeforeEach
public void setUp() {
tableBuilder =
Table.builder()
.name("test")
.columns(
List.of(
Column.builder().name("basic_column").type(ArrowType.Bool.INSTANCE).build()));
}

@Test
public void shouldBeNoChangesWithIdenticalTables() {
Table old = tableBuilder.build();
Table current = tableBuilder.build();

List<TableColumnChange> changes = current.getChanges(old);

assertEquals(0, changes.size(), "should be no changes");
}

@Test
public void shouldAddColumnIfNewTableHasAdditionalColumn() {
Table old = tableBuilder.build();
Table current =
tableBuilder
.columns(
List.of(
Column.builder().name("basic_column").type(ArrowType.Bool.INSTANCE).build(),
Column.builder()
.name("additional_column")
.type(ArrowType.Bool.INSTANCE)
.build()))
.build();

List<TableColumnChange> changes = current.getChanges(old);

assertEquals(1, changes.size(), "should be 1 change");
TableColumnChange change = changes.get(0);
assertEquals(TableColumnChangeType.ADD, change.getType());
assertEquals("additional_column", change.getColumnName());
assertEquals("additional_column", change.getCurrent().getName());
}

@Test
public void shouldRemoveColumnIfNewTableHasLessColumns() {
Table old =
Table.builder()
.name("test")
.columns(
List.of(
Column.builder().name("basic_column").type(ArrowType.Bool.INSTANCE).build(),
Column.builder()
.name("additional_column")
.type(ArrowType.Bool.INSTANCE)
.build()))
.build();

Table current = tableBuilder.build();

List<TableColumnChange> changes = current.getChanges(old);

assertEquals(1, changes.size(), "should be 1 change");
TableColumnChange change = changes.get(0);
assertEquals(TableColumnChangeType.REMOVE, change.getType());
assertEquals("additional_column", change.getColumnName());
assertEquals("additional_column", change.getPrevious().getName());
}

@Test
public void shouldUpdateColumnIfNewTableHasUpdateChange() {
Table old = tableBuilder.build();
Table current =
tableBuilder
.columns(
List.of(
Column.builder().name("basic_column").type(ArrowType.Utf8.INSTANCE).build()))
.build();

List<TableColumnChange> changes = current.getChanges(old);

assertEquals(1, changes.size(), "should be 1 change");
TableColumnChange change = changes.get(0);
assertEquals(TableColumnChangeType.UPDATE, change.getType());
assertEquals("basic_column", change.getColumnName());
assertEquals("basic_column", change.getCurrent().getName());
assertEquals("basic_column", change.getPrevious().getName());
assertEquals(ArrowType.Bool.INSTANCE, change.getPrevious().getType());
assertEquals(ArrowType.Utf8.INSTANCE, change.getCurrent().getType());
}
}