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

alexey pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git

commit d91d5c95dab38770890cac6a30be63f80eb82fec
Author: zchovan <[email protected]>
AuthorDate: Mon Jun 10 17:59:51 2024 +0200

    [tool] Add '--columns' param to 'table list'
    
    Currently there is no easy way to get table UUIDs from the kudu CLI,
    this patch adds the '--columns' optional parameter to the 'kudu table list'
    command that works similiar to 'kudu master/tserver list'.
    The available columns are: 'id', 'name', 'num_tablets',
    'num_replicas', 'live_row_count'.
    
    Change-Id: I324b920e6feb6139e7d884e3cf08069b0cb922a4
    Reviewed-on: http://gerrit.cloudera.org:8080/21496
    Reviewed-by: Wang Xixu <[email protected]>
    Tested-by: Marton Greber <[email protected]>
    Reviewed-by: Marton Greber <[email protected]>
---
 src/kudu/client/client-internal.cc  |  1 +
 src/kudu/client/client-internal.h   |  1 +
 src/kudu/tools/kudu-tool-test.cc    | 69 +++++++++++++++++++++++++++++++++++++
 src/kudu/tools/tool_action_table.cc | 64 ++++++++++++++++++++++++++++++++++
 4 files changed, 135 insertions(+)

diff --git a/src/kudu/client/client-internal.cc 
b/src/kudu/client/client-internal.cc
index f5c54a064..c5c0e27d8 100644
--- a/src/kudu/client/client-internal.cc
+++ b/src/kudu/client/client-internal.cc
@@ -512,6 +512,7 @@ Status KuduClient::Data::ListTablesWithInfo(KuduClient* 
client,
   }
   for (const auto& table : resp.tables()) {
     TableInfo info;
+    if (table.has_id()) info.id = table.id();
     info.table_name = table.name();
     info.live_row_count = table.has_live_row_count() ? table.live_row_count() 
: 0;
     info.num_tablets = table.has_num_tablets() ? table.num_tablets() : 0;
diff --git a/src/kudu/client/client-internal.h 
b/src/kudu/client/client-internal.h
index 56c0965c0..6efcd78b3 100644
--- a/src/kudu/client/client-internal.h
+++ b/src/kudu/client/client-internal.h
@@ -154,6 +154,7 @@ class KuduClient::Data {
   };
 
   struct TableInfo {
+    std::string id;
     std::string table_name;
     uint64_t live_row_count;
     int num_tablets;
diff --git a/src/kudu/tools/kudu-tool-test.cc b/src/kudu/tools/kudu-tool-test.cc
index df689edf3..8ed943fde 100644
--- a/src/kudu/tools/kudu-tool-test.cc
+++ b/src/kudu/tools/kudu-tool-test.cc
@@ -5370,6 +5370,75 @@ TEST_F(ToolTest, TestMasterList) {
   ASSERT_STR_CONTAINS(out, "VOTER");
 }
 
+TEST_F(ToolTest, TestTableList) {
+  ExternalMiniClusterOptions opts;
+  NO_FATALS(StartExternalMiniCluster(std::move(opts)));
+  shared_ptr<KuduClient> client;
+  ASSERT_OK(cluster_->CreateClient(nullptr, &client));
+
+  string master_addr = cluster_->master()->bound_rpc_addr().ToString();
+
+  constexpr const char* const kTableName = "kudu.table";
+
+  // Create a table.
+  TestWorkload workload(cluster_.get());
+  workload.set_table_name(kTableName);
+  workload.set_num_replicas(1);
+  workload.Setup();
+
+  shared_ptr<KuduTable> table;
+  ASSERT_OK(client->OpenTable(kTableName, &table));
+
+  // Confirm that the simple table listing works
+  {
+    string out;
+    NO_FATALS(RunActionStdoutString(
+        Substitute("table list $0", master_addr),
+        &out));
+
+    ASSERT_STR_CONTAINS(out, table->name());
+    ASSERT_STR_NOT_CONTAINS(out, table->id());
+    ASSERT_STR_NOT_CONTAINS(out, "num_replicas");
+  }
+
+  // Confirm that the --show_table_info flag works
+  {
+    string out;
+    NO_FATALS(RunActionStdoutString(
+        Substitute("table list $0 --show_table_info", master_addr),
+        &out));
+
+    ASSERT_STR_CONTAINS(out, table->name());
+    ASSERT_STR_NOT_CONTAINS(out, table->id());
+    ASSERT_STR_CONTAINS(out, "num_tablets");
+    ASSERT_STR_CONTAINS(out, "num_replicas");
+    ASSERT_STR_CONTAINS(out, "live_row_count");
+  }
+
+  // Confirm that the --columns flag works
+  {
+    string out;
+    NO_FATALS(RunActionStdoutString(
+        Substitute("table list $0 
--columns=id,name,live_row_count,num_tablets,num_replicas",
+                   master_addr),
+        &out));
+
+    ASSERT_STR_CONTAINS(out, table->id());
+    ASSERT_STR_CONTAINS(out, table->name());
+    ASSERT_STR_CONTAINS(out, "num_replicas");
+  }
+
+  // Confirm that wrong column name doesn't crash the tool
+  {
+    string stderr;
+    Status s = RunActionStderrString(
+        Substitute("table list $0 
--columns=VeryBadAbsolutelyIncorrectColumName", master_addr),
+        &stderr);
+    ASSERT_FALSE(s.ok());
+    ASSERT_STR_CONTAINS(stderr, "Invalid column name");
+  }
+}
+
 // Operate on Kudu tables:
 // (1)delete a table
 // (2)rename a table
diff --git a/src/kudu/tools/tool_action_table.cc 
b/src/kudu/tools/tool_action_table.cc
index 9d8ae7885..b6901d37a 100644
--- a/src/kudu/tools/tool_action_table.cc
+++ b/src/kudu/tools/tool_action_table.cc
@@ -110,6 +110,8 @@ using std::vector;
 using strings::Split;
 using strings::Substitute;
 
+DECLARE_string(columns);
+
 DEFINE_bool(check_row_existence, false,
             "Also check for the existence of the row on the leader replica of "
             "the tablet. If found, the full row will be printed; if not found, 
"
@@ -299,6 +301,56 @@ class TableLister {
     return output;
   }
 
+  static Status ListTablesWithColumns(const vector<string>& master_addresses,
+                                      const vector<string>& columns) {
+    client::sp::shared_ptr<KuduClient> client;
+    RETURN_NOT_OK(CreateKuduClient(master_addresses, &client, true /* 
can_see_all_replicas */));
+    vector<KuduClient::Data::TableInfo> tables_info;
+    RETURN_NOT_OK(client->data_->ListTablesWithInfo(client.get(),
+                                                    &tables_info,
+                                                    "" /* filter */,
+                                                    
FLAGS_show_tablet_partition_info,
+                                                    FLAGS_soft_deleted_only));
+
+    DataTable table(columns);
+
+    #define GET_PROPERTY(x) \
+          [](const KuduClient::Data::TableInfo& table_info) ->  \
+          string { return table_info.x;  }
+
+    #define GET_NUM_PROPERTY(x) \
+          [](const KuduClient::Data::TableInfo& table_info) -> \
+          string { return std::to_string(table_info.x); }
+
+    unordered_map<string, std::function<string(const 
KuduClient::Data::TableInfo& table_info)>>
+        mapping = {
+            {"id", GET_PROPERTY(id)},
+            {"name", GET_PROPERTY(table_name)},
+            {"num_tablets", GET_NUM_PROPERTY(num_tablets)},
+            {"num_replicas", GET_NUM_PROPERTY(num_replicas)},
+            {"live_row_count", GET_NUM_PROPERTY(live_row_count)},
+        };
+
+    #undef GET_PROPERTY()
+    #undef GET_NUM_PROPERTY()
+
+    for (const auto& tinfo : tables_info) {
+      vector<string> values;
+      for (const auto& column : columns) {
+        string lowercase_column;
+        ToLowerCase(column, &lowercase_column);
+        auto getter = mapping.find(lowercase_column);
+        if (getter == mapping.end()) {
+          return Status::InvalidArgument(Substitute("Invalid column name: $0", 
column));
+        }
+        values.push_back(getter->second(tinfo));
+      }
+      table.AddRow(values);
+    }
+
+    return table.PrintTo(cout);
+  }
+
   static Status ListTablets(const vector<string>& master_addresses) {
     client::sp::shared_ptr<KuduClient> client;
     RETURN_NOT_OK(CreateKuduClient(master_addresses,
@@ -865,6 +917,12 @@ Status RenameColumn(const RunnerContext& context) {
 Status ListTables(const RunnerContext& context) {
   vector<string> master_addresses;
   RETURN_NOT_OK(ParseMasterAddresses(context, &master_addresses));
+
+  if (!FLAGS_columns.empty()) {
+    vector<string> columns = Split(FLAGS_columns, ",", strings::SkipEmpty());
+    return TableLister::ListTablesWithColumns(master_addresses, columns);
+  }
+
   return TableLister::ListTablets(master_addresses);
 }
 
@@ -1878,6 +1936,12 @@ unique_ptr<Mode> BuildTableMode() {
       .AddOptionalParameter("show_hash_partition_info")
       .AddOptionalParameter("show_table_info")
       .AddOptionalParameter("list_table_output_format")
+      .AddOptionalParameter(
+          "columns",
+          string(""),
+          string("Comma-separated list of table info fields to "
+                 "include in output. \nPossible values: id, name, 
live_row_count, "
+                 "num_tablets, num_replicas"))
       .Build();
 
   unique_ptr<Action> list_in_flight =

Reply via email to