1 #pragma once 2 #ifndef EJDB2_H 3 #define EJDB2_H 4 5 /************************************************************************************************** 6 * EJDB2 7 * 8 * MIT License 9 * 10 * Copyright (c) 2012-2022 Softmotions Ltd <info@softmotions.com> 11 * 12 * Permission is hereby granted, free of charge, to any person obtaining a copy 13 * of this software and associated documentation files (the "Software"), to deal 14 * in the Software without restriction, including without limitation the rights 15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 * copies of the Software, and to permit persons to whom the Software is 17 * furnished to do so, subject to the following conditions: 18 * 19 * The above copyright notice and this permission notice shall be included in all 20 * copies or substantial portions of the Software. 21 * 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 * SOFTWARE. 29 *************************************************************************************************/ 30 31 #include "jql.h" 32 #include <iowow/iwkv.h> 33 34 IW_EXTERN_C_START 35 36 /** 37 * @brief ejdb2 initialization routine. 38 * @note Must be called before using any of ejdb API function. 39 */ 40 IW_EXPORT WUR iwrc ejdb_init(void); 41 42 /** Maximum length of EJDB collection name */ 43 #define EJDB_COLLECTION_NAME_MAX_LEN 255 44 45 /** 46 * @brief EJDB error codes. 47 */ 48 typedef enum { 49 _EJDB_ERROR_START = (IW_ERROR_START + 15000UL), 50 EJDB_ERROR_INVALID_COLLECTION_NAME, /**< Invalid collection name */ 51 EJDB_ERROR_INVALID_COLLECTION_META, /**< Invalid collection metadata */ 52 EJDB_ERROR_INVALID_COLLECTION_INDEX_META, /**< Invalid collection index metadata */ 53 EJDB_ERROR_INVALID_INDEX_MODE, /**< Invalid index mode specified */ 54 EJDB_ERROR_MISMATCHED_INDEX_UNIQUENESS_MODE, /**< Index exists but mismatched uniqueness constraint */ 55 EJDB_ERROR_UNIQUE_INDEX_CONSTRAINT_VIOLATED, /**< Unique index constraint violated */ 56 EJDB_ERROR_COLLECTION_NOT_FOUND, /**< Collection not found */ 57 EJDB_ERROR_TARGET_COLLECTION_EXISTS, /**< Target collection exists */ 58 EJDB_ERROR_PATCH_JSON_NOT_OBJECT, /**< Patch JSON must be an object (map) */ 59 _EJDB_ERROR_END, 60 } ejdb_ecode_t; 61 62 /** Index creation mode */ 63 typedef uint8_t ejdb_idx_mode_t; 64 65 /** Marks index is unique, no duplicated values allowed. */ 66 #define EJDB_IDX_UNIQUE ((ejdb_idx_mode_t) 0x01U) 67 68 /** Index values have string type. 69 * Type conversion will be performed on atempt to save value with other type */ 70 #define EJDB_IDX_STR ((ejdb_idx_mode_t) 0x04U) 71 72 /** Index values have signed integer 64 bit wide type. 73 * Type conversion will be performed on atempt to save value with other type */ 74 #define EJDB_IDX_I64 ((ejdb_idx_mode_t) 0x08U) 75 76 /** Index value have floating point type. 77 * @note Internally floating point numbers are converted to string 78 * with precision of 6 digits after decimal point. 79 */ 80 #define EJDB_IDX_F64 ((ejdb_idx_mode_t) 0x10U) 81 82 /** 83 * @brief Database handler. 84 */ 85 struct _EJDB; 86 typedef struct _EJDB*EJDB; 87 88 /** 89 * @brief EJDB HTTP/Websocket Server options. 90 */ 91 typedef struct _EJDB_HTTP { 92 bool enabled; /**< If HTTP/Websocket endpoint enabled. Default: false */ 93 int port; /**< Listen port number, required */ 94 const char *bind; /**< Listen IP/host. Default: `localhost` */ 95 const char *access_token; /**< Server access token passed in `X-Access-Token` header. Default: zero */ 96 size_t access_token_len; /**< Length of access token string. Default: zero */ 97 bool blocking; /**< Block `ejdb_open()` thread until http service finished. 98 Otherwise HTTP server will be started in background. */ 99 bool read_anon; /**< Allow anonymous read-only database access */ 100 size_t max_body_size; /**< Maximum WS/HTTP API body size. Default: 64Mb, Min: 512K */ 101 bool cors; /**< Allow CORS */ 102 const char *ssl_private_key; /**< Path to TLS 1.2 private key PEM */ 103 const char *ssl_certs; /**< Path to TLS 1.2 certificates */ 104 } EJDB_HTTP; 105 106 /** 107 * @brief EJDB open options. 108 */ 109 typedef struct _EJDB_OPTS { 110 IWKV_OPTS kv; /**< IWKV storage options. @see iwkv.h */ 111 EJDB_HTTP http; /**< HTTP/Websocket server options */ 112 bool no_wal; /**< Do not use write-ahead-log. Default: false */ 113 uint32_t sort_buffer_sz; /**< Max sorting buffer size. If exceeded an overflow temp file for sorted data will 114 created. 115 Default 16Mb, min: 1Mb */ 116 uint32_t document_buffer_sz; /**< Initial size of buffer in bytes used to process/store document during query 117 execution. 118 Default 64Kb, min: 16Kb */ 119 } EJDB_OPTS; 120 121 /** 122 * @brief Document representation as result of query execution. 123 * @see ejdb_exec() 124 */ 125 typedef struct _EJDB_DOC { 126 int64_t id; /**< Document ID. Not zero. */ 127 JBL raw; /**< JSON document in compact binary form. 128 Based on [Binn](https://github.com/liteserver/binn) format. 129 Not zero. */ 130 JBL_NODE node; /**< JSON document as in-memory tree. Not zero only if query has `apply` or `projection` 131 parts. 132 133 @warning The lifespan of @ref EJDB_DOC.node will be valid only during the call of 134 @ref EJDB_EXEC_VISITOR 135 It is true in all cases EXCEPT: 136 - @ref EJDB_EXEC.pool is not set by `ejdb_exec()` caller 137 - One of `ejdb_list()` methods used */ 138 139 struct _EJDB_DOC *next; /**< Reference to next document in result list or zero. 140 Makes sense only for `ejdb_list()` calls. */ 141 struct _EJDB_DOC *prev; /**< Reference to the previous document in result list or zero. 142 Makes sense only for `ejdb_list()` calls. */ 143 } *EJDB_DOC; 144 145 /** 146 * @brief Query result as list. 147 * Used as result of `ejdb_list()` query functions. 148 * 149 * @warning Getting result of query as list can be very memory consuming for large collections. 150 * Consider use of `ejdb_exec()` with visitor or set `limit` for query. 151 */ 152 typedef struct _EJDB_LIST { 153 EJDB db; /**< EJDB storage used for query execution. Not zero. */ 154 JQL q; /**< Query executed. Not zero. */ 155 EJDB_DOC first; /**< First document in result list. Zero if result set is empty. */ 156 IWPOOL *pool; /**< Memory pool used to store list of documents */ 157 } *EJDB_LIST; 158 159 struct _EJDB_EXEC; 160 161 /** 162 * @brief Visitor for matched documents during query execution. 163 * 164 * @param ctx Visitor context. 165 * @param doc Data in `doc` is valid only during execution of this method, to keep a data for farther 166 * processing you need to copy it. 167 * @param step [out] Move forward cursor to given number of steps, `1` by default. 168 */ 169 typedef iwrc (*EJDB_EXEC_VISITOR)(struct _EJDB_EXEC *ctx, EJDB_DOC doc, int64_t *step); 170 171 /** 172 * @brief Query execution context. 173 * Passed to `ejdb_exec()` to execute database query. 174 */ 175 typedef struct _EJDB_EXEC { 176 EJDB db; /**< EJDB database object. Required. */ 177 JQL q; /**< Query object to be executed. Created by `jql_create()` Required. */ 178 EJDB_EXEC_VISITOR visitor; /**< Optional visitor to handle documents in result set. */ 179 void *opaque; /**< Optional user data passed to visitor functions. */ 180 int64_t skip; /**< Number of records to skip. Takes precedence over `skip` encoded in query. */ 181 int64_t limit; /**< Result set size limitation. Zero means no limitations. Takes precedence over `limit` 182 encoded in query. */ 183 int64_t cnt; /**< Number of result documents processed by `visitor` */ 184 IWXSTR *log; /**< Optional query execution log buffer. If set major query execution/index selection 185 steps will be logged into */ 186 IWPOOL *pool; /**< Optional pool which can be used in query apply */ 187 } EJDB_EXEC; 188 189 /** 190 * @brief Open storage file. 191 * 192 * Storage can be opened only by one single process at time. 193 * 194 * @param opts Operating options. Can be stack allocated or disposed after `ejdb_open()` call. 195 * @param [out] ejdbp EJDB storage handle pointer as result. 196 */ 197 IW_EXPORT WUR iwrc ejdb_open(const EJDB_OPTS *opts, EJDB *ejdbp); 198 199 /** 200 * @brief Closes storage and frees up all resources. 201 * @param [in,out] ejdbp Pointer to storage handle, will set to zero oncompletion. 202 * 203 * @return `0` on success. 204 * Any non zero error codes. 205 */ 206 IW_EXPORT iwrc ejdb_close(EJDB *ejdbp); 207 208 /** 209 * @brief Executes a query. 210 * 211 * The `ux` structure should be configured before this call, 212 * usually it is a stack allocated object. 213 * 214 * Query object should be created by `jql_create()`. 215 * 216 * Example: 217 * 218 * @code {.c} 219 * 220 * JQL q; 221 * iwrc rc = jql_create(&q, "mycollection", "/[firstName=?]"); 222 * RCRET(rc); 223 * 224 * jql_set_str(q, 0, 0, "Andy"); // Set positional string query parameter 225 * 226 * EJDB_EXEC ux = { 227 * .db = db, 228 * .q = q, 229 * .visitor = my_query_results_visitor_func 230 * }; 231 * rc = ejdb_exec(&ux); // Execute query 232 * jql_destroy(&q); // Destroy query object 233 * 234 * @endcode 235 * 236 * Query object can be reused in many `ejdb_exec()` calls 237 * with different positional/named parameters. 238 * 239 * @param [in] ux Query execution params, object state may be changes during query execution. 240 * Not zero. 241 * 242 * @return `0` on success. 243 * Any non zero error codes. 244 */ 245 IW_EXPORT WUR iwrc ejdb_exec(EJDB_EXEC *ux); 246 247 /** 248 * @brief Executes a given query and builds a query result as linked list of documents. 249 * 250 * @warning Getting whole query result as linked list can be memory consuming for large collections. 251 * Consider use of `ejdb_exec()` with visitor or set a positive `limit` value. 252 * 253 * @param db Database handle. Not zero. 254 * @param q Query object. Not zero. 255 * @param [out] first First document in result set or zero if no matched documents found. 256 * @param limit Maximum number of documents in result set. Takes precedence over `limit` encoded in query. 257 * Zero means a `limit` encoded in `q` will be used. 258 * @param pool Memory pool will keep documents allocated in result set. Not zero. 259 * 260 * @return `0` on success. 261 * Any non zero error codes. 262 */ 263 IW_EXPORT WUR iwrc ejdb_list(EJDB db, JQL q, EJDB_DOC *first, int64_t limit, IWPOOL *pool); 264 265 /** 266 * @brief Executes a given query `q` then returns `count` of matched documents. 267 * 268 * @param db Database handle. Not zero. 269 * @param q Query object. Not zero. 270 * @param [out] count Placeholder for number of matched documents. Not zero. 271 * @param limit Limit of matched rows. Makes sense for update queries. 272 * 273 */ 274 IW_EXPORT WUR iwrc ejdb_count(EJDB db, JQL q, int64_t *count, int64_t limit); 275 276 /** 277 * @brief Executes a given query `q` then returns `count` of matched documents. 278 * 279 * @param db Database handle. Not zero. 280 * @param coll Name of document collection. 281 * Can be zero, in what collection name should be encoded in query. 282 * @param q Query text. Not zero. 283 * @param [out] count Placeholder for number of matched documents. Not zero. 284 * @param limit Limit of matched rows. Makes sense for update queries. 285 * 286 */ 287 IW_EXPORT WUR iwrc ejdb_count2(EJDB db, const char *coll, const char *q, int64_t *count, int64_t limit); 288 289 /** 290 * @brief Executes update query assuming that query object contains `apply` clause. 291 * Similar to `ejdb_count`. 292 * 293 * @param db Database handle. Not zero. 294 * @param q Query object. Not zero. 295 */ 296 IW_EXPORT WUR iwrc ejdb_update(EJDB db, JQL q); 297 298 /** 299 * @brief Executes update query assuming that query object contains `apply` clause. 300 * Similar to `ejdb_count`. 301 * 302 * @param db Database handle. Not zero. 303 * @param coll Name of document collection. 304 * Can be zero, in what collection name should be encoded in query. 305 * @param q Query text. Not zero. 306 */ 307 IW_EXPORT WUR iwrc ejdb_update2(EJDB db, const char *coll, const char *q); 308 309 /** 310 * @brief Executes a given `query` and builds a result as linked list of documents. 311 * 312 * @note Returned `listp` must be disposed by `ejdb_list_destroy()` 313 * @warning Getting whole query result as linked list can be memory consuming for large collections. 314 * Consider use of `ejdb_exec()` with visitor or set a positive `limit` value. 315 * 316 * @param db Database handle. Not zero. 317 * @param coll Collection name. If zero, collection name must be encoded in query. 318 * @param query Query text. Not zero. 319 * @param limit Maximum number of documents in result set. Takes precedence over `limit` encoded in query. 320 * Zero means a `limit` encoded in `query` will be used. 321 * @param [out] listp Holder for query result, should be disposed by `ejdb_list_destroy()`. 322 * Not zero. 323 * 324 * @return `0` on success. 325 * Any non zero error codes. 326 */ 327 IW_EXPORT WUR iwrc ejdb_list2(EJDB db, const char *coll, const char *query, int64_t limit, EJDB_LIST *listp); 328 329 /** 330 * @brief Executes a given `query` and builds a result as linked list of documents. 331 * 332 * @note Returned `listp` must be disposed by `ejdb_list_destroy()` 333 * @warning Getting whole query result as linked list can be memory consuming for large collections. 334 * Consider use of `ejdb_exec()` with visitor or set a positive `limit` value. 335 * 336 * @param db Database handle. Not zero. 337 * @param coll Collection name. If zero, collection name must be encoded in query. 338 * @param query Query text. Not zero. 339 * @param limit Maximum number of documents in result set. Takes precedence over `limit` encoded in query. 340 * @param log Optional buffer to collect query execution / index usage info. 341 * @param [out] listp Holder for query result, should be disposed by `ejdb_list_destroy()`. 342 * Not zero. 343 * 344 * @return `0` on success. 345 * Any non zero error codes. 346 */ 347 IW_EXPORT WUR iwrc ejdb_list3( 348 EJDB db, const char *coll, const char *query, int64_t limit, 349 IWXSTR *log, EJDB_LIST *listp); 350 351 /** 352 * @brief Executes a given query `q` and builds a result as linked list of documents (`listp`). 353 * 354 * @note Returned `listp` must be disposed by `ejdb_list_destroy()` 355 * @warning Getting whole query result as linked list can be memory consuming for large collections. 356 * Consider use of `ejdb_exec()` with visitor or set a positive `limit` value. 357 * 358 * @param db Database handle. Not zero. 359 * @param q Query object. Not zero. 360 * @param limit Maximum number of documents in result set. Takes precedence over `limit` encoded in query. 361 * @param log Optional buffer to collect query execution / index usage info. 362 * @param [out] listp Holder for query result, should be disposed by `ejdb_list_destroy()`. 363 * Not zero. 364 * 365 * @return `0` on success. 366 * Any non zero error codes. 367 */ 368 IW_EXPORT WUR iwrc ejdb_list4(EJDB db, JQL q, int64_t limit, IWXSTR *log, EJDB_LIST *listp); 369 370 /** 371 * @brief Destroy query result set and set `listp` to zero. 372 * @param [in,out] listp Can be zero. 373 */ 374 IW_EXPORT void ejdb_list_destroy(EJDB_LIST *listp); 375 376 /** 377 * @brief Apply rfc6902/rfc7396 JSON patch to the document identified by `id`. 378 * 379 * @param db Database handle. Not zero. 380 * @param coll Collection name. Not zero. 381 * @param patchjson JSON patch conformed to rfc6902 or rfc7396 specification. 382 * @param id Document id. Not zero. 383 * 384 * @return `0` on success. 385 * `IWKV_ERROR_NOTFOUND` if document not found. 386 * Any non zero error codes. 387 */ 388 IW_EXPORT WUR iwrc ejdb_patch(EJDB db, const char *coll, const char *patchjson, int64_t id); 389 390 /** 391 * @brief Apply rfc6902/rfc7396 JSON patch to the document identified by `id`. 392 * 393 * @param db Database handle. Not zero. 394 * @param coll Collection name. Not zero. 395 * @param patch JSON patch conformed to rfc6902 or rfc7396 specification. 396 * @param id Document id. Not zero. 397 * 398 * @return `0` on success. 399 * `IWKV_ERROR_NOTFOUND` if document not found. 400 * Any non zero error codes. 401 */ 402 IW_EXPORT WUR iwrc ejdb_patch_jbn(EJDB db, const char *coll, JBL_NODE patch, int64_t id); 403 404 405 /** 406 * @brief Apply rfc6902/rfc7396 JSON patch to the document identified by `id`. 407 * 408 * @param db Database handle. Not zero. 409 * @param coll Collection name. Not zero. 410 * @param patch JSON patch conformed to rfc6902 or rfc7396 specification. 411 * @param id Document id. Not zero. 412 * 413 * @return `0` on success. 414 * `IWKV_ERROR_NOTFOUND` if document not found. 415 * Any non zero error codes. 416 */ 417 IW_EXPORT WUR iwrc ejdb_patch_jbl(EJDB db, const char *coll, JBL patch, int64_t id); 418 419 /** 420 * @brief Apply JSON merge patch (rfc7396) to the document identified by `id` or 421 * insert new document under specified `id`. 422 * @note This is an atomic operation. 423 * 424 * @param db Database handle. Not zero. 425 * @param coll Collection name. Not zero. 426 * @param patchjson JSON merge patch conformed to rfc7396 specification. 427 * @param id Document id. Not zero. 428 * 429 */ 430 IW_EXPORT WUR iwrc ejdb_merge_or_put(EJDB db, const char *coll, const char *patchjson, int64_t id); 431 432 /** 433 * @brief Apply JSON merge patch (rfc7396) to the document identified by `id` or 434 * insert new document under specified `id`. 435 * @note This is an atomic operation. 436 * 437 * @param db Database handle. Not zero. 438 * @param coll Collection name. Not zero. 439 * @param patch JSON merge patch conformed to rfc7396 specification. 440 * @param id Document id. Not zero. 441 * 442 */ 443 IW_EXPORT WUR iwrc ejdb_merge_or_put_jbn(EJDB db, const char *coll, JBL_NODE patch, int64_t id); 444 445 /** 446 * @brief Apply JSON merge patch (rfc7396) to the document identified by `id` or 447 * insert new document under specified `id`. 448 * @note This is an atomic operation. 449 * 450 * @param db Database handle. Not zero. 451 * @param coll Collection name. Not zero. 452 * @param patch JSON merge patch conformed to rfc7396 specification. 453 * @param id Document id. Not zero. 454 * 455 */ 456 IW_EXPORT WUR iwrc ejdb_merge_or_put_jbl(EJDB db, const char *coll, JBL patch, int64_t id); 457 458 /** 459 * @brief Save a given `jbl` document under specified `id`. 460 * 461 * @param db Database handle. Not zero. 462 * @param coll Collection name. Not zero. 463 * @param jbl JSON document. Not zero. 464 * @param id Document identifier. Not zero. 465 * 466 * @return `0` on success. 467 * Any non zero error codes. 468 */ 469 IW_EXPORT WUR iwrc ejdb_put(EJDB db, const char *coll, JBL jbl, int64_t id); 470 471 /** 472 * @brief Save a given `jbn` document under specified `id`. 473 * 474 * @param db Database handle. Not zero. 475 * @param coll Collection name. Not zero. 476 * @param jbn JSON document. Not zero. 477 * @param id Document identifier. Not zero. 478 * 479 * @return `0` on success. 480 * Any non zero error codes. 481 */ 482 IW_EXPORT WUR iwrc ejdb_put_jbn(EJDB db, const char *coll, JBL_NODE jbn, int64_t id); 483 484 /** 485 * @brief Save a document into `coll` under new identifier. 486 * 487 * @param db Database handle. Not zero. 488 * @param coll Collection name. Not zero. 489 * @param jbl JSON document. Not zero. 490 * @param [out] oid Placeholder for new document id. Not zero. 491 * 492 * @return `0` on success. 493 * Any non zero error codes. 494 */ 495 IW_EXPORT WUR iwrc ejdb_put_new(EJDB db, const char *coll, JBL jbl, int64_t *oid); 496 497 /** 498 * @brief Save a document into `coll` under new identifier. 499 * 500 * @param db Database handle. Not zero. 501 * @param coll Collection name. Not zero. 502 * @param jbn JSON document. Not zero. 503 * @param [out] oid Placeholder for new document id. Not zero. 504 * 505 * @return `0` on success. 506 * Any non zero error codes. 507 */ 508 IW_EXPORT iwrc ejdb_put_new_jbn(EJDB db, const char *coll, JBL_NODE jbn, int64_t *id); 509 510 /** 511 * @brief Retrieve document identified by given `id` from collection `coll`. 512 * 513 * @param db Database handle. Not zero. 514 * @param coll Collection name. Not zero. 515 * @param id Document id. Not zero. 516 * @param [out] jblp Placeholder for document. 517 * Must be released by `jbl_destroy()` 518 * 519 * @return `0` on success. 520 * `IWKV_ERROR_NOTFOUND` if document not found. 521 * `IW_ERROR_NOT_EXISTS` if collection `coll` is not exists in db. 522 * Any non zero error codes. 523 */ 524 IW_EXPORT WUR iwrc ejdb_get(EJDB db, const char *coll, int64_t id, JBL *jblp); 525 526 /** 527 * @brief Remove document identified by given `id` from collection `coll`. 528 * 529 * @param db Database handle. Not zero. 530 * @param coll Collection name. Not zero. 531 * @param id Document id. Not zero. 532 * 533 * @return `0` on success. 534 * `IWKV_ERROR_NOTFOUND` if document not found. 535 * Any non zero error codes. 536 */ 537 IW_EXPORT iwrc ejdb_del(EJDB db, const char *coll, int64_t id); 538 539 /** 540 * @brief Remove collection under the given name `coll`. 541 * 542 * @param db Database handle. Not zero. 543 * @param coll Collection name. Not zero. 544 * 545 * @return `0` on success. 546 * Will return `0` if collection is not found. 547 * Any non zero error codes. 548 */ 549 IW_EXPORT iwrc ejdb_remove_collection(EJDB db, const char *coll); 550 551 /** 552 * @brief Rename collection `coll` to `new_coll`. 553 * 554 * @param db Database handle. Not zero. 555 * @param coll Old collection name. Not zero. 556 * @param new_coll New collection name. 557 * @return `0` on success. 558 * - `EJDB_ERROR_COLLECTION_NOT_FOUND` - if source `coll` is not found. 559 * - `EJDB_ERROR_TARGET_COLLECTION_EXISTS` - if `new_coll` is exists already. 560 * - Any other non zero error codes. 561 */ 562 IW_EXPORT iwrc ejdb_rename_collection(EJDB db, const char *coll, const char *new_coll); 563 564 /** 565 * @brief Create collection with given name if it has not existed before 566 * 567 * @param db Database handle. Not zero. 568 * @param coll Collection name. Not zero. 569 * 570 * @return `0` on success. 571 * Any non zero error codes. 572 */ 573 IW_EXPORT iwrc ejdb_ensure_collection(EJDB db, const char *coll); 574 575 /** 576 * @brief Create index with specified parameters if it has not existed before. 577 * 578 * @note Index `path` must be fully specified as rfc6901 JSON pointer 579 * and must not countain unspecified `*`/`**` element in middle sections. 580 * @see ejdb_idx_mode_t. 581 * 582 * Example document: 583 * 584 * @code 585 * { 586 * "address" : { 587 * "street": "High Street" 588 * } 589 * } 590 * @endcode 591 * 592 * Create unique index over all street names in nested address object: 593 * 594 * @code {.c} 595 * iwrc rc = ejdb_ensure_index(db, "mycoll", "/address/street", EJDB_IDX_UNIQUE | EJDB_IDX_STR); 596 * @endcode 597 * 598 * @param db Database handle. Not zero. 599 * @param coll Collection name. Not zero. 600 * @param path rfc6901 JSON pointer to indexed field. 601 * @param mode Index mode. 602 * 603 * @return `0` on success. 604 * `EJDB_ERROR_INVALID_INDEX_MODE` Invalid `mode` specified 605 * `EJDB_ERROR_MISMATCHED_INDEX_UNIQUENESS_MODE` trying to create non unique index over existing unique or vice 606 * versa. 607 * Any non zero error codes. 608 * 609 */ 610 IW_EXPORT iwrc ejdb_ensure_index(EJDB db, const char *coll, const char *path, ejdb_idx_mode_t mode); 611 612 /** 613 * @brief Remove index if it has existed before. 614 * 615 * @param db Database handle. Not zero. 616 * @param coll Collection name. Not zero. 617 * @param path rfc6901 JSON pointer to indexed field. 618 * @param mode Index mode. 619 * 620 * @return `0` on success. 621 * Will return `0` if collection is not found. 622 * Any non zero error codes. 623 */ 624 IW_EXPORT iwrc ejdb_remove_index(EJDB db, const char *coll, const char *path, ejdb_idx_mode_t mode); 625 626 /** 627 * @brief Returns JSON document describind database structure. 628 * @note Returned `jblp` must be disposed by `jbl_destroy()` 629 * 630 * Example database metadata: 631 * @code {.json} 632 * 633 * { 634 * "version": "2.0.0", // EJDB engine version 635 * "file": "db.jb", // Path to storage file 636 * "size": 16384, // Storage file size in bytes 637 * "collections": [ // List of collections 638 * { 639 * "name": "c1", // Collection name 640 * "dbid": 3, // Collection database ID 641 * "rnum": 2, // Number of documents in collection 642 * "indexes": [ // List of collections indexes 643 * { 644 * "ptr": "/n", // rfc6901 JSON pointer to indexed field 645 * "mode": 8, // Index mode. Here is EJDB_IDX_I64 646 * "idbf": 96, // Index flags. See iwdb_flags_t 647 * "dbid": 4, // Index database ID 648 * "rnum": 2 // Number records stored in index database 649 * } 650 * ] 651 * } 652 * ] 653 * } 654 * @endcode 655 * 656 * @param db Database handle. Not zero. 657 * @param [out] jblp JSON object describing ejdb storage. 658 * Must be disposed by `jbl_destroy()` 659 */ 660 IW_EXPORT iwrc ejdb_get_meta(EJDB db, JBL *jblp); 661 662 /** 663 * Creates an online database backup image and copies it into the specified `target_file`. 664 * During online backup phase read/write database operations are allowed and not 665 * blocked for significant amount of time. Backup finish time is placed into `ts` 666 * as number of milliseconds since epoch. 667 * 668 * Online backup guaranties what all records before `ts` timestamp will 669 * be stored in backup image. Later, online backup image can be 670 * opened as ordinary database file. 671 * 672 * @note In order to avoid deadlocks: close all opened database cursors 673 * before calling this method or do call in separate thread. 674 * 675 * @param Database handle. Not zero. 676 * @param [out] ts Backup completion timestamp 677 * @param target_file backup file path 678 */ 679 IW_EXPORT iwrc ejdb_online_backup(EJDB db, uint64_t *ts, const char *target_file); 680 681 /** 682 * @brief Get access to underlying IWKV storage. 683 * Use it with caution. 684 * 685 * @param db Database handle. Not zero. 686 * @param [out] kvp Placeholder for IWKV storage. 687 */ 688 IW_EXPORT iwrc ejdb_get_iwkv(EJDB db, IWKV *kvp); 689 690 /** 691 * @brief Return `\0` terminated ejdb2 source GIT revision hash. 692 */ 693 IW_EXPORT const char* ejdb_git_revision(void); 694 695 /** 696 * @brief Return `\0` terminated EJDB version string. 697 */ 698 IW_EXPORT const char* ejdb_version_full(void); 699 700 /** 701 * @brief Return major library version. 702 */ 703 IW_EXPORT unsigned int ejdb_version_major(void); 704 705 /** 706 * @brief Return minor library version. 707 */ 708 IW_EXPORT unsigned int ejdb_version_minor(void); 709 710 /** 711 * @brief Return patch library version. 712 */ 713 IW_EXPORT unsigned int ejdb_version_patch(void); 714 715 IW_EXTERN_C_END 716 #endif 717