[SERVER-12538] Possible to create indexes with invalid orderings Created: 29/Jan/14  Updated: 01/May/19  Resolved: 04/Feb/16

Status: Closed
Project: Core Server
Component/s: Index Maintenance
Affects Version/s: 2.5.4
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Jeremy Mikola Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates SERVER-11064 Stricter validation of index key patt... Closed
Related
related to SERVER-12540 GLE doesn't set error for failed inde... Closed
is related to SERVER-13383 IndexCatalog should forbid creation o... Closed
Operating System: ALL
Participants:

 Description   

With float and booleans, the value is used as-is and also incorporated into the name. I would expect to see validation that the ordering be either negative or positive one (either an integer or float). I also found that invalid index orderings (e.g. the ORLY object below, and strings like "not2d") are simply ignored (reported separately in SERVER-12540).

> db.foo.ensureIndex({a:4.5})
> db.foo.ensureIndex({a:-4.5})
> db.foo.ensureIndex({a:true})
> db.foo.ensureIndex({a:false})
> db.foo.ensureIndex({a:{ORLY:"YARLY"}})
> db.foo.getIndexes()
[
	{
		"v" : 1,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_",
		"ns" : "test.foo"
	},
	{
		"v" : 1,
		"key" : {
			"a" : 4.5
		},
		"name" : "a_4.5",
		"ns" : "test.foo"
	},
	{
		"v" : 1,
		"key" : {
			"a" : -4.5
		},
		"name" : "a_-4.5",
		"ns" : "test.foo"
	},
	{
		"v" : 1,
		"key" : {
			"a" : true
		},
		"name" : "a_true",
		"ns" : "test.foo"
	},
	{
		"v" : 1,
		"key" : {
			"a" : false
		},
		"name" : "a_false",
		"ns" : "test.foo"
	}
]

And build info:

> db.runCommand('buildInfo')
{
	"version" : "2.5.5-pre-",
	"gitVersion" : "92cf0713b74ce2f8b011e6768a66c4e99d75a8ea",
	"OpenSSLVersion" : "",
	"sysInfo" : "Linux ip-10-2-29-40 2.6.21.7-2.ec2.v1.2.fc8xen #1 SMP Fri Nov 20 17:48:28 EST 2009 x86_64 BOOST_LIB_VERSION=1_49",
	"loaderFlags" : "-fPIC -pthread -Wl,-z,now -rdynamic",
	"compilerFlags" : "-Wnon-virtual-dtor -Woverloaded-virtual -fPIC -fno-strict-aliasing -ggdb -pthread -Wall -Wsign-compare -Wno-unknown-pragmas -Winvalid-pch -Werror -pipe -O3 -Wno-unused-function -Wno-deprecated-declarations -fno-builtin-memcmp",
	"allocator" : "tcmalloc",
	"versionArray" : [
		2,
		5,
		5,
		-100
	],
	"javascriptEngine" : "V8",
	"bits" : 64,
	"debug" : false,
	"maxBsonObjectSize" : 16777216,
	"ok" : 1
}

The above was the latest nightly found on http://www.mongodb.org/downloads. All commits to master since that commit are: https://github.com/mongodb/mongo/compare/92cf0713b74ce2f8b011e6768a66c4e99d75a8ea...master

In particular, https://github.com/mongodb/mongo/commit/4ae262e2715092700e8fab73eb0b2bea1a119a3b (createIndexes command for SERVER-1627) did not exist in the build I tested with; however, hari.khalsa@10gen.com seemed to think that this sort of validation should have been in place for some time now.



 Comments   
Comment by Max Hirschhorn [ 04/Feb/16 ]

Closing as a duplicate of SERVER-11064 - the values in the index key pattern must now be a number > 0, a number < 0, or a string.

> db.foo.ensureIndex({a:true})
{
  "ok" : 0,
  "errmsg" : "bad index key pattern { a: true }: Values in index key pattern cannot be of type Bool. Only numbers > 0, numbers < 0, and strings are allowed.",
  "code" : 67
}
> db.foo.ensureIndex({a:1.0})
{
  "createdCollectionAutomatically" : false,
  "numIndexesBefore" : 1,
  "numIndexesAfter" : 2,
  "ok" : 1
}
> db.foo.ensureIndex({a:1.5})
{
  "createdCollectionAutomatically" : false,
  "numIndexesBefore" : 2,
  "numIndexesAfter" : 3,
  "ok" : 1
}
> db.foo.ensureIndex({a:NumberInt(2)})
{
  "createdCollectionAutomatically" : false,
  "numIndexesBefore" : 3,
  "numIndexesAfter" : 4,
  "ok" : 1
}
> db.foo.ensureIndex({a:NumberLong(3)})
{
  "createdCollectionAutomatically" : false,
  "numIndexesBefore" : 4,
  "numIndexesAfter" : 5,
  "ok" : 1
}
> db.foo.ensureIndex({a:"foo"})
{
  "ok" : 0,
  "errmsg" : "bad index key pattern { a: \"foo\" }: Unknown index plugin 'foo'",
  "code" : 67
}
> db.foo.ensureIndex({a:[1,2,3]})
{
  "ok" : 0,
  "errmsg" : "bad index key pattern { a: [ 1.0, 2.0, 3.0 ] }: Values in index key pattern cannot be of type Array. Only numbers > 0, numbers < 0, and strings are allowed.",
  "code" : 67
}
> db.foo.ensureIndex({a:{"foo":"bar"}})
{
  "ok" : 0,
  "errmsg" : "bad index key pattern { a: { foo: \"bar\" } }: Values in index key pattern cannot be of type Object. Only numbers > 0, numbers < 0, and strings are allowed.",
  "code" : 67
}
> db.foo.getIndexes()
[
  {
    "v" : 1,
    "key" : {
      "_id" : 1
    },
    "name" : "_id_",
    "ns" : "test.foo"
  },
  {
    "v" : 1,
    "key" : {
      "a" : 1
    },
    "name" : "a_1",
    "ns" : "test.foo"
  },
  {
    "v" : 1,
    "key" : {
      "a" : 1.5
    },
    "name" : "a_1.5",
    "ns" : "test.foo"
  },
  {
    "v" : 1,
    "key" : {
      "a" : 2
    },
    "name" : "a_2",
    "ns" : "test.foo"
  },
  {
    "v" : 1,
    "key" : {
      "a" : NumberLong(3)
    },
    "name" : "a_3",
    "ns" : "test.foo"
  }
]

Comment by Jeremy Mikola [ 03/Feb/14 ]

hari.khalsa@10gen.com: I'm not sure if you were going to use this ticket to touch up the index name creation in the server. If so, I'd suggest looking at this test for the PHP driver. My logic was:

  • Float and integers are the only values that could be < 0 and thus create descending indexes, so "_-1" is appended.
  • Everything else (boolean, float/int >= 0, and even null) would be 0 or a positive integer and thus create ascending indexes, so "_1" is appended
  • Any string values (plugin names) are appended as-is (e.g. "_2d", "_invalidPlugin") for name generation. If the plugin is invalid, the server will throw an error in course.
Comment by Jeremy Mikola [ 29/Jan/14 ]

> db.foo.ensureIndex({a:true})
> db.foo.ensureIndex({a:1.0})
> db.foo.ensureIndex({a:1.5})
> db.foo.ensureIndex({a:NumberInt(2)})
> db.foo.ensureIndex({a:NumberLong(3)})
> db.foo.ensureIndex({a:"foo"})
> db.foo.ensureIndex({a:[1,2,3]})
> db.foo.ensureIndex({a:{"foo":"bar"}})
> db.foo.getIndexes()
[
	{
		"v" : 1,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_",
		"ns" : "test.foo"
	},
	{
		"v" : 1,
		"key" : {
			"a" : true
		},
		"name" : "a_true",
		"ns" : "test.foo"
	},
	{
		"v" : 1,
		"key" : {
			"a" : 1
		},
		"name" : "a_1",
		"ns" : "test.foo"
	},
	{
		"v" : 1,
		"key" : {
			"a" : 1.5
		},
		"name" : "a_1.5",
		"ns" : "test.foo"
	},
	{
		"v" : 1,
		"key" : {
			"a" : 2
		},
		"name" : "a_2",
		"ns" : "test.foo"
	},
	{
		"v" : 1,
		"key" : {
			"a" : NumberLong(3)
		},
		"name" : "a_3",
		"ns" : "test.foo"
	}
]

Comment by Jeremy Mikola [ 29/Jan/14 ]

Based on my test, numerics and booleans will allow an index to be created. Every other type was invalid, except for the strings for special indexes (e.g. "2d").

Comment by J Rassi [ 29/Jan/14 ]

jmikola@gmail.com: can you confirm that this is reproducible with values int/long/float/boolean in the index key, but not other BSON types?

Generated at Thu Feb 08 03:28:48 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.