1 #include "ejdb_test.h"
2 #include <CUnit/Basic.h>
3
init_suite()4 int init_suite() {
5 int rc = ejdb_init();
6 return rc;
7 }
8
clean_suite()9 int clean_suite() {
10 return 0;
11 }
12
ejdb_test3_1()13 static void ejdb_test3_1() {
14 EJDB_OPTS opts = {
15 .kv = {
16 .path = "ejdb_test3_1.db",
17 .oflags = IWKV_TRUNC
18 },
19 .no_wal = true
20 };
21
22 EJDB db;
23 char dbuf[1024];
24 EJDB_LIST list = 0;
25 IWXSTR *log = iwxstr_new();
26 CU_ASSERT_PTR_NOT_NULL_FATAL(log);
27 IWXSTR *xstr = iwxstr_new();
28 CU_ASSERT_PTR_NOT_NULL_FATAL(xstr);
29
30 iwrc rc = ejdb_open(&opts, &db);
31 CU_ASSERT_EQUAL_FATAL(rc, 0);
32
33 rc = ejdb_ensure_index(db, "c1", "/f/b", EJDB_IDX_UNIQUE | EJDB_IDX_I64);
34 CU_ASSERT_EQUAL_FATAL(rc, 0);
35
36 for (int i = 1; i <= 10; ++i) {
37 snprintf(dbuf, sizeof(dbuf), "{\"f\":{\"b\":%d},\"n\":%d}", i, i);
38 rc = put_json(db, "c1", dbuf);
39 CU_ASSERT_EQUAL_FATAL(rc, 0);
40 if (i == 1) { // Check unique index constraint violation
41 rc = put_json(db, "c1", dbuf);
42 CU_ASSERT_EQUAL(rc, EJDB_ERROR_UNIQUE_INDEX_CONSTRAINT_VIOLATED);
43 }
44 rc = put_json(db, "c2", dbuf);
45 CU_ASSERT_EQUAL_FATAL(rc, 0);
46 }
47
48 rc = ejdb_ensure_index(db, "c2", "/f/b", EJDB_IDX_UNIQUE | EJDB_IDX_I64);
49 CU_ASSERT_EQUAL_FATAL(rc, 0);
50
51 rc = ejdb_list3(db, "c1", "/f/[b = 1]", 0, log, &list);
52 CU_ASSERT_EQUAL_FATAL(rc, 0);
53
54 CU_ASSERT_PTR_NOT_NULL_FATAL(strstr(iwxstr_ptr(log), "[INDEX] MATCHED UNIQUE|I64|10 /f/b EXPR1: 'b = 1' "
55 "INIT: IWKV_CURSOR_EQ"));
56 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[INDEX] SELECTED UNIQUE|I64|10 /f/b EXPR1: 'b = 1' "
57 "INIT: IWKV_CURSOR_EQ"));
58 int i = 0;
59 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
60 iwxstr_clear(xstr);
61 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
62 CU_ASSERT_EQUAL_FATAL(rc, 0);
63 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":1},\"n\":1}");
64 }
65 ejdb_list_destroy(&list);
66 iwxstr_clear(log);
67
68 // Q: /f/[b > 1]
69 rc = ejdb_list3(db, "c1", "/f/[b > 1]", 0, log, &list);
70 //if (rc) iwlog_ecode_error3(rc);
71 CU_ASSERT_EQUAL_FATAL(rc, 0);
72 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "MATCHED UNIQUE|I64|10 /f/b EXPR1: 'b > 1' "
73 "INIT: IWKV_CURSOR_GE"));
74 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "SELECTED UNIQUE|I64|10 /f/b EXPR1: 'b > 1' "
75 "INIT: IWKV_CURSOR_GE"));
76
77 i = 0;
78 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
79 iwxstr_clear(xstr);
80 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
81 CU_ASSERT_EQUAL_FATAL(rc, 0);
82 if (i == 0) {
83 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":2},\"n\":2}");
84 } else if (i == 8) {
85 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":10},\"n\":10}");
86 }
87 }
88 CU_ASSERT_EQUAL(i, 9);
89 ejdb_list_destroy(&list);
90 iwxstr_clear(log);
91
92 // Q: /f/[b >= 2]
93 rc = ejdb_list3(db, "c1", "/f/[b >= 3]", 0, log, &list);
94 CU_ASSERT_EQUAL_FATAL(rc, 0);
95 i = 0;
96 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
97 iwxstr_clear(xstr);
98 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
99 CU_ASSERT_EQUAL_FATAL(rc, 0);
100 if (i == 0) {
101 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":3},\"n\":3}");
102 } else if (i == 8) {
103 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":10},\"n\":10}");
104 }
105 }
106 CU_ASSERT_EQUAL(i, 8);
107 ejdb_list_destroy(&list);
108 iwxstr_clear(log);
109
110 // Q: /f/[b < 9]
111 rc = ejdb_list3(db, "c1", "/f/[b < 9]", 0, log, &list);
112 CU_ASSERT_EQUAL_FATAL(rc, 0);
113 i = 0;
114 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
115 iwxstr_clear(xstr);
116 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
117 CU_ASSERT_EQUAL_FATAL(rc, 0);
118 if (i == 0) {
119 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":8},\"n\":8}");
120 } else if (i == 7) {
121 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":1},\"n\":1}");
122 }
123 }
124 CU_ASSERT_EQUAL(i, 8);
125 ejdb_list_destroy(&list);
126
127 // Q: /f/[b < 11]
128 rc = ejdb_list3(db, "c1", "/f/[b < 11]", 0, log, &list);
129 CU_ASSERT_EQUAL_FATAL(rc, 0);
130 i = 0;
131 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
132 iwxstr_clear(xstr);
133 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
134 CU_ASSERT_EQUAL_FATAL(rc, 0);
135 if (i == 0) {
136 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":10},\"n\":10}");
137 } else if (i == 9) {
138 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":1},\"n\":1}");
139 }
140 }
141 ejdb_list_destroy(&list);
142 iwxstr_clear(log);
143
144 // Q: /f/[b < 11 and b >= 4]
145 rc = ejdb_list3(db, "c1", "/f/[b < 11 and b >= 4]", 0, log, &list);
146 CU_ASSERT_EQUAL_FATAL(rc, 0);
147 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[INDEX] SELECTED UNIQUE|I64|10 /f/b EXPR1: 'b >= 4' EXPR2: 'b < 11' "
148 "INIT: IWKV_CURSOR_GE"));
149 i = 0;
150 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
151 iwxstr_clear(xstr);
152 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
153 CU_ASSERT_EQUAL_FATAL(rc, 0);
154 if (i == 0) {
155 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":4},\"n\":4}");
156 } else if (i == 6) {
157 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":10},\"n\":10}");
158 }
159 }
160 ejdb_list_destroy(&list);
161 iwxstr_clear(log);
162
163 // Q: /f/[b < 11 and b > 0 or b = 0]
164 rc = ejdb_list3(db, "c1", "/f/[b < 11 and b > 0 or b = 0]", 0, log, &list);
165 CU_ASSERT_EQUAL_FATAL(rc, 0);
166 ejdb_list_destroy(&list);
167 iwxstr_clear(log);
168
169 // Q: /f/[b > 1 and b < 2 and b = 2 and b < 3]
170 rc = ejdb_list3(db, "c1", "/f/[b > 1 and b < 2 and b = 2 and b < 3]", 0, log, &list);
171 CU_ASSERT_EQUAL_FATAL(rc, 0);
172 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log),
173 "[INDEX] SELECTED UNIQUE|I64|10 /f/b EXPR1: 'b = 2' "
174 "INIT: IWKV_CURSOR_EQ"));
175 ejdb_list_destroy(&list);
176 iwxstr_clear(log);
177
178 // Q: /f/[b > 1 and b < 3 and b <= 4]
179 rc = ejdb_list3(db, "c1", "/f/[b > 1 and b < 3 and b <= 4]", 0, log, &list);
180 CU_ASSERT_EQUAL_FATAL(rc, 0);
181 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log),
182 "[INDEX] SELECTED UNIQUE|I64|10 /f/b EXPR1: 'b > 1' EXPR2: 'b < 3' "
183 "INIT: IWKV_CURSOR_GE"));
184 i = 0;
185 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
186 iwxstr_clear(xstr);
187 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
188 CU_ASSERT_EQUAL_FATAL(rc, 0);
189 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":2},\"n\":2}");
190 }
191 CU_ASSERT_EQUAL(i, 1);
192 ejdb_list_destroy(&list);
193 iwxstr_clear(log);
194
195 // Q: /f/[b > 1] and /f/[b < 3]
196 rc = ejdb_list3(db, "c1", "/f/[b > 1] and /f/[b < 3]", 0, log, &list);
197 CU_ASSERT_EQUAL_FATAL(rc, 0);
198 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log),
199 "[INDEX] MATCHED UNIQUE|I64|10 /f/b EXPR1: 'b > 1' INIT: IWKV_CURSOR_GE"));
200 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log),
201 "[INDEX] MATCHED UNIQUE|I64|10 /f/b EXPR1: 'b < 3' INIT: IWKV_CURSOR_GE"));
202 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log),
203 "[INDEX] SELECTED UNIQUE|I64|10 /f/b EXPR1: 'b > 1' INIT: IWKV_CURSOR_GE"));
204 ejdb_list_destroy(&list);
205 iwxstr_clear(log);
206
207 // Q: /f/[b > 1 or b != 1] and /f/[b < 3]
208 rc = ejdb_list3(db, "c1", "/f/[b > 1 or b != 1] and /f/[b < 3]", 0, log, &list);
209 CU_ASSERT_EQUAL_FATAL(rc, 0);
210 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log),
211 "[INDEX] SELECTED UNIQUE|I64|10 /f/b EXPR1: 'b < 3' "
212 "INIT: IWKV_CURSOR_GE"));
213 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[COLLECTOR] PLAIN"));
214 i = 0;
215 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
216 iwxstr_clear(xstr);
217 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
218 CU_ASSERT_EQUAL_FATAL(rc, 0);
219 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":2},\"n\":2}");
220 }
221 ejdb_list_destroy(&list);
222 iwxstr_clear(log);
223
224 // Q: /f/[b in [2,1112,4,6]]
225 rc = ejdb_list3(db, "c1", "/f/[b in [2,1112,4,6]]", 0, log, &list);
226 CU_ASSERT_EQUAL_FATAL(rc, 0);
227 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log),
228 "[INDEX] SELECTED UNIQUE|I64|10 /f/b EXPR1: 'b in [2,1112,4,6]' "
229 "INIT: IWKV_CURSOR_EQ"));
230 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[COLLECTOR] PLAIN"));
231 i = 0;
232 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
233 iwxstr_clear(xstr);
234 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
235 CU_ASSERT_EQUAL_FATAL(rc, 0);
236 if (i == 0) {
237 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":2},\"n\":2}");
238 } else if (i == 1) {
239 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":4},\"n\":4}");
240 } else if (i == 2) {
241 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":6},\"n\":6}");
242 }
243 }
244 CU_ASSERT_EQUAL(i, 3);
245 ejdb_list_destroy(&list);
246 iwxstr_clear(log);
247
248 // Q: /f/[b > 1] | asc /f/b
249 rc = ejdb_list3(db, "c1", "/f/[b > 1] | asc /f/b", 0, log, &list);
250 CU_ASSERT_EQUAL_FATAL(rc, 0);
251 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log),
252 "[INDEX] SELECTED UNIQUE|I64|10 /f/b EXPR1: 'b > 1' "
253 "INIT: IWKV_CURSOR_GE STEP: IWKV_CURSOR_PREV ORDERBY"));
254 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[COLLECTOR] PLAIN"));
255 i = 0;
256 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
257 iwxstr_clear(xstr);
258 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
259 CU_ASSERT_EQUAL_FATAL(rc, 0);
260 if (i == 0) {
261 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":2},\"n\":2}");
262 } else if (i == 8) {
263 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":10},\"n\":10}");
264 }
265 }
266 CU_ASSERT_EQUAL(i, 9);
267 ejdb_list_destroy(&list);
268 iwxstr_clear(log);
269
270 // Q: /f/[b > 1] | desc /f/b
271 rc = ejdb_list3(db, "c1", "/f/[b > 1] | desc /f/b", 0, log, &list);
272 CU_ASSERT_EQUAL_FATAL(rc, 0);
273 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log),
274 "[INDEX] SELECTED UNIQUE|I64|10 /f/b EXPR1: 'b > 1' "
275 "INIT: IWKV_CURSOR_GE"));
276 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[COLLECTOR] SORTER"));
277 i = 0;
278 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
279 iwxstr_clear(xstr);
280 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
281 CU_ASSERT_EQUAL_FATAL(rc, 0);
282 if (i == 0) {
283 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":10},\"n\":10}");
284 } else if (i == 8) {
285 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":2},\"n\":2}");
286 }
287 }
288 CU_ASSERT_EQUAL(i, 9);
289 ejdb_list_destroy(&list);
290 iwxstr_clear(log);
291
292 // Q: /f/[b > 2 and b < 10] | asc /f/b
293 rc = ejdb_list3(db, "c1", "/f/[b > 2 and b < 10] | asc /f/b", 0, log, &list);
294 CU_ASSERT_EQUAL_FATAL(rc, 0);
295 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log),
296 "[INDEX] SELECTED UNIQUE|I64|10 /f/b EXPR1: 'b > 2' EXPR2: 'b < 10' "
297 "INIT: IWKV_CURSOR_GE STEP: IWKV_CURSOR_PREV ORDERBY"));
298 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[COLLECTOR] PLAIN"));
299 i = 0;
300 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
301 iwxstr_clear(xstr);
302 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
303 CU_ASSERT_EQUAL_FATAL(rc, 0);
304 if (i == 0) {
305 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":3},\"n\":3}");
306 } else if (i == 6) {
307 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":9},\"n\":9}");
308 }
309 }
310 CU_ASSERT_EQUAL(i, 7);
311 ejdb_list_destroy(&list);
312 iwxstr_clear(log);
313
314 // Q: /f/[b > 2 and b < 10] | desc /f/b
315 rc = ejdb_list3(db, "c1", "/f/[b > 2 and b < 10] | desc /f/b", 0, log, &list);
316 CU_ASSERT_EQUAL_FATAL(rc, 0);
317 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[INDEX] SELECTED UNIQUE|I64|10 /f/b EXPR1: 'b < 10' EXPR2: 'b > 2' "
318 "INIT: IWKV_CURSOR_GE STEP: IWKV_CURSOR_NEXT ORDERBY"));
319 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[COLLECTOR] PLAIN"));
320 i = 0;
321 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
322 iwxstr_clear(xstr);
323 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
324 CU_ASSERT_EQUAL_FATAL(rc, 0);
325 if (i == 0) {
326 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":9},\"n\":9}");
327 } else if (i == 6) {
328 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":3},\"n\":3}");
329 }
330 }
331 CU_ASSERT_EQUAL(i, 7);
332 ejdb_list_destroy(&list);
333 iwxstr_clear(log);
334
335 rc = ejdb_close(&db);
336 CU_ASSERT_EQUAL_FATAL(rc, 0);
337 iwxstr_destroy(log);
338 iwxstr_destroy(xstr);
339 }
340
ejdb_test3_2()341 static void ejdb_test3_2() {
342 EJDB_OPTS opts = {
343 .kv = {
344 .path = "ejdb_test3_2.db",
345 .oflags = IWKV_TRUNC
346 },
347 .no_wal = true
348 };
349
350 EJDB db;
351 char dbuf[1024];
352 EJDB_LIST list = 0;
353 int i = 0;
354 IWXSTR *log = iwxstr_new();
355 CU_ASSERT_PTR_NOT_NULL_FATAL(log);
356 IWXSTR *xstr = iwxstr_new();
357 CU_ASSERT_PTR_NOT_NULL_FATAL(xstr);
358
359 iwrc rc = ejdb_open(&opts, &db);
360 CU_ASSERT_EQUAL_FATAL(rc, 0);
361
362 rc = ejdb_ensure_index(db, "a1", "/f/b", EJDB_IDX_I64);
363 CU_ASSERT_EQUAL_FATAL(rc, 0);
364
365 // Data:
366 //
367 // {"f":{"b":16777215},"n":9}
368 // {"f":{"b":16777215},"n":7}
369 // {"f":{"b":16777215},"n":5}
370 // {"f":{"b":16777215},"n":3}
371 // {"f":{"b":16777215},"n":1}
372 // {"f":{"b":127},"n":10}
373 // {"f":{"b":127},"n":8}
374 // {"f":{"b":127},"n":6}
375 // {"f":{"b":127},"n":4}
376 // {"f":{"b":127},"n":2}
377 // {"f":{"b":126},"n":12}
378 // {"f":{"b":126},"n":11}
379 //
380
381 for (i = 1; i <= 10; ++i) {
382 int v = (i % 2) ? 0xffffff : 127;
383 //fprintf(stderr, "\n{\"f\":{\"b\":%d},\"n\":%d}", v, i);
384 snprintf(dbuf, sizeof(dbuf), "{\"f\":{\"b\":%d},\"n\":%d}", v, i);
385 rc = put_json(db, "a1", dbuf);
386 CU_ASSERT_EQUAL_FATAL(rc, 0);
387 }
388 snprintf(dbuf, sizeof(dbuf), "{\"f\":{\"b\":%d},\"n\":%d}", 126, 11);
389 rc = put_json(db, "a1", dbuf);
390 CU_ASSERT_EQUAL_FATAL(rc, 0);
391 snprintf(dbuf, sizeof(dbuf), "{\"f\":{\"b\":%d},\"n\":%d}", 126, 12);
392 rc = put_json(db, "a1", dbuf);
393 CU_ASSERT_EQUAL_FATAL(rc, 0);
394
395 // GT
396 rc = ejdb_list3(db, "a1", "/f/[b > 127]", 0, log, &list);
397 CU_ASSERT_EQUAL_FATAL(rc, 0);
398
399 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[INDEX] SELECTED I64|12 /f/b EXPR1: 'b > 127' "
400 "INIT: IWKV_CURSOR_GE STEP: IWKV_CURSOR_PREV"));
401
402 i = 1;
403 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
404 iwxstr_clear(xstr);
405 if (i == 1) {
406 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
407 CU_ASSERT_EQUAL_FATAL(rc, 0);
408 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":16777215},\"n\":1}");
409 } else if (i == 9) {
410 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
411 CU_ASSERT_EQUAL_FATAL(rc, 0);
412 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":16777215},\"n\":9}");
413 }
414 }
415 CU_ASSERT_EQUAL(i, 6);
416 ejdb_list_destroy(&list);
417 iwxstr_clear(log);
418
419 // LT
420 rc = ejdb_list3(db, "a1", "/f/[b < 127]", 0, log, &list);
421 CU_ASSERT_EQUAL_FATAL(rc, 0);
422 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "SELECTED I64|12 /f/b EXPR1: 'b < 127' "
423 "INIT: IWKV_CURSOR_GE STEP: IWKV_CURSOR_NEXT"));
424
425 i = 1;
426 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
427 iwxstr_clear(xstr);
428 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
429 CU_ASSERT_EQUAL_FATAL(rc, 0);
430 if (i == 1) {
431 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":126},\"n\":12}");
432 } else if (i == 2) {
433 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":126},\"n\":11}");
434 }
435 }
436 CU_ASSERT_EQUAL(i, 3);
437 ejdb_list_destroy(&list);
438 iwxstr_clear(log);
439
440 // LT2
441 rc = ejdb_list3(db, "a1", "/f/[b < 16777216]", 0, log, &list);
442 CU_ASSERT_EQUAL_FATAL(rc, 0);
443 i = 1;
444 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
445 iwxstr_clear(xstr);
446 if (i == 1) {
447 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
448 CU_ASSERT_EQUAL_FATAL(rc, 0);
449 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":16777215},\"n\":9}");
450 } else if (i == 12) {
451 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
452 CU_ASSERT_EQUAL_FATAL(rc, 0);
453 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":126},\"n\":11}");
454 }
455 }
456 CU_ASSERT_EQUAL(i, 13);
457 ejdb_list_destroy(&list);
458 iwxstr_clear(log);
459
460 // EQ
461 rc = ejdb_list3(db, "a1", "/f/[b = 127]", 0, log, &list);
462 CU_ASSERT_EQUAL_FATAL(rc, 0);
463 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "SELECTED I64|12 /f/b EXPR1: 'b = 127' "
464 "INIT: IWKV_CURSOR_EQ"));
465
466 i = 1;
467 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
468 iwxstr_clear(xstr);
469 if (i == 1) {
470 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
471 CU_ASSERT_EQUAL_FATAL(rc, 0);
472 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":127},\"n\":2}");
473 } else if (i == 5) {
474 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
475 CU_ASSERT_EQUAL_FATAL(rc, 0);
476 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":127},\"n\":10}");
477 }
478 }
479 CU_ASSERT_EQUAL(i, 6);
480 ejdb_list_destroy(&list);
481 iwxstr_clear(log);
482
483 // IN
484 rc = ejdb_list3(db, "a1", "/f/[b in [333, 16777215, 127, 16777216]]", 0, log, &list);
485 CU_ASSERT_EQUAL_FATAL(rc, 0);
486 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[INDEX] SELECTED I64|12 /f/b "
487 "EXPR1: 'b in [333,16777215,127,16777216]' "
488 "INIT: IWKV_CURSOR_EQ"));
489 i = 1;
490 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
491 iwxstr_clear(xstr);
492 if (i == 1) {
493 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
494 CU_ASSERT_EQUAL_FATAL(rc, 0);
495 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":127},\"n\":2}");
496 } else if (i == 5) {
497 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
498 CU_ASSERT_EQUAL_FATAL(rc, 0);
499 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":127},\"n\":10}");
500 } else if (i == 6) {
501 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
502 CU_ASSERT_EQUAL_FATAL(rc, 0);
503 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":16777215},\"n\":1}");
504 } else if (i == 10) {
505 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
506 CU_ASSERT_EQUAL_FATAL(rc, 0);
507 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":16777215},\"n\":9}");
508 }
509 }
510 CU_ASSERT_EQUAL(i, 11);
511
512 ejdb_list_destroy(&list);
513 iwxstr_clear(log);
514
515 rc = ejdb_close(&db);
516 CU_ASSERT_EQUAL_FATAL(rc, 0);
517 iwxstr_destroy(log);
518 iwxstr_destroy(xstr);
519 }
520
ejdb_test3_3()521 static void ejdb_test3_3() {
522 EJDB_OPTS opts = {
523 .kv = {
524 .path = "ejdb_test3_3.db",
525 .oflags = IWKV_TRUNC
526 },
527 .no_wal = true
528 };
529 EJDB db;
530 char dbuf[1024];
531
532 int i = 0;
533 EJDB_LIST list = 0;
534 IWXSTR *log = iwxstr_new();
535 CU_ASSERT_PTR_NOT_NULL_FATAL(log);
536 IWXSTR *xstr = iwxstr_new();
537 CU_ASSERT_PTR_NOT_NULL_FATAL(xstr);
538
539 iwrc rc = ejdb_open(&opts, &db);
540 CU_ASSERT_EQUAL_FATAL(rc, 0);
541
542 rc = ejdb_ensure_index(db, "a2", "/f/b", EJDB_IDX_STR);
543 CU_ASSERT_EQUAL_FATAL(rc, 0);
544
545 char *data[] = {
546
547 // len: 200
548 "Ar4prlJssa2ckf0IpmDuRBZ2b0Q6PtPdTacjWFFuO23CiCjdyfHaliz9JaqK1HFEeaneiMO"
549 "7sNh87oDLVkvz7TnOV22v0njqmmd6b8DSfzaCwxFxcqrF7MinjUvJvct1Fr07MJWeG7C6SP"
550 "MlUjFQ4jNlds3kUQDP9yxQImH7BkmCqBCisIoh5zar8zSax1Pk7nZSpm1b",
551
552 // len: 115
553 "BkMSITU2qJ56xeX3nftUd3g4PuZwo9LY2mTGFtYKrrqhilPiR0UTHrDobstoShELlMHvPx61"
554 "KF8qQRPAn4OOUttNtkPE95XsjZQ8PPZW9ruWo1R9UMx",
555
556 // len: 64
557 "C1257xkZuJqXhQ5v5eWG8TlwKdCY77DQ0ScLyC3nGDTtC3A8DPDAiVC09EBFTUxp",
558
559 // len: 800
560 "D9z1bYv2oEp8n8B0BtY1VI4ezy8adAnPvqno9rdxM7RsMZDcLQyCEJ3vDMFqoJaRNbCtdbHh09"
561 "L0UijAR6wmQ87P90eAGKaEvuhoRzhoDZYpa37o7HZrBctcCxGHSrQMR0o1NKOz2vmEvhX6k02M"
562 "QopatRrL6jIkr9XXKgekOh6xcVyvUcnr6ttD3tqF0v0QN3ZPnXRCcVYyx0Ot9T6EfZik7HO3QW"
563 "jyblg4f4qqohprmGWKO8UfIIsF1gRPPacPc8oJXEFrbJu5NR4LidKpn6ygmTpstGVCanpCq2Yi"
564 "pkWrQpC1LkdSh3h2hNMUZbgZDgsvGzocuBuGgnyDd6I91PJjBmbFTXmILkT9t0ApvCGJTrc9aB"
565 "Sw5I9CAZRFRqVnRFUr7fA0OfQhN2zCu4d5m1XQg3yh9We4GI1ffhWsbnH4g59HbuAkm9jmz4mp"
566 "B6IJUSewlgq6YDgfsPNQXHboBVWAuR9NONIpfpmnU4wjuwI3j3QJAbi81u23QXAWJETvVBRqqU"
567 "ZqtqUjwnOCoPvkRV3WhfEHezmN9HTuxxl75WowRXyz8nwUe3xOXadmQwkhyYbWSSrO835XziTj"
568 "58e00zGi6eLwXD7xrKC7YeEb7HE4L8eKeEFiM1xC00ySIDkBNoclMxmExPg6kBUpiUT7HAEfaN"
569 "AN2VbdWFZsumDQHu3Q5XwrGdiQ6ubLTMuQEIv1IPTZIRTV5TQ59aUdiM6POdLFv9xuDjEgnBYd"
570 "MxcP60sNDIakuW2IeabKScwF5yx9PAg7D9K5WVWhpSQuzDFiTSSJPwkQfoWo"
571 };
572
573 snprintf(dbuf, sizeof(dbuf), "{\"f\":{\"b\":\"%s\"},\"n\":%d}", data[0], 1);
574 rc = put_json(db, "a2", dbuf);
575 CU_ASSERT_EQUAL_FATAL(rc, 0);
576
577 snprintf(dbuf, sizeof(dbuf), "{\"f\":{\"b\":\"%s\"},\"n\":%d}", data[1], 2);
578 rc = put_json(db, "a2", dbuf);
579 CU_ASSERT_EQUAL_FATAL(rc, 0);
580
581 snprintf(dbuf, sizeof(dbuf), "{\"f\":{\"b\":\"%s\"},\"n\":%" PRId64 "}", data[1], INT64_MAX - 1);
582 rc = put_json(db, "a2", dbuf);
583 CU_ASSERT_EQUAL_FATAL(rc, 0);
584
585 snprintf(dbuf, sizeof(dbuf), "{\"f\":{\"b\":\"%s\"},\"n\":%d}", data[2], 3);
586 rc = put_json(db, "a2", dbuf);
587 CU_ASSERT_EQUAL_FATAL(rc, 0);
588
589 snprintf(dbuf, sizeof(dbuf), "{\"f\":{\"b\":\"%s\"},\"n\":%d}", data[2], 4);
590 rc = put_json(db, "a2", dbuf);
591 CU_ASSERT_EQUAL_FATAL(rc, 0);
592
593
594 snprintf(dbuf, sizeof(dbuf), "{\"f\":{\"b\":\"%s\"},\"n\":%d}", data[3], 5);
595 rc = put_json(db, "a2", dbuf);
596 CU_ASSERT_EQUAL_FATAL(rc, 0);
597
598 // Q: /f/[b >= data[0]]
599 JQL q;
600 rc = jql_create(&q, "a2", "/f/[b >= :?]");
601 CU_ASSERT_EQUAL_FATAL(rc, 0);
602
603 rc = jql_set_str(q, 0, 0, data[0]);
604 CU_ASSERT_EQUAL_FATAL(rc, 0);
605
606 rc = ejdb_list4(db, q, 0, log, &list);
607 CU_ASSERT_EQUAL_FATAL(rc, 0);
608 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[INDEX] SELECTED STR|6 /f/b EXPR1: 'b >= :?' "
609 "INIT: IWKV_CURSOR_GE STEP: IWKV_CURSOR_PREV"));
610 i = 1;
611 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
612 JBL jbl1, jbl2;
613 rc = jbl_at(doc->raw, "/f/b", &jbl1);
614 CU_ASSERT_EQUAL_FATAL(rc, 0);
615 rc = jbl_at(doc->raw, "/n", &jbl2);
616 CU_ASSERT_EQUAL_FATAL(rc, 0);
617 int64_t llv = jbl_get_i64(jbl2);
618 const char *str = jbl_get_str(jbl1);
619 switch (i) {
620 case 1:
621 CU_ASSERT_EQUAL(llv, 1);
622 CU_ASSERT_STRING_EQUAL(str, data[0]);
623 break;
624 case 2:
625 CU_ASSERT_EQUAL(llv, 2);
626 CU_ASSERT_STRING_EQUAL(str, data[1]);
627 break;
628 case 3:
629 CU_ASSERT_EQUAL(llv, INT64_MAX - 1);
630 CU_ASSERT_STRING_EQUAL(str, data[1]);
631 break;
632 case 4:
633 CU_ASSERT_EQUAL(llv, 3);
634 CU_ASSERT_STRING_EQUAL(str, data[2]);
635 break;
636 case 5:
637 CU_ASSERT_EQUAL(llv, 4);
638 CU_ASSERT_STRING_EQUAL(str, data[2]);
639 break;
640 case 6:
641 CU_ASSERT_EQUAL(llv, 5);
642 CU_ASSERT_STRING_EQUAL(str, data[3]);
643 break;
644 }
645 jbl_destroy(&jbl1);
646 jbl_destroy(&jbl2);
647 }
648 CU_ASSERT_EQUAL(i, 7);
649
650 ejdb_list_destroy(&list);
651 iwxstr_clear(log);
652
653 // Q: /f/[b >= data[3]]
654 rc = jql_set_str(q, 0, 0, data[3]);
655 CU_ASSERT_EQUAL_FATAL(rc, 0);
656
657 rc = ejdb_list4(db, q, 0, log, &list);
658 CU_ASSERT_EQUAL_FATAL(rc, 0);
659 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[INDEX] SELECTED STR|6 /f/b EXPR1: 'b >= :?' "
660 "INIT: IWKV_CURSOR_GE STEP: IWKV_CURSOR_PREV"));
661
662 i = 1;
663 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
664 JBL jbl1, jbl2;
665 rc = jbl_at(doc->raw, "/f/b", &jbl1);
666 CU_ASSERT_EQUAL_FATAL(rc, 0);
667 rc = jbl_at(doc->raw, "/n", &jbl2);
668 CU_ASSERT_EQUAL_FATAL(rc, 0);
669 int64_t llv = jbl_get_i64(jbl2);
670 const char *str = jbl_get_str(jbl1);
671 CU_ASSERT_EQUAL(llv, 5);
672 CU_ASSERT_STRING_EQUAL(str, data[3]);
673 jbl_destroy(&jbl1);
674 jbl_destroy(&jbl2);
675 }
676 CU_ASSERT_EQUAL(i, 2);
677
678 // todo: record update
679 // todo: record removal
680
681 ejdb_list_destroy(&list);
682 iwxstr_clear(log);
683 jql_destroy(&q);
684
685 rc = ejdb_close(&db);
686 CU_ASSERT_EQUAL_FATAL(rc, 0);
687 iwxstr_destroy(log);
688 iwxstr_destroy(xstr);
689 }
690
691 // Test array index
ejdb_test3_4()692 static void ejdb_test3_4() {
693 EJDB_OPTS opts = {
694 .kv = {
695 .path = "ejdb_test3_4.db",
696 .oflags = IWKV_TRUNC
697 },
698 .no_wal = true
699 };
700 EJDB db;
701 char dbuf[1024];
702
703 int i = 0;
704 EJDB_LIST list = 0;
705 int64_t docId = 0;
706
707 IWPOOL *pool = iwpool_create(1024);
708 CU_ASSERT_PTR_NOT_NULL_FATAL(pool);
709 IWXSTR *log = iwxstr_new();
710 CU_ASSERT_PTR_NOT_NULL_FATAL(log);
711 IWXSTR *xstr = iwxstr_new();
712 CU_ASSERT_PTR_NOT_NULL_FATAL(xstr);
713
714 iwrc rc = ejdb_open(&opts, &db);
715 CU_ASSERT_EQUAL_FATAL(rc, 0);
716
717 rc = ejdb_ensure_index(db, "a3", "/tags", EJDB_IDX_STR);
718 CU_ASSERT_EQUAL_FATAL(rc, 0);
719
720 snprintf(dbuf, sizeof(dbuf), "{\"tags\": [\"foo\", \"bar\", \"gaz\"],\"n\":%d}", 1);
721 rc = put_json(db, "a3", dbuf);
722 CU_ASSERT_EQUAL_FATAL(rc, 0);
723
724 snprintf(dbuf, sizeof(dbuf), "{\"tags\": [\"gaz\", \"zaz\"],\"n\":%d}", 2);
725 rc = put_json2(db, "a3", dbuf, &docId);
726 CU_ASSERT_EQUAL_FATAL(rc, 0);
727
728 JQL q;
729 rc = jql_create(&q, "a3", "/tags/[** in :tags]");
730 CU_ASSERT_EQUAL_FATAL(rc, 0);
731
732 // Q:
733 JBL_NODE qtags;
734 rc = jbn_from_json("[\"zaz\",\"gaz\"]", &qtags, pool);
735 CU_ASSERT_EQUAL_FATAL(rc, 0);
736
737 rc = jql_set_json(q, "tags", 0, qtags);
738 CU_ASSERT_EQUAL_FATAL(rc, 0);
739
740 rc = ejdb_list4(db, q, 0, log, &list);
741 CU_ASSERT_EQUAL_FATAL(rc, 0);
742
743 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log),
744 "[INDEX] SELECTED STR|5 /tags EXPR1: '** in :tags' "
745 "INIT: IWKV_CURSOR_EQ"));
746 i = 1;
747 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
748 iwxstr_clear(xstr);
749 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
750 CU_ASSERT_EQUAL_FATAL(rc, 0);
751 if (i == 1) {
752 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"tags\":[\"foo\",\"bar\",\"gaz\"],\"n\":1}");
753 } else if ((i == 2) || (i == 3)) {
754 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"tags\":[\"gaz\",\"zaz\"],\"n\":2}");
755 }
756 }
757 CU_ASSERT_EQUAL(i, 4);
758 ejdb_list_destroy(&list);
759 iwxstr_clear(log);
760
761
762 // Get
763 CU_ASSERT_TRUE(docId > 0);
764 JBL jbl;
765 rc = ejdb_get(db, "a3", docId, &jbl);
766 CU_ASSERT_EQUAL_FATAL(rc, 0);
767 iwxstr_clear(xstr);
768 rc = jbl_as_json(jbl, jbl_xstr_json_printer, xstr, 0);
769 CU_ASSERT_EQUAL_FATAL(rc, 0);
770 jbl_destroy(&jbl);
771 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"tags\":[\"gaz\",\"zaz\"],\"n\":2}");
772 rc = put_json2(db, "a3", "{\"tags\": [\"gaz\",\"zaz\"],\"n\":2}", &docId);
773 CU_ASSERT_EQUAL_FATAL(rc, 0);
774
775 // Update {"tags":["gaz","zaz", "boo"], "n":2}
776 rc = put_json2(db, "a3", "{\"tags\": [\"gaz\",\"zaz\",\"boo\"],\"n\":2}", &docId);
777 CU_ASSERT_EQUAL_FATAL(rc, 0);
778
779 // Q:
780 rc = jbn_from_json("[\"zaz\",\"boo\"]", &qtags, pool);
781 CU_ASSERT_EQUAL_FATAL(rc, 0);
782 rc = jql_set_json(q, "tags", 0, qtags);
783 CU_ASSERT_EQUAL_FATAL(rc, 0);
784
785 rc = ejdb_list4(db, q, 0, log, &list);
786 CU_ASSERT_EQUAL_FATAL(rc, 0);
787 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log),
788 "[INDEX] SELECTED STR|6 /tags EXPR1: '** in :tags' "
789 "INIT: IWKV_CURSOR_EQ"));
790 i = 1;
791 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
792 iwxstr_clear(xstr);
793 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
794 CU_ASSERT_EQUAL_FATAL(rc, 0);
795 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"tags\":[\"gaz\",\"zaz\",\"boo\"],\"n\":2}");
796 }
797 CU_ASSERT_EQUAL(i, 3);
798 ejdb_list_destroy(&list);
799 iwxstr_clear(log);
800
801 // Remove last
802 rc = ejdb_del(db, "a3", docId);
803 CU_ASSERT_EQUAL_FATAL(rc, 0);
804
805 // G2
806 rc = jbn_from_json("[\"gaz\"]", &qtags, pool);
807 CU_ASSERT_EQUAL_FATAL(rc, 0);
808 rc = jql_set_json(q, "tags", 0, qtags);
809 CU_ASSERT_EQUAL_FATAL(rc, 0);
810
811 rc = ejdb_list4(db, q, 0, log, &list);
812 CU_ASSERT_EQUAL_FATAL(rc, 0);
813 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log),
814 "[INDEX] SELECTED STR|3 /tags EXPR1: '** in :tags' "
815 "INIT: IWKV_CURSOR_EQ"));
816 i = 1;
817 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
818 iwxstr_clear(xstr);
819 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
820 CU_ASSERT_EQUAL_FATAL(rc, 0);
821 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"tags\":[\"foo\",\"bar\",\"gaz\"],\"n\":1}");
822 }
823 CU_ASSERT_EQUAL(i, 2);
824
825 ejdb_list_destroy(&list);
826 iwxstr_clear(log);
827
828
829 jql_destroy(&q);
830
831 rc = ejdb_close(&db);
832 CU_ASSERT_EQUAL_FATAL(rc, 0);
833 iwxstr_destroy(log);
834 iwxstr_destroy(xstr);
835 iwpool_destroy(pool);
836 }
837
ejdb_test3_5()838 void ejdb_test3_5() {
839 EJDB_OPTS opts = {
840 .kv = {
841 .path = "ejdb_test3_5.db",
842 .oflags = IWKV_TRUNC
843 },
844 .no_wal = true
845 };
846 EJDB db;
847 EJDB_LIST list = 0;
848 char dbuf[1024];
849 IWXSTR *xstr = iwxstr_new();
850 CU_ASSERT_PTR_NOT_NULL_FATAL(xstr);
851
852 iwrc rc = ejdb_open(&opts, &db);
853 CU_ASSERT_EQUAL_FATAL(rc, 0);
854
855 for (int i = 1; i <= 10; ++i) {
856 snprintf(dbuf, sizeof(dbuf), "{\"f\":{\"b\":%d},\"n\":%d}", i, i);
857 rc = put_json(db, "c1", dbuf);
858 CU_ASSERT_EQUAL_FATAL(rc, 0);
859 }
860
861 rc = ejdb_list3(db, "c1", "/f/[b = 2] | del", 0, 0, &list);
862 CU_ASSERT_EQUAL_FATAL(rc, 0);
863 int i = 0;
864 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
865 iwxstr_clear(xstr);
866 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
867 CU_ASSERT_EQUAL_FATAL(rc, 0);
868 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":2},\"n\":2}");
869 }
870 CU_ASSERT_EQUAL_FATAL(i, 1);
871 ejdb_list_destroy(&list);
872
873 // Check if /f/[b = 2] has been deleted
874 rc = ejdb_list3(db, "c1", "/f/[b = 2]", 0, 0, &list);
875 CU_ASSERT_EQUAL_FATAL(rc, 0);
876 CU_ASSERT_PTR_NULL(list->first);
877 ejdb_list_destroy(&list);
878
879 // Ensure index on /f/b
880 rc = ejdb_ensure_index(db, "c2", "/f/b", EJDB_IDX_UNIQUE | EJDB_IDX_I64);
881 CU_ASSERT_EQUAL_FATAL(rc, 0);
882
883 rc = ejdb_list3(db, "c1", "/f/[b = 3] | del", 0, 0, &list);
884 CU_ASSERT_EQUAL_FATAL(rc, 0);
885 ejdb_list_destroy(&list);
886
887 // Check if /f/[b = 3] has been deleted
888 rc = ejdb_list3(db, "c1", "/f/[b = 3]", 0, 0, &list);
889 CU_ASSERT_EQUAL_FATAL(rc, 0);
890 CU_ASSERT_PTR_NULL(list->first);
891 ejdb_list_destroy(&list);
892
893 rc = ejdb_list3(db, "c1", "/* | asc /f/b", 0, 0, &list);
894 CU_ASSERT_EQUAL_FATAL(rc, 0);
895 i = 0;
896 for (EJDB_DOC doc = list->first; doc; doc = doc->next, ++i) {
897 iwxstr_clear(xstr);
898 rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
899 CU_ASSERT_EQUAL_FATAL(rc, 0);
900 if (i == 0) {
901 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":1},\"n\":1}");
902 } else if (i == 1) {
903 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":4},\"n\":4}");
904 } else if (i == 7) {
905 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"f\":{\"b\":10},\"n\":10}");
906 }
907 }
908 ejdb_list_destroy(&list);
909 CU_ASSERT_EQUAL_FATAL(i, 8);
910
911 // Remove rest of elements
912 rc = ejdb_list3(db, "c1", "/* | del | desc /f/b", 0, 0, &list);
913 CU_ASSERT_EQUAL_FATAL(rc, 0);
914 ejdb_list_destroy(&list);
915
916 // Check coll is empty
917 rc = ejdb_list3(db, "c1", "/*", 0, 0, &list);
918 CU_ASSERT_EQUAL_FATAL(rc, 0);
919 CU_ASSERT_PTR_NULL(list->first);
920 ejdb_list_destroy(&list);
921
922 rc = ejdb_close(&db);
923 CU_ASSERT_EQUAL_FATAL(rc, 0);
924 iwxstr_destroy(xstr);
925 }
926
jql_free_str(void * ptr,void * op)927 static void jql_free_str(void *ptr, void *op) {
928 if (ptr) {
929 free(ptr);
930 }
931 }
932
ejdb_test3_6()933 void ejdb_test3_6() {
934 EJDB_OPTS opts = {
935 .kv = {
936 .path = "ejdb_test3_6.db",
937 .oflags = IWKV_TRUNC
938 }
939 };
940
941 JQL q;
942 EJDB db;
943 EJDB_LIST list = 0;
944 IWXSTR *xstr = iwxstr_new();
945 CU_ASSERT_PTR_NOT_NULL_FATAL(xstr);
946
947 iwrc rc = ejdb_open(&opts, &db);
948 CU_ASSERT_EQUAL_FATAL(rc, 0);
949
950 rc = ejdb_ensure_index(db, "mycoll", "/foo", EJDB_IDX_UNIQUE | EJDB_IDX_STR);
951 CU_ASSERT_EQUAL_FATAL(rc, 0);
952
953
954 rc = put_json(db, "mycoll", "{\"foo\":\"baz\",\"baz\":\"qux\"}");
955 CU_ASSERT_EQUAL_FATAL(rc, 0);
956
957 rc = jql_create(&q, 0, "@mycoll/[foo re :?]");
958 CU_ASSERT_EQUAL_FATAL(rc, 0);
959
960 rc = jql_set_regexp(q, 0, 0, ".*");
961 CU_ASSERT_EQUAL_FATAL(rc, 0);
962
963 rc = ejdb_list4(db, q, 0, 0, &list);
964 CU_ASSERT_EQUAL_FATAL(rc, 0);
965 CU_ASSERT_PTR_NOT_NULL_FATAL(list->first);
966
967 iwxstr_clear(xstr);
968 rc = jbl_as_json(list->first->raw, jbl_xstr_json_printer, xstr, 0);
969 CU_ASSERT_EQUAL_FATAL(rc, 0);
970 CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\"foo\":\"baz\",\"baz\":\"qux\"}");
971 ejdb_list_destroy(&list);
972
973 // Now set regexp again
974 rc = jql_set_regexp2(q, 0, 0, strdup(".*"), jql_free_str, 0);
975 CU_ASSERT_EQUAL_FATAL(rc, 0);
976
977 rc = ejdb_list4(db, q, 0, 0, &list);
978 CU_ASSERT_EQUAL_FATAL(rc, 0);
979 CU_ASSERT_PTR_NOT_NULL_FATAL(list->first);
980
981 ejdb_list_destroy(&list);
982
983 rc = ejdb_close(&db);
984 CU_ASSERT_EQUAL_FATAL(rc, 0);
985 iwxstr_destroy(xstr);
986 jql_destroy(&q);
987 }
988
ejdb_test3_7()989 void ejdb_test3_7() {
990 EJDB_OPTS opts = {
991 .kv = {
992 .path = "ejdb_test3_7.db",
993 .oflags = IWKV_TRUNC
994 }
995 };
996 EJDB db;
997 iwrc rc = ejdb_open(&opts, &db);
998 CU_ASSERT_EQUAL_FATAL(rc, 0);
999
1000 rc = put_json(db, "cc1", "{'foo':1}");
1001 CU_ASSERT_EQUAL_FATAL(rc, 0);
1002
1003 rc = ejdb_rename_collection(db, "cc1", "cc2");
1004 CU_ASSERT_EQUAL_FATAL(rc, 0);
1005
1006 JBL jbl;
1007 rc = ejdb_get(db, "cc2", 1, &jbl);
1008 CU_ASSERT_EQUAL_FATAL(rc, 0);
1009 jbl_destroy(&jbl);
1010
1011 rc = ejdb_rename_collection(db, "cc1", "cc2");
1012 CU_ASSERT_EQUAL_FATAL(rc, EJDB_ERROR_COLLECTION_NOT_FOUND);
1013
1014 rc = ejdb_rename_collection(db, "cc2", "cc2");
1015 CU_ASSERT_EQUAL_FATAL(rc, EJDB_ERROR_TARGET_COLLECTION_EXISTS);
1016
1017 rc = ejdb_close(&db);
1018 CU_ASSERT_EQUAL_FATAL(rc, 0);
1019
1020 opts.kv.oflags = 0;
1021
1022 rc = ejdb_open(&opts, &db);
1023 CU_ASSERT_EQUAL_FATAL(rc, 0);
1024
1025 rc = ejdb_get(db, "cc2", 1, &jbl);
1026 CU_ASSERT_EQUAL_FATAL(rc, 0);
1027 jbl_destroy(&jbl);
1028
1029 rc = ejdb_close(&db);
1030 CU_ASSERT_EQUAL_FATAL(rc, 0);
1031 }
1032
ejdb_test3_8(void)1033 void ejdb_test3_8(void) {
1034 EJDB_OPTS opts = {
1035 .kv = {
1036 .path = "ejdb_test3_8.db",
1037 .oflags = IWKV_TRUNC
1038 },
1039 .no_wal = true
1040 };
1041
1042 EJDB db;
1043 JQL q;
1044 char buf[64];
1045 JBL_NODE n;
1046
1047 int64_t id1 = 0, id2 = 0;
1048 EJDB_LIST list = 0;
1049
1050 IWPOOL *pool = iwpool_create(255);
1051 IWXSTR *log = iwxstr_new();
1052 CU_ASSERT_PTR_NOT_NULL_FATAL(log);
1053
1054 iwrc rc = ejdb_open(&opts, &db);
1055 CU_ASSERT_EQUAL_FATAL(rc, 0);
1056
1057 rc = put_json2(db, "users", "{'name':'Andy'}", &id1);
1058 CU_ASSERT_EQUAL_FATAL(rc, 0);
1059
1060 rc = put_json2(db, "users", "{'name':'John'}", &id2);
1061 CU_ASSERT_EQUAL_FATAL(rc, 0);
1062
1063 rc = jql_create(&q, "users", "/=:?");
1064 CU_ASSERT_EQUAL_FATAL(rc, 0);
1065 rc = jql_set_i64(q, 0, 0, id1);
1066 CU_ASSERT_EQUAL_FATAL(rc, 0);
1067
1068 rc = ejdb_list4(db, q, 0, log, &list);
1069 CU_ASSERT_EQUAL_FATAL(rc, 0);
1070
1071 CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(log), "[INDEX] PK [COLLECTOR] PLAIN"));
1072 CU_ASSERT_PTR_NOT_NULL(list->first);
1073 CU_ASSERT_PTR_NULL(list->first->next);
1074
1075 jql_destroy(&q);
1076 ejdb_list_destroy(&list);
1077 iwxstr_clear(log);
1078
1079 rc = jql_create(&q, 0, "@users/=:id");
1080 CU_ASSERT_EQUAL_FATAL(rc, 0);
1081 rc = jql_set_str(q, "id", 0, "1");
1082 CU_ASSERT_EQUAL_FATAL(rc, 0);
1083 rc = ejdb_list4(db, q, 0, log, &list);
1084 CU_ASSERT_EQUAL_FATAL(rc, 0);
1085 CU_ASSERT_PTR_NOT_NULL(list->first);
1086 CU_ASSERT_PTR_NULL(list->first->next);
1087 jql_destroy(&q);
1088 ejdb_list_destroy(&list);
1089
1090 // matching against PK array
1091 snprintf(buf, sizeof(buf), "@users/=[%" PRId64 ",%" PRId64 "]", id1, id2);
1092 rc = jql_create(&q, 0, buf);
1093 CU_ASSERT_EQUAL_FATAL(rc, 0);
1094 rc = ejdb_list4(db, q, 0, log, &list);
1095 CU_ASSERT_EQUAL_FATAL(rc, 0);
1096 CU_ASSERT_PTR_NOT_NULL(list->first);
1097 CU_ASSERT_PTR_NOT_NULL(list->first->next);
1098 jql_destroy(&q);
1099 ejdb_list_destroy(&list);
1100
1101 // matching against PK array as JSON query paramater
1102 snprintf(buf, sizeof(buf), "[%" PRId64 ",%" PRId64 "]", id1, id2);
1103 rc = jbn_from_json(buf, &n, pool);
1104 CU_ASSERT_EQUAL_FATAL(rc, 0);
1105 rc = jql_create(&q, 0, "@users/=:?");
1106 CU_ASSERT_EQUAL_FATAL(rc, 0);
1107 rc = jql_set_json(q, 0, 0, n);
1108 CU_ASSERT_EQUAL_FATAL(rc, 0);
1109 rc = ejdb_list4(db, q, 0, log, &list);
1110 CU_ASSERT_EQUAL_FATAL(rc, 0);
1111 CU_ASSERT_PTR_NOT_NULL(list->first);
1112 CU_ASSERT_PTR_NOT_NULL(list->first->next);
1113 jql_destroy(&q);
1114 ejdb_list_destroy(&list);
1115
1116 rc = ejdb_close(&db);
1117 CU_ASSERT_EQUAL_FATAL(rc, 0);
1118 iwxstr_destroy(log);
1119 iwpool_destroy(pool);
1120 }
1121
main()1122 int main() {
1123 CU_pSuite pSuite = NULL;
1124 if (CUE_SUCCESS != CU_initialize_registry()) {
1125 return CU_get_error();
1126 }
1127 pSuite = CU_add_suite("ejdb_test3", init_suite, clean_suite);
1128 if (NULL == pSuite) {
1129 CU_cleanup_registry();
1130 return CU_get_error();
1131 }
1132 if ( (NULL == CU_add_test(pSuite, "ejdb_test3_1", ejdb_test3_1))
1133 || (NULL == CU_add_test(pSuite, "ejdb_test3_2", ejdb_test3_2))
1134 || (NULL == CU_add_test(pSuite, "ejdb_test3_3", ejdb_test3_3))
1135 || (NULL == CU_add_test(pSuite, "ejdb_test3_4", ejdb_test3_4))
1136 || (NULL == CU_add_test(pSuite, "ejdb_test3_5", ejdb_test3_5))
1137 || (NULL == CU_add_test(pSuite, "ejdb_test3_6", ejdb_test3_6))
1138 || (NULL == CU_add_test(pSuite, "ejdb_test3_7", ejdb_test3_7))
1139 || (NULL == CU_add_test(pSuite, "ejdb_test3_8", ejdb_test3_8))) {
1140 CU_cleanup_registry();
1141 return CU_get_error();
1142 }
1143 CU_basic_set_mode(CU_BRM_VERBOSE);
1144 CU_basic_run_tests();
1145 int ret = CU_get_error() || CU_get_number_of_failures();
1146 CU_cleanup_registry();
1147 return ret;
1148 }
1149