/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 |