mirror of https://github.com/mongodb/mongo
86 lines
3.4 KiB
JavaScript
86 lines
3.4 KiB
JavaScript
/*
|
|
* This script provides a runCommand override which intercepts CRUD/aggregation commands, creates
|
|
* histograms for all indexed fields and then dispatches to the original command. It is intended to
|
|
* be used for passthrough testing of the cost-based ranker.
|
|
*/
|
|
import {
|
|
getCollectionName,
|
|
getInnerCommand,
|
|
isSystemCollectionName,
|
|
isTimeSeriesCollection,
|
|
} from "jstests/libs/cmd_object_utils.js";
|
|
import {OverrideHelpers} from "jstests/libs/override_methods/override_helpers.js";
|
|
|
|
// List of commands which this script will override to first construct histograms.
|
|
const queryCommands = ["aggregate", "count", "delete", "distinct", "explain", "find", "findAndModify", "update"];
|
|
|
|
// Predicate function which returns true if a histogram over the given path can be constructed.
|
|
function isPathHistogrammable(path) {
|
|
const components = path.split(".");
|
|
return components.every((c) => {
|
|
return (
|
|
isNaN(Number(c)) && // Numeric path components are not supported.
|
|
c !== "$**"
|
|
); // Wildcard path not supported
|
|
});
|
|
}
|
|
|
|
// Returns true if the given collection has a collation specified.
|
|
function collectionHasCollation(db, collectionName) {
|
|
const collectionInfo = db.getCollectionInfos({name: collectionName});
|
|
if (!collectionInfo || collectionInfo.length === 0) {
|
|
return false;
|
|
}
|
|
return collectionInfo[0].options.hasOwnProperty("collation");
|
|
}
|
|
|
|
// Returns true if the collection can have 'analyze' run on it.
|
|
function isCollectionHistogrammable(db, coll) {
|
|
// TODO SERVER-100679: Remove collation restriction
|
|
return (
|
|
!coll.isCapped() &&
|
|
!isSystemCollectionName(coll.getName()) &&
|
|
!isTimeSeriesCollection(db, coll.getName()) &&
|
|
!collectionHasCollation(db, coll.getName())
|
|
);
|
|
}
|
|
|
|
export function runCommandOverride(conn, dbName, _cmdName, cmdObj, clientFunction, makeFuncArgs) {
|
|
// If we are running a non-query command, dispatch the original command. This is necessary to do
|
|
// here because the getCollectionName() function below will run a command itself, resulting in a
|
|
// recursive call to this function.
|
|
if (!queryCommands.includes(_cmdName)) {
|
|
return clientFunction.apply(conn, makeFuncArgs(cmdObj));
|
|
}
|
|
|
|
const db = conn.getDB(dbName);
|
|
const innerCmd = getInnerCommand(cmdObj);
|
|
const collectionName = getCollectionName(db, innerCmd);
|
|
const coll = db[collectionName];
|
|
|
|
// Make histograms for all indexed fields.
|
|
if (collectionName !== undefined && isCollectionHistogrammable(db, coll)) {
|
|
// Drop statistics collection. This should not be necessary, but it is currently a
|
|
// workaround for SERVER-100679.
|
|
db.system.statistics.getCollection(collectionName).drop();
|
|
|
|
const indexes = coll.getIndexes();
|
|
|
|
// Construct set of indexed paths
|
|
let indexedPaths = new Set();
|
|
indexes.forEach((index) =>
|
|
Object.keys(index.key)
|
|
.filter(isPathHistogrammable)
|
|
.forEach((path) => indexedPaths.add(path)),
|
|
);
|
|
// Create histogram for each path
|
|
indexedPaths.forEach((path) => assert.commandWorked(db.runCommand({analyze: collectionName, key: path})));
|
|
}
|
|
|
|
// Dispatch to original command after creating histograms.
|
|
return clientFunction.apply(conn, makeFuncArgs(cmdObj));
|
|
}
|
|
|
|
// Install the runCommand hook
|
|
OverrideHelpers.overrideRunCommand(runCommandOverride);
|