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());