Files
mongo/jstests/core/collation_plan_cache.js

240 lines
10 KiB
JavaScript

// Integration testing for the plan cache and index filter commands with collation.
(function() {
'use strict';
var coll = db.collation_plan_cache;
coll.drop();
assert.writeOK(coll.insert({a: 'foo', b: 5}));
// We need two indexes that each query can use so that a plan cache entry is created.
assert.commandWorked(coll.createIndex({a: 1}, {collation: {locale: 'en_US'}}));
assert.commandWorked(coll.createIndex({a: 1, b: 1}, {collation: {locale: 'en_US'}}));
// We need an index with a different collation, so that string comparisons affect the query
// shape.
assert.commandWorked(coll.createIndex({b: 1}, {collation: {locale: 'fr_CA'}}));
// listQueryShapes().
// Run a query so that an entry is inserted into the cache.
assert.commandWorked(
coll.runCommand("find", {filter: {a: 'foo', b: 5}, collation: {locale: "en_US"}}),
'find command failed');
// The query shape should have been added.
var shapes = coll.getPlanCache().listQueryShapes();
assert.eq(1, shapes.length, 'unexpected cache size after running query');
assert.eq(shapes[0],
{
query: {a: 'foo', b: 5},
sort: {},
projection: {},
collation: {
locale: 'en_US',
caseLevel: false,
caseFirst: 'off',
strength: 3,
numericOrdering: false,
alternate: 'non-ignorable',
maxVariable: 'punct',
normalization: false,
backwards: false,
version: '57.1'
}
},
'unexpected query shape returned from listQueryShapes()');
coll.getPlanCache().clear();
// getPlansByQuery().
// Passing a query with an empty collation object should throw.
assert.throws(function() {
coll.getPlanCache().getPlansByQuery(
{query: {a: 'foo', b: 5}, sort: {}, projection: {}, collation: {}});
}, [], 'empty collation object should throw');
// Passing a query with an invalid collation object should throw.
assert.throws(function() {
coll.getPlanCache().getPlansByQuery(
{query: {a: 'foo', b: 5}, sort: {}, projection: {}, collation: {bad: "value"}});
}, [], 'invalid collation object should throw');
// Run a query so that an entry is inserted into the cache.
assert.commandWorked(
coll.runCommand("find", {filter: {a: 'foo', b: 5}, collation: {locale: "en_US"}}),
'find command failed');
// The query should have cached plans.
assert.lt(
0,
coll.getPlanCache()
.getPlansByQuery(
{query: {a: 'foo', b: 5}, sort: {}, projection: {}, collation: {locale: 'en_US'}})
.length,
'unexpected number of cached plans for query');
// Test passing the query, sort, projection, and collation to getPlansByQuery() as separate
// arguments.
assert.lt(
0,
coll.getPlanCache().getPlansByQuery({a: 'foo', b: 5}, {}, {}, {locale: 'en_US'}).length,
'unexpected number of cached plans for query');
// Test passing the query, sort, projection, and collation to getPlansByQuery() as separate
// arguments.
assert.eq(0,
coll.getPlanCache().getPlansByQuery({a: 'foo', b: 5}).length,
'unexpected number of cached plans for query');
// A query with a different collation should have no cached plans.
assert.eq(
0,
coll.getPlanCache()
.getPlansByQuery(
{query: {a: 'foo', b: 5}, sort: {}, projection: {}, collation: {locale: 'fr_CA'}})
.length,
'unexpected number of cached plans for query');
// A query with different string locations should have no cached plans.
assert.eq(0,
coll.getPlanCache()
.getPlansByQuery({
query: {a: 'foo', b: 'bar'},
sort: {},
projection: {},
collation: {locale: 'en_US'}
})
.length,
'unexpected number of cached plans for query');
coll.getPlanCache().clear();
// clearPlansByQuery().
// Passing a query with an empty collation object should throw.
assert.throws(function() {
coll.getPlanCache().clearPlansByQuery(
{query: {a: 'foo', b: 5}, sort: {}, projection: {}, collation: {}});
}, [], 'empty collation object should throw');
// Passing a query with an invalid collation object should throw.
assert.throws(function() {
coll.getPlanCache().clearPlansByQuery(
{query: {a: 'foo', b: 5}, sort: {}, projection: {}, collation: {bad: "value"}});
}, [], 'invalid collation object should throw');
// Run a query so that an entry is inserted into the cache.
assert.commandWorked(
coll.runCommand("find", {filter: {a: 'foo', b: 5}, collation: {locale: "en_US"}}),
'find command failed');
assert.eq(1,
coll.getPlanCache().listQueryShapes().length,
'unexpected cache size after running query');
// Dropping a query shape with a different collation should have no effect.
coll.getPlanCache().clearPlansByQuery(
{query: {a: 'foo', b: 5}, sort: {}, projection: {}, collation: {locale: 'fr_CA'}});
assert.eq(1,
coll.getPlanCache().listQueryShapes().length,
'unexpected cache size after dropping uncached query shape');
// Dropping a query shape with different string locations should have no effect.
coll.getPlanCache().clearPlansByQuery(
{query: {a: 'foo', b: 'bar'}, sort: {}, projection: {}, collation: {locale: 'en_US'}});
assert.eq(1,
coll.getPlanCache().listQueryShapes().length,
'unexpected cache size after dropping uncached query shape');
// Dropping query shape.
coll.getPlanCache().clearPlansByQuery(
{query: {a: 'foo', b: 5}, sort: {}, projection: {}, collation: {locale: 'en_US'}});
assert.eq(0,
coll.getPlanCache().listQueryShapes().length,
'unexpected cache size after dropping query shapes');
// Index filter commands.
// planCacheSetFilter should fail if 'collation' is an empty object.
assert.commandFailed(
coll.runCommand('planCacheSetFilter',
{query: {a: 'foo', b: 5}, collation: {}, indexes: [{a: 1, b: 1}]}),
'planCacheSetFilter should fail on empty collation object');
// planCacheSetFilter should fail if 'collation' is an invalid object.
assert.commandFailed(
coll.runCommand(
'planCacheSetFilter',
{query: {a: 'foo', b: 5}, collation: {bad: "value"}, indexes: [{a: 1, b: 1}]}),
'planCacheSetFilter should fail on invalid collation object');
// Set a plan cache filter.
assert.commandWorked(
coll.runCommand(
'planCacheSetFilter',
{query: {a: 'foo', b: 5}, collation: {locale: 'en_US'}, indexes: [{a: 1, b: 1}]}),
'planCacheSetFilter failed');
// Check the plan cache filter was added.
var res = coll.runCommand('planCacheListFilters');
assert.commandWorked(res, 'planCacheListFilters failed');
assert.eq(1, res.filters.length, 'unexpected number of plan cache filters');
assert.eq(res.filters[0],
{
query: {a: 'foo', b: 5},
sort: {},
projection: {},
collation: {
locale: 'en_US',
caseLevel: false,
caseFirst: 'off',
strength: 3,
numericOrdering: false,
alternate: 'non-ignorable',
maxVariable: 'punct',
normalization: false,
backwards: false,
version: '57.1'
},
indexes: [{a: 1, b: 1}]
},
'unexpected plan cache filter');
// planCacheClearFilters should fail if 'collation' is an empty object.
assert.commandFailed(
coll.runCommand('planCacheClearFilters', {query: {a: 'foo', b: 5}, collation: {}}),
'planCacheClearFilters should fail on empty collation object');
// planCacheSetFilter should fail if 'collation' is an invalid object.
assert.commandFailed(coll.runCommand('planCacheClearFilters',
{query: {a: 'foo', b: 5}, collation: {bad: 'value'}}),
'planCacheClearFilters should fail on invalid collation object');
// Clearing a plan cache filter with no collation should have no effect.
assert.commandWorked(coll.runCommand('planCacheClearFilters', {query: {a: 'foo', b: 5}}));
assert.eq(1,
coll.runCommand('planCacheListFilters').filters.length,
'unexpected number of plan cache filters');
// Clearing a plan cache filter with a different collation should have no effect.
assert.commandWorked(coll.runCommand('planCacheClearFilters',
{query: {a: 'foo', b: 5}, collation: {locale: 'fr_CA'}}));
assert.eq(1,
coll.runCommand('planCacheListFilters').filters.length,
'unexpected number of plan cache filters');
// Clearing a plan cache filter with different string locations should have no effect.
assert.commandWorked(coll.runCommand(
'planCacheClearFilters', {query: {a: 'foo', b: 'bar', collation: {locale: 'en_US'}}}));
assert.eq(1,
coll.runCommand('planCacheListFilters').filters.length,
'unexpected number of plan cache filters');
// Clear plan cache filter.
assert.commandWorked(coll.runCommand('planCacheClearFilters',
{query: {a: 'foo', b: 5}, collation: {locale: 'en_US'}}));
assert.eq(0,
coll.runCommand('planCacheListFilters').filters.length,
'unexpected number of plan cache filters');
})();