#15 working in mongo $(projection)
authoradam <adamansky@gmail.com>
Sat, 10 Aug 2013 12:34:00 +0000 (19:34 +0700)
committeradam <adamansky@gmail.com>
Sat, 10 Aug 2013 12:34:00 +0000 (19:34 +0700)
tcejdb/bson.c
tcejdb/bson.h
tcejdb/ejdb.c
tcejdb/ejdb_private.h

index e5afaa4..cb9e529 100644 (file)
@@ -1,6 +1,7 @@
 /* bson.c */
 
 /*    Copyright 2009, 2010 10gen Inc.
+ *    Copyright (C) 2012-2013 Softmotions Ltd <info@softmotions.com>
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
index 8640456..1b7907a 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 /*    Copyright 2009-2012 10gen Inc.
+ *    Copyright (C) 2012-2013 Softmotions Ltd <info@softmotions.com>
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
index 435f59a..1932421 100644 (file)
@@ -511,6 +511,10 @@ EJQ* ejdbqueryhints(EJDB *jb, EJQ *q, const void *hintsbsdata) {
         bson_del(q->hints);
         q->hints = NULL;
     }
+    if (q->$ifields) {
+        tcmapdel(q->$ifields);
+        q->$ifields = NULL;
+    }
     q->hints = bs;
     return q;
 }
@@ -1642,6 +1646,10 @@ static void _qrydel(EJQ *q, bool freequery) {
         bson_del(q->hints);
         q->hints = NULL;
     }
+    if (q->$ifields) {
+        tcmapdel(q->$ifields);
+        q->$ifields = NULL;
+    }
     if (q->colbuf) {
         tcxstrdel(q->colbuf);
         q->colbuf = NULL;
@@ -2353,6 +2361,9 @@ static bool _qrydup(const EJQ *src, EJQ *target, uint32_t qflags) {
     if (src->hints) {
         target->hints = bson_dup(src->hints);
     }
+    if (src->$ifields) {
+        target->$ifields = tcmapdup(src->$ifields);
+    }
     if (src->orqlist) {
         target->orqlist = tclistnew2(TCLISTNUM(src->orqlist));
         for (int i = 0; i < TCLISTNUM(src->orqlist); ++i) {
@@ -3703,8 +3714,34 @@ static bool _qrypreprocess(EJCOLL *jcoll, EJQ *ejq, int qflags, EJQF **mqf,
                         _ejdbsetecode(jcoll->jb, JBEQINCEXCL, __FILE__, __LINE__, __func__);
                         return false;
                     }
+
                     *imode = inc;
                     const char *key = bson_iterator_key(&sit);
+
+                    char *pptr;
+                    //Checking the $(projection) operator.
+                    if (inc && (pptr = strstr(key, ".$")) && (*(pptr + 2) == '\0' || *(pptr + 2) == '.')) {// '.$' || '.$.'
+                        int dc = 0;
+                        for (int i = 0; *(key + i) != '\0'; ++i) {
+                            if (*(key + i) == '$' && (dc++ > 0)) break;
+                        }
+                        if (dc != 1) { //More than one '$' chars in projection it is invalid
+                            continue;
+                        }
+                        for (int i = 0; i < TCLISTNUM(qlist); ++i) {
+                            EJQF *qf = TCLISTVALPTR(qlist, i);
+                            int j;
+                            for (j = 0; *(key + j) != '\0' && *(key + j) == *(qf->fpath + j); ++j);
+                            if (key + j == pptr || key + j == pptr + 1) { //existing QF matched $(projection) prefix
+                                if (!ejq->$ifields) {
+                                    ejq->$ifields = tcmapnew2(TCMAPTINYBNUM);
+                                }
+                                tcmapput(ejq->$ifields, qf->fpath, qf->fpathsz, key, strlen(key));
+                                break;
+                            }
+                        }
+                        continue; //skip registering this fields in the fmap
+                    }
                     tcmapputkeep(fmap, key, strlen(key), &yes, sizeof (yes));
                 }
                 if (TCMAPRNUM(fmap) == 0) { //if {$fields : {}} we will force {$fields : {_id:1}}
index 66b6714..6afb716 100644 (file)
@@ -111,6 +111,11 @@ struct EJQ { /**> Query object. */
     TCLIST *orqlist; /**> List of $or joined query objects *EJQ */
     TCLIST *andqlist; /**> List of $and joined query objects *EJQ */
     bson *hints; /**> Hints bson object */
+    /**> Include $(projection) fields char* names.
+     *  Mapping EJQF fpath => $(projection) field name
+     *  http://docs.mongodb.org/manual/reference/projection/positional/#proj._S_
+     */
+    TCMAP *$ifields;
     uint32_t skip; /**> Number of records to skip. */
     uint32_t max; /**> Max number of results */
     uint32_t flags; /**> Control flags */