summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Rassi <rassi@10gen.com>2014-08-14 14:25:48 -0400
committerJason Rassi <rassi@10gen.com>2014-08-15 10:50:15 -0400
commita1042b421b4a1f046a0228ef316c95f001a4781b (patch)
treee6e15b0fbb4f021d4060a52c8c1c5faed2da8ad5
parentbe05259d36ec5f44c821c8f2d103a4ee83ebaf53 (diff)
downloadmongo-a1042b421b4a1f046a0228ef316c95f001a4781b.tar.gz
SERVER-14128 Disallow requests for non-unique _id indexes
-rw-r--r--jstests/core/index_id_unique.js25
-rw-r--r--src/mongo/db/catalog/index_catalog.cpp31
-rw-r--r--src/mongo/db/catalog/index_catalog.h4
3 files changed, 53 insertions, 7 deletions
diff --git a/jstests/core/index_id_unique.js b/jstests/core/index_id_unique.js
new file mode 100644
index 00000000000..ba0a22db47f
--- /dev/null
+++ b/jstests/core/index_id_unique.js
@@ -0,0 +1,25 @@
+// Test creation of the _id index with various values for the "unique" option.
+
+var coll = db.index_id_unique;
+
+// Creation of _id index with "non-zero" value for "unique" should succeed.
+coll.drop();
+assert.commandWorked(coll.runCommand("create", {autoIndexId: false}));
+assert.commandWorked(coll.ensureIndex({_id: 1}, {unique: true}));
+coll.drop();
+assert.commandWorked(coll.runCommand("create", {autoIndexId: false}));
+assert.commandWorked(coll.ensureIndex({_id: 1}, {unique: 1}));
+coll.drop();
+assert.commandWorked(coll.runCommand("create", {autoIndexId: false}));
+assert.commandWorked(coll.ensureIndex({_id: 1}, {unique: NumberLong(1)}));
+
+// Creation of _id index with "zero" value for "unique" should fail.
+coll.drop();
+assert.commandWorked(coll.runCommand("create", {autoIndexId: false}));
+assert.commandFailed(coll.ensureIndex({_id: 1}, {unique: false}));
+coll.drop();
+assert.commandWorked(coll.runCommand("create", {autoIndexId: false}));
+assert.commandFailed(coll.ensureIndex({_id: 1}, {unique: 0}));
+coll.drop();
+assert.commandWorked(coll.runCommand("create", {autoIndexId: false}));
+assert.commandFailed(coll.ensureIndex({_id: 1}, {unique: NumberLong(0)}));
diff --git a/src/mongo/db/catalog/index_catalog.cpp b/src/mongo/db/catalog/index_catalog.cpp
index b8567599410..77b68682877 100644
--- a/src/mongo/db/catalog/index_catalog.cpp
+++ b/src/mongo/db/catalog/index_catalog.cpp
@@ -462,6 +462,21 @@ namespace {
const NamespaceString& nss = _collection->ns();
+ BSONElement vElt = spec["v"];
+ if( !vElt.eoo() ) {
+ if ( !vElt.isNumber() ) {
+ return Status( ErrorCodes::CannotCreateIndex,
+ str::stream() << "non-numeric value for \"v\" field:" << vElt );
+ }
+ double v = vElt.Number();
+ // note (one day) we may be able to fresh build less versions than we can use
+ // isASupportedIndexVersionNumber() is what we can use
+ if ( v != 0 && v != 1 ) {
+ return Status( ErrorCodes::CannotCreateIndex,
+ str::stream() << "this version of mongod cannot build new indexes "
+ << "of version number " << v );
+ }
+ }
if ( nss.isSystemDotIndexes() )
return Status( ErrorCodes::CannotCreateIndex,
@@ -511,7 +526,13 @@ namespace {
<< "not allow document removal." );
}
- if ( !IndexDescriptor::isIdIndexPattern( key ) ) {
+ if ( IndexDescriptor::isIdIndexPattern( key ) ) {
+ BSONElement uniqueElt = spec["unique"];
+ if ( !uniqueElt.eoo() && !uniqueElt.trueValue() ) {
+ return Status( ErrorCodes::CannotCreateIndex, "_id index cannot be non-unique" );
+ }
+ }
+ else {
// for non _id indexes, we check to see if replication has turned off all indexes
// we _always_ created _id index
repl::ReplicationCoordinator* replCoord = repl::getGlobalReplicationCoordinator();
@@ -1085,13 +1106,9 @@ namespace {
int v = DefaultIndexVersionNumber;
if( !o["v"].eoo() ) {
- double vv = o["v"].Number();
- // note (one day) we may be able to fresh build less versions than we can use
- // isASupportedIndexVersionNumber() is what we can use
- uassert(14803, str::stream() << "this version of mongod cannot build new indexes of version number " << vv,
- vv == 0 || vv == 1);
- v = (int) vv;
+ v = o["v"].numberInt();
}
+
// idea is to put things we use a lot earlier
b.append("v", v);
diff --git a/src/mongo/db/catalog/index_catalog.h b/src/mongo/db/catalog/index_catalog.h
index a541a8bae0a..2f4ed0b677e 100644
--- a/src/mongo/db/catalog/index_catalog.h
+++ b/src/mongo/db/catalog/index_catalog.h
@@ -306,6 +306,10 @@ namespace mongo {
IndexCatalogEntry* _setupInMemoryStructures(OperationContext* txn,
IndexDescriptor* descriptor );
+ // Apply a set of transformations to the user-provided index object 'spec' to make it
+ // 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 );
Status _isSpecOk( const BSONObj& spec ) const;