From d5924bf3c850b7dd78730cda5e927dd660812b04 Mon Sep 17 00:00:00 2001 From: adam Date: Wed, 7 Aug 2013 21:51:15 +0700 Subject: [PATCH] Added support of top level query operators #81 --- tcejdb/ejdb.c | 118 ++++++++++++++++++++++++++++----------------------- tcejdb/testejdb/t2.c | 56 ++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 54 deletions(-) diff --git a/tcejdb/ejdb.c b/tcejdb/ejdb.c index 5ae1724..b1a3914 100644 --- a/tcejdb/ejdb.c +++ b/tcejdb/ejdb.c @@ -485,7 +485,7 @@ EJQ* ejdbqueryaddor(EJDB *jb, EJQ *q, const void *orbsdata) { if (q->orqlist == NULL) { q->orqlist = tclistnew2(TCLISTINYNUM); } - tclistpush(q->orqlist, oq, sizeof(*oq)); //copy root EJQ struct + tclistpush(q->orqlist, oq, sizeof (*oq)); //copy root EJQ struct TCFREE(oq); return q; } @@ -2260,7 +2260,7 @@ static bool _qrydup(const EJQ *src, EJQ *target, uint32_t qflags) { for (int i = 0; i < TCLISTNUM(src->orqlist); ++i) { EJQ q; if (_qrydup(TCLISTVALPTR(src->orqlist, i), &q, qflags)) { - tclistpush(target->orqlist, &q, sizeof(q)); + tclistpush(target->orqlist, &q, sizeof (q)); } } } @@ -4193,17 +4193,12 @@ static char* _fetch_bson_str_array2(EJDB *jb, bson_iterator *it, bson_type *type return tokens; } -//typedef struct { -// -//} _PQOBJCTX ; - static int _parse_qobj_impl(EJDB *jb, EJQ *q, bson_iterator *it, TCLIST *qlist, TCLIST *pathStack, EJQF *pqf, int elmatchgrp) { assert(it && qlist && pathStack); int ret = 0; - bson_type ftype; + bson_type ftype, bt; while ((ftype = bson_iterator_next(it)) != BSON_EOO) { - const char *fkey = bson_iterator_key(it); bool isckey = (*fkey == '$'); //Key is a control key: $in, $nin, $not, $all, ... EJQF qf; @@ -4228,7 +4223,8 @@ static int _parse_qobj_impl(EJDB *jb, EJQ *q, bson_iterator *it, TCLIST *qlist, !strcmp("$upsert", fkey) || !strcmp("$pull", fkey) || !strcmp("$pullAll", fkey) || - !strcmp("$do", fkey) + !strcmp("$do", fkey) || + !strcmp("$or", fkey) ) { if (pqf) { //Top level ops ret = JBEQERROR; @@ -4264,62 +4260,76 @@ static int _parse_qobj_impl(EJDB *jb, EJQ *q, bson_iterator *it, TCLIST *qlist, case BSON_ARRAY: { if (isckey) { - bson_iterator sit; - bson_iterator_subiterator(it, &sit); - bson_type atype = 0; - TCLIST *tokens = _fetch_bson_str_array(jb, &sit, &atype, (qf.flags & EJCONDICASE) ? JBICASE : 0); - if (atype == 0) { - ret = JBEQINOPNOTARRAY; - _ejdbsetecode(jb, ret, __FILE__, __LINE__, __func__); - tclistdel(tokens); + if (!strcmp("$or", fkey)) { + bson_iterator sit; + bson_iterator_subiterator(it, &sit); + while ((bt = bson_iterator_next(&sit)) != BSON_EOO) { + if (bt != BSON_OBJECT) { + continue; + } + if (ejdbqueryaddor(jb, q, bson_iterator_value(&sit)) == NULL) { + break; + } + } break; - } - assert(!qf.expr && !qf.fpath); - qf.ftype = BSON_ARRAY; - qf.expr = tclistdump(tokens, &qf.exprsz); - qf.exprlist = tokens; - if (!strcmp("$in", fkey) || !strcmp("$nin", fkey)) { - if (!strcmp("$nin", fkey)) { - qf.negate = true; + } else { + bson_iterator sit; + bson_iterator_subiterator(it, &sit); + bson_type atype = 0; + TCLIST *tokens = _fetch_bson_str_array(jb, &sit, &atype, (qf.flags & EJCONDICASE) ? JBICASE : 0); + if (atype == 0) { + ret = JBEQINOPNOTARRAY; + _ejdbsetecode(jb, ret, __FILE__, __LINE__, __func__); + tclistdel(tokens); + break; } - if (BSON_IS_NUM_TYPE(atype) || atype == BSON_BOOL || atype == BSON_DATE) { - qf.tcop = TDBQCNUMOREQ; - } else { - qf.tcop = TDBQCSTROREQ; - if (TCLISTNUM(tokens) >= JBINOPTMAPTHRESHOLD) { - assert(!qf.exprmap); - qf.exprmap = tcmapnew2(TCLISTNUM(tokens)); - for (int i = 0; i < TCLISTNUM(tokens); ++i) { - tcmapputkeep(qf.exprmap, TCLISTVALPTR(tokens, i), TCLISTVALSIZ(tokens, i), &yes, sizeof (yes)); + assert(!qf.expr && !qf.fpath); + qf.ftype = BSON_ARRAY; + qf.expr = tclistdump(tokens, &qf.exprsz); + qf.exprlist = tokens; + if (!strcmp("$in", fkey) || !strcmp("$nin", fkey)) { + if (!strcmp("$nin", fkey)) { + qf.negate = true; + } + if (BSON_IS_NUM_TYPE(atype) || atype == BSON_BOOL || atype == BSON_DATE) { + qf.tcop = TDBQCNUMOREQ; + } else { + qf.tcop = TDBQCSTROREQ; + if (TCLISTNUM(tokens) >= JBINOPTMAPTHRESHOLD) { + assert(!qf.exprmap); + qf.exprmap = tcmapnew2(TCLISTNUM(tokens)); + for (int i = 0; i < TCLISTNUM(tokens); ++i) { + tcmapputkeep(qf.exprmap, TCLISTVALPTR(tokens, i), TCLISTVALSIZ(tokens, i), &yes, sizeof (yes)); + } } } - } - } else if (!strcmp("$bt", fkey)) { //between - qf.tcop = TDBQCNUMBT; - if (TCLISTNUM(tokens) != 2) { - ret = JBEQINOPNOTARRAY; + } else if (!strcmp("$bt", fkey)) { //between + qf.tcop = TDBQCNUMBT; + if (TCLISTNUM(tokens) != 2) { + ret = JBEQINOPNOTARRAY; + _ejdbsetecode(jb, ret, __FILE__, __LINE__, __func__); + TCFREE(qf.expr); + tclistdel(qf.exprlist); + break; + } + } else if (!strcmp("$strand", fkey)) { //$strand + qf.tcop = TDBQCSTRAND; + } else if (!strcmp("$stror", fkey)) { //$stror + qf.tcop = TDBQCSTROR; + } else if (qf.flags & EJCONDSTARTWITH) { //$begin with some token + qf.tcop = TDBQCSTRORBW; + } else { + ret = JBEQINVALIDQCONTROL; _ejdbsetecode(jb, ret, __FILE__, __LINE__, __func__); TCFREE(qf.expr); tclistdel(qf.exprlist); break; } - } else if (!strcmp("$strand", fkey)) { //$strand - qf.tcop = TDBQCSTRAND; - } else if (!strcmp("$stror", fkey)) { //$stror - qf.tcop = TDBQCSTROR; - } else if (qf.flags & EJCONDSTARTWITH) { //$begin with some token - qf.tcop = TDBQCSTRORBW; - } else { - ret = JBEQINVALIDQCONTROL; - _ejdbsetecode(jb, ret, __FILE__, __LINE__, __func__); - TCFREE(qf.expr); - tclistdel(qf.exprlist); + qf.fpath = tcstrjoin(pathStack, '.'); + qf.fpathsz = strlen(qf.fpath); + TCLISTPUSH(qlist, &qf, sizeof (qf)); break; } - qf.fpath = tcstrjoin(pathStack, '.'); - qf.fpathsz = strlen(qf.fpath); - TCLISTPUSH(qlist, &qf, sizeof (qf)); - break; } else { bson_iterator sit; bson_iterator_subiterator(it, &sit); diff --git a/tcejdb/testejdb/t2.c b/tcejdb/testejdb/t2.c index 030578e..ed89029 100644 --- a/tcejdb/testejdb/t2.c +++ b/tcejdb/testejdb/t2.c @@ -2252,6 +2252,61 @@ void testQuery25() { //$or } } +void testQuery25_2() { //$or alternative + EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL); + CU_ASSERT_PTR_NOT_NULL_FATAL(contacts); + + bson bsq1; + bson_init_as_query(&bsq1); + bson_append_start_array(&bsq1, "$or"); + + bson_append_start_object(&bsq1, "0"); + bson_append_string(&bsq1, "name", "Ivanov"); + bson_append_finish_object(&bsq1); + + bson_append_start_object(&bsq1, "1"); + bson_append_string(&bsq1, "name", "Антонов"); + bson_append_finish_object(&bsq1); + + bson_append_finish_array(&bsq1); + bson_finish(&bsq1); + CU_ASSERT_FALSE_FATAL(bsq1.err); + + EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, NULL); + CU_ASSERT_PTR_NOT_NULL_FATAL(q1); + + uint32_t count = 0; + TCXSTR *log = tcxstrnew(); + TCLIST *q1res = ejdbqryexecute(contacts, q1, &count, 0, log); + //fprintf(stderr, "%s", TCXSTRPTR(log)); + + CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAX: 4294967295")); + CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "SKIP: 0")); + CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "COUNT ONLY: NO")); + CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "MAIN IDX: 'NONE'")); + CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ORDER FIELDS: 0")); + CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "ACTIVE CONDITIONS: 0")); + CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "$OR QUERIES: 2")); + CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FETCH ALL: NO")); + CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RUN FULLSCAN")); + CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS SIZE: 2")); + CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "RS COUNT: 2")); + CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "FINAL SORTING: NO")); + CU_ASSERT_EQUAL(count, 2); + CU_ASSERT_TRUE(TCLISTNUM(q1res) == 2); + + for (int i = 0; i < TCLISTNUM(q1res); ++i) { + CU_ASSERT_TRUE( + !bson_compare_string("Ivanov", TCLISTVALPTR(q1res, i), "name") || + !bson_compare_string("Антонов", TCLISTVALPTR(q1res, i), "name")); + + } + bson_destroy(&bsq1); + tclistdel(q1res); + tcxstrdel(log); + ejdbquerydel(q1); +} + void testQuery26() { //$not $nin EJCOLL *contacts = ejdbcreatecoll(jb, "contacts", NULL); CU_ASSERT_PTR_NOT_NULL_FATAL(contacts); @@ -4389,6 +4444,7 @@ int main() { (NULL == CU_add_test(pSuite, "testQuery23", testQuery23)) || (NULL == CU_add_test(pSuite, "testQuery24", testQuery24)) || (NULL == CU_add_test(pSuite, "testQuery25", testQuery25)) || + (NULL == CU_add_test(pSuite, "testQuery25_2", testQuery25_2)) || (NULL == CU_add_test(pSuite, "testQuery26", testQuery26)) || (NULL == CU_add_test(pSuite, "testQuery27", testQuery27)) || (NULL == CU_add_test(pSuite, "testOIDSMatching", testOIDSMatching)) || -- 2.7.4