From 96664345a98db1e79007e4733d9db90cbb50377b Mon Sep 17 00:00:00 2001 From: pancx Date: Sat, 22 Feb 2025 12:02:42 +0800 Subject: [PATCH 1/7] [#6493] feat(CLI): Support table format output for Schema and Table command Support table format output for Schema and Table command --- .../gravitino/cli/commands/ListSchema.java | 8 +- .../gravitino/cli/commands/ListTables.java | 29 +++-- .../gravitino/cli/commands/SchemaDetails.java | 2 +- .../gravitino/cli/commands/TableDetails.java | 4 +- .../gravitino/cli/outputs/TableFormat.java | 102 +++++++++++++++ .../gravitino/cli/output/TestTableFormat.java | 123 +++++++++++++++++- 6 files changed, 248 insertions(+), 20 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java index bbc881ce06e..5be4f4fcfe9 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java @@ -19,7 +19,6 @@ package org.apache.gravitino.cli.commands; -import com.google.common.base.Joiner; import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; @@ -60,8 +59,11 @@ public void handle() { exitWithError(exp.getMessage()); } - String all = schemas.length == 0 ? "No schemas exist." : Joiner.on(",").join(schemas); + if (schemas.length == 0) { + printInformation("No schemas found in catalog " + catalog); + return; + } - printInformation(all); + printResults(schemas); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java index e1389ed9d1a..642dd45766a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java @@ -19,12 +19,13 @@ package org.apache.gravitino.cli.commands; -import com.google.common.base.Joiner; import java.util.ArrayList; import java.util.List; import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.Namespace; import org.apache.gravitino.cli.CommandContext; +import org.apache.gravitino.rel.Table; +import org.apache.gravitino.rel.TableCatalog; /** List the names of all tables in a schema. */ public class ListTables extends TableCommand { @@ -49,22 +50,32 @@ public ListTables(CommandContext context, String metalake, String catalog, Strin public void handle() { NameIdentifier[] tables = null; Namespace name = Namespace.of(schema); + TableCatalog tableCatalog = null; + try { - tables = tableCatalog().listTables(name); + tableCatalog = tableCatalog(); + tables = tableCatalog.listTables(name); } catch (Exception exp) { exitWithError(exp.getMessage()); } List tableNames = new ArrayList<>(); - for (int i = 0; i < tables.length; i++) { - tableNames.add(tables[i].name()); + for (NameIdentifier table : tables) { + tableNames.add(table.name()); + } + // PERF load table may cause performance issue + Table[] tableObjects = new Table[tableNames.size()]; + int i = 0; + for (NameIdentifier tableIdent : tables) { + tableObjects[i] = tableCatalog.loadTable(tableIdent); + i++; } - String all = - tableNames.isEmpty() - ? "No tables exist." - : Joiner.on(System.lineSeparator()).join(tableNames); + if (tableNames.isEmpty()) { + printInformation("No tables exist."); + return; + } - printResults(all); + printResults(tableObjects); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SchemaDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SchemaDetails.java index b9c530aea5e..560fca20dfd 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SchemaDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SchemaDetails.java @@ -68,7 +68,7 @@ public void handle() { } if (result != null) { - printInformation(result.name() + "," + result.comment()); + printResults(result); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableDetails.java index 8ac9fb4fb63..23950e7ee93 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableDetails.java @@ -57,6 +57,8 @@ public void handle() { exitWithError(exp.getMessage()); } - printInformation(gTable.name() + "," + gTable.comment()); + if (gTable != null) { + printResults(gTable); + } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java b/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java index 6d08f73edf0..f266b81b79c 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java @@ -47,7 +47,9 @@ import java.util.Objects; import org.apache.gravitino.Catalog; import org.apache.gravitino.Metalake; +import org.apache.gravitino.Schema; import org.apache.gravitino.cli.CommandContext; +import org.apache.gravitino.rel.Table; /** * Abstract base class for formatting entity information into ASCII-art tables. Provides @@ -75,6 +77,14 @@ public static void output(Object entity, CommandContext context) { new CatalogTableFormat(context).output((Catalog) entity); } else if (entity instanceof Catalog[]) { new CatalogListTableFormat(context).output((Catalog[]) entity); + } else if (entity instanceof Schema) { + new SchemaTableFormat(context).output((Schema) entity); + } else if (entity instanceof Schema[]) { + new SchemaListTableFormat(context).output((Schema[]) entity); + } else if (entity instanceof Table) { + new TableDetailsTableFormat(context).output((Table) entity); + } else if (entity instanceof Table[]) { + new TableListTableFormat(context).output((Table[]) entity); } else { throw new IllegalArgumentException("Unsupported object type"); } @@ -540,4 +550,96 @@ public String getOutput(Catalog[] catalogs) { return getTableFormat(columnName); } } + + /** + * Formats a single {@link Schema} instance into a two-column table display. Displays catalog + * details including name and comment information. + */ + static final class SchemaTableFormat extends TableFormat { + public SchemaTableFormat(CommandContext context) { + super(context); + } + + /** {@inheritDoc} */ + @Override + public String getOutput(Schema schema) { + Column columnName = new Column(context, "schema"); + Column columnComment = new Column(context, "comment"); + + columnName.addCell(schema.name()); + columnComment.addCell(schema.comment()); + + return getTableFormat(columnName, columnComment); + } + } + + /** + * Formats an array of Schemas into a single-column table display. Lists all schema names in a + * vertical format. + */ + static final class SchemaListTableFormat extends TableFormat { + public SchemaListTableFormat(CommandContext context) { + super(context); + } + + /** {@inheritDoc} */ + @Override + public String getOutput(Schema[] schemas) { + Column column = new Column(context, "schema"); + Arrays.stream(schemas).forEach(schema -> column.addCell(schema.name())); + + return getTableFormat(column); + } + } + + /** + * Formats a single {@link Table} instance into a two-column table display. Displays table details + * including name and comment information. + */ + static final class TableDetailsTableFormat extends TableFormat { + public TableDetailsTableFormat(CommandContext context) { + super(context); + } + + /** {@inheritDoc} */ + @Override + public String getOutput(Table table) { + Column columnName = new Column(context, "name"); + Column columnType = new Column(context, "type"); + Column columnAutoIncrement = new Column(context, "AutoIncrement"); + Column columnNullable = new Column(context, "nullable"); + Column columnComment = new Column(context, "comment"); + + org.apache.gravitino.rel.Column[] columns = table.columns(); + for (org.apache.gravitino.rel.Column column : columns) { + columnName.addCell(column.name()); + columnType.addCell(column.dataType().simpleString()); + columnAutoIncrement.addCell(column.autoIncrement()); + columnNullable.addCell(column.nullable()); + columnComment.addCell(column.comment().isEmpty() ? "N/A" : column.comment()); + } + + return getTableFormat( + columnName, columnType, columnAutoIncrement, columnNullable, columnComment); + } + } + + /** + * Formats an array of {@link Table} into a single-column table display. Lists all table names in + * a vertical format. + */ + static final class TableListTableFormat extends TableFormat { + public TableListTableFormat(CommandContext context) { + super(context); + } + + /** {@inheritDoc} */ + @Override + public String getOutput(Table[] tables) { + Column column = new Column(context, "name"); + Arrays.stream(tables).forEach(table -> column.addCell(table.name())); + + return getTableFormat(column); + } + } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java b/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java index 64d5ea4987b..9c6df8e94e3 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java @@ -28,9 +28,13 @@ import java.nio.charset.StandardCharsets; import org.apache.gravitino.Catalog; import org.apache.gravitino.Metalake; +import org.apache.gravitino.Schema; import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.outputs.Column; import org.apache.gravitino.cli.outputs.TableFormat; +import org.apache.gravitino.rel.Table; +import org.apache.gravitino.rel.types.Type; +import org.apache.gravitino.rel.types.Types; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -295,6 +299,75 @@ void testListCatalogWithTableFormat() { output); } + @Test + void testSchemaDetailsWithTableFormat() { + CommandContext mockContext = getMockContext(); + Schema mockSchema = getMockSchema(); + + TableFormat.output(mockSchema, mockContext); + String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim(); + Assertions.assertEquals( + "+-------------+-----------------------+\n" + + "| Schema | Comment |\n" + + "+-------------+-----------------------+\n" + + "| demo_schema | This is a demo schema |\n" + + "+-------------+-----------------------+", + output); + } + + @Test + void testListSchemaWithTableFormat() { + CommandContext mockContext = getMockContext(); + Schema mockSchema1 = getMockSchema("schema1", "This is a schema"); + Schema mockSchema2 = getMockSchema("schema2", "This is another schema"); + + TableFormat.output(new Schema[] {mockSchema1, mockSchema2}, mockContext); + String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim(); + Assertions.assertEquals( + "+---------+\n" + + "| Schema |\n" + + "+---------+\n" + + "| schema1 |\n" + + "| schema2 |\n" + + "+---------+", + output); + } + + @Test + void testTableDetailsWithTableFormat() { + CommandContext mockContext = getMockContext(); + Table mockTable = getMockTable(); + + TableFormat.output(mockTable, mockContext); + String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim(); + Assertions.assertEquals( + "+------+---------+---------------+----------+-------------------------+\n" + + "| Name | Type | AutoIncrement | Nullable | Comment |\n" + + "+------+---------+---------------+----------+-------------------------+\n" + + "| id | integer | true | false | This is a int column |\n" + + "| name | string | false | true | This is a string column |\n" + + "+------+---------+---------------+----------+-------------------------+", + output); + } + + @Test + void testListTableWithTableFormat() { + CommandContext mockContext = getMockContext(); + Table mockTable1 = getMockTable("table1", "This is a table"); + Table mockTable2 = getMockTable("table2", "This is another table"); + + TableFormat.output(new Table[] {mockTable1, mockTable2}, mockContext); + String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim(); + Assertions.assertEquals( + "+--------+\n" + + "| Name |\n" + + "+--------+\n" + + "| table1 |\n" + + "| table2 |\n" + + "+--------+", + output); + } + @Test void testOutputWithUnsupportType() { CommandContext mockContext = getMockContext(); @@ -307,12 +380,6 @@ void testOutputWithUnsupportType() { }); } - private void addRepeatedCells(Column column, int count) { - for (int i = 0; i < count; i++) { - column.addCell(column.getHeader() + "-" + (i + 1)); - } - } - private CommandContext getMockContext() { CommandContext mockContext = mock(CommandContext.class); @@ -345,4 +412,48 @@ private Catalog getMockCatalog(String name, Catalog.Type type, String provider, return mockCatalog; } + + private Schema getMockSchema() { + return getMockSchema("demo_schema", "This is a demo schema"); + } + + private Schema getMockSchema(String name, String comment) { + Schema mockSchema = mock(Schema.class); + when(mockSchema.name()).thenReturn(name); + when(mockSchema.comment()).thenReturn(comment); + + return mockSchema; + } + + private Table getMockTable() { + return getMockTable("demo_table", "This is a demo table"); + } + + private Table getMockTable(String name, String comment) { + Table mockTable = mock(Table.class); + org.apache.gravitino.rel.Column mockColumnInt = + getMockColumn("id", Types.IntegerType.get(), "This is a int column", false, true); + org.apache.gravitino.rel.Column mockColumnString = + getMockColumn("name", Types.StringType.get(), "This is a string column", true, false); + + when(mockTable.name()).thenReturn(name); + when(mockTable.comment()).thenReturn(comment); + when(mockTable.columns()) + .thenReturn(new org.apache.gravitino.rel.Column[] {mockColumnInt, mockColumnString}); + + return mockTable; + } + + private org.apache.gravitino.rel.Column getMockColumn( + String name, Type dataType, String comment, boolean nullable, boolean autoIncrement) { + + org.apache.gravitino.rel.Column mockColumn = mock(org.apache.gravitino.rel.Column.class); + when(mockColumn.name()).thenReturn(name); + when(mockColumn.dataType()).thenReturn(dataType); + when(mockColumn.comment()).thenReturn(comment); + when(mockColumn.nullable()).thenReturn(nullable); + when(mockColumn.autoIncrement()).thenReturn(autoIncrement); + + return mockColumn; + } } From 2b67d2300f6dd029e506bc4a16d022b5e0a0e215 Mon Sep 17 00:00:00 2001 From: pancx Date: Sat, 22 Feb 2025 12:14:04 +0800 Subject: [PATCH 2/7] [#6493] feat(CLI): Support table format output for Schema and Table command fix some bugs. --- .../apache/gravitino/cli/commands/ListSchema.java | 14 ++++++++++++-- .../apache/gravitino/cli/outputs/TableFormat.java | 3 ++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java index 5be4f4fcfe9..69bfb18e80b 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java @@ -19,6 +19,8 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.Catalog; +import org.apache.gravitino.Schema; import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; @@ -48,9 +50,12 @@ public ListSchema(CommandContext context, String metalake, String catalog) { @Override public void handle() { String[] schemas = new String[0]; + Catalog tableCatalog = null; + try { GravitinoClient client = buildClient(metalake); - schemas = client.loadCatalog(catalog).asSchemas().listSchemas(); + tableCatalog = client.loadCatalog(catalog); + schemas = tableCatalog.asSchemas().listSchemas(); } catch (NoSuchMetalakeException err) { exitWithError(ErrorMessages.UNKNOWN_METALAKE); } catch (NoSuchCatalogException err) { @@ -64,6 +69,11 @@ public void handle() { return; } - printResults(schemas); + Schema[] schemaObjects = new Schema[schemas.length]; + for (int i = 0; i < schemas.length; i++) { + schemaObjects[i] = tableCatalog.asSchemas().loadSchema(schemas[i]); + } + + printResults(schemaObjects); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java b/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java index f266b81b79c..c3a4fa3647d 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java @@ -616,7 +616,8 @@ public String getOutput(Table table) { columnType.addCell(column.dataType().simpleString()); columnAutoIncrement.addCell(column.autoIncrement()); columnNullable.addCell(column.nullable()); - columnComment.addCell(column.comment().isEmpty() ? "N/A" : column.comment()); + columnComment.addCell( + column.comment() == null || column.comment().isEmpty() ? "N/A" : column.comment()); } return getTableFormat( From bccc0c1225c627c20f8d7b6b893c1da01c0959e2 Mon Sep 17 00:00:00 2001 From: pancx Date: Sat, 22 Feb 2025 12:15:03 +0800 Subject: [PATCH 3/7] [#6493] feat(CLI): Support table format output for Schema and Table command fix some bugs. --- .../main/java/org/apache/gravitino/cli/commands/ListSchema.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java index 69bfb18e80b..e71363f516c 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java @@ -68,7 +68,7 @@ public void handle() { printInformation("No schemas found in catalog " + catalog); return; } - + // PERF load table may cause performance issue Schema[] schemaObjects = new Schema[schemas.length]; for (int i = 0; i < schemas.length; i++) { schemaObjects[i] = tableCatalog.asSchemas().loadSchema(schemas[i]); From f266f5a869b3273986f80e32b6e65762180fc419 Mon Sep 17 00:00:00 2001 From: pancx Date: Sun, 23 Feb 2025 23:33:33 +0800 Subject: [PATCH 4/7] [#6493] feat(CLI): Support table format output for Schema and Table command fix some bugs. --- .../gravitino/cli/commands/ListSchema.java | 16 ++----- .../gravitino/cli/commands/ListTables.java | 20 ++------ .../gravitino/cli/outputs/TableFormat.java | 46 ++++++------------- .../integration/test/TableFormatOutputIT.java | 4 +- .../gravitino/cli/output/TestTableFormat.java | 22 +++------ 5 files changed, 28 insertions(+), 80 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java index e71363f516c..1651c1b1805 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java @@ -19,8 +19,6 @@ package org.apache.gravitino.cli.commands; -import org.apache.gravitino.Catalog; -import org.apache.gravitino.Schema; import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; @@ -50,12 +48,9 @@ public ListSchema(CommandContext context, String metalake, String catalog) { @Override public void handle() { String[] schemas = new String[0]; - Catalog tableCatalog = null; - try { GravitinoClient client = buildClient(metalake); - tableCatalog = client.loadCatalog(catalog); - schemas = tableCatalog.asSchemas().listSchemas(); + schemas = client.loadCatalog(catalog).asSchemas().listSchemas(); } catch (NoSuchMetalakeException err) { exitWithError(ErrorMessages.UNKNOWN_METALAKE); } catch (NoSuchCatalogException err) { @@ -65,15 +60,10 @@ public void handle() { } if (schemas.length == 0) { - printInformation("No schemas found in catalog " + catalog); + printInformation("No schemas exist."); return; } - // PERF load table may cause performance issue - Schema[] schemaObjects = new Schema[schemas.length]; - for (int i = 0; i < schemas.length; i++) { - schemaObjects[i] = tableCatalog.asSchemas().loadSchema(schemas[i]); - } - printResults(schemaObjects); + printResults(schemas); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java index 642dd45766a..5a25ec28279 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java @@ -24,8 +24,6 @@ import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.Namespace; import org.apache.gravitino.cli.CommandContext; -import org.apache.gravitino.rel.Table; -import org.apache.gravitino.rel.TableCatalog; /** List the names of all tables in a schema. */ public class ListTables extends TableCommand { @@ -50,25 +48,15 @@ public ListTables(CommandContext context, String metalake, String catalog, Strin public void handle() { NameIdentifier[] tables = null; Namespace name = Namespace.of(schema); - TableCatalog tableCatalog = null; - try { - tableCatalog = tableCatalog(); - tables = tableCatalog.listTables(name); + tables = tableCatalog().listTables(name); } catch (Exception exp) { exitWithError(exp.getMessage()); } List tableNames = new ArrayList<>(); - for (NameIdentifier table : tables) { - tableNames.add(table.name()); - } - // PERF load table may cause performance issue - Table[] tableObjects = new Table[tableNames.size()]; - int i = 0; - for (NameIdentifier tableIdent : tables) { - tableObjects[i] = tableCatalog.loadTable(tableIdent); - i++; + for (int i = 0; i < tables.length; i++) { + tableNames.add(tables[i].name()); } if (tableNames.isEmpty()) { @@ -76,6 +64,6 @@ public void handle() { return; } - printResults(tableObjects); + printResults(tableNames); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java b/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java index c3a4fa3647d..f90f9193e7c 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java @@ -79,12 +79,10 @@ public static void output(Object entity, CommandContext context) { new CatalogListTableFormat(context).output((Catalog[]) entity); } else if (entity instanceof Schema) { new SchemaTableFormat(context).output((Schema) entity); - } else if (entity instanceof Schema[]) { - new SchemaListTableFormat(context).output((Schema[]) entity); } else if (entity instanceof Table) { new TableDetailsTableFormat(context).output((Table) entity); - } else if (entity instanceof Table[]) { - new TableListTableFormat(context).output((Table[]) entity); + } else if (entity instanceof String[]) { + new ListTableFormat(context).output((String[]) entity); } else { throw new IllegalArgumentException("Unsupported object type"); } @@ -497,7 +495,7 @@ public MetalakeListTableFormat(CommandContext context) { @Override public String getOutput(Metalake[] metalakes) { - Column columnName = new Column(context, "metalake"); + Column columnName = new Column(context, "Name"); Arrays.stream(metalakes).forEach(metalake -> columnName.addCell(metalake.name())); return getTableFormat(columnName); @@ -544,7 +542,7 @@ public CatalogListTableFormat(CommandContext context) { /** {@inheritDoc} */ @Override public String getOutput(Catalog[] catalogs) { - Column columnName = new Column(context, "catalog"); + Column columnName = new Column(context, "Name"); Arrays.stream(catalogs).forEach(metalake -> columnName.addCell(metalake.name())); return getTableFormat(columnName); @@ -573,25 +571,6 @@ public String getOutput(Schema schema) { } } - /** - * Formats an array of Schemas into a single-column table display. Lists all schema names in a - * vertical format. - */ - static final class SchemaListTableFormat extends TableFormat { - public SchemaListTableFormat(CommandContext context) { - super(context); - } - - /** {@inheritDoc} */ - @Override - public String getOutput(Schema[] schemas) { - Column column = new Column(context, "schema"); - Arrays.stream(schemas).forEach(schema -> column.addCell(schema.name())); - - return getTableFormat(column); - } - } - /** * Formats a single {@link Table} instance into a two-column table display. Displays table details * including name and comment information. @@ -625,20 +604,21 @@ public String getOutput(Table table) { } } - /** - * Formats an array of {@link Table} into a single-column table display. Lists all table names in - * a vertical format. - */ - static final class TableListTableFormat extends TableFormat { - public TableListTableFormat(CommandContext context) { + static final class ListTableFormat extends TableFormat { + /** + * Creates a new {@link TableFormat} with the specified properties. + * + * @param context the command context. + */ + public ListTableFormat(CommandContext context) { super(context); } /** {@inheritDoc} */ @Override - public String getOutput(Table[] tables) { + public String getOutput(String[] entities) { Column column = new Column(context, "name"); - Arrays.stream(tables).forEach(table -> column.addCell(table.name())); + Arrays.stream(entities).forEach(column::addCell); return getTableFormat(column); } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/integration/test/TableFormatOutputIT.java b/clients/cli/src/test/java/org/apache/gravitino/cli/integration/test/TableFormatOutputIT.java index bca9e960ff5..e8b8b2c17df 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/integration/test/TableFormatOutputIT.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/integration/test/TableFormatOutputIT.java @@ -106,7 +106,7 @@ public void testMetalakeListCommand() { String output = new String(outputStream.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( "+-------------+\n" - + "| Metalake |\n" + + "| Name |\n" + "+-------------+\n" + "| my_metalake |\n" + "+-------------+", @@ -170,7 +170,7 @@ public void testCatalogListCommand() { String output = new String(outputStream.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( "+-----------+\n" - + "| Catalog |\n" + + "| Name |\n" + "+-----------+\n" + "| postgres |\n" + "| postgres2 |\n" diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java b/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java index 9c6df8e94e3..448ae31081a 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java @@ -255,7 +255,7 @@ void testListMetalakeWithTableFormat() { String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim(); Assertions.assertEquals( "+-----------+\n" - + "| Metalake |\n" + + "| Name |\n" + "+-----------+\n" + "| metalake1 |\n" + "| metalake2 |\n" @@ -282,16 +282,11 @@ void testCatalogDetailsWithTableFormat() { @Test void testListCatalogWithTableFormat() { CommandContext mockContext = getMockContext(); - Catalog mockCatalog1 = - getMockCatalog("catalog1", Catalog.Type.FILESET, "provider1", "This is a catalog"); - Catalog mockCatalog2 = - getMockCatalog("catalog2", Catalog.Type.RELATIONAL, "provider2", "This is another catalog"); - - TableFormat.output(new Catalog[] {mockCatalog1, mockCatalog2}, mockContext); + TableFormat.output(new String[] {"catalog1", "catalog2"}, mockContext); String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim(); Assertions.assertEquals( "+----------+\n" - + "| Catalog |\n" + + "| Name |\n" + "+----------+\n" + "| catalog1 |\n" + "| catalog2 |\n" @@ -318,14 +313,11 @@ void testSchemaDetailsWithTableFormat() { @Test void testListSchemaWithTableFormat() { CommandContext mockContext = getMockContext(); - Schema mockSchema1 = getMockSchema("schema1", "This is a schema"); - Schema mockSchema2 = getMockSchema("schema2", "This is another schema"); - - TableFormat.output(new Schema[] {mockSchema1, mockSchema2}, mockContext); + TableFormat.output(new String[] {"schema1", "schema2"}, mockContext); String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim(); Assertions.assertEquals( "+---------+\n" - + "| Schema |\n" + + "| Name |\n" + "+---------+\n" + "| schema1 |\n" + "| schema2 |\n" @@ -353,10 +345,8 @@ void testTableDetailsWithTableFormat() { @Test void testListTableWithTableFormat() { CommandContext mockContext = getMockContext(); - Table mockTable1 = getMockTable("table1", "This is a table"); - Table mockTable2 = getMockTable("table2", "This is another table"); - TableFormat.output(new Table[] {mockTable1, mockTable2}, mockContext); + TableFormat.output(new String[] {"table1", "table2"}, mockContext); String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim(); Assertions.assertEquals( "+--------+\n" From 2f12d06283635ed1b7881e55d5549bb5a721a871 Mon Sep 17 00:00:00 2001 From: pancx Date: Mon, 24 Feb 2025 00:23:07 +0800 Subject: [PATCH 5/7] [#6493] feat(CLI): Support table format output for Schema and Table command fix some bugs. --- .../main/java/org/apache/gravitino/cli/commands/ListTables.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java index 5a25ec28279..a46588cdf89 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java @@ -64,6 +64,6 @@ public void handle() { return; } - printResults(tableNames); + printResults(tableNames.toArray(new String[0])); } } From 6b454388fe4021ce4f92a3d15b1a0ae6033bbb19 Mon Sep 17 00:00:00 2001 From: pancx Date: Mon, 24 Feb 2025 14:22:23 +0800 Subject: [PATCH 6/7] [#6493] feat(CLI): Support table format output for Schema and Table command fix some bugs. --- .../gravitino/cli/commands/Command.java | 2 +- .../gravitino/cli/commands/ListSchema.java | 17 +++++-- .../gravitino/cli/commands/ListTables.java | 23 +++++---- .../gravitino/cli/outputs/TableFormat.java | 48 +++++++++++++------ .../integration/test/TableFormatOutputIT.java | 4 +- .../gravitino/cli/output/TestTableFormat.java | 39 ++++++++++----- 6 files changed, 91 insertions(+), 42 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java index f789e2336b9..de860f5a695 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java @@ -235,7 +235,7 @@ protected Builder constructClient(Builder * @param entity The entity to output. * @param The type of entity. */ - protected void output(T entity) { + private void output(T entity) { if (outputFormat == null) { PlainFormat.output(entity, context); return; diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java index 1651c1b1805..23ae6bce816 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java @@ -19,6 +19,8 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.Catalog; +import org.apache.gravitino.Schema; import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; @@ -48,9 +50,13 @@ public ListSchema(CommandContext context, String metalake, String catalog) { @Override public void handle() { String[] schemas = new String[0]; + GravitinoClient client; + Catalog gCatalog = null; + try { - GravitinoClient client = buildClient(metalake); - schemas = client.loadCatalog(catalog).asSchemas().listSchemas(); + client = buildClient(metalake); + gCatalog = client.loadCatalog(catalog); + schemas = gCatalog.asSchemas().listSchemas(); } catch (NoSuchMetalakeException err) { exitWithError(ErrorMessages.UNKNOWN_METALAKE); } catch (NoSuchCatalogException err) { @@ -59,11 +65,16 @@ public void handle() { exitWithError(exp.getMessage()); } + Schema[] schemaObjects = new Schema[schemas.length]; + for (int i = 0; i < schemas.length; i++) { + schemaObjects[i] = gCatalog.asSchemas().loadSchema(schemas[i]); + } + if (schemas.length == 0) { printInformation("No schemas exist."); return; } - printResults(schemas); + printResults(schemaObjects); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java index a46588cdf89..62a89149359 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java @@ -19,11 +19,11 @@ package org.apache.gravitino.cli.commands; -import java.util.ArrayList; -import java.util.List; import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.Namespace; import org.apache.gravitino.cli.CommandContext; +import org.apache.gravitino.rel.Table; +import org.apache.gravitino.rel.TableCatalog; /** List the names of all tables in a schema. */ public class ListTables extends TableCommand { @@ -48,22 +48,25 @@ public ListTables(CommandContext context, String metalake, String catalog, Strin public void handle() { NameIdentifier[] tables = null; Namespace name = Namespace.of(schema); + TableCatalog gCatalog = null; + try { - tables = tableCatalog().listTables(name); + gCatalog = tableCatalog(); + tables = gCatalog.listTables(name); } catch (Exception exp) { exitWithError(exp.getMessage()); } - List tableNames = new ArrayList<>(); - for (int i = 0; i < tables.length; i++) { - tableNames.add(tables[i].name()); - } - - if (tableNames.isEmpty()) { + if (tables.length == 0) { printInformation("No tables exist."); return; } - printResults(tableNames.toArray(new String[0])); + Table[] gTables = new Table[tables.length]; + for (int i = 0; i < tables.length; i++) { + gTables[i] = gCatalog.loadTable(tables[i]); + } + + printResults(gTables); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java b/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java index f90f9193e7c..e5021d62f3b 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/outputs/TableFormat.java @@ -79,10 +79,12 @@ public static void output(Object entity, CommandContext context) { new CatalogListTableFormat(context).output((Catalog[]) entity); } else if (entity instanceof Schema) { new SchemaTableFormat(context).output((Schema) entity); + } else if (entity instanceof Schema[]) { + new SchemaListTableFormat(context).output((Schema[]) entity); } else if (entity instanceof Table) { new TableDetailsTableFormat(context).output((Table) entity); - } else if (entity instanceof String[]) { - new ListTableFormat(context).output((String[]) entity); + } else if (entity instanceof Table[]) { + new TableListTableFormat(context).output((Table[]) entity); } else { throw new IllegalArgumentException("Unsupported object type"); } @@ -495,7 +497,7 @@ public MetalakeListTableFormat(CommandContext context) { @Override public String getOutput(Metalake[] metalakes) { - Column columnName = new Column(context, "Name"); + Column columnName = new Column(context, "metalake"); Arrays.stream(metalakes).forEach(metalake -> columnName.addCell(metalake.name())); return getTableFormat(columnName); @@ -542,7 +544,7 @@ public CatalogListTableFormat(CommandContext context) { /** {@inheritDoc} */ @Override public String getOutput(Catalog[] catalogs) { - Column columnName = new Column(context, "Name"); + Column columnName = new Column(context, "catalog"); Arrays.stream(catalogs).forEach(metalake -> columnName.addCell(metalake.name())); return getTableFormat(columnName); @@ -571,6 +573,25 @@ public String getOutput(Schema schema) { } } + /** + * Formats an array of Schemas into a single-column table display. Lists all schema names in a + * vertical format. + */ + static final class SchemaListTableFormat extends TableFormat { + public SchemaListTableFormat(CommandContext context) { + super(context); + } + + /** {@inheritDoc} */ + @Override + public String getOutput(Schema[] schemas) { + Column column = new Column(context, "schema"); + Arrays.stream(schemas).forEach(schema -> column.addCell(schema.name())); + + return getTableFormat(column); + } + } + /** * Formats a single {@link Table} instance into a two-column table display. Displays table details * including name and comment information. @@ -604,21 +625,20 @@ public String getOutput(Table table) { } } - static final class ListTableFormat extends TableFormat { - /** - * Creates a new {@link TableFormat} with the specified properties. - * - * @param context the command context. - */ - public ListTableFormat(CommandContext context) { + /** + * Formats an array of {@link Table} into a single-column table display. Lists all table names in + * a vertical format. + */ + static final class TableListTableFormat extends TableFormat { + public TableListTableFormat(CommandContext context) { super(context); } /** {@inheritDoc} */ @Override - public String getOutput(String[] entities) { - Column column = new Column(context, "name"); - Arrays.stream(entities).forEach(column::addCell); + public String getOutput(Table[] tables) { + Column column = new Column(context, "table"); + Arrays.stream(tables).forEach(table -> column.addCell(table.name())); return getTableFormat(column); } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/integration/test/TableFormatOutputIT.java b/clients/cli/src/test/java/org/apache/gravitino/cli/integration/test/TableFormatOutputIT.java index e8b8b2c17df..bca9e960ff5 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/integration/test/TableFormatOutputIT.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/integration/test/TableFormatOutputIT.java @@ -106,7 +106,7 @@ public void testMetalakeListCommand() { String output = new String(outputStream.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( "+-------------+\n" - + "| Name |\n" + + "| Metalake |\n" + "+-------------+\n" + "| my_metalake |\n" + "+-------------+", @@ -170,7 +170,7 @@ public void testCatalogListCommand() { String output = new String(outputStream.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( "+-----------+\n" - + "| Name |\n" + + "| Catalog |\n" + "+-----------+\n" + "| postgres |\n" + "| postgres2 |\n" diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java b/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java index 448ae31081a..60e9a50eea7 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/output/TestTableFormat.java @@ -255,7 +255,7 @@ void testListMetalakeWithTableFormat() { String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim(); Assertions.assertEquals( "+-----------+\n" - + "| Name |\n" + + "| Metalake |\n" + "+-----------+\n" + "| metalake1 |\n" + "| metalake2 |\n" @@ -282,11 +282,19 @@ void testCatalogDetailsWithTableFormat() { @Test void testListCatalogWithTableFormat() { CommandContext mockContext = getMockContext(); - TableFormat.output(new String[] {"catalog1", "catalog2"}, mockContext); + Catalog mockCatalog1 = + getMockCatalog( + "catalog1", Catalog.Type.RELATIONAL, "demo_provider", "This is a demo catalog"); + Catalog mockCatalog2 = + getMockCatalog( + "catalog2", Catalog.Type.RELATIONAL, "demo_provider", "This is another demo catalog"); + + TableFormat.output(new Catalog[] {mockCatalog1, mockCatalog2}, mockContext); + String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim(); Assertions.assertEquals( "+----------+\n" - + "| Name |\n" + + "| Catalog |\n" + "+----------+\n" + "| catalog1 |\n" + "| catalog2 |\n" @@ -313,15 +321,19 @@ void testSchemaDetailsWithTableFormat() { @Test void testListSchemaWithTableFormat() { CommandContext mockContext = getMockContext(); - TableFormat.output(new String[] {"schema1", "schema2"}, mockContext); + Schema mockSchema1 = getMockSchema("demo_schema1", "This is a demo schema"); + Schema mockSchema2 = getMockSchema("demo_schema2", "This is another demo schema"); + + TableFormat.output(new Schema[] {mockSchema1, mockSchema2}, mockContext); + String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim(); Assertions.assertEquals( - "+---------+\n" - + "| Name |\n" - + "+---------+\n" - + "| schema1 |\n" - + "| schema2 |\n" - + "+---------+", + "+--------------+\n" + + "| Schema |\n" + + "+--------------+\n" + + "| demo_schema1 |\n" + + "| demo_schema2 |\n" + + "+--------------+", output); } @@ -346,11 +358,14 @@ void testTableDetailsWithTableFormat() { void testListTableWithTableFormat() { CommandContext mockContext = getMockContext(); - TableFormat.output(new String[] {"table1", "table2"}, mockContext); + Table mockTable1 = getMockTable("table1", "This is a demo table"); + Table mockTable2 = getMockTable("table2", "This is another demo table"); + TableFormat.output(new Table[] {mockTable1, mockTable2}, mockContext); + String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim(); Assertions.assertEquals( "+--------+\n" - + "| Name |\n" + + "| Table |\n" + "+--------+\n" + "| table1 |\n" + "| table2 |\n" From 9f5f7c6fb16762b166a41d7f68ce97aa3b972a45 Mon Sep 17 00:00:00 2001 From: pancx Date: Mon, 24 Feb 2025 15:57:49 +0800 Subject: [PATCH 7/7] [#6493] feat(CLI): Support table format output for Schema and Table command fix some bugs. --- .../gravitino/cli/commands/ListSchema.java | 29 +++++++++++++------ .../gravitino/cli/commands/ListTables.java | 27 +++++++++++++---- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java index 23ae6bce816..05bfb492766 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java @@ -19,7 +19,7 @@ package org.apache.gravitino.cli.commands; -import org.apache.gravitino.Catalog; +import org.apache.gravitino.Audit; import org.apache.gravitino.Schema; import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; @@ -51,12 +51,10 @@ public ListSchema(CommandContext context, String metalake, String catalog) { public void handle() { String[] schemas = new String[0]; GravitinoClient client; - Catalog gCatalog = null; try { client = buildClient(metalake); - gCatalog = client.loadCatalog(catalog); - schemas = gCatalog.asSchemas().listSchemas(); + schemas = client.loadCatalog(catalog).asSchemas().listSchemas(); } catch (NoSuchMetalakeException err) { exitWithError(ErrorMessages.UNKNOWN_METALAKE); } catch (NoSuchCatalogException err) { @@ -65,16 +63,29 @@ public void handle() { exitWithError(exp.getMessage()); } - Schema[] schemaObjects = new Schema[schemas.length]; - for (int i = 0; i < schemas.length; i++) { - schemaObjects[i] = gCatalog.asSchemas().loadSchema(schemas[i]); - } - if (schemas.length == 0) { printInformation("No schemas exist."); return; } + Schema[] schemaObjects = new Schema[schemas.length]; + for (int i = 0; i < schemas.length; i++) { + String schemaName = schemas[i]; + Schema gSchema = + new Schema() { + @Override + public String name() { + return schemaName; + } + + @Override + public Audit auditInfo() { + return null; + } + }; + schemaObjects[i] = gSchema; + } + printResults(schemaObjects); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java index 62a89149359..1f098efce77 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java @@ -19,11 +19,12 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.Audit; import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.Namespace; import org.apache.gravitino.cli.CommandContext; +import org.apache.gravitino.rel.Column; import org.apache.gravitino.rel.Table; -import org.apache.gravitino.rel.TableCatalog; /** List the names of all tables in a schema. */ public class ListTables extends TableCommand { @@ -48,11 +49,9 @@ public ListTables(CommandContext context, String metalake, String catalog, Strin public void handle() { NameIdentifier[] tables = null; Namespace name = Namespace.of(schema); - TableCatalog gCatalog = null; try { - gCatalog = tableCatalog(); - tables = gCatalog.listTables(name); + tables = tableCatalog().listTables(name); } catch (Exception exp) { exitWithError(exp.getMessage()); } @@ -64,7 +63,25 @@ public void handle() { Table[] gTables = new Table[tables.length]; for (int i = 0; i < tables.length; i++) { - gTables[i] = gCatalog.loadTable(tables[i]); + String tableName = tables[i].name(); + gTables[i] = + new Table() { + + @Override + public String name() { + return tableName; + } + + @Override + public Column[] columns() { + return new Column[0]; + } + + @Override + public Audit auditInfo() { + return null; + } + }; } printResults(gTables);