@routier/core 0.3.0 → 0.5.0
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/README.md +2 -2
- package/dist/index.cjs +549 -462
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +554 -462
- package/dist/index.js.map +1 -1
- package/dist/plugins/TelemetryDbPlugin.d.ts +43 -0
- package/dist/plugins/index.cjs +538 -24
- package/dist/plugins/index.cjs.map +1 -1
- package/dist/plugins/index.d.ts +1 -0
- package/dist/plugins/index.js +544 -22
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/query/QueryOptionsCollection.d.ts +13 -0
- package/dist/plugins/query/explain.d.ts +82 -0
- package/dist/plugins/query/formatExplanation.d.ts +9 -0
- package/dist/plugins/query/index.d.ts +2 -0
- package/dist/plugins/query/types.d.ts +11 -0
- package/dist/plugins/types.d.ts +43 -1
- package/dist/plugins/wire/types.d.ts +17 -1
- package/dist/utilities/index.cjs +43 -12
- package/dist/utilities/index.cjs.map +1 -1
- package/dist/utilities/index.js +43 -12
- package/dist/utilities/index.js.map +1 -1
- package/package.json +6 -10
- package/dist/capabilities/Capability.d.ts +0 -11
- package/dist/capabilities/PerformanceCapability.d.ts +0 -13
- package/dist/capabilities/TracingCapability.d.ts +0 -11
- package/dist/capabilities/index.cjs +0 -820
- package/dist/capabilities/index.cjs.map +0 -1
- package/dist/capabilities/index.d.ts +0 -4
- package/dist/capabilities/index.js +0 -808
- package/dist/capabilities/index.js.map +0 -1
- package/dist/capabilities/performance/PerformanceTracker.d.ts +0 -11
- package/dist/capabilities/tracing/CallTraceManager.d.ts +0 -12
- package/dist/capabilities/types.d.ts +0 -17
package/dist/plugins/index.js
CHANGED
|
@@ -2396,8 +2396,26 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
2396
2396
|
class QueryOptionsCollection {
|
|
2397
2397
|
options = new Map();
|
|
2398
2398
|
nextExecutionTarget = "database";
|
|
2399
|
+
nextExecutionReason = null;
|
|
2399
2400
|
nextIndex = 0;
|
|
2400
2401
|
enumeratedItems = [];
|
|
2402
|
+
/** Cuts over to memory execution, keeping the first cause. See `MemoryExecutionReason`. */ cutOverToMemory(reason) {
|
|
2403
|
+
this.nextExecutionTarget = "memory";
|
|
2404
|
+
if (this.nextExecutionReason == null) {
|
|
2405
|
+
this.nextExecutionReason = reason;
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
/**
|
|
2409
|
+
* True when `split()` or `splitAt()` produced this collection.
|
|
2410
|
+
*
|
|
2411
|
+
* Those rebuild each half by re-adding its options, which re-derives execution targets
|
|
2412
|
+
* without the options that caused them — a post-join filter alone in the memory half
|
|
2413
|
+
* derives back to `"database"`. Anything reading `target` as a report of where work runs
|
|
2414
|
+
* has to reject a derived collection; see `explainQuery`.
|
|
2415
|
+
*/ derived = false;
|
|
2416
|
+
get isDerived() {
|
|
2417
|
+
return this.derived;
|
|
2418
|
+
}
|
|
2401
2419
|
get items() {
|
|
2402
2420
|
return this.options;
|
|
2403
2421
|
}
|
|
@@ -2418,7 +2436,7 @@ class QueryOptionsCollection {
|
|
|
2418
2436
|
if (mapValue.fields.some((x)=>x.isRename === true) || mapValue.fields.some((x)=>x.property?.isUnmapped === true)) {
|
|
2419
2437
|
// Cut over to memory execution since we are renaming a property with .map
|
|
2420
2438
|
// We do not want to figure out how the new name flows through the entire query
|
|
2421
|
-
this.
|
|
2439
|
+
this.cutOverToMemory("map-rename");
|
|
2422
2440
|
}
|
|
2423
2441
|
}
|
|
2424
2442
|
if (name === "filter") {
|
|
@@ -2430,13 +2448,13 @@ class QueryOptionsCollection {
|
|
|
2430
2448
|
return;
|
|
2431
2449
|
}
|
|
2432
2450
|
if (filterValue.expression.type === "not-parsable") {
|
|
2433
|
-
this.
|
|
2451
|
+
this.cutOverToMemory("not-parsable");
|
|
2434
2452
|
} else {
|
|
2435
2453
|
(0,_expressions_utils__rspack_import_0/* .forEach */.j)(filterValue.expression, (expression)=>{
|
|
2436
2454
|
if ((0,_assertions__rspack_import_1/* .isPropertyExpression */.e3)(expression) && expression.property.isUnmapped) {
|
|
2437
2455
|
// Cut over to memory execution, unmapped properties are not in the database and
|
|
2438
2456
|
// cannot be queried
|
|
2439
|
-
this.
|
|
2457
|
+
this.cutOverToMemory("unmapped-property");
|
|
2440
2458
|
return false;
|
|
2441
2459
|
}
|
|
2442
2460
|
if ((0,_assertions__rspack_import_1/* .isPropertyExpression */.e3)(expression) && expression.property.hasRenamedSegments) {
|
|
@@ -2444,7 +2462,7 @@ class QueryOptionsCollection {
|
|
|
2444
2462
|
// `from` (storage) names, but filter selectors reference the
|
|
2445
2463
|
// in-memory names. Memory execution runs after deserialization,
|
|
2446
2464
|
// where the in-memory names exist
|
|
2447
|
-
this.
|
|
2465
|
+
this.cutOverToMemory("renamed-property");
|
|
2448
2466
|
return false;
|
|
2449
2467
|
}
|
|
2450
2468
|
return true;
|
|
@@ -2455,8 +2473,10 @@ class QueryOptionsCollection {
|
|
|
2455
2473
|
const sortValue = value;
|
|
2456
2474
|
// Same rule as filters: sort selectors reference in-memory names, which
|
|
2457
2475
|
// only exist after deserialization when the property is renamed or unmapped
|
|
2458
|
-
if (sortValue.property != null &&
|
|
2459
|
-
this.
|
|
2476
|
+
if (sortValue.property != null && sortValue.property.isUnmapped) {
|
|
2477
|
+
this.cutOverToMemory("unmapped-property");
|
|
2478
|
+
} else if (sortValue.property != null && sortValue.property.hasRenamedSegments) {
|
|
2479
|
+
this.cutOverToMemory("renamed-property");
|
|
2460
2480
|
}
|
|
2461
2481
|
}
|
|
2462
2482
|
if (name === "nearest") {
|
|
@@ -2467,8 +2487,10 @@ class QueryOptionsCollection {
|
|
|
2467
2487
|
//
|
|
2468
2488
|
// This is also what lets every translator's in-memory fallback read the column by
|
|
2469
2489
|
// its resolved name — anything whose storage name differs never reaches them.
|
|
2470
|
-
if (nearestValue.property != null &&
|
|
2471
|
-
this.
|
|
2490
|
+
if (nearestValue.property != null && nearestValue.property.isUnmapped) {
|
|
2491
|
+
this.cutOverToMemory("unmapped-property");
|
|
2492
|
+
} else if (nearestValue.property != null && nearestValue.property.hasRenamedSegments) {
|
|
2493
|
+
this.cutOverToMemory("renamed-property");
|
|
2472
2494
|
}
|
|
2473
2495
|
}
|
|
2474
2496
|
if (name === "join") {
|
|
@@ -2480,7 +2502,7 @@ class QueryOptionsCollection {
|
|
|
2480
2502
|
// Set BEFORE the item is created, unlike `nearest`'s ratchet below, because this
|
|
2481
2503
|
// moves the join option itself rather than everything after it.
|
|
2482
2504
|
if (joinValue.crossPlugin === true) {
|
|
2483
|
-
this.
|
|
2505
|
+
this.cutOverToMemory("cross-plugin-join");
|
|
2484
2506
|
}
|
|
2485
2507
|
}
|
|
2486
2508
|
const item = {
|
|
@@ -2488,7 +2510,10 @@ class QueryOptionsCollection {
|
|
|
2488
2510
|
option: {
|
|
2489
2511
|
name,
|
|
2490
2512
|
target: this.nextExecutionTarget,
|
|
2491
|
-
value
|
|
2513
|
+
value,
|
|
2514
|
+
...this.nextExecutionReason == null ? {} : {
|
|
2515
|
+
reason: this.nextExecutionReason
|
|
2516
|
+
}
|
|
2492
2517
|
}
|
|
2493
2518
|
};
|
|
2494
2519
|
this.nextIndex++;
|
|
@@ -2511,7 +2536,7 @@ class QueryOptionsCollection {
|
|
|
2511
2536
|
//
|
|
2512
2537
|
// A plugin that DID push the search down loses nothing but the chance to also
|
|
2513
2538
|
// push down what follows it, which is a limit over ten rows.
|
|
2514
|
-
this.
|
|
2539
|
+
this.cutOverToMemory("after-nearest");
|
|
2515
2540
|
}
|
|
2516
2541
|
if (name === "join") {
|
|
2517
2542
|
// Everything AFTER a join runs in memory, for the same reason as `nearest`: this
|
|
@@ -2522,7 +2547,7 @@ class QueryOptionsCollection {
|
|
|
2522
2547
|
// OUTER rows read, not the pairs produced — a plausible-looking result with the
|
|
2523
2548
|
// wrong number of rows in it. Conjuncts that can safely run earlier are split off
|
|
2524
2549
|
// by the query builder BEFORE dispatch, which is the only exception.
|
|
2525
|
-
this.
|
|
2550
|
+
this.cutOverToMemory("after-join");
|
|
2526
2551
|
}
|
|
2527
2552
|
}
|
|
2528
2553
|
/**
|
|
@@ -2536,6 +2561,8 @@ class QueryOptionsCollection {
|
|
|
2536
2561
|
const sortedItems = this.enumeratedItems.toSorted((a, b)=>a.index - b.index);
|
|
2537
2562
|
const before = new QueryOptionsCollection();
|
|
2538
2563
|
const after = new QueryOptionsCollection();
|
|
2564
|
+
before.derived = true;
|
|
2565
|
+
after.derived = true;
|
|
2539
2566
|
let at = null;
|
|
2540
2567
|
for(let i = 0, length = sortedItems.length; i < length; i++){
|
|
2541
2568
|
const { option } = sortedItems[i];
|
|
@@ -2569,10 +2596,12 @@ class QueryOptionsCollection {
|
|
|
2569
2596
|
]
|
|
2570
2597
|
]));
|
|
2571
2598
|
const nextExecutionTarget = this.nextExecutionTarget;
|
|
2599
|
+
const nextExecutionReason = this.nextExecutionReason;
|
|
2572
2600
|
const nextIndex = this.nextIndex;
|
|
2573
2601
|
return ()=>{
|
|
2574
2602
|
this.options = new Map(options);
|
|
2575
2603
|
this.nextExecutionTarget = nextExecutionTarget;
|
|
2604
|
+
this.nextExecutionReason = nextExecutionReason;
|
|
2576
2605
|
this.nextIndex = nextIndex;
|
|
2577
2606
|
this.enumeratedItems = [];
|
|
2578
2607
|
};
|
|
@@ -2582,6 +2611,8 @@ class QueryOptionsCollection {
|
|
|
2582
2611
|
const sortedItems = this.enumeratedItems.toSorted((a, b)=>a.index - b.index);
|
|
2583
2612
|
const memoryQueryOptionsCollection = new QueryOptionsCollection();
|
|
2584
2613
|
const databaseQueryOptionsCollection = new QueryOptionsCollection();
|
|
2614
|
+
memoryQueryOptionsCollection.derived = true;
|
|
2615
|
+
databaseQueryOptionsCollection.derived = true;
|
|
2585
2616
|
for(let i = 0, length = sortedItems.length; i < length; i++){
|
|
2586
2617
|
const sortedItem = sortedItems[i];
|
|
2587
2618
|
if (sortedItem.option.target === "database") {
|
|
@@ -3012,8 +3043,10 @@ var __webpack_exports__ = {};
|
|
|
3012
3043
|
|
|
3013
3044
|
// EXPORTS
|
|
3014
3045
|
__webpack_require__.d(__webpack_exports__, {
|
|
3046
|
+
jO: () => (/* reexport */ TupleTranslator),
|
|
3015
3047
|
Mr: () => (/* reexport */ deserializeBulkPersist),
|
|
3016
3048
|
bX: () => (/* reexport */ ConcurrencyDbPlugin),
|
|
3049
|
+
ae: () => (/* reexport */ explainQuery),
|
|
3017
3050
|
_b: () => (/* reexport */ DEFAULT_SEMI_JOIN_KEY_THRESHOLD),
|
|
3018
3051
|
pt: () => (/* reexport */ types_QueryOrdering),
|
|
3019
3052
|
Ib: () => (/* reexport */ TranslatedSingleValue),
|
|
@@ -3027,26 +3060,32 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
3027
3060
|
d0: () => (/* reexport */ JsonTranslator),
|
|
3028
3061
|
PP: () => (/* reexport */ splitSendableOptions),
|
|
3029
3062
|
f2: () => (/* reexport */ TranslatedGroupValue),
|
|
3030
|
-
|
|
3063
|
+
wN: () => (/* reexport */ collectingSink),
|
|
3031
3064
|
QB: () => (/* reexport */ RetryDbPlugin),
|
|
3032
3065
|
m6: () => (/* reexport */ executeJoin),
|
|
3066
|
+
__: () => (/* reexport */ toEntityShape),
|
|
3033
3067
|
VW: () => (/* reexport */ applyInnerOptions),
|
|
3034
3068
|
Jd: () => (/* reexport */ EphemeralDataPlugin),
|
|
3035
3069
|
Pl: () => (/* reexport */ deserializePersistResult),
|
|
3036
3070
|
JF: () => (/* reexport */ DataTranslator),
|
|
3037
3071
|
HM: () => (/* reexport */ QueryOptionsCollection/* .QueryOptionsCollection */.H),
|
|
3038
3072
|
KB: () => (/* reexport */ createRequestHandler),
|
|
3039
|
-
|
|
3073
|
+
vZ: () => (/* reexport */ formatExplanation),
|
|
3040
3074
|
II: () => (/* reexport */ deserializeQueryOptions),
|
|
3075
|
+
n: () => (/* reexport */ serializeBulkPersist),
|
|
3041
3076
|
as: () => (/* reexport */ loadJoinInnerSide),
|
|
3042
3077
|
lA: () => (/* reexport */ semiJoinFilter),
|
|
3043
3078
|
kX: () => (/* reexport */ BatchingDbPlugin),
|
|
3044
3079
|
DF: () => (/* reexport */ SqlTranslator),
|
|
3080
|
+
qj: () => (/* reexport */ loggerSink),
|
|
3081
|
+
gH: () => (/* reexport */ MEMORY_EXECUTION_EXPLANATIONS),
|
|
3045
3082
|
BL: () => (/* reexport */ serializeQueryOptions),
|
|
3083
|
+
Kg: () => (/* reexport */ withExecutedQueries),
|
|
3046
3084
|
xw: () => (/* reexport */ TranslatedArrayValue),
|
|
3047
3085
|
zH: () => (/* reexport */ joinInPlugin),
|
|
3086
|
+
Pr: () => (/* reexport */ TelemetryDbPlugin),
|
|
3048
3087
|
XK: () => (/* reexport */ Query),
|
|
3049
|
-
|
|
3088
|
+
jE: () => (/* reexport */ EXECUTED_QUERIES_UNSUPPORTED)
|
|
3050
3089
|
});
|
|
3051
3090
|
|
|
3052
3091
|
;// CONCATENATED MODULE: ./src/plugins/translators/TranslatedArrayValue.ts
|
|
@@ -3581,7 +3620,11 @@ class Query {
|
|
|
3581
3620
|
id: `${event.id}-inner`,
|
|
3582
3621
|
source: event.source,
|
|
3583
3622
|
action: "query",
|
|
3584
|
-
reason: "join inner side"
|
|
3623
|
+
reason: "join inner side",
|
|
3624
|
+
explain: event.explain,
|
|
3625
|
+
// The same array the outer read pushes into, so a join reports BOTH reads in execution
|
|
3626
|
+
// order. Built fresh rather than spread, so this has to be carried explicitly.
|
|
3627
|
+
executedQueries: event.executedQueries
|
|
3585
3628
|
};
|
|
3586
3629
|
query(innerEvent, (result)=>{
|
|
3587
3630
|
if (result.ok === Result/* .PluginEventResult.ERROR */.D.ERROR) {
|
|
@@ -4281,6 +4324,386 @@ class SqlTranslator extends DataTranslator {
|
|
|
4281
4324
|
|
|
4282
4325
|
|
|
4283
4326
|
|
|
4327
|
+
;// CONCATENATED MODULE: ./src/plugins/query/explain.ts
|
|
4328
|
+
|
|
4329
|
+
/**
|
|
4330
|
+
* One sentence per reason code, written for someone meeting pushdown for the first time.
|
|
4331
|
+
*
|
|
4332
|
+
* Beside the codes rather than in the formatter, so console output, a failing test and the
|
|
4333
|
+
* docs all say the same thing.
|
|
4334
|
+
*/ const MEMORY_EXECUTION_EXPLANATIONS = {
|
|
4335
|
+
"not-parsable": "A filter could not be parsed into an expression tree, so it and every option after it run in memory.",
|
|
4336
|
+
"unmapped-property": "The property is not stored in the database, so it can only be read after deserialization.",
|
|
4337
|
+
"renamed-property": "The property is stored under a different name, and selectors use the in-memory name, so it can only be read after deserialization.",
|
|
4338
|
+
"map-rename": "A map renames or drops properties, so every option after it refers to names the database does not have.",
|
|
4339
|
+
"after-nearest": "A similarity search orders and limits rows, and the plugin cannot report whether it performed the search, so every option after it runs in memory.",
|
|
4340
|
+
"after-join": "A join produces [outer, inner] tuples rather than entities, and the plugin cannot report how it joined, so every option after it runs in memory.",
|
|
4341
|
+
"cross-plugin-join": "The two sides of this join live on different plugins, so neither can read the other's rows and the join runs in the datastore."
|
|
4342
|
+
};
|
|
4343
|
+
const EXECUTED_QUERIES_UNSUPPORTED = "This plugin did not report what it executed. It may not support explain.";
|
|
4344
|
+
const DATABASE_STEP_DESCRIPTION = "These options are sent to the plugin.";
|
|
4345
|
+
const MEMORY_STEP_DESCRIPTION = "Routier runs these over the rows the database returned, after deserializing them.";
|
|
4346
|
+
const UNNARROWED_READ_DESCRIPTION = "No option could be pushed down, so the plugin reads the whole collection.";
|
|
4347
|
+
/**
|
|
4348
|
+
* The reportable shape of one option's value.
|
|
4349
|
+
*
|
|
4350
|
+
* Serializable facts only, never the live selector functions — an explanation is a document a
|
|
4351
|
+
* caller may log, diff in a test, or send to a server, and a closure survives none of that.
|
|
4352
|
+
*/ const detailOf = (option)=>{
|
|
4353
|
+
if (option.name === "filter") {
|
|
4354
|
+
const value = option.value;
|
|
4355
|
+
if (value.expression == null) {
|
|
4356
|
+
return undefined;
|
|
4357
|
+
}
|
|
4358
|
+
try {
|
|
4359
|
+
return {
|
|
4360
|
+
expression: types/* .Expression.toJson */.r4.toJson(value.expression)
|
|
4361
|
+
};
|
|
4362
|
+
} catch {
|
|
4363
|
+
// `valueToJson` rejects a value no wire can carry. Reporting the rest of the
|
|
4364
|
+
// explanation beats taking the diagnostic down with the query it describes.
|
|
4365
|
+
return {
|
|
4366
|
+
expressionUnavailable: "This filter holds a value that cannot be serialized."
|
|
4367
|
+
};
|
|
4368
|
+
}
|
|
4369
|
+
}
|
|
4370
|
+
if (option.name === "sort") {
|
|
4371
|
+
const value = option.value;
|
|
4372
|
+
return {
|
|
4373
|
+
propertyName: value.propertyName,
|
|
4374
|
+
direction: value.direction
|
|
4375
|
+
};
|
|
4376
|
+
}
|
|
4377
|
+
if (option.name === "skip" || option.name === "take") {
|
|
4378
|
+
return {
|
|
4379
|
+
value: option.value
|
|
4380
|
+
};
|
|
4381
|
+
}
|
|
4382
|
+
if (option.name === "nearest") {
|
|
4383
|
+
const value = option.value;
|
|
4384
|
+
return {
|
|
4385
|
+
propertyName: value.propertyName,
|
|
4386
|
+
dimensions: value.vector.length,
|
|
4387
|
+
count: value.count
|
|
4388
|
+
};
|
|
4389
|
+
}
|
|
4390
|
+
if (option.name === "join") {
|
|
4391
|
+
const value = option.value;
|
|
4392
|
+
return {
|
|
4393
|
+
kind: value.kind,
|
|
4394
|
+
outerKey: value.outerKey.propertyName,
|
|
4395
|
+
innerKey: value.innerKey.propertyName,
|
|
4396
|
+
crossPlugin: value.crossPlugin,
|
|
4397
|
+
innerOptions: explainedOptionsOf(value.innerOptions)
|
|
4398
|
+
};
|
|
4399
|
+
}
|
|
4400
|
+
if (option.name === "map" || option.name === "group") {
|
|
4401
|
+
const value = option.value;
|
|
4402
|
+
return {
|
|
4403
|
+
fields: value.fields.map((x)=>({
|
|
4404
|
+
from: x.sourceName,
|
|
4405
|
+
to: x.destinationName
|
|
4406
|
+
}))
|
|
4407
|
+
};
|
|
4408
|
+
}
|
|
4409
|
+
return undefined;
|
|
4410
|
+
};
|
|
4411
|
+
const explainedOptionOf = (option, index)=>{
|
|
4412
|
+
const detail = detailOf(option);
|
|
4413
|
+
return {
|
|
4414
|
+
index,
|
|
4415
|
+
name: option.name,
|
|
4416
|
+
...detail == null ? {} : {
|
|
4417
|
+
detail
|
|
4418
|
+
}
|
|
4419
|
+
};
|
|
4420
|
+
};
|
|
4421
|
+
const explainedOptionsOf = (options)=>{
|
|
4422
|
+
const explained = [];
|
|
4423
|
+
let index = 0;
|
|
4424
|
+
options.forEach((option)=>explained.push(explainedOptionOf(option, index++)));
|
|
4425
|
+
return explained;
|
|
4426
|
+
};
|
|
4427
|
+
const summarize = (steps)=>{
|
|
4428
|
+
const reasons = [];
|
|
4429
|
+
let database = 0;
|
|
4430
|
+
let memory = 0;
|
|
4431
|
+
for (const step of steps){
|
|
4432
|
+
if (step.executedIn === "database") {
|
|
4433
|
+
database += step.options.length;
|
|
4434
|
+
continue;
|
|
4435
|
+
}
|
|
4436
|
+
memory += step.options.length;
|
|
4437
|
+
if (step.reason != null && reasons.includes(step.reason) === false) {
|
|
4438
|
+
reasons.push(step.reason);
|
|
4439
|
+
}
|
|
4440
|
+
}
|
|
4441
|
+
const counts = `${database} ${database === 1 ? "option ran" : "options ran"} in the database, ${memory} ran in memory.`;
|
|
4442
|
+
const causes = reasons.map((reason)=>MEMORY_EXECUTION_EXPLANATIONS[reason]).join(" ");
|
|
4443
|
+
return {
|
|
4444
|
+
database,
|
|
4445
|
+
memory,
|
|
4446
|
+
reasons,
|
|
4447
|
+
explanation: causes.length === 0 ? counts : `${counts} ${causes}`
|
|
4448
|
+
};
|
|
4449
|
+
};
|
|
4450
|
+
/**
|
|
4451
|
+
* Groups options into consecutive runs that execute in the same place.
|
|
4452
|
+
*
|
|
4453
|
+
* A step boundary is where execution moves, and a reader has to see the statement as step 1 OF
|
|
4454
|
+
* 2 to understand it is not the whole query. Cutting over to memory is a ratchet, so the
|
|
4455
|
+
* database options are always a prefix and there are at most two steps.
|
|
4456
|
+
*
|
|
4457
|
+
* A database step is emitted even when NO option pushed down, because the plugin is dispatched
|
|
4458
|
+
* either way — `createQueryPayload` always builds a database event. Without it, the worst case
|
|
4459
|
+
* the feature exists to expose reports "0 in the database" while the backend reads the whole
|
|
4460
|
+
* table, which is the opposite of the truth.
|
|
4461
|
+
*/ const toExecutionSteps = (options)=>{
|
|
4462
|
+
const steps = [];
|
|
4463
|
+
let index = 0;
|
|
4464
|
+
options.forEach((option)=>{
|
|
4465
|
+
const explained = explainedOptionOf(option, index++);
|
|
4466
|
+
const current = steps[steps.length - 1];
|
|
4467
|
+
if (current != null && current.executedIn === option.target) {
|
|
4468
|
+
current.options.push(explained);
|
|
4469
|
+
return;
|
|
4470
|
+
}
|
|
4471
|
+
steps.push({
|
|
4472
|
+
step: steps.length + 1,
|
|
4473
|
+
of: 0,
|
|
4474
|
+
executedIn: option.target,
|
|
4475
|
+
description: option.target === "database" ? DATABASE_STEP_DESCRIPTION : MEMORY_STEP_DESCRIPTION,
|
|
4476
|
+
options: [
|
|
4477
|
+
explained
|
|
4478
|
+
],
|
|
4479
|
+
...option.reason == null ? {} : {
|
|
4480
|
+
reason: option.reason,
|
|
4481
|
+
explanation: MEMORY_EXECUTION_EXPLANATIONS[option.reason]
|
|
4482
|
+
}
|
|
4483
|
+
});
|
|
4484
|
+
});
|
|
4485
|
+
if (steps[0]?.executedIn !== "database") {
|
|
4486
|
+
steps.unshift({
|
|
4487
|
+
step: 0,
|
|
4488
|
+
of: 0,
|
|
4489
|
+
executedIn: "database",
|
|
4490
|
+
description: UNNARROWED_READ_DESCRIPTION,
|
|
4491
|
+
options: []
|
|
4492
|
+
});
|
|
4493
|
+
}
|
|
4494
|
+
for(let i = 0; i < steps.length; i++){
|
|
4495
|
+
steps[i].step = i + 1;
|
|
4496
|
+
steps[i].of = steps.length;
|
|
4497
|
+
}
|
|
4498
|
+
return steps;
|
|
4499
|
+
};
|
|
4500
|
+
/**
|
|
4501
|
+
* Builds the explanation from the resolved options, with no plugin involvement.
|
|
4502
|
+
*
|
|
4503
|
+
* Takes the collection BEFORE `split()`, and throws otherwise. Splitting re-adds each half
|
|
4504
|
+
* into a fresh collection, which re-derives targets without the options that caused them — a
|
|
4505
|
+
* post-join filter alone in the memory half derives back to `"database"`, and the document
|
|
4506
|
+
* would report memory work as having run in the database.
|
|
4507
|
+
*/ const explainQuery = (options, context)=>{
|
|
4508
|
+
if (options.isDerived === true) {
|
|
4509
|
+
throw new Error("explainQuery was given a collection produced by split() or splitAt(). Those re-derive " + "execution targets without the options that caused them, so the explanation would report " + "memory work as having run in the database. Pass the collection as it was resolved, " + "before splitting.");
|
|
4510
|
+
}
|
|
4511
|
+
const executionSteps = toExecutionSteps(options);
|
|
4512
|
+
return {
|
|
4513
|
+
collection: context.collection,
|
|
4514
|
+
database: context.database,
|
|
4515
|
+
summary: summarize(executionSteps),
|
|
4516
|
+
executionSteps,
|
|
4517
|
+
plugin: {
|
|
4518
|
+
kind: context.pluginKind
|
|
4519
|
+
}
|
|
4520
|
+
};
|
|
4521
|
+
};
|
|
4522
|
+
/**
|
|
4523
|
+
* Attaches what the backend reported to the step that was sent to it.
|
|
4524
|
+
*
|
|
4525
|
+
* Reporting is optional for a plugin, so an empty report is not an error: the step is marked
|
|
4526
|
+
* `executedQueriesUnsupported` instead, and the rest of the explanation stands — the pushdown
|
|
4527
|
+
* analysis comes from the options and is correct with or without the plugin's statements.
|
|
4528
|
+
*
|
|
4529
|
+
* Copies the steps rather than writing into them, so the explanation a caller already holds
|
|
4530
|
+
* does not gain statements after the fact. Options and their details are shared with the
|
|
4531
|
+
* original — nothing mutates them, and copying deeper would only look safer than it is.
|
|
4532
|
+
*/ const withExecutedQueries = (explanation, executedQueries)=>{
|
|
4533
|
+
let attached = false;
|
|
4534
|
+
const executionSteps = explanation.executionSteps.map((step)=>{
|
|
4535
|
+
// Only the first database step: a plugin reports what IT ran, and everything it ran
|
|
4536
|
+
// was sent as one dispatch. Stamping the same statements onto a second database step
|
|
4537
|
+
// would claim they ran twice.
|
|
4538
|
+
if (step.executedIn !== "database" || attached === true) {
|
|
4539
|
+
return {
|
|
4540
|
+
...step,
|
|
4541
|
+
options: [
|
|
4542
|
+
...step.options
|
|
4543
|
+
]
|
|
4544
|
+
};
|
|
4545
|
+
}
|
|
4546
|
+
attached = true;
|
|
4547
|
+
if (executedQueries.length === 0) {
|
|
4548
|
+
return {
|
|
4549
|
+
...step,
|
|
4550
|
+
options: [
|
|
4551
|
+
...step.options
|
|
4552
|
+
],
|
|
4553
|
+
executedQueriesUnsupported: EXECUTED_QUERIES_UNSUPPORTED
|
|
4554
|
+
};
|
|
4555
|
+
}
|
|
4556
|
+
return {
|
|
4557
|
+
...step,
|
|
4558
|
+
options: [
|
|
4559
|
+
...step.options
|
|
4560
|
+
],
|
|
4561
|
+
executedQueries: [
|
|
4562
|
+
...executedQueries
|
|
4563
|
+
]
|
|
4564
|
+
};
|
|
4565
|
+
});
|
|
4566
|
+
return {
|
|
4567
|
+
...explanation,
|
|
4568
|
+
executionSteps
|
|
4569
|
+
};
|
|
4570
|
+
};
|
|
4571
|
+
|
|
4572
|
+
;// CONCATENATED MODULE: ./src/plugins/query/formatExplanation.ts
|
|
4573
|
+
const OPTION_LABEL_WIDTH = 8;
|
|
4574
|
+
const WRAP_WIDTH = 68;
|
|
4575
|
+
/** Wraps `text` to `WRAP_WIDTH`, prefixing every line with `indent`. */ const wrap = (text, indent)=>{
|
|
4576
|
+
const lines = [];
|
|
4577
|
+
let line = "";
|
|
4578
|
+
for (const word of text.split(" ")){
|
|
4579
|
+
if (line.length > 0 && line.length + word.length + 1 > WRAP_WIDTH) {
|
|
4580
|
+
lines.push(indent + line);
|
|
4581
|
+
line = word;
|
|
4582
|
+
continue;
|
|
4583
|
+
}
|
|
4584
|
+
line = line.length === 0 ? word : `${line} ${word}`;
|
|
4585
|
+
}
|
|
4586
|
+
if (line.length > 0) {
|
|
4587
|
+
lines.push(indent + line);
|
|
4588
|
+
}
|
|
4589
|
+
return lines;
|
|
4590
|
+
};
|
|
4591
|
+
const COMPARATOR_SYMBOLS = {
|
|
4592
|
+
"equals": "===",
|
|
4593
|
+
"greater-than": ">",
|
|
4594
|
+
"greater-than-equals": ">=",
|
|
4595
|
+
"less-than": "<",
|
|
4596
|
+
"less-than-equals": "<="
|
|
4597
|
+
};
|
|
4598
|
+
const describeValue = (value)=>{
|
|
4599
|
+
if (value == null) {
|
|
4600
|
+
return "?";
|
|
4601
|
+
}
|
|
4602
|
+
if (value.k === "raw") {
|
|
4603
|
+
return typeof value.v === "string" ? `"${value.v}"` : String(value.v);
|
|
4604
|
+
}
|
|
4605
|
+
if (value.k === "date") {
|
|
4606
|
+
return value.v;
|
|
4607
|
+
}
|
|
4608
|
+
if (value.k === "array") {
|
|
4609
|
+
return `[${value.v.map(describeValue).join(", ")}]`;
|
|
4610
|
+
}
|
|
4611
|
+
return value.k === "undefined" ? "undefined" : String(value.v);
|
|
4612
|
+
};
|
|
4613
|
+
/** Renders a serialized expression back to something close to the source predicate. */ const describeExpression = (expression)=>{
|
|
4614
|
+
if (expression == null) {
|
|
4615
|
+
return "?";
|
|
4616
|
+
}
|
|
4617
|
+
if (expression.t === "operator") {
|
|
4618
|
+
return `${describeExpression(expression.left)} ${expression.operator} ${describeExpression(expression.right)}`;
|
|
4619
|
+
}
|
|
4620
|
+
if (expression.t === "comparator") {
|
|
4621
|
+
const left = describeExpression(expression.left);
|
|
4622
|
+
const right = describeExpression(expression.right);
|
|
4623
|
+
const symbol = COMPARATOR_SYMBOLS[expression.comparator];
|
|
4624
|
+
if (symbol == null) {
|
|
4625
|
+
return `${left}.${expression.comparator}(${right})${expression.negated === true ? " === false" : ""}`;
|
|
4626
|
+
}
|
|
4627
|
+
return `${left} ${expression.negated === true ? "!==" : symbol} ${right}`;
|
|
4628
|
+
}
|
|
4629
|
+
if (expression.t === "property") {
|
|
4630
|
+
return expression.path;
|
|
4631
|
+
}
|
|
4632
|
+
if (expression.t === "value") {
|
|
4633
|
+
return describeValue(expression.value);
|
|
4634
|
+
}
|
|
4635
|
+
return expression.t === "empty" ? "(no filter)" : "(not parsable)";
|
|
4636
|
+
};
|
|
4637
|
+
const describeOption = (option)=>{
|
|
4638
|
+
const detail = option.detail;
|
|
4639
|
+
if (detail == null) {
|
|
4640
|
+
return "";
|
|
4641
|
+
}
|
|
4642
|
+
if (option.name === "filter") {
|
|
4643
|
+
return detail.expression == null ? String(detail.expressionUnavailable ?? "") : describeExpression(detail.expression);
|
|
4644
|
+
}
|
|
4645
|
+
if (option.name === "sort") {
|
|
4646
|
+
return `${detail.propertyName} ${detail.direction}`;
|
|
4647
|
+
}
|
|
4648
|
+
if (option.name === "skip" || option.name === "take") {
|
|
4649
|
+
return String(detail.value);
|
|
4650
|
+
}
|
|
4651
|
+
if (option.name === "join") {
|
|
4652
|
+
return `${detail.kind} → ${detail.outerKey} = ${detail.innerKey}`;
|
|
4653
|
+
}
|
|
4654
|
+
if (option.name === "nearest") {
|
|
4655
|
+
return `${detail.propertyName}, ${detail.count} nearest`;
|
|
4656
|
+
}
|
|
4657
|
+
if (option.name === "map" || option.name === "group") {
|
|
4658
|
+
const fields = detail.fields;
|
|
4659
|
+
return fields.map((x)=>x.from === x.to ? x.from : `${x.from} → ${x.to}`).join(", ");
|
|
4660
|
+
}
|
|
4661
|
+
return "";
|
|
4662
|
+
};
|
|
4663
|
+
const formatStep = (step, lines)=>{
|
|
4664
|
+
const reason = step.reason == null ? "" : ` [${step.reason}]`;
|
|
4665
|
+
lines.push(` STEP ${step.step} of ${step.of} — ${step.executedIn}${reason}`);
|
|
4666
|
+
lines.push(...wrap(step.description, " "));
|
|
4667
|
+
if (step.explanation != null) {
|
|
4668
|
+
lines.push(...wrap(step.explanation, " "));
|
|
4669
|
+
}
|
|
4670
|
+
lines.push("");
|
|
4671
|
+
for (const option of step.options){
|
|
4672
|
+
lines.push(` ${option.name.padEnd(OPTION_LABEL_WIDTH)} ${describeOption(option)}`.trimEnd());
|
|
4673
|
+
}
|
|
4674
|
+
for (const executed of step.executedQueries ?? []){
|
|
4675
|
+
lines.push("");
|
|
4676
|
+
lines.push(...executed.text.split("\n").map((line)=>` ${line}`));
|
|
4677
|
+
if (executed.parameters != null && executed.parameters.length > 0) {
|
|
4678
|
+
lines.push(` parameters: ${JSON.stringify(executed.parameters)}`);
|
|
4679
|
+
}
|
|
4680
|
+
}
|
|
4681
|
+
if (step.executedQueriesUnsupported != null) {
|
|
4682
|
+
lines.push("");
|
|
4683
|
+
lines.push(...wrap(step.executedQueriesUnsupported, " "));
|
|
4684
|
+
}
|
|
4685
|
+
lines.push("");
|
|
4686
|
+
};
|
|
4687
|
+
/**
|
|
4688
|
+
* Renders an explanation for a terminal.
|
|
4689
|
+
*
|
|
4690
|
+
* The STEP headers carry the whole lesson: a reader who has never heard of pushdown still sees
|
|
4691
|
+
* that the statement in step 1 is not the entire query. Nobody should have to notice a missing
|
|
4692
|
+
* ORDER BY to work that out.
|
|
4693
|
+
*/ const formatExplanation = (explanation)=>{
|
|
4694
|
+
const { collection, database, summary, executionSteps } = explanation;
|
|
4695
|
+
const stepCount = `${executionSteps.length} ${executionSteps.length === 1 ? "step" : "steps"}`;
|
|
4696
|
+
const lines = [
|
|
4697
|
+
`${collection} · ${database} · ${stepCount}`,
|
|
4698
|
+
""
|
|
4699
|
+
];
|
|
4700
|
+
for (const step of executionSteps){
|
|
4701
|
+
formatStep(step, lines);
|
|
4702
|
+
}
|
|
4703
|
+
lines.push(...wrap(summary.explanation, " "));
|
|
4704
|
+
return lines.join("\n");
|
|
4705
|
+
};
|
|
4706
|
+
|
|
4284
4707
|
;// CONCATENATED MODULE: ./src/plugins/query/types.ts
|
|
4285
4708
|
var types_QueryOrdering = /*#__PURE__*/ function(QueryOrdering) {
|
|
4286
4709
|
QueryOrdering["Descending"] = "desc";
|
|
@@ -4295,6 +4718,8 @@ var types_QueryOrdering = /*#__PURE__*/ function(QueryOrdering) {
|
|
|
4295
4718
|
|
|
4296
4719
|
|
|
4297
4720
|
|
|
4721
|
+
|
|
4722
|
+
|
|
4298
4723
|
// EXTERNAL MODULE: ./src/expressions/evaluate.ts
|
|
4299
4724
|
var evaluate = __webpack_require__(379);
|
|
4300
4725
|
;// CONCATENATED MODULE: ./src/plugins/wire/query.ts
|
|
@@ -4766,6 +5191,7 @@ const createRequestHandler = (options)=>{
|
|
|
4766
5191
|
const queryOptions = deserializeQueryOptions(request.options, schema, resolveSchema, // Applied to the outer collection AND to every collection a join reaches, so a
|
|
4767
5192
|
// join cannot be used to read around a scope
|
|
4768
5193
|
(target)=>scopeExpressionFor(target, context, "query"));
|
|
5194
|
+
const executedQueries = [];
|
|
4769
5195
|
return await new Promise((resolve)=>{
|
|
4770
5196
|
plugin.query({
|
|
4771
5197
|
// `false`: nothing here attaches to a change tracker — the tracker lives on
|
|
@@ -4774,7 +5200,9 @@ const createRequestHandler = (options)=>{
|
|
|
4774
5200
|
schemas: schemas,
|
|
4775
5201
|
id: (0,uuid/* .uuid */.u)(8),
|
|
4776
5202
|
source: "RequestHandler",
|
|
4777
|
-
action: "query"
|
|
5203
|
+
action: "query",
|
|
5204
|
+
explain: request.explain,
|
|
5205
|
+
executedQueries
|
|
4778
5206
|
}, (result)=>{
|
|
4779
5207
|
if (result.ok === Result/* .PluginEventResult.ERROR */.D.ERROR) {
|
|
4780
5208
|
resolve(failed(result.error));
|
|
@@ -4783,7 +5211,13 @@ const createRequestHandler = (options)=>{
|
|
|
4783
5211
|
resolve({
|
|
4784
5212
|
ok: true,
|
|
4785
5213
|
kind: "query",
|
|
4786
|
-
value: result.data.value
|
|
5214
|
+
value: result.data.value,
|
|
5215
|
+
// Only when asked, and only what the plugin reported. A plugin
|
|
5216
|
+
// that reported nothing sends nothing, and the caller marks the
|
|
5217
|
+
// remote step as not reported.
|
|
5218
|
+
...request.explain === true && executedQueries.length > 0 ? {
|
|
5219
|
+
executedQueries
|
|
5220
|
+
} : {}
|
|
4787
5221
|
});
|
|
4788
5222
|
});
|
|
4789
5223
|
});
|
|
@@ -5432,6 +5866,10 @@ class EphemeralDataPlugin {
|
|
|
5432
5866
|
}
|
|
5433
5867
|
innerRows.push(cloneRecord(record));
|
|
5434
5868
|
}
|
|
5869
|
+
const narrowing = outerKeys == null ? "full scan" : `narrowed by ${outerKeys.size} outer ${outerKeys.size === 1 ? "key" : "keys"}`;
|
|
5870
|
+
event.executedQueries.push({
|
|
5871
|
+
text: `${innerSchema.collectionName}: scanned ${innerRows.length} in-memory ${innerRows.length === 1 ? "record" : "records"} for join inner side (${narrowing})`
|
|
5872
|
+
});
|
|
5435
5873
|
done({
|
|
5436
5874
|
ok: "success",
|
|
5437
5875
|
innerSide: {
|
|
@@ -5541,7 +5979,13 @@ class EphemeralDataPlugin {
|
|
|
5541
5979
|
* collection to pair it with three rows.
|
|
5542
5980
|
*
|
|
5543
5981
|
* `cloned` is in storage shape, so the keys are read by resolved column name.
|
|
5544
|
-
*/
|
|
5982
|
+
*/ // No statement to quote — an ephemeral store walks its own records. Said
|
|
5983
|
+
// plainly so `.explain()` does not leave a reader wondering whether the
|
|
5984
|
+
// plugin simply failed to report. Before the inner side, to match execution order.
|
|
5985
|
+
event.executedQueries.push({
|
|
5986
|
+
text: `${operation.schema.collectionName}: scanned ${cloned.length} in-memory ${cloned.length === 1 ? "record" : "records"}`
|
|
5987
|
+
});
|
|
5988
|
+
const joinOption = operation.options.getLast("join");
|
|
5545
5989
|
const outerKeys = joinOption == null ? null : distinctJoinKeys(cloned, joinOption.value.outerKey, joinOption.value.semiJoinKeyThreshold, {
|
|
5546
5990
|
storageShape: true
|
|
5547
5991
|
});
|
|
@@ -5625,6 +6069,69 @@ class RetryDbPlugin {
|
|
|
5625
6069
|
}
|
|
5626
6070
|
}
|
|
5627
6071
|
|
|
6072
|
+
;// CONCATENATED MODULE: ./src/plugins/TelemetryDbPlugin.ts
|
|
6073
|
+
|
|
6074
|
+
/** Default sink: writes through the levelled logger, so ROUTIER_LOG_LEVEL governs it. */ const loggerSink = ()=>(e)=>{
|
|
6075
|
+
const line = `[routier] ${e.operation} ${e.schemas.join(",")} ${e.durationMs.toFixed(1)}ms`;
|
|
6076
|
+
if (e.ok === "error") {
|
|
6077
|
+
logger/* .logger.error */.vF.error(line, e.error);
|
|
6078
|
+
return;
|
|
6079
|
+
}
|
|
6080
|
+
logger/* .logger.info */.vF.info(line);
|
|
6081
|
+
};
|
|
6082
|
+
/** Pushes every event into `into`. For tests and custom buffering. */ const collectingSink = (into)=>(e)=>{
|
|
6083
|
+
into.push(e);
|
|
6084
|
+
};
|
|
6085
|
+
class TelemetryDbPlugin {
|
|
6086
|
+
plugin;
|
|
6087
|
+
onEvent;
|
|
6088
|
+
constructor(plugin, options = {}){
|
|
6089
|
+
this.plugin = plugin;
|
|
6090
|
+
this.onEvent = options.onEvent ?? loggerSink();
|
|
6091
|
+
}
|
|
6092
|
+
get databaseName() {
|
|
6093
|
+
return this.plugin.databaseName;
|
|
6094
|
+
}
|
|
6095
|
+
query(event, done) {
|
|
6096
|
+
const start = performance.now();
|
|
6097
|
+
this.plugin.query(event, (result)=>{
|
|
6098
|
+
this.emit("query", event, result, start);
|
|
6099
|
+
done(result);
|
|
6100
|
+
});
|
|
6101
|
+
}
|
|
6102
|
+
bulkPersist(event, done) {
|
|
6103
|
+
const start = performance.now();
|
|
6104
|
+
this.plugin.bulkPersist(event, (result)=>{
|
|
6105
|
+
this.emit("bulkPersist", event, result, start);
|
|
6106
|
+
done(result);
|
|
6107
|
+
});
|
|
6108
|
+
}
|
|
6109
|
+
destroy(event, done) {
|
|
6110
|
+
const start = performance.now();
|
|
6111
|
+
this.plugin.destroy(event, (result)=>{
|
|
6112
|
+
this.emit("destroy", event, result, start);
|
|
6113
|
+
done(result);
|
|
6114
|
+
});
|
|
6115
|
+
}
|
|
6116
|
+
emit(operation, event, result, start) {
|
|
6117
|
+
try {
|
|
6118
|
+
this.onEvent({
|
|
6119
|
+
operation,
|
|
6120
|
+
eventId: event.id,
|
|
6121
|
+
source: event.source,
|
|
6122
|
+
schemas: [
|
|
6123
|
+
...event.schemas.values()
|
|
6124
|
+
].map((s)=>s.collectionName),
|
|
6125
|
+
durationMs: performance.now() - start,
|
|
6126
|
+
ok: result.ok,
|
|
6127
|
+
error: result.ok === "success" ? undefined : result.error
|
|
6128
|
+
});
|
|
6129
|
+
} catch {
|
|
6130
|
+
// A broken sink must never fail the data operation.
|
|
6131
|
+
}
|
|
6132
|
+
}
|
|
6133
|
+
}
|
|
6134
|
+
|
|
5628
6135
|
;// CONCATENATED MODULE: ./src/plugins/CacheDbPlugin.ts
|
|
5629
6136
|
|
|
5630
6137
|
/**
|
|
@@ -5634,7 +6141,7 @@ class RetryDbPlugin {
|
|
|
5634
6141
|
* `PropertyInfo` objects carrying functions and would not survive `JSON.stringify`. A filter is
|
|
5635
6142
|
* identified by its source text plus its params, which is what the expression is derived from
|
|
5636
6143
|
* anyway — two queries with the same source and params are the same query.
|
|
5637
|
-
*/ const
|
|
6144
|
+
*/ const CacheDbPlugin_describeOption = (option)=>{
|
|
5638
6145
|
const value = option.value;
|
|
5639
6146
|
switch(option.name){
|
|
5640
6147
|
case "filter":
|
|
@@ -5668,7 +6175,7 @@ class CacheDbPlugin {
|
|
|
5668
6175
|
/** `schemaId` first, so invalidating a schema is a prefix match. */ keyFor(event) {
|
|
5669
6176
|
const parts = [];
|
|
5670
6177
|
event.operation.options.forEach((option)=>{
|
|
5671
|
-
parts.push(`${option.name}:${
|
|
6178
|
+
parts.push(`${option.name}:${CacheDbPlugin_describeOption(option)}`);
|
|
5672
6179
|
});
|
|
5673
6180
|
return `${String(event.operation.schema.id)}\u0000${parts.join("\u0001")}`;
|
|
5674
6181
|
}
|
|
@@ -5698,6 +6205,12 @@ class CacheDbPlugin {
|
|
|
5698
6205
|
// Re-set to move it to the end of the insertion order: most recently used.
|
|
5699
6206
|
this.entries.delete(key);
|
|
5700
6207
|
this.entries.set(key, cached);
|
|
6208
|
+
// Said rather than left blank. A hit means no database was touched, which is a fact
|
|
6209
|
+
// worth reporting — and an empty report would otherwise read as a plugin that failed
|
|
6210
|
+
// to say what it ran.
|
|
6211
|
+
event.executedQueries.push({
|
|
6212
|
+
text: "cache hit — no query was executed"
|
|
6213
|
+
});
|
|
5701
6214
|
done(Result/* .PluginEventResult.success */.D.success(event.id, this.rebuild(cached)));
|
|
5702
6215
|
return;
|
|
5703
6216
|
}
|
|
@@ -6082,6 +6595,7 @@ const DEFAULT_MAX_BATCH_SIZE = 100;
|
|
|
6082
6595
|
|
|
6083
6596
|
|
|
6084
6597
|
|
|
6598
|
+
|
|
6085
6599
|
})();
|
|
6086
6600
|
|
|
6087
6601
|
var __webpack_exports__BatchingDbPlugin = __webpack_exports__.kX;
|
|
@@ -6089,18 +6603,22 @@ var __webpack_exports__CacheDbPlugin = __webpack_exports__.y4;
|
|
|
6089
6603
|
var __webpack_exports__ConcurrencyDbPlugin = __webpack_exports__.bX;
|
|
6090
6604
|
var __webpack_exports__DEFAULT_SEMI_JOIN_KEY_THRESHOLD = __webpack_exports__._b;
|
|
6091
6605
|
var __webpack_exports__DataTranslator = __webpack_exports__.JF;
|
|
6606
|
+
var __webpack_exports__EXECUTED_QUERIES_UNSUPPORTED = __webpack_exports__.jE;
|
|
6092
6607
|
var __webpack_exports__EphemeralDataPlugin = __webpack_exports__.Jd;
|
|
6093
6608
|
var __webpack_exports__JsonTranslator = __webpack_exports__.d0;
|
|
6609
|
+
var __webpack_exports__MEMORY_EXECUTION_EXPLANATIONS = __webpack_exports__.gH;
|
|
6094
6610
|
var __webpack_exports__Query = __webpack_exports__.XK;
|
|
6095
6611
|
var __webpack_exports__QueryOptionsCollection = __webpack_exports__.HM;
|
|
6096
6612
|
var __webpack_exports__QueryOrdering = __webpack_exports__.pt;
|
|
6097
6613
|
var __webpack_exports__RetryDbPlugin = __webpack_exports__.QB;
|
|
6098
6614
|
var __webpack_exports__SqlTranslator = __webpack_exports__.DF;
|
|
6615
|
+
var __webpack_exports__TelemetryDbPlugin = __webpack_exports__.Pr;
|
|
6099
6616
|
var __webpack_exports__TranslatedArrayValue = __webpack_exports__.xw;
|
|
6100
6617
|
var __webpack_exports__TranslatedGroupValue = __webpack_exports__.f2;
|
|
6101
6618
|
var __webpack_exports__TranslatedSingleValue = __webpack_exports__.Ib;
|
|
6102
6619
|
var __webpack_exports__TupleTranslator = __webpack_exports__.jO;
|
|
6103
6620
|
var __webpack_exports__applyInnerOptions = __webpack_exports__.VW;
|
|
6621
|
+
var __webpack_exports__collectingSink = __webpack_exports__.wN;
|
|
6104
6622
|
var __webpack_exports__cosineDistance = __webpack_exports__.lO;
|
|
6105
6623
|
var __webpack_exports__createRequestHandler = __webpack_exports__.KB;
|
|
6106
6624
|
var __webpack_exports__deserializeBulkPersist = __webpack_exports__.Mr;
|
|
@@ -6108,9 +6626,12 @@ var __webpack_exports__deserializePersistResult = __webpack_exports__.Pl;
|
|
|
6108
6626
|
var __webpack_exports__deserializeQueryOptions = __webpack_exports__.II;
|
|
6109
6627
|
var __webpack_exports__distinctJoinKeys = __webpack_exports__.RK;
|
|
6110
6628
|
var __webpack_exports__executeJoin = __webpack_exports__.m6;
|
|
6629
|
+
var __webpack_exports__explainQuery = __webpack_exports__.ae;
|
|
6630
|
+
var __webpack_exports__formatExplanation = __webpack_exports__.vZ;
|
|
6111
6631
|
var __webpack_exports__hashJoin = __webpack_exports__.Bg;
|
|
6112
6632
|
var __webpack_exports__joinInPlugin = __webpack_exports__.zH;
|
|
6113
6633
|
var __webpack_exports__loadJoinInnerSide = __webpack_exports__.as;
|
|
6634
|
+
var __webpack_exports__loggerSink = __webpack_exports__.qj;
|
|
6114
6635
|
var __webpack_exports__nearestBy = __webpack_exports__.iG;
|
|
6115
6636
|
var __webpack_exports__readJoinKey = __webpack_exports__.qy;
|
|
6116
6637
|
var __webpack_exports__semiJoinFilter = __webpack_exports__.lA;
|
|
@@ -6119,6 +6640,7 @@ var __webpack_exports__serializePersistResult = __webpack_exports__.yR;
|
|
|
6119
6640
|
var __webpack_exports__serializeQueryOptions = __webpack_exports__.BL;
|
|
6120
6641
|
var __webpack_exports__splitSendableOptions = __webpack_exports__.PP;
|
|
6121
6642
|
var __webpack_exports__toEntityShape = __webpack_exports__.__;
|
|
6122
|
-
|
|
6643
|
+
var __webpack_exports__withExecutedQueries = __webpack_exports__.Kg;
|
|
6644
|
+
export { __webpack_exports__BatchingDbPlugin as BatchingDbPlugin, __webpack_exports__CacheDbPlugin as CacheDbPlugin, __webpack_exports__ConcurrencyDbPlugin as ConcurrencyDbPlugin, __webpack_exports__DEFAULT_SEMI_JOIN_KEY_THRESHOLD as DEFAULT_SEMI_JOIN_KEY_THRESHOLD, __webpack_exports__DataTranslator as DataTranslator, __webpack_exports__EXECUTED_QUERIES_UNSUPPORTED as EXECUTED_QUERIES_UNSUPPORTED, __webpack_exports__EphemeralDataPlugin as EphemeralDataPlugin, __webpack_exports__JsonTranslator as JsonTranslator, __webpack_exports__MEMORY_EXECUTION_EXPLANATIONS as MEMORY_EXECUTION_EXPLANATIONS, __webpack_exports__Query as Query, __webpack_exports__QueryOptionsCollection as QueryOptionsCollection, __webpack_exports__QueryOrdering as QueryOrdering, __webpack_exports__RetryDbPlugin as RetryDbPlugin, __webpack_exports__SqlTranslator as SqlTranslator, __webpack_exports__TelemetryDbPlugin as TelemetryDbPlugin, __webpack_exports__TranslatedArrayValue as TranslatedArrayValue, __webpack_exports__TranslatedGroupValue as TranslatedGroupValue, __webpack_exports__TranslatedSingleValue as TranslatedSingleValue, __webpack_exports__TupleTranslator as TupleTranslator, __webpack_exports__applyInnerOptions as applyInnerOptions, __webpack_exports__collectingSink as collectingSink, __webpack_exports__cosineDistance as cosineDistance, __webpack_exports__createRequestHandler as createRequestHandler, __webpack_exports__deserializeBulkPersist as deserializeBulkPersist, __webpack_exports__deserializePersistResult as deserializePersistResult, __webpack_exports__deserializeQueryOptions as deserializeQueryOptions, __webpack_exports__distinctJoinKeys as distinctJoinKeys, __webpack_exports__executeJoin as executeJoin, __webpack_exports__explainQuery as explainQuery, __webpack_exports__formatExplanation as formatExplanation, __webpack_exports__hashJoin as hashJoin, __webpack_exports__joinInPlugin as joinInPlugin, __webpack_exports__loadJoinInnerSide as loadJoinInnerSide, __webpack_exports__loggerSink as loggerSink, __webpack_exports__nearestBy as nearestBy, __webpack_exports__readJoinKey as readJoinKey, __webpack_exports__semiJoinFilter as semiJoinFilter, __webpack_exports__serializeBulkPersist as serializeBulkPersist, __webpack_exports__serializePersistResult as serializePersistResult, __webpack_exports__serializeQueryOptions as serializeQueryOptions, __webpack_exports__splitSendableOptions as splitSendableOptions, __webpack_exports__toEntityShape as toEntityShape, __webpack_exports__withExecutedQueries as withExecutedQueries };
|
|
6123
6645
|
|
|
6124
6646
|
//# sourceMappingURL=index.js.map
|