This is an automated email from the ASF dual-hosted git repository.

blue pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iceberg.git


The following commit(s) were added to refs/heads/master by this push:
     new d8cc2a2  Core: Support adding columns deleted in the same operation 
(#2204)
d8cc2a2 is described below

commit d8cc2a29364e57df95c4e50f4079bacd35e4a047
Author: Thomas <[email protected]>
AuthorDate: Tue Feb 9 14:05:27 2021 -0800

    Core: Support adding columns deleted in the same operation (#2204)
---
 .../main/java/org/apache/iceberg/SchemaUpdate.java |  6 ++-
 .../java/org/apache/iceberg/TestSchemaUpdate.java  | 55 ++++++++++++++++++++++
 2 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/core/src/main/java/org/apache/iceberg/SchemaUpdate.java 
b/core/src/main/java/org/apache/iceberg/SchemaUpdate.java
index 16ba971..e4f2593 100644
--- a/core/src/main/java/org/apache/iceberg/SchemaUpdate.java
+++ b/core/src/main/java/org/apache/iceberg/SchemaUpdate.java
@@ -136,13 +136,15 @@ class SchemaUpdate implements UpdateSchema {
           parentField.type().isNestedType() && 
parentField.type().asNestedType().isStructType(),
           "Cannot add to non-struct column: %s: %s", parent, 
parentField.type());
       parentId = parentField.fieldId();
+      Types.NestedField currentField = schema.findField(parent + "." + name);
       Preconditions.checkArgument(!deletes.contains(parentId),
           "Cannot add to a column that will be deleted: %s", parent);
-      Preconditions.checkArgument(schema.findField(parent + "." + name) == 
null,
+      Preconditions.checkArgument(currentField == null || 
deletes.contains(currentField.fieldId()),
           "Cannot add column, name already exists: %s.%s", parent, name);
       fullName = schema.findColumnName(parentId) + "." + name;
     } else {
-      Preconditions.checkArgument(schema.findField(name) == null,
+      Types.NestedField currentField = schema.findField(name);
+      Preconditions.checkArgument(currentField == null || 
deletes.contains(currentField.fieldId()),
           "Cannot add column, name already exists: %s", name);
       fullName = name;
     }
diff --git a/core/src/test/java/org/apache/iceberg/TestSchemaUpdate.java 
b/core/src/test/java/org/apache/iceberg/TestSchemaUpdate.java
index 4e48e1d..ecd29b8 100644
--- a/core/src/test/java/org/apache/iceberg/TestSchemaUpdate.java
+++ b/core/src/test/java/org/apache/iceberg/TestSchemaUpdate.java
@@ -502,6 +502,61 @@ public class TestSchemaUpdate {
   }
 
   @Test
+  public void testDeleteThenAdd() {
+    Schema schema = new Schema(required(1, "id", Types.IntegerType.get()));
+    Schema expected = new Schema(optional(2, "id", Types.IntegerType.get()));
+
+    Schema updated = new SchemaUpdate(schema, 1)
+        .deleteColumn("id")
+        .addColumn("id", optional(2, "id", Types.IntegerType.get()).type())
+        .apply();
+
+    Assert.assertEquals("Should match with added fields", expected.asStruct(), 
updated.asStruct());
+  }
+
+  @Test
+  public void testDeleteThenAddNested() {
+    Schema expectedNested = new Schema(
+        required(1, "id", Types.IntegerType.get()),
+        optional(2, "data", Types.StringType.get()),
+        optional(3, "preferences", Types.StructType.of(
+            optional(9, "feature2", Types.BooleanType.get()),
+            optional(24, "feature1", Types.BooleanType.get())
+        ), "struct of named boolean options"),
+        required(4, "locations", Types.MapType.ofRequired(10, 11,
+            Types.StructType.of(
+                    required(20, "address", Types.StringType.get()),
+                    required(21, "city", Types.StringType.get()),
+                    required(22, "state", Types.StringType.get()),
+                    required(23, "zip", Types.IntegerType.get())
+            ),
+            Types.StructType.of(
+                    required(12, "lat", Types.FloatType.get()),
+                    required(13, "long", Types.FloatType.get())
+            )), "map of address to coordinate"),
+        optional(5, "points", Types.ListType.ofOptional(14,
+            Types.StructType.of(
+                    required(15, "x", Types.LongType.get()),
+                    required(16, "y", Types.LongType.get())
+            )), "2-D cartesian points"),
+        required(6, "doubles", Types.ListType.ofRequired(17,
+            Types.DoubleType.get()
+        )),
+        optional(7, "properties", Types.MapType.ofOptional(18, 19,
+            Types.StringType.get(),
+            Types.StringType.get()
+        ), "string map of properties")
+    );
+
+    Schema updatedNested = new SchemaUpdate(SCHEMA, SCHEMA_LAST_COLUMN_ID)
+        .deleteColumn("preferences.feature1")
+        .addColumn("preferences", "feature1", Types.BooleanType.get())
+        .apply();
+
+    Assert.assertEquals("Should match with added fields", 
expectedNested.asStruct(), updatedNested.asStruct());
+  }
+
+  @Test
   public void testDeleteMissingColumn() {
     AssertHelpers.assertThrows("Should reject delete missing column",
         IllegalArgumentException.class, "missing column: col", () -> {

Reply via email to