/Users/deen/code/yugabyte-db/src/yb/yql/pggate/test/pggate_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 "yb/yql/pggate/test/pggate_test.h" |
17 | | |
18 | | #include <memory> |
19 | | #include <string> |
20 | | #include <unordered_set> |
21 | | |
22 | | #include <boost/optional.hpp> |
23 | | #include <gflags/gflags.h> |
24 | | |
25 | | #include "yb/common/entity_ids.h" |
26 | | #include "yb/common/pg_types.h" |
27 | | |
28 | | #include "yb/gutil/ref_counted.h" |
29 | | |
30 | | #include "yb/rpc/rpc_controller.h" |
31 | | |
32 | | #include "yb/tserver/tserver_util_fwd.h" |
33 | | #include "yb/tserver/tserver_service.proxy.h" |
34 | | #include "yb/tserver/tserver_shared_mem.h" |
35 | | |
36 | | #include "yb/util/memory/arena.h" |
37 | | #include "yb/util/memory/mc_types.h" |
38 | | #include "yb/util/result.h" |
39 | | #include "yb/util/status_log.h" |
40 | | |
41 | | #include "yb/yql/pggate/pggate_flags.h" |
42 | | #include "yb/yql/pggate/ybc_pggate.h" |
43 | | |
44 | | using namespace std::literals; |
45 | | |
46 | | DECLARE_string(pggate_master_addresses); |
47 | | DECLARE_string(test_leave_files); |
48 | | |
49 | | namespace yb { |
50 | | namespace pggate { |
51 | | namespace { |
52 | | |
53 | 0 | void FetchUniqueConstraintName(PgOid relation_id, char* dest, size_t max_size) { |
54 | 0 | CHECK(false) << "Not implemented"; |
55 | 0 | } |
56 | | |
57 | | YBCPgMemctx global_test_memctx = nullptr; |
58 | | |
59 | 0 | YBCPgMemctx GetCurrentTestYbMemctx() { |
60 | 0 | if (!global_test_memctx) { |
61 | 0 | global_test_memctx = YBCPgCreateMemctx(); |
62 | 0 | } |
63 | 0 | return global_test_memctx; |
64 | 0 | } |
65 | | |
66 | 0 | void ClearCurrentTestYbMemctx() { |
67 | 0 | if (global_test_memctx != nullptr) { |
68 | 0 | CHECK_YBC_STATUS(YBCPgDestroyMemctx(global_test_memctx)); |
69 | | |
70 | | // We assume the memory context has actually already been deleted. |
71 | 0 | global_test_memctx = nullptr; |
72 | 0 | } |
73 | 0 | } |
74 | | |
75 | 0 | const char* GetDebugQueryStringStub() { |
76 | 0 | return "GetDebugQueryString not implemented in test"; |
77 | 0 | } |
78 | | |
79 | | } // namespace |
80 | | |
81 | | PggateTest::PggateTest() |
82 | 0 | : tserver_shared_object_(CHECK_RESULT(tserver::TServerSharedObject::Create())) { |
83 | 0 | } |
84 | | |
85 | 0 | PggateTest::~PggateTest() { |
86 | 0 | } |
87 | | |
88 | | //-------------------------------------------------------------------------------------------------- |
89 | | // Error handling routines. |
90 | 0 | void PggateTest::CheckYBCStatus(YBCStatus status, const char* file_name, int line_number) { |
91 | 0 | CHECK_OK(Status(status, AddRef::kTrue)); |
92 | 0 | } |
93 | | |
94 | 0 | void *PggateTestAlloc(size_t bytes) { |
95 | 0 | static MemoryContext memctx; |
96 | 0 | return static_cast<void*>(memctx.AllocateBytes(bytes)); |
97 | 0 | } |
98 | | |
99 | | // This implementation is different from what PostgreSQL's cstring_to_text_with_len function does. |
100 | | // Here we just copy the given string and add a terminating zero. This is what our test expects. |
101 | 0 | struct varlena* PggateTestCStringToTextWithLen(const char* c, int size) { |
102 | 0 | static MemoryContext memctx; |
103 | 0 | CHECK_GE(size, 0); |
104 | 0 | CHECK_LE(size, 1024ll * 1024 * 1024 - 4); |
105 | |
|
106 | 0 | char* buf = static_cast<char*>(memctx.AllocateBytes(size + 1)); |
107 | 0 | memcpy(buf, c, size); |
108 | 0 | buf[size] = 0; |
109 | 0 | return reinterpret_cast<struct varlena*>(buf); |
110 | 0 | } |
111 | | |
112 | | //-------------------------------------------------------------------------------------------------- |
113 | | // Starting and ending routines. |
114 | | |
115 | 0 | void PggateTest::SetUp() { |
116 | 0 | FLAGS_test_leave_files = "always"; |
117 | 0 | YBTest::SetUp(); |
118 | 0 | } |
119 | | |
120 | 0 | void PggateTest::TearDown() { |
121 | | // It is important to destroy the memory context before destroying PgGate. |
122 | 0 | ClearCurrentTestYbMemctx(); |
123 | | |
124 | | // Destroy the client before shutting down servers. |
125 | 0 | YBCDestroyPgGate(); |
126 | | |
127 | | // Destroy all servers. |
128 | 0 | if (cluster_ != nullptr) { |
129 | 0 | cluster_->Shutdown(); |
130 | 0 | cluster_ = nullptr; |
131 | 0 | } |
132 | 0 | YBTest::TearDown(); |
133 | 0 | } |
134 | | |
135 | 0 | Status PggateTest::Init(const char *test_name, int num_tablet_servers) { |
136 | | // Create cluster before setting client API. |
137 | 0 | RETURN_NOT_OK(CreateCluster(num_tablet_servers)); |
138 | | |
139 | | // Init PgGate API. |
140 | 0 | CHECK_YBC_STATUS(YBCInit(test_name, PggateTestAlloc, PggateTestCStringToTextWithLen)); |
141 | |
|
142 | 0 | const YBCPgTypeEntity *type_table = nullptr; |
143 | 0 | int count = 0; |
144 | 0 | YBCTestGetTypeTable(&type_table, &count); |
145 | 0 | YBCPgCallbacks callbacks; |
146 | 0 | callbacks.FetchUniqueConstraintName = &FetchUniqueConstraintName; |
147 | 0 | callbacks.GetCurrentYbMemctx = &GetCurrentTestYbMemctx; |
148 | 0 | callbacks.GetDebugQueryString = &GetDebugQueryStringStub; |
149 | |
|
150 | 0 | { |
151 | 0 | auto proxy = cluster_->GetProxy<tserver::TabletServerServiceProxy>(cluster_->tablet_server(0)); |
152 | 0 | tserver::GetSharedDataRequestPB req; |
153 | 0 | tserver::GetSharedDataResponsePB resp; |
154 | 0 | rpc::RpcController controller; |
155 | 0 | controller.set_timeout(30s); |
156 | 0 | CHECK_OK(proxy.GetSharedData(req, &resp, &controller)); |
157 | 0 | CHECK_EQ(resp.data().size(), sizeof(*tserver_shared_object_)); |
158 | 0 | memcpy(pointer_cast<char*>(&*tserver_shared_object_), resp.data().c_str(), resp.data().size()); |
159 | 0 | } |
160 | 0 | FLAGS_pggate_tserver_shm_fd = tserver_shared_object_.GetFd(); |
161 | |
|
162 | 0 | YBCInitPgGate(type_table, count, callbacks); |
163 | | |
164 | | // Setup session. |
165 | 0 | CHECK_YBC_STATUS(YBCPgInitSession(nullptr /* pg_env */, nullptr /* database_name */)); |
166 | | |
167 | | // Setup database |
168 | 0 | SetupDB(); |
169 | 0 | return Status::OK(); |
170 | 0 | } |
171 | | |
172 | 0 | Status PggateTest::CreateCluster(int num_tablet_servers) { |
173 | | // Start mini-cluster with given number of tservers (default: 3). |
174 | 0 | ExternalMiniClusterOptions opts; |
175 | 0 | opts.num_tablet_servers = num_tablet_servers; |
176 | 0 | opts.data_root_counter = 0; |
177 | 0 | cluster_ = std::make_shared<ExternalMiniCluster>(opts); |
178 | 0 | CHECK_OK(cluster_->Start()); |
179 | | |
180 | | // Setup master address to construct YBClient. |
181 | 0 | FLAGS_pggate_master_addresses = cluster_->GetMasterAddresses(); |
182 | | |
183 | | // Sleep to make sure the cluster is ready before accepting client messages. |
184 | 0 | sleep(1); |
185 | 0 | return Status::OK(); |
186 | 0 | } |
187 | | |
188 | | //-------------------------------------------------------------------------------------------------- |
189 | | |
190 | 0 | void PggateTest::SetupDB(const string& db_name, const YBCPgOid db_oid) { |
191 | 0 | CreateDB(db_name, db_oid); |
192 | 0 | ConnectDB(db_name); |
193 | 0 | } |
194 | | |
195 | 0 | void PggateTest::CreateDB(const string& db_name, const YBCPgOid db_oid) { |
196 | 0 | YBCPgStatement pg_stmt; |
197 | 0 | CHECK_YBC_STATUS(YBCPgNewCreateDatabase( |
198 | 0 | db_name.c_str(), db_oid, 0 /* source_database_oid */, 0 /* next_oid */, false /* colocated */, |
199 | 0 | &pg_stmt)); |
200 | 0 | CHECK_YBC_STATUS(YBCPgExecCreateDatabase(pg_stmt)); |
201 | 0 | } |
202 | | |
203 | 0 | void PggateTest::ConnectDB(const string& db_name) { |
204 | 0 | CHECK_YBC_STATUS(YBCPgConnectDatabase(db_name.c_str())); |
205 | 0 | } |
206 | | |
207 | 0 | void PggateTest::BeginDDLTransaction() { |
208 | 0 | CHECK_YBC_STATUS(YBCPgEnterSeparateDdlTxnMode()); |
209 | 0 | } |
210 | | |
211 | 0 | void PggateTest::CommitDDLTransaction() { |
212 | 0 | CHECK_YBC_STATUS(YBCPgExitSeparateDdlTxnMode()); |
213 | 0 | } |
214 | | |
215 | 0 | void PggateTest::BeginTransaction() { |
216 | 0 | CHECK_YBC_STATUS(YBCPgBeginTransaction()); |
217 | 0 | } |
218 | | |
219 | 0 | void PggateTest::CommitTransaction() { |
220 | 0 | CHECK_YBC_STATUS(YBCPgCommitTransaction()); |
221 | 0 | } |
222 | | |
223 | | // ------------------------------------------------------------------------------------------------ |
224 | | // Make sure that DataType in common.proto matches the YBCPgDataType enum |
225 | | // TODO: find a better way to generate these enums. |
226 | | |
227 | | static_assert(static_cast<int>(DataType::UNKNOWN_DATA) == |
228 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_UNKNOWN_DATA), |
229 | | "DataType::UNKNOWN_DATA does not match YBCPgDataType::UNKNOWN_DATA"); |
230 | | |
231 | | static_assert(static_cast<int>(DataType::NULL_VALUE_TYPE) == |
232 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_NULL_VALUE_TYPE), |
233 | | "DataType::NULL_VALUE_TYPE does not match YBCPgDataType::NULL_VALUE_TYPE"); |
234 | | |
235 | | static_assert(static_cast<int>(DataType::INT8) == |
236 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_INT8), |
237 | | "DataType::INT8 does not match YBCPgDataType::INT8"); |
238 | | |
239 | | static_assert(static_cast<int>(DataType::INT16) == |
240 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_INT16), |
241 | | "DataType::INT16 does not match YBCPgDataType::INT16"); |
242 | | |
243 | | static_assert(static_cast<int>(DataType::INT32) == |
244 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_INT32), |
245 | | "DataType::INT32 does not match YBCPgDataType::INT32"); |
246 | | |
247 | | static_assert(static_cast<int>(DataType::INT64) == |
248 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_INT64), |
249 | | "DataType::INT64 does not match YBCPgDataType::INT64"); |
250 | | |
251 | | static_assert(static_cast<int>(DataType::STRING) == |
252 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_STRING), |
253 | | "DataType::STRING does not match YBCPgDataType::STRING"); |
254 | | |
255 | | static_assert(static_cast<int>(DataType::BOOL) == |
256 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_BOOL), |
257 | | "DataType::BOOL does not match YBCPgDataType::BOOL"); |
258 | | |
259 | | static_assert(static_cast<int>(DataType::FLOAT) == |
260 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_FLOAT), |
261 | | "DataType::FLOAT does not match YBCPgDataType::FLOAT"); |
262 | | |
263 | | static_assert(static_cast<int>(DataType::DOUBLE) == |
264 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_DOUBLE), |
265 | | "DataType::DOUBLE does not match YBCPgDataType::DOUBLE"); |
266 | | |
267 | | static_assert(static_cast<int>(DataType::BINARY) == |
268 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_BINARY), |
269 | | "DataType::BINARY does not match YBCPgDataType::BINARY"); |
270 | | |
271 | | static_assert(static_cast<int>(DataType::TIMESTAMP) == |
272 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_TIMESTAMP), |
273 | | "DataType::TIMESTAMP does not match YBCPgDataType::TIMESTAMP"); |
274 | | |
275 | | static_assert(static_cast<int>(DataType::DECIMAL) == |
276 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_DECIMAL), |
277 | | "DataType::DECIMAL does not match YBCPgDataType::DECIMAL"); |
278 | | |
279 | | static_assert(static_cast<int>(DataType::VARINT) == |
280 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_VARINT), |
281 | | "DataType::VARINT does not match YBCPgDataType::VARINT"); |
282 | | |
283 | | static_assert(static_cast<int>(DataType::INET) == |
284 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_INET), |
285 | | "DataType::INET does not match YBCPgDataType::INET"); |
286 | | |
287 | | static_assert(static_cast<int>(DataType::LIST) == |
288 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_LIST), |
289 | | "DataType::LIST does not match YBCPgDataType::LIST"); |
290 | | |
291 | | static_assert(static_cast<int>(DataType::MAP) == |
292 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_MAP), |
293 | | "DataType::MAP does not match YBCPgDataType::MAP"); |
294 | | |
295 | | static_assert(static_cast<int>(DataType::SET) == |
296 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_SET), |
297 | | "DataType::SET does not match YBCPgDataType::SET"); |
298 | | |
299 | | static_assert(static_cast<int>(DataType::UUID) == |
300 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_UUID), |
301 | | "DataType::UUID does not match YBCPgDataType::UUID"); |
302 | | |
303 | | static_assert(static_cast<int>(DataType::TIMEUUID) == |
304 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_TIMEUUID), |
305 | | "DataType::TIMEUUID does not match YBCPgDataType::TIMEUUID"); |
306 | | |
307 | | static_assert(static_cast<int>(DataType::TUPLE) == |
308 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_TUPLE), |
309 | | "DataType::TUPLE does not match YBCPgDataType::TUPLE"); |
310 | | |
311 | | static_assert(static_cast<int>(DataType::TYPEARGS) == |
312 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_TYPEARGS), |
313 | | "DataType::TYPEARGS does not match YBCPgDataType::TYPEARGS"); |
314 | | |
315 | | static_assert(static_cast<int>(DataType::USER_DEFINED_TYPE) == |
316 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_USER_DEFINED_TYPE), |
317 | | "DataType::USER_DEFINED_TYPE does not match YBCPgDataType::USER_DEFINED_TYPE"); |
318 | | |
319 | | static_assert(static_cast<int>(DataType::FROZEN) == |
320 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_FROZEN), |
321 | | "DataType::FROZEN does not match YBCPgDataType::FROZEN"); |
322 | | |
323 | | static_assert(static_cast<int>(DataType::DATE) == |
324 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_DATE), |
325 | | "DataType::DATE does not match YBCPgDataType::DATE"); |
326 | | |
327 | | static_assert(static_cast<int>(DataType::TIME) == |
328 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_TIME), |
329 | | "DataType::TIME does not match YBCPgDataType::TIME"); |
330 | | |
331 | | static_assert(static_cast<int>(DataType::JSONB) == |
332 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_JSONB), |
333 | | "DataType::JSONB does not match YBCPgDataType::JSONB"); |
334 | | |
335 | | static_assert(static_cast<int>(DataType::UINT8) == |
336 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_UINT8), |
337 | | "DataType::UINT8 does not match YBCPgDataType::UINT8"); |
338 | | |
339 | | static_assert(static_cast<int>(DataType::UINT16) == |
340 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_UINT16), |
341 | | "DataType::UINT16 does not match YBCPgDataType::UINT16"); |
342 | | |
343 | | static_assert(static_cast<int>(DataType::UINT32) == |
344 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_UINT32), |
345 | | "DataType::UINT32 does not match YBCPgDataType::UINT32"); |
346 | | |
347 | | static_assert(static_cast<int>(DataType::UINT64) == |
348 | | static_cast<int>(YBCPgDataType::YB_YQL_DATA_TYPE_UINT64), |
349 | | "DataType::UINT64 does not match YBCPgDataType::UINT64"); |
350 | | |
351 | | // End of data type enum consistency checking |
352 | | // ------------------------------------------------------------------------------------------------ |
353 | | |
354 | | } // namespace pggate |
355 | | } // namespace yb |