Skip to content
This repository was archived by the owner on May 17, 2021. It is now read-only.

Commit ceddc7c

Browse files
authored
COMPASS-406 Index Error (#57)
* Add new bugsnag fixture data and tests gathered from the node driver * Migrate invalid values check to new IXWARN_KEY_PATTERN * Drop indexes test and support for it Actually it was not possible to create a mongod with an invalid string going back at least to v2.6 which is our last mostly-supported version in Compass at this time. pzrq@rocket:~$ mongo MongoDB shell version: 2.6.12 connecting to: test > db.funky.createIndex({c:'infinityStr'}) { "createdCollectionAutomatically" : true, "numIndexesBefore" : 1, "ok" : 0, "errmsg" : "bad index key pattern { c: \"infinityStr\" }: Unknown index plugin 'infinityStr'", "code" : 67 } pzrq@rocket:~$ mongo MongoDB shell version: 3.2.12 connecting to: test > db.funky.createIndex({c:'infinityStr'}) { "ok" : 0, "errmsg" : "bad index key pattern { c: \"infinityStr\" }: Unknown index plugin 'infinityStr'", "code" : 67 }
1 parent fc2ee1b commit ceddc7c

File tree

5 files changed

+106
-20
lines changed

5 files changed

+106
-20
lines changed

lib/index-field.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ var IndexField = Model.extend({
88
props: {
99
field: 'string',
1010
value: {
11-
type: 'any',
12-
values: [1, -1, '2dsphere', '2d', 'geoHaystack', 'text', 'hashed']
11+
type: 'any'
1312
}
1413
},
1514
derived: {

lib/warnings.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,22 @@ var format = require('util').format;
66

77
var WARNINGS = {
88
'IXWARN_PREFIX': 1,
9-
'IXWARN_UNUSED': 2
9+
'IXWARN_UNUSED': 2,
10+
'IXWARN_KEY_PATTERN': 3
1011
};
1112

1213
// var debug = require('debug')('mongodb-index-model:warnings-mixin');
1314

15+
/**
16+
* List of valid values for an index.
17+
*
18+
* See https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#db.collection.createIndex
19+
* See https://docs.mongodb.com/manual/release-notes/3.4-compatibility/#stricter-validation-of-index-specifications
20+
*
21+
* @type {string[]}
22+
*/
23+
var VALID_INDEX_TYPE_VALUES = [1, -1, '2dsphere', '2d', 'geoHaystack', 'text', 'hashed'];
24+
1425
var WarningModel = Model.extend({
1526
idAttribute: 'code',
1627
props: {
@@ -67,6 +78,15 @@ var WarningsMixin = {
6778
details: 'This index has never been used and might therefore not be required.'
6879
}));
6980
break;
81+
case WARNINGS.IXWARN_KEY_PATTERN:
82+
idx.warnings.add(new WarningModel({
83+
code: warningCode,
84+
message: 'Index Key Pattern is not valid',
85+
details: 'This index has a key pattern that may not be valid in MongoDB 3.4 and later.' +
86+
'See https://docs.mongodb.com/manual/release-notes/3.4-compatibility/' +
87+
'#stricter-validation-of-index-specifications for more information.'
88+
}));
89+
break;
7090
default:
7191
throw new Error('Index warning code %i unknown.');
7292
}
@@ -98,6 +118,14 @@ var WarningsMixin = {
98118
} else {
99119
idx.warnings.remove(WARNINGS.IXWARN_UNUSED);
100120
}
121+
122+
// Check for potentially invalid values, e.g. Boolean true, 0, NaN, or
123+
// arbitrary strings that are not special like '2d' or 'geoHaystack'
124+
_.values(idx.key).forEach(function(value) {
125+
if (!_.includes(VALID_INDEX_TYPE_VALUES, value)) {
126+
collection.addWarningToIndex(WARNINGS.IXWARN_KEY_PATTERN, idx, {});
127+
}
128+
});
101129
});
102130
}
103131
};

test/fixture-bugsnag.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
module.exports = [
2+
{
3+
'v': 2,
4+
'key': {'a': Infinity},
5+
'name': 'a_Infinity',
6+
'ns': 'indexes.funky'
7+
},
8+
// Skip Decimal128 for now...
9+
// { v: 2,
10+
// key:
11+
// { a:
12+
// Decimal128 {
13+
// _bsontype: 'Decimal128',
14+
// bytes: <Buffer 01 00 00 00 00 00 00 00 00 00 00 00 00 00 58 30> } },
15+
// name: 'a_NumberDecimal("1E+12")',
16+
// ns: 'indexes.funky' } { a:
17+
// Decimal128 {
18+
// _bsontype: 'Decimal128',
19+
// bytes: <Buffer 01 00 00 00 00 00 00 00 00 00 00 00 00 00 58 30> } } Decimal128 {
20+
// _bsontype: 'Decimal128',
21+
// bytes: <Buffer 01 00 00 00 00 00 00 00 00 00 00 00 00 00 58 30> }
22+
{'v': 2, 'key': {'a': -2}, 'name': 'a_-2', 'ns': 'indexes.funky'},
23+
{'v': 2, 'key': {'a': 0.1}, 'name': 'a_0.1', 'ns': 'indexes.funky'},
24+
{'v': 2, 'key': {'a': -0.5}, 'name': 'a_-0.5', 'ns': 'indexes.funky'},
25+
{'v': 1, 'key': {'b': 0}, 'name': 'b_0', 'ns': 'indexes.funky'},
26+
{'v': 1, 'key': {'b': true}, 'name': 'b_true', 'ns': 'indexes.funky'}
27+
];

test/index.test.js

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
var assert = require('assert');
2-
var Index = require('../');
32
var IndexCollection = require('../').Collection;
43
var _ = require('lodash');
54

65
var INDEX_FIXTURE = require('./fixture');
6+
var INDEX_BUGSNAG_FIXTURE = require('./fixture-bugsnag');
77

88
describe('mongodb-index-model', function() {
99
var indexes;
10+
var bugsnagIndexes;
1011
before(function() {
1112
indexes = new IndexCollection(INDEX_FIXTURE, {parse: true});
13+
bugsnagIndexes = new IndexCollection(INDEX_BUGSNAG_FIXTURE, {parse: true});
1214
});
1315

1416
context('IndexModel', function() {
@@ -117,6 +119,33 @@ describe('mongodb-index-model', function() {
117119
assert.equal(indexes.get('seniors', 'name').fields.at(0).value, 1);
118120
});
119121

122+
context('when created via a v3.4.x mongod and mongoshell', function() {
123+
it('should accept Infinity index field values', function() {
124+
assert.equal(bugsnagIndexes.get('a_Infinity', 'name').fields.at(0).field, 'a');
125+
assert.equal(bugsnagIndexes.get('a_Infinity', 'name').fields.at(0).value, Infinity);
126+
});
127+
128+
it('should accept numbers less than -1 as index field values', function() {
129+
assert.equal(bugsnagIndexes.get('a_-2', 'name').fields.at(0).field, 'a');
130+
assert.equal(bugsnagIndexes.get('a_-2', 'name').fields.at(0).value, -2);
131+
});
132+
133+
it('should accept floats as index field values', function() {
134+
assert.equal(bugsnagIndexes.get('a_0.1', 'name').fields.at(0).field, 'a');
135+
assert.equal(bugsnagIndexes.get('a_0.1', 'name').fields.at(0).value, 0.1);
136+
});
137+
});
138+
139+
context('when created via a v3.2.x mongod and mongoshell', function() {
140+
// See https://jira.mongodb.org/browse/COMPASS-406
141+
// See https://app.bugsnag.com/mongodb/mongodb-compass/errors/581ea54b07b7add195ad49ce?event_id=585a8ea91c8db711005c6cb2
142+
// See https://jira.mongodb.org/browse/SERVER-11064
143+
it('should accept boolean true as index field values', function() {
144+
assert.equal(bugsnagIndexes.get('b_true', 'name').fields.at(0).field, 'b');
145+
assert.equal(bugsnagIndexes.get('b_true', 'name').fields.at(0).value, true);
146+
});
147+
});
148+
120149
it('should accept dotted field names', function() {
121150
assert.equal(indexes.get('seniors', 'name').fields.at(1).field, 'address.city');
122151
assert.equal(indexes.get('seniors', 'name').fields.at(1).value, 1);
@@ -130,19 +159,5 @@ describe('mongodb-index-model', function() {
130159
assert.equal(indexes.get('seniors', 'name').fields.at(0).geo, false);
131160
assert.equal(indexes.get('last_position_2dsphere', 'name').fields.at(0).geo, true);
132161
});
133-
134-
it('should not allow arbitary strings as values', function() {
135-
assert.throws(function() {
136-
/* eslint no-new: 0 */
137-
new Index({
138-
name: 'badIndex',
139-
key: {
140-
foo: 'someStrangeValue'
141-
}
142-
}, {
143-
parse: true
144-
});
145-
});
146-
});
147162
});
148163
});

test/warnings.test.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
var assert = require('assert');
22
var WarningsMixin = require('../lib/warnings').mixin;
33
var IndexCollection = require('../').Collection;
4-
// var _ = require('lodash');
5-
//
64
// var debug = require('debug')('mongodb-index-model:test:warnings');
75

86
var INDEX_FIXTURE = require('./fixture');
7+
var INDEX_BUGSNAG_FIXTURE = require('./fixture-bugsnag');
98

109
var IndexWithWarningsCollection = IndexCollection.extend(WarningsMixin);
1110

1211
describe('Index Warnings', function() {
1312
var indexes;
13+
var bugsnagIndexes;
1414
beforeEach(function() {
1515
indexes = new IndexWithWarningsCollection(INDEX_FIXTURE, {parse: true});
16+
bugsnagIndexes = new IndexWithWarningsCollection(INDEX_BUGSNAG_FIXTURE, {parse: true});
1617
});
1718

1819
context('IXWARN_PREFIX', function() {
@@ -125,4 +126,20 @@ describe('Index Warnings', function() {
125126
assert.ok(idx.warnings.length === 0);
126127
});
127128
});
129+
130+
context('IXWARN_KEY_PATTERN', function() {
131+
it('warns boolean true is not valid in 3.4+', function() {
132+
bugsnagIndexes.updateIndexWarnings();
133+
var index = bugsnagIndexes.get('b_true', 'name');
134+
assert.ok(index.warnings.length === 1);
135+
assert.ok(index.warnings.at(0).message.match(/Index Key Pattern is not valid/));
136+
});
137+
138+
it('warns 0 is not valid in 3.4+', function() {
139+
bugsnagIndexes.updateIndexWarnings();
140+
var index = bugsnagIndexes.get('b_0', 'name');
141+
assert.ok(index.warnings.length === 1);
142+
assert.ok(index.warnings.at(0).message.match(/Index Key Pattern is not valid/));
143+
});
144+
});
128145
});

0 commit comments

Comments
 (0)