summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec/projection.cpp
diff options
context:
space:
mode:
authorHari Khalsa <hkhalsa@10gen.com>2013-11-06 14:29:30 -0500
committerHari Khalsa <hkhalsa@10gen.com>2013-11-08 08:59:34 -0500
commit222862b67b7cf49075e72457808d297d8438f5d0 (patch)
treedd5cdf39afac4d0e5b54fd28c1072de953dba197 /src/mongo/db/exec/projection.cpp
parentfb7dfc56527680bd386de0a2024f7a2bfd216ad1 (diff)
downloadmongo-222862b67b7cf49075e72457808d297d8438f5d0.tar.gz
SERVER-10026 full projection support
Diffstat (limited to 'src/mongo/db/exec/projection.cpp')
-rw-r--r--src/mongo/db/exec/projection.cpp69
1 files changed, 62 insertions, 7 deletions
diff --git a/src/mongo/db/exec/projection.cpp b/src/mongo/db/exec/projection.cpp
index c208999a77e..c489dc0da33 100644
--- a/src/mongo/db/exec/projection.cpp
+++ b/src/mongo/db/exec/projection.cpp
@@ -30,15 +30,24 @@
#include "mongo/db/diskloc.h"
#include "mongo/db/exec/plan_stage.h"
-#include "mongo/db/exec/projection_executor.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/matcher/expression.h"
+#include "mongo/util/mongoutils/str.h"
namespace mongo {
- ProjectionStage::ProjectionStage(ParsedProjection* projection, WorkingSet* ws, PlanStage* child,
+ ProjectionStage::ProjectionStage(LiteProjection* liteProjection,
+ bool covered,
+ const MatchExpression* fullExpression,
+ WorkingSet* ws,
+ PlanStage* child,
const MatchExpression* filter)
- : _projection(projection), _ws(ws), _child(child), _filter(filter) { }
+ : _liteProjection(liteProjection),
+ _covered(covered),
+ _ws(ws),
+ _child(child),
+ _filter(filter),
+ _fullExpression(fullExpression) { }
ProjectionStage::~ProjectionStage() { }
@@ -53,11 +62,57 @@ namespace mongo {
if (PlanStage::ADVANCED == status) {
WorkingSetMember* member = _ws->get(id);
- Status status = ProjectionExecutor::apply(_projection, member);
- if (!status.isOK()) {
- warning() << "Couldn't execute projection: " << status.toString() << endl;
- return PlanStage::FAILURE;
+
+ BSONObj newObj;
+ if (_covered) {
+ // TODO: Rip execution out of the lite_projection and pass a WSM to something
+ // which does the right thing depending on the covered vs. noncovered cases.
+ BSONObjBuilder bob;
+ if (_liteProjection->_includeID) {
+ BSONElement elt;
+ member->getFieldDotted("_id", &elt);
+ verify(!elt.eoo());
+ bob.appendAs(elt, "_id");
+ }
+
+ BSONObjIterator it(_liteProjection->_source);
+ while (it.more()) {
+ BSONElement specElt = it.next();
+ if (mongoutils::str::equals("_id", specElt.fieldName())) {
+ continue;
+ }
+
+ BSONElement keyElt;
+ // We can project a field that doesn't exist. We just ignore it.
+ if (member->getFieldDotted(specElt.fieldName(), &keyElt) && !keyElt.eoo()) {
+ bob.appendAs(keyElt, specElt.fieldName());
+ }
+ }
+ newObj = bob.obj();
}
+ else {
+ // Planner should have done this.
+ verify(member->hasObj());
+
+ MatchDetails matchDetails;
+ matchDetails.requestElemMatchKey();
+
+ if (_liteProjection->transformRequiresDetails()) {
+ verify(_fullExpression->matchesBSON(member->obj, &matchDetails));
+ }
+
+ Status projStatus = _liteProjection->transform(member->obj, &newObj, &matchDetails);
+ if (!projStatus.isOK()) {
+ warning() << "Couldn't execute projection, status = " << projStatus.toString() << endl;
+ return PlanStage::FAILURE;
+ }
+ }
+
+ member->state = WorkingSetMember::OWNED_OBJ;
+ member->obj = newObj;
+ member->keyData.clear();
+ member->loc = DiskLoc();
+
*out = id;
++_commonStats.advanced;
}