diff options
-rw-r--r-- | jstests/sharding/array_shard_key.js | 160 | ||||
-rw-r--r-- | src/mongo/db/field_ref.h | 5 | ||||
-rw-r--r-- | src/mongo/db/s/collection_metadata.cpp | 40 | ||||
-rw-r--r-- | src/mongo/db/s/collection_metadata.h | 12 | ||||
-rw-r--r-- | src/mongo/s/chunk_manager.cpp | 1 | ||||
-rw-r--r-- | src/mongo/s/shard_key_pattern.cpp | 121 | ||||
-rw-r--r-- | src/mongo/s/shard_key_pattern.h | 3 |
7 files changed, 164 insertions, 178 deletions
diff --git a/jstests/sharding/array_shard_key.js b/jstests/sharding/array_shard_key.js index 4fd60c3f21d..cdbe4bda885 100644 --- a/jstests/sharding/array_shard_key.js +++ b/jstests/sharding/array_shard_key.js @@ -1,111 +1,113 @@ // Ensure you can't shard on an array key +(function() { + 'use strict'; -var st = new ShardingTest({name: jsTestName(), shards: 3}); + var st = new ShardingTest({shards: 3}); -var mongos = st.s0; + var mongos = st.s0; -var coll = mongos.getCollection(jsTestName() + ".foo"); + var coll = mongos.getCollection("TestDB.foo"); -st.shardColl(coll, {_id: 1, i: 1}, {_id: ObjectId(), i: 1}); - -printjson(mongos.getDB("config").chunks.find().toArray()); + st.shardColl(coll, {_id: 1, i: 1}, {_id: ObjectId(), i: 1}); -st.printShardingStatus(); + printjson(mongos.getDB("config").chunks.find().toArray()); -print("1: insert some invalid data"); + print("1: insert some invalid data"); -var value = null; + var value = null; -// Insert an object with invalid array key -assert.writeError(coll.insert({i: [1, 2]})); + // Insert an object with invalid array key + assert.writeError(coll.insert({i: [1, 2]})); -// Insert an object with all the right fields, but an invalid array val for _id -assert.writeError(coll.insert({_id: [1, 2], i: 3})); + // Insert an object with all the right fields, but an invalid array val for _id + assert.writeError(coll.insert({_id: [1, 2], i: 3})); -// Insert an object with valid array key -assert.writeOK(coll.insert({i: 1})); + // Insert an object with valid array key + assert.writeOK(coll.insert({i: 1})); -// Update the value with valid other field -value = coll.findOne({i: 1}); -assert.writeOK(coll.update(value, {$set: {j: 2}})); + // Update the value with valid other field + value = coll.findOne({i: 1}); + assert.writeOK(coll.update(value, {$set: {j: 2}})); -// Update the value with invalid other fields -value = coll.findOne({i: 1}); -assert.writeError(coll.update(value, Object.merge(value, {i: [3]}))); + // Update the value with invalid other fields + value = coll.findOne({i: 1}); + assert.writeError(coll.update(value, Object.merge(value, {i: [3]}))); -// Multi-update the value with invalid other fields -value = coll.findOne({i: 1}); -assert.writeError(coll.update(value, Object.merge(value, {i: [3, 4]}), false, true)); + // Multi-update the value with invalid other fields + value = coll.findOne({i: 1}); + assert.writeError(coll.update(value, Object.merge(value, {i: [3, 4]}), false, true)); -// Multi-update the value with other fields (won't work, but no error) -value = coll.findOne({i: 1}); -assert.writeOK(coll.update(Object.merge(value, {i: [1, 1]}), {$set: {k: 4}}, false, true)); + // Multi-update the value with other fields (won't work, but no error) + value = coll.findOne({i: 1}); + assert.writeOK(coll.update(Object.merge(value, {i: [1, 1]}), {$set: {k: 4}}, false, true)); -// Query the value with other fields (won't work, but no error) -value = coll.findOne({i: 1}); -coll.find(Object.merge(value, {i: [1, 1]})).toArray(); + // Query the value with other fields (won't work, but no error) + value = coll.findOne({i: 1}); + coll.find(Object.merge(value, {i: [1, 1]})).toArray(); -// Can't remove using multikey, but shouldn't error -value = coll.findOne({i: 1}); -coll.remove(Object.extend(value, {i: [1, 2, 3, 4]})); + // Can't remove using multikey, but shouldn't error + value = coll.findOne({i: 1}); + coll.remove(Object.extend(value, {i: [1, 2, 3, 4]})); -// Can't remove using multikey, but shouldn't error -value = coll.findOne({i: 1}); -assert.writeOK(coll.remove(Object.extend(value, {i: [1, 2, 3, 4, 5]}))); -assert.eq(coll.find().itcount(), 1); + // Can't remove using multikey, but shouldn't error + value = coll.findOne({i: 1}); + assert.writeOK(coll.remove(Object.extend(value, {i: [1, 2, 3, 4, 5]}))); + assert.eq(coll.find().itcount(), 1); -value = coll.findOne({i: 1}); -assert.writeOK(coll.remove(Object.extend(value, {i: 1}))); -assert.eq(coll.find().itcount(), 0); + value = coll.findOne({i: 1}); + assert.writeOK(coll.remove(Object.extend(value, {i: 1}))); + assert.eq(coll.find().itcount(), 0); -coll.ensureIndex({_id: 1, i: 1, j: 1}); -// Can insert document that will make index into a multi-key as long as it's not part of shard key. -coll.remove({}); -assert.writeOK(coll.insert({i: 1, j: [1, 2]})); -assert.eq(coll.find().itcount(), 1); + coll.ensureIndex({_id: 1, i: 1, j: 1}); + // Can insert document that will make index into a multi-key as long as it's not part of shard + // key. + coll.remove({}); + assert.writeOK(coll.insert({i: 1, j: [1, 2]})); + assert.eq(coll.find().itcount(), 1); -// Same is true for updates. -coll.remove({}); -coll.insert({_id: 1, i: 1}); -assert.writeOK(coll.update({_id: 1, i: 1}, {_id: 1, i: 1, j: [1, 2]})); -assert.eq(coll.find().itcount(), 1); + // Same is true for updates. + coll.remove({}); + coll.insert({_id: 1, i: 1}); + assert.writeOK(coll.update({_id: 1, i: 1}, {_id: 1, i: 1, j: [1, 2]})); + assert.eq(coll.find().itcount(), 1); -// Same for upserts. -coll.remove({}); -assert.writeOK(coll.update({_id: 1, i: 1}, {_id: 1, i: 1, j: [1, 2]}, true)); -assert.eq(coll.find().itcount(), 1); + // Same for upserts. + coll.remove({}); + assert.writeOK(coll.update({_id: 1, i: 1}, {_id: 1, i: 1, j: [1, 2]}, true)); + assert.eq(coll.find().itcount(), 1); -printjson("Sharding-then-inserting-multikey tested, now trying inserting-then-sharding-multikey"); + printjson( + "Sharding-then-inserting-multikey tested, now trying inserting-then-sharding-multikey"); -// Insert a bunch of data then shard over key which is an array -var coll = mongos.getCollection("" + coll + "2"); -for (var i = 0; i < 10; i++) { - // TODO : does not check weird cases like [ i, i ] - assert.writeOK(coll.insert({i: [i, i + 1]})); -} + // Insert a bunch of data then shard over key which is an array + var coll = mongos.getCollection("" + coll + "2"); + for (var i = 0; i < 10; i++) { + // TODO : does not check weird cases like [ i, i ] + assert.writeOK(coll.insert({i: [i, i + 1]})); + } -coll.ensureIndex({_id: 1, i: 1}); + coll.ensureIndex({_id: 1, i: 1}); -try { - st.shardColl(coll, {_id: 1, i: 1}, {_id: ObjectId(), i: 1}); -} catch (e) { - print("Correctly threw error on sharding with multikey index."); -} + try { + st.shardColl(coll, {_id: 1, i: 1}, {_id: ObjectId(), i: 1}); + } catch (e) { + print("Correctly threw error on sharding with multikey index."); + } -st.printShardingStatus(); + st.printShardingStatus(); -// Insert a bunch of data then shard over key which is not an array -var coll = mongos.getCollection("" + coll + "3"); -for (var i = 0; i < 10; i++) { - // TODO : does not check weird cases like [ i, i ] - assert.writeOK(coll.insert({i: i})); -} + // Insert a bunch of data then shard over key which is not an array + var coll = mongos.getCollection("" + coll + "3"); + for (var i = 0; i < 10; i++) { + // TODO : does not check weird cases like [ i, i ] + assert.writeOK(coll.insert({i: i})); + } -coll.ensureIndex({_id: 1, i: 1}); + coll.ensureIndex({_id: 1, i: 1}); -st.shardColl(coll, {_id: 1, i: 1}, {_id: ObjectId(), i: 1}); + st.shardColl(coll, {_id: 1, i: 1}, {_id: ObjectId(), i: 1}); -st.printShardingStatus(); + st.printShardingStatus(); -// Finish -st.stop(); + st.stop(); +})(); diff --git a/src/mongo/db/field_ref.h b/src/mongo/db/field_ref.h index 82116faf6fe..b6b218630b8 100644 --- a/src/mongo/db/field_ref.h +++ b/src/mongo/db/field_ref.h @@ -138,11 +138,6 @@ private: // with allocations. static const size_t kReserveAhead = 4; - /** - * Parses 'path' into parts. - */ - void _parse(StringData path); - /** Converts the field part index to the variable part equivalent */ size_t getIndex(size_t i) const { return i - kReserveAhead; diff --git a/src/mongo/db/s/collection_metadata.cpp b/src/mongo/db/s/collection_metadata.cpp index fbda424de67..b18e325adb0 100644 --- a/src/mongo/db/s/collection_metadata.cpp +++ b/src/mongo/db/s/collection_metadata.cpp @@ -45,26 +45,18 @@ CollectionMetadata::CollectionMetadata(const BSONObj& keyPattern, ChunkVersion collectionVersion, ChunkVersion shardVersion, RangeMap shardChunksMap) - : _keyPattern(keyPattern.getOwned()), + : _shardKeyPattern(keyPattern), _collVersion(collectionVersion), _shardVersion(shardVersion), _chunksMap(std::move(shardChunksMap)), _pendingMap(SimpleBSONObjComparator::kInstance.makeBSONObjIndexedMap<CachedChunkInfo>()), _rangesMap(SimpleBSONObjComparator::kInstance.makeBSONObjIndexedMap<CachedChunkInfo>()) { - invariant(!_keyPattern.isEmpty()); + invariant(_shardKeyPattern.isValid()); invariant(_collVersion.epoch() == _shardVersion.epoch()); invariant(_collVersion.isSet()); invariant(_collVersion >= _shardVersion); - // Parse the shard keys into the states 'keys' and 'keySet' members. - for (const auto& current : _keyPattern) { - auto newFieldRef(stdx::make_unique<FieldRef>()); - newFieldRef->parse(current.fieldNameStringData()); - - _keyFields.emplace_back(std::move(newFieldRef)); - } - if (_chunksMap.empty()) { invariant(!_shardVersion.isSet()); return; @@ -111,7 +103,7 @@ std::unique_ptr<CollectionMetadata> CollectionMetadata::cloneMinusPending( invariant(rangeMapContains(_pendingMap, chunk.getMin(), chunk.getMax())); auto metadata(stdx::make_unique<CollectionMetadata>( - _keyPattern, getCollVersion(), getShardVersion(), getChunks())); + _shardKeyPattern.toBSON(), getCollVersion(), getShardVersion(), getChunks())); metadata->_pendingMap = _pendingMap; metadata->_pendingMap.erase(chunk.getMin()); @@ -124,7 +116,7 @@ std::unique_ptr<CollectionMetadata> CollectionMetadata::clonePlusPending( invariant(!rangeMapOverlaps(_chunksMap, chunk.getMin(), chunk.getMax())); auto metadata(stdx::make_unique<CollectionMetadata>( - _keyPattern, getCollVersion(), getShardVersion(), getChunks())); + _shardKeyPattern.toBSON(), getCollVersion(), getShardVersion(), getChunks())); metadata->_pendingMap = _pendingMap; // If there are any pending chunks on the interval to be added this is ok, since pending chunks @@ -249,7 +241,7 @@ Status CollectionMetadata::checkChunkIsValid(const ChunkType& chunk) { void CollectionMetadata::toBSONBasic(BSONObjBuilder& bb) const { _collVersion.addToBSON(bb, "collVersion"); _shardVersion.addToBSON(bb, "shardVersion"); - bb.append("keyPattern", _keyPattern); + bb.append("keyPattern", _shardKeyPattern.toBSON()); } void CollectionMetadata::toBSONChunks(BSONArrayBuilder& bb) const { @@ -331,7 +323,7 @@ bool CollectionMetadata::getNextOrphanRange(const BSONObj& origLookupKey, KeyRan // bounds of the surrounding ranges in both maps. // - range->keyPattern = _keyPattern; + range->keyPattern = _shardKeyPattern.toBSON(); range->minKey = getMinKey(); range->maxKey = maxKey; @@ -361,29 +353,15 @@ bool CollectionMetadata::getNextOrphanRange(const BSONObj& origLookupKey, KeyRan } BSONObj CollectionMetadata::getMinKey() const { - BSONObjIterator it(_keyPattern); - BSONObjBuilder minKeyB; - while (it.more()) - minKeyB << it.next().fieldName() << MINKEY; - return minKeyB.obj(); + return _shardKeyPattern.getKeyPattern().globalMin(); } BSONObj CollectionMetadata::getMaxKey() const { - BSONObjIterator it(_keyPattern); - BSONObjBuilder maxKeyB; - while (it.more()) - maxKeyB << it.next().fieldName() << MAXKEY; - return maxKeyB.obj(); + return _shardKeyPattern.getKeyPattern().globalMax(); } bool CollectionMetadata::isValidKey(const BSONObj& key) const { - BSONObjIterator it(_keyPattern); - while (it.more()) { - BSONElement next = it.next(); - if (!key.hasField(next.fieldName())) - return false; - } - return key.nFields() == _keyPattern.nFields(); + return _shardKeyPattern.isShardKey(key); } } // namespace mongo diff --git a/src/mongo/db/s/collection_metadata.h b/src/mongo/db/s/collection_metadata.h index 51845fc3c1d..ea7392842d6 100644 --- a/src/mongo/db/s/collection_metadata.h +++ b/src/mongo/db/s/collection_metadata.h @@ -28,10 +28,9 @@ #pragma once -#include "mongo/db/field_ref_set.h" -#include "mongo/db/jsobj.h" #include "mongo/db/range_arithmetic.h" #include "mongo/s/chunk_version.h" +#include "mongo/s/shard_key_pattern.h" namespace mongo { @@ -148,11 +147,11 @@ public: } const BSONObj& getKeyPattern() const { - return _keyPattern; + return _shardKeyPattern.toBSON(); } const std::vector<std::unique_ptr<FieldRef>>& getKeyPatternFields() const { - return _keyFields; + return _shardKeyPattern.getKeyPatternFields(); } BSONObj getMinKey() const; @@ -185,7 +184,7 @@ public: private: // Shard key pattern for the collection - BSONObj _keyPattern; + ShardKeyPattern _shardKeyPattern; // a version for this collection that identifies the collection incarnation (ie, a // dropped and recreated collection with the same name would have a different version) @@ -194,9 +193,6 @@ private: // highest ChunkVersion for which this metadata's information is accurate ChunkVersion _shardVersion; - // A vector owning the FieldRefs parsed from the shard-key pattern of field names. - std::vector<std::unique_ptr<FieldRef>> _keyFields; - // Map of chunks tracked by this shard RangeMap _chunksMap; diff --git a/src/mongo/s/chunk_manager.cpp b/src/mongo/s/chunk_manager.cpp index 047bfa1d696..7b19211baaf 100644 --- a/src/mongo/s/chunk_manager.cpp +++ b/src/mongo/s/chunk_manager.cpp @@ -34,6 +34,7 @@ #include <vector> +#include "mongo/base/owned_pointer_vector.h" #include "mongo/bson/simple_bsonobj_comparator.h" #include "mongo/db/matcher/extensions_callback_noop.h" #include "mongo/db/query/collation/collation_index_key.h" diff --git a/src/mongo/s/shard_key_pattern.cpp b/src/mongo/s/shard_key_pattern.cpp index bce1698ecb3..3518a7e9cc2 100644 --- a/src/mongo/s/shard_key_pattern.cpp +++ b/src/mongo/s/shard_key_pattern.cpp @@ -44,33 +44,19 @@ namespace mongo { -using std::make_pair; -using std::pair; using std::shared_ptr; using std::string; using std::unique_ptr; using std::vector; using pathsupport::EqualityMatches; -using mongoutils::str::stream; const int ShardKeyPattern::kMaxShardKeySizeBytes = 512; const unsigned int ShardKeyPattern::kMaxFlattenedInCombinations = 4000000; -Status ShardKeyPattern::checkShardKeySize(const BSONObj& shardKey) { - if (shardKey.objsize() <= kMaxShardKeySizeBytes) - return Status::OK(); - - return Status(ErrorCodes::ShardKeyTooBig, - stream() << "shard keys must be less than " << kMaxShardKeySizeBytes - << " bytes, but key " - << shardKey - << " is " - << shardKey.objsize() - << " bytes"); -} +namespace { -static bool isHashedPatternEl(const BSONElement& el) { +bool isHashedPatternEl(const BSONElement& el) { return el.type() == String && el.String() == IndexNames::HASHED; } @@ -79,26 +65,23 @@ static bool isHashedPatternEl(const BSONElement& el) { * i) a hashed single field, e.g. { a : "hashed" }, or * ii) a compound list of ascending, potentially-nested field paths, e.g. { a : 1 , b.c : 1 } */ -static std::vector<std::unique_ptr<FieldRef>> parseShardKeyPattern(const BSONObj& keyPattern) { +std::vector<std::unique_ptr<FieldRef>> parseShardKeyPattern(const BSONObj& keyPattern) { std::vector<std::unique_ptr<FieldRef>> parsedPaths; - BSONObjIterator patternIt(keyPattern); - while (patternIt.more()) { - BSONElement patternEl = patternIt.next(); - parsedPaths.push_back(stdx::make_unique<FieldRef>(patternEl.fieldNameStringData())); - const FieldRef& patternPath = *parsedPaths.back(); + for (const auto& patternEl : keyPattern) { + auto newFieldRef(stdx::make_unique<FieldRef>(patternEl.fieldNameStringData())); // Empty path - if (patternPath.numParts() == 0) + if (newFieldRef->numParts() == 0) return {}; // Extra "." in path? - if (patternPath.dottedField() != patternEl.fieldNameStringData()) + if (newFieldRef->dottedField() != patternEl.fieldNameStringData()) return {}; // Empty parts of the path, ".."? - for (size_t i = 0; i < patternPath.numParts(); ++i) { - if (patternPath.getPart(i).size() == 0) + for (size_t i = 0; i < newFieldRef->numParts(); ++i) { + if (newFieldRef->getPart(i).empty()) return {}; } @@ -109,18 +92,48 @@ static std::vector<std::unique_ptr<FieldRef>> parseShardKeyPattern(const BSONObj } else if (patternEl.numberInt() != 1) { return {}; } + + parsedPaths.emplace_back(std::move(newFieldRef)); } return parsedPaths; } +bool isShardKeyElement(const BSONElement& element, bool allowRegex) { + if (element.eoo() || element.type() == Array) + return false; + + // TODO: Disallow regex all the time + if (!allowRegex && element.type() == RegEx) + return false; + + if (element.type() == Object && !element.embeddedObject().okForStorage()) + return false; + + return true; +} + +} // namespace + +Status ShardKeyPattern::checkShardKeySize(const BSONObj& shardKey) { + if (shardKey.objsize() <= kMaxShardKeySizeBytes) + return Status::OK(); + + return {ErrorCodes::ShardKeyTooBig, + str::stream() << "shard keys must be less than " << kMaxShardKeySizeBytes + << " bytes, but key " + << shardKey + << " is " + << shardKey.objsize() + << " bytes"}; +} + ShardKeyPattern::ShardKeyPattern(const BSONObj& keyPattern) : _keyPatternPaths(parseShardKeyPattern(keyPattern)), _keyPattern(_keyPatternPaths.empty() ? BSONObj() : keyPattern) {} ShardKeyPattern::ShardKeyPattern(const KeyPattern& keyPattern) - : _keyPatternPaths(parseShardKeyPattern(keyPattern.toBSON())), - _keyPattern(_keyPatternPaths.empty() ? KeyPattern(BSONObj()) : keyPattern) {} + : ShardKeyPattern(keyPattern.toBSON()) {} bool ShardKeyPattern::isValid() const { return !_keyPattern.toBSON().isEmpty(); @@ -134,6 +147,10 @@ const KeyPattern& ShardKeyPattern::getKeyPattern() const { return _keyPattern; } +const std::vector<std::unique_ptr<FieldRef>>& ShardKeyPattern::getKeyPatternFields() const { + return _keyPatternPaths; +} + const BSONObj& ShardKeyPattern::toBSON() const { return _keyPattern.toBSON(); } @@ -142,30 +159,22 @@ string ShardKeyPattern::toString() const { return toBSON().toString(); } -static bool isShardKeyElement(const BSONElement& element, bool allowRegex) { - // TODO: Disallow regex all the time - if (element.eoo() || element.type() == Array || (!allowRegex && element.type() == RegEx) || - (element.type() == Object && !element.embeddedObject().okForStorage())) - return false; - return true; -} - bool ShardKeyPattern::isShardKey(const BSONObj& shardKey) const { // Shard keys are always of the form: { 'nested.path' : value, 'nested.path2' : value } if (!isValid()) return false; - BSONObjIterator patternIt(_keyPattern.toBSON()); - while (patternIt.more()) { - BSONElement patternEl = patternIt.next(); + const auto& keyPatternBSON = _keyPattern.toBSON(); + for (const auto& patternEl : keyPatternBSON) { BSONElement keyEl = shardKey[patternEl.fieldNameStringData()]; + if (!isShardKeyElement(keyEl, true)) return false; } - return true; + return shardKey.nFields() == keyPatternBSON.nFields(); } BSONObj ShardKeyPattern::normalizeShardKey(const BSONObj& shardKey) const { @@ -350,18 +359,21 @@ BoundList ShardKeyPattern::flattenBounds(const IndexBounds& indexBounds) const { return BoundList(); } } - // To construct our bounds we will generate intervals based on bounds for - // the first field, then compound intervals based on constraints for the first - // 2 fields, then compound intervals for the first 3 fields, etc. - // As we loop through the fields, we start generating new intervals that will later - // get extended in another iteration of the loop. We define these partially constructed - // intervals using pairs of BSONObjBuilders (shared_ptrs, since after one iteration of the - // loop they still must exist outside their scope). - typedef vector<pair<shared_ptr<BSONObjBuilder>, shared_ptr<BSONObjBuilder>>> BoundBuilders; + + // To construct our bounds we will generate intervals based on bounds for the first field, then + // compound intervals based on constraints for the first 2 fields, then compound intervals for + // the first 3 fields, etc. + // + // As we loop through the fields, we start generating new intervals that will later get extended + // in another iteration of the loop. We define these partially constructed intervals using pairs + // of BSONObjBuilders (shared_ptrs, since after one iteration of the loop they still must exist + // outside their scope). + typedef vector<std::pair<std::shared_ptr<BSONObjBuilder>, std::shared_ptr<BSONObjBuilder>>> + BoundBuilders; BoundBuilders builders; - builders.push_back(make_pair(shared_ptr<BSONObjBuilder>(new BSONObjBuilder()), - shared_ptr<BSONObjBuilder>(new BSONObjBuilder()))); + builders.emplace_back(shared_ptr<BSONObjBuilder>(new BSONObjBuilder()), + shared_ptr<BSONObjBuilder>(new BSONObjBuilder())); BSONObjIterator keyIter(_keyPattern.toBSON()); // until equalityOnly is false, we are just dealing with equality (no range or $in queries). bool equalityOnly = true; @@ -403,9 +415,8 @@ BoundList ShardKeyPattern::flattenBounds(const IndexBounds& indexBounds) const { uassert(17439, "combinatorial limit of $in partitioning of results exceeded", newBuilders.size() < kMaxFlattenedInCombinations); - newBuilders.push_back( // - make_pair(shared_ptr<BSONObjBuilder>(new BSONObjBuilder()), - shared_ptr<BSONObjBuilder>(new BSONObjBuilder()))); + newBuilders.emplace_back(shared_ptr<BSONObjBuilder>(new BSONObjBuilder()), + shared_ptr<BSONObjBuilder>(new BSONObjBuilder())); newBuilders.back().first->appendElements(first); newBuilders.back().second->appendElements(second); newBuilders.back().first->appendAs(interval->start, fieldName); @@ -424,9 +435,11 @@ BoundList ShardKeyPattern::flattenBounds(const IndexBounds& indexBounds) const { } } } + BoundList ret; for (BoundBuilders::const_iterator i = builders.begin(); i != builders.end(); ++i) - ret.push_back(make_pair(i->first->obj(), i->second->obj())); + ret.emplace_back(i->first->obj(), i->second->obj()); + return ret; } diff --git a/src/mongo/s/shard_key_pattern.h b/src/mongo/s/shard_key_pattern.h index f7c1b8d387b..6b31d8e5dd5 100644 --- a/src/mongo/s/shard_key_pattern.h +++ b/src/mongo/s/shard_key_pattern.h @@ -31,7 +31,6 @@ #include <memory> #include <vector> -#include "mongo/base/owned_pointer_vector.h" #include "mongo/base/status.h" #include "mongo/base/status_with.h" #include "mongo/db/jsobj.h" @@ -94,6 +93,8 @@ public: const KeyPattern& getKeyPattern() const; + const std::vector<std::unique_ptr<FieldRef>>& getKeyPatternFields() const; + const BSONObj& toBSON() const; std::string toString() const; |