#43
authoradam <anton@adamansky.com>
Wed, 16 Jan 2013 04:40:58 +0000 (11:40 +0700)
committeradam <anton@adamansky.com>
Wed, 16 Jan 2013 04:40:58 +0000 (11:40 +0700)
tcejdb/ejdb.c
tcejdb/ejdb.h
tcejdb/testejdb/t2.c

index addfecd..f5a8772 100644 (file)
@@ -134,6 +134,7 @@ EJDB_EXPORT const char* ejdberrmsg(int ecode) {
         case JBEINVALIDBSONPK: return "invalid bson _id field";
         case JBEQONEEMATCH: return "only one $elemMatch allowed in the fieldpath"; //todo remove
         case JBEQINCEXCL: return "$fields hint cannot mix include and exclude fields";
+        case JBEQACTKEY: return "action key in $do block can only be one of: $join";
 
         default: return tcerrmsg(ecode);
     }
@@ -3300,6 +3301,7 @@ static int _parse_qobj_impl(EJDB *jb, EJQ *q, bson_iterator *it, TCLIST *qlist,
         if (pqf) {
             qf.elmatchgrp = pqf->elmatchgrp;
             qf.elmatchpos = pqf->elmatchpos;
+            qf.flags = pqf->flags;
         }
 
         if (!isckey) {
@@ -3470,15 +3472,31 @@ static int _parse_qobj_impl(EJDB *jb, EJQ *q, bson_iterator *it, TCLIST *qlist,
                         break;
                     }
 
-                    if (qf.flags & EJCONDOIT) { //$do
-                        assert(qf.updateobj == NULL);
+                    if (!strcmp("$elemMatch", fkey)) {
+                        if (qf.elmatchgrp) { //only one $elemMatch allowed in query field
+                            ret = JBEQERROR;
+                            _ejdbsetecode(jb, ret, __FILE__, __LINE__, __func__);
+                            break;
+                        }
+                        qf.elmatchgrp = ++elmatchgrp;
+                        char *fpath = tcstrjoin(pathStack, '.');
+                        qf.elmatchpos = strlen(fpath) + 1; //+ 1 to skip next dot '.'
+                        free(fpath);
+                    }
+                } else {
+                    if (qf.flags & EJCONDOIT) {
                         qf.updateobj = bson_create();
                         bson_init_as_query(qf.updateobj);
                         bson_type sbt;
                         bson_iterator sit;
                         bson_iterator_subiterator(it, &sit);
+                        int ac = 0;
                         while ((sbt = bson_iterator_next(&sit)) != BSON_EOO) {
-                            bson_append_field_from_iterator(&sit, qf.updateobj);
+                            const char *akey = bson_iterator_key(&sit);
+                            if (!strcmp("$join", akey)) {
+                                bson_append_field_from_iterator(&sit, qf.updateobj);
+                                ++ac;
+                            }
                         }
                         bson_finish(qf.updateobj);
                         if (qf.updateobj->err) {
@@ -3486,6 +3504,11 @@ static int _parse_qobj_impl(EJDB *jb, EJQ *q, bson_iterator *it, TCLIST *qlist,
                             _ejdbsetecode(jb, ret, __FILE__, __LINE__, __func__);
                             break;
                         }
+                        if (ac == 0) {
+                            ret = JBEQACTKEY;
+                            _ejdbsetecode(jb, ret, __FILE__, __LINE__, __func__);
+                            break;
+                        }
                         qf.fpath = strdup(fkey);
                         qf.fpathsz = strlen(qf.fpath);
                         qf.tcop = TDBQTRUE;
@@ -3493,18 +3516,6 @@ static int _parse_qobj_impl(EJDB *jb, EJQ *q, bson_iterator *it, TCLIST *qlist,
                         TCLISTPUSH(qlist, &qf, sizeof (qf));
                         break;
                     }
-
-                    if (!strcmp("$elemMatch", fkey)) {
-                        if (qf.elmatchgrp) { //only one $elemMatch allowed in query field
-                            ret = JBEQERROR;
-                            _ejdbsetecode(jb, ret, __FILE__, __LINE__, __func__);
-                            break;
-                        }
-                        qf.elmatchgrp = ++elmatchgrp;
-                        char *fpath = tcstrjoin(pathStack, '.');
-                        qf.elmatchpos = strlen(fpath) + 1; //+ 1 to skip next dot '.'
-                        free(fpath);
-                    }
                 }
                 bson_iterator sit;
                 bson_iterator_subiterator(it, &sit);
index 814dee4..92174fa 100644 (file)
@@ -46,7 +46,8 @@ enum { /** Error codes */
     JBEQERROR = 9009, /**< Query generic error. */
     JBEQUPDFAILED = 9010, /**< Updating failed. */
     JBEQONEEMATCH = 9011, /**< Only one $elemMatch allowed in the fieldpath. */
-    JBEQINCEXCL = 9012 /**< $fields hint cannot mix include and exclude fields */
+    JBEQINCEXCL = 9012, /**< $fields hint cannot mix include and exclude fields */
+    JBEQACTKEY = 9013 /**< action key in $do block can only be one of: $join */
 };
 
 enum { /** Database open modes */
index 8a113f3..33c9989 100644 (file)
@@ -4057,8 +4057,28 @@ void testTicket43() {
      objects with matching oids from collectionname
 
      {..., $do : {fpath : {$join : 'collectionname'}} }
-
+     Second form:
+     {..., $do : {fpath : {$join : {$ref : 'collectionname', $fields : {foo:1}} }} }
     */
+
+    bson bsq1;
+    bson_init_as_query(&bsq1);
+    bson_append_start_object(&bsq1, "$do");
+    bson_append_start_object(&bsq1, "homeref");
+    bson_append_start_object(&bsq1, "$join");
+    bson_append_string(&bsq1, "$join", "home");
+    bson_append_finish_object(&bsq1);
+    bson_append_finish_object(&bsq1);
+    bson_append_finish_object(&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);
+    ejdbquerydel(q1);
+
+    bson_destroy(&bsq1);
 }
 
 int main() {