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-query-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 <cmath>
17
#include <thread>
18
19
#include "yb/client/client.h"
20
#include "yb/client/table.h"
21
22
#include "yb/common/jsonb.h"
23
#include "yb/common/partition.h"
24
#include "yb/common/ql_protocol_util.h"
25
#include "yb/common/ql_type.h"
26
#include "yb/common/ql_value.h"
27
28
#include "yb/gutil/strings/substitute.h"
29
30
#include "yb/master/master.h"
31
#include "yb/master/ts_manager.h"
32
33
#include "yb/util/decimal.h"
34
#include "yb/util/result.h"
35
#include "yb/util/status_log.h"
36
#include "yb/util/yb_partition.h"
37
38
#include "yb/yql/cql/ql/test/ql-test-base.h"
39
40
using std::string;
41
using std::unique_ptr;
42
using std::shared_ptr;
43
using strings::Substitute;
44
45
namespace yb {
46
namespace ql {
47
48
class TestQLQuery : public QLTestBase {
49
 public:
50
0
  TestQLQuery() : QLTestBase() {
51
0
  }
52
53
  std::shared_ptr<QLRowBlock> ExecSelect(TestQLProcessor *processor, int expected_rows = 1) {
54
    auto select = "SELECT c1, c2, c3 FROM test_table WHERE c1 = 1";
55
    Status s = processor->Run(select);
56
    CHECK(s.ok());
57
    auto row_block = processor->row_block();
58
    EXPECT_EQ(expected_rows, row_block->row_count());
59
    return row_block;
60
  }
61
62
0
  void VerifyExpiry(TestQLProcessor *processor) {
63
0
    ExecSelect(processor, 0);
64
0
  }
65
66
0
  void CreateTableAndInsertRow(TestQLProcessor *processor, bool with_ttl = true) {
67
    // Create the table.
68
0
    const char *create_stmt =
69
0
        "CREATE TABLE test_table(c1 int, c2 int, c3 int, "
70
0
            "primary key(c1));";
71
0
    Status s = processor->Run(create_stmt);
72
0
    CHECK(s.ok());
73
74
0
    std::string insert_stmt("INSERT INTO test_table(c1, c2, c3) VALUES(1, 2, 3)");
75
0
    if (with_ttl) {
76
      // Insert row with ttl.
77
0
      insert_stmt += " USING TTL 1;";
78
0
    } else {
79
0
      insert_stmt += ";";
80
0
    }
81
0
    s = processor->Run(insert_stmt);
82
0
    CHECK_OK(s);
83
84
    // Verify row is present.
85
0
    auto row_block = ExecSelect(processor);
86
0
    QLRow& row = row_block->row(0);
87
88
0
    EXPECT_EQ(1, row.column(0).int32_value());
89
0
    EXPECT_EQ(2, row.column(1).int32_value());
90
0
    EXPECT_EQ(3, row.column(2).int32_value());
91
0
  }
92
93
  void TestSelectWithBounds(
94
      string select_stmt,
95
      TestQLProcessor* processor,
96
      const std::vector<std::tuple<int64_t, int, string, int, int>>& rows,
97
0
      int start_idx, int end_idx, string order_by_clause) {
98
0
    std::vector<std::tuple<int64_t, int, string, int, int>> test_rows(
99
0
        &rows[start_idx], &rows[end_idx]);
100
101
0
    select_stmt += order_by_clause;
102
103
0
    if (order_by_clause == " ORDER BY r1 DESC") {
104
0
      std::reverse(test_rows.begin(), test_rows.end());
105
0
    }
106
0
    CHECK_OK(processor->Run(select_stmt));
107
0
    auto row_block = processor->row_block();
108
    // checking result
109
0
    ASSERT_EQ(test_rows.size(), row_block->row_count());
110
0
    for (size_t i = 0; i < test_rows.size(); i++) {
111
0
      QLRow &row = row_block->row(i);
112
0
      EXPECT_EQ(std::get<1>(test_rows[i]), row.column(0).int32_value());
113
0
      EXPECT_EQ(std::get<2>(test_rows[i]), row.column(1).string_value());
114
0
      EXPECT_EQ(std::get<3>(test_rows[i]), row.column(2).int32_value());
115
0
      EXPECT_EQ(std::get<4>(test_rows[i]), row.column(3).int32_value());
116
0
    }
117
0
  }
118
119
  // Make sure regular scan works, but errors when order by is present.
120
  void TestSelectWithoutOrderBy(
121
      string select_stmt,
122
      TestQLProcessor *processor,
123
      const std::vector<std::tuple<int64_t, int, string, int, int>> &rows,
124
0
      int start_idx, int end_idx) {
125
    // Forward scan
126
0
    TestSelectWithBounds(select_stmt, processor, rows, start_idx, end_idx, "");
127
0
    CHECK_INVALID_STMT(select_stmt + " ORDER BY r1 DESC");
128
0
    CHECK_INVALID_STMT(select_stmt + " ORDER BY r1 ASC");
129
0
  }
130
131
  // Make sure normal scans and those with order by clause all work.
132
  void TestSelectWithOrderBy(
133
      string select_stmt,
134
      TestQLProcessor *processor,
135
      const std::vector<std::tuple<int64_t, int, string, int, int>> &rows,
136
0
      int start_idx, int end_idx) {
137
    // Forward scan
138
0
    TestSelectWithBounds(select_stmt, processor, rows, start_idx, end_idx, "");
139
0
    TestSelectWithBounds(select_stmt, processor, rows, start_idx, end_idx, " ORDER BY r1 ASC");
140
0
    TestSelectWithBounds(select_stmt, processor, rows, start_idx, end_idx, " ORDER BY r1 DESC");
141
0
  }
142
143
  void TestScanWithBoundsPartitionOps(const std::string& func_name, int64_t max_hash,
144
0
                                      int64_t min_hash) {
145
    //----------------------------------------------------------------------------------------------
146
    // Setting up cluster
147
    //----------------------------------------------------------------------------------------------
148
149
    // Init the simulated cluster.
150
0
    ASSERT_NO_FATALS(CreateSimulatedCluster());
151
152
    // Get a processor.
153
0
    TestQLProcessor *processor = GetQLProcessor();
154
155
    // Create test table.
156
0
    CHECK_OK(processor->Run("CREATE TABLE scan_bounds_test (h1 int, h2 text, r1 int, v1 int,"
157
0
                                " PRIMARY KEY((h1, h2), r1));"));
158
159
0
    client::YBTableName name(YQL_DATABASE_CQL, kDefaultKeyspaceName, "scan_bounds_test");
160
0
    shared_ptr<client::YBTable> table;
161
162
0
    ASSERT_OK(client_->OpenTable(name, &table));
163
164
    //----------------------------------------------------------------------------------------------
165
    // Initializing rows data
166
    //----------------------------------------------------------------------------------------------
167
168
    // generating input data with hash_code and inserting into table
169
0
    std::vector<std::tuple<int64_t, int, string, int, int>> rows;
170
0
    for (int i = 0; i < 10; i++) {
171
0
      std::string i_str = std::to_string(i);
172
0
      google::protobuf::RepeatedPtrField<QLExpressionPB> row;
173
0
      row.Add()->mutable_value()->set_int32_value(i);
174
0
      row.Add()->mutable_value()->set_string_value(i_str);
175
176
0
      std::string part_key;
177
0
      CHECK_OK(table->partition_schema().EncodeKey(row, &part_key));
178
0
      uint16_t hash_code = PartitionSchema::DecodeMultiColumnHashValue(part_key);
179
180
0
      int64_t cql_hash = func_name == "token" ? YBPartition::YBToCqlHashCode(hash_code) : hash_code;
181
0
      std::tuple<int64_t, int, string, int, int> values(cql_hash, i, i_str, i, i);
182
0
      rows.push_back(values);
183
0
      string stmt = Substitute("INSERT INTO scan_bounds_test (h1, h2, r1, v1) VALUES "
184
0
                                   "($0, '$1', $2, $3);", i, i, i, i);
185
0
      CHECK_OK(processor->Run(stmt));
186
0
    }
187
188
    // ordering rows by hash code
189
0
    std::sort(rows.begin(), rows.end(),
190
0
              [](const std::tuple<int64_t, int, string, int, int>& r1,
191
0
                 const std::tuple<int64_t, int, string, int, int>& r2) -> bool {
192
0
                return std::get<0>(r1) < std::get<0>(r2);
193
0
              });
194
195
    // CQL uses 64 bit hashes, but YB uses 16-bit internally.
196
    // Our bucket range is [cql_hash, cql_hash + bucket_size) -- start-inclusive, end-exclusive
197
    // We test the bucket ranges below by choosing the appropriate values for the bounds.
198
0
    int64_t bucket_size = 1;
199
0
    if (func_name == "token") {
200
0
      bucket_size = bucket_size << 48;
201
0
    }
202
203
    //----------------------------------------------------------------------------------------------
204
    // Testing Select with lower bound
205
    //----------------------------------------------------------------------------------------------
206
207
    //---------------------------------- Exclusive Lower Bound -------------------------------------
208
0
    string select_stmt_template = "SELECT * FROM scan_bounds_test WHERE $0(h1, h2) > $1";
209
210
    // Entire range: hashes 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
211
0
    TestSelectWithoutOrderBy(
212
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[0]) - 1), processor, rows,
213
0
        0, 10);
214
    // Partial range: hashes 4, 5, 6, 7, 8, 9
215
0
    TestSelectWithoutOrderBy(
216
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[3])), processor, rows,
217
0
        4, 10);
218
    // Empty range: no hashes.
219
0
    TestSelectWithoutOrderBy(
220
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[9])), processor, rows,
221
0
        0, 0);
222
    // Empty range: no hashes (checking overflow for max Cql hash)
223
0
    TestSelectWithoutOrderBy(
224
0
        Substitute(select_stmt_template, func_name, max_hash), processor, rows,
225
0
        0, 0);
226
227
    //---------------------------------- Inclusive Lower Bound -------------------------------------
228
0
    select_stmt_template = "SELECT * FROM scan_bounds_test WHERE $0(h1, h2) >= $1";
229
    // Entire range: hashes 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
230
0
    TestSelectWithoutOrderBy(
231
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[0]) + bucket_size - 1),
232
0
        processor, rows, 0, 10);
233
    // Partial range: hashes 6, 7, 8, 9
234
0
    TestSelectWithoutOrderBy(
235
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[6]) + bucket_size - 1),
236
0
        processor, rows, 6, 10);
237
    // Empty range: no hashes
238
0
    TestSelectWithoutOrderBy(
239
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[9]) + bucket_size), processor,
240
0
        rows, 0, 0);
241
242
    //----------------------------------------------------------------------------------------------
243
    // Testing Select with upper bound
244
    //----------------------------------------------------------------------------------------------
245
246
    //---------------------------------- Exclusive Upper Bound -------------------------------------
247
0
    select_stmt_template = "SELECT * FROM scan_bounds_test WHERE $0(h1, h2) < $1";
248
    // Entire range: hashes 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
249
0
    TestSelectWithoutOrderBy(
250
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[9]) + bucket_size), processor,
251
0
        rows, 0, 10);
252
    // Partial range: hashes 0, 1, 2, 3, 4, 5, 6
253
0
    TestSelectWithoutOrderBy(
254
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[7]) + bucket_size - 1),
255
0
        processor, rows, 0, 7);
256
    // Empty range: no hashes
257
0
    TestSelectWithoutOrderBy(
258
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[0]) + bucket_size - 1),
259
0
        processor, rows, 0, 0);
260
261
    //---------------------------------- Inclusive Upper Bound -------------------------------------
262
0
    select_stmt_template = "SELECT * FROM scan_bounds_test WHERE $0(h1, h2) <= $1";
263
    // Entire range: hashes 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
264
0
    TestSelectWithoutOrderBy(
265
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[9])), processor, rows, 0, 10);
266
    // Partial range: hashes 0, 1, 2
267
0
    TestSelectWithoutOrderBy(
268
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[2])), processor, rows, 0, 3);
269
    // Empty range: no hashes
270
0
    TestSelectWithoutOrderBy(
271
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[0]) - 1), processor, rows, 0,
272
0
        0);
273
274
    //----------------------------------------------------------------------------------------------
275
    // Testing Select with both lower and upper bounds
276
    //----------------------------------------------------------------------------------------------
277
0
    select_stmt_template = "SELECT * FROM scan_bounds_test WHERE $0(h1, h2) $1 $2 AND $3(h1, h2) "
278
0
        "$4 $5";
279
    // Entire range: hashes 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
280
0
    TestSelectWithoutOrderBy(
281
0
        Substitute(select_stmt_template, func_name, ">=", std::get<0>(rows[0]) + bucket_size - 1,
282
0
                   func_name, "<=", std::get<0>(rows[9])), processor, rows, 0, 10);
283
    // Partial Range: hashes 2, 3, 4, 5, 6, 7, 8
284
0
    TestSelectWithoutOrderBy(
285
0
        Substitute(select_stmt_template, func_name, ">", std::get<0>(rows[1]),
286
0
                   func_name, "<=", std::get<0>(rows[8])), processor, rows, 2, 9);
287
    // Partial Range: hashes 4, 5, 6
288
0
    TestSelectWithoutOrderBy(
289
0
        Substitute(select_stmt_template, func_name, ">=", std::get<0>(rows[4]) + bucket_size - 1,
290
0
                   func_name, "<", std::get<0>(rows[7]) + bucket_size - 1), processor, rows,
291
0
        4, 7);
292
    // Empty Range (inclusive lower bound): no hashes
293
0
    TestSelectWithoutOrderBy(
294
0
        Substitute(select_stmt_template, func_name, ">=", std::get<0>(rows[2]) + bucket_size - 1,
295
0
                   func_name, "<", std::get<0>(rows[2]) + bucket_size - 1), processor, rows, 0, 0);
296
    // Empty Range (inclusive upper bound): no hashes
297
0
    TestSelectWithoutOrderBy(
298
0
        Substitute(select_stmt_template, func_name, ">", std::get<0>(rows[2]),
299
0
                   func_name, "<=", std::get<0>(rows[2])), processor, rows, 0, 0);
300
    // Empty range: no hashes (checking overflow for max Cql hash)
301
0
    TestSelectWithoutOrderBy(
302
0
        Substitute(select_stmt_template, func_name, "<=", std::get<0>(rows[9]), func_name, ">",
303
0
        max_hash), processor, rows, 0, 0);
304
305
    //----------------------------------------------------------------------------------------------
306
    // Testing Select with range limits
307
    //----------------------------------------------------------------------------------------------
308
    // Entire range: [min, max].
309
0
    TestSelectWithoutOrderBy(
310
0
        Substitute(select_stmt_template, func_name, ">=", min_hash, func_name, "<=", max_hash),
311
0
        processor, rows, 0, 10);
312
313
    // Entire range: [min, min] (upper bound min is treated as a special case in Cassandra).
314
0
    TestSelectWithoutOrderBy(
315
0
        Substitute(select_stmt_template, func_name, ">=", min_hash, func_name,  "<=", min_hash),
316
0
        processor, rows, 0, func_name == "token" ? 10 : 0);
317
318
    // Entire range: [min, min). (upper bound min is treated as a special case in Cassandra).
319
0
    TestSelectWithoutOrderBy(
320
0
        Substitute(select_stmt_template, func_name, ">=", min_hash, func_name, "<", min_hash),
321
0
        processor, rows, 0, func_name == "token" ? 10 : 0);
322
323
    // Empty range: (max, max].
324
0
    TestSelectWithoutOrderBy(
325
0
        Substitute(select_stmt_template, func_name, ">", max_hash, func_name, "<=", max_hash),
326
0
        processor, rows, 0, 0);
327
328
    // Empty range: (max, min] (max as strict lower bound already excludes all hashes).
329
0
    TestSelectWithoutOrderBy(
330
0
        Substitute(select_stmt_template, func_name, ">", max_hash, func_name, "<=", min_hash),
331
0
        processor, rows, 0, 0);
332
333
    //----------------------------------------------------------------------------------------------
334
    // Testing Select with exact partition key
335
    //----------------------------------------------------------------------------------------------
336
0
    select_stmt_template = "SELECT * FROM scan_bounds_test WHERE $0(h1, h2) = $1";
337
    // testing existing hash: 2
338
0
    TestSelectWithoutOrderBy(
339
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[2])), processor, rows,
340
0
        2, 3);
341
0
    TestSelectWithoutOrderBy(
342
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[2])), processor, rows,
343
0
        2, 3);
344
    // testing non-existing hash: empty
345
0
    TestSelectWithoutOrderBy(
346
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[9]) + bucket_size), processor,
347
0
        rows, 0, 0);
348
0
    TestSelectWithoutOrderBy(
349
0
        Substitute(select_stmt_template, func_name, std::get<0>(rows[9]) + bucket_size), processor,
350
0
        rows, 0, 0);
351
352
    //----------------------------------------------------------------------------------------------
353
    // Testing Select with conditions on both partition key and individual hash columns
354
    //   - These queries are not always logical (i.e. partition key condition is usually irrelevant
355
    //   - if part. column values are given) but Cassandra supports them so we replicate its
356
    //     behavior
357
    //----------------------------------------------------------------------------------------------
358
0
    select_stmt_template = "SELECT * FROM scan_bounds_test WHERE "
359
0
        "h1 = $0 AND h2 = '$1' AND $2(h1, h2) $3 $4";
360
361
    // checking existing row with exact partition key: 6
362
0
    TestSelectWithOrderBy(
363
0
        Substitute(select_stmt_template, std::get<1>(rows[6]), std::get<2>(rows[6]), func_name,
364
0
                   "=", std::get<0>(rows[6])), processor, rows, 6, 7);
365
    // checking existing row with partition key bound: 3 with partition upper bound 7 (to include 3)
366
0
    TestSelectWithOrderBy(
367
0
        Substitute(select_stmt_template, std::get<1>(rows[3]), std::get<2>(rows[3]), func_name,
368
0
                   "<=", std::get<0>(rows[7])), processor, rows, 3, 4);
369
    // checking existing row with partition key bound: 4 with partition lower bound 5 (to exclude 4)
370
0
    TestSelectWithOrderBy(
371
0
        Substitute(select_stmt_template, std::get<1>(rows[4]), std::get<2>(rows[4]), func_name,
372
0
                   ">=", std::get<0>(rows[5])), processor, rows, 0, 0);
373
    // checking existing row with partition key bound: 7 with partition upper bound 6 (to exclude 7)
374
0
    TestSelectWithOrderBy(
375
0
        Substitute(select_stmt_template, std::get<1>(rows[7]), std::get<2>(rows[7]), func_name,
376
0
                   "<=", std::get<0>(rows[6])), processor, rows, 0, 0);
377
378
    //----------------------------------------------------------------------------------------------
379
    // Testing Invalid Statements
380
    //----------------------------------------------------------------------------------------------
381
382
    // Invalid number of arguments.
383
0
    CHECK_INVALID_STMT(Substitute("SELECT * FROM scan_bounds_test WHERE $0() > 0", func_name));
384
0
    CHECK_INVALID_STMT(Substitute("SELECT * FROM scan_bounds_test WHERE $0(h1) > 0", func_name));
385
0
    CHECK_INVALID_STMT(Substitute("SELECT * FROM scan_bounds_test WHERE $0(h1,h2,h1) > 0",
386
0
                                  func_name));
387
388
    // Invalid argument values.
389
0
    CHECK_INVALID_STMT(Substitute("SELECT * FROM scan_bounds_test WHERE $0(h2,h1) > 0", func_name));
390
0
    CHECK_INVALID_STMT(Substitute("SELECT * FROM scan_bounds_test WHERE $0(h1,h1) > 0", func_name));
391
0
    CHECK_INVALID_STMT(Substitute("SELECT * FROM scan_bounds_test WHERE $0(h2,h2) > 0", func_name));
392
0
    CHECK_INVALID_STMT(Substitute("SELECT * FROM scan_bounds_test WHERE $0(r1,h2) > 0", func_name));
393
0
    CHECK_INVALID_STMT(Substitute("SELECT * FROM scan_bounds_test WHERE $0(r1,v1) > 0", func_name));
394
395
    // Illogical conditions.
396
    // Two "greater-than" bounds
397
0
    CHECK_INVALID_STMT(
398
0
        Substitute("SELECT * FROM scan_bounds_test WHERE $0(h1,h2) > 0 AND $1(h1,h2) >= 0",
399
0
        func_name, func_name));
400
    // Two "less-than" bounds
401
0
    CHECK_INVALID_STMT(
402
0
        Substitute("SELECT * FROM scan_bounds_test WHERE $0(h1,h2) <= 0 AND $1(h1,h2) < 0",
403
0
        func_name, func_name));
404
    // Two "equal" conditions
405
0
    CHECK_INVALID_STMT(
406
0
        Substitute("SELECT * FROM scan_bounds_test WHERE $0(h1,h2) = 0 AND $1(h1,h2) = 0",
407
0
        func_name, func_name));
408
    // Both "equal" and "less than" conditions
409
0
    CHECK_INVALID_STMT(
410
0
        Substitute("SELECT * FROM scan_bounds_test WHERE $0(h1,h2) = 0 AND $1(h1,h2) <= 0",
411
0
        func_name, func_name));
412
    // Both "equal" and "greater than" conditions
413
0
    CHECK_INVALID_STMT(
414
0
        Substitute("SELECT * FROM scan_bounds_test WHERE $0(h1,h2) = 0 AND $1(h1,h2) >= 0",
415
0
        func_name, func_name));
416
0
  }
417
418
0
  void TestPartitionHash(const std::string& func_name) {
419
    //----------------------------------------------------------------------------------------------
420
    // Setting up cluster
421
    //----------------------------------------------------------------------------------------------
422
423
    // Init the simulated cluster.
424
0
    ASSERT_NO_FATALS(CreateSimulatedCluster());
425
426
    // Get a processor.
427
0
    TestQLProcessor *processor = GetQLProcessor();
428
429
    //----------------------------------------------------------------------------------------------
430
    // Testing all simple types (that are allowed in primary keys)
431
    //----------------------------------------------------------------------------------------------
432
0
    CHECK_OK(processor->Run(
433
0
        "create table partition_hash_bcall_simple_test("
434
0
        " h1 tinyint, h2 smallint, h3 int, h4 bigint, h5 varchar, h6 blob, h7 timestamp, "
435
0
        " h8 decimal, h9 inet, h10 uuid, h11 timeuuid, r int, v int,"
436
0
        " primary key((h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11), r));"));
437
438
    // Sample values to check hash value computation
439
0
    string key_values = "99, 9999, 999999, 99999999, 'foo bar', 0x12fe9a, "
440
0
        "'1999-12-01 16:32:44 GMT', 987654.0123, '204.101.0.168', "
441
0
        "97bda55b-6175-4c39-9e04-7c0205c709dc, 97bda55b-6175-1c39-9e04-7c0205c709dc";
442
443
0
    string insert_stmt = "INSERT INTO partition_hash_bcall_simple_test (h1, h2, h3, h4, h5, h6, "
444
0
        "h7, h8, h9, h10, h11, r, v) VALUES ($0, 1, 1);";
445
446
0
    CHECK_OK(processor->Run(Substitute(insert_stmt, key_values)));
447
448
0
    string select_stmt = Substitute(
449
0
        "SELECT * FROM partition_hash_bcall_simple_test WHERE "
450
0
            "$0(h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11) = $1($2)", func_name,
451
0
        func_name, key_values);
452
453
0
    CHECK_OK(processor->Run(select_stmt));
454
0
    auto row_block = processor->row_block();
455
456
    // Checking result.
457
0
    ASSERT_EQ(1, row_block->row_count());
458
459
    //----------------------------------------------------------------------------------------------
460
    // Testing separate UDT type.
461
    //----------------------------------------------------------------------------------------------
462
0
    CHECK_OK(processor->Run("CREATE TYPE udt_partition_hash_test(a int, b text)"));
463
464
0
    CHECK_OK(processor->Run(
465
0
        "CREATE TABLE partition_hash_bcall_udt_test("
466
0
        " h frozen<udt_partition_hash_test>, r int, v int, PRIMARY KEY ((h), r))"));
467
468
    // Sample values to check hash value computation
469
0
    key_values = "{a : 1, b : 'foo'}";
470
471
0
    insert_stmt = Substitute("INSERT INTO partition_hash_bcall_udt_test "
472
0
                             "(h, r, v) VALUES ($0, 1, 1);", key_values);
473
0
    CHECK_OK(processor->Run(insert_stmt));
474
475
0
    select_stmt = Substitute("SELECT * FROM partition_hash_bcall_udt_test WHERE "
476
0
                                 "$0(h) = $1($2)", func_name, func_name, key_values);
477
0
    CHECK_OK(processor->Run(select_stmt));
478
479
    // Checking result.
480
0
    row_block = processor->row_block();
481
0
    ASSERT_EQ(1, row_block->row_count());
482
483
    //----------------------------------------------------------------------------------------------
484
    // Testing parametric types (i.e. with frozen)
485
    //----------------------------------------------------------------------------------------------
486
0
    CHECK_OK(processor->Run(
487
0
        "CREATE TABLE partition_hash_bcall_frozen_test("
488
0
        " h1 frozen<map<int,text>>, h2 frozen<set<text>>, h3 frozen<list<int>>, "
489
0
        " h4 frozen<udt_partition_hash_test>, r int, v int, PRIMARY KEY ((h1, h2, h3, h4), r))"));
490
491
    // Sample values to check hash value computation
492
0
    key_values = "{1 : 'a', 2 : 'b'}, {'x', 'y'}, [3, 1, 2], {a : 1, b : 'foo'}";
493
494
0
    insert_stmt = Substitute("INSERT INTO partition_hash_bcall_frozen_test "
495
0
                                 "(h1, h2, h3, h4, r, v) VALUES ($0, 1, 1);", key_values);
496
0
    CHECK_OK(processor->Run(insert_stmt));
497
498
0
    select_stmt = Substitute("SELECT * FROM partition_hash_bcall_frozen_test WHERE "
499
0
                                 "$0(h1, h2, h3, h4) = $1($2)", func_name, func_name, key_values);
500
0
    CHECK_OK(processor->Run(select_stmt));
501
502
    // Checking result.
503
0
    row_block = processor->row_block();
504
0
    ASSERT_EQ(1, row_block->row_count());
505
0
  }
506
507
};
508
509
0
TEST_F(TestQLQuery, TestMissingSystemTable) {
510
  // Init the simulated cluster.
511
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
512
513
  // Get a processor.
514
0
  TestQLProcessor *processor = GetQLProcessor();
515
0
  const char* statement = "SELECT * FROM system.invalid_system_table_name";
516
0
  constexpr auto kRepetitions = 10;
517
0
  for (auto i = 0; i != kRepetitions; ++i) {
518
0
    CHECK_VALID_STMT(statement);
519
0
  }
520
0
}
521
522
0
TEST_F(TestQLQuery, TestQLQuerySimple) {
523
  // Init the simulated cluster.
524
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
525
526
  // Get a processor.
527
0
  TestQLProcessor *processor = GetQLProcessor();
528
0
  LOG(INFO) << "Running simple query test.";
529
  // Create the table 1.
530
0
  const char *create_stmt =
531
0
    "CREATE TABLE test_table(h1 int, h2 varchar, "
532
0
                            "r1 int, r2 varchar, "
533
0
                            "v1 int, v2 varchar, "
534
0
                            "primary key((h1, h2), r1, r2));";
535
0
  CHECK_VALID_STMT(create_stmt);
536
537
  // Test NOTFOUND. Select from empty table.
538
0
  CHECK_VALID_STMT("SELECT * FROM test_table");
539
0
  std::shared_ptr<QLRowBlock> empty_row_block = processor->row_block();
540
0
  CHECK_EQ(empty_row_block->row_count(), 0);
541
0
  CHECK_VALID_STMT("SELECT * FROM test_table WHERE h1 = 0 AND h2 = ''");
542
0
  empty_row_block = processor->row_block();
543
0
  CHECK_EQ(empty_row_block->row_count(), 0);
544
545
  // Check for valid allow filtering clauses.
546
0
  CHECK_VALID_STMT("SELECT * FROM test_table WHERE h1 = 0 AND h2 = '' ALLOW FILTERING");
547
0
  empty_row_block = processor->row_block();
548
0
  CHECK_EQ(empty_row_block->row_count(), 0);
549
550
0
  CHECK_VALID_STMT("SELECT h1, h2, r1, r2, v1, v2 FROM test_table "
551
0
      "  WHERE h1 = 7 AND h2 = 'h7' AND v1 = 1007 ALLOW FILTERING");
552
0
  empty_row_block = processor->row_block();
553
0
  CHECK_EQ(empty_row_block->row_count(), 0);
554
555
0
  CHECK_VALID_STMT("SELECT h1, h2, r1, r2, v1, v2 FROM test_table "
556
0
      "  WHERE h1 = 7 AND h2 = 'h7' AND v1 = 100 ALLOW FILTERING");
557
0
  empty_row_block = processor->row_block();
558
0
  CHECK_EQ(empty_row_block->row_count(), 0);
559
560
  // Insert 100 rows into the table.
561
0
  static const int kNumRows = 100;
562
0
  for (int idx = 0; idx < kNumRows; idx++) {
563
    // INSERT: Valid statement with column list.
564
0
    string stmt = Substitute("INSERT INTO test_table(h1, h2, r1, r2, v1, v2) "
565
0
                             "VALUES($0, 'h$1', $2, 'r$3', $4, 'v$5');",
566
0
                             idx, idx, idx+100, idx+100, idx+1000, idx+1000);
567
0
    CHECK_VALID_STMT(stmt);
568
0
  }
569
0
  LOG(INFO) << kNumRows << " rows inserted";
570
571
  //------------------------------------------------------------------------------------------------
572
  // Test simple query and result.
573
0
  CHECK_VALID_STMT("SELECT h1, h2, r1, r2, v1, v2 FROM test_table "
574
0
                   "  WHERE h1 = 7 AND h2 = 'h7' AND r1 = 107;");
575
576
0
  std::shared_ptr<QLRowBlock> row_block = processor->row_block();
577
0
  CHECK_EQ(row_block->row_count(), 1);
578
0
  const QLRow& ordered_row = row_block->row(0);
579
0
  CHECK_EQ(ordered_row.column(0).int32_value(), 7);
580
0
  CHECK_EQ(ordered_row.column(1).string_value(), "h7");
581
0
  CHECK_EQ(ordered_row.column(2).int32_value(), 107);
582
0
  CHECK_EQ(ordered_row.column(3).string_value(), "r107");
583
0
  CHECK_EQ(ordered_row.column(4).int32_value(), 1007);
584
0
  CHECK_EQ(ordered_row.column(5).string_value(), "v1007");
585
586
  // Test simple query and result with different order.
587
0
  CHECK_VALID_STMT("SELECT v1, v2, h1, h2, r1, r2 FROM test_table "
588
0
                   "  WHERE h1 = 7 AND h2 = 'h7' AND r1 = 107;");
589
590
0
  row_block = processor->row_block();
591
0
  CHECK_EQ(row_block->row_count(), 1);
592
0
  const QLRow& unordered_row = row_block->row(0);
593
0
  CHECK_EQ(unordered_row.column(0).int32_value(), 1007);
594
0
  CHECK_EQ(unordered_row.column(1).string_value(), "v1007");
595
0
  CHECK_EQ(unordered_row.column(2).int32_value(), 7);
596
0
  CHECK_EQ(unordered_row.column(3).string_value(), "h7");
597
0
  CHECK_EQ(unordered_row.column(4).int32_value(), 107);
598
0
  CHECK_EQ(unordered_row.column(5).string_value(), "r107");
599
600
  // Test single row query for the whole table.
601
0
  for (int idx = 0; idx < kNumRows; idx++) {
602
    // SELECT: Valid statement with column list.
603
0
    string stmt = Substitute("SELECT h1, h2, r1, r2, v1, v2 FROM test_table "
604
0
                             "WHERE h1 = $0 AND h2 = 'h$1' AND r1 = $2 AND r2 = 'r$3';",
605
0
                             idx, idx, idx+100, idx+100);
606
0
    CHECK_VALID_STMT(stmt);
607
608
0
    row_block = processor->row_block();
609
0
    CHECK_EQ(row_block->row_count(), 1);
610
0
    const QLRow& row = row_block->row(0);
611
0
    CHECK_EQ(row.column(0).int32_value(), idx);
612
0
    CHECK_EQ(row.column(1).string_value(), Substitute("h$0", idx));
613
0
    CHECK_EQ(row.column(2).int32_value(), idx + 100);
614
0
    CHECK_EQ(row.column(3).string_value(), Substitute("r$0", idx + 100));
615
0
    CHECK_EQ(row.column(4).int32_value(), idx + 1000);
616
0
    CHECK_EQ(row.column(5).string_value(), Substitute("v$0", idx + 1000));
617
0
  }
618
619
  // Test multi row query for the whole table.
620
  // Insert 20 rows of the same hash key into the table.
621
0
  static const int kHashNumRows = 20;
622
0
  int32 h1_shared = 1111111;
623
0
  const string h2_shared = "h2_shared_key";
624
0
  for (int idx = 0; idx < kHashNumRows; idx++) {
625
    // INSERT: Valid statement with column list.
626
0
    string stmt = Substitute("INSERT INTO test_table(h1, h2, r1, r2, v1, v2) "
627
0
                             "VALUES($0, '$1', $2, 'r$3', $4, 'v$5');",
628
0
                             h1_shared, h2_shared, idx+100, idx+100, idx+1000, idx+1000);
629
0
    CHECK_VALID_STMT(stmt);
630
0
  }
631
632
  // Select all 20 rows and check the values.
633
0
  const string multi_select = Substitute("SELECT h1, h2, r1, r2, v1, v2 FROM test_table "
634
0
                                         "WHERE h1 = $0 AND h2 = '$1';",
635
0
                                         h1_shared, h2_shared);
636
0
  CHECK_VALID_STMT(multi_select);
637
0
  row_block = processor->row_block();
638
639
  // Check the result set.
640
0
  CHECK_EQ(row_block->row_count(), kHashNumRows);
641
0
  for (int idx = 0; idx < kHashNumRows; idx++) {
642
0
    const QLRow& row = row_block->row(idx);
643
0
    CHECK_EQ(row.column(0).int32_value(), h1_shared);
644
0
    CHECK_EQ(row.column(1).string_value(), h2_shared);
645
0
    CHECK_EQ(row.column(2).int32_value(), idx + 100);
646
0
    CHECK_EQ(row.column(3).string_value(), Substitute("r$0", idx + 100));
647
0
    CHECK_EQ(row.column(4).int32_value(), idx + 1000);
648
0
    CHECK_EQ(row.column(5).string_value(), Substitute("v$0", idx + 1000));
649
0
  }
650
651
  // Select only 2 rows and check the values.
652
0
  int limit = 2;
653
0
  string limit_select = Substitute("SELECT h1, h2, r1, r2, v1, v2 FROM test_table "
654
0
                                   "WHERE h1 = $0 AND h2 = '$1' LIMIT $2;",
655
0
                                   h1_shared, h2_shared, limit);
656
0
  CHECK_VALID_STMT(limit_select);
657
0
  row_block = processor->row_block();
658
659
  // Check the result set.
660
0
  CHECK_EQ(row_block->row_count(), limit);
661
0
  int32_t prev_r1 = 0;
662
0
  string prev_r2;
663
0
  for (int idx = 0; idx < limit; idx++) {
664
0
    const QLRow& row = row_block->row(idx);
665
0
    CHECK_EQ(row.column(0).int32_value(), h1_shared);
666
0
    CHECK_EQ(row.column(1).string_value(), h2_shared);
667
0
    CHECK_EQ(row.column(2).int32_value(), idx + 100);
668
0
    CHECK_EQ(row.column(3).string_value(), Substitute("r$0", idx + 100));
669
0
    CHECK_EQ(row.column(4).int32_value(), idx + 1000);
670
0
    CHECK_EQ(row.column(5).string_value(), Substitute("v$0", idx + 1000));
671
0
    CHECK_GT(row.column(2).int32_value(), prev_r1);
672
0
    CHECK_GT(row.column(3).string_value(), prev_r2);
673
0
    prev_r1 = row.column(2).int32_value();
674
0
    prev_r2 = row.column(3).string_value();
675
0
  }
676
677
0
  limit_select = Substitute("SELECT h1, h2, r1, r2, v1, v2 FROM test_table "
678
0
                            "WHERE h1 = $0 AND h2 = '$1' LIMIT $2 ALLOW FILTERING;",
679
0
                            h1_shared, h2_shared, limit);
680
0
  CHECK_VALID_STMT(limit_select);
681
682
0
  const string drop_stmt = "DROP TABLE test_table;";
683
0
  EXEC_VALID_STMT(drop_stmt);
684
0
}
685
686
0
TEST_F(TestQLQuery, TestPagingState) {
687
  // Init the simulated cluster.
688
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
689
690
  // Get a processor.
691
0
  TestQLProcessor *processor = GetQLProcessor();
692
693
0
  LOG(INFO) << "Running paging state test.";
694
695
  // Create table.
696
0
  CHECK_VALID_STMT("CREATE TABLE t (h int, r int, v int, primary key((h), r));");
697
698
0
  static constexpr int kNumRows = 100;
699
  // Insert 100 rows of the same hash key into the table.
700
0
  {
701
0
    for (int i = 1; i <= kNumRows; i++) {
702
      // INSERT: Valid statement with column list.
703
0
      string stmt = Substitute("INSERT INTO t (h, r, v) VALUES ($0, $1, $2);", 1, i, 100 + i);
704
0
      CHECK_VALID_STMT(stmt);
705
0
    }
706
0
    LOG(INFO) << kNumRows << " rows inserted";
707
0
  }
708
709
  // Read a single row. Verify row and that the paging state is empty.
710
0
  CHECK_VALID_STMT("SELECT h, r, v FROM t WHERE h = 1 AND r = 1;");
711
0
  std::shared_ptr<QLRowBlock> row_block = processor->row_block();
712
0
  CHECK_EQ(row_block->row_count(), 1);
713
0
  const QLRow& row = row_block->row(0);
714
0
  CHECK_EQ(row.column(0).int32_value(), 1);
715
0
  CHECK_EQ(row.column(1).int32_value(), 1);
716
0
  CHECK_EQ(row.column(2).int32_value(), 101);
717
0
  CHECK(processor->rows_result()->paging_state().empty());
718
719
  // Read all rows. Verify rows and that they are read in the number of pages expected.
720
0
  {
721
0
    StatementParameters params;
722
0
    int kPageSize = 5;
723
0
    params.set_page_size(kPageSize);
724
0
    int page_count = 0;
725
0
    int i = 0;
726
0
    do {
727
0
      CHECK_OK(processor->Run("SELECT h, r, v FROM t WHERE h = 1;", params));
728
0
      std::shared_ptr<QLRowBlock> row_block = processor->row_block();
729
0
      CHECK_EQ(row_block->row_count(), kPageSize);
730
0
      for (int j = 0; j < kPageSize; j++) {
731
0
        const QLRow& row = row_block->row(j);
732
0
        i++;
733
0
        CHECK_EQ(row.column(0).int32_value(), 1);
734
0
        CHECK_EQ(row.column(1).int32_value(), i);
735
0
        CHECK_EQ(row.column(2).int32_value(), 100 + i);
736
0
      }
737
0
      page_count++;
738
0
      if (processor->rows_result()->paging_state().empty()) {
739
0
        break;
740
0
      }
741
0
      CHECK_OK(params.SetPagingState(processor->rows_result()->paging_state()));
742
0
    } while (true);
743
0
    CHECK_EQ(page_count, kNumRows / kPageSize);
744
0
  }
745
746
  // Read rows with a LIMIT. Verify rows and that they are read in the number of pages expected.
747
0
  {
748
0
    StatementParameters params;
749
0
    static constexpr int kLimit = 53;
750
0
    static constexpr int kPageSize = 5;
751
0
    params.set_page_size(kPageSize);
752
0
    int page_count = 0;
753
0
    int i = 0;
754
0
    string select_stmt = Substitute("SELECT h, r, v FROM t WHERE h = 1 LIMIT $0;", kLimit);
755
0
    do {
756
0
      CHECK_OK(processor->Run(select_stmt, params));
757
0
      std::shared_ptr<QLRowBlock> row_block = processor->row_block();
758
0
      for (size_t j = 0; j < row_block->row_count(); j++) {
759
0
        const QLRow& row = row_block->row(j);
760
0
        i++;
761
0
        CHECK_EQ(row.column(0).int32_value(), 1);
762
0
        CHECK_EQ(row.column(1).int32_value(), i);
763
0
        CHECK_EQ(row.column(2).int32_value(), 100 + i);
764
0
      }
765
0
      page_count++;
766
0
      if (processor->rows_result()->paging_state().empty()) {
767
0
        break;
768
0
      }
769
0
      CHECK_EQ(row_block->row_count(), kPageSize);
770
0
      CHECK_OK(params.SetPagingState(processor->rows_result()->paging_state()));
771
0
    } while (true);
772
0
    CHECK_EQ(i, kLimit);
773
0
    CHECK_EQ(page_count, static_cast<int>(ceil(static_cast<double>(kLimit) /
774
0
                                               static_cast<double>(kPageSize))));
775
0
  }
776
777
  // Insert anther 100 rows of different hash keys into the table.
778
0
  {
779
0
    for (int i = 1; i <= kNumRows; i++) {
780
      // INSERT: Valid statement with column list.
781
0
      string stmt = Substitute("INSERT INTO t (h, r, v) VALUES ($0, $1, $2);", i, 100 + i, 200 + i);
782
0
      CHECK_VALID_STMT(stmt);
783
0
    }
784
0
    LOG(INFO) << kNumRows << " rows inserted";
785
0
  }
786
787
  // Test full-table query without a hash key.
788
789
  // Read all rows. Verify rows and that they are read in the number of pages expected.
790
0
  {
791
0
    StatementParameters params;
792
0
    int kPageSize = 5;
793
0
    params.set_page_size(kPageSize);
794
0
    int page_count = 0;
795
0
    int row_count = 0;
796
0
    int sum = 0;
797
0
    do {
798
0
      CHECK_OK(processor->Run("SELECT h, r, v FROM t WHERE r > 100;", params));
799
0
      std::shared_ptr<QLRowBlock> row_block = processor->row_block();
800
0
      for (size_t j = 0; j < row_block->row_count(); j++) {
801
0
        const QLRow& row = row_block->row(j);
802
0
        CHECK_EQ(row.column(0).int32_value() + 100, row.column(1).int32_value());
803
0
        sum += row.column(0).int32_value();
804
0
        row_count++;
805
0
      }
806
0
      page_count++;
807
0
      if (processor->rows_result()->paging_state().empty()) {
808
0
        break;
809
0
      }
810
0
      CHECK_OK(params.SetPagingState(processor->rows_result()->paging_state()));
811
0
    } while (true);
812
0
    CHECK_EQ(row_count, kNumRows);
813
    // Page count should be at least "kNumRows / kPageSize". Can be more because some pages may not
814
    // be fully filled depending on the hash key distribution.
815
0
    CHECK_GE(page_count, kNumRows / kPageSize);
816
0
    CHECK_EQ(sum, (1 + kNumRows) * kNumRows / 2);
817
0
  }
818
819
  // Read rows with a LIMIT. Verify rows and that they are read in the number of pages expected.
820
0
  {
821
0
    StatementParameters params;
822
0
    static constexpr int kLimit = 53;
823
0
    static constexpr int kPageSize = 5;
824
0
    params.set_page_size(kPageSize);
825
0
    int page_count = 0;
826
0
    int row_count = 0;
827
0
    int sum = 0;
828
0
    string select_stmt = Substitute("SELECT h, r, v FROM t WHERE r > 100 LIMIT $0;", kLimit);
829
0
    do {
830
0
      CHECK_OK(processor->Run(select_stmt, params));
831
0
      std::shared_ptr<QLRowBlock> row_block = processor->row_block();
832
0
      for (size_t j = 0; j < row_block->row_count(); j++) {
833
0
        const QLRow& row = row_block->row(j);
834
0
        CHECK_EQ(row.column(0).int32_value() + 100, row.column(1).int32_value());
835
0
        sum += row.column(0).int32_value();
836
0
        row_count++;
837
0
      }
838
0
      page_count++;
839
0
      if (processor->rows_result()->paging_state().empty()) {
840
0
        break;
841
0
      }
842
0
      CHECK_OK(params.SetPagingState(processor->rows_result()->paging_state()));
843
0
    } while (true);
844
0
    CHECK_EQ(row_count, kLimit);
845
    // Page count should be at least "kLimit / kPageSize". Can be more because some pages may not
846
    // be fully filled depending on the hash key distribution. Same for sum which should be at
847
    // least the sum of the lowest consecutive kLimit number of "h" values. Can be more.
848
0
    CHECK_GE(page_count, static_cast<int>(ceil(static_cast<double>(kLimit) /
849
0
                                               static_cast<double>(kPageSize))));
850
0
    CHECK_GE(sum, (1 + kLimit) * kLimit / 2);
851
0
  }
852
853
  // Test queries with IN condition on hash key.
854
  // Verify rows and that they are read in the number of pages expected.
855
0
  {
856
0
    string select_stmt = "SELECT h, r, v FROM t WHERE h IN (1, 12, 23, 34, 45) AND r > 98;";
857
0
    VerifyPaginationSelect(processor, select_stmt, 2,
858
0
        "{ { int32:1, int32:99, int32:199 }, { int32:1, int32:100, int32:200 } }"
859
0
        "{ { int32:1, int32:101, int32:201 }, { int32:12, int32:112, int32:212 } }"
860
0
        "{ { int32:23, int32:123, int32:223 }, { int32:34, int32:134, int32:234 } }"
861
0
        "{ { int32:45, int32:145, int32:245 } }");
862
0
  }
863
864
  // Read rows with a LIMIT. Verify rows and that they are read in the number of pages expected.
865
0
  {
866
0
    string select_stmt = "SELECT h, r, v FROM t WHERE h IN (1, 12, 23, 34, 45) AND r > 98 LIMIT 5;";
867
0
    VerifyPaginationSelect(processor, select_stmt, 2,
868
0
        "{ { int32:1, int32:99, int32:199 }, { int32:1, int32:100, int32:200 } }"
869
0
            "{ { int32:1, int32:101, int32:201 }, { int32:12, int32:112, int32:212 } }"
870
0
            "{ { int32:23, int32:123, int32:223 } }");
871
872
0
    select_stmt = "SELECT h, r, v FROM t WHERE h IN (1, 12, 23, 34, 45) AND r > 98 LIMIT 2;";
873
0
    VerifyPaginationSelect(processor, select_stmt, 3,
874
0
        "{ { int32:1, int32:99, int32:199 }, { int32:1, int32:100, int32:200 } }");
875
0
  }
876
0
}
877
878
template <class T>
879
void RunPaginationWithDescTest(
880
    TestQLProcessor *processor, const char* type, const std::vector<T>& values,
881
0
    std::vector<QLRow>* rows) {
882
  /* Creating the table. */
883
0
  string create_stmt = Substitute("CREATE TABLE t_$0 (h int, r1 $1, r2 $2, v int, "
884
0
      "primary key((h), r1, r2)) WITH CLUSTERING ORDER BY (r1 DESC, r2 ASC);", type, type, type);
885
0
  CHECK_VALID_STMT(create_stmt);
886
887
  /* Inserting the values. */
888
0
  for (auto& value : values) {
889
0
    string stmt = Substitute("INSERT INTO t_$0 (h, r1, r2, v) VALUES (1, $1, $2, $3);",
890
0
        type, value, value, 0);
891
0
    CHECK_VALID_STMT(stmt);
892
0
  }
893
  /* Seting up low page size for reading to test paging. */
894
0
  StatementParameters params;
895
0
  int kPageSize = 5;
896
0
  params.set_page_size(kPageSize);
897
  /* Setting up range query, will include all values except minimum and maximum */
898
0
  auto min_val = values.front();
899
0
  auto max_val = values.back();
900
0
  int page_count = 0;
901
0
  string select_stmt = Substitute("SELECT h, r1, r2, v FROM t_$0 WHERE h = 1 AND "
902
0
    "r1 > $1 AND r2 > $2 AND r1 < $3 AND r2 < $4;", type, min_val, min_val, max_val, max_val );
903
  /* Reading rows, loading the rows vector to be checked later for each case */
904
0
  do {
905
0
    CHECK_OK(processor->Run(select_stmt, params));
906
0
    std::shared_ptr<QLRowBlock> row_block = processor->row_block();
907
0
    for (size_t j = 0; j < row_block->row_count(); j++) {
908
0
      const QLRow& row = row_block->row(j);
909
0
      rows->push_back(row);
910
0
    }
911
0
    page_count++;
912
0
    if (processor->rows_result()->paging_state().empty()) {
913
0
      break;
914
0
    }
915
0
    CHECK_OK(params.SetPagingState(processor->rows_result()->paging_state()));
916
0
  } while (true);
917
  /* Page count should be at least "<nrRowsRead> / kPageSize". */
918
  /* Can be more since some pages may not be fully filled depending on hash key distribution. */
919
0
  CHECK_GE(page_count, (values.size() - 2) / kPageSize);
920
0
}
Unexecuted instantiation: _ZN2yb2ql25RunPaginationWithDescTestIiEEvPNS0_15TestQLProcessorEPKcRKNSt3__16vectorIT_NS6_9allocatorIS8_EEEEPNS7_INS_5QLRowENS9_ISE_EEEE
Unexecuted instantiation: _ZN2yb2ql25RunPaginationWithDescTestINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEvPNS0_15TestQLProcessorEPKcRKNS2_6vectorIT_NS6_ISE_EEEEPNSD_INS_5QLRowENS6_ISJ_EEEE
Unexecuted instantiation: _ZN2yb2ql25RunPaginationWithDescTestIfEEvPNS0_15TestQLProcessorEPKcRKNSt3__16vectorIT_NS6_9allocatorIS8_EEEEPNS7_INS_5QLRowENS9_ISE_EEEE
Unexecuted instantiation: _ZN2yb2ql25RunPaginationWithDescTestIdEEvPNS0_15TestQLProcessorEPKcRKNSt3__16vectorIT_NS6_9allocatorIS8_EEEEPNS7_INS_5QLRowENS9_ISE_EEEE
921
922
0
TEST_F(TestQLQuery, TestPaginationWithDescSort) {
923
924
  // Init the simulated cluster.
925
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
926
927
  // Get a processor.
928
0
  TestQLProcessor *processor = GetQLProcessor();
929
930
0
  LOG(INFO) << "Running paging state test.";
931
932
  //------------------------------------------------------------------------------------------------
933
  // Testing integer types.
934
  //------------------------------------------------------------------------------------------------
935
0
  {
936
0
    std::vector<int> values;
937
0
    for (int i = 1; i <= 100; i++) {
938
0
      values.push_back(i);
939
0
    }
940
0
    std::vector<QLRow> rows;
941
0
    auto rows_ptr = &rows;
942
0
    RunPaginationWithDescTest(processor, "int", values, rows_ptr);
943
    // Checking rows values -- expecting results in descending order except for min and max values.
944
0
    CHECK_EQ(rows.size(), values.size() - 2);
945
    // Results should start from second-largest value.
946
0
    size_t curr_row_no = values.size() - 2;
947
0
    for (auto& row : rows) {
948
0
      CHECK_EQ(row.column(0).int32_value(), 1);
949
      // Expecting results in descending order.
950
0
      CHECK_EQ(row.column(1).int32_value(), values[curr_row_no]);
951
0
      CHECK_EQ(row.column(2).int32_value(), values[curr_row_no]);
952
0
      CHECK_EQ(row.column(3).int32_value(), 0);
953
0
      curr_row_no--;
954
0
    }
955
0
  }
956
957
  //------------------------------------------------------------------------------------------------
958
  // Testing timestamp type.
959
  //------------------------------------------------------------------------------------------------
960
0
  {
961
0
    std::vector<int> values;
962
0
    for (int i = 1; i <= 100; i++) {
963
0
      values.push_back(i);
964
0
    }
965
0
    std::vector<QLRow> rows;
966
0
    auto rows_ptr = &rows;
967
0
    RunPaginationWithDescTest(processor, "timestamp", values, rows_ptr);
968
    // Checking rows values -- expecting results in descending order except for min and max values.
969
0
    CHECK_EQ(rows.size(), values.size() - 2);
970
    // Results should start from second-largest value.
971
0
    size_t curr_row_no = values.size() - 2;
972
0
    int kMicrosPerMilli = 1000;
973
974
0
    for (auto& row : rows) {
975
0
      CHECK_EQ(row.column(0).int32_value(), 1);
976
      // Expecting results in descending order.
977
0
      CHECK_EQ(row.column(1).timestamp_value().ToInt64(), values[curr_row_no] * kMicrosPerMilli);
978
0
      CHECK_EQ(row.column(2).timestamp_value().ToInt64(), values[curr_row_no] * kMicrosPerMilli);
979
0
      CHECK_EQ(row.column(3).int32_value(), 0);
980
0
      curr_row_no--;
981
0
    }
982
0
  }
983
984
  //------------------------------------------------------------------------------------------------
985
  // Testing inet type.
986
  //------------------------------------------------------------------------------------------------
987
0
  {
988
0
    std::vector<string> values;
989
0
    std::vector<string> input_values;
990
    // Insert 100 rows of the same hash key into the table.
991
0
    for (int i = 1; i <= 100; i++) {
992
0
      string value = "127.0.0." + std::to_string(i);
993
0
      values.push_back(value);
994
0
      input_values.push_back("'" + value + "'");
995
0
    }
996
0
    std::vector<QLRow> rows;
997
0
    auto rows_ptr = &rows;
998
0
    RunPaginationWithDescTest(processor, "inet", input_values, rows_ptr);
999
    // Checking rows values -- expecting results in descending order except for min and max values.
1000
0
    CHECK_EQ(rows.size(), values.size() - 2);
1001
    // Results should start from second-largest value.
1002
0
    size_t curr_row_no = values.size() - 2;
1003
0
    for (auto& row : rows) {
1004
0
      CHECK_EQ(row.column(0).int32_value(), 1);
1005
      // Expecting results in descending order.
1006
0
      CHECK_EQ(row.column(1).inetaddress_value().ToString(), values[curr_row_no]);
1007
0
      CHECK_EQ(row.column(2).inetaddress_value().ToString(), values[curr_row_no]);
1008
0
      CHECK_EQ(row.column(3).int32_value(), 0);
1009
0
      curr_row_no--;
1010
0
    }
1011
0
  }
1012
1013
  //------------------------------------------------------------------------------------------------
1014
  // Testing uuid types.
1015
  //------------------------------------------------------------------------------------------------
1016
0
  {
1017
0
    std::vector<string> values;
1018
    // Uuid prefix value -- missing last two digits.
1019
0
    string uuid_prefix = "123e4567-e89b-02d3-a456-4266554400";
1020
    // Insert 90 rows (two digit numbers) of the same hash key into the table.
1021
0
    for (int i = 10; i < 100; i++) {
1022
0
      values.push_back(uuid_prefix + std::to_string(i));
1023
0
    }
1024
0
    std::vector<QLRow> rows;
1025
0
    auto rows_ptr = &rows;
1026
0
    RunPaginationWithDescTest(processor, "uuid", values, rows_ptr);
1027
    // Checking rows values -- expecting results in descending order except for min and max values.
1028
0
    CHECK_EQ(rows.size(), values.size() - 2);
1029
    // Results should start from second-largest value.
1030
0
    size_t curr_row_no = values.size() - 2;
1031
0
    for (auto &row : rows) {
1032
0
      CHECK_EQ(row.column(0).int32_value(), 1);
1033
      // Expecting results in descending order.
1034
0
      CHECK_EQ(row.column(1).uuid_value().ToString(), values[curr_row_no]);
1035
0
      CHECK_EQ(row.column(2).uuid_value().ToString(), values[curr_row_no]);
1036
0
      CHECK_EQ(row.column(3).int32_value(), 0);
1037
0
      curr_row_no--;
1038
0
    }
1039
0
  }
1040
1041
  //------------------------------------------------------------------------------------------------
1042
  // Testing decimal type.
1043
  //------------------------------------------------------------------------------------------------
1044
0
  {
1045
0
    std::vector<string> values;
1046
    // Insert 100 rows of the same hash key into the table.
1047
0
    for (int i = 10; i <= 100; i++) {
1048
0
      values.push_back(std::to_string(i) + ".25");
1049
0
    }
1050
0
    std::vector<QLRow> rows;
1051
0
    auto rows_ptr = &rows;
1052
0
    RunPaginationWithDescTest(processor, "decimal", values, rows_ptr);
1053
    // Checking rows values -- expecting results in descending order except for min and max values.
1054
0
    CHECK_EQ(rows.size(), values.size() - 2);
1055
    // Results should start from second-largest value.
1056
0
    size_t curr_row_no = values.size() - 2;
1057
0
    for (auto &row : rows) {
1058
0
      CHECK_EQ(row.column(0).int32_value(), 1);
1059
      // Expecting results in descending order.
1060
0
      util::Decimal dec;
1061
0
      CHECK_OK(dec.DecodeFromComparable(row.column(1).decimal_value()));
1062
0
      CHECK_EQ(dec.ToString(), values[curr_row_no]);
1063
0
      CHECK_OK(dec.DecodeFromComparable(row.column(2).decimal_value()));
1064
0
      CHECK_EQ(dec.ToString(), values[curr_row_no]);
1065
0
      CHECK_EQ(row.column(3).int32_value(), 0);
1066
0
      curr_row_no--;
1067
0
    }
1068
0
  }
1069
1070
  //------------------------------------------------------------------------------------------------
1071
  // Testing float type.
1072
  //------------------------------------------------------------------------------------------------
1073
0
  {
1074
0
    std::vector<float> values;
1075
    // Insert 100 rows of the same hash key into the table.
1076
0
    for (int i = 10; i <= 100; i++) {
1077
0
      values.push_back(i + .25);
1078
0
    }
1079
0
    std::vector<QLRow> rows;
1080
0
    auto rows_ptr = &rows;
1081
0
    RunPaginationWithDescTest(processor, "float", values, rows_ptr);
1082
    // Checking rows values -- expecting results in descending order except for min and max values.
1083
0
    CHECK_EQ(rows.size(), values.size() - 2);
1084
    // Results should start from second-largest value.
1085
0
    size_t curr_row_no = values.size() - 2;
1086
0
    for (auto &row : rows) {
1087
0
      CHECK_EQ(row.column(0).int32_value(), 1);
1088
      // Expecting results in descending order.
1089
0
      CHECK_EQ(row.column(1).float_value(), values[curr_row_no]);
1090
0
      CHECK_EQ(row.column(2).float_value(), values[curr_row_no]);
1091
0
      CHECK_EQ(row.column(3).int32_value(), 0);
1092
0
      curr_row_no--;
1093
0
    }
1094
0
  }
1095
1096
  //------------------------------------------------------------------------------------------------
1097
  // Testing double type.
1098
  //------------------------------------------------------------------------------------------------
1099
0
  {
1100
0
    std::vector<double> values;
1101
    // Insert 100 rows of the same hash key into the table.
1102
0
    for (int i = 10; i <= 100; i++) {
1103
0
      values.push_back(i + .25);
1104
0
    }
1105
0
    std::vector<QLRow> rows;
1106
0
    auto rows_ptr = &rows;
1107
0
    RunPaginationWithDescTest(processor, "double", values, rows_ptr);
1108
    // Checking rows values -- expecting results in descending order except for min and max values.
1109
0
    CHECK_EQ(rows.size(), values.size() - 2);
1110
    // Results should start from second-largest value.
1111
0
    size_t curr_row_no = values.size() - 2;
1112
0
    for (auto &row : rows) {
1113
0
      CHECK_EQ(row.column(0).int32_value(), 1);
1114
      // Expecting results in descending order.
1115
0
      CHECK_EQ(row.column(1).double_value(), values[curr_row_no]);
1116
0
      CHECK_EQ(row.column(2).double_value(), values[curr_row_no]);
1117
0
      CHECK_EQ(row.column(3).int32_value(), 0);
1118
0
      curr_row_no--;
1119
0
    }
1120
0
  }
1121
1122
  //------------------------------------------------------------------------------------------------
1123
  // Testing string types.
1124
  //------------------------------------------------------------------------------------------------
1125
0
  {
1126
0
    std::vector<string> values;
1127
0
    std::vector<string> input_values;
1128
    // Insert 90 rows (two digit numbers) of the same hash key into the table.
1129
0
    for (int i = 10; i < 100; i++) {
1130
0
      values.push_back(std::to_string(i));
1131
0
      input_values.push_back("'" + std::to_string(i) + "'");
1132
0
    }
1133
0
    std::vector<QLRow> rows;
1134
0
    auto rows_ptr = &rows;
1135
0
    RunPaginationWithDescTest(processor, "varchar", input_values, rows_ptr);
1136
    // Checking rows values -- expecting results in descending order except for min and max values.
1137
0
    CHECK_EQ(rows.size(), values.size() - 2);
1138
    // Results should start from second-largest value.
1139
0
    size_t curr_row_no = values.size() - 2;
1140
0
    for (auto &row : rows) {
1141
0
      CHECK_EQ(row.column(0).int32_value(), 1);
1142
      // Expecting results in descending order.
1143
0
      CHECK_EQ(row.column(1).string_value(), values[curr_row_no]);
1144
0
      CHECK_EQ(row.column(2).string_value(), values[curr_row_no]);
1145
0
      CHECK_EQ(row.column(3).int32_value(), 0);
1146
0
      curr_row_no--;
1147
0
    }
1148
0
  }
1149
0
}
1150
1151
0
TEST_F(TestQLQuery, TestQLQueryPartialHash) {
1152
  // Init the simulated cluster.
1153
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1154
1155
  // Get a processor.
1156
0
  TestQLProcessor *processor = GetQLProcessor();
1157
1158
0
  LOG(INFO) << "Running partial hash test.";
1159
  // Create the table 1.
1160
0
  const char *create_stmt =
1161
0
    "CREATE TABLE test_table(h1 int, h2 varchar, "
1162
0
                            "h3 bigint, h4 varchar, "
1163
0
                            "r1 int, r2 varchar, "
1164
0
                            "v1 int, v2 varchar, "
1165
0
                            "primary key((h1, h2, h3, h4), r1, r2));";
1166
0
  CHECK_VALID_STMT(create_stmt);
1167
1168
  // Test NOTFOUND. Select from empty table.
1169
0
  CHECK_VALID_STMT("SELECT * FROM test_table");
1170
0
  std::shared_ptr<QLRowBlock> empty_row_block = processor->row_block();
1171
0
  CHECK_EQ(empty_row_block->row_count(), 0);
1172
0
  CHECK_VALID_STMT("SELECT * FROM test_table WHERE h1 = 0 AND h2 = ''");
1173
0
  empty_row_block = processor->row_block();
1174
0
  CHECK_EQ(empty_row_block->row_count(), 0);
1175
1176
  // Insert 100 rows into the table.
1177
0
  static const int kNumRows = 100;
1178
0
  for (int idx = 0; idx < kNumRows; idx++) {
1179
    // INSERT: Valid statement with column list.
1180
0
    string stmt = Substitute("INSERT INTO test_table(h1, h2, h3, h4, r1, r2, v1, v2) "
1181
0
                             "VALUES($0, 'h$1', $2, 'h$3', $4, 'r$5', $6, 'v$7');",
1182
0
                             idx, idx, idx+100, idx+100, idx+1000, idx+1000, idx+10000, idx+10000);
1183
0
    CHECK_VALID_STMT(stmt);
1184
0
  }
1185
0
  LOG(INFO) << kNumRows << " rows inserted";
1186
1187
  //------------------------------------------------------------------------------------------------
1188
  // Check invalid case for using other operators for hash keys.
1189
0
  CHECK_INVALID_STMT("SELECT h1, h2, h3, h4, r1, r2, v1, v2 FROM test_table "
1190
0
                     "  WHERE h1 < 7;");
1191
0
  CHECK_INVALID_STMT("SELECT h1, h2, h3, h4, r1, r2, v1, v2 FROM test_table "
1192
0
                     "  WHERE h1 > 7 AND h2 > 'h7';");
1193
1194
  //------------------------------------------------------------------------------------------------
1195
  // Test partial hash keys and results.
1196
0
  LOG(INFO) << "Testing 3 out of 4 keys";
1197
0
  CHECK_VALID_STMT("SELECT h1, h2, h3, h4, r1, r2, v1, v2 FROM test_table "
1198
0
                   "  WHERE h1 = 7 AND h2 = 'h7' AND h3 = 107;");
1199
0
  std::shared_ptr<QLRowBlock> row_block = processor->row_block();
1200
0
  CHECK_EQ(row_block->row_count(), 1);
1201
0
  const QLRow& no_hash_row1 = row_block->row(0);
1202
0
  CHECK_EQ(no_hash_row1.column(0).int32_value(), 7);
1203
0
  CHECK_EQ(no_hash_row1.column(1).string_value(), "h7");
1204
0
  CHECK_EQ(no_hash_row1.column(2).int64_value(), 107);
1205
0
  CHECK_EQ(no_hash_row1.column(3).string_value(), "h107");
1206
0
  CHECK_EQ(no_hash_row1.column(4).int32_value(), 1007);
1207
0
  CHECK_EQ(no_hash_row1.column(5).string_value(), "r1007");
1208
0
  CHECK_EQ(no_hash_row1.column(6).int32_value(), 10007);
1209
0
  CHECK_EQ(no_hash_row1.column(7).string_value(), "v10007");
1210
1211
0
  LOG(INFO) << "Testing 2 out of 4 keys";
1212
0
  CHECK_VALID_STMT("SELECT h1, h2, h3, h4, r1, r2, v1, v2 FROM test_table "
1213
0
                   "  WHERE h1 = 7 AND h2 = 'h7';");
1214
0
  row_block = processor->row_block();
1215
0
  CHECK_EQ(row_block->row_count(), 1);
1216
0
  const QLRow& no_hash_row2 = row_block->row(0);
1217
0
  CHECK_EQ(no_hash_row2.column(0).int32_value(), 7);
1218
0
  CHECK_EQ(no_hash_row2.column(1).string_value(), "h7");
1219
0
  CHECK_EQ(no_hash_row2.column(2).int64_value(), 107);
1220
0
  CHECK_EQ(no_hash_row2.column(3).string_value(), "h107");
1221
0
  CHECK_EQ(no_hash_row2.column(4).int32_value(), 1007);
1222
0
  CHECK_EQ(no_hash_row2.column(5).string_value(), "r1007");
1223
0
  CHECK_EQ(no_hash_row2.column(6).int32_value(), 10007);
1224
0
  CHECK_EQ(no_hash_row2.column(7).string_value(), "v10007");
1225
1226
0
  LOG(INFO) << "Testing 1 out of 4 keys";
1227
0
  CHECK_VALID_STMT("SELECT h1, h2, h3, h4, r1, r2, v1, v2 FROM test_table "
1228
0
                   "  WHERE h1 = 7;");
1229
0
  row_block = processor->row_block();
1230
0
  CHECK_EQ(row_block->row_count(), 1);
1231
0
  const QLRow& no_hash_row3 = row_block->row(0);
1232
0
  CHECK_EQ(no_hash_row3.column(0).int32_value(), 7);
1233
0
  CHECK_EQ(no_hash_row3.column(1).string_value(), "h7");
1234
0
  CHECK_EQ(no_hash_row3.column(2).int64_value(), 107);
1235
0
  CHECK_EQ(no_hash_row3.column(3).string_value(), "h107");
1236
0
  CHECK_EQ(no_hash_row3.column(4).int32_value(), 1007);
1237
0
  CHECK_EQ(no_hash_row3.column(5).string_value(), "r1007");
1238
0
  CHECK_EQ(no_hash_row3.column(6).int32_value(), 10007);
1239
0
  CHECK_EQ(no_hash_row3.column(7).string_value(), "v10007");
1240
1241
  // Test simple query with only range key and check result.
1242
0
  LOG(INFO) << "Testing 0 out of 4 keys";
1243
0
  CHECK_VALID_STMT("SELECT h1, h2, h3, h4, r1, r2, v1, v2 FROM test_table "
1244
0
                   "WHERE r1 = 1007;");
1245
0
  row_block = processor->row_block();
1246
0
  CHECK_EQ(row_block->row_count(), 1);
1247
0
  const QLRow& no_hash_row4 = row_block->row(0);
1248
0
  CHECK_EQ(no_hash_row4.column(0).int32_value(), 7);
1249
0
  CHECK_EQ(no_hash_row4.column(1).string_value(), "h7");
1250
0
  CHECK_EQ(no_hash_row4.column(2).int64_value(), 107);
1251
0
  CHECK_EQ(no_hash_row4.column(3).string_value(), "h107");
1252
0
  CHECK_EQ(no_hash_row4.column(4).int32_value(), 1007);
1253
0
  CHECK_EQ(no_hash_row4.column(5).string_value(), "r1007");
1254
0
  CHECK_EQ(no_hash_row4.column(6).int32_value(), 10007);
1255
0
  CHECK_EQ(no_hash_row4.column(7).string_value(), "v10007");
1256
1257
0
  LOG(INFO) << "Testing 1 of every key each.";
1258
  // Test simple query with partial hash key and check result.
1259
0
  CHECK_VALID_STMT("SELECT h1, h2, h3, h4, r1, r2, v1, v2 FROM test_table "
1260
0
                   "WHERE h1 = 7;");
1261
0
  row_block = processor->row_block();
1262
0
  CHECK_EQ(row_block->row_count(), 1);
1263
0
  const QLRow& h1_hash_row = row_block->row(0);
1264
0
  CHECK_EQ(h1_hash_row.column(0).int32_value(), 7);
1265
0
  CHECK_EQ(h1_hash_row.column(1).string_value(), "h7");
1266
0
  CHECK_EQ(h1_hash_row.column(2).int64_value(), 107);
1267
0
  CHECK_EQ(h1_hash_row.column(3).string_value(), "h107");
1268
0
  CHECK_EQ(h1_hash_row.column(4).int32_value(), 1007);
1269
0
  CHECK_EQ(h1_hash_row.column(5).string_value(), "r1007");
1270
0
  CHECK_EQ(h1_hash_row.column(6).int32_value(), 10007);
1271
0
  CHECK_EQ(h1_hash_row.column(7).string_value(), "v10007");
1272
1273
0
  CHECK_VALID_STMT("SELECT h1, h2, h3, h4, r1, r2, v1, v2 FROM test_table "
1274
0
                   "  WHERE h2 = 'h7';");
1275
0
  row_block = processor->row_block();
1276
0
  CHECK_EQ(row_block->row_count(), 1);
1277
0
  const QLRow& h2_hash_row = row_block->row(0);
1278
0
  CHECK_EQ(h2_hash_row.column(0).int32_value(), 7);
1279
0
  CHECK_EQ(h2_hash_row.column(1).string_value(), "h7");
1280
0
  CHECK_EQ(h2_hash_row.column(2).int64_value(), 107);
1281
0
  CHECK_EQ(h2_hash_row.column(3).string_value(), "h107");
1282
0
  CHECK_EQ(h2_hash_row.column(4).int32_value(), 1007);
1283
0
  CHECK_EQ(h2_hash_row.column(5).string_value(), "r1007");
1284
0
  CHECK_EQ(h2_hash_row.column(6).int32_value(), 10007);
1285
0
  CHECK_EQ(h2_hash_row.column(7).string_value(), "v10007");
1286
1287
0
  CHECK_VALID_STMT("SELECT h1, h2, h3, h4, r1, r2, v1, v2 FROM test_table "
1288
0
                   "  WHERE h3 = 107;");
1289
0
  row_block = processor->row_block();
1290
0
  CHECK_EQ(row_block->row_count(), 1);
1291
0
  const QLRow& h3_hash_row = row_block->row(0);
1292
0
  CHECK_EQ(h3_hash_row.column(0).int32_value(), 7);
1293
0
  CHECK_EQ(h3_hash_row.column(1).string_value(), "h7");
1294
0
  CHECK_EQ(h3_hash_row.column(2).int64_value(), 107);
1295
0
  CHECK_EQ(h3_hash_row.column(3).string_value(), "h107");
1296
0
  CHECK_EQ(h3_hash_row.column(4).int32_value(), 1007);
1297
0
  CHECK_EQ(h3_hash_row.column(5).string_value(), "r1007");
1298
0
  CHECK_EQ(h3_hash_row.column(6).int32_value(), 10007);
1299
0
  CHECK_EQ(h3_hash_row.column(7).string_value(), "v10007");
1300
1301
0
  CHECK_VALID_STMT("SELECT h1, h2, h3, h4, r1, r2, v1, v2 FROM test_table "
1302
0
                   "  WHERE h4 = 'h107';");
1303
0
  row_block = processor->row_block();
1304
0
  CHECK_EQ(row_block->row_count(), 1);
1305
0
  const QLRow& h4_hash_row = row_block->row(0);
1306
0
  CHECK_EQ(h4_hash_row.column(0).int32_value(), 7);
1307
0
  CHECK_EQ(h4_hash_row.column(1).string_value(), "h7");
1308
0
  CHECK_EQ(h4_hash_row.column(2).int64_value(), 107);
1309
0
  CHECK_EQ(h4_hash_row.column(3).string_value(), "h107");
1310
0
  CHECK_EQ(h4_hash_row.column(4).int32_value(), 1007);
1311
0
  CHECK_EQ(h4_hash_row.column(5).string_value(), "r1007");
1312
0
  CHECK_EQ(h4_hash_row.column(6).int32_value(), 10007);
1313
0
  CHECK_EQ(h4_hash_row.column(7).string_value(), "v10007");
1314
1315
1316
  // Test multi row query for the whole table.
1317
  // Insert 20 rows of the same hash key into the table.
1318
0
  static const int kHashNumRows = 20;
1319
0
  static const int kNumFilterRows = 10;
1320
0
  int32 h1_shared = 1111111;
1321
0
  const string h2_shared = "h2_shared_key";
1322
0
  int64 h3_shared = 111111111;
1323
0
  const string h4_shared = "h4_shared_key";
1324
0
  for (int idx = 0; idx < kHashNumRows; idx++) {
1325
    // INSERT: Valid statement with column list.
1326
0
    string stmt = Substitute("INSERT INTO test_table(h1, h2, h3, h4, r1, r2, v1, v2) "
1327
0
                             "VALUES($0, '$1', $2, '$3', $4, 'r$5', $6, 'v$7');",
1328
0
                             h1_shared, h2_shared, h3_shared, h4_shared,
1329
0
                             idx+100, idx+100, idx+1000, idx+1000);
1330
0
    CHECK_VALID_STMT(stmt);
1331
0
  }
1332
1333
  // Select select rows and check the values.
1334
  // This test scans multiple tservers. Query result tested in java.
1335
  // TODO: Make QL understand paging states and continue.
1336
0
  LOG(INFO) << "Testing filter with partial hash keys.";
1337
0
  const string multi_select = Substitute("SELECT h1, h2, h3, h4, r1, r2, v1, v2 FROM test_table "
1338
0
                                         "WHERE h1 = $0 AND h2 = '$1' AND r1 > $2;",
1339
0
                                         h1_shared, h2_shared, kNumFilterRows + 100);
1340
0
  CHECK_VALID_STMT(multi_select);
1341
1342
0
  const string drop_stmt = "DROP TABLE test_table;";
1343
0
  EXEC_VALID_STMT(drop_stmt);
1344
0
}
1345
1346
0
TEST_F(TestQLQuery, TestInsertWithTTL) {
1347
  // Init the simulated cluster.
1348
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1349
1350
  // Get a processor.
1351
0
  TestQLProcessor *processor = GetQLProcessor();
1352
1353
0
  CreateTableAndInsertRow(processor);
1354
1355
  // Sleep for 1.1 seconds and verify ttl has expired.
1356
0
  std::this_thread::sleep_for(std::chrono::milliseconds(1100));
1357
1358
0
  VerifyExpiry(processor);
1359
0
}
1360
1361
TEST_F(TestQLQuery, TestUpdateWithTTL) {
1362
  // Init the simulated cluster.
1363
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1364
1365
  // Get a processor.
1366
  TestQLProcessor *processor = GetQLProcessor();
1367
1368
  CreateTableAndInsertRow(processor, false);
1369
1370
  // Now update the row with a TTL.
1371
  std::string update_stmt("UPDATE test_table USING TTL 1 SET c2 = 4, c3 = 5 WHERE c1 = 1;");
1372
  Status s = processor->Run(update_stmt);
1373
  CHECK(s.ok());
1374
1375
  // Sleep for 1.1 seconds and verify ttl has expired.
1376
  std::this_thread::sleep_for(std::chrono::milliseconds(1100));
1377
1378
  // c1 = 1 should still exist.
1379
  auto row_block = ExecSelect(processor);
1380
  QLRow& row = row_block->row(0);
1381
1382
  EXPECT_EQ(1, row.column(0).int32_value());
1383
  EXPECT_TRUE(row.column(1).IsNull());
1384
  EXPECT_TRUE(row.column(2).IsNull());
1385
1386
  // Try an update by setting the primary key, which should fail since set clause can't have
1387
  // primary keys.
1388
  std::string invalid_update_stmt("UPDATE test_table USING TTL 1 SET c1 = 4 WHERE c1 = 1;");
1389
  s = processor->Run(invalid_update_stmt);
1390
  CHECK(!s.ok());
1391
}
1392
1393
// The main goal of this test is to check that the serialization/deserialization operations match
1394
// The Java tests are more comprehensive but do not test the deserialization -- since they use the
1395
// Cassandra deserializer instead
1396
TEST_F(TestQLQuery, TestCollectionTypes) {
1397
  // Init the simulated cluster.
1398
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1399
1400
  // Get a processor.
1401
  TestQLProcessor *processor = GetQLProcessor();
1402
1403
  //------------------------------------------------------------------------------------------------
1404
  // Testing Map type
1405
  //------------------------------------------------------------------------------------------------
1406
1407
  // Create table.
1408
  const char *map_create_stmt =
1409
      "CREATE TABLE map_test (id int PRIMARY KEY, v int, mp map<int, varchar>, c varchar);";
1410
  Status s = processor->Run(map_create_stmt);
1411
  CHECK(s.ok());
1412
1413
  // Insert Values
1414
  std::string map_insert_stmt("INSERT INTO map_test (id, v, mp, c) values "
1415
      "(1, 3, {21 : 'a', 22 : 'b', 23 : 'c'}, 'x');");
1416
  s = processor->Run(map_insert_stmt);
1417
  CHECK_OK(s);
1418
1419
  // Check Select
1420
  auto map_select_stmt = "SELECT * FROM map_test WHERE id = 1";
1421
  s = processor->Run(map_select_stmt);
1422
  CHECK(s.ok());
1423
  auto map_row_block = processor->row_block();
1424
  EXPECT_EQ(1, map_row_block->row_count());
1425
  QLRow& map_row = map_row_block->row(0);
1426
1427
  // check row
1428
  EXPECT_EQ(1, map_row.column(0).int32_value());
1429
  EXPECT_EQ(3, map_row.column(1).int32_value());
1430
  EXPECT_EQ("x", map_row.column(3).string_value());
1431
  // check map
1432
  EXPECT_EQ(InternalType::kMapValue, map_row.column(2).type());
1433
  QLMapValuePB map_value = map_row.column(2).map_value();
1434
  // check keys
1435
  EXPECT_EQ(3, map_value.keys_size());
1436
  EXPECT_EQ(21, map_value.keys(0).int32_value());
1437
  EXPECT_EQ(22, map_value.keys(1).int32_value());
1438
  EXPECT_EQ(23, map_value.keys(2).int32_value());
1439
  // check values
1440
  EXPECT_EQ(3, map_value.values_size());
1441
  EXPECT_EQ("a", map_value.values(0).string_value());
1442
  EXPECT_EQ("b", map_value.values(1).string_value());
1443
  EXPECT_EQ("c", map_value.values(2).string_value());
1444
1445
  //------------------------------------------------------------------------------------------------
1446
  // Testing Set type
1447
  //------------------------------------------------------------------------------------------------
1448
1449
  // Create table.
1450
  const char *set_create_stmt =
1451
      "CREATE TABLE set_test (id int PRIMARY KEY, v int, st set<int>, c varchar);";
1452
  s = processor->Run(set_create_stmt);
1453
  CHECK(s.ok());
1454
1455
  // Insert Values
1456
  std::string set_insert_stmt("INSERT INTO set_test (id, v, st, c) values "
1457
      "(1, 3, {3, 4, 1, 1, 2, 4, 2}, 'x');");
1458
  s = processor->Run(set_insert_stmt);
1459
  CHECK_OK(s);
1460
1461
  // Check Select
1462
  auto set_select_stmt = "SELECT * FROM set_test WHERE id = 1";
1463
  s = processor->Run(set_select_stmt);
1464
  CHECK(s.ok());
1465
  auto set_row_block = processor->row_block();
1466
  EXPECT_EQ(1, set_row_block->row_count());
1467
  QLRow& set_row = set_row_block->row(0);
1468
1469
  // check row
1470
  EXPECT_EQ(1, set_row.column(0).int32_value());
1471
  EXPECT_EQ(3, set_row.column(1).int32_value());
1472
  EXPECT_EQ("x", set_row.column(3).string_value());
1473
  // check set
1474
  EXPECT_EQ(InternalType::kSetValue, set_row.column(2).type());
1475
  QLSeqValuePB set_value = set_row.column(2).set_value();
1476
  // check elems
1477
  // returned set should have no duplicates
1478
  EXPECT_EQ(4, set_value.elems_size());
1479
  // set elements should be in default (ascending) order
1480
  EXPECT_EQ(1, set_value.elems(0).int32_value());
1481
  EXPECT_EQ(2, set_value.elems(1).int32_value());
1482
  EXPECT_EQ(3, set_value.elems(2).int32_value());
1483
  EXPECT_EQ(4, set_value.elems(3).int32_value());
1484
1485
  //------------------------------------------------------------------------------------------------
1486
  // Testing List type
1487
  //------------------------------------------------------------------------------------------------
1488
1489
  // Create table.
1490
  const char *list_create_stmt =
1491
      "CREATE TABLE list_test"
1492
      "  (id int PRIMARY KEY, v int, ls list<varchar>, c varchar, lb list<blob>);";
1493
  s = processor->Run(list_create_stmt);
1494
  CHECK(s.ok());
1495
1496
  // Insert Values
1497
  std::string list_insert_stmt("INSERT INTO list_test (id, v, ls, c, lb) values "
1498
      "(1, 3, ['c', 'd', 'a', 'b', 'd', 'b'], 'x', [0x01, 0X02, 0x33, 0x04]);");
1499
  s = processor->Run(list_insert_stmt);
1500
  CHECK_OK(s);
1501
1502
  // Check Select
1503
  auto list_select_stmt = "SELECT * FROM list_test WHERE id = 1";
1504
  s = processor->Run(list_select_stmt);
1505
  CHECK(s.ok());
1506
  auto list_row_block = processor->row_block();
1507
  EXPECT_EQ(1, list_row_block->row_count());
1508
  QLRow& list_row = list_row_block->row(0);
1509
1510
  // check row
1511
  EXPECT_EQ(1, list_row.column(0).int32_value());
1512
  EXPECT_EQ(3, list_row.column(1).int32_value());
1513
  EXPECT_EQ("x", list_row.column(3).string_value());
1514
  // check set
1515
  EXPECT_EQ(InternalType::kListValue, list_row.column(2).type());
1516
  EXPECT_EQ(InternalType::kListValue, list_row.column(4).type());
1517
1518
  // check elems
1519
  // lists should preserve input length (keep duplicates if any)
1520
  QLSeqValuePB list_value = list_row.column(2).list_value();
1521
  EXPECT_EQ(6, list_value.elems_size());
1522
  QLSeqValuePB blist_value = list_row.column(4).list_value();
1523
  EXPECT_EQ(4, blist_value.elems_size());
1524
  // list elements should preserve input order
1525
  EXPECT_EQ("c", list_value.elems(0).string_value());
1526
  EXPECT_EQ("d", list_value.elems(1).string_value());
1527
  EXPECT_EQ("a", list_value.elems(2).string_value());
1528
  EXPECT_EQ("b", list_value.elems(3).string_value());
1529
  EXPECT_EQ("d", list_value.elems(4).string_value());
1530
  EXPECT_EQ("b", list_value.elems(5).string_value());
1531
1532
  EXPECT_EQ("\x1", blist_value.elems(0).binary_value());
1533
  EXPECT_EQ("\x2", blist_value.elems(1).binary_value());
1534
  EXPECT_EQ("\x33", blist_value.elems(2).binary_value());
1535
  EXPECT_EQ("\x4", blist_value.elems(3).binary_value());
1536
}
1537
1538
0
TEST_F(TestQLQuery, TestSystemLocal) {
1539
  // Init the simulated cluster.
1540
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1541
1542
  // Get a processor.
1543
0
  TestQLProcessor *processor = GetQLProcessor();
1544
1545
0
  auto set_select_stmt = "SELECT * FROM system.local";
1546
0
  CHECK_OK(processor->Run(set_select_stmt));
1547
1548
  // Validate rows.
1549
0
  auto row_block = processor->row_block();
1550
0
  EXPECT_EQ(1, row_block->row_count());
1551
0
  QLRow& row = row_block->row(0);
1552
0
  EXPECT_EQ("127.0.0.3", row.column(2).inetaddress_value().ToString()); // broadcast address.
1553
0
}
1554
1555
0
TEST_F(TestQLQuery, TestSystemTablesWithRestart) {
1556
  // Init the simulated cluster.
1557
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1558
1559
  // Get a processor.
1560
0
  TestQLProcessor *processor = GetQLProcessor();
1561
1562
  // Verify system table query works.
1563
0
  ASSERT_OK(processor->Run("SELECT * FROM system.peers"));
1564
1565
  // Restart the cluster.
1566
0
  ASSERT_OK(cluster_->RestartSync());
1567
1568
  // Verify system table query still works.
1569
0
  ASSERT_OK(processor->Run("SELECT * FROM system.peers"));
1570
0
}
1571
1572
0
TEST_F(TestQLQuery, TestInvalidPeerTableEntries) {
1573
  // Init the simulated cluster and wait for tservers.
1574
0
  int num_tservers = 3;
1575
0
  ASSERT_NO_FATALS(CreateSimulatedCluster(num_tservers));
1576
0
  ASSERT_OK(cluster_->WaitForTabletServerCount(num_tservers));
1577
1578
  // Verify system peers table.
1579
0
  TestQLProcessor* processor = GetQLProcessor();
1580
0
  ASSERT_OK(processor->Run("SELECT * FROM system.peers"));
1581
0
  std::shared_ptr<QLRowBlock> row_block = processor->row_block();
1582
0
  ASSERT_EQ(num_tservers - 1, row_block->row_count()) << row_block->ToString();
1583
1584
0
  auto ts_manager = ASSERT_RESULT(cluster_->GetLeaderMiniMaster())->master()->ts_manager();
1585
0
  NodeInstancePB instance;
1586
0
  instance.set_permanent_uuid("test");
1587
0
  instance.set_instance_seqno(0);
1588
1589
  // Use an invalid hostname for registration.
1590
0
  master::TSRegistrationPB registration;
1591
0
  auto hostport_pb = registration.mutable_common()->add_private_rpc_addresses();
1592
0
  const string invalid_host = "randomhost";
1593
0
  hostport_pb->set_host(invalid_host);
1594
0
  hostport_pb->set_port(123);
1595
1596
0
  ASSERT_OK(ts_manager->RegisterTS(instance, registration, CloudInfoPB(), nullptr));
1597
1598
  // Verify the peers table and ensure the invalid host is not present.
1599
0
  ASSERT_OK(processor->Run("SELECT * FROM system.peers"));
1600
0
  row_block = processor->row_block();
1601
0
  ASSERT_EQ(num_tservers - 1, row_block->row_count()) << row_block->ToString();
1602
0
  for (const auto& row : row_block->rows()) {
1603
0
    ASSERT_NE(invalid_host, row.column(0).inetaddress_value().ToString());
1604
0
  }
1605
0
}
1606
1607
0
TEST_F(TestQLQuery, TestPagination) {
1608
  // Init the simulated cluster.
1609
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1610
1611
  // Get a processor.
1612
0
  TestQLProcessor *processor = GetQLProcessor();
1613
1614
  // Create test table.
1615
0
  CHECK_OK(processor->Run("CREATE TABLE page_test (c int PRIMARY KEY);"));
1616
1617
  // Insert 10 different hash keys. They should go to different tablets.
1618
0
  for (int i = 1; i <= 10; i++) {
1619
0
    string stmt = Substitute("INSERT INTO page_test (c) VALUES ($0);", i);
1620
0
    CHECK_OK(processor->Run(stmt));
1621
0
  }
1622
1623
  // Do full-table query. All rows should be returned in one block.
1624
0
  CHECK_VALID_STMT("SELECT * FROM page_test;");
1625
1626
0
  auto row_block = processor->row_block();
1627
0
  EXPECT_EQ(10, row_block->row_count());
1628
0
  int sum = 0;
1629
0
  for (size_t i = 0; i < row_block->row_count(); i++) {
1630
0
    sum += row_block->row(i).column(0).int32_value();
1631
0
  }
1632
0
  EXPECT_EQ(55, sum);
1633
0
}
1634
1635
0
TEST_F(TestQLQuery, TestTokenBcall) {
1636
0
  TestPartitionHash("token");
1637
0
}
1638
1639
0
TEST_F(TestQLQuery, TestPartitionHashBcall) {
1640
0
  TestPartitionHash("partition_hash");
1641
0
}
1642
1643
0
TEST_F(TestQLQuery, TestScanWithBoundsToken) {
1644
0
  TestScanWithBoundsPartitionOps("token", std::numeric_limits<int64_t>::max(),
1645
0
                                 std::numeric_limits<int64_t>::min());
1646
0
}
1647
1648
0
TEST_F(TestQLQuery, TestScanWithBoundsPartitionHash) {
1649
0
  TestScanWithBoundsPartitionOps("partition_hash", std::numeric_limits<uint16_t>::max(),
1650
0
                                 std::numeric_limits<uint16_t>::min());
1651
  // Get a processor.
1652
0
  TestQLProcessor *processor = GetQLProcessor();
1653
0
  CHECK_INVALID_STMT("SELECT * FROM scan_bounds_test WHERE partition_hash(h1, h2) > 65536");
1654
0
  CHECK_INVALID_STMT("SELECT * FROM scan_bounds_test WHERE partition_hash(h1, h2) > -1");
1655
1656
  // Test mix of partition hash and token
1657
0
  CHECK_INVALID_STMT(
1658
0
      "SELECT * FROM scan_bounds_test WHERE partition_hash(h1,h2) > 0 AND token(h1,h2) >= 0");
1659
  // Two "less-than" bounds
1660
0
  CHECK_INVALID_STMT(
1661
0
      "SELECT * FROM scan_bounds_test WHERE partition_hash(h1,h2) <= 0 AND token(h1,h2) < 0");
1662
  // Two "equal" conditions
1663
0
  CHECK_INVALID_STMT(
1664
0
      "SELECT * FROM scan_bounds_test WHERE token(h1,h2) = 0 AND partition_hash(h1,h2) = 0");
1665
  // Both "equal" and "less than" conditions
1666
0
  CHECK_INVALID_STMT(
1667
0
      "SELECT * FROM scan_bounds_test WHERE token(h1,h2) = 0 AND partition_hash(h1,h2) <= 0");
1668
  // Both "equal" and "greater than" conditions
1669
0
  CHECK_INVALID_STMT(
1670
0
      "SELECT * FROM scan_bounds_test WHERE partition_hash(h1,h2) = 0 AND token(h1,h2) >= 0");
1671
0
}
1672
1673
0
TEST_F(TestQLQuery, TestInvalidGrammar) {
1674
  // Init the simulated cluster.
1675
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1676
1677
  // Get a processor.
1678
0
  TestQLProcessor *processor = GetQLProcessor();
1679
1680
0
  CHECK_INVALID_STMT("SELECT;");
1681
0
  CHECK_INVALID_STMT("SELECT 1;");
1682
0
  CHECK_INVALID_STMT("SELECT count ;");
1683
0
  CHECK_INVALID_STMT("SELECT \n   \n;");
1684
0
  CHECK_INVALID_STMT("SELECT \n  \n from \n \n \n ;");
1685
0
  CHECK_INVALID_STMT("SELECT * \n \n \n  from \n \n ;");
1686
0
  CHECK_INVALID_STMT("SELECT * from \"long \n  multiline table  name wi\nth  spaces   \"  \n ;");
1687
0
}
1688
1689
0
TEST_F(TestQLQuery, TestDeleteColumn) {
1690
  //------------------------------------------------------------------------------------------------
1691
  // Setting up cluster
1692
  //------------------------------------------------------------------------------------------------
1693
1694
  // Init the simulated cluster.
1695
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1696
1697
0
  TestQLProcessor *processor = GetQLProcessor();
1698
1699
  // Create test table.
1700
0
  CHECK_OK(processor->Run("CREATE TABLE delete_column (h int, v1 int, v2 int,"
1701
0
                            " PRIMARY KEY(h));"));
1702
1703
0
  client::YBTableName name(YQL_DATABASE_CQL, kDefaultKeyspaceName, "delete_column");
1704
1705
0
  for (int i = 0; i < 2; i++) {
1706
0
    string stmt = Substitute("INSERT INTO delete_column (h, v1, v2) VALUES "
1707
0
                               "($0, $1, $2);", i, i, i);
1708
0
    CHECK_OK(processor->Run(stmt));
1709
0
  }
1710
1711
  // Deleting the value
1712
0
  string delete_stmt = "DELETE v1 FROM delete_column WHERE h = 0";
1713
0
  CHECK_OK(processor->Run(delete_stmt));
1714
1715
0
  string select_stmt_template = "SELECT $0 FROM delete_column WHERE h = 0";
1716
  // Check that v1 is null
1717
0
  CHECK_OK(processor->Run(Substitute(select_stmt_template, "v1")));
1718
0
  auto row_block = processor->row_block();
1719
0
  ASSERT_EQ(1, row_block->row_count());
1720
0
  const QLRow &row1 = row_block->row(0);
1721
0
  EXPECT_TRUE(row1.column(0).IsNull());
1722
1723
  // Check that v2 is 0
1724
0
  CHECK_OK(processor->Run(Substitute(select_stmt_template, "v2")));
1725
0
  row_block = processor->row_block();
1726
0
  ASSERT_EQ(1, row_block->row_count());
1727
0
  const QLRow &row2 = row_block->row(0);
1728
0
  EXPECT_EQ(0, row2.column(0).int32_value());
1729
1730
  // Check that primary keys and * cannot be deleted
1731
0
  CHECK_INVALID_STMT("DELETE * FROM delete_column WHERE h = 0;");
1732
0
  CHECK_INVALID_STMT("DELETE h FROM delete_column WHERE h = 0;");
1733
0
}
1734
1735
0
TEST_F(TestQLQuery, TestTtlWritetimeInWhereClauseOfSelectStatements) {
1736
  // Init the simulated cluster.
1737
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1738
1739
0
  TestQLProcessor *processor = GetQLProcessor();
1740
1741
0
  CHECK_OK(
1742
0
      processor->Run("CREATE TABLE ttl_writetime_test (h int, v1 int, v2 int, PRIMARY KEY(h))"));
1743
1744
0
  client::YBTableName name(YQL_DATABASE_CQL, kDefaultKeyspaceName, "ttl_writetime_test");
1745
1746
0
  shared_ptr<client::YBTable> table;
1747
1748
0
  ASSERT_OK(client_->OpenTable(name, &table));
1749
1750
  // generating input data with hash_code and inserting into table
1751
0
  std::vector<std::tuple<int, int, int>> rows;
1752
0
  for (int i = 0; i < 5; i++) {
1753
0
    std::string i_str = std::to_string(i);
1754
0
    YBPartialRow row(&table->InternalSchema());
1755
0
    CHECK_OK(row.SetInt32(0, i));
1756
0
    CHECK_OK(row.SetInt32(1, i));
1757
0
    CHECK_OK(row.SetInt32(2, i));
1758
0
    std::tuple<int, int, int> values(i, i, i);
1759
0
    rows.push_back(values);
1760
0
    string stmt = Substitute("INSERT INTO ttl_writetime_test (h, v1, v2) VALUES "
1761
0
                               "($0, $1, $2) using ttl 100;", i, i, i);
1762
0
    CHECK_OK(processor->Run(stmt));
1763
0
  }
1764
1765
0
  for (int i = 5; i < 10; i++) {
1766
0
    std::string i_str = std::to_string(i);
1767
0
    YBPartialRow row(&table->InternalSchema());
1768
0
    CHECK_OK(row.SetInt32(0, i));
1769
0
    CHECK_OK(row.SetInt32(1, i));
1770
0
    CHECK_OK(row.SetInt32(2, i));
1771
0
    std::tuple<int, int, int> values(i, i, i);
1772
0
    rows.push_back(values);
1773
0
    string stmt = Substitute("INSERT INTO ttl_writetime_test (h, v1, v2) VALUES "
1774
0
                               "($0, $1, $2) using ttl 200;", i, i, i);
1775
0
    CHECK_OK(processor->Run(stmt));
1776
0
  }
1777
1778
0
  std::sort(rows.begin(), rows.end(),
1779
0
            [](const std::tuple<int, int, int>& r1,
1780
0
               const std::tuple<int, int, int>& r2) -> bool {
1781
0
              return std::get<0>(r1) < std::get<0>(r2);
1782
0
            });
1783
1784
1785
  // test that for ttl > 150, there are 5 elements that match what we expect
1786
0
  string select_stmt_template = "SELECT * FROM ttl_writetime_test WHERE ttl($0) $1 $2";
1787
1788
0
  string select_stmt = Substitute(select_stmt_template, "v1", "<", 150);
1789
0
  CHECK_OK(processor->Run(select_stmt));
1790
0
  auto row_block = processor->row_block();
1791
0
  std::vector<QLRow>& returned_rows_1 = row_block->rows();
1792
0
  std::sort(returned_rows_1.begin(), returned_rows_1.end(),
1793
0
            [](const QLRow &r1,
1794
0
               const QLRow &r2) -> bool {
1795
0
              return r1.column(0).int32_value() < r2.column(0).int32_value();
1796
0
            });
1797
  // checking result
1798
0
  ASSERT_EQ(5, row_block->row_count());
1799
0
  for (int i = 0; i < 5; i++) {
1800
0
    QLRow &row = returned_rows_1.at(i);
1801
0
    EXPECT_EQ(std::get<0>(rows[i]), row.column(0).int32_value());
1802
0
    EXPECT_EQ(std::get<1>(rows[i]), row.column(1).int32_value());
1803
0
    EXPECT_EQ(std::get<2>(rows[i]), row.column(2).int32_value());
1804
0
  }
1805
1806
  // Now, let us test that when we update a column with a new ttl, that it shows up
1807
  // Should update 2 entries
1808
0
  string update_stmt = "UPDATE ttl_writetime_test using ttl 300 set v1 = 7 where h = 7;";
1809
0
  CHECK_OK(processor->Run(update_stmt));
1810
0
  update_stmt = "UPDATE ttl_writetime_test using ttl 300 set v1 = 8 where h = 8;";
1811
0
  CHECK_OK(processor->Run(update_stmt));
1812
0
  select_stmt = Substitute(select_stmt_template, "v1", ">", 250);
1813
0
  CHECK_OK(processor->Run(select_stmt));
1814
0
  row_block = processor->row_block();
1815
0
  std::vector<QLRow>& returned_rows_2 = row_block->rows();
1816
0
  std::sort(returned_rows_2.begin(), returned_rows_2.end(),
1817
0
            [](const QLRow &r1,
1818
0
               const QLRow &r2) -> bool {
1819
0
              return r1.column(0).int32_value() < r2.column(0).int32_value();
1820
0
            });
1821
  // checking result
1822
0
  ASSERT_EQ(2, row_block->row_count());
1823
0
  for (int i = 7; i < 9; i++) {
1824
0
    QLRow &row = returned_rows_2.at(i - 7);
1825
0
    EXPECT_EQ(std::get<0>(rows[i]), row.column(0).int32_value());
1826
0
    EXPECT_EQ(std::get<1>(rows[i]), row.column(1).int32_value());
1827
0
    EXPECT_EQ(std::get<2>(rows[i]), row.column(2).int32_value());
1828
0
  }
1829
1830
0
  select_stmt = Substitute(select_stmt_template, "v2", ">", 250);
1831
0
  CHECK_OK(processor->Run(select_stmt));
1832
0
  row_block = processor->row_block();
1833
  // checking result
1834
0
  ASSERT_EQ(0, row_block->row_count());
1835
0
}
1836
1837
0
TEST_F(TestQLQuery, TestFloatPrimaryKey) {
1838
  // Init the simulated cluster.
1839
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1840
1841
  // Get a processor.
1842
0
  TestQLProcessor *processor = GetQLProcessor();
1843
1844
0
  float my_keys[] = {0.0f, 1.5f, 1.5001f, 1.51f, 2.0f};
1845
1846
0
  const string create_stmt = "CREATE TABLE float_key (a float, b int, primary key (a))";
1847
0
  string insert_template = "INSERT INTO float_key (a, b) VALUES ($0, $1);";
1848
0
  string select_template = "SELECT $0 FROM float_key where a = $1;";
1849
1850
0
  CHECK_OK(processor->Run(create_stmt));
1851
0
  for (int i = 0; i < 5; i++) {
1852
0
    LOG(INFO) << "Inserting " << my_keys[i];
1853
0
    CHECK_OK(processor->Run(Substitute(insert_template, my_keys[i], i)));
1854
0
  }
1855
1856
0
  for (int i = 0; i < 5; i++) {
1857
0
    LOG(INFO) << "Selecting " << my_keys[i];
1858
0
    CHECK_OK(processor->Run(Substitute(select_template, "*", my_keys[i])));
1859
0
    auto row_block = processor->row_block();
1860
0
    ASSERT_EQ(1, row_block->row_count());
1861
0
    std::vector<QLRow> &returned_rows = row_block->rows();
1862
0
    QLRow &row = returned_rows.at(0);
1863
0
    EXPECT_EQ(my_keys[i], row.column(0).float_value());
1864
0
    EXPECT_EQ(i, row.column(1).int32_value());
1865
0
  }
1866
0
}
1867
1868
0
TEST_F(TestQLQuery, TestDoublePrimaryKey) {
1869
  // Init the simulated cluster.
1870
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1871
1872
  // Get a processor.
1873
0
  TestQLProcessor *processor = GetQLProcessor();
1874
1875
0
  double my_keys[] = {0.0l, 1.5l, 1.5000000001l, 1.51l, 2.0l};
1876
  // Assert that the two numbers are equal as floats but not equal as doubles.
1877
0
  ASSERT_EQ(1.5f, 1.5000000001f);
1878
0
  ASSERT_LT(1.5l, 1.5000000001l);
1879
1880
0
  const string create_stmt = "CREATE TABLE double_key (a double, b int, primary key (a))";
1881
0
  string insert_template = "INSERT INTO double_key (a, b) VALUES ($0, $1);";
1882
0
  string select_template = "SELECT $0 FROM double_key where a = $1;";
1883
1884
0
  CHECK_OK(processor->Run(create_stmt));
1885
0
  for (int i = 0; i < 5; i++) {
1886
0
    LOG(INFO) << "Inserting " << my_keys[i];
1887
0
    CHECK_OK(processor->Run(Substitute(insert_template, my_keys[i], i)));
1888
0
  }
1889
1890
0
  for (int i = 0; i < 5; i++) {
1891
0
    LOG(INFO) << "Selecting " << my_keys[i];
1892
0
    CHECK_OK(processor->Run(Substitute(select_template, "*", my_keys[i])));
1893
0
    auto row_block = processor->row_block();
1894
0
    ASSERT_EQ(1, row_block->row_count());
1895
0
    std::vector<QLRow> &returned_rows = row_block->rows();
1896
0
    QLRow &row = returned_rows.at(0);
1897
0
    EXPECT_EQ(my_keys[i], row.column(0).double_value());
1898
0
    EXPECT_EQ(i, row.column(1).int32_value());
1899
0
  }
1900
0
}
1901
1902
1903
0
void verifyJson(std::shared_ptr<QLRowBlock> row_block) {
1904
  // Verify.
1905
0
  ASSERT_EQ(1, row_block->row_count());
1906
0
  std::vector<QLRow> &returned_rows = row_block->rows();
1907
0
  QLRow &row = returned_rows.at(0);
1908
  // All spaces are removed by rapidjson writer.
1909
0
  string json;
1910
0
  common::Jsonb jsonb(row.column(1).jsonb_value());
1911
0
  ASSERT_OK(jsonb.ToJsonString(&json));
1912
0
  EXPECT_EQ("{\"a\":1,\"b\":2}", json);
1913
0
  faststring buffer;
1914
0
  row.column(1).Serialize(QLType::Create(DataType::JSONB), YQL_CLIENT_CQL, &buffer);
1915
0
  int32_t len = 0;
1916
0
  Slice data(buffer);
1917
0
  ASSERT_OK(CQLDecodeNum(sizeof(len), NetworkByteOrder::Load32, &data, &len));
1918
0
  string val;
1919
0
  ASSERT_OK(CQLDecodeBytes(len, &data, &val));
1920
0
  EXPECT_EQ("{\"a\":1,\"b\":2}", val);
1921
0
}
1922
1923
0
TEST_F(TestQLQuery, TestJson) {
1924
  // Init the simulated cluster.
1925
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1926
1927
  // Get a processor.
1928
0
  TestQLProcessor *processor = GetQLProcessor();
1929
0
  CHECK_OK(processor->Run("CREATE TABLE test_json (k1 int PRIMARY KEY, data jsonb)"));
1930
0
  CHECK_OK(processor->Run(
1931
0
      "INSERT INTO test_json (k1, data) values (1, '{ \"a\" : 1, \"b\" : 2 }')"));
1932
0
  CHECK_OK(processor->Run("SELECT * FROM test_json"));
1933
0
  verifyJson(processor->row_block());
1934
1935
0
  CHECK_OK(processor->Run("SELECT * FROM test_json WHERE k1=1 AND data='{\"a\":1,\"b\":2}'"));
1936
0
  verifyJson(processor->row_block());
1937
1938
0
  CHECK_OK(processor->Run("SELECT * FROM test_json WHERE k1=1 AND data='{\"a\" : 1,\"b\" : 2}'"));
1939
0
  verifyJson(processor->row_block());
1940
1941
0
  CHECK_OK(processor->Run("SELECT * FROM test_json WHERE k1=1 AND data='{\"b\" : 2,\"a\" : 1}'"));
1942
0
  verifyJson(processor->row_block());
1943
1944
0
  CHECK_OK(processor->Run("SELECT * FROM test_json WHERE k1=1 AND data->'a' = '1'"));
1945
0
  verifyJson(processor->row_block());
1946
1947
0
  CHECK_OK(processor->Run("SELECT * FROM test_json WHERE k1=1 AND data->>'a' = '1'"));
1948
0
  verifyJson(processor->row_block());
1949
1950
0
  ASSERT_NOK(processor->Run("CREATE TABLE test_json1 (k1 jsonb PRIMARY KEY, data jsonb)"));
1951
0
  ASSERT_NOK(processor->Run("CREATE TABLE test_json2 (h1 int, r1 jsonb, c1 int, PRIMARY KEY ((h1)"
1952
0
                                ", r1))"));
1953
0
}
1954
1955
0
TEST_F(TestQLQuery, TestJsonUpdate) {
1956
  // Init the simulated cluster.
1957
0
  ASSERT_NO_FATALS(CreateSimulatedCluster());
1958
1959
  // Get a processor.
1960
0
  TestQLProcessor *processor = GetQLProcessor();
1961
0
  ASSERT_OK(processor->Run("CREATE TABLE test_json (k1 int PRIMARY KEY, data jsonb)"));
1962
0
  ASSERT_OK(processor->Run(
1963
0
      "INSERT INTO test_json (k1, data) values (1, '{ \"a\" : 1, \"b\" : 2 }')"));
1964
0
  ASSERT_OK(processor->Run("SELECT * FROM test_json"));
1965
0
  verifyJson(processor->row_block());
1966
1967
0
  ASSERT_OK(processor->Run("UPDATE test_json SET data->'a' = '100' WHERE k1 = 1"));
1968
0
  ASSERT_NOK(processor->Run("UPDATE test_json SET data->'new-field'->'c' = '100' WHERE k1 = 1"));
1969
0
  ASSERT_OK(processor->Run("UPDATE test_json SET data->'new-field' = '100' WHERE k1 = 1"));
1970
1971
0
  ASSERT_OK(processor->Run("UPDATE test_json SET data =  '{ \"a\": 2, \"b\": 4 }' WHERE k1 = 2"));
1972
1973
  // Setting primitive value in JSON column should work
1974
0
  ASSERT_OK(processor->Run("UPDATE test_json SET data='true' WHERE k1 = 1"));
1975
  // Trying to update primitive value in JSON column using field name should error out
1976
0
  ASSERT_NOK(processor->Run("UPDATE test_json SET data->'a' WHERE k1 = 1"));
1977
0
}
1978
1979
} // namespace ql
1980
} // namespace yb