From eadeb1b138f1593e18113c931e825eb473753262 Mon Sep 17 00:00:00 2001 From: adam Date: Sat, 10 Aug 2013 19:34:00 +0700 Subject: #15 working in mongo $(projection) --- tcejdb/bson.c | 1 + tcejdb/bson.h | 1 + tcejdb/ejdb.c | 37 +++++++++++++++++++++++++++++++++++++ tcejdb/ejdb_private.h | 5 +++++ 4 files changed, 44 insertions(+) (limited to 'tcejdb') diff --git a/tcejdb/bson.c b/tcejdb/bson.c index e5afaa4..cb9e529 100644 --- a/tcejdb/bson.c +++ b/tcejdb/bson.c @@ -1,6 +1,7 @@ /* bson.c */ /* Copyright 2009, 2010 10gen Inc. + * Copyright (C) 2012-2013 Softmotions Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tcejdb/bson.h b/tcejdb/bson.h index 8640456..1b7907a 100644 --- a/tcejdb/bson.h +++ b/tcejdb/bson.h @@ -4,6 +4,7 @@ */ /* Copyright 2009-2012 10gen Inc. + * Copyright (C) 2012-2013 Softmotions Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tcejdb/ejdb.c b/tcejdb/ejdb.c index 435f59a..1932421 100644 --- a/tcejdb/ejdb.c +++ b/tcejdb/ejdb.c @@ -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}} diff --git a/tcejdb/ejdb_private.h b/tcejdb/ejdb_private.h index 66b6714..6afb716 100644 --- a/tcejdb/ejdb_private.h +++ b/tcejdb/ejdb_private.h @@ -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 */ -- cgit v1.2.3