#15 #90
authoradam <adamansky@gmail.com>
Sat, 10 Aug 2013 17:42:11 +0000 (00:42 +0700)
committeradam <adamansky@gmail.com>
Sat, 10 Aug 2013 17:42:11 +0000 (00:42 +0700)
tcejdb/ejdb.c
tcejdb/testejdb/t2.c

index 1932421..95b1e58 100644 (file)
 
 #define JBISOPEN(JB_jb) ((JB_jb) && (JB_jb)->metadb && (JB_jb)->metadb->open) ? true : false
 
-#define JBISVALCOLNAME(JB_cname) ((JB_cname) && strlen(JB_cname) < JBMAXCOLNAMELEN && !strchr((JB_cname), '.'))
+#define JBISVALCOLNAME(JB_cname) ((JB_cname) && \
+    strlen(JB_cname) < JBMAXCOLNAMELEN && \
+    !strchr((JB_cname), '.') && \
+    !strchr((JB_cname), '$'))
 
 #define JBENSUREOPENLOCK(JB_jb, JB_lock, JB_ret)  \
                             assert(JB_jb); \
@@ -2497,10 +2500,11 @@ static bool _pushprocessedbson(EJDB *jb, EJQ *q, TCLIST *res, TCMAP *dfields, TC
         bool imode, const void *bsbuf, int bsbufsz) {
     assert(bsbuf && bsbufsz);
     bool rv = true;
-    if (!dfields && !ifields) { //Trivial case: no $do operations or $fields
+    if (!dfields && !ifields && !q->$ifields) { //Trivial case: no $do operations or $fields
         tclistpush(res, bsbuf, bsbufsz);
         return rv;
     }
+    int sp;
     char bstack[JBSBUFFERSZ];
     bson bsout;
     bson_init_on_stack(&bsout, bstack, bsbufsz, JBSBUFFERSZ);
@@ -2509,17 +2513,34 @@ static bool _pushprocessedbson(EJDB *jb, EJQ *q, TCLIST *res, TCMAP *dfields, TC
         rv = _exec$do(jb, q, dfields, bsbuf, &bsout);
     }
 
-    if (rv && ifields) { //$fields hints
+    if (rv && (ifields || q->$ifields)) { //$fields hints
+        TCMAP *_ifields = ifields;
+        if (!_ifields) {
+            _ifields = tcmapnew2(TCMAPRNUM(q->$ifields));
+        }
         char* inbuf = (bsout.finished) ? bsout.data : (char*) bsbuf;
         if (bsout.finished) {
             bson_init_size(&bsout, bson_size(&bsout));
         }
-        if (bson_strip(ifields, imode, inbuf, &bsout) != BSON_OK) {
+        if (q->$ifields) { //we have positional $(projection)
+            for (int i = 0; i < TCLISTNUM(q->qobjlist); ++i) {
+                EJQF *qf = TCLISTVALPTR(q->qobjlist, i);
+                const char *fpath = tcmapget(q->$ifields, qf->fpath, qf->fpathsz, &sp);
+                if (fpath) {
+                    //todo!!!!!
+                    fprintf(stderr, "\n\nfpath=%s", fpath);
+                }
+            }
+        }
+        if (bson_strip(_ifields, imode, inbuf, &bsout) != BSON_OK) {
             _ejdbsetecode(jb, JBEINVALIDBSON, __FILE__, __LINE__, __func__);
         }
         if (inbuf != bsbuf && inbuf != bstack) {
             TCFREE(inbuf);
         }
+        if (_ifields != ifields) {
+            tcmapdel(_ifields);
+        }
     }
 
     if (rv) {
index ecac42a..9085b2f 100644 (file)
@@ -4434,7 +4434,7 @@ void testTicket81() {
     CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
     bson_destroy(&b);
 
-    bson_init(&b); //true
+    bson_init(&b); //false
     bson_append_int(&b, "z", 22);
     bson_append_int(&b, "a", 1);
     bson_append_int(&b, "b", 3);
@@ -4505,6 +4505,70 @@ void testTicket81() {
     tcxstrdel(log);
 }
 
+//
+// https://github.com/Softmotions/ejdb/issues/15
+// http://docs.mongodb.org/manual/reference/projection/positional/#proj._S_
+
+void test$projection() {
+    EJCOLL *coll = ejdbcreatecoll(jb, "f_projection", NULL);
+    CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
+
+    bson b;
+    bson_oid_t oid;
+
+    bson_init(&b);
+    bson_append_int(&b, "z", 33);
+    bson_append_start_array(&b, "arr");
+    bson_append_int(&b, "0", 0);
+    bson_append_int(&b, "1", 1);
+    bson_append_int(&b, "2", 2);
+    bson_append_int(&b, "3", 3);
+    bson_append_finish_array(&b);
+    bson_finish(&b);
+    CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
+    bson_destroy(&b);
+
+    bson_init(&b);
+    bson_append_int(&b, "z", 33);
+    bson_append_start_array(&b, "arr");
+    bson_append_int(&b, "0", 3);
+    bson_append_int(&b, "1", 2);
+    bson_append_int(&b, "2", 1);
+    bson_append_int(&b, "3", 0);
+    bson_append_finish_array(&b);
+    bson_finish(&b);
+    CU_ASSERT_TRUE(ejdbsavebson(coll, &b, &oid));
+    bson_destroy(&b);
+
+    bson bshints;
+    bson_init_as_query(&bshints);
+    bson_append_start_object(&bshints, "$fields");
+    bson_append_int(&bshints, "arr.$", 1);
+    bson_append_finish_object(&bshints);
+    bson_finish(&bshints);
+    CU_ASSERT_FALSE_FATAL(bshints.err);
+
+    bson bsq1;
+    bson_init_as_query(&bsq1);
+    bson_append_int(&bsq1, "z", 33);
+    bson_append_start_object(&bsq1, "arr");
+    bson_append_int(&bsq1, "$gte", 2);
+    bson_append_finish_object(&bsq1);
+    bson_finish(&bsq1);
+
+    TCXSTR *log = tcxstrnew();
+    uint32_t count;
+    EJQ *q1 = ejdbcreatequery(jb, &bsq1, NULL, 0, &bshints);
+    CU_ASSERT_PTR_NOT_NULL_FATAL(q1);
+    TCLIST *q1res = ejdbqryexecute(coll, q1, &count, 0, log);
+
+    tclistdel(q1res);
+    ejdbquerydel(q1);
+    tcxstrdel(log);
+    bson_destroy(&bshints);
+    bson_destroy(&bsq1);
+}
+
 int main() {
     setlocale(LC_ALL, "en_US.UTF-8");
     CU_pSuite pSuite = NULL;
@@ -4578,6 +4642,7 @@ int main() {
             (NULL == CU_add_test(pSuite, "testTicket88", testTicket88)) ||
             (NULL == CU_add_test(pSuite, "testTicket89", testTicket89)) ||
             (NULL == CU_add_test(pSuite, "testTicket81", testTicket81)) ||
+            (NULL == CU_add_test(pSuite, "test$projection", test$projection)) ||
             (NULL == CU_add_test(pSuite, "testMetaInfo", testMetaInfo))
             ) {
         CU_cleanup_registry();