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> {

Reply via email to