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