Copilot commented on code in PR #13448:
URL: https://github.com/apache/gravitino/pull/13448#discussion_r4073238879


##########
core/src/main/java/org/apache/gravitino/catalog/ManagedTableOperations.java:
##########
@@ -407,7 +407,14 @@ private List<ColumnEntity> applyColumnChanges(
                 newPosition,
                 newNullable,
                 newAutoIncrement);
-        newColumns.add(newColumn.position(), newColumn);
+        if (newPosition.isPresent()) {
+          newColumns.add(newColumn.position(), newColumn);
+        } else {
+          // Stored positions go stale as sibling changes in the same alter 
add or
+          // remove columns, so without an explicit position change the column 
goes
+          // back to the list index it was removed from.
+          newColumns.add(i, newColumn);
+        }

Review Comment:
   The reinsertion relies on `i` representing “the list index the column was 
removed from,” but that’s not explicit from the variable name and is easy to 
break if the surrounding loop/indexing changes. Consider capturing a clearly 
named `removedIndex` at the point of removal (and using that here), or using an 
iterator-based approach (`ListIterator#add`) so the reinsertion index is 
inherently tied to the removal location.



##########
core/src/test/java/org/apache/gravitino/catalog/TestManagedTableOperations.java:
##########
@@ -336,6 +336,52 @@ private Column createColumn(String name, Type dataType, 
Expression defaultValue)
         .build();
   }
 
+  @Test
+  public void testAlterTableBundledColumnChanges() {
+    NameIdentifier tableIdent =
+        NameIdentifierUtil.ofTable(METALAKE_NAME, CATALOG_NAME, SCHEMA_NAME, 
"bundled");
+    Column[] columns =
+        new Column[] {
+          createColumn("col1", Types.StringType.get(), null),
+          createColumn("col2", Types.IntegerType.get(), 
Literals.integerLiteral(1)),
+          createColumn("col3", Types.StringType.get(), null)
+        };
+    tableOperations.createTable(
+        tableIdent,
+        columns,
+        "Test bundled alters",
+        StringIdentifier.newPropertiesWithId(
+            StringIdentifier.fromId(idGenerator.nextId()), 
Collections.emptyMap()),
+        new Transform[0],
+        Distributions.NONE,
+        new SortOrder[0],
+        Indexes.EMPTY_INDEXES);
+
+    // A delete of a lower-position column followed by an update of a
+    // higher-position one must neither crash nor reorder the remaining 
columns.
+    Table updated =
+        tableOperations.alterTable(
+            tableIdent,
+            TableChange.deleteColumn(new String[] {"col1"}, false),
+            TableChange.updateColumnComment(new String[] {"col3"}, "updated"));
+    Assertions.assertArrayEquals(
+        new String[] {"col2", "col3"},
+        Arrays.stream(updated.columns()).map(Column::name).toArray());
+
+    // An add at first() followed by an update of a later column must keep 
order.
+    Table updated2 =
+        tableOperations.alterTable(
+            tableIdent,
+            TableChange.addColumn(
+                new String[] {"colNew"},
+                Types.StringType.get(),
+                TableChange.ColumnPosition.first()),
+            TableChange.updateColumnComment(new String[] {"col3"}, "updated 
again"));

Review Comment:
   The new test verifies column ordering, but it doesn’t assert that 
`updateColumnComment` actually updated the comment value. Adding assertions on 
the updated column’s comment (for both `"updated"` and `"updated again"`) would 
ensure the “update” part of the bundled alter is validated, not just the 
resulting order.



##########
core/src/test/java/org/apache/gravitino/catalog/TestManagedTableOperations.java:
##########
@@ -336,6 +336,52 @@ private Column createColumn(String name, Type dataType, 
Expression defaultValue)
         .build();
   }
 
+  @Test
+  public void testAlterTableBundledColumnChanges() {
+    NameIdentifier tableIdent =
+        NameIdentifierUtil.ofTable(METALAKE_NAME, CATALOG_NAME, SCHEMA_NAME, 
"bundled");
+    Column[] columns =
+        new Column[] {
+          createColumn("col1", Types.StringType.get(), null),
+          createColumn("col2", Types.IntegerType.get(), 
Literals.integerLiteral(1)),
+          createColumn("col3", Types.StringType.get(), null)
+        };
+    tableOperations.createTable(
+        tableIdent,
+        columns,
+        "Test bundled alters",
+        StringIdentifier.newPropertiesWithId(
+            StringIdentifier.fromId(idGenerator.nextId()), 
Collections.emptyMap()),
+        new Transform[0],
+        Distributions.NONE,
+        new SortOrder[0],
+        Indexes.EMPTY_INDEXES);
+
+    // A delete of a lower-position column followed by an update of a
+    // higher-position one must neither crash nor reorder the remaining 
columns.
+    Table updated =
+        tableOperations.alterTable(
+            tableIdent,
+            TableChange.deleteColumn(new String[] {"col1"}, false),
+            TableChange.updateColumnComment(new String[] {"col3"}, "updated"));
+    Assertions.assertArrayEquals(
+        new String[] {"col2", "col3"},
+        Arrays.stream(updated.columns()).map(Column::name).toArray());
+
+    // An add at first() followed by an update of a later column must keep 
order.
+    Table updated2 =
+        tableOperations.alterTable(
+            tableIdent,
+            TableChange.addColumn(
+                new String[] {"colNew"},
+                Types.StringType.get(),
+                TableChange.ColumnPosition.first()),
+            TableChange.updateColumnComment(new String[] {"col3"}, "updated 
again"));
+    Assertions.assertArrayEquals(
+        new String[] {"colNew", "col2", "col3"},
+        Arrays.stream(updated2.columns()).map(Column::name).toArray());

Review Comment:
   `Stream#toArray()` returns `Object[]`, which makes the assertion less 
type-specific and can hide type issues. Prefer collecting into a `String[]` 
(e.g., `toArray(String[]::new)`) so the actual array type matches the expected 
`String[]` explicitly.



##########
core/src/test/java/org/apache/gravitino/catalog/TestManagedTableOperations.java:
##########
@@ -336,6 +336,52 @@ private Column createColumn(String name, Type dataType, 
Expression defaultValue)
         .build();
   }
 
+  @Test
+  public void testAlterTableBundledColumnChanges() {
+    NameIdentifier tableIdent =
+        NameIdentifierUtil.ofTable(METALAKE_NAME, CATALOG_NAME, SCHEMA_NAME, 
"bundled");
+    Column[] columns =
+        new Column[] {
+          createColumn("col1", Types.StringType.get(), null),
+          createColumn("col2", Types.IntegerType.get(), 
Literals.integerLiteral(1)),
+          createColumn("col3", Types.StringType.get(), null)
+        };
+    tableOperations.createTable(
+        tableIdent,
+        columns,
+        "Test bundled alters",
+        StringIdentifier.newPropertiesWithId(
+            StringIdentifier.fromId(idGenerator.nextId()), 
Collections.emptyMap()),
+        new Transform[0],
+        Distributions.NONE,
+        new SortOrder[0],
+        Indexes.EMPTY_INDEXES);
+
+    // A delete of a lower-position column followed by an update of a
+    // higher-position one must neither crash nor reorder the remaining 
columns.
+    Table updated =
+        tableOperations.alterTable(
+            tableIdent,
+            TableChange.deleteColumn(new String[] {"col1"}, false),
+            TableChange.updateColumnComment(new String[] {"col3"}, "updated"));

Review Comment:
   The new test verifies column ordering, but it doesn’t assert that 
`updateColumnComment` actually updated the comment value. Adding assertions on 
the updated column’s comment (for both `"updated"` and `"updated again"`) would 
ensure the “update” part of the bundled alter is validated, not just the 
resulting order.



##########
core/src/test/java/org/apache/gravitino/catalog/TestManagedTableOperations.java:
##########
@@ -336,6 +336,52 @@ private Column createColumn(String name, Type dataType, 
Expression defaultValue)
         .build();
   }
 
+  @Test
+  public void testAlterTableBundledColumnChanges() {
+    NameIdentifier tableIdent =
+        NameIdentifierUtil.ofTable(METALAKE_NAME, CATALOG_NAME, SCHEMA_NAME, 
"bundled");
+    Column[] columns =
+        new Column[] {
+          createColumn("col1", Types.StringType.get(), null),
+          createColumn("col2", Types.IntegerType.get(), 
Literals.integerLiteral(1)),
+          createColumn("col3", Types.StringType.get(), null)
+        };
+    tableOperations.createTable(
+        tableIdent,
+        columns,
+        "Test bundled alters",
+        StringIdentifier.newPropertiesWithId(
+            StringIdentifier.fromId(idGenerator.nextId()), 
Collections.emptyMap()),
+        new Transform[0],
+        Distributions.NONE,
+        new SortOrder[0],
+        Indexes.EMPTY_INDEXES);
+
+    // A delete of a lower-position column followed by an update of a
+    // higher-position one must neither crash nor reorder the remaining 
columns.
+    Table updated =
+        tableOperations.alterTable(
+            tableIdent,
+            TableChange.deleteColumn(new String[] {"col1"}, false),
+            TableChange.updateColumnComment(new String[] {"col3"}, "updated"));
+    Assertions.assertArrayEquals(
+        new String[] {"col2", "col3"},
+        Arrays.stream(updated.columns()).map(Column::name).toArray());

Review Comment:
   `Stream#toArray()` returns `Object[]`, which makes the assertion less 
type-specific and can hide type issues. Prefer collecting into a `String[]` 
(e.g., `toArray(String[]::new)`) so the actual array type matches the expected 
`String[]` explicitly.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to