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

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


The following commit(s) were added to refs/heads/master by this push:
     new 958248a  KUDU-3339 [tool] CLI to add a column
958248a is described below

commit 958248adf3ea70f12ab033e0041bfc5c922956af
Author: shenxingwuying <[email protected]>
AuthorDate: Mon Aug 23 17:18:36 2021 +0800

    KUDU-3339 [tool] CLI to add a column
    
    usage:
      kudu table add_column <master_addresses> <table_name> \
      <column_name> <data_type> [-encoding_type=<type>] \
      [-compression_type=<type>] [-default_value=<value>] \
      [-comment=<comment>]
    
    Change-Id: I93e6c2af07e9fa5aa909b4a09b79b7c54401d4e3
    Reviewed-on: http://gerrit.cloudera.org:8080/17851
    Tested-by: Kudu Jenkins
    Reviewed-by: Yingchun Lai <[email protected]>
---
 src/kudu/client/schema.cc           | 14 ++++++++
 src/kudu/client/schema.h            |  3 ++
 src/kudu/tools/kudu-tool-test.cc    | 69 +++++++++++++++++++++++++++++++++++++
 src/kudu/tools/tool_action_table.cc | 69 +++++++++++++++++++++++++++++++++++++
 4 files changed, 155 insertions(+)

diff --git a/src/kudu/client/schema.cc b/src/kudu/client/schema.cc
index e5a1bba..8c97e55 100644
--- a/src/kudu/client/schema.cc
+++ b/src/kudu/client/schema.cc
@@ -808,6 +808,20 @@ KuduColumnTypeAttributes 
KuduColumnSchema::type_attributes() const {
                                   type_attributes.length);
 }
 
+KuduColumnStorageAttributes KuduColumnSchema::storage_attributes() const {
+  ColumnStorageAttributes storage_attributes = 
DCHECK_NOTNULL(col_)->attributes();
+  KuduColumnStorageAttributes::EncodingType encoding_type;
+  KuduColumnStorageAttributes::StringToEncodingType(
+      kudu::EncodingType_Name(storage_attributes.encoding),
+      &encoding_type);
+  KuduColumnStorageAttributes::CompressionType compression_type;
+  KuduColumnStorageAttributes::StringToCompressionType(
+      kudu::CompressionType_Name(storage_attributes.compression),
+      &compression_type);
+  return KuduColumnStorageAttributes(encoding_type, compression_type,
+                                     storage_attributes.cfile_block_size);
+}
+
 const string& KuduColumnSchema::comment() const {
   return DCHECK_NOTNULL(col_)->comment();
 }
diff --git a/src/kudu/client/schema.h b/src/kudu/client/schema.h
index 086e7d9..6791e56 100644
--- a/src/kudu/client/schema.h
+++ b/src/kudu/client/schema.h
@@ -307,6 +307,9 @@ class KUDU_EXPORT KuduColumnSchema {
   /// @return Type attributes of the column schema.
   KuduColumnTypeAttributes type_attributes() const;
 
+  /// @return Storage attributes of the column schema.
+  KuduColumnStorageAttributes storage_attributes() const;
+
   /// @return comment of the column schema.
   ///
   /// @note An empty string will be returned if there is no comment.
diff --git a/src/kudu/tools/kudu-tool-test.cc b/src/kudu/tools/kudu-tool-test.cc
index df435a6..67c0193 100644
--- a/src/kudu/tools/kudu-tool-test.cc
+++ b/src/kudu/tools/kudu-tool-test.cc
@@ -1188,6 +1188,7 @@ TEST_F(ToolTest, TestModeHelp) {
         "column_set_comment.*Set comment for a column",
         "copy.*Copy table data to another table",
         "create.*Create a new table",
+        "add_column.*Add a column",
         "delete_column.*Delete a column",
         "delete.*Delete a table",
         "describe.*Describe a table",
@@ -4717,6 +4718,73 @@ TEST_F(ToolTest, TestColumnSetDefault) {
     "DECIMAL columns are not supported for setting default value by this 
tool"));
 }
 
+TEST_F(ToolTest, TestAddColumn) {
+  NO_FATALS(StartExternalMiniCluster());
+  const string& kTableName = "kudu.table.add.column";
+  const string& kColumnName0 = "col.0";
+  const string& kColumnName1 = "col.1";
+  KuduSchemaBuilder schema_builder;
+  schema_builder.AddColumn("key")
+      ->Type(client::KuduColumnSchema::INT32)
+      ->NotNull()
+      ->PrimaryKey();
+  schema_builder.AddColumn(kColumnName0)
+      ->Type(client::KuduColumnSchema::INT32)
+      ->NotNull();
+  KuduSchema schema;
+  ASSERT_OK(schema_builder.Build(&schema));
+
+  // Create the table
+  TestWorkload workload(cluster_.get());
+  workload.set_table_name(kTableName);
+  workload.set_schema(schema);
+  workload.set_num_replicas(1);
+  workload.Setup();
+
+  string master_addr = cluster_->master()->bound_rpc_addr().ToString();
+  shared_ptr<KuduClient> client;
+  ASSERT_OK(KuduClientBuilder()
+            .add_master_server_addr(master_addr)
+            .Build(&client));
+  shared_ptr<KuduTable> table;
+  ASSERT_OK(client->OpenTable(kTableName, &table));
+  ASSERT_STR_CONTAINS(table->schema().ToString(), kColumnName0);
+  ASSERT_STR_NOT_CONTAINS(table->schema().ToString(), kColumnName1);
+  NO_FATALS(RunActionStdoutNone(Substitute("table add_column $0 $1 $2 STRING "
+                                           "-encoding_type=DICT_ENCODING "
+                                           "-compression_type=LZ4 "
+                                           "-default_value=[\"abcd\"] "
+                                           "-comment=helloworld",
+                                           master_addr, kTableName, 
kColumnName1)));
+
+  ASSERT_OK(client->OpenTable(kTableName, &table));
+  ASSERT_STR_CONTAINS(table->schema().ToString(), kColumnName1);
+
+  KuduSchemaBuilder expected_schema_builder;
+  expected_schema_builder.AddColumn("key")
+      ->Type(kudu::client::KuduColumnSchema::INT32)
+      ->NotNull()
+      ->PrimaryKey();
+  expected_schema_builder.AddColumn(kColumnName1)
+      ->Type(client::KuduColumnSchema::STRING)
+      ->Compression(client::KuduColumnStorageAttributes::CompressionType::LZ4)
+      
->Encoding(client::KuduColumnStorageAttributes::EncodingType::DICT_ENCODING)
+      ->Default(client::KuduValue::CopyString(Slice("abcd")))
+      ->Comment("helloworld");
+  KuduSchema expected_schema;
+  ASSERT_OK(expected_schema_builder.Build(&expected_schema));
+
+  ASSERT_EQ(table->schema().Column(2).name(), 
expected_schema.Column(1).name());
+  ASSERT_EQ(table->schema().Column(2).is_nullable(), 
expected_schema.Column(1).is_nullable());
+  ASSERT_EQ(table->schema().Column(2).type(), 
expected_schema.Column(1).type());
+  ASSERT_EQ(table->schema().Column(2).storage_attributes().encoding(),
+            expected_schema.Column(1).storage_attributes().encoding());
+  ASSERT_EQ(table->schema().Column(2).storage_attributes().compression(),
+            expected_schema.Column(1).storage_attributes().compression());
+  ASSERT_EQ(table->schema().Column(2).comment(), 
expected_schema.Column(1).comment());
+  ASSERT_EQ(table->schema().Column(2), expected_schema.Column(1));
+}
+
 TEST_F(ToolTest, TestDeleteColumn) {
   NO_FATALS(StartExternalMiniCluster());
   constexpr const char* const kTableName = "kudu.table.delete.column";
@@ -4916,6 +4984,7 @@ TEST_F(ToolTest, TestSetReplicationFactor) {
   schema_builder.AddColumn("value")
       ->Type(client::KuduColumnSchema::INT32)
       ->NotNull();
+
   KuduSchema schema;
   ASSERT_OK(schema_builder.Build(&schema));
 
diff --git a/src/kudu/tools/tool_action_table.cc 
b/src/kudu/tools/tool_action_table.cc
index f85ff67..91614f9 100644
--- a/src/kudu/tools/tool_action_table.cc
+++ b/src/kudu/tools/tool_action_table.cc
@@ -127,6 +127,16 @@ DEFINE_int32(scan_batch_size, -1,
 
 DECLARE_bool(row_count_only);
 DECLARE_bool(show_scanner_stats);
+
+DEFINE_string(encoding_type, "AUTO_ENCODING",
+              "Type of encoding for the column including AUTO_ENCODING, 
PLAIN_ENCODING, "
+              "PREFIX_ENCODING, RLE, DICT_ENCODING, BIT_SHUFFLE, 
GROUP_VARINT");
+DEFINE_string(compression_type, "DEFAULT_COMPRESSION",
+              "Type of compression for the column including 
DEFAULT_COMPRESSION, "
+              "NO_COMPRESSION, SNAPPY, LZ4, ZLIB");
+DEFINE_string(default_value, "", "Default value for this column.");
+DEFINE_string(comment, "", "Comment for this column.");
+
 DECLARE_bool(show_values);
 DECLARE_string(replica_selection);
 DECLARE_string(tables);
@@ -217,6 +227,7 @@ const char* const kBlockSizeArg = "block_size";
 const char* const kColumnCommentArg = "column_comment";
 const char* const kCreateTableJSONArg = "create_table_json";
 const char* const kReplicationFactorArg = "replication_factor";
+const char* const kDataTypeArg = "data_type";
 
 enum PartitionAction {
   ADD,
@@ -975,6 +986,47 @@ Status ColumnSetComment(const RunnerContext& context) {
   return alterer->Alter();
 }
 
+Status AddColumn(const RunnerContext& context) {
+  const string& table_name = FindOrDie(context.required_args, kTableNameArg);
+  const string& column_name = FindOrDie(context.required_args, kColumnNameArg);
+  const string& data_type_name = FindOrDie(context.required_args, 
kDataTypeArg);
+
+  client::sp::shared_ptr<KuduClient> client;
+  RETURN_NOT_OK(CreateKuduClient(context, &client));
+  unique_ptr<KuduTableAlterer> alterer(client->NewTableAlterer(table_name));
+  KuduColumnSpec* column_spec = alterer->AddColumn(column_name);
+
+  KuduColumnSchema::DataType data_type;
+  RETURN_NOT_OK(KuduColumnSchema::StringToDataType(data_type_name, 
&data_type));
+  column_spec->Type(data_type);
+
+  if (!FLAGS_default_value.empty()) {
+    KuduValue* value = nullptr;
+    RETURN_NOT_OK(ParseValueOfType(FLAGS_default_value, data_type, &value));
+    column_spec->Default(value);
+  }
+
+  if (!FLAGS_encoding_type.empty()) {
+    KuduColumnStorageAttributes::EncodingType encoding_type;
+    
RETURN_NOT_OK(KuduColumnStorageAttributes::StringToEncodingType(FLAGS_encoding_type,
+                                                                    
&encoding_type));
+    column_spec->Encoding(encoding_type);
+  }
+
+  if (!FLAGS_compression_type.empty()) {
+    KuduColumnStorageAttributes::CompressionType compress_type;
+    
RETURN_NOT_OK(KuduColumnStorageAttributes::StringToCompressionType(FLAGS_compression_type,
+                                                                       
&compress_type));
+    column_spec->Compression(compress_type);
+  }
+
+  if (!FLAGS_comment.empty()) {
+    column_spec->Comment(FLAGS_comment);
+  }
+
+  return alterer->Alter();
+}
+
 Status DeleteColumn(const RunnerContext& context) {
   const string& table_name = FindOrDie(context.required_args, kTableNameArg);
   const string& column_name = FindOrDie(context.required_args, kColumnNameArg);
@@ -1496,6 +1548,22 @@ unique_ptr<Mode> BuildTableMode() {
       .AddRequiredParameter({ kColumnCommentArg, "Comment of the column" })
       .Build();
 
+  unique_ptr<Action> add_column =
+      ActionBuilder("add_column", &AddColumn)
+      .Description("Add a column")
+      .AddRequiredParameter({ kMasterAddressesArg, kMasterAddressesArgDesc })
+      .AddRequiredParameter({ kTableNameArg, "Name of the table to alter" })
+      .AddRequiredParameter({ kColumnNameArg, "Name of the table column to 
add" })
+      .AddRequiredParameter({ kDataTypeArg, "Data Type, eg: INT8, INT16, 
INT32, INT64, STRING,"
+                            " BOOL, FLOAT, DOUBLE, BINARY, UNIXTIME_MICROS, 
DECIMAL, VARCHAR,"
+                            " TIMESTAMP, DATE"})
+      .AddOptionalParameter(kEncodingTypeArg)
+      .AddOptionalParameter(kCompressionTypeArg)
+      .AddOptionalParameter(kDefaultValueArg)
+      .AddOptionalParameter("comment")
+      .Build();
+
+
   unique_ptr<Action> delete_column =
       ClusterActionBuilder("delete_column", &DeleteColumn)
       .Description("Delete a column")
@@ -1552,6 +1620,7 @@ unique_ptr<Mode> BuildTableMode() {
   return ModeBuilder("table")
       .Description("Operate on Kudu tables")
       .AddMode(BuildSetTableLimitMode())
+      .AddAction(std::move(add_column))
       .AddAction(std::move(add_range_partition))
       .AddAction(std::move(clear_comment))
       .AddAction(std::move(column_remove_default))

Reply via email to