summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Banala <arun.banala@10gen.com>2019-10-30 15:49:38 +0000
committerevergreen <evergreen@mongodb.com>2019-10-30 15:49:38 +0000
commit9034b668f90feb5a0f1ac9fd2a8714ecbe4cd057 (patch)
tree002e9ca071c0a7c0c0435059b90d2db6372dcced
parentedf22ddd2963839b50a658c43532e1742caeefc2 (diff)
downloadmongo-9034b668f90feb5a0f1ac9fd2a8714ecbe4cd057.tar.gz
SERVER-44050 Arrays are not correctly rejected during key generation for 'hashed' indexes
(cherry picked from commit 888f7e6fc10ccb999be203b8cbad4dbe19d0a5d2)
-rw-r--r--jstests/core/hashindex1.js10
-rw-r--r--src/mongo/db/index/expression_keys_private.cpp20
2 files changed, 22 insertions, 8 deletions
diff --git a/jstests/core/hashindex1.js b/jstests/core/hashindex1.js
index 93986ecfd5e..09a1e1f7b47 100644
--- a/jstests/core/hashindex1.js
+++ b/jstests/core/hashindex1.js
@@ -87,3 +87,13 @@ var total = t.find().hint({"_id": 1}).toArray().length;
var totala = t.find().hint(goodspec).toArray().length;
assert.eq(total, totala, "non-sparse index has wrong total");
assert.lt(totalb, totala, "sparse index should have smaller total");
+
+// Test that having arrays along the path of the index is not allowed.
+assert.commandWorked(t.createIndex({"field1.field2.0.field4": "hashed"}));
+assert.writeErrorWithCode(t.insert({field1: []}), 16766);
+assert.writeErrorWithCode(t.insert({field1: {field2: []}}), 16766);
+assert.writeErrorWithCode(t.insert({field1: {field2: {0: []}}}), 16766);
+assert.writeErrorWithCode(t.insert({field1: [{field2: {0: []}}]}), 16766);
+assert.writeErrorWithCode(t.insert({field1: {field2: {0: {field4: []}}}}), 16766);
+assert.writeOK(t.insert({field1: {field2: {0: {otherField: []}}}}));
+assert.writeOK(t.insert({field1: {field2: {0: {field4: 1}}}}));
diff --git a/src/mongo/db/index/expression_keys_private.cpp b/src/mongo/db/index/expression_keys_private.cpp
index 9fe3365f393..0a4cd2e42ed 100644
--- a/src/mongo/db/index/expression_keys_private.cpp
+++ b/src/mongo/db/index/expression_keys_private.cpp
@@ -361,7 +361,18 @@ void ExpressionKeysPrivate::getHashKeys(const BSONObj& obj,
const CollatorInterface* collator,
BSONObjSet* keys) {
const char* cstr = hashedField.c_str();
- BSONElement fieldVal = dps::extractElementAtPath(obj, cstr);
+ BSONElement fieldVal = dps::extractElementAtPathOrArrayAlongPath(obj, cstr);
+
+ // If we hit an array while traversing the path, 'cstr' will point to the path component
+ // immediately following the array, or the null termination byte if the final field in the path
+ // was an array.
+ uassert(
+ 16766,
+ str::stream()
+ << "Error: hashed indexes do not currently support array values. Found array at path: "
+ << hashedField.substr(
+ 0, hashedField.size() - StringData(cstr).size() - !StringData(cstr).empty()),
+ fieldVal.type() != BSONType::Array);
// Convert strings to comparison keys.
BSONObj fieldValObj;
@@ -370,13 +381,6 @@ void ExpressionKeysPrivate::getHashKeys(const BSONObj& obj,
CollationIndexKey::collationAwareIndexKeyAppend(fieldVal, collator, &bob);
fieldValObj = bob.obj();
fieldVal = fieldValObj.firstElement();
- }
-
- uassert(16766,
- "Error: hashed indexes do not currently support array values",
- fieldVal.type() != Array);
-
- if (!fieldVal.eoo()) {
BSONObj key = BSON("" << makeSingleHashKey(fieldVal, seed, hashVersion));
keys->insert(key);
} else if (!isSparse) {