1 /**
2 * @file unit-capi-sparse_real.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 real domains.
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/misc/utils.h"
43
44 #include <iostream>
45 #include <sstream>
46 #include <thread>
47
48 using namespace tiledb::test;
49
50 struct SparseRealFx2 {
51 // TileDB context
52 tiledb_ctx_t* ctx_;
53 tiledb_vfs_t* vfs_;
54
55 // Vector of supported filsystems
56 const std::vector<std::unique_ptr<SupportedFs>> fs_vec_;
57
58 // Functions
59 SparseRealFx2();
60 ~SparseRealFx2();
61 void create_temp_dir(const std::string& path);
62 void remove_temp_dir(const std::string& path);
63 void create_sparse_array(const std::string& path);
64 void write_sparse_array(const std::string& path);
65 void write_sparse_array_next_partition_bug(const std::string& path);
66 void read_sparse_array(const std::string& path);
67 void read_sparse_array_next_partition_bug(const std::string& path);
68 static std::string random_name(const std::string& prefix);
69 };
70
SparseRealFx2()71 SparseRealFx2::SparseRealFx2()
72 : fs_vec_(vfs_test_get_fs_vec()) {
73 // Initialize vfs test
74 REQUIRE(vfs_test_init(fs_vec_, &ctx_, &vfs_).ok());
75 }
76
~SparseRealFx2()77 SparseRealFx2::~SparseRealFx2() {
78 // Close vfs test
79 REQUIRE(vfs_test_close(fs_vec_, ctx_, vfs_).ok());
80 tiledb_vfs_free(&vfs_);
81 tiledb_ctx_free(&ctx_);
82 }
83
create_temp_dir(const std::string & path)84 void SparseRealFx2::create_temp_dir(const std::string& path) {
85 remove_temp_dir(path);
86 REQUIRE(tiledb_vfs_create_dir(ctx_, vfs_, path.c_str()) == TILEDB_OK);
87 }
88
remove_temp_dir(const std::string & path)89 void SparseRealFx2::remove_temp_dir(const std::string& path) {
90 int is_dir = 0;
91 REQUIRE(tiledb_vfs_is_dir(ctx_, vfs_, path.c_str(), &is_dir) == TILEDB_OK);
92 if (is_dir)
93 REQUIRE(tiledb_vfs_remove_dir(ctx_, vfs_, path.c_str()) == TILEDB_OK);
94 }
95
random_name(const std::string & prefix)96 std::string SparseRealFx2::random_name(const std::string& prefix) {
97 std::stringstream ss;
98 ss << prefix << "-" << std::this_thread::get_id() << "-"
99 << TILEDB_TIMESTAMP_NOW_MS;
100 return ss.str();
101 }
102
create_sparse_array(const std::string & path)103 void SparseRealFx2::create_sparse_array(const std::string& path) {
104 // Create dimensions
105 float dim_domain[] = {-180.0f, 180.0f, -90.0f, 90.0f};
106 float tile_extents[] = {10.1f, 10.1f};
107 tiledb_dimension_t* d1;
108 int rc = tiledb_dimension_alloc(
109 ctx_, "d1", TILEDB_FLOAT32, &dim_domain[0], &tile_extents[0], &d1);
110 CHECK(rc == TILEDB_OK);
111 tiledb_dimension_t* d2;
112 rc = tiledb_dimension_alloc(
113 ctx_, "d2", TILEDB_FLOAT32, &dim_domain[2], &tile_extents[1], &d2);
114 CHECK(rc == TILEDB_OK);
115
116 // Create domain
117 tiledb_domain_t* domain;
118 rc = tiledb_domain_alloc(ctx_, &domain);
119 CHECK(rc == TILEDB_OK);
120 rc = tiledb_domain_add_dimension(ctx_, domain, d1);
121 CHECK(rc == TILEDB_OK);
122 rc = tiledb_domain_add_dimension(ctx_, domain, d2);
123 CHECK(rc == TILEDB_OK);
124
125 // Create attributes
126 tiledb_attribute_t* a;
127 rc = tiledb_attribute_alloc(ctx_, "a", TILEDB_INT32, &a);
128 CHECK(rc == TILEDB_OK);
129 tiledb_filter_t* filter;
130 tiledb_filter_list_t* list;
131 rc = tiledb_filter_alloc(ctx_, TILEDB_FILTER_LZ4, &filter);
132 CHECK(rc == TILEDB_OK);
133 rc = tiledb_filter_list_alloc(ctx_, &list);
134 CHECK(rc == TILEDB_OK);
135 rc = tiledb_filter_list_add_filter(ctx_, list, filter);
136 CHECK(rc == TILEDB_OK);
137 rc = tiledb_attribute_set_filter_list(ctx_, a, list);
138 CHECK(rc == TILEDB_OK);
139
140 // Create array schema
141 tiledb_array_schema_t* array_schema;
142 rc = tiledb_array_schema_alloc(ctx_, TILEDB_SPARSE, &array_schema);
143 CHECK(rc == TILEDB_OK);
144 rc = tiledb_array_schema_set_cell_order(ctx_, array_schema, TILEDB_ROW_MAJOR);
145 CHECK(rc == TILEDB_OK);
146 rc = tiledb_array_schema_set_tile_order(ctx_, array_schema, TILEDB_ROW_MAJOR);
147 CHECK(rc == TILEDB_OK);
148 rc = tiledb_array_schema_set_domain(ctx_, array_schema, domain);
149 CHECK(rc == TILEDB_OK);
150 rc = tiledb_array_schema_add_attribute(ctx_, array_schema, a);
151 CHECK(rc == TILEDB_OK);
152
153 // Check array schema
154 rc = tiledb_array_schema_check(ctx_, array_schema);
155 CHECK(rc == TILEDB_OK);
156
157 // Create array
158 rc = tiledb_array_create(ctx_, path.c_str(), array_schema);
159 CHECK(rc == TILEDB_OK);
160
161 // Clean up
162 tiledb_filter_free(&filter);
163 tiledb_filter_list_free(&list);
164 tiledb_attribute_free(&a);
165 tiledb_dimension_free(&d1);
166 tiledb_dimension_free(&d2);
167 tiledb_domain_free(&domain);
168 tiledb_array_schema_free(&array_schema);
169 }
170
write_sparse_array(const std::string & path)171 void SparseRealFx2::write_sparse_array(const std::string& path) {
172 // Open array
173 tiledb_array_t* array;
174 int rc = tiledb_array_alloc(ctx_, path.c_str(), &array);
175 CHECK(rc == TILEDB_OK);
176 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
177 CHECK(rc == TILEDB_OK);
178
179 int a[] = {1, 2, 3, 4, 5};
180 uint64_t a_size = sizeof(a);
181 float coords_dim1[] = {-23.5f, 43.56f, 66.2f, -160.1f, 1.0f};
182 float coords_dim2[] = {-20.0f, 80.0f, -0.3f, 89.1f, 1.0f};
183 uint64_t coords_size = sizeof(coords_dim1);
184 tiledb_query_t* query;
185 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
186 REQUIRE(rc == TILEDB_OK);
187 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a, &a_size);
188 REQUIRE(rc == TILEDB_OK);
189 rc = tiledb_query_set_data_buffer(
190 ctx_, query, "d1", coords_dim1, &coords_size);
191 REQUIRE(rc == TILEDB_OK);
192 rc = tiledb_query_set_data_buffer(
193 ctx_, query, "d2", coords_dim2, &coords_size);
194 REQUIRE(rc == TILEDB_OK);
195 rc = tiledb_query_set_layout(ctx_, query, TILEDB_UNORDERED);
196 REQUIRE(rc == TILEDB_OK);
197 rc = tiledb_query_submit(ctx_, query);
198 REQUIRE(rc == TILEDB_OK);
199 rc = tiledb_query_finalize(ctx_, query);
200 REQUIRE(rc == TILEDB_OK);
201
202 // Close array
203 rc = tiledb_array_close(ctx_, array);
204 CHECK(rc == TILEDB_OK);
205
206 // Clean up
207 tiledb_array_free(&array);
208 tiledb_query_free(&query);
209 }
210
write_sparse_array_next_partition_bug(const std::string & path)211 void SparseRealFx2::write_sparse_array_next_partition_bug(
212 const std::string& path) {
213 // Open array
214 tiledb_array_t* array;
215 int rc = tiledb_array_alloc(ctx_, path.c_str(), &array);
216 CHECK(rc == TILEDB_OK);
217 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
218 CHECK(rc == TILEDB_OK);
219
220 int a[] = {1, 2};
221 uint64_t a_size = sizeof(a);
222 float coords_dim1[] = {-180.0f, -180.0f};
223 float coords_dim2[] = {1.0f, 2.0f};
224 uint64_t coords_size = sizeof(coords_dim1);
225 tiledb_query_t* query;
226 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
227 REQUIRE(rc == TILEDB_OK);
228 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a, &a_size);
229 REQUIRE(rc == TILEDB_OK);
230 rc = tiledb_query_set_data_buffer(
231 ctx_, query, "d1", coords_dim1, &coords_size);
232 REQUIRE(rc == TILEDB_OK);
233 rc = tiledb_query_set_data_buffer(
234 ctx_, query, "d2", coords_dim2, &coords_size);
235 REQUIRE(rc == TILEDB_OK);
236 rc = tiledb_query_set_layout(ctx_, query, TILEDB_UNORDERED);
237 REQUIRE(rc == TILEDB_OK);
238 rc = tiledb_query_submit(ctx_, query);
239 REQUIRE(rc == TILEDB_OK);
240 rc = tiledb_query_finalize(ctx_, query);
241 REQUIRE(rc == TILEDB_OK);
242
243 // Close array
244 rc = tiledb_array_close(ctx_, array);
245 CHECK(rc == TILEDB_OK);
246
247 // Clean up
248 tiledb_array_free(&array);
249 tiledb_query_free(&query);
250 }
251
read_sparse_array(const std::string & path)252 void SparseRealFx2::read_sparse_array(const std::string& path) {
253 // Open array
254 tiledb_array_t* array;
255 int rc = tiledb_array_alloc(ctx_, path.c_str(), &array);
256 CHECK(rc == TILEDB_OK);
257 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
258 CHECK(rc == TILEDB_OK);
259
260 int a[16];
261 uint64_t a_size = sizeof(a);
262 float coords_dim1[16];
263 float coords_dim2[16];
264 uint64_t coords_size = sizeof(coords_dim1);
265 tiledb_query_t* query;
266 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
267 REQUIRE(rc == TILEDB_OK);
268
269 // Create some subarray
270 float s0[] = {-180.0f, 180.0f};
271 float s1[] = {-90.0f, 90.0f};
272 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
273 REQUIRE(rc == TILEDB_OK);
274 rc = tiledb_query_add_range(ctx_, query, 0, &s0[0], &s0[1], nullptr);
275 REQUIRE(rc == TILEDB_OK);
276 rc = tiledb_query_add_range(ctx_, query, 1, &s1[0], &s1[1], nullptr);
277 REQUIRE(rc == TILEDB_OK);
278
279 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a, &a_size);
280 REQUIRE(rc == TILEDB_OK);
281 rc = tiledb_query_set_data_buffer(
282 ctx_, query, "d1", coords_dim1, &coords_size);
283 REQUIRE(rc == TILEDB_OK);
284 rc = tiledb_query_set_data_buffer(
285 ctx_, query, "d2", coords_dim2, &coords_size);
286 REQUIRE(rc == TILEDB_OK);
287 rc = tiledb_query_submit(ctx_, query);
288 REQUIRE(rc == TILEDB_OK);
289 rc = tiledb_query_finalize(ctx_, query);
290 REQUIRE(rc == TILEDB_OK);
291
292 int a_c[] = {4, 1, 5, 2, 3};
293 float coords_c_dim1[] = {-160.1f, -23.5f, 1.0f, 43.56f, 66.2f};
294 float coords_c_dim2[] = {89.1f, -20.0f, 1.0f, 80.0f, -0.3f};
295 CHECK(a_size == sizeof(a_c));
296 CHECK(!memcmp(a, a_c, sizeof(a_c)));
297 CHECK(coords_size == sizeof(coords_c_dim1));
298 CHECK(!memcmp(coords_dim1, coords_c_dim1, sizeof(coords_c_dim1)));
299 CHECK(!memcmp(coords_dim2, coords_c_dim2, sizeof(coords_c_dim2)));
300
301 // Close array
302 rc = tiledb_array_close(ctx_, array);
303 CHECK(rc == TILEDB_OK);
304
305 // Clean up
306 tiledb_array_free(&array);
307 tiledb_query_free(&query);
308 }
309
read_sparse_array_next_partition_bug(const std::string & path)310 void SparseRealFx2::read_sparse_array_next_partition_bug(
311 const std::string& path) {
312 // Open array
313 tiledb_array_t* array;
314 int rc = tiledb_array_alloc(ctx_, path.c_str(), &array);
315 CHECK(rc == TILEDB_OK);
316 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
317 CHECK(rc == TILEDB_OK);
318
319 int a[1];
320 uint64_t a_size = sizeof(a);
321 float coords_dim1[4];
322 float coords_dim2[4];
323 uint64_t coords_size = sizeof(coords_dim1);
324 tiledb_query_t* query;
325 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
326 REQUIRE(rc == TILEDB_OK);
327
328 // Set some subarray
329 float s0[] = {-180.0f, 180.0f};
330 float s1[] = {-90.0f, 90.0f};
331 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
332 REQUIRE(rc == TILEDB_OK);
333 rc = tiledb_query_add_range(ctx_, query, 0, &s0[0], &s0[1], nullptr);
334 REQUIRE(rc == TILEDB_OK);
335 rc = tiledb_query_add_range(ctx_, query, 1, &s1[0], &s1[1], nullptr);
336 REQUIRE(rc == TILEDB_OK);
337
338 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a, &a_size);
339 REQUIRE(rc == TILEDB_OK);
340 rc = tiledb_query_set_data_buffer(
341 ctx_, query, "d1", coords_dim1, &coords_size);
342 REQUIRE(rc == TILEDB_OK);
343 rc = tiledb_query_set_data_buffer(
344 ctx_, query, "d2", coords_dim2, &coords_size);
345 REQUIRE(rc == TILEDB_OK);
346 rc = tiledb_query_submit(ctx_, query);
347 REQUIRE(rc == TILEDB_OK);
348
349 CHECK(a_size == sizeof(int));
350 CHECK(a[0] == 1);
351 CHECK(coords_dim1[0] == -180.0f);
352 CHECK(coords_dim2[0] == 1.0f);
353
354 // Close array
355 rc = tiledb_array_close(ctx_, array);
356 CHECK(rc == TILEDB_OK);
357
358 // Clean up
359 tiledb_array_free(&array);
360 tiledb_query_free(&query);
361 }
362
363 TEST_CASE_METHOD(
364 SparseRealFx2,
365 "C API: Test 2d sparse array with real domain 2",
366 "[capi][sparse-real-2]") {
367 SupportedFsLocal local_fs;
368 std::string vector_name =
369 local_fs.file_prefix() + local_fs.temp_dir() + "sparse_real";
370 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
371
372 create_sparse_array(vector_name);
373 write_sparse_array(vector_name);
374 read_sparse_array(vector_name);
375
376 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
377 }
378
379 TEST_CASE_METHOD(
380 SparseRealFx2,
381 "C API: Test 2d sparse array with real domain, next subarray partition bug "
382 "2",
383 "[capi][sparse-real-2][sparse-real-next-partition-bug-2]") {
384 SupportedFsLocal local_fs;
385 std::string array_name = local_fs.file_prefix() + local_fs.temp_dir() +
386 "sparse_real_next_partition_bug";
387 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
388
389 create_sparse_array(array_name);
390 write_sparse_array_next_partition_bug(array_name);
391 read_sparse_array_next_partition_bug(array_name);
392
393 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
394 }
395
396 TEST_CASE_METHOD(
397 SparseRealFx2,
398 "C API: Test 2d sparse array with real domain, NaN in subarray 2",
399 "[capi][sparse-real-2][sparse-real-nan-subarray-2]") {
400 SupportedFsLocal local_fs;
401 std::string array_name =
402 local_fs.file_prefix() + local_fs.temp_dir() + "sparse_real_nan_subarray";
403 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
404
405 create_sparse_array(array_name);
406 write_sparse_array(array_name);
407
408 // Open array
409 tiledb_array_t* array;
410 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
411 CHECK(rc == TILEDB_OK);
412 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
413 CHECK(rc == TILEDB_OK);
414
415 tiledb_query_t* query;
416 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
417 REQUIRE(rc == TILEDB_OK);
418
419 // Set config for `sm.read_range_oob` = `error`
420 tiledb_config_t* config = nullptr;
421 tiledb_error_t* error = nullptr;
422 REQUIRE(tiledb_config_alloc(&config, &error) == TILEDB_OK);
423 REQUIRE(error == nullptr);
424 rc = tiledb_config_set(config, "sm.read_range_oob", "error", &error);
425 REQUIRE(rc == TILEDB_OK);
426 REQUIRE(error == nullptr);
427 rc = tiledb_query_set_config(ctx_, query, config);
428 REQUIRE(rc == TILEDB_OK);
429
430 // Create some subarray
431 float s0[] = {-180.0f, std::numeric_limits<float>::quiet_NaN()};
432 float s1[] = {-90.0f, std::numeric_limits<float>::infinity()};
433 rc = tiledb_query_add_range(ctx_, query, 0, &s0[0], &s0[1], nullptr);
434 REQUIRE(rc == TILEDB_ERR);
435 rc = tiledb_query_add_range(ctx_, query, 1, &s1[0], &s1[1], nullptr);
436 REQUIRE(rc == TILEDB_ERR);
437
438 // Clean up
439 rc = tiledb_array_close(ctx_, array);
440 CHECK(rc == TILEDB_OK);
441 tiledb_array_free(&array);
442 tiledb_config_free(&config);
443 tiledb_query_free(&query);
444
445 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
446 }
447
448 TEST_CASE_METHOD(
449 SparseRealFx2,
450 "C API: Test 2d sparse array with real domain 2, unary range",
451 "[capi][sparse-real-2]") {
452 SupportedFsLocal local_fs;
453 std::string array_name =
454 local_fs.file_prefix() + local_fs.temp_dir() + "sparse_real_unary";
455 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
456 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
457 create_sparse_array(array_name);
458
459 // Write twice (2 fragments)
460 write_sparse_array(array_name);
461 write_sparse_array(array_name);
462
463 // Open array
464 tiledb_array_t* array;
465 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
466 CHECK(rc == TILEDB_OK);
467 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
468 CHECK(rc == TILEDB_OK);
469
470 int a[1];
471 uint64_t a_size = sizeof(a);
472 float coords_dim1[1];
473 float coords_dim2[1];
474 uint64_t coords_size = sizeof(coords_dim1);
475 tiledb_query_t* query;
476 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
477 REQUIRE(rc == TILEDB_OK);
478
479 // Set some subarray
480 float s0[] = {-23.5f, -23.5f};
481 float s1[] = {-20.0f, -20.0f};
482 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
483 REQUIRE(rc == TILEDB_OK);
484 rc = tiledb_query_add_range(ctx_, query, 0, &s0[0], &s0[1], nullptr);
485 REQUIRE(rc == TILEDB_OK);
486 rc = tiledb_query_add_range(ctx_, query, 1, &s1[0], &s1[1], nullptr);
487 REQUIRE(rc == TILEDB_OK);
488
489 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a, &a_size);
490 REQUIRE(rc == TILEDB_OK);
491 rc = tiledb_query_set_data_buffer(
492 ctx_, query, "d1", coords_dim1, &coords_size);
493 REQUIRE(rc == TILEDB_OK);
494 rc = tiledb_query_set_data_buffer(
495 ctx_, query, "d2", coords_dim2, &coords_size);
496 REQUIRE(rc == TILEDB_OK);
497 rc = tiledb_query_submit(ctx_, query);
498 REQUIRE(rc == TILEDB_OK);
499 rc = tiledb_query_finalize(ctx_, query);
500 REQUIRE(rc == TILEDB_OK);
501
502 int a_c[] = {1};
503 float coords_c_dim1[] = {-23.5f};
504 float coords_c_dim2[] = {-20.0f};
505 CHECK(a_size == sizeof(a_c));
506 CHECK(!memcmp(a, a_c, sizeof(a_c)));
507 CHECK(coords_size == sizeof(coords_c_dim1));
508 CHECK(!memcmp(coords_dim1, coords_c_dim1, sizeof(coords_c_dim1)));
509 CHECK(!memcmp(coords_dim2, coords_c_dim2, sizeof(coords_c_dim2)));
510
511 // Close array
512 rc = tiledb_array_close(ctx_, array);
513 CHECK(rc == TILEDB_OK);
514
515 // Clean up
516 tiledb_array_free(&array);
517 tiledb_query_free(&query);
518
519 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
520 }
521