Fix: $rename can operate on nested json objects #107
[platform/upstream/ejdb.git] / src / ejdb / tests / ejdbtest2.c
1 /*
2  * File:   newcunittest.c
3  * Author: Adamansky Anton <adamansky@gmail.com>
4  *
5  * Created on Oct 1, 2012, 3:13:44 PM
6  */
7
8 #include "myconf.h"
9 #include "ejdb_private.h"
10 #include "CUnit/Basic.h"
11
12 /*
13  * CUnit Test Suite
14  */
15
16 static EJDB *jb;
17
18 int init_suite(void) {
19     jb = ejdbnew();
20     if (!ejdbopen(jb, "dbt2", JBOWRITER | JBOCREAT | JBOTRUNC)) {
21         return 1;
22     }
23     return 0;
24 }
25
26 int clean_suite(void) {
27     ejdbrmcoll(jb, "contacts", true);
28     ejdbclose(jb);
29     ejdbdel(jb);
30     return 0;
31 }
32
33 void testAddData(void) {
34     CU_ASSERT_PTR_NOT_NULL_FATAL(jb);
35     bson_oid_t oid;
36     EJCOLL *ccoll = ejdbcreatecoll(jb, "contacts", NULL);
37     CU_ASSERT_PTR_NOT_NULL(ccoll);
38
39     //Record 1
40     bson a1;
41
42     bson_init(&a1);
43     bson_append_string(&a1, "name", "Антонов");
44     bson_append_string(&a1, "phone", "333-222-333");
45     bson_append_int(&a1, "age", 33);
46     bson_append_long(&a1, "longscore", 0xFFFFFFFFFF01LL);
47     bson_append_double(&a1, "dblscore", 0.333333);
48     bson_append_start_object(&a1, "address");
49     bson_append_string(&a1, "city", "Novosibirsk");
50     bson_append_string(&a1, "country", "Russian Federation");
51     bson_append_string(&a1, "zip", "630090");
52     bson_append_string(&a1, "street", "Pirogova");
53     bson_append_int(&a1, "room", 334);
54     bson_append_finish_object(&a1); //EOF address
55     bson_append_start_array(&a1, "complexarr");
56     bson_append_start_object(&a1, "0");
57     bson_append_string(&a1, "key", "title");
58     bson_append_string(&a1, "value", "some title");
59     bson_append_finish_object(&a1);
60     bson_append_start_object(&a1, "1");
61     bson_append_string(&a1, "key", "comment");
62     bson_append_string(&a1, "value", "some comment");
63     bson_append_finish_object(&a1);
64     bson_append_finish_array(&a1); //EOF complexarr
65     CU_ASSERT_FALSE_FATAL(a1.err);
66         bson_append_symbol(&a1, "symbol", "apple");
67     bson_finish(&a1);
68     ejdbsavebson(ccoll, &a1, &oid);
69     bson_destroy(&a1);
70
71     //Record 2
72     bson_init(&a1);
73     bson_append_string(&a1, "name", "Адаманский");
74     bson_append_string(&a1, "phone", "444-123-333");
75     bson_append_long(&a1, "longscore", 0xFFFFFFFFFF02LL);
76     bson_append_double(&a1, "dblscore", 0.93);
77     bson_append_start_object(&a1, "address");
78     bson_append_string(&a1, "city", "Novosibirsk");
79     bson_append_string(&a1, "country", "Russian Federation");
80     bson_append_string(&a1, "zip", "630090");
81     bson_append_string(&a1, "street", "Pirogova");
82     bson_append_finish_object(&a1);
83     bson_append_start_array(&a1, "complexarr");
84     bson_append_start_object(&a1, "0");
85     bson_append_string(&a1, "key", "title");
86     bson_append_string(&a1, "value", "some title");
87     bson_append_finish_object(&a1);
88     bson_append_start_object(&a1, "1");
89     bson_append_string(&a1, "key", "title");
90     bson_append_string(&a1, "value", "some other title");
91     bson_append_finish_object(&a1);
92     bson_append_int(&a1, "2", 333);
93     bson_append_finish_array(&a1); //EOF complexarr
94     bson_append_start_array(&a1, "labels");
95     bson_append_string(&a1, "0", "red");
96     bson_append_string(&a1, "1", "green");
97     bson_append_string(&a1, "2", "with gap, label");
98     bson_append_finish_array(&a1);
99     bson_append_start_array(&a1, "drinks");
100     bson_append_int(&a1, "0", 4);
101     bson_append_long(&a1, "1", 556667);
102     bson_append_double(&a1, "2", 77676.22);
103     bson_append_finish_array(&a1);
104         bson_append_symbol(&a1, "symbol", "application");
105
106     bson_finish(&a1);
107     CU_ASSERT_FALSE_FATAL(a1.err);
108     ejdbsavebson(ccoll, &a1, &oid);
109     bson_destroy(&a1);
110
111     //Record 3
112     bson_init(&a1);
113     bson_append_string(&a1, "name", "Ivanov");
114     bson_append_long(&a1, "longscore", 66);
115     bson_append_double(&a1, "dblscore", 1.0);
116     bson_append_start_object(&a1, "address");
117     bson_append_string(&a1, "city", "Petropavlovsk");
118     bson_append_string(&a1, "country", "Russian Federation");
119     bson_append_string(&a1, "zip", "683042");
120     bson_append_string(&a1, "street", "Dalnaya");
121     bson_append_finish_object(&a1);
122     bson_append_start_array(&a1, "drinks");
123     bson_append_int(&a1, "0", 41);
124     bson_append_long(&a1, "1", 222334);
125     bson_append_double(&a1, "2", 77676.22);
126     bson_append_finish_array(&a1);
127         bson_append_symbol(&a1, "symbol", "bison");
128     bson_finish(&a1);
129     CU_ASSERT_FALSE_FATAL(a1.err);
130
131     CU_ASSERT_TRUE(ejdbsavebson(ccoll, &a1, &oid));
132     bson_destroy(&a1);
133 }
134
135 void testInvalidQueries1(void) {
136 }
137
138 void testSetIndex1(void) {
139     EJCOLL *ccoll = ejdbcreatecoll(jb, "contacts", NULL);
140     CU_ASSERT_PTR_NOT_NULL_FATAL(ccoll);
141     CU_ASSERT_TRUE(ejdbsetindex(ccoll, "ab.c.d", JBIDXSTR));
142     CU_ASSERT_TRUE(ejdbsetindex(ccoll, "ab.c.d", JBIDXSTR | JBIDXNUM));
143     CU_ASSERT_TRUE(ejdbsetindex(ccoll, "ab.c.d", JBIDXDROPALL));
144     CU_ASSERT_TRUE(ejdbsetindex(ccoll, "address.zip", JBIDXSTR));
145     CU_ASSERT_TRUE(ejdbsetindex(ccoll, "name", JBIDXSTR));
146
147     //Insert new record with active index
148     //Record 4
149     bson a1;
150     bson_oid_t oid;
151     bson_init(&a1);
152     bson_append_string(&a1, "name", "John Travolta");
153     bson_append_start_object(&a1, "address");
154     bson_append_string(&a1, "country", "USA");
155     bson_append_string(&a1, "zip", "4499995");
156     bson_append_finish_object(&a1);
157     bson_finish(&a1);
158     CU_ASSERT_FALSE_FATAL(a1.err);
159     CU_ASSERT_TRUE(ejdbsavebson(ccoll, &a1, &oid));
160     bson_destroy(&a1);
161
162
163     //Update record 4 with active index
164     //Record 4
165     bson_init(&a1);
166     bson_append_oid(&a1, "_id", &oid);
167     bson_append_string(&a1, "name", "John Travolta2");
168     bson_append_start_object(&a1, "address");
169     bson_append_string(&a1, "country", "USA");
170     bson_append_string(&a1, "zip", "4499996");
171     bson_append_finish_object(&a1);
172     bson_finish(&a1);
173     CU_ASSERT_FALSE_FATAL(a1.err);
174
175     CU_ASSERT_TRUE(ejdbsavebson(ccoll, &a1, &oid));
176     CU_ASSERT_TRUE(ejdbrmbson(ccoll, &oid));
177     bson_destroy(&a1);
178
179     //Save Travolta again
180     bson_init(&a1);
181     bson_append_oid(&a1, "_id", &oid);
182     bson_append_string(&a1, "name", "John Travolta");
183     bson_append_start_object(&a1, "address");
184     bson_append_string(&a1, "country", "USA");
185     bson_append_string(&a1, "zip", "4499996");
186     bson_append_string(&a1, "street", "Beverly Hills");
187     bson_append_finish_object(&a1);
188     bson_append_start_array(&a1, "labels");
189     bson_append_string(&a1, "0", "yellow");
190     bson_append_string(&a1, "1", "red");
191     bson_append_string(&a1, "2", "black");
192     bson_append_finish_array(&a1);
193     bson_finish(&a1);
194     CU_ASSERT_FALSE_FATAL(a1.err);
195     CU_ASSERT_TRUE(ejdbsavebson(ccoll, &a1, &oid));
196     bson_destroy(&a1);
197 }
198
199 void testQuery1(void) {
200     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
201     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
202
203     bson bsq1;
204     bson_init_as_query(&bsq1);
205     bson_append_string(&bsq1, "address.zip", "630090");
206     bson_finish(&bsq1);
207     CU_ASSERT_FALSE_FATAL(bsq1.err);
208
209     bson bshints;
210     bson_init_as_query(&bshints);
211     bson_append_start_object(&bshints, "$orderby");
212     bson_append_int(&bshints, "name", 1); //ASC order on name
213     bson_append_finish_object(&bshints);
214     bson_finish(&bshints);
215     CU_ASSERT_FALSE_FATAL(bshints.err);
216
217     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
218     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
219
220     uint32_t count = 0;
221     TCXSTR *log = tcxstrnew();
222     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
223
224     //for (int i = 0; i < TCLISTNUM(q1res); ++i) {
225     //    void *bsdata = TCLISTVALPTR(q1res, i);
226     //    bson_print_raw(bsdata, 0);
227     //}
228     //fprintf(stderr, "%s", TCXSTRPTR(log));
229
230     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
231     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'saddress.zip'"));
232     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 0"));
233     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
234     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
235     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
236     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
237     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
238     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
239     CU_ASSERT_EQUAL(count, 2);
240     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
241
242
243     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
244         if (i == 0) {
245             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
246             CU_ASSERT_FALSE(bson_compare_string("630090", TCLISTVALPTR(q1res, i), "address.zip"));
247         } else if (i == 1) {
248             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
249             CU_ASSERT_FALSE(bson_compare_string("630090", TCLISTVALPTR(q1res, i), "address.zip"));
250         } else {
251             CU_ASSERT_TRUE(false);
252         }
253     }
254
255     bson_destroy(&bsq1);
256     bson_destroy(&bshints);
257     tclistdel(q1res);
258     ejdbquerydel(q1);
259     tcxstrdel(log);
260 }
261
262 void testQuery2(void) {
263     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
264     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
265
266     bson bsq1;
267     bson_init_as_query(&bsq1);
268     bson_append_string(&bsq1, "address.zip", "630090");
269     bson_finish(&bsq1);
270     CU_ASSERT_FALSE_FATAL(bsq1.err);
271
272     bson bshints;
273     bson_init_as_query(&bshints);
274     bson_append_start_object(&bshints, "$orderby");
275     bson_append_int(&bshints, "name", -1); //DESC order on name
276     bson_append_finish_object(&bshints);
277     bson_finish(&bshints);
278     CU_ASSERT_FALSE_FATAL(bshints.err);
279
280     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
281     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
282
283     uint32_t count = 0;
284     TCXSTR *log = tcxstrnew();
285     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
286
287     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
288     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'saddress.zip'"));
289     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 0"));
290     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
291     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
292     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
293     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
294     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
295     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
296     CU_ASSERT_EQUAL(count, 2);
297     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
298
299     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
300         if (i == 0) {
301             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
302             CU_ASSERT_FALSE(bson_compare_string("630090", TCLISTVALPTR(q1res, i), "address.zip"));
303         } else if (i == 1) {
304             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
305             CU_ASSERT_FALSE(bson_compare_string("630090", TCLISTVALPTR(q1res, i), "address.zip"));
306         } else {
307             CU_ASSERT_TRUE(false);
308         }
309     }
310     bson_destroy(&bsq1);
311     bson_destroy(&bshints);
312     tclistdel(q1res);
313     ejdbquerydel(q1);
314     tcxstrdel(log);
315 }
316
317 void testQuery3(void) {
318     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
319     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
320     CU_ASSERT_TRUE(ejdbsetindex(contacts, "address.zip", JBIDXDROPALL));
321
322     bson bsq1;
323     bson_init_as_query(&bsq1);
324     bson_append_string(&bsq1, "address.zip", "630090");
325     bson_finish(&bsq1);
326     CU_ASSERT_FALSE_FATAL(bsq1.err);
327
328     bson bshints;
329     bson_init_as_query(&bshints);
330     bson_append_start_object(&bshints, "$orderby");
331     bson_append_int(&bshints, "name", 1); //ASC order on name
332     bson_append_finish_object(&bshints);
333     bson_finish(&bshints);
334     CU_ASSERT_FALSE_FATAL(bshints.err);
335
336     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
337     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
338
339     uint32_t count = 0;
340     TCXSTR *log = tcxstrnew();
341     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
342
343     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
344     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'sname'"));
345     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 20"));
346     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
347     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
348     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
349     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
350     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
351     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
352     CU_ASSERT_EQUAL(count, 2);
353     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
354
355     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
356         if (i == 0) {
357             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
358             CU_ASSERT_FALSE(bson_compare_string("630090", TCLISTVALPTR(q1res, i), "address.zip"));
359         } else if (i == 1) {
360             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
361             CU_ASSERT_FALSE(bson_compare_string("630090", TCLISTVALPTR(q1res, i), "address.zip"));
362         } else {
363             CU_ASSERT_TRUE(false);
364         }
365     }
366
367     bson_destroy(&bsq1);
368     bson_destroy(&bshints);
369     tclistdel(q1res);
370     ejdbquerydel(q1);
371     tcxstrdel(log);
372 }
373
374 void testQuery4(void) {
375     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
376     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
377     CU_ASSERT_TRUE(ejdbsetindex(contacts, "name", JBIDXDROPALL));
378
379     bson bsq1;
380     bson_init_as_query(&bsq1);
381     bson_append_string(&bsq1, "address.zip", "630090");
382     bson_finish(&bsq1);
383     CU_ASSERT_FALSE_FATAL(bsq1.err);
384
385     bson bshints;
386     bson_init_as_query(&bshints);
387     bson_append_start_object(&bshints, "$orderby");
388     bson_append_int(&bshints, "name", 1); //ASC order on name
389     bson_append_finish_object(&bshints);
390     bson_finish(&bshints);
391     CU_ASSERT_FALSE_FATAL(bshints.err);
392
393     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
394     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
395
396     uint32_t count = 0;
397     TCXSTR *log = tcxstrnew();
398     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
399
400     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
401     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
402     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
403     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
404     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
405     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
406     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
407     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
408     CU_ASSERT_EQUAL(count, 2);
409     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
410
411     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
412         if (i == 0) {
413             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
414             CU_ASSERT_FALSE(bson_compare_string("630090", TCLISTVALPTR(q1res, i), "address.zip"));
415         } else if (i == 1) {
416             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
417             CU_ASSERT_FALSE(bson_compare_string("630090", TCLISTVALPTR(q1res, i), "address.zip"));
418         } else {
419             CU_ASSERT_TRUE(false);
420         }
421     }
422     bson_destroy(&bsq1);
423     bson_destroy(&bshints);
424     tclistdel(q1res);
425     ejdbquerydel(q1);
426     tcxstrdel(log);
427 }
428
429 void testQuery5(void) {
430     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
431     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
432     bson bsq1;
433     bson_init_as_query(&bsq1);
434     bson_append_string(&bsq1, "labels", "red");
435     bson_finish(&bsq1);
436     CU_ASSERT_FALSE_FATAL(bsq1.err);
437
438     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
439     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
440
441     uint32_t count = 0;
442     TCXSTR *log = tcxstrnew();
443     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
444     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
445     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
446     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
447     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
448     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
449     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
450     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
451     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
452     CU_ASSERT_EQUAL(count, 2);
453     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
454
455     bson_destroy(&bsq1);
456     tclistdel(q1res);
457     tcxstrdel(log);
458     ejdbquerydel(q1);
459 }
460
461 void testQuery6(void) {
462     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
463     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
464     CU_ASSERT_TRUE(ejdbsetindex(contacts, "labels", JBIDXARR));
465
466     bson bsq1;
467     bson_init_as_query(&bsq1);
468     bson_append_string(&bsq1, "labels", "red");
469     bson_finish(&bsq1);
470     CU_ASSERT_FALSE_FATAL(bsq1.err);
471
472     bson bshints;
473     bson_init_as_query(&bshints);
474     bson_append_start_object(&bshints, "$orderby");
475     bson_append_int(&bshints, "name", 1); //ASC order on name
476     bson_append_finish_object(&bshints);
477     bson_finish(&bshints);
478     CU_ASSERT_FALSE_FATAL(bshints.err);
479
480     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
481     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
482
483     uint32_t count = 0;
484     TCXSTR *log = tcxstrnew();
485     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
486     //fprintf(stderr, "%s", TCXSTRPTR(log));
487
488     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
489     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'alabels'"));
490     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
491     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
492     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
493     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 5"));
494     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "token occurrence: \"red\" 2"));
495     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
496     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
497     CU_ASSERT_EQUAL(count, 2);
498     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
499
500     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
501         if (i == 0) {
502             CU_ASSERT_FALSE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
503             CU_ASSERT_FALSE(bson_compare_string("4499996", TCLISTVALPTR(q1res, i), "address.zip"));
504         } else if (i == 1) {
505             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
506             CU_ASSERT_FALSE(bson_compare_string("630090", TCLISTVALPTR(q1res, i), "address.zip"));
507         } else {
508             CU_ASSERT_TRUE(false);
509         }
510     }
511
512     bson_destroy(&bsq1);
513     bson_destroy(&bshints);
514     tclistdel(q1res);
515     tcxstrdel(log);
516     ejdbquerydel(q1);
517 }
518
519 void testQuery7(void) {
520     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
521     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
522
523     bson bsq1;
524     bson_init_as_query(&bsq1);
525     bson_append_string(&bsq1, "labels", "with gap, label");
526     bson_finish(&bsq1);
527     CU_ASSERT_FALSE_FATAL(bsq1.err);
528
529     bson bshints;
530     bson_init_as_query(&bshints);
531     bson_append_start_object(&bshints, "$orderby");
532     bson_append_int(&bshints, "name", 1); //ASC order on name
533     bson_append_finish_object(&bshints);
534     bson_finish(&bshints);
535     CU_ASSERT_FALSE_FATAL(bshints.err);
536
537     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
538     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
539
540     uint32_t count = 0;
541     TCXSTR *log = tcxstrnew();
542     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
543     //fprintf(stderr, "%s", TCXSTRPTR(log));
544
545     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
546     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'alabels'"));
547     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
548     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
549     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
550     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 5"));
551     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "token occurrence: \"with gap, label\" 1"));
552     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
553     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 1"));
554     CU_ASSERT_EQUAL(count, 1);
555     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 1);
556
557     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
558         if (i == 0) {
559             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
560         } else {
561             CU_ASSERT_TRUE(false);
562         }
563     }
564
565     bson_destroy(&bsq1);
566     bson_destroy(&bshints);
567     tclistdel(q1res);
568     tcxstrdel(log);
569     ejdbquerydel(q1);
570 }
571
572 void testQuery8(void) {
573     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
574     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
575
576     //"labels" : {"$in" : ["yellow", "green"]}
577     bson bsq1;
578     bson_init_as_query(&bsq1);
579     bson_append_start_object(&bsq1, "labels");
580     bson_append_start_array(&bsq1, "$in");
581     bson_append_string(&bsq1, "0", "green");
582     bson_append_string(&bsq1, "1", "yellow");
583     bson_append_finish_array(&bsq1);
584     bson_append_finish_object(&bsq1);
585     bson_finish(&bsq1);
586     CU_ASSERT_FALSE_FATAL(bsq1.err);
587
588     bson bshints;
589     bson_init_as_query(&bshints);
590     bson_append_start_object(&bshints, "$orderby");
591     bson_append_int(&bshints, "name", 1); //ASC order on name
592     bson_append_finish_object(&bshints);
593     bson_finish(&bshints);
594     CU_ASSERT_FALSE_FATAL(bshints.err);
595
596     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
597     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
598
599     uint32_t count = 0;
600     TCXSTR *log = tcxstrnew();
601     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
602     //fprintf(stderr, "%s", TCXSTRPTR(log));
603
604     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
605     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'alabels'"));
606     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
607     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
608     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
609     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 5"));
610     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "token occurrence: \"green\" 1"));
611     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "token occurrence: \"yellow\" 1"));
612     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
613     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
614     CU_ASSERT_EQUAL(count, 2);
615     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
616
617     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
618         if (i == 0) {
619             CU_ASSERT_FALSE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
620             CU_ASSERT_FALSE(bson_compare_string("yellow", TCLISTVALPTR(q1res, i), "labels.0"));
621         } else if (i == 1) {
622             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
623             CU_ASSERT_FALSE(bson_compare_string("green", TCLISTVALPTR(q1res, i), "labels.1"));
624         } else {
625             CU_ASSERT_TRUE(false);
626         }
627     }
628
629     bson_destroy(&bsq1);
630     bson_destroy(&bshints);
631     tclistdel(q1res);
632     tcxstrdel(log);
633     ejdbquerydel(q1);
634
635
636     //todo check hash tokens mode
637     CU_ASSERT_TRUE(ejdbsetindex(contacts, "labels", JBIDXDROPALL));
638
639     bson_init_as_query(&bsq1);
640     bson_append_start_object(&bsq1, "labels");
641     bson_append_start_array(&bsq1, "$in");
642
643     char nbuff[TCNUMBUFSIZ];
644     for (int i = 0; i <= JBINOPTMAPTHRESHOLD; ++i) {
645         bson_numstrn(nbuff, TCNUMBUFSIZ, i);
646         if (i == 2) {
647             bson_append_string(&bsq1, nbuff, "green");
648         } else if (i == 8) {
649             bson_append_string(&bsq1, nbuff, "yellow");
650         } else {
651             bson_append_string(&bsq1, nbuff, nbuff);
652         }
653     }
654     bson_append_finish_array(&bsq1);
655     bson_append_finish_object(&bsq1);
656     bson_finish(&bsq1);
657     CU_ASSERT_FALSE_FATAL(bsq1.err);
658
659     bson_init_as_query(&bshints);
660     bson_append_start_object(&bshints, "$orderby");
661     bson_append_int(&bshints, "name", 1); //ASC order on name
662     bson_append_finish_object(&bshints);
663     bson_finish(&bshints);
664     CU_ASSERT_FALSE_FATAL(bshints.err);
665
666     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
667     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
668     log = tcxstrnew();
669     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
670     //fprintf(stderr, "%s", TCXSTRPTR(log));
671
672     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "USING HASH TOKENS IN: labels"));
673     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
674     CU_ASSERT_EQUAL(count, 2);
675     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
676     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
677         if (i == 0) {
678             CU_ASSERT_FALSE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
679             CU_ASSERT_FALSE(bson_compare_string("yellow", TCLISTVALPTR(q1res, i), "labels.0"));
680         } else if (i == 1) {
681             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
682             CU_ASSERT_FALSE(bson_compare_string("green", TCLISTVALPTR(q1res, i), "labels.1"));
683         } else {
684             CU_ASSERT_TRUE(false);
685         }
686     }
687
688     bson_destroy(&bsq1);
689     bson_destroy(&bshints);
690     tclistdel(q1res);
691     tcxstrdel(log);
692     ejdbquerydel(q1);
693 }
694
695 void testQuery9(void) {
696     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
697     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
698     CU_ASSERT_TRUE(ejdbsetindex(contacts, "labels", JBIDXDROPALL));
699
700     bson bsq1;
701     bson_init_as_query(&bsq1);
702     bson_append_string(&bsq1, "labels", "red");
703     bson_finish(&bsq1);
704     CU_ASSERT_FALSE_FATAL(bsq1.err);
705
706     bson bshints;
707     bson_init_as_query(&bshints);
708     bson_append_start_object(&bshints, "$orderby");
709     bson_append_int(&bshints, "name", 1); //ASC order on name
710     bson_append_finish_object(&bshints);
711     bson_finish(&bshints);
712     CU_ASSERT_FALSE_FATAL(bshints.err);
713
714     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
715     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
716
717     uint32_t count = 0;
718     TCXSTR *log = tcxstrnew();
719     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
720
721     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
722     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
723     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
724     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
725     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
726     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP"));
727     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
728     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
729     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
730     CU_ASSERT_EQUAL(count, 2);
731     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
732
733     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
734         if (i == 0) {
735             CU_ASSERT_FALSE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
736             CU_ASSERT_FALSE(bson_compare_string("4499996", TCLISTVALPTR(q1res, i), "address.zip"));
737         } else if (i == 1) {
738             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
739             CU_ASSERT_FALSE(bson_compare_string("630090", TCLISTVALPTR(q1res, i), "address.zip"));
740         } else {
741             CU_ASSERT_TRUE(false);
742         }
743     }
744
745
746     bson_destroy(&bsq1);
747     bson_destroy(&bshints);
748     tclistdel(q1res);
749     tcxstrdel(log);
750     ejdbquerydel(q1);
751 }
752
753 void testQuery10(void) {
754     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
755     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
756     CU_ASSERT_TRUE(ejdbsetindex(contacts, "address.street", JBIDXSTR));
757
758     //"address.street" : {"$in" : ["Pirogova", "Beverly Hills"]}
759     bson bsq1;
760     bson_init_as_query(&bsq1);
761     bson_append_start_object(&bsq1, "address.street");
762     bson_append_start_array(&bsq1, "$in");
763     bson_append_string(&bsq1, "0", "Pirogova");
764     bson_append_string(&bsq1, "1", "Beverly Hills");
765     bson_append_finish_array(&bsq1);
766     bson_append_finish_object(&bsq1);
767     bson_finish(&bsq1);
768     CU_ASSERT_FALSE_FATAL(bsq1.err);
769
770     bson bshints;
771     bson_init_as_query(&bshints);
772     bson_append_start_object(&bshints, "$orderby");
773     bson_append_int(&bshints, "name", 1); //ASC order on name
774     bson_append_finish_object(&bshints);
775     bson_finish(&bshints);
776     CU_ASSERT_FALSE_FATAL(bshints.err);
777
778     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
779     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
780
781     uint32_t count = 0;
782     TCXSTR *log = tcxstrnew();
783     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
784
785     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
786     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'saddress.street'"));
787     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
788     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
789     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
790     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 6"));
791     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
792     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
793     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 3"));
794     CU_ASSERT_EQUAL(count, 3);
795     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 3);
796
797     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
798         if (i == 0) {
799             CU_ASSERT_FALSE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
800             CU_ASSERT_FALSE(bson_compare_string("Beverly Hills", TCLISTVALPTR(q1res, i), "address.street"));
801         } else if (i == 1) {
802             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
803             CU_ASSERT_FALSE(bson_compare_string("Pirogova", TCLISTVALPTR(q1res, i), "address.street"));
804         } else if (i == 2) {
805             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
806             CU_ASSERT_FALSE(bson_compare_string("Pirogova", TCLISTVALPTR(q1res, i), "address.street"));
807         } else {
808             CU_ASSERT_TRUE(false);
809         }
810     }
811     bson_destroy(&bsq1);
812     bson_destroy(&bshints);
813     tclistdel(q1res);
814     tcxstrdel(log);
815     ejdbquerydel(q1);
816 }
817
818 void testQuery11(void) {
819     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
820     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
821     CU_ASSERT_TRUE(ejdbsetindex(contacts, "address.street", JBIDXDROPALL));
822
823     //"address.street" : {"$in" : ["Pirogova", "Beverly Hills"]}
824     bson bsq1;
825     bson_init_as_query(&bsq1);
826     bson_append_start_object(&bsq1, "address.street");
827     bson_append_start_array(&bsq1, "$in");
828     bson_append_string(&bsq1, "0", "Pirogova");
829     bson_append_string(&bsq1, "1", "Beverly Hills");
830     bson_append_finish_array(&bsq1);
831     bson_append_finish_object(&bsq1);
832     bson_finish(&bsq1);
833     CU_ASSERT_FALSE_FATAL(bsq1.err);
834
835     bson bshints;
836     bson_init_as_query(&bshints);
837     bson_append_start_object(&bshints, "$orderby");
838     bson_append_int(&bshints, "name", 1); //ASC order on name
839     bson_append_finish_object(&bshints);
840     bson_finish(&bshints);
841     CU_ASSERT_FALSE_FATAL(bshints.err);
842
843     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
844     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
845
846     uint32_t count = 0;
847     TCXSTR *log = tcxstrnew();
848     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
849
850     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
851     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
852     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
853     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
854     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
855     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP"));
856     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
857     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
858     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 3"));
859     CU_ASSERT_EQUAL(count, 3);
860     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 3);
861
862     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
863         if (i == 0) {
864             CU_ASSERT_FALSE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
865             CU_ASSERT_FALSE(bson_compare_string("Beverly Hills", TCLISTVALPTR(q1res, i), "address.street"));
866         } else if (i == 1) {
867             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
868             CU_ASSERT_FALSE(bson_compare_string("Pirogova", TCLISTVALPTR(q1res, i), "address.street"));
869         } else if (i == 2) {
870             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
871             CU_ASSERT_FALSE(bson_compare_string("Pirogova", TCLISTVALPTR(q1res, i), "address.street"));
872         } else {
873             CU_ASSERT_TRUE(false);
874         }
875     }
876
877     bson_destroy(&bsq1);
878     bson_destroy(&bshints);
879     tclistdel(q1res);
880     tcxstrdel(log);
881     ejdbquerydel(q1);
882 }
883
884 void testQuery12(void) {
885     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
886     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
887
888     //"labels" : {"$in" : ["yellow", "green"]}
889     bson bsq1;
890     bson_init_as_query(&bsq1);
891     bson_append_start_object(&bsq1, "labels");
892     bson_append_start_array(&bsq1, "$in");
893     bson_append_string(&bsq1, "0", "green");
894     bson_append_string(&bsq1, "1", "yellow");
895     bson_append_finish_array(&bsq1);
896     bson_append_finish_object(&bsq1);
897     bson_finish(&bsq1);
898     CU_ASSERT_FALSE_FATAL(bsq1.err);
899
900     bson bshints;
901     bson_init_as_query(&bshints);
902     bson_append_start_object(&bshints, "$orderby");
903     bson_append_int(&bshints, "name", 1); //ASC order on name
904     bson_append_finish_object(&bshints);
905     bson_finish(&bshints);
906     CU_ASSERT_FALSE_FATAL(bshints.err);
907
908     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
909     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
910
911     uint32_t count = 0;
912     TCXSTR *log = tcxstrnew();
913     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
914     //fprintf(stderr, "%s", TCXSTRPTR(log));
915
916     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
917     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
918     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
919     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
920     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
921     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP"));
922     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
923     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
924     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
925     CU_ASSERT_EQUAL(count, 2);
926     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
927
928     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
929         if (i == 0) {
930             CU_ASSERT_FALSE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
931             CU_ASSERT_FALSE(bson_compare_string("yellow", TCLISTVALPTR(q1res, i), "labels.0"));
932         } else if (i == 1) {
933             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
934             CU_ASSERT_FALSE(bson_compare_string("green", TCLISTVALPTR(q1res, i), "labels.1"));
935         } else {
936             CU_ASSERT_TRUE(false);
937         }
938     }
939
940     bson_destroy(&bsq1);
941     bson_destroy(&bshints);
942     tclistdel(q1res);
943     tcxstrdel(log);
944     ejdbquerydel(q1);
945 }
946
947 void testQuery13(void) {
948     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
949     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
950
951     //"drinks" : {"$in" : [4, 77676.22]}
952     bson bsq1;
953     bson_init_as_query(&bsq1);
954     bson_append_start_object(&bsq1, "drinks");
955     bson_append_start_array(&bsq1, "$in");
956     bson_append_int(&bsq1, "0", 4);
957     bson_append_double(&bsq1, "1", 77676.22);
958     bson_append_finish_array(&bsq1);
959     bson_append_finish_object(&bsq1);
960     bson_finish(&bsq1);
961     CU_ASSERT_FALSE_FATAL(bsq1.err);
962
963     bson bshints;
964     bson_init_as_query(&bshints);
965     bson_append_start_object(&bshints, "$orderby");
966     bson_append_int(&bshints, "name", 1); //ASC order on name
967     bson_append_finish_object(&bshints);
968     bson_finish(&bshints);
969     CU_ASSERT_FALSE_FATAL(bshints.err);
970
971     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
972     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
973
974     uint32_t count = 0;
975     TCXSTR *log = tcxstrnew();
976     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
977     //fprintf(stderr, "%s", TCXSTRPTR(log));
978
979
980     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
981     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
982     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
983     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
984     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
985     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP"));
986     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
987     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
988     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
989     CU_ASSERT_EQUAL(count, 2);
990     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
991
992     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
993         if (i == 0) {
994             CU_ASSERT_FALSE(bson_compare_string("Ivanov", TCLISTVALPTR(q1res, i), "name"));
995             CU_ASSERT_FALSE(bson_compare_long(41, TCLISTVALPTR(q1res, i), "drinks.0"));
996             CU_ASSERT_FALSE(bson_compare_long(222334, TCLISTVALPTR(q1res, i), "drinks.1"));
997             CU_ASSERT_FALSE(bson_compare_double(77676.22, TCLISTVALPTR(q1res, i), "drinks.2"));
998         } else if (i == 1) {
999             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
1000             CU_ASSERT_FALSE(bson_compare_long(4, TCLISTVALPTR(q1res, i), "drinks.0"));
1001             CU_ASSERT_FALSE(bson_compare_long(556667, TCLISTVALPTR(q1res, i), "drinks.1"));
1002             CU_ASSERT_FALSE(bson_compare_double(77676.22, TCLISTVALPTR(q1res, i), "drinks.2"));
1003         } else {
1004             CU_ASSERT_TRUE(false);
1005         }
1006     }
1007
1008     bson_destroy(&bsq1);
1009     bson_destroy(&bshints);
1010     tclistdel(q1res);
1011     tcxstrdel(log);
1012     ejdbquerydel(q1);
1013 }
1014
1015 void testQuery14(void) {
1016     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
1017     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
1018     CU_ASSERT_TRUE(ejdbsetindex(contacts, "drinks", JBIDXARR));
1019
1020     //"drinks" : {"$in" : [4, 77676.22]}
1021     bson bsq1;
1022     bson_init_as_query(&bsq1);
1023     bson_append_start_object(&bsq1, "drinks");
1024     bson_append_start_array(&bsq1, "$in");
1025     bson_append_int(&bsq1, "0", 4);
1026     bson_append_double(&bsq1, "1", 77676.22);
1027     bson_append_finish_array(&bsq1);
1028     bson_append_finish_object(&bsq1);
1029     bson_finish(&bsq1);
1030     CU_ASSERT_FALSE_FATAL(bsq1.err);
1031
1032     bson bshints;
1033     bson_init_as_query(&bshints);
1034     bson_append_start_object(&bshints, "$orderby");
1035     bson_append_int(&bshints, "name", 1); //ASC order on name
1036     bson_append_finish_object(&bshints);
1037     bson_finish(&bshints);
1038     CU_ASSERT_FALSE_FATAL(bshints.err);
1039
1040     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1041     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1042
1043     uint32_t count = 0;
1044     TCXSTR *log = tcxstrnew();
1045     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1046     //fprintf(stderr, "%s", TCXSTRPTR(log));
1047
1048     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1049     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'adrinks'"));
1050     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1051     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1052     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
1053     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 21"));
1054     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1055     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "token occurrence: \"4\" 1"));
1056     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "token occurrence: \"77676.220000\" 2"));
1057     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
1058     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
1059     CU_ASSERT_EQUAL(count, 2);
1060     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
1061
1062     bson_destroy(&bsq1);
1063     bson_destroy(&bshints);
1064     tclistdel(q1res);
1065     tcxstrdel(log);
1066     ejdbquerydel(q1);
1067 }
1068
1069 void testQuery15(void) {
1070     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
1071     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
1072     CU_ASSERT_TRUE(ejdbsetindex(contacts, "dblscore", JBIDXNUM));
1073
1074     bson bsq1;
1075     bson_init_as_query(&bsq1);
1076     bson_append_double(&bsq1, "dblscore", 0.333333);
1077     bson_finish(&bsq1);
1078     CU_ASSERT_FALSE_FATAL(bsq1.err);
1079
1080     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
1081     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1082
1083     uint32_t count = 0;
1084     TCXSTR *log = tcxstrnew();
1085     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1086     //fprintf(stderr, "%s", TCXSTRPTR(log));
1087
1088     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1089     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'ndblscore'"));
1090     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
1091     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1092     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
1093     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 8"));
1094     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1095     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
1096     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 1"));
1097     CU_ASSERT_EQUAL(count, 1);
1098     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 1);
1099
1100     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1101         if (i == 0) {
1102             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
1103             CU_ASSERT_FALSE(bson_compare_double(0.333333, TCLISTVALPTR(q1res, i), "dblscore"));
1104         } else {
1105             CU_ASSERT_TRUE(false);
1106         }
1107     }
1108
1109     bson_destroy(&bsq1);
1110     tclistdel(q1res);
1111     tcxstrdel(log);
1112     ejdbquerydel(q1);
1113 }
1114
1115 void testQuery16(void) {
1116     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
1117     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
1118     CU_ASSERT_TRUE(ejdbsetindex(contacts, "dblscore", JBIDXDROPALL));
1119
1120     bson bsq1;
1121     bson_init_as_query(&bsq1);
1122     bson_append_double(&bsq1, "dblscore", 0.333333);
1123     bson_finish(&bsq1);
1124     CU_ASSERT_FALSE_FATAL(bsq1.err);
1125
1126     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
1127     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1128
1129     uint32_t count = 0;
1130     TCXSTR *log = tcxstrnew();
1131     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1132     //fprintf(stderr, "%s", TCXSTRPTR(log));
1133
1134     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1135     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
1136     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
1137     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1138     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
1139     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1140     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
1141     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 1"));
1142     CU_ASSERT_EQUAL(count, 1);
1143     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 1);
1144
1145     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1146         if (i == 0) {
1147             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
1148             CU_ASSERT_FALSE(bson_compare_double(0.333333, TCLISTVALPTR(q1res, i), "dblscore"));
1149         } else {
1150             CU_ASSERT_TRUE(false);
1151         }
1152     }
1153
1154     bson_destroy(&bsq1);
1155     tclistdel(q1res);
1156     tcxstrdel(log);
1157     ejdbquerydel(q1);
1158 }
1159
1160 void testQuery17(void) {
1161     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
1162     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
1163     CU_ASSERT_TRUE(ejdbsetindex(contacts, "dblscore", JBIDXNUM));
1164
1165     //"dblscore" : {"$bt" : [0.95, 0.3]}
1166     bson bsq1;
1167     bson_init_as_query(&bsq1);
1168     bson_append_start_object(&bsq1, "dblscore");
1169     bson_append_start_array(&bsq1, "$bt");
1170     bson_append_double(&bsq1, "0", 0.95);
1171     bson_append_double(&bsq1, "1", 0.333333);
1172     bson_append_finish_array(&bsq1);
1173     bson_append_finish_object(&bsq1);
1174     bson_finish(&bsq1);
1175     CU_ASSERT_FALSE_FATAL(bsq1.err);
1176
1177
1178     bson bshints;
1179     bson_init_as_query(&bshints);
1180     bson_append_start_object(&bshints, "$orderby");
1181     bson_append_int(&bshints, "dblscore", -1); //DESC order on name
1182     bson_append_finish_object(&bshints);
1183     bson_finish(&bshints);
1184     CU_ASSERT_FALSE_FATAL(bshints.err);
1185
1186     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1187     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1188
1189     uint32_t count = 0;
1190     TCXSTR *log = tcxstrnew();
1191     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1192     //fprintf(stderr, "%s", TCXSTRPTR(log));
1193
1194     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1195     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'ndblscore'"));
1196     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1197     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1198     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
1199     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1200     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 13"));
1201     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
1202     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
1203     CU_ASSERT_EQUAL(count, 2);
1204     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
1205
1206     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1207         if (i == 0) {
1208             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
1209             CU_ASSERT_FALSE(bson_compare_double(0.93, TCLISTVALPTR(q1res, i), "dblscore"));
1210         } else if (i == 1) {
1211             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
1212             CU_ASSERT_FALSE(bson_compare_double(0.333333, TCLISTVALPTR(q1res, i), "dblscore"));
1213         } else {
1214             CU_ASSERT_TRUE(false);
1215         }
1216     }
1217
1218     //Second query
1219     tcxstrclear(log);
1220     bson_destroy(&bsq1);
1221     bson_destroy(&bshints);
1222     tclistdel(q1res);
1223     ejdbquerydel(q1);
1224
1225     CU_ASSERT_TRUE(ejdbsetindex(contacts, "dblscore", JBIDXDROPALL));
1226
1227     bson_init_as_query(&bsq1);
1228     bson_append_start_object(&bsq1, "dblscore");
1229     bson_append_start_array(&bsq1, "$bt");
1230     bson_append_double(&bsq1, "0", 0.95);
1231     bson_append_double(&bsq1, "1", 0.333333);
1232     bson_append_finish_array(&bsq1);
1233     bson_append_finish_object(&bsq1);
1234     bson_finish(&bsq1);
1235     CU_ASSERT_FALSE_FATAL(bsq1.err);
1236
1237
1238     bson_init_as_query(&bshints);
1239     bson_append_start_object(&bshints, "$orderby");
1240     bson_append_int(&bshints, "dblscore", 1); //ASC order on name
1241     bson_append_finish_object(&bshints);
1242     bson_finish(&bshints);
1243     CU_ASSERT_FALSE_FATAL(bshints.err);
1244
1245     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1246     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1247
1248     count = 0;
1249     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1250
1251     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1252     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
1253     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1254     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1255     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
1256     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1257     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
1258     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
1259     CU_ASSERT_EQUAL(count, 2);
1260     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
1261
1262     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1263         if (i == 0) {
1264             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
1265             CU_ASSERT_FALSE(bson_compare_double(0.333333, TCLISTVALPTR(q1res, i), "dblscore"));
1266         } else if (i == 1) {
1267             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
1268             CU_ASSERT_FALSE(bson_compare_double(0.93, TCLISTVALPTR(q1res, i), "dblscore"));
1269         } else {
1270             CU_ASSERT_TRUE(false);
1271         }
1272     }
1273
1274     bson_destroy(&bsq1);
1275     bson_destroy(&bshints);
1276     tclistdel(q1res);
1277     tcxstrdel(log);
1278     ejdbquerydel(q1);
1279 }
1280
1281 void testQuery18(void) {
1282     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
1283     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
1284     CU_ASSERT_TRUE(ejdbsetindex(contacts, "name", JBIDXARR));
1285
1286     //{"name" : {$strand : ["Travolta", "John"]}}
1287     bson bsq1;
1288     bson_init_as_query(&bsq1);
1289     bson_append_start_object(&bsq1, "name");
1290     bson_append_start_array(&bsq1, "$strand");
1291     bson_append_string(&bsq1, "0", "Travolta");
1292     bson_append_string(&bsq1, "1", "John");
1293     bson_append_finish_array(&bsq1);
1294     bson_append_finish_object(&bsq1);
1295     bson_finish(&bsq1);
1296     CU_ASSERT_FALSE_FATAL(bsq1.err);
1297
1298     bson bshints;
1299     bson_init_as_query(&bshints);
1300     /*bson_append_start_object(&bshints, "$orderby");
1301     bson_append_int(&bshints, "dblscore", 1); //ASC order on name
1302     bson_append_finish_object(&bshints);*/
1303     bson_finish(&bshints);
1304     CU_ASSERT_FALSE_FATAL(bshints.err);
1305
1306     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1307     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1308
1309     uint32_t count = 0;
1310     TCXSTR *log = tcxstrnew();
1311     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1312     //fprintf(stderr, "%s", TCXSTRPTR(log));
1313
1314     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1315     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'aname'"));
1316     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
1317     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1318     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
1319     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1320     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 4"));
1321     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "token occurrence: \"John\" 1"));
1322     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "token occurrence: \"Travolta\" 1"));
1323     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
1324     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 1"));
1325     CU_ASSERT_EQUAL(count, 1);
1326     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 1);
1327
1328     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1329         if (i == 0) {
1330             CU_ASSERT_FALSE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
1331         } else {
1332             CU_ASSERT_TRUE(false);
1333         }
1334     }
1335
1336     //Second query
1337     tcxstrclear(log);
1338     tclistdel(q1res);
1339     CU_ASSERT_TRUE(ejdbsetindex(contacts, "name", JBIDXDROPALL));
1340
1341     count = 0;
1342     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1343
1344     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1345     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
1346     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
1347     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1348     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
1349     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1350     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
1351     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 1"));
1352     CU_ASSERT_EQUAL(count, 1);
1353     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 1);
1354
1355     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1356         if (i == 0) {
1357             CU_ASSERT_FALSE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
1358         } else {
1359             CU_ASSERT_TRUE(false);
1360         }
1361     }
1362
1363     bson_destroy(&bsq1);
1364     bson_destroy(&bshints);
1365     tclistdel(q1res);
1366     ejdbquerydel(q1);
1367
1368     //Third query
1369     CU_ASSERT_TRUE(ejdbsetindex(contacts, "labels", JBIDXARR));
1370
1371     bson_init_as_query(&bsq1);
1372     bson_append_start_object(&bsq1, "labels");
1373     bson_append_start_array(&bsq1, "$strand");
1374     bson_append_string(&bsq1, "0", "red");
1375     bson_append_string(&bsq1, "1", "black");
1376     bson_append_finish_array(&bsq1);
1377     bson_append_finish_object(&bsq1);
1378     bson_finish(&bsq1);
1379     CU_ASSERT_FALSE_FATAL(bsq1.err);
1380
1381     count = 0;
1382     tcxstrclear(log);
1383     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
1384     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1385     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1386     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 1"));
1387     CU_ASSERT_EQUAL(count, 1);
1388     //fprintf(stderr, "%s", TCXSTRPTR(log));
1389
1390     bson_destroy(&bsq1);
1391     tclistdel(q1res);
1392     tcxstrdel(log);
1393     ejdbquerydel(q1);
1394 }
1395
1396 void testQuery19(void) {
1397     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
1398     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
1399     CU_ASSERT_TRUE(ejdbsetindex(contacts, "name", JBIDXARR));
1400
1401     //{"name" : {$stror : ["Travolta", "Антонов", "John"]}}
1402     bson bsq1;
1403     bson_init_as_query(&bsq1);
1404     bson_append_start_object(&bsq1, "name");
1405     bson_append_start_array(&bsq1, "$stror");
1406     bson_append_string(&bsq1, "0", "Travolta");
1407     bson_append_string(&bsq1, "1", "Антонов");
1408     bson_append_string(&bsq1, "2", "John");
1409     bson_append_finish_array(&bsq1);
1410     bson_append_finish_object(&bsq1);
1411     bson_finish(&bsq1);
1412     CU_ASSERT_FALSE_FATAL(bsq1.err);
1413
1414     bson bshints;
1415     bson_init_as_query(&bshints);
1416     bson_append_start_object(&bshints, "$orderby");
1417     bson_append_int(&bshints, "name", -1); //DESC order on name
1418     bson_append_finish_object(&bshints);
1419     bson_finish(&bshints);
1420     CU_ASSERT_FALSE_FATAL(bshints.err);
1421
1422     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1423     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1424
1425     uint32_t count = 0;
1426     TCXSTR *log = tcxstrnew();
1427     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1428     //fprintf(stderr, "%s", TCXSTRPTR(log));
1429
1430     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1431     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'aname'"));
1432     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1433     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1434     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
1435     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 5"));
1436     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "token occurrence: \"John\" 1"));
1437     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "token occurrence: \"Travolta\" 1"));
1438     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "token occurrence: \"Антонов\" 1"));
1439     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1440     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
1441     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
1442     CU_ASSERT_EQUAL(count, 2);
1443     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
1444
1445     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1446         if (i == 0) {
1447             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
1448         } else if (i == 1) {
1449             CU_ASSERT_FALSE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
1450         } else {
1451             CU_ASSERT_TRUE(false);
1452         }
1453     }
1454
1455     //No-index query
1456     tcxstrclear(log);
1457     tclistdel(q1res);
1458     CU_ASSERT_TRUE(ejdbsetindex(contacts, "name", JBIDXDROPALL));
1459
1460     count = 0;
1461     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1462     //fprintf(stderr, "%s", TCXSTRPTR(log));
1463
1464     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1465     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
1466     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1467     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1468     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
1469     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1470     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
1471     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
1472     CU_ASSERT_EQUAL(count, 2);
1473     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
1474
1475     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1476         if (i == 0) {
1477             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
1478         } else if (i == 1) {
1479             CU_ASSERT_FALSE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
1480         } else {
1481             CU_ASSERT_TRUE(false);
1482         }
1483     }
1484
1485     bson_destroy(&bsq1);
1486     bson_destroy(&bshints);
1487     tclistdel(q1res);
1488     tcxstrdel(log);
1489     ejdbquerydel(q1);
1490 }
1491
1492 void testQuery20(void) {
1493     //dblscore
1494     //{'dblscore' : {'$gte' : 0.93}}
1495     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
1496     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
1497     CU_ASSERT_TRUE(ejdbsetindex(contacts, "dblscore", JBIDXNUM));
1498
1499     bson bsq1;
1500     bson_init_as_query(&bsq1);
1501     bson_append_start_object(&bsq1, "dblscore");
1502     bson_append_double(&bsq1, "$gte", 0.93);
1503     bson_append_finish_object(&bsq1);
1504     bson_finish(&bsq1);
1505     CU_ASSERT_FALSE_FATAL(bsq1.err);
1506
1507     bson bshints;
1508     bson_init_as_query(&bshints);
1509     bson_append_start_object(&bshints, "$orderby");
1510     bson_append_int(&bshints, "dblscore", 1); //ASC order on dblscore
1511     bson_append_finish_object(&bshints);
1512     bson_finish(&bshints);
1513     CU_ASSERT_FALSE_FATAL(bshints.err);
1514
1515     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1516     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1517
1518     uint32_t count = 0;
1519     TCXSTR *log = tcxstrnew();
1520     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1521     //fprintf(stderr, "%s", TCXSTRPTR(log));
1522
1523     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1524     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'ndblscore'"));
1525     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1526     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1527     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
1528     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 10"));
1529     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1530     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
1531     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
1532     CU_ASSERT_EQUAL(count, 2);
1533     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
1534
1535     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1536         if (i == 0) {
1537             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
1538             CU_ASSERT_FALSE(bson_compare_double(0.93, TCLISTVALPTR(q1res, i), "dblscore"));
1539         } else if (i == 1) {
1540             CU_ASSERT_FALSE(bson_compare_string("Ivanov", TCLISTVALPTR(q1res, i), "name"));
1541             CU_ASSERT_FALSE(bson_compare_double(1.0, TCLISTVALPTR(q1res, i), "dblscore"));
1542         } else {
1543             CU_ASSERT_TRUE(false);
1544         }
1545     }
1546
1547     bson_destroy(&bsq1);
1548     bson_destroy(&bshints);
1549     tclistdel(q1res);
1550     tcxstrdel(log);
1551     ejdbquerydel(q1);
1552
1553     //GT
1554
1555     bson_init_as_query(&bsq1);
1556     bson_append_start_object(&bsq1, "dblscore");
1557     bson_append_double(&bsq1, "$gt", 0.93);
1558     bson_append_finish_object(&bsq1);
1559     bson_finish(&bsq1);
1560     CU_ASSERT_FALSE_FATAL(bsq1.err);
1561
1562     bson_init_as_query(&bshints);
1563     bson_append_start_object(&bshints, "$orderby");
1564     bson_append_int(&bshints, "dblscore", 1); //ASC order on dblscore
1565     bson_append_finish_object(&bshints);
1566     bson_finish(&bshints);
1567     CU_ASSERT_FALSE_FATAL(bshints.err);
1568
1569     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1570     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1571
1572     count = 0;
1573     log = tcxstrnew();
1574     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1575     //fprintf(stderr, "%s", TCXSTRPTR(log));
1576
1577     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1578     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'ndblscore'"));
1579     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1580     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1581     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
1582     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 9"));
1583     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1584     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
1585     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 1"));
1586     CU_ASSERT_EQUAL(count, 1);
1587     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 1);
1588
1589     bson_destroy(&bsq1);
1590     bson_destroy(&bshints);
1591     tclistdel(q1res);
1592     tcxstrdel(log);
1593     ejdbquerydel(q1);
1594
1595     //NOINDEX
1596     CU_ASSERT_TRUE(ejdbsetindex(contacts, "dblscore", JBIDXDROPALL));
1597
1598     //NOINDEX GTE
1599     bson_init_as_query(&bsq1);
1600     bson_append_start_object(&bsq1, "dblscore");
1601     bson_append_double(&bsq1, "$gte", 0.93);
1602     bson_append_finish_object(&bsq1);
1603     bson_finish(&bsq1);
1604     CU_ASSERT_FALSE_FATAL(bsq1.err);
1605
1606     bson_init_as_query(&bshints);
1607     bson_append_start_object(&bshints, "$orderby");
1608     bson_append_int(&bshints, "dblscore", -1); //DESC order on dblscore
1609     bson_append_finish_object(&bshints);
1610     bson_finish(&bshints);
1611     CU_ASSERT_FALSE_FATAL(bshints.err);
1612
1613     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1614     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1615
1616     count = 0;
1617     log = tcxstrnew();
1618     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1619     //fprintf(stderr, "%s", TCXSTRPTR(log));
1620
1621     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1622     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
1623     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1624     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1625     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
1626     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1627     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
1628     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
1629     CU_ASSERT_EQUAL(count, 2);
1630     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
1631
1632     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1633         if (i == 1) {
1634             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
1635             CU_ASSERT_FALSE(bson_compare_double(0.93, TCLISTVALPTR(q1res, i), "dblscore"));
1636         } else if (i == 0) {
1637             CU_ASSERT_FALSE(bson_compare_string("Ivanov", TCLISTVALPTR(q1res, i), "name"));
1638             CU_ASSERT_FALSE(bson_compare_double(1.0, TCLISTVALPTR(q1res, i), "dblscore"));
1639         } else {
1640             CU_ASSERT_TRUE(false);
1641         }
1642     }
1643
1644     bson_destroy(&bsq1);
1645     bson_destroy(&bshints);
1646     tclistdel(q1res);
1647     tcxstrdel(log);
1648     ejdbquerydel(q1);
1649 }
1650
1651 void testQuery21(void) {
1652     //{'dblscore' : {'lte' : 0.93}}
1653     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
1654     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
1655     CU_ASSERT_TRUE(ejdbsetindex(contacts, "dblscore", JBIDXNUM));
1656
1657     //LTE
1658     bson bsq1;
1659     bson_init_as_query(&bsq1);
1660     bson_append_start_object(&bsq1, "dblscore");
1661     bson_append_double(&bsq1, "$lte", 0.93);
1662     bson_append_finish_object(&bsq1);
1663     bson_finish(&bsq1);
1664     CU_ASSERT_FALSE_FATAL(bsq1.err);
1665
1666     bson bshints;
1667     bson_init_as_query(&bshints);
1668     bson_append_start_object(&bshints, "$orderby");
1669     bson_append_int(&bshints, "dblscore", -1); //DESC order on dblscore
1670     bson_append_finish_object(&bshints);
1671     bson_finish(&bshints);
1672     CU_ASSERT_FALSE_FATAL(bshints.err);
1673
1674     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1675     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1676
1677     uint32_t count = 0;
1678     TCXSTR *log = tcxstrnew();
1679     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1680     //fprintf(stderr, "%s", TCXSTRPTR(log));
1681
1682     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1683     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'ndblscore'"));
1684     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1685     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1686     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
1687     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 12"));
1688     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1689     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
1690     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
1691     CU_ASSERT_EQUAL(count, 2);
1692     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
1693
1694     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1695         if (i == 0) {
1696             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
1697             CU_ASSERT_FALSE(bson_compare_double(0.93, TCLISTVALPTR(q1res, i), "dblscore"));
1698         } else if (i == 1) {
1699             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
1700             CU_ASSERT_FALSE(bson_compare_double(0.333333, TCLISTVALPTR(q1res, i), "dblscore"));
1701         } else {
1702             CU_ASSERT_TRUE(false);
1703         }
1704     }
1705
1706     bson_destroy(&bsq1);
1707     bson_destroy(&bshints);
1708     tclistdel(q1res);
1709     tcxstrdel(log);
1710     ejdbquerydel(q1);
1711
1712     //LT
1713     //{'dblscore' : {'$lt' : 0.93}}
1714     bson_init_as_query(&bsq1);
1715     bson_append_start_object(&bsq1, "dblscore");
1716     bson_append_double(&bsq1, "$lt", 0.93);
1717     bson_append_finish_object(&bsq1);
1718     bson_finish(&bsq1);
1719     CU_ASSERT_FALSE_FATAL(bsq1.err);
1720
1721     bson_init_as_query(&bshints);
1722     bson_append_start_object(&bshints, "$orderby");
1723     bson_append_int(&bshints, "dblscore", -1); //DESC order on dblscore
1724     bson_append_finish_object(&bshints);
1725     bson_finish(&bshints);
1726     CU_ASSERT_FALSE_FATAL(bshints.err);
1727
1728     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1729     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1730
1731     count = 0;
1732     log = tcxstrnew();
1733     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1734     //fprintf(stderr, "%s", TCXSTRPTR(log));
1735
1736     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1737     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'ndblscore'"));
1738     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1739     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1740     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
1741     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 11"));
1742     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1743     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
1744     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 1"));
1745     CU_ASSERT_EQUAL(count, 1);
1746     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 1);
1747
1748     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1749         if (i == 0) {
1750             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
1751             CU_ASSERT_FALSE(bson_compare_double(0.333333, TCLISTVALPTR(q1res, i), "dblscore"));
1752         } else {
1753             CU_ASSERT_TRUE(false);
1754         }
1755     }
1756
1757     bson_destroy(&bsq1);
1758     bson_destroy(&bshints);
1759     tclistdel(q1res);
1760     tcxstrdel(log);
1761     ejdbquerydel(q1);
1762
1763     CU_ASSERT_TRUE(ejdbsetindex(contacts, "dblscore", JBIDXDROPALL));
1764
1765     //NOINDEX GTE
1766     bson_init_as_query(&bsq1);
1767     bson_append_start_object(&bsq1, "dblscore");
1768     bson_append_double(&bsq1, "$lte", 0.93);
1769     bson_append_finish_object(&bsq1);
1770     bson_finish(&bsq1);
1771     CU_ASSERT_FALSE_FATAL(bsq1.err);
1772
1773     bson_init_as_query(&bshints);
1774     bson_append_start_object(&bshints, "$orderby");
1775     bson_append_int(&bshints, "dblscore", -1); //DESC order on dblscore
1776     bson_append_finish_object(&bshints);
1777     bson_finish(&bshints);
1778     CU_ASSERT_FALSE_FATAL(bshints.err);
1779
1780     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1781     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1782
1783     count = 0;
1784     log = tcxstrnew();
1785     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1786     //fprintf(stderr, "%s", TCXSTRPTR(log));
1787
1788     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1789     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
1790     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1791     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1792     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
1793     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1794     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
1795     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
1796     CU_ASSERT_EQUAL(count, 2);
1797     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
1798
1799     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1800         if (i == 0) {
1801             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
1802             CU_ASSERT_FALSE(bson_compare_double(0.93, TCLISTVALPTR(q1res, i), "dblscore"));
1803         } else if (i == 1) {
1804             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
1805             CU_ASSERT_FALSE(bson_compare_double(0.333333, TCLISTVALPTR(q1res, i), "dblscore"));
1806         } else {
1807             CU_ASSERT_TRUE(false);
1808         }
1809     }
1810
1811     bson_destroy(&bsq1);
1812     bson_destroy(&bshints);
1813     tclistdel(q1res);
1814     tcxstrdel(log);
1815     ejdbquerydel(q1);
1816 }
1817
1818 void testQuery22(void) {
1819     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
1820     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
1821     CU_ASSERT_TRUE(ejdbsetindex(contacts, "address.country", JBIDXSTR));
1822
1823     //{"address.country" : {$begin : "Ru"}}
1824     bson bsq1;
1825     bson_init_as_query(&bsq1);
1826     bson_append_start_object(&bsq1, "address.country");
1827     bson_append_string(&bsq1, "$begin", "Ru");
1828     bson_append_finish_object(&bsq1);
1829     bson_finish(&bsq1);
1830     CU_ASSERT_FALSE_FATAL(bsq1.err);
1831
1832     bson bshints;
1833     bson_init_as_query(&bshints);
1834     bson_append_start_object(&bshints, "$orderby");
1835     bson_append_int(&bshints, "dblscore", -1); //DESC order on dblscore
1836     bson_append_finish_object(&bshints);
1837     bson_finish(&bshints);
1838     CU_ASSERT_FALSE_FATAL(bshints.err);
1839
1840     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1841     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1842
1843     uint32_t count = 0;
1844     TCXSTR *log = tcxstrnew();
1845     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1846     //fprintf(stderr, "%s", TCXSTRPTR(log));
1847
1848     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1849     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'saddress.country'"));
1850     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1851     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1852     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
1853     CU_ASSERT_PTR_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1854     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 2"));
1855     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 3"));
1856     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
1857     CU_ASSERT_EQUAL(count, 3);
1858     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 3);
1859
1860     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1861         if (i == 0) {
1862             CU_ASSERT_FALSE(bson_compare_string("Ivanov", TCLISTVALPTR(q1res, i), "name"));
1863             CU_ASSERT_FALSE(bson_compare_double(1.0, TCLISTVALPTR(q1res, i), "dblscore"));
1864             CU_ASSERT_FALSE(bson_compare_string("Russian Federation", TCLISTVALPTR(q1res, i), "address.country"));
1865         } else if (i == 1) {
1866             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
1867             CU_ASSERT_FALSE(bson_compare_double(0.93, TCLISTVALPTR(q1res, i), "dblscore"));
1868             CU_ASSERT_FALSE(bson_compare_string("Russian Federation", TCLISTVALPTR(q1res, i), "address.country"));
1869         } else if (i == 2) {
1870             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
1871             CU_ASSERT_FALSE(bson_compare_double(0.333333, TCLISTVALPTR(q1res, i), "dblscore"));
1872             CU_ASSERT_FALSE(bson_compare_string("Russian Federation", TCLISTVALPTR(q1res, i), "address.country"));
1873         } else {
1874             CU_ASSERT_TRUE(false);
1875         }
1876     }
1877
1878     bson_destroy(&bsq1);
1879     bson_destroy(&bshints);
1880     tclistdel(q1res);
1881     tcxstrdel(log);
1882     ejdbquerydel(q1);
1883
1884     CU_ASSERT_TRUE(ejdbsetindex(contacts, "address.country", JBIDXDROPALL));
1885
1886     bson_init_as_query(&bsq1);
1887     bson_append_start_object(&bsq1, "address.country");
1888     bson_append_string(&bsq1, "$begin", "R");
1889     bson_append_finish_object(&bsq1);
1890     bson_finish(&bsq1);
1891     CU_ASSERT_FALSE_FATAL(bsq1.err);
1892
1893     bson_init_as_query(&bshints);
1894     bson_append_start_object(&bshints, "$orderby");
1895     bson_append_int(&bshints, "dblscore", -1); //DESC order on dblscore
1896     bson_append_finish_object(&bshints);
1897     bson_finish(&bshints);
1898     CU_ASSERT_FALSE_FATAL(bshints.err);
1899
1900     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1901     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1902
1903     count = 0;
1904     log = tcxstrnew();
1905     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1906     //fprintf(stderr, "%s", TCXSTRPTR(log));
1907
1908     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1909     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
1910     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1911     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1912     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
1913     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1914     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 3"));
1915     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
1916     CU_ASSERT_EQUAL(count, 3);
1917     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 3);
1918
1919     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1920         if (i == 0) {
1921             CU_ASSERT_FALSE(bson_compare_string("Ivanov", TCLISTVALPTR(q1res, i), "name"));
1922             CU_ASSERT_FALSE(bson_compare_double(1.0, TCLISTVALPTR(q1res, i), "dblscore"));
1923             CU_ASSERT_FALSE(bson_compare_string("Russian Federation", TCLISTVALPTR(q1res, i), "address.country"));
1924         } else if (i == 1) {
1925             CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name"));
1926             CU_ASSERT_FALSE(bson_compare_double(0.93, TCLISTVALPTR(q1res, i), "dblscore"));
1927             CU_ASSERT_FALSE(bson_compare_string("Russian Federation", TCLISTVALPTR(q1res, i), "address.country"));
1928         } else if (i == 2) {
1929             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
1930             CU_ASSERT_FALSE(bson_compare_double(0.333333, TCLISTVALPTR(q1res, i), "dblscore"));
1931             CU_ASSERT_FALSE(bson_compare_string("Russian Federation", TCLISTVALPTR(q1res, i), "address.country"));
1932         } else {
1933             CU_ASSERT_TRUE(false);
1934         }
1935     }
1936
1937     bson_destroy(&bsq1);
1938     bson_destroy(&bshints);
1939     tclistdel(q1res);
1940     tcxstrdel(log);
1941     ejdbquerydel(q1);
1942 }
1943
1944 void testQuery23(void) {
1945     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
1946     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
1947
1948     bson bsq1;
1949     bson_init_as_query(&bsq1);
1950     bson_append_regex(&bsq1, "name", "(IvaNov$|John\\ TraVolta$)", "i");
1951     bson_finish(&bsq1);
1952     CU_ASSERT_FALSE_FATAL(bsq1.err);
1953
1954     bson bshints;
1955     bson_init_as_query(&bshints);
1956     bson_append_start_object(&bshints, "$orderby");
1957     bson_append_int(&bshints, "name", -1); //DESC order on dblscore
1958     bson_append_finish_object(&bshints);
1959     bson_finish(&bshints);
1960     CU_ASSERT_FALSE_FATAL(bshints.err);
1961
1962     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
1963     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
1964
1965     uint32_t count = 0;
1966     TCXSTR *log = tcxstrnew();
1967     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
1968
1969     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
1970     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
1971     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
1972     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
1973     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
1974     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
1975     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
1976     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
1977     CU_ASSERT_EQUAL(count, 2);
1978     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
1979
1980     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
1981         if (i == 0) {
1982             CU_ASSERT_FALSE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
1983         } else if (i == 1) {
1984             CU_ASSERT_FALSE(bson_compare_string("Ivanov", TCLISTVALPTR(q1res, i), "name"));
1985         } else {
1986             CU_ASSERT_TRUE(false);
1987         }
1988     }
1989
1990     bson_destroy(&bsq1);
1991     bson_destroy(&bshints);
1992     tclistdel(q1res);
1993     tcxstrdel(log);
1994     ejdbquerydel(q1);
1995 }
1996
1997 void testQuery24(void) {
1998     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
1999     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
2000
2001     bson bsq1;
2002     bson_init_as_query(&bsq1);
2003     bson_finish(&bsq1);
2004     CU_ASSERT_FALSE_FATAL(bsq1.err);
2005
2006     bson bshints;
2007     bson_init_as_query(&bshints);
2008     bson_append_start_object(&bshints, "$orderby");
2009     bson_append_int(&bshints, "name", -1); //DESC order on name
2010     bson_append_finish_object(&bshints);
2011     bson_append_long(&bshints, "$skip", 1);
2012     bson_finish(&bshints);
2013     CU_ASSERT_FALSE_FATAL(bshints.err);
2014
2015     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
2016     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2017
2018     uint32_t count = 0;
2019     TCXSTR *log = tcxstrnew();
2020     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2021     //fprintf(stderr, "%s", TCXSTRPTR(log));
2022
2023     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAX: 4294967295"));
2024     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SKIP: 1"));
2025     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
2026     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
2027     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
2028     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 0"));
2029     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
2030     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
2031     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 3"));
2032     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
2033     CU_ASSERT_EQUAL(count, 3);
2034     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 3);
2035
2036     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2037         if (i == TCLISTNUM(q1res) - 1) {
2038             CU_ASSERT_FALSE(bson_compare_string("Ivanov", TCLISTVALPTR(q1res, i), "name"));
2039         }
2040     }
2041
2042     bson_destroy(&bsq1);
2043     bson_destroy(&bshints);
2044     tclistdel(q1res);
2045     tcxstrdel(log);
2046     ejdbquerydel(q1);
2047
2048     bson_init_as_query(&bsq1);
2049     bson_finish(&bsq1);
2050     CU_ASSERT_FALSE_FATAL(bsq1.err);
2051
2052     bson_init_as_query(&bshints);
2053     bson_append_start_object(&bshints, "$orderby");
2054     bson_append_int(&bshints, "name", -1); //DESC order on name
2055     bson_append_finish_object(&bshints);
2056     bson_append_long(&bshints, "$skip", 1);
2057     bson_append_long(&bshints, "$max", 2);
2058     bson_finish(&bshints);
2059     CU_ASSERT_FALSE_FATAL(bshints.err);
2060     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
2061     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2062
2063     count = 0;
2064     log = tcxstrnew();
2065     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2066     //fprintf(stderr, "%s", TCXSTRPTR(log));
2067
2068     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAX: 2"));
2069     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SKIP: 1"));
2070     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
2071     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
2072     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 1"));
2073     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 0"));
2074     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: YES"));
2075     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
2076     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
2077     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 2"));
2078     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: YES"));
2079     CU_ASSERT_EQUAL(count, 2);
2080     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
2081
2082     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2083         if (i == TCLISTNUM(q1res) - 1) {
2084             CU_ASSERT_FALSE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
2085         }
2086     }
2087
2088     bson_destroy(&bsq1);
2089     bson_destroy(&bshints);
2090     tclistdel(q1res);
2091     tcxstrdel(log);
2092     ejdbquerydel(q1);
2093
2094     //No order specified
2095     bson_init_as_query(&bsq1);
2096     bson_finish(&bsq1);
2097     CU_ASSERT_FALSE_FATAL(bsq1.err);
2098
2099     bson_init_as_query(&bshints);
2100     bson_append_long(&bshints, "$skip", 1);
2101     bson_append_long(&bshints, "$max", 2);
2102     bson_finish(&bshints);
2103     CU_ASSERT_FALSE_FATAL(bshints.err);
2104     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
2105     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2106
2107     count = 0;
2108     log = tcxstrnew();
2109     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2110     //fprintf(stderr, "%s", TCXSTRPTR(log));
2111
2112     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAX: 2"));
2113     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SKIP: 1"));
2114     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
2115     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
2116     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
2117     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 0"));
2118     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
2119     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
2120     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
2121     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 2"));
2122     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
2123     CU_ASSERT_EQUAL(count, 2);
2124     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
2125
2126     bson_destroy(&bsq1);
2127     bson_destroy(&bshints);
2128     tclistdel(q1res);
2129     tcxstrdel(log);
2130     ejdbquerydel(q1);
2131
2132     bson_init_as_query(&bsq1);
2133     bson_finish(&bsq1);
2134     CU_ASSERT_FALSE_FATAL(bsq1.err);
2135
2136     bson_init_as_query(&bshints);
2137     bson_append_long(&bshints, "$skip", 4);
2138     bson_append_long(&bshints, "$max", 2);
2139     bson_finish(&bshints);
2140     CU_ASSERT_FALSE_FATAL(bshints.err);
2141     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
2142     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2143
2144     count = 0;
2145     log = tcxstrnew();
2146     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2147     //fprintf(stderr, "%s", TCXSTRPTR(log));
2148
2149     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAX: 2"));
2150     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SKIP: 4"));
2151     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
2152     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
2153     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
2154     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 0"));
2155     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
2156     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
2157     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 0"));
2158     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 0"));
2159     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
2160     CU_ASSERT_EQUAL(count, 0);
2161     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 0);
2162
2163     bson_destroy(&bsq1);
2164     bson_destroy(&bshints);
2165     tclistdel(q1res);
2166     tcxstrdel(log);
2167     ejdbquerydel(q1);
2168
2169
2170     bson_init_as_query(&bsq1);
2171     bson_finish(&bsq1);
2172     CU_ASSERT_FALSE_FATAL(bsq1.err);
2173
2174     bson_init_as_query(&bshints);
2175     bson_append_start_object(&bshints, "$orderby");
2176     bson_append_int(&bshints, "name", 1); //ASC
2177     bson_append_finish_object(&bshints);
2178     bson_append_long(&bshints, "$skip", 3);
2179     bson_finish(&bshints);
2180     CU_ASSERT_FALSE_FATAL(bshints.err);
2181
2182     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
2183     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2184
2185     count = 0;
2186     log = tcxstrnew();
2187     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2188     //fprintf(stderr, "%s", TCXSTRPTR(log));
2189
2190     CU_ASSERT_EQUAL(count, 1);
2191     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 1);
2192
2193     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2194         if (i == TCLISTNUM(q1res) - 1) {
2195             CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
2196         }
2197     }
2198
2199     bson_destroy(&bsq1);
2200     bson_destroy(&bshints);
2201     tclistdel(q1res);
2202     tcxstrdel(log);
2203     ejdbquerydel(q1);
2204
2205 }
2206
2207 void testQuery25(void) { //$or
2208     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
2209     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
2210
2211     bson bsq1;
2212     bson_init_as_query(&bsq1);
2213     bson_finish(&bsq1);
2214     CU_ASSERT_FALSE_FATAL(bsq1.err);
2215
2216     bson obs[2];
2217     bson_init_as_query(&obs[0]);
2218     bson_append_string(&obs[0], "name", "Ivanov");
2219     bson_finish(&obs[0]);
2220     CU_ASSERT_FALSE_FATAL(obs[0].err);
2221
2222     bson_init_as_query(&obs[1]);
2223     bson_append_string(&obs[1], "name", "Антонов");
2224     bson_finish(&obs[1]);
2225     CU_ASSERT_FALSE_FATAL(obs[1].err);
2226
2227     EJQ *q1 = ejdbcreatequery(jb, &bsq1, obs, 2, NULL);
2228     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2229
2230     uint32_t count = 0;
2231     TCXSTR *log = tcxstrnew();
2232     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2233     //fprintf(stderr, "%s", TCXSTRPTR(log));
2234
2235     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAX: 4294967295"));
2236     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SKIP: 0"));
2237     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
2238     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
2239     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
2240     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 0"));
2241     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "$OR QUERIES: 2"));
2242     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
2243     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
2244     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
2245     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 2"));
2246     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
2247     CU_ASSERT_EQUAL(count, 2);
2248     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
2249
2250     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2251         CU_ASSERT_TRUE(
2252             !bson_compare_string("Ivanov", TCLISTVALPTR(q1res, i), "name") ||
2253             !bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
2254
2255     }
2256     bson_destroy(&bsq1);
2257     tclistdel(q1res);
2258     tcxstrdel(log);
2259     ejdbquerydel(q1);
2260
2261     for (int i = 0; i < 2; ++i) {
2262         bson_destroy(&obs[i]);
2263     }
2264 }
2265
2266 void testQuery25_2(void) { //$or alternative
2267     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
2268     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
2269
2270     bson bsq1;
2271     bson_init_as_query(&bsq1);
2272     bson_append_start_array(&bsq1, "$or");
2273
2274     bson_append_start_object(&bsq1, "0");
2275     bson_append_string(&bsq1, "name", "Ivanov");
2276     bson_append_finish_object(&bsq1);
2277
2278     bson_append_start_object(&bsq1, "1");
2279     bson_append_string(&bsq1, "name", "Антонов");
2280     bson_append_finish_object(&bsq1);
2281
2282     bson_append_finish_array(&bsq1);
2283     bson_finish(&bsq1);
2284     CU_ASSERT_FALSE_FATAL(bsq1.err);
2285
2286     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2287     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2288
2289     uint32_t count = 0;
2290     TCXSTR *log = tcxstrnew();
2291     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2292     //fprintf(stderr, "%s", TCXSTRPTR(log));
2293
2294     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAX: 4294967295"));
2295     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SKIP: 0"));
2296     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
2297     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
2298     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
2299     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 0"));
2300     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "$OR QUERIES: 2"));
2301     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
2302     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
2303     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
2304     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 2"));
2305     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
2306     CU_ASSERT_EQUAL(count, 2);
2307     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
2308
2309     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2310         CU_ASSERT_TRUE(
2311             !bson_compare_string("Ivanov", TCLISTVALPTR(q1res, i), "name") ||
2312             !bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name"));
2313
2314     }
2315     bson_destroy(&bsq1);
2316     tclistdel(q1res);
2317     tcxstrdel(log);
2318     ejdbquerydel(q1);
2319 }
2320
2321 void testQuery26(void) { //$not $nin
2322     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
2323     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
2324
2325     //{'address.city' : {$not : 'Novosibirsk'}}
2326     bson bsq1;
2327     bson_init_as_query(&bsq1);
2328     bson_append_start_object(&bsq1, "address.city");
2329     bson_append_string(&bsq1, "$not", "Novosibirsk");
2330     bson_append_finish_object(&bsq1);
2331     bson_finish(&bsq1);
2332     CU_ASSERT_FALSE_FATAL(bsq1.err);
2333
2334     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2335     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2336
2337     uint32_t count = 0;
2338     TCXSTR *log = tcxstrnew();
2339     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2340     //fprintf(stderr, "%s", TCXSTRPTR(log));
2341
2342     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAX: 4294967295"));
2343     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SKIP: 0"));
2344     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
2345     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
2346     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
2347     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
2348     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "$OR QUERIES: 0"));
2349     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
2350     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
2351     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
2352     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 2"));
2353     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
2354     CU_ASSERT_EQUAL(count, 2);
2355     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
2356
2357     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2358         CU_ASSERT_TRUE(bson_compare_string("Novosibirsk", TCLISTVALPTR(q1res, i), "address.city"));
2359     }
2360
2361     bson_destroy(&bsq1);
2362     tclistdel(q1res);
2363     tcxstrdel(log);
2364     ejdbquerydel(q1);
2365
2366     //Double negation {'address.city' : {$not : {'$not' : 'Novosibirsk'}}}
2367     bson_init_as_query(&bsq1);
2368     bson_append_start_object(&bsq1, "address.city");
2369     bson_append_start_object(&bsq1, "$not");
2370     bson_append_string(&bsq1, "$not", "Novosibirsk");
2371     bson_append_finish_object(&bsq1);
2372     bson_append_finish_object(&bsq1);
2373     bson_finish(&bsq1);
2374     CU_ASSERT_FALSE_FATAL(bsq1.err);
2375
2376     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2377     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2378
2379     count = 0;
2380     log = tcxstrnew();
2381     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2382     //fprintf(stderr, "%s", TCXSTRPTR(log));
2383     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAX: 4294967295"));
2384     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SKIP: 0"));
2385     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
2386     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
2387     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
2388     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
2389     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "$OR QUERIES: 0"));
2390     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
2391     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
2392     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
2393     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 2"));
2394     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
2395     CU_ASSERT_EQUAL(count, 2);
2396     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
2397
2398     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2399         CU_ASSERT_TRUE(!bson_compare_string("Novosibirsk", TCLISTVALPTR(q1res, i), "address.city"));
2400     }
2401
2402     bson_destroy(&bsq1);
2403     tclistdel(q1res);
2404     tcxstrdel(log);
2405     ejdbquerydel(q1);
2406
2407     //"name" : {"$nin" : ["John Travolta", "Ivanov"]}
2408     bson_init_as_query(&bsq1);
2409     bson_append_start_object(&bsq1, "name");
2410     bson_append_start_array(&bsq1, "$nin");
2411     bson_append_string(&bsq1, "0", "John Travolta");
2412     bson_append_string(&bsq1, "1", "Ivanov");
2413     bson_append_finish_array(&bsq1);
2414     bson_append_finish_object(&bsq1);
2415     bson_finish(&bsq1);
2416     CU_ASSERT_FALSE_FATAL(bsq1.err);
2417
2418     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2419     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2420
2421     count = 0;
2422     log = tcxstrnew();
2423     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2424     //fprintf(stderr, "%s", TCXSTRPTR(log));
2425
2426     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAX: 4294967295"));
2427     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SKIP: 0"));
2428     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
2429     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
2430     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
2431     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
2432     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "$OR QUERIES: 0"));
2433     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
2434     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
2435     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2"));
2436     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 2"));
2437     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
2438     CU_ASSERT_EQUAL(count, 2);
2439     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
2440
2441     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2442         CU_ASSERT_TRUE(bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
2443         CU_ASSERT_TRUE(bson_compare_string("Ivanov", TCLISTVALPTR(q1res, i), "name"));
2444     }
2445
2446     bson_destroy(&bsq1);
2447     tclistdel(q1res);
2448     tcxstrdel(log);
2449     ejdbquerydel(q1);
2450 }
2451
2452 void testQuery27(void) { //$exists
2453     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
2454     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
2455
2456     //{'address.room' : {$exists : true}}
2457     bson bsq1;
2458     bson_init_as_query(&bsq1);
2459     bson_append_start_object(&bsq1, "address.room");
2460     bson_append_bool(&bsq1, "$exists", true);
2461     bson_append_finish_object(&bsq1);
2462     bson_finish(&bsq1);
2463     CU_ASSERT_FALSE_FATAL(bsq1.err);
2464
2465     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2466     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2467
2468     uint32_t count = 0;
2469     TCXSTR *log = tcxstrnew();
2470     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2471     //fprintf(stderr, "%s", TCXSTRPTR(log));
2472
2473     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAX: 4294967295"));
2474     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SKIP: 0"));
2475     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
2476     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
2477     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
2478     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
2479     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "$OR QUERIES: 0"));
2480     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
2481     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
2482     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 1"));
2483     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
2484     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
2485     CU_ASSERT_EQUAL(count, 1);
2486     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 1);
2487
2488     bson_destroy(&bsq1);
2489     tclistdel(q1res);
2490     tcxstrdel(log);
2491     ejdbquerydel(q1);
2492
2493
2494     //{'address.room' : {$exists : true}}
2495     bson_init_as_query(&bsq1);
2496     bson_append_start_object(&bsq1, "address.room");
2497     bson_append_bool(&bsq1, "$exists", false);
2498     bson_append_finish_object(&bsq1);
2499     bson_finish(&bsq1);
2500     CU_ASSERT_FALSE_FATAL(bsq1.err);
2501
2502     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2503     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2504
2505     count = 0;
2506     log = tcxstrnew();
2507     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2508     //fprintf(stderr, "%s", TCXSTRPTR(log));
2509
2510     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAX: 4294967295"));
2511     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SKIP: 0"));
2512     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
2513     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
2514     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
2515     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
2516     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "$OR QUERIES: 0"));
2517     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
2518     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
2519     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 3"));
2520     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 3"));
2521     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
2522     CU_ASSERT_EQUAL(count, 3);
2523     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 3);
2524
2525     bson_destroy(&bsq1);
2526     tclistdel(q1res);
2527     tcxstrdel(log);
2528     ejdbquerydel(q1);
2529
2530     //{'address.room' : {$not :  {$exists : true}}} is equivalent to {'address.room' : {$exists : false}}
2531     bson_init_as_query(&bsq1);
2532     bson_append_start_object(&bsq1, "address.room");
2533     bson_append_start_object(&bsq1, "$not");
2534     bson_append_bool(&bsq1, "$exists", true);
2535     bson_append_finish_object(&bsq1);
2536     bson_append_finish_object(&bsq1);
2537     bson_finish(&bsq1);
2538     CU_ASSERT_FALSE_FATAL(bsq1.err);
2539
2540     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2541     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2542
2543     count = 0;
2544     log = tcxstrnew();
2545     q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2546     //fprintf(stderr, "%s", TCXSTRPTR(log));
2547
2548     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAX: 4294967295"));
2549     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SKIP: 0"));
2550     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO"));
2551     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
2552     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0"));
2553     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
2554     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "$OR QUERIES: 0"));
2555     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO"));
2556     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
2557     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 3"));
2558     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 3"));
2559     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO"));
2560     CU_ASSERT_EQUAL(count, 3);
2561     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 3);
2562
2563     bson_destroy(&bsq1);
2564     tclistdel(q1res);
2565     tcxstrdel(log);
2566     ejdbquerydel(q1);
2567 }
2568
2569 void testQuery28(void) { // $gte: 64 bit number
2570         // TEST for #127: int64_t large numbers
2571         int64_t int64value = 0xFFFFFFFFFF02LL;
2572     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
2573     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
2574
2575     bson bsq1;
2576     bson_init_as_query(&bsq1);
2577         bson_append_start_object(&bsq1, "longscore");
2578     bson_append_long(&bsq1, "$gte", int64value);
2579     bson_append_finish_object(&bsq1);
2580     bson_finish(&bsq1);
2581     CU_ASSERT_FALSE_FATAL(bsq1.err);
2582
2583     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2584     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2585
2586     uint32_t count = 0;
2587     TCXSTR *log = tcxstrnew();
2588     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2589     //fprintf(stderr, "%s", TCXSTRPTR(log));
2590
2591     CU_ASSERT_EQUAL(count, 1);
2592     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 1);
2593
2594     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2595         if (i == 0) {
2596             CU_ASSERT_FALSE(bson_compare_string("444-123-333", TCLISTVALPTR(q1res, i), "phone"));
2597             CU_ASSERT_FALSE(bson_compare_long(int64value, TCLISTVALPTR(q1res, i), "longscore"));
2598         } else {
2599             CU_ASSERT_TRUE(false);
2600         }
2601     }
2602
2603     bson_destroy(&bsq1);
2604     tclistdel(q1res);
2605     tcxstrdel(log);
2606     ejdbquerydel(q1);
2607 }
2608
2609 void testQuery29(void) { 
2610         // #129: Test $begin Query with Symbols
2611     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
2612     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
2613
2614     bson bsq1;
2615     bson_init_as_query(&bsq1);
2616     bson_append_start_object(&bsq1, "symbol");
2617     bson_append_string(&bsq1, "$begin", "app");
2618     bson_append_finish_object(&bsq1);
2619     bson_finish(&bsq1);
2620     CU_ASSERT_FALSE_FATAL(bsq1.err);
2621
2622     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2623     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2624
2625     uint32_t count = 0;
2626     TCXSTR *log = tcxstrnew();
2627     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2628     //fprintf(stderr, "%s", TCXSTRPTR(log));
2629
2630     CU_ASSERT_EQUAL(count, 2);  // should match symbol_info: apple, application
2631     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
2632
2633     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2634         if (i == 0) CU_ASSERT_FALSE(bson_compare_string("apple", TCLISTVALPTR(q1res, i), "symbol"));
2635         if (i == 1) CU_ASSERT_FALSE(bson_compare_string("application", TCLISTVALPTR(q1res, i), "symbol"));
2636     }
2637
2638     bson_destroy(&bsq1);
2639     tclistdel(q1res);
2640     tcxstrdel(log);
2641     ejdbquerydel(q1);
2642 }
2643
2644 void testQuery30(void) { 
2645         // #129: Test equal with Symbols
2646     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
2647     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
2648
2649     bson bsq1;
2650     bson_init_as_query(&bsq1);
2651     bson_append_string(&bsq1, "symbol", "bison");
2652     bson_finish(&bsq1);
2653     CU_ASSERT_FALSE_FATAL(bsq1.err);
2654
2655     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2656     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2657
2658     uint32_t count = 0;
2659     TCXSTR *log = tcxstrnew();
2660     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2661     //fprintf(stderr, "%s", TCXSTRPTR(log));
2662
2663     CU_ASSERT_EQUAL(count, 1);  // should match symbol_info: bison
2664     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 1);
2665
2666     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2667         if (i == 0) CU_ASSERT_FALSE(bson_compare_string("bison", TCLISTVALPTR(q1res, i), "symbol"));
2668     }
2669
2670     bson_destroy(&bsq1);
2671     tclistdel(q1res);
2672     tcxstrdel(log);
2673     ejdbquerydel(q1);
2674 }
2675
2676 void testQuery31(void) { 
2677         // #129: Test $in array Query with Symbols
2678     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
2679     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
2680
2681     bson bsq1;
2682     bson_init_as_query(&bsq1);
2683     bson_append_start_object(&bsq1, "symbol");
2684     bson_append_start_array(&bsq1, "$in");
2685     bson_append_string(&bsq1, "0", "apple");
2686     bson_append_string(&bsq1, "1", "bison");
2687     bson_append_finish_array(&bsq1);
2688     bson_append_finish_object(&bsq1);
2689     bson_finish(&bsq1);
2690     CU_ASSERT_FALSE_FATAL(bsq1.err);
2691
2692     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2693     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2694
2695     uint32_t count = 0;
2696     TCXSTR *log = tcxstrnew();
2697     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2698     //fprintf(stderr, "%s", TCXSTRPTR(log));
2699
2700     CU_ASSERT_EQUAL(count, 2);  // should match symbol_info: apple, bison
2701     CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2);
2702
2703     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2704         if (i == 0) CU_ASSERT_FALSE(bson_compare_string("apple", TCLISTVALPTR(q1res, i), "symbol"));
2705         if (i == 1) CU_ASSERT_FALSE(bson_compare_string("bison", TCLISTVALPTR(q1res, i), "symbol"));
2706     }
2707
2708     bson_destroy(&bsq1);
2709     tclistdel(q1res);
2710     tcxstrdel(log);
2711     ejdbquerydel(q1);
2712 }
2713
2714 void testOIDSMatching(void) { //OID matching
2715     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
2716     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
2717
2718     bson_type bt;
2719     bson bsq1;
2720     bson_init_as_query(&bsq1);
2721     bson_finish(&bsq1);
2722     CU_ASSERT_FALSE_FATAL(bsq1.err);
2723
2724     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2725     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2726
2727     uint32_t count = 0;
2728     TCXSTR *log = tcxstrnew();
2729     TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log);
2730     CU_ASSERT_TRUE(count > 0);
2731     //fprintf(stderr, "%s", TCXSTRPTR(log));
2732
2733     for (int i = 0; i < TCLISTNUM(q1res); ++i) { //first
2734         char soid[25];
2735         bson_oid_t *oid;
2736         void *bsdata = TCLISTVALPTR(q1res, i);
2737         bson_iterator it2;
2738         bt = bson_find_from_buffer(&it2, bsdata, JDBIDKEYNAME);
2739         CU_ASSERT_EQUAL_FATAL(bt, BSON_OID);
2740         oid = bson_iterator_oid(&it2);
2741         bson_oid_to_string(oid, soid);
2742         //fprintf(stderr, "\nOID: %s", soid);
2743
2744         //OID in string form maching
2745         bson bsq2;
2746         bson_init_as_query(&bsq2);
2747
2748         if (i % 2 == 0) {
2749             bson_append_string(&bsq2, JDBIDKEYNAME, soid);
2750         } else {
2751             bson_append_oid(&bsq2, JDBIDKEYNAME, oid);
2752         }
2753
2754         bson_finish(&bsq2);
2755         CU_ASSERT_FALSE_FATAL(bsq2.err);
2756
2757         TCXSTR *log2 = tcxstrnew();
2758         EJQ *q2 = ejdbcreatequery(jb, &bsq2, NULL, 0, NULL);
2759         TCLIST *q2res = ejdbqryexecute(contacts, q2, &count, 0, log2);
2760         CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log2), "PRIMARY KEY MATCHING:"));
2761         CU_ASSERT_EQUAL(count, 1);
2762
2763         tcxstrdel(log2);
2764         ejdbquerydel(q2);
2765         tclistdel(q2res);
2766         bson_destroy(&bsq2);
2767     }
2768
2769     bson_destroy(&bsq1);
2770     tclistdel(q1res);
2771     tcxstrdel(log);
2772     ejdbquerydel(q1);
2773 }
2774
2775 void testEmptyFieldIndex(void) {
2776     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
2777     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
2778     CU_ASSERT_TRUE(ejdbsetindex(coll, "name", JBIDXDROPALL));
2779
2780     bson a1;
2781     bson_oid_t oid;
2782     bson_init(&a1);
2783     bson_append_string(&a1, "name", ""); //Empty but indexed field
2784     CU_ASSERT_FALSE_FATAL(a1.err);
2785     bson_finish(&a1);
2786     CU_ASSERT_TRUE(ejdbsavebson(coll, &a1, &oid));
2787     bson_destroy(&a1);
2788     CU_ASSERT_EQUAL(ejdbecode(coll->jb), 0);
2789
2790     CU_ASSERT_TRUE(ejdbsetindex(coll, "name", JBIDXISTR)); //Ignore case string index
2791     CU_ASSERT_EQUAL(ejdbecode(coll->jb), 0);
2792
2793     bson_init(&a1);
2794     bson_append_string(&a1, "name", ""); //Empty but indexed field
2795     CU_ASSERT_FALSE_FATAL(a1.err);
2796     bson_finish(&a1);
2797     CU_ASSERT_TRUE(ejdbsavebson(coll, &a1, &oid));
2798     bson_destroy(&a1);
2799     CU_ASSERT_EQUAL(ejdbecode(coll->jb), 0);
2800 }
2801
2802 void testICaseIndex(void) {
2803     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
2804     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
2805     CU_ASSERT_TRUE(ejdbsetindex(coll, "name", JBIDXISTR)); //Ignore case string index
2806
2807     //Save one more record
2808     bson a1;
2809     bson_oid_t oid;
2810     bson_init(&a1);
2811     bson_append_string(&a1, "name", "HeLlo WorlD"); //#1
2812     CU_ASSERT_FALSE_FATAL(a1.err);
2813     bson_finish(&a1);
2814     CU_ASSERT_TRUE(ejdbsavebson(coll, &a1, &oid));
2815     bson_destroy(&a1);
2816     CU_ASSERT_EQUAL(ejdbecode(coll->jb), 0);
2817
2818     bson_init(&a1);
2819     bson_append_string(&a1, "name", "THéÂtRE — театр"); //#2
2820     CU_ASSERT_FALSE_FATAL(a1.err);
2821     bson_finish(&a1);
2822     CU_ASSERT_TRUE(ejdbsavebson(coll, &a1, &oid));
2823     bson_destroy(&a1);
2824     CU_ASSERT_EQUAL(ejdbecode(coll->jb), 0);
2825
2826
2827     //Case insensitive query using index
2828     // {"name" : {"$icase" : "HellO woRLD"}}
2829     bson bsq1;
2830     bson_init_as_query(&bsq1);
2831     bson_append_start_object(&bsq1, "name");
2832     bson_append_string(&bsq1, "$icase", "HellO woRLD");
2833     bson_append_finish_object(&bsq1);
2834     bson_finish(&bsq1);
2835     CU_ASSERT_FALSE_FATAL(bsq1.err);
2836
2837     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2838     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2839
2840     uint32_t count = 0;
2841     TCXSTR *log = tcxstrnew();
2842     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
2843     CU_ASSERT_TRUE(count == 1);
2844     //fprintf(stderr, "%s", TCXSTRPTR(log));
2845     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'iname'"));
2846     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
2847
2848     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2849         CU_ASSERT_TRUE(!bson_compare_string("HeLlo WorlD", TCLISTVALPTR(q1res, i), "name"));
2850     }
2851
2852     bson_destroy(&bsq1);
2853     tclistdel(q1res);
2854     tcxstrdel(log);
2855     ejdbquerydel(q1);
2856
2857     //OK then drop icase index
2858     CU_ASSERT_TRUE(ejdbsetindex(coll, "name", JBIDXISTR | JBIDXDROP)); //Ignore case string index
2859
2860     //Same query:
2861     //{"name" : {"$icase" : {$in : ["théâtre - театр", "hello world"]}}}
2862     bson_init_as_query(&bsq1);
2863     bson_append_start_object(&bsq1, "name");
2864     bson_append_start_object(&bsq1, "$icase");
2865     bson_append_start_array(&bsq1, "$in");
2866     bson_append_string(&bsq1, "0", "théâtre - театр");
2867     bson_append_string(&bsq1, "1", "hello world");
2868     bson_append_finish_array(&bsq1);
2869     bson_append_finish_object(&bsq1);
2870     bson_append_finish_object(&bsq1);
2871     bson_finish(&bsq1);
2872     CU_ASSERT_FALSE_FATAL(bsq1.err);
2873
2874     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2875     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2876
2877     count = 0;
2878     log = tcxstrnew();
2879     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
2880     //fprintf(stderr, "%s", TCXSTRPTR(log));
2881     CU_ASSERT_TRUE(count == 2);
2882     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
2883     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 2"));
2884
2885     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
2886         CU_ASSERT_TRUE(
2887             !bson_compare_string("HeLlo WorlD", TCLISTVALPTR(q1res, i), "name") ||
2888             !bson_compare_string("THéÂtRE — театр", TCLISTVALPTR(q1res, i), "name")
2889         );
2890     }
2891
2892     bson_destroy(&bsq1);
2893     tclistdel(q1res);
2894     tcxstrdel(log);
2895     ejdbquerydel(q1);
2896 }
2897
2898 void testTicket7(void) { //https://github.com/Softmotions/ejdb/issues/7
2899     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
2900     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
2901
2902     char xoid[25];
2903     bson_iterator it;
2904     bson_type bt;
2905     bson bsq1;
2906     bson_init_as_query(&bsq1);
2907     bson_finish(&bsq1);
2908     CU_ASSERT_FALSE_FATAL(bsq1.err);
2909
2910     const int onum = 3; //number of saved bsons
2911     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
2912     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
2913     uint32_t count = 0;
2914     TCXSTR *log = tcxstrnew();
2915     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
2916     //fprintf(stderr, "%s", TCXSTRPTR(log));
2917     CU_ASSERT_TRUE_FATAL(count >= onum);
2918
2919     for (int i = 0; i < TCLISTNUM(q1res) && i < onum; ++i) {
2920         void *bsdata = TCLISTVALPTR(q1res, i);
2921         CU_ASSERT_PTR_NOT_NULL_FATAL(bsdata);
2922     }
2923     //Now perform $in qry
2924     //{_id : {$in : ["oid1", "oid2", "oid3"]}}
2925     bson bsq2;
2926     bson_init_as_query(&bsq2);
2927     bson_append_start_object(&bsq2, "_id");
2928     bson_append_start_array(&bsq2, "$in");
2929     for (int i = 0; i < onum; ++i) {
2930         char ibuf[10];
2931         snprintf(ibuf, 10, "%d", i);
2932         bson_oid_t *oid = NULL;
2933         bt = bson_find_from_buffer(&it, TCLISTVALPTR(q1res, i), "_id");
2934         CU_ASSERT_TRUE_FATAL(bt == BSON_OID);
2935         oid = bson_iterator_oid(&it);
2936         CU_ASSERT_PTR_NOT_NULL_FATAL(oid);
2937         bson_oid_to_string(oid, xoid);
2938         //fprintf(stderr, "\ni=%s oid=%s", ibuf, xoid);
2939         if (i % 2 == 0) {
2940             bson_append_oid(&bsq2, ibuf, oid);
2941         } else {
2942             bson_append_string(&bsq2, ibuf, xoid);
2943         }
2944     }
2945     bson_append_finish_array(&bsq2);
2946     bson_append_finish_object(&bsq2);
2947     bson_finish(&bsq2);
2948     CU_ASSERT_FALSE_FATAL(bsq2.err);
2949
2950     EJQ *q2 = ejdbcreatequery(jb, &bsq2, NULL, 0, NULL);
2951     CU_ASSERT_PTR_NOT_NULL_FATAL(q2);
2952     uint32_t count2 = 0;
2953     TCXSTR *log2 = tcxstrnew();
2954     TCLIST *q2res = ejdbqryexecute(coll, q2, &count2, 0, log2);
2955     //fprintf(stderr, "\n%s", TCXSTRPTR(log2));
2956     CU_ASSERT_TRUE(count2 == 3);
2957     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log2), "MAIN IDX: 'NONE'"));
2958     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log2), "PRIMARY KEY MATCHING: TRUE"));
2959     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log2), "RS COUNT: 3"));
2960
2961     for (int i = 0; i < TCLISTNUM(q2res); ++i) {
2962         bson_oid_t *oid1 = NULL;
2963         bt = bson_find_from_buffer(&it, TCLISTVALPTR(q2res, i), "_id");
2964         CU_ASSERT_TRUE_FATAL(bt == BSON_OID);
2965         oid1 = bson_iterator_oid(&it);
2966         bool matched = false;
2967         for (int j = 0; j < TCLISTNUM(q1res); ++j) {
2968             bson_oid_t *oid2 = NULL;
2969             bt = bson_find_from_buffer(&it, TCLISTVALPTR(q1res, j), "_id");
2970             CU_ASSERT_TRUE_FATAL(bt == BSON_OID);
2971             oid2 = bson_iterator_oid(&it);
2972             if (!memcmp(oid1, oid2, sizeof (bson_oid_t))) {
2973                 matched = true;
2974                 void *ptr = tclistremove2(q1res, j);
2975                 if (ptr) {
2976                     TCFREE(ptr);
2977                 }
2978                 break;
2979             }
2980         }
2981         CU_ASSERT_TRUE(matched);
2982     }
2983
2984     bson_destroy(&bsq1);
2985     tclistdel(q1res);
2986     tcxstrdel(log);
2987     ejdbquerydel(q1);
2988
2989     bson_destroy(&bsq2);
2990     tclistdel(q2res);
2991     tcxstrdel(log2);
2992     ejdbquerydel(q2);
2993 }
2994
2995 void testTicket8(void) { //https://github.com/Softmotions/ejdb/issues/8
2996     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
2997     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
2998
2999     bson bsq1;
3000     bson_init_as_query(&bsq1);
3001     bson_finish(&bsq1);
3002     CU_ASSERT_FALSE_FATAL(bsq1.err);
3003
3004     bson bshits1;
3005     bson_init_as_query(&bshits1);
3006     bson_append_start_object(&bshits1, "$fields");
3007     bson_append_int(&bshits1, "_id", 1);
3008     bson_append_int(&bshits1, "phone", 1);
3009     bson_append_int(&bshits1, "address.city", 1);
3010     bson_append_int(&bshits1, "labels", 1);
3011     bson_append_finish_object(&bshits1);
3012     bson_finish(&bshits1);
3013     CU_ASSERT_FALSE_FATAL(bshits1.err);
3014
3015
3016     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshits1);
3017     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3018     uint32_t count = 0;
3019     TCXSTR *log = tcxstrnew();
3020     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3021     //fprintf(stderr, "%s", TCXSTRPTR(log));
3022
3023     //    for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3024     //        void *bsdata = TCLISTVALPTR(q1res, i);
3025     //        bson_print_raw(bsdata, 0);
3026     //    }
3027
3028     bson_type bt;
3029     bson_iterator it;
3030     int ccount = 0;
3031     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3032         void *bsdata = TCLISTVALPTR(q1res, i);
3033         CU_ASSERT_PTR_NOT_NULL_FATAL(bsdata);
3034
3035         if (!bson_compare_string("333-222-333", TCLISTVALPTR(q1res, i), "phone")) {
3036             ++ccount;
3037             bson_iterator_from_buffer(&it, bsdata);
3038             bt = bson_find_fieldpath_value("_id", &it);
3039             CU_ASSERT_TRUE(bt == BSON_OID);
3040             bson_iterator_from_buffer(&it, bsdata);
3041             bt = bson_find_fieldpath_value("address", &it);
3042             CU_ASSERT_TRUE(bt == BSON_OBJECT);
3043             bson_iterator_from_buffer(&it, bsdata);
3044             bt = bson_find_fieldpath_value("address.city", &it);
3045             CU_ASSERT_TRUE(bt == BSON_STRING);
3046             CU_ASSERT_FALSE(strcmp("Novosibirsk", bson_iterator_string(&it)));
3047             bson_iterator_from_buffer(&it, bsdata);
3048             bt = bson_find_fieldpath_value("address.zip", &it);
3049             CU_ASSERT_TRUE(bt == BSON_EOO);
3050             bson_iterator_from_buffer(&it, bsdata);
3051             bt = bson_find_fieldpath_value("age", &it);
3052             CU_ASSERT_TRUE(bt == BSON_EOO);
3053             bson_iterator_from_buffer(&it, bsdata);
3054             bt = bson_find_fieldpath_value("name", &it);
3055             CU_ASSERT_TRUE(bt == BSON_EOO);
3056             bson_iterator_from_buffer(&it, bsdata);
3057             bt = bson_find_fieldpath_value("labels", &it);
3058             CU_ASSERT_TRUE(bt == BSON_EOO);
3059         } else if (!bson_compare_string("444-123-333", TCLISTVALPTR(q1res, i), "phone")) {
3060             ++ccount;
3061             bson_iterator_from_buffer(&it, bsdata);
3062             bt = bson_find_fieldpath_value("_id", &it);
3063             CU_ASSERT_TRUE(bt == BSON_OID);
3064             bson_iterator_from_buffer(&it, bsdata);
3065             bt = bson_find_fieldpath_value("address", &it);
3066             CU_ASSERT_TRUE(bt == BSON_OBJECT);
3067             bson_iterator_from_buffer(&it, bsdata);
3068             bt = bson_find_fieldpath_value("address.city", &it);
3069             CU_ASSERT_TRUE(bt == BSON_STRING);
3070             CU_ASSERT_FALSE(strcmp("Novosibirsk", bson_iterator_string(&it)));
3071             bson_iterator_from_buffer(&it, bsdata);
3072             bt = bson_find_fieldpath_value("address.zip", &it);
3073             CU_ASSERT_TRUE(bt == BSON_EOO);
3074             bson_iterator_from_buffer(&it, bsdata);
3075             bt = bson_find_fieldpath_value("age", &it);
3076             CU_ASSERT_TRUE(bt == BSON_EOO);
3077             bson_iterator_from_buffer(&it, bsdata);
3078             bt = bson_find_fieldpath_value("name", &it);
3079             CU_ASSERT_TRUE(bt == BSON_EOO);
3080             bson_iterator_from_buffer(&it, bsdata);
3081             bt = bson_find_fieldpath_value("labels", &it);
3082             CU_ASSERT_TRUE(bt == BSON_ARRAY);
3083             CU_ASSERT_FALSE(bson_compare_string("red", bsdata, "labels.0"));
3084             CU_ASSERT_FALSE(bson_compare_string("green", bsdata, "labels.1"));
3085             CU_ASSERT_FALSE(bson_compare_string("with gap, label", bsdata, "labels.2"));
3086         }
3087     }
3088     CU_ASSERT_TRUE(ccount == 2);
3089     bson_destroy(&bshits1);
3090     tclistdel(q1res);
3091     tcxstrclear(log);
3092     ejdbquerydel(q1);
3093
3094     //NEXT Q
3095     bson_init_as_query(&bshits1);
3096     bson_append_start_object(&bshits1, "$fields");
3097     bson_append_int(&bshits1, "phone", 1);
3098     bson_append_int(&bshits1, "address.city", 0);
3099     bson_append_int(&bshits1, "labels", 0);
3100     bson_append_finish_object(&bshits1);
3101     bson_finish(&bshits1);
3102     CU_ASSERT_FALSE_FATAL(bshits1.err);
3103
3104     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshits1);
3105     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3106     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3107     CU_ASSERT_PTR_NULL_FATAL(q1res);
3108     CU_ASSERT_EQUAL(ejdbecode(jb), JBEQINCEXCL);
3109     ejdbquerydel(q1);
3110     tcxstrclear(log);
3111     bson_destroy(&bshits1);
3112     bson_destroy(&bsq1);
3113
3114     //NEXT Q
3115     bson_init_as_query(&bsq1);
3116     //bson_append_string(&bsq1, "name", "Антонов");
3117     bson_append_start_object(&bsq1, "address");
3118     bson_append_bool(&bsq1, "$exists", true);
3119     bson_append_finish_object(&bsq1);
3120     bson_finish(&bsq1);
3121     CU_ASSERT_FALSE_FATAL(bsq1.err);
3122
3123     bson_init_as_query(&bshits1);
3124     bson_append_start_object(&bshits1, "$fields");
3125     bson_append_int(&bshits1, "phone", 0);
3126     bson_append_int(&bshits1, "address.city", 0);
3127     bson_append_int(&bshits1, "address.room", 0);
3128     bson_append_int(&bshits1, "labels", 0);
3129     bson_append_int(&bshits1, "complexarr.0", 0);
3130     bson_append_int(&bshits1, "_id", 0);
3131     bson_append_finish_object(&bshits1);
3132     bson_finish(&bshits1);
3133     CU_ASSERT_FALSE_FATAL(bshits1.err);
3134     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshits1);
3135     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3136     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3137     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
3138     CU_ASSERT_EQUAL(ejdbecode(jb), TCESUCCESS);
3139
3140     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3141         void *bsdata = TCLISTVALPTR(q1res, i);
3142         bson_type bt;
3143         bson_iterator_from_buffer(&it, bsdata);
3144         bt = bson_find_fieldpath_value("_id", &it);
3145         CU_ASSERT_TRUE(bt == BSON_EOO);
3146         bson_iterator_from_buffer(&it, bsdata);
3147         bt = bson_find_fieldpath_value("phone", &it);
3148         CU_ASSERT_TRUE(bt == BSON_EOO);
3149         bson_iterator_from_buffer(&it, bsdata);
3150         bt = bson_find_fieldpath_value("address", &it);
3151         CU_ASSERT_TRUE(bt == BSON_OBJECT);
3152         bson_iterator_from_buffer(&it, bsdata);
3153         //bt = bson_find_fieldpath_value("address.country", &it);
3154         //CU_ASSERT_TRUE(bt == BSON_STRING);
3155         bson_iterator_from_buffer(&it, bsdata);
3156         bt = bson_find_fieldpath_value("address.city", &it);
3157         CU_ASSERT_TRUE(bt == BSON_EOO);
3158         bson_iterator_from_buffer(&it, bsdata);
3159         bt = bson_find_fieldpath_value("address.room", &it);
3160         CU_ASSERT_TRUE(bt == BSON_EOO);
3161         bson_iterator_from_buffer(&it, bsdata);
3162         bt = bson_find_fieldpath_value("labels", &it);
3163         CU_ASSERT_TRUE(bt == BSON_EOO);
3164         //bson_print_raw(bsdata, 0);
3165     }
3166
3167     bson_destroy(&bsq1);
3168     bson_destroy(&bshits1);
3169     tclistdel(q1res);
3170     tcxstrdel(log);
3171     ejdbquerydel(q1);
3172
3173 }
3174
3175 void testUpdate1(void) { //https://github.com/Softmotions/ejdb/issues/9
3176     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
3177     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
3178
3179     bson_iterator it;
3180
3181     //q: {name : 'John Travolta', $set : {'labels' : ['black', 'blue'], 'age' : 58}}
3182     bson bsq1;
3183     bson_init_as_query(&bsq1);
3184     bson_append_string(&bsq1, "name", "John Travolta");
3185     bson_append_start_object(&bsq1, "$set");
3186     bson_append_start_array(&bsq1, "labels");
3187     bson_append_string(&bsq1, "0", "black");
3188     bson_append_string(&bsq1, "1", "blue");
3189     bson_append_finish_array(&bsq1);
3190     bson_append_int(&bsq1, "age", 58);
3191     bson_append_finish_object(&bsq1);
3192     bson_finish(&bsq1);
3193     CU_ASSERT_FALSE_FATAL(bsq1.err);
3194
3195     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3196     CU_ASSERT_TRUE(ejdbecode(jb) == 0);
3197     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3198     uint32_t count = 0;
3199     TCXSTR *log = tcxstrnew();
3200     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3201     CU_ASSERT_TRUE(ejdbecode(jb) == 0);
3202     //fprintf(stderr, "%s", TCXSTRPTR(log));
3203     CU_ASSERT_EQUAL(1, count);
3204     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: YES"));
3205
3206     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3207         CU_ASSERT_TRUE(!bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
3208         bson_iterator_from_buffer(&it, TCLISTVALPTR(q1res, i));
3209         CU_ASSERT_TRUE(bson_find_from_buffer(&it, TCLISTVALPTR(q1res, i), "age") == BSON_EOO);
3210     }
3211
3212     bson_destroy(&bsq1);
3213     tclistdel(q1res);
3214     tcxstrdel(log);
3215     ejdbquerydel(q1);
3216
3217     //q2: {name : 'John Travolta', age: 58}
3218     bson_init_as_query(&bsq1);
3219     bson_append_string(&bsq1, "name", "John Travolta");
3220     bson_append_int(&bsq1, "age", 58);
3221     bson_append_finish_object(&bsq1);
3222     bson_finish(&bsq1);
3223     CU_ASSERT_FALSE_FATAL(bsq1.err);
3224
3225     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3226     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3227     count = 0;
3228     log = tcxstrnew();
3229     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3230     //fprintf(stderr, "%s", TCXSTRPTR(log));
3231     CU_ASSERT_EQUAL(1, TCLISTNUM(q1res));
3232     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: NO"));
3233
3234     int age = 58;
3235     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3236         CU_ASSERT_FALSE(bson_compare_long(age, TCLISTVALPTR(q1res, i), "age"));
3237         CU_ASSERT_FALSE(bson_compare_string("black", TCLISTVALPTR(q1res, i), "labels.0"));
3238         CU_ASSERT_FALSE(bson_compare_string("blue", TCLISTVALPTR(q1res, i), "labels.1"));
3239     }
3240     bson_destroy(&bsq1);
3241     tclistdel(q1res);
3242     tcxstrdel(log);
3243     ejdbquerydel(q1);
3244
3245     //q3: {name : 'John Travolta', '$inc' : {'age' : -1}}
3246     bson_init_as_query(&bsq1);
3247     bson_append_string(&bsq1, "name", "John Travolta");
3248     bson_append_start_object(&bsq1, "$inc");
3249     bson_append_int(&bsq1, "age", -1);
3250     bson_append_finish_object(&bsq1);
3251     bson_append_finish_object(&bsq1);
3252     bson_finish(&bsq1);
3253     CU_ASSERT_FALSE_FATAL(bsq1.err);
3254
3255     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3256     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3257     count = 0;
3258     log = tcxstrnew();
3259     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3260     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: YES"));
3261     bson_destroy(&bsq1);
3262     tclistdel(q1res);
3263     tcxstrdel(log);
3264     ejdbquerydel(q1);
3265
3266
3267     //q4: {name : 'John Travolta', age: 57}
3268     bson_init_as_query(&bsq1);
3269     bson_append_string(&bsq1, "name", "John Travolta");
3270     bson_append_int(&bsq1, "age", 57);
3271     bson_append_finish_object(&bsq1);
3272     bson_finish(&bsq1);
3273     CU_ASSERT_FALSE_FATAL(bsq1.err);
3274
3275     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3276     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3277     count = 0;
3278     log = tcxstrnew();
3279     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3280     //fprintf(stderr, "%s", TCXSTRPTR(log));
3281     CU_ASSERT_EQUAL(1, TCLISTNUM(q1res));
3282     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: NO"));
3283
3284     --age;
3285     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3286         CU_ASSERT_FALSE(bson_compare_long(age, TCLISTVALPTR(q1res, i), "age"));
3287     }
3288
3289     bson_destroy(&bsq1);
3290     tclistdel(q1res);
3291     tcxstrdel(log);
3292     ejdbquerydel(q1);
3293         
3294 }
3295
3296 void testUpdate2(void) { //https://github.com/Softmotions/ejdb/issues/9
3297     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
3298     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
3299     CU_ASSERT_TRUE(ejdbsetindex(coll, "age", JBIDXNUM));
3300
3301     //q: {name : 'John Travolta', '$inc' : {'age' : 1}}
3302     bson bsq1;
3303     bson_init_as_query(&bsq1);
3304     bson_append_string(&bsq1, "name", "John Travolta");
3305     bson_append_start_object(&bsq1, "$inc");
3306     bson_append_int(&bsq1, "age", 1);
3307     bson_append_finish_object(&bsq1);
3308     bson_append_start_object(&bsq1, "$set");
3309     bson_append_bool(&bsq1, "visited", true);
3310     bson_append_finish_object(&bsq1);
3311     bson_append_finish_object(&bsq1);
3312     bson_finish(&bsq1);
3313     CU_ASSERT_FALSE_FATAL(bsq1.err);
3314
3315     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3316     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3317     uint32_t count = 0;
3318     TCXSTR *log = tcxstrnew();
3319     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3320     //fprintf(stderr, "%s", TCXSTRPTR(log));
3321
3322     bson_destroy(&bsq1);
3323     tclistdel(q1res);
3324     tcxstrdel(log);
3325     ejdbquerydel(q1);
3326
3327     bson_init_as_query(&bsq1);
3328     bson_append_string(&bsq1, "name", "John Travolta");
3329     bson_append_int(&bsq1, "age", 58);
3330     bson_append_finish_object(&bsq1);
3331     bson_finish(&bsq1);
3332     CU_ASSERT_FALSE_FATAL(bsq1.err);
3333
3334     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3335     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3336     count = 0;
3337     log = tcxstrnew();
3338     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3339     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'nage'"));
3340     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 8"));
3341     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
3342     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3343         CU_ASSERT_FALSE(bson_compare_bool(true, TCLISTVALPTR(q1res, i), "visited"));
3344     }
3345
3346     bson_destroy(&bsq1);
3347     tclistdel(q1res);
3348     tcxstrdel(log);
3349     ejdbquerydel(q1);
3350
3351 }
3352
3353 void testUpdate3(void) {
3354     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
3355     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
3356
3357         //q5: {name: 'John Travolta', $rename: { "name" : "fullName"}}
3358     bson bsq1;
3359     bson_iterator it;
3360
3361         bson_init_as_query(&bsq1);
3362     bson_append_string(&bsq1, "name", "John Travolta");
3363     bson_append_start_object(&bsq1, "$rename");
3364     bson_append_string(&bsq1, "name", "fullName");
3365     //bson_append_finish_object(&bsq1);
3366     bson_append_finish_object(&bsq1);
3367     bson_finish(&bsq1);
3368     CU_ASSERT_FALSE_FATAL(bsq1.err);
3369
3370     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3371     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3372     uint32_t count = 0;
3373     TCXSTR *log = tcxstrnew();
3374     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3375
3376     //fprintf(stderr, "%s", TCXSTRPTR(log));
3377     CU_ASSERT_EQUAL(1, count);
3378     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: YES"));
3379
3380
3381     bson_destroy(&bsq1);
3382     tclistdel(q1res);
3383     tcxstrdel(log);
3384     ejdbquerydel(q1);
3385
3386     bson_init_as_query(&bsq1);
3387     bson_append_string(&bsq1, "fullName", "John Travolta");
3388     bson_append_finish_object(&bsq1);
3389     bson_finish(&bsq1);
3390     CU_ASSERT_FALSE_FATAL(bsq1.err);
3391
3392     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3393     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3394     count = 0;
3395     log = tcxstrnew();
3396     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3397
3398     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3399         CU_ASSERT_TRUE(!bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "fullName"));
3400         bson_iterator_from_buffer(&it, TCLISTVALPTR(q1res, i));
3401         CU_ASSERT_TRUE(bson_find_from_buffer(&it, TCLISTVALPTR(q1res, i), "name") == BSON_EOO);
3402     }
3403
3404     bson_destroy(&bsq1);
3405     tclistdel(q1res);
3406     tcxstrdel(log);
3407     ejdbquerydel(q1);
3408         
3409         //q6: {name: 'John Travolta', $rename: { "fullName" : "name"}}
3410         bson_init_as_query(&bsq1);
3411     bson_append_string(&bsq1, "fullName", "John Travolta");
3412     bson_append_start_object(&bsq1, "$rename");
3413     bson_append_string(&bsq1, "fullName", "name");
3414     //bson_append_finish_object(&bsq1);
3415     bson_append_finish_object(&bsq1);
3416     bson_finish(&bsq1);
3417     CU_ASSERT_FALSE_FATAL(bsq1.err);
3418
3419     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3420     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3421     count = 0;
3422     log = tcxstrnew();
3423     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3424
3425     //fprintf(stderr, "%s", TCXSTRPTR(log));
3426     CU_ASSERT_EQUAL(1, count);
3427     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: YES"));
3428
3429     bson_destroy(&bsq1);
3430     tclistdel(q1res);
3431     tcxstrdel(log);
3432     ejdbquerydel(q1);
3433
3434     bson_init_as_query(&bsq1);
3435     bson_append_string(&bsq1, "fullName", "John Travolta");
3436     bson_append_finish_object(&bsq1);
3437     bson_finish(&bsq1);
3438     CU_ASSERT_FALSE_FATAL(bsq1.err);
3439
3440     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3441     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3442     count = 0;
3443     log = tcxstrnew();
3444     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3445
3446     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3447         CU_ASSERT_TRUE(!bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
3448         bson_iterator_from_buffer(&it, TCLISTVALPTR(q1res, i));
3449         CU_ASSERT_TRUE(bson_find_from_buffer(&it, TCLISTVALPTR(q1res, i), "fullName") == BSON_EOO);
3450     }
3451
3452     bson_destroy(&bsq1);
3453     tclistdel(q1res);
3454     tcxstrdel(log);
3455     ejdbquerydel(q1);
3456         
3457 }
3458
3459 void testTicket88(void) { //https://github.com/Softmotions/ejdb/issues/88
3460     EJCOLL *ccoll = ejdbcreatecoll(jb, "ticket88", NULL);
3461     CU_ASSERT_PTR_NOT_NULL(ccoll);
3462
3463     bson r;
3464     bson_oid_t oid;
3465     for (int i = 0; i < 10; ++i) {
3466         bson_init(&r);
3467         bson_append_start_array(&r, "arr1");
3468         bson_append_start_object(&r, "0");
3469         bson_append_int(&r, "f1", 1 + i);
3470         bson_append_finish_object(&r);
3471         bson_append_start_object(&r, "1");
3472         bson_append_int(&r, "f1", 2 + i);
3473         bson_append_finish_object(&r);
3474         bson_append_finish_array(&r);
3475         bson_finish(&r);
3476         CU_ASSERT_TRUE(ejdbsavebson(ccoll, &r, &oid));
3477         bson_destroy(&r);
3478     }
3479
3480     bson bsq1;
3481     bson_init_as_query(&bsq1);
3482     bson_append_start_object(&bsq1, "$set");
3483     bson_append_string(&bsq1, "arr1.0.f2", "x");
3484     bson_append_int(&bsq1, "arr1.1", 1111);
3485     bson_append_string(&bsq1, "a.b", "c");
3486     bson_append_finish_object(&bsq1);
3487     bson_finish(&bsq1);
3488
3489     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3490     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3491     uint32_t count = 0;
3492     ejdbqryexecute(ccoll, q1, &count, JBQRYCOUNT, NULL);
3493     CU_ASSERT_TRUE(ejdbecode(jb) == 0);
3494     CU_ASSERT_EQUAL(count, 10);
3495     ejdbquerydel(q1);
3496     bson_destroy(&bsq1);
3497
3498     bson bsq2;
3499     bson_init_as_query(&bsq2);
3500     bson_append_string(&bsq2, "arr1.0.f2", "x");
3501     bson_append_int(&bsq2, "arr1.1", 1111);
3502     bson_append_string(&bsq2, "a.b", "c");
3503     bson_finish(&bsq2);
3504     q1 = ejdbcreatequery(jb, &bsq2, NULL, 0, NULL);
3505     ejdbqryexecute(ccoll, q1, &count, JBQRYCOUNT, NULL);
3506     CU_ASSERT_EQUAL(count, 10);
3507     ejdbquerydel(q1);
3508     bson_destroy(&bsq2);
3509 }
3510
3511 void testTicket89(void) { //https://github.com/Softmotions/ejdb/issues/89
3512     EJCOLL *ccoll = ejdbcreatecoll(jb, "ticket89", NULL);
3513     CU_ASSERT_PTR_NOT_NULL(ccoll);
3514
3515     bson r;
3516     bson_oid_t oid;
3517
3518     bson_init(&r);
3519     //{"test":[["aaa"],["bbb"]]}
3520     bson_append_start_array(&r, "test");
3521     bson_append_start_array(&r, "0");
3522     bson_append_string(&r, "0", "aaa");
3523     bson_append_finish_array(&r);
3524     bson_append_start_array(&r, "1");
3525     bson_append_string(&r, "0", "bbb");
3526     bson_append_finish_array(&r);
3527     bson_append_finish_array(&r);
3528     bson_finish(&r);
3529     CU_ASSERT_TRUE(ejdbsavebson(ccoll, &r, &oid));
3530     bson_destroy(&r);
3531
3532     bson bsq1;
3533     bson_init_as_query(&bsq1);
3534     bson_append_start_object(&bsq1, "$addToSet");
3535     bson_append_string(&bsq1, "test.0", "bbb");
3536     bson_append_finish_object(&bsq1);
3537     bson_finish(&bsq1);
3538
3539     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3540     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3541     uint32_t count = 0;
3542     ejdbqryexecute(ccoll, q1, &count, JBQRYCOUNT, NULL);
3543     CU_ASSERT_TRUE(ejdbecode(jb) == 0);
3544     CU_ASSERT_EQUAL(count, 1);
3545     ejdbquerydel(q1);
3546     bson_destroy(&bsq1);
3547
3548     bson_init_as_query(&bsq1);
3549     bson_append_string(&bsq1, "test.0.1", "bbb");
3550     bson_finish(&bsq1);
3551     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3552     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3553     ejdbqryexecute(ccoll, q1, &count, JBQRYCOUNT, NULL);
3554     CU_ASSERT_TRUE(ejdbecode(jb) == 0);
3555     CU_ASSERT_EQUAL(count, 1);
3556     ejdbquerydel(q1);
3557     bson_destroy(&bsq1);
3558 }
3559
3560 void testQueryBool(void) {
3561     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
3562     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
3563
3564     bson bsq1;
3565     bson_init_as_query(&bsq1);
3566     bson_append_bool(&bsq1, "visited", true);
3567     bson_finish(&bsq1);
3568     CU_ASSERT_FALSE_FATAL(bsq1.err);
3569
3570
3571     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3572     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3573     uint32_t count = 0;
3574     TCXSTR *log = tcxstrnew();
3575     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3576     //fprintf(stderr, "%s", TCXSTRPTR(log));
3577     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
3578     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
3579     CU_ASSERT_EQUAL(count, 1);
3580
3581     bson_destroy(&bsq1);
3582     tclistdel(q1res);
3583     tcxstrdel(log);
3584     ejdbquerydel(q1);
3585
3586     CU_ASSERT_TRUE(ejdbsetindex(coll, "visited", JBIDXNUM));
3587
3588     bson_init_as_query(&bsq1);
3589     bson_append_bool(&bsq1, "visited", true);
3590     bson_finish(&bsq1);
3591     CU_ASSERT_FALSE_FATAL(bsq1.err);
3592
3593     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3594     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3595     log = tcxstrnew();
3596     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3597     //fprintf(stderr, "%s", TCXSTRPTR(log));
3598     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'nvisited'"));
3599     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
3600     CU_ASSERT_EQUAL(count, 1);
3601
3602     bson_destroy(&bsq1);
3603     tclistdel(q1res);
3604     tcxstrdel(log);
3605     ejdbquerydel(q1);
3606 }
3607
3608 void testDropAll(void) {
3609     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
3610     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
3611     CU_ASSERT_TRUE(ejdbsetindex(coll, "name", JBIDXSTR));
3612
3613     bson bsq1;
3614     bson_init_as_query(&bsq1);
3615     bson_append_string(&bsq1, "name", "HeLlo WorlD");
3616     bson_append_bool(&bsq1, "$dropall", true);
3617     bson_finish(&bsq1);
3618     CU_ASSERT_FALSE_FATAL(bsq1.err);
3619
3620
3621     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3622     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3623     uint32_t count = 0;
3624     TCXSTR *log = tcxstrnew();
3625     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3626     //fprintf(stderr, "%s", TCXSTRPTR(log));
3627     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "$DROPALL ON:"));
3628     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'sname'"));
3629     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
3630
3631     bson_destroy(&bsq1);
3632     tclistdel(q1res);
3633     tcxstrdel(log);
3634     ejdbquerydel(q1);
3635
3636     //Select again
3637     bson_init_as_query(&bsq1);
3638     bson_append_string(&bsq1, "name", "HeLlo WorlD");
3639     bson_finish(&bsq1);
3640     CU_ASSERT_FALSE_FATAL(bsq1.err);
3641
3642     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3643     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3644     log = tcxstrnew();
3645     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3646     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'sname'"));
3647     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 0"));
3648     //fprintf(stderr, "\n\n%s", TCXSTRPTR(log));
3649
3650     bson_destroy(&bsq1);
3651     tclistdel(q1res);
3652     tcxstrdel(log);
3653     ejdbquerydel(q1);
3654 }
3655
3656 void testTokensBegin(void) {
3657     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
3658     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
3659     CU_ASSERT_TRUE(ejdbsetindex(coll, "name", JBIDXSTR));
3660
3661     //q: {'name' : {'$begin' : ['Ада', 'John T']}}
3662     bson bsq1;
3663     bson_init_as_query(&bsq1);
3664     bson_append_start_object(&bsq1, "name");
3665     bson_append_start_array(&bsq1, "$begin");
3666     bson_append_string(&bsq1, "0", "Ада");
3667     bson_append_string(&bsq1, "1", "John T");
3668     bson_append_string(&bsq1, "2", "QWE J");
3669     bson_append_finish_array(&bsq1);
3670     bson_append_finish_object(&bsq1);
3671     bson_finish(&bsq1);
3672     CU_ASSERT_FALSE_FATAL(bsq1.err);
3673
3674     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3675     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3676     uint32_t count = 0;
3677     TCXSTR *log = tcxstrnew();
3678     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3679     //fprintf(stderr, "%s", TCXSTRPTR(log));
3680
3681     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'sname'"));
3682     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX TCOP: 22"));
3683     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 2"));
3684     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3685         CU_ASSERT_TRUE(!bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name") ||
3686                        !bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
3687     }
3688
3689     bson_destroy(&bsq1);
3690     tclistdel(q1res);
3691     tcxstrdel(log);
3692     ejdbquerydel(q1);
3693
3694     //q: {'name' : {'$begin' : ['Ада', 'John T']}}
3695     bson_init_as_query(&bsq1);
3696     bson_append_start_object(&bsq1, "name");
3697     bson_append_start_array(&bsq1, "$begin");
3698     bson_append_string(&bsq1, "0", "Ада");
3699     bson_append_string(&bsq1, "1", "John T");
3700     bson_append_string(&bsq1, "2", "QWE J");
3701     bson_append_finish_array(&bsq1);
3702     bson_append_finish_object(&bsq1);
3703     bson_finish(&bsq1);
3704     CU_ASSERT_FALSE_FATAL(bsq1.err);
3705
3706
3707     CU_ASSERT_TRUE(ejdbsetindex(coll, "name", JBIDXDROPALL));
3708
3709     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3710     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3711     log = tcxstrnew();
3712     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3713     //fprintf(stderr, "%s", TCXSTRPTR(log));
3714
3715     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'"));
3716     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN"));
3717     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 2"));
3718     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3719         CU_ASSERT_TRUE(!bson_compare_string("Адаманский", TCLISTVALPTR(q1res, i), "name") ||
3720                        !bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
3721     }
3722
3723     bson_destroy(&bsq1);
3724     tclistdel(q1res);
3725     tcxstrdel(log);
3726     ejdbquerydel(q1);
3727 }
3728
3729 void testOneFieldManyConditions(void) {
3730     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
3731     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
3732
3733     bson bsq1;
3734     bson_init_as_query(&bsq1);
3735     bson_append_start_object(&bsq1, "age");
3736     bson_append_int(&bsq1, "$lt", 60);
3737     bson_append_int(&bsq1, "$gt", 50);
3738     bson_append_finish_object(&bsq1);
3739     bson_finish(&bsq1);
3740     CU_ASSERT_FALSE_FATAL(bsq1.err);
3741
3742     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3743     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3744     uint32_t count = 0;
3745     TCXSTR *log = tcxstrnew();
3746     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3747     //fprintf(stderr, "%s", TCXSTRPTR(log));
3748     CU_ASSERT_EQUAL(count, 1);
3749     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3750         CU_ASSERT_TRUE(!bson_compare_string("John Travolta", TCLISTVALPTR(q1res, i), "name"));
3751     }
3752     bson_destroy(&bsq1);
3753     tclistdel(q1res);
3754     tcxstrdel(log);
3755     ejdbquerydel(q1);
3756 }
3757
3758 void testAddToSet(void) {
3759     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
3760     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
3761     bson bsq1;
3762     bson_init_as_query(&bsq1);
3763     bson_append_string(&bsq1, "name", "Антонов");
3764     bson_append_start_object(&bsq1, "$addToSet");
3765     bson_append_string(&bsq1, "personal.tags", "tag1");
3766     bson_append_string(&bsq1, "labels", "green");
3767     bson_append_finish_object(&bsq1);
3768     bson_finish(&bsq1);
3769     CU_ASSERT_FALSE_FATAL(bsq1.err);
3770
3771     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3772     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3773     uint32_t count = 0;
3774     TCXSTR *log = tcxstrnew();
3775     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
3776     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: YES"));
3777     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
3778     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 0"));
3779     //fprintf(stderr, "%s", TCXSTRPTR(log));
3780     bson_destroy(&bsq1);
3781     tcxstrdel(log);
3782     ejdbquerydel(q1);
3783
3784     //check updated  data
3785     bson_init_as_query(&bsq1);
3786     bson_append_string(&bsq1, "name", "Антонов");
3787     bson_finish(&bsq1);
3788     CU_ASSERT_FALSE_FATAL(bsq1.err);
3789
3790     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3791     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3792     log = tcxstrnew();
3793     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3794     \
3795     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
3796     //fprintf(stderr, "\n\n%s", TCXSTRPTR(log));
3797
3798     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3799         CU_ASSERT_FALSE(bson_compare_string("tag1", TCLISTVALPTR(q1res, i), "personal.tags.0"));
3800         CU_ASSERT_FALSE(bson_compare_string("green", TCLISTVALPTR(q1res, i), "labels.0"));
3801     }
3802
3803     bson_destroy(&bsq1);
3804     tclistdel(q1res);
3805     tcxstrdel(log);
3806     ejdbquerydel(q1);
3807
3808     //Uppend more vals
3809     bson_init_as_query(&bsq1);
3810     bson_append_string(&bsq1, "name", "Антонов");
3811     bson_append_start_object(&bsq1, "$addToSet");
3812     bson_append_string(&bsq1, "personal.tags", "tag2");
3813     bson_append_string(&bsq1, "labels", "green");
3814     //bson_append_int(&bsq1, "scores", 1);
3815     bson_append_finish_object(&bsq1);
3816     bson_finish(&bsq1);
3817     CU_ASSERT_FALSE_FATAL(bsq1.err);
3818
3819     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3820     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3821     count = 0;
3822     log = tcxstrnew();
3823     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
3824     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: YES"));
3825     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
3826     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 0"));
3827     //fprintf(stderr, "%s", TCXSTRPTR(log));
3828     bson_destroy(&bsq1);
3829     tcxstrdel(log);
3830     ejdbquerydel(q1);
3831
3832
3833     //check updated  data
3834     bson_init_as_query(&bsq1);
3835     bson_append_string(&bsq1, "name", "Антонов");
3836     bson_finish(&bsq1);
3837     CU_ASSERT_FALSE_FATAL(bsq1.err);
3838
3839     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3840     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3841     log = tcxstrnew();
3842     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3843     \
3844     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
3845     //fprintf(stderr, "\n\n%s", TCXSTRPTR(log));
3846
3847     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3848         //bson_print_raw(TCLISTVALPTR(q1res, i), 0);
3849         CU_ASSERT_FALSE(bson_compare_string("tag1", TCLISTVALPTR(q1res, i), "personal.tags.0"));
3850         CU_ASSERT_FALSE(bson_compare_string("tag2", TCLISTVALPTR(q1res, i), "personal.tags.1"));
3851         CU_ASSERT_FALSE(bson_compare_string("green", TCLISTVALPTR(q1res, i), "labels.0"));
3852         CU_ASSERT_FALSE(!bson_compare_string("green", TCLISTVALPTR(q1res, i), "labels.1"));
3853     }
3854
3855     bson_destroy(&bsq1);
3856     tclistdel(q1res);
3857     tcxstrdel(log);
3858     ejdbquerydel(q1);
3859
3860     //Uppend more vals
3861     bson_init_as_query(&bsq1);
3862     bson_append_string(&bsq1, "name", "Антонов");
3863     bson_append_start_object(&bsq1, "$inc");
3864     bson_append_int(&bsq1, "age", -1);
3865     bson_append_finish_object(&bsq1);
3866     bson_append_start_object(&bsq1, "$addToSet");
3867     bson_append_string(&bsq1, "personal.tags", "tag3");
3868     bson_append_finish_object(&bsq1); //EOF $addToSet
3869     bson_append_start_object(&bsq1, "$addToSetAll");
3870     bson_append_start_array(&bsq1, "labels");
3871     bson_append_string(&bsq1, "0", "red");
3872     bson_append_string(&bsq1, "1", "black");
3873     bson_append_string(&bsq1, "2", "green");
3874     bson_append_finish_array(&bsq1);
3875     bson_append_finish_object(&bsq1); //EOF $addToSetAll
3876     bson_finish(&bsq1);
3877     CU_ASSERT_FALSE_FATAL(bsq1.err);
3878
3879     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3880     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3881     count = 0;
3882     log = tcxstrnew();
3883     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
3884     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: YES"));
3885     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
3886     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 0"));
3887     bson_destroy(&bsq1);
3888     tcxstrdel(log);
3889     ejdbquerydel(q1);
3890
3891     bson_init_as_query(&bsq1);
3892     bson_append_string(&bsq1, "name", "Антонов");
3893     bson_finish(&bsq1);
3894     CU_ASSERT_FALSE_FATAL(bsq1.err);
3895
3896     //check again
3897     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3898     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3899     log = tcxstrnew();
3900     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3901     \
3902     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
3903     //fprintf(stderr, "\n\n%s", TCXSTRPTR(log));
3904
3905     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3906         //bson_print_raw(TCLISTVALPTR(q1res, i), 0);
3907         CU_ASSERT_FALSE(bson_compare_string("tag1", TCLISTVALPTR(q1res, i), "personal.tags.0"));
3908         CU_ASSERT_FALSE(bson_compare_string("tag2", TCLISTVALPTR(q1res, i), "personal.tags.1"));
3909         CU_ASSERT_FALSE(bson_compare_string("tag3", TCLISTVALPTR(q1res, i), "personal.tags.2"));
3910         CU_ASSERT_FALSE(bson_compare_string("green", TCLISTVALPTR(q1res, i), "labels.0"));
3911         CU_ASSERT_FALSE(bson_compare_string("red", TCLISTVALPTR(q1res, i), "labels.1"));
3912         CU_ASSERT_FALSE(bson_compare_string("black", TCLISTVALPTR(q1res, i), "labels.2"));
3913         CU_ASSERT_TRUE(bson_compare_string("green", TCLISTVALPTR(q1res, i), "labels.3"));
3914     }
3915
3916     bson_destroy(&bsq1);
3917     tclistdel(q1res);
3918     tcxstrdel(log);
3919     ejdbquerydel(q1);
3920 }
3921
3922 void testTicket123(void) {
3923     EJCOLL *coll = ejdbcreatecoll(jb, "ticket123", NULL);
3924     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
3925
3926     bson bs1;
3927     bson_oid_t oid1;
3928     bson_init(&bs1);
3929     bson_append_start_object(&bs1, "abc");
3930     bson_append_start_array(&bs1, "de");
3931     bson_append_string(&bs1, "0", "g");
3932     bson_append_finish_array(&bs1);
3933     bson_append_start_array(&bs1, "fg");
3934     bson_append_finish_array(&bs1);
3935     bson_append_finish_object(&bs1);
3936     bson_finish(&bs1);
3937
3938     CU_ASSERT_TRUE_FATAL(ejdbsavebson(coll, &bs1, &oid1));
3939
3940     bson bsq1;
3941     bson_init_as_query(&bsq1);
3942     bson_append_start_object(&bsq1, "$addToSet");
3943     bson_append_string(&bsq1, "abc.g", "f");
3944     bson_append_finish_object(&bsq1);
3945     bson_finish(&bsq1);
3946     CU_ASSERT_FALSE_FATAL(bsq1.err);
3947
3948     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3949     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3950     uint32_t count = 0;
3951     TCXSTR *log = tcxstrnew();
3952     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
3953     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: YES"));
3954     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
3955     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 0"));
3956     //fprintf(stderr, "%s", TCXSTRPTR(log));
3957     bson_destroy(&bsq1);
3958     tcxstrdel(log);
3959     ejdbquerydel(q1);
3960
3961     //check updated  data
3962     bson_init_as_query(&bsq1);
3963     bson_finish(&bsq1);
3964     CU_ASSERT_FALSE_FATAL(bsq1.err);
3965
3966     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3967     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
3968     log = tcxstrnew();
3969     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
3970
3971     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
3972     //fprintf(stderr, "\n\n%s", TCXSTRPTR(log));
3973
3974     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
3975         CU_ASSERT_FALSE(bson_compare_string("g", TCLISTVALPTR(q1res, i), "abc.de.0"));
3976         CU_ASSERT_FALSE(bson_compare_string("f", TCLISTVALPTR(q1res, i), "abc.g.0"));
3977     }
3978
3979     bson_destroy(&bs1);
3980     bson_destroy(&bsq1);
3981     tclistdel(q1res);
3982     tcxstrdel(log);
3983     ejdbquerydel(q1);
3984 }
3985
3986 void testPush(void) {
3987     EJCOLL *coll = ejdbcreatecoll(jb, "ticket123", NULL);
3988     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
3989     
3990     bson bsq1;
3991     bson_init_as_query(&bsq1);
3992     bson_append_start_object(&bsq1, "$push");
3993     bson_append_string(&bsq1, "abc.g", "f");
3994     bson_append_finish_object(&bsq1);
3995     bson_finish(&bsq1);
3996     CU_ASSERT_FALSE_FATAL(bsq1.err);
3997     
3998     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
3999     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4000     uint32_t count = 0;
4001     TCXSTR *log = tcxstrnew();
4002     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
4003     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: YES"));
4004     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
4005     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 0"));
4006     //fprintf(stderr, "%s", TCXSTRPTR(log));
4007     bson_destroy(&bsq1);
4008     tcxstrdel(log);
4009     ejdbquerydel(q1);
4010     
4011     //check updated  data
4012     bson_init_as_query(&bsq1);
4013     bson_finish(&bsq1);
4014     CU_ASSERT_FALSE_FATAL(bsq1.err);
4015
4016     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4017     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4018     log = tcxstrnew();
4019     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4020
4021     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
4022     //fprintf(stderr, "\n\n%s", TCXSTRPTR(log));
4023
4024     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
4025         CU_ASSERT_FALSE(bson_compare_string("g", TCLISTVALPTR(q1res, i), "abc.de.0"));
4026         CU_ASSERT_FALSE(bson_compare_string("f", TCLISTVALPTR(q1res, i), "abc.g.0"));
4027         CU_ASSERT_FALSE(bson_compare_string("f", TCLISTVALPTR(q1res, i), "abc.g.1"));
4028     }
4029
4030     bson_destroy(&bsq1);
4031     tclistdel(q1res);
4032     tcxstrdel(log);
4033     ejdbquerydel(q1);
4034 }
4035
4036
4037 void testPushAll(void) {
4038     EJCOLL *coll = ejdbcreatecoll(jb, "ticket123", NULL);
4039     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
4040     
4041     bson bsq1;
4042     bson_init_as_query(&bsq1);
4043     bson_append_start_object(&bsq1, "$pushAll");
4044     bson_append_start_array(&bsq1, "abc.g");
4045     bson_append_string(&bsq1, "0", "h");
4046     bson_append_string(&bsq1, "1", "h");
4047     bson_append_int(&bsq1, "2", 11);
4048     bson_append_finish_array(&bsq1);
4049     bson_append_finish_object(&bsq1);
4050     bson_finish(&bsq1);
4051     CU_ASSERT_FALSE_FATAL(bsq1.err);
4052     
4053     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4054     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4055     uint32_t count = 0;
4056     TCXSTR *log = tcxstrnew();
4057     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
4058     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: YES"));
4059     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
4060     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 0"));
4061     //fprintf(stderr, "%s", TCXSTRPTR(log));
4062     bson_destroy(&bsq1);
4063     tcxstrdel(log);
4064     ejdbquerydel(q1);
4065     
4066     //check updated  data
4067     bson_init_as_query(&bsq1);
4068     bson_finish(&bsq1);
4069     CU_ASSERT_FALSE_FATAL(bsq1.err);
4070
4071     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4072     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4073     log = tcxstrnew();
4074     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4075
4076     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
4077     //fprintf(stderr, "\n\n%s", TCXSTRPTR(log));
4078
4079     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
4080         CU_ASSERT_FALSE(bson_compare_string("g", TCLISTVALPTR(q1res, i), "abc.de.0"));
4081         CU_ASSERT_FALSE(bson_compare_string("f", TCLISTVALPTR(q1res, i), "abc.g.0"));
4082         CU_ASSERT_FALSE(bson_compare_string("f", TCLISTVALPTR(q1res, i), "abc.g.1"));
4083         CU_ASSERT_FALSE(bson_compare_string("h", TCLISTVALPTR(q1res, i), "abc.g.2"));
4084         CU_ASSERT_FALSE(bson_compare_string("h", TCLISTVALPTR(q1res, i), "abc.g.3"));
4085         CU_ASSERT_FALSE(bson_compare_long(11, TCLISTVALPTR(q1res, i), "abc.g.4"));
4086     }
4087
4088     bson_destroy(&bsq1);
4089     tclistdel(q1res);
4090     tcxstrdel(log);
4091     ejdbquerydel(q1);
4092 }
4093
4094 void testRename2(void) {
4095     EJCOLL *coll = ejdbcreatecoll(jb, "ticket123", NULL);
4096     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
4097     bson bsq1;
4098     bson_init_as_query(&bsq1);
4099     bson_append_start_object(&bsq1, "$rename");
4100     bson_append_string(&bsq1, "abc.g", "abc.f");
4101     bson_append_finish_object(&bsq1);
4102     bson_finish(&bsq1);
4103     CU_ASSERT_FALSE_FATAL(bsq1.err);
4104     
4105     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4106     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4107     uint32_t count = 0;
4108     TCXSTR *log = tcxstrnew();
4109     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
4110     
4111     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: YES"));
4112     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
4113     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 0"));
4114     
4115     //fprintf(stderr, "%s", TCXSTRPTR(log));
4116     bson_destroy(&bsq1);
4117     tcxstrdel(log);
4118     ejdbquerydel(q1);
4119     
4120     //check updated  data
4121     bson_init_as_query(&bsq1);
4122     bson_finish(&bsq1);
4123     CU_ASSERT_FALSE_FATAL(bsq1.err);
4124
4125     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4126     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4127     log = tcxstrnew();
4128     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4129
4130     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
4131     //fprintf(stderr, "\n\n%s", TCXSTRPTR(log));
4132
4133     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
4134         CU_ASSERT_FALSE(bson_compare_string("g", TCLISTVALPTR(q1res, i), "abc.de.0"));
4135         CU_ASSERT_FALSE(bson_compare_string("f", TCLISTVALPTR(q1res, i), "abc.f.0"));
4136         CU_ASSERT_FALSE(bson_compare_string("f", TCLISTVALPTR(q1res, i), "abc.f.1"));
4137         CU_ASSERT_FALSE(bson_compare_string("h", TCLISTVALPTR(q1res, i), "abc.f.2"));
4138         CU_ASSERT_FALSE(bson_compare_string("h", TCLISTVALPTR(q1res, i), "abc.f.3"));
4139         CU_ASSERT_FALSE(bson_compare_long(11, TCLISTVALPTR(q1res, i), "abc.f.4"));
4140     }
4141
4142     bson_destroy(&bsq1);
4143     tclistdel(q1res);
4144     tcxstrdel(log);
4145     ejdbquerydel(q1);
4146 }
4147
4148
4149 void testPull(void) {
4150     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
4151     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
4152     bson bsq1;
4153     bson_init_as_query(&bsq1);
4154     bson_append_string(&bsq1, "name", "Антонов");
4155     bson_append_start_object(&bsq1, "$pull");
4156     bson_append_string(&bsq1, "personal.tags", "tag2");
4157     bson_append_string(&bsq1, "labels", "green");
4158     bson_append_finish_object(&bsq1);
4159     bson_finish(&bsq1);
4160     CU_ASSERT_FALSE_FATAL(bsq1.err);
4161
4162     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4163     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4164     uint32_t count = 0;
4165     TCXSTR *log = tcxstrnew();
4166     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
4167     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "UPDATING MODE: YES"));
4168     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
4169     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 0"));
4170     //fprintf(stderr, "%s", TCXSTRPTR(log));
4171     bson_destroy(&bsq1);
4172     tcxstrdel(log);
4173     ejdbquerydel(q1);
4174
4175     //check
4176     bson_init_as_query(&bsq1);
4177     bson_append_string(&bsq1, "name", "Антонов");
4178     bson_finish(&bsq1);
4179     CU_ASSERT_FALSE_FATAL(bsq1.err);
4180     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4181     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4182     log = tcxstrnew();
4183     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4184     
4185     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
4186     //fprintf(stderr, "\n\n%s", TCXSTRPTR(log));
4187
4188     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
4189         //bson_print_raw(TCLISTVALPTR(q1res, i), 0);
4190         CU_ASSERT_FALSE(bson_compare_string("tag1", TCLISTVALPTR(q1res, i), "personal.tags.0"));
4191         CU_ASSERT_FALSE(bson_compare_string("tag3", TCLISTVALPTR(q1res, i), "personal.tags.1"));
4192         CU_ASSERT_FALSE(bson_compare_string("red", TCLISTVALPTR(q1res, i), "labels.0"));
4193     }
4194
4195     bson_destroy(&bsq1);
4196     tclistdel(q1res);
4197     tcxstrdel(log);
4198     ejdbquerydel(q1);
4199 }
4200
4201 void testFindInComplexArray(void) {
4202     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
4203     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
4204     bson bsq1;
4205     bson_init_as_query(&bsq1);
4206     bson_append_string(&bsq1, "complexarr.key", "title");
4207     bson_append_string(&bsq1, "complexarr.value", "some title");
4208     bson_finish(&bsq1);
4209     CU_ASSERT_FALSE_FATAL(bsq1.err);
4210
4211     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4212     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4213     uint32_t count = 0;
4214     TCXSTR *log = tcxstrnew();
4215     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4216     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4217     //fprintf(stderr, "%s", TCXSTRPTR(log));
4218     CU_ASSERT_EQUAL_FATAL(count, 2);
4219
4220     // 0
4221     CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, 0), "name"));
4222
4223     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.0.key"));
4224     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 0), "complexarr.0.value"));
4225
4226     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.1.key"));
4227     CU_ASSERT_FALSE(bson_compare_string("some other title", TCLISTVALPTR(q1res, 0), "complexarr.1.value"));
4228
4229     // 1
4230     CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, 1), "name"));
4231     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 1), "complexarr.0.key"));
4232     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 1), "complexarr.0.value"));
4233
4234     bson_destroy(&bsq1);
4235     tclistdel(q1res);
4236     tcxstrdel(log);
4237     ejdbquerydel(q1);
4238
4239     //Check matching positional element
4240     bson_init_as_query(&bsq1);
4241     bson_append_string(&bsq1, "complexarr.0.key", "title");
4242     bson_finish(&bsq1);
4243     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4244     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4245     log = tcxstrnew();
4246     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4247     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4248     //fprintf(stderr, "\n%s", TCXSTRPTR(log));
4249     CU_ASSERT_EQUAL_FATAL(count, 2);
4250
4251     // 0
4252     CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, 0), "name"));
4253
4254     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.0.key"));
4255     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 0), "complexarr.0.value"));
4256
4257     // 1
4258     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.1.key"));
4259     CU_ASSERT_FALSE(bson_compare_string("some other title", TCLISTVALPTR(q1res, 0), "complexarr.1.value"));
4260
4261     CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, 1), "name"));
4262     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 1), "complexarr.0.key"));
4263     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 1), "complexarr.0.value"));
4264
4265     bson_destroy(&bsq1);
4266     tclistdel(q1res);
4267     tcxstrdel(log);
4268     ejdbquerydel(q1);
4269
4270     //Check simple el
4271     bson_init_as_query(&bsq1);
4272     bson_append_int(&bsq1, "complexarr.2", 333);
4273     bson_finish(&bsq1);
4274     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4275     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4276     log = tcxstrnew();
4277     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4278     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4279     //fprintf(stderr, "\n%s", TCXSTRPTR(log));
4280     CU_ASSERT_EQUAL_FATAL(count, 1);
4281
4282     // 0
4283     CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, 0), "name"));
4284
4285     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.0.key"));
4286     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 0), "complexarr.0.value"));
4287
4288     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.1.key"));
4289     CU_ASSERT_FALSE(bson_compare_string("some other title", TCLISTVALPTR(q1res, 0), "complexarr.1.value"));
4290
4291     CU_ASSERT_FALSE(bson_compare_long(333, TCLISTVALPTR(q1res, 0), "complexarr.2"));
4292
4293     bson_destroy(&bsq1);
4294     tclistdel(q1res);
4295     tcxstrdel(log);
4296     ejdbquerydel(q1);
4297
4298     //Check simple el2
4299     bson_init_as_query(&bsq1);
4300     bson_append_int(&bsq1, "complexarr", 333);
4301     bson_finish(&bsq1);
4302     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4303     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4304     log = tcxstrnew();
4305     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4306     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4307     //fprintf(stderr, "\n%s", TCXSTRPTR(log));
4308     CU_ASSERT_EQUAL_FATAL(count, 1);
4309
4310     // 0
4311     CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, 0), "name"));
4312
4313     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.0.key"));
4314     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 0), "complexarr.0.value"));
4315
4316     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.1.key"));
4317     CU_ASSERT_FALSE(bson_compare_string("some other title", TCLISTVALPTR(q1res, 0), "complexarr.1.value"));
4318
4319     CU_ASSERT_FALSE(bson_compare_long(333, TCLISTVALPTR(q1res, 0), "complexarr.2"));
4320
4321     bson_destroy(&bsq1);
4322     tclistdel(q1res);
4323     tcxstrdel(log);
4324     ejdbquerydel(q1);
4325
4326
4327     //$exists
4328     bson_init_as_query(&bsq1);
4329     bson_append_start_object(&bsq1, "complexarr.key");
4330     bson_append_bool(&bsq1, "$exists", true);
4331     bson_append_finish_object(&bsq1);
4332     bson_finish(&bsq1);
4333     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4334     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4335     log = tcxstrnew();
4336     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4337     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4338     CU_ASSERT_EQUAL(count, 2);
4339     bson_destroy(&bsq1);
4340     tclistdel(q1res);
4341     tcxstrdel(log);
4342     ejdbquerydel(q1);
4343
4344
4345     //$exists 2
4346     bson_init_as_query(&bsq1);
4347     bson_append_start_object(&bsq1, "complexarr.2");
4348     bson_append_bool(&bsq1, "$exists", true);
4349     bson_append_finish_object(&bsq1);
4350     bson_finish(&bsq1);
4351     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4352     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4353     log = tcxstrnew();
4354     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4355     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4356     CU_ASSERT_EQUAL(count, 1);
4357     bson_destroy(&bsq1);
4358     tclistdel(q1res);
4359     tcxstrdel(log);
4360     ejdbquerydel(q1);
4361
4362
4363     //$exists 3
4364     bson_init_as_query(&bsq1);
4365     bson_append_start_object(&bsq1, "complexarr.4");
4366     bson_append_bool(&bsq1, "$exists", true);
4367     bson_append_finish_object(&bsq1);
4368     bson_finish(&bsq1);
4369     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4370     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4371     log = tcxstrnew();
4372     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4373     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4374     CU_ASSERT_EQUAL(count, 0);
4375     bson_destroy(&bsq1);
4376     tclistdel(q1res);
4377     tcxstrdel(log);
4378     ejdbquerydel(q1);
4379 }
4380
4381 void testElemMatch(void) {
4382     // { complexarr: { $elemMatch: { key: 'title', value: 'some title' } } }
4383     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
4384     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
4385     bson bsq1;
4386     bson_init_as_query(&bsq1);
4387     bson_append_start_object(&bsq1, "complexarr");
4388     bson_append_start_object(&bsq1, "$elemMatch");
4389     bson_append_string(&bsq1, "key", "title");
4390     bson_append_string(&bsq1, "value", "some title");
4391     bson_append_finish_object(&bsq1);
4392     bson_append_finish_object(&bsq1);
4393     bson_finish(&bsq1);
4394     CU_ASSERT_FALSE_FATAL(bsq1.err);
4395
4396     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4397     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4398     uint32_t count = 0;
4399     TCXSTR *log = tcxstrnew();
4400     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4401     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4402     CU_ASSERT_EQUAL_FATAL(count, 2);
4403 //    fprintf(stderr, "%s", TCXSTRPTR(log));
4404
4405     // 0
4406     CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, 0), "name"));
4407
4408     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.0.key"));
4409     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 0), "complexarr.0.value"));
4410
4411     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.1.key"));
4412     CU_ASSERT_FALSE(bson_compare_string("some other title", TCLISTVALPTR(q1res, 0), "complexarr.1.value"));
4413
4414     // 1
4415     CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, 1), "name"));
4416
4417     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 1), "complexarr.0.key"));
4418     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 1), "complexarr.0.value"));
4419
4420     CU_ASSERT_FALSE(bson_compare_string("comment", TCLISTVALPTR(q1res, 1), "complexarr.1.key"));
4421     CU_ASSERT_FALSE(bson_compare_string("some comment", TCLISTVALPTR(q1res, 1), "complexarr.1.value"));
4422
4423     bson_destroy(&bsq1);
4424     tclistdel(q1res);
4425     tcxstrdel(log);
4426     ejdbquerydel(q1);
4427
4428     bson_init_as_query(&bsq1);
4429     bson_append_start_object(&bsq1, "complexarr");
4430     bson_append_start_object(&bsq1, "$elemMatch");
4431     bson_append_string(&bsq1, "key", "title");
4432     bson_append_string(&bsq1, "value", "some other title");
4433     bson_append_finish_object(&bsq1);
4434     bson_append_finish_object(&bsq1);
4435     bson_finish(&bsq1);
4436     CU_ASSERT_FALSE_FATAL(bsq1.err);
4437     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4438     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4439     log = tcxstrnew();
4440     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4441     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4442     //fprintf(stderr, "%s", TCXSTRPTR(log));
4443     CU_ASSERT_EQUAL_FATAL(count, 1);
4444
4445     // 0
4446     CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, 0), "name"));
4447
4448     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.0.key"));
4449     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 0), "complexarr.0.value"));
4450
4451     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.1.key"));
4452     CU_ASSERT_FALSE(bson_compare_string("some other title", TCLISTVALPTR(q1res, 0), "complexarr.1.value"));
4453
4454     bson_destroy(&bsq1);
4455     tclistdel(q1res);
4456     tcxstrdel(log);
4457     ejdbquerydel(q1);
4458
4459     bson_init_as_query(&bsq1);
4460     bson_append_start_object(&bsq1, "complexarr");
4461     bson_append_start_object(&bsq1, "$elemMatch");
4462     bson_append_string(&bsq1, "key", "title");
4463     bson_append_start_object(&bsq1, "value");
4464     bson_append_string(&bsq1, "$not", "some title");
4465     bson_append_finish_object(&bsq1);
4466     bson_append_finish_object(&bsq1);
4467     bson_append_finish_object(&bsq1);
4468     bson_finish(&bsq1);
4469     CU_ASSERT_FALSE_FATAL(bsq1.err);
4470     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4471     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4472     log = tcxstrnew();
4473     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4474     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4475 //    fprintf(stderr, "%s", TCXSTRPTR(log));
4476     CU_ASSERT_EQUAL_FATAL(count, 1);
4477
4478     // 0
4479     CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, 0), "name"));
4480
4481     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.0.key"));
4482     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 0), "complexarr.0.value"));
4483
4484     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.1.key"));
4485     CU_ASSERT_FALSE(bson_compare_string("some other title", TCLISTVALPTR(q1res, 0), "complexarr.1.value"));
4486
4487     bson_destroy(&bsq1);
4488     tclistdel(q1res);
4489     tcxstrdel(log);
4490     ejdbquerydel(q1);
4491
4492     bson_init_as_query(&bsq1);
4493     bson_append_string(&bsq1, "complexarr.key", "title");
4494     bson_append_string(&bsq1, "complexarr.value", "some other title");
4495     bson_finish(&bsq1);
4496     CU_ASSERT_FALSE_FATAL(bsq1.err);
4497     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4498     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4499     log = tcxstrnew();
4500     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4501     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4502     //fprintf(stderr, "%s", TCXSTRPTR(log));
4503     CU_ASSERT_EQUAL_FATAL(count, 1);
4504
4505     // 0
4506     CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, 0), "name"));
4507
4508     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.0.key"));
4509     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 0), "complexarr.0.value"));
4510
4511     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.1.key"));
4512     CU_ASSERT_FALSE(bson_compare_string("some other title", TCLISTVALPTR(q1res, 0), "complexarr.1.value"));
4513
4514     bson_destroy(&bsq1);
4515     tclistdel(q1res);
4516     tcxstrdel(log);
4517     ejdbquerydel(q1);
4518 }
4519
4520 void testNotElemMatch(void) {
4521     // { complexarr: { $not: { $elemMatch: { key: 'title', value: 'some title' } } } }
4522     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
4523     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
4524     bson bsq1;
4525     bson_init_as_query(&bsq1);
4526     bson_append_start_object(&bsq1, "complexarr");
4527     bson_append_start_object(&bsq1, "$not");
4528     bson_append_start_object(&bsq1, "$elemMatch");
4529     bson_append_string(&bsq1, "key", "title");
4530     bson_append_string(&bsq1, "value", "some title");
4531     bson_append_finish_object(&bsq1);//$elemMatch
4532     bson_append_finish_object(&bsq1);//$not
4533     //include $exists to exclude documents without complexarr
4534     bson_append_bool(&bsq1, "$exists", true);
4535     bson_append_finish_object(&bsq1);//complexarr
4536     bson_finish(&bsq1);
4537     CU_ASSERT_FALSE_FATAL(bsq1.err);
4538
4539     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4540     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4541     uint32_t count = 0;
4542     TCXSTR *log = tcxstrnew();
4543     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4544     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4545     //fprintf(stderr, "%s", TCXSTRPTR(log));
4546     CU_ASSERT_EQUAL_FATAL(count, 0);
4547
4548     bson_destroy(&bsq1);
4549     tclistdel(q1res);
4550     tcxstrdel(log);
4551     ejdbquerydel(q1);
4552
4553     bson_init_as_query(&bsq1);
4554     bson_append_start_object(&bsq1, "complexarr");
4555     bson_append_start_object(&bsq1, "$not");
4556     bson_append_start_object(&bsq1, "$elemMatch");
4557     bson_append_string(&bsq1, "key", "title");
4558     bson_append_string(&bsq1, "value", "some other title");
4559     bson_append_finish_object(&bsq1);//$elemMatch
4560     bson_append_finish_object(&bsq1);//$not
4561     bson_append_bool(&bsq1, "$exists", true);
4562     bson_append_finish_object(&bsq1);
4563     bson_finish(&bsq1);
4564     CU_ASSERT_FALSE_FATAL(bsq1.err);
4565     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4566     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4567     log = tcxstrnew();
4568     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4569     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4570     //fprintf(stderr, "%s", TCXSTRPTR(log));
4571     CU_ASSERT_EQUAL_FATAL(count, 1);
4572
4573     // 0
4574     CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, 0), "name"));
4575
4576     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.0.key"));
4577     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 0), "complexarr.0.value"));
4578
4579     CU_ASSERT_FALSE(bson_compare_string("comment", TCLISTVALPTR(q1res, 0), "complexarr.1.key"));
4580     CU_ASSERT_FALSE(bson_compare_string("some comment", TCLISTVALPTR(q1res, 0), "complexarr.1.value"));
4581
4582     bson_destroy(&bsq1);
4583     tclistdel(q1res);
4584     tcxstrdel(log);
4585     ejdbquerydel(q1);
4586
4587     bson_init_as_query(&bsq1);
4588     bson_append_start_object(&bsq1, "complexarr");
4589     bson_append_start_object(&bsq1, "$not");
4590     bson_append_start_object(&bsq1, "$elemMatch");
4591     bson_append_string(&bsq1, "key", "comment");
4592     bson_append_finish_object(&bsq1);//$elemMatch
4593     bson_append_finish_object(&bsq1);//$not
4594     bson_append_bool(&bsq1, "$exists", true);
4595     bson_append_finish_object(&bsq1);
4596     bson_finish(&bsq1);
4597     CU_ASSERT_FALSE_FATAL(bsq1.err);
4598     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4599     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4600     log = tcxstrnew();
4601     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4602     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4603     //fprintf(stderr, "%s", TCXSTRPTR(log));
4604     CU_ASSERT_EQUAL_FATAL(count, 1);
4605
4606     // 0
4607     CU_ASSERT_FALSE(bson_compare_string("Адаманский", TCLISTVALPTR(q1res, 0), "name"));
4608
4609     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.0.key"));
4610     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 0), "complexarr.0.value"));
4611
4612     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.1.key"));
4613     CU_ASSERT_FALSE(bson_compare_string("some other title", TCLISTVALPTR(q1res, 0), "complexarr.1.value"));
4614
4615     bson_destroy(&bsq1);
4616     tclistdel(q1res);
4617     tcxstrdel(log);
4618     ejdbquerydel(q1);
4619
4620     //ensure correct behaviour of double negative
4621     bson_init_as_query(&bsq1);
4622     bson_append_start_object(&bsq1, "complexarr");
4623     bson_append_start_object(&bsq1, "$not");
4624     bson_append_start_object(&bsq1, "$elemMatch");
4625     bson_append_string(&bsq1, "key", "title");
4626     bson_append_start_object(&bsq1, "value");
4627     bson_append_string(&bsq1, "$not", "some title");
4628     bson_append_finish_object(&bsq1);
4629     bson_append_finish_object(&bsq1);
4630     bson_append_finish_object(&bsq1);
4631     bson_append_finish_object(&bsq1);
4632     bson_finish(&bsq1);
4633     CU_ASSERT_FALSE_FATAL(bsq1.err);
4634     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4635     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4636     log = tcxstrnew();
4637     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4638     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4639     //fprintf(stderr, "%s", TCXSTRPTR(log));
4640     CU_ASSERT_EQUAL_FATAL(count, 1);
4641
4642     // 0
4643     CU_ASSERT_FALSE(bson_compare_string("Антонов", TCLISTVALPTR(q1res, 0), "name"));
4644
4645     CU_ASSERT_FALSE(bson_compare_string("title", TCLISTVALPTR(q1res, 0), "complexarr.0.key"));
4646     CU_ASSERT_FALSE(bson_compare_string("some title", TCLISTVALPTR(q1res, 0), "complexarr.0.value"));
4647
4648     CU_ASSERT_FALSE(bson_compare_string("comment", TCLISTVALPTR(q1res, 0), "complexarr.1.key"));
4649     CU_ASSERT_FALSE(bson_compare_string("some comment", TCLISTVALPTR(q1res, 0), "complexarr.1.value"));
4650
4651     bson_destroy(&bsq1);
4652     tclistdel(q1res);
4653     tcxstrdel(log);
4654     ejdbquerydel(q1);
4655 }
4656
4657 void testTicket16(void) {
4658     EJCOLL *coll = ejdbcreatecoll(jb, "abcd", NULL);
4659     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
4660     CU_ASSERT_EQUAL(coll->tdb->inum, 0);
4661     CU_ASSERT_TRUE(ejdbsetindex(coll, "abcd", JBIDXISTR));
4662     CU_ASSERT_TRUE(ejdbsetindex(coll, "abcd", JBIDXNUM));
4663     CU_ASSERT_EQUAL(coll->tdb->inum, 2);
4664     CU_ASSERT_TRUE(ejdbsetindex(coll, "abcd", JBIDXDROPALL));
4665     CU_ASSERT_EQUAL(coll->tdb->inum, 0);
4666 }
4667
4668 void testUpsert(void) {
4669     EJCOLL *coll = ejdbcreatecoll(jb, "abcd", NULL);
4670     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
4671     bson bsq1;
4672     bson_init_as_query(&bsq1);
4673     bson_append_string(&bsq1, "cde", "fgh"); //sel condition
4674     bson_append_start_object(&bsq1, "$upsert");
4675     bson_append_string(&bsq1, "cde", "fgh");
4676     bson_append_string(&bsq1, "ijk", "lmnp");
4677     bson_append_finish_object(&bsq1);
4678     bson_finish(&bsq1);
4679     CU_ASSERT_FALSE_FATAL(bsq1.err);
4680
4681     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4682     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4683     uint32_t count = 0;
4684     TCXSTR *log = tcxstrnew();
4685     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4686     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4687     CU_ASSERT_EQUAL(count, 1);
4688
4689     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
4690         bson_iterator it;
4691         CU_ASSERT_TRUE(bson_find_from_buffer(&it, TCLISTVALPTR(q1res, i), "_id") == BSON_OID);
4692         CU_ASSERT_FALSE(bson_compare_string("fgh", TCLISTVALPTR(q1res, i), "cde"));
4693         CU_ASSERT_FALSE(bson_compare_string("lmnp", TCLISTVALPTR(q1res, i), "ijk"));
4694     }
4695
4696     bson_destroy(&bsq1);
4697     tclistdel(q1res);
4698     tcxstrdel(log);
4699     ejdbquerydel(q1);
4700
4701     bson_init_as_query(&bsq1);
4702     bson_append_string(&bsq1, "cde", "fgh"); //sel condition
4703     bson_append_start_object(&bsq1, "$upsert");
4704     bson_append_string(&bsq1, "cde", "fgh");
4705     bson_append_string(&bsq1, "ijk", "lmnp+");
4706     bson_append_finish_object(&bsq1);
4707     bson_finish(&bsq1);
4708     CU_ASSERT_FALSE_FATAL(bsq1.err);
4709
4710     log = tcxstrnew();
4711     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4712     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4713     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4714     //fprintf(stderr, "%s", TCXSTRPTR(log));
4715     CU_ASSERT_EQUAL(count, 1);
4716
4717     bson_destroy(&bsq1);
4718     tclistdel(q1res);
4719     tcxstrdel(log);
4720     ejdbquerydel(q1);
4721
4722     bson_init_as_query(&bsq1);
4723     bson_append_string(&bsq1, "cde", "fgh");
4724     bson_finish(&bsq1);
4725     CU_ASSERT_FALSE_FATAL(bsq1.err);
4726
4727     log = tcxstrnew();
4728     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4729     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4730     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4731     //fprintf(stderr, "%s", TCXSTRPTR(log));
4732     CU_ASSERT_EQUAL(count, 1);
4733
4734     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
4735         CU_ASSERT_FALSE(bson_compare_string("fgh", TCLISTVALPTR(q1res, i), "cde"));
4736         CU_ASSERT_FALSE(bson_compare_string("lmnp+", TCLISTVALPTR(q1res, i), "ijk"));
4737     }
4738
4739     bson_destroy(&bsq1);
4740     tclistdel(q1res);
4741     tcxstrdel(log);
4742     ejdbquerydel(q1);
4743 }
4744
4745 void testPrimitiveCases1(void) {
4746     EJCOLL *coll = ejdbcreatecoll(jb, "abcd", NULL);
4747     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
4748     bson bsq1;
4749     bson_init_as_query(&bsq1);
4750     bson_finish(&bsq1);
4751     CU_ASSERT_FALSE_FATAL(bsq1.err);
4752
4753     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4754     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4755     uint32_t count = 0;
4756     TCXSTR *log = tcxstrnew();
4757     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
4758     CU_ASSERT_EQUAL(count, 1);
4759     //fprintf(stderr, "%s", TCXSTRPTR(log));
4760     CU_ASSERT_EQUAL(count, 1);
4761     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SIMPLE COUNT(*): 1"));
4762     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
4763     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 0"));
4764
4765     bson_destroy(&bsq1);
4766     tcxstrdel(log);
4767     ejdbquerydel(q1);
4768
4769     //$dropall on whole collection
4770     bson_init_as_query(&bsq1);
4771     bson_append_bool(&bsq1, "$dropall", true);
4772     bson_finish(&bsq1);
4773     CU_ASSERT_FALSE_FATAL(bsq1.err);
4774
4775     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4776     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4777     count = 0;
4778     log = tcxstrnew();
4779     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
4780     CU_ASSERT_EQUAL(count, 1);
4781     //fprintf(stderr, "%s", TCXSTRPTR(log));
4782     CU_ASSERT_EQUAL(count, 1);
4783     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "VANISH WHOLE COLLECTION ON $dropall"));
4784     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 1"));
4785     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 0"));
4786
4787     bson_destroy(&bsq1);
4788     tcxstrdel(log);
4789     ejdbquerydel(q1);
4790 }
4791
4792 void testTicket29(void) {
4793     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
4794     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
4795     CU_ASSERT_TRUE(ejdbsetindex(coll, "name", JBIDXARR));
4796
4797     bson a1;
4798     bson_init(&a1);
4799     bson_append_string(&a1, "name", "Hello Мир");
4800     bson_append_long(&a1, "longscore", 77);
4801     bson_finish(&a1);
4802     CU_ASSERT_FALSE_FATAL(a1.err);
4803
4804     bson_oid_t oid;
4805     CU_ASSERT_TRUE(ejdbsavebson(coll, &a1, &oid));
4806     bson_destroy(&a1);
4807
4808     //{"name" : {$strand : ["Hello", "Мир"]}}
4809     bson bsq1;
4810     bson_init_as_query(&bsq1);
4811     bson_append_start_object(&bsq1, "name");
4812     bson_append_start_array(&bsq1, "$strand");
4813     bson_append_string(&bsq1, "0", "Hello");
4814     bson_append_string(&bsq1, "1", "Мир");
4815     bson_append_finish_array(&bsq1);
4816     bson_append_finish_object(&bsq1);
4817     bson_finish(&bsq1);
4818     CU_ASSERT_FALSE_FATAL(bsq1.err);
4819
4820     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4821     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4822     uint32_t count = 0;
4823     TCXSTR *log = tcxstrnew();
4824     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4825     //fprintf(stderr, "%s", TCXSTRPTR(log));
4826     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4827     CU_ASSERT_EQUAL(count, 1);
4828     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "token occurrence: \"Hello\" 1"));
4829
4830     bson_destroy(&bsq1);
4831     tclistdel(q1res);
4832     tcxstrdel(log);
4833     ejdbquerydel(q1);
4834 }
4835
4836 void testTicket28(void) {
4837     EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL);
4838     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
4839     //{$some:2}
4840     bson bsq1;
4841     bson_init_as_query(&bsq1);
4842     bson_append_int(&bsq1, "$some", 2);
4843     bson_finish(&bsq1);
4844     CU_ASSERT_FALSE_FATAL(bsq1.err);
4845     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4846     CU_ASSERT_EQUAL(ejdbecode(jb), JBEQERROR);
4847     CU_ASSERT_PTR_NULL(q1);
4848     bson_destroy(&bsq1);
4849
4850     //Second step
4851     bson_init_as_query(&bsq1);
4852     bson_finish(&bsq1);
4853     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4854     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4855     uint32_t count = 0;
4856     TCXSTR *log = tcxstrnew();
4857     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4858     CU_ASSERT_EQUAL(ejdbecode(jb), TCESUCCESS);
4859     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4860
4861     bson_destroy(&bsq1);
4862     tcxstrdel(log);
4863     ejdbquerydel(q1);
4864     tclistdel(q1res);
4865 }
4866
4867 void testTicket38(void) {
4868     EJCOLL *coll = ejdbcreatecoll(jb, "ticket38", NULL);
4869     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
4870
4871     //R: {a: [ 'b', 'c', 'ddd', 3 ]}
4872     bson r1;
4873     bson_init(&r1);
4874     bson_append_start_array(&r1, "a");
4875     bson_append_string(&r1, "0", "b");
4876     bson_append_string(&r1, "1", "c");
4877     bson_append_string(&r1, "2", "ddd");
4878     bson_append_int(&r1, "3", 3);
4879     bson_append_finish_array(&r1);
4880     bson_finish(&r1);
4881     CU_ASSERT_FALSE_FATAL(r1.err);
4882
4883     bson_oid_t oid;
4884     CU_ASSERT_TRUE(ejdbsavebson(coll, &r1, &oid));
4885     bson_destroy(&r1);
4886
4887     //Q: {$pullAll:{a:[3, 2, 'c']}
4888     bson bsq1;
4889     bson_init_as_query(&bsq1);
4890     bson_append_start_object(&bsq1, "$pullAll");
4891     bson_append_start_array(&bsq1, "a");
4892     bson_append_int(&bsq1, "0", 3);
4893     bson_append_int(&bsq1, "1", 2);
4894     bson_append_string(&bsq1, "2", "c");
4895     bson_append_finish_array(&bsq1);
4896     bson_append_finish_object(&bsq1);
4897     bson_finish(&bsq1);
4898     CU_ASSERT_FALSE_FATAL(bsq1.err);
4899
4900     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4901     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4902     uint32_t count = 0;
4903     TCXSTR *log = tcxstrnew();
4904     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
4905     //fprintf(stderr, "%s", TCXSTRPTR(log));
4906
4907     tcxstrdel(log);
4908     ejdbquerydel(q1);
4909     bson_destroy(&bsq1);
4910
4911     //Q: {}
4912     bson_init_as_query(&bsq1);
4913     bson_finish(&bsq1);
4914     CU_ASSERT_FALSE_FATAL(bsq1.err);
4915     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
4916     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
4917     log = tcxstrnew();
4918     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
4919     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
4920
4921     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
4922         void *bsdata = TCLISTVALPTR(q1res, i);
4923         bson_iterator it;
4924         bson_iterator_from_buffer(&it, bsdata);
4925         bson_type bt = bson_find_fieldpath_value("_id", &it);
4926         CU_ASSERT_EQUAL(bt, BSON_OID);
4927         CU_ASSERT_FALSE(bson_compare_string("b", TCLISTVALPTR(q1res, i), "a.0"));
4928         CU_ASSERT_FALSE(bson_compare_string("ddd", TCLISTVALPTR(q1res, i), "a.1"));
4929         bt = bson_find_fieldpath_value("a.2", &it);
4930         CU_ASSERT_EQUAL(bt, BSON_EOO);
4931         bt = bson_find_fieldpath_value("a.3", &it);
4932         CU_ASSERT_EQUAL(bt, BSON_EOO);
4933     }
4934
4935     tcxstrdel(log);
4936     ejdbquerydel(q1);
4937     bson_destroy(&bsq1);
4938     tclistdel(q1res);
4939 }
4940
4941 void testTicket43(void) {
4942
4943     EJCOLL *coll = ejdbcreatecoll(jb, "ticket43", NULL);
4944     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
4945     EJCOLL *rcoll = ejdbcreatecoll(jb, "ticket43_refs", NULL);
4946     CU_ASSERT_PTR_NOT_NULL_FATAL(rcoll);
4947
4948     bson a1;
4949     bson_oid_t oid;
4950     bson_oid_t ref_oids[2];
4951     char xoid[25];
4952
4953     bson_init(&a1);
4954     bson_append_string(&a1, "name", "n1");
4955     bson_append_string(&a1, "name2", "n12");
4956     bson_finish(&a1);
4957     CU_ASSERT_FALSE_FATAL(a1.err);
4958     CU_ASSERT_TRUE_FATAL(ejdbsavebson(rcoll, &a1, &ref_oids[0]));
4959     bson_destroy(&a1);
4960
4961     bson_init(&a1);
4962     bson_append_string(&a1, "name", "n2");
4963     bson_append_string(&a1, "name2", "n22");
4964     bson_finish(&a1);
4965     CU_ASSERT_FALSE_FATAL(a1.err);
4966     CU_ASSERT_TRUE_FATAL(ejdbsavebson(rcoll, &a1, &ref_oids[1]));
4967     bson_destroy(&a1);
4968
4969     bson_init(&a1);
4970     bson_append_string(&a1, "name", "c1");
4971     bson_oid_to_string(&ref_oids[0], xoid);
4972     bson_append_string(&a1, "refs", xoid);
4973     bson_finish(&a1);
4974     CU_ASSERT_FALSE_FATAL(a1.err);
4975     CU_ASSERT_TRUE_FATAL(ejdbsavebson(coll, &a1, &oid));
4976     bson_destroy(&a1);
4977
4978     bson_init(&a1);
4979     bson_append_string(&a1, "name", "c2");
4980     bson_append_start_array(&a1, "arrefs");
4981     bson_oid_to_string(&ref_oids[0], xoid);
4982     bson_append_string(&a1, "0", xoid);
4983     bson_append_oid(&a1, "1", &ref_oids[1]);
4984     bson_append_finish_array(&a1);
4985     bson_finish(&a1);
4986     CU_ASSERT_FALSE_FATAL(a1.err);
4987     CU_ASSERT_TRUE_FATAL(ejdbsavebson(coll, &a1, &oid));
4988     bson_destroy(&a1);
4989
4990     /*
4991      Assuming fpath contains object id (or its string representation).
4992      In query results fpath values will be replaced by loaded bson
4993      objects with matching oids from collectionname
4994
4995      {..., $do : {fpath : {$join : 'collectionname'}} }
4996      $fields applied to the joined object:
4997      {..., $do : {fpath : {$join : 'collectionname'}} }, {$fields : {fpath.jonnedfpath : 1}}
4998      */
4999
5000     bson bsq1;
5001     bson_init_as_query(&bsq1);
5002     bson_append_string(&bsq1, "name", "c1");
5003     bson_append_start_object(&bsq1, "$do");
5004     bson_append_start_object(&bsq1, "refs");
5005     bson_append_string(&bsq1, "$join", "ticket43_refs");
5006     bson_append_finish_object(&bsq1);
5007     bson_append_finish_object(&bsq1);
5008     bson_finish(&bsq1);
5009     CU_ASSERT_FALSE_FATAL(bsq1.err);
5010
5011     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
5012     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5013
5014     uint32_t count = 0;
5015     TCXSTR *log = tcxstrnew();
5016     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
5017     //fprintf(stderr, "%s", TCXSTRPTR(log));
5018     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
5019     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FIELD: refs HAS $do OPERATION"));
5020     CU_ASSERT_EQUAL(count, 1);
5021
5022     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5023         CU_ASSERT_FALSE(bson_compare_string("n1", TCLISTVALPTR(q1res, i), "refs.name"));
5024     }
5025
5026     tclistdel(q1res);
5027     ejdbquerydel(q1);
5028     bson_destroy(&bsq1);
5029     tcxstrdel(log);
5030
5031     /////////////////////////////////////////////////////////////////////////////////////
5032
5033     bson_init_as_query(&bsq1);
5034     bson_append_string(&bsq1, "name", "c2");
5035     bson_append_start_object(&bsq1, "$do");
5036     bson_append_start_object(&bsq1, "arrefs");
5037     bson_append_string(&bsq1, "$join", "ticket43_refs");
5038     bson_append_finish_object(&bsq1);
5039     bson_append_finish_object(&bsq1);
5040     bson_finish(&bsq1);
5041     CU_ASSERT_FALSE_FATAL(bsq1.err);
5042
5043     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
5044     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5045
5046     count = 0;
5047     log = tcxstrnew();
5048     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
5049
5050     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
5051     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FIELD: arrefs HAS $do OPERATION"));
5052     CU_ASSERT_EQUAL(count, 1);
5053
5054     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5055         CU_ASSERT_FALSE(bson_compare_string("c2", TCLISTVALPTR(q1res, i), "name"));
5056         CU_ASSERT_FALSE(bson_compare_string("n1", TCLISTVALPTR(q1res, i), "arrefs.0.name"));
5057         CU_ASSERT_FALSE(bson_compare_string("n2", TCLISTVALPTR(q1res, i), "arrefs.1.name"));
5058     }
5059
5060     tclistdel(q1res);
5061     ejdbquerydel(q1);
5062     bson_destroy(&bsq1);
5063     tcxstrdel(log);
5064
5065     /////////////////////////////////////////////////////////////////////////////////////////////////
5066
5067     bson_init_as_query(&bsq1);
5068     bson_append_string(&bsq1, "name", "c2");
5069     bson_append_start_object(&bsq1, "$do");
5070     bson_append_start_object(&bsq1, "arrefs");
5071     bson_append_string(&bsq1, "$join", "ticket43_refs");
5072     bson_append_finish_object(&bsq1);
5073     bson_append_finish_object(&bsq1);
5074     bson_finish(&bsq1);
5075     CU_ASSERT_FALSE_FATAL(bsq1.err);
5076
5077
5078     bson bshits1;
5079     bson_init_as_query(&bshits1);
5080     bson_append_start_object(&bshits1, "$fields");
5081     bson_append_int(&bshits1, "arrefs.0.name", 0);
5082     bson_append_finish_object(&bshits1);
5083     bson_finish(&bshits1);
5084     CU_ASSERT_FALSE_FATAL(bshits1.err);
5085
5086     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshits1);
5087     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5088
5089     count = 0;
5090     log = tcxstrnew();
5091     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
5092     //fprintf(stderr, "%s", TCXSTRPTR(log));
5093     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
5094     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FIELD: arrefs HAS $do OPERATION"));
5095     CU_ASSERT_EQUAL(count, 1);
5096
5097     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5098         bson_type bt;
5099         bson_iterator it;
5100         bson_iterator_from_buffer(&it, TCLISTVALPTR(q1res, i));
5101         CU_ASSERT_FALSE(bson_compare_string("c2", TCLISTVALPTR(q1res, i), "name"));
5102         bt = bson_find_fieldpath_value("arrefs.0.name", &it);
5103         CU_ASSERT_TRUE(bt == BSON_EOO);
5104         CU_ASSERT_FALSE(bson_compare_string("n2", TCLISTVALPTR(q1res, i), "arrefs.1.name"));
5105     }
5106
5107     tclistdel(q1res);
5108     ejdbquerydel(q1);
5109     bson_destroy(&bsq1);
5110     bson_destroy(&bshits1);
5111     tcxstrdel(log);
5112 }
5113
5114 void testTicket54(void) {
5115     EJCOLL *coll = ejdbcreatecoll(jb, "ticket54", NULL);
5116     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
5117     bson b;
5118     bson_oid_t oid;
5119     bson_init(&b);
5120     bson_append_long(&b, "value", -10000000L);
5121     bson_finish(&b);
5122     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5123     bson_destroy(&b);
5124     CU_ASSERT_TRUE(ejdbsetindex(coll, "value", JBIDXNUM));
5125 }
5126
5127 void testMetaInfo(void) {
5128     bson *meta = ejdbmeta(jb);
5129     CU_ASSERT_PTR_NOT_NULL_FATAL(meta);
5130     const char *metabsdata = bson_data(meta);
5131     CU_ASSERT_FALSE(bson_compare_string("dbt2", metabsdata, "file"));
5132     CU_ASSERT_FALSE(bson_compare_string("contacts", metabsdata, "collections.1.name"));
5133     CU_ASSERT_FALSE(bson_compare_string("dbt2_contacts", metabsdata, "collections.1.file"));
5134     CU_ASSERT_FALSE(bson_compare_long(131071, metabsdata, "collections.1.options.buckets"));
5135     CU_ASSERT_FALSE(bson_compare_long(8, metabsdata, "collections.1.records"));
5136     bson_del(meta);
5137 }
5138
5139 void testTicket81(void) {
5140     EJCOLL *coll = ejdbcreatecoll(jb, "ticket81", NULL);
5141     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
5142
5143     bson b;
5144     bson_oid_t oid;
5145
5146     bson_init(&b); //true
5147     bson_append_int(&b, "z", 33);
5148     bson_append_int(&b, "a", 1);
5149     bson_append_int(&b, "b", 3);
5150     bson_append_int(&b, "c", 10);
5151     bson_append_int(&b, "d", 7);
5152     bson_finish(&b);
5153     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5154     bson_destroy(&b);
5155
5156     bson_init(&b); //false
5157     bson_append_int(&b, "z", 33);
5158     bson_append_int(&b, "a", 11);
5159     bson_append_int(&b, "b", 22);
5160     bson_append_int(&b, "c", 5);
5161     bson_append_int(&b, "d", 7);
5162     bson_finish(&b);
5163     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5164     bson_destroy(&b);
5165
5166     bson_init(&b); //true
5167     bson_append_int(&b, "z", 33);
5168     bson_append_int(&b, "b", 2);
5169     bson_append_int(&b, "d", 7);
5170     bson_finish(&b);
5171     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5172     bson_destroy(&b);
5173
5174     bson_init(&b); //false
5175     bson_append_int(&b, "z", 22);
5176     bson_append_int(&b, "a", 1);
5177     bson_append_int(&b, "b", 3);
5178     bson_append_int(&b, "c", 10);
5179     bson_append_int(&b, "d", 7);
5180     bson_finish(&b);
5181     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5182     bson_destroy(&b);
5183
5184     //z=33 AND (a=1 OR b=2) AND (c=5 OR d=7)
5185     //{z : 33, $and : [ {$or : [{a : 1}, {b : 2}]}, {$or : [{c : 5}, {d : 7}]} ] }
5186     bson_init_as_query(&b);
5187     bson_append_int(&b, "z", 33);
5188     bson_append_start_array(&b, "$and");
5189
5190     //{$or : [{a : 1}, {b : 2}]}
5191     bson_append_start_object(&b, "0");
5192     bson_append_start_array(&b, "$or");
5193     //{a : 1}
5194     bson_append_start_object(&b, "0");
5195     bson_append_int(&b, "a", 1);
5196     bson_append_finish_object(&b);
5197     //{b : 2}
5198     bson_append_start_object(&b, "1");
5199     bson_append_int(&b, "b", 2);
5200     bson_append_finish_object(&b);
5201     bson_append_finish_array(&b);
5202     bson_append_finish_object(&b); //eof {$or : [{a : 1}, {b : 2}]}
5203
5204     //{$or : [{c : 5}, {d : 7}]}
5205     bson_append_start_object(&b, "1");
5206     bson_append_start_array(&b, "$or");
5207     //{c : 5}
5208     bson_append_start_object(&b, "0");
5209     bson_append_int(&b, "c", 5);
5210     bson_append_finish_object(&b);
5211     //{d : 7}
5212     bson_append_start_object(&b, "1");
5213     bson_append_int(&b, "d", 7);
5214     bson_append_finish_object(&b);
5215     bson_append_finish_array(&b);
5216     bson_append_finish_object(&b); //eof {$or : [{c : 5}, {d : 7}]}
5217     bson_append_finish_array(&b); //eof $and
5218     bson_finish(&b);
5219
5220     TCXSTR *log = tcxstrnew();
5221     uint32_t count = 0;
5222     EJQ *q1 = ejdbcreatequery(jb, &b, NULL, 0, NULL);
5223     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5224     bson_destroy(&b);
5225
5226     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
5227     //fprintf(stderr, "%s", TCXSTRPTR(log));
5228     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
5229     CU_ASSERT_EQUAL(count, 2);
5230     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 1"));
5231     CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "$AND QUERIES: 2"));
5232
5233     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5234         //z=33 AND (a=1 OR b=2) AND (c=5 OR d=7)
5235         CU_ASSERT_FALSE(bson_compare_long(33, TCLISTVALPTR(q1res, i), "z"));
5236         CU_ASSERT_TRUE(!bson_compare_long(1, TCLISTVALPTR(q1res, i), "a") || !bson_compare_long(2, TCLISTVALPTR(q1res, i), "b"));
5237         CU_ASSERT_TRUE(!bson_compare_long(5, TCLISTVALPTR(q1res, i), "c") || !bson_compare_long(7, TCLISTVALPTR(q1res, i), "d"));
5238     }
5239     tclistdel(q1res);
5240     ejdbquerydel(q1);
5241     bson_destroy(&b);
5242     tcxstrdel(log);
5243 }
5244
5245 // $(projection)
5246 // https://github.com/Softmotions/ejdb/issues/15
5247 // http://docs.mongodb.org/manual/reference/projection/positional/#proj._S_
5248
5249 void testDQprojection(void) {
5250     EJCOLL *coll = ejdbcreatecoll(jb, "f_projection", NULL);
5251     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
5252
5253     bson b;
5254     bson_oid_t oid;
5255
5256     bson_init(&b);
5257     bson_append_int(&b, "z", 33);
5258     bson_append_start_array(&b, "arr");
5259     bson_append_int(&b, "0", 0);
5260     bson_append_int(&b, "1", 1);
5261     bson_append_int(&b, "2", 2);
5262     bson_append_int(&b, "3", 3);
5263     bson_append_finish_array(&b);
5264     bson_finish(&b);
5265     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5266     bson_destroy(&b);
5267
5268     bson_init(&b);
5269     bson_append_int(&b, "z", 33);
5270     bson_append_start_array(&b, "arr");
5271     bson_append_int(&b, "0", 3);
5272     bson_append_int(&b, "1", 2);
5273     bson_append_int(&b, "2", 1);
5274     bson_append_int(&b, "3", 0);
5275     bson_append_finish_array(&b);
5276     bson_finish(&b);
5277     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5278     bson_destroy(&b);
5279
5280     bson_init(&b);
5281     bson_append_int(&b, "z", 44);
5282     bson_append_start_array(&b, "arr");
5283     bson_append_start_object(&b, "0");
5284     bson_append_int(&b, "h", 1);
5285     bson_append_finish_object(&b);
5286     bson_append_start_object(&b, "1");
5287     bson_append_int(&b, "h", 2);
5288     bson_append_finish_object(&b);
5289     bson_append_finish_array(&b);
5290     bson_finish(&b);
5291     //bson_print_raw(bson_data(&b), 0);
5292     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5293     bson_destroy(&b);
5294
5295 //////// Q1
5296     bson bshints;
5297     bson_init_as_query(&bshints);
5298     bson_append_start_object(&bshints, "$fields");
5299     bson_append_int(&bshints, "arr.$", 1);
5300     bson_append_finish_object(&bshints);
5301     bson_finish(&bshints);
5302     CU_ASSERT_FALSE_FATAL(bshints.err);
5303
5304     bson bsq1;
5305     bson_init_as_query(&bsq1);
5306     bson_append_int(&bsq1, "z", 33);
5307     bson_append_start_object(&bsq1, "arr");
5308     bson_append_int(&bsq1, "$gte", 2);
5309     bson_append_finish_object(&bsq1);
5310     bson_finish(&bsq1);
5311
5312     TCXSTR *log = tcxstrnew();
5313     uint32_t count;
5314     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
5315     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5316     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
5317     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 2);
5318     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5319         CU_ASSERT_TRUE(!bson_compare_long(2, TCLISTVALPTR(q1res, i), "arr.0") || !bson_compare_long(3, TCLISTVALPTR(q1res, i), "arr.0"));
5320     }
5321
5322     tclistdel(q1res);
5323     ejdbquerydel(q1);
5324     tcxstrdel(log);
5325     bson_destroy(&bshints);
5326     bson_destroy(&bsq1);
5327
5328     /////// Q2
5329     bson_init_as_query(&bshints);
5330     bson_append_start_object(&bshints, "$fields");
5331     bson_append_int(&bshints, "arr.$.h", 1);
5332     bson_append_finish_object(&bshints);
5333     bson_finish(&bshints);
5334     CU_ASSERT_FALSE_FATAL(bshints.err);
5335
5336     bson_init_as_query(&bsq1);
5337     bson_append_int(&bsq1, "z", 44);
5338     bson_append_int(&bsq1, "arr.h", 2);
5339     bson_finish(&bsq1);
5340
5341     log = tcxstrnew();
5342     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
5343     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5344     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
5345     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
5346     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5347         CU_ASSERT_FALSE(bson_compare_long(2, TCLISTVALPTR(q1res, i), "arr.0.h"));
5348     }
5349     tclistdel(q1res);
5350     ejdbquerydel(q1);
5351     tcxstrdel(log);
5352     bson_destroy(&bshints);
5353     bson_destroy(&bsq1);
5354
5355
5356     /////// Q3
5357     bson_init_as_query(&bshints);
5358     bson_append_start_object(&bshints, "$fields");
5359     bson_append_int(&bshints, "arr.$.h", 1);
5360     bson_append_finish_object(&bshints);
5361     bson_finish(&bshints);
5362     CU_ASSERT_FALSE_FATAL(bshints.err);
5363
5364     //{z: 44, arr: {$elemMatch: {h: 2}} }
5365     bson_init_as_query(&bsq1);
5366     bson_append_int(&bsq1, "z", 44);
5367     bson_append_start_object(&bsq1, "arr");
5368     bson_append_start_object(&bsq1, "$elemMatch");
5369     bson_append_int(&bsq1, "h", 2);
5370     bson_append_finish_object(&bsq1);
5371     bson_append_finish_object(&bsq1);
5372     bson_finish(&bsq1);
5373
5374     log = tcxstrnew();
5375     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
5376     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5377     q1res = ejdbqryexecute(coll, q1, &count, 0, log);
5378     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
5379     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5380         CU_ASSERT_FALSE(bson_compare_long(2, TCLISTVALPTR(q1res, i), "arr.0.h"));
5381     }
5382     tclistdel(q1res);
5383     ejdbquerydel(q1);
5384     tcxstrdel(log);
5385     bson_destroy(&bshints);
5386     bson_destroy(&bsq1);
5387 }
5388
5389 void testTicket96(void) {
5390     EJCOLL *coll = ejdbgetcoll(jb, "f_projection");
5391     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
5392
5393     //{ $and : [ {arr : {$elemMatch : {h : 2}}} ]
5394     bson bsq1;
5395     bson_init_as_query(&bsq1);
5396     bson_append_start_array(&bsq1, "$and");
5397     bson_append_start_object(&bsq1, "0");
5398     bson_append_start_object(&bsq1, "arr");
5399     bson_append_start_object(&bsq1, "$elemMatch");
5400     bson_append_int(&bsq1, "h", 2);
5401     bson_append_finish_object(&bsq1);
5402     bson_append_finish_object(&bsq1);
5403     bson_append_finish_object(&bsq1);
5404     bson_append_finish_array(&bsq1);
5405     bson_finish(&bsq1);
5406
5407     CU_ASSERT_EQUAL(bsq1.err, 0);
5408
5409     TCXSTR *log = tcxstrnew();
5410     uint32_t count;
5411     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
5412     bson_destroy(&bsq1);
5413     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5414     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
5415     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
5416
5417     tclistdel(q1res);
5418     ejdbquerydel(q1);
5419     tcxstrdel(log);
5420 }
5421
5422
5423 // $(query)
5424 // https://github.com/Softmotions/ejdb/issues/15
5425 // http://docs.mongodb.org/manual/reference/projection/positional/#proj._S_
5426
5427 void testDQupdate(void) {
5428     EJCOLL *coll = ejdbcreatecoll(jb, "f_update", NULL);
5429     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
5430
5431     bson b;
5432     bson_oid_t oid;
5433
5434     bson_init(&b);
5435     bson_append_int(&b, "z", 33);
5436     bson_append_start_array(&b, "arr");
5437     bson_append_int(&b, "0", 0);
5438     bson_append_int(&b, "1", 1);
5439     bson_append_int(&b, "2", 2);
5440     bson_append_int(&b, "3", 3);
5441     bson_append_finish_array(&b);
5442     bson_finish(&b);
5443     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5444     bson_destroy(&b);
5445
5446     bson bsq1;
5447     bson_init_as_query(&bsq1);
5448     bson_append_int(&bsq1, "z", 33);
5449     bson_append_int(&bsq1, "arr", 1);
5450     bson_append_start_object(&bsq1, "$set");
5451     bson_append_int(&bsq1, "arr.$", 4);
5452     bson_append_finish_object(&bsq1);
5453     bson_finish(&bsq1);
5454
5455     TCXSTR *log = tcxstrnew();
5456     uint32_t count;
5457     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
5458     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5459     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
5460     CU_ASSERT_EQUAL(count, 1);
5461
5462     ejdbquerydel(q1);
5463     tcxstrdel(log);
5464     bson_destroy(&bsq1);
5465
5466     //Now check It
5467     bson_init_as_query(&bsq1);
5468     bson_append_int(&bsq1, "z", 33);
5469     bson_append_int(&bsq1, "arr", 4);
5470     bson_finish(&bsq1);
5471
5472     log = tcxstrnew();
5473     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
5474     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5475     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
5476     CU_ASSERT_EQUAL(count, 1);
5477
5478     ejdbquerydel(q1);
5479     tcxstrdel(log);
5480     bson_destroy(&bsq1);
5481
5482 }
5483
5484 void testDQupdate2(void) {
5485     EJCOLL *coll = ejdbcreatecoll(jb, "f_update", NULL);
5486     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
5487
5488     bson b;
5489     bson_oid_t oid;
5490
5491     bson_init(&b);
5492     bson_append_int(&b, "z", 44);
5493     bson_append_start_array(&b, "arr");
5494     bson_append_start_object(&b, "0");
5495     bson_append_int(&b, "h", 1);
5496     bson_append_finish_object(&b);
5497     bson_append_start_object(&b, "1");
5498     bson_append_int(&b, "h", 2);
5499     bson_append_finish_object(&b);
5500     bson_append_finish_array(&b);
5501     bson_finish(&b);
5502     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5503     bson_destroy(&b);
5504
5505     bson bsq1;
5506     bson_init_as_query(&bsq1);
5507     bson_append_int(&bsq1, "z", 44);
5508     bson_append_int(&bsq1, "arr.h", 2);
5509     bson_append_start_object(&bsq1, "$set");
5510     bson_append_int(&bsq1, "arr.$.h", 4);
5511     bson_append_int(&bsq1, "arr.$.z", 5);
5512     bson_append_int(&bsq1, "k", 55);
5513     bson_append_finish_object(&bsq1);
5514     bson_finish(&bsq1);
5515
5516     TCXSTR *log = tcxstrnew();
5517     uint32_t count;
5518     EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
5519     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5520     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
5521     CU_ASSERT_EQUAL(count, 1);
5522
5523     ejdbquerydel(q1);
5524     tcxstrdel(log);
5525     bson_destroy(&bsq1);
5526
5527     //Now check It
5528     bson_init_as_query(&bsq1);
5529     bson_append_int(&bsq1, "k", 55);
5530     bson_append_int(&bsq1, "arr.h", 4);
5531     bson_append_int(&bsq1, "arr.z", 5);
5532     bson_finish(&bsq1);
5533
5534     log = tcxstrnew();
5535     q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL);
5536     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5537     ejdbqryexecute(coll, q1, &count, JBQRYCOUNT, log);
5538     CU_ASSERT_EQUAL(count, 1);
5539
5540     ejdbquerydel(q1);
5541     tcxstrdel(log);
5542     bson_destroy(&bsq1);
5543 }
5544
5545 void testTicket99(void) {
5546     EJCOLL *coll = ejdbcreatecoll(jb, "ticket99", NULL);
5547     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
5548
5549     //create
5550     bson_oid_t oid;
5551     bson data;
5552     bson_init(&data);
5553     bson_append_start_array(&data, "arr");
5554     bson_append_start_object(&data, "0");
5555     bson_append_string(&data, "test0", "value");
5556     bson_append_finish_object(&data);
5557     bson_append_finish_array(&data);
5558     bson_append_finish_array(&data);
5559     bson_finish(&data);
5560     CU_ASSERT_TRUE(ejdbsavebson(coll, &data, &oid));
5561     bson_destroy(&data);
5562
5563     //set
5564     bson bsquery;
5565     bson_init_as_query(&bsquery);
5566     bson_append_oid(&bsquery, "_id", &oid);
5567     bson_append_start_object(&bsquery, "$set");
5568     bson_append_string(&bsquery, "arr.0.test0", "value0");
5569     bson_append_string(&bsquery, "arr.0.test1", "value1");
5570     bson_append_string(&bsquery, "arr.0.test2", "value2");
5571     bson_append_string(&bsquery, "arr.0.test3", "value3");
5572     bson_append_string(&bsquery, "arr.0.test4", "value4");
5573     bson_append_finish_object(&bsquery);
5574     bson_finish(&bsquery);
5575
5576     uint32_t count = ejdbupdate(coll, &bsquery, 0, 0, 0, 0);
5577     CU_ASSERT_EQUAL(count, 1);
5578     bson_destroy(&bsquery);
5579
5580     bson_init_as_query(&bsquery);
5581     bson_finish(&bsquery);
5582     EJQ *q1 = ejdbcreatequery(jb, &bsquery, NULL, 0, NULL);
5583     bson_destroy(&bsquery);
5584     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5585     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, NULL);
5586     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
5587
5588     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5589         CU_ASSERT_FALSE(bson_compare_string("value0", TCLISTVALPTR(q1res, i), "arr.0.test0"));
5590         CU_ASSERT_FALSE(bson_compare_string("value1", TCLISTVALPTR(q1res, i), "arr.0.test1"));
5591         CU_ASSERT_FALSE(bson_compare_string("value2", TCLISTVALPTR(q1res, i), "arr.0.test2"));
5592         CU_ASSERT_FALSE(bson_compare_string("value3", TCLISTVALPTR(q1res, i), "arr.0.test3"));
5593         CU_ASSERT_FALSE(bson_compare_string("value4", TCLISTVALPTR(q1res, i), "arr.0.test4"));
5594     }
5595
5596     tclistdel(q1res);
5597     ejdbquerydel(q1);
5598 }
5599
5600
5601 void testTicket101(void) {
5602     EJCOLL *coll = ejdbcreatecoll(jb, "ticket101", NULL);
5603     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
5604
5605     bson b;
5606     bson_oid_t oid;
5607
5608     bson_init(&b);
5609     bson_append_int(&b, "z", 33);
5610     bson_append_start_object(&b, "obj");
5611     bson_append_string(&b, "name", "abc");
5612     bson_append_int(&b, "score", 12);
5613     bson_append_finish_object(&b); //eof obj
5614     bson_append_start_array(&b, "arr");
5615     bson_append_int(&b, "0", 0);
5616     bson_append_start_object(&b, "1");
5617     bson_append_string(&b, "name", "cde");
5618     bson_append_int(&b, "score", 13);
5619     bson_append_finish_object(&b);
5620     bson_append_int(&b, "2", 2);
5621     bson_append_int(&b, "3", 3);
5622     bson_append_finish_array(&b); //eof arr
5623     bson_finish(&b);
5624     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5625     bson_destroy(&b);
5626
5627     bson bsq;
5628     bson_init_as_query(&bsq);
5629     bson_append_start_object(&bsq, "$unset");
5630     bson_append_string(&bsq, "obj.name", "");
5631     bson_append_bool(&bsq, "arr.1.score", true);
5632     bson_append_bool(&bsq, "arr.2", true);
5633     bson_append_finish_object(&bsq);
5634     bson_finish(&bsq);
5635
5636     uint32_t count = ejdbupdate(coll, &bsq, 0, 0, 0, 0);
5637     bson_destroy(&bsq);
5638     CU_ASSERT_EQUAL(count, 1);
5639
5640
5641     bson_init_as_query(&bsq);
5642     bson_finish(&bsq);
5643     EJQ *q1 = ejdbcreatequery(jb, &bsq, NULL, 0, NULL);
5644     bson_destroy(&bsq);
5645     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5646     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, NULL);
5647     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
5648
5649     bson_type bt;
5650     bson_iterator it;
5651     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5652         CU_ASSERT_FALSE(bson_compare_long(33,  TCLISTVALPTR(q1res, i), "z"));
5653         CU_ASSERT_FALSE(bson_compare_long(12,  TCLISTVALPTR(q1res, i), "obj.score"));
5654         bson_iterator_from_buffer(&it, TCLISTVALPTR(q1res, i));
5655         bt = bson_find_fieldpath_value("obj.name", &it);
5656         CU_ASSERT_TRUE(bt == BSON_EOO);
5657         bson_iterator_from_buffer(&it, TCLISTVALPTR(q1res, i));
5658         bt = bson_find_fieldpath_value("arr.2", &it);
5659         CU_ASSERT_TRUE(bt == BSON_UNDEFINED);
5660     }
5661
5662     tclistdel(q1res);
5663     ejdbquerydel(q1);
5664 }
5665
5666 void testTicket110(void) {
5667         EJCOLL *coll = ejdbcreatecoll(jb, "ticket110", NULL);
5668     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
5669         
5670         bson b;
5671     bson_oid_t oid;
5672
5673     bson_init(&b);
5674         bson_append_string(&b, "comment", "One");
5675         bson_append_string(&b, "status", "New");
5676         bson_append_int(&b, "xversion", 0);
5677         bson_append_int(&b, "value",  9855);
5678         bson_append_string(&b, "title", "Lead 0");
5679     bson_finish(&b);
5680     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5681     bson_destroy(&b);
5682         
5683         bson_init(&b);
5684         bson_append_string(&b, "comment", "Two");
5685         bson_append_string(&b, "status", "New");
5686         bson_append_int(&b, "xversion", 0);
5687         bson_append_string(&b, "value",  "18973");
5688         bson_append_string(&b, "title", "Lead 1");
5689     bson_finish(&b);
5690     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5691     bson_destroy(&b);
5692
5693         bson_init(&b);
5694         bson_append_string(&b, "comment", "Three");
5695         bson_append_string(&b, "status", "New");
5696         bson_append_int(&b, "xversion", 0);
5697         bson_append_string(&b, "value",  "25504");
5698         bson_append_string(&b, "title", "Lead 2");
5699     bson_finish(&b);
5700     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
5701     bson_destroy(&b);
5702
5703         
5704         //   
5705         bson bsq;
5706     bson_init_as_query(&bsq);
5707         bson_finish(&bsq);
5708         CU_ASSERT_FALSE_FATAL(bsq.err);
5709
5710         //
5711         bson bshints;
5712     bson_init_as_query(&bshints);
5713     bson_append_start_object(&bshints, "$orderby");
5714     bson_append_int(&bshints, "value", -1);
5715     bson_append_finish_object(&bshints);
5716     bson_finish(&bshints);
5717     CU_ASSERT_FALSE_FATAL(bshints.err);
5718         
5719         EJQ *q1 = ejdbcreatequery(jb, &bsq, NULL, 0, &bshints);
5720     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5721         
5722         uint32_t count = 0;
5723     TCXSTR *log = tcxstrnew();
5724     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
5725         
5726         bson_destroy(&bsq);
5727         bson_destroy(&bshints);
5728         
5729         tclistdel(q1res);
5730         tcxstrdel(log);
5731         ejdbquerydel(q1);
5732 }
5733
5734 // Ticket #14
5735 void testSlice(void) {
5736         EJCOLL *coll = ejdbgetcoll(jb, "f_projection");
5737     CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
5738         
5739         bson_iterator it;
5740         
5741 // { z : 44, $do : { arr : {$slice : 1} } }
5742         bson bsq;
5743     bson_init_as_query(&bsq);
5744     bson_append_int(&bsq, "z", 44);
5745     bson_append_start_object(&bsq, "$do");
5746     bson_append_start_object(&bsq, "arr");
5747     bson_append_int(&bsq, "$slice", 1);
5748     bson_append_finish_object(&bsq);
5749     bson_append_finish_object(&bsq);
5750     bson_finish(&bsq);
5751     CU_ASSERT_FALSE_FATAL(bsq.err);
5752         
5753         EJQ *q1 = ejdbcreatequery(jb, &bsq, NULL, 0, NULL);
5754     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5755         
5756         uint32_t count = 0;
5757     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, NULL);
5758         //fprintf(stderr, "\n%s", TCXSTRPTR(log));
5759         CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
5760     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5761                 void *bsdata = TCLISTVALPTR(q1res, i);
5762         CU_ASSERT_PTR_NOT_NULL_FATAL(bsdata);
5763         CU_ASSERT_FALSE(bson_compare_long(1, bsdata, "arr.0.h"));
5764                 bson_iterator_from_buffer(&it, bsdata);
5765                 CU_ASSERT_TRUE(bson_find_fieldpath_value("arr.1.h", &it) == BSON_EOO);
5766     }
5767         tclistdel(q1res);
5768         bson_destroy(&bsq);
5769         ejdbquerydel(q1);
5770         
5771         // { z : 44, $do : { arr : {$slice : 2} } }
5772         bson_init_as_query(&bsq);
5773     bson_append_int(&bsq, "z", 44);
5774     bson_append_start_object(&bsq, "$do");
5775     bson_append_start_object(&bsq, "arr");
5776     bson_append_int(&bsq, "$slice", 2);
5777     bson_append_finish_object(&bsq);
5778     bson_append_finish_object(&bsq);
5779     bson_finish(&bsq);
5780     CU_ASSERT_FALSE_FATAL(bsq.err);
5781         
5782         q1 = ejdbcreatequery(jb, &bsq, NULL, 0, NULL);
5783     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5784         
5785         count = 0;
5786     q1res = ejdbqryexecute(coll, q1, &count, 0, NULL);
5787         CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
5788         CU_ASSERT_EQUAL(count, 1);
5789     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5790                 void *bsdata = TCLISTVALPTR(q1res, i);
5791         CU_ASSERT_PTR_NOT_NULL_FATAL(bsdata);
5792         CU_ASSERT_FALSE(bson_compare_long(1, bsdata, "arr.0.h"));
5793         CU_ASSERT_FALSE(bson_compare_long(2, bsdata, "arr.1.h"));
5794                 bson_iterator_from_buffer(&it, bsdata);
5795                 CU_ASSERT_TRUE(bson_find_fieldpath_value("arr.2.h", &it) == BSON_EOO);
5796     }
5797         tclistdel(q1res);
5798         bson_destroy(&bsq);
5799         ejdbquerydel(q1);
5800         
5801         // { $do : { arr : {$slice : [1, 2]} } }
5802         bson_init_as_query(&bsq);
5803     bson_append_start_object(&bsq, "$do");
5804     bson_append_start_object(&bsq, "arr");
5805     bson_append_start_array(&bsq, "$slice");
5806         bson_append_int(&bsq, "0", 1);
5807         bson_append_int(&bsq, "1", 2);
5808         bson_append_finish_array(&bsq);
5809     bson_append_finish_object(&bsq);
5810     bson_append_finish_object(&bsq);
5811     bson_finish(&bsq);
5812     CU_ASSERT_FALSE_FATAL(bsq.err);
5813         
5814         q1 = ejdbcreatequery(jb, &bsq, NULL, 0, NULL);
5815     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5816         
5817         count = 0;
5818     q1res = ejdbqryexecute(coll, q1, &count, 0, NULL);
5819         CU_ASSERT_EQUAL(TCLISTNUM(q1res), 3);
5820         CU_ASSERT_EQUAL(count, 3);
5821     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5822                 void *bsdata = TCLISTVALPTR(q1res, i);
5823         CU_ASSERT_PTR_NOT_NULL_FATAL(bsdata);
5824                 if (i == 0) {
5825                         CU_ASSERT_FALSE(bson_compare_long(1, bsdata, "arr.0"));
5826                         CU_ASSERT_FALSE(bson_compare_long(2, bsdata, "arr.1"));
5827                         bson_iterator_from_buffer(&it, bsdata);
5828                         CU_ASSERT_TRUE(bson_find_fieldpath_value("arr.2", &it) == BSON_EOO);
5829                 } else if (i == 1) {
5830                         CU_ASSERT_FALSE(bson_compare_long(2, bsdata, "arr.0"));
5831                         CU_ASSERT_FALSE(bson_compare_long(1, bsdata, "arr.1"));
5832                         bson_iterator_from_buffer(&it, bsdata);
5833                         CU_ASSERT_TRUE(bson_find_fieldpath_value("arr.2", &it) == BSON_EOO);
5834                 } else if (i == 2) {
5835                         CU_ASSERT_FALSE(bson_compare_long(2, bsdata, "arr.0.h"));
5836                         bson_iterator_from_buffer(&it, bsdata);
5837                         CU_ASSERT_TRUE(bson_find_fieldpath_value("arr.1", &it) == BSON_EOO);
5838                 }
5839     }
5840         tclistdel(q1res);
5841         bson_destroy(&bsq);
5842         ejdbquerydel(q1);
5843         
5844         
5845         
5846 //{ _id: '54d7a2f07e671e140000001f',
5847 //  z: 33,
5848 //  arr: [ 0, 1, 2, 3 ] }
5849 //{ _id: '54d7a2f07e671e1400000020',
5850 //  z: 33,
5851 //  arr: [ 3, 2, 1, 0 ] }
5852 //{ _id: '54d7a2f07e671e1400000021',
5853 //  z: 44,
5854 //  arr: [ { h: 1 }, { h: 2 } ] } 
5855         
5856         // { $do : { arr : {$slice : [-3, 1]} } }
5857         bson_init_as_query(&bsq);
5858     bson_append_start_object(&bsq, "$do");
5859     bson_append_start_object(&bsq, "arr");
5860     bson_append_start_array(&bsq, "$slice");
5861         bson_append_int(&bsq, "0", -3);
5862         bson_append_int(&bsq, "1", 1);
5863         bson_append_finish_array(&bsq);
5864     bson_append_finish_object(&bsq);
5865     bson_append_finish_object(&bsq);
5866     bson_finish(&bsq);
5867     CU_ASSERT_FALSE_FATAL(bsq.err);
5868         
5869         q1 = ejdbcreatequery(jb, &bsq, NULL, 0, NULL);
5870     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5871         
5872         count = 0;
5873     q1res = ejdbqryexecute(coll, q1, &count, 0, NULL);
5874         CU_ASSERT_EQUAL(TCLISTNUM(q1res), 3);
5875         CU_ASSERT_EQUAL(count, 3);
5876     for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5877                 void *bsdata = TCLISTVALPTR(q1res, i);
5878         CU_ASSERT_PTR_NOT_NULL_FATAL(bsdata);
5879                 if (i == 0) {
5880                         CU_ASSERT_FALSE(bson_compare_long(1, bsdata, "arr.0"));
5881                         bson_iterator_from_buffer(&it, bsdata);
5882                         CU_ASSERT_TRUE(bson_find_fieldpath_value("arr.1", &it) == BSON_EOO);
5883                 } else if (i == 1) {
5884                         CU_ASSERT_FALSE(bson_compare_long(2, bsdata, "arr.0"));
5885                         bson_iterator_from_buffer(&it, bsdata);
5886                         CU_ASSERT_TRUE(bson_find_fieldpath_value("arr.1", &it) == BSON_EOO);
5887                 } else if (i == 2) {
5888                         CU_ASSERT_FALSE(bson_compare_long(2, bsdata, "arr.0.h"));
5889                         bson_iterator_from_buffer(&it, bsdata);
5890                         CU_ASSERT_TRUE(bson_find_fieldpath_value("arr.1", &it) == BSON_EOO);
5891                 }
5892     }
5893         tclistdel(q1res);
5894         bson_destroy(&bsq);
5895         ejdbquerydel(q1);
5896 }
5897
5898
5899 void testDistinct(void) {
5900     EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL);
5901     CU_ASSERT_PTR_NOT_NULL_FATAL(contacts);
5902
5903     uint32_t count;
5904     TCXSTR *log;
5905     bson *q1res; 
5906
5907     log = tcxstrnew();
5908     q1res = ejdbqrydistinct(contacts, "address", NULL, NULL, 0, &count, log);
5909
5910     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
5911     CU_ASSERT_EQUAL(count, 4);
5912     
5913     bson_del(q1res);
5914     
5915     bson bsq1;
5916     bson_init_as_query(&bsq1);
5917     bson_append_string(&bsq1, "address.street", "Pirogova");
5918     bson_finish(&bsq1);
5919     CU_ASSERT_FALSE_FATAL(bsq1.err);
5920
5921     q1res = ejdbqrydistinct(contacts, "address.room", &bsq1, NULL, 0, &count, log);
5922     
5923     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
5924     CU_ASSERT_EQUAL(count, 1);
5925     
5926     bson_del(q1res);
5927
5928     q1res = ejdbqrydistinct(contacts, "nonexisted", NULL, NULL, 0, &count, log);
5929     
5930     CU_ASSERT_PTR_NOT_NULL_FATAL(q1res);
5931     CU_ASSERT_EQUAL(count, 0);
5932     
5933     bson_del(q1res);
5934
5935     bson_destroy(&bsq1);
5936     tcxstrdel(log);
5937 }
5938
5939
5940 void testTicket117(void) {
5941         EJCOLL *coll = ejdbcreatecoll(jb, "ticket117", NULL);
5942         CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
5943         
5944         bson_oid_t oid;
5945         bson brec;
5946         
5947         bson_init(&brec);
5948     bson_append_string(&brec, "color", "Red");
5949     bson_finish(&brec);
5950     CU_ASSERT_FALSE_FATAL(brec.err);
5951     CU_ASSERT_TRUE_FATAL(ejdbsavebson(coll, &brec, &oid));
5952     bson_destroy(&brec);
5953         
5954         bson_init(&brec);
5955     bson_append_string(&brec, "color", "Green");
5956     bson_finish(&brec);
5957     CU_ASSERT_FALSE_FATAL(brec.err);
5958     CU_ASSERT_TRUE_FATAL(ejdbsavebson(coll, &brec, &oid));
5959     bson_destroy(&brec);
5960         
5961         CU_ASSERT_TRUE_FATAL(ejdbsetindex(coll, "color", JBIDXSTR));
5962         
5963         bson_init(&brec);
5964     bson_append_string(&brec, "color", "Blue");
5965     bson_finish(&brec);
5966     CU_ASSERT_FALSE_FATAL(brec.err);
5967     CU_ASSERT_TRUE_FATAL(ejdbsavebson(coll, &brec, &oid));
5968     bson_destroy(&brec);
5969         
5970         bson bsq;
5971     bson_init_as_query(&bsq);
5972         bson_append_string(&bsq, "color", "Blue");
5973         bson_finish(&bsq);
5974         CU_ASSERT_FALSE_FATAL(bsq.err);
5975         
5976         TCXSTR *log = tcxstrnew();
5977         uint32_t count = 0;
5978         EJQ *q1 = ejdbcreatequery(jb, &bsq, NULL, 0, NULL);
5979     bson_destroy(&bsq);
5980     CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
5981     TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
5982         CU_ASSERT_PTR_NOT_NULL(q1res);
5983     CU_ASSERT_EQUAL(TCLISTNUM(q1res), 1);
5984         
5985         for (int i = 0; i < TCLISTNUM(q1res); ++i) {
5986                 void *bsdata = TCLISTVALPTR(q1res, i);
5987         bson_print_raw(bsdata, 0);
5988     }
5989     //fprintf(stderr, "%s", TCXSTRPTR(log));
5990         CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'scolor'"));
5991         
5992         ejdbquerydel(q1);
5993         tclistdel(q1res);
5994         tcxstrdel(log);
5995 }
5996
5997
5998 int main() {
5999     setlocale(LC_ALL, "en_US.UTF-8");
6000     CU_pSuite pSuite = NULL;
6001
6002     /* Initialize the CUnit test registry */
6003     if (CUE_SUCCESS != CU_initialize_registry())
6004         return CU_get_error();
6005
6006     /* Add a suite to the registry */
6007     pSuite = CU_add_suite("ejdbtest2", init_suite, clean_suite);
6008     if (NULL == pSuite) {
6009         CU_cleanup_registry();
6010         return CU_get_error();
6011     }
6012
6013     /* Add the tests to the suite */
6014     if ((NULL == CU_add_test(pSuite, "testAddData", testAddData)) ||
6015             (NULL == CU_add_test(pSuite, "testInvalidQueries1", testInvalidQueries1)) ||
6016             (NULL == CU_add_test(pSuite, "testSetIndex1", testSetIndex1)) ||
6017             (NULL == CU_add_test(pSuite, "testQuery1", testQuery1)) ||
6018             (NULL == CU_add_test(pSuite, "testQuery2", testQuery2)) ||
6019             (NULL == CU_add_test(pSuite, "testQuery3", testQuery3)) ||
6020             (NULL == CU_add_test(pSuite, "testQuery4", testQuery4)) ||
6021             (NULL == CU_add_test(pSuite, "testQuery5", testQuery5)) ||
6022             (NULL == CU_add_test(pSuite, "testQuery6", testQuery6)) ||
6023             (NULL == CU_add_test(pSuite, "testQuery7", testQuery7)) ||
6024             (NULL == CU_add_test(pSuite, "testQuery8", testQuery8)) ||
6025             (NULL == CU_add_test(pSuite, "testQuery9", testQuery9)) ||
6026             (NULL == CU_add_test(pSuite, "testQuery10", testQuery10)) ||
6027             (NULL == CU_add_test(pSuite, "testQuery11", testQuery11)) ||
6028             (NULL == CU_add_test(pSuite, "testQuery12", testQuery12)) ||
6029             (NULL == CU_add_test(pSuite, "testQuery13", testQuery13)) ||
6030             (NULL == CU_add_test(pSuite, "testQuery14", testQuery14)) ||
6031             (NULL == CU_add_test(pSuite, "testQuery15", testQuery15)) ||
6032             (NULL == CU_add_test(pSuite, "testQuery16", testQuery16)) ||
6033             (NULL == CU_add_test(pSuite, "testQuery17", testQuery17)) ||
6034             (NULL == CU_add_test(pSuite, "testQuery18", testQuery18)) ||
6035             (NULL == CU_add_test(pSuite, "testQuery19", testQuery19)) ||
6036             (NULL == CU_add_test(pSuite, "testQuery20", testQuery20)) ||
6037             (NULL == CU_add_test(pSuite, "testQuery21", testQuery21)) ||
6038             (NULL == CU_add_test(pSuite, "testQuery22", testQuery22)) ||
6039             (NULL == CU_add_test(pSuite, "testQuery23", testQuery23)) ||
6040             (NULL == CU_add_test(pSuite, "testQuery24", testQuery24)) ||
6041             (NULL == CU_add_test(pSuite, "testQuery25", testQuery25)) ||
6042             (NULL == CU_add_test(pSuite, "testQuery25_2", testQuery25_2)) ||
6043             (NULL == CU_add_test(pSuite, "testQuery26", testQuery26)) ||
6044             (NULL == CU_add_test(pSuite, "testQuery27", testQuery27)) ||
6045                         (NULL == CU_add_test(pSuite, "testQuery28", testQuery28)) ||
6046                         (NULL == CU_add_test(pSuite, "testQuery29", testQuery29)) ||
6047                         (NULL == CU_add_test(pSuite, "testQuery30", testQuery30)) ||
6048                         (NULL == CU_add_test(pSuite, "testQuery31", testQuery31)) ||
6049             (NULL == CU_add_test(pSuite, "testOIDSMatching", testOIDSMatching)) ||
6050             (NULL == CU_add_test(pSuite, "testEmptyFieldIndex", testEmptyFieldIndex)) ||
6051             (NULL == CU_add_test(pSuite, "testICaseIndex", testICaseIndex)) ||
6052             (NULL == CU_add_test(pSuite, "testTicket7", testTicket7)) ||
6053             (NULL == CU_add_test(pSuite, "testTicket8", testTicket8)) ||
6054             (NULL == CU_add_test(pSuite, "testUpdate1", testUpdate1)) ||
6055             (NULL == CU_add_test(pSuite, "testUpdate2", testUpdate2)) ||
6056             (NULL == CU_add_test(pSuite, "testUpdate3", testUpdate3)) ||
6057             (NULL == CU_add_test(pSuite, "testQueryBool", testQueryBool)) ||
6058             (NULL == CU_add_test(pSuite, "testDropAll", testDropAll)) ||
6059             (NULL == CU_add_test(pSuite, "testTokensBegin", testTokensBegin)) ||
6060             (NULL == CU_add_test(pSuite, "testOneFieldManyConditions", testOneFieldManyConditions)) ||
6061             (NULL == CU_add_test(pSuite, "testAddToSet", testAddToSet)) ||
6062             (NULL == CU_add_test(pSuite, "testTicket123", testTicket123)) ||
6063             (NULL == CU_add_test(pSuite, "testPush", testPush)) ||
6064             (NULL == CU_add_test(pSuite, "testPushAll", testPushAll)) ||
6065             (NULL == CU_add_test(pSuite, "testRename2", testRename2)) ||
6066             (NULL == CU_add_test(pSuite, "testPull", testPull)) ||
6067             (NULL == CU_add_test(pSuite, "testFindInComplexArray", testFindInComplexArray)) ||
6068             (NULL == CU_add_test(pSuite, "testElemMatch", testElemMatch)) ||
6069             (NULL == CU_add_test(pSuite, "testNotElemMatch", testNotElemMatch)) ||
6070             (NULL == CU_add_test(pSuite, "testTicket16", testTicket16)) ||
6071             (NULL == CU_add_test(pSuite, "testUpsert", testUpsert)) ||
6072             (NULL == CU_add_test(pSuite, "testPrimitiveCases1", testPrimitiveCases1)) ||
6073             (NULL == CU_add_test(pSuite, "testTicket29", testTicket29)) ||
6074             (NULL == CU_add_test(pSuite, "testTicket28", testTicket28)) ||
6075             (NULL == CU_add_test(pSuite, "testTicket38", testTicket38)) ||
6076             (NULL == CU_add_test(pSuite, "testTicket43", testTicket43)) ||
6077             (NULL == CU_add_test(pSuite, "testTicket54", testTicket54)) ||
6078             (NULL == CU_add_test(pSuite, "testTicket88", testTicket88)) ||
6079             (NULL == CU_add_test(pSuite, "testTicket89", testTicket89)) ||
6080             (NULL == CU_add_test(pSuite, "testTicket81", testTicket81)) ||
6081             (NULL == CU_add_test(pSuite, "test$projection", testDQprojection)) ||
6082             (NULL == CU_add_test(pSuite, "test$update", testDQupdate)) ||
6083             (NULL == CU_add_test(pSuite, "test$update2", testDQupdate2)) ||
6084             (NULL == CU_add_test(pSuite, "testTicket96", testTicket96)) ||
6085             (NULL == CU_add_test(pSuite, "testTicket99", testTicket99)) ||
6086             (NULL == CU_add_test(pSuite, "testTicket101", testTicket101)) || 
6087             (NULL == CU_add_test(pSuite, "testTicket110", testTicket110)) ||
6088             (NULL == CU_add_test(pSuite, "testDistinct", testDistinct)) ||
6089                         (NULL == CU_add_test(pSuite, "testSlice", testSlice)) ||
6090                         (NULL == CU_add_test(pSuite, "testTicket117", testTicket117)) ||
6091             (NULL == CU_add_test(pSuite, "testMetaInfo", testMetaInfo))
6092     ) {
6093         CU_cleanup_registry();
6094         return CU_get_error();
6095     }
6096     /* Run all tests using the CUnit Basic interface */
6097     CU_basic_set_mode(CU_BRM_VERBOSE);
6098     CU_basic_run_tests();
6099     int ret = CU_get_error() || CU_get_number_of_failures();
6100     CU_cleanup_registry();
6101     return ret;
6102 }