@webda/ql 4.0.0-beta.5 → 4.0.0-beta.7
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 +72 -31
- package/lib/WebdaQLLexer.d.ts +44 -30
- package/lib/WebdaQLLexer.d.ts.map +1 -1
- package/lib/WebdaQLLexer.js +257 -152
- package/lib/WebdaQLLexer.js.map +1 -1
- package/lib/WebdaQLParserLexer.d.ts +44 -30
- package/lib/WebdaQLParserLexer.d.ts.map +1 -1
- package/lib/WebdaQLParserLexer.js +257 -152
- package/lib/WebdaQLParserLexer.js.map +1 -1
- package/lib/WebdaQLParserListener.d.ts +203 -30
- package/lib/WebdaQLParserListener.d.ts.map +1 -1
- package/lib/WebdaQLParserParser.d.ts +242 -44
- package/lib/WebdaQLParserParser.d.ts.map +1 -1
- package/lib/WebdaQLParserParser.js +2054 -715
- package/lib/WebdaQLParserParser.js.map +1 -1
- package/lib/WebdaQLParserVisitor.d.ts +126 -17
- package/lib/WebdaQLParserVisitor.d.ts.map +1 -1
- package/lib/aggregation-query.d.ts +95 -0
- package/lib/aggregation-query.d.ts.map +1 -0
- package/lib/aggregation-query.js +104 -0
- package/lib/aggregation-query.js.map +1 -0
- package/lib/aggregation-select.spec.d.ts +2 -0
- package/lib/aggregation-select.spec.d.ts.map +1 -0
- package/lib/aggregation-select.spec.js +165 -0
- package/lib/aggregation-select.spec.js.map +1 -0
- package/lib/aggregation.d.ts +97 -0
- package/lib/aggregation.d.ts.map +1 -0
- package/lib/aggregation.js +241 -0
- package/lib/aggregation.js.map +1 -0
- package/lib/aggregation.spec.d.ts +2 -0
- package/lib/aggregation.spec.d.ts.map +1 -0
- package/lib/aggregation.spec.js +360 -0
- package/lib/aggregation.spec.js.map +1 -0
- package/lib/bind.d.ts.map +1 -1
- package/lib/bind.js +29 -0
- package/lib/bind.js.map +1 -1
- package/lib/filter.d.ts +54 -0
- package/lib/filter.d.ts.map +1 -0
- package/lib/filter.js +135 -0
- package/lib/filter.js.map +1 -0
- package/lib/filter.spec.d.ts +2 -0
- package/lib/filter.spec.d.ts.map +1 -0
- package/lib/filter.spec.js +124 -0
- package/lib/filter.spec.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/query.d.ts +173 -12
- package/lib/query.d.ts.map +1 -1
- package/lib/query.js +529 -64
- package/lib/query.js.map +1 -1
- package/lib/query.spec.js +7 -4
- package/lib/query.spec.js.map +1 -1
- package/lib/statements.spec.d.ts +2 -0
- package/lib/statements.spec.d.ts.map +1 -0
- package/lib/statements.spec.js +423 -0
- package/lib/statements.spec.js.map +1 -0
- package/lib/webdaql-string.d.ts +9 -0
- package/lib/webdaql-string.d.ts.map +1 -1
- package/lib/webdaql-string.js +9 -8
- package/lib/webdaql-string.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { assertFilterQuery, ComparisonExpression, parse } from "./query.js";
|
|
2
|
+
import { bind } from "./bind.js";
|
|
3
|
+
import { WebdaQLError } from "./webdaql-string.js";
|
|
4
|
+
import { AggregationError, checkAlias, validateAggregation } from "./aggregation-query.js";
|
|
5
|
+
// Validation lives apart so query.ts can use it without importing this module back
|
|
6
|
+
export * from "./aggregation-query.js";
|
|
7
|
+
const TYPE_RANK = { number: 1, bigint: 1, string: 2, boolean: 3 };
|
|
8
|
+
/**
|
|
9
|
+
* Compare two values the way every backend orders aggregated rows
|
|
10
|
+
*
|
|
11
|
+
* null / undefined first, then numbers, strings (code unit order), booleans, then anything
|
|
12
|
+
* else by its JSON representation.
|
|
13
|
+
* @param a - first value
|
|
14
|
+
* @param b - second value
|
|
15
|
+
* @returns negative, zero or positive
|
|
16
|
+
*/
|
|
17
|
+
export function compareValues(a, b) {
|
|
18
|
+
const aNull = a === null || a === undefined;
|
|
19
|
+
const bNull = b === null || b === undefined;
|
|
20
|
+
if (aNull || bNull) {
|
|
21
|
+
return aNull === bNull ? 0 : aNull ? -1 : 1;
|
|
22
|
+
}
|
|
23
|
+
const rankA = TYPE_RANK[typeof a] ?? 4;
|
|
24
|
+
const rankB = TYPE_RANK[typeof b] ?? 4;
|
|
25
|
+
if (rankA !== rankB) {
|
|
26
|
+
return rankA - rankB;
|
|
27
|
+
}
|
|
28
|
+
const left = rankA === 4 ? JSON.stringify(a) : a;
|
|
29
|
+
const right = rankB === 4 ? JSON.stringify(b) : b;
|
|
30
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Read a dotted path, undefined when any segment is missing
|
|
34
|
+
*
|
|
35
|
+
* A Date is returned as its ISO string, the form JSON backends store: group keys, MIN / MAX and
|
|
36
|
+
* COUNT_DISTINCT then match on every backend.
|
|
37
|
+
* @param item - the object
|
|
38
|
+
* @param path - dotted path
|
|
39
|
+
* @returns the value
|
|
40
|
+
*/
|
|
41
|
+
function readPath(item, path) {
|
|
42
|
+
const value = ComparisonExpression.getAttributeValue(item, path.split("."));
|
|
43
|
+
if (value instanceof Date) {
|
|
44
|
+
return Number.isNaN(value.getTime()) ? null : value.toISOString();
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Create the accumulator of a metric
|
|
50
|
+
* @param metric - the metric
|
|
51
|
+
* @returns the accumulator
|
|
52
|
+
*/
|
|
53
|
+
function createAccumulator(metric) {
|
|
54
|
+
const value = (item) => (metric.field === undefined ? item : readPath(item, metric.field));
|
|
55
|
+
const present = (v) => v !== null && v !== undefined;
|
|
56
|
+
const numeric = (v) => typeof v === "number" && Number.isFinite(v);
|
|
57
|
+
switch (metric.fn) {
|
|
58
|
+
case "COUNT": {
|
|
59
|
+
let count = 0;
|
|
60
|
+
return { add: item => void (present(value(item)) && count++), result: () => count };
|
|
61
|
+
}
|
|
62
|
+
case "COUNT_DISTINCT": {
|
|
63
|
+
const seen = new Set();
|
|
64
|
+
return {
|
|
65
|
+
add: item => {
|
|
66
|
+
const v = value(item);
|
|
67
|
+
if (present(v))
|
|
68
|
+
seen.add(JSON.stringify(v));
|
|
69
|
+
},
|
|
70
|
+
result: () => seen.size
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
case "SUM": {
|
|
74
|
+
let sum = 0;
|
|
75
|
+
return {
|
|
76
|
+
add: item => {
|
|
77
|
+
const v = value(item);
|
|
78
|
+
if (numeric(v))
|
|
79
|
+
sum += v;
|
|
80
|
+
},
|
|
81
|
+
result: () => sum
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
case "AVG": {
|
|
85
|
+
let sum = 0;
|
|
86
|
+
let count = 0;
|
|
87
|
+
return {
|
|
88
|
+
add: item => {
|
|
89
|
+
const v = value(item);
|
|
90
|
+
if (numeric(v)) {
|
|
91
|
+
sum += v;
|
|
92
|
+
count++;
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
result: () => (count ? sum / count : null)
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
case "MIN":
|
|
99
|
+
case "MAX": {
|
|
100
|
+
const sign = metric.fn === "MIN" ? 1 : -1;
|
|
101
|
+
let current = undefined;
|
|
102
|
+
return {
|
|
103
|
+
add: item => {
|
|
104
|
+
const v = value(item);
|
|
105
|
+
if (present(v) && (current === undefined || sign * compareValues(v, current) < 0))
|
|
106
|
+
current = v;
|
|
107
|
+
},
|
|
108
|
+
result: () => current ?? null
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Streaming reference implementation of an aggregation
|
|
115
|
+
*
|
|
116
|
+
* Items must already match the query filter. Memory is O(groups), plus one Set per group per
|
|
117
|
+
* COUNT_DISTINCT. It is the fallback engine of repositories and the oracle of the
|
|
118
|
+
* conformance tests.
|
|
119
|
+
*/
|
|
120
|
+
export class Aggregator {
|
|
121
|
+
query;
|
|
122
|
+
maxGroups;
|
|
123
|
+
groups = new Map();
|
|
124
|
+
/**
|
|
125
|
+
* @param query - the aggregation; validated here
|
|
126
|
+
* @param maxGroups - throw AGGREGATION_TOO_MANY_GROUPS beyond this number of groups
|
|
127
|
+
*/
|
|
128
|
+
constructor(query, maxGroups = Number.POSITIVE_INFINITY) {
|
|
129
|
+
this.query = query;
|
|
130
|
+
this.maxGroups = maxGroups;
|
|
131
|
+
validateAggregation(query);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Create an empty group
|
|
135
|
+
* @param keys - group key values
|
|
136
|
+
* @returns the group
|
|
137
|
+
*/
|
|
138
|
+
createGroup(keys) {
|
|
139
|
+
return {
|
|
140
|
+
keys,
|
|
141
|
+
accumulators: Object.entries(this.query.metrics).map(([alias, metric]) => [alias, createAccumulator(metric)])
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Add a matching item
|
|
146
|
+
* @param item - the item
|
|
147
|
+
*/
|
|
148
|
+
add(item) {
|
|
149
|
+
const keys = this.query.groupBy.map(path => readPath(item, path) ?? null);
|
|
150
|
+
const id = JSON.stringify(keys);
|
|
151
|
+
let group = this.groups.get(id);
|
|
152
|
+
if (!group) {
|
|
153
|
+
if (this.groups.size >= this.maxGroups) {
|
|
154
|
+
throw new AggregationError("AGGREGATION_TOO_MANY_GROUPS", `Aggregation exceeds ${this.maxGroups} groups`);
|
|
155
|
+
}
|
|
156
|
+
group = this.createGroup(keys);
|
|
157
|
+
this.groups.set(id, group);
|
|
158
|
+
}
|
|
159
|
+
for (const [, accumulator] of group.accumulators) {
|
|
160
|
+
accumulator.add(item);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Compute the rows, ordered and limited
|
|
165
|
+
* @returns flat rows keyed by group path and metric alias
|
|
166
|
+
*/
|
|
167
|
+
rows() {
|
|
168
|
+
const groups = [...this.groups.values()];
|
|
169
|
+
if (!groups.length && !this.query.groupBy.length) {
|
|
170
|
+
groups.push(this.createGroup([]));
|
|
171
|
+
}
|
|
172
|
+
let rows = groups.map(group => {
|
|
173
|
+
const row = {};
|
|
174
|
+
this.query.groupBy.forEach((path, i) => (row[path] = group.keys[i]));
|
|
175
|
+
group.accumulators.forEach(([alias, accumulator]) => (row[alias] = accumulator.result()));
|
|
176
|
+
return row;
|
|
177
|
+
});
|
|
178
|
+
const orderBy = this.query.orderBy ?? [];
|
|
179
|
+
if (orderBy.length) {
|
|
180
|
+
rows.sort((a, b) => {
|
|
181
|
+
for (const order of orderBy) {
|
|
182
|
+
const c = compareValues(a[order.key], b[order.key]);
|
|
183
|
+
if (c)
|
|
184
|
+
return order.direction === "ASC" ? c : -c;
|
|
185
|
+
}
|
|
186
|
+
return 0;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
if (this.query.limit) {
|
|
190
|
+
rows = rows.slice(0, this.query.limit);
|
|
191
|
+
}
|
|
192
|
+
return rows;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const METRIC_KEYS = {
|
|
196
|
+
count: "COUNT",
|
|
197
|
+
countDistinct: "COUNT_DISTINCT",
|
|
198
|
+
sum: "SUM",
|
|
199
|
+
avg: "AVG",
|
|
200
|
+
min: "MIN",
|
|
201
|
+
max: "MAX"
|
|
202
|
+
};
|
|
203
|
+
/**
|
|
204
|
+
* Convert the object form of an aggregation to the canonical AST
|
|
205
|
+
* @param input - the object form
|
|
206
|
+
* @param params - values for the `?` / `:name` placeholders of the filter
|
|
207
|
+
* @returns the validated AST
|
|
208
|
+
* @throws WebdaQLError when the input is invalid
|
|
209
|
+
*/
|
|
210
|
+
export function toAggregationQuery(input, params) {
|
|
211
|
+
let filter = input.filter ?? "";
|
|
212
|
+
if (params !== undefined) {
|
|
213
|
+
filter = bind(filter, params);
|
|
214
|
+
}
|
|
215
|
+
const parsed = parse(filter);
|
|
216
|
+
// DELETE / UPDATE / SELECT statements are not filters
|
|
217
|
+
assertFilterQuery(parsed);
|
|
218
|
+
if (parsed.limit !== undefined || parsed.orderBy?.length || parsed.continuationToken !== undefined) {
|
|
219
|
+
throw new WebdaQLError("An aggregation filter cannot contain ORDER BY, LIMIT or OFFSET");
|
|
220
|
+
}
|
|
221
|
+
const metrics = {};
|
|
222
|
+
for (const [alias, spec] of Object.entries(input.metrics ?? {})) {
|
|
223
|
+
// Before assigning: an own `__proto__` key would otherwise change the prototype of `metrics`
|
|
224
|
+
checkAlias(alias);
|
|
225
|
+
const entries = Object.entries(spec ?? {});
|
|
226
|
+
if (entries.length !== 1 || !Object.prototype.hasOwnProperty.call(METRIC_KEYS, entries[0][0])) {
|
|
227
|
+
throw new WebdaQLError(`Metric '${alias}' must define exactly one of ${Object.keys(METRIC_KEYS).join(", ")}`);
|
|
228
|
+
}
|
|
229
|
+
const [kind, field] = entries[0];
|
|
230
|
+
const fn = METRIC_KEYS[kind];
|
|
231
|
+
metrics[alias] = fn === "COUNT" && field === "*" ? { fn } : { fn, field: field };
|
|
232
|
+
}
|
|
233
|
+
return validateAggregation({
|
|
234
|
+
filter: parsed.filter,
|
|
235
|
+
groupBy: [...(input.groupBy ?? [])],
|
|
236
|
+
metrics,
|
|
237
|
+
orderBy: input.orderBy?.map(order => ({ key: order.key, direction: order.direction })),
|
|
238
|
+
limit: input.limit
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=aggregation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregation.js","sourceRoot":"","sources":["../src/aggregation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregation.spec.d.ts","sourceRoot":"","sources":["../src/aggregation.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
2
|
+
var useValue = arguments.length > 2;
|
|
3
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
4
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
5
|
+
}
|
|
6
|
+
return useValue ? value : void 0;
|
|
7
|
+
};
|
|
8
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
9
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
10
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
11
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
12
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
13
|
+
var _, done = false;
|
|
14
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
15
|
+
var context = {};
|
|
16
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
17
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
18
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
19
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
20
|
+
if (kind === "accessor") {
|
|
21
|
+
if (result === void 0) continue;
|
|
22
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
23
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
24
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
25
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
26
|
+
}
|
|
27
|
+
else if (_ = accept(result)) {
|
|
28
|
+
if (kind === "field") initializers.unshift(_);
|
|
29
|
+
else descriptor[key] = _;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
33
|
+
done = true;
|
|
34
|
+
};
|
|
35
|
+
import { suite, test } from "@webda/test";
|
|
36
|
+
import * as assert from "assert";
|
|
37
|
+
import { Aggregator, AggregationError, compareValues, toAggregationQuery, validateAggregation } from "./aggregation.js";
|
|
38
|
+
import { AndExpression } from "./query.js";
|
|
39
|
+
import { WebdaQLError } from "./webdaql-string.js";
|
|
40
|
+
/**
|
|
41
|
+
* Build a valid aggregation query, overridden by the given fields
|
|
42
|
+
* @param over - fields to override
|
|
43
|
+
* @returns the query
|
|
44
|
+
*/
|
|
45
|
+
function q(over = {}) {
|
|
46
|
+
return {
|
|
47
|
+
filter: new AndExpression([]),
|
|
48
|
+
groupBy: ["status"],
|
|
49
|
+
metrics: { n: { fn: "COUNT" } },
|
|
50
|
+
...over
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
let ValidateAggregationTest = (() => {
|
|
54
|
+
let _classDecorators = [suite];
|
|
55
|
+
let _classDescriptor;
|
|
56
|
+
let _classExtraInitializers = [];
|
|
57
|
+
let _classThis;
|
|
58
|
+
let _instanceExtraInitializers = [];
|
|
59
|
+
let _valid_decorators;
|
|
60
|
+
let _rejects_decorators;
|
|
61
|
+
let _digitsInsideSegments_decorators;
|
|
62
|
+
let _missingGroupBy_decorators;
|
|
63
|
+
let _errorCode_decorators;
|
|
64
|
+
var ValidateAggregationTest = class {
|
|
65
|
+
static { _classThis = this; }
|
|
66
|
+
static {
|
|
67
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
68
|
+
_valid_decorators = [test];
|
|
69
|
+
_rejects_decorators = [test];
|
|
70
|
+
_digitsInsideSegments_decorators = [test];
|
|
71
|
+
_missingGroupBy_decorators = [test];
|
|
72
|
+
_errorCode_decorators = [test];
|
|
73
|
+
__esDecorate(this, null, _valid_decorators, { kind: "method", name: "valid", static: false, private: false, access: { has: obj => "valid" in obj, get: obj => obj.valid }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
74
|
+
__esDecorate(this, null, _rejects_decorators, { kind: "method", name: "rejects", static: false, private: false, access: { has: obj => "rejects" in obj, get: obj => obj.rejects }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
75
|
+
__esDecorate(this, null, _digitsInsideSegments_decorators, { kind: "method", name: "digitsInsideSegments", static: false, private: false, access: { has: obj => "digitsInsideSegments" in obj, get: obj => obj.digitsInsideSegments }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
76
|
+
__esDecorate(this, null, _missingGroupBy_decorators, { kind: "method", name: "missingGroupBy", static: false, private: false, access: { has: obj => "missingGroupBy" in obj, get: obj => obj.missingGroupBy }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
77
|
+
__esDecorate(this, null, _errorCode_decorators, { kind: "method", name: "errorCode", static: false, private: false, access: { has: obj => "errorCode" in obj, get: obj => obj.errorCode }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
78
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
79
|
+
ValidateAggregationTest = _classThis = _classDescriptor.value;
|
|
80
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
81
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
82
|
+
}
|
|
83
|
+
valid() {
|
|
84
|
+
const query = q({
|
|
85
|
+
groupBy: ["status", "owner.uuid"],
|
|
86
|
+
metrics: { n: { fn: "COUNT" }, total: { fn: "SUM", field: "points" }, d: { fn: "COUNT_DISTINCT", field: "tag" } },
|
|
87
|
+
orderBy: [
|
|
88
|
+
{ key: "n", direction: "DESC" },
|
|
89
|
+
{ key: "owner.uuid", direction: "ASC" }
|
|
90
|
+
],
|
|
91
|
+
limit: 10
|
|
92
|
+
});
|
|
93
|
+
assert.strictEqual(validateAggregation(query), query);
|
|
94
|
+
}
|
|
95
|
+
rejects() {
|
|
96
|
+
const bad = [
|
|
97
|
+
["no metric", { metrics: {} }],
|
|
98
|
+
["bad path", { groupBy: ["a b"] }],
|
|
99
|
+
["proto path", { groupBy: ["__proto__.x"] }],
|
|
100
|
+
["constructor path", { groupBy: ["a.constructor"] }],
|
|
101
|
+
["duplicate group", { groupBy: ["a", "a"] }],
|
|
102
|
+
["bad alias", { metrics: { "1n": { fn: "COUNT" } } }],
|
|
103
|
+
["underscore alias", { metrics: { _id: { fn: "COUNT" } } }],
|
|
104
|
+
["reserved alias", { metrics: { constructor: { fn: "COUNT" } } }],
|
|
105
|
+
["alias clash", { metrics: { status: { fn: "COUNT" } } }],
|
|
106
|
+
["unknown fn", { metrics: { n: { fn: "MEDIAN", field: "a" } } }],
|
|
107
|
+
["missing field", { metrics: { n: { fn: "SUM" } } }],
|
|
108
|
+
["bad field", { metrics: { n: { fn: "SUM", field: "a;drop" } } }],
|
|
109
|
+
["unknown order key", { orderBy: [{ key: "nope", direction: "ASC" }] }],
|
|
110
|
+
["bad direction", { orderBy: [{ key: "n", direction: "UP" }] }],
|
|
111
|
+
["zero limit", { limit: 0 }],
|
|
112
|
+
["float limit", { limit: 1.5 }],
|
|
113
|
+
["digit group segment", { groupBy: ["tags.0"] }],
|
|
114
|
+
["digit field segment", { metrics: { n: { fn: "MAX", field: "items.12.price" } } }]
|
|
115
|
+
];
|
|
116
|
+
for (const [name, over] of bad) {
|
|
117
|
+
assert.throws(() => validateAggregation(q(over)), WebdaQLError, name);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
digitsInsideSegments() {
|
|
121
|
+
// Only all-digit segments are rejected: MongoDB `$a.0` does not index arrays
|
|
122
|
+
validateAggregation(q({ groupBy: ["a1", "b.c2d"] }));
|
|
123
|
+
}
|
|
124
|
+
missingGroupBy() {
|
|
125
|
+
const query = { filter: new AndExpression([]), metrics: { n: { fn: "COUNT" } } };
|
|
126
|
+
validateAggregation(query);
|
|
127
|
+
assert.deepStrictEqual(query.groupBy, [], "a missing groupBy is normalized to []");
|
|
128
|
+
const agg = new Aggregator({ filter: new AndExpression([]), metrics: { n: { fn: "COUNT" } } });
|
|
129
|
+
agg.add({});
|
|
130
|
+
assert.deepStrictEqual(agg.rows(), [{ n: 1 }]);
|
|
131
|
+
}
|
|
132
|
+
errorCode() {
|
|
133
|
+
const err = new AggregationError("AGGREGATION_NOT_NATIVE", "nope");
|
|
134
|
+
assert.ok(err instanceof WebdaQLError);
|
|
135
|
+
assert.strictEqual(err.code, "AGGREGATION_NOT_NATIVE");
|
|
136
|
+
assert.strictEqual(err.name, "AggregationError");
|
|
137
|
+
}
|
|
138
|
+
constructor() {
|
|
139
|
+
__runInitializers(this, _instanceExtraInitializers);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
return ValidateAggregationTest = _classThis;
|
|
143
|
+
})();
|
|
144
|
+
/**
|
|
145
|
+
* Run an aggregation over items
|
|
146
|
+
* @param over - query overrides
|
|
147
|
+
* @param items - items, already filtered
|
|
148
|
+
* @returns the rows
|
|
149
|
+
*/
|
|
150
|
+
function run(over, items) {
|
|
151
|
+
const agg = new Aggregator(q(over));
|
|
152
|
+
items.forEach(item => agg.add(item));
|
|
153
|
+
return agg.rows();
|
|
154
|
+
}
|
|
155
|
+
const ITEMS = [
|
|
156
|
+
{ status: "open", points: 3, tag: "a", owner: { uuid: "u1" }, label: "delta" },
|
|
157
|
+
{ status: "open", points: "8", tag: "a", owner: { uuid: "u2" }, label: "alpha" },
|
|
158
|
+
{ status: "done", points: null, tag: "b", label: "charlie" },
|
|
159
|
+
{ status: null, points: 5, tag: null, owner: { uuid: "u1" } },
|
|
160
|
+
{ points: 2, tag: "c" }
|
|
161
|
+
];
|
|
162
|
+
let AggregatorTest = (() => {
|
|
163
|
+
let _classDecorators = [suite];
|
|
164
|
+
let _classDescriptor;
|
|
165
|
+
let _classExtraInitializers = [];
|
|
166
|
+
let _classThis;
|
|
167
|
+
let _instanceExtraInitializers = [];
|
|
168
|
+
let _compare_decorators;
|
|
169
|
+
let _groupedCounts_decorators;
|
|
170
|
+
let _metricSemantics_decorators;
|
|
171
|
+
let _emptyGroups_decorators;
|
|
172
|
+
let _nestedGroupAndOrderLimit_decorators;
|
|
173
|
+
let _dates_decorators;
|
|
174
|
+
let _maxGroups_decorators;
|
|
175
|
+
var AggregatorTest = class {
|
|
176
|
+
static { _classThis = this; }
|
|
177
|
+
static {
|
|
178
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
179
|
+
_compare_decorators = [test];
|
|
180
|
+
_groupedCounts_decorators = [test];
|
|
181
|
+
_metricSemantics_decorators = [test];
|
|
182
|
+
_emptyGroups_decorators = [test];
|
|
183
|
+
_nestedGroupAndOrderLimit_decorators = [test];
|
|
184
|
+
_dates_decorators = [test];
|
|
185
|
+
_maxGroups_decorators = [test];
|
|
186
|
+
__esDecorate(this, null, _compare_decorators, { kind: "method", name: "compare", static: false, private: false, access: { has: obj => "compare" in obj, get: obj => obj.compare }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
187
|
+
__esDecorate(this, null, _groupedCounts_decorators, { kind: "method", name: "groupedCounts", static: false, private: false, access: { has: obj => "groupedCounts" in obj, get: obj => obj.groupedCounts }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
188
|
+
__esDecorate(this, null, _metricSemantics_decorators, { kind: "method", name: "metricSemantics", static: false, private: false, access: { has: obj => "metricSemantics" in obj, get: obj => obj.metricSemantics }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
189
|
+
__esDecorate(this, null, _emptyGroups_decorators, { kind: "method", name: "emptyGroups", static: false, private: false, access: { has: obj => "emptyGroups" in obj, get: obj => obj.emptyGroups }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
190
|
+
__esDecorate(this, null, _nestedGroupAndOrderLimit_decorators, { kind: "method", name: "nestedGroupAndOrderLimit", static: false, private: false, access: { has: obj => "nestedGroupAndOrderLimit" in obj, get: obj => obj.nestedGroupAndOrderLimit }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
191
|
+
__esDecorate(this, null, _dates_decorators, { kind: "method", name: "dates", static: false, private: false, access: { has: obj => "dates" in obj, get: obj => obj.dates }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
192
|
+
__esDecorate(this, null, _maxGroups_decorators, { kind: "method", name: "maxGroups", static: false, private: false, access: { has: obj => "maxGroups" in obj, get: obj => obj.maxGroups }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
193
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
194
|
+
AggregatorTest = _classThis = _classDescriptor.value;
|
|
195
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
196
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
197
|
+
}
|
|
198
|
+
compare() {
|
|
199
|
+
assert.ok(compareValues(null, 0) < 0, "null first");
|
|
200
|
+
assert.ok(compareValues(undefined, "a") < 0, "undefined is null");
|
|
201
|
+
assert.strictEqual(compareValues(null, undefined), 0);
|
|
202
|
+
assert.ok(compareValues(2, 10) < 0, "numeric, not lexical");
|
|
203
|
+
assert.ok(compareValues("B", "a") < 0, "code unit order");
|
|
204
|
+
assert.ok(compareValues(false, true) < 0);
|
|
205
|
+
assert.ok(compareValues(1, "1") < 0, "numbers before strings");
|
|
206
|
+
assert.ok(compareValues("2026-01-02", "2026-01-10") < 0, "ISO dates as strings");
|
|
207
|
+
}
|
|
208
|
+
groupedCounts() {
|
|
209
|
+
assert.deepStrictEqual(run({ metrics: { n: { fn: "COUNT" } }, orderBy: [{ key: "status", direction: "ASC" }] }, ITEMS), [
|
|
210
|
+
{ status: null, n: 2 },
|
|
211
|
+
{ status: "done", n: 1 },
|
|
212
|
+
{ status: "open", n: 2 }
|
|
213
|
+
], "missing and null keys share one group, sorted first");
|
|
214
|
+
}
|
|
215
|
+
metricSemantics() {
|
|
216
|
+
assert.deepStrictEqual(run({
|
|
217
|
+
groupBy: [],
|
|
218
|
+
metrics: {
|
|
219
|
+
all: { fn: "COUNT" },
|
|
220
|
+
withTag: { fn: "COUNT", field: "tag" },
|
|
221
|
+
tags: { fn: "COUNT_DISTINCT", field: "tag" },
|
|
222
|
+
total: { fn: "SUM", field: "points" },
|
|
223
|
+
mean: { fn: "AVG", field: "points" },
|
|
224
|
+
lo: { fn: "MIN", field: "label" },
|
|
225
|
+
hi: { fn: "MAX", field: "points" }
|
|
226
|
+
}
|
|
227
|
+
}, ITEMS), [{ all: 5, withTag: 4, tags: 3, total: 10, mean: 10 / 3, lo: "alpha", hi: "8" }]);
|
|
228
|
+
}
|
|
229
|
+
emptyGroups() {
|
|
230
|
+
assert.deepStrictEqual(run({
|
|
231
|
+
groupBy: [],
|
|
232
|
+
metrics: {
|
|
233
|
+
n: { fn: "COUNT" },
|
|
234
|
+
total: { fn: "SUM", field: "points" },
|
|
235
|
+
mean: { fn: "AVG", field: "points" },
|
|
236
|
+
lo: { fn: "MIN", field: "points" },
|
|
237
|
+
d: { fn: "COUNT_DISTINCT", field: "tag" }
|
|
238
|
+
}
|
|
239
|
+
}, []), [{ n: 0, total: 0, mean: null, lo: null, d: 0 }], "a global aggregation always returns one row");
|
|
240
|
+
assert.deepStrictEqual(run({}, []), [], "a grouped aggregation over nothing has no row");
|
|
241
|
+
assert.deepStrictEqual(run({ groupBy: ["status"], metrics: { total: { fn: "SUM", field: "points" } } }, [{ status: "x", points: "1" }]), [{ status: "x", total: 0 }], "non-numeric values are ignored by SUM");
|
|
242
|
+
}
|
|
243
|
+
nestedGroupAndOrderLimit() {
|
|
244
|
+
assert.deepStrictEqual(run({
|
|
245
|
+
groupBy: ["owner.uuid"],
|
|
246
|
+
metrics: { n: { fn: "COUNT" } },
|
|
247
|
+
orderBy: [
|
|
248
|
+
{ key: "n", direction: "DESC" },
|
|
249
|
+
{ key: "owner.uuid", direction: "DESC" }
|
|
250
|
+
],
|
|
251
|
+
limit: 2
|
|
252
|
+
}, ITEMS), [
|
|
253
|
+
{ "owner.uuid": "u1", n: 2 },
|
|
254
|
+
{ "owner.uuid": null, n: 2 }
|
|
255
|
+
], "null sorts last in DESC");
|
|
256
|
+
}
|
|
257
|
+
dates() {
|
|
258
|
+
const items = [
|
|
259
|
+
{ day: new Date("2026-01-05T10:00:00.000Z"), at: new Date("2026-01-05T10:00:00.000Z") },
|
|
260
|
+
{ day: "2026-01-05T10:00:00.000Z", at: new Date("2025-12-31T23:59:59.000Z") },
|
|
261
|
+
{ day: new Date("2026-03-01T00:00:00.000Z"), at: "2026-03-01T00:00:00.000Z" }
|
|
262
|
+
];
|
|
263
|
+
// Group keys: a Date and its ISO string are one group, returned as the ISO string
|
|
264
|
+
assert.deepStrictEqual(run({
|
|
265
|
+
groupBy: ["day"],
|
|
266
|
+
metrics: { n: { fn: "COUNT" } },
|
|
267
|
+
orderBy: [{ key: "day", direction: "ASC" }]
|
|
268
|
+
}, items), [
|
|
269
|
+
{ day: "2026-01-05T10:00:00.000Z", n: 2 },
|
|
270
|
+
{ day: "2026-03-01T00:00:00.000Z", n: 1 }
|
|
271
|
+
]);
|
|
272
|
+
// MIN / MAX return ISO strings; COUNT_DISTINCT treats a Date and its ISO string alike
|
|
273
|
+
assert.deepStrictEqual(run({
|
|
274
|
+
groupBy: [],
|
|
275
|
+
metrics: {
|
|
276
|
+
lo: { fn: "MIN", field: "at" },
|
|
277
|
+
hi: { fn: "MAX", field: "at" },
|
|
278
|
+
days: { fn: "COUNT_DISTINCT", field: "day" }
|
|
279
|
+
}
|
|
280
|
+
}, items), [{ lo: "2025-12-31T23:59:59.000Z", hi: "2026-03-01T00:00:00.000Z", days: 2 }]);
|
|
281
|
+
}
|
|
282
|
+
maxGroups() {
|
|
283
|
+
const agg = new Aggregator(q({ groupBy: ["tag"] }), 2);
|
|
284
|
+
agg.add({ tag: "a" });
|
|
285
|
+
agg.add({ tag: "b" });
|
|
286
|
+
agg.add({ tag: "a" });
|
|
287
|
+
assert.throws(() => agg.add({ tag: "c" }), (err) => err.code === "AGGREGATION_TOO_MANY_GROUPS");
|
|
288
|
+
}
|
|
289
|
+
constructor() {
|
|
290
|
+
__runInitializers(this, _instanceExtraInitializers);
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
return AggregatorTest = _classThis;
|
|
294
|
+
})();
|
|
295
|
+
let ToAggregationQueryTest = (() => {
|
|
296
|
+
let _classDecorators = [suite];
|
|
297
|
+
let _classDescriptor;
|
|
298
|
+
let _classExtraInitializers = [];
|
|
299
|
+
let _classThis;
|
|
300
|
+
let _instanceExtraInitializers = [];
|
|
301
|
+
let _converts_decorators;
|
|
302
|
+
let _defaults_decorators;
|
|
303
|
+
let _rejects_decorators;
|
|
304
|
+
var ToAggregationQueryTest = class {
|
|
305
|
+
static { _classThis = this; }
|
|
306
|
+
static {
|
|
307
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
308
|
+
_converts_decorators = [test];
|
|
309
|
+
_defaults_decorators = [test];
|
|
310
|
+
_rejects_decorators = [test];
|
|
311
|
+
__esDecorate(this, null, _converts_decorators, { kind: "method", name: "converts", static: false, private: false, access: { has: obj => "converts" in obj, get: obj => obj.converts }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
312
|
+
__esDecorate(this, null, _defaults_decorators, { kind: "method", name: "defaults", static: false, private: false, access: { has: obj => "defaults" in obj, get: obj => obj.defaults }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
313
|
+
__esDecorate(this, null, _rejects_decorators, { kind: "method", name: "rejects", static: false, private: false, access: { has: obj => "rejects" in obj, get: obj => obj.rejects }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
314
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
315
|
+
ToAggregationQueryTest = _classThis = _classDescriptor.value;
|
|
316
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
317
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
318
|
+
}
|
|
319
|
+
converts() {
|
|
320
|
+
const query = toAggregationQuery({
|
|
321
|
+
filter: "status = :status AND points > :min",
|
|
322
|
+
groupBy: ["owner.uuid"],
|
|
323
|
+
metrics: { n: { count: "*" }, withTag: { count: "tag" }, d: { countDistinct: "tag" }, s: { sum: "points" } },
|
|
324
|
+
orderBy: [{ key: "n", direction: "DESC" }],
|
|
325
|
+
limit: 5
|
|
326
|
+
}, { status: "open", min: 1 });
|
|
327
|
+
assert.strictEqual(query.filter.toString(), 'status = "open" AND points > 1');
|
|
328
|
+
assert.deepStrictEqual(query.groupBy, ["owner.uuid"]);
|
|
329
|
+
assert.deepStrictEqual(query.metrics, {
|
|
330
|
+
n: { fn: "COUNT" },
|
|
331
|
+
withTag: { fn: "COUNT", field: "tag" },
|
|
332
|
+
d: { fn: "COUNT_DISTINCT", field: "tag" },
|
|
333
|
+
s: { fn: "SUM", field: "points" }
|
|
334
|
+
});
|
|
335
|
+
assert.deepStrictEqual(query.orderBy, [{ key: "n", direction: "DESC" }]);
|
|
336
|
+
assert.strictEqual(query.limit, 5);
|
|
337
|
+
}
|
|
338
|
+
defaults() {
|
|
339
|
+
const query = toAggregationQuery({ metrics: { n: { count: "*" } } });
|
|
340
|
+
assert.strictEqual(query.filter.toString(), "");
|
|
341
|
+
assert.deepStrictEqual(query.groupBy, []);
|
|
342
|
+
}
|
|
343
|
+
rejects() {
|
|
344
|
+
assert.throws(() => toAggregationQuery({ filter: "a = 1 LIMIT 3", metrics: { n: { count: "*" } } }), WebdaQLError);
|
|
345
|
+
assert.throws(() => toAggregationQuery({ filter: "a = 1 ORDER BY a", metrics: { n: { count: "*" } } }), WebdaQLError);
|
|
346
|
+
assert.throws(() => toAggregationQuery({ filter: "a = 1 OFFSET 'x'", metrics: { n: { count: "*" } } }), WebdaQLError);
|
|
347
|
+
assert.throws(() => toAggregationQuery({ filter: "DELETE WHERE a = 1", metrics: { n: { count: "*" } } }), WebdaQLError);
|
|
348
|
+
assert.throws(() => toAggregationQuery({ filter: "SELECT a WHERE a = 1", metrics: { n: { count: "*" } } }), WebdaQLError);
|
|
349
|
+
assert.throws(() => toAggregationQuery({ metrics: { n: { count: "*", sum: "a" } } }), WebdaQLError);
|
|
350
|
+
assert.throws(() => toAggregationQuery({ metrics: { n: { toString: "a" } } }), WebdaQLError);
|
|
351
|
+
assert.throws(() => toAggregationQuery({ metrics: { n: { sum: "*" } } }), WebdaQLError, "* only for count");
|
|
352
|
+
assert.throws(() => toAggregationQuery({ metrics: JSON.parse('{"__proto__": {"count": "*"}}') }), /Invalid metric alias/, "reserved alias is rejected, not dropped");
|
|
353
|
+
}
|
|
354
|
+
constructor() {
|
|
355
|
+
__runInitializers(this, _instanceExtraInitializers);
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
return ToAggregationQueryTest = _classThis;
|
|
359
|
+
})();
|
|
360
|
+
//# sourceMappingURL=aggregation.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregation.spec.js","sourceRoot":"","sources":["../src/aggregation.spec.ts"],"names":[],"mappings":"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"}
|