summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/lookup_pushdown_semantics.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/noPassthrough/lookup_pushdown_semantics.js')
-rw-r--r--jstests/noPassthrough/lookup_pushdown_semantics.js194
1 files changed, 185 insertions, 9 deletions
diff --git a/jstests/noPassthrough/lookup_pushdown_semantics.js b/jstests/noPassthrough/lookup_pushdown_semantics.js
index 2cb6de34020..1cae12893e7 100644
--- a/jstests/noPassthrough/lookup_pushdown_semantics.js
+++ b/jstests/noPassthrough/lookup_pushdown_semantics.js
@@ -8,9 +8,7 @@ load("jstests/libs/sbe_util.js"); // For 'checkSBEEnabled()'.
load("jstests/aggregation/extras/utils.js");
// Standalone cases.
-const conn = MongoRunner.runMongod({
- setParameter: {featureFlagSBELookupPushdown: true, featureFlagSBELookupPushdownIndexJoin: true}
-});
+const conn = MongoRunner.runMongod({setParameter: "featureFlagSBELookupPushdown=true"});
assert.neq(null, conn, "mongod was unable to start up");
const db = conn.getDB("lookup_pushdown");
if (!checkSBEEnabled(db, ["featureFlagSBELookupPushdown"])) {
@@ -48,6 +46,7 @@ function runTest_SingleForeignRecord({
if (foreignIndex) {
assert.commandWorked(foreignColl.createIndex(foreignIndex));
+ testDescription += ` (foreign index ${tojson(foreignIndex)})`;
}
const results = localColl.aggregate([{
@@ -98,6 +97,7 @@ function runTest_SingleLocalRecord({
if (foreignIndex) {
assert.commandWorked(foreignColl.createIndex(foreignIndex));
+ testDescription += ` (foreign index ${tojson(foreignIndex)})`;
}
const results = localColl.aggregate([{
@@ -148,12 +148,26 @@ function runTest_SingleLocalRecord({
assert.eq(results[0].matched, []);
})();
-(function testMatchingTopLevelFieldToScalar() {
+function testMatchingTopLevelFieldToNonArray(indexType) {
+ // NOTE: There is no shell equivalent for the following BSON types:
+ // - Code (13)
+ // - Symbol (14)
+ // - CodeWScope (15)
const docs = [
{_id: 0, a: NumberInt(0)},
{_id: 1, a: 3.14},
{_id: 2, a: NumberDecimal(3.14)},
{_id: 3, a: "abc"},
+ {_id: 4, a: {b: 1, c: 2, d: 3}},
+ {_id: 5, a: true},
+ {_id: 6, a: false},
+ {_id: 7, a: new ISODate("2022-01-01T00:00:00.00Z")},
+ {_id: 8, a: new Timestamp(1, 123)},
+ {_id: 9, a: new ObjectId("0102030405060708090A0B0C")},
+ {_id: 10, a: new BinData(0, "BBBBBBBBBBBBBBBBBBBBBBBBBBBB")},
+ {_id: 11, a: /hjkl/},
+ {_id: 12, a: /hjkl/g},
+ {_id: 13, a: new DBRef("collection", "id", "database")},
];
docs.forEach(doc => {
@@ -164,7 +178,7 @@ function runTest_SingleLocalRecord({
localField: "a",
foreignRecord: {b: doc.a},
foreignField: "b",
- foreignIndex: {b: 1},
+ foreignIndex: {b: indexType},
idsExpectedToMatch: [doc._id]
});
runTest_SingleLocalRecord({
@@ -174,7 +188,7 @@ function runTest_SingleLocalRecord({
localField: "b",
foreignRecords: docs,
foreignField: "a",
- foreignIndex: {a: 1},
+ foreignIndex: {a: indexType},
idsExpectedToMatch: [doc._id]
});
});
@@ -186,7 +200,7 @@ function runTest_SingleLocalRecord({
localField: "a",
foreignRecord: {b: 'xxx'},
foreignField: "b",
- foreignIndex: {b: 1},
+ foreignIndex: {b: indexType},
idsExpectedToMatch: []
});
runTest_SingleLocalRecord({
@@ -196,10 +210,172 @@ function runTest_SingleLocalRecord({
localField: "b",
foreignRecords: docs,
foreignField: "a",
- foreignIndex: {a: 1},
+ foreignIndex: {a: indexType},
idsExpectedToMatch: []
});
-})();
+}
+
+testMatchingTopLevelFieldToNonArray(1 /* indexType */);
+testMatchingTopLevelFieldToNonArray(-1 /* indexType */);
+testMatchingTopLevelFieldToNonArray("hashed" /* indexType */);
+
+function testMatchingTopLevelFieldToNullAndUndefined(indexType) {
+ const foreignRecords = [
+ {_id: 0, a: null},
+ {_id: 1, a: undefined},
+ ];
+ // We do not currently support hashed indexes on the collections with arrays.
+ if (indexType != "hashed") {
+ foreignRecords.push({_id: 2, a: []}, {_id: 3, a: [[]]});
+ }
+
+ runTest_SingleLocalRecord({
+ testDescription: "Null should match only to null",
+ localRecord: {b: null},
+ localField: "b",
+ foreignRecords,
+ foreignField: "a",
+ foreignIndex: {a: indexType},
+ idsExpectedToMatch: [0]
+ });
+}
+
+testMatchingTopLevelFieldToNullAndUndefined(1 /* indexType */);
+testMatchingTopLevelFieldToNullAndUndefined(-1 /* indexType */);
+testMatchingTopLevelFieldToNullAndUndefined("hashed" /* indexType */);
+
+function testMatchingTopLevelFieldToArrays(indexType) {
+ runTest_SingleLocalRecord({
+ testDescription: "Scalar should match arrays containing that value",
+ localRecord: {b: 1},
+ localField: "b",
+ foreignRecords: [
+ {_id: 0, a: 1},
+ {_id: 1, a: [1]},
+ {_id: 2, a: [1, 2, 3]},
+ {_id: 3, a: [3, 2, 1]},
+ {_id: 4, a: [4, 5, 6]},
+ {_id: 5, a: []},
+ ],
+ foreignField: "a",
+ foreignIndex: {a: indexType},
+ idsExpectedToMatch: [0, 1, 2, 3]
+ });
+
+ runTest_SingleLocalRecord({
+ testDescription: "Empty array should only match to empty array",
+ localRecord: {b: [[]]},
+ localField: "b",
+ foreignRecords: [
+ {_id: 0, a: null},
+ {_id: 1, a: undefined},
+ {_id: 2, a: []},
+ {_id: 3, a: [[]]},
+ {_id: 4, a: [null]},
+ {_id: 5, a: [undefined]},
+ {_id: 6, a: [1]},
+ {_id: 7, a: [1, 2, 3]},
+ ],
+ foreignField: "a",
+ foreignIndex: {a: indexType},
+ idsExpectedToMatch: [2, 3]
+ });
+
+ runTest_SingleLocalRecord({
+ testDescription: "Single element arrays should match only single-element arrays",
+ localRecord: {b: [[1]]},
+ localField: "b",
+ foreignRecords: [
+ {_id: 0, a: 1},
+ {_id: 1, a: [1]},
+ {_id: 2, a: [1, 2, 3]},
+ {_id: 3, a: [3, 2, 1]},
+ {_id: 4, a: [4, 5, 6]},
+ {_id: 5, a: []},
+ ],
+ foreignField: "a",
+ foreignIndex: {a: indexType},
+ idsExpectedToMatch: [1]
+ });
+
+ runTest_SingleLocalRecord({
+ testDescription: "Arrays with multiple elements should only match itself",
+ localRecord: {b: [[1, 2, 3]]},
+ localField: "b",
+ foreignRecords: [
+ {_id: 0, a: 1},
+ {_id: 1, a: [1]},
+ {_id: 2, a: [1, 2, 3]},
+ {_id: 3, a: [3, 2, 1]},
+ {_id: 4, a: [4, 5, 6]},
+ {_id: 5, a: []},
+ ],
+ foreignField: "a",
+ foreignIndex: {a: indexType},
+ idsExpectedToMatch: [2]
+ });
+
+ runTest_SingleLocalRecord({
+ testDescription: "Array queries must work on hashed indexes",
+ localRecord: {b: [[1, 2, 3]]},
+ localField: "b",
+ foreignRecords: [
+ {_id: 0, a: 1},
+ ],
+ foreignField: "a",
+ foreignIndex: {a: "hashed"},
+ idsExpectedToMatch: []
+ });
+}
+
+testMatchingTopLevelFieldToArrays(1 /* indexType */);
+testMatchingTopLevelFieldToArrays(-1 /* indexType */);
+
+function testMatchingWithNestedPaths(indexType) {
+ const foreignRecords = [
+ {_id: 0, a: {b: {c: 1}}},
+ {_id: 1, a: {no_b: 1}},
+ {_id: 2, a: {b: {no_c: 1}}},
+ ];
+ const idsExpectedToMatch = [0];
+
+ // We do not currently support hashed indexes on the collections with arrays.
+ if (indexType != "hashed") {
+ foreignRecords.push({_id: 3, a: {b: {c: [1]}}},
+ {_id: 4, a: [{b: [{c: 1}, {c: 2}]}, {b: [{c: 3}, {c: 4}]}]});
+ idsExpectedToMatch.push(3, 4);
+ }
+
+ runTest_SingleLocalRecord({
+ testDescription: "Index join with nested path in foreign field",
+ localRecord: {b: 1},
+ localField: "b",
+ foreignRecords,
+ foreignField: "a.b.c",
+ foreignIndex: {"a.b.c": indexType},
+ idsExpectedToMatch,
+ });
+
+ runTest_SingleForeignRecord({
+ testDescription: "Index join with nested path in local field",
+ localRecords: [
+ {_id: 0, a: {b: {c: 1}}},
+ {_id: 1, a: {b: {c: [1]}}},
+ {_id: 2, a: [{b: [{c: 1}, {c: 2}]}, {b: [{c: 3}, {c: 4}]}]},
+ {_id: 3, a: {no_b: 1}},
+ {_id: 4, a: {b: {no_c: 1}}},
+ ],
+ localField: "a.b.c",
+ foreignRecord: {b: 1},
+ foreignField: "b",
+ foreignIndex: {b: indexType},
+ idsExpectedToMatch: [0, 1, 2]
+ });
+}
+
+testMatchingWithNestedPaths(1 /* indexType */);
+testMatchingWithNestedPaths(-1 /* indexType */);
+testMatchingWithNestedPaths("hashed" /* indexType */);
MongoRunner.stopMongod(conn);
}());