YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/yql/pggate/test/pggate_test_select_multi_tablets.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 "yb/common/ybc-internal.h"
17
18
#include "yb/util/status_log.h"
19
20
#include "yb/yql/pggate/test/pggate_test.h"
21
#include "yb/yql/pggate/ybc_pggate.h"
22
23
namespace yb {
24
namespace pggate {
25
26
class PggateTestSelectMultiTablets : public PggateTest {
27
};
28
29
0
TEST_F(PggateTestSelectMultiTablets, TestSelectMultiTablets) {
30
0
  CHECK_OK(Init("TestSelectMultiTablet"));
31
32
0
  const char *tabname = "basic_table";
33
0
  const YBCPgOid tab_oid = 3;
34
0
  YBCPgStatement pg_stmt;
35
36
  // Create table in the connected database.
37
0
  int col_count = 0;
38
0
  CHECK_YBC_STATUS(YBCPgNewCreateTable(kDefaultDatabase, kDefaultSchema, tabname,
39
0
                                       kDefaultDatabaseOid, tab_oid,
40
0
                                       false /* is_shared_table */, true /* if_not_exist */,
41
0
                                       false /* add_primary_key */, true /* colocated */,
42
0
                                       kInvalidOid /* tablegroup_id */,
43
0
                                       kInvalidOid /* tablespace_id */,
44
0
                                       kInvalidOid /* matview_pg_table_id */,
45
0
                                       &pg_stmt));
46
0
  CHECK_YBC_STATUS(YBCTestCreateTableAddColumn(pg_stmt, "hash_key", ++col_count,
47
0
                                             DataType::INT64, true, true));
48
0
  CHECK_YBC_STATUS(YBCTestCreateTableAddColumn(pg_stmt, "id", ++col_count,
49
0
                                             DataType::INT32, false, true));
50
0
  CHECK_YBC_STATUS(YBCTestCreateTableAddColumn(pg_stmt, "dependent_count", ++col_count,
51
0
                                             DataType::INT16, false, false));
52
0
  CHECK_YBC_STATUS(YBCTestCreateTableAddColumn(pg_stmt, "project_count", ++col_count,
53
0
                                             DataType::INT32, false, false));
54
0
  CHECK_YBC_STATUS(YBCTestCreateTableAddColumn(pg_stmt, "salary", ++col_count,
55
0
                                             DataType::FLOAT, false, false));
56
0
  CHECK_YBC_STATUS(YBCTestCreateTableAddColumn(pg_stmt, "job", ++col_count,
57
0
                                             DataType::STRING, false, false));
58
0
  CHECK_YBC_STATUS(YBCPgExecCreateTable(pg_stmt));
59
0
  pg_stmt = nullptr;
60
61
  // SELECT: Empty Table ---------------------------------------------------------------------------
62
0
  LOG(INFO) << "Test SELECTing from empty table";
63
0
  CHECK_YBC_STATUS(YBCPgNewSelect(kDefaultDatabaseOid, tab_oid,
64
0
                                  NULL /* prepare_params */, &pg_stmt));
65
66
  // Specify the selected expressions.
67
0
  YBCPgExpr colref;
68
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 1, DataType::INT64, &colref));
69
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
70
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 2, DataType::INT32, &colref));
71
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
72
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 3, DataType::INT16, &colref));
73
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
74
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 4, DataType::INT32, &colref));
75
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
76
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 5, DataType::FLOAT, &colref));
77
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
78
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 6, DataType::STRING, &colref));
79
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
80
81
  // Execute select statement.
82
0
  BeginTransaction();
83
0
  CHECK_YBC_STATUS(YBCPgExecSelect(pg_stmt, nullptr /* exec_params */));
84
85
  // Fetching rows and check their contents.
86
0
  uint64_t *values = static_cast<uint64_t*>(YBCPAlloc(col_count * sizeof(uint64_t)));
87
0
  bool *isnulls = static_cast<bool*>(YBCPAlloc(col_count * sizeof(bool)));
88
0
  bool has_data = true;
89
0
  while (has_data) {
90
0
    CHECK_YBC_STATUS(YBCPgDmlFetch(pg_stmt, col_count, values, isnulls, nullptr, &has_data));
91
0
    CHECK(!has_data) << "Corrupted DB. Table is expected to be empty";
92
0
  }
93
0
  CommitTransaction();
94
95
  // Deallocate statement.
96
0
  pg_stmt = nullptr;
97
98
  // INSERT ----------------------------------------------------------------------------------------
99
  // Allocate new insert.
100
0
  CHECK_YBC_STATUS(YBCPgNewInsert(kDefaultDatabaseOid, tab_oid,
101
0
                                  false /* is_single_row_txn */, &pg_stmt));
102
103
  // Allocate constant expressions.
104
  // TODO(neil) We can also allocate expression with bind.
105
0
  int seed = 1;
106
0
  YBCPgExpr expr_hash;
107
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt8(pg_stmt, seed, false, &expr_hash));
108
0
  YBCPgExpr expr_id;
109
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt4(pg_stmt, seed, false, &expr_id));
110
0
  YBCPgExpr expr_depcnt;
111
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt2(pg_stmt, seed, false, &expr_depcnt));
112
0
  YBCPgExpr expr_projcnt;
113
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt4(pg_stmt, 100 + seed, false, &expr_projcnt));
114
0
  YBCPgExpr expr_salary;
115
0
  CHECK_YBC_STATUS(YBCTestNewConstantFloat4(pg_stmt, seed + 1.0*seed/10.0, false, &expr_salary));
116
0
  YBCPgExpr expr_job;
117
0
  string job = strings::Substitute("Job_title_$0", seed);
118
0
  CHECK_YBC_STATUS(YBCTestNewConstantText(pg_stmt, job.c_str(), false, &expr_job));
119
120
  // Set column value to be inserted.
121
0
  int attr_num = 0;
122
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_hash));
123
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_id));
124
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_depcnt));
125
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_projcnt));
126
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_salary));
127
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_job));
128
0
  CHECK_EQ(attr_num, col_count);
129
130
0
  const int insert_row_count = 7;
131
0
  for (int i = 0; i < insert_row_count; i++) {
132
    // Insert the row with the original seed.
133
0
    BeginTransaction();
134
0
    CHECK_YBC_STATUS(YBCPgExecInsert(pg_stmt));
135
0
    CommitTransaction();
136
137
    // Update the constant expresions to insert the next row.
138
    // TODO(neil) When we support binds, we can also call UpdateBind here.
139
0
    seed++;
140
0
    CHECK_YBC_STATUS(YBCPgUpdateConstInt8(expr_hash, seed, false));
141
0
    CHECK_YBC_STATUS(YBCPgUpdateConstInt4(expr_id, seed, false));
142
0
    CHECK_YBC_STATUS(YBCPgUpdateConstInt2(expr_depcnt, seed, false));
143
0
    CHECK_YBC_STATUS(YBCPgUpdateConstInt4(expr_projcnt, 100 + seed, false));
144
0
    CHECK_YBC_STATUS(YBCPgUpdateConstFloat4(expr_salary, seed + 1.0*seed/10.0, false));
145
0
    job = strings::Substitute("Job_title_$0", seed);
146
0
    CHECK_YBC_STATUS(YBCPgUpdateConstChar(expr_job, job.c_str(), job.size(), false));
147
0
  }
148
149
0
  pg_stmt = nullptr;
150
151
  // SELECT ----------------------------------------------------------------------------------------
152
0
  LOG(INFO) << "Test SELECTing from partitioned table WITH specifying RANGE column";
153
0
  CHECK_YBC_STATUS(YBCPgNewSelect(kDefaultDatabaseOid, tab_oid,
154
0
                                  NULL /* prepare_params */, &pg_stmt));
155
156
  // Specify the selected expressions.
157
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 1, DataType::INT64, &colref));
158
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
159
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 2, DataType::INT32, &colref));
160
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
161
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 3, DataType::INT16, &colref));
162
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
163
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 4, DataType::INT32, &colref));
164
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
165
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 5, DataType::FLOAT, &colref));
166
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
167
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 6, DataType::STRING, &colref));
168
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
169
170
  // Set partition and range columns for SELECT to select a specific row.
171
  // SELECT ... WHERE hash = seed AND id = seed.
172
0
  seed = 3;
173
0
  attr_num = 0;
174
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt8(pg_stmt, seed, false, &expr_hash));
175
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_hash));
176
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt4(pg_stmt, seed, false, &expr_id));
177
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_id));
178
179
  // Execute select statement.
180
0
  BeginTransaction();
181
0
  CHECK_YBC_STATUS(YBCPgExecSelect(pg_stmt, nullptr /* exec_params */));
182
183
  // Fetching rows and check their contents.
184
0
  values = static_cast<uint64_t*>(YBCPAlloc(col_count * sizeof(uint64_t)));
185
0
  isnulls = static_cast<bool*>(YBCPAlloc(col_count * sizeof(bool)));
186
0
  int select_row_count = 0;
187
0
  for (int i = 0; i < insert_row_count; i++) {
188
0
    has_data = false;
189
0
    CHECK_YBC_STATUS(YBCPgDmlFetch(pg_stmt, col_count, values, isnulls, nullptr, &has_data));
190
0
    if (!has_data) {
191
0
      break;
192
0
    }
193
0
    select_row_count++;
194
195
    // Print result
196
0
    LOG(INFO) << "ROW " << i << ": "
197
0
              << "hash_key = " << values[0]
198
0
              << ", id = " << values[1]
199
0
              << ", dependent count = " << values[2]
200
0
              << ", project count = " << values[3]
201
0
              << ", salary = " << *reinterpret_cast<float*>(&values[4])
202
0
              << ", job = (" << values[5] << ")";
203
204
    // Check result.
205
0
    int col_index = 0;
206
0
    int64_t id = values[col_index++];  // hash_key : int64
207
0
    CHECK_EQ(id, seed) << "Unexpected result for hash column";
208
0
    CHECK_EQ(values[col_index++], id);  // id : int32
209
0
    CHECK_EQ(values[col_index++], id);  // dependent_count : int16
210
0
    CHECK_EQ(values[col_index++], 100 + id);  // project_count : int32
211
212
0
    float salary = *reinterpret_cast<float*>(&values[col_index++]);  // salary : float
213
0
    CHECK_LE(salary, id + 1.0*id/10.0 + 0.01);
214
0
    CHECK_GE(salary, id + 1.0*id/10.0 - 0.01);
215
216
0
    string selected_job_name = reinterpret_cast<char*>(values[col_index++]);
217
0
    string expected_job_name = strings::Substitute("Job_title_$0", id);
218
0
    CHECK_EQ(selected_job_name, expected_job_name);
219
0
  }
220
0
  CHECK_EQ(select_row_count, 1) << "Unexpected row count";
221
0
  CommitTransaction();
222
223
0
  pg_stmt = nullptr;
224
225
  // SELECT ----------------------------------------------------------------------------------------
226
0
  LOG(INFO) << "Test SELECTing from partitioned table WITHOUT specifying RANGE column";
227
0
  CHECK_YBC_STATUS(YBCPgNewSelect(kDefaultDatabaseOid, tab_oid,
228
0
                                  NULL /* prepare_params */, &pg_stmt));
229
230
  // Specify the selected expressions.
231
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 1, DataType::INT64, &colref));
232
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
233
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 2, DataType::INT32, &colref));
234
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
235
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 3, DataType::INT16, &colref));
236
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
237
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 4, DataType::INT32, &colref));
238
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
239
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 5, DataType::FLOAT, &colref));
240
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
241
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 6, DataType::STRING, &colref));
242
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
243
244
  // Execute select statement.
245
0
  BeginTransaction();
246
0
  CHECK_YBC_STATUS(YBCPgExecSelect(pg_stmt, nullptr /* exec_params */));
247
248
  // Fetching rows and check their contents.
249
0
  values = static_cast<uint64_t*>(YBCPAlloc(col_count * sizeof(uint64_t)));
250
0
  isnulls = static_cast<bool*>(YBCPAlloc(col_count * sizeof(bool)));
251
0
  for (int i = 0; i < insert_row_count; i++) {
252
0
    has_data = false;
253
0
    CHECK_YBC_STATUS(YBCPgDmlFetch(pg_stmt, col_count, values, isnulls, nullptr, &has_data));
254
0
    CHECK(has_data) << "Not all inserted rows are fetch";
255
256
    // Print result
257
0
    LOG(INFO) << "ROW " << i << ": "
258
0
              << "hash_key = " << values[0]
259
0
              << ", id = " << values[1]
260
0
              << ", dependent count = " << values[2]
261
0
              << ", project count = " << values[3]
262
0
              << ", salary = " << *reinterpret_cast<float*>(&values[4])
263
0
              << ", job = (" << values[5] << ")";
264
265
    // Check result.
266
0
    int col_index = 0;
267
0
    int64_t id = values[col_index++];  // hash_key : int64
268
0
    CHECK_EQ(values[col_index++], id);  // id : int32
269
0
    CHECK_EQ(values[col_index++], id);  // dependent_count : int16
270
0
    CHECK_EQ(values[col_index++], 100 + id);  // project_count : int32
271
272
0
    float salary = *reinterpret_cast<float*>(&values[col_index++]);  // salary : float
273
0
    CHECK_LE(salary, id + 1.0*id/10.0 + 0.01); // salary
274
0
    CHECK_GE(salary, id + 1.0*id/10.0 - 0.01); // float
275
276
0
    string selected_job_name = reinterpret_cast<char*>(values[col_index++]);
277
0
    string expected_job_name = strings::Substitute("Job_title_$0", id);
278
0
    CHECK_EQ(selected_job_name, expected_job_name);
279
0
  }
280
0
  CommitTransaction();
281
282
0
  pg_stmt = nullptr;
283
0
}
284
285
} // namespace pggate
286
} // namespace yb