spice-couchbase 2.0.64 → 2.0.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.auto-optimize.test.js +122 -204
- package/build/index.count-query.test.js +27 -63
- package/build/index.index-management.test.js +283 -0
- package/build/index.js +486 -418
- package/build/index.multi_get.test.js +9 -56
- package/build/index.query-consistency.test.js +28 -72
- package/build/utility.js +182 -152
- package/build/utility.test.js +79 -59
- package/package.json +1 -1
- package/src/index.index-management.test.js +232 -0
- package/src/index.js +270 -8
- package/src/utility.js +78 -0
|
@@ -1,39 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
function
|
|
4
|
-
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
function
|
|
8
|
-
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
function
|
|
12
|
-
|
|
3
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
4
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
5
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
6
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
7
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
8
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
9
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
10
|
+
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
11
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
12
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
13
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
14
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
15
|
+
function _toPrimitive(t, e) { if ("object" != typeof t || !t) return t; var r; if ("undefined" != typeof Symbol && void 0 !== (r = t[Symbol.toPrimitive])) { var i = r.call(t, e || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === e ? String : Number)(t); }
|
|
13
16
|
var assert = require("node:assert/strict");
|
|
14
|
-
|
|
15
17
|
var fs = require("node:fs");
|
|
16
|
-
|
|
17
18
|
var path = require("node:path");
|
|
18
|
-
|
|
19
19
|
var vm = require("node:vm");
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
var {
|
|
26
|
-
buildCoveringIndex,
|
|
27
|
-
buildCoveringIndexDefinition
|
|
28
|
-
} = require("./utility");
|
|
29
|
-
|
|
20
|
+
var _require = require("node:test"),
|
|
21
|
+
test = _require.test;
|
|
22
|
+
var _require2 = require("./utility"),
|
|
23
|
+
buildCoveringIndex = _require2.buildCoveringIndex,
|
|
24
|
+
buildCoveringIndexDefinition = _require2.buildCoveringIndexDefinition;
|
|
30
25
|
var keyspace = {
|
|
31
26
|
bucket: "saturn",
|
|
32
27
|
scope: "test",
|
|
33
28
|
collection: "users"
|
|
34
29
|
};
|
|
35
30
|
var lookupQuery = "SELECT name, email FROM users WHERE status = 'active'";
|
|
36
|
-
|
|
37
31
|
function existingIndex(index_key) {
|
|
38
32
|
var overrides = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
39
33
|
return _objectSpread({
|
|
@@ -43,25 +37,21 @@ function existingIndex(index_key) {
|
|
|
43
37
|
index_key
|
|
44
38
|
}, overrides);
|
|
45
39
|
}
|
|
46
|
-
|
|
47
40
|
function executionScope() {
|
|
48
41
|
var indexes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
49
|
-
var {
|
|
50
|
-
inventoryError,
|
|
51
|
-
inventoryResponse,
|
|
52
|
-
plan
|
|
53
|
-
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
42
|
+
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
43
|
+
inventoryError = _ref.inventoryError,
|
|
44
|
+
inventoryResponse = _ref.inventoryResponse,
|
|
45
|
+
plan = _ref.plan;
|
|
54
46
|
var calls = [];
|
|
55
47
|
return {
|
|
56
48
|
calls,
|
|
57
|
-
|
|
58
49
|
query(statement, options) {
|
|
59
50
|
return _asyncToGenerator(function* () {
|
|
60
51
|
calls.push({
|
|
61
52
|
statement,
|
|
62
53
|
options
|
|
63
54
|
});
|
|
64
|
-
|
|
65
55
|
if (statement.startsWith("EXPLAIN ")) {
|
|
66
56
|
return {
|
|
67
57
|
rows: [plan || {
|
|
@@ -69,34 +59,28 @@ function executionScope() {
|
|
|
69
59
|
}]
|
|
70
60
|
};
|
|
71
61
|
}
|
|
72
|
-
|
|
73
62
|
if (statement.includes("FROM system:indexes")) {
|
|
74
63
|
if (inventoryError) throw inventoryError;
|
|
75
64
|
return inventoryResponse === undefined ? {
|
|
76
65
|
rows: indexes
|
|
77
66
|
} : inventoryResponse;
|
|
78
67
|
}
|
|
79
|
-
|
|
80
68
|
return {
|
|
81
69
|
rows: []
|
|
82
70
|
};
|
|
83
71
|
})();
|
|
84
72
|
}
|
|
85
|
-
|
|
86
73
|
};
|
|
87
74
|
}
|
|
88
|
-
|
|
89
75
|
function createStatements(scope) {
|
|
90
|
-
return scope.calls.filter(
|
|
91
|
-
var
|
|
92
|
-
statement
|
|
93
|
-
} = _ref;
|
|
76
|
+
return scope.calls.filter(_ref2 => {
|
|
77
|
+
var statement = _ref2.statement;
|
|
94
78
|
return statement.startsWith("CREATE INDEX ");
|
|
95
79
|
});
|
|
96
|
-
}
|
|
97
|
-
// Each load is a fresh module: its own seen-set, cooldown and policy.
|
|
98
|
-
|
|
80
|
+
}
|
|
99
81
|
|
|
82
|
+
// Isolate optimizer state and time without connecting to Couchbase or sleeping.
|
|
83
|
+
// Each load is a fresh module: its own seen-set, cooldown and policy.
|
|
100
84
|
function loadDriver(durationMs) {
|
|
101
85
|
var env = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
102
86
|
var tick = BigInt(0);
|
|
@@ -120,7 +104,6 @@ function loadDriver(durationMs) {
|
|
|
120
104
|
});
|
|
121
105
|
return module.exports;
|
|
122
106
|
}
|
|
123
|
-
|
|
124
107
|
function instanceOf(Database) {
|
|
125
108
|
var db = Object.create(Database.prototype);
|
|
126
109
|
db.bucket = "saturn";
|
|
@@ -133,59 +116,49 @@ function instanceOf(Database) {
|
|
|
133
116
|
rows: []
|
|
134
117
|
};
|
|
135
118
|
});
|
|
136
|
-
|
|
137
119
|
function query() {
|
|
138
120
|
return _query.apply(this, arguments);
|
|
139
121
|
}
|
|
140
|
-
|
|
141
122
|
return query;
|
|
142
123
|
}()
|
|
143
124
|
};
|
|
144
125
|
return db;
|
|
145
|
-
}
|
|
146
|
-
|
|
126
|
+
}
|
|
147
127
|
|
|
128
|
+
// Opted in wholesale: per-resource resolution has its own tests further down.
|
|
148
129
|
function createDatabase(durationMs) {
|
|
149
130
|
var env = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
150
131
|
var db = instanceOf(loadDriver(durationMs, env));
|
|
151
132
|
db.auto_optimize = true;
|
|
152
133
|
return db;
|
|
153
134
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
/*#__PURE__*/
|
|
157
|
-
_asyncToGenerator(function* () {
|
|
158
|
-
for (var duration of [1001, 2999, 3000, 3001]) {
|
|
135
|
+
test("auto-optimization only starts above the default 3-second threshold", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
136
|
+
var _loop = function* _loop() {
|
|
159
137
|
var db = createDatabase(duration);
|
|
160
138
|
var optimizations = 0;
|
|
161
|
-
db.optimize =
|
|
162
|
-
/*#__PURE__*/
|
|
163
|
-
_asyncToGenerator(function* () {
|
|
139
|
+
db.optimize = /*#__PURE__*/_asyncToGenerator(function* () {
|
|
164
140
|
optimizations += 1;
|
|
165
141
|
});
|
|
166
142
|
yield db.query("SELECT name FROM users WHERE status = 'active'");
|
|
167
143
|
assert.equal(optimizations, duration > 3000 ? 1 : 0, "".concat(duration, "ms"));
|
|
144
|
+
};
|
|
145
|
+
for (var duration of [1001, 2999, 3000, 3001]) {
|
|
146
|
+
yield* _loop();
|
|
168
147
|
}
|
|
169
148
|
}));
|
|
170
|
-
test("the explicit slow-query threshold override remains supported",
|
|
171
|
-
/*#__PURE__*/
|
|
172
|
-
_asyncToGenerator(function* () {
|
|
149
|
+
test("the explicit slow-query threshold override remains supported", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
173
150
|
var db = createDatabase(5001, {
|
|
174
151
|
SPICE_COUCHBASE_SLOW_QUERY_MS: "5000"
|
|
175
152
|
});
|
|
176
153
|
var optimizations = 0;
|
|
177
|
-
db.optimize =
|
|
178
|
-
/*#__PURE__*/
|
|
179
|
-
_asyncToGenerator(function* () {
|
|
154
|
+
db.optimize = /*#__PURE__*/_asyncToGenerator(function* () {
|
|
180
155
|
optimizations += 1;
|
|
181
156
|
});
|
|
182
157
|
yield db.query("SELECT name FROM users WHERE status = 'active'");
|
|
183
158
|
assert.equal(optimizations, 1);
|
|
184
159
|
}));
|
|
185
|
-
test("Fetch plans for full-document projections never create indexes",
|
|
186
|
-
|
|
187
|
-
_asyncToGenerator(function* () {
|
|
188
|
-
var _loop = function* _loop(projection) {
|
|
160
|
+
test("Fetch plans for full-document projections never create indexes", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
161
|
+
var _loop2 = function* _loop2() {
|
|
189
162
|
var db = createDatabase(0);
|
|
190
163
|
var statements = [];
|
|
191
164
|
var query = "SELECT ".concat(projection, " FROM users WHERE status = 'active' ORDER BY created_at DESC");
|
|
@@ -199,24 +172,19 @@ _asyncToGenerator(function* () {
|
|
|
199
172
|
}]
|
|
200
173
|
};
|
|
201
174
|
});
|
|
202
|
-
|
|
203
175
|
function query(_x) {
|
|
204
176
|
return _query2.apply(this, arguments);
|
|
205
177
|
}
|
|
206
|
-
|
|
207
178
|
return query;
|
|
208
179
|
}()
|
|
209
180
|
});
|
|
210
181
|
assert.deepEqual(statements, ["EXPLAIN ".concat(query)]);
|
|
211
182
|
};
|
|
212
|
-
|
|
213
183
|
for (var projection of ["*", "users.*", "`users`.*", "(`users`).*, META(`users`).id AS id"]) {
|
|
214
|
-
yield*
|
|
184
|
+
yield* _loop2();
|
|
215
185
|
}
|
|
216
186
|
}));
|
|
217
|
-
test("Fetch plans for explicit fields still create a covering index",
|
|
218
|
-
/*#__PURE__*/
|
|
219
|
-
_asyncToGenerator(function* () {
|
|
187
|
+
test("Fetch plans for explicit fields still create a covering index", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
220
188
|
var db = createDatabase(0);
|
|
221
189
|
var scope = executionScope();
|
|
222
190
|
yield db.optimize("SELECT name FROM users WHERE status = 'active'", scope);
|
|
@@ -252,11 +220,8 @@ test("case-distinct document fields are not collapsed", () => {
|
|
|
252
220
|
assert.match(statement, /`status`/);
|
|
253
221
|
assert.doesNotMatch(statement, /`name` DESC/);
|
|
254
222
|
});
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
test("an existing ".concat(state, " index with reordered projection keys prevents creation"),
|
|
258
|
-
/*#__PURE__*/
|
|
259
|
-
_asyncToGenerator(function* () {
|
|
223
|
+
var _loop3 = function _loop3(state) {
|
|
224
|
+
test("an existing ".concat(state, " index with reordered projection keys prevents creation"), /*#__PURE__*/_asyncToGenerator(function* () {
|
|
260
225
|
var scope = executionScope([existingIndex(["`deleted` INCLUDE MISSING", "`status`", "`name`", "`email`"], {
|
|
261
226
|
state
|
|
262
227
|
})]);
|
|
@@ -265,21 +230,15 @@ var _loop2 = function _loop2(state) {
|
|
|
265
230
|
assert.equal(createStatements(scope).length, 0);
|
|
266
231
|
}));
|
|
267
232
|
};
|
|
268
|
-
|
|
269
233
|
for (var state of ["online", "deferred", "pending", "building", "offline"]) {
|
|
270
|
-
|
|
234
|
+
_loop3(state);
|
|
271
235
|
}
|
|
272
|
-
|
|
273
|
-
test("a wider existing index covers a projection subset without another index",
|
|
274
|
-
/*#__PURE__*/
|
|
275
|
-
_asyncToGenerator(function* () {
|
|
236
|
+
test("a wider existing index covers a projection subset without another index", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
276
237
|
var scope = executionScope([existingIndex(["`deleted` INCLUDE MISSING", "`status`", "`name`", "`phone`", "`email` DESC"])]);
|
|
277
238
|
yield createDatabase(0).optimize(lookupQuery, scope);
|
|
278
239
|
assert.equal(createStatements(scope).length, 0);
|
|
279
240
|
}));
|
|
280
|
-
test("catalog key formatting, explicit ASC and attribute order are normalized",
|
|
281
|
-
/*#__PURE__*/
|
|
282
|
-
_asyncToGenerator(function* () {
|
|
241
|
+
test("catalog key formatting, explicit ASC and attribute order are normalized", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
283
242
|
for (var leadingKey of ["((`deleted`)) ASC INCLUDE MISSING", "deleted INCLUDE MISSING ASC"]) {
|
|
284
243
|
var scope = executionScope([existingIndex([leadingKey, "(status) ASC", "`name`", "email ASC"])]);
|
|
285
244
|
yield createDatabase(0).optimize(lookupQuery, scope);
|
|
@@ -291,33 +250,28 @@ var incompatibleIndexes = [["missing a projection field", existingIndex(["`delet
|
|
|
291
250
|
})], ["primary index", existingIndex([], {
|
|
292
251
|
is_primary: true
|
|
293
252
|
})]];
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
for (var
|
|
306
|
-
|
|
253
|
+
var _loop4 = function _loop4() {
|
|
254
|
+
_ref10 = _slicedToArray(_ref11, 2);
|
|
255
|
+
var reason = _ref10[0];
|
|
256
|
+
var index = _ref10[1];
|
|
257
|
+
test("does not mistake ".concat(reason, " for a compatible covering index"), /*#__PURE__*/_asyncToGenerator(function* () {
|
|
258
|
+
var scope = executionScope([index]);
|
|
259
|
+
yield createDatabase(0).optimize(lookupQuery, scope);
|
|
260
|
+
assert.equal(createStatements(scope).length, 1);
|
|
261
|
+
}));
|
|
262
|
+
},
|
|
263
|
+
_ref10;
|
|
264
|
+
for (var _ref11 of incompatibleIndexes) {
|
|
265
|
+
_loop4();
|
|
307
266
|
}
|
|
308
|
-
|
|
309
|
-
test("existing opposite sort direction does not satisfy the requested sort",
|
|
310
|
-
/*#__PURE__*/
|
|
311
|
-
_asyncToGenerator(function* () {
|
|
267
|
+
test("existing opposite sort direction does not satisfy the requested sort", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
312
268
|
var query = "".concat(lookupQuery, " ORDER BY created_at DESC");
|
|
313
269
|
var scope = executionScope([existingIndex(["`deleted` INCLUDE MISSING", "`status`", "`created_at`", "`name`", "`email`"])]);
|
|
314
270
|
yield createDatabase(0).optimize(query, scope);
|
|
315
271
|
assert.equal(createStatements(scope).length, 1);
|
|
316
272
|
assert.match(createStatements(scope)[0].statement, /`created_at` DESC/);
|
|
317
273
|
}));
|
|
318
|
-
test("same generated name is never recreated even if its keys are unavailable",
|
|
319
|
-
/*#__PURE__*/
|
|
320
|
-
_asyncToGenerator(function* () {
|
|
274
|
+
test("same generated name is never recreated even if its keys are unavailable", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
321
275
|
var candidate = buildCoveringIndexDefinition(lookupQuery, keyspace);
|
|
322
276
|
var scope = executionScope([{
|
|
323
277
|
name: candidate.name,
|
|
@@ -326,24 +280,19 @@ _asyncToGenerator(function* () {
|
|
|
326
280
|
yield createDatabase(0).optimize(lookupQuery, scope);
|
|
327
281
|
assert.equal(createStatements(scope).length, 0);
|
|
328
282
|
}));
|
|
329
|
-
test("catalog failure or incomplete results prevent creation and trigger cooldown",
|
|
330
|
-
|
|
331
|
-
_asyncToGenerator(function* () {
|
|
332
|
-
var _loop4 = function* _loop4(options) {
|
|
283
|
+
test("catalog failure or incomplete results prevent creation and trigger cooldown", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
284
|
+
var _loop5 = function* _loop5() {
|
|
333
285
|
var db = createDatabase(3001);
|
|
334
286
|
var scope = executionScope([], options);
|
|
335
287
|
yield db.optimize(lookupQuery, scope);
|
|
336
288
|
assert.equal(createStatements(scope).length, 0);
|
|
337
289
|
var retries = 0;
|
|
338
|
-
db.optimize =
|
|
339
|
-
/*#__PURE__*/
|
|
340
|
-
_asyncToGenerator(function* () {
|
|
290
|
+
db.optimize = /*#__PURE__*/_asyncToGenerator(function* () {
|
|
341
291
|
retries++;
|
|
342
292
|
});
|
|
343
293
|
yield db.query("SELECT email FROM users WHERE status = 'pending'");
|
|
344
294
|
assert.equal(retries, 0);
|
|
345
295
|
};
|
|
346
|
-
|
|
347
296
|
for (var options of [{
|
|
348
297
|
inventoryError: new Error("query service unavailable")
|
|
349
298
|
}, {
|
|
@@ -358,12 +307,10 @@ _asyncToGenerator(function* () {
|
|
|
358
307
|
}
|
|
359
308
|
}
|
|
360
309
|
}]) {
|
|
361
|
-
yield*
|
|
310
|
+
yield* _loop5();
|
|
362
311
|
}
|
|
363
312
|
}));
|
|
364
|
-
test("already-covered plans need neither an inventory lookup nor creation",
|
|
365
|
-
/*#__PURE__*/
|
|
366
|
-
_asyncToGenerator(function* () {
|
|
313
|
+
test("already-covered plans need neither an inventory lookup nor creation", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
367
314
|
var scope = executionScope([], {
|
|
368
315
|
plan: {
|
|
369
316
|
"#operator": "IndexScan3"
|
|
@@ -372,9 +319,7 @@ _asyncToGenerator(function* () {
|
|
|
372
319
|
yield createDatabase(0).optimize(lookupQuery, scope);
|
|
373
320
|
assert.equal(scope.calls.length, 1);
|
|
374
321
|
}));
|
|
375
|
-
test("a default collection uses default names in its inventory lookup",
|
|
376
|
-
/*#__PURE__*/
|
|
377
|
-
_asyncToGenerator(function* () {
|
|
322
|
+
test("a default collection uses default names in its inventory lookup", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
378
323
|
var db = createDatabase(0);
|
|
379
324
|
db.scope_name = undefined;
|
|
380
325
|
db.collection_name = undefined;
|
|
@@ -386,134 +331,112 @@ _asyncToGenerator(function* () {
|
|
|
386
331
|
collection: "_default"
|
|
387
332
|
}));
|
|
388
333
|
assert.match(createStatements(scope)[0].statement, /`saturn`\.`_default`\.`_default`/);
|
|
389
|
-
}));
|
|
334
|
+
}));
|
|
335
|
+
|
|
336
|
+
// ---- Per-resource opt-in for auto cover indexing ----
|
|
337
|
+
|
|
390
338
|
// Nothing decided at instance level: resolution falls through to the call,
|
|
391
339
|
// the application policy and the static lists.
|
|
392
|
-
|
|
393
340
|
function createUnconfiguredDatabase() {
|
|
394
341
|
var env = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
395
342
|
return instanceOf(loadDriver(3001, env));
|
|
396
343
|
}
|
|
397
|
-
|
|
398
344
|
function optimizationsFor(_x2, _x3) {
|
|
399
345
|
return _optimizationsFor.apply(this, arguments);
|
|
400
346
|
}
|
|
401
|
-
|
|
402
347
|
function _optimizationsFor() {
|
|
403
348
|
_optimizationsFor = _asyncToGenerator(function* (db, statement) {
|
|
404
349
|
var optimizations = 0;
|
|
405
|
-
db.optimize =
|
|
406
|
-
/*#__PURE__*/
|
|
407
|
-
_asyncToGenerator(function* () {
|
|
350
|
+
db.optimize = /*#__PURE__*/_asyncToGenerator(function* () {
|
|
408
351
|
optimizations += 1;
|
|
409
352
|
});
|
|
410
|
-
|
|
411
353
|
for (var _len = arguments.length, queryArgs = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
|
|
412
354
|
queryArgs[_key - 2] = arguments[_key];
|
|
413
355
|
}
|
|
414
|
-
|
|
415
356
|
yield db.query(statement, ...queryArgs);
|
|
416
357
|
return optimizations;
|
|
417
358
|
});
|
|
418
359
|
return _optimizationsFor.apply(this, arguments);
|
|
419
360
|
}
|
|
420
|
-
|
|
421
361
|
var slowLookup = "SELECT name FROM users WHERE status = 'active'";
|
|
422
362
|
var EVERY_RESOURCE = {
|
|
423
363
|
SPICE_COUCHBASE_OPTIMIZE_RESOURCES: "*"
|
|
424
364
|
};
|
|
425
|
-
test("no resource is auto-indexed unless something opts it in",
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
assert.equal((yield optimizationsFor(createUnconfiguredDatabase(), slowLookup)), 0);
|
|
429
|
-
assert.equal((yield optimizationsFor(createUnconfiguredDatabase({
|
|
365
|
+
test("no resource is auto-indexed unless something opts it in", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
366
|
+
assert.equal(yield optimizationsFor(createUnconfiguredDatabase(), slowLookup), 0);
|
|
367
|
+
assert.equal(yield optimizationsFor(createUnconfiguredDatabase({
|
|
430
368
|
SPICE_COUCHBASE_OPTIMIZE_RESOURCES: ""
|
|
431
|
-
}), slowLookup)
|
|
369
|
+
}), slowLookup), 0);
|
|
432
370
|
}));
|
|
433
|
-
test("SPICE_COUCHBASE_OPTIMIZE_RESOURCES enables the instance's collection, case-insensitively",
|
|
434
|
-
/*#__PURE__*/
|
|
435
|
-
_asyncToGenerator(function* () {
|
|
371
|
+
test("SPICE_COUCHBASE_OPTIMIZE_RESOURCES enables the instance's collection, case-insensitively", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
436
372
|
var env = {
|
|
437
373
|
SPICE_COUCHBASE_OPTIMIZE_RESOURCES: " Users ,audit_log,, `sessions` "
|
|
438
374
|
};
|
|
439
|
-
assert.equal(
|
|
375
|
+
assert.equal(yield optimizationsFor(createUnconfiguredDatabase(env), slowLookup), 1);
|
|
440
376
|
var sessions = createUnconfiguredDatabase(env);
|
|
441
377
|
sessions.collection_name = "sessions";
|
|
442
|
-
assert.equal(
|
|
378
|
+
assert.equal(yield optimizationsFor(sessions, "SELECT id FROM sessions"), 1);
|
|
443
379
|
var orders = createUnconfiguredDatabase(env);
|
|
444
380
|
orders.collection_name = "orders";
|
|
445
|
-
assert.equal(
|
|
381
|
+
assert.equal(yield optimizationsFor(orders, "SELECT total FROM orders WHERE status = 'paid'"), 0);
|
|
446
382
|
}));
|
|
447
|
-
test("a wildcard restores auto indexing for every resource",
|
|
448
|
-
/*#__PURE__*/
|
|
449
|
-
_asyncToGenerator(function* () {
|
|
383
|
+
test("a wildcard restores auto indexing for every resource", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
450
384
|
var db = createUnconfiguredDatabase(EVERY_RESOURCE);
|
|
451
385
|
db.collection_name = "anything";
|
|
452
|
-
assert.equal(
|
|
386
|
+
assert.equal(yield optimizationsFor(db, "SELECT a FROM anything WHERE b = 1"), 1);
|
|
453
387
|
}));
|
|
454
|
-
test("legacy bucket mode resolves the resource from the type literal the driver adds",
|
|
455
|
-
/*#__PURE__*/
|
|
456
|
-
_asyncToGenerator(function* () {
|
|
388
|
+
test("legacy bucket mode resolves the resource from the type literal the driver adds", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
457
389
|
var env = {
|
|
458
390
|
SPICE_COUCHBASE_OPTIMIZE_RESOURCES: "audit_log"
|
|
459
391
|
};
|
|
460
|
-
|
|
461
|
-
|
|
392
|
+
for (var _ref24 of [["audit_log", 1], ["users", 0]]) {
|
|
393
|
+
var _ref23 = _slicedToArray(_ref24, 2);
|
|
394
|
+
var type = _ref23[0];
|
|
395
|
+
var expected = _ref23[1];
|
|
462
396
|
var db = createUnconfiguredDatabase(env);
|
|
463
397
|
db.collection_name = "_default";
|
|
464
398
|
db.scope_name = "_default";
|
|
465
|
-
assert.equal(
|
|
399
|
+
assert.equal(yield optimizationsFor(db, "SELECT actor FROM `saturn` WHERE type = '".concat(type, "' AND deleted = false")), expected, type);
|
|
466
400
|
}
|
|
467
401
|
}));
|
|
468
|
-
test("a fully qualified or aliased FROM keyspace matches on its last segment",
|
|
469
|
-
/*#__PURE__*/
|
|
470
|
-
_asyncToGenerator(function* () {
|
|
402
|
+
test("a fully qualified or aliased FROM keyspace matches on its last segment", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
471
403
|
var env = {
|
|
472
404
|
SPICE_COUCHBASE_OPTIMIZE_RESOURCES: "logs"
|
|
473
405
|
};
|
|
474
|
-
|
|
475
406
|
for (var statement of ["SELECT level FROM `default`:`saturn`.`app`.`logs` WHERE level = 'error'", "SELECT l.level FROM saturn.app.logs AS l WHERE l.level = 'error'", "SELECT u.name FROM users AS u JOIN `logs` AS l ON l.user_id = META(u).id"]) {
|
|
476
407
|
var db = createUnconfiguredDatabase(env);
|
|
477
408
|
db.collection_name = "_default";
|
|
478
|
-
assert.equal(
|
|
409
|
+
assert.equal(yield optimizationsFor(db, statement), 1, statement);
|
|
479
410
|
}
|
|
480
411
|
}));
|
|
481
|
-
test("connection or constructor lists work without the environment variable",
|
|
482
|
-
/*#__PURE__*/
|
|
483
|
-
_asyncToGenerator(function* () {
|
|
412
|
+
test("connection or constructor lists work without the environment variable", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
484
413
|
var db = createUnconfiguredDatabase();
|
|
485
414
|
db.enabled_resources = new Set(["users"]);
|
|
486
|
-
assert.equal(
|
|
415
|
+
assert.equal(yield optimizationsFor(db, slowLookup), 1);
|
|
487
416
|
}));
|
|
488
|
-
test("an explicit instance setting overrides every resource list",
|
|
489
|
-
/*#__PURE__*/
|
|
490
|
-
_asyncToGenerator(function* () {
|
|
417
|
+
test("an explicit instance setting overrides every resource list", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
491
418
|
var on = createUnconfiguredDatabase();
|
|
492
419
|
on.auto_optimize = true;
|
|
493
|
-
assert.equal(
|
|
420
|
+
assert.equal(yield optimizationsFor(on, slowLookup), 1);
|
|
494
421
|
var off = createUnconfiguredDatabase(EVERY_RESOURCE);
|
|
495
422
|
off.auto_optimize = false;
|
|
496
|
-
assert.equal(
|
|
423
|
+
assert.equal(yield optimizationsFor(off, slowLookup), 0);
|
|
497
424
|
}));
|
|
498
|
-
test("a single call can opt in or out through query options",
|
|
499
|
-
|
|
500
|
-
_asyncToGenerator(function* () {
|
|
501
|
-
assert.equal((yield optimizationsFor(createUnconfiguredDatabase(), slowLookup, {
|
|
425
|
+
test("a single call can opt in or out through query options", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
426
|
+
assert.equal(yield optimizationsFor(createUnconfiguredDatabase(), slowLookup, {
|
|
502
427
|
auto_optimize: true
|
|
503
|
-
})
|
|
504
|
-
assert.equal(
|
|
428
|
+
}), 1);
|
|
429
|
+
assert.equal(yield optimizationsFor(createUnconfiguredDatabase(EVERY_RESOURCE), slowLookup, {
|
|
505
430
|
auto_optimize: false
|
|
506
|
-
})
|
|
507
|
-
assert.equal(
|
|
431
|
+
}), 0);
|
|
432
|
+
assert.equal(yield optimizationsFor(createUnconfiguredDatabase(EVERY_RESOURCE), slowLookup, "cluster", {
|
|
508
433
|
optimize: false
|
|
509
|
-
})
|
|
510
|
-
|
|
511
|
-
assert.equal(
|
|
512
|
-
assert.equal(
|
|
434
|
+
}), 0);
|
|
435
|
+
// The scan-consistency shorthand is not an opt-in or opt-out.
|
|
436
|
+
assert.equal(yield optimizationsFor(createUnconfiguredDatabase(EVERY_RESOURCE), slowLookup, "cluster", true), 1);
|
|
437
|
+
assert.equal(yield optimizationsFor(createUnconfiguredDatabase(), slowLookup, "cluster", true), 0);
|
|
513
438
|
}));
|
|
514
|
-
test("an application policy decides per resource and sees the statement context",
|
|
515
|
-
/*#__PURE__*/
|
|
516
|
-
_asyncToGenerator(function* () {
|
|
439
|
+
test("an application policy decides per resource and sees the statement context", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
517
440
|
var Database = loadDriver(3001);
|
|
518
441
|
var seen = [];
|
|
519
442
|
Database.setAutoOptimizePolicy((resource, context) => {
|
|
@@ -523,8 +446,8 @@ _asyncToGenerator(function* () {
|
|
|
523
446
|
assert.equal(Database.getAutoOptimizePolicy().length, 2);
|
|
524
447
|
var users = instanceOf(Database);
|
|
525
448
|
users.connection_name = "default";
|
|
526
|
-
assert.equal(
|
|
527
|
-
|
|
449
|
+
assert.equal(yield optimizationsFor(users, slowLookup), 1);
|
|
450
|
+
// Objects cross the vm boundary, so compare by value rather than prototype.
|
|
528
451
|
assert.equal(JSON.stringify(seen[0]), JSON.stringify(["users", {
|
|
529
452
|
query: slowLookup,
|
|
530
453
|
connection: "default",
|
|
@@ -532,47 +455,42 @@ _asyncToGenerator(function* () {
|
|
|
532
455
|
}]));
|
|
533
456
|
var orders = instanceOf(Database);
|
|
534
457
|
orders.collection_name = "orders";
|
|
535
|
-
assert.equal(
|
|
458
|
+
assert.equal(yield optimizationsFor(orders, "SELECT total FROM orders WHERE status = 'paid'"), 0);
|
|
536
459
|
}));
|
|
537
|
-
test("a policy that returns undefined defers to the static lists",
|
|
538
|
-
|
|
539
|
-
_asyncToGenerator(function* () {
|
|
540
|
-
for (var [env, expected] of [[{
|
|
460
|
+
test("a policy that returns undefined defers to the static lists", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
461
|
+
for (var _ref33 of [[{
|
|
541
462
|
SPICE_COUCHBASE_OPTIMIZE_RESOURCES: "users"
|
|
542
463
|
}, 1], [{}, 0]]) {
|
|
464
|
+
var _ref32 = _slicedToArray(_ref33, 2);
|
|
465
|
+
var env = _ref32[0];
|
|
466
|
+
var expected = _ref32[1];
|
|
543
467
|
var Database = loadDriver(3001, env);
|
|
544
468
|
Database.setAutoOptimizePolicy(() => undefined);
|
|
545
|
-
assert.equal(
|
|
469
|
+
assert.equal(yield optimizationsFor(instanceOf(Database), slowLookup), expected);
|
|
546
470
|
}
|
|
547
471
|
}));
|
|
548
|
-
test("an explicit policy refusal wins over the wildcard, and a throwing policy counts as a refusal",
|
|
549
|
-
/*#__PURE__*/
|
|
550
|
-
_asyncToGenerator(function* () {
|
|
472
|
+
test("an explicit policy refusal wins over the wildcard, and a throwing policy counts as a refusal", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
551
473
|
for (var policy of [() => false, () => {
|
|
552
474
|
throw new Error("settings unavailable");
|
|
553
475
|
}]) {
|
|
554
476
|
var Database = loadDriver(3001, EVERY_RESOURCE);
|
|
555
477
|
Database.setAutoOptimizePolicy(policy);
|
|
556
|
-
assert.equal(
|
|
478
|
+
assert.equal(yield optimizationsFor(instanceOf(Database), slowLookup), 0);
|
|
557
479
|
}
|
|
558
480
|
}));
|
|
559
|
-
test("the policy can be cleared and must be a function",
|
|
560
|
-
/*#__PURE__*/
|
|
561
|
-
_asyncToGenerator(function* () {
|
|
481
|
+
test("the policy can be cleared and must be a function", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
562
482
|
var Database = loadDriver(3001, EVERY_RESOURCE);
|
|
563
483
|
Database.setAutoOptimizePolicy(() => false);
|
|
564
484
|
Database.setAutoOptimizePolicy(null);
|
|
565
485
|
assert.equal(Database.getAutoOptimizePolicy(), null);
|
|
566
|
-
assert.equal(
|
|
486
|
+
assert.equal(yield optimizationsFor(instanceOf(Database), slowLookup), 1);
|
|
567
487
|
assert.throws(() => Database.setAutoOptimizePolicy("users"), {
|
|
568
488
|
name: "TypeError"
|
|
569
489
|
});
|
|
570
490
|
}));
|
|
571
|
-
test("a declined statement is not remembered as already optimised",
|
|
572
|
-
/*#__PURE__*/
|
|
573
|
-
_asyncToGenerator(function* () {
|
|
491
|
+
test("a declined statement is not remembered as already optimised", /*#__PURE__*/_asyncToGenerator(function* () {
|
|
574
492
|
var db = createUnconfiguredDatabase();
|
|
575
|
-
assert.equal(
|
|
493
|
+
assert.equal(yield optimizationsFor(db, slowLookup), 0);
|
|
576
494
|
db.auto_optimize = true;
|
|
577
|
-
assert.equal(
|
|
495
|
+
assert.equal(yield optimizationsFor(db, slowLookup), 1);
|
|
578
496
|
}));
|