This is an automated email from the ASF dual-hosted git repository. abukor pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/kudu.git
commit 768b6885485dcb74f2731ba59fdebf2e28d0a3a3 Author: Attila Bukor <[email protected]> AuthorDate: Tue Oct 1 18:01:23 2019 +0200 KUDU-1938 Add range partition support pt 6 Change-Id: Ib82985f09fef8d3372f40412156cd7a8ce69d61c Reviewed-on: http://gerrit.cloudera.org:8080/14333 Reviewed-by: Grant Henke <[email protected]> Tested-by: Kudu Jenkins --- src/kudu/common/partition-test.cc | 54 +++++++++++++++++++++++++ src/kudu/common/partition.cc | 11 +++++ src/kudu/common/partition.h | 1 + src/kudu/integration-tests/varchar-itest.cc | 62 +++++++++++++++++++++++++++-- 4 files changed, 125 insertions(+), 3 deletions(-) diff --git a/src/kudu/common/partition-test.cc b/src/kudu/common/partition-test.cc index 799d292..9091eed 100644 --- a/src/kudu/common/partition-test.cc +++ b/src/kudu/common/partition-test.cc @@ -803,4 +803,58 @@ TEST_F(PartitionTest, TestIncrementRangePartitionStringBounds) { check(test, false); } } + +TEST_F(PartitionTest, TestVarcharRangePartitions) { + Schema schema({ ColumnSchema("c1", VARCHAR, false, nullptr, nullptr, + ColumnStorageAttributes(), ColumnTypeAttributes(10)), + ColumnSchema("c2", VARCHAR, false, nullptr, nullptr, + ColumnStorageAttributes(), ColumnTypeAttributes(10)) }, + { ColumnId(0), ColumnId(1) }, 2); + + PartitionSchemaPB schema_builder; + PartitionSchema partition_schema; + ASSERT_OK(PartitionSchema::FromPB(schema_builder, schema, &partition_schema)); + + vector<vector<boost::optional<string>>> tests { + { string("a"), string("b"), string("a"), string("b\0", 2) }, + { string("a"), boost::none, string("a"), string("\0", 1) }, + }; + + auto check = [&] (const vector<boost::optional<string>>& test, bool lower_bound) { + CHECK_EQ(4, test.size()); + KuduPartialRow bound(&schema); + if (test[0]) ASSERT_OK(bound.SetVarchar("c1", *test[0])); + if (test[1]) ASSERT_OK(bound.SetVarchar("c2", *test[1])); + + vector<string> components; + partition_schema.AppendRangeDebugStringComponentsOrMin(bound, &components); + SCOPED_TRACE(JoinStrings(components, ", ")); + SCOPED_TRACE(lower_bound ? "lower bound" : "upper bound"); + + if (lower_bound) { + ASSERT_OK(partition_schema.MakeLowerBoundRangePartitionKeyInclusive(&bound)); + } else { + ASSERT_OK(partition_schema.MakeUpperBoundRangePartitionKeyExclusive(&bound)); + } + + Slice val; + if (test[2]) { + ASSERT_OK(bound.GetVarchar("c1", &val)); + ASSERT_EQ(*test[2], val); + } else { + ASSERT_FALSE(bound.IsColumnSet("c1")); + } + if (test[3]) { + ASSERT_OK(bound.GetVarchar("c2", &val)); + ASSERT_EQ(*test[3], val); + } else { + ASSERT_FALSE(bound.IsColumnSet("c2")); + } + }; + + for (const auto& test : tests) { + check(test, true); + check(test, false); + } +} } // namespace kudu diff --git a/src/kudu/common/partition.cc b/src/kudu/common/partition.cc index 02b9062..571ec4a 100644 --- a/src/kudu/common/partition.cc +++ b/src/kudu/common/partition.cc @@ -1013,6 +1013,9 @@ namespace { case UNIXTIME_MICROS: RETURN_NOT_OK(row->SetInt64(idx, INT64_MIN + 1)); break; + case VARCHAR: + RETURN_NOT_OK(row->SetVarchar(idx, Slice("\0", 1))); + break; case STRING: RETURN_NOT_OK(row->SetStringCopy(idx, Slice("\0", 1))); break; @@ -1109,6 +1112,14 @@ namespace { RETURN_NOT_OK(row->SetBinaryCopy(idx, incremented)); break; } + case VARCHAR: { + Slice value; + RETURN_NOT_OK(row->GetVarchar(idx, &value)); + string incremented = value.ToString(); + incremented.push_back('\0'); + RETURN_NOT_OK(row->SetVarchar(idx, incremented)); + break; + } case STRING: { Slice value; RETURN_NOT_OK(row->GetString(idx, &value)); diff --git a/src/kudu/common/partition.h b/src/kudu/common/partition.h index d8e499b..761e8e2 100644 --- a/src/kudu/common/partition.h +++ b/src/kudu/common/partition.h @@ -267,6 +267,7 @@ class PartitionSchema { friend class PartitionPruner; FRIEND_TEST(PartitionTest, TestIncrementRangePartitionBounds); FRIEND_TEST(PartitionTest, TestIncrementRangePartitionStringBounds); + FRIEND_TEST(PartitionTest, TestVarcharRangePartitions); // Returns a text description of the encoded range key suitable for debug printing. std::string RangeKeyDebugString(Slice range_key, const Schema& schema) const; diff --git a/src/kudu/integration-tests/varchar-itest.cc b/src/kudu/integration-tests/varchar-itest.cc index ad92f8a..aab7623 100644 --- a/src/kudu/integration-tests/varchar-itest.cc +++ b/src/kudu/integration-tests/varchar-itest.cc @@ -40,14 +40,18 @@ namespace client { using sp::shared_ptr; -class VarcharItest : public ExternalMiniClusterITestBase {}; +class VarcharItest : public ExternalMiniClusterITestBase { + protected: + void SetUp() override { + NO_FATALS(StartCluster({}, {}, kNumServers)); + } -TEST_F(VarcharItest, TestCharVarcharTruncation) { const int kNumServers = 3; const int kNumTablets = 3; const char* const kTableName = "varchar-table"; - NO_FATALS(StartCluster({}, {}, kNumServers)); +}; +TEST_F(VarcharItest, TestVarcharTruncation) { KuduSchemaBuilder builder; builder.AddColumn("key")->Type(KuduColumnSchema::INT64) ->NotNull()->PrimaryKey(); @@ -106,5 +110,57 @@ TEST_F(VarcharItest, TestInvalidLength) { ASSERT_FALSE(s.ok()); } +TEST_F(VarcharItest, TestVarcharRangePartition) { + KuduSchemaBuilder builder; + builder.AddColumn("key")->Type(KuduColumnSchema::VARCHAR) + ->Length(10)->NotNull()->PrimaryKey(); + builder.AddColumn("value")->Type(KuduColumnSchema::VARCHAR) + ->Length(10); + KuduSchema schema; + ASSERT_OK(builder.Build(&schema)); + + KuduPartialRow* lower_bound = schema.NewRow(); + ASSERT_OK(lower_bound->SetVarchar("key", "bar")); + KuduPartialRow* upper_bound = schema.NewRow(); + ASSERT_OK(upper_bound->SetVarchar("key", "foo")); + + unique_ptr<client::KuduTableCreator> table_creator(client_->NewTableCreator()); + ASSERT_OK(table_creator->table_name(kTableName) + .schema(&schema) + .num_replicas(kNumServers) + .set_range_partition_columns({ "key" }) + .add_range_partition(lower_bound, upper_bound) + .Create()); + shared_ptr<KuduTable> table; + ASSERT_OK(client_->OpenTable(kTableName, &table)); + + shared_ptr<KuduSession> session = client_->NewSession(); + ASSERT_OK(session->SetFlushMode(KuduSession::AUTO_FLUSH_BACKGROUND)); + KuduInsert* insert = table->NewInsert(); + KuduPartialRow* write = insert->mutable_row(); + + ASSERT_OK(write->SetVarchar("key", "baz")); + ASSERT_OK(write->SetVarchar("value", "foobar")); + ASSERT_OK(session->Apply(insert)); + ASSERT_OK(session->Flush()); + + KuduScanner scanner(table.get()); + ASSERT_OK(scanner.SetFaultTolerant()); + ASSERT_OK(scanner.Open()); + ASSERT_TRUE(scanner.HasMoreRows()); + while (scanner.HasMoreRows()) { + KuduScanBatch batch; + ASSERT_OK(scanner.NextBatch(&batch)); + for (const KuduScanBatch::RowPtr& read : batch) { + Slice key; + ASSERT_OK(read.GetVarchar("key", &key)); + ASSERT_EQ("baz", key); + Slice value; + ASSERT_OK(read.GetVarchar("value", &value)); + ASSERT_EQ("foobar", value); + } + } +} + } // namespace client } // namespace kudu
