YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/yql/pgwrapper/pg_gin_index-test.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
13
#include <string>
14
15
#include "yb/client/client.h"
16
#include "yb/client/table_info.h"
17
#include "yb/client/yb_table_name.h"
18
19
#include "yb/gutil/bind_internal.h"
20
21
#include "yb/integration-tests/mini_cluster_base.h"
22
23
#include "yb/util/async_util.h"
24
25
#include "yb/yql/pgwrapper/libpq_test_base.h"
26
#include "yb/yql/pgwrapper/libpq_utils.h"
27
28
namespace yb {
29
namespace pgwrapper {
30
31
namespace {
32
33
constexpr auto kDatabaseName = "yugabyte";
34
constexpr auto kIndexName = "ginidx";
35
constexpr auto kTableName = "gintab";
36
const client::YBTableName kYBTableName(YQLDatabase::YQL_DATABASE_PGSQL, kDatabaseName, kTableName);
37
38
} // namespace
39
40
class PgGinIndexTest : public LibPqTestBase {
41
 public:
42
0
  void SetUp() override {
43
0
    LibPqTestBase::SetUp();
44
45
0
    conn_ = std::make_unique<PGConn>(ASSERT_RESULT(ConnectToDB(kDatabaseName)));
46
0
  }
47
48
 protected:
49
  std::unique_ptr<PGConn> conn_;
50
};
51
52
namespace {
53
54
// A copy of the same function in pg_libpq-test.cc.  Eventually, issue #6868 should provide a way to
55
// do this easily for both this file and that.
56
Result<string> GetTableIdByTableName(
57
0
    client::YBClient* client, const string& namespace_name, const string& table_name) {
58
0
  const auto tables = VERIFY_RESULT(client->ListTables());
59
0
  for (const auto& t : tables) {
60
0
    if (t.namespace_name() == namespace_name && t.table_name() == table_name) {
61
0
      return t.table_id();
62
0
    }
63
0
  }
64
0
  return STATUS(NotFound, "The table does not exist");
65
0
}
66
67
} // namespace
68
69
// Test creating a ybgin index on an array whose element type is unsupported for primary key.
70
0
TEST_F(PgGinIndexTest, YB_DISABLE_TEST_IN_TSAN(UnsupportedArrayElementType)) {
71
0
  ASSERT_OK(conn_->ExecuteFormat("CREATE TABLE $0 (a tsvector[])", kTableName));
72
0
  auto status = conn_->ExecuteFormat("CREATE INDEX $0 ON $1 USING ybgin (a)",
73
0
                                     kIndexName, kTableName);
74
75
  // Make sure that the index isn't created on PG side.
76
0
  ASSERT_NOK(status);
77
0
  auto msg = status.message().ToBuffer();
78
0
  ASSERT_TRUE(msg.find("INDEX on column of type 'TSVECTOR' not yet supported") != std::string::npos)
79
0
      << status;
80
81
  // Make sure that the index isn't created on YB side.
82
  // First, check the table to make sure schema version isn't incremented.
83
0
  auto client = ASSERT_RESULT(cluster_->CreateClient());
84
0
  auto table_id = ASSERT_RESULT(GetTableIdByTableName(client.get(), kDatabaseName, kTableName));
85
0
  auto table_info = std::make_shared<client::YBTableInfo>();
86
0
  Synchronizer sync;
87
0
  ASSERT_OK(client->GetTableSchemaById(table_id, table_info, sync.AsStatusCallback()));
88
0
  ASSERT_OK(sync.Wait());
89
0
  ASSERT_EQ(table_info->schema.version(), 0);
90
  // Second, check that the index doesn't exist.
91
0
  auto result = GetTableIdByTableName(client.get(), kDatabaseName, kIndexName);
92
0
  ASSERT_NOK(result);
93
0
}
94
95
// Test SPLIT option.
96
0
TEST_F(PgGinIndexTest, YB_DISABLE_TEST_IN_TSAN(SplitOption)) {
97
0
  ASSERT_OK(conn_->ExecuteFormat("CREATE TABLE $0 (v tsvector)", kTableName));
98
0
  ASSERT_OK(conn_->ExecuteFormat("INSERT INTO $0 VALUES ('ab bc'), ('cd ef gh')", kTableName));
99
100
  // Hash splitting shouldn't work since the default partitioning scheme is range.
101
0
  auto status = conn_->ExecuteFormat("CREATE INDEX ON $0 USING ybgin (v) SPLIT INTO 4 TABLETS",
102
0
                                     kTableName);
103
0
  ASSERT_NOK(status);
104
0
  auto msg = status.message().ToBuffer();
105
0
  ASSERT_TRUE(msg.find("HASH columns must be present to split by number of tablets")
106
0
              != std::string::npos) << status;
107
108
  // Range splitting should work.
109
0
  ASSERT_OK(conn_->ExecuteFormat("CREATE INDEX $0 ON $1 USING ybgin (v)"
110
0
                                 " SPLIT AT VALUES (('bar'), ('foo'))",
111
0
                                 kIndexName, kTableName));
112
  // Check that partitions were actually created.
113
0
  auto client = ASSERT_RESULT(cluster_->CreateClient());
114
0
  auto index_id = ASSERT_RESULT(GetTableIdByTableName(client.get(), kDatabaseName, kIndexName));
115
0
  auto index_info = std::make_shared<client::YBTableInfo>();
116
0
  Synchronizer sync;
117
0
  ASSERT_OK(client->GetTableSchemaById(index_id, index_info, sync.AsStatusCallback()));
118
0
  ASSERT_OK(sync.Wait());
119
0
  PartitionSchemaPB pb;
120
0
  index_info->partition_schema.ToPB(&pb);
121
0
  LOG(INFO) << "Index partition schema: " << pb.DebugString();
122
0
  ASSERT_EQ(pb.range_schema().splits_size(), 2);
123
  // Check SELECT.
124
0
  {
125
0
    auto query = Format("SELECT count(*) FROM $0 where v @@ 'bc'", kTableName);
126
0
    ASSERT_TRUE(ASSERT_RESULT(conn_->HasIndexScan(query)));
127
0
    auto res = ASSERT_RESULT(conn_->Fetch(query));
128
0
    ASSERT_EQ(PQntuples(res.get()), 1);
129
0
    ASSERT_EQ(PQnfields(res.get()), 1);
130
0
    auto value = ASSERT_RESULT(GetInt64(res.get(), 0, 0));
131
0
    ASSERT_EQ(value, 1);
132
0
  }
133
0
  {
134
0
    auto query = Format("SELECT unnest.lexeme FROM $0, LATERAL unnest(v) where v @@ 'bc'",
135
0
                        kTableName);
136
0
    ASSERT_TRUE(ASSERT_RESULT(conn_->HasIndexScan(query)));
137
0
    auto res = ASSERT_RESULT(conn_->Fetch(query));
138
0
    ASSERT_EQ(PQntuples(res.get()), 2);
139
0
    ASSERT_EQ(PQnfields(res.get()), 1);
140
0
    std::vector<std::string> values{
141
0
      ASSERT_RESULT(GetString(res.get(), 0, 0)),
142
0
      ASSERT_RESULT(GetString(res.get(), 1, 0)),
143
0
    };
144
0
    ASSERT_EQ(values[0], "ab");
145
0
    ASSERT_EQ(values[1], "bc");
146
0
  }
147
148
  // Hash partitioning is currently not possible, so we can't test hash splitting.
149
0
}
150
151
} // namespace pgwrapper
152
} // namespace yb