From 6b454388fe4021ce4f92a3d15b1a0ae6033bbb19 Mon Sep 17 00:00:00 2001 From: pancx Date: Mon, 24 Feb 2025 14:22:23 +0800 Subject: [PATCH] [#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"