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_update.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 PggateTestDelete : public PggateTest {
29
};
30
31
0
TEST_F(PggateTestDelete, TestDelete) {
32
0
  CHECK_OK(Init("TestDelete"));
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(YBCPgExecCreateTable(pg_stmt));
61
0
  pg_stmt = nullptr;
62
63
  // INSERT ----------------------------------------------------------------------------------------
64
  // Allocate new insert.
65
0
  CHECK_YBC_STATUS(YBCPgNewInsert(kDefaultDatabaseOid, tab_oid,
66
0
                                  false /* is_single_row_txn */, &pg_stmt));
67
68
  // Allocate constant expressions.
69
  // TODO(neil) We can also allocate expression with bind.
70
0
  int seed = 1;
71
0
  YBCPgExpr expr_hash;
72
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt8(pg_stmt, seed, false, &expr_hash));
73
0
  YBCPgExpr expr_id;
74
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt4(pg_stmt, seed, false, &expr_id));
75
0
  YBCPgExpr expr_depcnt;
76
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt2(pg_stmt, seed, false, &expr_depcnt));
77
0
  YBCPgExpr expr_projcnt;
78
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt4(pg_stmt, 100 + seed, false, &expr_projcnt));
79
0
  YBCPgExpr expr_salary;
80
0
  CHECK_YBC_STATUS(YBCTestNewConstantFloat4(pg_stmt, seed + 1.0*seed/10.0, false, &expr_salary));
81
0
  YBCPgExpr expr_job;
82
0
  string job = strings::Substitute("Job_title_$0", seed);
83
0
  CHECK_YBC_STATUS(YBCTestNewConstantText(pg_stmt, job.c_str(), false, &expr_job));
84
85
  // Set column value to be inserted.
86
0
  int attr_num = 0;
87
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_hash));
88
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_id));
89
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_depcnt));
90
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_projcnt));
91
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_salary));
92
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_job));
93
0
  CHECK_EQ(attr_num, col_count);
94
95
0
  const int insert_row_count = 7;
96
0
  for (int i = 0; i < insert_row_count; i++) {
97
    // Insert the row with the original seed.
98
0
    BeginTransaction();
99
0
    CHECK_YBC_STATUS(YBCPgExecInsert(pg_stmt));
100
0
    CommitTransaction();
101
102
    // Update the constant expresions to insert the next row.
103
    // TODO(neil) When we support binds, we can also call UpdateBind here.
104
0
    seed++;
105
0
    CHECK_YBC_STATUS(YBCPgUpdateConstInt8(expr_hash, seed, false));
106
0
    CHECK_YBC_STATUS(YBCPgUpdateConstInt4(expr_id, seed, false));
107
0
    CHECK_YBC_STATUS(YBCPgUpdateConstInt2(expr_depcnt, seed, false));
108
0
    CHECK_YBC_STATUS(YBCPgUpdateConstInt4(expr_projcnt, 100 + seed, false));
109
0
    CHECK_YBC_STATUS(YBCPgUpdateConstFloat4(expr_salary, seed + 1.0*seed/10.0, false));
110
0
    job = strings::Substitute("Job_title_$0", seed);
111
0
    CHECK_YBC_STATUS(YBCPgUpdateConstChar(expr_job, job.c_str(), job.size(), false));
112
0
  }
113
114
0
  pg_stmt = nullptr;
115
116
  // UPDATE ----------------------------------------------------------------------------------------
117
  // Allocate new update.
118
0
  CHECK_YBC_STATUS(YBCPgNewUpdate(kDefaultDatabaseOid, tab_oid,
119
0
                                  false /* is_single_row_txn */, &pg_stmt));
120
121
  // Allocate constant expressions.
122
  // TODO(neil) We can also allocate expression with bind.
123
0
  seed = 1;
124
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt8(pg_stmt, seed, false, &expr_hash));
125
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt4(pg_stmt, seed, false, &expr_id));
126
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt2(pg_stmt, 77 + seed, false, &expr_depcnt));
127
0
  CHECK_YBC_STATUS(YBCTestNewConstantInt4(pg_stmt, 77 + 100 + seed, false, &expr_projcnt));
128
0
  CHECK_YBC_STATUS(YBCTestNewConstantFloat4(pg_stmt, 77 + seed + 1.0*seed/10.0, false,
129
0
                                            &expr_salary));
130
0
  job = strings::Substitute("Job_title_$0", seed + 77);
131
0
  CHECK_YBC_STATUS(YBCTestNewConstantText(pg_stmt, job.c_str(), false, &expr_job));
132
133
0
  attr_num = 0;
134
  // Specify the rows we want to update by binding primary columns.
135
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_hash));
136
0
  CHECK_YBC_STATUS(YBCPgDmlBindColumn(pg_stmt, ++attr_num, expr_id));
137
138
  // Specify new values for the columns we want to update.
139
0
  CHECK_YBC_STATUS(YBCPgDmlAssignColumn(pg_stmt, ++attr_num, expr_depcnt));
140
0
  CHECK_YBC_STATUS(YBCPgDmlAssignColumn(pg_stmt, ++attr_num, expr_projcnt));
141
0
  CHECK_YBC_STATUS(YBCPgDmlAssignColumn(pg_stmt, ++attr_num, expr_salary));
142
0
  CHECK_YBC_STATUS(YBCPgDmlAssignColumn(pg_stmt, ++attr_num, expr_job));
143
0
  CHECK_EQ(attr_num, col_count);
144
145
  // UPDATE all of odd rows.
146
0
  const int update_row_count = (insert_row_count + 1)/ 2;
147
0
  for (int i = 0; i < update_row_count; i++) {
148
    // Update the row with the original seed.
149
0
    BeginTransaction();
150
0
    CHECK_YBC_STATUS(YBCPgExecUpdate(pg_stmt));
151
0
    CommitTransaction();
152
153
    // Update the constant expresions to update the next row.
154
    // TODO(neil) When we support binds, we can also call UpdateBind here.
155
0
    seed = seed + 2;
156
0
    CHECK_YBC_STATUS(YBCPgUpdateConstInt8(expr_hash, seed, false));
157
0
    CHECK_YBC_STATUS(YBCPgUpdateConstInt4(expr_id, seed, false));
158
0
    CHECK_YBC_STATUS(YBCPgUpdateConstInt2(expr_depcnt, 77 + seed, false));
159
0
    CHECK_YBC_STATUS(YBCPgUpdateConstInt4(expr_projcnt, 77 + 100 + seed, false));
160
0
    CHECK_YBC_STATUS(YBCPgUpdateConstFloat4(expr_salary, 77 + seed + 1.0*seed/10.0, false));
161
0
    job = strings::Substitute("Job_title_$0", 77 + seed);
162
0
    CHECK_YBC_STATUS(YBCPgUpdateConstChar(expr_job, job.c_str(), job.size(), false));
163
0
  }
164
165
0
  pg_stmt = nullptr;
166
167
  // SELECT ----------------------------------------------------------------------------------------
168
0
  LOG(INFO) << "Test SELECTing from non-partitioned table";
169
0
  CHECK_YBC_STATUS(YBCPgNewSelect(kDefaultDatabaseOid, tab_oid,
170
0
                                  NULL /* prepare_params */, &pg_stmt));
171
172
  // Specify the selected expressions.
173
0
  YBCPgExpr colref;
174
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 1, DataType::INT64, &colref));
175
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
176
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 2, DataType::INT32, &colref));
177
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
178
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 3, DataType::INT16, &colref));
179
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
180
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 4, DataType::INT32, &colref));
181
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
182
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 5, DataType::FLOAT, &colref));
183
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
184
0
  CHECK_YBC_STATUS(YBCTestNewColumnRef(pg_stmt, 6, DataType::STRING, &colref));
185
0
  CHECK_YBC_STATUS(YBCPgDmlAppendTarget(pg_stmt, colref));
186
187
  // Execute select statement.
188
0
  BeginTransaction();
189
0
  CHECK_YBC_STATUS(YBCPgExecSelect(pg_stmt, nullptr /* exec_params */));
190
191
  // Fetching rows and check their contents.
192
0
  uint64_t *values = static_cast<uint64_t*>(YBCPAlloc(col_count * sizeof(uint64_t)));
193
0
  bool *isnulls = static_cast<bool*>(YBCPAlloc(col_count * sizeof(bool)));
194
0
  int select_row_count = 0;
195
0
  for (int i = 0; i < insert_row_count; i++) {
196
0
    bool has_data = false;
197
0
    CHECK_YBC_STATUS(YBCPgDmlFetch(pg_stmt, col_count, values, isnulls, nullptr, &has_data));
198
0
    if (!has_data) {
199
0
      break;
200
0
    }
201
0
    select_row_count++;
202
203
    // Print result
204
0
    LOG(INFO) << "ROW " << select_row_count << ": "
205
0
              << "hash_key = " << values[0]
206
0
              << ", id = " << values[1]
207
0
              << ", dependent count = " << values[2]
208
0
              << ", project count = " << values[3]
209
0
              << ", salary = " << *reinterpret_cast<float*>(&values[4])
210
0
              << ", job = (" << values[5] << ")";
211
212
    // Check result.
213
0
    int col_index = 0;
214
0
    int32_t hash_id = narrow_cast<int32_t>(values[col_index++]);  // id : int32
215
0
    int32_t id = narrow_cast<int32_t>(values[col_index++]);  // id : int32
216
0
    CHECK_EQ(hash_id, id) << "Expect hash and range key share the same value";
217
0
    if (id%2 == 0) {
218
      // Check if EVEN rows stays the same as inserted.
219
0
      CHECK_EQ(values[col_index++], id);  // dependent_count : int16
220
0
      CHECK_EQ(values[col_index++], 100 + id);  // project_count : int32
221
222
      // salary : float
223
0
      float salary = *reinterpret_cast<float*>(&values[col_index++]);
224
0
      CHECK_LE(salary, id + 1.0*id/10.0 + 0.01);
225
0
      CHECK_GE(salary, id + 1.0*id/10.0 - 0.01);
226
227
0
      string selected_job_name = reinterpret_cast<char*>(values[col_index++]);
228
0
      string expected_job_name = strings::Substitute("Job_title_$0", id);
229
0
      CHECK_EQ(selected_job_name, expected_job_name);
230
231
0
    } else {
232
      // Check if ODD rows have been updated.
233
0
      CHECK_EQ(values[col_index++], 77 + id);  // dependent_count : int16
234
0
      CHECK_EQ(values[col_index++], 77 + 100 + id);  // project_count : int32
235
236
      // salary : float
237
0
      float salary = *reinterpret_cast<float*>(&values[col_index++]);
238
0
      CHECK_LE(salary, 77 + id + 1.0*id/10.0 + 0.01);
239
0
      CHECK_GE(salary, 77 + id + 1.0*id/10.0 - 0.01);
240
241
0
      string selected_job_name = reinterpret_cast<char*>(values[col_index++]);
242
0
      string expected_job_name = strings::Substitute("Job_title_$0", 77 + id);
243
0
      CHECK_EQ(selected_job_name, expected_job_name);
244
0
    }
245
0
  }
246
0
  CHECK_EQ(select_row_count, insert_row_count) << "Unexpected row count";
247
0
  CommitTransaction();
248
249
0
  pg_stmt = nullptr;
250
0
}
251
252
} // namespace pggate
253
} // namespace yb