YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/yql/cql/ql/test/ql-create-table-test.cc
Line
Count
Source (jump to first uncovered line)
1
//--------------------------------------------------------------------------------------------------
2
// Copyright (c) YugaByte, Inc.
3
//
4
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
// in compliance with the License.  You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software distributed under the License
10
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
// or implied.  See the License for the specific language governing permissions and limitations
12
// under the License.
13
//
14
//--------------------------------------------------------------------------------------------------
15
16
#include <boost/algorithm/string.hpp>
17
18
#include "yb/common/ql_value.h"
19
#include "yb/common/transaction.h"
20
21
#include "yb/master/catalog_manager_if.h"
22
#include "yb/master/master_ddl.pb.h"
23
#include "yb/master/master_defaults.h"
24
25
#include "yb/util/status_log.h"
26
27
#include "yb/yql/cql/ql/test/ql-test-base.h"
28
29
DECLARE_int32(TEST_simulate_slow_table_create_secs);
30
DECLARE_bool(master_enable_metrics_snapshotter);
31
DECLARE_bool(tserver_enable_metrics_snapshotter);
32
DECLARE_int32(metrics_snapshotter_interval_ms);
33
DECLARE_string(metrics_snapshotter_table_metrics_whitelist);
34
DECLARE_string(metrics_snapshotter_tserver_metrics_whitelist);
35
36
37
namespace yb {
38
namespace master {
39
class CatalogManager;
40
class Master;
41
}
42
namespace ql {
43
44
#define EXEC_DUPLICATE_OBJECT_CREATE_STMT(stmt)                         \
45
0
  EXEC_INVALID_STMT_WITH_ERROR(stmt, "Duplicate Object. Object")
46
47
class TestQLCreateTable : public QLTestBase {
48
 public:
49
0
  TestQLCreateTable() : QLTestBase() {
50
0
  }
51
52
0
  inline const string CreateStmt(string params) {
53
0
    return "CREATE TABLE " + params;
54
0
  }
55
56
0
  inline const string CreateIfNotExistsStmt(string params) {
57
0
    return "CREATE TABLE IF NOT EXISTS " + params;
58
0
  }
59
};
60
61
0
TEST_F(TestQLCreateTable, TestQLCreateTableSimple) {
62
  // Init the simulated cluster.
63
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
64
65
  // Get an available processor.
66
0
  TestQLProcessor *processor = GetQLProcessor();
67
68
0
  const string table1 = "human_resource1(id int, name varchar, primary key(id));";
69
0
  const string table2 = "human_resource2(id int primary key, name varchar);";
70
0
  const string table3 = "human_resource3(id int, name varchar primary key);";
71
0
  const string table4 = "human_resource4(id int, name varchar, primary key(id, name));";
72
0
  const string table5 = "human_resource5(id int, name varchar, primary key((id), name));";
73
0
  const string table6 =
74
0
      "human_resource6(id int, name varchar, salary int, primary key((id, name), salary));";
75
76
0
  const string table7 = "human_resource7(id int, name varchar, primary key(id));";
77
0
  const string table8 = "human_resource8(id int primary key, name varchar);";
78
0
  const string table9 = "human_resource9(id int, name varchar primary key);";
79
0
  const string table10 = "human_resource10(id int, name varchar, primary key(id, name));";
80
0
  const string table11 = "human_resource11(id int, name varchar, primary key((id), name));";
81
0
  const string table12 =
82
0
      "human_resource12(id int, name varchar, salary int, primary key((id, name), salary));";
83
84
  // Define primary key before defining columns.
85
0
  const string table13 =
86
0
      "human_resource13(id int, primary key((id, name), salary), name varchar, salary int);";
87
88
  // Create the table 1.
89
0
  EXEC_VALID_STMT(CreateStmt(table1));
90
91
  // Create the table 2. Use "id" as primary key.
92
0
  EXEC_VALID_STMT(CreateStmt(table2));
93
94
  // Create the table 3. Use "name" as primary key.
95
0
  EXEC_VALID_STMT(CreateStmt(table3));
96
97
  // Create the table 4. Use both "id" and "name" as primary key.
98
0
  EXEC_VALID_STMT(CreateStmt(table4));
99
100
  // Create the table 5. Use both "id" as hash primary key.
101
0
  EXEC_VALID_STMT(CreateStmt(table5));
102
103
  // Create the table 6. Use both "id" and "name" as hash primary key.
104
0
  EXEC_VALID_STMT(CreateStmt(table6));;
105
106
  // Create table 7.
107
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table7));
108
109
  // Create the table 8. Use "id" as primary key.
110
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table8));
111
112
  // Create the table 9. Use "name" as primary key.
113
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table9));
114
115
  // Create the table 10. Use both "id" and "name" as primary key.
116
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table10));
117
118
  // Create the table 11. Use both "id" as hash primary key.
119
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table11));
120
121
  // Create the table 12. Use both "id" and "name" as hash primary key.
122
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table12));
123
124
  // Create the table 13. Define primary key before the columns.
125
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table13));
126
127
  // Verify that all 'CREATE TABLE' statements fail for tables that have already been created.
128
0
  EXEC_DUPLICATE_OBJECT_CREATE_STMT(CreateStmt(table1));
129
0
  EXEC_DUPLICATE_OBJECT_CREATE_STMT(CreateStmt(table2));
130
0
  EXEC_DUPLICATE_OBJECT_CREATE_STMT(CreateStmt(table3));
131
0
  EXEC_DUPLICATE_OBJECT_CREATE_STMT(CreateStmt(table4));
132
0
  EXEC_DUPLICATE_OBJECT_CREATE_STMT(CreateStmt(table5));
133
0
  EXEC_DUPLICATE_OBJECT_CREATE_STMT(CreateStmt(table6));
134
0
  EXEC_DUPLICATE_OBJECT_CREATE_STMT(CreateStmt(table7));
135
0
  EXEC_DUPLICATE_OBJECT_CREATE_STMT(CreateStmt(table8));
136
0
  EXEC_DUPLICATE_OBJECT_CREATE_STMT(CreateStmt(table9));
137
0
  EXEC_DUPLICATE_OBJECT_CREATE_STMT(CreateStmt(table10));
138
0
  EXEC_DUPLICATE_OBJECT_CREATE_STMT(CreateStmt(table11));
139
0
  EXEC_DUPLICATE_OBJECT_CREATE_STMT(CreateStmt(table12));
140
141
  // Verify that all 'CREATE TABLE IF EXISTS' statements succeed for tables that have already been
142
  // created.
143
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table1));
144
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table2));
145
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table3));
146
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table4));
147
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table5));
148
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table6));
149
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table7));
150
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table8));
151
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table9));
152
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table10));
153
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table11));
154
0
  EXEC_VALID_STMT(CreateIfNotExistsStmt(table12));
155
156
0
  const string drop_stmt = "DROP TABLE human_resource1;";
157
0
  EXEC_VALID_STMT(drop_stmt);
158
0
}
159
160
// Tests fix for https://github.com/YugaByte/yugabyte-db/issues/798.
161
// In order to reproduce the issue consistently, we have inserted a sleep after the table has been
162
// inserted in the master's memory map so that a subsequent request can find it and return an
163
// AlreadyPresent error. Before the fix, a CREATE TABLE IF NOT EXISTS will immediately return
164
// after encountering the error without waiting for the table to be ready to serve read/write
165
// requests which happens when a CREATE TABLE statement succeeds.
166
167
// This test creates a new thread to simulate two concurrent CREATE TABLE statements. In the  main
168
// thread we issue a CREATE TABLE IF NOT EXIST statement which should wait until the master is done
169
// sleeping and the table is in a ready state. Without the fix, the INSERT statement always fails
170
// with a "Table Not Found" error.
171
0
TEST_F(TestQLCreateTable, TestQLConcurrentCreateTableAndCreateTableIfNotExistsStmts) {
172
0
  FLAGS_TEST_simulate_slow_table_create_secs = 10;
173
  // Init the simulated cluster.
174
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
175
176
  // Get an available processor.
177
0
  TestQLProcessor *processor1 = GetQLProcessor();
178
0
  TestQLProcessor *processor2 = GetQLProcessor();
179
180
0
  auto s = processor1->Run("create keyspace k;");
181
182
0
  std::thread t1([&] {
183
0
    auto s2 = processor1->Run("CREATE TABLE k.t(k int PRIMARY KEY);");
184
0
    CHECK_OK(s2);
185
0
    LOG(INFO) << "Created keyspace table t";
186
0
  });
187
188
  // Sleep for 5 sec to give the previous statement a head start.
189
0
  SleepFor(MonoDelta::FromSeconds(5));
190
191
  // Before the fix, this would return immediately with Status::OK() without waiting for the table
192
  // to be ready to serve read/write requests. With the fix, this statement shouldn't return until
193
  // the table is ready, which happens after FLAGS_TEST_simulate_slow_table_create_secs seconds have
194
  // elapsed.
195
0
  s = processor2->Run("CREATE TABLE IF NOT EXISTS k.t(k int PRIMARY KEY);");
196
0
  CHECK_OK(s);
197
198
0
  s = processor2->Run("INSERT INTO k.t(k) VALUES (1)");
199
0
  CHECK_OK(s);
200
201
0
  t1.join();
202
0
}
203
204
// Same test as TestQLConcurrentCreateTableAndCreateTableIfNotExistsStmts, but this time we verify
205
// that whenever a CREATE TABLE statement returns "Duplicate Table. Already present", the table
206
// is ready to accept write requests.
207
0
TEST_F(TestQLCreateTable, TestQLConcurrentCreateTableStmt) {
208
0
  FLAGS_TEST_simulate_slow_table_create_secs = 10;
209
  // Init the simulated cluster.
210
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
211
212
  // Get an available processor.
213
0
  TestQLProcessor *processor1 = GetQLProcessor();
214
0
  TestQLProcessor *processor2 = GetQLProcessor();
215
216
0
  auto s = processor1->Run("create keyspace k;");
217
218
0
  std::thread t1([&] {
219
0
    auto s2 = processor1->Run("CREATE TABLE k.t(k int PRIMARY KEY);");
220
0
    CHECK_OK(s2);
221
0
    LOG(INFO) << "Created keyspace table t";
222
0
  });
223
224
  // Sleep for 5 sec to give the previous statement a head start.
225
0
  SleepFor(MonoDelta::FromSeconds(5));
226
227
  // Wait until the table is already present in the tables map of the master.
228
0
  s = processor2->Run("CREATE TABLE k.t(k int PRIMARY KEY);");
229
0
  EXPECT_FALSE(s.ToString().find("Duplicate Object. Object ") == string::npos);
230
231
0
  s = processor2->Run("INSERT INTO k.t(k) VALUES (1)");
232
0
  EXPECT_OK(s);
233
234
0
  t1.join();
235
0
}
236
237
0
TEST_F(TestQLCreateTable, TestQLCreateTableWithTTL) {
238
  // Init the simulated cluster.
239
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
240
241
  // Get an available processor.
242
0
  TestQLProcessor *processor = GetQLProcessor();
243
244
  // Create the table 1.
245
0
  const string table1 = "human_resource100(id int, name varchar, PRIMARY KEY(id));";
246
0
  EXEC_VALID_STMT(CreateStmt(table1));
247
248
0
  EXEC_VALID_STMT("CREATE TABLE table_with_ttl (c1 int, c2 int, c3 int, PRIMARY KEY(c1)) WITH "
249
0
                      "default_time_to_live = 1;");
250
251
  // Query the table schema.
252
0
  auto *catalog_manager = &cluster_->mini_master()->catalog_manager();
253
0
  master::GetTableSchemaRequestPB request_pb;
254
0
  master::GetTableSchemaResponsePB response_pb;
255
0
  request_pb.mutable_table()->mutable_namespace_()->set_name(kDefaultKeyspaceName);
256
0
  request_pb.mutable_table()->set_table_name("table_with_ttl");
257
258
  // Verify ttl was stored in syscatalog table.
259
0
  CHECK_OK(catalog_manager->GetTableSchema(&request_pb, &response_pb));
260
0
  const TablePropertiesPB& properties_pb = response_pb.schema().table_properties();
261
0
  EXPECT_TRUE(properties_pb.has_default_time_to_live());
262
  // We store ttl in milliseconds internally.
263
0
  EXPECT_EQ(1000, properties_pb.default_time_to_live());
264
0
}
265
266
0
TEST_F(TestQLCreateTable, TestQLCreateTableWithClusteringOrderBy) {
267
  // Init the simulated cluster.
268
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
269
270
  // Get an available processor.
271
0
  TestQLProcessor *processor = GetQLProcessor();
272
273
0
  const string table1 = "human_resource1(id int, first_name varchar, last_name varchar, "
274
0
      "primary key(id, first_name, last_name)) WITH CLUSTERING ORDER BY(first_name ASC);";
275
0
  const string table2 = "human_resource2(id int, first_name varchar, last_name varchar, "
276
0
      "primary key(id, first_name, last_name)) WITH CLUSTERING ORDER BY(first_name ASC) AND "
277
0
      "CLUSTERING ORDER BY (last_name DESC);";
278
0
  const string table3 = "human_resource3(id int, first_name varchar, last_name varchar, "
279
0
      "primary key(id, first_name, last_name)) "
280
0
      "WITH CLUSTERING ORDER BY(first_name ASC, last_name DESC);";
281
0
  const string table4 = "human_resource4(id int, first_name varchar, last_name varchar, "
282
0
      "primary key(id, last_name, first_name)) "
283
0
      "WITH CLUSTERING ORDER BY(last_name ASC, last_name DESC);";
284
0
  const string table5 = "human_resource5(id int, first_name varchar, last_name varchar, "
285
0
      "primary key(id, last_name, first_name)) "
286
0
      "WITH CLUSTERING ORDER BY(last_name ASC, first_name DESC, last_name DESC);";
287
0
  const string table6 = "human_resource6(id int, first_name varchar, last_name varchar, "
288
0
      "primary key(id, first_name, last_name)) "
289
0
      "WITH CLUSTERING ORDER BY(last_name DESC, first_name DESC);";
290
0
  const string table7 = "human_resource7(id int, first_name varchar, last_name varchar, "
291
0
      "primary key(id, first_name, last_name)) "
292
0
      "WITH CLUSTERING ORDER BY(last_name DESC) AND "
293
0
      "CLUSTERING ORDER BY (first_name DESC);";
294
0
  const string table8 = "human_resource8(id int, first_name varchar, last_name varchar, "
295
0
      "primary key(id, first_name, last_name)) "
296
0
      "WITH CLUSTERING ORDER BY(last_name DESC, last_name DESC);";
297
0
  const string table9 = "human_resource9(id int, first_name varchar, last_name varchar, "
298
0
      "primary key(id, first_name, last_name)) "
299
0
      "WITH CLUSTERING ORDER BY(first_name DESC, last_name DESC, something DESC);";
300
0
  const string table10 = "human_resource10(id int, first_name varchar, last_name varchar, "
301
0
      "primary key(id, last_name, first_name)) "
302
0
      "WITH CLUSTERING ORDER BY(something ASC);";
303
0
  const string table11 = "human_resource10(id int, first_name varchar, last_name varchar, age int, "
304
0
      "primary key(id, last_name, first_name)) "
305
0
      "WITH CLUSTERING ORDER BY(age ASC);";
306
0
  const string table12 = "human_resource10(id int, first_name varchar, last_name varchar, "
307
0
      "primary key(id, last_name, first_name)) "
308
0
      "WITH CLUSTERING ORDER BY(id);";
309
  // Create the table 1.
310
0
  EXEC_VALID_STMT(CreateStmt(table1));
311
0
  EXEC_VALID_STMT(CreateStmt(table2));
312
0
  EXEC_VALID_STMT(CreateStmt(table3));
313
0
  EXEC_VALID_STMT(CreateStmt(table4));
314
0
  EXEC_VALID_STMT(CreateStmt(table5));
315
316
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table6),
317
0
      "Invalid Table Property. Columns in the CLUSTERING ORDER directive must be in same order "
318
0
      "as the clustering key columns order (first_name must appear before last_name)");
319
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table7),
320
0
      "Invalid Table Property. Columns in the CLUSTERING ORDER directive must be in same order "
321
0
      "as the clustering key columns order (first_name must appear before last_name)");
322
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table8),
323
0
      "Invalid Table Property. Missing CLUSTERING ORDER for column first_name");
324
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table9),
325
0
      "Invalid Table Property. Not a clustering key colum");
326
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table10),
327
0
      "Invalid Table Property. Not a clustering key colum");
328
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table11),
329
0
      "Invalid Table Property. Not a clustering key colum");
330
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table12),
331
0
      "Invalid Table Property. Not a clustering key colum");
332
0
}
333
334
0
TEST_F(TestQLCreateTable, TestQLCreateTableWithPartitionScemeOf) {
335
  // Init the simulated cluster.
336
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
337
338
  // Get an available processor.
339
0
  TestQLProcessor *processor = GetQLProcessor();
340
341
0
  const string table1 = "devices(supplier_id INT, device_id DOUBLE, model_year INT, "
342
0
      "device_name TEXT, PRIMARY KEY((supplier_id, device_id), model_year));";
343
0
  const string table2 = "descriptions1(supplier_id INT, device_id DOUBLE, description TEXT, "
344
0
      "PRIMARY KEY((supplier_id, device_id))) with partition scheme of devices;";
345
0
  const string table3 = "descriptions2(supp_id INT, dev_id DOUBLE, description TEXT, "
346
0
      "image_id INT, PRIMARY KEY((supp_id, dev_id), image_id)) "
347
0
      "with partition scheme of devices;";
348
0
  const string table4 = "descriptions3(supplier_id INT, device_id DOUBLE, description TEXT, "
349
0
      "PRIMARY KEY(supplier_id, device_id)) with partition scheme of devices;";
350
0
  const string table5 = "descriptions4(supplier_id INT, device_id DOUBLE, model_year INT, "
351
0
      "description TEXT, PRIMARY KEY((supplier_id, device_id, model_year))) "
352
0
      "with partition scheme of devices;";
353
0
  const string table6 = "descriptions5(supplier_id INT, device_id DOUBLE, description TEXT, "
354
0
      "PRIMARY KEY((supplier_id, device_id))) with partition scheme of non_existing_table;";
355
0
  const string table7 = "descriptions6(supp_id INT, dev_id DOUBLE, description TEXT, "
356
0
      "image_id INT, PRIMARY KEY((supp_id, description))) with partition scheme of devices;";
357
0
  const string table8 = "descriptions7(supp_id INT, dev_id DOUBLE, description TEXT, "
358
0
      "image_id INT, PRIMARY KEY((dev_id, supp_id))) with partition scheme of devices;";
359
0
  const string table9 = "descriptions8(supp_id INT, dev_id DOUBLE, description TEXT, "
360
0
      "image_id INT, PRIMARY KEY((supp_id, image_id))) with partition scheme of devices;";
361
0
  const string table10 = "descriptions9(supp_id INT, dev_id DOUBLE, description TEXT, "
362
0
      "image_id INT, PRIMARY KEY((description, image_id))) with partition scheme of devices;";
363
0
  const string table11 = "descriptions10(supp_id INT, dev_id DOUBLE, description TEXT, "
364
0
      "image_id INT, PRIMARY KEY((supp_id, dev_id))) with partition scheme devices;";
365
0
  const string table12 = "descriptions11(supp_id INT, dev_id DOUBLE, description TEXT, "
366
0
      "image_id INT, PRIMARY KEY((supp_id, dev_id))) with partition schema of devices;";
367
0
  const string table13 = "descriptions12(supp_id INT, dev_id DOUBLE, description TEXT, "
368
0
      "image_id INT, PRIMARY KEY((supp_id, dev_id))) with partitioning scheme of devices;";
369
370
  // Create the devices tables.
371
0
  EXEC_VALID_STMT(CreateStmt(table1));
372
373
0
  EXEC_VALID_STMT(CreateStmt(table2));
374
0
  EXEC_VALID_STMT(CreateStmt(table3));
375
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table4),
376
0
                               "The number of hash keys in the current table "
377
0
                                   "differ from the number of hash keys in 'devices'");
378
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table5),
379
0
                               "The number of hash keys in the current table "
380
0
                                   "differ from the number of hash keys in 'devices'");
381
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table6),
382
0
                               "Object Not Found");
383
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table7),
384
0
                               "The hash key 'description' in the current table has a different "
385
0
                                   "datatype from the corresponding hash key in 'devices'");
386
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table8),
387
0
                               "The hash key 'dev_id' in the current table has a different "
388
0
                                   "datatype from the corresponding hash key in 'devices'");
389
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table9),
390
0
                               "The hash key 'image_id' in the current table has a different "
391
0
                                   "datatype from the corresponding hash key in 'devices'");
392
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table10),
393
0
                               "The hash key 'description' in the current table has a different "
394
0
                                   "datatype from the corresponding hash key in 'devices'");
395
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table11),
396
0
                               "syntax error");
397
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table12),
398
0
                               "syntax error");
399
0
  EXEC_INVALID_STMT_WITH_ERROR(CreateStmt(table13),
400
0
                               "syntax error");
401
0
}
402
403
// Check for presence of rows in system.metrics table.
404
0
TEST_F(TestQLCreateTable, TestMetrics) {
405
0
  FLAGS_master_enable_metrics_snapshotter = true;
406
0
  FLAGS_tserver_enable_metrics_snapshotter = true;
407
408
0
  std::vector<std::string> table_metrics =
409
0
  {"rocksdb_bytes_per_read_sum", "rocksdb_bytes_per_read_count"};
410
0
  FLAGS_metrics_snapshotter_table_metrics_whitelist = boost::algorithm::join(table_metrics, ",");
411
412
0
  std::vector<std::string> tserver_metrics = {
413
0
    "handler_latency_yb_tserver_TabletServerService_ListTablets_sum",
414
0
    "handler_latency_yb_tserver_TabletServerService_ListTablets_count",
415
0
    "handler_latency_yb_tserver_TabletServerService_ListTabletsForTabletServer_sum"};
416
0
  FLAGS_metrics_snapshotter_tserver_metrics_whitelist =
417
0
    boost::algorithm::join(tserver_metrics, ",");
418
419
  // rf1 cluster.
420
0
  ASSERT_NO_FATALS(CreateSimulatedCluster(1));
421
422
0
  TestQLProcessor* processor = GetQLProcessor();
423
0
  ASSERT_OK(processor->Run("create keyspace k"));
424
425
0
  auto table_name = "tmptable";
426
427
0
  ASSERT_OK(processor->Run(Format("CREATE TABLE k.$0(id int PRIMARY KEY)", table_name)));
428
429
  // Sleep for 5 sec to give the previous statement a head start.
430
0
  SleepFor(MonoDelta::FromSeconds(5));
431
432
0
  int num_inserts = 100;
433
0
  for (int i = 0; i < num_inserts; i++) {
434
0
    ASSERT_OK(processor->Run(Format("INSERT INTO k.$0 (id) VALUES ($1)", table_name, i)));
435
0
  }
436
437
  // Read from table, ignore output.
438
0
  ASSERT_OK(processor->Run(Format("SELECT * FROM k.$0", table_name)));
439
440
  // Sleep enough for one tick of metrics snapshotter (and a bit more).
441
0
  SleepFor(MonoDelta::FromMilliseconds(3 * FLAGS_metrics_snapshotter_interval_ms + 200));
442
443
  // Verify whitelist functionality for table metrics.
444
0
  {
445
0
    ASSERT_OK(processor->Run(Format("SELECT metric FROM $0.$1 WHERE entity_type=\'table\'",
446
0
            yb::master::kSystemNamespaceName, kMetricsSnapshotsTableName)));
447
448
0
    auto row_block = processor->row_block();
449
450
0
    std::unordered_set<std::string> t;
451
0
    for (size_t i = 0; i < row_block->row_count(); i++) {
452
0
      QLRow &row = row_block->row(i);
453
0
      t.insert(row.column(0).string_value());
454
0
    }
455
456
0
    EXPECT_EQ(t.size(), table_metrics.size());
457
0
    for (const auto& table_metric : table_metrics) {
458
0
      EXPECT_NE(t.find(table_metric), t.end());
459
0
    }
460
0
  }
461
462
  // Verify whitelist functionality for tserver metrics.
463
0
  {
464
0
    ASSERT_OK(processor->Run(Format("SELECT metric FROM $0.$1 WHERE entity_type=\'tserver\'",
465
0
            yb::master::kSystemNamespaceName, kMetricsSnapshotsTableName)));
466
467
0
    auto row_block = processor->row_block();
468
469
0
    std::unordered_set<std::string> t;
470
0
    for (size_t i = 0; i < row_block->row_count(); i++) {
471
0
      QLRow &row = row_block->row(i);
472
0
      t.insert(row.column(0).string_value());
473
0
    }
474
475
0
    EXPECT_EQ(t.size(), tserver_metrics.size());
476
0
    for (const auto& tserver_metric : tserver_metrics) {
477
0
      EXPECT_NE(t.find(tserver_metric), t.end());
478
0
    }
479
0
  }
480
481
0
  ASSERT_OK(processor->Run(Format("DROP TABLE k.$0", table_name)));
482
0
}
483
484
} // namespace ql
485
} // namespace yb