Skip to content

Commit

Permalink
[apache#5746] improve(CLI): Support table format output for Audit com…
Browse files Browse the repository at this point in the history
…mand

Add Table format.
  • Loading branch information
Abyss-lord committed Feb 16, 2025
1 parent 128cafe commit 663c338
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public ListSchema(CommandContext context, String metalake, String catalog) {
public void handle() {
List<Schema> schemas = Lists.newArrayList();
try {
// There may be a performance overhead
GravitinoClient client = buildClient(metalake);
SupportsSchemas gObject = client.loadCatalog(catalog).asSchemas();
for (String schemaName : gObject.listSchemas()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -47,24 +48,26 @@ public ListTables(CommandContext context, String metalake, String catalog, Strin
/** List the names of all tables in a schema. */
@Override
public void handle() {
NameIdentifier[] tables = null;
NameIdentifier[] tables;
Namespace name = Namespace.of(schema);
TableCatalog tableCatalog;
List<Table> tablesList = new ArrayList<>();

try {
tables = tableCatalog().listTables(name);
// There may be a performance overhead
tableCatalog = tableCatalog();
tables = tableCatalog.listTables(name);
for (NameIdentifier table : tables) {
tablesList.add(tableCatalog.loadTable(table));
}
} catch (Exception exp) {
exitWithError(exp.getMessage());
}

List<String> tableNames = new ArrayList<>();
for (int i = 0; i < tables.length; i++) {
tableNames.add(tables[i].name());
if (tablesList.isEmpty()) {
printResults("No tables exist.");
} else {
printResults(tablesList.toArray(new Table[0]));
}

String all =
tableNames.isEmpty()
? "No tables exist."
: Joiner.on(System.lineSeparator()).join(tableNames);

printResults(all);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@ public void handle() {
exitWithError(exp.getMessage());
}

printInformation(gTable.name() + "," + gTable.comment());
printResults(gTable);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
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
Expand Down Expand Up @@ -88,6 +89,10 @@ public static void output(Object entity, CommandContext context) {
new SchemaTableFormat(context).output((Schema) entity);
} else if (entity instanceof Schema[]) {
new SchemasTableFormat(context).output((Schema[]) entity);
} else if (entity instanceof Table) {
new TableTableFormat(context).output((Table) entity);
} else if (entity instanceof Table[]) {
new TablesTableFormat(context).output((Table[]) entity);
} else if (entity instanceof Audit) {
new AuditTableFormat(context).output((Audit) entity);
} else {
Expand Down Expand Up @@ -657,6 +662,57 @@ public String getOutput(Schema[] schemas) {
}
}

/**
* Formats a single Table instance into a three-column table display. Displays table details
* including column-name, column-type, and column-comment information.
*/
static final class TableTableFormat extends TableFormat<Table> {
public TableTableFormat(CommandContext context) {
super(context);
}

/** {@inheritDoc} */
@Override
public String getOutput(Table entity) {
Column columnA = new Column(context, "NAME");
Column columnB = new Column(context, "TYPE");
Column columnC = new Column(context, "COMMENT");

for (org.apache.gravitino.rel.Column column : entity.columns()) {
columnA.addCell(column.name());
columnB.addCell(column.dataType().simpleString());
columnC.addCell(column.comment());
}

return getTableFormat(columnA, columnB, columnC);
}
}

/**
* Formats an array of Tables into a single-column table display. Lists all table names in a
* vertical format.
*/
static final class TablesTableFormat extends TableFormat<Table[]> {
public TablesTableFormat(CommandContext context) {
super(context);
}

/** {@inheritDoc} */
@Override
public String getOutput(Table[] entities) {
if (entities.length == 0) {
return null;
} else {
Column columnName = new Column(context, "NAME");
for (Table table : entities) {
columnName.addCell(table.name());
}

return getTableFormat(columnName);
}
}
}

static final class AuditTableFormat extends TableFormat<Audit> {
public AuditTableFormat(CommandContext context) {
super(context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import org.apache.gravitino.Schema;
import org.apache.gravitino.cli.CommandContext;
import org.apache.gravitino.cli.outputs.PlainFormat;
import org.apache.gravitino.rel.Table;
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;
Expand Down Expand Up @@ -122,6 +124,31 @@ void testListSchemaWithPlainFormat() {
Assertions.assertEquals("schema1\n" + "schema2", output);
}

@Test
void testTableDetailsWithPlainFormat() {
CommandContext mockContext = getMockContext();
Table mockTable = getMockTable();
PlainFormat.output(mockTable, mockContext);
String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim();
Assertions.assertEquals(
"demo_table\n"
+ "col1, boolean, This is a column\n"
+ "col2, string, This is another column\n"
+ "This is a table",
output);
}

@Test
void testListTableWithPlainFormat() {
CommandContext mockContext = getMockContext();
Table mockTable1 = getMockTable("table1", "This is a table");
Table mockTable2 = getMockTable("table2", "This is another table");

PlainFormat.output(new Table[] {mockTable1, mockTable2}, mockContext);
String output = new String(outContent.toByteArray(), StandardCharsets.UTF_8).trim();
Assertions.assertEquals("table1\n" + "table2", output);
}

@Test
void testAuditWithPlainFormat() {
CommandContext mockContext = getMockContext();
Expand Down Expand Up @@ -192,6 +219,34 @@ private Schema getMockSchema(String name, String comment) {
return mockSchema;
}

private Table getMockTable() {
Table mockTable = mock(Table.class);
when(mockTable.name()).thenReturn("demo_table");
when(mockTable.comment()).thenReturn("This is a table");
org.apache.gravitino.rel.Column mockColumn1 = mock(org.apache.gravitino.rel.Column.class);
when(mockColumn1.name()).thenReturn("col1");
when(mockColumn1.dataType()).thenReturn(Types.BooleanType.get());
when(mockColumn1.comment()).thenReturn("This is a column");

org.apache.gravitino.rel.Column mockColumn2 = mock(org.apache.gravitino.rel.Column.class);
when(mockColumn2.name()).thenReturn("col2");
when(mockColumn2.dataType()).thenReturn(Types.StringType.get());
when(mockColumn2.comment()).thenReturn("This is another column");

when(mockTable.columns())
.thenReturn(new org.apache.gravitino.rel.Column[] {mockColumn1, mockColumn2});

return mockTable;
}

private Table getMockTable(String name, String comment) {
Table mockTable = mock(Table.class);
when(mockTable.name()).thenReturn(name);
when(mockTable.comment()).thenReturn(comment);

return mockTable;
}

private Audit getMockAudit() {
Audit mockAudit = mock(Audit.class);
when(mockAudit.creator()).thenReturn("demo_user");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
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.Types;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -365,6 +367,40 @@ void testListSchemaWithTableFormat() {
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 | COMMENT |\n"
+ "+------+---------+------------------------+\n"
+ "| col1 | boolean | This is a column |\n"
+ "| col2 | string | This is another 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 testAuditWithTableFormat() {
CommandContext mockContext = getMockContext();
Expand Down Expand Up @@ -444,6 +480,32 @@ private Schema getMockSchema(String name, String comment) {
return mockSchema;
}

private Table getMockTable() {
Table mockTable = mock(Table.class);
org.apache.gravitino.rel.Column mockColumn1 = mock(org.apache.gravitino.rel.Column.class);
when(mockColumn1.name()).thenReturn("col1");
when(mockColumn1.dataType()).thenReturn(Types.BooleanType.get());
when(mockColumn1.comment()).thenReturn("This is a column");

org.apache.gravitino.rel.Column mockColumn2 = mock(org.apache.gravitino.rel.Column.class);
when(mockColumn2.name()).thenReturn("col2");
when(mockColumn2.dataType()).thenReturn(Types.StringType.get());
when(mockColumn2.comment()).thenReturn("This is another column");

when(mockTable.columns())
.thenReturn(new org.apache.gravitino.rel.Column[] {mockColumn1, mockColumn2});

return mockTable;
}

private Table getMockTable(String name, String comment) {
Table mockTable = mock(Table.class);
when(mockTable.name()).thenReturn(name);
when(mockTable.comment()).thenReturn(comment);

return mockTable;
}

private Audit getMockAudit() {
Audit mockAudit = mock(Audit.class);
when(mockAudit.creator()).thenReturn("demo_user");
Expand Down

0 comments on commit 663c338

Please sign in to comment.