summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Wawrzyniak <anna.wawrzyniak@mongodb.com>2022-01-05 22:04:05 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-01-05 23:09:49 +0000
commitad4f490665681d18c1291ce52e8ba6a01f20788b (patch)
tree0f66ff42cbd01b4877a61e602fc35499a5d8cba2
parent93830dc1960795465ed46532ceffb3a4b976a9a5 (diff)
downloadmongo-ad4f490665681d18c1291ce52e8ba6a01f20788b.tar.gz
SERVER-60254 Enable group pushdown $unionWith explain tests
-rw-r--r--jstests/aggregation/extras/utils.js9
-rw-r--r--jstests/aggregation/sources/unionWith/unionWith_explain.js128
2 files changed, 79 insertions, 58 deletions
diff --git a/jstests/aggregation/extras/utils.js b/jstests/aggregation/extras/utils.js
index 626a7a6939b..f25f77d5a7f 100644
--- a/jstests/aggregation/extras/utils.js
+++ b/jstests/aggregation/extras/utils.js
@@ -100,15 +100,15 @@ function documentEq(dl, dr, verbose = false, valueComparator, fieldsToSkip = [])
if (!dl.hasOwnProperty(propertyName))
continue;
+ if (fieldsToSkip.includes(propertyName))
+ continue;
+
// The documents aren't equal if they don't both have the property.
if (!dr.hasOwnProperty(propertyName)) {
debug('documentEq: dr doesn\'t have property ' + propertyName);
return false;
}
- if (fieldsToSkip.includes(propertyName))
- continue;
-
if (!anyEq(dl[propertyName], dr[propertyName], verbose, valueComparator, fieldsToSkip)) {
return false;
}
@@ -119,6 +119,9 @@ function documentEq(dl, dr, verbose = false, valueComparator, fieldsToSkip = [])
if (!dr.hasOwnProperty(propertyName))
continue;
+ if (fieldsToSkip.includes(propertyName))
+ continue;
+
// If dl doesn't have this they are not equal; if it does, we compared it above and know it
// to be equal.
if (!dl.hasOwnProperty(propertyName)) {
diff --git a/jstests/aggregation/sources/unionWith/unionWith_explain.js b/jstests/aggregation/sources/unionWith/unionWith_explain.js
index 8044881e3a8..664844c6159 100644
--- a/jstests/aggregation/sources/unionWith/unionWith_explain.js
+++ b/jstests/aggregation/sources/unionWith/unionWith_explain.js
@@ -28,6 +28,27 @@ for (let i = 0; i < docsPerColl; i++) {
assert.commandWorked(collB.insert({b: i, val: i * 2, groupKey: i}));
assert.commandWorked(collC.insert({c: i, val: 10 - i, groupKey: i}));
}
+
+const executionStatsIngoredFields = [
+ "executionTimeMillis",
+ "executionTimeMillisEstimate",
+ "saveState",
+ "restoreState",
+];
+
+const stagesIgnoredFields = [
+ "slots",
+];
+
+const mongosIgnoredFields = [
+ "works",
+ "needTime",
+].concat(executionStatsIngoredFields, stagesIgnoredFields);
+
+const queryPlannerIgnoredFields = [
+ "optimizedPipeline",
+].concat(stagesIgnoredFields);
+
function getUnionWithStage(explain) {
if (explain.splitPipeline != null) {
// If there is only one shard, the whole pipeline will run on that shard.
@@ -49,71 +70,67 @@ function buildErrorString(unionExplain, realExplain, field) {
"\nRegular:\n" + tojson(realExplain);
}
-function docEqWithIgnoredFields(union, regular) {
- return documentEq(union, regular, false /* verbose */, null /* valueComparator */, [
- "executionTimeMillis",
- "executionTimeMillisEstimate",
- "saveState",
- "restoreState",
- "works",
- "needTime",
- "slots",
- ]);
+function anyEqWithIgnoredFields(union, regular, ignoredFields) {
+ return anyEq(union, regular, false /* verbose */, null /* valueComparator */, ignoredFields);
}
-function arrayEqWithIgnoredFields(union, regular) {
- return arrayEq(union, regular, false /* verbose */, null /* valueComparator */, [
- "slots",
- ]);
+function documentEqWithIgnoredFields(union, regular, ignoredFields) {
+ return documentEq(
+ union, regular, false /* verbose */, null /* valueComparator */, ignoredFields);
}
-function assertExplainEq(unionExplain, regularExplain) {
- const unionStage = getUnionWithStage(unionExplain);
- assert(unionStage);
- const unionSubExplain = unionStage.$unionWith.pipeline;
+function arrayEqWithIgnoredFields(union, regular, ignoredFields) {
+ return arrayEq(union, regular, false /* verbose */, null /* valueComparator */, ignoredFields);
+}
+
+function assertExplainEq(union, regular) {
if (FixtureHelpers.isMongos(testDB)) {
- const splitPipe = unionExplain.splitPipeline;
- if (splitPipe === null) {
- assert.eq(unionSubExplain.splitPipeline,
- regularExplain.splitPipeline,
- buildErrorString(unionSubExplain, regularExplain, "splitPipeline"));
- } else {
- assert(
- docEqWithIgnoredFields(unionSubExplain.splitPipeline, regularExplain.splitPipeline),
- buildErrorString(unionSubExplain, regularExplain, "splitPipeline"));
- }
- assert.eq(unionSubExplain.mergeType,
- regularExplain.mergeType,
- buildErrorString(unionSubExplain, regularExplain, "mergeType"));
- assert(docEqWithIgnoredFields(unionSubExplain.shards, regularExplain.shards),
- buildErrorString(unionSubExplain, regularExplain, "shards"));
+ assert(
+ anyEqWithIgnoredFields(union.splitPipeline, regular.splitPipeline, mongosIgnoredFields),
+ buildErrorString(union, regular, "splitPipeline"));
+
+ assert.eq(
+ union.mergeType, regular.mergeType, buildErrorString(union, regular, "mergeType"));
+
+ assert(documentEqWithIgnoredFields(union.shards, regular.shards, mongosIgnoredFields),
+ buildErrorString(union, regular, "shards"));
+ } else if ("executionStats" in regular) {
+ const unionStats = union[0].$cursor.executionStats;
+ const regularStats = regular.executionStats;
+
+ assert(documentEqWithIgnoredFields(unionStats.executionStages,
+ regularStats.executionStages,
+ executionStatsIngoredFields),
+ buildErrorString(unionStats, regularStats, "executionStages"));
+ } else if ("stages" in regular) {
+ assert(arrayEqWithIgnoredFields(union, regular.stages, stagesIgnoredFields),
+ buildErrorString(union, regular, "stages"));
+ } else if ("queryPlanner" in regular) {
+ assert.eq(union.length, 1, "Expected single union stage");
+ const unionCursor = union[0].$cursor;
+ assert(documentEqWithIgnoredFields(
+ regular.queryPlanner, unionCursor.queryPlanner, queryPlannerIgnoredFields),
+ buildErrorString(unionCursor, regular, "queryPlanner"));
} else {
- if ("executionStats" in unionSubExplain[0].$cursor) {
- const unionSubStats =
- unionStage.$unionWith.pipeline[0].$cursor.executionStats.executionStages;
- const realStats = regularExplain.executionStats.executionStages;
- assert(docEqWithIgnoredFields(unionSubStats, realStats),
- buildErrorString(unionSubStats, realStats, "stages"));
- } else {
- const realExplain = regularExplain.stages;
- assert(arrayEqWithIgnoredFields(unionSubExplain, realExplain),
- buildErrorString(unionSubExplain, realExplain, "stages"));
- }
+ assert(false,
+ "Don't know how to compare following explains.\n" +
+ "regular: " + tojson(regularExplain) + "\n" +
+ "union: " + tojson(unionSubExplain) + "\n");
}
}
-function testPipeline(pipeline) {
- // When the SBE $group pushdown feature is enabled, a $group alone is pushed down but it is not
- // when it's in $unionWith sub-pipeline. So, we don't need test such scenarios for now.
- // Eventually such scenarios should be enabled.
- if (groupPushdownEnabled && pipeline.some(stage => stage.hasOwnProperty("$group"))) {
- return;
- }
+function assertExplainMatch(unionExplain, regularExplain) {
+ const unionStage = getUnionWithStage(unionExplain);
+ assert(unionStage);
+ const unionSubExplain = unionStage.$unionWith.pipeline;
+ assertExplainEq(unionSubExplain, regularExplain);
+}
+function testPipeline(pipeline) {
let unionResult = collA.aggregate([{$unionWith: {coll: collB.getName(), pipeline: pipeline}}],
{explain: true});
let queryResult = collB.aggregate(pipeline, {explain: true});
- assertExplainEq(unionResult, queryResult);
+ assertExplainMatch(unionResult, queryResult);
}
testPipeline([{$addFields: {bump: true}}]);
@@ -180,7 +197,8 @@ assert.commandWorked(expectedResult);
let unionStage = getUnionWithStage(result);
assert(unionStage, result);
if (FixtureHelpers.isMongos(testDB)) {
- assert(docEqWithIgnoredFields(expectedResult.shards, unionStage.$unionWith.pipeline.shards),
+ assert(documentEqWithIgnoredFields(
+ expectedResult.shards, unionStage.$unionWith.pipeline.shards, mongosIgnoredFields),
buildErrorString(unionStage, expectedResult));
// TODO SERVER-50597 Fix unionWith nReturned stat in sharded cluster
// assert.eq(unionStage.nReturned, docsPerColl, unionStage);
@@ -227,7 +245,7 @@ result = collA.explain("executionStats").aggregate([
{$unionWith: {coll: indexedColl.getName(), pipeline: [{$match: {val: {$gt: 2}}}]}}
]);
expectedResult = indexedColl.explain("executionStats").aggregate([{$match: {val: {$gt: 2}}}]);
-assertExplainEq(result, expectedResult);
+assertExplainMatch(result, expectedResult);
// Test a nested $unionWith which itself should perform an index scan.
testPipeline([{$unionWith: {coll: indexedColl.getName(), pipeline: [{$match: {val: {$gt: 0}}}]}}]);
@@ -240,6 +258,6 @@ if (!res["failpoint.disablePipelineOptimization"].mode) {
result = collA.explain("executionStats")
.aggregate([{$unionWith: indexedColl.getName()}, {$match: {val: {$gt: 2}}}]);
expectedResult = indexedColl.explain("executionStats").aggregate([{$match: {val: {$gt: 2}}}]);
- assertExplainEq(result, expectedResult);
+ assertExplainMatch(result, expectedResult);
}
})();