summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2016-05-23 17:55:01 -0400
committerDavid Storch <david.storch@10gen.com>2016-05-25 14:40:31 -0400
commit439df4c3bdff0194cff402a6268a9bdb9de44a7a (patch)
treec1d0c8d613d65516cce48327d183776464016634 /src
parent15deafbf2aa6524f3b05dd729b4ff378e18a2162 (diff)
downloadmongo-439df4c3bdff0194cff402a6268a9bdb9de44a7a.tar.gz
SERVER-23945 make IndexCatalog::_fixIndexSpec() use Status instead of throwing
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/catalog/index_catalog.cpp19
-rw-r--r--src/mongo/db/catalog/index_catalog.h2
-rw-r--r--src/mongo/db/fts/fts_element_iterator_test.cpp17
-rw-r--r--src/mongo/db/fts/fts_index_format_test.cpp56
-rw-r--r--src/mongo/db/fts/fts_matcher_test.cpp46
-rw-r--r--src/mongo/db/fts/fts_spec.cpp137
-rw-r--r--src/mongo/db/fts/fts_spec.h5
-rw-r--r--src/mongo/db/fts/fts_spec_legacy.cpp18
-rw-r--r--src/mongo/db/fts/fts_spec_test.cpp58
-rw-r--r--src/mongo/db/index/s2_access_method.cpp39
-rw-r--r--src/mongo/db/index/s2_access_method.h7
-rw-r--r--src/mongo/db/index_legacy.cpp2
-rw-r--r--src/mongo/db/index_legacy.h3
13 files changed, 230 insertions, 179 deletions
diff --git a/src/mongo/db/catalog/index_catalog.cpp b/src/mongo/db/catalog/index_catalog.cpp
index 2c3408a71fc..da3d0553d9f 100644
--- a/src/mongo/db/catalog/index_catalog.cpp
+++ b/src/mongo/db/catalog/index_catalog.cpp
@@ -276,18 +276,21 @@ StatusWith<BSONObj> IndexCatalog::prepareSpecForCreate(OperationContext* txn,
if (!status.isOK())
return StatusWith<BSONObj>(status);
- BSONObj fixed = _fixIndexSpec(original);
+ auto fixed = _fixIndexSpec(original);
+ if (!fixed.isOK()) {
+ return fixed;
+ }
// we double check with new index spec
- status = _isSpecOk(txn, fixed);
+ status = _isSpecOk(txn, fixed.getValue());
if (!status.isOK())
return StatusWith<BSONObj>(status);
- status = _doesSpecConflictWithExisting(txn, fixed);
+ status = _doesSpecConflictWithExisting(txn, fixed.getValue());
if (!status.isOK())
return StatusWith<BSONObj>(status);
- return StatusWith<BSONObj>(fixed);
+ return fixed;
}
Status IndexCatalog::createIndexOnEmptyCollection(OperationContext* txn, BSONObj spec) {
@@ -1257,8 +1260,12 @@ BSONObj IndexCatalog::fixIndexKey(const BSONObj& key) {
return key;
}
-BSONObj IndexCatalog::_fixIndexSpec(const BSONObj& spec) {
- BSONObj o = IndexLegacy::adjustIndexSpecObject(spec);
+StatusWith<BSONObj> IndexCatalog::_fixIndexSpec(const BSONObj& spec) {
+ auto statusWithSpec = IndexLegacy::adjustIndexSpecObject(spec);
+ if (!statusWithSpec.isOK()) {
+ return statusWithSpec;
+ }
+ BSONObj o = statusWithSpec.getValue();
BSONObjBuilder b;
diff --git a/src/mongo/db/catalog/index_catalog.h b/src/mongo/db/catalog/index_catalog.h
index 108f8b9966e..dac775501a2 100644
--- a/src/mongo/db/catalog/index_catalog.h
+++ b/src/mongo/db/catalog/index_catalog.h
@@ -364,7 +364,7 @@ private:
// conform to the standard for insertion. This function adds the 'v' field if it didn't
// exist, removes the '_id' field if it exists, applies plugin-level transformations if
// appropriate, etc.
- static BSONObj _fixIndexSpec(const BSONObj& spec);
+ static StatusWith<BSONObj> _fixIndexSpec(const BSONObj& spec);
Status _isSpecOk(OperationContext* txn, const BSONObj& spec) const;
diff --git a/src/mongo/db/fts/fts_element_iterator_test.cpp b/src/mongo/db/fts/fts_element_iterator_test.cpp
index 26e390d0f28..014eeec119d 100644
--- a/src/mongo/db/fts/fts_element_iterator_test.cpp
+++ b/src/mongo/db/fts/fts_element_iterator_test.cpp
@@ -37,6 +37,7 @@ namespace mongo {
namespace fts {
using std::string;
+using unittest::assertGet;
TEST(FTSElementIterator, Test1) {
BSONObj obj = fromjson(
@@ -47,7 +48,7 @@ TEST(FTSElementIterator, Test1) {
BSONObj indexSpec = fromjson("{ key : { a : \"text\" }, weights : { b : 10, d : 5 } }");
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
Weights::const_iterator itt = spec.weights().begin();
ASSERT(itt != spec.weights().end());
ASSERT_EQUALS("a", itt->first);
@@ -92,7 +93,7 @@ TEST(FTSElementIterator, Test2) {
BSONObj indexSpec = fromjson("{ key : { \"a.b.c\" : \"text\", d : \"text\" } }");
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
FTSElementIterator it(spec, obj);
@@ -137,7 +138,7 @@ TEST(FTSElementIterator, Test3) {
BSONObj indexSpec =
fromjson("{ key : { a : \"text\", \"a.b.c\" : \"text\" }, weights : { \"a.b.c\" : 5 } }");
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
Weights::const_iterator itt = spec.weights().begin();
ASSERT(itt != spec.weights().end());
ASSERT_EQUALS("a", itt->first);
@@ -183,7 +184,7 @@ TEST(FTSElementIterator, Test4) {
BSONObj indexSpec = fromjson("{ key : { \"a.b.c\" : \"text\" }, weights : { \"a.b.c\" : 5 } }");
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
FTSElementIterator it(spec, obj);
ASSERT(it.more());
@@ -223,7 +224,7 @@ TEST(FTSElementIterator, Test5) {
BSONObj indexSpec =
fromjson("{ key : { a : \"text\" }, weights : { b : 20, c : 10, \"d.e.f\" : 5 } }");
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
FTSElementIterator it(spec, obj);
ASSERT(it.more());
@@ -269,7 +270,7 @@ TEST(FTSElementIterator, Test6) {
BSONObj indexSpec =
fromjson("{ key : { a : \"text\" }, weights : { b : 20, c : 10, \"d.e.f\" : 5 } }");
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
FTSElementIterator it(spec, obj);
ASSERT(it.more());
@@ -313,7 +314,7 @@ TEST(FTSElementIterator, LanguageOverrideV2) {
BSONObj indexSpec =
fromjson("{ key : { \"a.b.c\" : \"text\", d : \"text\" }, textIndexVersion: 2.0 }");
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
FTSElementIterator it(spec, obj);
@@ -362,7 +363,7 @@ TEST(FTSElementIterator, LanguageOverrideV3) {
BSONObj indexSpec =
fromjson("{ key : { \"a.b.c\" : \"text\", d : \"text\" }, textIndexVersion: 3.0 }");
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
FTSElementIterator it(spec, obj);
diff --git a/src/mongo/db/fts/fts_index_format_test.cpp b/src/mongo/db/fts/fts_index_format_test.cpp
index 8d19e975cab..af353d51f26 100644
--- a/src/mongo/db/fts/fts_index_format_test.cpp
+++ b/src/mongo/db/fts/fts_index_format_test.cpp
@@ -45,10 +45,11 @@ namespace mongo {
namespace fts {
using std::string;
+using unittest::assertGet;
TEST(FTSIndexFormat, Simple1) {
- FTSSpec spec(FTSSpec::fixSpec(BSON("key" << BSON("data"
- << "text"))));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("data"
+ << "text")))));
BSONObjSet keys;
FTSIndexFormat::getKeys(spec,
BSON("data"
@@ -64,9 +65,9 @@ TEST(FTSIndexFormat, Simple1) {
}
TEST(FTSIndexFormat, ExtraBack1) {
- FTSSpec spec(FTSSpec::fixSpec(BSON("key" << BSON("data"
- << "text"
- << "x" << 1))));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("data"
+ << "text"
+ << "x" << 1)))));
BSONObjSet keys;
FTSIndexFormat::getKeys(spec,
BSON("data"
@@ -83,31 +84,9 @@ TEST(FTSIndexFormat, ExtraBack1) {
ASSERT_EQUALS(5, i.next().numberInt());
}
-/*
-TEST( FTSIndexFormat, ExtraBackArray1 ) {
- FTSSpec spec( FTSSpec::fixSpec( BSON( "key" << BSON( "data" << "text" <<
- "x.y" << 1 ) ) ) );
- BSONObjSet keys;
- FTSIndexFormat::getKeys( spec,
- BSON( "data" << "cat" <<
- "x" << BSON_ARRAY( BSON( "y" << 1 ) <<
- BSON( "y" << 2 ) ) ),
- &keys );
-
- ASSERT_EQUALS( 1U, keys.size() );
- BSONObj key = *(keys.begin());
- log() << "e: " << key << endl;
- ASSERT_EQUALS( 3, key.nFields() );
- BSONObjIterator i( key );
- ASSERT_EQUALS( StringData("cat"), i.next().valuestr() );
- ASSERT( i.next().numberDouble() > 0 );
- ASSERT_EQUALS( 5, i.next().numberInt() );
-}
-*/
-
TEST(FTSIndexFormat, ExtraFront1) {
- FTSSpec spec(FTSSpec::fixSpec(BSON("key" << BSON("x" << 1 << "data"
- << "text"))));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("x" << 1 << "data"
+ << "text")))));
BSONObjSet keys;
FTSIndexFormat::getKeys(spec,
BSON("data"
@@ -125,8 +104,8 @@ TEST(FTSIndexFormat, ExtraFront1) {
}
TEST(FTSIndexFormat, StopWords1) {
- FTSSpec spec(FTSSpec::fixSpec(BSON("key" << BSON("data"
- << "text"))));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("data"
+ << "text")))));
BSONObjSet keys1;
FTSIndexFormat::getKeys(spec,
@@ -173,8 +152,9 @@ void assertEqualsIndexKeys(std::set<std::string>& expectedKeys, const BSONObjSet
* Terms that are too long are not truncated in version 1.
*/
TEST(FTSIndexFormat, LongWordsTextIndexVersion1) {
- FTSSpec spec(FTSSpec::fixSpec(BSON("key" << BSON("data"
- << "text") << "textIndexVersion" << 1)));
+ FTSSpec spec(
+ assertGet(FTSSpec::fixSpec(BSON("key" << BSON("data"
+ << "text") << "textIndexVersion" << 1))));
BSONObjSet keys;
string longPrefix(1024U, 'a');
// "aaa...aaacat"
@@ -201,8 +181,9 @@ TEST(FTSIndexFormat, LongWordsTextIndexVersion1) {
* characters of the term to form the index key.
*/
TEST(FTSIndexFormat, LongWordTextIndexVersion2) {
- FTSSpec spec(FTSSpec::fixSpec(BSON("key" << BSON("data"
- << "text") << "textIndexVersion" << 2)));
+ FTSSpec spec(
+ assertGet(FTSSpec::fixSpec(BSON("key" << BSON("data"
+ << "text") << "textIndexVersion" << 2))));
BSONObjSet keys;
string longPrefix(1024U, 'a');
// "aaa...aaacat"
@@ -234,8 +215,9 @@ TEST(FTSIndexFormat, LongWordTextIndexVersion2) {
* characters of the term to form the index key.
*/
TEST(FTSIndexFormat, LongWordTextIndexVersion3) {
- FTSSpec spec(FTSSpec::fixSpec(BSON("key" << BSON("data"
- << "text") << "textIndexVersion" << 3)));
+ FTSSpec spec(
+ assertGet(FTSSpec::fixSpec(BSON("key" << BSON("data"
+ << "text") << "textIndexVersion" << 3))));
BSONObjSet keys;
string longPrefix(1024U, 'a');
// "aaa...aaacat"
diff --git a/src/mongo/db/fts/fts_matcher_test.cpp b/src/mongo/db/fts/fts_matcher_test.cpp
index 9b590fa67a3..8fdb705222e 100644
--- a/src/mongo/db/fts/fts_matcher_test.cpp
+++ b/src/mongo/db/fts/fts_matcher_test.cpp
@@ -36,6 +36,8 @@
namespace mongo {
namespace fts {
+using unittest::assertGet;
+
TEST(FTSMatcher, NegWild1) {
FTSQueryImpl q;
q.setQuery("foo -bar");
@@ -44,8 +46,8 @@ TEST(FTSMatcher, NegWild1) {
q.setDiacriticSensitive(false);
ASSERT(q.parse(TEXT_INDEX_VERSION_3).isOK());
FTSMatcher m(q,
- FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("$**"
- << "text")))));
+ FTSSpec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("$**"
+ << "text"))))));
ASSERT(m.hasNegativeTerm(BSON("x" << BSON("y"
<< "bar"))));
@@ -62,8 +64,8 @@ TEST(FTSMatcher, NegWild2) {
q.setDiacriticSensitive(false);
ASSERT(q.parse(TEXT_INDEX_VERSION_3).isOK());
FTSMatcher m(q,
- FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("$**"
- << "text")))));
+ FTSSpec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("$**"
+ << "text"))))));
ASSERT(m.hasNegativeTerm(BSON("x" << BSON("y"
<< "pizza restaurant"))));
@@ -79,8 +81,8 @@ TEST(FTSMatcher, Phrase1) {
q.setDiacriticSensitive(false);
ASSERT(q.parse(TEXT_INDEX_VERSION_3).isOK());
FTSMatcher m(q,
- FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("$**"
- << "text")))));
+ FTSSpec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("$**"
+ << "text"))))));
ASSERT(m.positivePhrasesMatch(BSON("x"
<< "table top")));
@@ -105,8 +107,8 @@ TEST(FTSMatcher, Phrase2) {
q.setDiacriticSensitive(false);
ASSERT(q.parse(TEXT_INDEX_VERSION_3).isOK());
FTSMatcher m(q,
- FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
- << "text")))));
+ FTSSpec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("x"
+ << "text"))))));
ASSERT(m.positivePhrasesMatch(BSON("x" << BSON_ARRAY("table top"))));
}
@@ -120,8 +122,8 @@ TEST(FTSMatcher, ParsesUsingDocLanguage) {
q.setDiacriticSensitive(false);
ASSERT(q.parse(TEXT_INDEX_VERSION_3).isOK());
FTSMatcher m(q,
- FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
- << "text")))));
+ FTSSpec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("x"
+ << "text"))))));
// Even though the search language is "none", the document {x: "gladly"} should be
// parsed using the English stemmer, and as such should match the negated term "glad".
@@ -138,8 +140,8 @@ TEST(FTSMatcher, MatcherDoesNotFilterStopWordsNeg) {
q.setDiacriticSensitive(false);
ASSERT(q.parse(TEXT_INDEX_VERSION_3).isOK());
FTSMatcher m(q,
- FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
- << "text")))));
+ FTSSpec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("x"
+ << "text"))))));
ASSERT(m.hasNegativeTerm(BSON("x"
<< "the")));
@@ -154,8 +156,8 @@ TEST(FTSMatcher, MatcherDoesNotFilterStopWordsPos) {
q.setDiacriticSensitive(false);
ASSERT(q.parse(TEXT_INDEX_VERSION_3).isOK());
FTSMatcher m(q,
- FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
- << "text")))));
+ FTSSpec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("x"
+ << "text"))))));
ASSERT(m.hasPositiveTerm(BSON("x"
<< "the")));
@@ -171,8 +173,8 @@ static bool docHasPositiveTermWithCase(const std::string& doc, const std::string
q.setDiacriticSensitive(false);
ASSERT(q.parse(TEXT_INDEX_VERSION_3).isOK());
FTSMatcher m(q,
- FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
- << "text")))));
+ FTSSpec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("x"
+ << "text"))))));
return m.hasPositiveTerm(BSON("x" << doc));
}
@@ -202,8 +204,8 @@ static bool docHasNegativeTermWithCase(const std::string& doc, const std::string
q.setDiacriticSensitive(false);
ASSERT(q.parse(TEXT_INDEX_VERSION_3).isOK());
FTSMatcher m(q,
- FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
- << "text")))));
+ FTSSpec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("x"
+ << "text"))))));
return m.hasNegativeTerm(BSON("x" << doc));
}
@@ -233,8 +235,8 @@ static bool docPositivePhrasesMatchWithCase(const std::string& doc, const std::s
q.setDiacriticSensitive(false);
ASSERT(q.parse(TEXT_INDEX_VERSION_3).isOK());
FTSMatcher m(q,
- FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
- << "text")))));
+ FTSSpec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("x"
+ << "text"))))));
return m.positivePhrasesMatch(BSON("x" << doc));
}
@@ -260,8 +262,8 @@ static bool docNegativePhrasesMatchWithCase(const std::string& doc, const std::s
q.setDiacriticSensitive(false);
ASSERT(q.parse(TEXT_INDEX_VERSION_3).isOK());
FTSMatcher m(q,
- FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
- << "text")))));
+ FTSSpec(assertGet(FTSSpec::fixSpec(BSON("key" << BSON("x"
+ << "text"))))));
return m.negativePhrasesMatch(BSON("x" << doc));
}
diff --git a/src/mongo/db/fts/fts_spec.cpp b/src/mongo/db/fts/fts_spec.cpp
index 5663d338bc6..05248d157b7 100644
--- a/src/mongo/db/fts/fts_spec.cpp
+++ b/src/mongo/db/fts/fts_spec.cpp
@@ -259,14 +259,17 @@ void _addFTSStuff(BSONObjBuilder* b) {
b->append("_ftsx", 1);
}
-void verifyFieldNameNotReserved(StringData s) {
- uassert(17289,
- "text index with reserved fields _fts/_ftsx not allowed",
- s != "_fts" && s != "_ftsx");
+Status verifyFieldNameNotReserved(StringData s) {
+ if (s == "_fts" || s == "_ftsx") {
+ return {ErrorCodes::CannotCreateIndex,
+ "text index with reserved fields _fts/_ftsx not allowed"};
+ }
+
+ return Status::OK();
}
}
-BSONObj FTSSpec::fixSpec(const BSONObj& spec) {
+StatusWith<BSONObj> FTSSpec::fixSpec(const BSONObj& spec) {
if (spec["textIndexVersion"].numberInt() == TEXT_INDEX_VERSION_1) {
return _fixSpecV1(spec);
}
@@ -284,11 +287,15 @@ BSONObj FTSSpec::fixSpec(const BSONObj& spec) {
while (i.more()) {
BSONElement e = i.next();
if (str::equals(e.fieldName(), "_fts")) {
- uassert(17271, "expecting _fts:\"text\"", INDEX_NAME == e.valuestrsafe());
+ if (INDEX_NAME != e.valuestrsafe()) {
+ return {ErrorCodes::CannotCreateIndex, "expecting _fts:\"text\""};
+ }
addedFtsStuff = true;
b.append(e);
} else if (str::equals(e.fieldName(), "_ftsx")) {
- uassert(17272, "expecting _ftsx:1", e.numberInt() == 1);
+ if (e.numberInt() != 1) {
+ return {ErrorCodes::CannotCreateIndex, "expecting _ftsx:1"};
+ }
b.append(e);
} else if (e.type() == String && INDEX_NAME == e.valuestr()) {
if (!addedFtsStuff) {
@@ -298,9 +305,10 @@ BSONObj FTSSpec::fixSpec(const BSONObj& spec) {
m[e.fieldName()] = 1;
} else {
- uassert(17273,
- "expected value 1 or -1 for non-text key in compound index",
- e.numberInt() == 1 || e.numberInt() == -1);
+ if (e.numberInt() != 1 && e.numberInt() != -1) {
+ return {ErrorCodes::CannotCreateIndex,
+ "expected value 1 or -1 for non-text key in compound index"};
+ }
b.append(e);
}
}
@@ -317,29 +325,50 @@ BSONObj FTSSpec::fixSpec(const BSONObj& spec) {
// extraBefore fields
while (String != e.type()) {
- verifyFieldNameNotReserved(e.fieldNameStringData());
- verify(i.more());
+ Status notReservedStatus = verifyFieldNameNotReserved(e.fieldNameStringData());
+ if (!notReservedStatus.isOK()) {
+ return notReservedStatus;
+ }
+
+ if (!i.more()) {
+ return {ErrorCodes::CannotCreateIndex,
+ "expected additional fields in text index key pattern"};
+ }
+
e = i.next();
}
// text fields
bool alreadyFixed = str::equals(e.fieldName(), "_fts");
if (alreadyFixed) {
- uassert(17288, "expected _ftsx after _fts", i.more());
+ if (!i.more()) {
+ return {ErrorCodes::CannotCreateIndex, "expected _ftsx after _fts"};
+ }
e = i.next();
- uassert(17274, "expected _ftsx after _fts", str::equals(e.fieldName(), "_ftsx"));
+ if (!str::equals(e.fieldName(), "_ftsx")) {
+ return {ErrorCodes::CannotCreateIndex, "expected _ftsx after _fts"};
+ }
e = i.next();
} else {
do {
- verifyFieldNameNotReserved(e.fieldNameStringData());
+ Status notReservedStatus = verifyFieldNameNotReserved(e.fieldNameStringData());
+ if (!notReservedStatus.isOK()) {
+ return notReservedStatus;
+ }
e = i.next();
} while (!e.eoo() && e.type() == String);
}
// extraAfterFields
while (!e.eoo()) {
- uassert(17389, "'text' fields in index must all be adjacent", e.type() != String);
- verifyFieldNameNotReserved(e.fieldNameStringData());
+ if (e.type() == BSONType::String) {
+ return {ErrorCodes::CannotCreateIndex,
+ "'text' fields in index must all be adjacent"};
+ }
+ Status notReservedStatus = verifyFieldNameNotReserved(e.fieldNameStringData());
+ if (!notReservedStatus.isOK()) {
+ return notReservedStatus;
+ }
e = i.next();
}
}
@@ -349,36 +378,50 @@ BSONObj FTSSpec::fixSpec(const BSONObj& spec) {
BSONObjIterator i(spec["weights"].Obj());
while (i.more()) {
BSONElement e = i.next();
- uassert(17283, "weight for text index needs numeric type", e.isNumber());
+ if (!e.isNumber()) {
+ return {ErrorCodes::CannotCreateIndex, "weight for text index needs numeric type"};
+ }
m[e.fieldName()] = e.numberInt();
}
} else if (spec["weights"].str() == WILDCARD) {
m[WILDCARD] = 1;
} else if (!spec["weights"].eoo()) {
- uasserted(17284, "text index option 'weights' must be an object");
+ return {ErrorCodes::CannotCreateIndex, "text index option 'weights' must be an object"};
}
- uassert(28823, "text index option 'weights' must specify fields or the wildcard", !m.empty());
+ if (m.empty()) {
+ return {ErrorCodes::CannotCreateIndex,
+ "text index option 'weights' must specify fields or the wildcard"};
+ }
BSONObj weights;
{
BSONObjBuilder b;
for (map<string, int>::iterator i = m.begin(); i != m.end(); ++i) {
- uassert(16674,
- str::stream() << "text index weight must be in the exclusive interval (0,"
- << MAX_WORD_WEIGHT << ") but found: " << i->second,
- i->second > 0 && i->second < MAX_WORD_WEIGHT);
+ if (i->second <= 0 || i->second >= MAX_WORD_WEIGHT) {
+ return {ErrorCodes::CannotCreateIndex,
+ str::stream() << "text index weight must be in the exclusive interval (0,"
+ << MAX_WORD_WEIGHT << ") but found: " << i->second};
+ }
// Verify weight refers to a valid field.
if (i->first != "$**") {
FieldRef keyField(i->first);
- uassert(17294, "weight cannot be on an empty field", keyField.numParts() != 0);
+ if (keyField.numParts() == 0) {
+ return {ErrorCodes::CannotCreateIndex, "weight cannot be on an empty field"};
+ }
+
for (size_t partNum = 0; partNum < keyField.numParts(); partNum++) {
StringData part = keyField.getPart(partNum);
- uassert(17291, "weight cannot have empty path component", !part.empty());
- uassert(17292,
- "weight cannot have path component with $ prefix",
- !part.startsWith("$"));
+ if (part.empty()) {
+ return {ErrorCodes::CannotCreateIndex,
+ "weight cannot have empty path component"};
+ }
+
+ if (part.startsWith("$")) {
+ return {ErrorCodes::CannotCreateIndex,
+ "weight cannot have path component with $ prefix"};
+ }
}
}
@@ -391,22 +434,22 @@ BSONObj FTSSpec::fixSpec(const BSONObj& spec) {
string default_language(default_language_elt.str());
if (default_language_elt.eoo()) {
default_language = moduleDefaultLanguage;
- } else {
- uassert(
- 17263, "default_language needs a string type", default_language_elt.type() == String);
+ } else if (default_language_elt.type() != BSONType::String) {
+ return {ErrorCodes::CannotCreateIndex, "default_language needs a string type"};
+ }
+
+ if (!FTSLanguage::make(default_language, TEXT_INDEX_VERSION_3).getStatus().isOK()) {
+ return {ErrorCodes::CannotCreateIndex, "default_language is not valid"};
}
- uassert(17264,
- "default_language is not valid",
- FTSLanguage::make(default_language, TEXT_INDEX_VERSION_3).getStatus().isOK());
BSONElement language_override_elt = spec["language_override"];
string language_override(language_override_elt.str());
if (language_override_elt.eoo()) {
language_override = "language";
- } else {
- uassert(17136,
- "language_override is not valid",
- language_override_elt.type() == String && validateOverride(language_override));
+ } else if (language_override_elt.type() != BSONType::String) {
+ return {ErrorCodes::CannotCreateIndex, "language_override must be a string"};
+ } else if (!validateOverride(language_override)) {
+ return {ErrorCodes::CannotCreateIndex, "language_override is not valid"};
}
int version = -1;
@@ -430,13 +473,17 @@ BSONObj FTSSpec::fixSpec(const BSONObj& spec) {
} else if (str::equals(e.fieldName(), "v")) {
version = e.numberInt();
} else if (str::equals(e.fieldName(), "textIndexVersion")) {
- uassert(17293, "text index option 'textIndexVersion' must be a number", e.isNumber());
- textIndexVersion = e.numberInt();
- uassert(16730,
- str::stream() << "bad textIndexVersion: " << textIndexVersion,
- textIndexVersion == TEXT_INDEX_VERSION_2 ||
- textIndexVersion == TEXT_INDEX_VERSION_3); // supported indexes
+ if (!e.isNumber()) {
+ return {ErrorCodes::CannotCreateIndex,
+ "text index option 'textIndexVersion' must be a number"};
+ }
+ textIndexVersion = e.numberInt();
+ if (textIndexVersion != TEXT_INDEX_VERSION_2 &&
+ textIndexVersion != TEXT_INDEX_VERSION_3) {
+ return {ErrorCodes::CannotCreateIndex,
+ str::stream() << "bad textIndexVersion: " << textIndexVersion};
+ }
} else {
b.append(e);
}
diff --git a/src/mongo/db/fts/fts_spec.h b/src/mongo/db/fts/fts_spec.h
index 6356f3a58a8..a00e04f7052 100644
--- a/src/mongo/db/fts/fts_spec.h
+++ b/src/mongo/db/fts/fts_spec.h
@@ -34,6 +34,7 @@
#include <vector>
#include <string>
+#include "mongo/base/status_with.h"
#include "mongo/db/fts/fts_language.h"
#include "mongo/db/fts/fts_util.h"
#include "mongo/db/fts/stemmer.h"
@@ -113,7 +114,7 @@ public:
const Weights& weights() const {
return _weights;
}
- static BSONObj fixSpec(const BSONObj& spec);
+ static StatusWith<BSONObj> fixSpec(const BSONObj& spec);
/**
* Returns text index version.
@@ -164,7 +165,7 @@ private:
const FTSLanguage& _getLanguageToUseV1(const BSONObj& userDoc) const;
- static BSONObj _fixSpecV1(const BSONObj& spec);
+ static StatusWith<BSONObj> _fixSpecV1(const BSONObj& spec);
//
// Instance variables.
diff --git a/src/mongo/db/fts/fts_spec_legacy.cpp b/src/mongo/db/fts/fts_spec_legacy.cpp
index b7867dba520..15739d8787d 100644
--- a/src/mongo/db/fts/fts_spec_legacy.cpp
+++ b/src/mongo/db/fts/fts_spec_legacy.cpp
@@ -191,7 +191,7 @@ void FTSSpec::_scoreDocumentV1(const BSONObj& obj, TermFrequencyMap* term_freqs)
}
}
-BSONObj FTSSpec::_fixSpecV1(const BSONObj& spec) {
+StatusWith<BSONObj> FTSSpec::_fixSpecV1(const BSONObj& spec) {
map<string, int> m;
BSONObj keyPattern;
@@ -238,10 +238,11 @@ BSONObj FTSSpec::_fixSpecV1(const BSONObj& spec) {
{
BSONObjBuilder b;
for (map<string, int>::iterator i = m.begin(); i != m.end(); ++i) {
- uassert(17365,
- str::stream() << "text index weight must be in the exclusive interval (0,"
- << MAX_WORD_WEIGHT << ") but found: " << i->second,
- i->second > 0 && i->second < MAX_WORD_WEIGHT);
+ if (i->second <= 0 || i->second >= MAX_WORD_WEIGHT) {
+ return {ErrorCodes::CannotCreateIndex,
+ str::stream() << "text index weight must be in the exclusive interval (0,"
+ << MAX_WORD_WEIGHT << ") but found: " << i->second};
+ }
b.append(i->first, i->second);
}
weights = b.obj();
@@ -277,9 +278,10 @@ BSONObj FTSSpec::_fixSpecV1(const BSONObj& spec) {
version = e.numberInt();
} else if (str::equals(e.fieldName(), "textIndexVersion")) {
textIndexVersion = e.numberInt();
- uassert(17366,
- str::stream() << "bad textIndexVersion: " << textIndexVersion,
- textIndexVersion == 1);
+ if (textIndexVersion != 1) {
+ return {ErrorCodes::CannotCreateIndex,
+ str::stream() << "bad textIndexVersion: " << textIndexVersion};
+ }
} else {
b.append(e);
}
diff --git a/src/mongo/db/fts/fts_spec_test.cpp b/src/mongo/db/fts/fts_spec_test.cpp
index deca03a01e6..5ecc0109333 100644
--- a/src/mongo/db/fts/fts_spec_test.cpp
+++ b/src/mongo/db/fts/fts_spec_test.cpp
@@ -38,6 +38,7 @@ namespace mongo {
using std::set;
using std::string;
+using unittest::assertGet;
namespace fts {
@@ -49,10 +50,10 @@ void assertFixSuccess(const std::string& s) {
try {
// fixSpec() should not throw on a valid spec.
- BSONObj fixed = FTSSpec::fixSpec(user);
+ BSONObj fixed = assertGet(FTSSpec::fixSpec(user));
// fixSpec() on an already-fixed spec shouldn't change it.
- BSONObj fixed2 = FTSSpec::fixSpec(fixed);
+ BSONObj fixed2 = assertGet(FTSSpec::fixSpec(fixed));
ASSERT_EQUALS(fixed, fixed2);
} catch (UserException&) {
ASSERT(false);
@@ -64,14 +65,7 @@ void assertFixSuccess(const std::string& s) {
*/
void assertFixFailure(const std::string& s) {
BSONObj user = fromjson(s);
-
- try {
- // fixSpec() on an invalid spec should uassert.
- BSONObj fixed = FTSSpec::fixSpec(user);
- } catch (UserException&) {
- return;
- }
- ASSERT(false);
+ ASSERT_NOT_OK(FTSSpec::fixSpec(user));
}
TEST(FTSSpec, FixNormalKey1) {
@@ -192,7 +186,7 @@ TEST(FTSSpec, ScoreSingleField1) {
<< "text"
<< "text") << "weights" << BSON("title" << 10));
- FTSSpec spec(FTSSpec::fixSpec(user));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(user)));
TermFrequencyMap m;
spec.scoreDocument(BSON("title"
@@ -210,7 +204,7 @@ TEST(FTSSpec, ScoreMultipleField1) {
<< "text"
<< "text") << "weights" << BSON("title" << 10));
- FTSSpec spec(FTSSpec::fixSpec(user));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(user)));
TermFrequencyMap m;
spec.scoreDocument(BSON("title"
@@ -236,7 +230,7 @@ TEST(FTSSpec, ScoreMultipleField2) {
<< "a.b"
<< "text"));
- FTSSpec spec(FTSSpec::fixSpec(user));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(user)));
TermFrequencyMap m;
spec.scoreDocument(BSON("a" << BSON("b"
@@ -251,7 +245,7 @@ TEST(FTSSpec, ScoreRepeatWord) {
<< "text"
<< "text") << "weights" << BSON("title" << 10));
- FTSSpec spec(FTSSpec::fixSpec(user));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(user)));
TermFrequencyMap m;
spec.scoreDocument(BSON("title"
@@ -266,7 +260,7 @@ TEST(FTSSpec, ScoreRepeatWord) {
TEST(FTSSpec, Extra1) {
BSONObj user = BSON("key" << BSON("data"
<< "text"));
- FTSSpec spec(FTSSpec::fixSpec(user));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(user)));
ASSERT_EQUALS(0U, spec.numExtraBefore());
ASSERT_EQUALS(0U, spec.numExtraAfter());
}
@@ -275,20 +269,20 @@ TEST(FTSSpec, Extra2) {
BSONObj user = BSON("key" << BSON("data"
<< "text"
<< "x" << 1));
- BSONObj fixed = FTSSpec::fixSpec(user);
+ BSONObj fixed = assertGet(FTSSpec::fixSpec(user));
FTSSpec spec(fixed);
ASSERT_EQUALS(0U, spec.numExtraBefore());
ASSERT_EQUALS(1U, spec.numExtraAfter());
ASSERT_EQUALS(StringData("x"), spec.extraAfter(0));
- BSONObj fixed2 = FTSSpec::fixSpec(fixed);
+ BSONObj fixed2 = assertGet(FTSSpec::fixSpec(fixed));
ASSERT_EQUALS(fixed, fixed2);
}
TEST(FTSSpec, Extra3) {
BSONObj user = BSON("key" << BSON("x" << 1 << "data"
<< "text"));
- BSONObj fixed = FTSSpec::fixSpec(user);
+ BSONObj fixed = assertGet(FTSSpec::fixSpec(user));
ASSERT_EQUALS(BSON("x" << 1 << "_fts"
<< "text"
@@ -296,7 +290,7 @@ TEST(FTSSpec, Extra3) {
fixed["key"].Obj());
ASSERT_EQUALS(BSON("data" << 1), fixed["weights"].Obj());
- BSONObj fixed2 = FTSSpec::fixSpec(fixed);
+ BSONObj fixed2 = assertGet(FTSSpec::fixSpec(fixed));
ASSERT_EQUALS(fixed, fixed2);
FTSSpec spec(fixed);
@@ -323,7 +317,7 @@ TEST(FTSSpec, Extra3) {
TEST(FTSSpec, NestedArraysPos1) {
BSONObj user = BSON("key" << BSON("a.b"
<< "text"));
- FTSSpec spec(FTSSpec::fixSpec(user));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(user)));
// The following document matches {"a.b": {$type: 2}}, so "term" should be indexed.
BSONObj obj = fromjson("{a: [{b: ['term']}]}"); // indirectly nested arrays
@@ -335,7 +329,7 @@ TEST(FTSSpec, NestedArraysPos1) {
TEST(FTSSpec, NestedArraysPos2) {
BSONObj user = BSON("key" << BSON("$**"
<< "text"));
- FTSSpec spec(FTSSpec::fixSpec(user));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(user)));
// The wildcard spec implies a full recursive traversal, so "term" should be indexed.
BSONObj obj = fromjson("{a: {b: [['term']]}}"); // directly nested arrays
@@ -347,7 +341,7 @@ TEST(FTSSpec, NestedArraysPos2) {
TEST(FTSSpec, NestedArraysNeg1) {
BSONObj user = BSON("key" << BSON("a.b"
<< "text"));
- FTSSpec spec(FTSSpec::fixSpec(user));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(user)));
// The following document does not match {"a.b": {$type: 2}}, so "term" should not be
// indexed.
@@ -361,7 +355,7 @@ TEST(FTSSpec, NestedArraysNeg1) {
TEST(FTSSpec, NestedLanguages_PerArrayItemStemming) {
BSONObj indexSpec = BSON("key" << BSON("a.b.c"
<< "text"));
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
TermFrequencyMap tfm;
BSONObj obj = fromjson(
@@ -390,7 +384,7 @@ TEST(FTSSpec, NestedLanguages_PerArrayItemStemming) {
TEST(FTSSpec, NestedLanguages_PerSubdocStemming) {
BSONObj indexSpec = BSON("key" << BSON("a.b.c"
<< "text"));
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
TermFrequencyMap tfm;
BSONObj obj = fromjson(
@@ -421,7 +415,7 @@ TEST(FTSSpec, NestedLanguages_PerSubdocStemming) {
TEST(FTSSpec, NestedLanguages_NestedArrays) {
BSONObj indexSpec = BSON("key" << BSON("a.b.c"
<< "text"));
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
TermFrequencyMap tfm;
BSONObj obj = fromjson(
@@ -452,7 +446,7 @@ TEST(FTSSpec, NestedLanguages_NestedArrays) {
TEST(FTSSpec, NestedLanguages_PathPruning) {
BSONObj indexSpec = BSON("key" << BSON("a.b.c"
<< "text"));
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
TermFrequencyMap tfm;
BSONObj obj = fromjson(
@@ -485,7 +479,7 @@ TEST(FTSSpec, NestedLanguages_PathPruning) {
TEST(FTSSpec, NestedLanguages_Wildcard) {
BSONObj indexSpec = BSON("key" << BSON("$**"
<< "text"));
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
TermFrequencyMap tfm;
BSONObj obj = fromjson(
@@ -519,7 +513,7 @@ TEST(FTSSpec, NestedLanguages_Wildcard) {
TEST(FTSSpec, NestedLanguages_WildcardOverride) {
BSONObj indexSpec = BSON("key" << BSON("$**"
<< "text") << "weights" << BSON("d.e.f" << 20));
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
TermFrequencyMap tfm;
BSONObj obj = fromjson(
@@ -556,7 +550,7 @@ TEST(FTSSpec, TextIndexLegacyNestedArrays) {
// textIndexVersion=1 FTSSpec objects do not index nested arrays.
{
BSONObj indexSpec = fromjson("{key: {'a.b': 'text'}, textIndexVersion: 1}");
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
TermFrequencyMap tfm;
spec.scoreDocument(obj, &tfm);
ASSERT_EQUALS(tfm.size(), 0U);
@@ -565,7 +559,7 @@ TEST(FTSSpec, TextIndexLegacyNestedArrays) {
// textIndexVersion=2 FTSSpec objects do index nested arrays.
{
BSONObj indexSpec = fromjson("{key: {'a.b': 'text'}, textIndexVersion: 2}");
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
TermFrequencyMap tfm;
spec.scoreDocument(obj, &tfm);
ASSERT_EQUALS(tfm.size(), 1U);
@@ -580,7 +574,7 @@ TEST(FTSSpec, TextIndexLegacyLanguageRecognition) {
// for purposes of stopword processing.
{
BSONObj indexSpec = fromjson("{key: {'a': 'text'}, textIndexVersion: 1}");
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
TermFrequencyMap tfm;
spec.scoreDocument(obj, &tfm);
ASSERT_EQUALS(tfm.size(), 1U); // "the" not recognized as stopword
@@ -589,7 +583,7 @@ TEST(FTSSpec, TextIndexLegacyLanguageRecognition) {
// textIndexVersion=2 FTSSpec objects recognize two-letter codes.
{
BSONObj indexSpec = fromjson("{key: {'a': 'text'}, textIndexVersion: 2}");
- FTSSpec spec(FTSSpec::fixSpec(indexSpec));
+ FTSSpec spec(assertGet(FTSSpec::fixSpec(indexSpec)));
TermFrequencyMap tfm;
spec.scoreDocument(obj, &tfm);
ASSERT_EQUALS(tfm.size(), 0U); // "the" recognized as stopword
diff --git a/src/mongo/db/index/s2_access_method.cpp b/src/mongo/db/index/s2_access_method.cpp
index c6519519b44..a05f72855dc 100644
--- a/src/mongo/db/index/s2_access_method.cpp
+++ b/src/mongo/db/index/s2_access_method.cpp
@@ -80,7 +80,7 @@ S2AccessMethod::S2AccessMethod(IndexCatalogEntry* btreeState, SortedDataInterfac
}
// static
-BSONObj S2AccessMethod::fixSpec(const BSONObj& specObj) {
+StatusWith<BSONObj> S2AccessMethod::fixSpec(const BSONObj& specObj) {
// If the spec object has the field "2dsphereIndexVersion", validate it. If it doesn't, add
// {2dsphereIndexVersion: 3}, which is the default for newly-built indexes.
@@ -92,22 +92,33 @@ BSONObj S2AccessMethod::fixSpec(const BSONObj& specObj) {
return bob.obj();
}
- uassert(40108,
- str::stream() << "Invalid type or value for geo index version { "
- << kIndexVersionFieldName << " : " << indexVersionElt
- << " }, only versions: [" << S2_INDEX_VERSION_1 << ","
- << S2_INDEX_VERSION_2 << "," << S2_INDEX_VERSION_3 << "] are supported",
- indexVersionElt.isNumber() && ((indexVersionElt.type() != mongo::NumberDouble) ||
- std::isnormal(indexVersionElt.numberDouble())));
+ if (!indexVersionElt.isNumber()) {
+ return {ErrorCodes::CannotCreateIndex,
+ str::stream() << "Invalid type for geo index version { " << kIndexVersionFieldName
+ << " : " << indexVersionElt << " }, only versions: ["
+ << S2_INDEX_VERSION_1 << "," << S2_INDEX_VERSION_2 << ","
+ << S2_INDEX_VERSION_3 << "] are supported"};
+ }
+
+ if (indexVersionElt.type() == BSONType::NumberDouble &&
+ !std::isnormal(indexVersionElt.numberDouble())) {
+ return {ErrorCodes::CannotCreateIndex,
+ str::stream() << "Invalid value for geo index version { " << kIndexVersionFieldName
+ << " : " << indexVersionElt << " }, only versions: ["
+ << S2_INDEX_VERSION_1 << "," << S2_INDEX_VERSION_2 << ","
+ << S2_INDEX_VERSION_3 << "] are supported"};
+ }
const auto indexVersion = indexVersionElt.numberLong();
+ if (indexVersion != S2_INDEX_VERSION_1 && indexVersion != S2_INDEX_VERSION_2 &&
+ indexVersion != S2_INDEX_VERSION_3) {
+ return {ErrorCodes::CannotCreateIndex,
+ str::stream() << "unsupported geo index version { " << kIndexVersionFieldName
+ << " : " << indexVersionElt << " }, only versions: ["
+ << S2_INDEX_VERSION_1 << "," << S2_INDEX_VERSION_2 << ","
+ << S2_INDEX_VERSION_3 << "] are supported"};
+ }
- uassert(17394,
- str::stream() << "unsupported geo index version { " << kIndexVersionFieldName << " : "
- << indexVersionElt << " }, only versions: [" << S2_INDEX_VERSION_1 << ","
- << S2_INDEX_VERSION_2 << "," << S2_INDEX_VERSION_3 << "] are supported",
- (indexVersion == S2_INDEX_VERSION_3 || indexVersion == S2_INDEX_VERSION_2 ||
- indexVersion == S2_INDEX_VERSION_1));
return specObj;
}
diff --git a/src/mongo/db/index/s2_access_method.h b/src/mongo/db/index/s2_access_method.h
index 7bc819adcce..3d39e10fcc9 100644
--- a/src/mongo/db/index/s2_access_method.h
+++ b/src/mongo/db/index/s2_access_method.h
@@ -29,6 +29,7 @@
#pragma once
#include "mongo/base/status.h"
+#include "mongo/base/status_with.h"
#include "mongo/db/index/index_access_method.h"
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/index/s2_common.h"
@@ -44,9 +45,11 @@ public:
* Takes an index spec object for this index and returns a copy tweaked to conform to the
* expected format. When an index build is initiated, this function is called on the spec
* object the user provides, and the return value of this function is the final spec object
- * that gets saved in the index catalog. Throws a UserException if 'specObj' is invalid.
+ * that gets saved in the index catalog.
+ *
+ * Returns a non-OK status if 'specObj' is invalid.
*/
- static BSONObj fixSpec(const BSONObj& specObj);
+ static StatusWith<BSONObj> fixSpec(const BSONObj& specObj);
private:
/**
diff --git a/src/mongo/db/index_legacy.cpp b/src/mongo/db/index_legacy.cpp
index e9d19cc511d..f477b562927 100644
--- a/src/mongo/db/index_legacy.cpp
+++ b/src/mongo/db/index_legacy.cpp
@@ -40,7 +40,7 @@
namespace mongo {
// static
-BSONObj IndexLegacy::adjustIndexSpecObject(const BSONObj& obj) {
+StatusWith<BSONObj> IndexLegacy::adjustIndexSpecObject(const BSONObj& obj) {
std::string pluginName = IndexNames::findPluginName(obj.getObjectField("key"));
if (IndexNames::TEXT == pluginName) {
diff --git a/src/mongo/db/index_legacy.h b/src/mongo/db/index_legacy.h
index 19640c02e71..e1408a16dd3 100644
--- a/src/mongo/db/index_legacy.h
+++ b/src/mongo/db/index_legacy.h
@@ -29,6 +29,7 @@
#pragma once
+#include "mongo/base/status_with.h"
#include "mongo/db/jsobj.h"
namespace mongo {
@@ -54,7 +55,7 @@ public:
* GEO_2DSPHERE provide additional validation on the index spec, and tweak the index spec
* object to conform to their expected format.
*/
- static BSONObj adjustIndexSpecObject(const BSONObj& obj);
+ static StatusWith<BSONObj> adjustIndexSpecObject(const BSONObj& obj);
/**
* Returns the BSONObj that is inserted into an index when the object is missing the keys