1 /**
2 * @file unit-capi-string_dims.cc
3 *
4 * @section LICENSE
5 *
6 * The MIT License
7 *
8 * @copyright Copyright (c) 2017-2021 TileDB Inc.
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * THE SOFTWARE.
27 *
28 * @section DESCRIPTION
29 *
30 * Tests of C API for sparse arrays with string dimensions.
31 */
32
33 #include "catch.hpp"
34 #include "test/src/helpers.h"
35 #include "test/src/vfs_helpers.h"
36 #ifdef _WIN32
37 #include "tiledb/sm/filesystem/win.h"
38 #else
39 #include "tiledb/sm/filesystem/posix.h"
40 #endif
41 #include "tiledb/sm/c_api/tiledb.h"
42 #include "tiledb/sm/c_api/tiledb_serialization.h"
43 #include "tiledb/sm/enums/serialization_type.h"
44 #include "tiledb/sm/misc/utils.h"
45
46 #include <chrono>
47 #include <iostream>
48 #include <sstream>
49 #include <thread>
50
51 using namespace tiledb::test;
52
53 typedef std::pair<std::string, uint64_t> EstSize;
54
55 struct StringDimsFx {
56 /**
57 * If true, array schema is serialized before submission, to test the
58 * serialization paths.
59 */
60 bool serialize_ = false;
61
62 // TileDB context
63 tiledb_ctx_t* ctx_;
64 tiledb_vfs_t* vfs_;
65
66 // Vector of supported filsystems
67 const std::vector<std::unique_ptr<SupportedFs>> fs_vec_;
68
69 // Used to get the number of directories or files of another directory
70 struct get_num_struct {
71 tiledb_ctx_t* ctx;
72 tiledb_vfs_t* vfs;
73 int num;
74 };
75 static int get_dir_num(const char* path, void* data);
76
77 // Functions
78 StringDimsFx();
79 ~StringDimsFx();
80 void create_temp_dir(const std::string& path);
81 void remove_temp_dir(const std::string& path);
82 std::string random_name(const std::string& prefix);
83 int array_create_wrapper(
84 const std::string& path, tiledb_array_schema_t* array_schema);
85 int array_schema_load_wrapper(
86 const std::string& path, tiledb_array_schema_t** array_schema);
87 void write_array_ascii(const std::string& array_name);
88 void write_array_1d(
89 tiledb_ctx_t* ctx,
90 const std::string& array_name,
91 tiledb_layout_t layout,
92 const std::vector<uint64_t>& d_off,
93 const std::string& d_val,
94 const std::vector<int32_t>& a);
95 void write_array_2d(
96 tiledb_ctx_t* ctx,
97 const std::string& array_name,
98 tiledb_layout_t layout,
99 const std::vector<uint64_t>& d1_off,
100 const std::string& d1_val,
101 const std::vector<int32_t>& d2,
102 const std::vector<int32_t>& a);
103 int tiledb_array_get_non_empty_domain_var_size_from_name_wrapper(
104 tiledb_ctx_t* ctx,
105 tiledb_array_t* array,
106 const char* name,
107 uint64_t* start_size,
108 uint64_t* end_size,
109 int32_t* is_empty);
110 int tiledb_array_get_non_empty_domain_var_from_name_wrapper(
111 tiledb_ctx_t* ctx,
112 tiledb_array_t* array,
113 const char* name,
114 void* start,
115 void* end,
116 int32_t* is_empty);
117 int tiledb_array_get_non_empty_domain_from_name_wrapper(
118 tiledb_ctx_t* ctx,
119 tiledb_array_t* array,
120 const char* name,
121 void* domain,
122 int32_t* is_empty);
123 int tiledb_query_submit_wrapper(
124 tiledb_ctx_t* ctx, tiledb_query_t* query, const std::string& array_uri);
125 void get_non_empty_domain(
126 const std::string& array_name,
127 const std::string& dim_name,
128 std::vector<int32_t>* dom,
129 int32_t* is_empty);
130 void get_non_empty_domain_var(
131 const std::string& array_name,
132 const std::string& dim_name,
133 std::string* start,
134 std::string* end,
135 int32_t* is_empty);
136 void get_est_result_size_var(
137 tiledb_array_t* array,
138 unsigned dim_idx,
139 const std::string& dim_name,
140 const std::string& start,
141 const std::string& end,
142 uint64_t* size_off,
143 uint64_t* size_val);
144 void read_array_1d(
145 tiledb_ctx_t* ctx,
146 tiledb_array_t* array,
147 tiledb_layout_t layout,
148 const std::string& start,
149 const std::string& end,
150 std::vector<uint64_t>* d_off,
151 std::string* d_val,
152 std::vector<int32_t>* a,
153 tiledb_query_status_t* status);
154 void read_array_2d(
155 tiledb_ctx_t* ctx,
156 tiledb_array_t* array,
157 tiledb_layout_t layout,
158 const std::string& d1_start,
159 const std::string& d1_end,
160 int32_t d2_start,
161 int32_t d2_end,
162 std::vector<uint64_t>* d1_off,
163 std::string* d1_val,
164 std::vector<int32_t>* d2,
165 std::vector<int32_t>* a,
166 tiledb_query_status_t* status);
167 };
168
StringDimsFx()169 StringDimsFx::StringDimsFx()
170 : fs_vec_(vfs_test_get_fs_vec()) {
171 // Initialize vfs test
172 REQUIRE(vfs_test_init(fs_vec_, &ctx_, &vfs_).ok());
173 }
174
~StringDimsFx()175 StringDimsFx::~StringDimsFx() {
176 // Close vfs test
177 REQUIRE(vfs_test_close(fs_vec_, ctx_, vfs_).ok());
178 tiledb_vfs_free(&vfs_);
179 tiledb_ctx_free(&ctx_);
180 }
181
create_temp_dir(const std::string & path)182 void StringDimsFx::create_temp_dir(const std::string& path) {
183 remove_temp_dir(path);
184 REQUIRE(tiledb_vfs_create_dir(ctx_, vfs_, path.c_str()) == TILEDB_OK);
185 }
186
remove_temp_dir(const std::string & path)187 void StringDimsFx::remove_temp_dir(const std::string& path) {
188 int is_dir = 0;
189 REQUIRE(tiledb_vfs_is_dir(ctx_, vfs_, path.c_str(), &is_dir) == TILEDB_OK);
190 if (is_dir)
191 REQUIRE(tiledb_vfs_remove_dir(ctx_, vfs_, path.c_str()) == TILEDB_OK);
192 }
193
random_name(const std::string & prefix)194 std::string StringDimsFx::random_name(const std::string& prefix) {
195 std::stringstream ss;
196 ss << prefix << "-" << std::this_thread::get_id() << "-"
197 << TILEDB_TIMESTAMP_NOW_MS;
198 return ss.str();
199 }
200
get_dir_num(const char * path,void * data)201 int StringDimsFx::get_dir_num(const char* path, void* data) {
202 auto data_struct = (StringDimsFx::get_num_struct*)data;
203 auto ctx = data_struct->ctx;
204 auto vfs = data_struct->vfs;
205 int is_dir;
206 int rc = tiledb_vfs_is_dir(ctx, vfs, path, &is_dir);
207 CHECK(rc == TILEDB_OK);
208 auto meta_dir =
209 std::string("/") + tiledb::sm::constants::array_metadata_folder_name;
210 auto schema_dir =
211 std::string("/") + tiledb::sm::constants::array_schema_folder_name;
212 if (!tiledb::sm::utils::parse::ends_with(path, meta_dir) &&
213 !tiledb::sm::utils::parse::ends_with(path, schema_dir)) {
214 // Ignoring the meta folder and the schema folder
215 data_struct->num += is_dir;
216 }
217
218 return 1;
219 }
220
array_schema_load_wrapper(const std::string & path,tiledb_array_schema_t ** array_schema)221 int StringDimsFx::array_schema_load_wrapper(
222 const std::string& path, tiledb_array_schema_t** array_schema) {
223 #ifndef TILEDB_SERIALIZATION
224 return tiledb_array_schema_load(ctx_, path.c_str(), array_schema);
225 #endif
226
227 if (!serialize_) {
228 return tiledb_array_schema_load(ctx_, path.c_str(), array_schema);
229 }
230
231 // Load array.
232 int rc = tiledb_array_schema_load(ctx_, path.c_str(), array_schema);
233 REQUIRE(rc == TILEDB_OK);
234
235 // Serialize the array
236 tiledb_buffer_t* buff;
237 REQUIRE(
238 tiledb_serialize_array_schema(
239 ctx_,
240 *array_schema,
241 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
242 1,
243 &buff) == TILEDB_OK);
244
245 // Load array schema from the rest server
246 tiledb_array_schema_t* new_array_schema = nullptr;
247 REQUIRE(
248 tiledb_deserialize_array_schema(
249 ctx_,
250 buff,
251 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
252 0,
253 &new_array_schema) == TILEDB_OK);
254
255 // Serialize the new array schema and deserialize into the original array
256 // schema.
257 tiledb_array_schema_free(array_schema);
258 tiledb_buffer_t* buff2;
259 REQUIRE(
260 tiledb_serialize_array_schema(
261 ctx_,
262 new_array_schema,
263 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
264 0,
265 &buff2) == TILEDB_OK);
266 REQUIRE(
267 tiledb_deserialize_array_schema(
268 ctx_,
269 buff2,
270 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
271 1,
272 array_schema) == TILEDB_OK);
273
274 // Clean up.
275 tiledb_array_schema_free(&new_array_schema);
276 tiledb_buffer_free(&buff);
277 tiledb_buffer_free(&buff2);
278
279 return rc;
280 }
281
array_create_wrapper(const std::string & path,tiledb_array_schema_t * array_schema)282 int StringDimsFx::array_create_wrapper(
283 const std::string& path, tiledb_array_schema_t* array_schema) {
284 #ifndef TILEDB_SERIALIZATION
285 return tiledb_array_create(ctx_, path.c_str(), array_schema);
286 #endif
287
288 if (!serialize_) {
289 return tiledb_array_create(ctx_, path.c_str(), array_schema);
290 }
291
292 // Serialize the array
293 tiledb_buffer_t* buff;
294 REQUIRE(
295 tiledb_serialize_array_schema(
296 ctx_,
297 array_schema,
298 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
299 1,
300 &buff) == TILEDB_OK);
301
302 // Load array schema from the rest server
303 tiledb_array_schema_t* new_array_schema = nullptr;
304 REQUIRE(
305 tiledb_deserialize_array_schema(
306 ctx_,
307 buff,
308 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
309 0,
310 &new_array_schema) == TILEDB_OK);
311
312 // Create array from new schema
313 int rc = tiledb_array_create(ctx_, path.c_str(), new_array_schema);
314
315 // Serialize the new array schema and deserialize into the original array
316 // schema.
317 tiledb_buffer_t* buff2;
318 tiledb_array_schema_t* new_array_schema2 = nullptr;
319 REQUIRE(
320 tiledb_serialize_array_schema(
321 ctx_,
322 new_array_schema,
323 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
324 0,
325 &buff2) == TILEDB_OK);
326 REQUIRE(
327 tiledb_deserialize_array_schema(
328 ctx_,
329 buff2,
330 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
331 1,
332 &new_array_schema2) == TILEDB_OK);
333
334 // Clean up.
335 tiledb_array_schema_free(&new_array_schema);
336 tiledb_array_schema_free(&new_array_schema2);
337 tiledb_buffer_free(&buff);
338 tiledb_buffer_free(&buff2);
339
340 return rc;
341 }
342
tiledb_query_submit_wrapper(tiledb_ctx_t * ctx,tiledb_query_t * query,const std::string & array_uri)343 int StringDimsFx::tiledb_query_submit_wrapper(
344 tiledb_ctx_t* ctx, tiledb_query_t* query, const std::string& array_uri) {
345 #ifndef TILEDB_SERIALIZATION
346 return tiledb_query_submit(ctx, query);
347 #endif
348
349 if (!serialize_) {
350 return tiledb_query_submit(ctx, query);
351 }
352
353 // Get the query type and layout
354 tiledb_query_type_t query_type;
355 tiledb_layout_t layout;
356 REQUIRE(tiledb_query_get_type(ctx, query, &query_type) == TILEDB_OK);
357 REQUIRE(tiledb_query_get_layout(ctx, query, &layout) == TILEDB_OK);
358
359 // Serialize the query (client-side).
360 tiledb_buffer_list_t* buff_list1;
361 int rc = tiledb_serialize_query(ctx, query, TILEDB_CAPNP, 1, &buff_list1);
362
363 // Global order writes are not (yet) supported for serialization. Just
364 // check that serialization is an error, and then execute the regular query.
365 if (layout == TILEDB_GLOBAL_ORDER && query_type == TILEDB_WRITE) {
366 REQUIRE(rc == TILEDB_ERR);
367 tiledb_buffer_list_free(&buff_list1);
368 return tiledb_query_submit(ctx, query);
369 } else {
370 REQUIRE(rc == TILEDB_OK);
371 }
372
373 // Copy the data to a temporary memory region ("send over the network").
374 tiledb_buffer_t* buff1;
375 REQUIRE(tiledb_buffer_list_flatten(ctx, buff_list1, &buff1) == TILEDB_OK);
376 uint64_t buff1_size;
377 void* buff1_data;
378 REQUIRE(
379 tiledb_buffer_get_data(ctx, buff1, &buff1_data, &buff1_size) ==
380 TILEDB_OK);
381 void* buff1_copy = std::malloc(buff1_size);
382 REQUIRE(buff1_copy != nullptr);
383 std::memcpy(buff1_copy, buff1_data, buff1_size);
384 tiledb_buffer_free(&buff1);
385
386 // Create a new buffer that wraps the data from the temporary buffer.
387 // This mimics what the REST server side would do.
388 tiledb_buffer_t* buff2;
389 REQUIRE(tiledb_buffer_alloc(ctx, &buff2) == TILEDB_OK);
390 REQUIRE(
391 tiledb_buffer_set_data(ctx, buff2, buff1_copy, buff1_size) == TILEDB_OK);
392
393 // Open a new array instance.
394 tiledb_array_t* new_array = nullptr;
395 REQUIRE(tiledb_array_alloc(ctx, array_uri.c_str(), &new_array) == TILEDB_OK);
396 REQUIRE(tiledb_array_open(ctx, new_array, query_type) == TILEDB_OK);
397
398 // Create a new query and deserialize from the buffer (server-side)
399 tiledb_query_t* new_query = nullptr;
400 REQUIRE(
401 tiledb_query_alloc(ctx, new_array, query_type, &new_query) == TILEDB_OK);
402 REQUIRE(
403 tiledb_deserialize_query(ctx, buff2, TILEDB_CAPNP, 0, new_query) ==
404 TILEDB_OK);
405
406 // Next, for reads, allocate buffers for the new query.
407 std::vector<void*> to_free;
408 if (query_type == TILEDB_READ) {
409 tiledb_array_schema_t* schema;
410 REQUIRE(tiledb_array_get_schema(ctx, new_array, &schema) == TILEDB_OK);
411 uint32_t num_attributes;
412 REQUIRE(
413 tiledb_array_schema_get_attribute_num(ctx, schema, &num_attributes) ==
414 TILEDB_OK);
415 for (uint32_t i = 0; i < num_attributes; i++) {
416 tiledb_attribute_t* attr;
417 REQUIRE(
418 tiledb_array_schema_get_attribute_from_index(ctx, schema, i, &attr) ==
419 TILEDB_OK);
420 const char* name;
421 REQUIRE(tiledb_attribute_get_name(ctx, attr, &name) == TILEDB_OK);
422 uint32_t cell_num;
423 REQUIRE(
424 tiledb_attribute_get_cell_val_num(ctx, attr, &cell_num) == TILEDB_OK);
425 bool var_len = cell_num == TILEDB_VAR_NUM;
426
427 if (var_len) {
428 void* buff;
429 uint64_t* buff_size;
430 uint64_t* offset_buff;
431 uint64_t* offset_buff_size;
432 REQUIRE(
433 tiledb_query_get_data_buffer(
434 ctx, new_query, name, &buff, &buff_size) == TILEDB_OK);
435 REQUIRE(
436 tiledb_query_get_offsets_buffer(
437 ctx, new_query, name, &offset_buff, &offset_buff_size) ==
438 TILEDB_OK);
439 // Buffers will always be null after deserialization on server side
440 REQUIRE(buff == nullptr);
441 REQUIRE(offset_buff == nullptr);
442 if (buff_size != nullptr) {
443 // Buffer size was set for the attribute; allocate one of the
444 // appropriate size.
445 buff = std::malloc(*buff_size);
446 offset_buff = (uint64_t*)std::malloc(*offset_buff_size);
447 to_free.push_back(buff);
448 to_free.push_back(offset_buff);
449
450 REQUIRE(
451 tiledb_query_set_data_buffer(
452 ctx, new_query, name, buff, buff_size) == TILEDB_OK);
453 REQUIRE(
454 tiledb_query_set_offsets_buffer(
455 ctx, new_query, name, offset_buff, offset_buff_size) ==
456 TILEDB_OK);
457 }
458 } else {
459 void* buff;
460 uint64_t* buff_size;
461 REQUIRE(
462 tiledb_query_get_data_buffer(
463 ctx, new_query, name, &buff, &buff_size) == TILEDB_OK);
464 // Buffers will always be null after deserialization on server side
465 REQUIRE(buff == nullptr);
466 if (buff_size != nullptr) {
467 // Buffer size was set for the attribute; allocate one of the
468 // appropriate size.
469 buff = std::malloc(*buff_size);
470 to_free.push_back(buff);
471 REQUIRE(
472 tiledb_query_set_data_buffer(
473 ctx, new_query, name, buff, buff_size) == TILEDB_OK);
474 }
475 }
476
477 tiledb_attribute_free(&attr);
478 }
479
480 // Repeat for coords
481 void* buff;
482 uint64_t* buff_size;
483 REQUIRE(
484 tiledb_query_get_data_buffer(
485 ctx, new_query, TILEDB_COORDS, &buff, &buff_size) == TILEDB_OK);
486 if (buff_size != nullptr) {
487 buff = std::malloc(*buff_size);
488 to_free.push_back(buff);
489 REQUIRE(
490 tiledb_query_set_data_buffer(
491 ctx, new_query, TILEDB_COORDS, buff, buff_size) == TILEDB_OK);
492 }
493
494 // Repeat for split dimensions, if they are set we will set the buffer
495 uint32_t num_dimension;
496 tiledb_domain_t* domain;
497 REQUIRE(tiledb_array_schema_get_domain(ctx, schema, &domain) == TILEDB_OK);
498 REQUIRE(tiledb_domain_get_ndim(ctx, domain, &num_dimension) == TILEDB_OK);
499
500 for (uint32_t i = 0; i < num_dimension; i++) {
501 tiledb_dimension_t* dim;
502 REQUIRE(
503 tiledb_domain_get_dimension_from_index(ctx, domain, i, &dim) ==
504 TILEDB_OK);
505 const char* name;
506 REQUIRE(tiledb_dimension_get_name(ctx, dim, &name) == TILEDB_OK);
507
508 void* buff = nullptr;
509 uint64_t* buff_size = nullptr;
510 uint64_t* offset_buff = nullptr;
511 uint64_t* offset_buff_size = nullptr;
512
513 uint32_t cell_val_num = 0;
514 REQUIRE(
515 tiledb_dimension_get_cell_val_num(ctx, dim, &cell_val_num) ==
516 TILEDB_OK);
517
518 if (cell_val_num == TILEDB_VAR_NUM) {
519 REQUIRE(
520 tiledb_query_get_data_buffer(
521 ctx, new_query, name, &buff, &buff_size) == TILEDB_OK);
522 REQUIRE(
523 tiledb_query_get_offsets_buffer(
524 ctx, new_query, name, &offset_buff, &offset_buff_size) ==
525 TILEDB_OK);
526 } else {
527 REQUIRE(
528 tiledb_query_get_data_buffer(
529 ctx, new_query, name, &buff, &buff_size) == TILEDB_OK);
530 }
531 // Buffers will always be null after deserialization on server side
532 REQUIRE(buff == nullptr);
533 REQUIRE(offset_buff == nullptr);
534 if (offset_buff_size != nullptr) {
535 // Buffer size was set for the attribute; allocate one of the
536 // appropriate size.
537 offset_buff = static_cast<uint64_t*>(std::malloc(*offset_buff_size));
538 to_free.push_back(offset_buff);
539 buff = std::malloc(*buff_size);
540 to_free.push_back(buff);
541 REQUIRE(
542 tiledb_query_set_data_buffer(
543 ctx, new_query, name, buff, buff_size) == TILEDB_OK);
544 REQUIRE(
545 tiledb_query_set_offsets_buffer(
546 ctx, new_query, name, offset_buff, offset_buff_size) ==
547 TILEDB_OK);
548 } else if (buff_size != nullptr) {
549 // Buffer size was set for the attribute; allocate one of the
550 // appropriate size.
551 buff = std::malloc(*buff_size);
552 to_free.push_back(buff);
553 REQUIRE(
554 tiledb_query_set_data_buffer(
555 ctx, new_query, name, buff, buff_size) == TILEDB_OK);
556 }
557 tiledb_dimension_free(&dim);
558 }
559
560 tiledb_domain_free(&domain);
561 tiledb_array_schema_free(&schema);
562 }
563
564 // Submit the new query ("on the server").
565 rc = tiledb_query_submit(ctx, new_query);
566
567 // Serialize the new query and "send it over the network" (server-side)
568 tiledb_buffer_list_t* buff_list2;
569 REQUIRE(
570 tiledb_serialize_query(ctx, new_query, TILEDB_CAPNP, 0, &buff_list2) ==
571 TILEDB_OK);
572 tiledb_buffer_t* buff3;
573 REQUIRE(tiledb_buffer_list_flatten(ctx, buff_list2, &buff3) == TILEDB_OK);
574 uint64_t buff3_size;
575 void* buff3_data;
576 REQUIRE(
577 tiledb_buffer_get_data(ctx, buff3, &buff3_data, &buff3_size) ==
578 TILEDB_OK);
579 void* buff3_copy = std::malloc(buff3_size);
580 REQUIRE(buff3_copy != nullptr);
581 std::memcpy(buff3_copy, buff3_data, buff3_size);
582 tiledb_buffer_free(&buff2);
583 tiledb_buffer_free(&buff3);
584
585 // Create a new buffer that wraps the data from the temporary buffer.
586 tiledb_buffer_t* buff4;
587 REQUIRE(tiledb_buffer_alloc(ctx, &buff4) == TILEDB_OK);
588 REQUIRE(
589 tiledb_buffer_set_data(ctx, buff4, buff3_copy, buff3_size) == TILEDB_OK);
590
591 // Deserialize into the original query. Client-side
592 REQUIRE(
593 tiledb_deserialize_query(ctx, buff4, TILEDB_CAPNP, 1, query) ==
594 TILEDB_OK);
595
596 // Clean up.
597 REQUIRE(tiledb_array_close(ctx, new_array) == TILEDB_OK);
598 tiledb_query_free(&new_query);
599 tiledb_array_free(&new_array);
600 tiledb_buffer_free(&buff4);
601 tiledb_buffer_list_free(&buff_list1);
602 tiledb_buffer_list_free(&buff_list2);
603 std::free(buff1_copy);
604 std::free(buff3_copy);
605 for (void* b : to_free)
606 std::free(b);
607
608 return rc;
609 }
610
write_array_ascii(const std::string & array_name)611 void StringDimsFx::write_array_ascii(const std::string& array_name) {
612 // Open array
613 tiledb_array_t* array;
614 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
615 CHECK(rc == TILEDB_OK);
616 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
617 CHECK(rc == TILEDB_OK);
618
619 // Create and submit query
620 tiledb_query_t* query;
621 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
622 REQUIRE(rc == TILEDB_OK);
623
624 char d_data[] = "aabbbcdddd";
625 uint64_t d_data_size = strlen(d_data);
626 uint64_t d_off[] = {0, 2, 5, 6};
627 uint64_t d_off_size = sizeof(d_off);
628 int32_t a_data[] = {1, 2, 3, 4};
629 uint64_t a_size = sizeof(a_data);
630 rc = tiledb_query_set_data_buffer(ctx_, query, "d", d_data, &d_data_size);
631 REQUIRE(rc == TILEDB_ERR);
632 rc = tiledb_query_set_data_buffer(ctx_, query, "d", d_data, &d_data_size);
633 REQUIRE(rc == TILEDB_OK);
634 rc = tiledb_query_set_offsets_buffer(ctx_, query, "d", d_off, &d_off_size);
635 REQUIRE(rc == TILEDB_OK);
636 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a_data, &a_size);
637 REQUIRE(rc == TILEDB_OK);
638 rc = tiledb_query_set_layout(ctx_, query, TILEDB_GLOBAL_ORDER);
639 REQUIRE(rc == TILEDB_OK);
640 rc = tiledb_query_submit_wrapper(ctx_, query, array_name);
641 REQUIRE(rc == TILEDB_OK);
642 rc = tiledb_query_finalize(ctx_, query);
643 REQUIRE(rc == TILEDB_OK);
644
645 // Close array
646 rc = tiledb_array_close(ctx_, array);
647 CHECK(rc == TILEDB_OK);
648
649 // Clean up
650 tiledb_array_free(&array);
651 tiledb_query_free(&query);
652 }
653
write_array_1d(tiledb_ctx_t * ctx,const std::string & array_name,tiledb_layout_t layout,const std::vector<uint64_t> & d_off,const std::string & d_val,const std::vector<int32_t> & a)654 void StringDimsFx::write_array_1d(
655 tiledb_ctx_t* ctx,
656 const std::string& array_name,
657 tiledb_layout_t layout,
658 const std::vector<uint64_t>& d_off,
659 const std::string& d_val,
660 const std::vector<int32_t>& a) {
661 // Open array
662 tiledb_array_t* array;
663 int rc = tiledb_array_alloc(ctx, array_name.c_str(), &array);
664 CHECK(rc == TILEDB_OK);
665 rc = tiledb_array_open(ctx, array, TILEDB_WRITE);
666 CHECK(rc == TILEDB_OK);
667
668 // Create and submit query
669 tiledb_query_t* query;
670 rc = tiledb_query_alloc(ctx, array, TILEDB_WRITE, &query);
671 REQUIRE(rc == TILEDB_OK);
672
673 uint64_t d_off_size = d_off.size() * sizeof(uint64_t);
674 uint64_t d_val_size = d_val.size();
675 uint64_t a_size = a.size() * sizeof(int32_t);
676 rc = tiledb_query_set_data_buffer(
677 ctx, query, "d", (void*)&d_val[0], &d_val_size);
678 REQUIRE(rc == TILEDB_OK);
679 rc = tiledb_query_set_offsets_buffer(
680 ctx, query, "d", (uint64_t*)&d_off[0], &d_off_size);
681 REQUIRE(rc == TILEDB_OK);
682 rc = tiledb_query_set_data_buffer(ctx, query, "a", (void*)a.data(), &a_size);
683 REQUIRE(rc == TILEDB_OK);
684 rc = tiledb_query_set_layout(ctx, query, layout);
685 REQUIRE(rc == TILEDB_OK);
686 rc = tiledb_query_submit_wrapper(ctx, query, array_name);
687 REQUIRE(rc == TILEDB_OK);
688 rc = tiledb_query_finalize(ctx, query);
689 REQUIRE(rc == TILEDB_OK);
690
691 // Close array
692 rc = tiledb_array_close(ctx, array);
693 CHECK(rc == TILEDB_OK);
694
695 // Clean up
696 tiledb_array_free(&array);
697 tiledb_query_free(&query);
698 }
699
write_array_2d(tiledb_ctx_t * ctx,const std::string & array_name,tiledb_layout_t layout,const std::vector<uint64_t> & d1_off,const std::string & d1_val,const std::vector<int32_t> & d2,const std::vector<int32_t> & a)700 void StringDimsFx::write_array_2d(
701 tiledb_ctx_t* ctx,
702 const std::string& array_name,
703 tiledb_layout_t layout,
704 const std::vector<uint64_t>& d1_off,
705 const std::string& d1_val,
706 const std::vector<int32_t>& d2,
707 const std::vector<int32_t>& a) {
708 // Open array
709 tiledb_array_t* array;
710 int rc = tiledb_array_alloc(ctx, array_name.c_str(), &array);
711 CHECK(rc == TILEDB_OK);
712 rc = tiledb_array_open(ctx, array, TILEDB_WRITE);
713 CHECK(rc == TILEDB_OK);
714
715 // Create and submit query
716 tiledb_query_t* query;
717 rc = tiledb_query_alloc(ctx, array, TILEDB_WRITE, &query);
718 REQUIRE(rc == TILEDB_OK);
719
720 uint64_t d1_off_size = d1_off.size() * sizeof(uint64_t);
721 uint64_t d1_val_size = d1_val.size();
722 uint64_t d2_size = d2.size() * sizeof(int32_t);
723 uint64_t a_size = a.size() * sizeof(int32_t);
724 rc = tiledb_query_set_data_buffer(
725 ctx, query, "d1", (void*)&d1_val[0], &d1_val_size);
726 REQUIRE(rc == TILEDB_OK);
727 rc = tiledb_query_set_offsets_buffer(
728 ctx, query, "d1", (uint64_t*)&d1_off[0], &d1_off_size);
729 REQUIRE(rc == TILEDB_OK);
730 rc = tiledb_query_set_data_buffer(
731 ctx, query, "d2", (void*)d2.data(), &d2_size);
732 REQUIRE(rc == TILEDB_OK);
733 rc = tiledb_query_set_data_buffer(ctx, query, "a", (void*)a.data(), &a_size);
734 REQUIRE(rc == TILEDB_OK);
735 rc = tiledb_query_set_layout(ctx, query, layout);
736 REQUIRE(rc == TILEDB_OK);
737 rc = tiledb_query_submit_wrapper(ctx, query, array_name);
738 REQUIRE(rc == TILEDB_OK);
739 rc = tiledb_query_finalize(ctx, query);
740 REQUIRE(rc == TILEDB_OK);
741
742 // Close array
743 rc = tiledb_array_close(ctx, array);
744 CHECK(rc == TILEDB_OK);
745
746 // Clean up
747 tiledb_array_free(&array);
748 tiledb_query_free(&query);
749 }
750
tiledb_array_get_non_empty_domain_from_name_wrapper(tiledb_ctx_t * ctx,tiledb_array_t * array,const char * name,void * domain,int32_t * is_empty)751 int StringDimsFx::tiledb_array_get_non_empty_domain_from_name_wrapper(
752 tiledb_ctx_t* ctx,
753 tiledb_array_t* array,
754 const char* name,
755 void* domain,
756 int32_t* is_empty) {
757 int ret = tiledb_array_get_non_empty_domain_from_name(
758 ctx, array, name, domain, is_empty);
759 #ifndef TILEDB_SERIALIZATION
760 return ret;
761 #endif
762
763 if (ret != TILEDB_OK || !serialize_)
764 return ret;
765
766 // Serialize the non_empty_domain
767 tiledb_buffer_t* buff;
768 REQUIRE(
769 tiledb_serialize_array_non_empty_domain_all_dimensions(
770 ctx,
771 array,
772 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
773 0,
774 &buff) == TILEDB_OK);
775
776 // Deserialize to validate we can round-trip
777 REQUIRE(
778 tiledb_deserialize_array_non_empty_domain_all_dimensions(
779 ctx,
780 array,
781 buff,
782 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
783 1) == TILEDB_OK);
784
785 tiledb_buffer_free(&buff);
786
787 return tiledb_array_get_non_empty_domain_from_name(
788 ctx, array, name, domain, is_empty);
789 }
790
get_non_empty_domain(const std::string & array_name,const std::string & dim_name,std::vector<int32_t> * dom,int32_t * is_empty)791 void StringDimsFx::get_non_empty_domain(
792 const std::string& array_name,
793 const std::string& dim_name,
794 std::vector<int32_t>* dom,
795 int32_t* is_empty) {
796 dom->resize(2);
797
798 // Open array
799 tiledb_array_t* array;
800 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
801 CHECK(rc == TILEDB_OK);
802 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
803 CHECK(rc == TILEDB_OK);
804
805 // Get non-empty domain
806 rc = tiledb_array_get_non_empty_domain_from_name_wrapper(
807 ctx_, array, dim_name.c_str(), &(*dom)[0], is_empty);
808 CHECK(rc == TILEDB_OK);
809
810 // Close array
811 rc = tiledb_array_close(ctx_, array);
812 CHECK(rc == TILEDB_OK);
813
814 // Clean up
815 tiledb_array_free(&array);
816 }
817
tiledb_array_get_non_empty_domain_var_size_from_name_wrapper(tiledb_ctx_t * ctx,tiledb_array_t * array,const char * name,uint64_t * start_size,uint64_t * end_size,int32_t * is_empty)818 int StringDimsFx::tiledb_array_get_non_empty_domain_var_size_from_name_wrapper(
819 tiledb_ctx_t* ctx,
820 tiledb_array_t* array,
821 const char* name,
822 uint64_t* start_size,
823 uint64_t* end_size,
824 int32_t* is_empty) {
825 int ret = tiledb_array_get_non_empty_domain_var_size_from_name(
826 ctx, array, name, start_size, end_size, is_empty);
827 #ifndef TILEDB_SERIALIZATION
828 return ret;
829 #endif
830
831 if (ret != TILEDB_OK || !serialize_)
832 return ret;
833
834 // Serialize the non_empty_domain
835 tiledb_buffer_t* buff;
836 REQUIRE(
837 tiledb_serialize_array_non_empty_domain_all_dimensions(
838 ctx,
839 array,
840 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
841 0,
842 &buff) == TILEDB_OK);
843
844 // Deserialize to validate we can round-trip
845 REQUIRE(
846 tiledb_deserialize_array_non_empty_domain_all_dimensions(
847 ctx,
848 array,
849 buff,
850 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
851 1) == TILEDB_OK);
852
853 tiledb_buffer_free(&buff);
854
855 return tiledb_array_get_non_empty_domain_var_size_from_name(
856 ctx, array, name, start_size, end_size, is_empty);
857 }
858
tiledb_array_get_non_empty_domain_var_from_name_wrapper(tiledb_ctx_t * ctx,tiledb_array_t * array,const char * name,void * start,void * end,int32_t * is_empty)859 int StringDimsFx::tiledb_array_get_non_empty_domain_var_from_name_wrapper(
860 tiledb_ctx_t* ctx,
861 tiledb_array_t* array,
862 const char* name,
863 void* start,
864 void* end,
865 int32_t* is_empty) {
866 int ret = tiledb_array_get_non_empty_domain_var_from_name(
867 ctx, array, name, start, end, is_empty);
868 #ifndef TILEDB_SERIALIZATION
869 return ret;
870 #endif
871
872 if (ret != TILEDB_OK || !serialize_)
873 return ret;
874
875 // Serialize the non_empty_domain
876 tiledb_buffer_t* buff;
877 REQUIRE(
878 tiledb_serialize_array_non_empty_domain_all_dimensions(
879 ctx,
880 array,
881 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
882 0,
883 &buff) == TILEDB_OK);
884
885 // Deserialize to validate we can round-trip
886 REQUIRE(
887 tiledb_deserialize_array_non_empty_domain_all_dimensions(
888 ctx,
889 array,
890 buff,
891 (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
892 1) == TILEDB_OK);
893
894 tiledb_buffer_free(&buff);
895
896 return tiledb_array_get_non_empty_domain_var_from_name(
897 ctx, array, name, start, end, is_empty);
898 }
899
get_non_empty_domain_var(const std::string & array_name,const std::string & dim_name,std::string * start,std::string * end,int32_t * is_empty)900 void StringDimsFx::get_non_empty_domain_var(
901 const std::string& array_name,
902 const std::string& dim_name,
903 std::string* start,
904 std::string* end,
905 int32_t* is_empty) {
906 // Open array
907 tiledb_array_t* array;
908 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
909 CHECK(rc == TILEDB_OK);
910 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
911 CHECK(rc == TILEDB_OK);
912
913 // Get non-empty domain size
914 uint64_t start_size = 0, end_size = 0;
915 rc = tiledb_array_get_non_empty_domain_var_size_from_name_wrapper(
916 ctx_, array, dim_name.c_str(), &start_size, &end_size, is_empty);
917 CHECK(rc == TILEDB_OK);
918
919 // Get non-empty domain
920 start->resize(start_size);
921 end->resize(end_size);
922 rc = tiledb_array_get_non_empty_domain_var_from_name_wrapper(
923 ctx_, array, dim_name.c_str(), &(*start)[0], &(*end)[0], is_empty);
924 CHECK(rc == TILEDB_OK);
925
926 // Close array
927 rc = tiledb_array_close(ctx_, array);
928 CHECK(rc == TILEDB_OK);
929
930 // Clean up
931 tiledb_array_free(&array);
932 }
933
get_est_result_size_var(tiledb_array_t * array,unsigned dim_idx,const std::string & dim_name,const std::string & start,const std::string & end,uint64_t * size_off,uint64_t * size_val)934 void StringDimsFx::get_est_result_size_var(
935 tiledb_array_t* array,
936 unsigned dim_idx,
937 const std::string& dim_name,
938 const std::string& start,
939 const std::string& end,
940 uint64_t* size_off,
941 uint64_t* size_val) {
942 tiledb_query_t* query;
943 int rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
944 CHECK(rc == TILEDB_OK);
945 rc = tiledb_query_add_range_var(
946 ctx_, query, dim_idx, start.data(), start.size(), end.data(), end.size());
947 CHECK(rc == TILEDB_OK);
948 rc = tiledb_query_get_est_result_size_var(
949 ctx_, query, dim_name.c_str(), size_off, size_val);
950 CHECK(rc == TILEDB_OK);
951 tiledb_query_free(&query);
952 }
953
read_array_1d(tiledb_ctx_t * ctx,tiledb_array_t * array,tiledb_layout_t layout,const std::string & start,const std::string & end,std::vector<uint64_t> * d_off,std::string * d_val,std::vector<int32_t> * a,tiledb_query_status_t * status)954 void StringDimsFx::read_array_1d(
955 tiledb_ctx_t* ctx,
956 tiledb_array_t* array,
957 tiledb_layout_t layout,
958 const std::string& start,
959 const std::string& end,
960 std::vector<uint64_t>* d_off,
961 std::string* d_val,
962 std::vector<int32_t>* a,
963 tiledb_query_status_t* status) {
964 // Create query
965 tiledb_query_t* query;
966 int rc = tiledb_query_alloc(ctx, array, TILEDB_READ, &query);
967 CHECK(rc == TILEDB_OK);
968 rc = tiledb_query_add_range_var(
969 ctx, query, 0, start.data(), start.size(), end.data(), end.size());
970 CHECK(rc == TILEDB_OK);
971
972 // Check range num
973 uint64_t range_num;
974 rc = tiledb_query_get_range_num(ctx_, query, 0, &range_num);
975 CHECK(rc == TILEDB_OK);
976 CHECK(range_num == 1);
977
978 // Check getting range from an invalid range index
979 uint64_t start_size = 0, end_size = 0;
980 rc = tiledb_query_get_range_var_size(
981 ctx_, query, 0, 2, &start_size, &end_size);
982 CHECK(rc == TILEDB_ERR);
983 std::vector<char> start_data(start_size);
984 std::vector<char> end_data(end_size);
985 rc = tiledb_query_get_range_var(
986 ctx_, query, 0, 2, start_data.data(), end_data.data());
987 CHECK(rc == TILEDB_ERR);
988
989 // Check ranges
990 rc = tiledb_query_get_range_var_size(
991 ctx_, query, 0, 0, &start_size, &end_size);
992 CHECK(rc == TILEDB_OK);
993 start_data.resize(start_size);
994 end_data.resize(end_size);
995 rc = tiledb_query_get_range_var(
996 ctx_, query, 0, 0, start_data.data(), end_data.data());
997 CHECK(rc == TILEDB_OK);
998 CHECK(std::string(start_data.data(), start_data.size()) == start);
999 CHECK(std::string(end_data.data(), end_data.size()) == end);
1000
1001 // Set query buffers
1002 uint64_t d_off_size = d_off->size() * sizeof(uint64_t);
1003 uint64_t d_val_size = d_val->size();
1004 uint64_t a_size = a->size() * sizeof(int32_t);
1005 rc = tiledb_query_set_data_buffer(
1006 ctx, query, "d", (void*)d_val->data(), &d_val_size);
1007 REQUIRE(rc == TILEDB_OK);
1008 rc = tiledb_query_set_offsets_buffer(
1009 ctx, query, "d", (uint64_t*)d_off->data(), &d_off_size);
1010 REQUIRE(rc == TILEDB_OK);
1011 rc = tiledb_query_set_data_buffer(ctx, query, "a", a->data(), &a_size);
1012 REQUIRE(rc == TILEDB_OK);
1013
1014 // Set layout
1015 rc = tiledb_query_set_layout(ctx, query, layout);
1016 REQUIRE(rc == TILEDB_OK);
1017
1018 // Submit query
1019 const char* array_uri;
1020 rc = tiledb_array_get_uri(ctx, array, &array_uri);
1021 CHECK(rc == TILEDB_OK);
1022 rc = tiledb_query_submit_wrapper(ctx, query, array_uri);
1023 CHECK(rc == TILEDB_OK);
1024
1025 // Get status
1026 rc = tiledb_query_get_status(ctx, query, status);
1027 CHECK(rc == TILEDB_OK);
1028
1029 // Resize the result buffers
1030 d_off->resize(d_off_size / sizeof(uint64_t));
1031 d_val->resize(d_val_size / sizeof(char));
1032 a->resize(a_size / sizeof(int32_t));
1033
1034 // Clean up
1035 tiledb_query_free(&query);
1036 }
1037
read_array_2d(tiledb_ctx_t * ctx,tiledb_array_t * array,tiledb_layout_t layout,const std::string & d1_start,const std::string & d1_end,int32_t d2_start,int32_t d2_end,std::vector<uint64_t> * d1_off,std::string * d1_val,std::vector<int32_t> * d2,std::vector<int32_t> * a,tiledb_query_status_t * status)1038 void StringDimsFx::read_array_2d(
1039 tiledb_ctx_t* ctx,
1040 tiledb_array_t* array,
1041 tiledb_layout_t layout,
1042 const std::string& d1_start,
1043 const std::string& d1_end,
1044 int32_t d2_start,
1045 int32_t d2_end,
1046 std::vector<uint64_t>* d1_off,
1047 std::string* d1_val,
1048 std::vector<int32_t>* d2,
1049 std::vector<int32_t>* a,
1050 tiledb_query_status_t* status) {
1051 // Create query
1052 tiledb_query_t* query;
1053 int rc = tiledb_query_alloc(ctx, array, TILEDB_READ, &query);
1054 CHECK(rc == TILEDB_OK);
1055 rc = tiledb_query_add_range_var(
1056 ctx,
1057 query,
1058 0,
1059 d1_start.data(),
1060 d1_start.size(),
1061 d1_end.data(),
1062 d1_end.size());
1063 CHECK(rc == TILEDB_OK);
1064 rc = tiledb_query_add_range(ctx, query, 1, &d2_start, &d2_end, nullptr);
1065 CHECK(rc == TILEDB_OK);
1066
1067 // Check range num d1
1068 uint64_t range_num;
1069 rc = tiledb_query_get_range_num(ctx_, query, 0, &range_num);
1070 CHECK(rc == TILEDB_OK);
1071 CHECK(range_num == 1);
1072 // Check range num d2
1073 rc = tiledb_query_get_range_num(ctx_, query, 1, &range_num);
1074 CHECK(rc == TILEDB_OK);
1075 CHECK(range_num == 1);
1076
1077 // Check getting range from an invalid range index
1078 uint64_t d1_start_size = 0, d1_end_size = 0;
1079 rc = tiledb_query_get_range_var_size(
1080 ctx_, query, 0, 2, &d1_start_size, &d1_end_size);
1081 CHECK(rc == TILEDB_ERR);
1082 std::vector<char> d1_start_data(d1_start_size);
1083 std::vector<char> d1_end_data(d1_end_size);
1084 rc = tiledb_query_get_range_var(
1085 ctx_, query, 0, 2, d1_start_data.data(), d1_end_data.data());
1086 CHECK(rc == TILEDB_ERR);
1087
1088 // Check ranges
1089 rc = tiledb_query_get_range_var_size(
1090 ctx_, query, 0, 0, &d1_start_size, &d1_end_size);
1091 CHECK(rc == TILEDB_OK);
1092 d1_start_data.resize(d1_start_size);
1093 d1_end_data.resize(d1_end_size);
1094 rc = tiledb_query_get_range_var(
1095 ctx_, query, 0, 0, d1_start_data.data(), d1_end_data.data());
1096 CHECK(rc == TILEDB_OK);
1097 CHECK(std::string(d1_start_data.data(), d1_start_data.size()) == d1_start);
1098 CHECK(std::string(d1_end_data.data(), d1_end_data.size()) == d1_end);
1099
1100 const void *d2_start_data, *d2_end_data, *stride;
1101 rc = tiledb_query_get_range(
1102 ctx_, query, 1, 0, &d2_start_data, &d2_end_data, &stride);
1103 CHECK(rc == TILEDB_OK);
1104 CHECK(*(int32_t*)d2_start_data == d2_start);
1105 CHECK(*(int32_t*)d2_end_data == d2_end);
1106 CHECK(stride == nullptr);
1107
1108 // Set query buffers
1109 uint64_t d1_off_size = d1_off->size() * sizeof(uint64_t);
1110 uint64_t d1_val_size = d1_val->size();
1111 uint64_t d2_size = d2->size() * sizeof(int32_t);
1112 uint64_t a_size = a->size() * sizeof(int32_t);
1113 rc = tiledb_query_set_data_buffer(
1114 ctx, query, "d1", (void*)d1_val->data(), &d1_val_size);
1115 REQUIRE(rc == TILEDB_OK);
1116 rc = tiledb_query_set_offsets_buffer(
1117 ctx, query, "d1", (uint64_t*)d1_off->data(), &d1_off_size);
1118 REQUIRE(rc == TILEDB_OK);
1119 rc = tiledb_query_set_data_buffer(ctx, query, "d2", d2->data(), &d2_size);
1120 REQUIRE(rc == TILEDB_OK);
1121 rc = tiledb_query_set_data_buffer(ctx, query, "a", a->data(), &a_size);
1122 REQUIRE(rc == TILEDB_OK);
1123
1124 // Set layout
1125 rc = tiledb_query_set_layout(ctx, query, layout);
1126 REQUIRE(rc == TILEDB_OK);
1127
1128 // Submit query
1129 const char* array_uri;
1130 rc = tiledb_array_get_uri(ctx, array, &array_uri);
1131 CHECK(rc == TILEDB_OK);
1132 rc = tiledb_query_submit_wrapper(ctx, query, array_uri);
1133 CHECK(rc == TILEDB_OK);
1134
1135 // Get status
1136 rc = tiledb_query_get_status(ctx, query, status);
1137 CHECK(rc == TILEDB_OK);
1138
1139 // Resize the result buffers
1140 d1_off->resize(d1_off_size / sizeof(uint64_t));
1141 d1_val->resize(d1_val_size / sizeof(char));
1142 d2->resize(d2_size / sizeof(int32_t));
1143 a->resize(a_size / sizeof(int32_t));
1144
1145 // Clean up
1146 tiledb_query_free(&query);
1147 }
1148
1149 TEST_CASE_METHOD(
1150 StringDimsFx,
1151 "C API: Test sparse array with string dimensions, array schema",
1152 "[capi][sparse][string-dims][array-schema]") {
1153 SECTION("- No serialization") {
1154 serialize_ = false;
1155 }
1156 SECTION("- Serialization") {
1157 serialize_ = true;
1158 }
1159 SupportedFsLocal local_fs;
1160 std::string array_name =
1161 local_fs.file_prefix() + local_fs.temp_dir() + "string_dims";
1162 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1163
1164 // Create dimension
1165 tiledb_domain_t* domain;
1166 tiledb_dimension_t* d;
1167 char tmp;
1168 int rc =
1169 tiledb_dimension_alloc(ctx_, "d", TILEDB_STRING_ASCII, &tmp, nullptr, &d);
1170 REQUIRE(rc == TILEDB_ERR);
1171 rc =
1172 tiledb_dimension_alloc(ctx_, "d", TILEDB_STRING_ASCII, nullptr, &tmp, &d);
1173 REQUIRE(rc == TILEDB_ERR);
1174 rc = tiledb_dimension_alloc(
1175 ctx_, "d", TILEDB_STRING_ASCII, nullptr, nullptr, &d);
1176 REQUIRE(rc == TILEDB_OK);
1177
1178 // Setting cell val num to a TILEDB_STRING_ASCII dimension should error out
1179 rc = tiledb_dimension_set_cell_val_num(ctx_, d, 4);
1180 REQUIRE(rc == TILEDB_ERR);
1181 rc = tiledb_dimension_set_cell_val_num(ctx_, d, TILEDB_VAR_NUM);
1182 REQUIRE(rc == TILEDB_OK);
1183
1184 // Create domain
1185 rc = tiledb_domain_alloc(ctx_, &domain);
1186 REQUIRE(rc == TILEDB_OK);
1187 rc = tiledb_domain_add_dimension(ctx_, domain, d);
1188 REQUIRE(rc == TILEDB_OK);
1189
1190 // Setting a string dimension to a dense array should error out
1191 tiledb_array_schema_t* array_schema;
1192 rc = tiledb_array_schema_alloc(ctx_, TILEDB_DENSE, &array_schema);
1193 REQUIRE(rc == TILEDB_OK);
1194 rc = tiledb_array_schema_set_domain(ctx_, array_schema, domain);
1195 REQUIRE(rc == TILEDB_ERR);
1196 tiledb_array_schema_free(&array_schema);
1197
1198 // Create sparse array schema
1199 rc = tiledb_array_schema_alloc(ctx_, TILEDB_SPARSE, &array_schema);
1200 REQUIRE(rc == TILEDB_OK);
1201
1202 // Set domain to schema
1203 rc = tiledb_array_schema_set_domain(ctx_, array_schema, domain);
1204 REQUIRE(rc == TILEDB_OK);
1205
1206 // Create attributes
1207 tiledb_attribute_t* a;
1208 rc = tiledb_attribute_alloc(ctx_, "a", TILEDB_INT32, &a);
1209 REQUIRE(rc == TILEDB_OK);
1210
1211 // Check array schema
1212 rc = tiledb_array_schema_check(ctx_, array_schema);
1213 REQUIRE(rc == TILEDB_OK);
1214
1215 // Create array
1216 rc = array_create_wrapper(array_name, array_schema);
1217 REQUIRE(rc == TILEDB_OK);
1218
1219 // Clean up
1220 tiledb_array_schema_free(&array_schema);
1221 tiledb_dimension_free(&d);
1222 tiledb_domain_free(&domain);
1223 tiledb_attribute_free(&a);
1224
1225 // Load array schema and domain
1226 rc = array_schema_load_wrapper(array_name, &array_schema);
1227 REQUIRE(rc == TILEDB_OK);
1228 rc = tiledb_array_schema_get_domain(ctx_, array_schema, &domain);
1229 REQUIRE(rc == TILEDB_OK);
1230
1231 // Get dimension
1232 rc = tiledb_domain_get_dimension_from_index(ctx_, domain, 0, &d);
1233 REQUIRE(rc == TILEDB_OK);
1234
1235 // Check dimension type, domain and tile extent
1236 tiledb_datatype_t type;
1237 rc = tiledb_dimension_get_type(ctx_, d, &type);
1238 REQUIRE(rc == TILEDB_OK);
1239 CHECK(type == TILEDB_STRING_ASCII);
1240 const void *dom, *extent;
1241 rc = tiledb_dimension_get_domain(ctx_, d, &dom);
1242 REQUIRE(rc == TILEDB_OK);
1243 CHECK(dom == nullptr);
1244 rc = tiledb_dimension_get_tile_extent(ctx_, d, &extent);
1245 REQUIRE(rc == TILEDB_OK);
1246 CHECK(extent == nullptr);
1247
1248 // Clean up
1249 tiledb_array_schema_free(&array_schema);
1250 tiledb_domain_free(&domain);
1251 tiledb_dimension_free(&d);
1252
1253 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1254 }
1255
1256 TEST_CASE_METHOD(
1257 StringDimsFx,
1258 "C API: Test sparse array with string dimensions, check duplicates, global "
1259 "order",
1260 "[capi][sparse][string-dims][duplicates][global]") {
1261 SECTION("- No serialization") {
1262 serialize_ = false;
1263 }
1264 SECTION("- Serialization") {
1265 serialize_ = true;
1266 }
1267 SupportedFsLocal local_fs;
1268 std::string array_name =
1269 local_fs.file_prefix() + local_fs.temp_dir() + "string_dims";
1270 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1271
1272 create_array(
1273 ctx_,
1274 array_name,
1275 TILEDB_SPARSE,
1276 {"d"},
1277 {TILEDB_STRING_ASCII},
1278 {nullptr},
1279 {nullptr},
1280 {"a"},
1281 {TILEDB_INT32},
1282 {1},
1283 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1)},
1284 TILEDB_ROW_MAJOR,
1285 TILEDB_ROW_MAJOR,
1286 2,
1287 false,
1288 false);
1289
1290 // Open array
1291 tiledb_array_t* array;
1292 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1293 CHECK(rc == TILEDB_OK);
1294 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1295 CHECK(rc == TILEDB_OK);
1296
1297 // Create and submit query
1298 tiledb_query_t* query;
1299 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
1300 REQUIRE(rc == TILEDB_OK);
1301
1302 char d_data[] = "aabbbbdddd";
1303 uint64_t d_data_size = sizeof(d_data) - 1; // Ignore '\0'
1304 uint64_t d_off[] = {0, 2, 4, 6};
1305 uint64_t d_off_size = sizeof(d_off);
1306 int32_t a_data[] = {1, 2, 3, 4};
1307 uint64_t a_size = sizeof(a_data);
1308 rc = tiledb_query_set_data_buffer(ctx_, query, "d", d_data, &d_data_size);
1309 REQUIRE(rc == TILEDB_OK);
1310 rc = tiledb_query_set_offsets_buffer(ctx_, query, "d", d_off, &d_off_size);
1311 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a_data, &a_size);
1312 REQUIRE(rc == TILEDB_OK);
1313 rc = tiledb_query_set_layout(ctx_, query, TILEDB_GLOBAL_ORDER);
1314 REQUIRE(rc == TILEDB_OK);
1315 rc = tiledb_query_submit_wrapper(ctx_, query, array_name);
1316 REQUIRE(rc == TILEDB_ERR);
1317
1318 // Close array
1319 rc = tiledb_array_close(ctx_, array);
1320 CHECK(rc == TILEDB_OK);
1321
1322 // Clean up
1323 tiledb_array_free(&array);
1324 tiledb_query_free(&query);
1325
1326 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1327 }
1328
1329 TEST_CASE_METHOD(
1330 StringDimsFx,
1331 "C API: Test sparse array with string dimensions, check duplicates, "
1332 "unordered",
1333 "[capi][sparse][string-dims][duplicates][unordered]") {
1334 SECTION("- No serialization") {
1335 serialize_ = false;
1336 }
1337 SECTION("- Serialization") {
1338 serialize_ = true;
1339 }
1340 SupportedFsLocal local_fs;
1341 std::string array_name =
1342 local_fs.file_prefix() + local_fs.temp_dir() + "string_dims";
1343 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1344
1345 create_array(
1346 ctx_,
1347 array_name,
1348 TILEDB_SPARSE,
1349 {"d"},
1350 {TILEDB_STRING_ASCII},
1351 {nullptr},
1352 {nullptr},
1353 {"a"},
1354 {TILEDB_INT32},
1355 {1},
1356 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1)},
1357 TILEDB_ROW_MAJOR,
1358 TILEDB_ROW_MAJOR,
1359 2,
1360 false,
1361 false);
1362
1363 // Open array
1364 tiledb_array_t* array;
1365 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1366 CHECK(rc == TILEDB_OK);
1367 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1368 CHECK(rc == TILEDB_OK);
1369
1370 // Create and submit query
1371 tiledb_query_t* query;
1372 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
1373 REQUIRE(rc == TILEDB_OK);
1374
1375 char d_data[] = "ddddbbaabb";
1376 uint64_t d_data_size = sizeof(d_data) - 1; // Ignore '\0'
1377 uint64_t d_off[] = {0, 4, 6, 8};
1378 uint64_t d_off_size = sizeof(d_off);
1379 int32_t a_data[] = {1, 2, 3, 4};
1380 uint64_t a_size = sizeof(a_data);
1381 rc = tiledb_query_set_data_buffer(ctx_, query, "d", d_data, &d_data_size);
1382 REQUIRE(rc == TILEDB_OK);
1383 rc = tiledb_query_set_offsets_buffer(ctx_, query, "d", d_off, &d_off_size);
1384 REQUIRE(rc == TILEDB_OK);
1385 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a_data, &a_size);
1386 REQUIRE(rc == TILEDB_OK);
1387 rc = tiledb_query_set_layout(ctx_, query, TILEDB_UNORDERED);
1388 REQUIRE(rc == TILEDB_OK);
1389 rc = tiledb_query_submit_wrapper(ctx_, query, array_name);
1390 REQUIRE(rc == TILEDB_ERR);
1391
1392 // Close array
1393 rc = tiledb_array_close(ctx_, array);
1394 CHECK(rc == TILEDB_OK);
1395
1396 // Clean up
1397 tiledb_array_free(&array);
1398 tiledb_query_free(&query);
1399
1400 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1401 }
1402
1403 TEST_CASE_METHOD(
1404 StringDimsFx,
1405 "C API: Test sparse array with string dimensions, check global order "
1406 "violation",
1407 "[capi][sparse][string-dims][global-order][violation]") {
1408 SECTION("- No serialization") {
1409 serialize_ = false;
1410 }
1411 SECTION("- Serialization") {
1412 serialize_ = true;
1413 }
1414 SupportedFsLocal local_fs;
1415 std::string array_name =
1416 local_fs.file_prefix() + local_fs.temp_dir() + "string_dims";
1417 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1418
1419 create_array(
1420 ctx_,
1421 array_name,
1422 TILEDB_SPARSE,
1423 {"d"},
1424 {TILEDB_STRING_ASCII},
1425 {nullptr},
1426 {nullptr},
1427 {"a"},
1428 {TILEDB_INT32},
1429 {1},
1430 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1)},
1431 TILEDB_ROW_MAJOR,
1432 TILEDB_ROW_MAJOR,
1433 2,
1434 false,
1435 false);
1436
1437 // Open array
1438 tiledb_array_t* array;
1439 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1440 CHECK(rc == TILEDB_OK);
1441 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1442 CHECK(rc == TILEDB_OK);
1443
1444 // Create and submit query
1445 tiledb_query_t* query;
1446 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
1447 REQUIRE(rc == TILEDB_OK);
1448
1449 char d_data[] = "ddddbbbcaa";
1450 uint64_t d_data_size = sizeof(d_data) - 1; // Ignore '\0'
1451 uint64_t d_off[] = {0, 4, 6, 8};
1452 uint64_t d_off_size = sizeof(d_off);
1453 int32_t a_data[] = {1, 2, 3, 4};
1454 uint64_t a_size = sizeof(a_data);
1455 rc = tiledb_query_set_data_buffer(ctx_, query, "d", d_data, &d_data_size);
1456 REQUIRE(rc == TILEDB_OK);
1457 rc = tiledb_query_set_offsets_buffer(ctx_, query, "d", d_off, &d_off_size);
1458 REQUIRE(rc == TILEDB_OK);
1459 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a_data, &a_size);
1460 REQUIRE(rc == TILEDB_OK);
1461 rc = tiledb_query_set_layout(ctx_, query, TILEDB_GLOBAL_ORDER);
1462 REQUIRE(rc == TILEDB_OK);
1463 rc = tiledb_query_submit_wrapper(ctx_, query, array_name);
1464 REQUIRE(rc == TILEDB_ERR);
1465
1466 // Close array
1467 rc = tiledb_array_close(ctx_, array);
1468 CHECK(rc == TILEDB_OK);
1469
1470 // Clean up
1471 tiledb_array_free(&array);
1472 tiledb_query_free(&query);
1473
1474 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1475 }
1476
1477 TEST_CASE_METHOD(
1478 StringDimsFx,
1479 "C API: Test sparse array with string dimensions, errors",
1480 "[capi][sparse][string-dims][errors]") {
1481 SECTION("- No serialization") {
1482 serialize_ = false;
1483 }
1484 SECTION("- Serialization") {
1485 serialize_ = true;
1486 }
1487 SupportedFsLocal local_fs;
1488 std::string array_name =
1489 local_fs.file_prefix() + local_fs.temp_dir() + "string_dims";
1490 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1491
1492 // Create array
1493 create_array(
1494 ctx_,
1495 array_name,
1496 TILEDB_SPARSE,
1497 {"d"},
1498 {TILEDB_STRING_ASCII},
1499 {nullptr},
1500 {nullptr},
1501 {"a"},
1502 {TILEDB_INT32},
1503 {1},
1504 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1)},
1505 TILEDB_ROW_MAJOR,
1506 TILEDB_ROW_MAJOR,
1507 2,
1508 false,
1509 false);
1510
1511 // ####### WRITE #######
1512
1513 // Open array
1514 tiledb_array_t* array;
1515 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1516 CHECK(rc == TILEDB_OK);
1517 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1518 CHECK(rc == TILEDB_OK);
1519
1520 // Create and submit query
1521 tiledb_query_t* query;
1522 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
1523 REQUIRE(rc == TILEDB_OK);
1524
1525 char d_data[] = "ccbbddddaa";
1526 uint64_t d_data_size = sizeof(d_data) - 1; // Ignore '\0'
1527 uint64_t d_off[] = {0, 2, 4, 8};
1528 uint64_t d_off_size = sizeof(d_off);
1529 int32_t a_data[] = {3, 2, 4, 1};
1530 uint64_t a_size = sizeof(a_data);
1531 rc = tiledb_query_set_data_buffer(ctx_, query, "d", d_data, &d_data_size);
1532 REQUIRE(rc == TILEDB_OK);
1533 rc = tiledb_query_set_offsets_buffer(ctx_, query, "d", d_off, &d_off_size);
1534 REQUIRE(rc == TILEDB_OK);
1535 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a_data, &a_size);
1536 REQUIRE(rc == TILEDB_OK);
1537 rc = tiledb_query_set_layout(ctx_, query, TILEDB_UNORDERED);
1538 REQUIRE(rc == TILEDB_OK);
1539 rc = tiledb_query_submit_wrapper(ctx_, query, array_name);
1540 REQUIRE(rc == TILEDB_OK);
1541
1542 // Close array
1543 rc = tiledb_array_close(ctx_, array);
1544 CHECK(rc == TILEDB_OK);
1545
1546 // Clean up
1547 tiledb_array_free(&array);
1548 tiledb_query_free(&query);
1549
1550 // ####### CHECK ERRORS #######
1551 // Open array
1552 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1553 CHECK(rc == TILEDB_OK);
1554 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1555 CHECK(rc == TILEDB_OK);
1556
1557 // Get non-empty domain and array max buffer sizes
1558 int32_t dom[4];
1559 int32_t is_empty;
1560 uint64_t size = 1024;
1561 rc = tiledb_array_get_non_empty_domain(ctx_, array, dom, &is_empty);
1562 CHECK(rc == TILEDB_ERR);
1563
1564 // Set subarray and buffer
1565 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1566 REQUIRE(rc == TILEDB_OK);
1567 rc = tiledb_query_set_subarray(ctx_, query, dom);
1568 REQUIRE(rc == TILEDB_ERR);
1569 int32_t buff[10];
1570 uint64_t buff_size = sizeof(buff);
1571 rc = tiledb_query_set_data_buffer(
1572 ctx_, query, TILEDB_COORDS, buff, &buff_size);
1573 REQUIRE(rc == TILEDB_ERR);
1574 int data[1];
1575 uint64_t data_size;
1576 rc = tiledb_query_set_data_buffer(ctx_, query, "d", data, &data_size);
1577 REQUIRE(rc == TILEDB_OK);
1578
1579 // Get estimated buffer size
1580 rc = tiledb_query_get_est_result_size(ctx_, query, TILEDB_COORDS, &size);
1581 CHECK(rc == TILEDB_ERR);
1582 rc = tiledb_query_get_est_result_size(ctx_, query, "d", &size);
1583 CHECK(rc == TILEDB_ERR);
1584
1585 // Close array
1586 rc = tiledb_array_close(ctx_, array);
1587 CHECK(rc == TILEDB_OK);
1588
1589 // Clean up
1590 tiledb_array_free(&array);
1591 tiledb_query_free(&query);
1592
1593 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1594 }
1595
1596 TEST_CASE_METHOD(
1597 StringDimsFx,
1598 "C API: Test sparse array with string dimensions, 1d",
1599 "[capi][sparse][string-dims][1d][basic]") {
1600 SECTION("- No serialization") {
1601 serialize_ = false;
1602 }
1603 SECTION("- Serialization") {
1604 serialize_ = true;
1605 }
1606 SupportedFsLocal local_fs;
1607 std::string array_name =
1608 local_fs.file_prefix() + local_fs.temp_dir() + "string_dims";
1609 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1610
1611 // Create array
1612 create_array(
1613 ctx_,
1614 array_name,
1615 TILEDB_SPARSE,
1616 {"d"},
1617 {TILEDB_STRING_ASCII},
1618 {nullptr},
1619 {nullptr},
1620 {"a"},
1621 {TILEDB_INT32},
1622 {1},
1623 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1)},
1624 TILEDB_ROW_MAJOR,
1625 TILEDB_ROW_MAJOR,
1626 2,
1627 false,
1628 false);
1629
1630 // Write
1631 std::vector<uint64_t> d_off = {0, 2, 4, 8};
1632 std::string d_val("ccbbddddaa");
1633 std::vector<int32_t> a = {3, 2, 4, 1};
1634 write_array_1d(ctx_, array_name, TILEDB_UNORDERED, d_off, d_val, a);
1635
1636 // ####### READ #######
1637
1638 // Open array
1639 tiledb_array_t* array;
1640 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1641 CHECK(rc == TILEDB_OK);
1642 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1643 CHECK(rc == TILEDB_OK);
1644
1645 // Check proper errors for getting non-empty domain
1646 char dom[100];
1647 int32_t is_empty = false;
1648 uint64_t start_size, end_size;
1649 rc = tiledb_array_get_non_empty_domain_from_index(
1650 ctx_, array, 0, dom, &is_empty);
1651 CHECK(rc == TILEDB_ERR);
1652 rc = tiledb_array_get_non_empty_domain_from_name(
1653 ctx_, array, "d", dom, &is_empty);
1654 CHECK(rc == TILEDB_ERR);
1655 rc = tiledb_array_get_non_empty_domain_var_size_from_index(
1656 ctx_, array, 2, &start_size, &end_size, &is_empty);
1657 CHECK(rc == TILEDB_ERR);
1658 rc = tiledb_array_get_non_empty_domain_var_size_from_name(
1659 ctx_, array, "foo", &start_size, &end_size, &is_empty);
1660 CHECK(rc == TILEDB_ERR);
1661
1662 std::string start, end;
1663 get_non_empty_domain_var(array_name, "d", &start, &end, &is_empty);
1664 CHECK(is_empty == 0);
1665 CHECK(start == "aa");
1666 CHECK(end == "dddd");
1667
1668 // Create query
1669 tiledb_query_t* query;
1670 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1671 CHECK(rc == TILEDB_OK);
1672 char s1[] = "a";
1673 char s2[] = "ee";
1674
1675 // Check we can add empty ranges
1676 rc = tiledb_query_add_range_var(ctx_, query, 0, s1, 0, s2, 2);
1677 CHECK(rc == TILEDB_OK);
1678 rc = tiledb_query_add_range_var(ctx_, query, 0, s1, 1, s2, 0);
1679 CHECK(rc == TILEDB_OK);
1680 rc = tiledb_query_add_range_var(ctx_, query, 0, nullptr, 0, s2, 2);
1681 CHECK(rc == TILEDB_OK);
1682 rc = tiledb_query_add_range_var(ctx_, query, 0, s1, 1, nullptr, 0);
1683 CHECK(rc == TILEDB_OK);
1684
1685 // Clean query and re-alloc
1686 tiledb_query_free(&query);
1687 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1688 CHECK(rc == TILEDB_OK);
1689
1690 // Check errors when adding range
1691 rc = tiledb_query_add_range(ctx_, query, 0, s1, s2, nullptr);
1692 CHECK(rc == TILEDB_ERR);
1693 rc = tiledb_query_add_range_var(ctx_, query, 1, s1, 1, s2, 2);
1694 CHECK(rc == TILEDB_ERR);
1695 rc = tiledb_query_add_range_var(ctx_, query, 0, nullptr, 1, s2, 2);
1696 CHECK(rc == TILEDB_ERR);
1697 rc = tiledb_query_add_range_var(ctx_, query, 0, s1, 1, nullptr, 2);
1698 CHECK(rc == TILEDB_ERR);
1699
1700 // Add string range
1701 rc = tiledb_query_add_range_var(ctx_, query, 0, s1, 1, s2, 2);
1702 CHECK(rc == TILEDB_OK);
1703
1704 // Check error on getting estimated result size
1705 uint64_t size_off = 0, size_val = 0;
1706 rc = tiledb_query_get_est_result_size(ctx_, query, "d", &size_off);
1707 CHECK(rc == TILEDB_ERR);
1708
1709 // Get estimated result size
1710 rc = tiledb_query_get_est_result_size_var(
1711 ctx_, query, "d", &size_off, &size_val);
1712 CHECK(rc == TILEDB_OK);
1713 CHECK(size_off == 32);
1714 CHECK(size_val == 10);
1715
1716 // Clean query
1717 tiledb_query_free(&query);
1718
1719 // Set layout
1720 tiledb_layout_t layout = TILEDB_ROW_MAJOR;
1721 SECTION("Global order") {
1722 layout = TILEDB_GLOBAL_ORDER;
1723 }
1724 SECTION("Row-major") {
1725 layout = TILEDB_ROW_MAJOR;
1726 }
1727 SECTION("Col-major") {
1728 layout = TILEDB_COL_MAJOR;
1729 }
1730 SECTION("Unordered") {
1731 layout = TILEDB_UNORDERED;
1732 }
1733
1734 // Read [a, ee]
1735 std::vector<uint64_t> r_d_off(10);
1736 std::string r_d_val;
1737 r_d_val.resize(20);
1738 std::vector<int32_t> r_a(10);
1739 tiledb_query_status_t status;
1740 read_array_1d(
1741 ctx_, array, layout, "a", "ee", &r_d_off, &r_d_val, &r_a, &status);
1742 CHECK(status == TILEDB_COMPLETED);
1743 CHECK(r_d_val == "aabbccdddd");
1744 std::vector<uint64_t> c_d_off = {0, 2, 4, 6};
1745 CHECK(r_d_off == c_d_off);
1746 std::vector<int32_t> c_a = {1, 2, 3, 4};
1747 CHECK(r_a == c_a);
1748
1749 // Read [aab, cc]
1750 r_d_off.resize(10);
1751 r_d_val.resize(20);
1752 r_a.resize(10);
1753 read_array_1d(
1754 ctx_, array, layout, "aab", "cc", &r_d_off, &r_d_val, &r_a, &status);
1755 CHECK(status == TILEDB_COMPLETED);
1756 CHECK(r_d_val == "bbcc");
1757 c_d_off = {0, 2};
1758 CHECK(r_d_off == c_d_off);
1759 c_a = {2, 3};
1760 CHECK(r_a == c_a);
1761
1762 // Read [aa, cc] - INCOMPLETE
1763 r_d_off.resize(2);
1764 r_d_val.resize(20);
1765 r_a.resize(10);
1766 read_array_1d(
1767 ctx_, array, layout, "aa", "cc", &r_d_off, &r_d_val, &r_a, &status);
1768 CHECK(status == TILEDB_INCOMPLETE);
1769 CHECK(r_d_val == "aabb");
1770 c_d_off = {0, 2};
1771 CHECK(r_d_off == c_d_off);
1772 c_a = {1, 2};
1773 CHECK(r_a == c_a);
1774
1775 // Read [aa, cc] - INCOMPLETE, no result
1776 r_d_off.resize(1);
1777 r_d_val.resize(1);
1778 r_a.resize(10);
1779 read_array_1d(
1780 ctx_, array, layout, "aa", "bb", &r_d_off, &r_d_val, &r_a, &status);
1781 CHECK(status == TILEDB_INCOMPLETE);
1782 CHECK(r_d_val.size() == 0);
1783 CHECK(r_d_off.size() == 0);
1784 CHECK(r_a.size() == 0);
1785
1786 // Close array
1787 rc = tiledb_array_close(ctx_, array);
1788 CHECK(rc == TILEDB_OK);
1789
1790 // Clean up
1791 tiledb_array_free(&array);
1792
1793 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1794 }
1795
1796 TEST_CASE_METHOD(
1797 StringDimsFx,
1798 "C API: Test sparse array with string dimensions, 1d, consolidation",
1799 "[capi][sparse][string-dims][1d][consolidation]") {
1800 SECTION("- No serialization") {
1801 serialize_ = false;
1802 }
1803 SECTION("- Serialization") {
1804 serialize_ = true;
1805 }
1806 SupportedFsLocal local_fs;
1807 std::string array_name =
1808 local_fs.file_prefix() + local_fs.temp_dir() + "string_dims";
1809 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1810
1811 // Create array
1812 create_array(
1813 ctx_,
1814 array_name,
1815 TILEDB_SPARSE,
1816 {"d"},
1817 {TILEDB_STRING_ASCII},
1818 {nullptr},
1819 {nullptr},
1820 {"a"},
1821 {TILEDB_INT32},
1822 {1},
1823 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1)},
1824 TILEDB_ROW_MAJOR,
1825 TILEDB_ROW_MAJOR,
1826 2,
1827 false,
1828 false);
1829
1830 // Write #1
1831 std::vector<uint64_t> d_off = {0, 2, 4, 8};
1832 std::string d_val("ccbbddddaa");
1833 std::vector<int32_t> a = {3, 2, 4, 1};
1834 write_array_1d(ctx_, array_name, TILEDB_UNORDERED, d_off, d_val, a);
1835
1836 // Write #2
1837 d_off = {0, 1, 2};
1838 d_val = "abee";
1839 a = {5, 6, 7};
1840 write_array_1d(ctx_, array_name, TILEDB_GLOBAL_ORDER, d_off, d_val, a);
1841
1842 // Open array
1843 tiledb_array_t* array;
1844 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1845 CHECK(rc == TILEDB_OK);
1846 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1847 CHECK(rc == TILEDB_OK);
1848
1849 // Get non-empty domain
1850 std::string start, end;
1851 int32_t is_empty;
1852 get_non_empty_domain_var(array_name, "d", &start, &end, &is_empty);
1853 CHECK(is_empty == 0);
1854 CHECK(start == "a");
1855 CHECK(end == "ee");
1856
1857 // Get estimated result size
1858 uint64_t size_off = 0, size_val = 0;
1859 get_est_result_size_var(array, 0, "d", "a", "ee", &size_off, &size_val);
1860 CHECK(size_off == 56);
1861 CHECK(size_val == 14);
1862
1863 // Set layout
1864 tiledb_layout_t layout = TILEDB_ROW_MAJOR;
1865 SECTION("Global order") {
1866 layout = TILEDB_GLOBAL_ORDER;
1867 }
1868 SECTION("Row-major") {
1869 layout = TILEDB_ROW_MAJOR;
1870 }
1871 SECTION("Col-major") {
1872 layout = TILEDB_COL_MAJOR;
1873 }
1874 SECTION("Unordered") {
1875 layout = TILEDB_UNORDERED;
1876 }
1877
1878 // Read [a, ee]
1879 std::vector<uint64_t> r_d_off(10);
1880 std::string r_d_val;
1881 r_d_val.resize(20);
1882 std::vector<int32_t> r_a(10);
1883 tiledb_query_status_t status;
1884 read_array_1d(
1885 ctx_, array, layout, "a", "ee", &r_d_off, &r_d_val, &r_a, &status);
1886 CHECK(status == TILEDB_COMPLETED);
1887 CHECK(r_d_val == "aaabbbccddddee");
1888 std::vector<uint64_t> c_d_off = {0, 1, 3, 4, 6, 8, 12};
1889 CHECK(r_d_off == c_d_off);
1890 std::vector<int32_t> c_a = {5, 1, 6, 2, 3, 4, 7};
1891 CHECK(r_a == c_a);
1892
1893 // Close array
1894 rc = tiledb_array_close(ctx_, array);
1895 CHECK(rc == TILEDB_OK);
1896
1897 // Check number of fragments
1898 get_num_struct dirs = {ctx_, vfs_, 0};
1899 rc = tiledb_vfs_ls(ctx_, vfs_, array_name.c_str(), &get_dir_num, &dirs);
1900 CHECK(rc == TILEDB_OK);
1901 CHECK(dirs.num == 2);
1902
1903 // Consolidate
1904 rc = tiledb_array_consolidate(ctx_, array_name.c_str(), nullptr);
1905 CHECK(rc == TILEDB_OK);
1906 rc = tiledb_array_vacuum(ctx_, array_name.c_str(), nullptr);
1907
1908 // Check number of fragments
1909 dirs = {ctx_, vfs_, 0};
1910 rc = tiledb_vfs_ls(ctx_, vfs_, array_name.c_str(), &get_dir_num, &dirs);
1911 CHECK(rc == TILEDB_OK);
1912 CHECK(dirs.num == 1);
1913
1914 // Get non-empty domain
1915 start = "";
1916 end = "";
1917 get_non_empty_domain_var(array_name, "d", &start, &end, &is_empty);
1918 CHECK(is_empty == 0);
1919 CHECK(start == "a");
1920 CHECK(end == "ee");
1921
1922 // Free array
1923 tiledb_array_free(&array);
1924
1925 // Open array
1926 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1927 CHECK(rc == TILEDB_OK);
1928 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1929 CHECK(rc == TILEDB_OK);
1930
1931 // Read [a, ee]
1932 r_d_off.resize(10);
1933 r_d_val.resize(20);
1934 r_a.resize(10);
1935 read_array_1d(
1936 ctx_, array, layout, "a", "ee", &r_d_off, &r_d_val, &r_a, &status);
1937 CHECK(status == TILEDB_COMPLETED);
1938 CHECK(r_d_val == "aaabbbccddddee");
1939 CHECK(r_d_off == c_d_off);
1940 CHECK(r_a == c_a);
1941
1942 // Close array
1943 rc = tiledb_array_close(ctx_, array);
1944 CHECK(rc == TILEDB_OK);
1945
1946 // Clean up
1947 tiledb_array_free(&array);
1948
1949 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1950 }
1951
1952 TEST_CASE_METHOD(
1953 StringDimsFx,
1954 "C API: Test sparse array with string dimensions, 1d, allow duplicates",
1955 "[capi][sparse][string-dims][1d][allow-dups]") {
1956 SECTION("- No serialization") {
1957 serialize_ = false;
1958 }
1959 SECTION("- Serialization") {
1960 serialize_ = true;
1961 }
1962 SupportedFsLocal local_fs;
1963 std::string array_name =
1964 local_fs.file_prefix() + local_fs.temp_dir() + "string_dims";
1965 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1966
1967 // Create array
1968 create_array(
1969 ctx_,
1970 array_name,
1971 TILEDB_SPARSE,
1972 {"d"},
1973 {TILEDB_STRING_ASCII},
1974 {nullptr},
1975 {nullptr},
1976 {"a"},
1977 {TILEDB_INT32},
1978 {1},
1979 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1)},
1980 TILEDB_ROW_MAJOR,
1981 TILEDB_ROW_MAJOR,
1982 2,
1983 true,
1984 false);
1985
1986 // Write
1987 std::vector<uint64_t> d_off = {0, 2, 4, 8};
1988 std::string d_val("ccccddddaa");
1989 std::vector<int32_t> a = {2, 3, 4, 1};
1990 write_array_1d(ctx_, array_name, TILEDB_UNORDERED, d_off, d_val, a);
1991
1992 // ####### READ #######
1993
1994 // Open array
1995 tiledb_array_t* array;
1996 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1997 CHECK(rc == TILEDB_OK);
1998 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1999 CHECK(rc == TILEDB_OK);
2000
2001 // Check non-empty domain
2002 std::string start, end;
2003 int32_t is_empty;
2004 get_non_empty_domain_var(array_name, "d", &start, &end, &is_empty);
2005 CHECK(is_empty == 0);
2006 CHECK(start == "aa");
2007 CHECK(end == "dddd");
2008
2009 // Set layout
2010 tiledb_layout_t layout = TILEDB_ROW_MAJOR;
2011 SECTION("Global order") {
2012 layout = TILEDB_GLOBAL_ORDER;
2013 }
2014 SECTION("Row-major") {
2015 layout = TILEDB_ROW_MAJOR;
2016 }
2017 SECTION("Col-major") {
2018 layout = TILEDB_COL_MAJOR;
2019 }
2020 SECTION("Unordered") {
2021 layout = TILEDB_UNORDERED;
2022 }
2023
2024 // Read [a, e]
2025 std::vector<uint64_t> r_d_off(10);
2026 std::string r_d_val;
2027 r_d_val.resize(20);
2028 std::vector<int32_t> r_a(10);
2029 tiledb_query_status_t status;
2030 read_array_1d(
2031 ctx_, array, layout, "a", "e", &r_d_off, &r_d_val, &r_a, &status);
2032 CHECK(status == TILEDB_COMPLETED);
2033 CHECK(r_d_val == "aaccccdddd");
2034 std::vector<uint64_t> c_d_off = {0, 2, 4, 6};
2035 CHECK(r_d_off == c_d_off);
2036 // The ordering of 'a' is undefined for duplicate dimension
2037 // elements. Check both for dimension element "c".
2038 std::vector<int32_t> c_a_1 = {1, 3, 2, 4};
2039 std::vector<int32_t> c_a_2 = {1, 2, 3, 4};
2040 const bool c_a_matches = r_a == c_a_1 || r_a == c_a_2;
2041 CHECK(c_a_matches);
2042
2043 // Close array
2044 rc = tiledb_array_close(ctx_, array);
2045 CHECK(rc == TILEDB_OK);
2046
2047 // Clean up
2048 tiledb_array_free(&array);
2049
2050 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
2051 }
2052
2053 TEST_CASE_METHOD(
2054 StringDimsFx,
2055 "C API: Test sparse array with string dimensions, 1d, dedup",
2056 "[capi][sparse][string-dims][1d][dedup]") {
2057 SECTION("- No serialization") {
2058 serialize_ = false;
2059 }
2060 SECTION("- Serialization") {
2061 serialize_ = true;
2062 }
2063 SupportedFsLocal local_fs;
2064 std::string array_name =
2065 local_fs.file_prefix() + local_fs.temp_dir() + "string_dims";
2066 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
2067
2068 // Create array
2069 create_array(
2070 ctx_,
2071 array_name,
2072 TILEDB_SPARSE,
2073 {"d"},
2074 {TILEDB_STRING_ASCII},
2075 {nullptr},
2076 {nullptr},
2077 {"a"},
2078 {TILEDB_INT32},
2079 {1},
2080 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1)},
2081 TILEDB_ROW_MAJOR,
2082 TILEDB_ROW_MAJOR,
2083 2,
2084 false,
2085 false);
2086
2087 // Create config
2088 tiledb_config_t* config = nullptr;
2089 tiledb_error_t* error = nullptr;
2090 int rc = tiledb_config_alloc(&config, &error);
2091 CHECK(rc == TILEDB_OK);
2092 CHECK(error == nullptr);
2093 rc = tiledb_config_set(config, "sm.dedup_coords", "true", &error);
2094 CHECK(rc == TILEDB_OK);
2095
2096 // Create context
2097 tiledb_ctx_t* ctx;
2098 rc = tiledb_ctx_alloc(config, &ctx);
2099 CHECK(rc == TILEDB_OK);
2100
2101 // Write
2102 std::vector<uint64_t> d_off = {0, 2, 4, 8};
2103 std::string d_val("ccccddddaa");
2104 std::vector<int32_t> a = {2, 3, 4, 1};
2105 write_array_1d(ctx, array_name, TILEDB_UNORDERED, d_off, d_val, a);
2106
2107 // Clean up
2108 tiledb_config_free(&config);
2109
2110 // ####### READ #######
2111
2112 // Open array
2113 tiledb_array_t* array;
2114 rc = tiledb_array_alloc(ctx, array_name.c_str(), &array);
2115 CHECK(rc == TILEDB_OK);
2116 rc = tiledb_array_open(ctx, array, TILEDB_READ);
2117 CHECK(rc == TILEDB_OK);
2118
2119 // Check non-empty domain
2120 std::string start, end;
2121 int32_t is_empty;
2122 get_non_empty_domain_var(array_name, "d", &start, &end, &is_empty);
2123 CHECK(is_empty == 0);
2124 CHECK(start == "aa");
2125 CHECK(end == "dddd");
2126
2127 // Set layout
2128 tiledb_layout_t layout = TILEDB_ROW_MAJOR;
2129 SECTION("Global order") {
2130 layout = TILEDB_GLOBAL_ORDER;
2131 }
2132 SECTION("Row-major") {
2133 layout = TILEDB_ROW_MAJOR;
2134 }
2135 SECTION("Col-major") {
2136 layout = TILEDB_COL_MAJOR;
2137 }
2138 SECTION("Unordered") {
2139 layout = TILEDB_UNORDERED;
2140 }
2141
2142 // Read [a, e]
2143 std::vector<uint64_t> r_d_off(10);
2144 std::string r_d_val;
2145 r_d_val.resize(20);
2146 std::vector<int32_t> r_a(10);
2147 tiledb_query_status_t status;
2148 read_array_1d(
2149 ctx, array, layout, "a", "e", &r_d_off, &r_d_val, &r_a, &status);
2150 CHECK(status == TILEDB_COMPLETED);
2151 CHECK(r_d_val == "aaccdddd");
2152 std::vector<uint64_t> c_d_off = {0, 2, 4};
2153 CHECK(r_d_off == c_d_off);
2154 // Either value for dimension index 'cc' may be de-duped.
2155 std::vector<int32_t> c_a_1 = {1, 2, 4};
2156 std::vector<int32_t> c_a_2 = {1, 3, 4};
2157 const bool c_a_matches = r_a == c_a_1 || r_a == c_a_2;
2158 CHECK(c_a_matches);
2159
2160 // Close array
2161 rc = tiledb_array_close(ctx, array);
2162 CHECK(rc == TILEDB_OK);
2163
2164 // Clean up
2165 tiledb_array_free(&array);
2166 tiledb_ctx_free(&ctx);
2167
2168 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
2169 }
2170
2171 TEST_CASE_METHOD(
2172 StringDimsFx,
2173 "C API: Test sparse array with string dimensions, 2d",
2174 "[capi][sparse][string-dims][2d]") {
2175 SECTION("- No serialization") {
2176 serialize_ = false;
2177 }
2178 SECTION("- Serialization") {
2179 serialize_ = true;
2180 }
2181 SupportedFsLocal local_fs;
2182 std::string array_name =
2183 local_fs.file_prefix() + local_fs.temp_dir() + "string_dims";
2184 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
2185
2186 // Create array
2187 int32_t dom[] = {1, 10};
2188 int32_t extent = 5;
2189 create_array(
2190 ctx_,
2191 array_name,
2192 TILEDB_SPARSE,
2193 {"d1", "d2"},
2194 {TILEDB_STRING_ASCII, TILEDB_INT32},
2195 {nullptr, dom},
2196 {nullptr, &extent},
2197 {"a"},
2198 {TILEDB_INT32},
2199 {1},
2200 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1)},
2201 TILEDB_ROW_MAJOR,
2202 TILEDB_ROW_MAJOR,
2203 2,
2204 false,
2205 false);
2206
2207 // Write
2208 tiledb_layout_t write_layout = TILEDB_UNORDERED;
2209 SECTION("Unordered write") {
2210 write_layout = TILEDB_UNORDERED;
2211 }
2212 SECTION("Global write") {
2213 write_layout = TILEDB_GLOBAL_ORDER;
2214 }
2215 std::vector<uint64_t> d1_off = {0, 2, 4, 6};
2216 std::string d1_val("aabbccdddd");
2217 std::vector<int32_t> d2 = {1, 2, 3, 4};
2218 std::vector<int32_t> a = {11, 12, 13, 14};
2219 write_array_2d(ctx_, array_name, write_layout, d1_off, d1_val, d2, a);
2220
2221 // ####### READ #######
2222
2223 // Check non-empty domain
2224 std::string start, end;
2225 int32_t is_empty;
2226 get_non_empty_domain_var(array_name, "d1", &start, &end, &is_empty);
2227 CHECK(is_empty == 0);
2228 CHECK(start == "aa");
2229 CHECK(end == "dddd");
2230 std::vector<int32_t> non_empty;
2231 get_non_empty_domain(array_name, "d2", &non_empty, &is_empty);
2232 CHECK(is_empty == 0);
2233 CHECK(non_empty[0] == 1);
2234 CHECK(non_empty[1] == 4);
2235
2236 // Open array
2237 tiledb_array_t* array;
2238 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
2239 CHECK(rc == TILEDB_OK);
2240 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
2241 CHECK(rc == TILEDB_OK);
2242
2243 // Set layout
2244 tiledb_layout_t layout = TILEDB_ROW_MAJOR;
2245
2246 SECTION("Global order") {
2247 layout = TILEDB_GLOBAL_ORDER;
2248 }
2249 SECTION("Row-major read") {
2250 layout = TILEDB_ROW_MAJOR;
2251 }
2252 SECTION("Col-major") {
2253 layout = TILEDB_COL_MAJOR;
2254 }
2255 SECTION("Unordered") {
2256 layout = TILEDB_UNORDERED;
2257 }
2258
2259 // Read [a, e], [1, 10]
2260 std::vector<uint64_t> r_d1_off(10);
2261 std::string r_d1_val;
2262 r_d1_val.resize(20);
2263 std::vector<int32_t> r_d2(10);
2264 std::vector<int32_t> r_a(10);
2265 tiledb_query_status_t status;
2266 read_array_2d(
2267 ctx_,
2268 array,
2269 layout,
2270 "a",
2271 "e",
2272 1,
2273 10,
2274 &r_d1_off,
2275 &r_d1_val,
2276 &r_d2,
2277 &r_a,
2278 &status);
2279 CHECK(status == TILEDB_COMPLETED);
2280 CHECK(r_d1_val == "aabbccdddd");
2281 std::vector<uint64_t> c_d1_off = {0, 2, 4, 6};
2282 CHECK(r_d1_off == c_d1_off);
2283 std::vector<int32_t> c_d2 = {1, 2, 3, 4};
2284 CHECK(r_d2 == c_d2);
2285 std::vector<int32_t> c_a = {11, 12, 13, 14};
2286 CHECK(r_a == c_a);
2287
2288 // Read [a, cc], [2, 3]
2289 r_d1_off.resize(10);
2290 r_d1_val.resize(20);
2291 r_d2.resize(10);
2292 r_a.resize(10);
2293 read_array_2d(
2294 ctx_,
2295 array,
2296 layout,
2297 "a",
2298 "cc",
2299 2,
2300 3,
2301 &r_d1_off,
2302 &r_d1_val,
2303 &r_d2,
2304 &r_a,
2305 &status);
2306 CHECK(status == TILEDB_COMPLETED);
2307 CHECK(r_d1_val == "bbcc");
2308 c_d1_off = {0, 2};
2309 CHECK(r_d1_off == c_d1_off);
2310 c_d2 = {2, 3};
2311 CHECK(r_d2 == c_d2);
2312 c_a = {12, 13};
2313 CHECK(r_a == c_a);
2314
2315 // Close array
2316 rc = tiledb_array_close(ctx_, array);
2317 CHECK(rc == TILEDB_OK);
2318
2319 std::this_thread::sleep_for(std::chrono::milliseconds(1));
2320
2321 // Write again
2322 d1_off = {0, 1, 2};
2323 d1_val = "abff";
2324 d2 = {2, 2, 3};
2325 a = {15, 16, 17};
2326 write_array_2d(ctx_, array_name, write_layout, d1_off, d1_val, d2, a);
2327
2328 std::this_thread::sleep_for(std::chrono::milliseconds(1));
2329
2330 // Create config
2331 tiledb_config_t* config = nullptr;
2332 tiledb_error_t* error = nullptr;
2333 rc = tiledb_config_alloc(&config, &error);
2334 CHECK(rc == TILEDB_OK);
2335 CHECK(error == nullptr);
2336 rc = tiledb_config_set(
2337 config, "sm.consolidation.mode", "fragment_meta", &error);
2338 CHECK(rc == TILEDB_OK);
2339
2340 // Consolidate fragment metadata
2341 rc = tiledb_array_consolidate(ctx_, array_name.c_str(), config);
2342 CHECK(rc == TILEDB_OK);
2343 tiledb_array_free(&array);
2344
2345 // Open array
2346 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
2347 CHECK(rc == TILEDB_OK);
2348 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
2349 CHECK(rc == TILEDB_OK);
2350
2351 // Read [a, ff], [1, 10]
2352 r_d1_off.resize(20);
2353 r_d1_val.resize(20);
2354 r_d2.resize(20);
2355 r_a.resize(20);
2356 read_array_2d(
2357 ctx_,
2358 array,
2359 TILEDB_GLOBAL_ORDER,
2360 "a",
2361 "ff",
2362 1,
2363 10,
2364 &r_d1_off,
2365 &r_d1_val,
2366 &r_d2,
2367 &r_a,
2368 &status);
2369 CHECK(status == TILEDB_COMPLETED);
2370 CHECK(r_d1_val == "aaabbbccddddff");
2371 c_d1_off = {0, 1, 3, 4, 6, 8, 12};
2372 CHECK(r_d1_off == c_d1_off);
2373 c_d2 = {2, 1, 2, 2, 3, 4, 3};
2374 CHECK(r_d2 == c_d2);
2375 c_a = {15, 11, 16, 12, 13, 14, 17};
2376 CHECK(r_a == c_a);
2377
2378 // Close array
2379 rc = tiledb_array_close(ctx_, array);
2380 CHECK(rc == TILEDB_OK);
2381 tiledb_array_free(&array);
2382
2383 // Consolidate
2384 rc = tiledb_array_consolidate(ctx_, array_name.c_str(), nullptr);
2385 CHECK(rc == TILEDB_OK);
2386 rc = tiledb_array_vacuum(ctx_, array_name.c_str(), nullptr);
2387 CHECK(rc == TILEDB_OK);
2388
2389 // Open array
2390 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
2391 CHECK(rc == TILEDB_OK);
2392 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
2393 CHECK(rc == TILEDB_OK);
2394
2395 // Read [a, ff], [1, 10]
2396 r_d1_off.resize(20);
2397 r_d1_val.resize(20);
2398 r_d2.resize(20);
2399 r_a.resize(20);
2400 read_array_2d(
2401 ctx_,
2402 array,
2403 TILEDB_GLOBAL_ORDER,
2404 "a",
2405 "ff",
2406 1,
2407 10,
2408 &r_d1_off,
2409 &r_d1_val,
2410 &r_d2,
2411 &r_a,
2412 &status);
2413 CHECK(status == TILEDB_COMPLETED);
2414 CHECK(r_d1_val == "aaabbbccddddff");
2415 c_d1_off = {0, 1, 3, 4, 6, 8, 12};
2416 CHECK(r_d1_off == c_d1_off);
2417 c_d2 = {2, 1, 2, 2, 3, 4, 3};
2418 CHECK(r_d2 == c_d2);
2419 c_a = {15, 11, 16, 12, 13, 14, 17};
2420 CHECK(r_a == c_a);
2421
2422 // Close array
2423 rc = tiledb_array_close(ctx_, array);
2424 CHECK(rc == TILEDB_OK);
2425
2426 // Clean up
2427 tiledb_array_free(&array);
2428 tiledb_config_free(&config);
2429
2430 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
2431 }