@hypequery/datasets 0.20.0 → 0.22.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 +6 -0
- package/dist/api.type-test.js +7 -1
- package/dist/catalog.d.ts +7 -3
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +15 -3
- package/dist/contract.d.ts +1 -1
- package/dist/contract.d.ts.map +1 -1
- package/dist/dataset-compilation.d.ts +45 -0
- package/dist/dataset-compilation.d.ts.map +1 -0
- package/dist/dataset-compilation.js +1 -0
- package/dist/dataset-query.d.ts +3 -3
- package/dist/dataset-query.d.ts.map +1 -1
- package/dist/dataset-query.js +7 -71
- package/dist/dataset-sql-dialect.d.ts +11 -0
- package/dist/dataset-sql-dialect.d.ts.map +1 -0
- package/dist/dataset-sql-dialect.js +1 -0
- package/dist/dataset.d.ts +3 -2
- package/dist/dataset.d.ts.map +1 -1
- package/dist/execution-capabilities.d.ts +28 -0
- package/dist/execution-capabilities.d.ts.map +1 -0
- package/dist/execution-capabilities.js +17 -0
- package/dist/execution-capabilities.json +13 -0
- package/dist/executor.d.ts +17 -38
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +37 -400
- package/dist/index.d.ts +9 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/internal.d.ts +3 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +2 -0
- package/dist/measure.d.ts +56 -19
- package/dist/measure.d.ts.map +1 -1
- package/dist/measure.js +5 -65
- package/dist/metric-query-engine.d.ts +29 -0
- package/dist/metric-query-engine.d.ts.map +1 -0
- package/dist/metric-query-engine.js +106 -0
- package/dist/portable-executor.d.ts +20 -6
- package/dist/portable-executor.d.ts.map +1 -1
- package/dist/portable-executor.js +29 -9
- package/dist/query-builder-protocol.d.ts +4 -0
- package/dist/query-builder-protocol.d.ts.map +1 -1
- package/dist/query-helpers.d.ts +10 -10
- package/dist/query-helpers.d.ts.map +1 -1
- package/dist/query-helpers.js +1 -3
- package/dist/query-planner.d.ts +7 -3
- package/dist/query-planner.d.ts.map +1 -1
- package/dist/query-planner.js +10 -12
- package/dist/semantic-planner.d.ts.map +1 -1
- package/dist/semantic-planner.js +2 -0
- package/dist/semantic-query-schema.d.ts.map +1 -1
- package/dist/semantic-query-schema.js +3 -3
- package/dist/types.d.ts +22 -16
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/agent-catalog-projection.d.ts +1 -0
- package/dist/utils/agent-catalog-projection.d.ts.map +1 -1
- package/dist/utils/agent-catalog-projection.js +2 -1
- package/dist/utils/approximate-measures.d.ts +1 -0
- package/dist/utils/approximate-measures.d.ts.map +1 -1
- package/dist/utils/approximate-measures.js +10 -4
- package/dist/utils/base-measure-definition.d.ts +23 -0
- package/dist/utils/base-measure-definition.d.ts.map +1 -0
- package/dist/utils/base-measure-definition.js +65 -0
- package/dist/utils/build-dataset-query-builder.d.ts +5 -0
- package/dist/utils/build-dataset-query-builder.d.ts.map +1 -0
- package/dist/utils/build-dataset-query-builder.js +62 -0
- package/dist/utils/clickhouse-dataset-sql-dialect.d.ts +4 -0
- package/dist/utils/clickhouse-dataset-sql-dialect.d.ts.map +1 -0
- package/dist/utils/clickhouse-dataset-sql-dialect.js +6 -0
- package/dist/utils/compile-dataset-query.d.ts +10 -0
- package/dist/utils/compile-dataset-query.d.ts.map +1 -0
- package/dist/utils/compile-dataset-query.js +71 -0
- package/dist/utils/composite-time-measure-sql.d.ts +10 -0
- package/dist/utils/composite-time-measure-sql.d.ts.map +1 -0
- package/dist/utils/composite-time-measure-sql.js +61 -0
- package/dist/utils/dataset-derived-query.d.ts +1 -2
- package/dist/utils/dataset-derived-query.d.ts.map +1 -1
- package/dist/utils/dataset-derived-query.js +16 -30
- package/dist/utils/dataset-filter-types.d.ts +28 -0
- package/dist/utils/dataset-filter-types.d.ts.map +1 -0
- package/dist/utils/dataset-filter-types.js +1 -0
- package/dist/utils/dataset-query-validation.d.ts.map +1 -1
- package/dist/utils/dataset-query-validation.js +15 -3
- package/dist/utils/dataset-sql-dialect.d.ts +5 -0
- package/dist/utils/dataset-sql-dialect.d.ts.map +1 -0
- package/dist/utils/dataset-sql-dialect.js +5 -0
- package/dist/utils/dataset-target.d.ts +3 -0
- package/dist/utils/dataset-target.d.ts.map +1 -0
- package/dist/utils/dataset-target.js +3 -0
- package/dist/utils/derived-measure-sql.d.ts +1 -0
- package/dist/utils/derived-measure-sql.d.ts.map +1 -1
- package/dist/utils/derived-measure-sql.js +9 -6
- package/dist/utils/derived-measure-validation.d.ts.map +1 -1
- package/dist/utils/derived-measure-validation.js +4 -25
- package/dist/utils/filter-definition.d.ts +3 -0
- package/dist/utils/filter-definition.d.ts.map +1 -0
- package/dist/utils/filter-definition.js +3 -0
- package/dist/utils/measure-dependencies.d.ts +8 -0
- package/dist/utils/measure-dependencies.d.ts.map +1 -0
- package/dist/utils/measure-dependencies.js +44 -0
- package/dist/utils/measure-evaluation-graph.d.ts +23 -0
- package/dist/utils/measure-evaluation-graph.d.ts.map +1 -0
- package/dist/utils/measure-evaluation-graph.js +38 -0
- package/dist/utils/measure-time-grains.d.ts.map +1 -1
- package/dist/utils/measure-time-grains.js +4 -2
- package/dist/utils/metric-derived-query.d.ts +8 -0
- package/dist/utils/metric-derived-query.d.ts.map +1 -0
- package/dist/utils/metric-derived-query.js +106 -0
- package/dist/utils/metric-query-builder.d.ts +5 -0
- package/dist/utils/metric-query-builder.d.ts.map +1 -0
- package/dist/utils/metric-query-builder.js +50 -0
- package/dist/utils/metric-query-result.d.ts +10 -0
- package/dist/utils/metric-query-result.d.ts.map +1 -0
- package/dist/utils/metric-query-result.js +18 -0
- package/dist/utils/metric-query-validation.d.ts +6 -0
- package/dist/utils/metric-query-validation.d.ts.map +1 -0
- package/dist/utils/metric-query-validation.js +116 -0
- package/dist/utils/relationship-builder-plan.d.ts +4 -2
- package/dist/utils/relationship-builder-plan.d.ts.map +1 -1
- package/dist/utils/relationship-builder-plan.js +10 -13
- package/dist/utils/relationship-measure-sql.d.ts +14 -0
- package/dist/utils/relationship-measure-sql.d.ts.map +1 -0
- package/dist/utils/relationship-measure-sql.js +44 -0
- package/dist/utils/relationship-measure-types.d.ts +36 -0
- package/dist/utils/relationship-measure-types.d.ts.map +1 -0
- package/dist/utils/relationship-measure-types.js +1 -0
- package/dist/utils/relationship-measures.d.ts +23 -0
- package/dist/utils/relationship-measures.d.ts.map +1 -0
- package/dist/utils/relationship-measures.js +62 -0
- package/dist/utils/relationship-validation.d.ts +1 -1
- package/dist/utils/relationship-validation.d.ts.map +1 -1
- package/dist/utils/relationship-validation.js +3 -5
- package/dist/utils/semantic-query-syntax.d.ts +6 -0
- package/dist/utils/semantic-query-syntax.d.ts.map +1 -0
- package/dist/utils/semantic-query-syntax.js +25 -0
- package/dist/utils/shift-measure-grains.d.ts +5 -0
- package/dist/utils/shift-measure-grains.d.ts.map +1 -0
- package/dist/utils/shift-measure-grains.js +10 -0
- package/dist/utils/shift-measure-sql.d.ts +5 -2
- package/dist/utils/shift-measure-sql.d.ts.map +1 -1
- package/dist/utils/shift-measure-sql.js +25 -8
- package/dist/utils/shift-measure-validation.js +3 -3
- package/dist/utils/shift-wall-time-sql.d.ts +4 -0
- package/dist/utils/shift-wall-time-sql.d.ts.map +1 -0
- package/dist/utils/shift-wall-time-sql.js +17 -0
- package/dist/utils/snapshot-execution-context.d.ts +4 -0
- package/dist/utils/snapshot-execution-context.d.ts.map +1 -0
- package/dist/utils/snapshot-execution-context.js +16 -0
- package/dist/utils/time-measure-axis-sql.d.ts +1 -0
- package/dist/utils/time-measure-axis-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-axis-sql.js +5 -4
- package/dist/utils/time-measure-axis.d.ts.map +1 -1
- package/dist/utils/time-measure-axis.js +3 -2
- package/dist/utils/time-measure-context-sql.d.ts +6 -0
- package/dist/utils/time-measure-context-sql.d.ts.map +1 -0
- package/dist/utils/time-measure-context-sql.js +21 -0
- package/dist/utils/time-measure-dataset-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-dataset-sql.js +27 -9
- package/dist/utils/time-measure-leaf-sql.d.ts +14 -0
- package/dist/utils/time-measure-leaf-sql.d.ts.map +1 -0
- package/dist/utils/time-measure-leaf-sql.js +52 -0
- package/dist/utils/time-measure-result-sql.d.ts +1 -1
- package/dist/utils/time-measure-result-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-result-sql.js +4 -3
- package/dist/utils/time-measure-source-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-source-sql.js +8 -4
- package/dist/utils/time-query-measures.d.ts.map +1 -1
- package/dist/utils/time-query-measures.js +4 -8
- package/dist/utils/window-query-signature.d.ts.map +1 -1
- package/dist/utils/window-query-signature.js +12 -2
- package/dist/validation.js +1 -1
- package/package.json +8 -7
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { GRAIN_FUNCTIONS } from '../constants.js';
|
|
2
|
+
import { addTimeSql as add, subtractTimeSql as subtract } from './time-arithmetic-sql.js';
|
|
3
|
+
import { calendarBucketGuardSql } from './time-axis-calendar-guard.js';
|
|
4
|
+
import { shiftRangePredicateSql } from './shift-measure-sql.js';
|
|
5
|
+
import { isCountAggregation, windowAggregateSql } from './window-aggregation-sql.js';
|
|
6
|
+
/** Keyed source membership retains distinct/average semantics and row multiplicity. */
|
|
7
|
+
export function timeMeasureLeafSql(id, context, base, window, axis, dims) {
|
|
8
|
+
const keys = dims.map(dim => dim.alias);
|
|
9
|
+
const ranges = `_hq_ranges${id}`;
|
|
10
|
+
const rows = `_hq_rows${id}`;
|
|
11
|
+
const aggregate = `_hq_leaf${id}`;
|
|
12
|
+
const value = `_hq_value${id}`;
|
|
13
|
+
const group = `_hq_period${keys.length ? `, ${keys.join(', ')}` : ''}`;
|
|
14
|
+
const expression = windowAggregateSql(base.definition, base.value, base.arg);
|
|
15
|
+
if (window?.cumulative) {
|
|
16
|
+
const population = `_hq_history${id}`;
|
|
17
|
+
const partial = `_hq_partial${id}`;
|
|
18
|
+
const operation = base.definition.aggregation === 'count' ? 'sum' : base.definition.aggregation;
|
|
19
|
+
const partition = keys.length ? `tuple(${keys.join(', ')})` : 'tuple(0)';
|
|
20
|
+
const historyGroup = `_hq_time${keys.length ? `, ${keys.join(', ')}` : ''}`;
|
|
21
|
+
return {
|
|
22
|
+
ctes: [
|
|
23
|
+
`${population} AS (SELECT * FROM _hq_source WHERE _hq_time < (SELECT max(_hq_eval_end) FROM _hq_context${context}))`,
|
|
24
|
+
`${partial} AS (SELECT ${historyGroup}, ${partition} AS _hq_partition, toNullable(${expression}) AS _hq_partial FROM ${population} GROUP BY ${historyGroup})`,
|
|
25
|
+
`${aggregate} AS (SELECT _hq_time, _hq_partition, ${operation}OrNull(_hq_partial) OVER (PARTITION BY _hq_partition ORDER BY _hq_time ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS ${value} FROM ${partial})`,
|
|
26
|
+
],
|
|
27
|
+
population, aggregate, context, cumulative: true, guard: '0',
|
|
28
|
+
count: isCountAggregation(base.definition),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const lower = window?.trailing ? subtract('_hq_eval_end', window.trailing.amount, window.trailing.unit)
|
|
32
|
+
: window?.toDate ? `${GRAIN_FUNCTIONS[window.toDate]}(_hq_eval_period)` : '_hq_eval_lower';
|
|
33
|
+
const upper = window ? '_hq_eval_end' : '_hq_eval_upper';
|
|
34
|
+
const lowerInclusive = window ? '1' : '_hq_lower_inclusive';
|
|
35
|
+
const upperInclusive = window ? '0' : '_hq_upper_inclusive';
|
|
36
|
+
const first = `${GRAIN_FUNCTIONS[axis.grain]}(_hq_scan_lower)`;
|
|
37
|
+
const last = `${GRAIN_FUNCTIONS[axis.grain]}(_hq_scan_upper)`;
|
|
38
|
+
const count = `greatest(0, dateDiff('${axis.grain}', ${first}, ${last}) + if(_hq_scan_upper > ${last} OR _hq_scan_upper_inclusive, 1, 0))`;
|
|
39
|
+
const fanout = window ? `throwIf(${count} > 1000, 'A window row contributes to more than 1000 buckets.')` : '0';
|
|
40
|
+
const guard = `${fanout} + ${calendarBucketGuardSql(first, `${count} + ${fanout}`, axis.grain)}`;
|
|
41
|
+
const predicate = shiftRangePredicateSql('r._hq_time', { lower: 'b._hq_scan_lower', upper: 'b._hq_scan_upper', lowerInclusive: 'b._hq_scan_lower_inclusive', upperInclusive: 'b._hq_scan_upper_inclusive' });
|
|
42
|
+
return {
|
|
43
|
+
ctes: [
|
|
44
|
+
`${ranges} AS (SELECT _hq_period, ${lower} AS _hq_scan_lower, ${upper} AS _hq_scan_upper, ${lowerInclusive} AS _hq_scan_lower_inclusive, ${upperInclusive} AS _hq_scan_upper_inclusive FROM _hq_context${context})`,
|
|
45
|
+
`_hq_keys${id} AS (SELECT *, ${add(first, `arrayJoin(range(toUInt64(${count} + ${guard})))`, axis.grain)} AS _hq_source_period FROM ${ranges})`,
|
|
46
|
+
`${rows} AS (SELECT r.*, b._hq_period FROM _hq_source AS r INNER JOIN _hq_keys${id} AS b ON ${GRAIN_FUNCTIONS[axis.grain]}(r._hq_time) = b._hq_source_period WHERE ${predicate})`,
|
|
47
|
+
`${aggregate} AS (SELECT ${group}, toNullable(${expression}) AS ${value} FROM ${rows} GROUP BY ${group})`,
|
|
48
|
+
],
|
|
49
|
+
population: rows, aggregate, context, cumulative: false,
|
|
50
|
+
guard: `(SELECT coalesce(max(${guard}), 0) FROM ${ranges})`, count: isCountAggregation(base.definition),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -2,5 +2,5 @@ import type { AnyDatasetInstance, DatasetQuery } from '../types.js';
|
|
|
2
2
|
import type { DatasetQueryExecutionOptions } from '../dataset-query.js';
|
|
3
3
|
import type { TimeMeasureSqlDimension } from './time-measure-source-sql.js';
|
|
4
4
|
/** Evaluate formulas after aggregation, then apply output ordering and pagination. */
|
|
5
|
-
export declare function buildTimeMeasureResultSql(ds: AnyDatasetInstance, query: DatasetQuery, options: DatasetQueryExecutionOptions, dims: readonly TimeMeasureSqlDimension[], ctes: readonly string[], validationGuard: string): string;
|
|
5
|
+
export declare function buildTimeMeasureResultSql(ds: AnyDatasetInstance, query: DatasetQuery, options: DatasetQueryExecutionOptions, dims: readonly TimeMeasureSqlDimension[], ctes: readonly string[], validationGuard: string, formulasEvaluated?: boolean): string;
|
|
6
6
|
//# sourceMappingURL=time-measure-result-sql.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-measure-result-sql.d.ts","sourceRoot":"","sources":["../../src/utils/time-measure-result-sql.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"time-measure-result-sql.d.ts","sourceRoot":"","sources":["../../src/utils/time-measure-result-sql.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AAIxE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAE5E,sFAAsF;AACtF,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,4BAA4B,EACrC,IAAI,EAAE,SAAS,uBAAuB,EAAE,EACxC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,eAAe,EAAE,MAAM,EACvB,iBAAiB,UAAQ,GACxB,MAAM,CAuBR"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
import { semanticOrderDirection } from './semantic-query-syntax.js';
|
|
1
2
|
import { quoteSQLIdentifier } from '../sql-utils.js';
|
|
2
3
|
import { getDerivedMeasure } from './dataset-measures.js';
|
|
3
4
|
import { derivedProjection } from './derived-measure-sql.js';
|
|
4
5
|
/** Evaluate formulas after aggregation, then apply output ordering and pagination. */
|
|
5
|
-
export function buildTimeMeasureResultSql(ds, query, options, dims, ctes, validationGuard) {
|
|
6
|
+
export function buildTimeMeasureResultSql(ds, query, options, dims, ctes, validationGuard, formulasEvaluated = false) {
|
|
6
7
|
const selected = query.measures ?? [];
|
|
7
8
|
const projections = [
|
|
8
9
|
quoteSQLIdentifier('period'),
|
|
9
10
|
...dims.map(dimension => quoteSQLIdentifier(dimension.name)),
|
|
10
11
|
...selected.map(name => {
|
|
11
12
|
const derived = getDerivedMeasure(ds.measures, name);
|
|
12
|
-
return derived ? derivedProjection(name, derived) : quoteSQLIdentifier(name);
|
|
13
|
+
return derived && !formulasEvaluated ? derivedProjection(name, derived) : quoteSQLIdentifier(name);
|
|
13
14
|
}),
|
|
14
15
|
];
|
|
15
16
|
// Keep toSQL independently guarded too. This branch produces no valid
|
|
@@ -20,7 +21,7 @@ export function buildTimeMeasureResultSql(ds, query, options, dims, ctes, valida
|
|
|
20
21
|
+ ` UNION ALL SELECT ${nullProjections} FROM _hq_bounds WHERE ${validationGuard} = 1)`;
|
|
21
22
|
let sql = `WITH ${[...ctes, resultCte].join(',\n')} SELECT ${outputNames.map(quoteSQLIdentifier).join(', ')} FROM _hq_result`;
|
|
22
23
|
const order = query.orderBy?.length ? query.orderBy : [{ field: 'period', direction: 'asc' }];
|
|
23
|
-
sql += ` ORDER BY ${order.map(item => `${quoteSQLIdentifier(item.field)} ${item.direction
|
|
24
|
+
sql += ` ORDER BY ${order.map(item => `${quoteSQLIdentifier(item.field)} ${semanticOrderDirection(item.direction)}`).join(', ')}`;
|
|
24
25
|
const limit = options.executionLimit ?? query.limit;
|
|
25
26
|
if (limit !== undefined)
|
|
26
27
|
sql += ` LIMIT ${limit}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-measure-source-sql.d.ts","sourceRoot":"","sources":["../../src/utils/time-measure-source-sql.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"time-measure-source-sql.d.ts","sourceRoot":"","sources":["../../src/utils/time-measure-source-sql.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACrG,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AAUxE,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,iBAAiB,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,OAAO,EAAE,CAAC;IACtB,UAAU,EAAE,uBAAuB,EAAE,CAAC;IACtC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,0FAA0F;AAC1F,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC3B,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,OAAO,EAAE,4BAA4B,GACpC,oBAAoB,CA6DtB"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { resolveRelationshipMeasure } from './relationship-measures.js';
|
|
2
|
+
import { relationshipMeasureExpressions } from './relationship-measure-sql.js';
|
|
1
3
|
import { queryTimeSql } from './query-timezone.js';
|
|
2
4
|
import { resolveDimensionExpression, resolveFilterField, resolveTenantFilterColumn } from '../query-planner.js';
|
|
3
5
|
import { applyRelationshipJoins, buildRelationshipBuilderContext, qualifyBaseColumn } from './relationship-builder-plan.js';
|
|
@@ -19,7 +21,8 @@ export function buildTimeMeasureSourceSql(ds, query, baseNames, filters, options
|
|
|
19
21
|
for (const dimension of dims)
|
|
20
22
|
sourceParts.push(resolveDimensionExpression(ds, dimension.name, joinCtx));
|
|
21
23
|
for (const name of baseNames) {
|
|
22
|
-
const
|
|
24
|
+
const related = name.includes('.') ? resolveRelationshipMeasure(ds, name) : undefined;
|
|
25
|
+
const definition = related?.definition ?? getBaseMeasure(ds.measures, name);
|
|
23
26
|
if (!definition)
|
|
24
27
|
throw new Error(`Window input "${name}" is not a base measure.`);
|
|
25
28
|
const spec = measureToAggregationSpec(name, definition);
|
|
@@ -28,9 +31,10 @@ export function buildTimeMeasureSourceSql(ds, query, baseNames, filters, options
|
|
|
28
31
|
const value = `_hq_v${bases.length}`;
|
|
29
32
|
const arg = `_hq_a${bases.length}`;
|
|
30
33
|
bases.push({ name, definition, value, arg });
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
sourceParts.push(
|
|
34
|
+
const expressions = related ? relationshipMeasureExpressions(ds, name, joinCtx) : undefined;
|
|
35
|
+
const expression = expressions?.field ?? spec.sql ?? resolveDimensionExpression(ds, spec.field, joinCtx);
|
|
36
|
+
sourceParts.push(expressions ? expression : applyFilteredAggregationExpression(ds, spec, expression, joinCtx));
|
|
37
|
+
sourceParts.push(expressions?.arg ?? (spec.argField ? resolveDimensionExpression(ds, spec.argField, joinCtx) : 'NULL'));
|
|
34
38
|
}
|
|
35
39
|
// A positional tuple isolates internal names from the source table's names.
|
|
36
40
|
const sourceIdentifiers = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-query-measures.d.ts","sourceRoot":"","sources":["../../src/utils/time-query-measures.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"time-query-measures.d.ts","sourceRoot":"","sources":["../../src/utils/time-query-measures.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAGzK,MAAM,MAAM,qBAAqB,GAAG,uBAAuB,GAAG,sBAAsB,CAAC;AAErF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAQzH;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,wBAAwB,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC,GAAG,OAAO,CAE3I;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAOlG"}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { measureDependencyNames } from './measure-dependencies.js';
|
|
2
|
+
import { isShiftMeasure, isWindowMeasure } from './dataset-measures.js';
|
|
2
3
|
export function selectedTimeMeasures(dataset, query) {
|
|
3
|
-
const names =
|
|
4
|
-
for (const name of query.measures ?? []) {
|
|
5
|
-
const derived = getDerivedMeasure(dataset.measures, name);
|
|
6
|
-
if (derived)
|
|
7
|
-
Object.values(derived.uses).forEach(input => names.add(input));
|
|
8
|
-
}
|
|
4
|
+
const names = measureDependencyNames(dataset.measures, query.measures ?? []);
|
|
9
5
|
const measures = new Map();
|
|
10
6
|
for (const name of names) {
|
|
11
7
|
const definition = Object.hasOwn(dataset.measures, name) ? dataset.measures[name] : undefined;
|
|
@@ -15,7 +11,7 @@ export function selectedTimeMeasures(dataset, query) {
|
|
|
15
11
|
return measures;
|
|
16
12
|
}
|
|
17
13
|
export function usesTimeMeasure(definition, measures) {
|
|
18
|
-
return Object.values(definition.uses).some(name =>
|
|
14
|
+
return measureDependencyNames(measures, Object.values(definition.uses)).some(name => isWindowMeasure(measures[name]) || isShiftMeasure(measures[name]));
|
|
19
15
|
}
|
|
20
16
|
export function rejectTimeMeasuresOnBackend(dataset, query) {
|
|
21
17
|
const measures = [...selectedTimeMeasures(dataset, query).values()];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"window-query-signature.d.ts","sourceRoot":"","sources":["../../src/utils/window-query-signature.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"window-query-signature.d.ts","sourceRoot":"","sources":["../../src/utils/window-query-signature.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMpE,uFAAuF;AACvF,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0BzG"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { measureDependencyNames } from './measure-dependencies.js';
|
|
1
2
|
import { getBaseMeasure, getDerivedMeasure } from './dataset-measures.js';
|
|
2
3
|
import { selectedTimeMeasures } from './time-query-measures.js';
|
|
3
4
|
import { windowCatalogMetadata } from './window-catalog-metadata.js';
|
|
@@ -5,16 +6,25 @@ import { measureToAggregationSpec } from './dataset-normalization.js';
|
|
|
5
6
|
/** Preserve existing cache keys; add execution dependencies for windows and shifts. */
|
|
6
7
|
export function windowQuerySignature(ds, query) {
|
|
7
8
|
const timeMeasures = selectedTimeMeasures(ds, query);
|
|
8
|
-
|
|
9
|
+
const dependencies = measureDependencyNames(ds.measures, query.measures ?? []);
|
|
10
|
+
const nestedFormula = dependencies.some(name => {
|
|
11
|
+
const formula = getDerivedMeasure(ds.measures, name);
|
|
12
|
+
return formula && Object.values(formula.uses).some(input => getDerivedMeasure(ds.measures, input));
|
|
13
|
+
});
|
|
14
|
+
if (!timeMeasures.size && !nestedFormula)
|
|
9
15
|
return {};
|
|
10
16
|
return {
|
|
11
17
|
windowTimeKey: ds.timeKey,
|
|
12
18
|
windowTimeDimension: ds.timeKey ? ds.dimensions[ds.timeKey] : undefined,
|
|
19
|
+
baseInputs: dependencies.flatMap(name => {
|
|
20
|
+
const base = getBaseMeasure(ds.measures, name);
|
|
21
|
+
return base ? [{ name, ...measureToAggregationSpec(name, base) }] : [];
|
|
22
|
+
}),
|
|
13
23
|
windows: [...timeMeasures].sort(([a], [b]) => a.localeCompare(b)).map(([name, definition]) => {
|
|
14
24
|
const base = getBaseMeasure(ds.measures, definition.measure);
|
|
15
25
|
return { name, ...windowCatalogMetadata(definition), base: base ? measureToAggregationSpec(definition.measure, base) : undefined };
|
|
16
26
|
}),
|
|
17
|
-
windowFormulas:
|
|
27
|
+
windowFormulas: dependencies.flatMap(name => {
|
|
18
28
|
const derived = getDerivedMeasure(ds.measures, name);
|
|
19
29
|
if (!derived)
|
|
20
30
|
return [];
|
package/dist/validation.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hypequery/datasets",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.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",
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"dist"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@hypequery/protocol": "^0.
|
|
45
|
+
"@hypequery/protocol": "^0.18.0",
|
|
46
46
|
"@noble/hashes": "^1.8.0",
|
|
47
47
|
"zod": "^3.22.4",
|
|
48
|
-
"zod-to-json-schema": "^3.
|
|
48
|
+
"zod-to-json-schema": "^3.25.2"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"zod": "^3.22.4"
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@types/node": "^18.19.80",
|
|
60
60
|
"typescript": "^5.7.3",
|
|
61
|
-
"@vitest/coverage-v8": "^
|
|
62
|
-
"vitest": "^
|
|
63
|
-
"@hypequery/protocol-conformance": "^0.
|
|
61
|
+
"@vitest/coverage-v8": "^5.0.2",
|
|
62
|
+
"vitest": "^5.0.2",
|
|
63
|
+
"@hypequery/protocol-conformance": "^0.15.0"
|
|
64
64
|
},
|
|
65
65
|
"repository": {
|
|
66
66
|
"type": "git",
|
|
@@ -83,6 +83,7 @@
|
|
|
83
83
|
"test:types": "tsc --project tsconfig.type-tests.json",
|
|
84
84
|
"test:watch": "vitest watch",
|
|
85
85
|
"test:coverage": "vitest run --coverage",
|
|
86
|
-
"
|
|
86
|
+
"test:coverage:full": "node scripts/run-integration-tests.js --include-unit-tests --coverage",
|
|
87
|
+
"lint": "eslint \"src/**/*.ts\""
|
|
87
88
|
}
|
|
88
89
|
}
|