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 =
