You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by aw...@apache.org on 2019/08/20 04:32:55 UTC
[kudu] 02/02: [tools] Add table tools to delete column and alter
column
This is an automated email from the ASF dual-hosted git repository.
awong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git
commit dc3cbb795218b9b05da78f65249cbaf61395cc50
Author: zhangyifan27 <ch...@163.com>
AuthorDate: Thu Aug 1 12:04:30 2019 +0800
[tools] Add table tools to delete column and alter column
This patch supports to delete column and alter column for
a table by command line tools.
The 'delete_column' tool can be used as:
- kudu table delete_column <master_addresses> <table_name> <column_name>
The alter column tools can be used as:
- kudu table column_set_default <master_addresses> <table_name> <column_name> <default_value>
(<default_value> should be provided as a JSON array, e.g. [1] or ["foo"])
- kudu table column_remove_default <master_addresses> <table_name> <column_name>
- kudu table column_set_compression <master_addresses> <table_name> <column_name> <compression_type>
- kudu table column_set_encoding <master_addresses> <table_name> <column_name> <encoding_type>
- kudu table column_set_block_size <master_addresses> <table_name> <column_name> <block_size>
Change-Id: I228340e46fe48ffc782c4c7346f890444b8c550f
Reviewed-on: http://gerrit.cloudera.org:8080/13976
Tested-by: Kudu Jenkins
Reviewed-by: Adar Dembo <ad...@cloudera.com>
Reviewed-by: Andrew Wong <aw...@cloudera.com>
Reviewed-by: Yingchun Lai <40...@qq.com>
---
src/kudu/client/schema.cc | 9 ++
src/kudu/client/schema.h | 7 +
src/kudu/tools/kudu-tool-test.cc | 251 ++++++++++++++++++++++++++++++++-
src/kudu/tools/tool_action_table.cc | 270 +++++++++++++++++++++++++++++++++++-
4 files changed, 534 insertions(+), 3 deletions(-)
diff --git a/src/kudu/client/schema.cc b/src/kudu/client/schema.cc
index 78113fb..eaae666 100644
--- a/src/kudu/client/schema.cc
+++ b/src/kudu/client/schema.cc
@@ -718,6 +718,15 @@ KuduColumnSchema KuduSchema::Column(size_t idx) const {
attrs, type_attrs, col.comment());
}
+bool KuduSchema::HasColumn(const std::string& col_name, KuduColumnSchema* col_schema) const {
+ int idx = schema_->find_column(col_name);
+ if (idx == Schema::kColumnNotFound) {
+ return false;
+ }
+ *col_schema = Column(idx);
+ return true;
+}
+
KuduPartialRow* KuduSchema::NewRow() const {
return new KuduPartialRow(schema_);
}
diff --git a/src/kudu/client/schema.h b/src/kudu/client/schema.h
index 10c7578..c5c3c52 100644
--- a/src/kudu/client/schema.h
+++ b/src/kudu/client/schema.h
@@ -575,6 +575,13 @@ class KUDU_EXPORT KuduSchema {
/// @return Schema for the specified column.
KuduColumnSchema Column(size_t idx) const;
+ /// @param [in] col_name
+ /// Column name.
+ /// @param [out] col_schema.
+ /// Schema for the specified column.
+ /// @return @c true iff the specified column exists.
+ bool HasColumn(const std::string& col_name, KuduColumnSchema* col_schema) const;
+
/// @return The number of columns in the schema.
size_t num_columns() const;
diff --git a/src/kudu/tools/kudu-tool-test.cc b/src/kudu/tools/kudu-tool-test.cc
index 13efcd0..17ccf4c 100644
--- a/src/kudu/tools/kudu-tool-test.cc
+++ b/src/kudu/tools/kudu-tool-test.cc
@@ -134,6 +134,7 @@
DECLARE_bool(hive_metastore_sasl_enabled);
DECLARE_bool(show_values);
+DECLARE_bool(show_attributes);
DECLARE_string(block_manager);
DECLARE_string(hive_metastore_uris);
@@ -2922,6 +2923,8 @@ TEST_F(ToolTest, TestMasterList) {
// (4)list tables
// (5)scan a table
// (6)copy a table
+// (7)alter a column
+// (8)delete a column
TEST_F(ToolTest, TestDeleteTable) {
NO_FATALS(StartExternalMiniCluster());
shared_ptr<KuduClient> client;
@@ -3003,7 +3006,6 @@ TEST_F(ToolTest, TestRenameColumn) {
workload.Setup();
string master_addr = cluster_->master()->bound_rpc_addr().ToString();
- string out;
NO_FATALS(RunActionStdoutNone(Substitute("table rename_column $0 $1 $2 $3",
master_addr, kTableName,
kColumnName, kNewColumnName)));
@@ -3252,6 +3254,253 @@ TEST_P(ToolTestCopyTableParameterized, TestCopyTable) {
}
}
+TEST_F(ToolTest, TestAlterColumn) {
+ NO_FATALS(StartExternalMiniCluster());
+ const string& kTableName = "kudu.table.alter.column";
+ const string& kColumnName = "col.0";
+
+ KuduSchemaBuilder schema_builder;
+ schema_builder.AddColumn("key")
+ ->Type(client::KuduColumnSchema::INT32)
+ ->NotNull()
+ ->PrimaryKey();
+ schema_builder.AddColumn(kColumnName)
+ ->Type(client::KuduColumnSchema::INT32)
+ ->NotNull()
+ ->Compression(KuduColumnStorageAttributes::CompressionType::LZ4)
+ ->Encoding(KuduColumnStorageAttributes::EncodingType::BIT_SHUFFLE)
+ ->BlockSize(40960);
+ 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;
+ FLAGS_show_attributes = true;
+
+ // Test a few error cases.
+ const auto check_bad_input = [&](const string& alter_type,
+ const string& alter_value,
+ const string& err) {
+ string stderr;
+ Status s = RunActionStderrString(
+ Substitute("table $0 $1 $2 $3 $4",
+ alter_type, master_addr, kTableName, kColumnName, alter_value), &stderr);
+ ASSERT_TRUE(s.IsRuntimeError());
+ ASSERT_STR_CONTAINS(stderr, err);
+ };
+
+ // Set write_default value for a column.
+ NO_FATALS(RunActionStdoutNone(Substitute("table column_set_default $0 $1 $2 $3",
+ master_addr, kTableName, kColumnName, "[1024]")));
+ ASSERT_OK(client->OpenTable(kTableName, &table));
+ ASSERT_STR_CONTAINS(table->schema().ToString(), "1024");
+
+ // Remove write_default value for a column.
+ NO_FATALS(RunActionStdoutNone(Substitute("table column_remove_default $0 $1 $2",
+ master_addr, kTableName, kColumnName)));
+ ASSERT_OK(client->OpenTable(kTableName, &table));
+ ASSERT_STR_NOT_CONTAINS(table->schema().ToString(), "1024");
+
+ // Alter compression type for a column.
+ NO_FATALS(RunActionStdoutNone(Substitute("table column_set_compression $0 $1 $2 $3",
+ master_addr, kTableName, kColumnName,
+ "DEFAULT_COMPRESSION")));
+ ASSERT_OK(client->OpenTable(kTableName, &table));
+ ASSERT_STR_CONTAINS(table->schema().ToString(), "DEFAULT_COMPRESSION");
+ ASSERT_STR_NOT_CONTAINS(table->schema().ToString(), "LZ4");
+
+ // Test invalid compression type.
+ NO_FATALS(check_bad_input("column_set_compression",
+ "UNKNOWN_COMPRESSION_TYPE",
+ "Failed to parse compression type"));
+
+ // Alter encoding type for a column.
+ NO_FATALS(RunActionStdoutNone(Substitute("table column_set_encoding $0 $1 $2 $3",
+ master_addr, kTableName, kColumnName,
+ "PLAIN_ENCODING")));
+ ASSERT_OK(client->OpenTable(kTableName, &table));
+ ASSERT_STR_CONTAINS(table->schema().ToString(), "PLAIN_ENCODING");
+ ASSERT_STR_NOT_CONTAINS(table->schema().ToString(), "BIT_SHUFFLE");
+
+ // Test invalid encoding type.
+ NO_FATALS(check_bad_input("column_set_encoding",
+ "UNKNOWN_ENCODING_TYPE",
+ "Failed to parse encoding type"));
+
+ // Alter block_size for a column.
+ NO_FATALS(RunActionStdoutNone(Substitute("table column_set_block_size $0 $1 $2 $3",
+ master_addr, kTableName, kColumnName, "10240")));
+ ASSERT_OK(client->OpenTable(kTableName, &table));
+ ASSERT_STR_CONTAINS(table->schema().ToString(), "10240");
+ ASSERT_STR_NOT_CONTAINS(table->schema().ToString(), "40960");
+
+ // Test invalid block_size.
+ NO_FATALS(check_bad_input("column_set_block_size", "0", "Invalid block size:"));
+}
+
+TEST_F(ToolTest, TestColumnSetDefault) {
+ NO_FATALS(StartExternalMiniCluster());
+ const string& kTableName = "kudu.table.set.default";
+ const string& kIntColumn = "col.int";
+ const string& kStringColumn = "col.string";
+ const string& kBoolColumn = "col.bool";
+ const string& kFloatColumn = "col.float";
+ const string& kDoubleColumn = "col.double";
+ const string& kBinaryColumn = "col.binary";
+ const string& kUnixtimeMicrosColumn = "col.unixtime_micros";
+ const string& kDecimalColumn = "col.decimal";
+
+ KuduSchemaBuilder schema_builder;
+ schema_builder.AddColumn("key")
+ ->Type(client::KuduColumnSchema::INT32)
+ ->NotNull()
+ ->PrimaryKey();
+ schema_builder.AddColumn(kIntColumn)
+ ->Type(client::KuduColumnSchema::INT64);
+ schema_builder.AddColumn(kStringColumn)
+ ->Type(client::KuduColumnSchema::STRING);
+ schema_builder.AddColumn(kBoolColumn)
+ ->Type(client::KuduColumnSchema::BOOL);
+ schema_builder.AddColumn(kFloatColumn)
+ ->Type(client::KuduColumnSchema::FLOAT);
+ schema_builder.AddColumn(kDoubleColumn)
+ ->Type(client::KuduColumnSchema::DOUBLE);
+ schema_builder.AddColumn(kBinaryColumn)
+ ->Type(client::KuduColumnSchema::BINARY);
+ schema_builder.AddColumn(kUnixtimeMicrosColumn)
+ ->Type(client::KuduColumnSchema::UNIXTIME_MICROS);
+ schema_builder.AddColumn(kDecimalColumn)
+ ->Type(client::KuduColumnSchema::DECIMAL)
+ ->Precision(30)
+ ->Scale(4);
+ 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;
+ FLAGS_show_attributes = true;
+
+ // Test setting write_default value for a column.
+ const auto check_set_defult = [&](const string& col_name,
+ const string& value,
+ const string& target_value) {
+ RunActionStdoutNone(Substitute("table column_set_default $0 $1 $2 $3",
+ master_addr, kTableName, col_name, value));
+ ASSERT_OK(client->OpenTable(kTableName, &table));
+ ASSERT_STR_CONTAINS(table->schema().ToString(), target_value);
+ };
+
+ // Test a few error cases.
+ const auto check_bad_input = [&](const string& col_name,
+ const string& value,
+ const string& err) {
+ string stderr;
+ Status s = RunActionStderrString(
+ Substitute("table column_set_default $0 $1 $2 $3",
+ master_addr, kTableName, col_name, value), &stderr);
+ ASSERT_TRUE(s.IsRuntimeError());
+ ASSERT_STR_CONTAINS(stderr, err);
+ };
+
+ // Set write_default value for a int column.
+ NO_FATALS(check_set_defult(kIntColumn, "[-2]", "-2"));
+ NO_FATALS(check_bad_input(kIntColumn, "[\"string\"]", "unable to parse"));
+ NO_FATALS(check_bad_input(kIntColumn, "[123.4]", "unable to parse"));
+
+ // Set write_default value for a string column.
+ NO_FATALS(check_set_defult(kStringColumn, "[\"string_value\"]", "string_value"));
+ NO_FATALS(check_bad_input(kStringColumn, "[123]", "unable to parse"));
+ // Test empty string is a valid default value for a string column.
+ NO_FATALS(check_set_defult(kStringColumn, "[\"\"]", "\"\""));
+ NO_FATALS(check_set_defult(kStringColumn, "[null]", "\"\""));
+ // Test invalid input of an empty string.
+ NO_FATALS(check_bad_input(kStringColumn, "\"\"", "expected object array but got string"));
+ NO_FATALS(check_bad_input(kStringColumn, "[]", "you should provide one default value"));
+
+ // Set write_default value for a bool column.
+ NO_FATALS(check_set_defult(kBoolColumn, "[true]", "true"));
+ NO_FATALS(check_set_defult(kBoolColumn, "[false]", "false"));
+ NO_FATALS(check_bad_input(kBoolColumn, "[TRUE]", "JSON text is corrupt: Invalid value."));
+
+ // Set write_default value for a float column.
+ NO_FATALS(check_set_defult(kFloatColumn, "[1.23]", "1.23"));
+
+ // Set write_default value for a double column.
+ NO_FATALS(check_set_defult(kDoubleColumn, "[-1.2345]", "-1.2345"));
+
+ // Set write_default value for a binary column.
+ // Empty string tests is the same with string column.
+ NO_FATALS(check_set_defult(kBinaryColumn, "[\"binary_value\"]", "binary_value"));
+
+ // Set write_default value for a unixtime_micro column.
+ NO_FATALS(check_set_defult(kUnixtimeMicrosColumn, "[12345]", "12345"));
+
+ // Test setting write_default value for a decimal column.
+ NO_FATALS(check_bad_input(
+ kDecimalColumn,
+ "[123]",
+ "DECIMAL columns are not supported for setting default value by this tool"));
+}
+
+TEST_F(ToolTest, TestDeleteColumn) {
+ NO_FATALS(StartExternalMiniCluster());
+ const string& kTableName = "kudu.table.delete.column";
+ const string& kColumnName = "col.0";
+
+ KuduSchemaBuilder schema_builder;
+ schema_builder.AddColumn("key")
+ ->Type(client::KuduColumnSchema::INT32)
+ ->NotNull()
+ ->PrimaryKey();
+ schema_builder.AddColumn(kColumnName)
+ ->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(), kColumnName);
+ NO_FATALS(RunActionStdoutNone(Substitute("table delete_column $0 $1 $2",
+ master_addr, kTableName, kColumnName)));
+ ASSERT_OK(client->OpenTable(kTableName, &table));
+ ASSERT_STR_NOT_CONTAINS(table->schema().ToString(), kColumnName);
+}
+
Status CreateLegacyHmsTable(HmsClient* client,
const string& hms_database_name,
const string& hms_table_name,
diff --git a/src/kudu/tools/tool_action_table.cc b/src/kudu/tools/tool_action_table.cc
index f5cbed2..5739186 100644
--- a/src/kudu/tools/tool_action_table.cc
+++ b/src/kudu/tools/tool_action_table.cc
@@ -46,6 +46,7 @@
#include "kudu/gutil/map-util.h"
#include "kudu/gutil/stl_util.h"
#include "kudu/gutil/strings/join.h"
+#include "kudu/gutil/strings/numbers.h"
#include "kudu/gutil/strings/split.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/tools/table_scanner.h"
@@ -53,10 +54,12 @@
#include "kudu/tools/tool_action_common.h"
#include "kudu/util/jsonreader.h"
#include "kudu/util/status.h"
+#include "kudu/util/string_case.h"
using kudu::client::KuduClient;
using kudu::client::KuduClientBuilder;
using kudu::client::KuduColumnSchema;
+using kudu::client::KuduColumnStorageAttributes;
using kudu::client::KuduPredicate;
using kudu::client::KuduScanToken;
using kudu::client::KuduScanTokenBuilder;
@@ -65,6 +68,7 @@ using kudu::client::KuduSchema;
using kudu::client::KuduTable;
using kudu::client::KuduTableAlterer;
using kudu::client::KuduTableCreator;
+using kudu::client::KuduValue;
using kudu::client::internal::ReplicaController;
using std::cerr;
using std::cout;
@@ -72,6 +76,7 @@ using std::endl;
using std::set;
using std::string;
using std::unique_ptr;
+using std::unordered_map;
using std::vector;
using strings::Split;
using strings::Substitute;
@@ -160,10 +165,14 @@ const char* const kConfigValueArg = "config_value";
const char* const kErrorMsgArg = "unable to parse value $0 for column $1 of type $2";
const char* const kTableRangeLowerBoundArg = "table_range_lower_bound";
const char* const kTableRangeUpperBoundArg = "table_range_upper_bound";
+const char* const kDefaultValueArg = "default_value";
+const char* const kCompressionTypeArg = "compression_type";
+const char* const kEncodingTypeArg = "encoding_type";
+const char* const kBlockSizeArg = "block_size";
enum PartitionAction {
- ADD,
- DROP,
+ ADD,
+ DROP,
};
Status DeleteTable(const RunnerContext& context) {
@@ -654,6 +663,203 @@ Status AddRangePartition(const RunnerContext& context) {
return ModifyRangePartition(context, PartitionAction::ADD);
}
+Status ParseValueOfType(const string& default_value,
+ KuduColumnSchema::DataType type,
+ KuduValue** value) {
+ JsonReader reader(default_value);
+ RETURN_NOT_OK(reader.Init());
+ vector<const rapidjson::Value*> values;
+ RETURN_NOT_OK(reader.ExtractObjectArray(reader.root(),
+ /*field=*/nullptr,
+ &values));
+ if (values.size() != 1) {
+ return Status::InvalidArgument(Substitute(
+ "We got $0 value(s), you should provide one default value.",
+ std::to_string(values.size())));
+ }
+
+ string msg = Substitute("unable to parse value for column type $0",
+ KuduColumnSchema::DataTypeToString(type));
+ switch (type) {
+ case KuduColumnSchema::DataType::INT8:
+ case KuduColumnSchema::DataType::INT16:
+ case KuduColumnSchema::DataType::INT32:
+ case KuduColumnSchema::DataType::INT64:
+ case KuduColumnSchema::DataType::UNIXTIME_MICROS: {
+ int64_t int_value;
+ RETURN_NOT_OK_PREPEND(
+ reader.ExtractInt64(values[0], /*field=*/nullptr, &int_value), msg);
+ *value = KuduValue::FromInt(int_value);
+ break;
+ }
+ case KuduColumnSchema::DataType::BINARY:
+ case KuduColumnSchema::DataType::STRING: {
+ string str_value;
+ RETURN_NOT_OK_PREPEND(
+ reader.ExtractString(values[0], /*field=*/nullptr, &str_value), msg);
+ *value = KuduValue::CopyString(str_value);
+ break;
+ }
+ case KuduColumnSchema::DataType::BOOL: {
+ bool bool_value;
+ RETURN_NOT_OK_PREPEND(
+ reader.ExtractBool(values[0], /*field=*/nullptr, &bool_value), msg);
+ *value = KuduValue::FromBool(bool_value);
+ break;
+ }
+ case KuduColumnSchema::DataType::FLOAT: {
+ double double_value;
+ RETURN_NOT_OK_PREPEND(
+ reader.ExtractDouble(values[0], /*field=*/nullptr, &double_value), msg);
+ *value = KuduValue::FromFloat(double_value);
+ break;
+ }
+ case KuduColumnSchema::DataType::DOUBLE: {
+ double double_value;
+ RETURN_NOT_OK_PREPEND(
+ reader.ExtractDouble(values[0], /*field=*/nullptr, &double_value), msg);
+ *value = KuduValue::FromDouble(double_value);
+ break;
+ }
+ case KuduColumnSchema::DataType::DECIMAL:
+ default:
+ return Status::NotSupported(Substitute(
+ "$0 columns are not supported for setting default value by this tool,"
+ "is this tool out of date?",
+ KuduColumnSchema::DataTypeToString(type)));
+ }
+ return Status::OK();
+}
+
+Status ColumnSetDefault(const RunnerContext& context) {
+ const string& table_name = FindOrDie(context.required_args, kTableNameArg);
+ const string& column_name = FindOrDie(context.required_args, kColumnNameArg);
+ const string& default_value = FindOrDie(context.required_args, kDefaultValueArg);
+
+ client::sp::shared_ptr<KuduClient> client;
+ RETURN_NOT_OK(CreateKuduClient(context, &client));
+ KuduSchema schema;
+ RETURN_NOT_OK(client->GetTableSchema(table_name, &schema));
+
+ // Here we use the first column to initialize an object of KuduColumnSchema
+ // for there is no default constructor for it.
+ KuduColumnSchema col_schema = schema.Column(0);
+ if (!schema.HasColumn(column_name, &col_schema)) {
+ return Status::NotFound(Substitute("Couldn't find column $0", column_name));
+ }
+
+ KuduValue* value = nullptr;
+ RETURN_NOT_OK(ParseValueOfType(default_value, col_schema.type(), &value));
+ unique_ptr<KuduTableAlterer> alterer(client->NewTableAlterer(table_name));
+ alterer->AlterColumn(column_name)->Default(value);
+ return alterer->Alter();
+}
+
+Status ColumnRemoveDefault(const RunnerContext& context) {
+ const string& table_name = FindOrDie(context.required_args, kTableNameArg);
+ const string& column_name = FindOrDie(context.required_args, kColumnNameArg);
+
+ client::sp::shared_ptr<KuduClient> client;
+ RETURN_NOT_OK(CreateKuduClient(context, &client));
+ unique_ptr<KuduTableAlterer> alterer(client->NewTableAlterer(table_name));
+ alterer->AlterColumn(column_name)->RemoveDefault();
+ return alterer->Alter();
+}
+
+Status ColumnSetCompression(const RunnerContext& context) {
+ const string& table_name = FindOrDie(context.required_args, kTableNameArg);
+ const string& column_name = FindOrDie(context.required_args, kColumnNameArg);
+ const string& compression_type_arg = FindOrDie(context.required_args, kCompressionTypeArg);
+ std::string compression_type_uc;
+ ToUpperCase(compression_type_arg, &compression_type_uc);
+
+ static unordered_map<string, KuduColumnStorageAttributes::CompressionType> compression_type_map =
+ {{"DEFAULT_COMPRESSION", KuduColumnStorageAttributes::CompressionType::DEFAULT_COMPRESSION},
+ {"NO_COMPRESSION", KuduColumnStorageAttributes::CompressionType::NO_COMPRESSION},
+ {"SNAPPY", KuduColumnStorageAttributes::CompressionType::SNAPPY},
+ {"LZ4", KuduColumnStorageAttributes::CompressionType::LZ4},
+ {"ZLIB", KuduColumnStorageAttributes::CompressionType::ZLIB}};
+
+ const KuduColumnStorageAttributes::CompressionType* compression_type =
+ FindOrNull(compression_type_map, compression_type_uc);
+ if (!compression_type) {
+ return Status::InvalidArgument(Substitute(
+ "Failed to parse compression type from $0, supported compression types are: $1.",
+ compression_type_arg,
+ JoinKeysIterator(compression_type_map.begin(), compression_type_map.end(), ", ")));
+ }
+
+ client::sp::shared_ptr<KuduClient> client;
+ RETURN_NOT_OK(CreateKuduClient(context, &client));
+ unique_ptr<KuduTableAlterer> alterer(client->NewTableAlterer(table_name));
+ alterer->AlterColumn(column_name)->Compression(*compression_type);
+ return alterer->Alter();
+}
+
+Status ColumnSetEncoding(const RunnerContext& context) {
+ const string& table_name = FindOrDie(context.required_args, kTableNameArg);
+ const string& column_name = FindOrDie(context.required_args, kColumnNameArg);
+ const string& encoding_type_arg = FindOrDie(context.required_args, kEncodingTypeArg);
+ std::string encoding_type_uc;
+ ToUpperCase(encoding_type_arg, &encoding_type_uc);
+
+ static unordered_map<string, KuduColumnStorageAttributes::EncodingType> encoding_type_map =
+ {{"AUTO_ENCODING", KuduColumnStorageAttributes::EncodingType::AUTO_ENCODING},
+ {"PLAIN_ENCODING", KuduColumnStorageAttributes::EncodingType::PLAIN_ENCODING},
+ {"PREFIX_ENCODING", KuduColumnStorageAttributes::EncodingType::PREFIX_ENCODING},
+ {"RLE", KuduColumnStorageAttributes::EncodingType::RLE},
+ {"DICT_ENCODING", KuduColumnStorageAttributes::EncodingType::DICT_ENCODING},
+ {"BIT_SHUFFLE", KuduColumnStorageAttributes::EncodingType::BIT_SHUFFLE}};
+
+ const KuduColumnStorageAttributes::EncodingType* encoding_type =
+ FindOrNull(encoding_type_map, encoding_type_uc);
+ if (!encoding_type) {
+ return Status::InvalidArgument(Substitute(
+ "Failed to parse encoding type from $0, supported encoding types are: $1.",
+ encoding_type_arg,
+ JoinKeysIterator(encoding_type_map.begin(), encoding_type_map.end(), ", ")));
+ }
+
+ client::sp::shared_ptr<KuduClient> client;
+ RETURN_NOT_OK(CreateKuduClient(context, &client));
+ unique_ptr<KuduTableAlterer> alterer(client->NewTableAlterer(table_name));
+ alterer->AlterColumn(column_name)->Encoding(*encoding_type);
+ return alterer->Alter();
+}
+
+Status ColumnSetBlockSize(const RunnerContext& context) {
+ const string& table_name = FindOrDie(context.required_args, kTableNameArg);
+ const string& column_name = FindOrDie(context.required_args, kColumnNameArg);
+ const string& str_block_size = FindOrDie(context.required_args, kBlockSizeArg);
+
+ int32_t block_size;
+ if (!safe_strto32(str_block_size, &block_size)) {
+ return Status::InvalidArgument(Substitute(
+ "Unable to parse block_size value: $0.", str_block_size));
+ }
+ if (block_size <= 0) {
+ return Status::InvalidArgument(Substitute(
+ "Invalid block size: $0, it should be set higher than 0.", str_block_size));
+ }
+
+ client::sp::shared_ptr<KuduClient> client;
+ RETURN_NOT_OK(CreateKuduClient(context, &client));
+ unique_ptr<KuduTableAlterer> alterer(client->NewTableAlterer(table_name));
+ alterer->AlterColumn(column_name)->BlockSize(block_size);
+ 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);
+
+ client::sp::shared_ptr<KuduClient> client;
+ RETURN_NOT_OK(CreateKuduClient(context, &client));
+ unique_ptr<KuduTableAlterer> alterer(client->NewTableAlterer(table_name));
+ alterer->DropColumn(column_name);
+ return alterer->Alter();
+}
+
} // anonymous namespace
unique_ptr<Mode> BuildTableMode() {
@@ -800,9 +1006,69 @@ unique_ptr<Mode> BuildTableMode() {
.AddOptionalParameter("upper_bound_type")
.Build();
+ unique_ptr<Action> column_set_default =
+ ActionBuilder("column_set_default", &ColumnSetDefault)
+ .Description("Set write_default value for a column")
+ .AddRequiredParameter({ kMasterAddressesArg, kMasterAddressesArgDesc })
+ .AddRequiredParameter({ kTableNameArg, "Name of the table to alter" })
+ .AddRequiredParameter({ kColumnNameArg, "Name of the table column to alter" })
+ .AddRequiredParameter({ kDefaultValueArg,
+ "Write default value of the column, should be provided as a "
+ "JSON array, e.g. [1] or [\"foo\"]" })
+ .Build();
+
+ unique_ptr<Action> column_remove_default =
+ ActionBuilder("column_remove_default", &ColumnRemoveDefault)
+ .Description("Remove write_default value for a column")
+ .AddRequiredParameter({ kMasterAddressesArg, kMasterAddressesArgDesc })
+ .AddRequiredParameter({ kTableNameArg, "Name of the table to alter" })
+ .AddRequiredParameter({ kColumnNameArg, "Name of the table column to alter" })
+ .Build();
+
+ unique_ptr<Action> column_set_compression =
+ ActionBuilder("column_set_compression", &ColumnSetCompression)
+ .Description("Set compression type for a column")
+ .AddRequiredParameter({ kMasterAddressesArg, kMasterAddressesArgDesc })
+ .AddRequiredParameter({ kTableNameArg, "Name of the table to alter" })
+ .AddRequiredParameter({ kColumnNameArg, "Name of the table column to alter" })
+ .AddRequiredParameter({ kCompressionTypeArg, "Compression type of the column" })
+ .Build();
+
+ unique_ptr<Action> column_set_encoding =
+ ActionBuilder("column_set_encoding", &ColumnSetEncoding)
+ .Description("Set encoding type for a column")
+ .AddRequiredParameter({ kMasterAddressesArg, kMasterAddressesArgDesc })
+ .AddRequiredParameter({ kTableNameArg, "Name of the table to alter" })
+ .AddRequiredParameter({ kColumnNameArg, "Name of the table column to alter" })
+ .AddRequiredParameter({ kEncodingTypeArg, "Encoding type of the column" })
+ .Build();
+
+ unique_ptr<Action> column_set_block_size =
+ ActionBuilder("column_set_block_size", &ColumnSetBlockSize)
+ .Description("Set block size for a column")
+ .AddRequiredParameter({ kMasterAddressesArg, kMasterAddressesArgDesc })
+ .AddRequiredParameter({ kTableNameArg, "Name of the table to alter" })
+ .AddRequiredParameter({ kColumnNameArg, "Name of the table column to alter" })
+ .AddRequiredParameter({ kBlockSizeArg, "Block size of the column" })
+ .Build();
+
+ unique_ptr<Action> delete_column =
+ ActionBuilder("delete_column", &DeleteColumn)
+ .Description("Delete a column")
+ .AddRequiredParameter({ kMasterAddressesArg, kMasterAddressesArgDesc })
+ .AddRequiredParameter({ kTableNameArg, "Name of the table to alter" })
+ .AddRequiredParameter({ kColumnNameArg, "Name of the table column to delete" })
+ .Build();
+
return ModeBuilder("table")
.Description("Operate on Kudu tables")
.AddAction(std::move(add_range_partition))
+ .AddAction(std::move(column_set_default))
+ .AddAction(std::move(column_remove_default))
+ .AddAction(std::move(column_set_compression))
+ .AddAction(std::move(column_set_encoding))
+ .AddAction(std::move(column_set_block_size))
+ .AddAction(std::move(delete_column))
.AddAction(std::move(delete_table))
.AddAction(std::move(describe_table))
.AddAction(std::move(drop_range_partition))