1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
'use strict';
/*
* yield_and_hashed.js (extends yield_rooted_or.js)
*
* Intersperse queries which use the AND_HASH stage with updates and deletes of documents they may
* match.
*/
load('jstests/concurrency/fsm_libs/extend_workload.js'); // for extendWorkload
load('jstests/concurrency/fsm_workloads/yield_rooted_or.js'); // for $config
var $config = extendWorkload(
$config,
function($config, $super) {
/*
* Issue a query that will use the AND_HASH stage. This is a little tricky, so use
* stagedebug to force it to happen. Unfortunately this means it can't be batched.
*/
$config.states.query = function andHash(db, collName) {
var nMatches = 100;
assertAlways.lte(nMatches, this.nDocs);
// Construct the query plan: two ixscans under an andHashed.
// Scan c <= nMatches
var ixscan1 = {
ixscan: {
args: {
name: 'stages_and_hashed',
keyPattern: {c: 1},
startKey: {'': nMatches},
endKey: {},
endKeyInclusive: true,
direction: -1
}
}
};
// Scan d >= this.nDocs - nMatches
var ixscan2 = {
ixscan: {
args: {
name: 'stages_and_hashed',
keyPattern: {d: 1},
startKey: {'': this.nDocs - nMatches},
endKey: {},
endKeyInclusive: true,
direction: 1
}
}
};
var andix1ix2 = {
andHash: {args: {nodes: [ixscan1, ixscan2]}}
};
// On non-MMAP storage engines, index intersection plans will always re-filter
// the docs to make sure we don't get any spurious matches.
var fetch = {
fetch: {
filter: {c: {$lte: nMatches}, d: {$gte: (this.nDocs - nMatches)}},
args: {node: andix1ix2}
}
};
var res = db.runCommand({stageDebug: {plan: fetch, collection: collName}});
assertAlways.commandWorked(res);
for (var i = 0; i < res.results.length; i++) {
var result = res.results[i];
assertAlways.lte(result.c, nMatches);
assertAlways.gte(result.d, this.nDocs - nMatches);
}
};
return $config;
});
|