From: adam Date: Mon, 14 Jan 2013 11:33:36 +0000 (+0700) Subject: #38 X-Git-Tag: v1.2.12~513 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f2f43f9be11a6445ec1c8d6970a1252606c4b8ed;p=platform%2Fupstream%2Fejdb.git #38 --- diff --git a/node/nodejs b/node/nodejs index 27ed8b0..c50c33e 160000 --- a/node/nodejs +++ b/node/nodejs @@ -1 +1 @@ -Subproject commit 27ed8b05d1b0aed074d3363d901a206d007b28bc +Subproject commit c50c33e9397d7a0a8717e8ce7530572907c054ad diff --git a/tcejdb/bson.c b/tcejdb/bson.c index 3b1f637..2a91390 100644 --- a/tcejdb/bson.c +++ b/tcejdb/bson.c @@ -25,6 +25,7 @@ #include "bson.h" #include "encoding.h" #include "myconf.h" +#include "tcutil.h" const int initialBufferSize = 128; @@ -372,10 +373,6 @@ EJDB_EXPORT void bson_visit_fields(bson_iterator *it, bson_traverse_flags_t flag bson_visit_fields_impl(flags, pstack, 0, it, visitor, op); } - - - - static bson_type bson_find_fieldpath_value_impl(char* pstack, int curr, FFPCTX *ffpctx, bson_iterator *it) { int i; bson_type t; @@ -1255,23 +1252,23 @@ EJDB_EXPORT int bson_numstrn(char *str, int maxbuf, int64_t i) { } } -static bson_bool_t bson_isnumstr(const char *str, int len){ - assert(str); - bool isnum = false; - while(len > 0 && *str > '\0' && *str <= ' '){ - str++; - len--; - } - while(len > 0 && *str >= '0' && *str <= '9'){ - isnum = true; - str++; - len--; - } - while(len > 0 && *str > '\0' && *str <= ' '){ - str++; - len--; - } - return (isnum && (*str == '\0' || len == 0)); +static bson_bool_t bson_isnumstr(const char *str, int len) { + assert(str); + bool isnum = false; + while (len > 0 && *str > '\0' && *str <= ' ') { + str++; + len--; + } + while (len > 0 && *str >= '0' && *str <= '9') { + isnum = true; + str++; + len--; + } + while (len > 0 && *str > '\0' && *str <= ' ') { + str++; + len--; + } + return (isnum && (*str == '\0' || len == 0)); } EJDB_EXPORT void bson_swap_endian64(void *outp, const void *inp) { @@ -1614,13 +1611,13 @@ EJDB_EXPORT bson* bson_create_from_buffer2(bson *rv, const void* buf, int bufsz) return rv; } -EJDB_EXPORT bool bson_find_merged_array_sets(const void *mbuf, const void *inbuf) { +EJDB_EXPORT bool bson_find_merged_array_sets(const void *mbuf, const void *inbuf, bool expandall) { assert(mbuf && inbuf); bool found = false; bson_iterator it, it2; bson_type bt, bt2; bson_iterator_from_buffer(&it, mbuf); - while ((bt = bson_iterator_next(&it)) != BSON_EOO) { + while (!found && (bt = bson_iterator_next(&it)) != BSON_EOO) { bson_iterator_from_buffer(&it2, inbuf); bt2 = bson_find_fieldpath_value(bson_iterator_key(&it), &it2); if (bt2 != BSON_ARRAY) { @@ -1628,15 +1625,26 @@ EJDB_EXPORT bool bson_find_merged_array_sets(const void *mbuf, const void *inbuf } bson_iterator sit; bson_iterator_subiterator(&it2, &sit); - while ((bt2 = bson_iterator_next(&sit)) != BSON_EOO) { - if (!bson_compare_it_current(&sit, &it)) { - found = true; - break; + while (!found && (bt2 = bson_iterator_next(&sit)) != BSON_EOO) { + if (expandall) { + if (bt2 != BSON_ARRAY) { + continue; + } + bson_iterator sit2; + bson_iterator_subiterator(&sit, &sit2); + while ((bt2 = bson_iterator_next(&sit2)) != BSON_EOO) { + if (!bson_compare_it_current(&sit, &it)) { + found = true; + break; + } + } + } else { + if (!bson_compare_it_current(&sit, &it)) { + found = true; + break; + } } } - if (found) { - break; - } } return found; } @@ -1654,7 +1662,7 @@ EJDB_EXPORT bool bson_find_unmerged_array_sets(const void *mbuf, const void *inb allfound = false; break; } - if (bt2 != BSON_ARRAY) { //some other field + if (bt2 != BSON_ARRAY) { //not an array field continue; } allfound = false; @@ -1679,6 +1687,7 @@ typedef struct { int mfields; int ecode; bool duty; + bool expandall; } BSON_MASETS_CTX; static bson_visitor_cmd_t bson_merge_array_sets_pull_tf(const char *fpath, int fpathlen, const char *key, int keylen, const bson_iterator *it, bool after, void *op) { @@ -1686,9 +1695,9 @@ static bson_visitor_cmd_t bson_merge_array_sets_pull_tf(const char *fpath, int f assert(ctx && ctx->mfields >= 0); bson_iterator mit; bson_type bt = bson_iterator_type(it); - if (bt != BSON_OBJECT && bt != BSON_ARRAY) { //simple primitive case + if (bt != BSON_OBJECT && bt != BSON_ARRAY) { //trivial case if (after) { - return BSON_VCMD_OK; + return (BSON_VCMD_OK); } bson_append_field_from_iterator(it, ctx->bsout); return (BSON_VCMD_SKIP_AFTER); @@ -1696,7 +1705,7 @@ static bson_visitor_cmd_t bson_merge_array_sets_pull_tf(const char *fpath, int f if (bt == BSON_ARRAY) { bson_iterator_from_buffer(&mit, ctx->mbuf); bt = bson_find_fieldpath_value2(fpath, fpathlen, &mit); - if (bt == BSON_EOO) { + if (bt == BSON_EOO || (ctx->expandall && bt != BSON_ARRAY)) { bson_append_field_from_iterator(it, ctx->bsout); return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER); } @@ -1708,13 +1717,26 @@ static bson_visitor_cmd_t bson_merge_array_sets_pull_tf(const char *fpath, int f bson_iterator_subiterator(it, &ait); bson_append_start_array(ctx->bsout, key); int c = 0; + bool found = false; while ((bt = bson_iterator_next(&ait)) != BSON_EOO) { - if (!bson_compare_it_current(&ait, &mit)) { - continue; + found = false; + if (ctx->expandall) { + bson_iterator mitsub; + bson_iterator_subiterator(&mit, &mitsub); + while ((bt = bson_iterator_next(&mitsub)) != BSON_EOO) { + if (!bson_compare_it_current(&ait, &mitsub)) { + found = true; + break; + } + } + } else { + found = !bson_compare_it_current(&ait, &mit); + } + if (!found) { + char kbuf[TCNUMBUFSIZ]; + bson_numstrn(kbuf, TCNUMBUFSIZ, c++); + bson_append_field_from_iterator2(kbuf, &ait, ctx->bsout); } - char kbuf[TCNUMBUFSIZ]; - bson_numstrn(kbuf, TCNUMBUFSIZ, c++); - bson_append_field_from_iterator2(kbuf, &ait, ctx->bsout); } bson_append_finish_array(ctx->bsout); return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER); @@ -1734,9 +1756,9 @@ static bson_visitor_cmd_t bson_merge_array_sets_tf(const char *fpath, int fpathl bson_iterator mit; bson_type bt = bson_iterator_type(it); - if (bt != BSON_OBJECT && bt != BSON_ARRAY) { //simple primitive case + if (bt != BSON_OBJECT && bt != BSON_ARRAY) { //trivial case if (after) { - return BSON_VCMD_OK; + return (BSON_VCMD_OK); } bson_append_field_from_iterator(it, ctx->bsout); return (BSON_VCMD_SKIP_AFTER); @@ -1744,7 +1766,7 @@ static bson_visitor_cmd_t bson_merge_array_sets_tf(const char *fpath, int fpathl if (bt == BSON_ARRAY) { bson_iterator_from_buffer(&mit, ctx->mbuf); bt = bson_find_fieldpath_value2(fpath, fpathlen, &mit); - if (bt == BSON_EOO) { + if (bt == BSON_EOO || (ctx->expandall && bt != BSON_ARRAY)) { bson_append_field_from_iterator(it, ctx->bsout); return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER); } @@ -1757,18 +1779,44 @@ static bson_visitor_cmd_t bson_merge_array_sets_tf(const char *fpath, int fpathl bson_append_start_array(ctx->bsout, key); bool found = false; int c = 0; - while ((bt = bson_iterator_next(&ait)) != BSON_EOO) { - if (!found && !bson_compare_it_current(&ait, &mit)) { - found = true; + if (ctx->expandall) { //Set of array elements to add + while ((bt = bson_iterator_next(&ait)) != BSON_EOO) { //Flush current array + bson_append_field_from_iterator(&ait, ctx->bsout); + ++c; + } + //Iterate over set to add + bson_iterator mitsub; + bson_iterator_subiterator(&mit, &mitsub); //mit has BSON_ARRAY type + while ((bt = bson_iterator_next(&mitsub)) != BSON_EOO) { + found = false; + bson_iterator_subiterator(it, &ait); //Rewind main array iterator + while ((bt = bson_iterator_next(&ait)) != BSON_EOO) { + if (!bson_compare_it_current(&ait, &mitsub)) { + found = true; + break; + } + } + if (!found) { //Append missing element + char kbuf[TCNUMBUFSIZ]; + bson_numstrn(kbuf, TCNUMBUFSIZ, c++); + bson_append_field_from_iterator2(kbuf, &mitsub, ctx->bsout); + ctx->duty = true; + } + } + } else { //Single element to add + while ((bt = bson_iterator_next(&ait)) != BSON_EOO) { + if (!found && !bson_compare_it_current(&ait, &mit)) { + found = true; + } + bson_append_field_from_iterator(&ait, ctx->bsout); + ++c; + } + if (!found) { //uppend missing element into array + char kbuf[TCNUMBUFSIZ]; + bson_numstrn(kbuf, TCNUMBUFSIZ, c); + bson_append_field_from_iterator2(kbuf, &mit, ctx->bsout); + ctx->duty = true; } - bson_append_field_from_iterator(&ait, ctx->bsout); - ++c; - } - if (!found) { //uppend missing element into array - char kbuf[TCNUMBUFSIZ]; - bson_numstrn(kbuf, TCNUMBUFSIZ, c); - bson_append_field_from_iterator2(kbuf, &mit, ctx->bsout); - ctx->duty = true; } bson_append_finish_array(ctx->bsout); return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER); @@ -1783,18 +1831,19 @@ static bson_visitor_cmd_t bson_merge_array_sets_tf(const char *fpath, int fpathl } -EJDB_EXPORT int bson_merge_array_sets(const void *mbuf, const void *inbuf, bool pull, bson *bsout) { +EJDB_EXPORT int bson_merge_array_sets(const void *mbuf, const void *inbuf, bool pull, bool expandall, bson *bsout) { assert(mbuf && inbuf && bsout); if (bsout->finished) { return BSON_ERROR; } - BSON_MASETS_CTX ctx; - ctx.bsout = bsout; - ctx.mbuf = mbuf; - ctx.mfields = 0; - ctx.duty = false; - ctx.ecode = BSON_OK; - + BSON_MASETS_CTX ctx = { + .bsout = bsout, + .mbuf = mbuf, + .mfields = 0, + .duty = false, + .expandall = expandall, + .ecode = BSON_OK + }; bson_type bt, bt2; bson_iterator it, it2; bson_iterator_from_buffer(&it, mbuf); diff --git a/tcejdb/bson.h b/tcejdb/bson.h index 726ac25..98ddc23 100644 --- a/tcejdb/bson.h +++ b/tcejdb/bson.h @@ -181,8 +181,6 @@ EJDB_EXPORT bson_type bson_find(bson_iterator *it, const bson *obj, const char * EJDB_EXPORT bson_type bson_find_from_buffer(bson_iterator *it, const char *buffer, const char *name); - - typedef struct { /**< Find field path context */ const char* fpath; int fplen; @@ -1142,8 +1140,8 @@ EJDB_EXPORT bson* bson_create_from_buffer(const void *buf, int bufsz); EJDB_EXPORT bson* bson_create_from_buffer2(bson *bs, const void *buf, int bufsz); EJDB_EXPORT bool bson_find_unmerged_array_sets(const void *mbuf, const void *inbuf); -EJDB_EXPORT bool bson_find_merged_array_sets(const void *mbuf, const void *inbuf); -EJDB_EXPORT int bson_merge_array_sets(const void *mbuf, const void *inbuf, bool pull, bson *bsout); +EJDB_EXPORT bool bson_find_merged_array_sets(const void *mbuf, const void *inbuf, bool expandall); +EJDB_EXPORT int bson_merge_array_sets(const void *mbuf, const void *inbuf, bool pull, bool expandall, bson *bsout); EJDB_EXTERN_C_END diff --git a/tcejdb/ejdb.c b/tcejdb/ejdb.c index 6f24ae6..b508d3c 100644 --- a/tcejdb/ejdb.c +++ b/tcejdb/ejdb.c @@ -634,7 +634,7 @@ EJDB_EXPORT TCLIST* ejdbqryexecute(EJCOLL *jcoll, const EJQ *q, uint32_t *count, _ejdbsetecode(jcoll->jb, TCEINVALID, __FILE__, __LINE__, __func__); return NULL; } - JBCLOCKMETHOD(jcoll, (q->flags & EJQUPDATING) ? true : false); + JBCLOCKMETHOD(jcoll, (q->flags & EJQUPDATING) ? true : false); _ejdbsetecode(jcoll->jb, TCESUCCESS, __FILE__, __LINE__, __func__); if (ejdbecode(jcoll->jb) != TCESUCCESS) { //we are not in fatal state JBCUNLOCKMETHOD(jcoll); @@ -1696,28 +1696,38 @@ static bool _qryupdate(EJCOLL *jcoll, const EJQ *ejq, void *bsbuf, int bsbufsz, bsout.dataSize = 0; bson_reset(&bsout); - const EJQF *setqf = NULL; - const EJQF *incqf = NULL; - const EJQF *addsetqf = NULL; - const EJQF *pullqf = NULL; + const EJQF *setqf = NULL; /*$set*/ + const EJQF *incqf = NULL; /*$inc*/ + const EJQF * addsetqf[2] = {NULL}; /*$addToSet, $addToSetAll*/ + const EJQF * pullqf[2] = {NULL}; /*$pull, $pullAll*/ - //$set, $inc, $addToSet, $pull operations + //$set, $inc, $addToSet, $addToSetAll, $pull, $pullAll operations for (int i = 0; i < TCLISTNUM(ejq->qobjlist); ++i) { const EJQF *qf = TCLISTVALPTR(ejq->qobjlist, i); if (qf->updateobj == NULL) { continue; } - if (!setqf && qf->flags & EJCONDSET) { //$set + if (qf->flags & EJCONDSET) { //$set setqf = qf; - } else if (!incqf && qf->flags & EJCONDINC) { + continue; + } + if (qf->flags & EJCONDINC) { //$inc incqf = qf; - } else if (!addsetqf && qf->flags & EJCONDADDSET) { - addsetqf = qf; - } else if (!pullqf && qf->flags & EJCONDPULL) { - pullqf = qf; - } else { - assert(0); - break; + continue; + } + if (qf->flags & EJCONDADDSET) { //$addToSet, $addToSetAll + if (qf->flags & EJCONDALL) { + addsetqf[1] = qf; + } else { + addsetqf[0] = qf; + } + } + if (qf->flags & EJCONDPULL) { //$pull, $pullAll + if (qf->flags & EJCONDALL) { + pullqf[1] = qf; + } else { + pullqf[0] = qf; + } } } if (setqf) { //$set @@ -1770,14 +1780,18 @@ static bool _qryupdate(EJCOLL *jcoll, const EJQ *ejq, void *bsbuf, int bsbufsz, update = true; } } + + if (!rv) { + goto finish; + } } - if (!rv) { - goto finish; - } - if (pullqf) { //$pull + + for (int i = 0; i < 2; ++i) { //$pull $pullAll + const EJQF *qf = pullqf[i]; + if (!qf) continue; char* inbuf = (bsout.finished) ? bsout.data : bsbuf; - if (bson_find_merged_array_sets(bson_data(pullqf->updateobj), inbuf)) { + if (bson_find_merged_array_sets(bson_data(qf->updateobj), inbuf, (qf->flags & EJCONDALL))) { if (bsout.finished) { //reinit `bsout`, `inbuf` already points to `bsout.data` and will be freed later bson_init_size(&bsout, bson_size(&bsout)); @@ -1785,8 +1799,8 @@ static bool _qryupdate(EJCOLL *jcoll, const EJQ *ejq, void *bsbuf, int bsbufsz, assert(bsout.data == NULL); bson_init_size(&bsout, bsbufsz); } - //$pull merge - if (bson_merge_array_sets(bson_data(pullqf->updateobj), inbuf, true, &bsout)) { + //$pull $pullAll merge + if (bson_merge_array_sets(bson_data(qf->updateobj), inbuf, true, (qf->flags & EJCONDALL), &bsout)) { rv = false; _ejdbsetecode(jcoll->jb, JBEQUPDFAILED, __FILE__, __LINE__, __func__); } @@ -1796,14 +1810,16 @@ static bool _qryupdate(EJCOLL *jcoll, const EJQ *ejq, void *bsbuf, int bsbufsz, bson_finish(&bsout); update = true; } - } - if (!rv) { - goto finish; + if (!rv) { + goto finish; + } } - if (addsetqf) { //$addToSet + for (int i = 0; i < 2; ++i) { //$addToSet $addToSetAll + const EJQF *qf = addsetqf[i]; + if (!qf) continue; char* inbuf = (bsout.finished) ? bsout.data : bsbuf; - if (bson_find_unmerged_array_sets(bson_data(addsetqf->updateobj), inbuf)) { + if ((qf->flags & EJCONDALL) || bson_find_unmerged_array_sets(bson_data(qf->updateobj), inbuf)) { //Missing $addToSet element in some array field found if (bsout.finished) { //reinit `bsout`, `inbuf` already points to `bsout.data` and will be freed later @@ -1812,8 +1828,8 @@ static bool _qryupdate(EJCOLL *jcoll, const EJQ *ejq, void *bsbuf, int bsbufsz, assert(bsout.data == NULL); bson_init_size(&bsout, bsbufsz); } - //$addToSet merge - if (bson_merge_array_sets(bson_data(addsetqf->updateobj), inbuf, false, &bsout)) { + //$addToSet $addToSetAll merge + if (bson_merge_array_sets(bson_data(qf->updateobj), inbuf, false, (qf->flags & EJCONDALL), &bsout)) { rv = false; _ejdbsetecode(jcoll->jb, JBEQUPDFAILED, __FILE__, __LINE__, __func__); } @@ -1823,12 +1839,12 @@ static bool _qryupdate(EJCOLL *jcoll, const EJQ *ejq, void *bsbuf, int bsbufsz, bson_finish(&bsout); update = true; } + if (!update || !rv) { + goto finish; + } } - if (!update || !rv) { - goto finish; - } - if (bsout.err) { + if (bsout.err) { //Resulting BSON is OK? rv = false; _ejdbsetecode(jcoll->jb, JBEQUPDFAILED, __FILE__, __LINE__, __func__); goto finish; @@ -3217,8 +3233,10 @@ static int _parse_qobj_impl(EJDB *jb, EJQ *q, bson_iterator *it, TCLIST *qlist, !strcmp("$inc", fkey) || !strcmp("$dropall", fkey) || !strcmp("$addToSet", fkey) || + !strcmp("$addToSetAll", fkey) || !strcmp("$upsert", fkey) || - !strcmp("$pull", fkey)) { + !strcmp("$pull", fkey) || + !strcmp("$pullAll", fkey)) { if (pqf) { //Top level ops ret = JBEQERROR; _ejdbsetecode(jb, ret, __FILE__, __LINE__, __func__); @@ -3332,6 +3350,12 @@ static int _parse_qobj_impl(EJDB *jb, EJQ *q, bson_iterator *it, TCLIST *qlist, } else if (!strcmp("$upsert", fkey)) { qf.flags |= EJCONDSET; qf.flags |= EJCONDUPSERT; + } else if (!strcmp("$addToSetAll", fkey)) { + qf.flags |= EJCONDADDSET; + qf.flags |= EJCONDALL; + } else if (!strcmp("$pullAll", fkey)) { + qf.flags |= EJCONDPULL; + qf.flags |= EJCONDALL; } } if ((qf.flags & (EJCONDSET | EJCONDINC | EJCONDADDSET | EJCONDPULL))) { @@ -3343,6 +3367,10 @@ static int _parse_qobj_impl(EJDB *jb, EJQ *q, bson_iterator *it, TCLIST *qlist, bson_iterator sit; bson_iterator_subiterator(it, &sit); while ((sbt = bson_iterator_next(&sit)) != BSON_EOO) { + if ((qf.flags & EJCONDALL) && sbt != BSON_ARRAY) { + //$addToSetAll & $pullAll accepts arrays only as argument + continue; + } bson_append_field_from_iterator(&sit, qf.updateobj); } bson_finish(qf.updateobj); diff --git a/tcejdb/ejdb_private.h b/tcejdb/ejdb_private.h index eda3eca..452e211 100644 --- a/tcejdb/ejdb_private.h +++ b/tcejdb/ejdb_private.h @@ -58,7 +58,8 @@ enum { /**> Query field flags */ EJCONDINC = 1 << 11, /**> $inc Inc field update operation */ EJCONDADDSET = 1 << 12, /**> $addToSet Adds value to the array only if its not in the array already. */ EJCONDPULL = 1 << 13, /**> $pull Removes all occurrences of value from field, if field is an array */ - EJCONDUPSERT = 1 << 14 /**> $upsert Upsert $set operation */ + EJCONDUPSERT = 1 << 14, /**> $upsert Upsert $set operation */ + EJCONDALL = 1 << 15 /**> 'All' modificator for $pull or $addToSet ($addToSetAll or $pullAll) */ }; diff --git a/tcejdb/testejdb/t2.c b/tcejdb/testejdb/t2.c index affa3f1..932965d 100644 --- a/tcejdb/testejdb/t2.c +++ b/tcejdb/testejdb/t2.c @@ -3366,8 +3366,14 @@ void test$addToSet() { bson_append_finish_object(&bsq1); bson_append_start_object(&bsq1, "$addToSet"); bson_append_string(&bsq1, "personal.tags", "tag3"); - bson_append_string(&bsq1, "labels", "red"); - bson_append_finish_object(&bsq1); + bson_append_finish_object(&bsq1); //EOF $addToSet + bson_append_start_object(&bsq1, "$addToSetAll"); + bson_append_start_array(&bsq1, "labels"); + bson_append_string(&bsq1, "0", "red"); + bson_append_string(&bsq1, "1", "black"); + bson_append_string(&bsq1, "2", "green"); + bson_append_finish_array(&bsq1); + bson_append_finish_object(&bsq1); //EOF $addToSetAll bson_finish(&bsq1); CU_ASSERT_FALSE_FATAL(bsq1.err); @@ -3403,6 +3409,8 @@ void test$addToSet() { CU_ASSERT_FALSE(bson_compare_string("tag3", TCLISTVALPTR(q1res, i), "personal.tags.2")); CU_ASSERT_FALSE(bson_compare_string("green", TCLISTVALPTR(q1res, i), "labels.0")); CU_ASSERT_FALSE(bson_compare_string("red", TCLISTVALPTR(q1res, i), "labels.1")); + CU_ASSERT_FALSE(bson_compare_string("black", TCLISTVALPTR(q1res, i), "labels.2")); + CU_ASSERT_TRUE(bson_compare_string("green", TCLISTVALPTR(q1res, i), "labels.3")); } bson_destroy(&bsq1);