summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/sharding/array_shard_key.js160
-rw-r--r--src/mongo/db/field_ref.h5
-rw-r--r--src/mongo/db/s/collection_metadata.cpp40
-rw-r--r--src/mongo/db/s/collection_metadata.h12
-rw-r--r--src/mongo/s/chunk_manager.cpp1
-rw-r--r--src/mongo/s/shard_key_pattern.cpp121
-rw-r--r--src/mongo/s/shard_key_pattern.h3
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;