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

jmclean pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 4c886eb290 [#5755] Add List and Map types to table/columns in 
Gravitino CLI (#6098)
4c886eb290 is described below

commit 4c886eb290bf1aec5a72734ad4a583a60717f7f8
Author: Vincent Chee Jia Hong <33974196+jhc...@users.noreply.github.com>
AuthorDate: Sun Jan 5 22:06:11 2025 +0000

    [#5755] Add List and Map types to table/columns in Gravitino CLI (#6098)
    
    ### What changes were proposed in this pull request?
    - Supporting list and map types in Gravitino CLI operations.
    
    ### Why are the changes needed?
    Fix: # (issue) https://github.com/apache/gravitino/issues/5755
    
    ### Does this PR introduce _any_ user-facing change?
    No
    
    ### How was this patch tested?
    Unit test to verify ParseType class can handle list and map input.
---
 .../java/org/apache/gravitino/cli/ParseType.java   | 39 +++++++++-
 .../org/apache/gravitino/cli/TestParseType.java    | 84 +++++++++++++++-------
 2 files changed, 96 insertions(+), 27 deletions(-)

diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/ParseType.java 
b/clients/cli/src/main/java/org/apache/gravitino/cli/ParseType.java
index e797d0552a..9442175ef8 100644
--- a/clients/cli/src/main/java/org/apache/gravitino/cli/ParseType.java
+++ b/clients/cli/src/main/java/org/apache/gravitino/cli/ParseType.java
@@ -22,6 +22,7 @@ package org.apache.gravitino.cli;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.apache.gravitino.rel.types.Type;
+import org.apache.gravitino.rel.types.Types;
 
 public class ParseType {
 
@@ -36,7 +37,7 @@ public class ParseType {
    * @return a {@link org.apache.gravitino.cli.ParsedType} object representing 
the parsed type name.
    * @throws IllegalArgumentException if the data type format is unsupported 
or malformed
    */
-  public static ParsedType parse(String datatype) {
+  public static ParsedType parseBasicType(String datatype) {
     Pattern pattern = Pattern.compile("^(\\w+)\\((\\d+)(?:,(\\d+))?\\)$");
     Matcher matcher = pattern.matcher(datatype);
 
@@ -57,8 +58,8 @@ public class ParseType {
     return null;
   }
 
-  public static Type toType(String datatype) {
-    ParsedType parsed = parse(datatype);
+  private static Type toBasicType(String datatype) {
+    ParsedType parsed = parseBasicType(datatype);
 
     if (parsed != null) {
       if (parsed.getPrecision() != null && parsed.getScale() != null) {
@@ -70,4 +71,36 @@ public class ParseType {
 
     return TypeConverter.convert(datatype);
   }
+
+  private static Type toListType(String datatype) {
+    Pattern pattern = Pattern.compile("^list\\((.+)\\)$");
+    Matcher matcher = pattern.matcher(datatype);
+    if (matcher.matches()) {
+      Type elementType = toBasicType(matcher.group(1));
+      return Types.ListType.of(elementType, false);
+    }
+    throw new IllegalArgumentException("Malformed list type: " + datatype);
+  }
+
+  private static Type toMapType(String datatype) {
+    Pattern pattern = Pattern.compile("^map\\((.+),(.+)\\)$");
+    Matcher matcher = pattern.matcher(datatype);
+    if (matcher.matches()) {
+      Type keyType = toBasicType(matcher.group(1));
+      Type valueType = toBasicType(matcher.group(2));
+      return Types.MapType.of(keyType, valueType, false);
+    }
+    throw new IllegalArgumentException("Malformed map type: " + datatype);
+  }
+
+  public static Type toType(String datatype) {
+    if (datatype.startsWith("list")) {
+      return toListType(datatype);
+    } else if (datatype.startsWith("map")) {
+      return toMapType(datatype);
+    }
+
+    // fallback: if not complex type, parse as primitive type
+    return toBasicType(datatype);
+  }
 }
diff --git 
a/clients/cli/src/test/java/org/apache/gravitino/cli/TestParseType.java 
b/clients/cli/src/test/java/org/apache/gravitino/cli/TestParseType.java
index c53d3c2bdc..6c9132dbf4 100644
--- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestParseType.java
+++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestParseType.java
@@ -19,49 +19,85 @@
 
 package org.apache.gravitino.cli;
 
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
+import org.apache.gravitino.rel.types.Type;
+import org.apache.gravitino.rel.types.Types;
 import org.junit.jupiter.api.Test;
 
 public class TestParseType {
 
   @Test
-  public void testParseVarcharWithLength() {
-    ParsedType parsed = ParseType.parse("varchar(10)");
-    assertNotNull(parsed);
-    assertEquals("varchar", parsed.getTypeName());
-    assertEquals(10, parsed.getLength());
-    assertNull(parsed.getScale());
-    assertNull(parsed.getPrecision());
+  public void testParseTypeVarcharWithLength() {
+    Type type = ParseType.toType("varchar(10)");
+    assertThat(type, instanceOf(Types.VarCharType.class));
+    assertEquals(10, ((Types.VarCharType) type).length());
   }
 
   @Test
-  public void testParseDecimalWithPrecisionAndScale() {
-    ParsedType parsed = ParseType.parse("decimal(10,5)");
-    assertNotNull(parsed);
-    assertEquals("decimal", parsed.getTypeName());
-    assertEquals(10, parsed.getPrecision());
-    assertEquals(5, parsed.getScale());
-    assertNull(parsed.getLength());
+  public void testParseTypeDecimalWithPrecisionAndScale() {
+    Type type = ParseType.toType("decimal(10,5)");
+    assertThat(type, instanceOf(Types.DecimalType.class));
+    assertEquals(10, ((Types.DecimalType) type).precision());
+    assertEquals(5, ((Types.DecimalType) type).scale());
   }
 
   @Test
-  public void testParseIntegerWithoutParameters() {
-    ParsedType parsed = ParseType.parse("int()");
-    assertNull(parsed); // Expect null because the format is unsupported
+  public void testParseTypeListValidInput() {
+    Type type = ParseType.toType("list(integer)");
+    assertThat(type, instanceOf(Types.ListType.class));
+    Type elementType = ((Types.ListType) type).elementType();
+    assertThat(elementType, instanceOf(Types.IntegerType.class));
   }
 
   @Test
-  public void testParseOrdinaryInput() {
-    assertNull(ParseType.parse("string"));
-    assertNull(ParseType.parse("int"));
+  public void testParseTypeListMalformedInput() {
+    assertThrows(IllegalArgumentException.class, () -> 
ParseType.toType("list()"));
+    assertThrows(IllegalArgumentException.class, () -> 
ParseType.toType("list(10)"));
+    assertThrows(IllegalArgumentException.class, () -> 
ParseType.toType("list(unknown)"));
+    assertThrows(IllegalArgumentException.class, () -> 
ParseType.toType("list(integer,integer)"));
+    assertThrows(IllegalArgumentException.class, () -> 
ParseType.toType("list(integer"));
   }
 
   @Test
-  public void testParseMalformedInput() {
-    assertNull(ParseType.parse("varchar(-10)"));
-    assertNull(ParseType.parse("decimal(10,abc)"));
+  public void testParseTypeMapValidInput() {
+    Type type = ParseType.toType("map(string,integer)");
+    assertThat(type, instanceOf(Types.MapType.class));
+    Type keyType = ((Types.MapType) type).keyType();
+    Type valueType = ((Types.MapType) type).valueType();
+    assertThat(keyType, instanceOf(Types.StringType.class));
+    assertThat(valueType, instanceOf(Types.IntegerType.class));
+  }
+
+  @Test
+  public void testParseTypeMapMalformedInput() {
+    assertThrows(IllegalArgumentException.class, () -> 
ParseType.toType("map()"));
+    assertThrows(IllegalArgumentException.class, () -> 
ParseType.toType("map(10,10)"));
+    assertThrows(IllegalArgumentException.class, () -> 
ParseType.toType("map(unknown,unknown)"));
+    assertThrows(IllegalArgumentException.class, () -> 
ParseType.toType("map(string)"));
+    assertThrows(
+        IllegalArgumentException.class, () -> 
ParseType.toType("map(string,integer,integer)"));
+    assertThrows(IllegalArgumentException.class, () -> 
ParseType.toType("map(string,integer"));
+  }
+
+  @Test
+  public void testParseTypeIntegerWithoutParameters() {
+    assertThrows(IllegalArgumentException.class, () -> 
ParseType.toType("int()"));
+  }
+
+  @Test
+  public void testParseTypeOrdinaryInput() {
+    assertNull(ParseType.parseBasicType("string"));
+    assertNull(ParseType.parseBasicType("int"));
+  }
+
+  @Test
+  public void testParseTypeMalformedInput() {
+    assertThrows(IllegalArgumentException.class, () -> 
ParseType.toType("varchar(-10)"));
+    assertThrows(IllegalArgumentException.class, () -> 
ParseType.toType("decimal(10,abc)"));
   }
 }

Reply via email to