Fix: $rename can operate on nested json objects #107
[platform/upstream/ejdb.git] / src / ejdb / ejdb.h
1 /**************************************************************************************************
2  *  C/C++ API for EJDB database library http://ejdb.org
3  *  Copyright (C) 2012-2015 Softmotions Ltd <info@softmotions.com>
4  *
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  *************************************************************************************************/
16
17 #ifndef EJDB_H
18 #define        EJDB_H
19
20 #include "bson.h"
21 #include "tcutil.h"
22
23 EJDB_EXTERN_C_START
24
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
28 #endif
29
30 struct EJDB; /**< EJDB database object. */
31 typedef struct EJDB EJDB;
32
33 struct EJCOLL; /*< EJDB collection handle. */
34 typedef struct EJCOLL EJCOLL;
35
36 struct EJQ; /**< EJDB query. */
37 typedef struct EJQ EJQ;
38
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 */
44 } EJCOLLOPTS;
45
46
47 typedef TCLIST* EJQRESULT; /**< EJDB query result */
48
49 #define JBMAXCOLNAMELEN 128
50
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 */
71 };
72
73 enum { /** Database open modes */
74     JBOREADER = 1u << 0,    /**< Open as a reader. */
75     JBOWRITER = 1u << 1,    /**< Open as a writer. */
76     JBOCREAT = 1u << 2,     /**< Create if db file not exists. */
77     JBOTRUNC = 1u << 3,     /**< Truncate db on open. */
78     JBONOLCK = 1u << 4,     /**< Open without locking. */
79     JBOLCKNB = 1u << 5,     /**< Lock without blocking. */
80     JBOTSYNC = 1u << 6      /**< Synchronize every transaction. */
81 };
82
83 enum { /** Index modes, index types. */
84     JBIDXDROP = 1u << 0,    /**< Drop index. */
85     JBIDXDROPALL = 1u << 1, /**< Drop index for all types. */
86     JBIDXOP = 1u << 2,      /**< Optimize indexes. */
87     JBIDXREBLD = 1u << 3,   /**< Rebuild index. */
88     JBIDXNUM = 1u << 4,     /**< Number index. */
89     JBIDXSTR = 1u << 5,     /**< String index.*/
90     JBIDXARR = 1u << 6,     /**< Array token index. */
91     JBIDXISTR = 1u << 7     /**< Case insensitive string index */
92 };
93
94 enum { /*< Query search mode flags in ejdbqryexecute() */
95     JBQRYCOUNT = 1u,        /*< Query only count(*) */
96     JBQRYFINDONE = 1u << 1  /*< Fetch first record only */
97 };
98
99 /**
100  * Returns EJDB library version string. Eg: "1.1.13"
101  */
102 EJDB_EXPORT const char *ejdbversion();
103
104 /**
105  * Return true if passed `oid` string cat be converted to valid
106  * 12 bit BSON object identifier (OID).
107  * @param oid String
108  */
109 EJDB_EXPORT bool ejdbisvalidoidstr(const char *oid);
110
111 /**
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.
115  */
116 EJDB_EXPORT const char *ejdberrmsg(int ecode);
117
118 /**
119  * Get the last happened error code of a EJDB database object.
120  * @param jb
121  * @return The return value is the last happened error code.
122  */
123 EJDB_EXPORT int ejdbecode(EJDB *jb);
124
125 /**
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.
129  */
130 EJDB_EXPORT EJDB* ejdbnew(void);
131
132 /**
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
135  * @param jb
136  */
137 EJDB_EXPORT void ejdbdel(EJDB *jb);
138
139 /**
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.
144  */
145 EJDB_EXPORT bool ejdbclose(EJDB *jb);
146
147 /**
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.
159  * @return
160  */
161 EJDB_EXPORT bool ejdbopen(EJDB *jb, const char *path, int mode);
162
163
164 /**
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
168  */
169 EJDB_EXPORT bool ejdbisopen(EJDB *jb);
170
171 /**
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.
177  */
178 EJDB_EXPORT EJCOLL* ejdbgetcoll(EJDB *jb, const char *colname);
179
180 /**
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.
185  */
186 EJDB_EXPORT TCLIST* ejdbgetcolls(EJDB *jb);
187
188 /**
189  * Same as ejdbgetcoll() but automatically creates new collection
190  * if it does't exists.
191  *
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.
196  *
197  * @return Collection handle or NULL if error.
198  */
199 EJDB_EXPORT EJCOLL* ejdbcreatecoll(EJDB *jb, const char *colname, EJCOLLOPTS *opts);
200
201 /**
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.
207  */
208 EJDB_EXPORT bool ejdbrmcoll(EJDB *jb, const char *colname, bool unlinkfile);
209
210 /**
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.
214  *
215  * NOTE: Field names of passed `bs` object may not contain `$` and `.` characters,
216  *       error condition will be fired in this case.
217  *
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.
222  */
223 EJDB_EXPORT bool ejdbsavebson(EJCOLL *coll, bson *bs, bson_oid_t *oid);
224
225 /**
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.
229  *
230  * NOTE: Field names of passed `bs` object may not contain `$` and `.` characters,
231  *       error condition will be fired in this case.
232  *
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.
238  */
239 EJDB_EXPORT bool ejdbsavebson2(EJCOLL *jcoll, bson *bs, bson_oid_t *oid, bool merge);
240
241 EJDB_EXPORT bool ejdbsavebson3(EJCOLL *jcoll, const void *bsdata, bson_oid_t *oid, bool merge);
242
243 /**
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.
249  * @return
250  */
251 EJDB_EXPORT bool ejdbrmbson(EJCOLL *coll, bson_oid_t *oid);
252
253 /**
254  * Load BSON object with specified 'oid'.
255  * If loaded bson is not NULL it must be freed by bson_del().
256  * @param coll
257  * @param oid
258  * @return BSON object if exists otherwise return NULL.
259  */
260 EJDB_EXPORT bson* ejdbloadbson(EJCOLL *coll, const bson_oid_t *oid);
261
262 /**
263  * Create the query object.
264  * 
265  * Sucessfully created queries must be destroyed with ejdbquerydel().
266  * 
267  * See the complete query language specification: 
268  * 
269  *      http://ejdb.org/doc/ql/ql.html
270  * 
271  * Many query examples can be found in `src/ejdb/test/ejdbtest2.c` test case.
272  *
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.
279  */
280 EJDB_EXPORT EJQ* ejdbcreatequery(EJDB *jb, bson *qobj, bson *orqobjs, int orqobjsnum, bson *hints);
281
282
283 /**
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.
289  */
290 EJDB_EXPORT EJQ* ejdbcreatequery2(EJDB *jb, const void *qbsdata);
291
292 /**
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.
298  */
299 EJDB_EXPORT EJQ* ejdbqueryaddor(EJDB *jb, EJQ *q, const void *orbsdata);
300
301 /**
302  * Set hints for the query.
303  * @param jb EJDB database handle.
304  * @param hintsbsdata Query hints BSON data.
305  * @return NULL on error.
306  */
307 EJDB_EXPORT EJQ* ejdbqueryhints(EJDB *jb, EJQ *q, const void *hintsbsdata);
308
309 /**
310  * Destroy query object created with ejdbcreatequery().
311  * @param q
312  */
313 EJDB_EXPORT void ejdbquerydel(EJQ *q);
314
315 /**
316  * Set index for JSON field in EJDB collection.
317  *
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.
323  *
324  *  - One JSON field can have several indexes for different types.
325  *
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)
332  *
333  *  Examples:
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)`
340  *
341  *   Many index examples can be found in `testejdb/t2.c` test case.
342  *
343  * @param coll Collection handle.
344  * @param ipath BSON field path.
345  * @param flags Index flags.
346  * @return
347  */
348 EJDB_EXPORT bool ejdbsetindex(EJCOLL *coll, const char *ipath, int flags);
349
350 /**
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.
354  *
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.
366  */
367 EJDB_EXPORT EJQRESULT ejdbqryexecute(EJCOLL *jcoll, const EJQ *q, uint32_t *count, int qflags, TCXSTR *log);
368
369 /**
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.
372  */
373 EJDB_EXPORT int ejdbqresultnum(EJQRESULT qr);
374
375 /**
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.
380  */
381 EJDB_EXPORT const void* ejdbqresultbsondata(EJQRESULT qr, int pos, int *size);
382
383 /**
384  * Disposes the query result set and frees a records buffers.
385  */
386 EJDB_EXPORT void ejdbqresultdispose(EJQRESULT qr);
387
388 /**
389  * Convenient method to execute update queries.
390  *
391  * See the complete query language specification: 
392  * 
393  *      http://ejdb.org/doc/ql/ql.html
394  *
395  *
396  * @return Number of updated records
397  */
398 EJDB_EXPORT uint32_t ejdbupdate(EJCOLL *jcoll, bson *qobj, bson *orqobjs, int orqobjsnum, bson *hints, TCXSTR *log);
399
400 /**
401  * Provides 'distinct' operation over query 
402  * 
403  * (http://docs.mongodb.org/manual/reference/method/db.collection.distinct/).
404  * 
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.
410  * 
411  * NOTE: Queries with update instruction not supported.
412  * 
413  * @return Unique values by specified path and query (as BSON array)
414  */
415 EJDB_EXPORT bson* ejdbqrydistinct(EJCOLL *jcoll, const char *fpath, bson *qobj, bson *orqobjs, int orqobjsnum, uint32_t *count, TCXSTR *log);
416
417 /**
418  * Synchronize content of a EJDB collection database with the file on device.
419  * @param jcoll EJDB collection.
420  * @return On success return true.
421  */
422 EJDB_EXPORT bool ejdbsyncoll(EJCOLL *jcoll);
423
424 /**
425  * Synchronize entire EJDB database and
426  * all of its collections with storage.
427  * @param jb Database hand
428  */
429 EJDB_EXPORT bool ejdbsyncdb(EJDB *jb);
430
431 /** Begin transaction for EJDB collection. */
432 EJDB_EXPORT bool ejdbtranbegin(EJCOLL *coll);
433
434 /** Commit transaction for EJDB collection. */
435 EJDB_EXPORT bool ejdbtrancommit(EJCOLL *coll);
436
437 /** Abort transaction for EJDB collection. */
438 EJDB_EXPORT bool ejdbtranabort(EJCOLL *coll);
439
440 /** Get current transaction status, it will be placed into txActive*/
441 EJDB_EXPORT bool ejdbtranstatus(EJCOLL *jcoll, bool *txactive);
442
443
444 /** Gets description of EJDB database and its collections. */
445 EJDB_EXPORT bson* ejdbmeta(EJDB *jb);
446
447 /** Export/Import settings used in `ejdbexport()` and `ejdbimport()` functions. */
448 enum {
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.
452 };
453
454 /**
455  * Exports database collections data to the specified directory.
456  * Database read lock will be taken on each collection.
457  *
458  * NOTE: Only data exported as BSONs can be imported with `ejdbimport()`
459  *
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`
466  */
467 EJDB_EXPORT bool ejdbexport(EJDB *jb, const char *path, TCLIST *cnames, int flags, TCXSTR *log);
468
469 /**
470  * Imports previously exported collections data into ejdb.
471  * Global database write lock will be applied during import operation.
472  *
473  * NOTE: Only data exported as BSONs can be imported with `ejdbimport()`
474  *
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.
482  *
483  *             `JBIMPORTREPLACE` Recreate existing collections and replace
484  *                               all their data with imported entries.
485  *                               Collections options will be imported.
486  *
487  *             `0`              Implies `JBIMPORTUPDATE`
488  * @param log Optional operation log buffer.
489  * @return
490  */
491 EJDB_EXPORT bool ejdbimport(EJDB *jb, const char *path, TCLIST *cnames, int flags, TCXSTR *log);
492
493 /**
494  * Execute the ejdb database command.
495  *
496  * Supported commands:
497  *
498  *
499  *  1) Exports database collections data. See ejdbexport() method.
500  *
501  *    "export" : {
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
505  *    }
506  *
507  *    Command response:
508  *       {
509  *          "log" : string,        //Diagnostic log about executing this command
510  *          "error" : string|null, //ejdb error message
511  *          "errorCode" : int|0,   //ejdb error code
512  *       }
513  *
514  *  2) Imports previously exported collections data into ejdb.
515  *
516  *    "import" : {
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
520  *     }
521  *
522  *     Command response:
523  *       {
524  *          "log" : string,        //Diagnostic log about executing this command
525  *          "error" : string|null, //ejdb error message
526  *          "errorCode" : int|0,   //ejdb error code
527  *       }
528  *
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.
532  */
533 EJDB_EXPORT bson* ejdbcommand(EJDB *jb, bson *cmdbson);
534 EJDB_EXPORT bson* ejdbcommand2(EJDB *jb, void *cmdbsondata);
535
536 EJDB_EXTERN_C_END
537
538 #endif        /* EJDB_H */
539