summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHari Khalsa <hkhalsa@10gen.com>2014-04-24 08:58:00 -0400
committerHari Khalsa <hkhalsa@10gen.com>2014-04-24 09:09:00 -0400
commit8ef75e363a3ea17f6a5f7be55460c528c6bae32f (patch)
treee9cc6a5e194a66b18ce2b13ff5000b5283d7e740
parent7f8f4b7d140639b00b59047e600c9c793da3a3de (diff)
downloadmongo-8ef75e363a3ea17f6a5f7be55460c528c6bae32f.tar.gz
SERVER-13632 clean up stagedebug cmd so passing collection around is easlier
-rw-r--r--jstests/core/stages_and_hash.js8
-rw-r--r--jstests/core/stages_and_sorted.js5
-rw-r--r--jstests/core/stages_collection_scan.js17
-rw-r--r--jstests/core/stages_fetch.js9
-rw-r--r--jstests/core/stages_ixscan.js25
-rw-r--r--jstests/core/stages_limit_skip.js7
-rw-r--r--jstests/core/stages_mergesort.js7
-rw-r--r--jstests/core/stages_or.js9
-rw-r--r--jstests/core/stages_text.js8
-rw-r--r--src/mongo/db/exec/stagedebug_cmd.cpp85
10 files changed, 109 insertions, 71 deletions
diff --git a/jstests/core/stages_and_hash.js b/jstests/core/stages_and_hash.js
index 42ae0c8e34d..b16c023fe2b 100644
--- a/jstests/core/stages_and_hash.js
+++ b/jstests/core/stages_and_hash.js
@@ -1,6 +1,8 @@
t = db.stages_and_hashed;
t.drop();
+var collname = "stages_and_hashed";
+
var N = 50;
for (var i = 0; i < N; ++i) {
t.insert({foo: i, bar: N - i, baz: i});
@@ -23,20 +25,20 @@ ixscan2 = {ixscan: {args:{name: "stages_and_hashed", keyPattern:{bar: 1},
// bar = 50 - foo
// Intersection is (foo=0 bar=50, foo=1 bar=49, ..., foo=10 bar=40)
andix1ix2 = {andHash: {args: { nodes: [ixscan1, ixscan2]}}}
-res = db.runCommand({stageDebug: andix1ix2});
+res = db.runCommand({stageDebug: {plan: andix1ix2, collection: collname}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 11);
// This should raise an error as we can't filter on baz since we haven't done a fetch and it's not
// in the index data.
andix1ix2badfilter = {andHash: {filter: {baz: 5}, args: {nodes: [ixscan1, ixscan2]}}};
-res = db.runCommand({stageDebug: andix1ix2badfilter});
+res = db.runCommand({stageDebug: {collection: collname, plan:andix1ix2badfilter}});
assert.eq(res.ok, 0);
// Filter predicates from 2 indices. Tests that we union the idx info.
andix1ix2filter = {andHash: {filter: {bar: {$in: [45, 46, 48]},
foo: {$in: [4,5,6]}},
args: {nodes: [ixscan1, ixscan2]}}};
-res = db.runCommand({stageDebug: andix1ix2filter});
+res = db.runCommand({stageDebug: {collection: collname, plan: andix1ix2filter}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 2);
diff --git a/jstests/core/stages_and_sorted.js b/jstests/core/stages_and_sorted.js
index 96fe82049c5..9b7bf7ad415 100644
--- a/jstests/core/stages_and_sorted.js
+++ b/jstests/core/stages_and_sorted.js
@@ -1,5 +1,6 @@
t = db.stages_and_sorted;
t.drop();
+var collname = "stages_and_sorted";
var N = 10;
for (var i = 0; i < N; ++i) {
@@ -38,13 +39,13 @@ ixscan3 = {ixscan: {args:{name: "stages_and_sorted", keyPattern:{baz: 1},
// Intersect foo==1 with bar==1 with baz==12.
andix1ix2 = {andSorted: {args: {nodes: [ixscan1, ixscan2, ixscan3]}}};
-res = db.runCommand({stageDebug: andix1ix2});
+res = db.runCommand({stageDebug: {collection: collname, plan: andix1ix2}});
printjson(res);
assert.eq(res.ok, 1);
assert.eq(res.results.length, N);
// Might as well make sure that hashed does the same thing.
andix1ix2hash = {andHash: {args: {nodes: [ixscan1, ixscan2, ixscan3]}}};
-res = db.runCommand({stageDebug: andix1ix2hash});
+res = db.runCommand({stageDebug: {collection: collname, plan: andix1ix2hash}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, N);
diff --git a/jstests/core/stages_collection_scan.js b/jstests/core/stages_collection_scan.js
index 6adfe971b58..fe93a9b6bf0 100644
--- a/jstests/core/stages_collection_scan.js
+++ b/jstests/core/stages_collection_scan.js
@@ -1,38 +1,39 @@
// Test basic query stage collection scan functionality.
t = db.stages_collection_scan;
t.drop();
+var collname = "stages_collection_scan";
var N = 50;
for (var i = 0; i < N; ++i) {
t.insert({foo: i});
}
-forward = {cscan: {args: {name: "stages_collection_scan", direction: 1}}}
-res = db.runCommand({stageDebug: forward});
+forward = {cscan: {args: {direction: 1}}}
+res = db.runCommand({stageDebug: {collection: collname, plan: forward}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, N);
assert.eq(res.results[0].foo, 0);
assert.eq(res.results[49].foo, 49);
// And, backwards.
-backward = {cscan: {args: {name: "stages_collection_scan", direction: -1}}}
-res = db.runCommand({stageDebug: backward});
+backward = {cscan: {args: {direction: -1}}}
+res = db.runCommand({stageDebug: {collection: collname, plan: backward}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, N);
assert.eq(res.results[0].foo, 49);
assert.eq(res.results[49].foo, 0);
-forwardFiltered = {cscan: {args: {name: "stages_collection_scan", direction: 1},
+forwardFiltered = {cscan: {args: {direction: 1},
filter: {foo: {$lt: 25}}}}
-res = db.runCommand({stageDebug: forwardFiltered});
+res = db.runCommand({stageDebug: {collection: collname, plan: forwardFiltered}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 25);
assert.eq(res.results[0].foo, 0);
assert.eq(res.results[24].foo, 24);
-backwardFiltered = {cscan: {args: {name: "stages_collection_scan", direction: -1},
+backwardFiltered = {cscan: {args: {direction: -1},
filter: {foo: {$lt: 25}}}}
-res = db.runCommand({stageDebug: backwardFiltered});
+res = db.runCommand({stageDebug: {collection: collname, plan: backwardFiltered}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 25);
assert.eq(res.results[0].foo, 24);
diff --git a/jstests/core/stages_fetch.js b/jstests/core/stages_fetch.js
index 4f84bf05a17..02b209295d9 100644
--- a/jstests/core/stages_fetch.js
+++ b/jstests/core/stages_fetch.js
@@ -1,6 +1,7 @@
// Test basic fetch functionality.
t = db.stages_fetch;
t.drop();
+var collname = "stages_fetch";
var N = 50;
for (var i = 0; i < N; ++i) {
@@ -11,21 +12,21 @@ t.ensureIndex({foo: 1});
// 20 <= foo <= 30
// bar == 25 (not covered, should error.)
-ixscan1 = {ixscan: {args:{name: "stages_fetch", keyPattern:{foo:1},
+ixscan1 = {ixscan: {args:{keyPattern:{foo:1},
startKey: {"": 20},
endKey: {"" : 30}, endKeyInclusive: true,
direction: 1},
filter: {bar: 25}}};
-res = db.runCommand({stageDebug: ixscan1});
+res = db.runCommand({stageDebug: {collection: collname, plan: ixscan1}});
assert.eq(res.ok, 0);
// Now, add a fetch. We should be able to filter on the non-covered field since we fetched the obj.
-ixscan2 = {ixscan: {args:{name: "stages_fetch", keyPattern:{foo:1},
+ixscan2 = {ixscan: {args:{keyPattern:{foo:1},
startKey: {"": 20},
endKey: {"" : 30}, endKeyInclusive: true,
direction: 1}}}
fetch = {fetch: {args: {node: ixscan2}, filter: {bar: 25}}}
-res = db.runCommand({stageDebug: fetch});
+res = db.runCommand({stageDebug: {collection: collname, plan: fetch}});
printjson(res);
assert.eq(res.ok, 1);
assert.eq(res.results.length, 1);
diff --git a/jstests/core/stages_ixscan.js b/jstests/core/stages_ixscan.js
index a2cf628d551..743bb727ccb 100644
--- a/jstests/core/stages_ixscan.js
+++ b/jstests/core/stages_ixscan.js
@@ -1,6 +1,7 @@
// Test basic query stage index scan functionality.
t = db.stages_ixscan;
t.drop();
+var collname = "stages_ixscan";
var N = 50;
for (var i = 0; i < N; ++i) {
@@ -11,60 +12,60 @@ t.ensureIndex({foo: 1})
t.ensureIndex({foo: 1, baz: 1});
// foo <= 20
-ixscan1 = {ixscan: {args:{name: "stages_ixscan", keyPattern:{foo: 1},
+ixscan1 = {ixscan: {args:{keyPattern:{foo: 1},
startKey: {"": 20},
endKey: {}, endKeyInclusive: true,
direction: -1}}};
-res = db.runCommand({stageDebug: ixscan1});
+res = db.runCommand({stageDebug: {collection: collname, plan: ixscan1}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 21);
// 20 <= foo < 30
-ixscan1 = {ixscan: {args:{name: "stages_ixscan", keyPattern:{foo: 1},
+ixscan1 = {ixscan: {args:{keyPattern:{foo: 1},
startKey: {"": 20},
endKey: {"" : 30}, endKeyInclusive: false,
direction: 1}}};
-res = db.runCommand({stageDebug: ixscan1});
+res = db.runCommand({stageDebug: {collection: collname, plan: ixscan1}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 10);
// 20 <= foo <= 30
-ixscan1 = {ixscan: {args:{name: "stages_ixscan", keyPattern:{foo: 1},
+ixscan1 = {ixscan: {args:{keyPattern:{foo: 1},
startKey: {"": 20},
endKey: {"" : 30}, endKeyInclusive: true,
direction: 1}}};
-res = db.runCommand({stageDebug: ixscan1});
+res = db.runCommand({stageDebug: {collection: collname, plan: ixscan1}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 11);
// 20 <= foo <= 30
// foo == 25
-ixscan1 = {ixscan: {args:{name: "stages_ixscan", keyPattern:{foo: 1},
+ixscan1 = {ixscan: {args:{keyPattern:{foo: 1},
startKey: {"": 20},
endKey: {"" : 30}, endKeyInclusive: true,
direction: 1},
filter: {foo: 25}}};
-res = db.runCommand({stageDebug: ixscan1});
+res = db.runCommand({stageDebug: {collection: collname, plan: ixscan1}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 1);
// 20 <= foo <= 30
// baz == 25 (in index so we can match against it.)
-ixscan1 = {ixscan: {args:{name: "stages_ixscan", keyPattern:{foo:1, baz: 1},
+ixscan1 = {ixscan: {args:{keyPattern:{foo:1, baz: 1},
startKey: {"": 20, "":MinKey},
endKey: {"" : 30, "":MaxKey}, endKeyInclusive: true,
direction: 1},
filter: {baz: 25}}};
-res = db.runCommand({stageDebug: ixscan1});
+res = db.runCommand({stageDebug: {collection: collname, plan: ixscan1}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 1);
// 20 <= foo <= 30
// bar == 25 (not covered, should error.)
-ixscan1 = {ixscan: {args:{name: "stages_ixscan", keyPattern:{foo:1, baz: 1},
+ixscan1 = {ixscan: {args:{keyPattern:{foo:1, baz: 1},
startKey: {"": 20, "":MinKey},
endKey: {"" : 30, "":MaxKey}, endKeyInclusive: true,
direction: 1},
filter: {bar: 25}}};
-res = db.runCommand({stageDebug: ixscan1});
+res = db.runCommand({stageDebug: {collection: collname, plan: ixscan1}});
assert.eq(res.ok, 0);
diff --git a/jstests/core/stages_limit_skip.js b/jstests/core/stages_limit_skip.js
index 45564c75024..4586033cfff 100644
--- a/jstests/core/stages_limit_skip.js
+++ b/jstests/core/stages_limit_skip.js
@@ -1,6 +1,7 @@
// Test limit and skip
t = db.stages_limit_skip;
t.drop();
+var collname = "stages_limit_skip";
var N = 50;
for (var i = 0; i < N; ++i) {
@@ -11,12 +12,12 @@ t.ensureIndex({foo: 1})
// foo <= 20, decreasing
// Limit of 5 results.
-ixscan1 = {ixscan: {args:{name: "stages_limit_skip", keyPattern:{foo: 1},
+ixscan1 = {ixscan: {args:{keyPattern:{foo: 1},
startKey: {"": 20},
endKey: {}, endKeyInclusive: true,
direction: -1}}};
limit1 = {limit: {args: {node: ixscan1, num: 5}}}
-res = db.runCommand({stageDebug: limit1});
+res = db.runCommand({stageDebug: {collection: collname, plan: limit1}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 5);
assert.eq(res.results[0].foo, 20);
@@ -25,7 +26,7 @@ assert.eq(res.results[4].foo, 16);
// foo <= 20, decreasing
// Skip 5 results.
skip1 = {skip: {args: {node: ixscan1, num: 5}}}
-res = db.runCommand({stageDebug: skip1});
+res = db.runCommand({stageDebug: {collection: collname, plan: skip1}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 16);
assert.eq(res.results[0].foo, 15);
diff --git a/jstests/core/stages_mergesort.js b/jstests/core/stages_mergesort.js
index ecbed024085..ac11f3164c7 100644
--- a/jstests/core/stages_mergesort.js
+++ b/jstests/core/stages_mergesort.js
@@ -1,6 +1,7 @@
// Test query stage merge sorting.
t = db.stages_mergesort;
t.drop();
+var collname = "stages_mergesort";
var N = 10;
for (var i = 0; i < N; ++i) {
@@ -13,18 +14,18 @@ t.ensureIndex({baz: 1, bar:1})
// foo == 1
// We would (internally) use "": MinKey and "": MaxKey for the bar index bounds.
-ixscan1 = {ixscan: {args:{name: "stages_mergesort", keyPattern:{foo: 1, bar:1},
+ixscan1 = {ixscan: {args:{keyPattern:{foo: 1, bar:1},
startKey: {"": 1, "": 0},
endKey: {"": 1, "": 100000}, endKeyInclusive: true,
direction: 1}}};
// baz == 1
-ixscan2 = {ixscan: {args:{name: "stages_mergesort", keyPattern:{baz: 1, bar:1},
+ixscan2 = {ixscan: {args:{keyPattern:{baz: 1, bar:1},
startKey: {"": 1, "": 0},
endKey: {"": 1, "": 100000}, endKeyInclusive: true,
direction: 1}}};
mergesort = {mergeSort: {args: {nodes: [ixscan1, ixscan2], pattern: {bar: 1}}}};
-res = db.runCommand({stageDebug: mergesort});
+res = db.runCommand({stageDebug: {plan: mergesort, collection: collname}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 2 * N);
assert.eq(res.results[0].bar, 0);
diff --git a/jstests/core/stages_or.js b/jstests/core/stages_or.js
index bb0e02b11d4..92f85b15694 100644
--- a/jstests/core/stages_or.js
+++ b/jstests/core/stages_or.js
@@ -1,6 +1,7 @@
// Test basic OR functionality
t = db.stages_or;
t.drop();
+var collname = "stages_or";
var N = 50;
for (var i = 0; i < N; ++i) {
@@ -12,22 +13,22 @@ t.ensureIndex({bar: 1})
t.ensureIndex({baz: 1})
// baz >= 40
-ixscan1 = {ixscan: {args:{name: "stages_or", keyPattern:{baz: 1},
+ixscan1 = {ixscan: {args:{keyPattern:{baz: 1},
startKey: {"": 40}, endKey: {},
endKeyInclusive: true, direction: 1}}};
// foo >= 40
-ixscan2 = {ixscan: {args:{name: "stages_or", keyPattern:{foo: 1},
+ixscan2 = {ixscan: {args:{keyPattern:{foo: 1},
startKey: {"": 40}, endKey: {},
endKeyInclusive: true, direction: 1}}};
// OR of baz and foo. Baz == foo and we dedup.
orix1ix2 = {or: {args: {nodes: [ixscan1, ixscan2], dedup:true}}};
-res = db.runCommand({stageDebug: orix1ix2});
+res = db.runCommand({stageDebug: {collection: collname, plan: orix1ix2}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 10);
// No deduping, 2x the results.
orix1ix2nodd = {or: {args: {nodes: [ixscan1, ixscan2], dedup:false}}};
-res = db.runCommand({stageDebug: orix1ix2nodd});
+res = db.runCommand({stageDebug: {collection: collname, plan: orix1ix2nodd}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 20);
diff --git a/jstests/core/stages_text.js b/jstests/core/stages_text.js
index 8407ffe1e14..077416b98af 100644
--- a/jstests/core/stages_text.js
+++ b/jstests/core/stages_text.js
@@ -2,16 +2,20 @@
t = db.stages_text;
t.drop();
+var collname = "stages_text";
+
t.save({x: "az b x"})
t.ensureIndex({x: "text"})
// We expect to retrieve 'b'
-res = db.runCommand({stageDebug: {text: {args: {name: "test.stages_text", search: "b"}}}});
+res = db.runCommand({stageDebug: {collection: collname,
+ plan: {text: {args: {search: "b"}}}}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 1);
// I have not been indexed yet.
-res = db.runCommand({stageDebug: {text: {args: {name: "test.stages_text", search: "hari"}}}});
+res = db.runCommand({stageDebug: {collection: collname,
+ plan: {text: {args: {search: "hari"}}}}});
assert.eq(res.ok, 1);
assert.eq(res.results.length, 0);
diff --git a/src/mongo/db/exec/stagedebug_cmd.cpp b/src/mongo/db/exec/stagedebug_cmd.cpp
index c0596bc16c1..800b5ce1701 100644
--- a/src/mongo/db/exec/stagedebug_cmd.cpp
+++ b/src/mongo/db/exec/stagedebug_cmd.cpp
@@ -55,7 +55,7 @@ namespace mongo {
/**
* A command for manually constructing a query tree and running it.
*
- * db.runCommand({stageDebug: rootNode})
+ * db.runCommand({stageDebug: {collection: collname, plan: rootNode}})
*
* The value of the filter field is a BSONObj that specifies values that fields must have. What
* you'd pass to a matcher.
@@ -63,12 +63,12 @@ namespace mongo {
* Leaf Nodes:
*
* node -> {ixscan: {filter: {FILTER},
- * args: {name: "collectionname", indexKeyPattern: kpObj, start: startObj,
+ * args: {indexKeyPattern: kpObj, start: startObj,
* stop: stopObj, endInclusive: true/false, direction: -1/1,
* limit: int}}}
- * node -> {cscan: {filter: {filter}, args: {name: "collectionname", direction: -1/1}}}
+ * node -> {cscan: {filter: {filter}, args: {direction: -1/1}}}
* TODO: language for text.
- * node -> {text: {filter: {filter}, args: {name: "collectionname", search: "searchstr"}}}
+ * node -> {text: {filter: {filter}, args: {search: "searchstr"}}}
*
* Internal Nodes:
*
@@ -80,7 +80,6 @@ namespace mongo {
* node -> {skip: {args: {node: node, num: posint}}}
* node -> {sort: {args: {node: node, pattern: objWithSortCriterion }}}
* node -> {mergeSort: {args: {nodes: [node, node], pattern: objWithSortCriterion}}}
- * node -> {cscan: {filter: {filter}, args: {name: "collectionname" }}}
*
* Forthcoming Nodes:
*
@@ -111,13 +110,34 @@ namespace mongo {
if (argElt.eoo() || !argElt.isABSONObj()) { return false; }
BSONObj argObj = argElt.Obj();
- OwnedPointerVector<MatchExpression> exprs;
- auto_ptr<WorkingSet> ws(new WorkingSet());
+ // Pull out the collection name.
+ BSONElement collElt = argObj["collection"];
+ if (collElt.eoo() || (String != collElt.type())) {
+ return false;
+ }
+ string collName = collElt.String();
+ // Need a context to get the actual Collection*
Client::ReadContext ctx(dbname);
- PlanStage* userRoot = parseQuery(ctx.ctx().db(), argObj, ws.get(), &exprs);
- uassert(16911, "Couldn't parse plan from " + argObj.toString(), NULL != userRoot);
+ // Make sure the collection is valid.
+ Database* db = ctx.ctx().db();
+ Collection* collection = db->getCollection(db->name() + '.' + collName);
+ uassert(17446, "Couldn't find the collection " + collName, NULL != collection);
+
+ // Pull out the plan
+ BSONElement planElt = argObj["plan"];
+ if (planElt.eoo() || !planElt.isABSONObj()) {
+ return false;
+ }
+ BSONObj planObj = planElt.Obj();
+
+ // Parse the plan into these.
+ OwnedPointerVector<MatchExpression> exprs;
+ auto_ptr<WorkingSet> ws(new WorkingSet());
+
+ PlanStage* userRoot = parseQuery(collection, planObj, ws.get(), &exprs);
+ uassert(16911, "Couldn't parse plan from " + cmdObj.toString(), NULL != userRoot);
// Add a fetch at the top for the user so we can get obj back for sure.
// TODO: Do we want to do this for the user? I think so.
@@ -135,8 +155,11 @@ namespace mongo {
return true;
}
- PlanStage* parseQuery(Database* db, BSONObj obj, WorkingSet* workingSet,
+ PlanStage* parseQuery(Collection* collection,
+ BSONObj obj,
+ WorkingSet* workingSet,
OwnedPointerVector<MatchExpression>* exprs) {
+
BSONElement firstElt = obj.firstElement();
if (!firstElt.isABSONObj()) { return NULL; }
BSONObj paramObj = firstElt.Obj();
@@ -174,13 +197,12 @@ namespace mongo {
string nodeName = firstElt.fieldName();
if ("ixscan" == nodeName) {
-
- Collection* collection = db->getCollection( db->name() + "." + nodeArgs["name"].String() );
- uassert(16913, "Can't find collection " + nodeArgs["name"].String(), collection);
+ // This'll throw if it's not an obj but that's OK.
+ BSONObj keyPatternObj = nodeArgs["keyPattern"].Obj();
IndexDescriptor* desc =
- collection->getIndexCatalog()->findIndexByKeyPattern(nodeArgs["keyPattern"].Obj());
- uassert(16890, "Can't find index: " + nodeArgs["keyPattern"].Obj().toString(), desc );
+ collection->getIndexCatalog()->findIndexByKeyPattern(keyPatternObj);
+ uassert(16890, "Can't find index: " + keyPatternObj.toString(), desc);
IndexScanParams params;
params.descriptor = desc;
@@ -205,7 +227,7 @@ namespace mongo {
uassert(16922, "node of AND isn't an obj?: " + e.toString(),
e.isABSONObj());
- PlanStage* subNode = parseQuery(db, e.Obj(), workingSet, exprs);
+ PlanStage* subNode = parseQuery(collection, e.Obj(), workingSet, exprs);
uassert(16923, "Can't parse sub-node of AND: " + e.Obj().toString(),
NULL != subNode);
// takes ownership
@@ -231,7 +253,7 @@ namespace mongo {
uassert(16925, "node of AND isn't an obj?: " + e.toString(),
e.isABSONObj());
- PlanStage* subNode = parseQuery(db, e.Obj(), workingSet, exprs);
+ PlanStage* subNode = parseQuery(collection, e.Obj(), workingSet, exprs);
uassert(16926, "Can't parse sub-node of AND: " + e.Obj().toString(),
NULL != subNode);
// takes ownership
@@ -254,7 +276,7 @@ namespace mongo {
while (it.more()) {
BSONElement e = it.next();
if (!e.isABSONObj()) { return NULL; }
- PlanStage* subNode = parseQuery(db, e.Obj(), workingSet, exprs);
+ PlanStage* subNode = parseQuery(collection, e.Obj(), workingSet, exprs);
uassert(16936, "Can't parse sub-node of OR: " + e.Obj().toString(),
NULL != subNode);
// takes ownership
@@ -266,7 +288,10 @@ namespace mongo {
else if ("fetch" == nodeName) {
uassert(16929, "Node argument must be provided to fetch",
nodeArgs["node"].isABSONObj());
- PlanStage* subNode = parseQuery(db, nodeArgs["node"].Obj(), workingSet, exprs);
+ PlanStage* subNode = parseQuery(collection,
+ nodeArgs["node"].Obj(),
+ workingSet,
+ exprs);
return new FetchStage(workingSet, subNode, matcher);
}
else if ("limit" == nodeName) {
@@ -276,7 +301,10 @@ namespace mongo {
nodeArgs["node"].isABSONObj());
uassert(16931, "Num argument must be provided to limit",
nodeArgs["num"].isNumber());
- PlanStage* subNode = parseQuery(db, nodeArgs["node"].Obj(), workingSet, exprs);
+ PlanStage* subNode = parseQuery(collection,
+ nodeArgs["node"].Obj(),
+ workingSet,
+ exprs);
return new LimitStage(nodeArgs["num"].numberInt(), workingSet, subNode);
}
else if ("skip" == nodeName) {
@@ -286,16 +314,15 @@ namespace mongo {
nodeArgs["node"].isABSONObj());
uassert(16933, "Num argument must be provided to skip",
nodeArgs["num"].isNumber());
- PlanStage* subNode = parseQuery(db, nodeArgs["node"].Obj(), workingSet, exprs);
+ PlanStage* subNode = parseQuery(collection,
+ nodeArgs["node"].Obj(),
+ workingSet,
+ exprs);
return new SkipStage(nodeArgs["num"].numberInt(), workingSet, subNode);
}
else if ("cscan" == nodeName) {
CollectionScanParams params;
-
- // What collection?
- string ns = db->name() + "." + nodeArgs["name"].String();
- params.collection = db->getCollection(ns);
- uassert(16962, "Can't find collection " + ns, NULL != params.collection );
+ params.collection = collection;
// What direction?
uassert(16963, "Direction argument must be specified and be a number",
@@ -340,7 +367,7 @@ namespace mongo {
uassert(16973, "node of mergeSort isn't an obj?: " + e.toString(),
e.isABSONObj());
- PlanStage* subNode = parseQuery(db, e.Obj(), workingSet, exprs);
+ PlanStage* subNode = parseQuery(collection, e.Obj(), workingSet, exprs);
uassert(16974, "Can't parse sub-node of mergeSort: " + e.Obj().toString(),
NULL != subNode);
// takes ownership
@@ -349,10 +376,8 @@ namespace mongo {
return mergeStage.release();
}
else if ("text" == nodeName) {
- string ns = nodeArgs["name"].String();
string search = nodeArgs["search"].String();
- Collection* collection = db->getCollection( ns );
- uassert(17193, "Can't find namespace " + ns, collection);
+
vector<IndexDescriptor*> idxMatches;
collection->getIndexCatalog()->findIndexByType("text", idxMatches);
uassert(17194, "Expected exactly one text index", idxMatches.size() == 1);