@hypequery/datasets 0.24.0 → 0.26.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/dist/cache/definition-identity.d.ts +9 -6
- package/dist/cache/definition-identity.d.ts.map +1 -1
- package/dist/cache/definition-identity.js +12 -6
- 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 +11 -3
- package/dist/catalog.d.ts +4 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +2 -0
- package/dist/contract.d.ts +3 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +2 -0
- package/dist/dataset-compilation.d.ts +2 -0
- package/dist/dataset-compilation.d.ts.map +1 -1
- package/dist/dataset-sql-dialect.d.ts +3 -1
- package/dist/dataset-sql-dialect.d.ts.map +1 -1
- package/dist/dataset.d.ts +3 -1
- package/dist/dataset.d.ts.map +1 -1
- package/dist/dataset.js +23 -32
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -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 +8 -1
- package/dist/protocol-adapter.d.ts.map +1 -1
- package/dist/protocol-adapter.js +4 -6
- package/dist/protocol-rehydrate.d.ts.map +1 -1
- package/dist/protocol-rehydrate.js +2 -0
- package/dist/query-builder-protocol.d.ts +3 -1
- package/dist/query-builder-protocol.d.ts.map +1 -1
- package/dist/relationship-check.d.ts.map +1 -1
- package/dist/relationship-check.js +3 -5
- package/dist/semantic-planner.d.ts.map +1 -1
- package/dist/semantic-planner.js +35 -15
- package/dist/semantic-query-schema.d.ts +6 -0
- package/dist/semantic-query-schema.d.ts.map +1 -1
- package/dist/semantic-query-schema.js +6 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +4 -3
- package/dist/types.d.ts +84 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/aggregate-state-functions.d.ts +2 -1
- package/dist/utils/aggregate-state-functions.d.ts.map +1 -1
- package/dist/utils/aggregate-state-functions.js +5 -19
- 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 +12 -15
- package/dist/utils/clickhouse-dataset-sql-dialect.d.ts.map +1 -1
- package/dist/utils/clickhouse-dataset-sql-dialect.js +3 -0
- 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 +16 -5
- 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 +19 -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 +12 -2
- package/dist/utils/dataset-source.d.ts +35 -2
- package/dist/utils/dataset-source.d.ts.map +1 -1
- package/dist/utils/dataset-source.js +47 -4
- 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/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/metric-derived-query.d.ts.map +1 -1
- package/dist/utils/metric-derived-query.js +6 -12
- 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 +7 -13
- package/dist/utils/metric-query-validation.d.ts.map +1 -1
- package/dist/utils/metric-query-validation.js +7 -1
- package/dist/utils/portable-aggregations.d.ts +6 -3
- package/dist/utils/portable-aggregations.d.ts.map +1 -1
- package/dist/utils/portable-aggregations.js +16 -7
- package/dist/utils/query-timezone.d.ts +1 -1
- package/dist/utils/query-timezone.d.ts.map +1 -1
- package/dist/utils/query-timezone.js +3 -3
- package/dist/utils/relationship-builder-plan.d.ts +12 -10
- package/dist/utils/relationship-builder-plan.d.ts.map +1 -1
- package/dist/utils/relationship-builder-plan.js +20 -19
- package/dist/utils/relationship-measure-sql.d.ts.map +1 -1
- package/dist/utils/relationship-measure-sql.js +6 -3
- 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/snapshot-execution-context.d.ts.map +1 -1
- package/dist/utils/snapshot-execution-context.js +3 -0
- package/dist/utils/time-measure-axis-sql.d.ts +1 -1
- package/dist/utils/time-measure-axis-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-axis-sql.js +2 -1
- package/dist/utils/time-measure-leaf-sql.d.ts +1 -1
- package/dist/utils/time-measure-leaf-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-leaf-sql.js +3 -1
- package/dist/utils/time-measure-source-sql.d.ts +3 -0
- package/dist/utils/time-measure-source-sql.d.ts.map +1 -1
- package/dist/utils/time-measure-source-sql.js +10 -9
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row-scope.d.ts","sourceRoot":"","sources":["../../src/utils/row-scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACb,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtF,sEAAsE;AACtE,MAAM,MAAM,iBAAiB,GAAG,eAAe,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9E;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,IAAI,CAAC,kBAAkB,EAAE,WAAW,CAAC,EACzC,OAAO,CAAC,EAAE,gBAAgB,GACzB,iBAAiB,EAAE,CAGrB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,YAAY,EAAE,CAEtF;AAED,oFAAoF;AACpF,wBAAgB,aAAa,CAC3B,EAAE,EAAE,gBAAgB,EACpB,KAAK,EAAE,SAAS,iBAAiB,EAAE,EACnC,OAAO,GAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAyB,GACrD,gBAAgB,CAKlB"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getRuntimeTenantPredicate } from './tenant-runtime.js';
|
|
2
|
+
/**
|
|
3
|
+
* The trusted predicates restricting which source rows of `ds` any query may
|
|
4
|
+
* read (RFC 0020). They apply to the queried dataset and to every joined
|
|
5
|
+
* relationship target alike. `tenantKey` with a runtime tenant lowers to one
|
|
6
|
+
* predicate; the trusted cross-tenant scope (`scope: 'all'`) lowers to none.
|
|
7
|
+
*/
|
|
8
|
+
export function datasetRowScope(ds, context) {
|
|
9
|
+
const tenant = getRuntimeTenantPredicate(context);
|
|
10
|
+
return tenant && ds.tenantKey ? [{ column: ds.tenantKey, ...tenant }] : [];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The call's RFC 0019 enforced constraints, from trusted context only. They
|
|
14
|
+
* apply to the queried dataset, in its filter vocabulary, never to joined
|
|
15
|
+
* targets.
|
|
16
|
+
*/
|
|
17
|
+
export function runtimeConstraints(context) {
|
|
18
|
+
return context?.runtime?.constraints ?? [];
|
|
19
|
+
}
|
|
20
|
+
/** ANDs each row-scope predicate onto `qb`, with columns qualified by `qualify`. */
|
|
21
|
+
export function applyRowScope(qb, scope, qualify = column => column) {
|
|
22
|
+
for (const predicate of scope) {
|
|
23
|
+
qb = qb.where(qualify(predicate.column), predicate.operator, predicate.value);
|
|
24
|
+
}
|
|
25
|
+
return qb;
|
|
26
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AnyDatasetInstance, ExecutionContext } from '../types.js';
|
|
2
|
+
import type { QueryBuilderFactoryLike, QueryBuilderLike } from '../query-builder-protocol.js';
|
|
3
|
+
import type { DatasetSqlDialectRules } from '../dataset-sql-dialect.js';
|
|
4
|
+
import { type RelationshipBuilderContext } from './relationship-builder-plan.js';
|
|
5
|
+
export interface ScopedDatasetSourceOptions {
|
|
6
|
+
builderFactory: Pick<QueryBuilderFactoryLike, 'table'>;
|
|
7
|
+
ds: AnyDatasetInstance;
|
|
8
|
+
context?: ExecutionContext;
|
|
9
|
+
joinCtx: RelationshipBuilderContext | undefined;
|
|
10
|
+
dialect: DatasetSqlDialectRules;
|
|
11
|
+
timezone: string | undefined;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The dataset's source as a builder with every trusted row restriction
|
|
15
|
+
* applied (RFC 0020): `FINAL`, relationship joins scoped by each target's own
|
|
16
|
+
* row scope, the dataset's row scope, and the call's enforced constraints.
|
|
17
|
+
*
|
|
18
|
+
* Every builder-path query shape reads its source through here, so none can
|
|
19
|
+
* read rows the context does not allow. Callers add their own selections,
|
|
20
|
+
* filters and aggregations on top; every predicate here is ANDed with them.
|
|
21
|
+
*/
|
|
22
|
+
export declare function scopedDatasetSource(options: ScopedDatasetSourceOptions): QueryBuilderLike;
|
|
23
|
+
//# sourceMappingURL=scoped-dataset-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoped-dataset-source.d.ts","sourceRoot":"","sources":["../../src/utils/scoped-dataset-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAC9F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAIxE,OAAO,EAGL,KAAK,0BAA0B,EAChC,MAAM,gCAAgC,CAAC;AAIxC,MAAM,WAAW,0BAA0B;IACzC,cAAc,EAAE,IAAI,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC;IACvD,EAAE,EAAE,kBAAkB,CAAC;IACvB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,OAAO,EAAE,0BAA0B,GAAG,SAAS,CAAC;IAChD,OAAO,EAAE,sBAAsB,CAAC;IAChC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,gBAAgB,CAiBzF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { resolveFilterField } from '../query-planner.js';
|
|
2
|
+
import { FINAL_SAFETY_SETTINGS, datasetSourceBuilder, queryReadsFinal } from './dataset-source.js';
|
|
3
|
+
import { queryTimeFilter } from './query-timezone.js';
|
|
4
|
+
import { applyRelationshipJoins, qualifyBaseColumn, } from './relationship-builder-plan.js';
|
|
5
|
+
import { assertEnforcedConstraints } from './enforced-constraints.js';
|
|
6
|
+
import { applyRowScope, datasetRowScope, runtimeConstraints } from './row-scope.js';
|
|
7
|
+
/**
|
|
8
|
+
* The dataset's source as a builder with every trusted row restriction
|
|
9
|
+
* applied (RFC 0020): `FINAL`, relationship joins scoped by each target's own
|
|
10
|
+
* row scope, the dataset's row scope, and the call's enforced constraints.
|
|
11
|
+
*
|
|
12
|
+
* Every builder-path query shape reads its source through here, so none can
|
|
13
|
+
* read rows the context does not allow. Callers add their own selections,
|
|
14
|
+
* filters and aggregations on top; every predicate here is ANDed with them.
|
|
15
|
+
*/
|
|
16
|
+
export function scopedDatasetSource(options) {
|
|
17
|
+
const { ds, context, joinCtx, dialect, timezone } = options;
|
|
18
|
+
// Validators report this too; checked here so no path can skip it.
|
|
19
|
+
assertEnforcedConstraints(ds, context);
|
|
20
|
+
let qb = applyRelationshipJoins(datasetSourceBuilder(options.builderFactory, ds), joinCtx);
|
|
21
|
+
// A resolved join target is read with FINAL even when this dataset isn't.
|
|
22
|
+
if (queryReadsFinal(ds, joinCtx) && qb.settings)
|
|
23
|
+
qb = qb.settings(FINAL_SAFETY_SETTINGS);
|
|
24
|
+
qb = applyRowScope(qb, datasetRowScope(ds, context), column => qualifyBaseColumn(joinCtx, column));
|
|
25
|
+
// Constraints are filters in the dataset's vocabulary, applied exactly as a
|
|
26
|
+
// caller filter on the same field would be.
|
|
27
|
+
for (const constraint of runtimeConstraints(context)) {
|
|
28
|
+
const expression = resolveFilterField(ds, constraint.field, joinCtx);
|
|
29
|
+
for (const predicate of queryTimeFilter(dialect, ds, constraint, expression, timezone)) {
|
|
30
|
+
qb = qb.where(predicate.expression, predicate.operator, predicate.value);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return qb;
|
|
34
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshot-execution-context.d.ts","sourceRoot":"","sources":["../../src/utils/snapshot-execution-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,kFAAkF;AAClF,wBAAgB,wBAAwB,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"snapshot-execution-context.d.ts","sourceRoot":"","sources":["../../src/utils/snapshot-execution-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,kFAAkF;AAClF,wBAAgB,wBAAwB,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,SAAS,CAgBjG"}
|
|
@@ -9,6 +9,9 @@ export function snapshotExecutionContext(context) {
|
|
|
9
9
|
...context.runtime,
|
|
10
10
|
// Copy tenant objects and ID lists; retain adapter and AbortSignal identity.
|
|
11
11
|
tenant: structuredClone(context.runtime.tenant),
|
|
12
|
+
...(context.runtime.constraints === undefined
|
|
13
|
+
? {}
|
|
14
|
+
: { constraints: structuredClone(context.runtime.constraints) }),
|
|
12
15
|
},
|
|
13
16
|
}),
|
|
14
17
|
...(context.cache && { cache: { ...context.cache } }),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { StatementParameters } from './statement-parameters.js';
|
|
2
2
|
import type { TimeMeasureAxis } from './time-measure-axis.js';
|
|
3
|
-
import type
|
|
3
|
+
import { type TimeMeasureSqlSource } from './time-measure-source-sql.js';
|
|
4
4
|
import type { ShiftMeasureDefinition } from '../types.js';
|
|
5
5
|
export interface TimeMeasureSqlAxis {
|
|
6
6
|
ctes: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-measure-axis-sql.d.ts","sourceRoot":"","sources":["../../src/utils/time-measure-axis-sql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"time-measure-axis-sql.d.ts","sourceRoot":"","sources":["../../src/utils/time-measure-axis-sql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAqB,KAAK,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAE5F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAG1D,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,6DAA6D;AAC7D,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,mBAAmB,EAC9B,MAAM,EAAE,oBAAoB,EAC5B,IAAI,EAAE,eAAe,EACrB,MAAM,GAAE,SAAS,sBAAsB,EAAO,GAC7C,kBAAkB,CA2CpB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { sourceTimezoneSql } from './time-measure-source-sql.js';
|
|
1
2
|
import { calendarBucketGuardSql } from './time-axis-calendar-guard.js';
|
|
2
3
|
import { shiftCalendarGuardSql, shiftWallTimeSeriesGuardSql } from './shift-measure-sql.js';
|
|
3
4
|
/** Build bounded output buckets using the query timezone. */
|
|
@@ -24,7 +25,7 @@ export function buildTimeMeasureAxisSql(statement, source, axis, shifts = []) {
|
|
|
24
25
|
const postSeriesGuard = shifts.map(shift => shiftWallTimeSeriesGuardSql(dialect, shift, axis.grain)).join(' + ') || '0';
|
|
25
26
|
// A zero-row scalar retains the converted timestamp type and query timezone.
|
|
26
27
|
// Reading any(time) here would scan the entire population just for its type.
|
|
27
|
-
const timezone =
|
|
28
|
+
const timezone = sourceTimezoneSql(dialect);
|
|
28
29
|
const bounds = [
|
|
29
30
|
// The bounds come from the caller's time filter: bind them, never inline them.
|
|
30
31
|
`${dialect.parseTimestamp(statement.bind(axis.lower, 'string'), timezone)} AS _hq_lower`,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DatasetSqlDialectRules } from '../dataset-sql-dialect.js';
|
|
2
2
|
import type { WindowMeasureDefinition } from '../types.js';
|
|
3
3
|
import type { TimeMeasureAxis } from './time-measure-axis.js';
|
|
4
|
-
import type
|
|
4
|
+
import { type TimeMeasureSqlBase, type TimeMeasureSqlDimension } from './time-measure-source-sql.js';
|
|
5
5
|
/** Keyed source membership retains distinct/average semantics and row multiplicity. */
|
|
6
6
|
export declare function timeMeasureLeafSql(dialect: DatasetSqlDialectRules, id: number, context: number, base: TimeMeasureSqlBase, window: WindowMeasureDefinition | undefined, axis: TimeMeasureAxis, dims: readonly TimeMeasureSqlDimension[]): {
|
|
7
7
|
ctes: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-measure-leaf-sql.d.ts","sourceRoot":"","sources":["../../src/utils/time-measure-leaf-sql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"time-measure-leaf-sql.d.ts","sourceRoot":"","sources":["../../src/utils/time-measure-leaf-sql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAqB,KAAK,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAKxH,uFAAuF;AACvF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,sBAAsB,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,uBAAuB,GAAG,SAAS,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,uBAAuB,EAAE;;;;;;;;EA+CtO"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { sourceTimezoneSql } from './time-measure-source-sql.js';
|
|
1
2
|
import { calendarBucketGuardSql } from './time-axis-calendar-guard.js';
|
|
2
3
|
import { shiftRangePredicateSql } from './shift-measure-sql.js';
|
|
3
4
|
import { isCountAggregation } from './count-aggregations.js';
|
|
@@ -27,7 +28,8 @@ export function timeMeasureLeafSql(dialect, id, context, base, window, axis, dim
|
|
|
27
28
|
};
|
|
28
29
|
}
|
|
29
30
|
const lower = window?.trailing ? dialect.subtractTime('_hq_eval_end', window.trailing.amount, window.trailing.unit)
|
|
30
|
-
|
|
31
|
+
// Keep the to-date start zoned: a calendar Date would bucket in server time.
|
|
32
|
+
: window?.toDate ? dialect.truncateTimeInZone('_hq_eval_period', window.toDate, sourceTimezoneSql(dialect)) : '_hq_eval_lower';
|
|
31
33
|
const upper = window ? '_hq_eval_end' : '_hq_eval_upper';
|
|
32
34
|
const lowerInclusive = window ? '1' : '_hq_lower_inclusive';
|
|
33
35
|
const upperInclusive = window ? '0' : '_hq_upper_inclusive';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AnyDatasetInstance, DatasetQuery, MeasureDefinition, MetricFilter } from '../types.js';
|
|
2
2
|
import type { DatasetQueryExecutionOptions } from '../dataset-query.js';
|
|
3
3
|
import type { StatementParameters } from './statement-parameters.js';
|
|
4
|
+
import type { DatasetSqlDialectRules } from '../dataset-sql-dialect.js';
|
|
4
5
|
export interface TimeMeasureSqlDimension {
|
|
5
6
|
name: string;
|
|
6
7
|
alias: string;
|
|
@@ -17,6 +18,8 @@ export interface TimeMeasureSqlSource {
|
|
|
17
18
|
bases: TimeMeasureSqlBase[];
|
|
18
19
|
rowAlias: string;
|
|
19
20
|
}
|
|
21
|
+
/** The query timezone carried by `_hq_source` time, read from a zero-row scalar without scanning. */
|
|
22
|
+
export declare function sourceTimezoneSql(dialect: DatasetSqlDialectRules): string;
|
|
20
23
|
/** Isolate authored expressions, joins, tenancy and filters from internal SQL aliases. */
|
|
21
24
|
export declare function buildTimeMeasureSourceSql(ds: AnyDatasetInstance, query: DatasetQuery, baseNames: Iterable<string>, filters: readonly MetricFilter[], options: DatasetQueryExecutionOptions, statement: StatementParameters): TimeMeasureSqlSource;
|
|
22
25
|
//# sourceMappingURL=time-measure-source-sql.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-measure-source-sql.d.ts","sourceRoot":"","sources":["../../src/utils/time-measure-source-sql.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACrG,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"time-measure-source-sql.d.ts","sourceRoot":"","sources":["../../src/utils/time-measure-source-sql.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACrG,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AAQxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAExE,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,uBAAuB,EAAE,CAAC;IACtC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qGAAqG;AACrG,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAEzE;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,EACrC,SAAS,EAAE,mBAAmB,GAC7B,oBAAoB,CAoEtB"}
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { scopedDatasetSource } from './scoped-dataset-source.js';
|
|
2
2
|
import { resolveRelationshipMeasure } from './relationship-measures.js';
|
|
3
3
|
import { relationshipMeasureExpressions } from './relationship-measure-sql.js';
|
|
4
4
|
import { queryTimeFilter, queryTimeSql } from './query-timezone.js';
|
|
5
|
-
import { resolveDimensionExpression, resolveFilterField
|
|
6
|
-
import {
|
|
7
|
-
import { getRuntimeTenantPredicate } from './tenant-runtime.js';
|
|
5
|
+
import { resolveDimensionExpression, resolveFilterField } from '../query-planner.js';
|
|
6
|
+
import { buildRelationshipBuilderContext } from './relationship-builder-plan.js';
|
|
8
7
|
import { segmentFilters } from './segments.js';
|
|
9
8
|
import { getBaseMeasure } from './dataset-measures.js';
|
|
10
9
|
import { measureToAggregationSpec } from './dataset-normalization.js';
|
|
11
10
|
import { applyFilteredAggregationExpression } from './filtered-aggregation-sql.js';
|
|
12
11
|
import { assertNoRawSqlUnderJoins } from './sql-under-joins.js';
|
|
12
|
+
/** The query timezone carried by `_hq_source` time, read from a zero-row scalar without scanning. */
|
|
13
|
+
export function sourceTimezoneSql(dialect) {
|
|
14
|
+
return dialect.timezoneOf(dialect.assumeNotNull('(SELECT _hq_time FROM _hq_source LIMIT 0)'));
|
|
15
|
+
}
|
|
13
16
|
/** Isolate authored expressions, joins, tenancy and filters from internal SQL aliases. */
|
|
14
17
|
export function buildTimeMeasureSourceSql(ds, query, baseNames, filters, options, statement) {
|
|
15
18
|
const { dialect } = statement;
|
|
@@ -17,7 +20,9 @@ export function buildTimeMeasureSourceSql(ds, query, baseNames, filters, options
|
|
|
17
20
|
const joinCtx = buildRelationshipBuilderContext(ds, query, options.context, dialect);
|
|
18
21
|
// Keep source expressions in their own SELECT scope: internal aliases cannot
|
|
19
22
|
// capture authored SQL identifiers, even if a physical column shares a name.
|
|
20
|
-
let raw =
|
|
23
|
+
let raw = scopedDatasetSource({
|
|
24
|
+
builderFactory: options.builderFactory, ds, context: options.context, joinCtx, dialect, timezone: query.timezone,
|
|
25
|
+
});
|
|
21
26
|
const dims = (query.dimensions ?? []).map((name, i) => ({ name, alias: `_hq_d${i}` }));
|
|
22
27
|
const sourceParts = [resolveDimensionExpression(ds, ds.timeKey, joinCtx)];
|
|
23
28
|
for (const dimension of dims)
|
|
@@ -50,10 +55,6 @@ export function buildTimeMeasureSourceSql(ds, query, baseNames, filters, options
|
|
|
50
55
|
while (sourceIdentifiers.some(text => text.includes(rowAlias)))
|
|
51
56
|
rowAlias += '_';
|
|
52
57
|
raw = raw.select([`${dialect.packRow(sourceParts)} AS ${rowAlias}`]);
|
|
53
|
-
const tenant = getRuntimeTenantPredicate(options.context);
|
|
54
|
-
const tenantColumn = resolveTenantFilterColumn(ds, options.context);
|
|
55
|
-
if (tenant && tenantColumn)
|
|
56
|
-
raw = raw.where(qualifyBaseColumn(joinCtx, tenantColumn), tenant.operator, tenant.value);
|
|
57
58
|
// The time axis already consumed every time-key bound, so these are the
|
|
58
59
|
// remaining caller filters.
|
|
59
60
|
for (const filter of filters) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hypequery/datasets",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.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",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"!dist/**/type-tests/**"
|
|
56
56
|
],
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@hypequery/protocol": "^0.
|
|
58
|
+
"@hypequery/protocol": "^0.23.0",
|
|
59
59
|
"@noble/hashes": "^2.4.0",
|
|
60
60
|
"zod": "^4.6.6",
|
|
61
61
|
"zod-to-json-schema": "^3.25.2"
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"typescript": "^6.0.3",
|
|
74
74
|
"@vitest/coverage-v8": "^5.0.5",
|
|
75
75
|
"vitest": "^5.0.5",
|
|
76
|
-
"@hypequery/protocol-conformance": "^0.16.
|
|
76
|
+
"@hypequery/protocol-conformance": "^0.16.2"
|
|
77
77
|
},
|
|
78
78
|
"repository": {
|
|
79
79
|
"type": "git",
|