diff options
author | Hari Khalsa <hkhalsa@10gen.com> | 2014-04-24 08:58:00 -0400 |
---|---|---|
committer | Hari Khalsa <hkhalsa@10gen.com> | 2014-04-24 09:09:00 -0400 |
commit | 8ef75e363a3ea17f6a5f7be55460c528c6bae32f (patch) | |
tree | e9cc6a5e194a66b18ce2b13ff5000b5283d7e740 | |
parent | 7f8f4b7d140639b00b59047e600c9c793da3a3de (diff) | |
download | mongo-8ef75e363a3ea17f6a5f7be55460c528c6bae32f.tar.gz |
SERVER-13632 clean up stagedebug cmd so passing collection around is easlier
-rw-r--r-- | jstests/core/stages_and_hash.js | 8 | ||||
-rw-r--r-- | jstests/core/stages_and_sorted.js | 5 | ||||
-rw-r--r-- | jstests/core/stages_collection_scan.js | 17 | ||||
-rw-r--r-- | jstests/core/stages_fetch.js | 9 | ||||
-rw-r--r-- | jstests/core/stages_ixscan.js | 25 | ||||
-rw-r--r-- | jstests/core/stages_limit_skip.js | 7 | ||||
-rw-r--r-- | jstests/core/stages_mergesort.js | 7 | ||||
-rw-r--r-- | jstests/core/stages_or.js | 9 | ||||
-rw-r--r-- | jstests/core/stages_text.js | 8 | ||||
-rw-r--r-- | src/mongo/db/exec/stagedebug_cmd.cpp | 85 |
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); |