@hypequery/datasets 0.23.1 → 0.25.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 +14 -0
- package/dist/aggregations.d.ts +3 -0
- package/dist/aggregations.d.ts.map +1 -1
- package/dist/aggregations.js +6 -0
- package/dist/cache/definition-identity.d.ts +9 -6
- package/dist/cache/definition-identity.d.ts.map +1 -1
- package/dist/cache/definition-identity.js +14 -8
- package/dist/cache/protocol-cache-keys.d.ts.map +1 -1
- package/dist/cache/protocol-cache-keys.js +29 -6
- package/dist/cache/query-signature.d.ts.map +1 -1
- package/dist/cache/query-signature.js +12 -1
- package/dist/catalog.d.ts +7 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +5 -2
- package/dist/client-contract/query-schema.d.ts +19 -0
- package/dist/client-contract/query-schema.d.ts.map +1 -0
- package/dist/client-contract/query-schema.js +85 -0
- package/dist/constants.d.ts +5 -4
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +7 -6
- package/dist/contract.d.ts +5 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +6 -3
- package/dist/dataset-compilation.d.ts +2 -0
- package/dist/dataset-compilation.d.ts.map +1 -1
- package/dist/dataset-sql-dialect.d.ts +119 -0
- package/dist/dataset-sql-dialect.d.ts.map +1 -1
- package/dist/dataset.d.ts +4 -2
- package/dist/dataset.d.ts.map +1 -1
- package/dist/dataset.js +23 -31
- package/dist/in-memory-backend.d.ts.map +1 -1
- package/dist/in-memory-backend.js +2 -0
- package/dist/index.d.ts +49 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -6
- package/dist/internal.d.ts +5 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +5 -1
- package/dist/measure.d.ts +9 -1
- package/dist/measure.d.ts.map +1 -1
- package/dist/measure.js +9 -1
- package/dist/metric-query-engine.d.ts +0 -1
- package/dist/metric-query-engine.d.ts.map +1 -1
- package/dist/metric-query-engine.js +11 -3
- package/dist/protocol-adapter.d.ts.map +1 -1
- package/dist/protocol-adapter.js +2 -3
- package/dist/protocol-deployment-adapter.d.ts.map +1 -1
- package/dist/protocol-deployment-adapter.js +7 -1
- package/dist/protocol-rehydrate.d.ts.map +1 -1
- package/dist/protocol-rehydrate.js +1 -0
- package/dist/protocol-schema-adapter.d.ts +7 -7
- package/dist/protocol-schema-adapter.d.ts.map +1 -1
- package/dist/protocol-schema-adapter.js +12 -245
- package/dist/query-builder-protocol.d.ts +34 -1
- package/dist/query-builder-protocol.d.ts.map +1 -1
- package/dist/query-planner.d.ts +14 -5
- package/dist/query-planner.d.ts.map +1 -1
- package/dist/query-planner.js +53 -34
- package/dist/relationship-check.d.ts.map +1 -1
- package/dist/relationship-check.js +8 -8
- package/dist/schemas.d.ts +17 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +16 -0
- package/dist/semantic-planner.d.ts.map +1 -1
- package/dist/semantic-planner.js +49 -13
- package/dist/semantic-query-schema.d.ts +8 -1
- package/dist/semantic-query-schema.d.ts.map +1 -1
- package/dist/semantic-query-schema.js +18 -12
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +4 -3
- package/dist/types.d.ts +105 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/aggregate-state-functions.d.ts +24 -0
- package/dist/utils/aggregate-state-functions.d.ts.map +1 -0
- package/dist/utils/aggregate-state-functions.js +60 -0
- package/dist/utils/approximate-measures.d.ts +3 -1
- package/dist/utils/approximate-measures.d.ts.map +1 -1
- package/dist/utils/approximate-measures.js +8 -2
- package/dist/utils/base-measure-definition.d.ts +16 -0
- package/dist/utils/base-measure-definition.d.ts.map +1 -1
- package/dist/utils/base-measure-definition.js +31 -0
- package/dist/utils/build-dataset-query-builder.d.ts +1 -1
- package/dist/utils/build-dataset-query-builder.d.ts.map +1 -1
- package/dist/utils/build-dataset-query-builder.js +26 -21
- package/dist/utils/by-name.d.ts +8 -0
- package/dist/utils/by-name.d.ts.map +1 -0
- package/dist/utils/by-name.js +44 -0
- package/dist/utils/calendar-shift-sql.d.ts +5 -4
- package/dist/utils/calendar-shift-sql.d.ts.map +1 -1
- package/dist/utils/calendar-shift-sql.js +8 -8
- package/dist/utils/clickhouse-dataset-sql-dialect.d.ts +2 -2
- package/dist/utils/clickhouse-dataset-sql-dialect.d.ts.map +1 -1
- package/dist/utils/clickhouse-dataset-sql-dialect.js +143 -1
- package/dist/utils/compile-dataset-query.d.ts +1 -1
- package/dist/utils/compile-dataset-query.d.ts.map +1 -1
- package/dist/utils/compile-dataset-query.js +22 -8
- package/dist/utils/composite-time-measure-sql.d.ts +3 -5
- package/dist/utils/composite-time-measure-sql.d.ts.map +1 -1
- package/dist/utils/composite-time-measure-sql.js +15 -16
- package/dist/utils/count-aggregations.d.ts +4 -0
- package/dist/utils/count-aggregations.d.ts.map +1 -0
- package/dist/utils/count-aggregations.js +6 -0
- package/dist/utils/dataset-definition-validation.d.ts +1 -1
- package/dist/utils/dataset-definition-validation.d.ts.map +1 -1
- package/dist/utils/dataset-definition-validation.js +55 -26
- package/dist/utils/dataset-derived-query.d.ts +2 -4
- package/dist/utils/dataset-derived-query.d.ts.map +1 -1
- package/dist/utils/dataset-derived-query.js +11 -14
- package/dist/utils/dataset-having.d.ts +5 -7
- package/dist/utils/dataset-having.d.ts.map +1 -1
- package/dist/utils/dataset-having.js +9 -12
- package/dist/utils/dataset-normalization.d.ts.map +1 -1
- package/dist/utils/dataset-normalization.js +1 -0
- package/dist/utils/dataset-query-validation.d.ts +1 -1
- package/dist/utils/dataset-query-validation.d.ts.map +1 -1
- package/dist/utils/dataset-query-validation.js +19 -2
- package/dist/utils/dataset-source.d.ts +42 -0
- package/dist/utils/dataset-source.d.ts.map +1 -0
- package/dist/utils/dataset-source.js +59 -0
- package/dist/utils/dataset-sql-dialect.d.ts +13 -2
- package/dist/utils/dataset-sql-dialect.d.ts.map +1 -1
- package/dist/utils/dataset-sql-dialect.js +74 -1
- package/dist/utils/dataset-time-keys.d.ts +32 -0
- package/dist/utils/dataset-time-keys.d.ts.map +1 -0
- package/dist/utils/dataset-time-keys.js +55 -0
- package/dist/utils/dataset-validation.d.ts.map +1 -1
- package/dist/utils/dataset-validation.js +7 -0
- package/dist/utils/deployable-formulas.d.ts +33 -0
- package/dist/utils/deployable-formulas.d.ts.map +1 -0
- package/dist/utils/deployable-formulas.js +102 -0
- package/dist/utils/derived-cte-validation.d.ts +5 -0
- package/dist/utils/derived-cte-validation.d.ts.map +1 -1
- package/dist/utils/derived-cte-validation.js +77 -8
- package/dist/utils/derived-measure-sql.d.ts +10 -2
- package/dist/utils/derived-measure-sql.d.ts.map +1 -1
- package/dist/utils/derived-measure-sql.js +23 -43
- package/dist/utils/enforced-constraints.d.ts +14 -0
- package/dist/utils/enforced-constraints.d.ts.map +1 -0
- package/dist/utils/enforced-constraints.js +57 -0
- package/dist/utils/filter-field-type.d.ts +14 -0
- package/dist/utils/filter-field-type.d.ts.map +1 -0
- package/dist/utils/filter-field-type.js +21 -0
- package/dist/utils/filtered-aggregation-sql.d.ts +2 -1
- package/dist/utils/filtered-aggregation-sql.d.ts.map +1 -1
- package/dist/utils/filtered-aggregation-sql.js +18 -35
- package/dist/utils/groupable.d.ts +7 -0
- package/dist/utils/groupable.d.ts.map +1 -0
- package/dist/utils/groupable.js +8 -0
- package/dist/utils/metric-derived-query.d.ts +2 -4
- package/dist/utils/metric-derived-query.d.ts.map +1 -1
- package/dist/utils/metric-derived-query.js +58 -51
- package/dist/utils/metric-query-builder.d.ts +1 -1
- package/dist/utils/metric-query-builder.d.ts.map +1 -1
- package/dist/utils/metric-query-builder.js +22 -20
- package/dist/utils/metric-query-validation.d.ts.map +1 -1
- package/dist/utils/metric-query-validation.js +14 -1
- package/dist/utils/portable-aggregations.d.ts +1 -0
- package/dist/utils/portable-aggregations.d.ts.map +1 -1
- package/dist/utils/portable-aggregations.js +5 -0
- package/dist/utils/protocol-schema-conversion.d.ts +12 -0
- package/dist/utils/protocol-schema-conversion.d.ts.map +1 -0
- package/dist/utils/protocol-schema-conversion.js +61 -0
- package/dist/utils/query-field-references.d.ts +10 -0
- package/dist/utils/query-field-references.d.ts.map +1 -0
- package/dist/utils/query-field-references.js +38 -0
- package/dist/utils/query-timezone.d.ts +41 -3
- package/dist/utils/query-timezone.d.ts.map +1 -1
- package/dist/utils/query-timezone.js +76 -9
- package/dist/utils/raw-sql-dialect-check.d.ts +12 -0
- package/dist/utils/raw-sql-dialect-check.d.ts.map +1 -0
- package/dist/utils/raw-sql-dialect-check.js +37 -0
- package/dist/utils/relationship-builder-plan.d.ts +37 -18
- package/dist/utils/relationship-builder-plan.d.ts.map +1 -1
- package/dist/utils/relationship-builder-plan.js +43 -28
- package/dist/utils/relationship-measure-sql.d.ts +14 -4
- package/dist/utils/relationship-measure-sql.d.ts.map +1 -1
- package/dist/utils/relationship-measure-sql.js +36 -10
- package/dist/utils/relationship-measures.d.ts.map +1 -1
- package/dist/utils/relationship-measures.js +3 -0
- package/dist/utils/relationship-validation.d.ts.map +1 -1
- package/dist/utils/relationship-validation.js +2 -0
- package/dist/utils/row-scope.d.ts +23 -0
- package/dist/utils/row-scope.d.ts.map +1 -0
- package/dist/utils/row-scope.js +26 -0
- package/dist/utils/scoped-dataset-source.d.ts +23 -0
- package/dist/utils/scoped-dataset-source.d.ts.map +1 -0
- package/dist/utils/scoped-dataset-source.js +34 -0
- package/dist/utils/semantic-tool.d.ts +2 -2
- package/dist/utils/semantic-tool.d.ts.map +1 -1
- package/dist/utils/semantic-tool.js +1 -1
- package/dist/utils/shift-measure-sql.d.ts +5 -4
- package/dist/utils/shift-measure-sql.d.ts.map +1 -1
- package/dist/utils/shift-measure-sql.js +25 -26
- package/dist/utils/shift-wall-time-sql.d.ts +2 -1
- package/dist/utils/shift-wall-time-sql.d.ts.map +1 -1
- package/dist/utils/shift-wall-time-sql.js +7 -7
- package/dist/utils/snapshot-execution-context.d.ts.map +1 -1
- package/dist/utils/snapshot-execution-context.js +3 -0
- package/dist/utils/statement-parameters.d.ts +58 -0
- package/dist/utils/statement-parameters.d.ts.map +1 -0
- package/dist/utils/statement-parameters.js +101 -0
- package/dist/utils/time-axis-calendar-guard.d.ts +2 -1
- package/dist/utils/time-axis-calendar-guard.d.ts.map +1 -1
- package/dist/utils/time-axis-calendar-guard.js +5 -7
- package/dist/utils/time-measure-axis-sql.d.ts +3 -2
- package/dist/utils/time-measure-axis-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-axis-sql.js +20 -22
- package/dist/utils/time-measure-context-sql.d.ts +3 -2
- package/dist/utils/time-measure-context-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-context-sql.js +11 -11
- package/dist/utils/time-measure-dataset-sql.d.ts +7 -5
- package/dist/utils/time-measure-dataset-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-dataset-sql.js +17 -12
- package/dist/utils/time-measure-leaf-sql.d.ts +3 -2
- package/dist/utils/time-measure-leaf-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-leaf-sql.js +19 -18
- package/dist/utils/time-measure-result-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-result-sql.js +10 -11
- package/dist/utils/time-measure-source-sql.d.ts +5 -2
- package/dist/utils/time-measure-source-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-source-sql.js +33 -23
- package/dist/utils/time-measure-values-sql.d.ts +4 -3
- package/dist/utils/time-measure-values-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-values-sql.js +26 -29
- package/dist/utils/timestamp-instants.d.ts +17 -0
- package/dist/utils/timestamp-instants.d.ts.map +1 -0
- package/dist/utils/timestamp-instants.js +34 -0
- package/dist/utils/timestamp-text.d.ts +12 -0
- package/dist/utils/timestamp-text.d.ts.map +1 -0
- package/dist/utils/timestamp-text.js +18 -0
- package/dist/utils/zod-json-schema.d.ts +8 -0
- package/dist/utils/zod-json-schema.d.ts.map +1 -0
- package/dist/utils/zod-json-schema.js +18 -0
- package/dist/utils/zod-schema-version.d.ts +19 -0
- package/dist/utils/zod-schema-version.d.ts.map +1 -0
- package/dist/utils/zod-schema-version.js +6 -0
- package/dist/utils/zod-v3-protocol-schema.d.ts +10 -0
- package/dist/utils/zod-v3-protocol-schema.d.ts.map +1 -0
- package/dist/utils/zod-v3-protocol-schema.js +164 -0
- package/dist/utils/zod-v4-protocol-schema.d.ts +12 -0
- package/dist/utils/zod-v4-protocol-schema.d.ts.map +1 -0
- package/dist/utils/zod-v4-protocol-schema.js +171 -0
- package/dist/validation.d.ts +7 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +42 -8
- package/package.json +21 -12
- package/dist/api.type-test.d.ts +0 -2
- package/dist/api.type-test.d.ts.map +0 -1
- package/dist/api.type-test.js +0 -251
- package/dist/utils/time-arithmetic-sql.d.ts +0 -4
- package/dist/utils/time-arithmetic-sql.d.ts.map +0 -1
- package/dist/utils/time-arithmetic-sql.js +0 -9
- package/dist/utils/window-aggregation-sql.d.ts +0 -5
- package/dist/utils/window-aggregation-sql.d.ts.map +0 -1
- package/dist/utils/window-aggregation-sql.js +0 -17
package/dist/validation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI1D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAgB9E;AAED,0FAA0F;AAC1F,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAG9E;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3D;AAgBD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CA6C7F"}
|
package/dist/validation.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared validation utilities for semantic layer queries.
|
|
3
3
|
*/
|
|
4
|
+
import { parseTimestampInstant } from './utils/timestamp-instants.js';
|
|
5
|
+
import { isTimestampText } from './utils/timestamp-text.js';
|
|
4
6
|
/**
|
|
5
7
|
* Checks if a value matches the expected field type.
|
|
6
8
|
*
|
|
@@ -11,16 +13,45 @@
|
|
|
11
13
|
export function matchesFieldType(fieldType, value) {
|
|
12
14
|
switch (fieldType) {
|
|
13
15
|
case 'string':
|
|
14
|
-
case 'timestamp':
|
|
15
16
|
return typeof value === 'string';
|
|
17
|
+
case 'timestamp':
|
|
18
|
+
return isTimestampText(value);
|
|
16
19
|
case 'number':
|
|
17
|
-
|
|
20
|
+
// Number filters bind as Float64; an integer beyond 2^53 is already rounded
|
|
21
|
+
// and would silently match nothing against an exact Int64/UInt64 column.
|
|
22
|
+
return typeof value === 'number' && Number.isFinite(value)
|
|
23
|
+
&& (!Number.isInteger(value) || Number.isSafeInteger(value));
|
|
18
24
|
case 'boolean':
|
|
19
25
|
return typeof value === 'boolean';
|
|
20
26
|
default:
|
|
21
27
|
return false;
|
|
22
28
|
}
|
|
23
29
|
}
|
|
30
|
+
/** True when a list holds both instants (`Z` or an offset) and offset-free timestamps. */
|
|
31
|
+
export function mixesInstantsAndLocalTimes(values) {
|
|
32
|
+
const instants = values.map(value => parseTimestampInstant(value) !== undefined);
|
|
33
|
+
return instants.some(Boolean) && !instants.every(Boolean);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* An `in` list is one predicate, so every member is read in the same zone:
|
|
37
|
+
* an instant and a local time cannot share one without changing a meaning.
|
|
38
|
+
*/
|
|
39
|
+
export function mixedInstantListError(field) {
|
|
40
|
+
return `"in" cannot mix instants (with Z or an offset) and local timestamps for field "${field}"; use one form.`;
|
|
41
|
+
}
|
|
42
|
+
function typeError(filter, fieldType, plural) {
|
|
43
|
+
if (fieldType === 'timestamp') {
|
|
44
|
+
const what = plural ? 'ISO 8601 timestamps' : 'an ISO 8601 timestamp';
|
|
45
|
+
return `"${filter.operator}" expects ${what} for field "${filter.field}", such as 2026-01-31 or 2026-01-31T12:00:00Z, with a real calendar date and time.`;
|
|
46
|
+
}
|
|
47
|
+
if (fieldType === 'number') {
|
|
48
|
+
const what = plural ? 'number values' : 'a number value';
|
|
49
|
+
return `"${filter.operator}" expects ${what} for field "${filter.field}"; integers must be safe integers (within ±2^53) to compare exactly. Declare a large id as dimension.string() to filter it exactly.`;
|
|
50
|
+
}
|
|
51
|
+
return plural
|
|
52
|
+
? `"${filter.operator}" expects ${fieldType} values for field "${filter.field}".`
|
|
53
|
+
: `"${filter.operator}" expects a ${fieldType} value for field "${filter.field}".`;
|
|
54
|
+
}
|
|
24
55
|
/**
|
|
25
56
|
* Validates a filter value against the expected field type.
|
|
26
57
|
*
|
|
@@ -34,7 +65,7 @@ export function validateFilterValue(filter, fieldType) {
|
|
|
34
65
|
case 'neq':
|
|
35
66
|
return matchesFieldType(fieldType, filter.value)
|
|
36
67
|
? null
|
|
37
|
-
:
|
|
68
|
+
: typeError(filter, fieldType, false);
|
|
38
69
|
case 'gt':
|
|
39
70
|
case 'gte':
|
|
40
71
|
case 'lt':
|
|
@@ -44,7 +75,7 @@ export function validateFilterValue(filter, fieldType) {
|
|
|
44
75
|
}
|
|
45
76
|
return matchesFieldType(fieldType, filter.value)
|
|
46
77
|
? null
|
|
47
|
-
:
|
|
78
|
+
: typeError(filter, fieldType, false);
|
|
48
79
|
case 'like':
|
|
49
80
|
if (fieldType !== 'string' && fieldType !== 'timestamp') {
|
|
50
81
|
return `"like" is only supported for string or timestamp field "${filter.field}".`;
|
|
@@ -57,16 +88,19 @@ export function validateFilterValue(filter, fieldType) {
|
|
|
57
88
|
if (!Array.isArray(filter.value) || filter.value.length === 0) {
|
|
58
89
|
return `"${filter.operator}" expects a non-empty array for field "${filter.field}".`;
|
|
59
90
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
91
|
+
if (!filter.value.every(value => matchesFieldType(fieldType, value))) {
|
|
92
|
+
return typeError(filter, fieldType, true);
|
|
93
|
+
}
|
|
94
|
+
return filter.operator === 'in' && fieldType === 'timestamp' && mixesInstantsAndLocalTimes(filter.value)
|
|
95
|
+
? mixedInstantListError(filter.field)
|
|
96
|
+
: null;
|
|
63
97
|
case 'between':
|
|
64
98
|
if (!Array.isArray(filter.value) || filter.value.length !== 2) {
|
|
65
99
|
return `"between" expects a two-item array for field "${filter.field}".`;
|
|
66
100
|
}
|
|
67
101
|
return filter.value.every(value => matchesFieldType(fieldType, value))
|
|
68
102
|
? null
|
|
69
|
-
:
|
|
103
|
+
: typeError(filter, fieldType, true);
|
|
70
104
|
default:
|
|
71
105
|
return `Unsupported semantic filter operator "${String(filter.operator)}".`;
|
|
72
106
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hypequery/datasets",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "Code-first TypeScript semantic layer for ClickHouse datasets, metrics, multi-tenancy, and AI agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"semantic-layer",
|
|
@@ -24,6 +24,11 @@
|
|
|
24
24
|
"import": "./dist/index.js",
|
|
25
25
|
"require": "./dist/index.js"
|
|
26
26
|
},
|
|
27
|
+
"./schemas": {
|
|
28
|
+
"types": "./dist/schemas.d.ts",
|
|
29
|
+
"import": "./dist/schemas.js",
|
|
30
|
+
"require": "./dist/schemas.js"
|
|
31
|
+
},
|
|
27
32
|
"./internal": {
|
|
28
33
|
"types": "./dist/internal.d.ts",
|
|
29
34
|
"import": "./dist/internal.js",
|
|
@@ -34,27 +39,31 @@
|
|
|
34
39
|
"*": {
|
|
35
40
|
"internal": [
|
|
36
41
|
"./dist/internal.d.ts"
|
|
42
|
+
],
|
|
43
|
+
"schemas": [
|
|
44
|
+
"./dist/schemas.d.ts"
|
|
37
45
|
]
|
|
38
46
|
}
|
|
39
47
|
},
|
|
40
48
|
"license": "Apache-2.0",
|
|
41
49
|
"files": [
|
|
42
|
-
"dist"
|
|
50
|
+
"dist",
|
|
51
|
+
"!dist/**/*.test.*",
|
|
52
|
+
"!dist/**/*.type-test.*",
|
|
53
|
+
"!dist/**/__tests__/**",
|
|
54
|
+
"!dist/**/tests/**",
|
|
55
|
+
"!dist/**/type-tests/**"
|
|
43
56
|
],
|
|
44
57
|
"dependencies": {
|
|
45
|
-
"@hypequery/protocol": "^0.
|
|
46
|
-
"@noble/hashes": "^
|
|
47
|
-
"zod": "^
|
|
58
|
+
"@hypequery/protocol": "^0.22.0",
|
|
59
|
+
"@noble/hashes": "^2.4.0",
|
|
60
|
+
"zod": "^4.6.6",
|
|
48
61
|
"zod-to-json-schema": "^3.25.2"
|
|
49
62
|
},
|
|
50
63
|
"peerDependencies": {
|
|
51
|
-
"zod": "^3.22.4",
|
|
52
64
|
"@hypequery/clickhouse": ">=2.13.0"
|
|
53
65
|
},
|
|
54
66
|
"peerDependenciesMeta": {
|
|
55
|
-
"zod": {
|
|
56
|
-
"optional": true
|
|
57
|
-
},
|
|
58
67
|
"@hypequery/clickhouse": {
|
|
59
68
|
"optional": true
|
|
60
69
|
}
|
|
@@ -62,9 +71,9 @@
|
|
|
62
71
|
"devDependencies": {
|
|
63
72
|
"@types/node": "^18.19.80",
|
|
64
73
|
"typescript": "^6.0.3",
|
|
65
|
-
"@vitest/coverage-v8": "^5.0.
|
|
66
|
-
"vitest": "^5.0.
|
|
67
|
-
"@hypequery/protocol-conformance": "^0.
|
|
74
|
+
"@vitest/coverage-v8": "^5.0.5",
|
|
75
|
+
"vitest": "^5.0.5",
|
|
76
|
+
"@hypequery/protocol-conformance": "^0.16.1"
|
|
68
77
|
},
|
|
69
78
|
"repository": {
|
|
70
79
|
"type": "git",
|
package/dist/api.type-test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"api.type-test.d.ts","sourceRoot":"","sources":["../src/api.type-test.ts"],"names":[],"mappings":""}
|
package/dist/api.type-test.js
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import { add, between, buildCanonicalSemanticQuerySchemas, buildProtocolDeploymentContract, createDatasetClient, dataset, desc, dimension, eq, measure, publishDatasets, publishToCloud, rehydrateProtocolDeploymentContract, } from './index.js';
|
|
2
|
-
const Orders = dataset('orders', {
|
|
3
|
-
source: 'orders',
|
|
4
|
-
tenantKey: 'tenant_id',
|
|
5
|
-
timeKey: 'created_at',
|
|
6
|
-
dimensions: {
|
|
7
|
-
id: dimension.string(),
|
|
8
|
-
tenantId: dimension.string({ column: 'tenant_id' }),
|
|
9
|
-
status: dimension.string(),
|
|
10
|
-
amount: dimension.number(),
|
|
11
|
-
createdAt: dimension.timestamp({ column: 'created_at' }),
|
|
12
|
-
},
|
|
13
|
-
measures: {
|
|
14
|
-
revenue: measure.sum('amount'),
|
|
15
|
-
completedRevenue: measure.sum('amount', {
|
|
16
|
-
filters: [eq('status', 'completed')],
|
|
17
|
-
}),
|
|
18
|
-
doubledRevenue: measure.derived({
|
|
19
|
-
uses: { revenue: 'revenue' },
|
|
20
|
-
formula: ({ revenue }) => add(revenue, revenue),
|
|
21
|
-
}),
|
|
22
|
-
},
|
|
23
|
-
});
|
|
24
|
-
const _SegmentedOrders = dataset('segmentedOrders', {
|
|
25
|
-
source: 'orders',
|
|
26
|
-
dimensions: { status: dimension.string() },
|
|
27
|
-
measures: { revenue: measure.sum('amount') },
|
|
28
|
-
segments: { paid: { filters: [eq('status', 'paid')] } },
|
|
29
|
-
});
|
|
30
|
-
const validDatasetSegments = { segments: ['paid'] };
|
|
31
|
-
const validMetricSegments = { segments: ['paid'] };
|
|
32
|
-
void validDatasetSegments;
|
|
33
|
-
void validMetricSegments;
|
|
34
|
-
// @ts-expect-error only declared segment names are accepted.
|
|
35
|
-
const invalidDatasetSegments = { segments: ['paidd'] };
|
|
36
|
-
// @ts-expect-error only declared segment names are accepted on metric queries.
|
|
37
|
-
const invalidMetricSegments = { segments: ['paidd'] };
|
|
38
|
-
// @ts-expect-error a dataset without segments has no selectable segment names.
|
|
39
|
-
const invalidPlainSegments = { segments: ['paid'] };
|
|
40
|
-
void invalidDatasetSegments;
|
|
41
|
-
void invalidMetricSegments;
|
|
42
|
-
void invalidPlainSegments;
|
|
43
|
-
// @ts-expect-error standalone metrics may only target base measures.
|
|
44
|
-
Orders.metric('invalidDerivedMetric', { measure: 'doubledRevenue' });
|
|
45
|
-
dataset('derivedDependency', {
|
|
46
|
-
source: 'orders',
|
|
47
|
-
dimensions: { amount: dimension.number() },
|
|
48
|
-
measures: {
|
|
49
|
-
revenue: measure.sum('amount'),
|
|
50
|
-
doubled: measure.derived({ uses: { value: 'revenue' }, formula: ({ value }) => add(value, value) }),
|
|
51
|
-
quadrupled: measure.derived({ uses: { value: 'doubled' }, formula: ({ value }) => add(value, value) }),
|
|
52
|
-
},
|
|
53
|
-
});
|
|
54
|
-
const _WindowOrders = dataset('windowOrders', {
|
|
55
|
-
source: 'orders', timeKey: 'createdAt',
|
|
56
|
-
dimensions: { createdAt: dimension.timestamp(), amount: dimension.number() },
|
|
57
|
-
measures: {
|
|
58
|
-
revenue: measure.sum('amount'),
|
|
59
|
-
trailingRevenue: measure.trailing('revenue', { amount: 7, unit: 'day' }),
|
|
60
|
-
runningRevenue: measure.cumulative('revenue'),
|
|
61
|
-
growth: measure.derived({ uses: { running: 'runningRevenue' }, formula: ({ running }) => add(running, running) }),
|
|
62
|
-
},
|
|
63
|
-
});
|
|
64
|
-
// @ts-expect-error standalone metrics may only target base measures, even in the unified registry.
|
|
65
|
-
_WindowOrders.metric('invalidWindowMetric', { measure: 'runningRevenue' });
|
|
66
|
-
dataset('invalidWindowInput', {
|
|
67
|
-
source: 'orders', timeKey: 'createdAt',
|
|
68
|
-
dimensions: { createdAt: dimension.timestamp(), amount: dimension.number() },
|
|
69
|
-
measures: {
|
|
70
|
-
revenue: measure.sum('amount'),
|
|
71
|
-
growth: measure.derived({ uses: { value: 'revenue' }, formula: ({ value }) => add(value, value) }),
|
|
72
|
-
// @ts-expect-error a window must wrap a base measure.
|
|
73
|
-
invalid: measure.cumulative('growth'),
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
|
-
const deploymentContract = buildProtocolDeploymentContract([Orders]);
|
|
77
|
-
rehydrateProtocolDeploymentContract(deploymentContract);
|
|
78
|
-
dataset('invalidDependency', {
|
|
79
|
-
source: 'orders',
|
|
80
|
-
dimensions: { amount: dimension.number() },
|
|
81
|
-
measures: {
|
|
82
|
-
revenue: measure.sum('amount'),
|
|
83
|
-
// @ts-expect-error derived inputs must name a base measure on this dataset.
|
|
84
|
-
typo: measure.derived({ uses: { value: 'reveneu' }, formula: ({ value }) => add(value, value) }),
|
|
85
|
-
},
|
|
86
|
-
});
|
|
87
|
-
dataset('crossDatasetDependency', {
|
|
88
|
-
source: 'orders',
|
|
89
|
-
dimensions: { amount: dimension.number() },
|
|
90
|
-
measures: {
|
|
91
|
-
revenue: measure.sum('amount'),
|
|
92
|
-
// @ts-expect-error qualified references cannot name measures from another dataset.
|
|
93
|
-
foreign: measure.derived({ uses: { value: 'other.revenue' }, formula: ({ value }) => add(value, value) }),
|
|
94
|
-
},
|
|
95
|
-
});
|
|
96
|
-
dataset('missingBaseMeasures', {
|
|
97
|
-
source: 'orders',
|
|
98
|
-
dimensions: { amount: dimension.number() },
|
|
99
|
-
measures: {
|
|
100
|
-
// @ts-expect-error a dataset without base measures cannot define a derived input.
|
|
101
|
-
invalid: measure.derived({ uses: { value: 'revenue' }, formula: ({ value }) => add(value, value) }),
|
|
102
|
-
},
|
|
103
|
-
});
|
|
104
|
-
const Customers = dataset('customers', {
|
|
105
|
-
source: 'customers',
|
|
106
|
-
dimensions: {
|
|
107
|
-
id: dimension.string(),
|
|
108
|
-
status: dimension.string(),
|
|
109
|
-
},
|
|
110
|
-
measures: {
|
|
111
|
-
customerCount: measure.count('id'),
|
|
112
|
-
},
|
|
113
|
-
});
|
|
114
|
-
const revenueMetric = Orders.metric('revenueMetric', { measure: 'revenue' });
|
|
115
|
-
const completedRevenueMetric = Orders.metric('completedRevenueMetric', { measure: 'completedRevenue' });
|
|
116
|
-
const averageRevenueMetric = Orders.metric('averageRevenueMetric', {
|
|
117
|
-
uses: { revenue: revenueMetric, completedRevenue: completedRevenueMetric },
|
|
118
|
-
formula: ({ revenue, completedRevenue }) => add(revenue, completedRevenue),
|
|
119
|
-
});
|
|
120
|
-
const customerCountMetric = Customers.metric('customerCountMetric', { measure: 'customerCount' });
|
|
121
|
-
const _publishedDatasets = publishDatasets()
|
|
122
|
-
.publish(Orders, { metrics: { revenue: revenueMetric } })
|
|
123
|
-
.publish(Customers, {
|
|
124
|
-
alias: 'accounts',
|
|
125
|
-
metrics: { customers: customerCountMetric },
|
|
126
|
-
})
|
|
127
|
-
.build();
|
|
128
|
-
const _cloudPublication = publishToCloud({
|
|
129
|
-
datasets: { Orders, Customers },
|
|
130
|
-
access: { roles: [], scopes: [] },
|
|
131
|
-
});
|
|
132
|
-
// @ts-expect-error published metrics must belong to the dataset being published.
|
|
133
|
-
publishDatasets().publish(Orders, { metrics: { customerCountMetric } });
|
|
134
|
-
const canonicalSchemas = buildCanonicalSemanticQuerySchemas({
|
|
135
|
-
orders: { ...Orders, metrics: { revenueMetric } },
|
|
136
|
-
});
|
|
137
|
-
canonicalSchemas.queryDataset.parse({ dataset: 'orders', measures: ['revenue'] });
|
|
138
|
-
const _manifestHash = canonicalSchemas.manifestHash;
|
|
139
|
-
const _statusFilter = eq('status', 'completed');
|
|
140
|
-
const _createdAtRange = between('createdAt', '2025-01-01', '2025-01-31');
|
|
141
|
-
const _revenueSort = desc('revenueMetric');
|
|
142
|
-
Orders.metric('validDerivedMetric', {
|
|
143
|
-
uses: { revenue: revenueMetric },
|
|
144
|
-
formula: ({ revenue }) => add(revenue, revenue),
|
|
145
|
-
});
|
|
146
|
-
// @ts-expect-error derived metrics can only use base metrics from the same dataset.
|
|
147
|
-
Orders.metric('invalidCrossDatasetDerivedMetric', {
|
|
148
|
-
uses: { customerCount: customerCountMetric },
|
|
149
|
-
formula: () => add('customerCount', 'customerCount'),
|
|
150
|
-
});
|
|
151
|
-
// @ts-expect-error derived metrics can only use base metrics, not derived metric refs.
|
|
152
|
-
Orders.metric('invalidDerivedFromDerivedMetric', {
|
|
153
|
-
uses: { averageRevenue: averageRevenueMetric },
|
|
154
|
-
formula: () => add('averageRevenue', 'averageRevenue'),
|
|
155
|
-
});
|
|
156
|
-
const runtimeContext = {
|
|
157
|
-
runtime: {
|
|
158
|
-
tenant: 'tenant-1',
|
|
159
|
-
},
|
|
160
|
-
};
|
|
161
|
-
const abortableContext = {
|
|
162
|
-
abortSignal: new AbortController().signal,
|
|
163
|
-
};
|
|
164
|
-
void abortableContext;
|
|
165
|
-
const _legacyTenantRuntimeContext = {
|
|
166
|
-
runtime: {
|
|
167
|
-
tenant: { id: 'tenant-1' },
|
|
168
|
-
},
|
|
169
|
-
};
|
|
170
|
-
const _tenantSetRuntimeContext = {
|
|
171
|
-
runtime: {
|
|
172
|
-
tenant: { in: ['tenant-1', 'tenant-2'] },
|
|
173
|
-
},
|
|
174
|
-
};
|
|
175
|
-
const _crossTenantRuntimeContext = {
|
|
176
|
-
runtime: {
|
|
177
|
-
tenant: { scope: 'all' },
|
|
178
|
-
},
|
|
179
|
-
};
|
|
180
|
-
const builderFactory = {
|
|
181
|
-
table: () => ({
|
|
182
|
-
select: () => builderFactory.table('orders'),
|
|
183
|
-
sum: () => builderFactory.table('orders'),
|
|
184
|
-
count: () => builderFactory.table('orders'),
|
|
185
|
-
countDistinct: () => builderFactory.table('orders'),
|
|
186
|
-
avg: () => builderFactory.table('orders'),
|
|
187
|
-
min: () => builderFactory.table('orders'),
|
|
188
|
-
max: () => builderFactory.table('orders'),
|
|
189
|
-
argMax: () => builderFactory.table('orders'),
|
|
190
|
-
argMin: () => builderFactory.table('orders'),
|
|
191
|
-
quantile: () => builderFactory.table('orders'),
|
|
192
|
-
stddev: () => builderFactory.table('orders'),
|
|
193
|
-
variance: () => builderFactory.table('orders'),
|
|
194
|
-
where: () => builderFactory.table('orders'),
|
|
195
|
-
leftJoin: () => builderFactory.table('orders'),
|
|
196
|
-
groupBy: () => builderFactory.table('orders'),
|
|
197
|
-
orderBy: () => builderFactory.table('orders'),
|
|
198
|
-
limit: () => builderFactory.table('orders'),
|
|
199
|
-
offset: () => builderFactory.table('orders'),
|
|
200
|
-
toSQLWithParams: () => ({ sql: 'SELECT 1', parameters: [] }),
|
|
201
|
-
execute: async () => [],
|
|
202
|
-
}),
|
|
203
|
-
rawQuery: async () => [],
|
|
204
|
-
};
|
|
205
|
-
const analytics = createDatasetClient({ queryBuilder: builderFactory });
|
|
206
|
-
const _datasetCompilation = analytics.compileDataset(Orders, { measures: ['doubledRevenue'] });
|
|
207
|
-
// @ts-expect-error compilation accepts declared dataset measures only.
|
|
208
|
-
analytics.compileDataset(Orders, { measures: ['missing'] });
|
|
209
|
-
// @ts-expect-error compilation accepts declared dataset dimensions only.
|
|
210
|
-
analytics.compileDataset(Orders, { dimensions: ['missing'] });
|
|
211
|
-
// @ts-expect-error standalone metric handles are not dataset compilation targets.
|
|
212
|
-
analytics.compileDataset(Orders.metric('revenue', { measure: 'revenue' }));
|
|
213
|
-
const explicitAnalytics = analytics;
|
|
214
|
-
const datasetQuery = { dimensions: ['status'], measures: ['revenue'] };
|
|
215
|
-
analytics.validate(revenueMetric, { dimensions: ['status'] }, runtimeContext);
|
|
216
|
-
analytics.toSQL(completedRevenueMetric, { dimensions: ['status'] }, runtimeContext);
|
|
217
|
-
analytics.toSQL(revenueMetric, { orderBy: [desc('revenueMetric')] }, runtimeContext);
|
|
218
|
-
analytics.validate(Orders, datasetQuery, runtimeContext);
|
|
219
|
-
analytics.toSQL(Orders, datasetQuery, runtimeContext);
|
|
220
|
-
void analytics.execute(Orders, datasetQuery, runtimeContext);
|
|
221
|
-
void runtimeContext;
|
|
222
|
-
void explicitAnalytics;
|
|
223
|
-
// Sanity: the simulated shape reproduces the original incompatibility.
|
|
224
|
-
// @ts-expect-error a schema-typed builder does not satisfy the strict protocol
|
|
225
|
-
const strictRejection = simulatedTypedFactory;
|
|
226
|
-
const typedAccepted = simulatedTypedFactory;
|
|
227
|
-
const typedClient = createDatasetClient({ queryBuilder: simulatedTypedFactory });
|
|
228
|
-
const typedRuntime = { runtime: { builderFactory: simulatedTypedFactory } };
|
|
229
|
-
// @ts-expect-error non-builder objects are still rejected
|
|
230
|
-
const rejectedFactory = { notABuilder: true };
|
|
231
|
-
void strictRejection;
|
|
232
|
-
void typedAccepted;
|
|
233
|
-
void typedClient;
|
|
234
|
-
void typedRuntime;
|
|
235
|
-
void rejectedFactory;
|
|
236
|
-
// ---------------------------------------------------------------------------
|
|
237
|
-
// Portable execution exclusions carry a named reason (HQ-45)
|
|
238
|
-
// ---------------------------------------------------------------------------
|
|
239
|
-
import { PortableExecutionUnsupportedError as PortableUnsupported, UNSUPPORTED_CONTRACT_REASONS as REASONS, UnsupportedContractFeatureError as ContractFeatureError, } from './index.js';
|
|
240
|
-
const namedReason = REASONS.ambiguousMeasureSql;
|
|
241
|
-
const literalReason = 'HQ_PORTABLE_DATASET_NOT_ACTIVATED';
|
|
242
|
-
// @ts-expect-error an unnamed reason is not an exclusion
|
|
243
|
-
const unnamedReason = 'HQ_PORTABLE_SOMETHING_ELSE';
|
|
244
|
-
const featureReason = new ContractFeatureError('orders', 'metric', 'detail', namedReason).reason;
|
|
245
|
-
// The three-argument constructor stays valid for existing callers.
|
|
246
|
-
const legacyFeatureError = new ContractFeatureError('orders', 'metric', 'detail');
|
|
247
|
-
const executionReason = new PortableUnsupported('message', { reason: literalReason }).reason;
|
|
248
|
-
void unnamedReason;
|
|
249
|
-
void featureReason;
|
|
250
|
-
void legacyFeatureError;
|
|
251
|
-
void executionReason;
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { TimeGrain } from '../types.js';
|
|
2
|
-
export declare function addTimeSql(time: string, amount: string | number, grain: TimeGrain): string;
|
|
3
|
-
export declare function subtractTimeSql(time: string, amount: number, grain: TimeGrain): string;
|
|
4
|
-
//# sourceMappingURL=time-arithmetic-sql.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"time-arithmetic-sql.d.ts","sourceRoot":"","sources":["../../src/utils/time-arithmetic-sql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAM7C,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAE1F;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAEtF"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
const INTERVAL_FUNCTIONS = {
|
|
2
|
-
minute: 'Minutes', hour: 'Hours', day: 'Days', week: 'Weeks', month: 'Months', quarter: 'Quarters', year: 'Years',
|
|
3
|
-
};
|
|
4
|
-
export function addTimeSql(time, amount, grain) {
|
|
5
|
-
return `add${INTERVAL_FUNCTIONS[grain]}(${time}, ${amount})`;
|
|
6
|
-
}
|
|
7
|
-
export function subtractTimeSql(time, amount, grain) {
|
|
8
|
-
return `subtract${INTERVAL_FUNCTIONS[grain]}(${time}, ${amount})`;
|
|
9
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { MeasureDefinition } from '../types.js';
|
|
2
|
-
/** NULL for an empty non-count population, including nullable measure inputs. */
|
|
3
|
-
export declare function windowAggregateSql(definition: MeasureDefinition, value: string, arg: string): string;
|
|
4
|
-
export declare function isCountAggregation(definition: MeasureDefinition): boolean;
|
|
5
|
-
//# sourceMappingURL=window-aggregation-sql.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"window-aggregation-sql.d.ts","sourceRoot":"","sources":["../../src/utils/window-aggregation-sql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAYpG;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAEzE"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/** NULL for an empty non-count population, including nullable measure inputs. */
|
|
2
|
-
export function windowAggregateSql(definition, value, arg) {
|
|
3
|
-
switch (definition.aggregation) {
|
|
4
|
-
case 'count': return `count(${value})`;
|
|
5
|
-
case 'countDistinct': return `uniqExact(${value})`;
|
|
6
|
-
case 'approxCountDistinct': return `uniq(${value})`;
|
|
7
|
-
case 'percentile': return `quantileOrNull(${definition.level})(${value})`;
|
|
8
|
-
case 'argMax': return `argMaxOrNull(${value}, ${arg})`;
|
|
9
|
-
case 'argMin': return `argMinOrNull(${value}, ${arg})`;
|
|
10
|
-
case 'stddev': return `stddevSampOrNull(${value})`;
|
|
11
|
-
case 'variance': return `varSampOrNull(${value})`;
|
|
12
|
-
default: return `${definition.aggregation}OrNull(${value})`;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
export function isCountAggregation(definition) {
|
|
16
|
-
return ['count', 'countDistinct', 'approxCountDistinct'].includes(definition.aggregation);
|
|
17
|
-
}
|