1 /**************************************************************************************************
2 * C/C++ API for EJDB database library http://ejdb.org
3 * Copyright (C) 2012-2015 Softmotions Ltd <info@softmotions.com>
5 * This file is part of EJDB.
6 * EJDB is free software; you can redistribute it and/or modify it under the terms of
7 * the GNU Lesser General Public License as published by the Free Software Foundation; either
8 * version 2.1 of the License or any later version. EJDB is distributed in the hope
9 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
11 * License for more details.
12 * You should have received a copy of the GNU Lesser General Public License along with EJDB;
13 * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
14 * Boston, MA 02111-1307 USA.
15 *************************************************************************************************/
25 #ifndef EJDB_MAX_IMPORTED_BSON_SIZE
26 //64 MB is the default maximum size of bson object imported with `ejdbimport()`
27 #define EJDB_MAX_IMPORTED_BSON_SIZE 67108864
30 struct EJDB; /**< EJDB database object. */
31 typedef struct EJDB EJDB;
33 struct EJCOLL; /*< EJDB collection handle. */
34 typedef struct EJCOLL EJCOLL;
36 struct EJQ; /**< EJDB query. */
37 typedef struct EJQ EJQ;
39 typedef struct { /**< EJDB collection tuning options. */
40 bool large; /**< Large collection. It can be larger than 2GB. Default false */
41 bool compressed; /**< Collection records will be compressed with DEFLATE compression. Default: false */
42 int64_t records; /**< Expected records number in the collection. Default: 128K */
43 int cachedrecords; /**< Maximum number of records cached in memory. Default: 0 */
47 typedef TCLIST* EJQRESULT; /**< EJDB query result */
49 #define JBMAXCOLNAMELEN 128
51 enum { /** Error codes */
52 JBEINVALIDCOLNAME = 9000, /**< Invalid collection name. */
53 JBEINVALIDBSON = 9001, /**< Invalid bson object. */
54 JBEINVALIDBSONPK = 9002, /**< Invalid bson object id. */
55 JBEQINVALIDQCONTROL = 9003, /**< Invalid query control field starting with '$'. */
56 JBEQINOPNOTARRAY = 9004, /**< $strand, $stror, $in, $nin, $bt keys requires not empty array value. */
57 JBEMETANVALID = 9005, /**< Inconsistent database metadata. */
58 JBEFPATHINVALID = 9006, /**< Invalid field path value. */
59 JBEQINVALIDQRX = 9007, /**< Invalid query regexp value. */
60 JBEQRSSORTING = 9008, /**< Result set sorting error. */
61 JBEQERROR = 9009, /**< Query generic error. */
62 JBEQUPDFAILED = 9010, /**< Updating failed. */
63 JBEQONEEMATCH = 9011, /**< Only one $elemMatch allowed in the fieldpath. */
64 JBEQINCEXCL = 9012, /**< $fields hint cannot mix include and exclude fields */
65 JBEQACTKEY = 9013, /**< action key in $do block can only be one of: $join, $slice */
66 JBEMAXNUMCOLS = 9014, /**< Exceeded the maximum number of collections per database */
67 JBEEI = 9015, /**< EJDB export/import error */
68 JBEEJSONPARSE = 9016, /**< JSON parsing failed */
69 JBETOOBIGBSON = 9017, /**< BSON size is too big */
70 JBEINVALIDCMD = 9018 /**< Invalid ejdb command specified */
73 enum { /** Database open modes */
74 JBOREADER = 1 << 0, /**< Open as a reader. */
75 JBOWRITER = 1 << 1, /**< Open as a writer. */
76 JBOCREAT = 1 << 2, /**< Create if db file not exists. */
77 JBOTRUNC = 1 << 3, /**< Truncate db on open. */
78 JBONOLCK = 1 << 4, /**< Open without locking. */
79 JBOLCKNB = 1 << 5, /**< Lock without blocking. */
80 JBOTSYNC = 1 << 6 /**< Synchronize every transaction. */
83 enum { /** Index modes, index types. */
84 JBIDXDROP = 1 << 0, /**< Drop index. */
85 JBIDXDROPALL = 1 << 1, /**< Drop index for all types. */
86 JBIDXOP = 1 << 2, /**< Optimize indexes. */
87 JBIDXREBLD = 1 << 3, /**< Rebuild index. */
88 JBIDXNUM = 1 << 4, /**< Number index. */
89 JBIDXSTR = 1 << 5, /**< String index.*/
90 JBIDXARR = 1 << 6, /**< Array token index. */
91 JBIDXISTR = 1 << 7 /**< Case insensitive string index */
94 enum { /*< Query search mode flags in ejdbqryexecute() */
95 JBQRYCOUNT = 1, /*< Query only count(*) */
96 JBQRYFINDONE = 1 << 1 /*< Fetch first record only */
100 * Returns EJDB library version string. Eg: "1.1.13"
102 EJDB_EXPORT const char *ejdbversion();
105 * Return true if passed `oid` string cat be converted to valid
106 * 12 bit BSON object identifier (OID).
109 EJDB_EXPORT bool ejdbisvalidoidstr(const char *oid);
112 * Get the message string corresponding to an error code.
113 * @param ecode `ecode' specifies the error code.
114 * @return The return value is the message string of the error code.
116 EJDB_EXPORT const char *ejdberrmsg(int ecode);
119 * Get the last happened error code of a EJDB database object.
121 * @return The return value is the last happened error code.
123 EJDB_EXPORT int ejdbecode(EJDB *jb);
126 * Create a EJDB database object. On error returns NULL.
127 * Created pointer must be freed by ejdbdel()
128 * @return The return value is the new EJDB database object or NULL if error.
130 EJDB_EXPORT EJDB* ejdbnew(void);
133 * Delete database object. If the database is not closed, it is closed implicitly.
134 * Note that the deleted object and its derivatives can not be used anymore
137 EJDB_EXPORT void ejdbdel(EJDB *jb);
140 * Close a table database object. If a writer opens a database but does not close it appropriately,
141 * the database will be broken.
142 * @param jb EJDB handle.
143 * @return If successful return true, otherwise return false.
145 EJDB_EXPORT bool ejdbclose(EJDB *jb);
148 * Opens EJDB database.
149 * @param jb Database object created with `ejdbnew'
150 * @param path Path to the database file.
151 * @param mode Open mode bitmask flags:
152 * `JBOREADER` Open as a reader.
153 * `JBOWRITER` Open as a writer.
154 * `JBOCREAT` Create db if it not exists
155 * `JBOTRUNC` Truncate db.
156 * `JBONOLCK` Open without locking.
157 * `JBOLCKNB` Lock without blocking.
158 * `JBOTSYNC` Synchronize every transaction.
161 EJDB_EXPORT bool ejdbopen(EJDB *jb, const char *path, int mode);
165 * Return true if database is in open state
166 * @param jb EJDB database hadle
167 * @return True if database is in open state otherwise false
169 EJDB_EXPORT bool ejdbisopen(EJDB *jb);
172 * Retrieve collection handle for collection specified `collname`.
173 * If collection with specified name does't exists it will return NULL.
174 * @param jb EJDB handle.
175 * @param colname Name of collection.
176 * @return If error NULL will be returned.
178 EJDB_EXPORT EJCOLL* ejdbgetcoll(EJDB *jb, const char *colname);
181 * Allocate a new TCLIST populated with shallow copy of all
182 * collection handles (EJCOLL) currently opened.
183 * @param jb EJDB handle.
184 * @return If error NULL will be returned.
186 EJDB_EXPORT TCLIST* ejdbgetcolls(EJDB *jb);
189 * Same as ejdbgetcoll() but automatically creates new collection
190 * if it does't exists.
192 * @param jb EJDB handle.
193 * @param colname Name of collection.
194 * @param opts Options applied only for newly created collection.
195 * For existing collections it takes no effect.
197 * @return Collection handle or NULL if error.
199 EJDB_EXPORT EJCOLL* ejdbcreatecoll(EJDB *jb, const char *colname, EJCOLLOPTS *opts);
202 * Removes collections specified by `colname`
203 * @param jb EJDB handle.
204 * @param colname Name of collection.
205 * @param unlink It true the collection db file and all of its index files will be removed.
206 * @return If successful return true, otherwise return false.
208 EJDB_EXPORT bool ejdbrmcoll(EJDB *jb, const char *colname, bool unlinkfile);
211 * Persist BSON object in the collection.
212 * If saved bson does't have _id primary key then `oid` will be set to generated bson _id,
213 * otherwise `oid` will be set to the current bson's _id field.
215 * NOTE: Field names of passed `bs` object may not contain `$` and `.` characters,
216 * error condition will be fired in this case.
218 * @param coll JSON collection handle.
219 * @param bson BSON object id pointer.
220 * @param oid OID pointer will be set to object's _id
221 * @return If successful return true, otherwise return false.
223 EJDB_EXPORT bool ejdbsavebson(EJCOLL *coll, bson *bs, bson_oid_t *oid);
226 * Persist BSON object in the collection.
227 * If saved bson does't have _id primary key then `oid` will be set to generated bson _id,
228 * otherwise `oid` will be set to the current bson's _id field.
230 * NOTE: Field names of passed `bs` object may not contain `$` and `.` characters,
231 * error condition will be fired in this case.
233 * @param coll JSON collection handle.
234 * @param bs BSON object id pointer.
235 * @param oid OID pointer will be set to object's _id
236 * @param merge If true the merge will be performend with old and new objects. Otherwise old object will be replaced.
237 * @return If successful return true, otherwise return false.
239 EJDB_EXPORT bool ejdbsavebson2(EJCOLL *jcoll, bson *bs, bson_oid_t *oid, bool merge);
241 EJDB_EXPORT bool ejdbsavebson3(EJCOLL *jcoll, const void *bsdata, bson_oid_t *oid, bool merge);
244 * Remove BSON object from collection.
245 * The `oid` argument should points the primary key (_id)
246 * of the bson record to be removed.
247 * @param coll JSON collection ref.
248 * @param oid BSON object id pointer.
251 EJDB_EXPORT bool ejdbrmbson(EJCOLL *coll, bson_oid_t *oid);
254 * Load BSON object with specified 'oid'.
255 * If loaded bson is not NULL it must be freed by bson_del().
258 * @return BSON object if exists otherwise return NULL.
260 EJDB_EXPORT bson* ejdbloadbson(EJCOLL *coll, const bson_oid_t *oid);
263 * Create the query object.
265 * Sucessfully created queries must be destroyed with ejdbquerydel().
267 * See the complete query language specification:
269 * http://ejdb.org/doc/ql/ql.html
271 * Many query examples can be found in `src/ejdb/test/ejdbtest2.c` test case.
273 * @param jb EJDB database handle.
274 * @param qobj Main BSON query object.
275 * @param orqobjs Array of additional OR query objects (joined with OR predicate).
276 * @param orqobjsnum Number of OR query objects.
277 * @param hints BSON object with query hints.
278 * @return On success return query handle. On error returns NULL.
280 EJDB_EXPORT EJQ* ejdbcreatequery(EJDB *jb, bson *qobj, bson *orqobjs, int orqobjsnum, bson *hints);
284 * Alternative query creation method convenient to use
285 * with `ejdbqueryaddor` and `ejdbqueryhints` methods.
286 * @param jb EJDB database handle.
287 * @param qobj Main query object BSON data.
288 * @return On success return query handle. On error returns NULL.
290 EJDB_EXPORT EJQ* ejdbcreatequery2(EJDB *jb, const void *qbsdata);
293 * Add OR restriction to query object.
294 * @param jb EJDB database handle.
295 * @param q Query handle.
296 * @param orbsdata OR restriction BSON data.
297 * @return NULL on error.
299 EJDB_EXPORT EJQ* ejdbqueryaddor(EJDB *jb, EJQ *q, const void *orbsdata);
302 * Set hints for the query.
303 * @param jb EJDB database handle.
304 * @param hintsbsdata Query hints BSON data.
305 * @return NULL on error.
307 EJDB_EXPORT EJQ* ejdbqueryhints(EJDB *jb, EJQ *q, const void *hintsbsdata);
310 * Destroy query object created with ejdbcreatequery().
313 EJDB_EXPORT void ejdbquerydel(EJQ *q);
316 * Set index for JSON field in EJDB collection.
318 * - Available index types:
319 * - `JBIDXSTR` String index for JSON string values.
320 * - `JBIDXISTR` Case insensitive string index for JSON string values.
321 * - `JBIDXNUM` Index for JSON number values.
322 * - `JBIDXARR` Token index for JSON arrays and string values.
324 * - One JSON field can have several indexes for different types.
326 * - Available index operations:
327 * - `JBIDXDROP` Drop index of specified type.
328 * - Eg: flag = JBIDXDROP | JBIDXNUM (Drop number index)
329 * - `JBIDXDROPALL` Drop index for all types.
330 * - `JBIDXREBLD` Rebuild index of specified type.
331 * - `JBIDXOP` Optimize index of specified type. (Optimize the B+ tree index file)
334 * - Set index for JSON path `addressbook.number` for strings and numbers:
335 * `ejdbsetindex(ccoll, "album.number", JBIDXSTR | JBIDXNUM)`
336 * - Set index for array:
337 * `ejdbsetindex(ccoll, "album.tags", JBIDXARR)`
338 * - Rebuild previous index:
339 * `ejdbsetindex(ccoll, "album.tags", JBIDXARR | JBIDXREBLD)`
341 * Many index examples can be found in `testejdb/t2.c` test case.
343 * @param coll Collection handle.
344 * @param ipath BSON field path.
345 * @param flags Index flags.
348 EJDB_EXPORT bool ejdbsetindex(EJCOLL *coll, const char *ipath, int flags);
351 * Execute the query against EJDB collection.
352 * It is better to execute update queries with specified `JBQRYCOUNT` control
353 * flag avoid unnecessarily rows fetching.
355 * @param jcoll EJDB database
356 * @param q Query handle created with ejdbcreatequery()
357 * @param count Output count pointer. Result set size will be stored into it.
358 * @param qflags Execution flag.
359 * * `JBQRYCOUNT` The only count of matching records will be computed
360 * without resultset, this operation is analog of count(*)
361 * in SQL and can be faster than operations with resultsets.
362 * @param log Optional extended string to collect debug information during query execution, can be NULL.
363 * @return TCLIST with matched bson records data.
364 * If (qflags & JBQRYCOUNT) then NULL will be returned
365 * and only count reported.
367 EJDB_EXPORT EJQRESULT ejdbqryexecute(EJCOLL *jcoll, const EJQ *q, uint32_t *count, int qflags, TCXSTR *log);
370 * Returns the number of elements in the query result set.
371 * @param qr Query result set. Can be `NULL` in this case 0 is returned.
373 EJDB_EXPORT int ejdbqresultnum(EJQRESULT qr);
376 * Gets the pointer of query result BSON data buffer at the specified position `pos`.
377 * If `qr` is `NULL` or `idx` is put of index range then the `NULL` pointer will be returned.
378 * @param qr Query result set object.
379 * @param pos Zero based position of the record.
381 EJDB_EXPORT const void* ejdbqresultbsondata(EJQRESULT qr, int pos, int *size);
384 * Disposes the query result set and frees a records buffers.
386 EJDB_EXPORT void ejdbqresultdispose(EJQRESULT qr);
389 * Convenient method to execute update queries.
391 * See the complete query language specification:
393 * http://ejdb.org/doc/ql/ql.html
396 * @return Number of updated records
398 EJDB_EXPORT uint32_t ejdbupdate(EJCOLL *jcoll, bson *qobj, bson *orqobjs, int orqobjsnum, bson *hints, TCXSTR *log);
401 * Provides 'distinct' operation over query
403 * (http://docs.mongodb.org/manual/reference/method/db.collection.distinct/).
405 * @param jcoll EJDB database collection handle.
406 * @param fpath Field path to collect distinct values from.
407 * @param qobj Main BSON query object.
408 * @param orqobjs Array of additional OR query objects (joined with OR predicate).
409 * @param orqobjsnum Number of OR query objects.
411 * NOTE: Queries with update instruction not supported.
413 * @return Unique values by specified path and query (as BSON array)
415 EJDB_EXPORT bson* ejdbqrydistinct(EJCOLL *jcoll, const char *fpath, bson *qobj, bson *orqobjs, int orqobjsnum, uint32_t *count, TCXSTR *log);
418 * Synchronize content of a EJDB collection database with the file on device.
419 * @param jcoll EJDB collection.
420 * @return On success return true.
422 EJDB_EXPORT bool ejdbsyncoll(EJCOLL *jcoll);
425 * Synchronize entire EJDB database and
426 * all of its collections with storage.
427 * @param jb Database hand
429 EJDB_EXPORT bool ejdbsyncdb(EJDB *jb);
431 /** Begin transaction for EJDB collection. */
432 EJDB_EXPORT bool ejdbtranbegin(EJCOLL *coll);
434 /** Commit transaction for EJDB collection. */
435 EJDB_EXPORT bool ejdbtrancommit(EJCOLL *coll);
437 /** Abort transaction for EJDB collection. */
438 EJDB_EXPORT bool ejdbtranabort(EJCOLL *coll);
440 /** Get current transaction status, it will be placed into txActive*/
441 EJDB_EXPORT bool ejdbtranstatus(EJCOLL *jcoll, bool *txactive);
444 /** Gets description of EJDB database and its collections. */
445 EJDB_EXPORT bson* ejdbmeta(EJDB *jb);
447 /** Export/Import settings used in `ejdbexport()` and `ejdbimport()` functions. */
449 JBJSONEXPORT = 1, //Database collections will be exported as JSON files.
450 JBIMPORTUPDATE = 1 << 1, //Update existing collection entries with imported ones. Missing collections will be created.
451 JBIMPORTREPLACE = 1 << 2 //Recreate all collections and replace all collection data with imported entries.
455 * Exports database collections data to the specified directory.
456 * Database read lock will be taken on each collection.
458 * NOTE: Only data exported as BSONs can be imported with `ejdbimport()`
460 * @param jb EJDB database handle.
461 * @param path The directory path in which data will be exported.
462 * @param cnames List of collection names to export. `NULL` implies that all existing collections will be exported.
463 * @param flags. Can be set to `JBJSONEXPORT` in order to export data as JSON files instead exporting into BSONs.
464 * @param log Optional operation string log buffer.
465 * @return on sucess `true`
467 EJDB_EXPORT bool ejdbexport(EJDB *jb, const char *path, TCLIST *cnames, int flags, TCXSTR *log);
470 * Imports previously exported collections data into ejdb.
471 * Global database write lock will be applied during import operation.
473 * NOTE: Only data exported as BSONs can be imported with `ejdbimport()`
475 * @param jb EJDB database handle.
476 * @param path The directory path in which data resides.
477 * @param cnames List of collection names to import. `NULL` implies that all collections found in `path` will be imported.
478 * @param flags Can be one of:
479 * `JBIMPORTUPDATE` Update existing collection entries with imported ones.
480 * Existing collections will not be recreated.
481 * For existing collections options will not be imported.
483 * `JBIMPORTREPLACE` Recreate existing collections and replace
484 * all their data with imported entries.
485 * Collections options will be imported.
487 * `0` Implies `JBIMPORTUPDATE`
488 * @param log Optional operation log buffer.
491 EJDB_EXPORT bool ejdbimport(EJDB *jb, const char *path, TCLIST *cnames, int flags, TCXSTR *log);
494 * Execute the ejdb database command.
496 * Supported commands:
499 * 1) Exports database collections data. See ejdbexport() method.
502 * "path" : string, //Export files target directory
503 * "cnames" : [string array]|null, //List of collection names to export
504 * "mode" : int|null //Values: null|`JBJSONEXPORT` See ejdbexport() method
509 * "log" : string, //Diagnostic log about executing this command
510 * "error" : string|null, //ejdb error message
511 * "errorCode" : int|0, //ejdb error code
514 * 2) Imports previously exported collections data into ejdb.
517 * "path" : string //Import files source directory
518 * "cnames" : [string array]|null, //List of collection names to import
519 * "mode" : int|null //Values: null|`JBIMPORTUPDATE`|`JBIMPORTREPLACE` See ejdbimport() method
524 * "log" : string, //Diagnostic log about executing this command
525 * "error" : string|null, //ejdb error message
526 * "errorCode" : int|0, //ejdb error code
529 * @param jb EJDB database handle.
530 * @param cmd BSON command spec.
531 * @return Allocated command response BSON object. Caller should call `bson_del()` on it.
533 EJDB_EXPORT bson* ejdbcommand(EJDB *jb, bson *cmdbson);
534 EJDB_EXPORT bson* ejdbcommand2(EJDB *jb, void *cmdbsondata);