1 /**
2  * @file   tiledb.cc
3  *
4  * @section LICENSE
5  *
6  * The MIT License
7  *
8  * @copyright Copyright (c) 2017-2021 TileDB, Inc.
9  * @copyright Copyright (c) 2016 MIT and Intel Corporation
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a copy
12  * of this software and associated documentation files (the "Software"), to deal
13  * in the Software without restriction, including without limitation the rights
14  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  * copies of the Software, and to permit persons to whom the Software is
16  * furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27  * THE SOFTWARE.
28  *
29  * @section DESCRIPTION
30  *
31  * This file defines the C API of TileDB.
32  */
33 
34 #include "tiledb/sm/c_api/tiledb.h"
35 #include "tiledb/common/heap_profiler.h"
36 #include "tiledb/common/logger.h"
37 #include "tiledb/sm/array/array.h"
38 #include "tiledb/sm/array_schema/array_schema.h"
39 #include "tiledb/sm/c_api/tiledb_experimental.h"
40 #include "tiledb/sm/c_api/tiledb_serialization.h"
41 #include "tiledb/sm/c_api/tiledb_struct_def.h"
42 #include "tiledb/sm/config/config.h"
43 #include "tiledb/sm/config/config_iter.h"
44 #include "tiledb/sm/cpp_api/core_interface.h"
45 #include "tiledb/sm/enums/array_type.h"
46 #include "tiledb/sm/enums/encryption_type.h"
47 #include "tiledb/sm/enums/filesystem.h"
48 #include "tiledb/sm/enums/filter_option.h"
49 #include "tiledb/sm/enums/filter_type.h"
50 #include "tiledb/sm/enums/object_type.h"
51 #include "tiledb/sm/enums/query_status.h"
52 #include "tiledb/sm/enums/query_type.h"
53 #include "tiledb/sm/enums/serialization_type.h"
54 #include "tiledb/sm/enums/vfs_mode.h"
55 #include "tiledb/sm/filesystem/vfs.h"
56 #include "tiledb/sm/filesystem/vfs_file_handle.h"
57 #include "tiledb/sm/filter/compression_filter.h"
58 #include "tiledb/sm/filter/filter_pipeline.h"
59 #include "tiledb/sm/misc/utils.h"
60 #include "tiledb/sm/query/query.h"
61 #include "tiledb/sm/query/query_condition.h"
62 #include "tiledb/sm/rest/rest_client.h"
63 #include "tiledb/sm/serialization/array_schema.h"
64 #include "tiledb/sm/serialization/array_schema_evolution.h"
65 #include "tiledb/sm/serialization/config.h"
66 #include "tiledb/sm/serialization/query.h"
67 #include "tiledb/sm/stats/global_stats.h"
68 #include "tiledb/sm/storage_manager/context.h"
69 #include "tiledb/sm/subarray/subarray.h"
70 #include "tiledb/sm/subarray/subarray_partitioner.h"
71 
72 #include <map>
73 #include <memory>
74 #include <sstream>
75 
76 using namespace tiledb::common;
77 
78 /* ****************************** */
79 /*       ENUMS TO/FROM STR        */
80 /* ****************************** */
81 
tiledb_query_type_to_str(tiledb_query_type_t query_type,const char ** str)82 int32_t tiledb_query_type_to_str(
83     tiledb_query_type_t query_type, const char** str) {
84   const auto& strval =
85       tiledb::sm::query_type_str((tiledb::sm::QueryType)query_type);
86   *str = strval.c_str();
87   return strval.empty() ? TILEDB_ERR : TILEDB_OK;
88 }
89 
tiledb_query_type_from_str(const char * str,tiledb_query_type_t * query_type)90 int32_t tiledb_query_type_from_str(
91     const char* str, tiledb_query_type_t* query_type) {
92   tiledb::sm::QueryType val = tiledb::sm::QueryType::READ;
93   if (!tiledb::sm::query_type_enum(str, &val).ok())
94     return TILEDB_ERR;
95   *query_type = (tiledb_query_type_t)val;
96   return TILEDB_OK;
97 }
98 
tiledb_object_type_to_str(tiledb_object_t object_type,const char ** str)99 int32_t tiledb_object_type_to_str(
100     tiledb_object_t object_type, const char** str) {
101   const auto& strval =
102       tiledb::sm::object_type_str((tiledb::sm::ObjectType)object_type);
103   *str = strval.c_str();
104   return strval.empty() ? TILEDB_ERR : TILEDB_OK;
105 }
106 
tiledb_object_type_from_str(const char * str,tiledb_object_t * object_type)107 int32_t tiledb_object_type_from_str(
108     const char* str, tiledb_object_t* object_type) {
109   tiledb::sm::ObjectType val = tiledb::sm::ObjectType::INVALID;
110   if (!tiledb::sm::object_type_enum(str, &val).ok())
111     return TILEDB_ERR;
112   *object_type = (tiledb_object_t)val;
113   return TILEDB_OK;
114 }
115 
tiledb_filesystem_to_str(tiledb_filesystem_t filesystem,const char ** str)116 int32_t tiledb_filesystem_to_str(
117     tiledb_filesystem_t filesystem, const char** str) {
118   const auto& strval =
119       tiledb::sm::filesystem_str((tiledb::sm::Filesystem)filesystem);
120   *str = strval.c_str();
121   return strval.empty() ? TILEDB_ERR : TILEDB_OK;
122 }
123 
tiledb_filesystem_from_str(const char * str,tiledb_filesystem_t * filesystem)124 int32_t tiledb_filesystem_from_str(
125     const char* str, tiledb_filesystem_t* filesystem) {
126   tiledb::sm::Filesystem val = tiledb::sm::Filesystem::S3;
127   if (!tiledb::sm::filesystem_enum(str, &val).ok())
128     return TILEDB_ERR;
129   *filesystem = (tiledb_filesystem_t)val;
130   return TILEDB_OK;
131 }
132 
tiledb_datatype_to_str(tiledb_datatype_t datatype,const char ** str)133 int32_t tiledb_datatype_to_str(tiledb_datatype_t datatype, const char** str) {
134   const auto& strval = tiledb::sm::datatype_str((tiledb::sm::Datatype)datatype);
135   *str = strval.c_str();
136   return strval.empty() ? TILEDB_ERR : TILEDB_OK;
137 }
138 
tiledb_datatype_from_str(const char * str,tiledb_datatype_t * datatype)139 int32_t tiledb_datatype_from_str(const char* str, tiledb_datatype_t* datatype) {
140   tiledb::sm::Datatype val = tiledb::sm::Datatype::UINT8;
141   if (!tiledb::sm::datatype_enum(str, &val).ok())
142     return TILEDB_ERR;
143   *datatype = (tiledb_datatype_t)val;
144   return TILEDB_OK;
145 }
146 
tiledb_array_type_to_str(tiledb_array_type_t array_type,const char ** str)147 int32_t tiledb_array_type_to_str(
148     tiledb_array_type_t array_type, const char** str) {
149   const auto& strval =
150       tiledb::sm::array_type_str((tiledb::sm::ArrayType)array_type);
151   *str = strval.c_str();
152   return strval.empty() ? TILEDB_ERR : TILEDB_OK;
153 }
154 
tiledb_array_type_from_str(const char * str,tiledb_array_type_t * array_type)155 int32_t tiledb_array_type_from_str(
156     const char* str, tiledb_array_type_t* array_type) {
157   tiledb::sm::ArrayType val = tiledb::sm::ArrayType::DENSE;
158   if (!tiledb::sm::array_type_enum(str, &val).ok())
159     return TILEDB_ERR;
160   *array_type = (tiledb_array_type_t)val;
161   return TILEDB_OK;
162 }
163 
tiledb_layout_to_str(tiledb_layout_t layout,const char ** str)164 int32_t tiledb_layout_to_str(tiledb_layout_t layout, const char** str) {
165   const auto& strval = tiledb::sm::layout_str((tiledb::sm::Layout)layout);
166   *str = strval.c_str();
167   return strval.empty() ? TILEDB_ERR : TILEDB_OK;
168 }
169 
tiledb_layout_from_str(const char * str,tiledb_layout_t * layout)170 int32_t tiledb_layout_from_str(const char* str, tiledb_layout_t* layout) {
171   tiledb::sm::Layout val = tiledb::sm::Layout::ROW_MAJOR;
172   if (!tiledb::sm::layout_enum(str, &val).ok())
173     return TILEDB_ERR;
174   *layout = (tiledb_layout_t)val;
175   return TILEDB_OK;
176 }
177 
tiledb_filter_type_to_str(tiledb_filter_type_t filter_type,const char ** str)178 int32_t tiledb_filter_type_to_str(
179     tiledb_filter_type_t filter_type, const char** str) {
180   const auto& strval =
181       tiledb::sm::filter_type_str((tiledb::sm::FilterType)filter_type);
182   *str = strval.c_str();
183   return strval.empty() ? TILEDB_ERR : TILEDB_OK;
184 }
185 
tiledb_filter_type_from_str(const char * str,tiledb_filter_type_t * filter_type)186 int32_t tiledb_filter_type_from_str(
187     const char* str, tiledb_filter_type_t* filter_type) {
188   tiledb::sm::FilterType val = tiledb::sm::FilterType::FILTER_NONE;
189   if (!tiledb::sm::filter_type_enum(str, &val).ok())
190     return TILEDB_ERR;
191   *filter_type = (tiledb_filter_type_t)val;
192   return TILEDB_OK;
193 }
194 
tiledb_filter_option_to_str(tiledb_filter_option_t filter_option,const char ** str)195 int32_t tiledb_filter_option_to_str(
196     tiledb_filter_option_t filter_option, const char** str) {
197   const auto& strval =
198       tiledb::sm::filter_option_str((tiledb::sm::FilterOption)filter_option);
199   *str = strval.c_str();
200   return strval.empty() ? TILEDB_ERR : TILEDB_OK;
201 }
202 
tiledb_filter_option_from_str(const char * str,tiledb_filter_option_t * filter_option)203 int32_t tiledb_filter_option_from_str(
204     const char* str, tiledb_filter_option_t* filter_option) {
205   tiledb::sm::FilterOption val = tiledb::sm::FilterOption::COMPRESSION_LEVEL;
206   if (!tiledb::sm::filter_option_enum(str, &val).ok())
207     return TILEDB_ERR;
208   *filter_option = (tiledb_filter_option_t)val;
209   return TILEDB_OK;
210 }
211 
tiledb_encryption_type_to_str(tiledb_encryption_type_t encryption_type,const char ** str)212 int32_t tiledb_encryption_type_to_str(
213     tiledb_encryption_type_t encryption_type, const char** str) {
214   const auto& strval = tiledb::sm::encryption_type_str(
215       (tiledb::sm::EncryptionType)encryption_type);
216   *str = strval.c_str();
217   return strval.empty() ? TILEDB_ERR : TILEDB_OK;
218 }
219 
tiledb_encryption_type_from_str(const char * str,tiledb_encryption_type_t * encryption_type)220 int32_t tiledb_encryption_type_from_str(
221     const char* str, tiledb_encryption_type_t* encryption_type) {
222   auto [st, et] = tiledb::sm::encryption_type_enum(str);
223   if (!st.ok())
224     return TILEDB_ERR;
225   *encryption_type = (tiledb_encryption_type_t)et.value();
226   return TILEDB_OK;
227 }
228 
tiledb_query_status_to_str(tiledb_query_status_t query_status,const char ** str)229 int32_t tiledb_query_status_to_str(
230     tiledb_query_status_t query_status, const char** str) {
231   const auto& strval =
232       tiledb::sm::query_status_str((tiledb::sm::QueryStatus)query_status);
233   *str = strval.c_str();
234   return strval.empty() ? TILEDB_ERR : TILEDB_OK;
235 }
236 
tiledb_query_status_from_str(const char * str,tiledb_query_status_t * query_status)237 int32_t tiledb_query_status_from_str(
238     const char* str, tiledb_query_status_t* query_status) {
239   tiledb::sm::QueryStatus val = tiledb::sm::QueryStatus::UNINITIALIZED;
240   if (!tiledb::sm::query_status_enum(str, &val).ok())
241     return TILEDB_ERR;
242   *query_status = (tiledb_query_status_t)val;
243   return TILEDB_OK;
244 }
245 
tiledb_serialization_type_to_str(tiledb_serialization_type_t serialization_type,const char ** str)246 int32_t tiledb_serialization_type_to_str(
247     tiledb_serialization_type_t serialization_type, const char** str) {
248   const auto& strval = tiledb::sm::serialization_type_str(
249       (tiledb::sm::SerializationType)serialization_type);
250   *str = strval.c_str();
251   return strval.empty() ? TILEDB_ERR : TILEDB_OK;
252 }
253 
tiledb_serialization_type_from_str(const char * str,tiledb_serialization_type_t * serialization_type)254 int32_t tiledb_serialization_type_from_str(
255     const char* str, tiledb_serialization_type_t* serialization_type) {
256   tiledb::sm::SerializationType val = tiledb::sm::SerializationType::CAPNP;
257   if (!tiledb::sm::serialization_type_enum(str, &val).ok())
258     return TILEDB_ERR;
259   *serialization_type = (tiledb_serialization_type_t)val;
260   return TILEDB_OK;
261 }
262 
tiledb_walk_order_to_str(tiledb_walk_order_t walk_order,const char ** str)263 int32_t tiledb_walk_order_to_str(
264     tiledb_walk_order_t walk_order, const char** str) {
265   const auto& strval =
266       tiledb::sm::walkorder_str((tiledb::sm::WalkOrder)walk_order);
267   *str = strval.c_str();
268   return strval.empty() ? TILEDB_ERR : TILEDB_OK;
269 }
270 
tiledb_walk_order_from_str(const char * str,tiledb_walk_order_t * walk_order)271 int32_t tiledb_walk_order_from_str(
272     const char* str, tiledb_walk_order_t* walk_order) {
273   tiledb::sm::WalkOrder val = tiledb::sm::WalkOrder::PREORDER;
274   if (!tiledb::sm::walkorder_enum(str, &val).ok())
275     return TILEDB_ERR;
276   *walk_order = (tiledb_walk_order_t)val;
277   return TILEDB_OK;
278 }
279 
tiledb_vfs_mode_to_str(tiledb_vfs_mode_t vfs_mode,const char ** str)280 int32_t tiledb_vfs_mode_to_str(tiledb_vfs_mode_t vfs_mode, const char** str) {
281   const auto& strval = tiledb::sm::vfsmode_str((tiledb::sm::VFSMode)vfs_mode);
282   *str = strval.c_str();
283   return strval.empty() ? TILEDB_ERR : TILEDB_OK;
284 }
285 
tiledb_vfs_mode_from_str(const char * str,tiledb_vfs_mode_t * vfs_mode)286 int32_t tiledb_vfs_mode_from_str(const char* str, tiledb_vfs_mode_t* vfs_mode) {
287   tiledb::sm::VFSMode val = tiledb::sm::VFSMode::VFS_READ;
288   if (!tiledb::sm::vfsmode_enum(str, &val).ok())
289     return TILEDB_ERR;
290   *vfs_mode = (tiledb_vfs_mode_t)val;
291   return TILEDB_OK;
292 }
293 
294 /* ****************************** */
295 /*            CONSTANTS           */
296 /* ****************************** */
297 
tiledb_coords()298 const char* tiledb_coords() {
299   return tiledb::sm::constants::coords.c_str();
300 }
301 
tiledb_var_num()302 uint32_t tiledb_var_num() {
303   return tiledb::sm::constants::var_num;
304 }
305 
tiledb_max_path()306 uint32_t tiledb_max_path() {
307   return tiledb::sm::constants::path_max_len;
308 }
309 
tiledb_offset_size()310 uint64_t tiledb_offset_size() {
311   return tiledb::sm::constants::cell_var_offset_size;
312 }
313 
tiledb_datatype_size(tiledb_datatype_t type)314 uint64_t tiledb_datatype_size(tiledb_datatype_t type) {
315   return tiledb::sm::datatype_size(static_cast<tiledb::sm::Datatype>(type));
316 }
317 
tiledb_timestamp_now_ms()318 uint64_t tiledb_timestamp_now_ms() {
319   return tiledb::sm::utils::time::timestamp_now_ms();
320 }
321 
322 /* ****************************** */
323 /*            VERSION             */
324 /* ****************************** */
325 
tiledb_version(int32_t * major,int32_t * minor,int32_t * rev)326 void tiledb_version(int32_t* major, int32_t* minor, int32_t* rev) {
327   *major = tiledb::sm::constants::library_version[0];
328   *minor = tiledb::sm::constants::library_version[1];
329   *rev = tiledb::sm::constants::library_version[2];
330 }
331 
332 /* ********************************* */
333 /*         AUXILIARY FUNCTIONS       */
334 /* ********************************* */
335 
336 /* Saves a status inside the context object. */
save_error(tiledb_ctx_t * ctx,const Status & st)337 static bool save_error(tiledb_ctx_t* ctx, const Status& st) {
338   // No error
339   if (st.ok())
340     return false;
341 
342   // Store new error
343   ctx->ctx_->save_error(st);
344 
345   // There is an error
346   return true;
347 }
348 
create_error(tiledb_error_t ** error,const Status & st)349 static bool create_error(tiledb_error_t** error, const Status& st) {
350   if (st.ok())
351     return false;
352 
353   (*error) = new (std::nothrow) tiledb_error_t;
354   if (*error == nullptr)
355     return true;
356   (*error)->errmsg_ = st.to_string();
357 
358   return true;
359 }
360 
sanity_check(tiledb_ctx_t * ctx,const tiledb_array_t * array)361 inline int32_t sanity_check(tiledb_ctx_t* ctx, const tiledb_array_t* array) {
362   if (array == nullptr || array->array_ == nullptr) {
363     auto st = Status::Error("Invalid TileDB array object");
364     LOG_STATUS(st);
365     save_error(ctx, st);
366     return TILEDB_ERR;
367   }
368   return TILEDB_OK;
369 }
370 
sanity_check(tiledb_ctx_t * ctx,const tiledb_buffer_t * buffer)371 inline int32_t sanity_check(tiledb_ctx_t* ctx, const tiledb_buffer_t* buffer) {
372   if (buffer == nullptr || buffer->buffer_ == nullptr) {
373     auto st = Status::Error("Invalid TileDB buffer object");
374     LOG_STATUS(st);
375     save_error(ctx, st);
376     return TILEDB_ERR;
377   }
378   return TILEDB_OK;
379 }
380 
sanity_check(tiledb_ctx_t * ctx,const tiledb_buffer_list_t * buffer_list)381 inline int32_t sanity_check(
382     tiledb_ctx_t* ctx, const tiledb_buffer_list_t* buffer_list) {
383   if (buffer_list == nullptr || buffer_list->buffer_list_ == nullptr) {
384     auto st = Status::Error("Invalid TileDB buffer list object");
385     LOG_STATUS(st);
386     save_error(ctx, st);
387     return TILEDB_ERR;
388   }
389   return TILEDB_OK;
390 }
391 
sanity_check(tiledb_config_t * config,tiledb_error_t ** error)392 inline int32_t sanity_check(tiledb_config_t* config, tiledb_error_t** error) {
393   if (config == nullptr || config->config_ == nullptr) {
394     auto st = Status::Error("Cannot set config; Invalid config object");
395     LOG_STATUS(st);
396     create_error(error, st);
397     return TILEDB_ERR;
398   }
399 
400   *error = nullptr;
401   return TILEDB_OK;
402 }
403 
sanity_check(tiledb_ctx_t * ctx,tiledb_config_t * config)404 inline int32_t sanity_check(tiledb_ctx_t* ctx, tiledb_config_t* config) {
405   if (config == nullptr || config->config_ == nullptr) {
406     auto st = Status::Error("Cannot set config; Invalid config object");
407     LOG_STATUS(st);
408     save_error(ctx, st);
409     return TILEDB_ERR;
410   }
411 
412   return TILEDB_OK;
413 }
414 
sanity_check(tiledb_ctx_t * ctx,const tiledb_config_t * config)415 inline int32_t sanity_check(tiledb_ctx_t* ctx, const tiledb_config_t* config) {
416   if (config == nullptr || config->config_ == nullptr) {
417     auto st = Status::Error("Cannot set config; Invalid config object");
418     LOG_STATUS(st);
419     save_error(ctx, st);
420     return TILEDB_ERR;
421   }
422 
423   return TILEDB_OK;
424 }
425 
sanity_check(tiledb_config_iter_t * config_iter,tiledb_error_t ** error)426 inline int32_t sanity_check(
427     tiledb_config_iter_t* config_iter, tiledb_error_t** error) {
428   if (config_iter == nullptr || config_iter->config_iter_ == nullptr) {
429     auto st =
430         Status::Error("Cannot set config; Invalid config iterator object");
431     LOG_STATUS(st);
432     create_error(error, st);
433     return TILEDB_ERR;
434   }
435 
436   *error = nullptr;
437   return TILEDB_OK;
438 }
439 
sanity_check(tiledb_ctx_t * ctx)440 inline int32_t sanity_check(tiledb_ctx_t* ctx) {
441   if (ctx == nullptr)
442     return TILEDB_ERR;
443   if (ctx->ctx_ == nullptr || ctx->ctx_->storage_manager() == nullptr) {
444     auto st = Status::Error("Invalid TileDB context");
445     LOG_STATUS(st);
446     save_error(ctx, st);
447     return TILEDB_ERR;
448   }
449   return TILEDB_OK;
450 }
451 
sanity_check(tiledb_ctx_t * ctx,const tiledb_error_t * err)452 inline int32_t sanity_check(tiledb_ctx_t* ctx, const tiledb_error_t* err) {
453   if (err == nullptr) {
454     auto st = Status::Error("Invalid TileDB error object");
455     LOG_STATUS(st);
456     save_error(ctx, st);
457     return TILEDB_ERR;
458   }
459   return TILEDB_OK;
460 }
461 
sanity_check(tiledb_ctx_t * ctx,const tiledb_attribute_t * attr)462 inline int32_t sanity_check(tiledb_ctx_t* ctx, const tiledb_attribute_t* attr) {
463   if (attr == nullptr || attr->attr_ == nullptr) {
464     auto st = Status::Error("Invalid TileDB attribute object");
465     LOG_STATUS(st);
466     save_error(ctx, st);
467     return TILEDB_ERR;
468   }
469   return TILEDB_OK;
470 }
471 
sanity_check(tiledb_ctx_t * ctx,const tiledb_filter_t * filter)472 inline int32_t sanity_check(tiledb_ctx_t* ctx, const tiledb_filter_t* filter) {
473   if (filter == nullptr || filter->filter_ == nullptr) {
474     auto st = Status::Error("Invalid TileDB filter object");
475     LOG_STATUS(st);
476     save_error(ctx, st);
477     return TILEDB_ERR;
478   }
479   return TILEDB_OK;
480 }
481 
sanity_check(tiledb_ctx_t * ctx,const tiledb_filter_list_t * filter_list)482 inline int32_t sanity_check(
483     tiledb_ctx_t* ctx, const tiledb_filter_list_t* filter_list) {
484   if (filter_list == nullptr || filter_list->pipeline_ == nullptr) {
485     auto st = Status::Error("Invalid TileDB filter list object");
486     LOG_STATUS(st);
487     save_error(ctx, st);
488     return TILEDB_ERR;
489   }
490   return TILEDB_OK;
491 }
492 
sanity_check(tiledb_ctx_t * ctx,const tiledb_dimension_t * dim)493 inline int32_t sanity_check(tiledb_ctx_t* ctx, const tiledb_dimension_t* dim) {
494   if (dim == nullptr || dim->dim_ == nullptr) {
495     auto st = Status::Error("Invalid TileDB dimension object");
496     LOG_STATUS(st);
497     save_error(ctx, st);
498     return TILEDB_ERR;
499   }
500   return TILEDB_OK;
501 }
502 
sanity_check(tiledb_ctx_t * ctx,const tiledb_array_schema_t * array_schema)503 inline int32_t sanity_check(
504     tiledb_ctx_t* ctx, const tiledb_array_schema_t* array_schema) {
505   if (array_schema == nullptr || array_schema->array_schema_ == nullptr) {
506     auto st = Status::Error("Invalid TileDB array schema object");
507     LOG_STATUS(st);
508     save_error(ctx, st);
509     return TILEDB_ERR;
510   }
511   return TILEDB_OK;
512 }
513 
sanity_check(tiledb_ctx_t * ctx,const tiledb_array_schema_evolution_t * schema_evolution)514 inline int32_t sanity_check(
515     tiledb_ctx_t* ctx,
516     const tiledb_array_schema_evolution_t* schema_evolution) {
517   if (schema_evolution == nullptr ||
518       schema_evolution->array_schema_evolution_ == nullptr) {
519     auto st = Status::Error("Invalid TileDB array schema evolution object");
520     LOG_STATUS(st);
521     save_error(ctx, st);
522     return TILEDB_ERR;
523   }
524   return TILEDB_OK;
525 }
526 
sanity_check(tiledb_ctx_t * ctx,const tiledb_domain_t * domain)527 inline int32_t sanity_check(tiledb_ctx_t* ctx, const tiledb_domain_t* domain) {
528   if (domain == nullptr || domain->domain_ == nullptr) {
529     auto st = Status::Error("Invalid TileDB domain object");
530     LOG_STATUS(st);
531     save_error(ctx, st);
532     return TILEDB_ERR;
533   }
534   return TILEDB_OK;
535 }
536 
sanity_check(tiledb_ctx_t * ctx,const tiledb_query_t * query)537 inline int32_t sanity_check(tiledb_ctx_t* ctx, const tiledb_query_t* query) {
538   if (query == nullptr || query->query_ == nullptr) {
539     auto st = Status::Error("Invalid TileDB query object");
540     LOG_STATUS(st);
541     save_error(ctx, st);
542     return TILEDB_ERR;
543   }
544   return TILEDB_OK;
545 }
546 
sanity_check(tiledb_ctx_t * ctx,const tiledb_query_condition_t * cond)547 inline int32_t sanity_check(
548     tiledb_ctx_t* ctx, const tiledb_query_condition_t* cond) {
549   if (cond == nullptr || cond->query_condition_ == nullptr) {
550     auto st = Status::Error("Invalid TileDB query condition object");
551     LOG_STATUS(st);
552     save_error(ctx, st);
553     return TILEDB_ERR;
554   }
555   return TILEDB_OK;
556 }
557 
sanity_check(tiledb_ctx_t * ctx,const tiledb_vfs_t * vfs)558 inline int32_t sanity_check(tiledb_ctx_t* ctx, const tiledb_vfs_t* vfs) {
559   if (vfs == nullptr || vfs->vfs_ == nullptr) {
560     auto st = Status::Error("Invalid TileDB virtual filesystem object");
561     LOG_STATUS(st);
562     save_error(ctx, st);
563     return TILEDB_ERR;
564   }
565   return TILEDB_OK;
566 }
567 
sanity_check(tiledb_ctx_t * ctx,const tiledb_vfs_fh_t * fh)568 inline int32_t sanity_check(tiledb_ctx_t* ctx, const tiledb_vfs_fh_t* fh) {
569   if (fh == nullptr || fh->vfs_fh_ == nullptr) {
570     auto st = Status::Error("Invalid TileDB virtual filesystem file handle");
571     LOG_STATUS(st);
572     save_error(ctx, st);
573     return TILEDB_ERR;
574   }
575   return TILEDB_OK;
576 }
577 
sanity_check(tiledb_ctx_t * ctx,const tiledb_fragment_info_t * fragment_info)578 inline int32_t sanity_check(
579     tiledb_ctx_t* ctx, const tiledb_fragment_info_t* fragment_info) {
580   if (fragment_info == nullptr || fragment_info->fragment_info_ == nullptr) {
581     auto st = Status::Error("Invalid TileDB fragment info object");
582     LOG_STATUS(st);
583     save_error(ctx, st);
584     return TILEDB_ERR;
585   }
586   return TILEDB_OK;
587 }
588 
check_filter_type(tiledb_ctx_t * ctx,tiledb_filter_t * filter,tiledb_filter_type_t type)589 inline int32_t check_filter_type(
590     tiledb_ctx_t* ctx, tiledb_filter_t* filter, tiledb_filter_type_t type) {
591   auto cpp_type = static_cast<tiledb::sm::FilterType>(type);
592   if (filter->filter_->type() != cpp_type) {
593     auto st = Status::FilterError(
594         "Invalid filter type (expected " + filter_type_str(cpp_type) + ")");
595     LOG_STATUS(st);
596     save_error(ctx, st);
597     return TILEDB_ERR;
598   }
599   return TILEDB_OK;
600 }
601 
602 /**
603  * Helper macro similar to save_error() that catches all exceptions when
604  * executing 'stmt'.
605  *
606  * @param ctx TileDB context
607  * @param stmt Statement to execute
608  */
609 #define SAVE_ERROR_CATCH(ctx, stmt)                                        \
610   [&]() {                                                                  \
611     auto _s = Status::Ok();                                                \
612     try {                                                                  \
613       _s = (stmt);                                                         \
614     } catch (const std::exception& e) {                                    \
615       auto st = Status::Error(                                             \
616           std::string("Internal TileDB uncaught exception; ") + e.what()); \
617       LOG_STATUS(st);                                                      \
618       save_error(ctx, st);                                                 \
619       return true;                                                         \
620     }                                                                      \
621     return save_error(ctx, _s);                                            \
622   }()
623 
624 /** For debugging, use this definition instead to not catch exceptions. */
625 //#define SAVE_ERROR_CATCH(ctx, stmt) save_error(ctx, (stmt))
626 
627 /* ********************************* */
628 /*              ERROR                */
629 /* ********************************* */
630 
tiledb_error_message(tiledb_error_t * err,const char ** errmsg)631 int32_t tiledb_error_message(tiledb_error_t* err, const char** errmsg) {
632   if (err == nullptr)
633     return TILEDB_ERR;
634   if (err->errmsg_.empty())
635     *errmsg = nullptr;
636   else
637     *errmsg = err->errmsg_.c_str();
638   return TILEDB_OK;
639 }
640 
tiledb_error_free(tiledb_error_t ** err)641 void tiledb_error_free(tiledb_error_t** err) {
642   if (err != nullptr && *err != nullptr) {
643     delete (*err);
644     *err = nullptr;
645   }
646 }
647 
648 /* ********************************* */
649 /*              BUFFER               */
650 /* ********************************* */
651 
tiledb_buffer_alloc(tiledb_ctx_t * ctx,tiledb_buffer_t ** buffer)652 int32_t tiledb_buffer_alloc(tiledb_ctx_t* ctx, tiledb_buffer_t** buffer) {
653   if (sanity_check(ctx) == TILEDB_ERR)
654     return TILEDB_ERR;
655 
656   // Create a buffer struct
657   *buffer = new (std::nothrow) tiledb_buffer_t;
658   if (*buffer == nullptr) {
659     auto st = Status::Error("Failed to allocate TileDB buffer object");
660     LOG_STATUS(st);
661     save_error(ctx, st);
662     return TILEDB_OOM;
663   }
664 
665   // Create a new buffer object
666   (*buffer)->buffer_ = new (std::nothrow) tiledb::sm::Buffer();
667   if ((*buffer)->buffer_ == nullptr) {
668     delete *buffer;
669     *buffer = nullptr;
670     auto st = Status::Error("Failed to allocate TileDB buffer object");
671     LOG_STATUS(st);
672     save_error(ctx, st);
673     return TILEDB_OOM;
674   }
675 
676   // Success
677   return TILEDB_OK;
678 }
679 
tiledb_buffer_free(tiledb_buffer_t ** buffer)680 void tiledb_buffer_free(tiledb_buffer_t** buffer) {
681   if (buffer != nullptr && *buffer != nullptr) {
682     delete (*buffer)->buffer_;
683     delete (*buffer);
684     *buffer = nullptr;
685   }
686 }
687 
tiledb_buffer_set_type(tiledb_ctx_t * ctx,tiledb_buffer_t * buffer,tiledb_datatype_t datatype)688 int32_t tiledb_buffer_set_type(
689     tiledb_ctx_t* ctx, tiledb_buffer_t* buffer, tiledb_datatype_t datatype) {
690   if (sanity_check(ctx) == TILEDB_ERR ||
691       sanity_check(ctx, buffer) == TILEDB_ERR)
692     return TILEDB_ERR;
693 
694   buffer->datatype_ = static_cast<tiledb::sm::Datatype>(datatype);
695 
696   return TILEDB_OK;
697 }
698 
tiledb_buffer_get_type(tiledb_ctx_t * ctx,const tiledb_buffer_t * buffer,tiledb_datatype_t * datatype)699 int32_t tiledb_buffer_get_type(
700     tiledb_ctx_t* ctx,
701     const tiledb_buffer_t* buffer,
702     tiledb_datatype_t* datatype) {
703   if (sanity_check(ctx) == TILEDB_ERR ||
704       sanity_check(ctx, buffer) == TILEDB_ERR)
705     return TILEDB_ERR;
706 
707   *datatype = static_cast<tiledb_datatype_t>(buffer->datatype_);
708 
709   return TILEDB_OK;
710 }
711 
tiledb_buffer_get_data(tiledb_ctx_t * ctx,const tiledb_buffer_t * buffer,void ** data,uint64_t * num_bytes)712 int32_t tiledb_buffer_get_data(
713     tiledb_ctx_t* ctx,
714     const tiledb_buffer_t* buffer,
715     void** data,
716     uint64_t* num_bytes) {
717   if (sanity_check(ctx) == TILEDB_ERR ||
718       sanity_check(ctx, buffer) == TILEDB_ERR)
719     return TILEDB_ERR;
720 
721   *data = buffer->buffer_->data();
722   *num_bytes = buffer->buffer_->size();
723 
724   return TILEDB_OK;
725 }
726 
tiledb_buffer_set_data(tiledb_ctx_t * ctx,tiledb_buffer_t * buffer,void * data,uint64_t size)727 int32_t tiledb_buffer_set_data(
728     tiledb_ctx_t* ctx, tiledb_buffer_t* buffer, void* data, uint64_t size) {
729   if (sanity_check(ctx) == TILEDB_ERR ||
730       sanity_check(ctx, buffer) == TILEDB_ERR)
731     return TILEDB_ERR;
732 
733   // Create a temporary Buffer object as a wrapper.
734   tiledb::sm::Buffer tmp_buffer(data, size);
735 
736   // Swap with the given buffer.
737   if (SAVE_ERROR_CATCH(ctx, buffer->buffer_->swap(tmp_buffer)))
738     return TILEDB_ERR;
739 
740   // 'tmp_buffer' now destructs, freeing the old allocation (if any) of the
741   // given buffer.
742 
743   return TILEDB_OK;
744 }
745 
746 /* ********************************* */
747 /*            BUFFER LIST            */
748 /* ********************************* */
749 
tiledb_buffer_list_alloc(tiledb_ctx_t * ctx,tiledb_buffer_list_t ** buffer_list)750 int32_t tiledb_buffer_list_alloc(
751     tiledb_ctx_t* ctx, tiledb_buffer_list_t** buffer_list) {
752   if (sanity_check(ctx) == TILEDB_ERR)
753     return TILEDB_ERR;
754 
755   // Create a buffer list struct
756   *buffer_list = new (std::nothrow) tiledb_buffer_list_t;
757   if (*buffer_list == nullptr) {
758     auto st = Status::Error("Failed to allocate TileDB buffer list object");
759     LOG_STATUS(st);
760     save_error(ctx, st);
761     return TILEDB_OOM;
762   }
763 
764   // Create a new buffer_list object
765   (*buffer_list)->buffer_list_ = new (std::nothrow) tiledb::sm::BufferList;
766   if ((*buffer_list)->buffer_list_ == nullptr) {
767     delete *buffer_list;
768     *buffer_list = nullptr;
769     auto st = Status::Error("Failed to allocate TileDB buffer list object");
770     LOG_STATUS(st);
771     save_error(ctx, st);
772     return TILEDB_OOM;
773   }
774 
775   // Success
776   return TILEDB_OK;
777 }
778 
tiledb_buffer_list_free(tiledb_buffer_list_t ** buffer_list)779 void tiledb_buffer_list_free(tiledb_buffer_list_t** buffer_list) {
780   if (buffer_list != nullptr && *buffer_list != nullptr) {
781     delete (*buffer_list)->buffer_list_;
782     delete (*buffer_list);
783     *buffer_list = nullptr;
784   }
785 }
786 
tiledb_buffer_list_get_num_buffers(tiledb_ctx_t * ctx,const tiledb_buffer_list_t * buffer_list,uint64_t * num_buffers)787 int32_t tiledb_buffer_list_get_num_buffers(
788     tiledb_ctx_t* ctx,
789     const tiledb_buffer_list_t* buffer_list,
790     uint64_t* num_buffers) {
791   // Sanity check
792   if (sanity_check(ctx) == TILEDB_ERR ||
793       sanity_check(ctx, buffer_list) == TILEDB_ERR)
794     return TILEDB_ERR;
795 
796   *num_buffers = buffer_list->buffer_list_->num_buffers();
797 
798   return TILEDB_OK;
799 }
800 
tiledb_buffer_list_get_buffer(tiledb_ctx_t * ctx,const tiledb_buffer_list_t * buffer_list,uint64_t buffer_idx,tiledb_buffer_t ** buffer)801 int32_t tiledb_buffer_list_get_buffer(
802     tiledb_ctx_t* ctx,
803     const tiledb_buffer_list_t* buffer_list,
804     uint64_t buffer_idx,
805     tiledb_buffer_t** buffer) {
806   // Sanity check
807   if (sanity_check(ctx) == TILEDB_ERR ||
808       sanity_check(ctx, buffer_list) == TILEDB_ERR)
809     return TILEDB_ERR;
810 
811   // Get the underlying buffer
812   tiledb::sm::Buffer* b;
813   if (SAVE_ERROR_CATCH(
814           ctx, buffer_list->buffer_list_->get_buffer(buffer_idx, &b)))
815     return TILEDB_ERR;
816 
817   // Create a buffer struct
818   *buffer = new (std::nothrow) tiledb_buffer_t;
819   if (*buffer == nullptr) {
820     auto st = Status::Error("Failed to allocate TileDB buffer object");
821     LOG_STATUS(st);
822     save_error(ctx, st);
823     return TILEDB_OOM;
824   }
825 
826   // Set the buffer pointer to a non-owning wrapper of the underlying buffer
827   (*buffer)->buffer_ =
828       new (std::nothrow) tiledb::sm::Buffer(b->data(), b->size());
829   if ((*buffer)->buffer_ == nullptr) {
830     delete *buffer;
831     *buffer = nullptr;
832     auto st = Status::Error("Failed to allocate TileDB buffer object");
833     LOG_STATUS(st);
834     save_error(ctx, st);
835     return TILEDB_OOM;
836   }
837 
838   return TILEDB_OK;
839 }
840 
tiledb_buffer_list_get_total_size(tiledb_ctx_t * ctx,const tiledb_buffer_list_t * buffer_list,uint64_t * total_size)841 int32_t tiledb_buffer_list_get_total_size(
842     tiledb_ctx_t* ctx,
843     const tiledb_buffer_list_t* buffer_list,
844     uint64_t* total_size) {
845   // Sanity check
846   if (sanity_check(ctx) == TILEDB_ERR ||
847       sanity_check(ctx, buffer_list) == TILEDB_ERR)
848     return TILEDB_ERR;
849 
850   *total_size = buffer_list->buffer_list_->total_size();
851 
852   return TILEDB_OK;
853 }
854 
tiledb_buffer_list_flatten(tiledb_ctx_t * ctx,const tiledb_buffer_list_t * buffer_list,tiledb_buffer_t ** buffer)855 int32_t tiledb_buffer_list_flatten(
856     tiledb_ctx_t* ctx,
857     const tiledb_buffer_list_t* buffer_list,
858     tiledb_buffer_t** buffer) {
859   // Sanity check
860   if (sanity_check(ctx) == TILEDB_ERR ||
861       sanity_check(ctx, buffer_list) == TILEDB_ERR)
862     return TILEDB_ERR;
863 
864   // Create a buffer instance
865   if (tiledb_buffer_alloc(ctx, buffer) == TILEDB_ERR ||
866       sanity_check(ctx, *buffer) == TILEDB_ERR)
867     return TILEDB_ERR;
868 
869   // Resize the dest buffer
870   const auto nbytes = buffer_list->buffer_list_->total_size();
871   if (SAVE_ERROR_CATCH(ctx, (*buffer)->buffer_->realloc(nbytes)))
872     return TILEDB_ERR;
873 
874   // Read all into the dest buffer
875   buffer_list->buffer_list_->reset_offset();
876   if (SAVE_ERROR_CATCH(
877           ctx,
878           buffer_list->buffer_list_->read((*buffer)->buffer_->data(), nbytes)))
879     return TILEDB_ERR;
880 
881   // Set the result size
882   (*buffer)->buffer_->set_size(nbytes);
883 
884   return TILEDB_OK;
885 }
886 
887 /* ****************************** */
888 /*            CONFIG              */
889 /* ****************************** */
890 
tiledb_config_alloc(tiledb_config_t ** config,tiledb_error_t ** error)891 int32_t tiledb_config_alloc(tiledb_config_t** config, tiledb_error_t** error) {
892   // Create a new config struct
893   *config = new (std::nothrow) tiledb_config_t;
894   if (*config == nullptr) {
895     auto st =
896         Status::Error("Cannot create config object; Memory allocation failed");
897     LOG_STATUS(st);
898     create_error(error, st);
899     return TILEDB_OOM;
900   }
901 
902   // Create storage manager
903   (*config)->config_ = new (std::nothrow) tiledb::sm::Config();
904   if ((*config)->config_ == nullptr) {
905     auto st =
906         Status::Error("Cannot create config object; Memory allocation failed");
907     LOG_STATUS(st);
908     create_error(error, st);
909     if (*config != nullptr) {
910       delete *config;
911       *config = nullptr;
912     }
913     return TILEDB_OOM;
914   }
915 
916   // Success
917   *error = nullptr;
918   return TILEDB_OK;
919 }
920 
tiledb_config_free(tiledb_config_t ** config)921 void tiledb_config_free(tiledb_config_t** config) {
922   if (config != nullptr && *config != nullptr) {
923     delete (*config)->config_;
924     delete (*config);
925     *config = nullptr;
926   }
927 }
928 
tiledb_config_set(tiledb_config_t * config,const char * param,const char * value,tiledb_error_t ** error)929 int32_t tiledb_config_set(
930     tiledb_config_t* config,
931     const char* param,
932     const char* value,
933     tiledb_error_t** error) {
934   if (sanity_check(config, error) == TILEDB_ERR)
935     return TILEDB_ERR;
936 
937   if (create_error(error, config->config_->set(param, value)))
938     return TILEDB_ERR;
939 
940   *error = nullptr;
941   return TILEDB_OK;
942 }
943 
tiledb_config_get(tiledb_config_t * config,const char * param,const char ** value,tiledb_error_t ** error)944 int32_t tiledb_config_get(
945     tiledb_config_t* config,
946     const char* param,
947     const char** value,
948     tiledb_error_t** error) {
949   if (sanity_check(config, error) == TILEDB_ERR)
950     return TILEDB_ERR;
951 
952   if (create_error(error, config->config_->get(param, value)))
953     return TILEDB_ERR;
954 
955   *error = nullptr;
956   return TILEDB_OK;
957 }
958 
tiledb_config_load_from_file(tiledb_config_t * config,const char * filename,tiledb_error_t ** error)959 int32_t tiledb_config_load_from_file(
960     tiledb_config_t* config, const char* filename, tiledb_error_t** error) {
961   if (sanity_check(config, error) == TILEDB_ERR)
962     return TILEDB_ERR;
963 
964   if (filename == nullptr) {
965     auto st = Status::Error("Cannot load from file; Invalid filename");
966     LOG_STATUS(st);
967     create_error(error, st);
968   }
969 
970   if (create_error(error, config->config_->load_from_file(filename)))
971     return TILEDB_ERR;
972 
973   *error = nullptr;
974   return TILEDB_OK;
975 }
976 
tiledb_config_save_to_file(tiledb_config_t * config,const char * filename,tiledb_error_t ** error)977 int32_t tiledb_config_save_to_file(
978     tiledb_config_t* config, const char* filename, tiledb_error_t** error) {
979   if (sanity_check(config, error) == TILEDB_ERR)
980     return TILEDB_ERR;
981 
982   if (filename == nullptr) {
983     auto st = Status::Error("Cannot save to file; Invalid filename");
984     LOG_STATUS(st);
985     create_error(error, st);
986   }
987 
988   if (create_error(error, config->config_->save_to_file(filename)))
989     return TILEDB_ERR;
990 
991   *error = nullptr;
992   return TILEDB_OK;
993 }
994 
tiledb_config_unset(tiledb_config_t * config,const char * param,tiledb_error_t ** error)995 int32_t tiledb_config_unset(
996     tiledb_config_t* config, const char* param, tiledb_error_t** error) {
997   if (sanity_check(config, error) == TILEDB_ERR)
998     return TILEDB_ERR;
999 
1000   if (create_error(error, config->config_->unset(param)))
1001     return TILEDB_ERR;
1002 
1003   *error = nullptr;
1004   return TILEDB_OK;
1005 }
1006 
tiledb_config_compare(tiledb_config_t * lhs,tiledb_config_t * rhs,uint8_t * equal)1007 int32_t tiledb_config_compare(
1008     tiledb_config_t* lhs, tiledb_config_t* rhs, uint8_t* equal) {
1009   auto st = Status::Error("Invalid \"equal\" argument");
1010   if (equal == nullptr)
1011     LOG_STATUS(st);
1012   tiledb_error_t* error = nullptr;
1013   if (sanity_check(lhs, &error) == TILEDB_ERR)
1014     return TILEDB_ERR;
1015   if (sanity_check(rhs, &error) == TILEDB_ERR)
1016     return TILEDB_ERR;
1017   if (*lhs->config_ == *rhs->config_)
1018     *equal = 1;
1019   else
1020     *equal = 0;
1021   return TILEDB_OK;
1022 }
1023 
1024 /* ****************************** */
1025 /*           CONFIG ITER          */
1026 /* ****************************** */
1027 
tiledb_config_iter_alloc(tiledb_config_t * config,const char * prefix,tiledb_config_iter_t ** config_iter,tiledb_error_t ** error)1028 int32_t tiledb_config_iter_alloc(
1029     tiledb_config_t* config,
1030     const char* prefix,
1031     tiledb_config_iter_t** config_iter,
1032     tiledb_error_t** error) {
1033   if (sanity_check(config, error) == TILEDB_ERR)
1034     return TILEDB_ERR;
1035 
1036   *config_iter = new (std::nothrow) tiledb_config_iter_t;
1037   if (*config_iter == nullptr) {
1038     auto st = Status::Error(
1039         "Cannot create config iterator object; Memory allocation failed");
1040     LOG_STATUS(st);
1041     create_error(error, st);
1042     return TILEDB_OOM;
1043   }
1044 
1045   std::string prefix_str = (prefix == nullptr) ? "" : std::string(prefix);
1046   (*config_iter)->config_iter_ =
1047       new (std::nothrow) tiledb::sm::ConfigIter(config->config_, prefix_str);
1048   if ((*config_iter)->config_iter_ == nullptr) {
1049     auto st = Status::Error(
1050         "Cannot create config iterator object; Memory allocation failed");
1051     LOG_STATUS(st);
1052     create_error(error, st);
1053     delete *config_iter;
1054     *config_iter = nullptr;
1055     return TILEDB_OOM;
1056   }
1057 
1058   *error = nullptr;
1059   return TILEDB_OK;
1060 }
1061 
tiledb_config_iter_reset(tiledb_config_t * config,tiledb_config_iter_t * config_iter,const char * prefix,tiledb_error_t ** error)1062 int32_t tiledb_config_iter_reset(
1063     tiledb_config_t* config,
1064     tiledb_config_iter_t* config_iter,
1065     const char* prefix,
1066     tiledb_error_t** error) {
1067   if (sanity_check(config, error) == TILEDB_ERR ||
1068       sanity_check(config_iter, error) == TILEDB_ERR)
1069     return TILEDB_ERR;
1070 
1071   std::string prefix_str = (prefix == nullptr) ? "" : std::string(prefix);
1072   config_iter->config_iter_->reset(config->config_, prefix_str);
1073 
1074   *error = nullptr;
1075   return TILEDB_OK;
1076 }
1077 
tiledb_config_iter_free(tiledb_config_iter_t ** config_iter)1078 void tiledb_config_iter_free(tiledb_config_iter_t** config_iter) {
1079   if (config_iter != nullptr && *config_iter != nullptr) {
1080     delete (*config_iter)->config_iter_;
1081     delete *config_iter;
1082     *config_iter = nullptr;
1083   }
1084 }
1085 
tiledb_config_iter_here(tiledb_config_iter_t * config_iter,const char ** param,const char ** value,tiledb_error_t ** error)1086 int32_t tiledb_config_iter_here(
1087     tiledb_config_iter_t* config_iter,
1088     const char** param,
1089     const char** value,
1090     tiledb_error_t** error) {
1091   if (sanity_check(config_iter, error) == TILEDB_ERR)
1092     return TILEDB_ERR;
1093 
1094   if (config_iter->config_iter_->end()) {
1095     *param = nullptr;
1096     *value = nullptr;
1097   } else {
1098     *param = config_iter->config_iter_->param().c_str();
1099     *value = config_iter->config_iter_->value().c_str();
1100   }
1101 
1102   *error = nullptr;
1103   return TILEDB_OK;
1104 }
1105 
tiledb_config_iter_next(tiledb_config_iter_t * config_iter,tiledb_error_t ** error)1106 int32_t tiledb_config_iter_next(
1107     tiledb_config_iter_t* config_iter, tiledb_error_t** error) {
1108   if (sanity_check(config_iter, error) == TILEDB_ERR)
1109     return TILEDB_ERR;
1110 
1111   config_iter->config_iter_->next();
1112 
1113   *error = nullptr;
1114   return TILEDB_OK;
1115 }
1116 
tiledb_config_iter_done(tiledb_config_iter_t * config_iter,int32_t * done,tiledb_error_t ** error)1117 int32_t tiledb_config_iter_done(
1118     tiledb_config_iter_t* config_iter, int32_t* done, tiledb_error_t** error) {
1119   if (sanity_check(config_iter, error) == TILEDB_ERR)
1120     return TILEDB_ERR;
1121 
1122   *done = (int32_t)config_iter->config_iter_->end();
1123 
1124   *error = nullptr;
1125   return TILEDB_OK;
1126 }
1127 
1128 /* ****************************** */
1129 /*            CONTEXT             */
1130 /* ****************************** */
1131 
tiledb_ctx_alloc(tiledb_config_t * config,tiledb_ctx_t ** ctx)1132 int32_t tiledb_ctx_alloc(tiledb_config_t* config, tiledb_ctx_t** ctx) try {
1133   if (config != nullptr && config->config_ == nullptr)
1134     return TILEDB_ERR;
1135 
1136   // Create a context object
1137   *ctx = new (std::nothrow) tiledb_ctx_t;
1138   if (*ctx == nullptr)
1139     return TILEDB_OOM;
1140 
1141   // Create a context object
1142   (*ctx)->ctx_ = new (std::nothrow) tiledb::sm::Context();
1143   if ((*ctx)->ctx_ == nullptr) {
1144     delete (*ctx);
1145     (*ctx) = nullptr;
1146     return TILEDB_OOM;
1147   }
1148 
1149   // Initialize the context
1150   auto conf =
1151       (config == nullptr) ? (tiledb::sm::Config*)nullptr : config->config_;
1152   auto st = (*ctx)->ctx_->init(conf);
1153 
1154   if (!st.ok()) {
1155     delete (*ctx)->ctx_;
1156     delete (*ctx);
1157     (*ctx) = nullptr;
1158     LOG_STATUS(st);
1159     return TILEDB_ERR;
1160   }
1161 
1162   // Success
1163   return TILEDB_OK;
1164 } catch (const std::bad_alloc& e) {
1165   delete (*ctx)->ctx_;
1166   delete (*ctx);
1167   (*ctx) = nullptr;
1168   auto st = Status::Error(
1169       std::string("Internal TileDB uncaught std::bad_alloc exception; ") +
1170       e.what());
1171   LOG_STATUS(st);
1172   return TILEDB_OOM;
1173 } catch (const std::exception& e) {
1174   delete (*ctx)->ctx_;
1175   delete (*ctx);
1176   (*ctx) = nullptr;
1177   auto st = Status::Error(
1178       std::string("Internal TileDB uncaught exception; ") + e.what());
1179   LOG_STATUS(st);
1180   return TILEDB_ERR;
1181 }
1182 
tiledb_ctx_free(tiledb_ctx_t ** ctx)1183 void tiledb_ctx_free(tiledb_ctx_t** ctx) {
1184   if (ctx != nullptr && *ctx != nullptr) {
1185     delete (*ctx)->ctx_;
1186     delete (*ctx);
1187     *ctx = nullptr;
1188   }
1189 }
1190 
tiledb_ctx_get_stats(tiledb_ctx_t * ctx,char ** stats_json)1191 int32_t tiledb_ctx_get_stats(tiledb_ctx_t* ctx, char** stats_json) {
1192   if (sanity_check(ctx) == TILEDB_ERR)
1193     return TILEDB_ERR;
1194 
1195   if (stats_json == nullptr)
1196     return TILEDB_ERR;
1197 
1198   const std::string str = ctx->ctx_->stats()->dump(2, 0);
1199 
1200   *stats_json = static_cast<char*>(std::malloc(str.size() + 1));
1201   if (*stats_json == nullptr)
1202     return TILEDB_ERR;
1203 
1204   std::memcpy(*stats_json, str.data(), str.size());
1205   (*stats_json)[str.size()] = '\0';
1206 
1207   return TILEDB_OK;
1208 }
1209 
tiledb_ctx_get_config(tiledb_ctx_t * ctx,tiledb_config_t ** config)1210 int32_t tiledb_ctx_get_config(tiledb_ctx_t* ctx, tiledb_config_t** config) {
1211   // Create a new config struct
1212   *config = new (std::nothrow) tiledb_config_t;
1213   if (*config == nullptr)
1214     return TILEDB_OOM;
1215 
1216   (*config)->config_ = new (std::nothrow) tiledb::sm::Config();
1217   if ((*config)->config_ == nullptr) {
1218     delete (*config);
1219     *config = nullptr;
1220     return TILEDB_OOM;
1221   }
1222 
1223   // this assignment is a copy
1224   *((*config)->config_) = ctx->ctx_->storage_manager()->config();
1225 
1226   return TILEDB_OK;
1227 }
1228 
tiledb_ctx_get_last_error(tiledb_ctx_t * ctx,tiledb_error_t ** err)1229 int32_t tiledb_ctx_get_last_error(tiledb_ctx_t* ctx, tiledb_error_t** err) {
1230   // sanity check
1231   if (ctx == nullptr || ctx->ctx_ == nullptr)
1232     return TILEDB_ERR;
1233 
1234   Status last_error = ctx->ctx_->last_error();
1235 
1236   // No last error
1237   if (last_error.ok()) {
1238     *err = nullptr;
1239     return TILEDB_OK;
1240   }
1241 
1242   // Create error struct
1243   *err = new (std::nothrow) tiledb_error_t;
1244   if (*err == nullptr)
1245     return TILEDB_OOM;
1246 
1247   // Set error message
1248   (*err)->errmsg_ = last_error.to_string();
1249 
1250   // Success
1251   return TILEDB_OK;
1252 }
1253 
tiledb_ctx_is_supported_fs(tiledb_ctx_t * ctx,tiledb_filesystem_t fs,int32_t * is_supported)1254 int32_t tiledb_ctx_is_supported_fs(
1255     tiledb_ctx_t* ctx, tiledb_filesystem_t fs, int32_t* is_supported) {
1256   if (sanity_check(ctx) == TILEDB_ERR)
1257     return TILEDB_ERR;
1258 
1259   *is_supported = (int32_t)ctx->ctx_->storage_manager()->vfs()->supports_fs(
1260       static_cast<tiledb::sm::Filesystem>(fs));
1261 
1262   return TILEDB_OK;
1263 }
1264 
tiledb_ctx_cancel_tasks(tiledb_ctx_t * ctx)1265 int32_t tiledb_ctx_cancel_tasks(tiledb_ctx_t* ctx) {
1266   if (sanity_check(ctx) == TILEDB_ERR)
1267     return TILEDB_ERR;
1268 
1269   if (SAVE_ERROR_CATCH(ctx, ctx->ctx_->storage_manager()->cancel_all_tasks()))
1270     return TILEDB_ERR;
1271 
1272   return TILEDB_OK;
1273 }
1274 
tiledb_ctx_set_tag(tiledb_ctx_t * ctx,const char * key,const char * value)1275 int32_t tiledb_ctx_set_tag(
1276     tiledb_ctx_t* ctx, const char* key, const char* value) {
1277   if (sanity_check(ctx) == TILEDB_ERR)
1278     return TILEDB_ERR;
1279 
1280   if (SAVE_ERROR_CATCH(ctx, ctx->ctx_->storage_manager()->set_tag(key, value)))
1281     return TILEDB_ERR;
1282 
1283   return TILEDB_OK;
1284 }
1285 
1286 /* ****************************** */
1287 /*              GROUP             */
1288 /* ****************************** */
1289 
tiledb_group_create(tiledb_ctx_t * ctx,const char * group_uri)1290 int32_t tiledb_group_create(tiledb_ctx_t* ctx, const char* group_uri) {
1291   if (sanity_check(ctx) == TILEDB_ERR)
1292     return TILEDB_ERR;
1293 
1294   // Check for error
1295   if (group_uri == nullptr) {
1296     auto st = Status::Error("Invalid group directory argument is NULL");
1297     LOG_STATUS(st);
1298     save_error(ctx, st);
1299     return TILEDB_ERR;
1300   }
1301 
1302   // Create the group
1303   if (SAVE_ERROR_CATCH(
1304           ctx, ctx->ctx_->storage_manager()->group_create(group_uri)))
1305     return TILEDB_ERR;
1306 
1307   // Success
1308   return TILEDB_OK;
1309 }
1310 
1311 /* ********************************* */
1312 /*              FILTER               */
1313 /* ********************************* */
1314 
tiledb_filter_alloc(tiledb_ctx_t * ctx,tiledb_filter_type_t type,tiledb_filter_t ** filter)1315 int32_t tiledb_filter_alloc(
1316     tiledb_ctx_t* ctx, tiledb_filter_type_t type, tiledb_filter_t** filter) {
1317   if (sanity_check(ctx) == TILEDB_ERR)
1318     return TILEDB_ERR;
1319 
1320   // Create a filter struct
1321   *filter = new (std::nothrow) tiledb_filter_t;
1322   if (*filter == nullptr) {
1323     auto st = Status::Error("Failed to allocate TileDB filter object");
1324     LOG_STATUS(st);
1325     save_error(ctx, st);
1326     return TILEDB_OOM;
1327   }
1328 
1329   // Create a new Filter object of the given type
1330   (*filter)->filter_ =
1331       tiledb::sm::Filter::create(static_cast<tiledb::sm::FilterType>(type));
1332   if ((*filter)->filter_ == nullptr) {
1333     delete *filter;
1334     *filter = nullptr;
1335     auto st = Status::Error("Failed to allocate TileDB filter object");
1336     LOG_STATUS(st);
1337     save_error(ctx, st);
1338     return TILEDB_OOM;
1339   }
1340 
1341   // Success
1342   return TILEDB_OK;
1343 }
1344 
tiledb_filter_free(tiledb_filter_t ** filter)1345 void tiledb_filter_free(tiledb_filter_t** filter) {
1346   if (filter != nullptr && *filter != nullptr) {
1347     delete (*filter)->filter_;
1348     delete (*filter);
1349     *filter = nullptr;
1350   }
1351 }
1352 
tiledb_filter_get_type(tiledb_ctx_t * ctx,tiledb_filter_t * filter,tiledb_filter_type_t * type)1353 int32_t tiledb_filter_get_type(
1354     tiledb_ctx_t* ctx, tiledb_filter_t* filter, tiledb_filter_type_t* type) {
1355   if (sanity_check(ctx) == TILEDB_ERR ||
1356       sanity_check(ctx, filter) == TILEDB_ERR)
1357     return TILEDB_ERR;
1358 
1359   *type = static_cast<tiledb_filter_type_t>(filter->filter_->type());
1360 
1361   return TILEDB_OK;
1362 }
1363 
tiledb_filter_set_option(tiledb_ctx_t * ctx,tiledb_filter_t * filter,tiledb_filter_option_t option,const void * value)1364 int32_t tiledb_filter_set_option(
1365     tiledb_ctx_t* ctx,
1366     tiledb_filter_t* filter,
1367     tiledb_filter_option_t option,
1368     const void* value) {
1369   if (sanity_check(ctx) == TILEDB_ERR ||
1370       sanity_check(ctx, filter) == TILEDB_ERR)
1371     return TILEDB_ERR;
1372 
1373   if (SAVE_ERROR_CATCH(
1374           ctx,
1375           filter->filter_->set_option(
1376               static_cast<tiledb::sm::FilterOption>(option), value)))
1377     return TILEDB_ERR;
1378 
1379   // Success
1380   return TILEDB_OK;
1381 }
1382 
tiledb_filter_get_option(tiledb_ctx_t * ctx,tiledb_filter_t * filter,tiledb_filter_option_t option,void * value)1383 int32_t tiledb_filter_get_option(
1384     tiledb_ctx_t* ctx,
1385     tiledb_filter_t* filter,
1386     tiledb_filter_option_t option,
1387     void* value) {
1388   if (sanity_check(ctx) == TILEDB_ERR ||
1389       sanity_check(ctx, filter) == TILEDB_ERR)
1390     return TILEDB_ERR;
1391 
1392   if (SAVE_ERROR_CATCH(
1393           ctx,
1394           filter->filter_->get_option(
1395               static_cast<tiledb::sm::FilterOption>(option), value)))
1396     return TILEDB_ERR;
1397 
1398   // Success
1399   return TILEDB_OK;
1400 }
1401 
1402 /* ********************************* */
1403 /*            FILTER LIST            */
1404 /* ********************************* */
1405 
tiledb_filter_list_alloc(tiledb_ctx_t * ctx,tiledb_filter_list_t ** filter_list)1406 int32_t tiledb_filter_list_alloc(
1407     tiledb_ctx_t* ctx, tiledb_filter_list_t** filter_list) {
1408   if (sanity_check(ctx) == TILEDB_ERR)
1409     return TILEDB_ERR;
1410 
1411   // Create a filter struct
1412   *filter_list = new (std::nothrow) tiledb_filter_list_t;
1413   if (*filter_list == nullptr) {
1414     auto st = Status::Error("Failed to allocate TileDB filter list object");
1415     LOG_STATUS(st);
1416     save_error(ctx, st);
1417     return TILEDB_OOM;
1418   }
1419 
1420   // Create a new FilterPipeline object
1421   (*filter_list)->pipeline_ = new (std::nothrow) tiledb::sm::FilterPipeline();
1422   if ((*filter_list)->pipeline_ == nullptr) {
1423     delete *filter_list;
1424     *filter_list = nullptr;
1425     auto st = Status::Error("Failed to allocate TileDB filter list object");
1426     LOG_STATUS(st);
1427     save_error(ctx, st);
1428     return TILEDB_OOM;
1429   }
1430 
1431   // Success
1432   return TILEDB_OK;
1433 }
1434 
tiledb_filter_list_free(tiledb_filter_list_t ** filter_list)1435 void tiledb_filter_list_free(tiledb_filter_list_t** filter_list) {
1436   if (filter_list != nullptr && *filter_list != nullptr) {
1437     delete (*filter_list)->pipeline_;
1438     delete (*filter_list);
1439     *filter_list = nullptr;
1440   }
1441 }
1442 
tiledb_filter_list_add_filter(tiledb_ctx_t * ctx,tiledb_filter_list_t * filter_list,tiledb_filter_t * filter)1443 int32_t tiledb_filter_list_add_filter(
1444     tiledb_ctx_t* ctx,
1445     tiledb_filter_list_t* filter_list,
1446     tiledb_filter_t* filter) {
1447   if (sanity_check(ctx) == TILEDB_ERR ||
1448       sanity_check(ctx, filter_list) == TILEDB_ERR ||
1449       sanity_check(ctx, filter) == TILEDB_ERR)
1450     return TILEDB_ERR;
1451 
1452   if (SAVE_ERROR_CATCH(
1453           ctx, filter_list->pipeline_->add_filter(*filter->filter_)))
1454     return TILEDB_ERR;
1455 
1456   return TILEDB_OK;
1457 }
1458 
tiledb_filter_list_set_max_chunk_size(tiledb_ctx_t * ctx,const tiledb_filter_list_t * filter_list,uint32_t max_chunk_size)1459 int32_t tiledb_filter_list_set_max_chunk_size(
1460     tiledb_ctx_t* ctx,
1461     const tiledb_filter_list_t* filter_list,
1462     uint32_t max_chunk_size) {
1463   if (sanity_check(ctx) == TILEDB_ERR ||
1464       sanity_check(ctx, filter_list) == TILEDB_ERR)
1465     return TILEDB_ERR;
1466 
1467   filter_list->pipeline_->set_max_chunk_size(max_chunk_size);
1468 
1469   return TILEDB_OK;
1470 }
1471 
tiledb_filter_list_get_nfilters(tiledb_ctx_t * ctx,const tiledb_filter_list_t * filter_list,uint32_t * nfilters)1472 int32_t tiledb_filter_list_get_nfilters(
1473     tiledb_ctx_t* ctx,
1474     const tiledb_filter_list_t* filter_list,
1475     uint32_t* nfilters) {
1476   if (sanity_check(ctx) == TILEDB_ERR ||
1477       sanity_check(ctx, filter_list) == TILEDB_ERR)
1478     return TILEDB_ERR;
1479 
1480   *nfilters = filter_list->pipeline_->size();
1481 
1482   return TILEDB_OK;
1483 }
1484 
tiledb_filter_list_get_filter_from_index(tiledb_ctx_t * ctx,const tiledb_filter_list_t * filter_list,uint32_t index,tiledb_filter_t ** filter)1485 int32_t tiledb_filter_list_get_filter_from_index(
1486     tiledb_ctx_t* ctx,
1487     const tiledb_filter_list_t* filter_list,
1488     uint32_t index,
1489     tiledb_filter_t** filter) {
1490   if (sanity_check(ctx) == TILEDB_ERR ||
1491       sanity_check(ctx, filter_list) == TILEDB_ERR)
1492     return TILEDB_ERR;
1493 
1494   uint32_t nfilters = filter_list->pipeline_->size();
1495   if (nfilters == 0 && index == 0) {
1496     *filter = nullptr;
1497     return TILEDB_OK;
1498   }
1499 
1500   if (index >= nfilters) {
1501     auto st = Status::Error(
1502         "Filter " + std::to_string(index) + " out of bounds, filter list has " +
1503         std::to_string(nfilters) + " filters.");
1504     LOG_STATUS(st);
1505     save_error(ctx, st);
1506     return TILEDB_ERR;
1507   }
1508 
1509   auto f = filter_list->pipeline_->get_filter(index);
1510   if (f == nullptr) {
1511     auto st = Status::Error("Failed to retrieve filter at index");
1512     LOG_STATUS(st);
1513     save_error(ctx, st);
1514     return TILEDB_ERR;
1515   }
1516 
1517   *filter = new (std::nothrow) tiledb_filter_t;
1518   if (*filter == nullptr) {
1519     auto st = Status::Error("Failed to allocate TileDB filter object");
1520     LOG_STATUS(st);
1521     save_error(ctx, st);
1522     return TILEDB_OOM;
1523   }
1524 
1525   (*filter)->filter_ = f->clone();
1526 
1527   return TILEDB_OK;
1528 }
1529 
tiledb_filter_list_get_max_chunk_size(tiledb_ctx_t * ctx,const tiledb_filter_list_t * filter_list,uint32_t * max_chunk_size)1530 int32_t tiledb_filter_list_get_max_chunk_size(
1531     tiledb_ctx_t* ctx,
1532     const tiledb_filter_list_t* filter_list,
1533     uint32_t* max_chunk_size) {
1534   if (sanity_check(ctx) == TILEDB_ERR ||
1535       sanity_check(ctx, filter_list) == TILEDB_ERR)
1536     return TILEDB_ERR;
1537 
1538   *max_chunk_size = filter_list->pipeline_->max_chunk_size();
1539 
1540   return TILEDB_OK;
1541 }
1542 
1543 /* ********************************* */
1544 /*            ATTRIBUTE              */
1545 /* ********************************* */
1546 
tiledb_attribute_alloc(tiledb_ctx_t * ctx,const char * name,tiledb_datatype_t type,tiledb_attribute_t ** attr)1547 int32_t tiledb_attribute_alloc(
1548     tiledb_ctx_t* ctx,
1549     const char* name,
1550     tiledb_datatype_t type,
1551     tiledb_attribute_t** attr) {
1552   if (sanity_check(ctx) == TILEDB_ERR)
1553     return TILEDB_ERR;
1554 
1555   // Create an attribute struct
1556   *attr = new (std::nothrow) tiledb_attribute_t;
1557   if (*attr == nullptr) {
1558     auto st = Status::Error("Failed to allocate TileDB attribute object");
1559     LOG_STATUS(st);
1560     save_error(ctx, st);
1561     return TILEDB_OOM;
1562   }
1563 
1564   // Create a new Attribute object
1565   (*attr)->attr_ = new (std::nothrow)
1566       tiledb::sm::Attribute(name, static_cast<tiledb::sm::Datatype>(type));
1567   if ((*attr)->attr_ == nullptr) {
1568     delete *attr;
1569     *attr = nullptr;
1570     auto st = Status::Error("Failed to allocate TileDB attribute object");
1571     LOG_STATUS(st);
1572     save_error(ctx, st);
1573     return TILEDB_OOM;
1574   }
1575 
1576   // Success
1577   return TILEDB_OK;
1578 }
1579 
tiledb_attribute_free(tiledb_attribute_t ** attr)1580 void tiledb_attribute_free(tiledb_attribute_t** attr) {
1581   if (attr != nullptr && *attr != nullptr) {
1582     delete (*attr)->attr_;
1583     delete (*attr);
1584     *attr = nullptr;
1585   }
1586 }
1587 
tiledb_attribute_set_nullable(tiledb_ctx_t * ctx,tiledb_attribute_t * attr,uint8_t nullable)1588 int32_t tiledb_attribute_set_nullable(
1589     tiledb_ctx_t* ctx, tiledb_attribute_t* attr, uint8_t nullable) {
1590   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, attr) == TILEDB_ERR)
1591     return TILEDB_ERR;
1592 
1593   if (SAVE_ERROR_CATCH(
1594           ctx, attr->attr_->set_nullable(static_cast<bool>(nullable))))
1595     return TILEDB_ERR;
1596 
1597   return TILEDB_OK;
1598 }
1599 
tiledb_attribute_set_filter_list(tiledb_ctx_t * ctx,tiledb_attribute_t * attr,tiledb_filter_list_t * filter_list)1600 int32_t tiledb_attribute_set_filter_list(
1601     tiledb_ctx_t* ctx,
1602     tiledb_attribute_t* attr,
1603     tiledb_filter_list_t* filter_list) {
1604   if (sanity_check(ctx) == TILEDB_ERR ||
1605       sanity_check(ctx, attr) == TILEDB_ERR ||
1606       sanity_check(ctx, filter_list) == TILEDB_ERR)
1607     return TILEDB_ERR;
1608 
1609   if (SAVE_ERROR_CATCH(
1610           ctx, attr->attr_->set_filter_pipeline(filter_list->pipeline_)))
1611     return TILEDB_ERR;
1612 
1613   return TILEDB_OK;
1614 }
1615 
tiledb_attribute_set_cell_val_num(tiledb_ctx_t * ctx,tiledb_attribute_t * attr,uint32_t cell_val_num)1616 int32_t tiledb_attribute_set_cell_val_num(
1617     tiledb_ctx_t* ctx, tiledb_attribute_t* attr, uint32_t cell_val_num) {
1618   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, attr) == TILEDB_ERR)
1619     return TILEDB_ERR;
1620   if (SAVE_ERROR_CATCH(ctx, attr->attr_->set_cell_val_num(cell_val_num)))
1621     return TILEDB_ERR;
1622   return TILEDB_OK;
1623 }
1624 
tiledb_attribute_get_name(tiledb_ctx_t * ctx,const tiledb_attribute_t * attr,const char ** name)1625 int32_t tiledb_attribute_get_name(
1626     tiledb_ctx_t* ctx, const tiledb_attribute_t* attr, const char** name) {
1627   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, attr) == TILEDB_ERR)
1628     return TILEDB_ERR;
1629 
1630   *name = attr->attr_->name().c_str();
1631 
1632   return TILEDB_OK;
1633 }
1634 
tiledb_attribute_get_type(tiledb_ctx_t * ctx,const tiledb_attribute_t * attr,tiledb_datatype_t * type)1635 int32_t tiledb_attribute_get_type(
1636     tiledb_ctx_t* ctx,
1637     const tiledb_attribute_t* attr,
1638     tiledb_datatype_t* type) {
1639   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, attr) == TILEDB_ERR)
1640     return TILEDB_ERR;
1641   *type = static_cast<tiledb_datatype_t>(attr->attr_->type());
1642   return TILEDB_OK;
1643 }
1644 
tiledb_attribute_get_nullable(tiledb_ctx_t * ctx,tiledb_attribute_t * attr,uint8_t * nullable)1645 int32_t tiledb_attribute_get_nullable(
1646     tiledb_ctx_t* ctx, tiledb_attribute_t* attr, uint8_t* nullable) {
1647   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, attr) == TILEDB_ERR)
1648     return TILEDB_ERR;
1649 
1650   if (SAVE_ERROR_CATCH(
1651           ctx, attr->attr_->get_nullable(reinterpret_cast<bool*>(nullable))))
1652     return TILEDB_ERR;
1653 
1654   return TILEDB_OK;
1655 }
1656 
tiledb_attribute_get_filter_list(tiledb_ctx_t * ctx,tiledb_attribute_t * attr,tiledb_filter_list_t ** filter_list)1657 int32_t tiledb_attribute_get_filter_list(
1658     tiledb_ctx_t* ctx,
1659     tiledb_attribute_t* attr,
1660     tiledb_filter_list_t** filter_list) {
1661   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, attr) == TILEDB_ERR)
1662     return TILEDB_ERR;
1663 
1664   // Create a filter list struct
1665   *filter_list = new (std::nothrow) tiledb_filter_list_t;
1666   if (*filter_list == nullptr) {
1667     auto st = Status::Error("Failed to allocate TileDB filter list object");
1668     LOG_STATUS(st);
1669     save_error(ctx, st);
1670     return TILEDB_OOM;
1671   }
1672 
1673   // Create a new FilterPipeline object
1674   (*filter_list)->pipeline_ =
1675       new (std::nothrow) tiledb::sm::FilterPipeline(attr->attr_->filters());
1676   if ((*filter_list)->pipeline_ == nullptr) {
1677     delete *filter_list;
1678     *filter_list = nullptr;
1679     auto st = Status::Error("Failed to allocate TileDB filter list object");
1680     LOG_STATUS(st);
1681     save_error(ctx, st);
1682     return TILEDB_OOM;
1683   }
1684 
1685   return TILEDB_OK;
1686 }
1687 
tiledb_attribute_get_cell_val_num(tiledb_ctx_t * ctx,const tiledb_attribute_t * attr,uint32_t * cell_val_num)1688 int32_t tiledb_attribute_get_cell_val_num(
1689     tiledb_ctx_t* ctx, const tiledb_attribute_t* attr, uint32_t* cell_val_num) {
1690   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, attr) == TILEDB_ERR)
1691     return TILEDB_ERR;
1692   *cell_val_num = attr->attr_->cell_val_num();
1693   return TILEDB_OK;
1694 }
1695 
tiledb_attribute_get_cell_size(tiledb_ctx_t * ctx,const tiledb_attribute_t * attr,uint64_t * cell_size)1696 int32_t tiledb_attribute_get_cell_size(
1697     tiledb_ctx_t* ctx, const tiledb_attribute_t* attr, uint64_t* cell_size) {
1698   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, attr) == TILEDB_ERR)
1699     return TILEDB_ERR;
1700   *cell_size = attr->attr_->cell_size();
1701   return TILEDB_OK;
1702 }
1703 
tiledb_attribute_dump(tiledb_ctx_t * ctx,const tiledb_attribute_t * attr,FILE * out)1704 int32_t tiledb_attribute_dump(
1705     tiledb_ctx_t* ctx, const tiledb_attribute_t* attr, FILE* out) {
1706   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, attr) == TILEDB_ERR)
1707     return TILEDB_ERR;
1708   attr->attr_->dump(out);
1709   return TILEDB_OK;
1710 }
1711 
tiledb_attribute_set_fill_value(tiledb_ctx_t * ctx,tiledb_attribute_t * attr,const void * value,uint64_t size)1712 int32_t tiledb_attribute_set_fill_value(
1713     tiledb_ctx_t* ctx,
1714     tiledb_attribute_t* attr,
1715     const void* value,
1716     uint64_t size) {
1717   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, attr) == TILEDB_ERR)
1718     return TILEDB_ERR;
1719 
1720   if (SAVE_ERROR_CATCH(ctx, attr->attr_->set_fill_value(value, size)))
1721     return TILEDB_ERR;
1722 
1723   return TILEDB_OK;
1724 }
1725 
tiledb_attribute_get_fill_value(tiledb_ctx_t * ctx,tiledb_attribute_t * attr,const void ** value,uint64_t * size)1726 int32_t tiledb_attribute_get_fill_value(
1727     tiledb_ctx_t* ctx,
1728     tiledb_attribute_t* attr,
1729     const void** value,
1730     uint64_t* size) {
1731   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, attr) == TILEDB_ERR)
1732     return TILEDB_ERR;
1733 
1734   if (SAVE_ERROR_CATCH(ctx, attr->attr_->get_fill_value(value, size)))
1735     return TILEDB_ERR;
1736 
1737   return TILEDB_OK;
1738 }
1739 
tiledb_attribute_set_fill_value_nullable(tiledb_ctx_t * ctx,tiledb_attribute_t * attr,const void * value,uint64_t size,uint8_t valid)1740 int32_t tiledb_attribute_set_fill_value_nullable(
1741     tiledb_ctx_t* ctx,
1742     tiledb_attribute_t* attr,
1743     const void* value,
1744     uint64_t size,
1745     uint8_t valid) {
1746   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, attr) == TILEDB_ERR)
1747     return TILEDB_ERR;
1748 
1749   if (SAVE_ERROR_CATCH(ctx, attr->attr_->set_fill_value(value, size, valid)))
1750     return TILEDB_ERR;
1751 
1752   return TILEDB_OK;
1753 }
1754 
tiledb_attribute_get_fill_value_nullable(tiledb_ctx_t * ctx,tiledb_attribute_t * attr,const void ** value,uint64_t * size,uint8_t * valid)1755 int32_t tiledb_attribute_get_fill_value_nullable(
1756     tiledb_ctx_t* ctx,
1757     tiledb_attribute_t* attr,
1758     const void** value,
1759     uint64_t* size,
1760     uint8_t* valid) {
1761   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, attr) == TILEDB_ERR)
1762     return TILEDB_ERR;
1763 
1764   if (SAVE_ERROR_CATCH(ctx, attr->attr_->get_fill_value(value, size, valid)))
1765     return TILEDB_ERR;
1766 
1767   return TILEDB_OK;
1768 }
1769 
1770 /* ********************************* */
1771 /*              DOMAIN               */
1772 /* ********************************* */
1773 
tiledb_domain_alloc(tiledb_ctx_t * ctx,tiledb_domain_t ** domain)1774 int32_t tiledb_domain_alloc(tiledb_ctx_t* ctx, tiledb_domain_t** domain) {
1775   if (sanity_check(ctx) == TILEDB_ERR)
1776     return TILEDB_ERR;
1777 
1778   // Create a domain struct
1779   *domain = new (std::nothrow) tiledb_domain_t;
1780   if (*domain == nullptr) {
1781     auto st = Status::Error("Failed to allocate TileDB domain object");
1782     LOG_STATUS(st);
1783     save_error(ctx, st);
1784     return TILEDB_OOM;
1785   }
1786 
1787   // Create a new Domain object
1788   (*domain)->domain_ = new (std::nothrow) tiledb::sm::Domain();
1789   if ((*domain)->domain_ == nullptr) {
1790     delete *domain;
1791     *domain = nullptr;
1792     auto st = Status::Error("Failed to allocate TileDB domain object");
1793     LOG_STATUS(st);
1794     save_error(ctx, st);
1795     return TILEDB_OOM;
1796   }
1797   return TILEDB_OK;
1798 }
1799 
tiledb_domain_free(tiledb_domain_t ** domain)1800 void tiledb_domain_free(tiledb_domain_t** domain) {
1801   if (domain != nullptr && *domain != nullptr) {
1802     delete (*domain)->domain_;
1803     delete *domain;
1804     *domain = nullptr;
1805   }
1806 }
1807 
tiledb_domain_get_type(tiledb_ctx_t * ctx,const tiledb_domain_t * domain,tiledb_datatype_t * type)1808 int32_t tiledb_domain_get_type(
1809     tiledb_ctx_t* ctx, const tiledb_domain_t* domain, tiledb_datatype_t* type) {
1810   if (sanity_check(ctx) == TILEDB_ERR ||
1811       sanity_check(ctx, domain) == TILEDB_ERR)
1812     return TILEDB_ERR;
1813 
1814   if (domain->domain_->dim_num() == 0) {
1815     auto st = Status::Error("Cannot get domain type; Domain has no dimensions");
1816     LOG_STATUS(st);
1817     save_error(ctx, st);
1818     return TILEDB_OOM;
1819   }
1820 
1821   if (!domain->domain_->all_dims_same_type()) {
1822     auto st = Status::Error(
1823         "Cannot get domain type; Not applicable to heterogeneous dimensions");
1824     LOG_STATUS(st);
1825     save_error(ctx, st);
1826     return TILEDB_ERR;
1827   }
1828 
1829   *type = static_cast<tiledb_datatype_t>(domain->domain_->dimension(0)->type());
1830   return TILEDB_OK;
1831 }
1832 
tiledb_domain_get_ndim(tiledb_ctx_t * ctx,const tiledb_domain_t * domain,uint32_t * ndim)1833 int32_t tiledb_domain_get_ndim(
1834     tiledb_ctx_t* ctx, const tiledb_domain_t* domain, uint32_t* ndim) {
1835   if (sanity_check(ctx) == TILEDB_ERR ||
1836       sanity_check(ctx, domain) == TILEDB_ERR)
1837     return TILEDB_ERR;
1838   *ndim = domain->domain_->dim_num();
1839   return TILEDB_OK;
1840 }
1841 
tiledb_domain_add_dimension(tiledb_ctx_t * ctx,tiledb_domain_t * domain,tiledb_dimension_t * dim)1842 int32_t tiledb_domain_add_dimension(
1843     tiledb_ctx_t* ctx, tiledb_domain_t* domain, tiledb_dimension_t* dim) {
1844   if (sanity_check(ctx) == TILEDB_ERR ||
1845       sanity_check(ctx, domain) == TILEDB_ERR)
1846     return TILEDB_ERR;
1847 
1848   if (SAVE_ERROR_CATCH(ctx, domain->domain_->add_dimension(dim->dim_)))
1849     return TILEDB_ERR;
1850 
1851   return TILEDB_OK;
1852 }
1853 
tiledb_domain_dump(tiledb_ctx_t * ctx,const tiledb_domain_t * domain,FILE * out)1854 int32_t tiledb_domain_dump(
1855     tiledb_ctx_t* ctx, const tiledb_domain_t* domain, FILE* out) {
1856   if (sanity_check(ctx) == TILEDB_ERR ||
1857       sanity_check(ctx, domain) == TILEDB_ERR)
1858     return TILEDB_ERR;
1859   domain->domain_->dump(out);
1860   return TILEDB_OK;
1861 }
1862 
1863 /* ********************************* */
1864 /*             DIMENSION             */
1865 /* ********************************* */
1866 
tiledb_dimension_alloc(tiledb_ctx_t * ctx,const char * name,tiledb_datatype_t type,const void * dim_domain,const void * tile_extent,tiledb_dimension_t ** dim)1867 int32_t tiledb_dimension_alloc(
1868     tiledb_ctx_t* ctx,
1869     const char* name,
1870     tiledb_datatype_t type,
1871     const void* dim_domain,
1872     const void* tile_extent,
1873     tiledb_dimension_t** dim) {
1874   if (sanity_check(ctx) == TILEDB_ERR)
1875     return TILEDB_ERR;
1876 
1877   // Create a dimension struct
1878   *dim = new (std::nothrow) tiledb_dimension_t;
1879   if (*dim == nullptr) {
1880     auto st = Status::Error("Failed to allocate TileDB dimension object");
1881     LOG_STATUS(st);
1882     save_error(ctx, st);
1883     return TILEDB_OOM;
1884   }
1885 
1886   // Create a new Dimension object
1887   (*dim)->dim_ = new (std::nothrow)
1888       tiledb::sm::Dimension(name, static_cast<tiledb::sm::Datatype>(type));
1889   if ((*dim)->dim_ == nullptr) {
1890     delete *dim;
1891     *dim = nullptr;
1892     auto st = Status::Error("Failed to allocate TileDB dimension object");
1893     LOG_STATUS(st);
1894     save_error(ctx, st);
1895     return TILEDB_OOM;
1896   }
1897 
1898   // Set domain
1899   if (SAVE_ERROR_CATCH(ctx, (*dim)->dim_->set_domain(dim_domain))) {
1900     delete (*dim)->dim_;
1901     delete *dim;
1902     *dim = nullptr;
1903     return TILEDB_ERR;
1904   }
1905 
1906   // Set tile extent
1907   if (SAVE_ERROR_CATCH(ctx, (*dim)->dim_->set_tile_extent(tile_extent))) {
1908     delete (*dim)->dim_;
1909     delete *dim;
1910     *dim = nullptr;
1911     return TILEDB_ERR;
1912   }
1913 
1914   // Success
1915   return TILEDB_OK;
1916 }
1917 
tiledb_dimension_free(tiledb_dimension_t ** dim)1918 void tiledb_dimension_free(tiledb_dimension_t** dim) {
1919   if (dim != nullptr && *dim != nullptr) {
1920     delete (*dim)->dim_;
1921     delete *dim;
1922     *dim = nullptr;
1923   }
1924 }
1925 
tiledb_dimension_set_filter_list(tiledb_ctx_t * ctx,tiledb_dimension_t * dim,tiledb_filter_list_t * filter_list)1926 int32_t tiledb_dimension_set_filter_list(
1927     tiledb_ctx_t* ctx,
1928     tiledb_dimension_t* dim,
1929     tiledb_filter_list_t* filter_list) {
1930   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, dim) == TILEDB_ERR ||
1931       sanity_check(ctx, filter_list) == TILEDB_ERR)
1932     return TILEDB_ERR;
1933 
1934   if (SAVE_ERROR_CATCH(
1935           ctx, dim->dim_->set_filter_pipeline(filter_list->pipeline_)))
1936     return TILEDB_ERR;
1937 
1938   return TILEDB_OK;
1939 }
1940 
tiledb_dimension_set_cell_val_num(tiledb_ctx_t * ctx,tiledb_dimension_t * dim,uint32_t cell_val_num)1941 int32_t tiledb_dimension_set_cell_val_num(
1942     tiledb_ctx_t* ctx, tiledb_dimension_t* dim, uint32_t cell_val_num) {
1943   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, dim) == TILEDB_ERR)
1944     return TILEDB_ERR;
1945   if (SAVE_ERROR_CATCH(ctx, dim->dim_->set_cell_val_num(cell_val_num)))
1946     return TILEDB_ERR;
1947   return TILEDB_OK;
1948 }
1949 
tiledb_dimension_get_filter_list(tiledb_ctx_t * ctx,tiledb_dimension_t * dim,tiledb_filter_list_t ** filter_list)1950 int32_t tiledb_dimension_get_filter_list(
1951     tiledb_ctx_t* ctx,
1952     tiledb_dimension_t* dim,
1953     tiledb_filter_list_t** filter_list) {
1954   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, dim) == TILEDB_ERR)
1955     return TILEDB_ERR;
1956 
1957   // Create a filter list struct
1958   *filter_list = new (std::nothrow) tiledb_filter_list_t;
1959   if (*filter_list == nullptr) {
1960     auto st = Status::Error("Failed to allocate TileDB filter list object");
1961     LOG_STATUS(st);
1962     save_error(ctx, st);
1963     return TILEDB_OOM;
1964   }
1965 
1966   // Create a new FilterPipeline object
1967   (*filter_list)->pipeline_ =
1968       new (std::nothrow) tiledb::sm::FilterPipeline(dim->dim_->filters());
1969   if ((*filter_list)->pipeline_ == nullptr) {
1970     delete *filter_list;
1971     *filter_list = nullptr;
1972     auto st = Status::Error("Failed to allocate TileDB filter list object");
1973     LOG_STATUS(st);
1974     save_error(ctx, st);
1975     return TILEDB_OOM;
1976   }
1977 
1978   return TILEDB_OK;
1979 }
1980 
tiledb_dimension_get_cell_val_num(tiledb_ctx_t * ctx,const tiledb_dimension_t * dim,uint32_t * cell_val_num)1981 int32_t tiledb_dimension_get_cell_val_num(
1982     tiledb_ctx_t* ctx, const tiledb_dimension_t* dim, uint32_t* cell_val_num) {
1983   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, dim) == TILEDB_ERR)
1984     return TILEDB_ERR;
1985   *cell_val_num = dim->dim_->cell_val_num();
1986   return TILEDB_OK;
1987 }
1988 
tiledb_dimension_get_name(tiledb_ctx_t * ctx,const tiledb_dimension_t * dim,const char ** name)1989 int32_t tiledb_dimension_get_name(
1990     tiledb_ctx_t* ctx, const tiledb_dimension_t* dim, const char** name) {
1991   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, dim) == TILEDB_ERR)
1992     return TILEDB_ERR;
1993   *name = dim->dim_->name().c_str();
1994   return TILEDB_OK;
1995 }
1996 
tiledb_dimension_get_type(tiledb_ctx_t * ctx,const tiledb_dimension_t * dim,tiledb_datatype_t * type)1997 int32_t tiledb_dimension_get_type(
1998     tiledb_ctx_t* ctx, const tiledb_dimension_t* dim, tiledb_datatype_t* type) {
1999   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, dim) == TILEDB_ERR)
2000     return TILEDB_ERR;
2001   *type = static_cast<tiledb_datatype_t>(dim->dim_->type());
2002   return TILEDB_OK;
2003 }
2004 
tiledb_dimension_get_domain(tiledb_ctx_t * ctx,const tiledb_dimension_t * dim,const void ** domain)2005 int32_t tiledb_dimension_get_domain(
2006     tiledb_ctx_t* ctx, const tiledb_dimension_t* dim, const void** domain) {
2007   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, dim) == TILEDB_ERR)
2008     return TILEDB_ERR;
2009   *domain = dim->dim_->domain().data();
2010   return TILEDB_OK;
2011 }
2012 
tiledb_dimension_get_tile_extent(tiledb_ctx_t * ctx,const tiledb_dimension_t * dim,const void ** tile_extent)2013 int32_t tiledb_dimension_get_tile_extent(
2014     tiledb_ctx_t* ctx,
2015     const tiledb_dimension_t* dim,
2016     const void** tile_extent) {
2017   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, dim) == TILEDB_ERR)
2018     return TILEDB_ERR;
2019   *tile_extent = dim->dim_->tile_extent().data();
2020   return TILEDB_OK;
2021 }
2022 
tiledb_dimension_dump(tiledb_ctx_t * ctx,const tiledb_dimension_t * dim,FILE * out)2023 int32_t tiledb_dimension_dump(
2024     tiledb_ctx_t* ctx, const tiledb_dimension_t* dim, FILE* out) {
2025   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, dim) == TILEDB_ERR)
2026     return TILEDB_ERR;
2027   dim->dim_->dump(out);
2028   return TILEDB_OK;
2029 }
2030 
tiledb_domain_get_dimension_from_index(tiledb_ctx_t * ctx,const tiledb_domain_t * domain,uint32_t index,tiledb_dimension_t ** dim)2031 int32_t tiledb_domain_get_dimension_from_index(
2032     tiledb_ctx_t* ctx,
2033     const tiledb_domain_t* domain,
2034     uint32_t index,
2035     tiledb_dimension_t** dim) {
2036   if (sanity_check(ctx) == TILEDB_ERR ||
2037       sanity_check(ctx, domain) == TILEDB_ERR) {
2038     return TILEDB_ERR;
2039   }
2040   uint32_t ndim = domain->domain_->dim_num();
2041   if (ndim == 0 && index == 0) {
2042     *dim = nullptr;
2043     return TILEDB_OK;
2044   }
2045   if (index > (ndim - 1)) {
2046     std::ostringstream errmsg;
2047     errmsg << "Dimension " << index << " out of bounds, domain has rank "
2048            << ndim;
2049     auto st = Status::DomainError(errmsg.str());
2050     LOG_STATUS(st);
2051     save_error(ctx, st);
2052     return TILEDB_ERR;
2053   }
2054   *dim = new (std::nothrow) tiledb_dimension_t;
2055   if (*dim == nullptr) {
2056     auto st = Status::Error("Failed to allocate TileDB dimension object");
2057     LOG_STATUS(st);
2058     save_error(ctx, st);
2059     return TILEDB_OOM;
2060   }
2061   (*dim)->dim_ = new (std::nothrow)
2062       tiledb::sm::Dimension(domain->domain_->dimension(index));
2063   if ((*dim)->dim_ == nullptr) {
2064     delete *dim;
2065     *dim = nullptr;
2066     auto st = Status::Error("Failed to allocate TileDB dimension object");
2067     LOG_STATUS(st);
2068     save_error(ctx, st);
2069     return TILEDB_OOM;
2070   }
2071   return TILEDB_OK;
2072 }
2073 
tiledb_domain_get_dimension_from_name(tiledb_ctx_t * ctx,const tiledb_domain_t * domain,const char * name,tiledb_dimension_t ** dim)2074 int32_t tiledb_domain_get_dimension_from_name(
2075     tiledb_ctx_t* ctx,
2076     const tiledb_domain_t* domain,
2077     const char* name,
2078     tiledb_dimension_t** dim) {
2079   if (sanity_check(ctx) == TILEDB_ERR ||
2080       sanity_check(ctx, domain) == TILEDB_ERR) {
2081     return TILEDB_ERR;
2082   }
2083   uint32_t ndim = domain->domain_->dim_num();
2084   if (ndim == 0) {
2085     *dim = nullptr;
2086     return TILEDB_OK;
2087   }
2088   std::string name_string(name);
2089   auto found_dim = domain->domain_->dimension(name_string);
2090 
2091   if (found_dim == nullptr) {
2092     auto st = Status::DomainError(
2093         std::string("Dimension '") + name + "' does not exist");
2094     LOG_STATUS(st);
2095     save_error(ctx, st);
2096     return TILEDB_ERR;
2097   }
2098 
2099   *dim = new (std::nothrow) tiledb_dimension_t;
2100   if (*dim == nullptr) {
2101     auto st = Status::Error("Failed to allocate TileDB dimension object");
2102     save_error(ctx, st);
2103     return TILEDB_OOM;
2104   }
2105   (*dim)->dim_ = new (std::nothrow) tiledb::sm::Dimension(found_dim);
2106   if ((*dim)->dim_ == nullptr) {
2107     delete *dim;
2108     *dim = nullptr;
2109     auto st = Status::Error("Failed to allocate TileDB dimension object");
2110     LOG_STATUS(st);
2111     save_error(ctx, st);
2112     return TILEDB_OOM;
2113   }
2114   return TILEDB_OK;
2115 }
2116 
tiledb_domain_has_dimension(tiledb_ctx_t * ctx,const tiledb_domain_t * domain,const char * name,int32_t * has_dim)2117 int32_t tiledb_domain_has_dimension(
2118     tiledb_ctx_t* ctx,
2119     const tiledb_domain_t* domain,
2120     const char* name,
2121     int32_t* has_dim) {
2122   if (sanity_check(ctx) == TILEDB_ERR ||
2123       sanity_check(ctx, domain) == TILEDB_ERR) {
2124     return TILEDB_ERR;
2125   }
2126 
2127   bool b;
2128   if (SAVE_ERROR_CATCH(ctx, domain->domain_->has_dimension(name, &b)))
2129     return TILEDB_ERR;
2130 
2131   *has_dim = b ? 1 : 0;
2132 
2133   return TILEDB_OK;
2134 }
2135 
2136 /* ****************************** */
2137 /*           ARRAY SCHEMA         */
2138 /* ****************************** */
2139 
tiledb_array_schema_alloc(tiledb_ctx_t * ctx,tiledb_array_type_t array_type,tiledb_array_schema_t ** array_schema)2140 int32_t tiledb_array_schema_alloc(
2141     tiledb_ctx_t* ctx,
2142     tiledb_array_type_t array_type,
2143     tiledb_array_schema_t** array_schema) {
2144   if (sanity_check(ctx) == TILEDB_ERR)
2145     return TILEDB_ERR;
2146 
2147   // Create array schema struct
2148   *array_schema = new (std::nothrow) tiledb_array_schema_t;
2149   if (*array_schema == nullptr) {
2150     auto st = Status::Error("Failed to allocate TileDB array schema object");
2151     LOG_STATUS(st);
2152     save_error(ctx, st);
2153     return TILEDB_OOM;
2154   }
2155 
2156   // Create a new ArraySchema object
2157   (*array_schema)->array_schema_ = new (std::nothrow)
2158       tiledb::sm::ArraySchema(static_cast<tiledb::sm::ArrayType>(array_type));
2159   if ((*array_schema)->array_schema_ == nullptr) {
2160     delete *array_schema;
2161     *array_schema = nullptr;
2162     auto st = Status::Error("Failed to allocate TileDB array schema object");
2163     LOG_STATUS(st);
2164     save_error(ctx, st);
2165     return TILEDB_OOM;
2166   }
2167 
2168   // Success
2169   return TILEDB_OK;
2170 }
2171 
tiledb_array_schema_free(tiledb_array_schema_t ** array_schema)2172 void tiledb_array_schema_free(tiledb_array_schema_t** array_schema) {
2173   if (array_schema != nullptr && *array_schema != nullptr) {
2174     delete (*array_schema)->array_schema_;
2175     delete *array_schema;
2176     *array_schema = nullptr;
2177   }
2178 }
2179 
tiledb_array_schema_add_attribute(tiledb_ctx_t * ctx,tiledb_array_schema_t * array_schema,tiledb_attribute_t * attr)2180 int32_t tiledb_array_schema_add_attribute(
2181     tiledb_ctx_t* ctx,
2182     tiledb_array_schema_t* array_schema,
2183     tiledb_attribute_t* attr) {
2184   if (sanity_check(ctx) == TILEDB_ERR ||
2185       sanity_check(ctx, array_schema) == TILEDB_ERR ||
2186       sanity_check(ctx, attr) == TILEDB_ERR)
2187     return TILEDB_ERR;
2188   if (SAVE_ERROR_CATCH(
2189           ctx, array_schema->array_schema_->add_attribute(attr->attr_)))
2190     return TILEDB_ERR;
2191   return TILEDB_OK;
2192 }
2193 
tiledb_array_schema_set_allows_dups(tiledb_ctx_t * ctx,tiledb_array_schema_t * array_schema,int allows_dups)2194 int32_t tiledb_array_schema_set_allows_dups(
2195     tiledb_ctx_t* ctx, tiledb_array_schema_t* array_schema, int allows_dups) {
2196   if (sanity_check(ctx) == TILEDB_ERR ||
2197       sanity_check(ctx, array_schema) == TILEDB_ERR)
2198     return TILEDB_ERR;
2199   if (SAVE_ERROR_CATCH(
2200           ctx, array_schema->array_schema_->set_allows_dups(allows_dups)))
2201     return TILEDB_ERR;
2202   return TILEDB_OK;
2203 }
2204 
tiledb_array_schema_get_allows_dups(tiledb_ctx_t * ctx,tiledb_array_schema_t * array_schema,int * allows_dups)2205 int32_t tiledb_array_schema_get_allows_dups(
2206     tiledb_ctx_t* ctx, tiledb_array_schema_t* array_schema, int* allows_dups) {
2207   if (sanity_check(ctx) == TILEDB_ERR ||
2208       sanity_check(ctx, array_schema) == TILEDB_ERR)
2209     return TILEDB_ERR;
2210   *allows_dups = (int)array_schema->array_schema_->allows_dups();
2211   return TILEDB_OK;
2212 }
2213 
tiledb_array_schema_set_domain(tiledb_ctx_t * ctx,tiledb_array_schema_t * array_schema,tiledb_domain_t * domain)2214 int32_t tiledb_array_schema_set_domain(
2215     tiledb_ctx_t* ctx,
2216     tiledb_array_schema_t* array_schema,
2217     tiledb_domain_t* domain) {
2218   if (sanity_check(ctx) == TILEDB_ERR ||
2219       sanity_check(ctx, array_schema) == TILEDB_ERR)
2220     return TILEDB_ERR;
2221   if (SAVE_ERROR_CATCH(
2222           ctx, array_schema->array_schema_->set_domain(domain->domain_)))
2223     return TILEDB_ERR;
2224   return TILEDB_OK;
2225 }
2226 
tiledb_array_schema_set_capacity(tiledb_ctx_t * ctx,tiledb_array_schema_t * array_schema,uint64_t capacity)2227 int32_t tiledb_array_schema_set_capacity(
2228     tiledb_ctx_t* ctx, tiledb_array_schema_t* array_schema, uint64_t capacity) {
2229   if (sanity_check(ctx) == TILEDB_ERR ||
2230       sanity_check(ctx, array_schema) == TILEDB_ERR)
2231     return TILEDB_ERR;
2232   array_schema->array_schema_->set_capacity(capacity);
2233   return TILEDB_OK;
2234 }
2235 
tiledb_array_schema_set_cell_order(tiledb_ctx_t * ctx,tiledb_array_schema_t * array_schema,tiledb_layout_t cell_order)2236 int32_t tiledb_array_schema_set_cell_order(
2237     tiledb_ctx_t* ctx,
2238     tiledb_array_schema_t* array_schema,
2239     tiledb_layout_t cell_order) {
2240   if (sanity_check(ctx) == TILEDB_ERR ||
2241       sanity_check(ctx, array_schema) == TILEDB_ERR)
2242     return TILEDB_ERR;
2243   if (SAVE_ERROR_CATCH(
2244           ctx,
2245           array_schema->array_schema_->set_cell_order(
2246               static_cast<tiledb::sm::Layout>(cell_order))))
2247     return TILEDB_ERR;
2248   return TILEDB_OK;
2249 }
2250 
tiledb_array_schema_set_tile_order(tiledb_ctx_t * ctx,tiledb_array_schema_t * array_schema,tiledb_layout_t tile_order)2251 int32_t tiledb_array_schema_set_tile_order(
2252     tiledb_ctx_t* ctx,
2253     tiledb_array_schema_t* array_schema,
2254     tiledb_layout_t tile_order) {
2255   if (sanity_check(ctx) == TILEDB_ERR ||
2256       sanity_check(ctx, array_schema) == TILEDB_ERR)
2257     return TILEDB_ERR;
2258   if (SAVE_ERROR_CATCH(
2259           ctx,
2260           array_schema->array_schema_->set_tile_order(
2261               static_cast<tiledb::sm::Layout>(tile_order))))
2262     return TILEDB_ERR;
2263   return TILEDB_OK;
2264 }
2265 
tiledb_array_schema_set_coords_filter_list(tiledb_ctx_t * ctx,tiledb_array_schema_t * array_schema,tiledb_filter_list_t * filter_list)2266 int32_t tiledb_array_schema_set_coords_filter_list(
2267     tiledb_ctx_t* ctx,
2268     tiledb_array_schema_t* array_schema,
2269     tiledb_filter_list_t* filter_list) {
2270   if (sanity_check(ctx) == TILEDB_ERR ||
2271       sanity_check(ctx, array_schema) == TILEDB_ERR ||
2272       sanity_check(ctx, filter_list) == TILEDB_ERR)
2273     return TILEDB_ERR;
2274 
2275   if (SAVE_ERROR_CATCH(
2276           ctx,
2277           array_schema->array_schema_->set_coords_filter_pipeline(
2278               filter_list->pipeline_)))
2279     return TILEDB_ERR;
2280 
2281   return TILEDB_OK;
2282 }
2283 
tiledb_array_schema_set_offsets_filter_list(tiledb_ctx_t * ctx,tiledb_array_schema_t * array_schema,tiledb_filter_list_t * filter_list)2284 int32_t tiledb_array_schema_set_offsets_filter_list(
2285     tiledb_ctx_t* ctx,
2286     tiledb_array_schema_t* array_schema,
2287     tiledb_filter_list_t* filter_list) {
2288   if (sanity_check(ctx) == TILEDB_ERR ||
2289       sanity_check(ctx, array_schema) == TILEDB_ERR ||
2290       sanity_check(ctx, filter_list) == TILEDB_ERR)
2291     return TILEDB_ERR;
2292 
2293   if (SAVE_ERROR_CATCH(
2294           ctx,
2295           array_schema->array_schema_->set_cell_var_offsets_filter_pipeline(
2296               filter_list->pipeline_)))
2297     return TILEDB_ERR;
2298 
2299   return TILEDB_OK;
2300 }
2301 
tiledb_array_schema_check(tiledb_ctx_t * ctx,tiledb_array_schema_t * array_schema)2302 int32_t tiledb_array_schema_check(
2303     tiledb_ctx_t* ctx, tiledb_array_schema_t* array_schema) {
2304   if (sanity_check(ctx) == TILEDB_ERR ||
2305       sanity_check(ctx, array_schema) == TILEDB_ERR)
2306     return TILEDB_ERR;
2307 
2308   if (SAVE_ERROR_CATCH(ctx, array_schema->array_schema_->check()))
2309     return TILEDB_ERR;
2310 
2311   return TILEDB_OK;
2312 }
2313 
tiledb_array_schema_load(tiledb_ctx_t * ctx,const char * array_uri,tiledb_array_schema_t ** array_schema)2314 int32_t tiledb_array_schema_load(
2315     tiledb_ctx_t* ctx,
2316     const char* array_uri,
2317     tiledb_array_schema_t** array_schema) {
2318   if (sanity_check(ctx) == TILEDB_ERR)
2319     return TILEDB_ERR;
2320 
2321   // Create array schema
2322   *array_schema = new (std::nothrow) tiledb_array_schema_t;
2323   if (*array_schema == nullptr) {
2324     auto st = Status::Error("Failed to allocate TileDB array schema object");
2325     LOG_STATUS(st);
2326     save_error(ctx, st);
2327     return TILEDB_OOM;
2328   }
2329 
2330   // Check array name
2331   tiledb::sm::URI uri(array_uri);
2332   if (uri.is_invalid()) {
2333     auto st = Status::Error("Failed to load array schema; Invalid array URI");
2334     LOG_STATUS(st);
2335     save_error(ctx, st);
2336     return TILEDB_ERR;
2337   }
2338 
2339   if (uri.is_tiledb()) {
2340     // Check REST client
2341     auto rest_client = ctx->ctx_->storage_manager()->rest_client();
2342     if (rest_client == nullptr) {
2343       auto st = Status::Error(
2344           "Failed to load array schema; remote array with no REST client.");
2345       LOG_STATUS(st);
2346       save_error(ctx, st);
2347       return TILEDB_ERR;
2348     }
2349 
2350     if (SAVE_ERROR_CATCH(
2351             ctx,
2352             rest_client->get_array_schema_from_rest(
2353                 uri, &(*array_schema)->array_schema_))) {
2354       delete *array_schema;
2355       return TILEDB_ERR;
2356     }
2357   } else {
2358     // Create key
2359     tiledb::sm::EncryptionKey key;
2360     if (SAVE_ERROR_CATCH(
2361             ctx,
2362             key.set_key(
2363                 static_cast<tiledb::sm::EncryptionType>(TILEDB_NO_ENCRYPTION),
2364                 nullptr,
2365                 0)))
2366       return TILEDB_ERR;
2367 
2368     // Load array schema
2369     auto storage_manager = ctx->ctx_->storage_manager();
2370 
2371     if (SAVE_ERROR_CATCH(
2372             ctx,
2373             storage_manager->load_array_schema(
2374                 uri, key, &((*array_schema)->array_schema_)))) {
2375       delete *array_schema;
2376       return TILEDB_ERR;
2377     }
2378   }
2379   return TILEDB_OK;
2380 }
2381 
tiledb_array_schema_load_with_key(tiledb_ctx_t * ctx,const char * array_uri,tiledb_encryption_type_t encryption_type,const void * encryption_key,uint32_t key_length,tiledb_array_schema_t ** array_schema)2382 int32_t tiledb_array_schema_load_with_key(
2383     tiledb_ctx_t* ctx,
2384     const char* array_uri,
2385     tiledb_encryption_type_t encryption_type,
2386     const void* encryption_key,
2387     uint32_t key_length,
2388     tiledb_array_schema_t** array_schema) {
2389   if (sanity_check(ctx) == TILEDB_ERR)
2390     return TILEDB_ERR;
2391 
2392   // Create array schema
2393   *array_schema = new (std::nothrow) tiledb_array_schema_t;
2394   if (*array_schema == nullptr) {
2395     auto st = Status::Error("Failed to allocate TileDB array schema object");
2396     LOG_STATUS(st);
2397     save_error(ctx, st);
2398     return TILEDB_OOM;
2399   }
2400 
2401   // Check array name
2402   tiledb::sm::URI uri(array_uri);
2403   if (uri.is_invalid()) {
2404     delete *array_schema;
2405     *array_schema = nullptr;
2406     auto st = Status::Error("Failed to load array schema; Invalid array URI");
2407     LOG_STATUS(st);
2408     save_error(ctx, st);
2409     return TILEDB_ERR;
2410   }
2411 
2412   if (uri.is_tiledb()) {
2413     // Check REST client
2414     auto rest_client = ctx->ctx_->storage_manager()->rest_client();
2415     if (rest_client == nullptr) {
2416       delete *array_schema;
2417       *array_schema = nullptr;
2418       auto st = Status::Error(
2419           "Failed to load array schema; remote array with no REST client.");
2420       LOG_STATUS(st);
2421       save_error(ctx, st);
2422       return TILEDB_ERR;
2423     }
2424 
2425     if (SAVE_ERROR_CATCH(
2426             ctx,
2427             rest_client->get_array_schema_from_rest(
2428                 uri, &(*array_schema)->array_schema_))) {
2429       delete *array_schema;
2430       *array_schema = nullptr;
2431       return TILEDB_ERR;
2432     }
2433   } else {
2434     // Create key
2435     tiledb::sm::EncryptionKey key;
2436     if (SAVE_ERROR_CATCH(
2437             ctx,
2438             key.set_key(
2439                 static_cast<tiledb::sm::EncryptionType>(encryption_type),
2440                 encryption_key,
2441                 key_length))) {
2442       delete *array_schema;
2443       *array_schema = nullptr;
2444       return TILEDB_ERR;
2445     }
2446 
2447     // Load array schema
2448     auto storage_manager = ctx->ctx_->storage_manager();
2449 
2450     if (SAVE_ERROR_CATCH(
2451             ctx,
2452             storage_manager->load_array_schema(
2453                 uri, key, &((*array_schema)->array_schema_)))) {
2454       delete *array_schema;
2455       *array_schema = nullptr;
2456       return TILEDB_ERR;
2457     }
2458   }
2459   return TILEDB_OK;
2460 }
2461 
tiledb_array_schema_get_array_type(tiledb_ctx_t * ctx,const tiledb_array_schema_t * array_schema,tiledb_array_type_t * array_type)2462 int32_t tiledb_array_schema_get_array_type(
2463     tiledb_ctx_t* ctx,
2464     const tiledb_array_schema_t* array_schema,
2465     tiledb_array_type_t* array_type) {
2466   if (sanity_check(ctx) == TILEDB_ERR ||
2467       sanity_check(ctx, array_schema) == TILEDB_ERR)
2468     return TILEDB_ERR;
2469   *array_type = static_cast<tiledb_array_type_t>(
2470       array_schema->array_schema_->array_type());
2471   return TILEDB_OK;
2472 }
2473 
tiledb_array_schema_get_capacity(tiledb_ctx_t * ctx,const tiledb_array_schema_t * array_schema,uint64_t * capacity)2474 int32_t tiledb_array_schema_get_capacity(
2475     tiledb_ctx_t* ctx,
2476     const tiledb_array_schema_t* array_schema,
2477     uint64_t* capacity) {
2478   if (sanity_check(ctx) == TILEDB_ERR ||
2479       sanity_check(ctx, array_schema) == TILEDB_ERR)
2480     return TILEDB_ERR;
2481   *capacity = array_schema->array_schema_->capacity();
2482   return TILEDB_OK;
2483 }
2484 
tiledb_array_schema_get_cell_order(tiledb_ctx_t * ctx,const tiledb_array_schema_t * array_schema,tiledb_layout_t * cell_order)2485 int32_t tiledb_array_schema_get_cell_order(
2486     tiledb_ctx_t* ctx,
2487     const tiledb_array_schema_t* array_schema,
2488     tiledb_layout_t* cell_order) {
2489   if (sanity_check(ctx) == TILEDB_ERR ||
2490       sanity_check(ctx, array_schema) == TILEDB_ERR)
2491     return TILEDB_ERR;
2492   *cell_order =
2493       static_cast<tiledb_layout_t>(array_schema->array_schema_->cell_order());
2494   return TILEDB_OK;
2495 }
2496 
tiledb_array_schema_get_coords_filter_list(tiledb_ctx_t * ctx,tiledb_array_schema_t * array_schema,tiledb_filter_list_t ** filter_list)2497 int32_t tiledb_array_schema_get_coords_filter_list(
2498     tiledb_ctx_t* ctx,
2499     tiledb_array_schema_t* array_schema,
2500     tiledb_filter_list_t** filter_list) {
2501   if (sanity_check(ctx) == TILEDB_ERR ||
2502       sanity_check(ctx, array_schema) == TILEDB_ERR)
2503     return TILEDB_ERR;
2504 
2505   // Create a filter list struct
2506   *filter_list = new (std::nothrow) tiledb_filter_list_t;
2507   if (*filter_list == nullptr) {
2508     auto st = Status::Error("Failed to allocate TileDB filter list object");
2509     LOG_STATUS(st);
2510     save_error(ctx, st);
2511     return TILEDB_OOM;
2512   }
2513 
2514   // Create a new FilterPipeline object
2515   (*filter_list)->pipeline_ = new (std::nothrow)
2516       tiledb::sm::FilterPipeline(array_schema->array_schema_->coords_filters());
2517   if ((*filter_list)->pipeline_ == nullptr) {
2518     delete *filter_list;
2519     *filter_list = nullptr;
2520     auto st = Status::Error("Failed to allocate TileDB filter list object");
2521     LOG_STATUS(st);
2522     save_error(ctx, st);
2523     return TILEDB_OOM;
2524   }
2525 
2526   return TILEDB_OK;
2527 }
2528 
tiledb_array_schema_get_offsets_filter_list(tiledb_ctx_t * ctx,tiledb_array_schema_t * array_schema,tiledb_filter_list_t ** filter_list)2529 int32_t tiledb_array_schema_get_offsets_filter_list(
2530     tiledb_ctx_t* ctx,
2531     tiledb_array_schema_t* array_schema,
2532     tiledb_filter_list_t** filter_list) {
2533   if (sanity_check(ctx) == TILEDB_ERR ||
2534       sanity_check(ctx, array_schema) == TILEDB_ERR)
2535     return TILEDB_ERR;
2536 
2537   // Create a filter list struct
2538   *filter_list = new (std::nothrow) tiledb_filter_list_t;
2539   if (*filter_list == nullptr) {
2540     auto st = Status::Error("Failed to allocate TileDB filter list object");
2541     LOG_STATUS(st);
2542     save_error(ctx, st);
2543     return TILEDB_OOM;
2544   }
2545 
2546   // Create a new FilterPipeline object
2547   (*filter_list)->pipeline_ = new (std::nothrow) tiledb::sm::FilterPipeline(
2548       array_schema->array_schema_->cell_var_offsets_filters());
2549   if ((*filter_list)->pipeline_ == nullptr) {
2550     delete *filter_list;
2551     *filter_list = nullptr;
2552     auto st = Status::Error("Failed to allocate TileDB filter list object");
2553     LOG_STATUS(st);
2554     save_error(ctx, st);
2555     return TILEDB_OOM;
2556   }
2557 
2558   return TILEDB_OK;
2559 }
2560 
tiledb_array_schema_get_domain(tiledb_ctx_t * ctx,const tiledb_array_schema_t * array_schema,tiledb_domain_t ** domain)2561 int32_t tiledb_array_schema_get_domain(
2562     tiledb_ctx_t* ctx,
2563     const tiledb_array_schema_t* array_schema,
2564     tiledb_domain_t** domain) {
2565   if (sanity_check(ctx) == TILEDB_ERR ||
2566       sanity_check(ctx, array_schema) == TILEDB_ERR)
2567     return TILEDB_ERR;
2568 
2569   // Create a domain struct
2570   *domain = new (std::nothrow) tiledb_domain_t;
2571   if (*domain == nullptr) {
2572     auto st = Status::Error("Failed to allocate TileDB domain object");
2573     LOG_STATUS(st);
2574     save_error(ctx, st);
2575     return TILEDB_OOM;
2576   }
2577 
2578   // Create a new Domain object
2579   (*domain)->domain_ = new (std::nothrow)
2580       tiledb::sm::Domain(array_schema->array_schema_->domain());
2581   if ((*domain)->domain_ == nullptr) {
2582     delete *domain;
2583     *domain = nullptr;
2584     auto st =
2585         Status::Error("Failed to allocate TileDB domain object in object");
2586     LOG_STATUS(st);
2587     save_error(ctx, st);
2588     return TILEDB_OOM;
2589   }
2590   return TILEDB_OK;
2591 }
2592 
tiledb_array_schema_get_tile_order(tiledb_ctx_t * ctx,const tiledb_array_schema_t * array_schema,tiledb_layout_t * tile_order)2593 int32_t tiledb_array_schema_get_tile_order(
2594     tiledb_ctx_t* ctx,
2595     const tiledb_array_schema_t* array_schema,
2596     tiledb_layout_t* tile_order) {
2597   if (sanity_check(ctx) == TILEDB_ERR ||
2598       sanity_check(ctx, array_schema) == TILEDB_ERR)
2599     return TILEDB_ERR;
2600   *tile_order =
2601       static_cast<tiledb_layout_t>(array_schema->array_schema_->tile_order());
2602   return TILEDB_OK;
2603 }
2604 
tiledb_array_schema_get_attribute_num(tiledb_ctx_t * ctx,const tiledb_array_schema_t * array_schema,uint32_t * attribute_num)2605 int32_t tiledb_array_schema_get_attribute_num(
2606     tiledb_ctx_t* ctx,
2607     const tiledb_array_schema_t* array_schema,
2608     uint32_t* attribute_num) {
2609   if (sanity_check(ctx) == TILEDB_ERR ||
2610       sanity_check(ctx, array_schema) == TILEDB_ERR)
2611     return TILEDB_ERR;
2612   *attribute_num = array_schema->array_schema_->attribute_num();
2613   return TILEDB_OK;
2614 }
2615 
tiledb_array_schema_dump(tiledb_ctx_t * ctx,const tiledb_array_schema_t * array_schema,FILE * out)2616 int32_t tiledb_array_schema_dump(
2617     tiledb_ctx_t* ctx, const tiledb_array_schema_t* array_schema, FILE* out) {
2618   if (sanity_check(ctx) == TILEDB_ERR ||
2619       sanity_check(ctx, array_schema) == TILEDB_ERR)
2620     return TILEDB_ERR;
2621   array_schema->array_schema_->dump(out);
2622   return TILEDB_OK;
2623 }
2624 
tiledb_array_schema_get_attribute_from_index(tiledb_ctx_t * ctx,const tiledb_array_schema_t * array_schema,uint32_t index,tiledb_attribute_t ** attr)2625 int32_t tiledb_array_schema_get_attribute_from_index(
2626     tiledb_ctx_t* ctx,
2627     const tiledb_array_schema_t* array_schema,
2628     uint32_t index,
2629     tiledb_attribute_t** attr) {
2630   if (sanity_check(ctx) == TILEDB_ERR ||
2631       sanity_check(ctx, array_schema) == TILEDB_ERR) {
2632     return TILEDB_ERR;
2633   }
2634   uint32_t attribute_num = array_schema->array_schema_->attribute_num();
2635   if (attribute_num == 0) {
2636     *attr = nullptr;
2637     return TILEDB_OK;
2638   }
2639   if (index >= attribute_num) {
2640     std::ostringstream errmsg;
2641     errmsg << "Attribute index: " << index << " out of bounds given "
2642            << attribute_num << " attributes in array "
2643            << array_schema->array_schema_->array_uri().to_string();
2644     auto st = Status::ArraySchemaError(errmsg.str());
2645     LOG_STATUS(st);
2646     save_error(ctx, st);
2647     return TILEDB_ERR;
2648   }
2649 
2650   auto found_attr = array_schema->array_schema_->attribute(index);
2651   assert(found_attr != nullptr);
2652 
2653   *attr = new (std::nothrow) tiledb_attribute_t;
2654   if (*attr == nullptr) {
2655     auto st = Status::Error("Failed to allocate TileDB attribute");
2656     LOG_STATUS(st);
2657     save_error(ctx, st);
2658     return TILEDB_OOM;
2659   }
2660 
2661   // Create an attribute object
2662   (*attr)->attr_ = new (std::nothrow) tiledb::sm::Attribute(found_attr);
2663 
2664   // Check for allocation error
2665   if ((*attr)->attr_ == nullptr) {
2666     delete *attr;
2667     *attr = nullptr;
2668     auto st = Status::Error("Failed to allocate TileDB attribute");
2669     LOG_STATUS(st);
2670     save_error(ctx, st);
2671     return TILEDB_OOM;
2672   }
2673   return TILEDB_OK;
2674 }
2675 
tiledb_array_schema_get_attribute_from_name(tiledb_ctx_t * ctx,const tiledb_array_schema_t * array_schema,const char * name,tiledb_attribute_t ** attr)2676 int32_t tiledb_array_schema_get_attribute_from_name(
2677     tiledb_ctx_t* ctx,
2678     const tiledb_array_schema_t* array_schema,
2679     const char* name,
2680     tiledb_attribute_t** attr) {
2681   if (sanity_check(ctx) == TILEDB_ERR ||
2682       sanity_check(ctx, array_schema) == TILEDB_ERR) {
2683     return TILEDB_ERR;
2684   }
2685   uint32_t attribute_num = array_schema->array_schema_->attribute_num();
2686   if (attribute_num == 0) {
2687     *attr = nullptr;
2688     return TILEDB_OK;
2689   }
2690   std::string name_string(name);
2691   auto found_attr = array_schema->array_schema_->attribute(name_string);
2692   if (found_attr == nullptr) {
2693     auto st = Status::ArraySchemaError(
2694         std::string("Attribute name: ") +
2695         (name_string.empty() ? "<anonymous>" : name) +
2696         " does not exist for array " +
2697         array_schema->array_schema_->array_uri().to_string());
2698     LOG_STATUS(st);
2699     save_error(ctx, st);
2700     return TILEDB_ERR;
2701   }
2702   *attr = new (std::nothrow) tiledb_attribute_t;
2703   if (*attr == nullptr) {
2704     auto st = Status::Error("Failed to allocate TileDB attribute");
2705     LOG_STATUS(st);
2706     save_error(ctx, st);
2707     return TILEDB_OOM;
2708   }
2709   // Create an attribute object
2710   (*attr)->attr_ = new (std::nothrow) tiledb::sm::Attribute(found_attr);
2711   // Check for allocation error
2712   if ((*attr)->attr_ == nullptr) {
2713     delete *attr;
2714     *attr = nullptr;
2715     auto st = Status::Error("Failed to allocate TileDB attribute");
2716     LOG_STATUS(st);
2717     save_error(ctx, st);
2718     return TILEDB_OOM;
2719   }
2720   return TILEDB_OK;
2721 }
2722 
tiledb_array_schema_has_attribute(tiledb_ctx_t * ctx,const tiledb_array_schema_t * array_schema,const char * name,int32_t * has_attr)2723 int32_t tiledb_array_schema_has_attribute(
2724     tiledb_ctx_t* ctx,
2725     const tiledb_array_schema_t* array_schema,
2726     const char* name,
2727     int32_t* has_attr) {
2728   if (sanity_check(ctx) == TILEDB_ERR ||
2729       sanity_check(ctx, array_schema) == TILEDB_ERR) {
2730     return TILEDB_ERR;
2731   }
2732 
2733   bool b;
2734   if (SAVE_ERROR_CATCH(
2735           ctx, array_schema->array_schema_->has_attribute(name, &b)))
2736     return TILEDB_ERR;
2737 
2738   *has_attr = b ? 1 : 0;
2739 
2740   return TILEDB_OK;
2741 }
2742 
2743 /* ********************************* */
2744 /*            SCHEMA EVOLUTION       */
2745 /* ********************************* */
2746 
tiledb_array_schema_evolution_alloc(tiledb_ctx_t * ctx,tiledb_array_schema_evolution_t ** array_schema_evolution)2747 int32_t tiledb_array_schema_evolution_alloc(
2748     tiledb_ctx_t* ctx,
2749     tiledb_array_schema_evolution_t** array_schema_evolution) {
2750   // Sanity check
2751   if (sanity_check(ctx) == TILEDB_ERR)
2752     return TILEDB_ERR;
2753 
2754   // Create schema evolution struct
2755   *array_schema_evolution = new (std::nothrow) tiledb_array_schema_evolution_t;
2756   if (*array_schema_evolution == nullptr) {
2757     auto st = Status::Error(
2758         "Failed to allocate TileDB array schema evolution object");
2759     LOG_STATUS(st);
2760     save_error(ctx, st);
2761     return TILEDB_OOM;
2762   }
2763 
2764   // Create a new SchemaEvolution object
2765   (*array_schema_evolution)->array_schema_evolution_ =
2766       new (std::nothrow) tiledb::sm::ArraySchemaEvolution();
2767   if ((*array_schema_evolution)->array_schema_evolution_ == nullptr) {
2768     delete *array_schema_evolution;
2769     *array_schema_evolution = nullptr;
2770     auto st = Status::Error(
2771         "Failed to allocate TileDB array schema evolution object");
2772     LOG_STATUS(st);
2773     save_error(ctx, st);
2774     return TILEDB_OOM;
2775   }
2776 
2777   // Success
2778   return TILEDB_OK;
2779 }
2780 
tiledb_array_schema_evolution_free(tiledb_array_schema_evolution_t ** array_schema_evolution)2781 void tiledb_array_schema_evolution_free(
2782     tiledb_array_schema_evolution_t** array_schema_evolution) {
2783   if (array_schema_evolution != nullptr && *array_schema_evolution != nullptr) {
2784     delete (*array_schema_evolution)->array_schema_evolution_;
2785     delete *array_schema_evolution;
2786     *array_schema_evolution = nullptr;
2787   }
2788 }
2789 
tiledb_array_schema_evolution_add_attribute(tiledb_ctx_t * ctx,tiledb_array_schema_evolution_t * array_schema_evolution,tiledb_attribute_t * attr)2790 int32_t tiledb_array_schema_evolution_add_attribute(
2791     tiledb_ctx_t* ctx,
2792     tiledb_array_schema_evolution_t* array_schema_evolution,
2793     tiledb_attribute_t* attr) {
2794   if (sanity_check(ctx) == TILEDB_ERR ||
2795       sanity_check(ctx, array_schema_evolution) == TILEDB_ERR ||
2796       sanity_check(ctx, attr) == TILEDB_ERR)
2797     return TILEDB_ERR;
2798 
2799   if (SAVE_ERROR_CATCH(
2800           ctx,
2801           array_schema_evolution->array_schema_evolution_->add_attribute(
2802               attr->attr_)))
2803     return TILEDB_ERR;
2804   return TILEDB_OK;
2805 
2806   // Success
2807   return TILEDB_OK;
2808 }
2809 
tiledb_array_schema_evolution_drop_attribute(tiledb_ctx_t * ctx,tiledb_array_schema_evolution_t * array_schema_evolution,const char * attribute_name)2810 int32_t tiledb_array_schema_evolution_drop_attribute(
2811     tiledb_ctx_t* ctx,
2812     tiledb_array_schema_evolution_t* array_schema_evolution,
2813     const char* attribute_name) {
2814   if (sanity_check(ctx) == TILEDB_ERR ||
2815       sanity_check(ctx, array_schema_evolution) == TILEDB_ERR)
2816     return TILEDB_ERR;
2817 
2818   if (SAVE_ERROR_CATCH(
2819           ctx,
2820           array_schema_evolution->array_schema_evolution_->drop_attribute(
2821               attribute_name)))
2822     return TILEDB_ERR;
2823   return TILEDB_OK;
2824   // Success
2825   return TILEDB_OK;
2826 }
2827 
2828 /* ****************************** */
2829 /*              QUERY             */
2830 /* ****************************** */
2831 
tiledb_query_alloc(tiledb_ctx_t * ctx,tiledb_array_t * array,tiledb_query_type_t query_type,tiledb_query_t ** query)2832 int32_t tiledb_query_alloc(
2833     tiledb_ctx_t* ctx,
2834     tiledb_array_t* array,
2835     tiledb_query_type_t query_type,
2836     tiledb_query_t** query) {
2837   // Sanity check
2838   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
2839     return TILEDB_ERR;
2840 
2841   // Error if array is not open
2842   if (!array->array_->is_open()) {
2843     auto st = Status::Error("Cannot create query; Input array is not open");
2844     *query = nullptr;
2845     LOG_STATUS(st);
2846     save_error(ctx, st);
2847     return TILEDB_ERR;
2848   }
2849 
2850   // Error is the query type and array query type do not match
2851   tiledb::sm::QueryType array_query_type;
2852   if (SAVE_ERROR_CATCH(ctx, array->array_->get_query_type(&array_query_type)))
2853     return TILEDB_ERR;
2854   if (query_type != static_cast<tiledb_query_type_t>(array_query_type)) {
2855     std::stringstream errmsg;
2856     errmsg << "Cannot create query; "
2857            << "Array query type does not match declared query type: "
2858            << "(" << query_type_str(array_query_type) << " != "
2859            << tiledb::sm::query_type_str(
2860                   static_cast<tiledb::sm::QueryType>(query_type))
2861            << ")";
2862     *query = nullptr;
2863     auto st = Status::Error(errmsg.str());
2864     LOG_STATUS(st);
2865     save_error(ctx, st);
2866     return TILEDB_ERR;
2867   }
2868 
2869   // Create query struct
2870   *query = new (std::nothrow) tiledb_query_t;
2871   if (*query == nullptr) {
2872     auto st = Status::Error(
2873         "Failed to allocate TileDB query object; Memory allocation failed");
2874     LOG_STATUS(st);
2875     save_error(ctx, st);
2876     return TILEDB_OOM;
2877   }
2878 
2879   // Create query
2880   (*query)->query_ = new (std::nothrow)
2881       tiledb::sm::Query(ctx->ctx_->storage_manager(), array->array_);
2882   if ((*query)->query_ == nullptr) {
2883     auto st = Status::Error(
2884         "Failed to allocate TileDB query object; Memory allocation failed");
2885     delete *query;
2886     *query = nullptr;
2887     LOG_STATUS(st);
2888     save_error(ctx, st);
2889     return TILEDB_OOM;
2890   }
2891 
2892   // Success
2893   return TILEDB_OK;
2894 }
2895 
tiledb_query_get_stats(tiledb_ctx_t * ctx,tiledb_query_t * query,char ** stats_json)2896 int32_t tiledb_query_get_stats(
2897     tiledb_ctx_t* ctx, tiledb_query_t* query, char** stats_json) {
2898   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
2899     return TILEDB_ERR;
2900 
2901   if (stats_json == nullptr)
2902     return TILEDB_ERR;
2903 
2904   const std::string str = query->query_->stats()->dump(2, 0);
2905 
2906   *stats_json = static_cast<char*>(std::malloc(str.size() + 1));
2907   if (*stats_json == nullptr)
2908     return TILEDB_ERR;
2909 
2910   std::memcpy(*stats_json, str.data(), str.size());
2911   (*stats_json)[str.size()] = '\0';
2912 
2913   return TILEDB_OK;
2914 }
2915 
tiledb_query_set_config(tiledb_ctx_t * ctx,tiledb_query_t * query,tiledb_config_t * config)2916 int32_t tiledb_query_set_config(
2917     tiledb_ctx_t* ctx, tiledb_query_t* query, tiledb_config_t* config) {
2918   // Sanity check
2919   if (sanity_check(ctx) == TILEDB_ERR ||
2920       sanity_check(ctx, query) == TILEDB_ERR ||
2921       sanity_check(ctx, config) == TILEDB_ERR)
2922     return TILEDB_ERR;
2923 
2924   if (SAVE_ERROR_CATCH(ctx, query->query_->set_config(*(config->config_))))
2925     return TILEDB_ERR;
2926 
2927   return TILEDB_OK;
2928 }
2929 
tiledb_query_get_config(tiledb_ctx_t * ctx,tiledb_query_t * query,tiledb_config_t ** config)2930 int32_t tiledb_query_get_config(
2931     tiledb_ctx_t* ctx, tiledb_query_t* query, tiledb_config_t** config) {
2932   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
2933     return TILEDB_ERR;
2934 
2935   // Create a new config struct
2936   *config = new (std::nothrow) tiledb_config_t;
2937   if (*config == nullptr)
2938     return TILEDB_OOM;
2939 
2940   // Create storage manager
2941   (*config)->config_ = new (std::nothrow) tiledb::sm::Config();
2942   if ((*config)->config_ == nullptr) {
2943     delete (*config);
2944     *config = nullptr;
2945     return TILEDB_OOM;
2946   }
2947 
2948   *((*config)->config_) = *query->query_->config();
2949 
2950   // Success
2951   return TILEDB_OK;
2952 }
2953 
tiledb_query_set_subarray(tiledb_ctx_t * ctx,tiledb_query_t * query,const void * subarray)2954 int32_t tiledb_query_set_subarray(
2955     tiledb_ctx_t* ctx, tiledb_query_t* query, const void* subarray) {
2956   // Sanity check
2957   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
2958     return TILEDB_ERR;
2959 
2960   // Set subarray
2961   if (SAVE_ERROR_CATCH(ctx, query->query_->set_subarray(subarray)))
2962     return TILEDB_ERR;
2963 
2964   return TILEDB_OK;
2965 }
2966 
tiledb_query_set_buffer(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,void * buffer,uint64_t * buffer_size)2967 int32_t tiledb_query_set_buffer(
2968     tiledb_ctx_t* ctx,
2969     tiledb_query_t* query,
2970     const char* name,
2971     void* buffer,
2972     uint64_t* buffer_size) {
2973   // Sanity check
2974   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
2975     return TILEDB_ERR;
2976 
2977   // Set attribute buffer
2978   if (SAVE_ERROR_CATCH(
2979           ctx, query->query_->set_data_buffer(name, buffer, buffer_size)))
2980     return TILEDB_ERR;
2981 
2982   return TILEDB_OK;
2983 }
2984 
tiledb_query_set_buffer_var(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,uint64_t * buffer_off,uint64_t * buffer_off_size,void * buffer_val,uint64_t * buffer_val_size)2985 int32_t tiledb_query_set_buffer_var(
2986     tiledb_ctx_t* ctx,
2987     tiledb_query_t* query,
2988     const char* name,
2989     uint64_t* buffer_off,
2990     uint64_t* buffer_off_size,
2991     void* buffer_val,
2992     uint64_t* buffer_val_size) {
2993   // Sanity check
2994   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
2995     return TILEDB_ERR;
2996 
2997   // Set attribute buffers
2998   if (SAVE_ERROR_CATCH(
2999           ctx,
3000           query->query_->set_data_buffer(name, buffer_val, buffer_val_size)))
3001     return TILEDB_ERR;
3002   if (SAVE_ERROR_CATCH(
3003           ctx,
3004           query->query_->set_offsets_buffer(name, buffer_off, buffer_off_size)))
3005     return TILEDB_ERR;
3006 
3007   return TILEDB_OK;
3008 }
3009 
tiledb_query_set_buffer_nullable(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,void * buffer,uint64_t * buffer_size,uint8_t * buffer_validity_bytemap,uint64_t * buffer_validity_bytemap_size)3010 int32_t tiledb_query_set_buffer_nullable(
3011     tiledb_ctx_t* ctx,
3012     tiledb_query_t* query,
3013     const char* name,
3014     void* buffer,
3015     uint64_t* buffer_size,
3016     uint8_t* buffer_validity_bytemap,
3017     uint64_t* buffer_validity_bytemap_size) {
3018   // Sanity check
3019   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3020     return TILEDB_ERR;
3021 
3022   // Set attribute buffer
3023   if (SAVE_ERROR_CATCH(
3024           ctx, query->query_->set_data_buffer(name, buffer, buffer_size)))
3025     return TILEDB_ERR;
3026   if (SAVE_ERROR_CATCH(
3027           ctx,
3028           query->query_->set_validity_buffer(
3029               name, buffer_validity_bytemap, buffer_validity_bytemap_size)))
3030     return TILEDB_ERR;
3031 
3032   return TILEDB_OK;
3033 }
3034 
tiledb_query_set_buffer_var_nullable(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,uint64_t * buffer_off,uint64_t * buffer_off_size,void * buffer_val,uint64_t * buffer_val_size,uint8_t * buffer_validity_bytemap,uint64_t * buffer_validity_bytemap_size)3035 int32_t tiledb_query_set_buffer_var_nullable(
3036     tiledb_ctx_t* ctx,
3037     tiledb_query_t* query,
3038     const char* name,
3039     uint64_t* buffer_off,
3040     uint64_t* buffer_off_size,
3041     void* buffer_val,
3042     uint64_t* buffer_val_size,
3043     uint8_t* buffer_validity_bytemap,
3044     uint64_t* buffer_validity_bytemap_size) {
3045   // Sanity check
3046   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3047     return TILEDB_ERR;
3048 
3049   // Set attribute buffers
3050   if (SAVE_ERROR_CATCH(
3051           ctx,
3052           query->query_->set_data_buffer(name, buffer_val, buffer_val_size)))
3053     return TILEDB_ERR;
3054   if (SAVE_ERROR_CATCH(
3055           ctx,
3056           query->query_->set_offsets_buffer(name, buffer_off, buffer_off_size)))
3057     return TILEDB_ERR;
3058   if (SAVE_ERROR_CATCH(
3059           ctx,
3060           query->query_->set_validity_buffer(
3061               name, buffer_validity_bytemap, buffer_validity_bytemap_size)))
3062     return TILEDB_ERR;
3063 
3064   return TILEDB_OK;
3065 }
3066 
tiledb_query_set_data_buffer(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,void * buffer,uint64_t * buffer_size)3067 int32_t tiledb_query_set_data_buffer(
3068     tiledb_ctx_t* ctx,
3069     tiledb_query_t* query,
3070     const char* name,
3071     void* buffer,
3072     uint64_t* buffer_size) {  // Sanity check
3073   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3074     return TILEDB_ERR;
3075 
3076   // Set attribute buffer
3077   if (SAVE_ERROR_CATCH(
3078           ctx, query->query_->set_data_buffer(name, buffer, buffer_size)))
3079     return TILEDB_ERR;
3080 
3081   return TILEDB_OK;
3082 }
3083 
tiledb_query_set_offsets_buffer(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,uint64_t * buffer_offsets,uint64_t * buffer_offsets_size)3084 int32_t tiledb_query_set_offsets_buffer(
3085     tiledb_ctx_t* ctx,
3086     tiledb_query_t* query,
3087     const char* name,
3088     uint64_t* buffer_offsets,
3089     uint64_t* buffer_offsets_size) {  // Sanity check
3090   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3091     return TILEDB_ERR;
3092 
3093   // Set attribute buffer
3094   if (SAVE_ERROR_CATCH(
3095           ctx,
3096           query->query_->set_offsets_buffer(
3097               name, buffer_offsets, buffer_offsets_size)))
3098     return TILEDB_ERR;
3099 
3100   return TILEDB_OK;
3101 }
3102 
tiledb_query_set_validity_buffer(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,uint8_t * buffer_validity,uint64_t * buffer_validity_size)3103 int32_t tiledb_query_set_validity_buffer(
3104     tiledb_ctx_t* ctx,
3105     tiledb_query_t* query,
3106     const char* name,
3107     uint8_t* buffer_validity,
3108     uint64_t* buffer_validity_size) {  // Sanity check
3109   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3110     return TILEDB_ERR;
3111 
3112   // Set attribute buffer
3113   if (SAVE_ERROR_CATCH(
3114           ctx,
3115           query->query_->set_validity_buffer(
3116               name, buffer_validity, buffer_validity_size)))
3117     return TILEDB_ERR;
3118 
3119   return TILEDB_OK;
3120 }
3121 
tiledb_query_get_buffer(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,void ** buffer,uint64_t ** buffer_size)3122 int32_t tiledb_query_get_buffer(
3123     tiledb_ctx_t* ctx,
3124     tiledb_query_t* query,
3125     const char* name,
3126     void** buffer,
3127     uint64_t** buffer_size) {
3128   // Sanity check
3129   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3130     return TILEDB_ERR;
3131 
3132   // Set attribute buffer
3133   if (SAVE_ERROR_CATCH(
3134           ctx, query->query_->get_data_buffer(name, buffer, buffer_size)))
3135     return TILEDB_ERR;
3136 
3137   return TILEDB_OK;
3138 }
3139 
tiledb_query_get_buffer_var(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,uint64_t ** buffer_off,uint64_t ** buffer_off_size,void ** buffer_val,uint64_t ** buffer_val_size)3140 int32_t tiledb_query_get_buffer_var(
3141     tiledb_ctx_t* ctx,
3142     tiledb_query_t* query,
3143     const char* name,
3144     uint64_t** buffer_off,
3145     uint64_t** buffer_off_size,
3146     void** buffer_val,
3147     uint64_t** buffer_val_size) {
3148   // Sanity check
3149   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3150     return TILEDB_ERR;
3151 
3152   // Get attribute buffers
3153   if (SAVE_ERROR_CATCH(
3154           ctx,
3155           query->query_->get_data_buffer(name, buffer_val, buffer_val_size)))
3156     return TILEDB_ERR;
3157   if (SAVE_ERROR_CATCH(
3158           ctx,
3159           query->query_->get_offsets_buffer(name, buffer_off, buffer_off_size)))
3160     return TILEDB_ERR;
3161 
3162   return TILEDB_OK;
3163 }
3164 
tiledb_query_get_buffer_nullable(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,void ** buffer,uint64_t ** buffer_size,uint8_t ** buffer_validity_bytemap,uint64_t ** buffer_validity_bytemap_size)3165 int32_t tiledb_query_get_buffer_nullable(
3166     tiledb_ctx_t* ctx,
3167     tiledb_query_t* query,
3168     const char* name,
3169     void** buffer,
3170     uint64_t** buffer_size,
3171     uint8_t** buffer_validity_bytemap,
3172     uint64_t** buffer_validity_bytemap_size) {
3173   // Sanity check
3174   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3175     return TILEDB_ERR;
3176 
3177   // Set attribute buffer
3178   if (SAVE_ERROR_CATCH(
3179           ctx, query->query_->get_data_buffer(name, buffer, buffer_size)))
3180     return TILEDB_ERR;
3181   if (SAVE_ERROR_CATCH(
3182           ctx,
3183           query->query_->get_validity_buffer(
3184               name, buffer_validity_bytemap, buffer_validity_bytemap_size)))
3185     return TILEDB_ERR;
3186 
3187   return TILEDB_OK;
3188 }
3189 
tiledb_query_get_buffer_var_nullable(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,uint64_t ** buffer_off,uint64_t ** buffer_off_size,void ** buffer_val,uint64_t ** buffer_val_size,uint8_t ** buffer_validity_bytemap,uint64_t ** buffer_validity_bytemap_size)3190 int32_t tiledb_query_get_buffer_var_nullable(
3191     tiledb_ctx_t* ctx,
3192     tiledb_query_t* query,
3193     const char* name,
3194     uint64_t** buffer_off,
3195     uint64_t** buffer_off_size,
3196     void** buffer_val,
3197     uint64_t** buffer_val_size,
3198     uint8_t** buffer_validity_bytemap,
3199     uint64_t** buffer_validity_bytemap_size) {
3200   // Sanity check
3201   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3202     return TILEDB_ERR;
3203 
3204   // Get attribute buffers
3205   if (SAVE_ERROR_CATCH(
3206           ctx,
3207           query->query_->get_data_buffer(name, buffer_val, buffer_val_size)))
3208     return TILEDB_ERR;
3209   if (SAVE_ERROR_CATCH(
3210           ctx,
3211           query->query_->get_offsets_buffer(name, buffer_off, buffer_off_size)))
3212     return TILEDB_ERR;
3213   if (SAVE_ERROR_CATCH(
3214           ctx,
3215           query->query_->get_validity_buffer(
3216               name, buffer_validity_bytemap, buffer_validity_bytemap_size)))
3217     return TILEDB_ERR;
3218 
3219   return TILEDB_OK;
3220 }
3221 
tiledb_query_get_data_buffer(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,void ** buffer,uint64_t ** buffer_size)3222 int32_t tiledb_query_get_data_buffer(
3223     tiledb_ctx_t* ctx,
3224     tiledb_query_t* query,
3225     const char* name,
3226     void** buffer,
3227     uint64_t** buffer_size) {
3228   // Sanity check
3229   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3230     return TILEDB_ERR;
3231 
3232   // Get attribute buffer
3233   if (SAVE_ERROR_CATCH(
3234           ctx, query->query_->get_data_buffer(name, buffer, buffer_size)))
3235     return TILEDB_ERR;
3236 
3237   return TILEDB_OK;
3238 }
3239 
tiledb_query_get_offsets_buffer(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,uint64_t ** buffer,uint64_t ** buffer_size)3240 int32_t tiledb_query_get_offsets_buffer(
3241     tiledb_ctx_t* ctx,
3242     tiledb_query_t* query,
3243     const char* name,
3244     uint64_t** buffer,
3245     uint64_t** buffer_size) {
3246   // Sanity check
3247   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3248     return TILEDB_ERR;
3249 
3250   // Get attribute buffer
3251   if (SAVE_ERROR_CATCH(
3252           ctx, query->query_->get_offsets_buffer(name, buffer, buffer_size)))
3253     return TILEDB_ERR;
3254 
3255   return TILEDB_OK;
3256 }
3257 
tiledb_query_get_validity_buffer(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * name,uint8_t ** buffer,uint64_t ** buffer_size)3258 int32_t tiledb_query_get_validity_buffer(
3259     tiledb_ctx_t* ctx,
3260     tiledb_query_t* query,
3261     const char* name,
3262     uint8_t** buffer,
3263     uint64_t** buffer_size) {
3264   // Sanity check
3265   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3266     return TILEDB_ERR;
3267 
3268   // Get attribute buffer
3269   if (SAVE_ERROR_CATCH(
3270           ctx, query->query_->get_validity_buffer(name, buffer, buffer_size)))
3271     return TILEDB_ERR;
3272 
3273   return TILEDB_OK;
3274 }
3275 
tiledb_query_set_layout(tiledb_ctx_t * ctx,tiledb_query_t * query,tiledb_layout_t layout)3276 int32_t tiledb_query_set_layout(
3277     tiledb_ctx_t* ctx, tiledb_query_t* query, tiledb_layout_t layout) {
3278   // Sanity check
3279   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3280     return TILEDB_ERR;
3281 
3282   // Set layout
3283   if (SAVE_ERROR_CATCH(
3284           ctx,
3285           query->query_->set_layout(static_cast<tiledb::sm::Layout>(layout))))
3286     return TILEDB_ERR;
3287 
3288   return TILEDB_OK;
3289 }
3290 
tiledb_query_set_condition(tiledb_ctx_t * const ctx,tiledb_query_t * const query,const tiledb_query_condition_t * const cond)3291 int32_t tiledb_query_set_condition(
3292     tiledb_ctx_t* const ctx,
3293     tiledb_query_t* const query,
3294     const tiledb_query_condition_t* const cond) {
3295   // Sanity check
3296   if (sanity_check(ctx) == TILEDB_ERR ||
3297       sanity_check(ctx, query) == TILEDB_ERR ||
3298       sanity_check(ctx, cond) == TILEDB_ERR)
3299     return TILEDB_ERR;
3300 
3301   // Set layout
3302   if (SAVE_ERROR_CATCH(
3303           ctx, query->query_->set_condition(*cond->query_condition_)))
3304     return TILEDB_ERR;
3305 
3306   return TILEDB_OK;
3307 }
3308 
tiledb_query_finalize(tiledb_ctx_t * ctx,tiledb_query_t * query)3309 int32_t tiledb_query_finalize(tiledb_ctx_t* ctx, tiledb_query_t* query) {
3310   // Trivial case
3311   if (query == nullptr)
3312     return TILEDB_OK;
3313 
3314   // Sanity check
3315   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3316     return TILEDB_ERR;
3317 
3318   // Flush query
3319   if (SAVE_ERROR_CATCH(ctx, query->query_->finalize()))
3320     return TILEDB_ERR;
3321 
3322   return TILEDB_OK;
3323 }
3324 
tiledb_query_free(tiledb_query_t ** query)3325 void tiledb_query_free(tiledb_query_t** query) {
3326   if (query != nullptr && *query != nullptr) {
3327     delete (*query)->query_;
3328     delete *query;
3329     *query = nullptr;
3330   }
3331 }
3332 
tiledb_query_submit(tiledb_ctx_t * ctx,tiledb_query_t * query)3333 int32_t tiledb_query_submit(tiledb_ctx_t* ctx, tiledb_query_t* query) {
3334   // Sanity checks
3335   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3336     return TILEDB_ERR;
3337 
3338   if (SAVE_ERROR_CATCH(ctx, query->query_->submit()))
3339     return TILEDB_ERR;
3340 
3341   return TILEDB_OK;
3342 }
3343 
tiledb_query_submit_async(tiledb_ctx_t * ctx,tiledb_query_t * query,void (* callback)(void *),void * callback_data)3344 int32_t tiledb_query_submit_async(
3345     tiledb_ctx_t* ctx,
3346     tiledb_query_t* query,
3347     void (*callback)(void*),
3348     void* callback_data) {
3349   // Sanity checks
3350   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3351     return TILEDB_ERR;
3352 
3353   if (SAVE_ERROR_CATCH(
3354           ctx, query->query_->submit_async(callback, callback_data)))
3355     return TILEDB_ERR;
3356 
3357   return TILEDB_OK;
3358 }
3359 
tiledb_query_has_results(tiledb_ctx_t * ctx,tiledb_query_t * query,int32_t * has_results)3360 int32_t tiledb_query_has_results(
3361     tiledb_ctx_t* ctx, tiledb_query_t* query, int32_t* has_results) {
3362   // Sanity check
3363   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3364     return TILEDB_ERR;
3365 
3366   *has_results = query->query_->has_results();
3367 
3368   return TILEDB_OK;
3369 }
3370 
tiledb_query_get_status(tiledb_ctx_t * ctx,tiledb_query_t * query,tiledb_query_status_t * status)3371 int32_t tiledb_query_get_status(
3372     tiledb_ctx_t* ctx, tiledb_query_t* query, tiledb_query_status_t* status) {
3373   // Sanity check
3374   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3375     return TILEDB_ERR;
3376 
3377   *status = (tiledb_query_status_t)query->query_->status();
3378 
3379   return TILEDB_OK;
3380 }
3381 
tiledb_query_get_type(tiledb_ctx_t * ctx,tiledb_query_t * query,tiledb_query_type_t * query_type)3382 int32_t tiledb_query_get_type(
3383     tiledb_ctx_t* ctx, tiledb_query_t* query, tiledb_query_type_t* query_type) {
3384   // Sanity check
3385   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3386     return TILEDB_ERR;
3387 
3388   *query_type = static_cast<tiledb_query_type_t>(query->query_->type());
3389 
3390   return TILEDB_OK;
3391 }
3392 
tiledb_query_get_layout(tiledb_ctx_t * ctx,tiledb_query_t * query,tiledb_layout_t * query_layout)3393 int32_t tiledb_query_get_layout(
3394     tiledb_ctx_t* ctx, tiledb_query_t* query, tiledb_layout_t* query_layout) {
3395   // Sanity check
3396   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3397     return TILEDB_ERR;
3398 
3399   *query_layout = static_cast<tiledb_layout_t>(query->query_->layout());
3400 
3401   return TILEDB_OK;
3402 }
3403 
tiledb_query_get_array(tiledb_ctx_t * ctx,tiledb_query_t * query,tiledb_array_t ** array)3404 int32_t tiledb_query_get_array(
3405     tiledb_ctx_t* ctx, tiledb_query_t* query, tiledb_array_t** array) {
3406   // Sanity check
3407   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3408     return TILEDB_ERR;
3409 
3410   // Create array datatype
3411   *array = new (std::nothrow) tiledb_array_t;
3412   if (*array == nullptr) {
3413     auto st = Status::Error(
3414         "Failed to create TileDB array object; Memory allocation error");
3415     LOG_STATUS(st);
3416     save_error(ctx, st);
3417     return TILEDB_OOM;
3418   }
3419 
3420   // Allocate an array object, copied from the query's array.
3421   (*array)->array_ =
3422       new (std::nothrow) tiledb::sm::Array(*query->query_->array());
3423   if ((*array)->array_ == nullptr) {
3424     delete *array;
3425     *array = nullptr;
3426     auto st = Status::Error(
3427         "Failed to create TileDB array object; Memory allocation "
3428         "error");
3429     LOG_STATUS(st);
3430     save_error(ctx, st);
3431     return TILEDB_OOM;
3432   }
3433 
3434   return TILEDB_OK;
3435 }
3436 
tiledb_query_add_range(tiledb_ctx_t * ctx,tiledb_query_t * query,uint32_t dim_idx,const void * start,const void * end,const void * stride)3437 int32_t tiledb_query_add_range(
3438     tiledb_ctx_t* ctx,
3439     tiledb_query_t* query,
3440     uint32_t dim_idx,
3441     const void* start,
3442     const void* end,
3443     const void* stride) {
3444   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3445     return TILEDB_ERR;
3446 
3447   if (SAVE_ERROR_CATCH(
3448           ctx, query->query_->add_range(dim_idx, start, end, stride)))
3449     return TILEDB_ERR;
3450 
3451   return TILEDB_OK;
3452 }
3453 
tiledb_query_add_range_by_name(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * dim_name,const void * start,const void * end,const void * stride)3454 int32_t tiledb_query_add_range_by_name(
3455     tiledb_ctx_t* ctx,
3456     tiledb_query_t* query,
3457     const char* dim_name,
3458     const void* start,
3459     const void* end,
3460     const void* stride) {
3461   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3462     return TILEDB_ERR;
3463 
3464   if (SAVE_ERROR_CATCH(
3465           ctx, query->query_->add_range_by_name(dim_name, start, end, stride)))
3466     return TILEDB_ERR;
3467 
3468   return TILEDB_OK;
3469 }
3470 
tiledb_query_add_range_var(tiledb_ctx_t * ctx,tiledb_query_t * query,uint32_t dim_idx,const void * start,uint64_t start_size,const void * end,uint64_t end_size)3471 int32_t tiledb_query_add_range_var(
3472     tiledb_ctx_t* ctx,
3473     tiledb_query_t* query,
3474     uint32_t dim_idx,
3475     const void* start,
3476     uint64_t start_size,
3477     const void* end,
3478     uint64_t end_size) {
3479   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3480     return TILEDB_ERR;
3481 
3482   if (SAVE_ERROR_CATCH(
3483           ctx,
3484           query->query_->add_range_var(
3485               dim_idx, start, start_size, end, end_size)))
3486     return TILEDB_ERR;
3487 
3488   return TILEDB_OK;
3489 }
3490 
tiledb_query_add_range_var_by_name(tiledb_ctx_t * ctx,tiledb_query_t * query,const char * dim_name,const void * start,uint64_t start_size,const void * end,uint64_t end_size)3491 int32_t tiledb_query_add_range_var_by_name(
3492     tiledb_ctx_t* ctx,
3493     tiledb_query_t* query,
3494     const char* dim_name,
3495     const void* start,
3496     uint64_t start_size,
3497     const void* end,
3498     uint64_t end_size) {
3499   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3500     return TILEDB_ERR;
3501 
3502   if (SAVE_ERROR_CATCH(
3503           ctx,
3504           query->query_->add_range_var_by_name(
3505               dim_name, start, start_size, end, end_size)))
3506     return TILEDB_ERR;
3507 
3508   return TILEDB_OK;
3509 }
3510 
tiledb_query_get_range_num(tiledb_ctx_t * ctx,const tiledb_query_t * query,uint32_t dim_idx,uint64_t * range_num)3511 int32_t tiledb_query_get_range_num(
3512     tiledb_ctx_t* ctx,
3513     const tiledb_query_t* query,
3514     uint32_t dim_idx,
3515     uint64_t* range_num) {
3516   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3517     return TILEDB_ERR;
3518 
3519   if (SAVE_ERROR_CATCH(ctx, query->query_->get_range_num(dim_idx, range_num)))
3520     return TILEDB_ERR;
3521 
3522   return TILEDB_OK;
3523 }
3524 
tiledb_query_get_range_num_from_name(tiledb_ctx_t * ctx,const tiledb_query_t * query,const char * dim_name,uint64_t * range_num)3525 int32_t tiledb_query_get_range_num_from_name(
3526     tiledb_ctx_t* ctx,
3527     const tiledb_query_t* query,
3528     const char* dim_name,
3529     uint64_t* range_num) {
3530   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3531     return TILEDB_ERR;
3532 
3533   if (SAVE_ERROR_CATCH(
3534           ctx, query->query_->get_range_num_from_name(dim_name, range_num)))
3535     return TILEDB_ERR;
3536 
3537   return TILEDB_OK;
3538 }
3539 
tiledb_query_get_range(tiledb_ctx_t * ctx,const tiledb_query_t * query,uint32_t dim_idx,uint64_t range_idx,const void ** start,const void ** end,const void ** stride)3540 int32_t tiledb_query_get_range(
3541     tiledb_ctx_t* ctx,
3542     const tiledb_query_t* query,
3543     uint32_t dim_idx,
3544     uint64_t range_idx,
3545     const void** start,
3546     const void** end,
3547     const void** stride) {
3548   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3549     return TILEDB_ERR;
3550 
3551   if (SAVE_ERROR_CATCH(
3552           ctx,
3553           query->query_->get_range(dim_idx, range_idx, start, end, stride)))
3554     return TILEDB_ERR;
3555 
3556   return TILEDB_OK;
3557 }
3558 
tiledb_query_get_range_from_name(tiledb_ctx_t * ctx,const tiledb_query_t * query,const char * dim_name,uint64_t range_idx,const void ** start,const void ** end,const void ** stride)3559 int32_t tiledb_query_get_range_from_name(
3560     tiledb_ctx_t* ctx,
3561     const tiledb_query_t* query,
3562     const char* dim_name,
3563     uint64_t range_idx,
3564     const void** start,
3565     const void** end,
3566     const void** stride) {
3567   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3568     return TILEDB_ERR;
3569 
3570   if (SAVE_ERROR_CATCH(
3571           ctx,
3572           query->query_->get_range_from_name(
3573               dim_name, range_idx, start, end, stride)))
3574     return TILEDB_ERR;
3575 
3576   return TILEDB_OK;
3577 }
3578 
tiledb_query_get_range_var_size(tiledb_ctx_t * ctx,const tiledb_query_t * query,uint32_t dim_idx,uint64_t range_idx,uint64_t * start_size,uint64_t * end_size)3579 int32_t tiledb_query_get_range_var_size(
3580     tiledb_ctx_t* ctx,
3581     const tiledb_query_t* query,
3582     uint32_t dim_idx,
3583     uint64_t range_idx,
3584     uint64_t* start_size,
3585     uint64_t* end_size) {
3586   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3587     return TILEDB_ERR;
3588 
3589   if (SAVE_ERROR_CATCH(
3590           ctx,
3591           query->query_->get_range_var_size(
3592               dim_idx, range_idx, start_size, end_size)))
3593     return TILEDB_ERR;
3594 
3595   return TILEDB_OK;
3596 }
3597 
tiledb_query_get_range_var_size_from_name(tiledb_ctx_t * ctx,const tiledb_query_t * query,const char * dim_name,uint64_t range_idx,uint64_t * start_size,uint64_t * end_size)3598 int32_t tiledb_query_get_range_var_size_from_name(
3599     tiledb_ctx_t* ctx,
3600     const tiledb_query_t* query,
3601     const char* dim_name,
3602     uint64_t range_idx,
3603     uint64_t* start_size,
3604     uint64_t* end_size) {
3605   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3606     return TILEDB_ERR;
3607 
3608   if (SAVE_ERROR_CATCH(
3609           ctx,
3610           query->query_->get_range_var_size_from_name(
3611               dim_name, range_idx, start_size, end_size)))
3612     return TILEDB_ERR;
3613 
3614   return TILEDB_OK;
3615 }
3616 
tiledb_query_get_range_var(tiledb_ctx_t * ctx,const tiledb_query_t * query,uint32_t dim_idx,uint64_t range_idx,void * start,void * end)3617 int32_t tiledb_query_get_range_var(
3618     tiledb_ctx_t* ctx,
3619     const tiledb_query_t* query,
3620     uint32_t dim_idx,
3621     uint64_t range_idx,
3622     void* start,
3623     void* end) {
3624   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3625     return TILEDB_ERR;
3626 
3627   if (SAVE_ERROR_CATCH(
3628           ctx, query->query_->get_range_var(dim_idx, range_idx, start, end)))
3629     return TILEDB_ERR;
3630 
3631   return TILEDB_OK;
3632 }
3633 
tiledb_query_get_range_var_from_name(tiledb_ctx_t * ctx,const tiledb_query_t * query,const char * dim_name,uint64_t range_idx,void * start,void * end)3634 int32_t tiledb_query_get_range_var_from_name(
3635     tiledb_ctx_t* ctx,
3636     const tiledb_query_t* query,
3637     const char* dim_name,
3638     uint64_t range_idx,
3639     void* start,
3640     void* end) {
3641   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3642     return TILEDB_ERR;
3643 
3644   if (SAVE_ERROR_CATCH(
3645           ctx,
3646           query->query_->get_range_var_from_name(
3647               dim_name, range_idx, start, end)))
3648     return TILEDB_ERR;
3649 
3650   return TILEDB_OK;
3651 }
3652 
tiledb_query_get_est_result_size(tiledb_ctx_t * ctx,const tiledb_query_t * query,const char * name,uint64_t * size)3653 int32_t tiledb_query_get_est_result_size(
3654     tiledb_ctx_t* ctx,
3655     const tiledb_query_t* query,
3656     const char* name,
3657     uint64_t* size) {
3658   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3659     return TILEDB_ERR;
3660 
3661   if (SAVE_ERROR_CATCH(ctx, query->query_->get_est_result_size(name, size)))
3662     return TILEDB_ERR;
3663 
3664   return TILEDB_OK;
3665 }
3666 
tiledb_query_get_est_result_size_var(tiledb_ctx_t * ctx,const tiledb_query_t * query,const char * name,uint64_t * size_off,uint64_t * size_val)3667 int32_t tiledb_query_get_est_result_size_var(
3668     tiledb_ctx_t* ctx,
3669     const tiledb_query_t* query,
3670     const char* name,
3671     uint64_t* size_off,
3672     uint64_t* size_val) {
3673   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3674     return TILEDB_ERR;
3675 
3676   if (SAVE_ERROR_CATCH(
3677           ctx, query->query_->get_est_result_size(name, size_off, size_val)))
3678     return TILEDB_ERR;
3679 
3680   return TILEDB_OK;
3681 }
3682 
tiledb_query_get_est_result_size_nullable(tiledb_ctx_t * ctx,const tiledb_query_t * query,const char * name,uint64_t * size_val,uint64_t * size_validity)3683 int32_t tiledb_query_get_est_result_size_nullable(
3684     tiledb_ctx_t* ctx,
3685     const tiledb_query_t* query,
3686     const char* name,
3687     uint64_t* size_val,
3688     uint64_t* size_validity) {
3689   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3690     return TILEDB_ERR;
3691 
3692   if (SAVE_ERROR_CATCH(
3693           ctx,
3694           query->query_->get_est_result_size_nullable(
3695               name, size_val, size_validity)))
3696     return TILEDB_ERR;
3697 
3698   return TILEDB_OK;
3699 }
3700 
tiledb_query_get_est_result_size_var_nullable(tiledb_ctx_t * ctx,const tiledb_query_t * query,const char * name,uint64_t * size_off,uint64_t * size_val,uint64_t * size_validity)3701 int32_t tiledb_query_get_est_result_size_var_nullable(
3702     tiledb_ctx_t* ctx,
3703     const tiledb_query_t* query,
3704     const char* name,
3705     uint64_t* size_off,
3706     uint64_t* size_val,
3707     uint64_t* size_validity) {
3708   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3709     return TILEDB_ERR;
3710 
3711   if (SAVE_ERROR_CATCH(
3712           ctx,
3713           query->query_->get_est_result_size_nullable(
3714               name, size_off, size_val, size_validity)))
3715     return TILEDB_ERR;
3716 
3717   return TILEDB_OK;
3718 }
3719 
tiledb_query_get_fragment_num(tiledb_ctx_t * ctx,const tiledb_query_t * query,uint32_t * num)3720 int32_t tiledb_query_get_fragment_num(
3721     tiledb_ctx_t* ctx, const tiledb_query_t* query, uint32_t* num) {
3722   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3723     return TILEDB_ERR;
3724 
3725   if (SAVE_ERROR_CATCH(ctx, query->query_->get_written_fragment_num(num)))
3726     return TILEDB_ERR;
3727 
3728   return TILEDB_OK;
3729 }
3730 
tiledb_query_get_fragment_uri(tiledb_ctx_t * ctx,const tiledb_query_t * query,uint64_t idx,const char ** uri)3731 int32_t tiledb_query_get_fragment_uri(
3732     tiledb_ctx_t* ctx,
3733     const tiledb_query_t* query,
3734     uint64_t idx,
3735     const char** uri) {
3736   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3737     return TILEDB_ERR;
3738 
3739   if (SAVE_ERROR_CATCH(ctx, query->query_->get_written_fragment_uri(idx, uri)))
3740     return TILEDB_ERR;
3741 
3742   return TILEDB_OK;
3743 }
3744 
tiledb_query_get_fragment_timestamp_range(tiledb_ctx_t * ctx,const tiledb_query_t * query,uint64_t idx,uint64_t * t1,uint64_t * t2)3745 int32_t tiledb_query_get_fragment_timestamp_range(
3746     tiledb_ctx_t* ctx,
3747     const tiledb_query_t* query,
3748     uint64_t idx,
3749     uint64_t* t1,
3750     uint64_t* t2) {
3751   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
3752     return TILEDB_ERR;
3753 
3754   if (SAVE_ERROR_CATCH(
3755           ctx,
3756           query->query_->get_written_fragment_timestamp_range(idx, t1, t2)))
3757     return TILEDB_ERR;
3758 
3759   return TILEDB_OK;
3760 }
3761 
3762 /* ****************************** */
3763 /*          QUERY CONDITION       */
3764 /* ****************************** */
3765 
tiledb_query_condition_alloc(tiledb_ctx_t * const ctx,tiledb_query_condition_t ** const cond)3766 int32_t tiledb_query_condition_alloc(
3767     tiledb_ctx_t* const ctx, tiledb_query_condition_t** const cond) {
3768   if (sanity_check(ctx) == TILEDB_ERR) {
3769     *cond = nullptr;
3770     return TILEDB_ERR;
3771   }
3772 
3773   // Create query condition struct
3774   *cond = new (std::nothrow) tiledb_query_condition_t;
3775   if (*cond == nullptr) {
3776     auto st = Status::Error(
3777         "Failed to create TileDB query condition object; Memory allocation "
3778         "error");
3779     LOG_STATUS(st);
3780     save_error(ctx, st);
3781     return TILEDB_OOM;
3782   }
3783 
3784   // Create QueryCondition object
3785   (*cond)->query_condition_ = new (std::nothrow) tiledb::sm::QueryCondition();
3786   if ((*cond)->query_condition_ == nullptr) {
3787     auto st = Status::Error("Failed to allocate TileDB query condition object");
3788     LOG_STATUS(st);
3789     save_error(ctx, st);
3790     delete *cond;
3791     *cond = nullptr;
3792     return TILEDB_OOM;
3793   }
3794 
3795   // Success
3796   return TILEDB_OK;
3797 }
3798 
tiledb_query_condition_free(tiledb_query_condition_t ** cond)3799 void tiledb_query_condition_free(tiledb_query_condition_t** cond) {
3800   if (cond != nullptr && *cond != nullptr) {
3801     delete (*cond)->query_condition_;
3802     delete *cond;
3803     *cond = nullptr;
3804   }
3805 }
3806 
tiledb_query_condition_init(tiledb_ctx_t * const ctx,tiledb_query_condition_t * const cond,const char * const attribute_name,const void * const condition_value,const uint64_t condition_value_size,const tiledb_query_condition_op_t op)3807 int32_t tiledb_query_condition_init(
3808     tiledb_ctx_t* const ctx,
3809     tiledb_query_condition_t* const cond,
3810     const char* const attribute_name,
3811     const void* const condition_value,
3812     const uint64_t condition_value_size,
3813     const tiledb_query_condition_op_t op) {
3814   if (sanity_check(ctx) == TILEDB_ERR ||
3815       sanity_check(ctx, cond) == TILEDB_ERR) {
3816     return TILEDB_ERR;
3817   }
3818 
3819   // Initialize the QueryCondition object
3820   auto st = cond->query_condition_->init(
3821       std::string(attribute_name),
3822       condition_value,
3823       condition_value_size,
3824       static_cast<tiledb::sm::QueryConditionOp>(op));
3825   if (!st.ok()) {
3826     LOG_STATUS(st);
3827     save_error(ctx, st);
3828     return TILEDB_ERR;
3829   }
3830 
3831   // Success
3832   return TILEDB_OK;
3833 }
3834 
tiledb_query_condition_combine(tiledb_ctx_t * const ctx,const tiledb_query_condition_t * const left_cond,const tiledb_query_condition_t * const right_cond,const tiledb_query_condition_combination_op_t combination_op,tiledb_query_condition_t ** const combined_cond)3835 int32_t tiledb_query_condition_combine(
3836     tiledb_ctx_t* const ctx,
3837     const tiledb_query_condition_t* const left_cond,
3838     const tiledb_query_condition_t* const right_cond,
3839     const tiledb_query_condition_combination_op_t combination_op,
3840     tiledb_query_condition_t** const combined_cond) {
3841   // Sanity check
3842   if (sanity_check(ctx) == TILEDB_ERR ||
3843       sanity_check(ctx, left_cond) == TILEDB_ERR ||
3844       sanity_check(ctx, right_cond) == TILEDB_ERR)
3845     return TILEDB_ERR;
3846 
3847   // Create the combined query condition struct
3848   *combined_cond = new (std::nothrow) tiledb_query_condition_t;
3849   if (*combined_cond == nullptr) {
3850     auto st = Status::Error(
3851         "Failed to create TileDB query condition object; Memory allocation "
3852         "error");
3853     LOG_STATUS(st);
3854     save_error(ctx, st);
3855     return TILEDB_OOM;
3856   }
3857 
3858   // Create the combined QueryCondition object
3859   (*combined_cond)->query_condition_ =
3860       new (std::nothrow) tiledb::sm::QueryCondition();
3861   if ((*combined_cond)->query_condition_ == nullptr) {
3862     auto st = Status::Error("Failed to allocate TileDB query condition object");
3863     LOG_STATUS(st);
3864     save_error(ctx, st);
3865     delete *combined_cond;
3866     *combined_cond = nullptr;
3867     return TILEDB_OOM;
3868   }
3869 
3870   if (SAVE_ERROR_CATCH(
3871           ctx,
3872           left_cond->query_condition_->combine(
3873               *right_cond->query_condition_,
3874               static_cast<tiledb::sm::QueryConditionCombinationOp>(
3875                   combination_op),
3876               (*combined_cond)->query_condition_))) {
3877     delete (*combined_cond)->query_condition_;
3878     delete *combined_cond;
3879     return TILEDB_ERR;
3880   }
3881 
3882   return TILEDB_OK;
3883 }
3884 
3885 /* ****************************** */
3886 /*              ARRAY             */
3887 /* ****************************** */
3888 
tiledb_array_alloc(tiledb_ctx_t * ctx,const char * array_uri,tiledb_array_t ** array)3889 int32_t tiledb_array_alloc(
3890     tiledb_ctx_t* ctx, const char* array_uri, tiledb_array_t** array) {
3891   if (sanity_check(ctx) == TILEDB_ERR) {
3892     *array = nullptr;
3893     return TILEDB_ERR;
3894   }
3895 
3896   // Create array struct
3897   *array = new (std::nothrow) tiledb_array_t;
3898   if (*array == nullptr) {
3899     auto st = Status::Error(
3900         "Failed to create TileDB array object; Memory allocation error");
3901     LOG_STATUS(st);
3902     save_error(ctx, st);
3903     return TILEDB_OOM;
3904   }
3905 
3906   // Check array URI
3907   auto uri = tiledb::sm::URI(array_uri);
3908   if (uri.is_invalid()) {
3909     auto st =
3910         Status::Error("Failed to create TileDB array object; Invalid URI");
3911     delete *array;
3912     *array = nullptr;
3913     LOG_STATUS(st);
3914     save_error(ctx, st);
3915     return TILEDB_ERR;
3916   }
3917 
3918   // Allocate an array object
3919   (*array)->array_ =
3920       new (std::nothrow) tiledb::sm::Array(uri, ctx->ctx_->storage_manager());
3921   if ((*array)->array_ == nullptr) {
3922     delete *array;
3923     *array = nullptr;
3924     auto st = Status::Error(
3925         "Failed to create TileDB array object; Memory allocation "
3926         "error");
3927     LOG_STATUS(st);
3928     save_error(ctx, st);
3929     return TILEDB_OOM;
3930   }
3931 
3932   // Success
3933   return TILEDB_OK;
3934 }
3935 
tiledb_array_set_open_timestamp_start(tiledb_ctx_t * ctx,tiledb_array_t * array,uint64_t timestamp_start)3936 int32_t tiledb_array_set_open_timestamp_start(
3937     tiledb_ctx_t* ctx, tiledb_array_t* array, uint64_t timestamp_start) {
3938   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
3939     return TILEDB_ERR;
3940 
3941   if (SAVE_ERROR_CATCH(
3942           ctx, array->array_->set_timestamp_start(timestamp_start)))
3943     return TILEDB_ERR;
3944 
3945   return TILEDB_OK;
3946 }
3947 
tiledb_array_set_open_timestamp_end(tiledb_ctx_t * ctx,tiledb_array_t * array,uint64_t timestamp_end)3948 int32_t tiledb_array_set_open_timestamp_end(
3949     tiledb_ctx_t* ctx, tiledb_array_t* array, uint64_t timestamp_end) {
3950   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
3951     return TILEDB_ERR;
3952 
3953   if (SAVE_ERROR_CATCH(ctx, array->array_->set_timestamp_end(timestamp_end)))
3954     return TILEDB_ERR;
3955 
3956   return TILEDB_OK;
3957 }
3958 
tiledb_array_get_open_timestamp_start(tiledb_ctx_t * ctx,tiledb_array_t * array,uint64_t * timestamp_start)3959 int32_t tiledb_array_get_open_timestamp_start(
3960     tiledb_ctx_t* ctx, tiledb_array_t* array, uint64_t* timestamp_start) {
3961   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
3962     return TILEDB_ERR;
3963 
3964   *timestamp_start = array->array_->timestamp_start();
3965 
3966   return TILEDB_OK;
3967 }
3968 
tiledb_array_get_open_timestamp_end(tiledb_ctx_t * ctx,tiledb_array_t * array,uint64_t * timestamp_end)3969 int32_t tiledb_array_get_open_timestamp_end(
3970     tiledb_ctx_t* ctx, tiledb_array_t* array, uint64_t* timestamp_end) {
3971   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
3972     return TILEDB_ERR;
3973 
3974   *timestamp_end = array->array_->timestamp_end_opened_at();
3975 
3976   return TILEDB_OK;
3977 }
3978 
tiledb_array_open(tiledb_ctx_t * ctx,tiledb_array_t * array,tiledb_query_type_t query_type)3979 int32_t tiledb_array_open(
3980     tiledb_ctx_t* ctx, tiledb_array_t* array, tiledb_query_type_t query_type) {
3981   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
3982     return TILEDB_ERR;
3983 
3984   // Open array
3985   if (SAVE_ERROR_CATCH(
3986           ctx,
3987           array->array_->open(
3988               static_cast<tiledb::sm::QueryType>(query_type),
3989               static_cast<tiledb::sm::EncryptionType>(TILEDB_NO_ENCRYPTION),
3990               nullptr,
3991               0)))
3992     return TILEDB_ERR;
3993 
3994   return TILEDB_OK;
3995 }
3996 
tiledb_array_open_at(tiledb_ctx_t * ctx,tiledb_array_t * array,tiledb_query_type_t query_type,uint64_t timestamp)3997 int32_t tiledb_array_open_at(
3998     tiledb_ctx_t* ctx,
3999     tiledb_array_t* array,
4000     tiledb_query_type_t query_type,
4001     uint64_t timestamp) {
4002   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4003     return TILEDB_ERR;
4004 
4005   // Open array
4006   if (SAVE_ERROR_CATCH(
4007           ctx,
4008           array->array_->open(
4009               static_cast<tiledb::sm::QueryType>(query_type),
4010               0,
4011               timestamp,
4012               static_cast<tiledb::sm::EncryptionType>(TILEDB_NO_ENCRYPTION),
4013               nullptr,
4014               0)))
4015     return TILEDB_ERR;
4016 
4017   return TILEDB_OK;
4018 }
4019 
tiledb_array_open_with_key(tiledb_ctx_t * ctx,tiledb_array_t * array,tiledb_query_type_t query_type,tiledb_encryption_type_t encryption_type,const void * encryption_key,uint32_t key_length)4020 int32_t tiledb_array_open_with_key(
4021     tiledb_ctx_t* ctx,
4022     tiledb_array_t* array,
4023     tiledb_query_type_t query_type,
4024     tiledb_encryption_type_t encryption_type,
4025     const void* encryption_key,
4026     uint32_t key_length) {
4027   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4028     return TILEDB_ERR;
4029 
4030   // Open array
4031   if (SAVE_ERROR_CATCH(
4032           ctx,
4033           array->array_->open(
4034               static_cast<tiledb::sm::QueryType>(query_type),
4035               static_cast<tiledb::sm::EncryptionType>(encryption_type),
4036               encryption_key,
4037               key_length)))
4038     return TILEDB_ERR;
4039 
4040   return TILEDB_OK;
4041 }
4042 
tiledb_array_open_at_with_key(tiledb_ctx_t * ctx,tiledb_array_t * array,tiledb_query_type_t query_type,tiledb_encryption_type_t encryption_type,const void * encryption_key,uint32_t key_length,uint64_t timestamp)4043 int32_t tiledb_array_open_at_with_key(
4044     tiledb_ctx_t* ctx,
4045     tiledb_array_t* array,
4046     tiledb_query_type_t query_type,
4047     tiledb_encryption_type_t encryption_type,
4048     const void* encryption_key,
4049     uint32_t key_length,
4050     uint64_t timestamp) {
4051   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4052     return TILEDB_ERR;
4053 
4054   // Open array
4055   if (SAVE_ERROR_CATCH(
4056           ctx,
4057           array->array_->open(
4058               static_cast<tiledb::sm::QueryType>(query_type),
4059               0,
4060               timestamp,
4061               static_cast<tiledb::sm::EncryptionType>(encryption_type),
4062               encryption_key,
4063               key_length)))
4064     return TILEDB_ERR;
4065 
4066   return TILEDB_OK;
4067 }
4068 
tiledb_array_is_open(tiledb_ctx_t * ctx,tiledb_array_t * array,int32_t * is_open)4069 int32_t tiledb_array_is_open(
4070     tiledb_ctx_t* ctx, tiledb_array_t* array, int32_t* is_open) {
4071   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4072     return TILEDB_ERR;
4073 
4074   *is_open = (int32_t)array->array_->is_open();
4075 
4076   return TILEDB_OK;
4077 }
4078 
tiledb_array_reopen(tiledb_ctx_t * ctx,tiledb_array_t * array)4079 int32_t tiledb_array_reopen(tiledb_ctx_t* ctx, tiledb_array_t* array) {
4080   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4081     return TILEDB_ERR;
4082 
4083   // Reopen array
4084   if (SAVE_ERROR_CATCH(ctx, array->array_->reopen()))
4085     return TILEDB_ERR;
4086 
4087   return TILEDB_OK;
4088 }
4089 
tiledb_array_reopen_at(tiledb_ctx_t * ctx,tiledb_array_t * array,uint64_t timestamp_end)4090 int32_t tiledb_array_reopen_at(
4091     tiledb_ctx_t* ctx, tiledb_array_t* array, uint64_t timestamp_end) {
4092   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4093     return TILEDB_ERR;
4094 
4095   // Reopen array
4096   if (SAVE_ERROR_CATCH(ctx, array->array_->reopen(0, timestamp_end)))
4097     return TILEDB_ERR;
4098 
4099   return TILEDB_OK;
4100 }
4101 
tiledb_array_get_timestamp(tiledb_ctx_t * ctx,tiledb_array_t * array,uint64_t * timestamp)4102 int32_t tiledb_array_get_timestamp(
4103     tiledb_ctx_t* ctx, tiledb_array_t* array, uint64_t* timestamp) {
4104   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4105     return TILEDB_ERR;
4106 
4107   *timestamp = array->array_->timestamp_end_opened_at();
4108 
4109   return TILEDB_OK;
4110 }
4111 
tiledb_array_set_config(tiledb_ctx_t * ctx,tiledb_array_t * array,tiledb_config_t * config)4112 int32_t tiledb_array_set_config(
4113     tiledb_ctx_t* ctx, tiledb_array_t* array, tiledb_config_t* config) {
4114   // Sanity check
4115   if (sanity_check(ctx) == TILEDB_ERR ||
4116       sanity_check(ctx, array) == TILEDB_ERR ||
4117       sanity_check(ctx, config) == TILEDB_ERR)
4118     return TILEDB_ERR;
4119 
4120   if (SAVE_ERROR_CATCH(ctx, array->array_->set_config(*(config->config_))))
4121     return TILEDB_ERR;
4122 
4123   return TILEDB_OK;
4124 }
4125 
tiledb_array_get_config(tiledb_ctx_t * ctx,tiledb_array_t * array,tiledb_config_t ** config)4126 int32_t tiledb_array_get_config(
4127     tiledb_ctx_t* ctx, tiledb_array_t* array, tiledb_config_t** config) {
4128   // Sanity check
4129   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4130     return TILEDB_ERR;
4131 
4132   // Create a new config struct
4133   *config = new (std::nothrow) tiledb_config_t;
4134   if (*config == nullptr)
4135     return TILEDB_OOM;
4136 
4137   // Get the array config
4138   (*config)->config_ = new (std::nothrow) tiledb::sm::Config();
4139   *((*config)->config_) = array->array_->config();
4140   if ((*config)->config_ == nullptr) {
4141     delete (*config);
4142     *config = nullptr;
4143     return TILEDB_OOM;
4144   }
4145 
4146   return TILEDB_OK;
4147 }
4148 
tiledb_array_close(tiledb_ctx_t * ctx,tiledb_array_t * array)4149 int32_t tiledb_array_close(tiledb_ctx_t* ctx, tiledb_array_t* array) {
4150   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4151     return TILEDB_ERR;
4152 
4153   // Close array
4154   if (SAVE_ERROR_CATCH(ctx, array->array_->close()))
4155     return TILEDB_ERR;
4156 
4157   return TILEDB_OK;
4158 }
4159 
tiledb_array_free(tiledb_array_t ** array)4160 void tiledb_array_free(tiledb_array_t** array) {
4161   if (array != nullptr && *array != nullptr) {
4162     delete (*array)->array_;
4163     delete *array;
4164     *array = nullptr;
4165   }
4166 }
4167 
tiledb_array_get_schema(tiledb_ctx_t * ctx,tiledb_array_t * array,tiledb_array_schema_t ** array_schema)4168 int32_t tiledb_array_get_schema(
4169     tiledb_ctx_t* ctx,
4170     tiledb_array_t* array,
4171     tiledb_array_schema_t** array_schema) {
4172   if (sanity_check(ctx) == TILEDB_ERR ||
4173       sanity_check(ctx, array) == TILEDB_ERR) {
4174     return TILEDB_ERR;
4175   }
4176 
4177   *array_schema = new (std::nothrow) tiledb_array_schema_t;
4178   if (*array_schema == nullptr) {
4179     auto st = Status::Error("Failed to allocate TileDB array schema");
4180     LOG_STATUS(st);
4181     save_error(ctx, st);
4182     return TILEDB_OOM;
4183   }
4184 
4185   // Get schema
4186   auto schema = (tiledb::sm::ArraySchema*)nullptr;
4187   if (SAVE_ERROR_CATCH(ctx, array->array_->get_array_schema(&schema))) {
4188     delete *array_schema;
4189     *array_schema = nullptr;
4190     return TILEDB_ERR;
4191   }
4192 
4193   (*array_schema)->array_schema_ =
4194       new (std::nothrow) tiledb::sm::ArraySchema(schema);
4195 
4196   return TILEDB_OK;
4197 }
4198 
tiledb_array_get_query_type(tiledb_ctx_t * ctx,tiledb_array_t * array,tiledb_query_type_t * query_type)4199 int32_t tiledb_array_get_query_type(
4200     tiledb_ctx_t* ctx, tiledb_array_t* array, tiledb_query_type_t* query_type) {
4201   // Sanity checks
4202   if (sanity_check(ctx) == TILEDB_ERR ||
4203       sanity_check(ctx, array) == TILEDB_ERR) {
4204     return TILEDB_ERR;
4205   }
4206 
4207   // Get query_type
4208   tiledb::sm::QueryType type;
4209   if (SAVE_ERROR_CATCH(ctx, array->array_->get_query_type(&type)))
4210     return TILEDB_ERR;
4211 
4212   *query_type = static_cast<tiledb_query_type_t>(type);
4213 
4214   return TILEDB_OK;
4215 }
4216 
tiledb_array_create(tiledb_ctx_t * ctx,const char * array_uri,const tiledb_array_schema_t * array_schema)4217 int32_t tiledb_array_create(
4218     tiledb_ctx_t* ctx,
4219     const char* array_uri,
4220     const tiledb_array_schema_t* array_schema) {
4221   // Sanity checks
4222   if (sanity_check(ctx) == TILEDB_ERR ||
4223       sanity_check(ctx, array_schema) == TILEDB_ERR)
4224     return TILEDB_ERR;
4225 
4226   // Check array name
4227   tiledb::sm::URI uri(array_uri);
4228   if (uri.is_invalid()) {
4229     auto st = Status::Error("Failed to create array; Invalid array URI");
4230     LOG_STATUS(st);
4231     save_error(ctx, st);
4232     return TILEDB_ERR;
4233   }
4234 
4235   if (uri.is_tiledb()) {
4236     // Check REST client
4237     auto rest_client = ctx->ctx_->storage_manager()->rest_client();
4238     if (rest_client == nullptr) {
4239       auto st = Status::Error(
4240           "Failed to create array; remote array with no REST client.");
4241       LOG_STATUS(st);
4242       save_error(ctx, st);
4243       return TILEDB_ERR;
4244     }
4245 
4246     if (SAVE_ERROR_CATCH(
4247             ctx,
4248             rest_client->post_array_schema_to_rest(
4249                 uri, array_schema->array_schema_)))
4250       return TILEDB_ERR;
4251   } else {
4252     // Create key
4253     tiledb::sm::EncryptionKey key;
4254     if (SAVE_ERROR_CATCH(
4255             ctx,
4256             key.set_key(
4257                 static_cast<tiledb::sm::EncryptionType>(TILEDB_NO_ENCRYPTION),
4258                 nullptr,
4259                 0)))
4260       return TILEDB_ERR;
4261 
4262     // Create the array
4263     if (SAVE_ERROR_CATCH(
4264             ctx,
4265             ctx->ctx_->storage_manager()->array_create(
4266                 uri, array_schema->array_schema_, key)))
4267       return TILEDB_ERR;
4268   }
4269   return TILEDB_OK;
4270 }
4271 
tiledb_array_create_with_key(tiledb_ctx_t * ctx,const char * array_uri,const tiledb_array_schema_t * array_schema,tiledb_encryption_type_t encryption_type,const void * encryption_key,uint32_t key_length)4272 int32_t tiledb_array_create_with_key(
4273     tiledb_ctx_t* ctx,
4274     const char* array_uri,
4275     const tiledb_array_schema_t* array_schema,
4276     tiledb_encryption_type_t encryption_type,
4277     const void* encryption_key,
4278     uint32_t key_length) {
4279   // Sanity checks
4280   if (sanity_check(ctx) == TILEDB_ERR ||
4281       sanity_check(ctx, array_schema) == TILEDB_ERR)
4282     return TILEDB_ERR;
4283 
4284   // Check array name
4285   tiledb::sm::URI uri(array_uri);
4286   if (uri.is_invalid()) {
4287     auto st = Status::Error("Failed to create array; Invalid array URI");
4288     LOG_STATUS(st);
4289     save_error(ctx, st);
4290     return TILEDB_ERR;
4291   }
4292 
4293   if (uri.is_tiledb()) {
4294     // Check unencrypted
4295     if (encryption_type != TILEDB_NO_ENCRYPTION) {
4296       auto st = Status::Error(
4297           "Failed to create array; encrypted remote arrays are not supported.");
4298       LOG_STATUS(st);
4299       save_error(ctx, st);
4300       return TILEDB_ERR;
4301     }
4302 
4303     // Check REST client
4304     auto rest_client = ctx->ctx_->storage_manager()->rest_client();
4305     if (rest_client == nullptr) {
4306       auto st = Status::Error(
4307           "Failed to create array; remote array with no REST client.");
4308       LOG_STATUS(st);
4309       save_error(ctx, st);
4310       return TILEDB_ERR;
4311     }
4312 
4313     if (SAVE_ERROR_CATCH(
4314             ctx,
4315             rest_client->post_array_schema_to_rest(
4316                 uri, array_schema->array_schema_)))
4317       return TILEDB_ERR;
4318   } else {
4319     // Create key
4320     tiledb::sm::EncryptionKey key;
4321     if (SAVE_ERROR_CATCH(
4322             ctx,
4323             key.set_key(
4324                 static_cast<tiledb::sm::EncryptionType>(encryption_type),
4325                 encryption_key,
4326                 key_length)))
4327       return TILEDB_ERR;
4328 
4329     // Create the array
4330     if (SAVE_ERROR_CATCH(
4331             ctx,
4332             ctx->ctx_->storage_manager()->array_create(
4333                 uri, array_schema->array_schema_, key)))
4334       return TILEDB_ERR;
4335   }
4336   return TILEDB_OK;
4337 }
4338 
tiledb_array_consolidate(tiledb_ctx_t * ctx,const char * array_uri,tiledb_config_t * config)4339 int32_t tiledb_array_consolidate(
4340     tiledb_ctx_t* ctx, const char* array_uri, tiledb_config_t* config) {
4341   // Sanity checks
4342   if (sanity_check(ctx) == TILEDB_ERR)
4343     return TILEDB_ERR;
4344 
4345   if (SAVE_ERROR_CATCH(
4346           ctx,
4347           ctx->ctx_->storage_manager()->array_consolidate(
4348               array_uri,
4349               static_cast<tiledb::sm::EncryptionType>(TILEDB_NO_ENCRYPTION),
4350               nullptr,
4351               0,
4352               (config == nullptr) ? &ctx->ctx_->storage_manager()->config() :
4353                                     config->config_)))
4354     return TILEDB_ERR;
4355 
4356   return TILEDB_OK;
4357 }
4358 
tiledb_array_consolidate_with_key(tiledb_ctx_t * ctx,const char * array_uri,tiledb_encryption_type_t encryption_type,const void * encryption_key,uint32_t key_length,tiledb_config_t * config)4359 int32_t tiledb_array_consolidate_with_key(
4360     tiledb_ctx_t* ctx,
4361     const char* array_uri,
4362     tiledb_encryption_type_t encryption_type,
4363     const void* encryption_key,
4364     uint32_t key_length,
4365     tiledb_config_t* config) {
4366   // Sanity checks
4367   if (sanity_check(ctx) == TILEDB_ERR)
4368     return TILEDB_ERR;
4369 
4370   if (SAVE_ERROR_CATCH(
4371           ctx,
4372           ctx->ctx_->storage_manager()->array_consolidate(
4373               array_uri,
4374               static_cast<tiledb::sm::EncryptionType>(encryption_type),
4375               encryption_key,
4376               key_length,
4377               (config == nullptr) ? &ctx->ctx_->storage_manager()->config() :
4378                                     config->config_)))
4379     return TILEDB_ERR;
4380 
4381   return TILEDB_OK;
4382 }
4383 
tiledb_array_vacuum(tiledb_ctx_t * ctx,const char * array_uri,tiledb_config_t * config)4384 int32_t tiledb_array_vacuum(
4385     tiledb_ctx_t* ctx, const char* array_uri, tiledb_config_t* config) {
4386   // Sanity checks
4387   if (sanity_check(ctx) == TILEDB_ERR)
4388     return TILEDB_ERR;
4389 
4390   if (SAVE_ERROR_CATCH(
4391           ctx,
4392           ctx->ctx_->storage_manager()->array_vacuum(
4393               array_uri,
4394               (config == nullptr) ? &ctx->ctx_->storage_manager()->config() :
4395                                     config->config_)))
4396     return TILEDB_ERR;
4397 
4398   return TILEDB_OK;
4399 }
4400 
tiledb_array_get_non_empty_domain(tiledb_ctx_t * ctx,tiledb_array_t * array,void * domain,int32_t * is_empty)4401 int32_t tiledb_array_get_non_empty_domain(
4402     tiledb_ctx_t* ctx, tiledb_array_t* array, void* domain, int32_t* is_empty) {
4403   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4404     return TILEDB_ERR;
4405 
4406   bool is_empty_b;
4407 
4408   if (SAVE_ERROR_CATCH(
4409           ctx,
4410           ctx->ctx_->storage_manager()->array_get_non_empty_domain(
4411               array->array_, domain, &is_empty_b)))
4412     return TILEDB_ERR;
4413 
4414   *is_empty = (int32_t)is_empty_b;
4415 
4416   return TILEDB_OK;
4417 }
4418 
tiledb_array_get_non_empty_domain_from_index(tiledb_ctx_t * ctx,tiledb_array_t * array,uint32_t idx,void * domain,int32_t * is_empty)4419 int32_t tiledb_array_get_non_empty_domain_from_index(
4420     tiledb_ctx_t* ctx,
4421     tiledb_array_t* array,
4422     uint32_t idx,
4423     void* domain,
4424     int32_t* is_empty) {
4425   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4426     return TILEDB_ERR;
4427 
4428   bool is_empty_b;
4429 
4430   if (SAVE_ERROR_CATCH(
4431           ctx,
4432           ctx->ctx_->storage_manager()->array_get_non_empty_domain_from_index(
4433               array->array_, idx, domain, &is_empty_b)))
4434     return TILEDB_ERR;
4435 
4436   *is_empty = (int32_t)is_empty_b;
4437 
4438   return TILEDB_OK;
4439 }
4440 
tiledb_array_get_non_empty_domain_from_name(tiledb_ctx_t * ctx,tiledb_array_t * array,const char * name,void * domain,int32_t * is_empty)4441 int32_t tiledb_array_get_non_empty_domain_from_name(
4442     tiledb_ctx_t* ctx,
4443     tiledb_array_t* array,
4444     const char* name,
4445     void* domain,
4446     int32_t* is_empty) {
4447   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4448     return TILEDB_ERR;
4449 
4450   bool is_empty_b;
4451 
4452   if (SAVE_ERROR_CATCH(
4453           ctx,
4454           ctx->ctx_->storage_manager()->array_get_non_empty_domain_from_name(
4455               array->array_, name, domain, &is_empty_b)))
4456     return TILEDB_ERR;
4457 
4458   *is_empty = (int32_t)is_empty_b;
4459 
4460   return TILEDB_OK;
4461 }
4462 
tiledb_array_get_non_empty_domain_var_size_from_index(tiledb_ctx_t * ctx,tiledb_array_t * array,uint32_t idx,uint64_t * start_size,uint64_t * end_size,int32_t * is_empty)4463 int32_t tiledb_array_get_non_empty_domain_var_size_from_index(
4464     tiledb_ctx_t* ctx,
4465     tiledb_array_t* array,
4466     uint32_t idx,
4467     uint64_t* start_size,
4468     uint64_t* end_size,
4469     int32_t* is_empty) {
4470   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4471     return TILEDB_ERR;
4472 
4473   bool is_empty_b = true;
4474 
4475   if (SAVE_ERROR_CATCH(
4476           ctx,
4477           ctx->ctx_->storage_manager()
4478               ->array_get_non_empty_domain_var_size_from_index(
4479                   array->array_, idx, start_size, end_size, &is_empty_b)))
4480     return TILEDB_ERR;
4481 
4482   *is_empty = (int32_t)is_empty_b;
4483 
4484   return TILEDB_OK;
4485 }
4486 
tiledb_array_get_non_empty_domain_var_size_from_name(tiledb_ctx_t * ctx,tiledb_array_t * array,const char * name,uint64_t * start_size,uint64_t * end_size,int32_t * is_empty)4487 int32_t tiledb_array_get_non_empty_domain_var_size_from_name(
4488     tiledb_ctx_t* ctx,
4489     tiledb_array_t* array,
4490     const char* name,
4491     uint64_t* start_size,
4492     uint64_t* end_size,
4493     int32_t* is_empty) {
4494   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4495     return TILEDB_ERR;
4496 
4497   bool is_empty_b = true;
4498 
4499   if (SAVE_ERROR_CATCH(
4500           ctx,
4501           ctx->ctx_->storage_manager()
4502               ->array_get_non_empty_domain_var_size_from_name(
4503                   array->array_, name, start_size, end_size, &is_empty_b)))
4504     return TILEDB_ERR;
4505 
4506   *is_empty = (int32_t)is_empty_b;
4507 
4508   return TILEDB_OK;
4509 }
4510 
tiledb_array_get_non_empty_domain_var_from_index(tiledb_ctx_t * ctx,tiledb_array_t * array,uint32_t idx,void * start,void * end,int32_t * is_empty)4511 int32_t tiledb_array_get_non_empty_domain_var_from_index(
4512     tiledb_ctx_t* ctx,
4513     tiledb_array_t* array,
4514     uint32_t idx,
4515     void* start,
4516     void* end,
4517     int32_t* is_empty) {
4518   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4519     return TILEDB_ERR;
4520 
4521   bool is_empty_b = true;
4522 
4523   if (SAVE_ERROR_CATCH(
4524           ctx,
4525           ctx->ctx_->storage_manager()
4526               ->array_get_non_empty_domain_var_from_index(
4527                   array->array_, idx, start, end, &is_empty_b)))
4528     return TILEDB_ERR;
4529 
4530   *is_empty = (int32_t)is_empty_b;
4531 
4532   return TILEDB_OK;
4533 }
4534 
tiledb_array_get_non_empty_domain_var_from_name(tiledb_ctx_t * ctx,tiledb_array_t * array,const char * name,void * start,void * end,int32_t * is_empty)4535 int32_t tiledb_array_get_non_empty_domain_var_from_name(
4536     tiledb_ctx_t* ctx,
4537     tiledb_array_t* array,
4538     const char* name,
4539     void* start,
4540     void* end,
4541     int32_t* is_empty) {
4542   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4543     return TILEDB_ERR;
4544 
4545   bool is_empty_b = true;
4546 
4547   if (SAVE_ERROR_CATCH(
4548           ctx,
4549           ctx->ctx_->storage_manager()
4550               ->array_get_non_empty_domain_var_from_name(
4551                   array->array_, name, start, end, &is_empty_b)))
4552     return TILEDB_ERR;
4553 
4554   *is_empty = (int32_t)is_empty_b;
4555 
4556   return TILEDB_OK;
4557 }
4558 
tiledb_array_get_uri(tiledb_ctx_t * ctx,tiledb_array_t * array,const char ** array_uri)4559 int32_t tiledb_array_get_uri(
4560     tiledb_ctx_t* ctx, tiledb_array_t* array, const char** array_uri) {
4561   // Sanity checks
4562   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4563     return TILEDB_ERR;
4564 
4565   *array_uri = array->array_->array_uri().c_str();
4566 
4567   return TILEDB_OK;
4568 }
4569 
tiledb_array_encryption_type(tiledb_ctx_t * ctx,const char * array_uri,tiledb_encryption_type_t * encryption_type)4570 int32_t tiledb_array_encryption_type(
4571     tiledb_ctx_t* ctx,
4572     const char* array_uri,
4573     tiledb_encryption_type_t* encryption_type) {
4574   // Sanity checks
4575   if (sanity_check(ctx) == TILEDB_ERR || array_uri == nullptr ||
4576       encryption_type == nullptr)
4577     return TILEDB_ERR;
4578 
4579   tiledb::sm::EncryptionType enc;
4580   if (SAVE_ERROR_CATCH(
4581           ctx,
4582           ctx->ctx_->storage_manager()->array_get_encryption(array_uri, &enc)))
4583     return TILEDB_ERR;
4584 
4585   *encryption_type = static_cast<tiledb_encryption_type_t>(enc);
4586 
4587   return TILEDB_OK;
4588 }
4589 
tiledb_array_put_metadata(tiledb_ctx_t * ctx,tiledb_array_t * array,const char * key,tiledb_datatype_t value_type,uint32_t value_num,const void * value)4590 int32_t tiledb_array_put_metadata(
4591     tiledb_ctx_t* ctx,
4592     tiledb_array_t* array,
4593     const char* key,
4594     tiledb_datatype_t value_type,
4595     uint32_t value_num,
4596     const void* value) {
4597   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4598     return TILEDB_ERR;
4599 
4600   // Put metadata
4601   if (SAVE_ERROR_CATCH(
4602           ctx,
4603           array->array_->put_metadata(
4604               key,
4605               static_cast<tiledb::sm::Datatype>(value_type),
4606               value_num,
4607               value)))
4608     return TILEDB_ERR;
4609 
4610   return TILEDB_OK;
4611 }
4612 
tiledb_array_delete_metadata(tiledb_ctx_t * ctx,tiledb_array_t * array,const char * key)4613 int32_t tiledb_array_delete_metadata(
4614     tiledb_ctx_t* ctx, tiledb_array_t* array, const char* key) {
4615   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4616     return TILEDB_ERR;
4617 
4618   // Put metadata
4619   if (SAVE_ERROR_CATCH(ctx, array->array_->delete_metadata(key)))
4620     return TILEDB_ERR;
4621 
4622   return TILEDB_OK;
4623 }
4624 
tiledb_array_get_metadata(tiledb_ctx_t * ctx,tiledb_array_t * array,const char * key,tiledb_datatype_t * value_type,uint32_t * value_num,const void ** value)4625 int32_t tiledb_array_get_metadata(
4626     tiledb_ctx_t* ctx,
4627     tiledb_array_t* array,
4628     const char* key,
4629     tiledb_datatype_t* value_type,
4630     uint32_t* value_num,
4631     const void** value) {
4632   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4633     return TILEDB_ERR;
4634 
4635   // Get metadata
4636   tiledb::sm::Datatype type;
4637   if (SAVE_ERROR_CATCH(
4638           ctx, array->array_->get_metadata(key, &type, value_num, value)))
4639     return TILEDB_ERR;
4640 
4641   *value_type = static_cast<tiledb_datatype_t>(type);
4642 
4643   return TILEDB_OK;
4644 }
4645 
tiledb_array_get_metadata_num(tiledb_ctx_t * ctx,tiledb_array_t * array,uint64_t * num)4646 int32_t tiledb_array_get_metadata_num(
4647     tiledb_ctx_t* ctx, tiledb_array_t* array, uint64_t* num) {
4648   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4649     return TILEDB_ERR;
4650 
4651   // Get metadata num
4652   if (SAVE_ERROR_CATCH(ctx, array->array_->get_metadata_num(num)))
4653     return TILEDB_ERR;
4654 
4655   return TILEDB_OK;
4656 }
4657 
tiledb_array_get_metadata_from_index(tiledb_ctx_t * ctx,tiledb_array_t * array,uint64_t index,const char ** key,uint32_t * key_len,tiledb_datatype_t * value_type,uint32_t * value_num,const void ** value)4658 int32_t tiledb_array_get_metadata_from_index(
4659     tiledb_ctx_t* ctx,
4660     tiledb_array_t* array,
4661     uint64_t index,
4662     const char** key,
4663     uint32_t* key_len,
4664     tiledb_datatype_t* value_type,
4665     uint32_t* value_num,
4666     const void** value) {
4667   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4668     return TILEDB_ERR;
4669 
4670   // Get metadata
4671   tiledb::sm::Datatype type;
4672   if (SAVE_ERROR_CATCH(
4673           ctx,
4674           array->array_->get_metadata(
4675               index, key, key_len, &type, value_num, value)))
4676     return TILEDB_ERR;
4677 
4678   *value_type = static_cast<tiledb_datatype_t>(type);
4679 
4680   return TILEDB_OK;
4681 }
4682 
tiledb_array_has_metadata_key(tiledb_ctx_t * ctx,tiledb_array_t * array,const char * key,tiledb_datatype_t * value_type,int32_t * has_key)4683 int32_t tiledb_array_has_metadata_key(
4684     tiledb_ctx_t* ctx,
4685     tiledb_array_t* array,
4686     const char* key,
4687     tiledb_datatype_t* value_type,
4688     int32_t* has_key) {
4689   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
4690     return TILEDB_ERR;
4691 
4692   // Check whether metadata has_key
4693   bool has_the_key;
4694   tiledb::sm::Datatype type;
4695   if (SAVE_ERROR_CATCH(
4696           ctx, array->array_->has_metadata_key(key, &type, &has_the_key)))
4697     return TILEDB_ERR;
4698 
4699   *has_key = has_the_key ? 1 : 0;
4700   if (has_the_key) {
4701     *value_type = static_cast<tiledb_datatype_t>(type);
4702   }
4703   return TILEDB_OK;
4704 }
4705 
tiledb_array_consolidate_metadata(tiledb_ctx_t * ctx,const char * array_uri,tiledb_config_t * config)4706 int32_t tiledb_array_consolidate_metadata(
4707     tiledb_ctx_t* ctx, const char* array_uri, tiledb_config_t* config) {
4708   // Sanity checks
4709   if (sanity_check(ctx) == TILEDB_ERR)
4710     return TILEDB_ERR;
4711 
4712   if (SAVE_ERROR_CATCH(
4713           ctx,
4714           ctx->ctx_->storage_manager()->array_metadata_consolidate(
4715               array_uri,
4716               static_cast<tiledb::sm::EncryptionType>(TILEDB_NO_ENCRYPTION),
4717               nullptr,
4718               0,
4719               (config == nullptr) ? &ctx->ctx_->storage_manager()->config() :
4720                                     config->config_)))
4721     return TILEDB_ERR;
4722 
4723   return TILEDB_OK;
4724 }
4725 
tiledb_array_consolidate_metadata_with_key(tiledb_ctx_t * ctx,const char * array_uri,tiledb_encryption_type_t encryption_type,const void * encryption_key,uint32_t key_length,tiledb_config_t * config)4726 int32_t tiledb_array_consolidate_metadata_with_key(
4727     tiledb_ctx_t* ctx,
4728     const char* array_uri,
4729     tiledb_encryption_type_t encryption_type,
4730     const void* encryption_key,
4731     uint32_t key_length,
4732     tiledb_config_t* config) {
4733   // Sanity checks
4734   if (sanity_check(ctx) == TILEDB_ERR)
4735     return TILEDB_ERR;
4736 
4737   if (SAVE_ERROR_CATCH(
4738           ctx,
4739           ctx->ctx_->storage_manager()->array_metadata_consolidate(
4740               array_uri,
4741               static_cast<tiledb::sm::EncryptionType>(encryption_type),
4742               encryption_key,
4743               key_length,
4744               (config == nullptr) ? &ctx->ctx_->storage_manager()->config() :
4745                                     config->config_)))
4746     return TILEDB_ERR;
4747 
4748   return TILEDB_OK;
4749 }
4750 
tiledb_array_evolve(tiledb_ctx_t * ctx,const char * array_uri,tiledb_array_schema_evolution_t * array_schema_evolution)4751 int32_t tiledb_array_evolve(
4752     tiledb_ctx_t* ctx,
4753     const char* array_uri,
4754     tiledb_array_schema_evolution_t* array_schema_evolution) {
4755   // Sanity Checks
4756   if (sanity_check(ctx) == TILEDB_ERR ||
4757       sanity_check(ctx, array_schema_evolution) == TILEDB_ERR)
4758     return TILEDB_ERR;
4759 
4760   // Check array name
4761   tiledb::sm::URI uri(array_uri);
4762   if (uri.is_invalid()) {
4763     auto st = Status::Error("Failed to create array; Invalid array URI");
4764     LOG_STATUS(st);
4765     save_error(ctx, st);
4766     return TILEDB_ERR;
4767   }
4768 
4769   // Create key
4770   tiledb::sm::EncryptionKey key;
4771   if (SAVE_ERROR_CATCH(
4772           ctx,
4773           key.set_key(
4774               static_cast<tiledb::sm::EncryptionType>(TILEDB_NO_ENCRYPTION),
4775               nullptr,
4776               0)))
4777     return TILEDB_ERR;
4778 
4779   if (SAVE_ERROR_CATCH(
4780           ctx,
4781           ctx->ctx_->storage_manager()->array_evolve_schema(
4782               uri, array_schema_evolution->array_schema_evolution_, key)))
4783     return TILEDB_ERR;
4784 
4785   // Success
4786   return TILEDB_OK;
4787 }
4788 
tiledb_array_upgrade_version(tiledb_ctx_t * ctx,const char * array_uri,tiledb_config_t * config)4789 int32_t tiledb_array_upgrade_version(
4790     tiledb_ctx_t* ctx, const char* array_uri, tiledb_config_t* config) {
4791   // Sanity Checks
4792   if (sanity_check(ctx) == TILEDB_ERR)
4793     return TILEDB_ERR;
4794 
4795   // Check array name
4796   tiledb::sm::URI uri(array_uri);
4797   if (uri.is_invalid()) {
4798     auto st = Status::Error("Failed to find the array; Invalid array URI");
4799     LOG_STATUS(st);
4800     save_error(ctx, st);
4801     return TILEDB_ERR;
4802   }
4803 
4804   if (SAVE_ERROR_CATCH(
4805           ctx,
4806           ctx->ctx_->storage_manager()->array_upgrade_version(
4807               uri,
4808               (config == nullptr) ? &ctx->ctx_->storage_manager()->config() :
4809                                     config->config_)))
4810     return TILEDB_ERR;
4811 
4812   // Success
4813   return TILEDB_OK;
4814 }
4815 
4816 /* ****************************** */
4817 /*         OBJECT MANAGEMENT      */
4818 /* ****************************** */
4819 
tiledb_object_type(tiledb_ctx_t * ctx,const char * path,tiledb_object_t * type)4820 int32_t tiledb_object_type(
4821     tiledb_ctx_t* ctx, const char* path, tiledb_object_t* type) {
4822   if (sanity_check(ctx) == TILEDB_ERR)
4823     return TILEDB_ERR;
4824 
4825   auto uri = tiledb::sm::URI(path);
4826   tiledb::sm::ObjectType object_type;
4827   if (SAVE_ERROR_CATCH(
4828           ctx, ctx->ctx_->storage_manager()->object_type(uri, &object_type)))
4829     return TILEDB_ERR;
4830 
4831   *type = static_cast<tiledb_object_t>(object_type);
4832   return TILEDB_OK;
4833 }
4834 
tiledb_object_remove(tiledb_ctx_t * ctx,const char * path)4835 int32_t tiledb_object_remove(tiledb_ctx_t* ctx, const char* path) {
4836   if (sanity_check(ctx) == TILEDB_ERR)
4837     return TILEDB_ERR;
4838   if (SAVE_ERROR_CATCH(ctx, ctx->ctx_->storage_manager()->object_remove(path)))
4839     return TILEDB_ERR;
4840   return TILEDB_OK;
4841 }
4842 
tiledb_object_move(tiledb_ctx_t * ctx,const char * old_path,const char * new_path)4843 int32_t tiledb_object_move(
4844     tiledb_ctx_t* ctx, const char* old_path, const char* new_path) {
4845   if (sanity_check(ctx) == TILEDB_ERR)
4846     return TILEDB_ERR;
4847   if (SAVE_ERROR_CATCH(
4848           ctx, ctx->ctx_->storage_manager()->object_move(old_path, new_path)))
4849     return TILEDB_ERR;
4850   return TILEDB_OK;
4851 }
4852 
tiledb_object_walk(tiledb_ctx_t * ctx,const char * path,tiledb_walk_order_t order,int32_t (* callback)(const char *,tiledb_object_t,void *),void * data)4853 int32_t tiledb_object_walk(
4854     tiledb_ctx_t* ctx,
4855     const char* path,
4856     tiledb_walk_order_t order,
4857     int32_t (*callback)(const char*, tiledb_object_t, void*),
4858     void* data) {
4859   // Sanity checks
4860   if (sanity_check(ctx) == TILEDB_ERR)
4861     return TILEDB_ERR;
4862   if (callback == nullptr) {
4863     auto st = Status::Error("Cannot initiate walk; Invalid callback function");
4864     LOG_STATUS(st);
4865     save_error(ctx, st);
4866     return TILEDB_ERR;
4867   }
4868 
4869   // Create an object iterator
4870   tiledb::sm::StorageManager::ObjectIter* obj_iter;
4871   if (SAVE_ERROR_CATCH(
4872           ctx,
4873           ctx->ctx_->storage_manager()->object_iter_begin(
4874               &obj_iter, path, static_cast<tiledb::sm::WalkOrder>(order))))
4875     return TILEDB_ERR;
4876 
4877   // For as long as there is another object and the callback indicates to
4878   // continue, walk over the TileDB objects in the path
4879   const char* obj_name;
4880   tiledb::sm::ObjectType obj_type;
4881   bool has_next;
4882   int32_t rc = 0;
4883   do {
4884     if (SAVE_ERROR_CATCH(
4885             ctx,
4886             ctx->ctx_->storage_manager()->object_iter_next(
4887                 obj_iter, &obj_name, &obj_type, &has_next))) {
4888       ctx->ctx_->storage_manager()->object_iter_free(obj_iter);
4889       return TILEDB_ERR;
4890     }
4891     if (!has_next)
4892       break;
4893     rc = callback(obj_name, tiledb_object_t(obj_type), data);
4894   } while (rc == 1);
4895 
4896   // Clean up
4897   ctx->ctx_->storage_manager()->object_iter_free(obj_iter);
4898 
4899   if (rc == -1)
4900     return TILEDB_ERR;
4901   return TILEDB_OK;
4902 }
4903 
tiledb_object_ls(tiledb_ctx_t * ctx,const char * path,int32_t (* callback)(const char *,tiledb_object_t,void *),void * data)4904 int32_t tiledb_object_ls(
4905     tiledb_ctx_t* ctx,
4906     const char* path,
4907     int32_t (*callback)(const char*, tiledb_object_t, void*),
4908     void* data) {
4909   // Sanity checks
4910   if (sanity_check(ctx) == TILEDB_ERR)
4911     return TILEDB_ERR;
4912   if (callback == nullptr) {
4913     auto st =
4914         Status::Error("Cannot initiate object ls; Invalid callback function");
4915     LOG_STATUS(st);
4916     save_error(ctx, st);
4917     return TILEDB_ERR;
4918   }
4919 
4920   // Create an object iterator
4921   tiledb::sm::StorageManager::ObjectIter* obj_iter;
4922   if (SAVE_ERROR_CATCH(
4923           ctx,
4924           ctx->ctx_->storage_manager()->object_iter_begin(&obj_iter, path)))
4925     return TILEDB_ERR;
4926 
4927   // For as long as there is another object and the callback indicates to
4928   // continue, walk over the TileDB objects in the path
4929   const char* obj_name;
4930   tiledb::sm::ObjectType obj_type;
4931   bool has_next;
4932   int32_t rc = 0;
4933   do {
4934     if (SAVE_ERROR_CATCH(
4935             ctx,
4936             ctx->ctx_->storage_manager()->object_iter_next(
4937                 obj_iter, &obj_name, &obj_type, &has_next))) {
4938       ctx->ctx_->storage_manager()->object_iter_free(obj_iter);
4939       return TILEDB_ERR;
4940     }
4941     if (!has_next)
4942       break;
4943     rc = callback(obj_name, tiledb_object_t(obj_type), data);
4944   } while (rc == 1);
4945 
4946   // Clean up
4947   ctx->ctx_->storage_manager()->object_iter_free(obj_iter);
4948 
4949   if (rc == -1)
4950     return TILEDB_ERR;
4951   return TILEDB_OK;
4952 }
4953 
4954 /* ****************************** */
4955 /*        VIRTUAL FILESYSTEM      */
4956 /* ****************************** */
4957 
tiledb_vfs_alloc(tiledb_ctx_t * ctx,tiledb_config_t * config,tiledb_vfs_t ** vfs)4958 int32_t tiledb_vfs_alloc(
4959     tiledb_ctx_t* ctx, tiledb_config_t* config, tiledb_vfs_t** vfs) {
4960   if (sanity_check(ctx) == TILEDB_ERR)
4961     return TILEDB_ERR;
4962 
4963   if (config != nullptr && config->config_ == nullptr) {
4964     auto st = Status::Error("Cannot create VFS; Invalid config");
4965     LOG_STATUS(st);
4966     save_error(ctx, st);
4967     return TILEDB_ERR;
4968   }
4969 
4970   // Create VFS struct
4971   *vfs = new (std::nothrow) tiledb_vfs_t;
4972   if (*vfs == nullptr) {
4973     auto st =
4974         Status::Error("Failed to allocate TileDB virtual filesystem object");
4975     LOG_STATUS(st);
4976     save_error(ctx, st);
4977     return TILEDB_OOM;
4978   }
4979 
4980   // Create VFS object
4981   (*vfs)->vfs_ = new (std::nothrow) tiledb::sm::VFS();
4982   if ((*vfs)->vfs_ == nullptr) {
4983     auto st =
4984         Status::Error("Failed to allocate TileDB virtual filesystem object");
4985     LOG_STATUS(st);
4986     save_error(ctx, st);
4987     delete *vfs;
4988     *vfs = nullptr;
4989     return TILEDB_OOM;
4990   }
4991 
4992   // Initialize VFS object
4993   auto stats = ctx->ctx_->storage_manager()->stats();
4994   auto compute_tp = ctx->ctx_->storage_manager()->compute_tp();
4995   auto io_tp = ctx->ctx_->storage_manager()->io_tp();
4996   auto vfs_config = config ? config->config_ : nullptr;
4997   auto ctx_config = ctx->ctx_->storage_manager()->config();
4998   if (SAVE_ERROR_CATCH(
4999           ctx,
5000           (*vfs)->vfs_->init(
5001               stats, compute_tp, io_tp, &ctx_config, vfs_config))) {
5002     delete (*vfs)->vfs_;
5003     delete vfs;
5004     return TILEDB_ERR;
5005   }
5006 
5007   // Success
5008   return TILEDB_OK;
5009 }
5010 
tiledb_vfs_free(tiledb_vfs_t ** vfs)5011 void tiledb_vfs_free(tiledb_vfs_t** vfs) {
5012   const auto st = (*vfs)->vfs_->terminate();
5013   if (!st.ok()) {
5014     LOG_STATUS(st);
5015   }
5016 
5017   if (vfs != nullptr && *vfs != nullptr) {
5018     delete (*vfs)->vfs_;
5019     delete *vfs;
5020     *vfs = nullptr;
5021   }
5022 }
5023 
tiledb_vfs_get_config(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,tiledb_config_t ** config)5024 int32_t tiledb_vfs_get_config(
5025     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, tiledb_config_t** config) {
5026   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5027     return TILEDB_ERR;
5028 
5029   // Create a new config struct
5030   *config = new (std::nothrow) tiledb_config_t;
5031   if (*config == nullptr)
5032     return TILEDB_OOM;
5033 
5034   // Create a new config
5035   (*config)->config_ = new (std::nothrow) tiledb::sm::Config();
5036   if ((*config)->config_ == nullptr) {
5037     delete (*config);
5038     *config = nullptr;
5039     return TILEDB_OOM;
5040   }
5041 
5042   *((*config)->config_) = vfs->vfs_->config();
5043 
5044   // Success
5045   return TILEDB_OK;
5046 }
5047 
tiledb_vfs_create_bucket(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri)5048 int32_t tiledb_vfs_create_bucket(
5049     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, const char* uri) {
5050   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5051     return TILEDB_ERR;
5052 
5053   if (SAVE_ERROR_CATCH(ctx, vfs->vfs_->create_bucket(tiledb::sm::URI(uri))))
5054     return TILEDB_ERR;
5055 
5056   return TILEDB_OK;
5057 }
5058 
tiledb_vfs_remove_bucket(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri)5059 int32_t tiledb_vfs_remove_bucket(
5060     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, const char* uri) {
5061   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5062     return TILEDB_ERR;
5063 
5064   if (SAVE_ERROR_CATCH(ctx, vfs->vfs_->remove_bucket(tiledb::sm::URI(uri))))
5065     return TILEDB_ERR;
5066 
5067   return TILEDB_OK;
5068 }
5069 
tiledb_vfs_empty_bucket(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri)5070 int32_t tiledb_vfs_empty_bucket(
5071     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, const char* uri) {
5072   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5073     return TILEDB_ERR;
5074 
5075   if (SAVE_ERROR_CATCH(ctx, vfs->vfs_->empty_bucket(tiledb::sm::URI(uri))))
5076     return TILEDB_ERR;
5077 
5078   return TILEDB_OK;
5079 }
5080 
tiledb_vfs_is_empty_bucket(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri,int32_t * is_empty)5081 int32_t tiledb_vfs_is_empty_bucket(
5082     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, const char* uri, int32_t* is_empty) {
5083   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5084     return TILEDB_ERR;
5085 
5086   bool b;
5087   if (SAVE_ERROR_CATCH(
5088           ctx, vfs->vfs_->is_empty_bucket(tiledb::sm::URI(uri), &b)))
5089     return TILEDB_ERR;
5090   *is_empty = (int32_t)b;
5091 
5092   return TILEDB_OK;
5093 }
5094 
tiledb_vfs_is_bucket(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri,int32_t * is_bucket)5095 int32_t tiledb_vfs_is_bucket(
5096     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, const char* uri, int32_t* is_bucket) {
5097   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5098     return TILEDB_ERR;
5099 
5100   bool exists;
5101   if (SAVE_ERROR_CATCH(
5102           ctx, vfs->vfs_->is_bucket(tiledb::sm::URI(uri), &exists)))
5103     return TILEDB_ERR;
5104 
5105   *is_bucket = (int32_t)exists;
5106 
5107   return TILEDB_OK;
5108 }
5109 
tiledb_vfs_create_dir(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri)5110 int32_t tiledb_vfs_create_dir(
5111     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, const char* uri) {
5112   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5113     return TILEDB_ERR;
5114 
5115   if (SAVE_ERROR_CATCH(ctx, vfs->vfs_->create_dir(tiledb::sm::URI(uri))))
5116     return TILEDB_ERR;
5117 
5118   return TILEDB_OK;
5119 }
5120 
tiledb_vfs_is_dir(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri,int32_t * is_dir)5121 int32_t tiledb_vfs_is_dir(
5122     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, const char* uri, int32_t* is_dir) {
5123   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5124     return TILEDB_ERR;
5125 
5126   bool exists;
5127   if (SAVE_ERROR_CATCH(ctx, vfs->vfs_->is_dir(tiledb::sm::URI(uri), &exists)))
5128     return TILEDB_ERR;
5129   *is_dir = (int32_t)exists;
5130 
5131   return TILEDB_OK;
5132 }
5133 
tiledb_vfs_remove_dir(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri)5134 int32_t tiledb_vfs_remove_dir(
5135     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, const char* uri) {
5136   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5137     return TILEDB_ERR;
5138 
5139   if (SAVE_ERROR_CATCH(ctx, vfs->vfs_->remove_dir(tiledb::sm::URI(uri))))
5140     return TILEDB_ERR;
5141 
5142   return TILEDB_OK;
5143 }
5144 
tiledb_vfs_is_file(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri,int32_t * is_file)5145 int32_t tiledb_vfs_is_file(
5146     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, const char* uri, int32_t* is_file) {
5147   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5148     return TILEDB_ERR;
5149 
5150   bool exists;
5151   if (SAVE_ERROR_CATCH(ctx, vfs->vfs_->is_file(tiledb::sm::URI(uri), &exists)))
5152     return TILEDB_ERR;
5153   *is_file = (int32_t)exists;
5154 
5155   return TILEDB_OK;
5156 }
5157 
tiledb_vfs_remove_file(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri)5158 int32_t tiledb_vfs_remove_file(
5159     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, const char* uri) {
5160   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5161     return TILEDB_ERR;
5162 
5163   if (SAVE_ERROR_CATCH(ctx, vfs->vfs_->remove_file(tiledb::sm::URI(uri))))
5164     return TILEDB_ERR;
5165 
5166   return TILEDB_OK;
5167 }
5168 
tiledb_vfs_dir_size(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri,uint64_t * size)5169 int32_t tiledb_vfs_dir_size(
5170     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, const char* uri, uint64_t* size) {
5171   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5172     return TILEDB_ERR;
5173 
5174   if (SAVE_ERROR_CATCH(ctx, vfs->vfs_->dir_size(tiledb::sm::URI(uri), size)))
5175     return TILEDB_ERR;
5176 
5177   return TILEDB_OK;
5178 }
5179 
tiledb_vfs_file_size(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri,uint64_t * size)5180 int32_t tiledb_vfs_file_size(
5181     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, const char* uri, uint64_t* size) {
5182   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5183     return TILEDB_ERR;
5184 
5185   if (SAVE_ERROR_CATCH(ctx, vfs->vfs_->file_size(tiledb::sm::URI(uri), size)))
5186     return TILEDB_ERR;
5187 
5188   return TILEDB_OK;
5189 }
5190 
tiledb_vfs_move_file(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * old_uri,const char * new_uri)5191 int32_t tiledb_vfs_move_file(
5192     tiledb_ctx_t* ctx,
5193     tiledb_vfs_t* vfs,
5194     const char* old_uri,
5195     const char* new_uri) {
5196   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5197     return TILEDB_ERR;
5198 
5199   if (SAVE_ERROR_CATCH(
5200           ctx,
5201           vfs->vfs_->move_file(
5202               tiledb::sm::URI(old_uri), tiledb::sm::URI(new_uri))))
5203     return TILEDB_ERR;
5204 
5205   return TILEDB_OK;
5206 }
5207 
tiledb_vfs_move_dir(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * old_uri,const char * new_uri)5208 int32_t tiledb_vfs_move_dir(
5209     tiledb_ctx_t* ctx,
5210     tiledb_vfs_t* vfs,
5211     const char* old_uri,
5212     const char* new_uri) {
5213   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5214     return TILEDB_ERR;
5215 
5216   if (SAVE_ERROR_CATCH(
5217           ctx,
5218           vfs->vfs_->move_dir(
5219               tiledb::sm::URI(old_uri), tiledb::sm::URI(new_uri))))
5220     return TILEDB_ERR;
5221 
5222   return TILEDB_OK;
5223 }
5224 
tiledb_vfs_copy_file(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * old_uri,const char * new_uri)5225 int32_t tiledb_vfs_copy_file(
5226     tiledb_ctx_t* ctx,
5227     tiledb_vfs_t* vfs,
5228     const char* old_uri,
5229     const char* new_uri) {
5230   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5231     return TILEDB_ERR;
5232 
5233   if (SAVE_ERROR_CATCH(
5234           ctx,
5235           vfs->vfs_->copy_file(
5236               tiledb::sm::URI(old_uri), tiledb::sm::URI(new_uri))))
5237     return TILEDB_ERR;
5238 
5239   return TILEDB_OK;
5240 }
5241 
tiledb_vfs_copy_dir(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * old_uri,const char * new_uri)5242 int32_t tiledb_vfs_copy_dir(
5243     tiledb_ctx_t* ctx,
5244     tiledb_vfs_t* vfs,
5245     const char* old_uri,
5246     const char* new_uri) {
5247   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5248     return TILEDB_ERR;
5249 
5250   if (SAVE_ERROR_CATCH(
5251           ctx,
5252           vfs->vfs_->copy_dir(
5253               tiledb::sm::URI(old_uri), tiledb::sm::URI(new_uri))))
5254     return TILEDB_ERR;
5255 
5256   return TILEDB_OK;
5257 }
5258 
tiledb_vfs_open(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri,tiledb_vfs_mode_t mode,tiledb_vfs_fh_t ** fh)5259 int32_t tiledb_vfs_open(
5260     tiledb_ctx_t* ctx,
5261     tiledb_vfs_t* vfs,
5262     const char* uri,
5263     tiledb_vfs_mode_t mode,
5264     tiledb_vfs_fh_t** fh) {
5265   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5266     return TILEDB_ERR;
5267 
5268   *fh = new (std::nothrow) tiledb_vfs_fh_t;
5269   if (*fh == nullptr) {
5270     auto st = Status::Error(
5271         "Failed to create TileDB VFS file handle; Memory allocation error");
5272     LOG_STATUS(st);
5273     save_error(ctx, st);
5274     return TILEDB_OOM;
5275   }
5276 
5277   // Check URI
5278   auto fh_uri = tiledb::sm::URI(uri);
5279   if (fh_uri.is_invalid()) {
5280     auto st =
5281         Status::Error("Failed to create TileDB VFS file handle; Invalid URI");
5282     delete *fh;
5283     *fh = nullptr;
5284     LOG_STATUS(st);
5285     save_error(ctx, st);
5286     return TILEDB_ERR;
5287   }
5288   auto vfs_mode = static_cast<tiledb::sm::VFSMode>(mode);
5289 
5290   // Create VFS file handle
5291   (*fh)->vfs_fh_ =
5292       new (std::nothrow) tiledb::sm::VFSFileHandle(fh_uri, vfs->vfs_, vfs_mode);
5293   if ((*fh)->vfs_fh_ == nullptr) {
5294     auto st = Status::Error(
5295         "Failed to create TileDB VFS file handle; Memory allocation error");
5296     LOG_STATUS(st);
5297     save_error(ctx, st);
5298     delete (*fh);
5299     *fh = nullptr;
5300     return TILEDB_OOM;
5301   }
5302 
5303   // Open VFS file
5304   if (SAVE_ERROR_CATCH(ctx, (*fh)->vfs_fh_->open())) {
5305     delete (*fh)->vfs_fh_;
5306     delete (*fh);
5307     *fh = nullptr;
5308     return TILEDB_ERR;
5309   }
5310 
5311   return TILEDB_OK;
5312 }
5313 
tiledb_vfs_close(tiledb_ctx_t * ctx,tiledb_vfs_fh_t * fh)5314 int32_t tiledb_vfs_close(tiledb_ctx_t* ctx, tiledb_vfs_fh_t* fh) {
5315   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, fh) == TILEDB_ERR)
5316     return TILEDB_ERR;
5317 
5318   if (SAVE_ERROR_CATCH(ctx, fh->vfs_fh_->close()))
5319     return TILEDB_ERR;
5320 
5321   return TILEDB_OK;
5322 }
5323 
tiledb_vfs_read(tiledb_ctx_t * ctx,tiledb_vfs_fh_t * fh,uint64_t offset,void * buffer,uint64_t nbytes)5324 int32_t tiledb_vfs_read(
5325     tiledb_ctx_t* ctx,
5326     tiledb_vfs_fh_t* fh,
5327     uint64_t offset,
5328     void* buffer,
5329     uint64_t nbytes) {
5330   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, fh) == TILEDB_ERR)
5331     return TILEDB_ERR;
5332 
5333   if (SAVE_ERROR_CATCH(ctx, fh->vfs_fh_->read(offset, buffer, nbytes)))
5334     return TILEDB_ERR;
5335 
5336   return TILEDB_OK;
5337 }
5338 
tiledb_vfs_write(tiledb_ctx_t * ctx,tiledb_vfs_fh_t * fh,const void * buffer,uint64_t nbytes)5339 int32_t tiledb_vfs_write(
5340     tiledb_ctx_t* ctx,
5341     tiledb_vfs_fh_t* fh,
5342     const void* buffer,
5343     uint64_t nbytes) {
5344   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, fh) == TILEDB_ERR)
5345     return TILEDB_ERR;
5346 
5347   if (SAVE_ERROR_CATCH(ctx, fh->vfs_fh_->write(buffer, nbytes)))
5348     return TILEDB_ERR;
5349 
5350   return TILEDB_OK;
5351 }
5352 
tiledb_vfs_sync(tiledb_ctx_t * ctx,tiledb_vfs_fh_t * fh)5353 int32_t tiledb_vfs_sync(tiledb_ctx_t* ctx, tiledb_vfs_fh_t* fh) {
5354   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, fh) == TILEDB_ERR)
5355     return TILEDB_ERR;
5356 
5357   if (SAVE_ERROR_CATCH(ctx, fh->vfs_fh_->sync()))
5358     return TILEDB_ERR;
5359 
5360   return TILEDB_OK;
5361 }
5362 
tiledb_vfs_ls(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * path,int32_t (* callback)(const char *,void *),void * data)5363 int32_t tiledb_vfs_ls(
5364     tiledb_ctx_t* ctx,
5365     tiledb_vfs_t* vfs,
5366     const char* path,
5367     int32_t (*callback)(const char*, void*),
5368     void* data) {
5369   // Sanity checks
5370   if (sanity_check(ctx) == TILEDB_ERR)
5371     return TILEDB_ERR;
5372   if (callback == nullptr) {
5373     auto st =
5374         Status::Error("Cannot initiate VFS ls; Invalid callback function");
5375     LOG_STATUS(st);
5376     save_error(ctx, st);
5377     return TILEDB_ERR;
5378   }
5379 
5380   // Get children
5381   std::vector<tiledb::sm::URI> children;
5382   auto st = vfs->vfs_->ls(tiledb::sm::URI(path), &children);
5383 
5384   if (!st.ok())
5385     return TILEDB_ERR;
5386 
5387   // Apply the callback to every child
5388   int rc = 1;
5389   for (const auto& uri : children) {
5390     rc = callback(uri.to_string().c_str(), data);
5391     if (rc != 1)
5392       break;
5393   }
5394 
5395   if (rc == -1)
5396     return TILEDB_ERR;
5397   return TILEDB_OK;
5398 }
5399 
tiledb_vfs_fh_free(tiledb_vfs_fh_t ** fh)5400 void tiledb_vfs_fh_free(tiledb_vfs_fh_t** fh) {
5401   if (fh != nullptr && *fh != nullptr) {
5402     delete (*fh)->vfs_fh_;
5403     delete *fh;
5404     *fh = nullptr;
5405   }
5406 }
5407 
tiledb_vfs_fh_is_closed(tiledb_ctx_t * ctx,tiledb_vfs_fh_t * fh,int32_t * is_closed)5408 int32_t tiledb_vfs_fh_is_closed(
5409     tiledb_ctx_t* ctx, tiledb_vfs_fh_t* fh, int32_t* is_closed) {
5410   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, fh) == TILEDB_ERR)
5411     return TILEDB_ERR;
5412 
5413   *is_closed = !fh->vfs_fh_->is_open();
5414 
5415   return TILEDB_OK;
5416 }
5417 
tiledb_vfs_touch(tiledb_ctx_t * ctx,tiledb_vfs_t * vfs,const char * uri)5418 int32_t tiledb_vfs_touch(
5419     tiledb_ctx_t* ctx, tiledb_vfs_t* vfs, const char* uri) {
5420   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, vfs) == TILEDB_ERR)
5421     return TILEDB_ERR;
5422 
5423   if (SAVE_ERROR_CATCH(ctx, vfs->vfs_->touch(tiledb::sm::URI(uri))))
5424     return TILEDB_ERR;
5425 
5426   return TILEDB_OK;
5427 }
5428 
5429 /* ****************************** */
5430 /*              URI               */
5431 /* ****************************** */
5432 
tiledb_uri_to_path(tiledb_ctx_t * ctx,const char * uri,char * path_out,uint32_t * path_length)5433 int32_t tiledb_uri_to_path(
5434     tiledb_ctx_t* ctx, const char* uri, char* path_out, uint32_t* path_length) {
5435   if (sanity_check(ctx) == TILEDB_ERR || uri == nullptr ||
5436       path_out == nullptr || path_length == nullptr)
5437     return TILEDB_ERR;
5438 
5439   std::string path = tiledb::sm::URI::to_path(uri);
5440   if (path.empty() || path.length() + 1 > *path_length) {
5441     *path_length = 0;
5442     return TILEDB_ERR;
5443   } else {
5444     *path_length = static_cast<uint32_t>(path.length());
5445     path.copy(path_out, path.length());
5446     path_out[path.length()] = '\0';
5447     return TILEDB_OK;
5448   }
5449 }
5450 
5451 /* ****************************** */
5452 /*             Stats              */
5453 /* ****************************** */
5454 
tiledb_stats_enable()5455 int32_t tiledb_stats_enable() {
5456   tiledb::sm::stats::all_stats.set_enabled(true);
5457   return TILEDB_OK;
5458 }
5459 
tiledb_stats_disable()5460 int32_t tiledb_stats_disable() {
5461   tiledb::sm::stats::all_stats.set_enabled(false);
5462   return TILEDB_OK;
5463 }
5464 
tiledb_stats_reset()5465 int32_t tiledb_stats_reset() {
5466   tiledb::sm::stats::all_stats.reset();
5467   return TILEDB_OK;
5468 }
5469 
tiledb_stats_dump(FILE * out)5470 int32_t tiledb_stats_dump(FILE* out) {
5471   tiledb::sm::stats::all_stats.dump(out);
5472   return TILEDB_OK;
5473 }
5474 
tiledb_stats_dump_str(char ** out)5475 int32_t tiledb_stats_dump_str(char** out) {
5476   if (out == nullptr)
5477     return TILEDB_ERR;
5478 
5479   std::string str;
5480   tiledb::sm::stats::all_stats.dump(&str);
5481 
5482   *out = static_cast<char*>(std::malloc(str.size() + 1));
5483   if (*out == nullptr)
5484     return TILEDB_ERR;
5485 
5486   std::memcpy(*out, str.data(), str.size());
5487   (*out)[str.size()] = '\0';
5488 
5489   return TILEDB_OK;
5490 }
5491 
tiledb_stats_raw_dump(FILE * out)5492 int32_t tiledb_stats_raw_dump(FILE* out) {
5493   tiledb::sm::stats::all_stats.raw_dump(out);
5494   return TILEDB_OK;
5495 }
5496 
tiledb_stats_raw_dump_str(char ** out)5497 int32_t tiledb_stats_raw_dump_str(char** out) {
5498   if (out == nullptr)
5499     return TILEDB_ERR;
5500 
5501   std::string str;
5502   tiledb::sm::stats::all_stats.raw_dump(&str);
5503 
5504   *out = static_cast<char*>(std::malloc(str.size() + 1));
5505   if (*out == nullptr)
5506     return TILEDB_ERR;
5507 
5508   std::memcpy(*out, str.data(), str.size());
5509   (*out)[str.size()] = '\0';
5510 
5511   return TILEDB_OK;
5512 }
5513 
tiledb_stats_free_str(char ** out)5514 int32_t tiledb_stats_free_str(char** out) {
5515   if (out != nullptr) {
5516     std::free(*out);
5517     *out = nullptr;
5518   }
5519   return TILEDB_OK;
5520 }
5521 
5522 /* ****************************** */
5523 /*          Heap Profiler         */
5524 /* ****************************** */
5525 
tiledb_heap_profiler_enable(const char * const file_name_prefix,const uint64_t dump_interval_ms,const uint64_t dump_interval_bytes,const uint64_t dump_threshold_bytes)5526 int32_t tiledb_heap_profiler_enable(
5527     const char* const file_name_prefix,
5528     const uint64_t dump_interval_ms,
5529     const uint64_t dump_interval_bytes,
5530     const uint64_t dump_threshold_bytes) {
5531   tiledb::common::heap_profiler.enable(
5532       file_name_prefix ? std::string(file_name_prefix) : "",
5533       dump_interval_ms,
5534       dump_interval_bytes,
5535       dump_threshold_bytes);
5536   return TILEDB_OK;
5537 }
5538 
5539 /* ****************************** */
5540 /*          Serialization         */
5541 /* ****************************** */
5542 
tiledb_serialize_array_schema(tiledb_ctx_t * ctx,const tiledb_array_schema_t * array_schema,tiledb_serialization_type_t serialize_type,int32_t client_side,tiledb_buffer_t ** buffer)5543 int32_t tiledb_serialize_array_schema(
5544     tiledb_ctx_t* ctx,
5545     const tiledb_array_schema_t* array_schema,
5546     tiledb_serialization_type_t serialize_type,
5547     int32_t client_side,
5548     tiledb_buffer_t** buffer) {
5549   // Sanity check
5550   if (sanity_check(ctx) == TILEDB_ERR ||
5551       sanity_check(ctx, array_schema) == TILEDB_ERR)
5552     return TILEDB_ERR;
5553 
5554   // Create buffer
5555   if (tiledb_buffer_alloc(ctx, buffer) != TILEDB_OK ||
5556       sanity_check(ctx, *buffer) == TILEDB_ERR)
5557     return TILEDB_ERR;
5558 
5559   if (SAVE_ERROR_CATCH(
5560           ctx,
5561           tiledb::sm::serialization::array_schema_serialize(
5562               array_schema->array_schema_,
5563               (tiledb::sm::SerializationType)serialize_type,
5564               (*buffer)->buffer_,
5565               client_side))) {
5566     tiledb_buffer_free(buffer);
5567     return TILEDB_ERR;
5568   }
5569 
5570   return TILEDB_OK;
5571 }
5572 
tiledb_deserialize_array_schema(tiledb_ctx_t * ctx,const tiledb_buffer_t * buffer,tiledb_serialization_type_t serialize_type,int32_t client_side,tiledb_array_schema_t ** array_schema)5573 int32_t tiledb_deserialize_array_schema(
5574     tiledb_ctx_t* ctx,
5575     const tiledb_buffer_t* buffer,
5576     tiledb_serialization_type_t serialize_type,
5577     int32_t client_side,
5578     tiledb_array_schema_t** array_schema) {
5579   // Currently unused:
5580   (void)client_side;
5581 
5582   // Sanity check
5583   if (sanity_check(ctx) == TILEDB_ERR ||
5584       sanity_check(ctx, buffer) == TILEDB_ERR)
5585     return TILEDB_ERR;
5586 
5587   // Create array schema struct
5588   *array_schema = new (std::nothrow) tiledb_array_schema_t;
5589   if (*array_schema == nullptr) {
5590     auto st = Status::Error("Failed to allocate TileDB array schema object");
5591     LOG_STATUS(st);
5592     save_error(ctx, st);
5593     return TILEDB_OOM;
5594   }
5595 
5596   if (SAVE_ERROR_CATCH(
5597           ctx,
5598           tiledb::sm::serialization::array_schema_deserialize(
5599               &((*array_schema)->array_schema_),
5600               (tiledb::sm::SerializationType)serialize_type,
5601               *buffer->buffer_))) {
5602     delete *array_schema;
5603     *array_schema = nullptr;
5604     return TILEDB_ERR;
5605   }
5606 
5607   return TILEDB_OK;
5608 }
5609 
tiledb_serialize_array_schema_evolution(tiledb_ctx_t * ctx,const tiledb_array_schema_evolution_t * array_schema_evolution,tiledb_serialization_type_t serialize_type,int32_t client_side,tiledb_buffer_t ** buffer)5610 int32_t tiledb_serialize_array_schema_evolution(
5611     tiledb_ctx_t* ctx,
5612     const tiledb_array_schema_evolution_t* array_schema_evolution,
5613     tiledb_serialization_type_t serialize_type,
5614     int32_t client_side,
5615     tiledb_buffer_t** buffer) {
5616   // Sanity check
5617   if (sanity_check(ctx) == TILEDB_ERR ||
5618       sanity_check(ctx, array_schema_evolution) == TILEDB_ERR)
5619     return TILEDB_ERR;
5620 
5621   // Create buffer
5622   if (tiledb_buffer_alloc(ctx, buffer) != TILEDB_OK ||
5623       sanity_check(ctx, *buffer) == TILEDB_ERR)
5624     return TILEDB_ERR;
5625 
5626   if (SAVE_ERROR_CATCH(
5627           ctx,
5628           tiledb::sm::serialization::array_schema_evolution_serialize(
5629               array_schema_evolution->array_schema_evolution_,
5630               (tiledb::sm::SerializationType)serialize_type,
5631               (*buffer)->buffer_,
5632               client_side))) {
5633     tiledb_buffer_free(buffer);
5634     return TILEDB_ERR;
5635   }
5636 
5637   return TILEDB_OK;
5638 }
5639 
tiledb_deserialize_array_schema_evolution(tiledb_ctx_t * ctx,const tiledb_buffer_t * buffer,tiledb_serialization_type_t serialize_type,int32_t client_side,tiledb_array_schema_evolution_t ** array_schema_evolution)5640 int32_t tiledb_deserialize_array_schema_evolution(
5641     tiledb_ctx_t* ctx,
5642     const tiledb_buffer_t* buffer,
5643     tiledb_serialization_type_t serialize_type,
5644     int32_t client_side,
5645     tiledb_array_schema_evolution_t** array_schema_evolution) {
5646   // Currently unused:
5647   (void)client_side;
5648 
5649   // Sanity check
5650   if (sanity_check(ctx) == TILEDB_ERR ||
5651       sanity_check(ctx, buffer) == TILEDB_ERR)
5652     return TILEDB_ERR;
5653 
5654   // Create array schema struct
5655   *array_schema_evolution = new (std::nothrow) tiledb_array_schema_evolution_t;
5656   if (*array_schema_evolution == nullptr) {
5657     auto st = Status::Error(
5658         "Failed to allocate TileDB array schema evolution object");
5659     LOG_STATUS(st);
5660     save_error(ctx, st);
5661     return TILEDB_OOM;
5662   }
5663 
5664   if (SAVE_ERROR_CATCH(
5665           ctx,
5666           tiledb::sm::serialization::array_schema_evolution_deserialize(
5667               &((*array_schema_evolution)->array_schema_evolution_),
5668               (tiledb::sm::SerializationType)serialize_type,
5669               *buffer->buffer_))) {
5670     delete *array_schema_evolution;
5671     *array_schema_evolution = nullptr;
5672     return TILEDB_ERR;
5673   }
5674 
5675   return TILEDB_OK;
5676 }
5677 
tiledb_serialize_query(tiledb_ctx_t * ctx,const tiledb_query_t * query,tiledb_serialization_type_t serialize_type,int32_t client_side,tiledb_buffer_list_t ** buffer_list)5678 int32_t tiledb_serialize_query(
5679     tiledb_ctx_t* ctx,
5680     const tiledb_query_t* query,
5681     tiledb_serialization_type_t serialize_type,
5682     int32_t client_side,
5683     tiledb_buffer_list_t** buffer_list) {
5684   // Sanity check
5685   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
5686     return TILEDB_ERR;
5687 
5688   // Allocate a buffer list
5689   if (tiledb_buffer_list_alloc(ctx, buffer_list) != TILEDB_OK ||
5690       sanity_check(ctx, *buffer_list) == TILEDB_ERR)
5691     return TILEDB_ERR;
5692 
5693   if (SAVE_ERROR_CATCH(
5694           ctx,
5695           tiledb::sm::serialization::query_serialize(
5696               query->query_,
5697               (tiledb::sm::SerializationType)serialize_type,
5698               client_side == 1,
5699               (*buffer_list)->buffer_list_))) {
5700     tiledb_buffer_list_free(buffer_list);
5701     return TILEDB_ERR;
5702   }
5703 
5704   return TILEDB_OK;
5705 }
5706 
tiledb_deserialize_query(tiledb_ctx_t * ctx,const tiledb_buffer_t * buffer,tiledb_serialization_type_t serialize_type,int32_t client_side,tiledb_query_t * query)5707 int32_t tiledb_deserialize_query(
5708     tiledb_ctx_t* ctx,
5709     const tiledb_buffer_t* buffer,
5710     tiledb_serialization_type_t serialize_type,
5711     int32_t client_side,
5712     tiledb_query_t* query) {
5713   // Sanity check
5714   if (sanity_check(ctx) == TILEDB_ERR ||
5715       sanity_check(ctx, query) == TILEDB_ERR ||
5716       sanity_check(ctx, buffer) == TILEDB_ERR)
5717     return TILEDB_ERR;
5718 
5719   if (SAVE_ERROR_CATCH(
5720           ctx,
5721           tiledb::sm::serialization::query_deserialize(
5722               *buffer->buffer_,
5723               (tiledb::sm::SerializationType)serialize_type,
5724               client_side == 1,
5725               nullptr,
5726               query->query_,
5727               ctx->ctx_->storage_manager()->compute_tp())))
5728     return TILEDB_ERR;
5729 
5730   return TILEDB_OK;
5731 }
5732 
tiledb_serialize_array_nonempty_domain(tiledb_ctx_t * ctx,const tiledb_array_t * array,const void * nonempty_domain,int32_t is_empty,tiledb_serialization_type_t serialize_type,int32_t client_side,tiledb_buffer_t ** buffer)5733 int32_t tiledb_serialize_array_nonempty_domain(
5734     tiledb_ctx_t* ctx,
5735     const tiledb_array_t* array,
5736     const void* nonempty_domain,
5737     int32_t is_empty,
5738     tiledb_serialization_type_t serialize_type,
5739     int32_t client_side,
5740     tiledb_buffer_t** buffer) {
5741   // Currently unused:
5742   (void)client_side;
5743 
5744   // Sanity check
5745   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
5746     return TILEDB_ERR;
5747 
5748   // Create buffer
5749   if (tiledb_buffer_alloc(ctx, buffer) != TILEDB_OK ||
5750       sanity_check(ctx, *buffer) == TILEDB_ERR)
5751     return TILEDB_ERR;
5752 
5753   if (SAVE_ERROR_CATCH(
5754           ctx,
5755           tiledb::sm::serialization::nonempty_domain_serialize(
5756               array->array_,
5757               nonempty_domain,
5758               is_empty,
5759               (tiledb::sm::SerializationType)serialize_type,
5760               (*buffer)->buffer_))) {
5761     tiledb_buffer_free(buffer);
5762     return TILEDB_ERR;
5763   }
5764 
5765   return TILEDB_OK;
5766 }
5767 
tiledb_deserialize_array_nonempty_domain(tiledb_ctx_t * ctx,const tiledb_array_t * array,const tiledb_buffer_t * buffer,tiledb_serialization_type_t serialize_type,int32_t client_side,void * nonempty_domain,int32_t * is_empty)5768 int32_t tiledb_deserialize_array_nonempty_domain(
5769     tiledb_ctx_t* ctx,
5770     const tiledb_array_t* array,
5771     const tiledb_buffer_t* buffer,
5772     tiledb_serialization_type_t serialize_type,
5773     int32_t client_side,
5774     void* nonempty_domain,
5775     int32_t* is_empty) {
5776   // Currently unused:
5777   (void)client_side;
5778 
5779   // Sanity check
5780   if (sanity_check(ctx) == TILEDB_ERR ||
5781       sanity_check(ctx, array) == TILEDB_ERR ||
5782       sanity_check(ctx, buffer) == TILEDB_ERR)
5783     return TILEDB_ERR;
5784 
5785   bool is_empty_bool;
5786   if (SAVE_ERROR_CATCH(
5787           ctx,
5788           tiledb::sm::serialization::nonempty_domain_deserialize(
5789               array->array_,
5790               *buffer->buffer_,
5791               (tiledb::sm::SerializationType)serialize_type,
5792               nonempty_domain,
5793               &is_empty_bool)))
5794     return TILEDB_ERR;
5795 
5796   *is_empty = is_empty_bool ? 1 : 0;
5797 
5798   return TILEDB_OK;
5799 }
5800 
tiledb_serialize_array_non_empty_domain_all_dimensions(tiledb_ctx_t * ctx,const tiledb_array_t * array,tiledb_serialization_type_t serialize_type,int32_t client_side,tiledb_buffer_t ** buffer)5801 int32_t tiledb_serialize_array_non_empty_domain_all_dimensions(
5802     tiledb_ctx_t* ctx,
5803     const tiledb_array_t* array,
5804     tiledb_serialization_type_t serialize_type,
5805     int32_t client_side,
5806     tiledb_buffer_t** buffer) {
5807   // Currently unused:
5808   (void)client_side;
5809 
5810   // Sanity check
5811   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
5812     return TILEDB_ERR;
5813 
5814   // Create buffer
5815   if (tiledb_buffer_alloc(ctx, buffer) != TILEDB_OK ||
5816       sanity_check(ctx, *buffer) == TILEDB_ERR)
5817     return TILEDB_ERR;
5818 
5819   if (SAVE_ERROR_CATCH(
5820           ctx,
5821           tiledb::sm::serialization::nonempty_domain_serialize(
5822               array->array_,
5823               (tiledb::sm::SerializationType)serialize_type,
5824               (*buffer)->buffer_))) {
5825     tiledb_buffer_free(buffer);
5826     return TILEDB_ERR;
5827   }
5828 
5829   return TILEDB_OK;
5830 }
5831 
tiledb_deserialize_array_non_empty_domain_all_dimensions(tiledb_ctx_t * ctx,tiledb_array_t * array,const tiledb_buffer_t * buffer,tiledb_serialization_type_t serialize_type,int32_t client_side)5832 int32_t tiledb_deserialize_array_non_empty_domain_all_dimensions(
5833     tiledb_ctx_t* ctx,
5834     tiledb_array_t* array,
5835     const tiledb_buffer_t* buffer,
5836     tiledb_serialization_type_t serialize_type,
5837     int32_t client_side) {
5838   // Currently unused:
5839   (void)client_side;
5840 
5841   // Sanity check
5842   if (sanity_check(ctx) == TILEDB_ERR ||
5843       sanity_check(ctx, array) == TILEDB_ERR ||
5844       sanity_check(ctx, buffer) == TILEDB_ERR)
5845     return TILEDB_ERR;
5846 
5847   if (SAVE_ERROR_CATCH(
5848           ctx,
5849           tiledb::sm::serialization::nonempty_domain_deserialize(
5850               array->array_,
5851               *buffer->buffer_,
5852               (tiledb::sm::SerializationType)serialize_type)))
5853     return TILEDB_ERR;
5854 
5855   return TILEDB_OK;
5856 }
5857 
tiledb_serialize_array_max_buffer_sizes(tiledb_ctx_t * ctx,const tiledb_array_t * array,const void * subarray,tiledb_serialization_type_t serialize_type,tiledb_buffer_t ** buffer)5858 int32_t tiledb_serialize_array_max_buffer_sizes(
5859     tiledb_ctx_t* ctx,
5860     const tiledb_array_t* array,
5861     const void* subarray,
5862     tiledb_serialization_type_t serialize_type,
5863     tiledb_buffer_t** buffer) {
5864   // Sanity check
5865   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
5866     return TILEDB_ERR;
5867 
5868   // Allocate buffer
5869   if (tiledb_buffer_alloc(ctx, buffer) != TILEDB_OK ||
5870       sanity_check(ctx, *buffer) == TILEDB_ERR)
5871     return TILEDB_ERR;
5872 
5873   // Serialize
5874   if (SAVE_ERROR_CATCH(
5875           ctx,
5876           tiledb::sm::serialization::max_buffer_sizes_serialize(
5877               array->array_,
5878               subarray,
5879               (tiledb::sm::SerializationType)serialize_type,
5880               (*buffer)->buffer_))) {
5881     tiledb_buffer_free(buffer);
5882     return TILEDB_ERR;
5883   }
5884 
5885   return TILEDB_OK;
5886 }
5887 
tiledb_serialize_array_metadata(tiledb_ctx_t * ctx,const tiledb_array_t * array,tiledb_serialization_type_t serialize_type,tiledb_buffer_t ** buffer)5888 int32_t tiledb_serialize_array_metadata(
5889     tiledb_ctx_t* ctx,
5890     const tiledb_array_t* array,
5891     tiledb_serialization_type_t serialize_type,
5892     tiledb_buffer_t** buffer) {
5893   // Sanity check
5894   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, array) == TILEDB_ERR)
5895     return TILEDB_ERR;
5896 
5897   // Allocate buffer
5898   if (tiledb_buffer_alloc(ctx, buffer) != TILEDB_OK ||
5899       sanity_check(ctx, *buffer) == TILEDB_ERR)
5900     return TILEDB_ERR;
5901 
5902   // Serialize
5903   if (SAVE_ERROR_CATCH(
5904           ctx,
5905           tiledb::sm::serialization::array_metadata_serialize(
5906               array->array_,
5907               (tiledb::sm::SerializationType)serialize_type,
5908               (*buffer)->buffer_))) {
5909     tiledb_buffer_free(buffer);
5910     return TILEDB_ERR;
5911   }
5912 
5913   return TILEDB_OK;
5914 }
5915 
tiledb_deserialize_array_metadata(tiledb_ctx_t * ctx,tiledb_array_t * array,tiledb_serialization_type_t serialize_type,const tiledb_buffer_t * buffer)5916 int32_t tiledb_deserialize_array_metadata(
5917     tiledb_ctx_t* ctx,
5918     tiledb_array_t* array,
5919     tiledb_serialization_type_t serialize_type,
5920     const tiledb_buffer_t* buffer) {
5921   // Sanity check
5922   if (sanity_check(ctx) == TILEDB_ERR ||
5923       sanity_check(ctx, array) == TILEDB_ERR ||
5924       sanity_check(ctx, buffer) == TILEDB_ERR)
5925     return TILEDB_ERR;
5926 
5927   // Deserialize
5928   if (SAVE_ERROR_CATCH(
5929           ctx,
5930           tiledb::sm::serialization::array_metadata_deserialize(
5931               array->array_,
5932               (tiledb::sm::SerializationType)serialize_type,
5933               *(buffer->buffer_)))) {
5934     return TILEDB_ERR;
5935   }
5936 
5937   return TILEDB_OK;
5938 }
5939 
tiledb_serialize_query_est_result_sizes(tiledb_ctx_t * ctx,const tiledb_query_t * query,tiledb_serialization_type_t serialize_type,int32_t client_side,tiledb_buffer_t ** buffer)5940 int32_t tiledb_serialize_query_est_result_sizes(
5941     tiledb_ctx_t* ctx,
5942     const tiledb_query_t* query,
5943     tiledb_serialization_type_t serialize_type,
5944     int32_t client_side,
5945     tiledb_buffer_t** buffer) {
5946   // Sanity check
5947   if (sanity_check(ctx) == TILEDB_ERR || sanity_check(ctx, query) == TILEDB_ERR)
5948     return TILEDB_ERR;
5949 
5950   // Allocate buffer
5951   if (tiledb_buffer_alloc(ctx, buffer) != TILEDB_OK ||
5952       sanity_check(ctx, *buffer) == TILEDB_ERR)
5953     return TILEDB_ERR;
5954 
5955   if (SAVE_ERROR_CATCH(
5956           ctx,
5957           tiledb::sm::serialization::query_est_result_size_serialize(
5958               query->query_,
5959               (tiledb::sm::SerializationType)serialize_type,
5960               client_side == 1,
5961               (*buffer)->buffer_))) {
5962     tiledb_buffer_free(buffer);
5963     return TILEDB_ERR;
5964   }
5965 
5966   return TILEDB_OK;
5967 }
5968 
tiledb_deserialize_query_est_result_sizes(tiledb_ctx_t * ctx,tiledb_query_t * query,tiledb_serialization_type_t serialize_type,int32_t client_side,const tiledb_buffer_t * buffer)5969 int32_t tiledb_deserialize_query_est_result_sizes(
5970     tiledb_ctx_t* ctx,
5971     tiledb_query_t* query,
5972     tiledb_serialization_type_t serialize_type,
5973     int32_t client_side,
5974     const tiledb_buffer_t* buffer) {
5975   // Sanity check
5976   if (sanity_check(ctx) == TILEDB_ERR ||
5977       sanity_check(ctx, query) == TILEDB_ERR ||
5978       sanity_check(ctx, buffer) == TILEDB_ERR)
5979     return TILEDB_ERR;
5980 
5981   if (SAVE_ERROR_CATCH(
5982           ctx,
5983           tiledb::sm::serialization::query_est_result_size_deserialize(
5984               query->query_,
5985               (tiledb::sm::SerializationType)serialize_type,
5986               client_side == 1,
5987               *buffer->buffer_)))
5988     return TILEDB_ERR;
5989 
5990   return TILEDB_OK;
5991 }
5992 
tiledb_serialize_config(tiledb_ctx_t * ctx,const tiledb_config_t * config,tiledb_serialization_type_t serialize_type,int32_t client_side,tiledb_buffer_t ** buffer)5993 int32_t tiledb_serialize_config(
5994     tiledb_ctx_t* ctx,
5995     const tiledb_config_t* config,
5996     tiledb_serialization_type_t serialize_type,
5997     int32_t client_side,
5998     tiledb_buffer_t** buffer) {
5999   // Sanity check
6000   if (sanity_check(ctx) == TILEDB_ERR ||
6001       sanity_check(ctx, config) == TILEDB_ERR)
6002     return TILEDB_ERR;
6003 
6004   // Create buffer
6005   if (tiledb_buffer_alloc(ctx, buffer) != TILEDB_OK ||
6006       sanity_check(ctx, *buffer) == TILEDB_ERR)
6007     return TILEDB_ERR;
6008 
6009   if (SAVE_ERROR_CATCH(
6010           ctx,
6011           tiledb::sm::serialization::config_serialize(
6012               config->config_,
6013               (tiledb::sm::SerializationType)serialize_type,
6014               (*buffer)->buffer_,
6015               client_side))) {
6016     tiledb_buffer_free(buffer);
6017     return TILEDB_ERR;
6018   }
6019 
6020   return TILEDB_OK;
6021 }
6022 
tiledb_deserialize_config(tiledb_ctx_t * ctx,const tiledb_buffer_t * buffer,tiledb_serialization_type_t serialize_type,int32_t client_side,tiledb_config_t ** config)6023 int32_t tiledb_deserialize_config(
6024     tiledb_ctx_t* ctx,
6025     const tiledb_buffer_t* buffer,
6026     tiledb_serialization_type_t serialize_type,
6027     int32_t client_side,
6028     tiledb_config_t** config) {
6029   // Currently unused:
6030   (void)client_side;
6031 
6032   // Sanity check
6033   if (sanity_check(ctx) == TILEDB_ERR ||
6034       sanity_check(ctx, buffer) == TILEDB_ERR)
6035     return TILEDB_ERR;
6036 
6037   // Create array schema struct
6038   *config = new (std::nothrow) tiledb_config_t;
6039   if (*config == nullptr) {
6040     auto st = Status::Error("Failed to allocate TileDB config object");
6041     LOG_STATUS(st);
6042     save_error(ctx, st);
6043     return TILEDB_OOM;
6044   }
6045 
6046   if (SAVE_ERROR_CATCH(
6047           ctx,
6048           tiledb::sm::serialization::config_deserialize(
6049               &((*config)->config_),
6050               (tiledb::sm::SerializationType)serialize_type,
6051               *buffer->buffer_))) {
6052     delete *config;
6053     *config = nullptr;
6054     return TILEDB_ERR;
6055   }
6056 
6057   return TILEDB_OK;
6058 }
6059 
6060 /* ****************************** */
6061 /*            C++ API             */
6062 /* ****************************** */
6063 
tiledb_query_submit_async_func(tiledb_ctx_t * ctx,tiledb_query_t * query,void * callback_func,void * callback_data)6064 int32_t tiledb::impl::tiledb_query_submit_async_func(
6065     tiledb_ctx_t* ctx,
6066     tiledb_query_t* query,
6067     void* callback_func,
6068     void* callback_data) {
6069   if (sanity_check(ctx) == TILEDB_ERR ||
6070       sanity_check(ctx, query) == TILEDB_ERR || callback_func == nullptr)
6071     return TILEDB_ERR;
6072 
6073   std::function<void(void*)> callback =
6074       *reinterpret_cast<std::function<void(void*)>*>(callback_func);
6075 
6076   if (SAVE_ERROR_CATCH(
6077           ctx, query->query_->submit_async(callback, callback_data)))
6078     return TILEDB_ERR;
6079 
6080   return TILEDB_OK;
6081 }
6082 
6083 /* ****************************** */
6084 /*          FRAGMENT INFO         */
6085 /* ****************************** */
6086 
tiledb_fragment_info_alloc(tiledb_ctx_t * ctx,const char * array_uri,tiledb_fragment_info_t ** fragment_info)6087 int32_t tiledb_fragment_info_alloc(
6088     tiledb_ctx_t* ctx,
6089     const char* array_uri,
6090     tiledb_fragment_info_t** fragment_info) {
6091   if (sanity_check(ctx) == TILEDB_ERR) {
6092     *fragment_info = nullptr;
6093     return TILEDB_ERR;
6094   }
6095 
6096   // Create fragment info struct
6097   *fragment_info = new (std::nothrow) tiledb_fragment_info_t;
6098   if (*fragment_info == nullptr) {
6099     auto st = Status::Error(
6100         "Failed to create TileDB fragment info object; Memory allocation "
6101         "error");
6102     LOG_STATUS(st);
6103     save_error(ctx, st);
6104     return TILEDB_OOM;
6105   }
6106 
6107   // Check array URI
6108   auto uri = tiledb::sm::URI(array_uri);
6109   if (uri.is_invalid()) {
6110     auto st = Status::Error(
6111         "Failed to create TileDB fragment info object; Invalid URI");
6112     delete *fragment_info;
6113     *fragment_info = nullptr;
6114     LOG_STATUS(st);
6115     save_error(ctx, st);
6116     return TILEDB_ERR;
6117   }
6118 
6119   // Allocate a fragment info object
6120   (*fragment_info)->fragment_info_ = new (std::nothrow)
6121       tiledb::sm::FragmentInfo(uri, ctx->ctx_->storage_manager());
6122   if ((*fragment_info)->fragment_info_ == nullptr) {
6123     delete *fragment_info;
6124     *fragment_info = nullptr;
6125     auto st = Status::Error(
6126         "Failed to create TileDB fragment info object; Memory allocation "
6127         "error");
6128     LOG_STATUS(st);
6129     save_error(ctx, st);
6130     return TILEDB_OOM;
6131   }
6132 
6133   // Success
6134   return TILEDB_OK;
6135 }
6136 
tiledb_fragment_info_free(tiledb_fragment_info_t ** fragment_info)6137 void tiledb_fragment_info_free(tiledb_fragment_info_t** fragment_info) {
6138   if (fragment_info != nullptr && *fragment_info != nullptr) {
6139     delete (*fragment_info)->fragment_info_;
6140     delete *fragment_info;
6141     *fragment_info = nullptr;
6142   }
6143 }
6144 
tiledb_fragment_info_load(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info)6145 int32_t tiledb_fragment_info_load(
6146     tiledb_ctx_t* ctx, tiledb_fragment_info_t* fragment_info) {
6147   if (sanity_check(ctx) == TILEDB_ERR ||
6148       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6149     return TILEDB_ERR;
6150 
6151   // Get config from ctx
6152   tiledb::sm::Config config = ctx->ctx_->storage_manager()->config();
6153 
6154   // Load fragment info
6155   if (SAVE_ERROR_CATCH(
6156           ctx,
6157           fragment_info->fragment_info_->load(
6158               config,
6159               static_cast<tiledb::sm::EncryptionType>(TILEDB_NO_ENCRYPTION),
6160               nullptr,
6161               0)))
6162     return TILEDB_ERR;
6163 
6164   return TILEDB_OK;
6165 }
6166 
tiledb_fragment_info_load_with_key(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,tiledb_encryption_type_t encryption_type,const void * encryption_key,uint32_t key_length)6167 int32_t tiledb_fragment_info_load_with_key(
6168     tiledb_ctx_t* ctx,
6169     tiledb_fragment_info_t* fragment_info,
6170     tiledb_encryption_type_t encryption_type,
6171     const void* encryption_key,
6172     uint32_t key_length) {
6173   if (sanity_check(ctx) == TILEDB_ERR ||
6174       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6175     return TILEDB_ERR;
6176 
6177   // Get config from ctx
6178   tiledb::sm::Config config = ctx->ctx_->storage_manager()->config();
6179 
6180   // Load fragment info
6181   if (SAVE_ERROR_CATCH(
6182           ctx,
6183           fragment_info->fragment_info_->load(
6184               config,
6185               static_cast<tiledb::sm::EncryptionType>(encryption_type),
6186               encryption_key,
6187               key_length)))
6188     return TILEDB_ERR;
6189 
6190   return TILEDB_OK;
6191 }
6192 
tiledb_fragment_info_get_fragment_num(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t * fragment_num)6193 int32_t tiledb_fragment_info_get_fragment_num(
6194     tiledb_ctx_t* ctx,
6195     tiledb_fragment_info_t* fragment_info,
6196     uint32_t* fragment_num) {
6197   if (sanity_check(ctx) == TILEDB_ERR ||
6198       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6199     return TILEDB_ERR;
6200 
6201   *fragment_num = fragment_info->fragment_info_->fragment_num();
6202 
6203   return TILEDB_OK;
6204 }
6205 
tiledb_fragment_info_get_fragment_uri(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,const char ** uri)6206 int32_t tiledb_fragment_info_get_fragment_uri(
6207     tiledb_ctx_t* ctx,
6208     tiledb_fragment_info_t* fragment_info,
6209     uint32_t fid,
6210     const char** uri) {
6211   if (sanity_check(ctx) == TILEDB_ERR ||
6212       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6213     return TILEDB_ERR;
6214 
6215   if (SAVE_ERROR_CATCH(
6216           ctx, fragment_info->fragment_info_->get_fragment_uri(fid, uri)))
6217     return TILEDB_ERR;
6218 
6219   return TILEDB_OK;
6220 }
6221 
tiledb_fragment_info_get_fragment_size(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint64_t * size)6222 int32_t tiledb_fragment_info_get_fragment_size(
6223     tiledb_ctx_t* ctx,
6224     tiledb_fragment_info_t* fragment_info,
6225     uint32_t fid,
6226     uint64_t* size) {
6227   if (sanity_check(ctx) == TILEDB_ERR ||
6228       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6229     return TILEDB_ERR;
6230 
6231   if (SAVE_ERROR_CATCH(
6232           ctx, fragment_info->fragment_info_->get_fragment_size(fid, size)))
6233     return TILEDB_ERR;
6234 
6235   return TILEDB_OK;
6236 }
6237 
tiledb_fragment_info_get_dense(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,int32_t * dense)6238 int32_t tiledb_fragment_info_get_dense(
6239     tiledb_ctx_t* ctx,
6240     tiledb_fragment_info_t* fragment_info,
6241     uint32_t fid,
6242     int32_t* dense) {
6243   if (sanity_check(ctx) == TILEDB_ERR ||
6244       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6245     return TILEDB_ERR;
6246 
6247   if (SAVE_ERROR_CATCH(
6248           ctx, fragment_info->fragment_info_->get_dense(fid, dense)))
6249     return TILEDB_ERR;
6250 
6251   return TILEDB_OK;
6252 }
6253 
tiledb_fragment_info_get_sparse(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,int32_t * sparse)6254 int32_t tiledb_fragment_info_get_sparse(
6255     tiledb_ctx_t* ctx,
6256     tiledb_fragment_info_t* fragment_info,
6257     uint32_t fid,
6258     int32_t* sparse) {
6259   if (sanity_check(ctx) == TILEDB_ERR ||
6260       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6261     return TILEDB_ERR;
6262 
6263   if (SAVE_ERROR_CATCH(
6264           ctx, fragment_info->fragment_info_->get_sparse(fid, sparse)))
6265     return TILEDB_ERR;
6266 
6267   return TILEDB_OK;
6268 }
6269 
tiledb_fragment_info_get_timestamp_range(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint64_t * start,uint64_t * end)6270 int32_t tiledb_fragment_info_get_timestamp_range(
6271     tiledb_ctx_t* ctx,
6272     tiledb_fragment_info_t* fragment_info,
6273     uint32_t fid,
6274     uint64_t* start,
6275     uint64_t* end) {
6276   if (sanity_check(ctx) == TILEDB_ERR ||
6277       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6278     return TILEDB_ERR;
6279 
6280   if (SAVE_ERROR_CATCH(
6281           ctx,
6282           fragment_info->fragment_info_->get_timestamp_range(fid, start, end)))
6283     return TILEDB_ERR;
6284 
6285   return TILEDB_OK;
6286 }
6287 
tiledb_fragment_info_get_non_empty_domain_from_index(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint32_t did,void * domain)6288 int32_t tiledb_fragment_info_get_non_empty_domain_from_index(
6289     tiledb_ctx_t* ctx,
6290     tiledb_fragment_info_t* fragment_info,
6291     uint32_t fid,
6292     uint32_t did,
6293     void* domain) {
6294   if (sanity_check(ctx) == TILEDB_ERR ||
6295       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6296     return TILEDB_ERR;
6297 
6298   if (SAVE_ERROR_CATCH(
6299           ctx,
6300           fragment_info->fragment_info_->get_non_empty_domain(
6301               fid, did, domain)))
6302     return TILEDB_ERR;
6303 
6304   return TILEDB_OK;
6305 }
6306 
tiledb_fragment_info_get_non_empty_domain_from_name(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,const char * dim_name,void * domain)6307 int32_t tiledb_fragment_info_get_non_empty_domain_from_name(
6308     tiledb_ctx_t* ctx,
6309     tiledb_fragment_info_t* fragment_info,
6310     uint32_t fid,
6311     const char* dim_name,
6312     void* domain) {
6313   if (sanity_check(ctx) == TILEDB_ERR ||
6314       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6315     return TILEDB_ERR;
6316 
6317   if (SAVE_ERROR_CATCH(
6318           ctx,
6319           fragment_info->fragment_info_->get_non_empty_domain(
6320               fid, dim_name, domain)))
6321     return TILEDB_ERR;
6322 
6323   return TILEDB_OK;
6324 }
6325 
tiledb_fragment_info_get_non_empty_domain_var_size_from_index(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint32_t did,uint64_t * start_size,uint64_t * end_size)6326 int32_t tiledb_fragment_info_get_non_empty_domain_var_size_from_index(
6327     tiledb_ctx_t* ctx,
6328     tiledb_fragment_info_t* fragment_info,
6329     uint32_t fid,
6330     uint32_t did,
6331     uint64_t* start_size,
6332     uint64_t* end_size) {
6333   if (sanity_check(ctx) == TILEDB_ERR ||
6334       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6335     return TILEDB_ERR;
6336 
6337   if (SAVE_ERROR_CATCH(
6338           ctx,
6339           fragment_info->fragment_info_->get_non_empty_domain_var_size(
6340               fid, did, start_size, end_size)))
6341     return TILEDB_ERR;
6342 
6343   return TILEDB_OK;
6344 }
6345 
tiledb_fragment_info_get_non_empty_domain_var_size_from_name(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,const char * dim_name,uint64_t * start_size,uint64_t * end_size)6346 int32_t tiledb_fragment_info_get_non_empty_domain_var_size_from_name(
6347     tiledb_ctx_t* ctx,
6348     tiledb_fragment_info_t* fragment_info,
6349     uint32_t fid,
6350     const char* dim_name,
6351     uint64_t* start_size,
6352     uint64_t* end_size) {
6353   if (sanity_check(ctx) == TILEDB_ERR ||
6354       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6355     return TILEDB_ERR;
6356 
6357   if (SAVE_ERROR_CATCH(
6358           ctx,
6359           fragment_info->fragment_info_->get_non_empty_domain_var_size(
6360               fid, dim_name, start_size, end_size)))
6361     return TILEDB_ERR;
6362 
6363   return TILEDB_OK;
6364 }
6365 
tiledb_fragment_info_get_non_empty_domain_var_from_index(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint32_t did,void * start,void * end)6366 int32_t tiledb_fragment_info_get_non_empty_domain_var_from_index(
6367     tiledb_ctx_t* ctx,
6368     tiledb_fragment_info_t* fragment_info,
6369     uint32_t fid,
6370     uint32_t did,
6371     void* start,
6372     void* end) {
6373   if (sanity_check(ctx) == TILEDB_ERR ||
6374       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6375     return TILEDB_ERR;
6376 
6377   if (SAVE_ERROR_CATCH(
6378           ctx,
6379           fragment_info->fragment_info_->get_non_empty_domain_var(
6380               fid, did, start, end)))
6381     return TILEDB_ERR;
6382 
6383   return TILEDB_OK;
6384 }
6385 
tiledb_fragment_info_get_non_empty_domain_var_from_name(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,const char * dim_name,void * start,void * end)6386 int32_t tiledb_fragment_info_get_non_empty_domain_var_from_name(
6387     tiledb_ctx_t* ctx,
6388     tiledb_fragment_info_t* fragment_info,
6389     uint32_t fid,
6390     const char* dim_name,
6391     void* start,
6392     void* end) {
6393   if (sanity_check(ctx) == TILEDB_ERR ||
6394       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6395     return TILEDB_ERR;
6396 
6397   if (SAVE_ERROR_CATCH(
6398           ctx,
6399           fragment_info->fragment_info_->get_non_empty_domain_var(
6400               fid, dim_name, start, end)))
6401     return TILEDB_ERR;
6402 
6403   return TILEDB_OK;
6404 }
6405 
tiledb_fragment_info_get_mbr_num(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint64_t * mbr_num)6406 int32_t tiledb_fragment_info_get_mbr_num(
6407     tiledb_ctx_t* ctx,
6408     tiledb_fragment_info_t* fragment_info,
6409     uint32_t fid,
6410     uint64_t* mbr_num) {
6411   if (sanity_check(ctx) == TILEDB_ERR ||
6412       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6413     return TILEDB_ERR;
6414 
6415   // Get config from ctx
6416   tiledb::sm::Config config = ctx->ctx_->storage_manager()->config();
6417 
6418   if (SAVE_ERROR_CATCH(
6419           ctx, fragment_info->fragment_info_->get_mbr_num(fid, mbr_num)))
6420     return TILEDB_ERR;
6421 
6422   return TILEDB_OK;
6423 }
6424 
tiledb_fragment_info_get_mbr_from_index(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint32_t mid,uint32_t did,void * mbr)6425 int32_t tiledb_fragment_info_get_mbr_from_index(
6426     tiledb_ctx_t* ctx,
6427     tiledb_fragment_info_t* fragment_info,
6428     uint32_t fid,
6429     uint32_t mid,
6430     uint32_t did,
6431     void* mbr) {
6432   if (sanity_check(ctx) == TILEDB_ERR ||
6433       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6434     return TILEDB_ERR;
6435 
6436   // Get config from ctx
6437   tiledb::sm::Config config = ctx->ctx_->storage_manager()->config();
6438 
6439   if (SAVE_ERROR_CATCH(
6440           ctx, fragment_info->fragment_info_->get_mbr(fid, mid, did, mbr)))
6441     return TILEDB_ERR;
6442 
6443   return TILEDB_OK;
6444 }
6445 
tiledb_fragment_info_get_mbr_from_name(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint32_t mid,const char * dim_name,void * mbr)6446 int32_t tiledb_fragment_info_get_mbr_from_name(
6447     tiledb_ctx_t* ctx,
6448     tiledb_fragment_info_t* fragment_info,
6449     uint32_t fid,
6450     uint32_t mid,
6451     const char* dim_name,
6452     void* mbr) {
6453   if (sanity_check(ctx) == TILEDB_ERR ||
6454       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6455     return TILEDB_ERR;
6456 
6457   // Get config from ctx
6458   tiledb::sm::Config config = ctx->ctx_->storage_manager()->config();
6459 
6460   if (SAVE_ERROR_CATCH(
6461           ctx, fragment_info->fragment_info_->get_mbr(fid, mid, dim_name, mbr)))
6462     return TILEDB_ERR;
6463 
6464   return TILEDB_OK;
6465 }
6466 
tiledb_fragment_info_get_mbr_var_size_from_index(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint32_t mid,uint32_t did,uint64_t * start_size,uint64_t * end_size)6467 int32_t tiledb_fragment_info_get_mbr_var_size_from_index(
6468     tiledb_ctx_t* ctx,
6469     tiledb_fragment_info_t* fragment_info,
6470     uint32_t fid,
6471     uint32_t mid,
6472     uint32_t did,
6473     uint64_t* start_size,
6474     uint64_t* end_size) {
6475   if (sanity_check(ctx) == TILEDB_ERR ||
6476       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6477     return TILEDB_ERR;
6478 
6479   // Get config from ctx
6480   tiledb::sm::Config config = ctx->ctx_->storage_manager()->config();
6481 
6482   if (SAVE_ERROR_CATCH(
6483           ctx,
6484           fragment_info->fragment_info_->get_mbr_var_size(
6485               fid, mid, did, start_size, end_size)))
6486     return TILEDB_ERR;
6487 
6488   return TILEDB_OK;
6489 }
6490 
tiledb_fragment_info_get_mbr_var_size_from_name(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint32_t mid,const char * dim_name,uint64_t * start_size,uint64_t * end_size)6491 int32_t tiledb_fragment_info_get_mbr_var_size_from_name(
6492     tiledb_ctx_t* ctx,
6493     tiledb_fragment_info_t* fragment_info,
6494     uint32_t fid,
6495     uint32_t mid,
6496     const char* dim_name,
6497     uint64_t* start_size,
6498     uint64_t* end_size) {
6499   if (sanity_check(ctx) == TILEDB_ERR ||
6500       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6501     return TILEDB_ERR;
6502 
6503   // Get config from ctx
6504   tiledb::sm::Config config = ctx->ctx_->storage_manager()->config();
6505 
6506   if (SAVE_ERROR_CATCH(
6507           ctx,
6508           fragment_info->fragment_info_->get_mbr_var_size(
6509               fid, mid, dim_name, start_size, end_size)))
6510     return TILEDB_ERR;
6511 
6512   return TILEDB_OK;
6513 }
6514 
tiledb_fragment_info_get_mbr_var_from_index(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint32_t mid,uint32_t did,void * start,void * end)6515 int32_t tiledb_fragment_info_get_mbr_var_from_index(
6516     tiledb_ctx_t* ctx,
6517     tiledb_fragment_info_t* fragment_info,
6518     uint32_t fid,
6519     uint32_t mid,
6520     uint32_t did,
6521     void* start,
6522     void* end) {
6523   if (sanity_check(ctx) == TILEDB_ERR ||
6524       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6525     return TILEDB_ERR;
6526 
6527   // Get config from ctx
6528   tiledb::sm::Config config = ctx->ctx_->storage_manager()->config();
6529 
6530   if (SAVE_ERROR_CATCH(
6531           ctx,
6532           fragment_info->fragment_info_->get_mbr_var(
6533               fid, mid, did, start, end)))
6534     return TILEDB_ERR;
6535 
6536   return TILEDB_OK;
6537 }
6538 
tiledb_fragment_info_get_mbr_var_from_name(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint32_t mid,const char * dim_name,void * start,void * end)6539 int32_t tiledb_fragment_info_get_mbr_var_from_name(
6540     tiledb_ctx_t* ctx,
6541     tiledb_fragment_info_t* fragment_info,
6542     uint32_t fid,
6543     uint32_t mid,
6544     const char* dim_name,
6545     void* start,
6546     void* end) {
6547   if (sanity_check(ctx) == TILEDB_ERR ||
6548       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6549     return TILEDB_ERR;
6550 
6551   // Get config from ctx
6552   tiledb::sm::Config config = ctx->ctx_->storage_manager()->config();
6553 
6554   if (SAVE_ERROR_CATCH(
6555           ctx,
6556           fragment_info->fragment_info_->get_mbr_var(
6557               fid, mid, dim_name, start, end)))
6558     return TILEDB_ERR;
6559 
6560   return TILEDB_OK;
6561 }
6562 
tiledb_fragment_info_get_cell_num(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint64_t * cell_num)6563 int32_t tiledb_fragment_info_get_cell_num(
6564     tiledb_ctx_t* ctx,
6565     tiledb_fragment_info_t* fragment_info,
6566     uint32_t fid,
6567     uint64_t* cell_num) {
6568   if (sanity_check(ctx) == TILEDB_ERR ||
6569       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6570     return TILEDB_ERR;
6571 
6572   if (SAVE_ERROR_CATCH(
6573           ctx, fragment_info->fragment_info_->get_cell_num(fid, cell_num)))
6574     return TILEDB_ERR;
6575 
6576   return TILEDB_OK;
6577 }
6578 
tiledb_fragment_info_get_version(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,uint32_t * version)6579 int32_t tiledb_fragment_info_get_version(
6580     tiledb_ctx_t* ctx,
6581     tiledb_fragment_info_t* fragment_info,
6582     uint32_t fid,
6583     uint32_t* version) {
6584   if (sanity_check(ctx) == TILEDB_ERR ||
6585       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6586     return TILEDB_ERR;
6587 
6588   if (SAVE_ERROR_CATCH(
6589           ctx, fragment_info->fragment_info_->get_version(fid, version)))
6590     return TILEDB_ERR;
6591 
6592   return TILEDB_OK;
6593 }
6594 
tiledb_fragment_info_has_consolidated_metadata(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,int32_t * has)6595 int32_t tiledb_fragment_info_has_consolidated_metadata(
6596     tiledb_ctx_t* ctx,
6597     tiledb_fragment_info_t* fragment_info,
6598     uint32_t fid,
6599     int32_t* has) {
6600   if (sanity_check(ctx) == TILEDB_ERR ||
6601       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6602     return TILEDB_ERR;
6603 
6604   if (SAVE_ERROR_CATCH(
6605           ctx,
6606           fragment_info->fragment_info_->has_consolidated_metadata(fid, has)))
6607     return TILEDB_ERR;
6608 
6609   return TILEDB_OK;
6610 }
6611 
tiledb_fragment_info_get_unconsolidated_metadata_num(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t * unconsolidated)6612 int32_t tiledb_fragment_info_get_unconsolidated_metadata_num(
6613     tiledb_ctx_t* ctx,
6614     tiledb_fragment_info_t* fragment_info,
6615     uint32_t* unconsolidated) {
6616   if (sanity_check(ctx) == TILEDB_ERR ||
6617       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6618     return TILEDB_ERR;
6619 
6620   *unconsolidated =
6621       fragment_info->fragment_info_->unconsolidated_metadata_num();
6622 
6623   return TILEDB_OK;
6624 }
6625 
tiledb_fragment_info_get_to_vacuum_num(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t * to_vacuum_num)6626 int32_t tiledb_fragment_info_get_to_vacuum_num(
6627     tiledb_ctx_t* ctx,
6628     tiledb_fragment_info_t* fragment_info,
6629     uint32_t* to_vacuum_num) {
6630   if (sanity_check(ctx) == TILEDB_ERR ||
6631       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6632     return TILEDB_ERR;
6633 
6634   *to_vacuum_num = fragment_info->fragment_info_->to_vacuum_num();
6635 
6636   return TILEDB_OK;
6637 }
6638 
tiledb_fragment_info_get_to_vacuum_uri(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,const char ** uri)6639 int32_t tiledb_fragment_info_get_to_vacuum_uri(
6640     tiledb_ctx_t* ctx,
6641     tiledb_fragment_info_t* fragment_info,
6642     uint32_t fid,
6643     const char** uri) {
6644   if (sanity_check(ctx) == TILEDB_ERR ||
6645       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6646     return TILEDB_ERR;
6647 
6648   if (SAVE_ERROR_CATCH(
6649           ctx, fragment_info->fragment_info_->get_to_vacuum_uri(fid, uri)))
6650     return TILEDB_ERR;
6651 
6652   return TILEDB_OK;
6653 }
6654 
tiledb_fragment_info_get_array_schema(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,tiledb_array_schema_t ** array_schema)6655 int32_t tiledb_fragment_info_get_array_schema(
6656     tiledb_ctx_t* ctx,
6657     tiledb_fragment_info_t* fragment_info,
6658     uint32_t fid,
6659     tiledb_array_schema_t** array_schema) {
6660   if (sanity_check(ctx) == TILEDB_ERR ||
6661       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6662     return TILEDB_ERR;
6663 
6664   // Create array schema
6665   *array_schema = new (std::nothrow) tiledb_array_schema_t;
6666   if (*array_schema == nullptr) {
6667     auto st = Status::Error("Failed to allocate TileDB array schema object");
6668     LOG_STATUS(st);
6669     save_error(ctx, st);
6670     return TILEDB_OOM;
6671   }
6672 
6673   if (SAVE_ERROR_CATCH(
6674           ctx,
6675           fragment_info->fragment_info_->get_array_schema(
6676               fid, &(*array_schema)->array_schema_))) {
6677     delete *array_schema;
6678     *array_schema = nullptr;
6679     return TILEDB_ERR;
6680   }
6681 
6682   return TILEDB_OK;
6683 }
6684 
tiledb_fragment_info_get_array_schema_name(tiledb_ctx_t * ctx,tiledb_fragment_info_t * fragment_info,uint32_t fid,const char ** schema_name)6685 int32_t tiledb_fragment_info_get_array_schema_name(
6686     tiledb_ctx_t* ctx,
6687     tiledb_fragment_info_t* fragment_info,
6688     uint32_t fid,
6689     const char** schema_name) {
6690   if (sanity_check(ctx) == TILEDB_ERR ||
6691       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6692     return TILEDB_ERR;
6693 
6694   if (SAVE_ERROR_CATCH(
6695           ctx,
6696           fragment_info->fragment_info_->get_array_schema_name(
6697               fid, schema_name)))
6698     return TILEDB_ERR;
6699 
6700   assert(schema_name != nullptr);
6701 
6702   return TILEDB_OK;
6703 }
6704 
tiledb_fragment_info_dump(tiledb_ctx_t * ctx,const tiledb_fragment_info_t * fragment_info,FILE * out)6705 int32_t tiledb_fragment_info_dump(
6706     tiledb_ctx_t* ctx, const tiledb_fragment_info_t* fragment_info, FILE* out) {
6707   if (sanity_check(ctx) == TILEDB_ERR ||
6708       sanity_check(ctx, fragment_info) == TILEDB_ERR)
6709     return TILEDB_ERR;
6710   fragment_info->fragment_info_->dump(out);
6711   return TILEDB_OK;
6712 }
6713