mirror of https://github.com/mongodb/mongo
129 lines
4.9 KiB
JavaScript
129 lines
4.9 KiB
JavaScript
import {getCommandName} from "jstests/libs/cmd_object_utils.js";
|
|
|
|
// Store the original 'runCommand' function before applying any overrides.
|
|
const preOverrideRunCommand = Mongo.prototype.runCommand;
|
|
|
|
/**
|
|
* The OverrideHelpers object defines convenience methods for overriding commands and functions in
|
|
* the mongo shell.
|
|
*/
|
|
export const OverrideHelpers = (function () {
|
|
function makeIsAggregationWithFirstStage(stageName) {
|
|
return function (commandName, commandObj) {
|
|
if (commandName !== "aggregate" || typeof commandObj !== "object" || commandObj === null) {
|
|
return false;
|
|
}
|
|
|
|
if (!Array.isArray(commandObj.pipeline) || commandObj.pipeline.length === 0) {
|
|
return false;
|
|
}
|
|
|
|
const firstStage = commandObj.pipeline[0];
|
|
if (typeof firstStage !== "object" || firstStage === null) {
|
|
return false;
|
|
}
|
|
|
|
return Object.keys(firstStage)[0] === stageName;
|
|
};
|
|
}
|
|
|
|
function isAggregationWithOutOrMergeStage(commandName, commandObj) {
|
|
if (commandName !== "aggregate" || typeof commandObj !== "object" || commandObj === null) {
|
|
return false;
|
|
}
|
|
|
|
if (!Array.isArray(commandObj.pipeline) || commandObj.pipeline.length === 0) {
|
|
return false;
|
|
}
|
|
|
|
const lastStage = commandObj.pipeline[commandObj.pipeline.length - 1];
|
|
if (typeof lastStage !== "object" || lastStage === null) {
|
|
return false;
|
|
}
|
|
|
|
const lastStageName = Object.keys(lastStage)[0];
|
|
return lastStageName === "$out" || lastStageName === "$merge";
|
|
}
|
|
|
|
function isMapReduceWithInlineOutput(commandName, commandObj) {
|
|
if (
|
|
(commandName !== "mapReduce" && commandName !== "mapreduce") ||
|
|
typeof commandObj !== "object" ||
|
|
commandObj === null
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
if (typeof commandObj.out !== "object") {
|
|
return false;
|
|
}
|
|
|
|
return commandObj.out.hasOwnProperty("inline");
|
|
}
|
|
|
|
function prependOverrideInParallelShell(overrideFile) {
|
|
const startParallelShellOriginal = startParallelShell;
|
|
|
|
startParallelShell = function (jsCode, port, noConnect) {
|
|
let newCode;
|
|
if (typeof jsCode === "function") {
|
|
// Load the override file and immediately invoke the supplied function.
|
|
if (jsCode.constructor.name === "AsyncFunction") {
|
|
newCode = `await import("${overrideFile}"); await (${jsCode.toString()})();`;
|
|
} else {
|
|
newCode = `await import("${overrideFile}"); (${jsCode.toString()})();`;
|
|
}
|
|
} else {
|
|
newCode = `await import("${overrideFile}"); ${jsCode};`;
|
|
}
|
|
|
|
return startParallelShellOriginal(newCode, port, noConnect);
|
|
};
|
|
}
|
|
|
|
function overrideRunCommand(overrideFunc) {
|
|
const mongoRunCommandOriginal = Mongo.prototype.runCommand;
|
|
|
|
Mongo.prototype.runCommand = function (dbName, commandObj, options) {
|
|
return overrideFunc(
|
|
this,
|
|
dbName,
|
|
getCommandName(commandObj),
|
|
commandObj,
|
|
mongoRunCommandOriginal,
|
|
(commandObj, db = dbName) => [db, commandObj, options],
|
|
);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Higher order function for executing `db.runCommand()` commands without overrides.
|
|
* Example usage:
|
|
* const res = OverrideHelpers.withPreOverrideRunCommand(() => db.adminCommand(cmd));
|
|
*/
|
|
function withPreOverrideRunCommand(fn) {
|
|
const overriddenRunCommand = Mongo.prototype.runCommand;
|
|
try {
|
|
Mongo.prototype.runCommand = preOverrideRunCommand;
|
|
return fn();
|
|
} finally {
|
|
Mongo.prototype.runCommand = overriddenRunCommand;
|
|
}
|
|
}
|
|
|
|
return {
|
|
isAggregationWithListLocalSessionsStage: makeIsAggregationWithFirstStage("$listLocalSessions"),
|
|
isAggregationWithOutOrMergeStage: isAggregationWithOutOrMergeStage,
|
|
isAggregationWithCurrentOpStage: makeIsAggregationWithFirstStage("$currentOp"),
|
|
isAggregationWithChangeStreamStage: makeIsAggregationWithFirstStage("$changeStream"),
|
|
isAggregationWithPlanCacheStatsStage: makeIsAggregationWithFirstStage("$planCacheStats"),
|
|
isAggregationWithInternalListCollections: makeIsAggregationWithFirstStage("$_internalListCollections"),
|
|
isAggregationWithListClusterCatalog: makeIsAggregationWithFirstStage("$listClusterCatalog"),
|
|
isAggregationWithQuerySettings: makeIsAggregationWithFirstStage("$querySettings"),
|
|
isMapReduceWithInlineOutput: isMapReduceWithInlineOutput,
|
|
prependOverrideInParallelShell: prependOverrideInParallelShell,
|
|
overrideRunCommand: overrideRunCommand,
|
|
withPreOverrideRunCommand: withPreOverrideRunCommand,
|
|
};
|
|
})();
|