@hypequery/datasets 0.23.1 → 0.24.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.js +2 -2
- package/dist/cache/query-signature.d.ts.map +1 -1
- package/dist/cache/query-signature.js +3 -0
- package/dist/catalog.d.ts +3 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +3 -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 +2 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +4 -3
- package/dist/dataset-sql-dialect.d.ts +117 -0
- package/dist/dataset-sql-dialect.d.ts.map +1 -1
- package/dist/dataset.d.ts +1 -1
- package/dist/dataset.d.ts.map +1 -1
- package/dist/dataset.js +2 -1
- package/dist/in-memory-backend.d.ts.map +1 -1
- package/dist/in-memory-backend.js +2 -0
- package/dist/index.d.ts +48 -5
- 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.map +1 -1
- package/dist/metric-query-engine.js +4 -3
- package/dist/protocol-adapter.d.ts.map +1 -1
- package/dist/protocol-adapter.js +5 -3
- package/dist/protocol-deployment-adapter.d.ts.map +1 -1
- package/dist/protocol-deployment-adapter.js +7 -1
- 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 +32 -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 +5 -3
- 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 +16 -0
- package/dist/semantic-query-schema.d.ts +2 -1
- package/dist/semantic-query-schema.d.ts.map +1 -1
- package/dist/semantic-query-schema.js +12 -12
- package/dist/types.d.ts +22 -1
- 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.map +1 -1
- package/dist/utils/build-dataset-query-builder.js +16 -8
- 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 +140 -1
- package/dist/utils/compile-dataset-query.d.ts.map +1 -1
- package/dist/utils/compile-dataset-query.js +9 -6
- 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.map +1 -1
- package/dist/utils/dataset-definition-validation.js +36 -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.map +1 -1
- package/dist/utils/dataset-query-validation.js +7 -0
- package/dist/utils/dataset-source.d.ts +9 -0
- package/dist/utils/dataset-source.d.ts.map +1 -0
- package/dist/utils/dataset-source.js +16 -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-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/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 +54 -41
- package/dist/utils/metric-query-builder.d.ts.map +1 -1
- package/dist/utils/metric-query-builder.js +17 -9
- package/dist/utils/metric-query-validation.d.ts.map +1 -1
- package/dist/utils/metric-query-validation.js +7 -0
- 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 +75 -8
- 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 +25 -8
- package/dist/utils/relationship-builder-plan.d.ts.map +1 -1
- package/dist/utils/relationship-builder-plan.js +23 -9
- 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 +33 -10
- package/dist/utils/relationship-measures.d.ts.map +1 -1
- package/dist/utils/relationship-measures.js +3 -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/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 +2 -1
- package/dist/utils/time-measure-axis-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-axis-sql.js +19 -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 +2 -1
- package/dist/utils/time-measure-leaf-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-leaf-sql.js +17 -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 +2 -2
- package/dist/utils/time-measure-source-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-source-sql.js +25 -16
- 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
|
@@ -1,249 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
function canonicalValue(input, path) {
|
|
11
|
-
try {
|
|
12
|
-
if (Array.isArray(input)) {
|
|
13
|
-
return validateCanonicalValue({
|
|
14
|
-
$hypequery: {
|
|
15
|
-
type: 'array',
|
|
16
|
-
version: 1,
|
|
17
|
-
values: input.map((item, index) => canonicalValue(item, `${path}[${index}]`)),
|
|
18
|
-
},
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
if (typeof input === 'object' && input !== null) {
|
|
22
|
-
if ('$hypequery' in input)
|
|
23
|
-
return validateCanonicalValue(input);
|
|
24
|
-
const prototype = Object.getPrototypeOf(input);
|
|
25
|
-
if (prototype !== Object.prototype && prototype !== null) {
|
|
26
|
-
throw new ProtocolSchemaAdapterError('Default is not portable plain data', path);
|
|
27
|
-
}
|
|
28
|
-
return validateCanonicalValue({
|
|
29
|
-
$hypequery: {
|
|
30
|
-
type: 'map',
|
|
31
|
-
version: 1,
|
|
32
|
-
entries: Object.entries(input)
|
|
33
|
-
.sort(([left], [right]) => left.localeCompare(right))
|
|
34
|
-
.map(([key, value]) => [key, canonicalValue(value, `${path}.${key}`)]),
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
return validateCanonicalValue(input);
|
|
39
|
-
}
|
|
40
|
-
catch (error) {
|
|
41
|
-
if (error instanceof ProtocolSchemaAdapterError)
|
|
42
|
-
throw error;
|
|
43
|
-
throw new ProtocolSchemaAdapterError('Default is not a canonical protocol value', path);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
function typeName(schema) {
|
|
47
|
-
return String(schema?._def?.typeName ?? 'Unknown');
|
|
48
|
-
}
|
|
49
|
-
function description(schema) {
|
|
50
|
-
return typeof schema.description === 'string'
|
|
51
|
-
? schema.description
|
|
52
|
-
: undefined;
|
|
53
|
-
}
|
|
54
|
-
function annotate(schema, result) {
|
|
55
|
-
const value = description(schema);
|
|
56
|
-
return value === undefined ? result : { ...result, description: value };
|
|
57
|
-
}
|
|
58
|
-
function convertString(schema, path) {
|
|
59
|
-
const result = { kind: 'string' };
|
|
60
|
-
for (const check of schema._def.checks) {
|
|
61
|
-
switch (check.kind) {
|
|
62
|
-
case 'min':
|
|
63
|
-
result.minLength = check.value;
|
|
64
|
-
break;
|
|
65
|
-
case 'max':
|
|
66
|
-
result.maxLength = check.value;
|
|
67
|
-
break;
|
|
68
|
-
case 'length':
|
|
69
|
-
result.minLength = check.value;
|
|
70
|
-
result.maxLength = check.value;
|
|
71
|
-
break;
|
|
72
|
-
default:
|
|
73
|
-
throw new ProtocolSchemaAdapterError(`Unsupported Zod string check "${String(check.kind)}"`, path);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return annotate(schema, result);
|
|
77
|
-
}
|
|
78
|
-
function convertNumber(schema, path) {
|
|
79
|
-
const result = { kind: 'number' };
|
|
80
|
-
for (const check of schema._def.checks) {
|
|
81
|
-
switch (check.kind) {
|
|
82
|
-
case 'int':
|
|
83
|
-
result.kind = 'integer';
|
|
84
|
-
break;
|
|
85
|
-
case 'min':
|
|
86
|
-
result[check.inclusive === false ? 'exclusiveMinimum' : 'minimum'] = check.value;
|
|
87
|
-
break;
|
|
88
|
-
case 'max':
|
|
89
|
-
result[check.inclusive === false ? 'exclusiveMaximum' : 'maximum'] = check.value;
|
|
90
|
-
break;
|
|
91
|
-
case 'finite':
|
|
92
|
-
break;
|
|
93
|
-
default:
|
|
94
|
-
throw new ProtocolSchemaAdapterError(`Unsupported Zod number check "${String(check.kind)}"`, path);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return annotate(schema, result);
|
|
98
|
-
}
|
|
99
|
-
function isOptionalProperty(schema) {
|
|
100
|
-
const name = typeName(schema);
|
|
101
|
-
return name === 'ZodOptional' || name === 'ZodDefault';
|
|
102
|
-
}
|
|
103
|
-
function nativeEnumValues(input) {
|
|
104
|
-
const values = Object.keys(input)
|
|
105
|
-
.filter(key => typeof input[String(input[key])] !== 'number')
|
|
106
|
-
.map(key => input[key]);
|
|
107
|
-
return [...new Set(values)];
|
|
108
|
-
}
|
|
109
|
-
function isUnconstrainedRecordKey(schema) {
|
|
110
|
-
if (schema === undefined || typeName(schema) !== 'ZodString')
|
|
111
|
-
return false;
|
|
112
|
-
const definition = schema._def;
|
|
113
|
-
return Array.isArray(definition.checks)
|
|
114
|
-
&& definition.checks.length === 0
|
|
115
|
-
&& definition.coerce !== true;
|
|
116
|
-
}
|
|
117
|
-
function convert(schema, path) {
|
|
118
|
-
const definition = schema._def;
|
|
119
|
-
switch (typeName(schema)) {
|
|
120
|
-
case 'ZodAny':
|
|
121
|
-
case 'ZodUnknown':
|
|
122
|
-
return annotate(schema, { kind: 'any' });
|
|
123
|
-
case 'ZodNever':
|
|
124
|
-
case 'ZodVoid':
|
|
125
|
-
case 'ZodUndefined':
|
|
126
|
-
return annotate(schema, { kind: 'void' });
|
|
127
|
-
case 'ZodNull':
|
|
128
|
-
return annotate(schema, { kind: 'null' });
|
|
129
|
-
case 'ZodBoolean':
|
|
130
|
-
return annotate(schema, { kind: 'boolean' });
|
|
131
|
-
case 'ZodString':
|
|
132
|
-
return convertString(schema, path);
|
|
133
|
-
case 'ZodNumber':
|
|
134
|
-
return convertNumber(schema, path);
|
|
135
|
-
case 'ZodLiteral':
|
|
136
|
-
return annotate(schema, {
|
|
137
|
-
kind: 'literal',
|
|
138
|
-
value: canonicalValue(definition.value, `${path}.value`),
|
|
139
|
-
});
|
|
140
|
-
case 'ZodEnum':
|
|
141
|
-
return annotate(schema, {
|
|
142
|
-
kind: 'enum',
|
|
143
|
-
values: [...definition.values],
|
|
144
|
-
});
|
|
145
|
-
case 'ZodNativeEnum': {
|
|
146
|
-
const values = nativeEnumValues(definition.values);
|
|
147
|
-
return annotate(schema, { kind: 'enum', values });
|
|
148
|
-
}
|
|
149
|
-
case 'ZodArray': {
|
|
150
|
-
const result = {
|
|
151
|
-
kind: 'array',
|
|
152
|
-
items: convert(definition.type, `${path}.items`),
|
|
153
|
-
};
|
|
154
|
-
if (definition.minLength?.value !== undefined)
|
|
155
|
-
result.minItems = definition.minLength.value;
|
|
156
|
-
if (definition.maxLength?.value !== undefined)
|
|
157
|
-
result.maxItems = definition.maxLength.value;
|
|
158
|
-
if (definition.exactLength?.value !== undefined) {
|
|
159
|
-
result.minItems = definition.exactLength.value;
|
|
160
|
-
result.maxItems = definition.exactLength.value;
|
|
161
|
-
}
|
|
162
|
-
return annotate(schema, result);
|
|
163
|
-
}
|
|
164
|
-
case 'ZodObject': {
|
|
165
|
-
if (typeName(definition.catchall) !== 'ZodNever') {
|
|
166
|
-
throw new ProtocolSchemaAdapterError('Unsupported Zod object catchall', path);
|
|
167
|
-
}
|
|
168
|
-
const shape = definition.shape();
|
|
169
|
-
const properties = Object.fromEntries(Object.entries(shape).map(([name, property]) => [
|
|
170
|
-
name,
|
|
171
|
-
convert(property, `${path}.properties.${name}`),
|
|
172
|
-
]));
|
|
173
|
-
const required = Object.entries(shape)
|
|
174
|
-
.filter(([, property]) => !isOptionalProperty(property))
|
|
175
|
-
.map(([name]) => name);
|
|
176
|
-
const unknownProperties = definition.unknownKeys === 'passthrough'
|
|
177
|
-
? 'preserve'
|
|
178
|
-
: definition.unknownKeys === 'strict'
|
|
179
|
-
? 'reject'
|
|
180
|
-
: 'strip';
|
|
181
|
-
return annotate(schema, {
|
|
182
|
-
kind: 'object',
|
|
183
|
-
properties,
|
|
184
|
-
required,
|
|
185
|
-
unknownProperties,
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
case 'ZodRecord':
|
|
189
|
-
if (!isUnconstrainedRecordKey(definition.keyType)) {
|
|
190
|
-
throw new ProtocolSchemaAdapterError('Unsupported constrained Zod record key', path);
|
|
191
|
-
}
|
|
192
|
-
return annotate(schema, {
|
|
193
|
-
kind: 'record',
|
|
194
|
-
values: convert(definition.valueType, `${path}.values`),
|
|
195
|
-
});
|
|
196
|
-
case 'ZodUnion':
|
|
197
|
-
return annotate(schema, {
|
|
198
|
-
kind: 'union',
|
|
199
|
-
variants: definition.options.map((option, index) => convert(option, `${path}.variants[${index}]`)),
|
|
200
|
-
});
|
|
201
|
-
case 'ZodDiscriminatedUnion':
|
|
202
|
-
// RFC 0004 has no separate discriminator index. Converting every option
|
|
203
|
-
// drops only Zod's lookup metadata; each object's literal discriminator
|
|
204
|
-
// property remains part of its protocol variant.
|
|
205
|
-
return annotate(schema, {
|
|
206
|
-
kind: 'union',
|
|
207
|
-
variants: [...definition.options.values()].map((option, index) => convert(option, `${path}.variants[${index}]`)),
|
|
208
|
-
});
|
|
209
|
-
case 'ZodNullable':
|
|
210
|
-
return annotate(schema, {
|
|
211
|
-
kind: 'union',
|
|
212
|
-
variants: [convert(definition.innerType, `${path}.variants[0]`), { kind: 'null' }],
|
|
213
|
-
});
|
|
214
|
-
case 'ZodOptional':
|
|
215
|
-
return annotate(schema, convert(definition.innerType, path));
|
|
216
|
-
case 'ZodDefault': {
|
|
217
|
-
const inner = convert(definition.innerType, path);
|
|
218
|
-
if (inner.kind === 'void') {
|
|
219
|
-
throw new ProtocolSchemaAdapterError('Void schemas cannot carry defaults', path);
|
|
220
|
-
}
|
|
221
|
-
return annotate(schema, {
|
|
222
|
-
...inner,
|
|
223
|
-
default: canonicalValue(definition.defaultValue(), `${path}.default`),
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
case 'ZodBranded':
|
|
227
|
-
return annotate(schema, convert(definition.type, path));
|
|
228
|
-
case 'ZodReadonly':
|
|
229
|
-
return annotate(schema, convert(definition.innerType, path));
|
|
230
|
-
case 'ZodEffects': {
|
|
231
|
-
const effectType = String(definition.effect?.type ?? 'unknown');
|
|
232
|
-
if (effectType !== 'refinement') {
|
|
233
|
-
throw new ProtocolSchemaAdapterError(`Unsupported Zod effect "${effectType}"`, path);
|
|
234
|
-
}
|
|
235
|
-
// A refinement preserves the wrapped schema's input and output shape.
|
|
236
|
-
// The rule itself remains enforced by Zod, but cannot be advertised by
|
|
237
|
-
// ProtocolSchema (for example, a cross-field selection requirement).
|
|
238
|
-
return annotate(schema, convert(definition.schema, path));
|
|
239
|
-
}
|
|
240
|
-
default:
|
|
241
|
-
throw new ProtocolSchemaAdapterError(`Unsupported Zod type "${typeName(schema)}"`, path);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
/** Converts the portable subset of a Zod v3 schema into RFC 0004. */
|
|
1
|
+
import { validateProtocolSchema } from '@hypequery/protocol';
|
|
2
|
+
import { isZod4Schema } from './utils/zod-schema-version.js';
|
|
3
|
+
import { convertZodV3Schema } from './utils/zod-v3-protocol-schema.js';
|
|
4
|
+
import { convertZodV4Schema } from './utils/zod-v4-protocol-schema.js';
|
|
5
|
+
export { ProtocolSchemaAdapterError } from './utils/protocol-schema-conversion.js';
|
|
6
|
+
/**
|
|
7
|
+
* Converts the portable subset of a Zod schema into RFC 0004. Accepts schemas
|
|
8
|
+
* from Zod 3 or Zod 4, so a caller's own copy of Zod need not match ours.
|
|
9
|
+
*/
|
|
245
10
|
export function zodToProtocolSchema(schema, path = '$') {
|
|
246
11
|
if (schema === undefined)
|
|
247
12
|
return validateProtocolSchema({ kind: 'any' });
|
|
248
|
-
return validateProtocolSchema(
|
|
13
|
+
return validateProtocolSchema(isZod4Schema(schema)
|
|
14
|
+
? convertZodV4Schema(schema, path)
|
|
15
|
+
: convertZodV3Schema(schema, path));
|
|
249
16
|
}
|
|
@@ -9,7 +9,14 @@
|
|
|
9
9
|
* This keeps @hypequery/serve DB-agnostic while enabling first-class builder usage.
|
|
10
10
|
*/
|
|
11
11
|
import type { DatasetSqlDialect } from './dataset-sql-dialect.js';
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* A chainable query builder instance (what `.table(name)` returns).
|
|
14
|
+
*
|
|
15
|
+
* Aliases and column arguments the datasets planner passes are SQL text as
|
|
16
|
+
* the datasets dialect spells it: generated output aliases arrive already
|
|
17
|
+
* quoted (for example `` `revenue` ``). Insert them verbatim; do not quote
|
|
18
|
+
* them again.
|
|
19
|
+
*/
|
|
13
20
|
export interface QueryBuilderLike {
|
|
14
21
|
select(columns: string[] | string): QueryBuilderLike;
|
|
15
22
|
sum(column: string, alias?: string): QueryBuilderLike;
|
|
@@ -30,7 +37,21 @@ export interface QueryBuilderLike {
|
|
|
30
37
|
variance?(column: string, alias?: string): QueryBuilderLike;
|
|
31
38
|
/** Estimated number of distinct non-NULL values of `column`. */
|
|
32
39
|
approxCountDistinct?(column: string, alias?: string): QueryBuilderLike;
|
|
40
|
+
/**
|
|
41
|
+
* Finalize the aggregate states in `column` with `stateFunction`'s `-Merge`
|
|
42
|
+
* combinator (ClickHouse `uniqMerge(users)`). `stateFunction` is one of the
|
|
43
|
+
* datasets allowlist. `@hypequery/clickhouse` implements it from the release
|
|
44
|
+
* that adds `mergeState`.
|
|
45
|
+
*/
|
|
46
|
+
mergeState?(stateFunction: string, column: string, alias?: string): QueryBuilderLike;
|
|
33
47
|
where(column: string, operator: string, value: unknown): QueryBuilderLike;
|
|
48
|
+
/**
|
|
49
|
+
* Optional: read the table source with ClickHouse `FINAL`. Needed only for
|
|
50
|
+
* datasets declared `final: true`; querying one through a builder without
|
|
51
|
+
* it is refused rather than run without `FINAL`, which would count every
|
|
52
|
+
* unmerged row version.
|
|
53
|
+
*/
|
|
54
|
+
final?(): QueryBuilderLike;
|
|
34
55
|
leftJoin(table: string, leftColumn: string, rightColumn: string, alias?: string, on?: QueryBuilderJoinCondition | QueryBuilderJoinCondition[]): QueryBuilderLike;
|
|
35
56
|
/**
|
|
36
57
|
* Single-match LEFT JOIN (ClickHouse `LEFT ANY JOIN`). Required to query
|
|
@@ -55,6 +76,16 @@ export interface QueryBuilderLike {
|
|
|
55
76
|
sql: string;
|
|
56
77
|
parameters: unknown[];
|
|
57
78
|
};
|
|
79
|
+
/**
|
|
80
|
+
* Optional: compile with each bound value written through `placeholder`,
|
|
81
|
+
* called once per value in SQL order, its result inserted verbatim. Lets
|
|
82
|
+
* the datasets planner own placeholder spelling and numbering when it
|
|
83
|
+
* embeds this statement in a larger one. Required on datasets dialects that
|
|
84
|
+
* number placeholders (such as Postgres `$n`) and only called there:
|
|
85
|
+
* positional `?` dialects keep using `toSQLWithParams`, unchanged.
|
|
86
|
+
* `@hypequery/clickhouse` implements it from 2.14.0.
|
|
87
|
+
*/
|
|
88
|
+
toSQLWithPlaceholders?(placeholder: (value: unknown) => string): string;
|
|
58
89
|
execute<T = Record<string, unknown>>(options?: {
|
|
59
90
|
abortSignal?: AbortSignal;
|
|
60
91
|
}): Promise<T[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-builder-protocol.d.ts","sourceRoot":"","sources":["../src/query-builder-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE
|
|
1
|
+
{"version":3,"file":"query-builder-protocol.d.ts","sourceRoot":"","sources":["../src/query-builder-protocol.ts"],"names":[],"mappings":"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"}
|
package/dist/query-planner.d.ts
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
import type { AggregationSpec, AnyDatasetInstance, ExecutionContext, MeasureDefinition, MetricOrderBy, TimeGrain } from "./types.js";
|
|
2
2
|
import type { QueryBuilderLike } from "./query-builder-protocol.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { DatasetSqlDialectRules } from './dataset-sql-dialect.js';
|
|
4
4
|
import { type RelationshipBuilderContext } from './utils/relationship-builder-plan.js';
|
|
5
5
|
type DatasetShape = AnyDatasetInstance;
|
|
6
6
|
export declare function resolveDimensionExpression(ds: DatasetShape, dimensionName: string, joinCtx?: RelationshipBuilderContext): string;
|
|
7
7
|
export declare function resolveFilterField(ds: DatasetShape, filterField: string, joinCtx?: RelationshipBuilderContext): string;
|
|
8
|
-
export declare function buildDimensionSelectionPlan(ds: DatasetShape, dimensions: string[], grain: TimeGrain | undefined, joinCtx
|
|
8
|
+
export declare function buildDimensionSelectionPlan(ds: DatasetShape, dimensions: string[], grain: TimeGrain | undefined, joinCtx: RelationshipBuilderContext | undefined, timezone: string | undefined, dialect: DatasetSqlDialectRules): {
|
|
9
9
|
selectParts: string[];
|
|
10
10
|
groupByParts: string[];
|
|
11
11
|
};
|
|
12
|
-
export declare function applyAggregationSpec(qb: QueryBuilderLike, ds: DatasetShape, spec: AggregationSpec,
|
|
12
|
+
export declare function applyAggregationSpec(qb: QueryBuilderLike, ds: DatasetShape, spec: AggregationSpec, name: string, joinCtx: RelationshipBuilderContext | undefined, dialect: DatasetSqlDialectRules, expressions?: {
|
|
13
13
|
field: string;
|
|
14
14
|
arg?: string;
|
|
15
15
|
}): QueryBuilderLike;
|
|
16
|
-
export declare function applyMeasureDefinition(qb: QueryBuilderLike, ds: DatasetShape, name: string, definition: MeasureDefinition, joinCtx
|
|
17
|
-
|
|
16
|
+
export declare function applyMeasureDefinition(qb: QueryBuilderLike, ds: DatasetShape, name: string, definition: MeasureDefinition, joinCtx: RelationshipBuilderContext | undefined, dialect: DatasetSqlDialectRules): QueryBuilderLike;
|
|
17
|
+
/**
|
|
18
|
+
* Appends ORDER BY, LIMIT and OFFSET. Under joins, an order on a selected
|
|
19
|
+
* qualified dimension repeats its guarded expression (the GROUP BY key) rather
|
|
20
|
+
* than naming the alias, which the engine may resolve to the raw joined column;
|
|
21
|
+
* any other qualified order (a related measure) sorts by its quoted alias.
|
|
22
|
+
*/
|
|
23
|
+
export declare function appendOrderLimitOffset(qb: QueryBuilderLike, orderBy: MetricOrderBy[] | undefined, grain: TimeGrain | undefined, limit: number | undefined, offset: number | undefined, joinCtx: RelationshipBuilderContext | undefined, dialect: DatasetSqlDialectRules, selection?: {
|
|
24
|
+
ds: DatasetShape;
|
|
25
|
+
dimensions: readonly string[];
|
|
26
|
+
}): QueryBuilderLike;
|
|
18
27
|
export declare function resolveTenantFilterColumn(ds: DatasetShape, context?: ExecutionContext): string | undefined;
|
|
19
28
|
export {};
|
|
20
29
|
//# sourceMappingURL=query-planner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-planner.d.ts","sourceRoot":"","sources":["../src/query-planner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,SAAS,EACV,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAIpE,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"query-planner.d.ts","sourceRoot":"","sources":["../src/query-planner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,SAAS,EACV,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAIpE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EAGL,KAAK,0BAA0B,EAChC,MAAM,sCAAsC,CAAC;AAK9C,KAAK,YAAY,GAAG,kBAAkB,CAAC;AAEvC,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,YAAY,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,0BAA0B,GACnC,MAAM,CAUR;AAED,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,YAAY,EAChB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,0BAA0B,GACnC,MAAM,CAMR;AAED,wBAAgB,2BAA2B,CACzC,EAAE,EAAE,YAAY,EAChB,UAAU,EAAE,MAAM,EAAE,EACpB,KAAK,EAAE,SAAS,GAAG,SAAS,EAC5B,OAAO,EAAE,0BAA0B,GAAG,SAAS,EAC/C,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,OAAO,EAAE,sBAAsB,GAC9B;IAAE,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAkCnD;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,gBAAgB,EACpB,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE,eAAe,EACrB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,0BAA0B,GAAG,SAAS,EAC/C,OAAO,EAAE,sBAAsB,EAC/B,WAAW,CAAC,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,gBAAgB,CAmFlB;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,gBAAgB,EACpB,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,iBAAiB,EAC7B,OAAO,EAAE,0BAA0B,GAAG,SAAS,EAC/C,OAAO,EAAE,sBAAsB,GAC9B,gBAAgB,CAElB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,gBAAgB,EACpB,OAAO,EAAE,aAAa,EAAE,GAAG,SAAS,EACpC,KAAK,EAAE,SAAS,GAAG,SAAS,EAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,0BAA0B,GAAG,SAAS,EAC/C,OAAO,EAAE,sBAAsB,EAC/B,SAAS,CAAC,EAAE;IAAE,EAAE,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAC9D,gBAAgB,CAsBlB;AAED,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,YAAY,EAChB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,GAAG,SAAS,CAMpB"}
|
package/dist/query-planner.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { semanticOrderDirection } from './utils/semantic-query-syntax.js';
|
|
2
2
|
import { queryTimeSql } from './utils/query-timezone.js';
|
|
3
3
|
import { assertNoRawSqlUnderJoins } from './utils/sql-under-joins.js';
|
|
4
|
-
import {
|
|
4
|
+
import { isSupportedTimeGrain } from "./constants.js";
|
|
5
5
|
import { applyFilteredAggregationExpression } from './utils/filtered-aggregation-sql.js';
|
|
6
6
|
import { getRuntimeTenantPredicate } from './utils/tenant-runtime.js';
|
|
7
|
-
import { clickhouseDatasetSqlDialect } from './utils/clickhouse-dataset-sql-dialect.js';
|
|
8
7
|
import { isQualifiedField } from './utils/relationship-fields.js';
|
|
9
|
-
import { qualifyBaseColumn,
|
|
8
|
+
import { qualifyBaseColumn, resolveQualifiedExpression, } from './utils/relationship-builder-plan.js';
|
|
10
9
|
import { measureToAggregationSpec } from './utils/dataset-normalization.js';
|
|
11
10
|
import { validatePercentileLevel } from './measure.js';
|
|
11
|
+
import { assertAggregateStateFunction } from './utils/aggregate-state-functions.js';
|
|
12
12
|
export function resolveDimensionExpression(ds, dimensionName, joinCtx) {
|
|
13
13
|
if (joinCtx && isQualifiedField(dimensionName)) {
|
|
14
|
-
return
|
|
14
|
+
return resolveQualifiedExpression(ds, dimensionName, joinCtx);
|
|
15
15
|
}
|
|
16
16
|
const definition = ds.dimensions[dimensionName];
|
|
17
17
|
if (definition?.sql) {
|
|
@@ -22,50 +22,51 @@ export function resolveDimensionExpression(ds, dimensionName, joinCtx) {
|
|
|
22
22
|
}
|
|
23
23
|
export function resolveFilterField(ds, filterField, joinCtx) {
|
|
24
24
|
if (joinCtx && isQualifiedField(filterField)) {
|
|
25
|
-
return
|
|
25
|
+
return resolveQualifiedExpression(ds, filterField, joinCtx);
|
|
26
26
|
}
|
|
27
27
|
const resolvedField = ds.filters[filterField]?.field ?? filterField;
|
|
28
28
|
return resolveDimensionExpression(ds, resolvedField, joinCtx);
|
|
29
29
|
}
|
|
30
|
-
export function buildDimensionSelectionPlan(ds, dimensions, grain, joinCtx, timezone, dialect
|
|
30
|
+
export function buildDimensionSelectionPlan(ds, dimensions, grain, joinCtx, timezone, dialect) {
|
|
31
31
|
const selectParts = [];
|
|
32
32
|
const groupByParts = new Set();
|
|
33
33
|
if (grain) {
|
|
34
|
-
|
|
35
|
-
if (!fn) {
|
|
34
|
+
if (!isSupportedTimeGrain(grain)) {
|
|
36
35
|
throw new Error(`Unsupported time grain "${grain}".`);
|
|
37
36
|
}
|
|
38
37
|
const time = resolveDimensionExpression(ds, String(ds.timeKey), joinCtx);
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
const period = dialect.quoteIdentifier('period');
|
|
39
|
+
selectParts.push(`${dialect.truncateTime(queryTimeSql(dialect, time, timezone), grain)} AS ${period}`);
|
|
40
|
+
groupByParts.add(period);
|
|
41
41
|
}
|
|
42
42
|
for (const dimensionName of dimensions) {
|
|
43
43
|
const expression = resolveDimensionExpression(ds, dimensionName, joinCtx);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
? dialect.quoteIdentifier(dimensionName)
|
|
49
|
-
: dimensionName;
|
|
50
|
-
selectParts.push(`${expression} AS ${alias}`);
|
|
51
|
-
groupByParts.add(alias);
|
|
52
|
-
}
|
|
53
|
-
else if (expression === dimensionName) {
|
|
44
|
+
// Every generated alias is quoted: reserved words and engines that fold
|
|
45
|
+
// unquoted case (Postgres) must keep the semantic name. With joins in
|
|
46
|
+
// scope every selection is table-qualified, so it is always aliased.
|
|
47
|
+
if (!joinCtx && expression === dimensionName) {
|
|
54
48
|
selectParts.push(dimensionName);
|
|
55
49
|
groupByParts.add(dimensionName);
|
|
56
50
|
}
|
|
57
51
|
else {
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
const alias = dialect.quoteIdentifier(dimensionName);
|
|
53
|
+
selectParts.push(`${expression} AS ${alias}`);
|
|
54
|
+
// A qualified alias (`customer.tier`) can resolve to the physical joined
|
|
55
|
+
// column, so group on its guarded expression: the match marker stays
|
|
56
|
+
// part of the key whatever the engine's alias-resolution rules.
|
|
57
|
+
groupByParts.add(joinCtx && isQualifiedField(dimensionName) ? expression : alias);
|
|
60
58
|
}
|
|
61
59
|
}
|
|
62
60
|
return { selectParts, groupByParts: Array.from(groupByParts) };
|
|
63
61
|
}
|
|
64
|
-
export function applyAggregationSpec(qb, ds, spec,
|
|
62
|
+
export function applyAggregationSpec(qb, ds, spec, name, joinCtx, dialect, expressions) {
|
|
63
|
+
// The semantic name is the output alias, quoted so it survives reserved
|
|
64
|
+
// words and case folding; messages keep the unquoted name.
|
|
65
|
+
const alias = dialect.quoteIdentifier(name);
|
|
65
66
|
if (spec.sql) {
|
|
66
|
-
assertNoRawSqlUnderJoins('measure',
|
|
67
|
+
assertNoRawSqlUnderJoins('measure', name, spec.sql, joinCtx);
|
|
67
68
|
}
|
|
68
|
-
const fieldOrExpr = expressions?.field ?? applyFilteredAggregationExpression(ds, spec, spec.sql ?? resolveDimensionExpression(ds, spec.field, joinCtx), joinCtx);
|
|
69
|
+
const fieldOrExpr = expressions?.field ?? applyFilteredAggregationExpression(ds, spec, spec.sql ?? resolveDimensionExpression(ds, spec.field, joinCtx), joinCtx, dialect);
|
|
69
70
|
switch (spec.aggregation) {
|
|
70
71
|
case "sum":
|
|
71
72
|
return qb.sum(fieldOrExpr, alias);
|
|
@@ -82,7 +83,7 @@ export function applyAggregationSpec(qb, ds, spec, alias, joinCtx, expressions)
|
|
|
82
83
|
case "argMax":
|
|
83
84
|
case "argMin": {
|
|
84
85
|
if (!spec.argField) {
|
|
85
|
-
throw new Error(`Aggregation "${spec.aggregation}" for "${
|
|
86
|
+
throw new Error(`Aggregation "${spec.aggregation}" for "${name}" requires an argField ("by" column).`);
|
|
86
87
|
}
|
|
87
88
|
const argExpr = expressions?.arg ?? resolveDimensionExpression(ds, spec.argField, joinCtx);
|
|
88
89
|
if (spec.aggregation === "argMax") {
|
|
@@ -98,7 +99,7 @@ export function applyAggregationSpec(qb, ds, spec, alias, joinCtx, expressions)
|
|
|
98
99
|
}
|
|
99
100
|
case "percentile": {
|
|
100
101
|
if (spec.level == null) {
|
|
101
|
-
throw new Error(`Aggregation "percentile" for "${
|
|
102
|
+
throw new Error(`Aggregation "percentile" for "${name}" requires a level.`);
|
|
102
103
|
}
|
|
103
104
|
validatePercentileLevel(spec.level);
|
|
104
105
|
if (!qb.quantile) {
|
|
@@ -111,6 +112,16 @@ export function applyAggregationSpec(qb, ds, spec, alias, joinCtx, expressions)
|
|
|
111
112
|
throw new Error('Query builder does not support approxCountDistinct aggregations.');
|
|
112
113
|
}
|
|
113
114
|
return qb.approxCountDistinct(fieldOrExpr, alias);
|
|
115
|
+
case "merge": {
|
|
116
|
+
assertAggregateStateFunction(spec.stateFunction, `Measure "${name}"`);
|
|
117
|
+
if (spec.filters?.length) {
|
|
118
|
+
throw new Error(`Measure filters are not supported on merge aggregations ("${name}").`);
|
|
119
|
+
}
|
|
120
|
+
if (!qb.mergeState) {
|
|
121
|
+
throw new Error('Query builder does not support merge aggregations (mergeState).');
|
|
122
|
+
}
|
|
123
|
+
return qb.mergeState(spec.stateFunction, fieldOrExpr, alias);
|
|
124
|
+
}
|
|
114
125
|
case "stddev":
|
|
115
126
|
if (!qb.stddev) {
|
|
116
127
|
throw new Error('Query builder does not support stddev aggregations.');
|
|
@@ -125,20 +136,28 @@ export function applyAggregationSpec(qb, ds, spec, alias, joinCtx, expressions)
|
|
|
125
136
|
throw new Error(`Unknown aggregation type: ${spec.aggregation}`);
|
|
126
137
|
}
|
|
127
138
|
}
|
|
128
|
-
export function applyMeasureDefinition(qb, ds, name, definition, joinCtx) {
|
|
129
|
-
return applyAggregationSpec(qb, ds, measureToAggregationSpec(name, definition), name, joinCtx);
|
|
139
|
+
export function applyMeasureDefinition(qb, ds, name, definition, joinCtx, dialect) {
|
|
140
|
+
return applyAggregationSpec(qb, ds, measureToAggregationSpec(name, definition), name, joinCtx, dialect);
|
|
130
141
|
}
|
|
131
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Appends ORDER BY, LIMIT and OFFSET. Under joins, an order on a selected
|
|
144
|
+
* qualified dimension repeats its guarded expression (the GROUP BY key) rather
|
|
145
|
+
* than naming the alias, which the engine may resolve to the raw joined column;
|
|
146
|
+
* any other qualified order (a related measure) sorts by its quoted alias.
|
|
147
|
+
*/
|
|
148
|
+
export function appendOrderLimitOffset(qb, orderBy, grain, limit, offset, joinCtx, dialect, selection) {
|
|
132
149
|
if (orderBy && orderBy.length > 0) {
|
|
133
150
|
for (const order of orderBy) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
151
|
+
// A selected related dimension orders by its guarded expression, for the
|
|
152
|
+
// same alias-resolution reason it groups by it.
|
|
153
|
+
const column = joinCtx && isQualifiedField(order.field) && selection?.dimensions.includes(order.field)
|
|
154
|
+
? resolveDimensionExpression(selection.ds, order.field, joinCtx)
|
|
155
|
+
: dialect.quoteIdentifier(order.field);
|
|
137
156
|
qb = qb.orderBy(column, semanticOrderDirection(order.direction));
|
|
138
157
|
}
|
|
139
158
|
}
|
|
140
159
|
else if (grain) {
|
|
141
|
-
qb = qb.orderBy("period", "ASC");
|
|
160
|
+
qb = qb.orderBy(dialect.quoteIdentifier("period"), "ASC");
|
|
142
161
|
}
|
|
143
162
|
if (limit != null) {
|
|
144
163
|
qb = qb.limit(limit);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relationship-check.d.ts","sourceRoot":"","sources":["../src/relationship-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;
|
|
1
|
+
{"version":3,"file":"relationship-check.d.ts","sourceRoot":"","sources":["../src/relationship-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAyB,KAAK,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAGnG,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,mCAAmC,CAAC;AAE3C,YAAY,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAE9E,MAAM,WAAW,yBAAyB;IACxC,uDAAuD;IACvD,YAAY,EAAE,wBAAwB,CAAC;IACvC;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,6DAA6D;IAC7D,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,wBAAwB;IACvC,oEAAoE;IACpE,EAAE,EAAE,OAAO,CAAC;IACZ,4CAA4C;IAC5C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAKD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,kBAAkB,EACtB,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,wBAAwB,CAAC,CAqCnC"}
|
|
@@ -16,8 +16,10 @@
|
|
|
16
16
|
* }
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
|
+
import { datasetSourceBuilder } from './utils/dataset-source.js';
|
|
19
20
|
import { toQueryBuilderFactory } from './query-builder-protocol.js';
|
|
20
21
|
import { getRuntimeTenantPredicate, validateTenantRuntime } from './utils/tenant-runtime.js';
|
|
22
|
+
import { resolveDatasetSqlDialect } from './utils/dataset-sql-dialect.js';
|
|
21
23
|
import { listToOneRelationships, readCount, relationshipKeyIssue, } from './utils/relationship-key-check.js';
|
|
22
24
|
const ROWS_ALIAS = '__hq_rows';
|
|
23
25
|
const KEYS_ALIAS = '__hq_keys';
|
|
@@ -29,6 +31,7 @@ const KEYS_ALIAS = '__hq_keys';
|
|
|
29
31
|
*/
|
|
30
32
|
export async function checkRelationships(ds, options) {
|
|
31
33
|
const factory = toQueryBuilderFactory(options.queryBuilder);
|
|
34
|
+
const dialect = resolveDatasetSqlDialect(factory);
|
|
32
35
|
const tenantPredicate = getRuntimeTenantPredicate(options.context);
|
|
33
36
|
const entries = listToOneRelationships(ds, options.relationships);
|
|
34
37
|
const issues = [];
|
|
@@ -37,10 +40,9 @@ export async function checkRelationships(ds, options) {
|
|
|
37
40
|
if (tenantError) {
|
|
38
41
|
throw new Error(`Cannot check relationship "${entry.relationship}": ${tenantError}`);
|
|
39
42
|
}
|
|
40
|
-
let qb = factory
|
|
41
|
-
.table(entry.target.source)
|
|
43
|
+
let qb = datasetSourceBuilder(factory, entry.target)
|
|
42
44
|
.count(entry.column, ROWS_ALIAS)
|
|
43
|
-
.countDistinct(entry.columns ?
|
|
45
|
+
.countDistinct(entry.columns ? dialect.packRow(entry.columns) : entry.column, KEYS_ALIAS);
|
|
44
46
|
if (entry.columns) {
|
|
45
47
|
for (const column of entry.columns)
|
|
46
48
|
qb = qb.where(column, 'isNotNull', undefined);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@hypequery/datasets/schemas`: Zod-backed query schemas and agent tools.
|
|
3
|
+
*
|
|
4
|
+
* Everything here builds or reads Zod schemas. It lives apart from the root
|
|
5
|
+
* entry so that defining and querying datasets never loads Zod. In 1.0 the
|
|
6
|
+
* root entry stops re-exporting these and Zod becomes an optional peer
|
|
7
|
+
* dependency needed only by this entry.
|
|
8
|
+
*/
|
|
9
|
+
export { generateDatasetTools, toOpenAITools, toAISDKTools, toMcpTools, } from './tools.js';
|
|
10
|
+
export type { AISDKToolDefinition, DatasetToolAnalytics, DatasetToolMode, GenerateDatasetToolsOptions, JsonSchema, McpToolDefinition, OpenAIToolDefinition, SemanticToolDefinition, } from './tools.js';
|
|
11
|
+
export { buildDatasetInputSchema, buildMetricInputSchema, buildCanonicalSemanticQuerySchemas, toSemanticJsonSchema, DEFAULT_SEMANTIC_QUERY_SCHEMA_LIMITS, buildDatasetInputProtocolSchema, buildMetricInputProtocolSchema, } from './semantic-query-schema.js';
|
|
12
|
+
export type { CanonicalSemanticQuerySchemas, SemanticMetricQueryContract, SemanticQuerySchemaLimits, SemanticQuerySchemaOptions, SemanticQuerySchemaSource, } from './semantic-query-schema.js';
|
|
13
|
+
export { ProtocolSchemaAdapterError, zodToProtocolSchema } from './protocol-schema-adapter.js';
|
|
14
|
+
export type { AnyZodSchema } from './utils/zod-schema-version.js';
|
|
15
|
+
export { buildClientContractQuerySchemas } from './client-contract/query-schema.js';
|
|
16
|
+
export type { ClientContractQuerySchemas, ClientEndpointQuerySchema } from './client-contract/query-schema.js';
|
|
17
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,YAAY,EACZ,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,2BAA2B,EAC3B,UAAU,EACV,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,kCAAkC,EAClC,oBAAoB,EACpB,oCAAoC,EACpC,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,6BAA6B,EAC7B,2BAA2B,EAC3B,yBAAyB,EACzB,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC/F,YAAY,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGlE,OAAO,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AACpF,YAAY,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC"}
|
package/dist/schemas.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@hypequery/datasets/schemas`: Zod-backed query schemas and agent tools.
|
|
3
|
+
*
|
|
4
|
+
* Everything here builds or reads Zod schemas. It lives apart from the root
|
|
5
|
+
* entry so that defining and querying datasets never loads Zod. In 1.0 the
|
|
6
|
+
* root entry stops re-exporting these and Zod becomes an optional peer
|
|
7
|
+
* dependency needed only by this entry.
|
|
8
|
+
*/
|
|
9
|
+
// Agent/tool metadata
|
|
10
|
+
export { generateDatasetTools, toOpenAITools, toAISDKTools, toMcpTools, } from './tools.js';
|
|
11
|
+
// Canonical semantic query schemas shared by Serve, MCP, and agent adapters.
|
|
12
|
+
export { buildDatasetInputSchema, buildMetricInputSchema, buildCanonicalSemanticQuerySchemas, toSemanticJsonSchema, DEFAULT_SEMANTIC_QUERY_SCHEMA_LIMITS, buildDatasetInputProtocolSchema, buildMetricInputProtocolSchema, } from './semantic-query-schema.js';
|
|
13
|
+
// Zod to RFC 0004 protocol schemas, for Zod 3 or Zod 4 input.
|
|
14
|
+
export { ProtocolSchemaAdapterError, zodToProtocolSchema } from './protocol-schema-adapter.js';
|
|
15
|
+
// Client-contract query schemas.
|
|
16
|
+
export { buildClientContractQuerySchemas } from './client-contract/query-schema.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"semantic-planner.d.ts","sourceRoot":"","sources":["../src/semantic-planner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAGhB,WAAW,EACX,SAAS,EACT,gBAAgB,EACjB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EACV,QAAQ,EAIT,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"semantic-planner.d.ts","sourceRoot":"","sources":["../src/semantic-planner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAGhB,WAAW,EACX,SAAS,EACT,gBAAgB,EACjB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EACV,QAAQ,EAIT,MAAM,oBAAoB,CAAC;AA+M5B,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,kBAAkB,EACtB,KAAK,GAAE,YAAiB,EACxB,OAAO,CAAC,EAAE,gBAAgB,GACzB,QAAQ,CAoBV;AA2FD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,GAAG,gBAAgB,EACpC,KAAK,GAAE,WAAgB,EACvB,OAAO,CAAC,EAAE,gBAAgB,GACzB,QAAQ,CAcV"}
|