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

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


The following commit(s) were added to refs/heads/master by this push:
     new 6aa01e203 KUDU-1261 [Java] Add array column support in 
AlterTableOptions
6aa01e203 is described below

commit 6aa01e2030e8656787e1953c2de210dd2be4847b
Author: Abhishek Chennaka <[email protected]>
AuthorDate: Tue Oct 21 20:58:12 2025 -0700

    KUDU-1261 [Java] Add array column support in AlterTableOptions
    
    Added new methods addNullableArrayColumn() to AlterTableOptions to allow
    adding array-type columns to existing tables. These methods handle both
    basic and attribute-based array types (e.g., DECIMAL, VARCHAR) safely 
without
    direct use of Type.NESTED. Updated addNullableColumn()/addColumn() to reject
    nested types with a clear message.
    
    Introduced testAlterAddArrayColumns() to verify schema creation, mixed-null
    array insertion, and data retrieval.
    
    Change-Id: I22892e1a181f487d3146b1819a5cb0ea56579403
    Reviewed-on: http://gerrit.cloudera.org:8080/23570
    Tested-by: Abhishek Chennaka <[email protected]>
    Reviewed-by: Alexey Serbin <[email protected]>
---
 .../org/apache/kudu/client/AlterTableOptions.java  | 60 +++++++++++++
 .../org/apache/kudu/client/TestAlterTable.java     | 98 ++++++++++++++++++++++
 2 files changed, 158 insertions(+)

diff --git 
a/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableOptions.java 
b/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableOptions.java
index 7ee79a672..8b1069e3c 100644
--- 
a/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableOptions.java
+++ 
b/java/kudu-client/src/main/java/org/apache/kudu/client/AlterTableOptions.java
@@ -33,6 +33,7 @@ import org.apache.yetus.audience.InterfaceAudience;
 import org.apache.yetus.audience.InterfaceStability;
 
 import org.apache.kudu.ColumnSchema;
+import org.apache.kudu.ColumnTypeAttributes;
 import org.apache.kudu.Common;
 import org.apache.kudu.Schema;
 import org.apache.kudu.Type;
@@ -106,12 +107,18 @@ public class AlterTableOptions {
 
   /**
    * Add a new column that's not nullable.
+   * <p><b>Note:</b> To add array-typed columns, use
+   * {@link #addNullableArrayColumn(String, Type)}
    * @param name name of the new column
    * @param type type of the new column
    * @param defaultVal default value used for the currently existing rows
    * @return this instance
    */
   public AlterTableOptions addColumn(String name, Type type, Object 
defaultVal) {
+    if (type == Type.NESTED) {
+      throw new IllegalArgumentException(
+          "Use addNullableArrayColumn() for array columns instead of 
addNullableColumn().");
+    }
     return addColumn(new ColumnSchema.ColumnSchemaBuilder(name, type)
         .defaultValue(defaultVal)
         .build());
@@ -119,28 +126,81 @@ public class AlterTableOptions {
 
   /**
    * Add a new column that's nullable and has no default value.
+   * <p><b>Note:</b> To add array-typed columns, use
+   * {@link #addNullableArrayColumn(String, Type)}.
    * @param name name of the new column
    * @param type type of the new column
    * @return this instance
    */
   public AlterTableOptions addNullableColumn(String name, Type type) {
+    if (type == Type.NESTED) {
+      throw new IllegalArgumentException(
+          "Use addNullableArrayColumn() for array columns instead of 
addNullableColumn().");
+    }
     return addNullableColumn(name, type, null);
   }
 
   /**
    * Add a new column that's nullable.
+   * <p><b>Note:</b> To add array-typed columns, use
+   * {@link #addNullableArrayColumn(String, Type)}.
    * @param name name of the new column
    * @param type type of the new column
    * @param defaultVal the default value of the new column
    * @return this instance
    */
   public AlterTableOptions addNullableColumn(String name, Type type, Object 
defaultVal) {
+    if (type == Type.NESTED) {
+      throw new IllegalArgumentException(
+          "Use addNullableArrayColumn() for array columns instead of 
addNullableColumn().");
+    }
     return addColumn(new ColumnSchema.ColumnSchemaBuilder(name, type)
         .nullable(true)
         .defaultValue(defaultVal)
         .build());
   }
 
+
+  // TODO(achennaka) : Update addArrayColumn() here once default values for 
array datatype
+  // are implemented.
+  /**
+   * Adds a new nullable array column to the table schema.
+   *
+   * <p>If {@code attrs} is {@code null}, the column will use the default
+   * type attributes for the specified element type.
+   *
+   * @param name name of the new array column
+   * @param elementType element type stored in the array
+   * @param attrs optional type attributes for the element type
+   *              (precision/scale for DECIMAL, length for VARCHAR, etc.)
+   * @return this {@link AlterTableOptions} instance
+   * @throws IllegalArgumentException if the element type is unsupported
+   */
+  public AlterTableOptions addNullableArrayColumn(
+      String name, Type elementType, ColumnTypeAttributes attrs) {
+    ColumnSchema.ColumnSchemaBuilder builder =
+        new ColumnSchema.ColumnSchemaBuilder(name, elementType)
+            .array(true)
+            .nullable(true);
+    if (attrs != null) {
+      builder.typeAttributes(attrs);
+    }
+    return addColumn(builder.build());
+  }
+
+  /**
+   * Adds a new nullable array column to the table schema using
+   * the default type attributes for the element type.
+   *
+   * @param name name of the new array column
+   * @param elementType element type stored in the array
+   * @return this {@link AlterTableOptions} instance
+   * @throws IllegalArgumentException if the element type is unsupported
+   */
+  public AlterTableOptions addNullableArrayColumn(String name, Type 
elementType) {
+    return addNullableArrayColumn(name, elementType, null);
+  }
+
   /**
    * Drop a column.
    * @param name name of the column
diff --git 
a/java/kudu-client/src/test/java/org/apache/kudu/client/TestAlterTable.java 
b/java/kudu-client/src/test/java/org/apache/kudu/client/TestAlterTable.java
index d1f41c829..305c96787 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestAlterTable.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestAlterTable.java
@@ -22,10 +22,12 @@ import static 
org.apache.kudu.test.ClientTestUtil.scanTableToStrings;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -44,6 +46,7 @@ import org.junit.function.ThrowingRunnable;
 import org.apache.kudu.ColumnSchema;
 import org.apache.kudu.ColumnSchema.CompressionAlgorithm;
 import org.apache.kudu.ColumnSchema.Encoding;
+import org.apache.kudu.ColumnTypeAttributes;
 import org.apache.kudu.Schema;
 import org.apache.kudu.Type;
 import org.apache.kudu.test.KuduTestHarness;
@@ -370,6 +373,101 @@ public class TestAlterTable {
     assertEquals(0, col.getDefaultValue());
   }
 
+  @Test
+  public void testAlterAddArrayColumns() throws Exception {
+    // Create a simple base table
+    KuduTable table = createTable(ImmutableList.of());
+    insertRows(table, 0, 3);
+    assertEquals(3, countRowsInTable(table));
+
+    // Add several array columns via AlterTableOptions
+    AlterTableOptions opts = new AlterTableOptions()
+        .addNullableArrayColumn("ints_array", Type.INT32)
+        .addNullableArrayColumn("strings_array", Type.STRING)
+        .addNullableArrayColumn("decimals_array", Type.DECIMAL,
+            new ColumnTypeAttributes.ColumnTypeAttributesBuilder()
+                .precision(5)
+                .scale(2)
+                .build());
+
+    client.alterTable(tableName, opts);
+
+    // Verify schema after alter
+    table = client.openTable(tableName);
+    Schema schema = table.getSchema();
+    assertNotNull(schema.getColumn("ints_array"));
+    assertTrue(schema.getColumn("ints_array").isArray());
+    assertEquals(Type.INT32, schema.getColumn("ints_array")
+        .getNestedTypeDescriptor().getArrayDescriptor().getElemType());
+
+    assertTrue(schema.getColumn("strings_array").isArray());
+    assertEquals(Type.STRING, schema.getColumn("strings_array")
+        .getNestedTypeDescriptor().getArrayDescriptor().getElemType());
+
+    assertTrue(schema.getColumn("decimals_array").isArray());
+    assertEquals(Type.DECIMAL, schema.getColumn("decimals_array")
+        .getNestedTypeDescriptor().getArrayDescriptor().getElemType());
+
+    // Insert a row with array values
+    final KuduSession session = client.newSession();
+    Insert insert = table.newInsert();
+    PartialRow row = insert.getRow();
+    row.addInt("c0", 10);
+    row.addInt("c1", 10);
+
+    row.addArrayInt32(schema.getColumnIndex("ints_array"),
+        new int[]{1, 2, 3}, new boolean[]{true, false, true});
+
+    row.addArrayString(schema.getColumnIndex("strings_array"),
+        new String[]{"a", null, "c"}, null);
+
+    row.addArrayDecimal(schema.getColumnIndex("decimals_array"),
+        new BigDecimal[]{BigDecimal.valueOf(123, 2), null, 
BigDecimal.valueOf(456, 2)},
+        null);
+
+    session.apply(insert);
+    session.flush();
+    RowError[] rowErrors = session.getPendingErrors().getRowErrors();
+    assertEquals(0, rowErrors.length);
+
+    // Read back and verify data
+    KuduScanner scanner = client.newScannerBuilder(table).build();
+    RowResult rr = scanner.nextRows().next();
+
+    // ints_array
+    ArrayCellView ints = rr.getArray("ints_array");
+    assertEquals(3, ints.length());
+    assertEquals(1, ints.getInt32(0));
+    assertFalse(ints.isValid(1)); // null element
+    assertEquals(3, ints.getInt32(2));
+
+    // strings_array
+    ArrayCellView strs = rr.getArray("strings_array");
+    assertEquals(3, strs.length());
+    assertEquals("a", strs.getString(0));
+    assertFalse(strs.isValid(1));
+    assertEquals("c", strs.getString(2));
+
+    // decimals_array
+    BigDecimal[] decs = 
ArrayCellViewHelper.toDecimalArray(rr.getArray("decimals_array"), 5, 2);
+    assertEquals(new BigDecimal("1.23"), decs[0]);
+    assertNull(decs[1]);
+    assertEquals(new BigDecimal("4.56"), decs[2]);
+
+    // Verify schema-aware getArrayData() dispatch works
+    Integer[] intsBoxed = (Integer[]) rr.getArrayData("ints_array");
+    assertArrayEquals(new Integer[]{1, null, 3}, intsBoxed);
+
+    String[] strsBoxed = (String[]) rr.getArrayData("strings_array");
+    assertArrayEquals(new String[]{"a", null, "c"}, strsBoxed);
+
+    BigDecimal[] decsBoxed = (BigDecimal[]) rr.getArrayData("decimals_array");
+    assertEquals(new BigDecimal("1.23"), decsBoxed[0]);
+    assertNull(decsBoxed[1]);
+    assertEquals(new BigDecimal("4.56"), decsBoxed[2]);
+  }
+
+
   @Test
   public void testRenameKeyColumn() throws Exception {
     KuduTable table = createTable(ImmutableList.of());

Reply via email to