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
The following commit(s) were added to refs/heads/master by this push:
new 8c20126d8 KUDU-2671: Extra test coverage for KuduScanTokens.
8c20126d8 is described below
commit 8c20126d8a648f3fed15b4f41527089947d80d11
Author: Mahesh Reddy <[email protected]>
AuthorDate: Tue Jul 12 16:49:26 2022 -0700
KUDU-2671: Extra test coverage for KuduScanTokens.
This patch adds extra test coverage for scans using
KuduScanTokens. Specifically, the test case is on a
table with custom hash schemas and non covering ranges.
Change-Id: I0dec5c713940c1f8d66416c6a287b93e250d90e6
Reviewed-on: http://gerrit.cloudera.org:8080/18721
Tested-by: Alexey Serbin <[email protected]>
Reviewed-by: Alexey Serbin <[email protected]>
---
src/kudu/client/client.h | 4 -
src/kudu/client/scan_token-test.cc | 214 +++++++++++++++++++++++++++++++++++--
2 files changed, 208 insertions(+), 10 deletions(-)
diff --git a/src/kudu/client/client.h b/src/kudu/client/client.h
index 418dfe261..5fabee2ac 100644
--- a/src/kudu/client/client.h
+++ b/src/kudu/client/client.h
@@ -3114,10 +3114,6 @@ class KUDU_EXPORT KuduScanner {
///
/// Scan token locality information can be inspected using the
/// KuduScanToken::tablet() function.
-///
-/// Scan tokens are not yet compatible for tables that contain range-specific
-/// hash schemas. To be clear, the existing use case of tables with all ranges
-/// using the table wide hash schema is functional as expected.
class KUDU_EXPORT KuduScanToken {
public:
diff --git a/src/kudu/client/scan_token-test.cc
b/src/kudu/client/scan_token-test.cc
index f38dae6ae..d0a6f5377 100644
--- a/src/kudu/client/scan_token-test.cc
+++ b/src/kudu/client/scan_token-test.cc
@@ -595,16 +595,15 @@ TEST_F(ScanTokenTest,
ScanTokensWithCustomHashSchemasPerRange) {
// Create table
shared_ptr<KuduTable> table;
{
- unique_ptr<KuduPartialRow> lower_bound(schema.NewRow());
- unique_ptr<KuduPartialRow> upper_bound(schema.NewRow());
unique_ptr<KuduTableCreator> table_creator(client_->NewTableCreator());
table_creator->table_name("table");
table_creator->num_replicas(1);
table_creator->schema(&schema);
-
table_creator->add_hash_partitions({ "col" }, 2);
{
+ unique_ptr<KuduPartialRow> lower_bound(schema.NewRow());
+ unique_ptr<KuduPartialRow> upper_bound(schema.NewRow());
ASSERT_OK(lower_bound->SetInt64("col", 0));
ASSERT_OK(upper_bound->SetInt64("col", 100));
unique_ptr<KuduTableCreator::KuduRangePartition> range_partition(
@@ -615,14 +614,14 @@ TEST_F(ScanTokenTest,
ScanTokensWithCustomHashSchemasPerRange) {
}
{
- lower_bound.reset(schema.NewRow());
- upper_bound.reset(schema.NewRow());
+ unique_ptr<KuduPartialRow> lower_bound(schema.NewRow());
+ unique_ptr<KuduPartialRow> upper_bound(schema.NewRow());
ASSERT_OK(lower_bound->SetInt64("col", 100));
ASSERT_OK(upper_bound->SetInt64("col", 200));
unique_ptr<KuduTableCreator::KuduRangePartition> range_partition(
new KuduTableCreator::KuduRangePartition(lower_bound.release(),
upper_bound.release()));
- range_partition->add_hash_partitions({ "col"}, 2);
+ range_partition->add_hash_partitions({ "col" }, 2);
table_creator->add_custom_range_partition(range_partition.release());
}
@@ -732,6 +731,209 @@ TEST_F(ScanTokenTest,
ScanTokensWithCustomHashSchemasPerRange) {
}
}
+TEST_F(ScanTokenTest, TestScanTokensWithCustomHashSchemasPerNonCoveringRange) {
+ FLAGS_enable_per_range_hash_schemas = true;
+ KuduSchema schema;
+ // Create schema
+ {
+ KuduSchemaBuilder builder;
+
builder.AddColumn("col")->NotNull()->Type(KuduColumnSchema::INT64)->PrimaryKey();
+ ASSERT_OK(builder.Build(&schema));
+ }
+
+ // Create table
+ shared_ptr<KuduTable> table;
+ {
+ unique_ptr<KuduTableCreator> table_creator(client_->NewTableCreator());
+ table_creator->table_name("table");
+ table_creator->num_replicas(1);
+ table_creator->schema(&schema);
+ table_creator->add_hash_partitions({ "col" }, 2);
+
+ {
+ unique_ptr<KuduPartialRow> lower_bound(schema.NewRow());
+ unique_ptr<KuduPartialRow> upper_bound(schema.NewRow());
+ ASSERT_OK(lower_bound->SetInt64("col", 0));
+ ASSERT_OK(upper_bound->SetInt64("col", 100));
+ unique_ptr<KuduTableCreator::KuduRangePartition> range_partition(
+ new KuduTableCreator::KuduRangePartition(lower_bound.release(),
upper_bound.release()));
+ range_partition->add_hash_partitions({ "col" }, 4);
+ table_creator->add_custom_range_partition(range_partition.release());
+ }
+
+ {
+ unique_ptr<KuduPartialRow> lower_bound(schema.NewRow());
+ unique_ptr<KuduPartialRow> upper_bound(schema.NewRow());
+ ASSERT_OK(lower_bound->SetInt64("col", 200));
+ ASSERT_OK(upper_bound->SetInt64("col", 300));
+ unique_ptr<KuduTableCreator::KuduRangePartition> range_partition(
+ new KuduTableCreator::KuduRangePartition(lower_bound.release(),
upper_bound.release()));
+ range_partition->add_hash_partitions({ "col" }, 2);
+ table_creator->add_custom_range_partition(range_partition.release());
+ }
+
+ ASSERT_OK(table_creator->Create());
+ ASSERT_OK(client_->OpenTable("table", &table));
+ }
+
+ // Create session
+ shared_ptr<KuduSession> session = client_->NewSession();
+ session->SetTimeoutMillis(10000);
+ ASSERT_OK(session->SetFlushMode(KuduSession::AUTO_FLUSH_BACKGROUND));
+
+ // Insert rows
+ for (int i = 0; i < 100; i++) {
+ unique_ptr<KuduInsert> insert(table->NewInsert());
+ ASSERT_OK(insert->mutable_row()->SetInt64("col", i));
+ ASSERT_OK(session->Apply(insert.release()));
+ }
+ for (int i = 200; i < 300; i++) {
+ unique_ptr<KuduInsert> insert(table->NewInsert());
+ ASSERT_OK(insert->mutable_row()->SetInt64("col", i));
+ ASSERT_OK(session->Apply(insert.release()));
+ }
+ ASSERT_OK(session->Flush());
+
+ uint64_t expected_count = 0;
+ CheckLiveRowCount("table", &expected_count);
+ ASSERT_EQ(expected_count, 200);
+
+ { // no predicates
+ vector<KuduScanToken*> tokens;
+ ElementDeleter deleter(&tokens);
+ ASSERT_OK(KuduScanTokenBuilder(table.get()).Build(&tokens));
+
+ ASSERT_EQ(6, tokens.size());
+ ASSERT_EQ(200, CountRows(tokens));
+ shared_ptr<KuduClient> new_client;
+ ASSERT_OK(cluster_->CreateClient(nullptr, &new_client));
+ int64_t row_count = 0;
+ ASSERT_OK(CountRowsSeq(new_client.get(), tokens, &row_count));
+ ASSERT_EQ(200, row_count);
+ NO_FATALS(VerifyTabletInfo(tokens));
+ }
+
+ { // range predicate
+ vector<KuduScanToken*> tokens;
+ ElementDeleter deleter(&tokens);
+ KuduScanTokenBuilder builder(table.get());
+ unique_ptr<KuduPredicate> predicate(table->NewComparisonPredicate(
+ "col", KuduPredicate::GREATER_EQUAL, KuduValue::FromInt(150)));
+ ASSERT_OK(builder.AddConjunctPredicate(predicate.release()));
+ ASSERT_OK(builder.Build(&tokens));
+
+ ASSERT_EQ(2, tokens.size());
+ ASSERT_EQ(100, CountRows(tokens));
+ NO_FATALS(VerifyTabletInfo(tokens));
+ }
+
+ { // range predicate
+ vector<KuduScanToken*> tokens;
+ ElementDeleter deleter(&tokens);
+ KuduScanTokenBuilder builder(table.get());
+ unique_ptr<KuduPredicate> predicate(table->NewComparisonPredicate(
+ "col", KuduPredicate::GREATER_EQUAL, KuduValue::FromInt(100)));
+ ASSERT_OK(builder.AddConjunctPredicate(predicate.release()));
+ unique_ptr<KuduPredicate> predicate1(table->NewComparisonPredicate(
+ "col", KuduPredicate::LESS, KuduValue::FromInt(200)));
+ ASSERT_OK(builder.AddConjunctPredicate(predicate1.release()));
+ ASSERT_OK(builder.Build(&tokens));
+
+ ASSERT_EQ(0, tokens.size());
+ ASSERT_EQ(0, CountRows(tokens));
+ NO_FATALS(VerifyTabletInfo(tokens));
+ }
+
+ { // range predicate
+ vector<KuduScanToken*> tokens;
+ ElementDeleter deleter(&tokens);
+ KuduScanTokenBuilder builder(table.get());
+ unique_ptr<KuduPredicate> predicate(table->NewComparisonPredicate(
+ "col", KuduPredicate::GREATER_EQUAL, KuduValue::FromInt(50)));
+ ASSERT_OK(builder.AddConjunctPredicate(predicate.release()));
+ unique_ptr<KuduPredicate> predicate1(table->NewComparisonPredicate(
+ "col", KuduPredicate::LESS, KuduValue::FromInt(250)));
+ ASSERT_OK(builder.AddConjunctPredicate(predicate1.release()));
+ ASSERT_OK(builder.Build(&tokens));
+
+ ASSERT_EQ(6, tokens.size());
+ ASSERT_EQ(100, CountRows(tokens));
+ NO_FATALS(VerifyTabletInfo(tokens));
+ }
+
+ { // range predicate
+ vector<KuduScanToken*> tokens;
+ ElementDeleter deleter(&tokens);
+ KuduScanTokenBuilder builder(table.get());
+ unique_ptr<KuduPredicate> predicate(table->NewComparisonPredicate(
+ "col", KuduPredicate::GREATER_EQUAL, KuduValue::FromInt(-50)));
+ ASSERT_OK(builder.AddConjunctPredicate(predicate.release()));
+ unique_ptr<KuduPredicate> predicate1(table->NewComparisonPredicate(
+ "col", KuduPredicate::LESS, KuduValue::FromInt(350)));
+ ASSERT_OK(builder.AddConjunctPredicate(predicate1.release()));
+ ASSERT_OK(builder.Build(&tokens));
+
+ ASSERT_EQ(6, tokens.size());
+ ASSERT_EQ(200, CountRows(tokens));
+ NO_FATALS(VerifyTabletInfo(tokens));
+ }
+
+ { // equality predicate
+ vector<KuduScanToken*> tokens;
+ ElementDeleter deleter(&tokens);
+ KuduScanTokenBuilder builder(table.get());
+ unique_ptr<KuduPredicate> predicate(table->NewComparisonPredicate(
+ "col", KuduPredicate::EQUAL, KuduValue::FromInt(242)));
+ ASSERT_OK(builder.AddConjunctPredicate(predicate.release()));
+ ASSERT_OK(builder.Build(&tokens));
+
+ ASSERT_EQ(1, tokens.size());
+ ASSERT_EQ(1, CountRows(tokens));
+ NO_FATALS(VerifyTabletInfo(tokens));
+ }
+
+ { // IS NOT NULL predicate
+ vector<KuduScanToken*> tokens;
+ ElementDeleter deleter(&tokens);
+ KuduScanTokenBuilder builder(table.get());
+ unique_ptr<KuduPredicate> predicate(table->NewIsNotNullPredicate("col"));
+ ASSERT_OK(builder.AddConjunctPredicate(predicate.release()));
+ ASSERT_OK(builder.Build(&tokens));
+
+ ASSERT_EQ(6, tokens.size());
+ ASSERT_EQ(200, CountRows(tokens));
+ NO_FATALS(VerifyTabletInfo(tokens));
+ }
+
+ { // IS NULL predicate
+ vector<KuduScanToken*> tokens;
+ ElementDeleter deleter(&tokens);
+ KuduScanTokenBuilder builder(table.get());
+ unique_ptr<KuduPredicate> predicate(table->NewIsNullPredicate("col"));
+ ASSERT_OK(builder.AddConjunctPredicate(predicate.release()));
+ ASSERT_OK(builder.Build(&tokens));
+
+ ASSERT_GE(0, tokens.size());
+ ASSERT_EQ(0, CountRows(tokens));
+ NO_FATALS(VerifyTabletInfo(tokens));
+ }
+
+ { // primary key bound
+ vector<KuduScanToken*> tokens;
+ ElementDeleter deleter(&tokens);
+ KuduScanTokenBuilder builder(table.get());
+ unique_ptr<KuduPartialRow> upper_bound(schema.NewRow());
+ ASSERT_OK(upper_bound->SetInt64("col", 40));
+
+ ASSERT_OK(builder.AddUpperBound(*upper_bound));
+ ASSERT_OK(builder.Build(&tokens));
+
+ ASSERT_EQ(4, tokens.size());
+ ASSERT_EQ(40, CountRows(tokens));
+ NO_FATALS(VerifyTabletInfo(tokens));
+ }
+}
+
class TimestampPropagationParamTest :
public ScanTokenTest,
public ::testing::WithParamInterface<kudu::ReadMode> {