summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHari Khalsa <hkhalsa@10gen.com>2014-02-14 14:22:52 -0500
committerHari Khalsa <hkhalsa@10gen.com>2014-02-19 12:45:44 -0500
commitcfdf055eee1b1d0eed3d13c0c2d4d66a27dff662 (patch)
tree08fafe5cf887b3c12e3e07a36a4468db96b8d703
parent00c7183b1a79b795f3d39c9079bb2f795c1cabb6 (diff)
downloadmongo-cfdf055eee1b1d0eed3d13c0c2d4d66a27dff662.tar.gz
SERVER-10026 push access method name into index descriptor, pay attention to it in planning
-rw-r--r--src/mongo/db/catalog/index_catalog.cpp15
-rw-r--r--src/mongo/db/exec/sort.cpp3
-rw-r--r--src/mongo/db/index/index_descriptor.h23
-rw-r--r--src/mongo/db/index_names.cpp43
-rw-r--r--src/mongo/db/index_names.h45
-rw-r--r--src/mongo/db/query/get_runner.cpp2
-rw-r--r--src/mongo/db/query/index_entry.h87
-rw-r--r--src/mongo/db/query/plan_cache_test.cpp14
-rw-r--r--src/mongo/db/query/query_planner_test.cpp21
-rw-r--r--src/mongo/db/query/query_planner_text_test.cpp15
-rw-r--r--src/mongo/dbtests/namespacetests.cpp3
11 files changed, 177 insertions, 94 deletions
diff --git a/src/mongo/db/catalog/index_catalog.cpp b/src/mongo/db/catalog/index_catalog.cpp
index 15bb9e8bf79..817094d3a5e 100644
--- a/src/mongo/db/catalog/index_catalog.cpp
+++ b/src/mongo/db/catalog/index_catalog.cpp
@@ -99,8 +99,11 @@ namespace mongo {
continue;
}
+ BSONObj ownedInfoObj = id.info.obj().getOwned();
+ BSONObj keyPattern = ownedInfoObj.getObjectField("key");
IndexDescriptor* descriptor = new IndexDescriptor( _collection,
- id.info.obj().getOwned() );
+ _getAccessMethodName(keyPattern),
+ ownedInfoObj );
IndexCatalogEntry* entry = _setupInMemoryStructures( descriptor );
fassert( 17340, entry->isReady() );
@@ -352,7 +355,10 @@ namespace mongo {
invariant( _inProgress == false );
// need this first for names, etc...
- IndexDescriptor* descriptor = new IndexDescriptor( _collection, _spec );
+ BSONObj keyPattern = _spec.getObjectField("key");
+ IndexDescriptor* descriptor = new IndexDescriptor( _collection,
+ IndexNames::findPluginName(keyPattern),
+ _spec );
auto_ptr<IndexDescriptor> descriptorCleaner( descriptor );
_indexName = descriptor->indexName();
@@ -858,7 +864,8 @@ namespace mongo {
for ( size_t i = 0; i < toReturn.size(); i++ ) {
BSONObj spec = toReturn[i];
- IndexDescriptor desc( _collection, spec );
+ BSONObj keyPattern = spec.getObjectField("key");
+ IndexDescriptor desc( _collection, _getAccessMethodName(keyPattern), spec );
int idxNo = _details->_catalogFindIndexByName( desc.indexName(), true );
invariant( idxNo >= 0 );
@@ -1046,7 +1053,7 @@ namespace mongo {
IndexAccessMethod* IndexCatalog::_createAccessMethod( const IndexDescriptor* desc,
IndexCatalogEntry* entry ) {
- string type = _getAccessMethodName(desc->keyPattern());
+ const string& type = desc->getAccessMethodName();
if (IndexNames::HASHED == type)
return new HashAccessMethod( entry );
diff --git a/src/mongo/db/exec/sort.cpp b/src/mongo/db/exec/sort.cpp
index 3347e25ff39..7eda354b32e 100644
--- a/src/mongo/db/exec/sort.cpp
+++ b/src/mongo/db/exec/sort.cpp
@@ -30,6 +30,7 @@
#include <algorithm>
+#include "mongo/db/index_names.h"
#include "mongo/db/exec/working_set_common.h"
#include "mongo/db/exec/working_set_computed_data.h"
#include "mongo/db/index/btree_key_generator.h"
@@ -217,7 +218,7 @@ namespace mongo {
params.options = QueryPlannerParams::NO_TABLE_SCAN;
// We're creating a "virtual index" with key pattern equal to the sort order.
- IndexEntry sortOrder(sortObj, true, false, "doesnt_matter", BSONObj());
+ IndexEntry sortOrder(sortObj, IndexNames::BTREE, true, false, "doesnt_matter", BSONObj());
params.indices.push_back(sortOrder);
CanonicalQuery* rawQueryForSort;
diff --git a/src/mongo/db/index/index_descriptor.h b/src/mongo/db/index/index_descriptor.h
index 753091c7b5b..212c20c2485 100644
--- a/src/mongo/db/index/index_descriptor.h
+++ b/src/mongo/db/index/index_descriptor.h
@@ -56,9 +56,10 @@ namespace mongo {
* OnDiskIndexData is a pointer to the memory mapped per-index data.
* infoObj is a copy of the index-describing BSONObj contained in the OnDiskIndexData.
*/
- IndexDescriptor(Collection* collection, BSONObj infoObj)
+ IndexDescriptor(Collection* collection, const std::string& accessMethodName, BSONObj infoObj)
: _magic(123987),
_collection(collection),
+ _accessMethodName(accessMethodName),
_infoObj(infoObj.getOwned()),
_numFields(infoObj.getObjectField("key").nFields()),
_keyPattern(infoObj.getObjectField("key").getOwned()),
@@ -102,13 +103,16 @@ namespace mongo {
//
// Return the name of the index.
- const string& indexName() const { _checkOk(); return _indexName; }
+ const std::string& indexName() const { _checkOk(); return _indexName; }
// Return the name of the indexed collection.
- const string& parentNS() const { return _parentNS; }
+ const std::string& parentNS() const { return _parentNS; }
// Return the name of this index's storage area (database.table.$index)
- const string& indexNamespace() const { return _indexNamespace; }
+ const std::string& indexNamespace() const { return _indexNamespace; }
+
+ // Return the name of the access method we must use to access this index's data.
+ const std::string& getAccessMethodName() const { return _accessMethodName; }
//
// Properties every index has
@@ -144,7 +148,7 @@ namespace mongo {
//
// Return a (rather compact) string representation.
- string toString() const { _checkOk(); return _infoObj.toString(); }
+ std::string toString() const { _checkOk(); return _infoObj.toString(); }
// Return the info object.
const BSONObj& infoObj() const { _checkOk(); return _infoObj; }
@@ -166,6 +170,9 @@ namespace mongo {
// Related catalog information of the parent collection
Collection* _collection;
+ // What access method should we use for this index?
+ std::string _accessMethodName;
+
// The BSONObj describing the index. Accessed through the various members above.
const BSONObj _infoObj;
@@ -173,9 +180,9 @@ namespace mongo {
int64_t _numFields; // How many fields are indexed?
BSONObj _keyPattern;
- string _indexName;
- string _parentNS;
- string _indexNamespace;
+ std::string _indexName;
+ std::string _parentNS;
+ std::string _indexNamespace;
bool _isIdIndex;
bool _sparse;
bool _dropDups;
diff --git a/src/mongo/db/index_names.cpp b/src/mongo/db/index_names.cpp
index 9f0cace9d10..d3f79886e36 100644
--- a/src/mongo/db/index_names.cpp
+++ b/src/mongo/db/index_names.cpp
@@ -37,6 +37,7 @@ namespace mongo {
const string IndexNames::GEO_2DSPHERE = "2dsphere";
const string IndexNames::TEXT = "text";
const string IndexNames::HASHED = "hashed";
+ const string IndexNames::BTREE = "";
// static
string IndexNames::findPluginName(const BSONObj& keyPattern) {
@@ -48,7 +49,47 @@ namespace mongo {
return e.String();
}
- return "";
+ return IndexNames::BTREE;
+ }
+
+ // static
+ bool IndexNames::existedBefore24(const string& name) {
+ return name == IndexNames::BTREE
+ || name == IndexNames::GEO_2D
+ || name == IndexNames::GEO_HAYSTACK
+ || name == IndexNames::HASHED;
+ }
+
+ // static
+ bool IndexNames::isKnownName(const string& name) {
+ return name == IndexNames::GEO_2D
+ || name == IndexNames::GEO_2DSPHERE
+ || name == IndexNames::GEO_HAYSTACK
+ || name == IndexNames::TEXT
+ || name == IndexNames::HASHED
+ || name == IndexNames::BTREE;
+ }
+
+ // static
+ IndexType IndexNames::nameToType(const string& accessMethod) {
+ if (IndexNames::GEO_2D == accessMethod) {
+ return INDEX_2D;
+ }
+ else if (IndexNames::GEO_HAYSTACK == accessMethod) {
+ return INDEX_HAYSTACK;
+ }
+ else if (IndexNames::GEO_2DSPHERE == accessMethod) {
+ return INDEX_2DSPHERE;
+ }
+ else if (IndexNames::TEXT == accessMethod) {
+ return INDEX_TEXT;
+ }
+ else if (IndexNames::HASHED == accessMethod) {
+ return INDEX_HASHED;
+ }
+ else {
+ return INDEX_BTREE;
+ }
}
} // namespace mongo
diff --git a/src/mongo/db/index_names.h b/src/mongo/db/index_names.h
index 03f7786c879..fd7af42675b 100644
--- a/src/mongo/db/index_names.h
+++ b/src/mongo/db/index_names.h
@@ -37,6 +37,26 @@ namespace mongo {
class BSONObj;
/**
+ * We need to know what 'type' an index is in order to plan correctly. We can't entirely rely
+ * on the key pattern to tell us what kind of index we have.
+ *
+ * An example of the Bad Thing That We Must Avoid:
+ * 1. Create a 2dsphere index in 2.4, insert some docs.
+ * 2. Downgrade to 2.2. Insert some more docs into the collection w/the 2dsphere
+ * index. 2.2 treats the index as a normal btree index and creates keys accordingly.
+ * 3. Using the 2dsphere index in 2.4 gives wrong results or assert-fails or crashes as
+ * the data isn't what we expect.
+ */
+ enum IndexType {
+ INDEX_BTREE,
+ INDEX_2D,
+ INDEX_HAYSTACK,
+ INDEX_2DSPHERE,
+ INDEX_TEXT,
+ INDEX_HASHED,
+ };
+
+ /**
* We use the string representation of index names all over the place, so we declare them all
* once here.
*/
@@ -47,18 +67,14 @@ namespace mongo {
static const string GEO_2DSPHERE;
static const string TEXT;
static const string HASHED;
+ static const string BTREE;
/**
* True if is a regular (non-plugin) index or uses a plugin that existed before 2.4.
* These plugins are grandfathered in and allowed to exist in DBs with
* PDFILE_MINOR_VERSION_22_AND_OLDER
*/
- static bool existedBefore24(const string& name) {
- return name.empty()
- || name == IndexNames::GEO_2D
- || name == IndexNames::GEO_HAYSTACK
- || name == IndexNames::HASHED;
- }
+ static bool existedBefore24(const string& name);
/**
* Return the first string value in the provided object. For an index key pattern,
@@ -66,14 +82,15 @@ namespace mongo {
*/
static string findPluginName(const BSONObj& keyPattern);
- static bool isKnownName(const string& name) {
- return name.empty()
- || name == IndexNames::GEO_2D
- || name == IndexNames::GEO_2DSPHERE
- || name == IndexNames::GEO_HAYSTACK
- || name == IndexNames::TEXT
- || name == IndexNames::HASHED;
- }
+ /**
+ * Is the provided access method name one we recognize?
+ */
+ static bool isKnownName(const string& name);
+
+ /**
+ * Convert an index name to an IndexType.
+ */
+ static IndexType nameToType(const string& accessMethod);
};
} // namespace mongo
diff --git a/src/mongo/db/query/get_runner.cpp b/src/mongo/db/query/get_runner.cpp
index fb42358636d..033b58457ce 100644
--- a/src/mongo/db/query/get_runner.cpp
+++ b/src/mongo/db/query/get_runner.cpp
@@ -171,6 +171,7 @@ namespace mongo {
while (ii.more()) {
const IndexDescriptor* desc = ii.next();
plannerParams.indices.push_back(IndexEntry(desc->keyPattern(),
+ desc->getAccessMethodName(),
desc->isMultikey(),
desc->isSparse(),
desc->indexName(),
@@ -700,6 +701,7 @@ namespace mongo {
// if it's a win unless it's the first field.
if (desc->keyPattern().firstElement().fieldName() == field) {
plannerParams.indices.push_back(IndexEntry(desc->keyPattern(),
+ desc->getAccessMethodName(),
desc->isMultikey(),
desc->isSparse(),
desc->indexName(),
diff --git a/src/mongo/db/query/index_entry.h b/src/mongo/db/query/index_entry.h
index 06eee6c3508..9e81e78ee85 100644
--- a/src/mongo/db/query/index_entry.h
+++ b/src/mongo/db/query/index_entry.h
@@ -36,66 +36,57 @@
namespace mongo {
/**
- * We need to know what 'type' an index is in order to plan correctly.
- * Rather than look this up repeatedly we figure it out once.
- */
- enum IndexType {
- INDEX_BTREE,
- INDEX_2D,
- INDEX_HAYSTACK,
- INDEX_2DSPHERE,
- INDEX_TEXT,
- INDEX_HASHED,
- };
-
- /**
* This name sucks, but every name involving 'index' is used somewhere.
*/
struct IndexEntry {
+ /**
+ * Use this constructor if you're making an IndexEntry from the catalog.
+ */
IndexEntry(const BSONObj& kp,
- bool mk = false,
- bool sp = false,
- const string& n = "default_name",
- const BSONObj& io = BSONObj())
+ const string& accessMethod,
+ bool mk,
+ bool sp,
+ const string& n,
+ const BSONObj& io)
: keyPattern(kp),
multikey(mk),
sparse(sp),
name(n),
infoObj(io) {
- // XXX: This is the wrong way to set this and this is dangerous. We need to check in
- // the catalog to see if we should override the plugin name instead of just grabbing it
- // directly from the key pattern. Move this a level higher to wherever IndexEntry is
- // created.
- //
- // An example of the Bad Thing That We Must Avoid:
- // 1. Create a 2dsphere index in 2.4, insert some docs.
- // 2. Downgrade to 2.2. Insert some more docs into the collection w/the 2dsphere
- // index. 2.2 treats the index as a normal btree index and creates keys accordingly.
- // 3. Using the 2dsphere index in 2.4 gives wrong results or assert-fails or crashes as
- // the data isn't what we expect.
- string typeStr = IndexNames::findPluginName(keyPattern);
-
- if (IndexNames::GEO_2D == typeStr) {
- type = INDEX_2D;
- }
- else if (IndexNames::GEO_HAYSTACK == typeStr) {
- type = INDEX_HAYSTACK;
- }
- else if (IndexNames::GEO_2DSPHERE == typeStr) {
- type = INDEX_2DSPHERE;
- }
- else if (IndexNames::TEXT == typeStr) {
- type = INDEX_TEXT;
- }
- else if (IndexNames::HASHED == typeStr) {
- type = INDEX_HASHED;
- }
- else {
- type = INDEX_BTREE;
- }
+ type = IndexNames::nameToType(accessMethod);
}
+ /**
+ * For testing purposes only.
+ */
+ IndexEntry(const BSONObj& kp,
+ bool mk,
+ bool sp,
+ const string& n,
+ const BSONObj& io)
+ : keyPattern(kp),
+ multikey(mk),
+ sparse(sp),
+ name(n),
+ infoObj(io) {
+
+ type = IndexNames::nameToType(IndexNames::findPluginName(keyPattern));
+ }
+
+ /**
+ * For testing purposes only.
+ */
+ IndexEntry(const BSONObj& kp)
+ : keyPattern(kp),
+ multikey(false),
+ sparse(false),
+ name("test_foo"),
+ infoObj(BSONObj()) {
+
+ type = IndexNames::nameToType(IndexNames::findPluginName(keyPattern));
+ }
+
BSONObj keyPattern;
bool multikey;
diff --git a/src/mongo/db/query/plan_cache_test.cpp b/src/mongo/db/query/plan_cache_test.cpp
index dc57ad962f0..b5898052973 100644
--- a/src/mongo/db/query/plan_cache_test.cpp
+++ b/src/mongo/db/query/plan_cache_test.cpp
@@ -404,13 +404,19 @@ namespace {
// The first false means not multikey.
// The second false means not sparse.
// The third arg is the index name and I am egotistical.
- params.indices.push_back(IndexEntry(keyPattern, multikey, false,
- "hari_king_of_the_stove"));
+ params.indices.push_back(IndexEntry(keyPattern,
+ multikey,
+ false,
+ "hari_king_of_the_stove",
+ BSONObj()));
}
void addIndex(BSONObj keyPattern, bool multikey, bool sparse) {
- params.indices.push_back(IndexEntry(keyPattern, multikey, sparse,
- "note_to_self_dont_break_build"));
+ params.indices.push_back(IndexEntry(keyPattern,
+ multikey,
+ sparse,
+ "note_to_self_dont_break_build",
+ BSONObj()));
}
//
diff --git a/src/mongo/db/query/query_planner_test.cpp b/src/mongo/db/query/query_planner_test.cpp
index 02a9af3dbab..283f0a2108a 100644
--- a/src/mongo/db/query/query_planner_test.cpp
+++ b/src/mongo/db/query/query_planner_test.cpp
@@ -70,14 +70,19 @@ namespace {
void addIndex(BSONObj keyPattern, bool multikey = false) {
// The first false means not multikey.
// The second false means not sparse.
- // The third arg is the index name and I am egotistical.
- params.indices.push_back(IndexEntry(keyPattern, multikey, false,
- "hari_king_of_the_stove"));
+ params.indices.push_back(IndexEntry(keyPattern,
+ multikey,
+ false,
+ "hari_king_of_the_stove",
+ BSONObj()));
}
void addIndex(BSONObj keyPattern, bool multikey, bool sparse) {
- params.indices.push_back(IndexEntry(keyPattern, multikey, sparse,
- "note_to_self_dont_break_build"));
+ params.indices.push_back(IndexEntry(keyPattern,
+ multikey,
+ sparse,
+ "note_to_self_dont_break_build",
+ BSONObj()));
}
//
@@ -2827,7 +2832,7 @@ namespace {
ASSERT(NULL == indexTree);
// No relevant index matching the index tag.
- relevantIndices.push_back(IndexEntry(BSON("a" << 1), false, false, "a_1"));
+ relevantIndices.push_back(IndexEntry(BSON("a" << 1)));
CanonicalQuery *cq;
Status cqStatus = CanonicalQuery::canonicalize(ns, BSON("a" << 3), &cq);
@@ -2847,7 +2852,7 @@ namespace {
boost::scoped_ptr<CanonicalQuery> scopedCq(cq);
PlanCacheIndexTree* indexTree = new PlanCacheIndexTree();
- indexTree->setIndexEntry(IndexEntry(BSON("a" << 1), false, false, "a_1"));
+ indexTree->setIndexEntry(IndexEntry(BSON("a" << 1)));
map<BSONObj, size_t> indexMap;
@@ -2875,7 +2880,7 @@ namespace {
// Mismatched tree topology.
PlanCacheIndexTree* child = new PlanCacheIndexTree();
- child->setIndexEntry(IndexEntry(BSON("a" << 1), false, false, "a_1"));
+ child->setIndexEntry(IndexEntry(BSON("a" << 1)));
indexTree->children.push_back(child);
s = QueryPlanner::tagAccordingToCache(scopedCq->root(), indexTree, indexMap);
ASSERT_NOT_OK(s);
diff --git a/src/mongo/db/query/query_planner_text_test.cpp b/src/mongo/db/query/query_planner_text_test.cpp
index f3cfc6dcca5..64fddc22620 100644
--- a/src/mongo/db/query/query_planner_text_test.cpp
+++ b/src/mongo/db/query/query_planner_text_test.cpp
@@ -70,14 +70,19 @@ namespace {
void addIndex(BSONObj keyPattern, bool multikey = false) {
// The first false means not multikey.
// The second false means not sparse.
- // The third arg is the index name and I am egotistical.
- params.indices.push_back(IndexEntry(keyPattern, multikey, false,
- "hari_king_of_the_stove"));
+ params.indices.push_back(IndexEntry(keyPattern,
+ multikey,
+ false,
+ "hari_king_of_the_stove",
+ BSONObj()));
}
void addIndex(BSONObj keyPattern, bool multikey, bool sparse) {
- params.indices.push_back(IndexEntry(keyPattern, multikey, sparse,
- "note_to_self_dont_break_build"));
+ params.indices.push_back(IndexEntry(keyPattern,
+ multikey,
+ sparse,
+ "note_to_self_dont_break_build",
+ BSONObj()));
}
//
diff --git a/src/mongo/dbtests/namespacetests.cpp b/src/mongo/dbtests/namespacetests.cpp
index 1ad4f43abfb..372f3a45286 100644
--- a/src/mongo/dbtests/namespacetests.cpp
+++ b/src/mongo/dbtests/namespacetests.cpp
@@ -36,6 +36,7 @@
#include "mongo/db/index/btree_key_generator.h"
#include "mongo/db/index/expression_key_generator.h"
#include "mongo/db/index_legacy.h"
+#include "mongo/db/index_names.h"
#include "mongo/db/json.h"
#include "mongo/db/query/internal_plans.h"
#include "mongo/db/queryutil.h"
@@ -66,7 +67,7 @@ namespace NamespaceTests {
BSONObj bobj = builder.done();
- _index.reset( new IndexDescriptor( NULL, bobj ) );
+ _index.reset( new IndexDescriptor( NULL, IndexNames::BTREE, bobj ) );
_keyPattern = key().getOwned();