From 7b969531de3dd18e28175fc59082e3e2ff9eb16c Mon Sep 17 00:00:00 2001 From: Alexander Ignatyev Date: Fri, 10 Feb 2023 20:24:26 +0000 Subject: SERVER-72468 Test Compound Wildcard Index filters and hiding --- .../wildcard/compound_wildcard_index_filter.js | 154 ++++++++++++++++++++ .../wildcard/compound_wildcard_index_hiding.js | 156 +++++++++++++++++++++ 2 files changed, 310 insertions(+) create mode 100644 jstests/core/index/wildcard/compound_wildcard_index_filter.js create mode 100644 jstests/core/index/wildcard/compound_wildcard_index_hiding.js (limited to 'jstests') diff --git a/jstests/core/index/wildcard/compound_wildcard_index_filter.js b/jstests/core/index/wildcard/compound_wildcard_index_filter.js new file mode 100644 index 00000000000..8ac0bdedf6d --- /dev/null +++ b/jstests/core/index/wildcard/compound_wildcard_index_filter.js @@ -0,0 +1,154 @@ +/** + * Tests that Compound Wildcard Indexes can be added/removed/listed from index filters. + * + * @tags: [ + * not_allowed_with_security_token, + * does_not_support_stepdowns, + * featureFlagCompoundWildcardIndexes, + * ] + */ + +(function() { +"use strict"; + +function findFilter(cwiFilter, filterList) { + for (const filter of filterList) { + if (bsonWoCompare(cwiFilter.query, filter.query) == 0) { + if (filter.indexes.find(keyPattern => + bsonWoCompare(cwiFilter.keyPattern, keyPattern) == 0)) { + return filter; + } + if (filter.indexes.find(indexName => cwiFilter.indexName == indexName)) { + return filter; + } + } + } + + return null; +} + +function getIndexName(coll, keyPattern) { + const indexes = coll.getIndexes(); + const index = indexes.find(index => bsonWoCompare(index.key, keyPattern) == 0); + if (index !== undefined) { + return index.name; + } + return null; +} + +const collectionName = "compound_wildcard_index_filter"; +const coll = db[collectionName]; +coll.drop(); + +const cwiFilterList = [ + // Note: 'wildcardProjection' cannot be specified if the wildcard field is not "$**". + { + keyPattern: {a: 1, b: 1, "c.$**": 1}, + wildcardProjection: undefined, + query: {a: 1, b: 1, "c.d": 1}, + }, + { + keyPattern: {a: 1, "c.$**": 1, b: 1}, + wildcardProjection: undefined, + query: {a: 1, b: 1, "c.a": 1}, + }, + { + keyPattern: {"c.$**": 1, a: 1, b: 1}, + wildcardProjection: undefined, + query: {a: 1, b: 1, "c.front": 1}, + }, + { + keyPattern: {a: 1, b: 1, "$**": 1}, + wildcardProjection: {"c": 1}, + query: {a: 1, b: 1, "c": 1}, + }, + { + keyPattern: {a: 1, "$**": 1, b: 1}, + wildcardProjection: {"d": 1}, + query: {a: 1, b: 1, "d": 1}, + }, + { + keyPattern: {"$**": 1, a: 1, b: 1}, + wildcardProjection: {"front": 1}, + query: {a: 1, b: 1, "front": 1}, + }, +]; + +// create indexes +for (const cwiFilter of cwiFilterList) { + const options = {}; + if (cwiFilter.wildcardProjection) { + options["wildcardProjection"] = cwiFilter.wildcardProjection; + } + + assert.commandWorked(coll.createIndex(cwiFilter.keyPattern, options)); + cwiFilter.indexName = getIndexName(coll, cwiFilter.keyPattern); + assert.neq(null, cwiFilter.indexName); +} + +let expectedNumberOfFilters = 0; + +// create and validate filters using indexes' key patterns +for (const cwiFilter of cwiFilterList) { + assert.commandWorked(db.runCommand({ + planCacheSetFilter: collectionName, + query: cwiFilter.query, + indexes: [cwiFilter.keyPattern], + })); + + expectedNumberOfFilters += 1; + + const filters = assert.commandWorked(db.runCommand({planCacheListFilters: collectionName})); + assert.eq(expectedNumberOfFilters, filters.filters.length, filters); + + assert.neq(null, findFilter(cwiFilter, filters.filters), filters.filters); +} + +// clear and validate filters using indexes' key patterns +for (const cwiFilter of cwiFilterList) { + assert.commandWorked(db.runCommand({ + planCacheClearFilters: collectionName, + query: cwiFilter.query, + indexes: [cwiFilter.keyPattern], + })); + + expectedNumberOfFilters -= 1; + + const filters = assert.commandWorked(db.runCommand({planCacheListFilters: collectionName})); + assert.eq(expectedNumberOfFilters, filters.filters.length, filters); + + assert.eq(null, findFilter(cwiFilter, filters.filters), filters.filters); +} + +// create and validate filters using indexes' names +for (const cwiFilter of cwiFilterList) { + assert.commandWorked(db.runCommand({ + planCacheSetFilter: collectionName, + query: cwiFilter.query, + indexes: [cwiFilter.indexName], + })); + + expectedNumberOfFilters += 1; + + const filters = assert.commandWorked(db.runCommand({planCacheListFilters: collectionName})); + assert.eq(expectedNumberOfFilters, filters.filters.length, filters); + + assert.neq(null, findFilter(cwiFilter, filters.filters), filters.filters); +} + +// clear and validate filters using indexes' names +for (const cwiFilter of cwiFilterList) { + assert.commandWorked(db.runCommand({ + planCacheClearFilters: collectionName, + query: cwiFilter.query, + indexes: [cwiFilter.indexName], + })); + + expectedNumberOfFilters -= 1; + + const filters = assert.commandWorked(db.runCommand({planCacheListFilters: collectionName})); + assert.eq(expectedNumberOfFilters, filters.filters.length, filters); + + assert.eq(null, findFilter(cwiFilter, filters.filters), filters.filters); +} +})(); diff --git a/jstests/core/index/wildcard/compound_wildcard_index_hiding.js b/jstests/core/index/wildcard/compound_wildcard_index_hiding.js new file mode 100644 index 00000000000..609b7cff019 --- /dev/null +++ b/jstests/core/index/wildcard/compound_wildcard_index_hiding.js @@ -0,0 +1,156 @@ +/** + * Tests that Compound Wildcard Indexes can be hidden. + * + * @tags: [ + * not_allowed_with_security_token, + * does_not_support_stepdowns, + * featureFlagCompoundWildcardIndexes, + * ] + */ + +(function() { +"use strict"; + +const collectionName = "compound_wildcard_index_hiding"; +const cwiList = [ + { + keyPattern: {a: 1, b: 1, "c.$**": 1}, + wildcardProjection: undefined, + }, + { + keyPattern: {a: 1, "c.$**": 1, b: 1}, + wildcardProjection: undefined, + }, + { + keyPattern: {"c.$**": 1, a: 1, b: 1}, + wildcardProjection: undefined, + }, + { + keyPattern: {a: 1, b: 1, "$**": 1}, + wildcardProjection: {"c": 1}, + }, + { + keyPattern: {a: 1, "$**": 1, b: 1}, + wildcardProjection: {"d": 1}, + }, + { + keyPattern: {"$**": 1, a: 1, b: 1}, + wildcardProjection: {"front": 1}, + }, +]; + +function getIndexName(coll, keyPattern) { + const indexes = coll.getIndexes(); + const index = indexes.find(index => bsonWoCompare(index.key, keyPattern) == 0); + if (index !== undefined) { + return index.name; + } + return null; +} + +function findIndex(coll, indexSpec) { + const indexes = coll.getIndexes(); + + for (const index of indexes) { + if (bsonWoCompare(index.key, indexSpec.keyPattern) == 0) { + return index; + } + } + + return null; +} + +function createIndex(coll, indexSpec) { + const options = {}; + if (indexSpec.wildcardProjection) { + options["wildcardProjection"] = indexSpec.wildcardProjection; + } + if (indexSpec.hidden) { + options["hidden"] = true; + } + + assert.commandWorked(coll.createIndex(indexSpec.keyPattern, options)); + indexSpec.indexName = getIndexName(coll, indexSpec.keyPattern); + assert.neq(null, indexSpec.indexName); +} + +function validateIndex(coll, indexSpec) { + const index = findIndex(coll, indexSpec); + assert.neq(null, index); + + if (indexSpec.hidden) { + assert.eq(true, index.hidden); + } else { + assert.neq(true, index.hidden); + } +} + +function setIndexVisibilityByKeyPattern(collectionName, keyPattern, hidden) { + assert.commandWorked(db.runCommand({collMod: collectionName, index: {keyPattern, hidden}})); +} + +function setIndexVisibilityByIndexName(collectionName, indexName, hidden) { + assert.commandWorked( + db.runCommand({collMod: collectionName, index: {name: indexName, hidden}})); +} + +function testCompoundWildcardIndexesHiding(cwiList, collectionName) { + db[collectionName].drop(); + assert.commandWorked(db.createCollection(collectionName)); + const coll = db[collectionName]; + let expectedNumberOfIndexes = coll.getIndexes().length; + + // create indexes + for (const indexSpec of cwiList) { + createIndex(coll, indexSpec); + + expectedNumberOfIndexes += 1; + assert.eq(expectedNumberOfIndexes, coll.getIndexes().length); + validateIndex(coll, indexSpec); + } + + // Toggle index visibility twice by key pattern + for (let i = 0; i < 2; ++i) { + for (const indexSpec of cwiList) { + indexSpec.hidden = !indexSpec.hidden; + setIndexVisibilityByKeyPattern(collectionName, indexSpec.keyPattern, indexSpec.hidden); + validateIndex(coll, indexSpec); + } + } + + // Toggle index visibility twice by index name + for (let i = 0; i < 2; ++i) { + for (const indexSpec of cwiList) { + indexSpec.hidden = !indexSpec.hidden; + setIndexVisibilityByIndexName(collectionName, indexSpec.indexName, indexSpec.hidden); + validateIndex(coll, indexSpec); + } + } + + // remove indexes + for (const indexSpec of cwiList) { + assert.commandWorked(coll.dropIndex(indexSpec.keyPattern)); + + expectedNumberOfIndexes -= 1; + assert.eq(expectedNumberOfIndexes, coll.getIndexes().length); + const index = findIndex(coll, indexSpec); + assert.eq(null, index); + } +} + +///////////////////////////////////////////////////////////////////////// +// 1. Create, hide, unhide, and delete Compound Wildcard Indexes. + +for (const index of cwiList) { + index["hidden"] = false; +} +testCompoundWildcardIndexesHiding(cwiList, collectionName); + +///////////////////////////////////////////////////////////////////////// +// 2. Create hidden, unhide, hide, and delete Compound Wildcard Indexes. + +for (const index of cwiList) { + index["hidden"] = true; +} +testCompoundWildcardIndexesHiding(cwiList, collectionName); +})(); -- cgit v1.2.1