diff options
author | Hari Khalsa <hkhalsa@10gen.com> | 2014-02-14 14:22:52 -0500 |
---|---|---|
committer | Hari Khalsa <hkhalsa@10gen.com> | 2014-02-19 12:45:44 -0500 |
commit | cfdf055eee1b1d0eed3d13c0c2d4d66a27dff662 (patch) | |
tree | 08fafe5cf887b3c12e3e07a36a4468db96b8d703 /src/mongo | |
parent | 00c7183b1a79b795f3d39c9079bb2f795c1cabb6 (diff) | |
download | mongo-cfdf055eee1b1d0eed3d13c0c2d4d66a27dff662.tar.gz |
SERVER-10026 push access method name into index descriptor, pay attention to it in planning
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/catalog/index_catalog.cpp | 15 | ||||
-rw-r--r-- | src/mongo/db/exec/sort.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/index/index_descriptor.h | 23 | ||||
-rw-r--r-- | src/mongo/db/index_names.cpp | 43 | ||||
-rw-r--r-- | src/mongo/db/index_names.h | 45 | ||||
-rw-r--r-- | src/mongo/db/query/get_runner.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/query/index_entry.h | 87 | ||||
-rw-r--r-- | src/mongo/db/query/plan_cache_test.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/query/query_planner_test.cpp | 21 | ||||
-rw-r--r-- | src/mongo/db/query/query_planner_text_test.cpp | 15 | ||||
-rw-r--r-- | src/mongo/dbtests/namespacetests.cpp | 3 |
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(); |