summaryrefslogtreecommitdiff
path: root/jstests/core/idhack.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/core/idhack.js')
-rw-r--r--jstests/core/idhack.js201
1 files changed, 101 insertions, 100 deletions
diff --git a/jstests/core/idhack.js b/jstests/core/idhack.js
index a2fb8f39640..880716ed206 100644
--- a/jstests/core/idhack.js
+++ b/jstests/core/idhack.js
@@ -1,103 +1,104 @@
// @tags: [requires_non_retryable_writes, assumes_balancer_off]
(function() {
- "use strict";
-
- const t = db.idhack;
- t.drop();
-
- // Include helpers for analyzing explain output.
- load("jstests/libs/analyze_plan.js");
-
- assert.writeOK(t.insert({_id: {x: 1}, z: 1}));
- assert.writeOK(t.insert({_id: {x: 2}, z: 2}));
- assert.writeOK(t.insert({_id: {x: 3}, z: 3}));
- assert.writeOK(t.insert({_id: 1, z: 4}));
- assert.writeOK(t.insert({_id: 2, z: 5}));
- assert.writeOK(t.insert({_id: 3, z: 6}));
-
- assert.eq(2, t.findOne({_id: {x: 2}}).z);
- assert.eq(2, t.find({_id: {$gte: 2}}).count());
- assert.eq(2, t.find({_id: {$gte: 2}}).itcount());
-
- t.update({_id: {x: 2}}, {$set: {z: 7}});
- assert.eq(7, t.findOne({_id: {x: 2}}).z);
-
- t.update({_id: {$gte: 2}}, {$set: {z: 8}}, false, true);
- assert.eq(4, t.findOne({_id: 1}).z);
- assert.eq(8, t.findOne({_id: 2}).z);
- assert.eq(8, t.findOne({_id: 3}).z);
-
- // explain output should show that the ID hack was applied.
- const query = {_id: {x: 2}};
- let explain = t.find(query).explain(true);
- assert.eq(1, explain.executionStats.nReturned);
- assert.eq(1, explain.executionStats.totalKeysExamined);
- assert(isIdhack(db, explain.queryPlanner.winningPlan));
-
- // ID hack cannot be used with hint().
- t.ensureIndex({_id: 1, a: 1});
- explain = t.find(query).hint({_id: 1, a: 1}).explain();
- assert(!isIdhack(db, explain.queryPlanner.winningPlan));
-
- // ID hack cannot be used with skip().
- explain = t.find(query).skip(1).explain();
- assert(!isIdhack(db, explain.queryPlanner.winningPlan));
-
- // ID hack cannot be used with a regex predicate.
- assert.writeOK(t.insert({_id: "abc"}));
- explain = t.find({_id: /abc/}).explain();
- assert.eq({_id: "abc"}, t.findOne({_id: /abc/}));
- assert(!isIdhack(db, explain.queryPlanner.winningPlan));
-
- // Covered query returning _id field only can be handled by ID hack.
- explain = t.find(query, {_id: 1}).explain();
- assert(isIdhack(db, explain.queryPlanner.winningPlan));
- // Check doc from covered ID hack query.
- assert.eq({_id: {x: 2}}, t.findOne(query, {_id: 1}));
-
- //
- // Non-covered projection for idhack.
- //
-
- t.drop();
- assert.writeOK(t.insert({_id: 0, a: 0, b: [{c: 1}, {c: 2}]}));
- assert.writeOK(t.insert({_id: 1, a: 1, b: [{c: 3}, {c: 4}]}));
-
- // Simple inclusion.
- assert.eq({_id: 1, a: 1}, t.find({_id: 1}, {a: 1}).next());
- assert.eq({a: 1}, t.find({_id: 1}, {_id: 0, a: 1}).next());
- assert.eq({_id: 0, a: 0}, t.find({_id: 0}, {_id: 1, a: 1}).next());
-
- // Non-simple: exclusion.
- assert.eq({_id: 1, a: 1}, t.find({_id: 1}, {b: 0}).next());
- assert.eq({_id: 0}, t.find({_id: 0}, {a: 0, b: 0}).next());
-
- // Non-simple: dotted fields.
- assert.eq({b: [{c: 1}, {c: 2}]}, t.find({_id: 0}, {_id: 0, "b.c": 1}).next());
- assert.eq({_id: 1}, t.find({_id: 1}, {"foo.bar": 1}).next());
-
- // Non-simple: elemMatch projection.
- assert.eq({_id: 1, b: [{c: 4}]}, t.find({_id: 1}, {b: {$elemMatch: {c: 4}}}).next());
-
- // Non-simple: .returnKey().
- assert.eq({_id: 1}, t.find({_id: 1}).returnKey().next());
-
- // Non-simple: .returnKey() overrides other projections.
- assert.eq({_id: 1}, t.find({_id: 1}, {a: 1}).returnKey().next());
-
- // Test that equality queries on _id with min() or max() require hint().
- let err = assert.throws(() => t.find({_id: 2}).min({_id: 1}).itcount());
- assert.commandFailedWithCode(err, 51173);
- err = assert.throws(() => t.find({_id: 2}).max({_id: 3}).itcount());
- assert.commandFailedWithCode(err, 51173);
-
- // Test that equality queries on _id respect min() and max().
- assert.eq({_id: 1}, t.find({_id: 1}).hint({_id: 1}).min({_id: 0}).returnKey().next());
- assert.eq({_id: 1},
- t.find({_id: 1}).hint({_id: 1}).min({_id: 0}).max({_id: 2}).returnKey().next());
- assert.eq(0, t.find({_id: 1}).hint({_id: 1}).max({_id: 0}).itcount());
- assert.eq(0, t.find({_id: 1}).hint({_id: 1}).min({_id: 2}).itcount());
-
- explain = t.find({_id: 2}).hint({_id: 1}).min({_id: 1}).max({_id: 3}).explain();
- assert(!isIdhack(db, explain.queryPlanner.winningPlan));
+"use strict";
+
+const t = db.idhack;
+t.drop();
+
+// Include helpers for analyzing explain output.
+load("jstests/libs/analyze_plan.js");
+
+assert.writeOK(t.insert({_id: {x: 1}, z: 1}));
+assert.writeOK(t.insert({_id: {x: 2}, z: 2}));
+assert.writeOK(t.insert({_id: {x: 3}, z: 3}));
+assert.writeOK(t.insert({_id: 1, z: 4}));
+assert.writeOK(t.insert({_id: 2, z: 5}));
+assert.writeOK(t.insert({_id: 3, z: 6}));
+
+assert.eq(2, t.findOne({_id: {x: 2}}).z);
+assert.eq(2, t.find({_id: {$gte: 2}}).count());
+assert.eq(2, t.find({_id: {$gte: 2}}).itcount());
+
+t.update({_id: {x: 2}}, {$set: {z: 7}});
+assert.eq(7, t.findOne({_id: {x: 2}}).z);
+
+t.update({_id: {$gte: 2}}, {$set: {z: 8}}, false, true);
+assert.eq(4, t.findOne({_id: 1}).z);
+assert.eq(8, t.findOne({_id: 2}).z);
+assert.eq(8, t.findOne({_id: 3}).z);
+
+// explain output should show that the ID hack was applied.
+const query = {
+ _id: {x: 2}
+};
+let explain = t.find(query).explain(true);
+assert.eq(1, explain.executionStats.nReturned);
+assert.eq(1, explain.executionStats.totalKeysExamined);
+assert(isIdhack(db, explain.queryPlanner.winningPlan));
+
+// ID hack cannot be used with hint().
+t.ensureIndex({_id: 1, a: 1});
+explain = t.find(query).hint({_id: 1, a: 1}).explain();
+assert(!isIdhack(db, explain.queryPlanner.winningPlan));
+
+// ID hack cannot be used with skip().
+explain = t.find(query).skip(1).explain();
+assert(!isIdhack(db, explain.queryPlanner.winningPlan));
+
+// ID hack cannot be used with a regex predicate.
+assert.writeOK(t.insert({_id: "abc"}));
+explain = t.find({_id: /abc/}).explain();
+assert.eq({_id: "abc"}, t.findOne({_id: /abc/}));
+assert(!isIdhack(db, explain.queryPlanner.winningPlan));
+
+// Covered query returning _id field only can be handled by ID hack.
+explain = t.find(query, {_id: 1}).explain();
+assert(isIdhack(db, explain.queryPlanner.winningPlan));
+// Check doc from covered ID hack query.
+assert.eq({_id: {x: 2}}, t.findOne(query, {_id: 1}));
+
+//
+// Non-covered projection for idhack.
+//
+
+t.drop();
+assert.writeOK(t.insert({_id: 0, a: 0, b: [{c: 1}, {c: 2}]}));
+assert.writeOK(t.insert({_id: 1, a: 1, b: [{c: 3}, {c: 4}]}));
+
+// Simple inclusion.
+assert.eq({_id: 1, a: 1}, t.find({_id: 1}, {a: 1}).next());
+assert.eq({a: 1}, t.find({_id: 1}, {_id: 0, a: 1}).next());
+assert.eq({_id: 0, a: 0}, t.find({_id: 0}, {_id: 1, a: 1}).next());
+
+// Non-simple: exclusion.
+assert.eq({_id: 1, a: 1}, t.find({_id: 1}, {b: 0}).next());
+assert.eq({_id: 0}, t.find({_id: 0}, {a: 0, b: 0}).next());
+
+// Non-simple: dotted fields.
+assert.eq({b: [{c: 1}, {c: 2}]}, t.find({_id: 0}, {_id: 0, "b.c": 1}).next());
+assert.eq({_id: 1}, t.find({_id: 1}, {"foo.bar": 1}).next());
+
+// Non-simple: elemMatch projection.
+assert.eq({_id: 1, b: [{c: 4}]}, t.find({_id: 1}, {b: {$elemMatch: {c: 4}}}).next());
+
+// Non-simple: .returnKey().
+assert.eq({_id: 1}, t.find({_id: 1}).returnKey().next());
+
+// Non-simple: .returnKey() overrides other projections.
+assert.eq({_id: 1}, t.find({_id: 1}, {a: 1}).returnKey().next());
+
+// Test that equality queries on _id with min() or max() require hint().
+let err = assert.throws(() => t.find({_id: 2}).min({_id: 1}).itcount());
+assert.commandFailedWithCode(err, 51173);
+err = assert.throws(() => t.find({_id: 2}).max({_id: 3}).itcount());
+assert.commandFailedWithCode(err, 51173);
+
+// Test that equality queries on _id respect min() and max().
+assert.eq({_id: 1}, t.find({_id: 1}).hint({_id: 1}).min({_id: 0}).returnKey().next());
+assert.eq({_id: 1}, t.find({_id: 1}).hint({_id: 1}).min({_id: 0}).max({_id: 2}).returnKey().next());
+assert.eq(0, t.find({_id: 1}).hint({_id: 1}).max({_id: 0}).itcount());
+assert.eq(0, t.find({_id: 1}).hint({_id: 1}).min({_id: 2}).itcount());
+
+explain = t.find({_id: 2}).hint({_id: 1}).min({_id: 1}).max({_id: 3}).explain();
+assert(!isIdhack(db, explain.queryPlanner.winningPlan));
})();