@hypequery/datasets 0.8.0 → 0.9.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/api.type-test.js +1 -0
- package/dist/catalog.d.ts +4 -1
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +16 -6
- package/dist/contract.d.ts +3 -1
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +3 -1
- package/dist/dataset-query.d.ts.map +1 -1
- package/dist/dataset-query.js +8 -5
- package/dist/dataset.d.ts +4 -3
- package/dist/dataset.d.ts.map +1 -1
- package/dist/dataset.js +5 -4
- package/dist/executor.d.ts +7 -1
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +39 -10
- package/dist/field.d.ts +4 -4
- package/dist/field.d.ts.map +1 -1
- package/dist/in-memory-backend.d.ts +5 -0
- package/dist/in-memory-backend.d.ts.map +1 -1
- package/dist/in-memory-backend.js +41 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/query-builder-protocol.d.ts +12 -0
- package/dist/query-builder-protocol.d.ts.map +1 -1
- package/dist/query-planner.d.ts +7 -6
- package/dist/query-planner.d.ts.map +1 -1
- package/dist/query-planner.js +63 -16
- package/dist/relationships.d.ts +9 -9
- package/dist/relationships.d.ts.map +1 -1
- package/dist/semantic-plan.d.ts +50 -9
- package/dist/semantic-plan.d.ts.map +1 -1
- package/dist/semantic-plan.js +9 -0
- package/dist/semantic-planner.d.ts.map +1 -1
- package/dist/semantic-planner.js +67 -5
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +29 -18
- package/dist/types.d.ts +29 -12
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/dataset-normalization.d.ts +1 -1
- package/dist/utils/dataset-normalization.d.ts.map +1 -1
- package/dist/utils/dataset-normalization.js +11 -1
- package/dist/utils/dataset-query-validation.d.ts.map +1 -1
- package/dist/utils/dataset-query-validation.js +50 -12
- 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 +4 -4
- package/dist/utils/relationship-builder-plan.d.ts +56 -0
- package/dist/utils/relationship-builder-plan.d.ts.map +1 -0
- package/dist/utils/relationship-builder-plan.js +92 -0
- package/dist/utils/relationship-fields.d.ts +62 -0
- package/dist/utils/relationship-fields.d.ts.map +1 -0
- package/dist/utils/relationship-fields.js +98 -0
- package/dist/utils/relationship-validation.d.ts +15 -0
- package/dist/utils/relationship-validation.d.ts.map +1 -0
- package/dist/utils/relationship-validation.js +29 -0
- package/package.json +1 -1
package/dist/api.type-test.js
CHANGED
|
@@ -81,6 +81,7 @@ const builderFactory = {
|
|
|
81
81
|
min: () => builderFactory.table('orders'),
|
|
82
82
|
max: () => builderFactory.table('orders'),
|
|
83
83
|
where: () => builderFactory.table('orders'),
|
|
84
|
+
leftJoin: () => builderFactory.table('orders'),
|
|
84
85
|
groupBy: () => builderFactory.table('orders'),
|
|
85
86
|
orderBy: () => builderFactory.table('orders'),
|
|
86
87
|
limit: () => builderFactory.table('orders'),
|
package/dist/catalog.d.ts
CHANGED
|
@@ -41,7 +41,8 @@ export interface RelationshipCatalogEntry {
|
|
|
41
41
|
target: string;
|
|
42
42
|
from: string;
|
|
43
43
|
to: string;
|
|
44
|
-
|
|
44
|
+
queryable: boolean;
|
|
45
|
+
fields: string[];
|
|
45
46
|
}
|
|
46
47
|
export interface DatasetCatalog {
|
|
47
48
|
name: string;
|
|
@@ -63,6 +64,8 @@ export type DatasetCatalogMap = Record<string, DatasetCatalog>;
|
|
|
63
64
|
export type DatasetCatalogSource = AnyDatasetInstance & {
|
|
64
65
|
metrics?: Record<string, MetricHandle>;
|
|
65
66
|
};
|
|
67
|
+
/** All queryable relationship field names (`<relationship>.<dimension>`) a catalog advertises. */
|
|
68
|
+
export declare function getQueryableRelationshipFields(catalog: DatasetCatalog): string[];
|
|
66
69
|
export declare function getDatasetCatalog(dataset: DatasetCatalogSource): DatasetCatalog;
|
|
67
70
|
export declare function getDatasetCatalogs(datasets: Record<string, DatasetCatalogSource>): DatasetCatalogMap;
|
|
68
71
|
//# sourceMappingURL=catalog.d.ts.map
|
package/dist/catalog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,sBAAsB,EACtB,wBAAwB,EACxB,aAAa,EACb,SAAS,EACV,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
|
package/dist/catalog.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SEMANTIC_FILTER_OPERATORS, SUPPORTED_TIME_GRAINS } from './constants.js';
|
|
2
|
+
import { listQueryableRelationshipFields } from './utils/relationship-fields.js';
|
|
2
3
|
function dimensionToCatalog(dimension) {
|
|
3
4
|
return {
|
|
4
5
|
type: dimension.fieldType,
|
|
@@ -45,21 +46,32 @@ function metricToCatalog(metric) {
|
|
|
45
46
|
requires: contract.requires,
|
|
46
47
|
};
|
|
47
48
|
}
|
|
48
|
-
function relationshipToCatalog(relationship) {
|
|
49
|
+
function relationshipToCatalog(name, relationship) {
|
|
49
50
|
return {
|
|
50
51
|
kind: relationship.kind,
|
|
51
52
|
target: relationship.target().name,
|
|
52
53
|
from: relationship.from,
|
|
53
54
|
to: relationship.to,
|
|
54
|
-
|
|
55
|
+
queryable: relationship.kind !== 'hasMany',
|
|
56
|
+
fields: listQueryableRelationshipFields(name, relationship),
|
|
55
57
|
};
|
|
56
58
|
}
|
|
59
|
+
/** All queryable relationship field names (`<relationship>.<dimension>`) a catalog advertises. */
|
|
60
|
+
export function getQueryableRelationshipFields(catalog) {
|
|
61
|
+
return Object.values(catalog.relationships)
|
|
62
|
+
.filter(relationship => relationship.queryable)
|
|
63
|
+
.flatMap(relationship => relationship.fields);
|
|
64
|
+
}
|
|
57
65
|
export function getDatasetCatalog(dataset) {
|
|
58
66
|
const dimensionNames = Object.keys(dataset.dimensions);
|
|
59
67
|
const measureNames = Object.keys(dataset.measures);
|
|
60
68
|
const metricNames = Object.keys(dataset.metrics ?? {});
|
|
61
69
|
const supportedGrains = dataset.timeKey ? [...SUPPORTED_TIME_GRAINS] : [];
|
|
62
70
|
const maxLimit = dataset.limits?.maxResultSize;
|
|
71
|
+
const relationships = Object.fromEntries(Object.entries(dataset.relationships).map(([name, relationship]) => [
|
|
72
|
+
name,
|
|
73
|
+
relationshipToCatalog(name, relationship),
|
|
74
|
+
]));
|
|
63
75
|
return {
|
|
64
76
|
name: dataset.name,
|
|
65
77
|
source: dataset.source,
|
|
@@ -81,10 +93,7 @@ export function getDatasetCatalog(dataset) {
|
|
|
81
93
|
name,
|
|
82
94
|
filterToCatalog(filter, dataset.dimensions),
|
|
83
95
|
])),
|
|
84
|
-
relationships
|
|
85
|
-
name,
|
|
86
|
-
relationshipToCatalog(relationship),
|
|
87
|
-
])),
|
|
96
|
+
relationships,
|
|
88
97
|
limits: dataset.limits,
|
|
89
98
|
requiresTenant: !!dataset.tenantKey,
|
|
90
99
|
supportedGrains,
|
|
@@ -92,6 +101,7 @@ export function getDatasetCatalog(dataset) {
|
|
|
92
101
|
...dimensionNames,
|
|
93
102
|
...measureNames,
|
|
94
103
|
...metricNames,
|
|
104
|
+
...Object.values(relationships).flatMap(relationship => relationship.fields),
|
|
95
105
|
...(dataset.timeKey ? ['period'] : []),
|
|
96
106
|
],
|
|
97
107
|
maxLimit,
|
package/dist/contract.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { DatasetLimits } from './types.js';
|
|
|
4
4
|
* Version of the semantic contract format. Bump when the serialized shape
|
|
5
5
|
* changes in a way that snapshot consumers must account for.
|
|
6
6
|
*/
|
|
7
|
-
export declare const SEMANTIC_CONTRACT_VERSION =
|
|
7
|
+
export declare const SEMANTIC_CONTRACT_VERSION = 2;
|
|
8
8
|
export interface ContractDimension {
|
|
9
9
|
type: DimensionCatalogEntry['type'];
|
|
10
10
|
column?: string;
|
|
@@ -45,6 +45,8 @@ export interface ContractRelationship {
|
|
|
45
45
|
target: string;
|
|
46
46
|
from: string;
|
|
47
47
|
to: string;
|
|
48
|
+
queryable: boolean;
|
|
49
|
+
fields: string[];
|
|
48
50
|
}
|
|
49
51
|
export interface ContractDataset {
|
|
50
52
|
name: string;
|
package/dist/contract.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC9B,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD;;;GAGG;AACH,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,mBAAmB,CAAC,aAAa,CAAC,CAAC;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAC;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
|
package/dist/contract.js
CHANGED
|
@@ -6,7 +6,7 @@ import { sortedRecord, uniqueSorted } from './utils/canonical-json.js';
|
|
|
6
6
|
* Version of the semantic contract format. Bump when the serialized shape
|
|
7
7
|
* changes in a way that snapshot consumers must account for.
|
|
8
8
|
*/
|
|
9
|
-
export const SEMANTIC_CONTRACT_VERSION =
|
|
9
|
+
export const SEMANTIC_CONTRACT_VERSION = 2;
|
|
10
10
|
/**
|
|
11
11
|
* Builds a deterministic semantic contract from dataset instances.
|
|
12
12
|
*
|
|
@@ -106,6 +106,8 @@ function relationshipToContract(entry) {
|
|
|
106
106
|
target: entry.target,
|
|
107
107
|
from: entry.from,
|
|
108
108
|
to: entry.to,
|
|
109
|
+
queryable: entry.queryable,
|
|
110
|
+
fields: uniqueSorted(entry.fields),
|
|
109
111
|
};
|
|
110
112
|
}
|
|
111
113
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataset-query.d.ts","sourceRoot":"","sources":["../src/dataset-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAQ7F,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"dataset-query.d.ts","sourceRoot":"","sources":["../src/dataset-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAQ7F,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAyBxD,MAAM,WAAW,4BAA4B;IAC3C,cAAc,EAAE,uBAAuB,CAAC;IACxC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,YAAY,EACnB,OAAO,CAAC,EAAE,gBAAgB,GACzB,gBAAgB,CAElB;AAED,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,4BAA4B,GACpC,gBAAgB,CA4ClB;AAED,wBAAsB,eAAe,CACnC,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,kBAAkB,CAAC,CAa7B"}
|
package/dist/dataset-query.js
CHANGED
|
@@ -2,6 +2,7 @@ import { appendOrderLimitOffset, applyMeasureDefinition, buildDimensionSelection
|
|
|
2
2
|
import { validateDatasetQueryInput } from './utils/dataset-query-validation.js';
|
|
3
3
|
import { getRuntimeTenantId, getRuntimeTenantPredicate, } from './utils/tenant-runtime.js';
|
|
4
4
|
import { applyPagination, overfetchLimit } from './utils/pagination.js';
|
|
5
|
+
import { applyRelationshipJoins, buildRelationshipBuilderContext, qualifyBaseColumn, } from './utils/relationship-builder-plan.js';
|
|
5
6
|
function toResultMeta(qb, timingMs, context) {
|
|
6
7
|
return {
|
|
7
8
|
sql: qb.toSQLWithParams().sql,
|
|
@@ -17,14 +18,16 @@ export function buildDatasetQueryBuilder(ds, query, options) {
|
|
|
17
18
|
if (!validation.valid) {
|
|
18
19
|
throw new Error(`Invalid dataset query: ${validation.errors.join('; ')}`);
|
|
19
20
|
}
|
|
21
|
+
const joinCtx = buildRelationshipBuilderContext(ds, query, options.context);
|
|
20
22
|
let qb = options.builderFactory.table(ds.source);
|
|
21
|
-
|
|
23
|
+
qb = applyRelationshipJoins(qb, joinCtx);
|
|
24
|
+
const { selectParts, groupByParts } = buildDimensionSelectionPlan(ds, query.dimensions ?? [], query.by, joinCtx);
|
|
22
25
|
const measureNames = query.measures ?? Object.keys(ds.measures);
|
|
23
26
|
if (selectParts.length > 0) {
|
|
24
27
|
qb = qb.select(selectParts);
|
|
25
28
|
}
|
|
26
29
|
for (const measureName of measureNames) {
|
|
27
|
-
qb = applyMeasureDefinition(qb, ds, measureName, ds.measures[measureName]);
|
|
30
|
+
qb = applyMeasureDefinition(qb, ds, measureName, ds.measures[measureName], joinCtx);
|
|
28
31
|
}
|
|
29
32
|
if (groupByParts.length > 0) {
|
|
30
33
|
qb = qb.groupBy(groupByParts);
|
|
@@ -32,13 +35,13 @@ export function buildDatasetQueryBuilder(ds, query, options) {
|
|
|
32
35
|
const tenantColumn = resolveTenantFilterColumn(ds, options.context);
|
|
33
36
|
const tenantPredicate = getRuntimeTenantPredicate(options.context);
|
|
34
37
|
if (tenantPredicate && tenantColumn) {
|
|
35
|
-
qb = qb.where(tenantColumn, tenantPredicate.operator, tenantPredicate.value);
|
|
38
|
+
qb = qb.where(qualifyBaseColumn(joinCtx, tenantColumn), tenantPredicate.operator, tenantPredicate.value);
|
|
36
39
|
}
|
|
37
40
|
for (const filter of query.filters ?? []) {
|
|
38
|
-
const resolvedField = resolveFilterField(ds, filter.field);
|
|
41
|
+
const resolvedField = resolveFilterField(ds, filter.field, joinCtx);
|
|
39
42
|
qb = qb.where(resolvedField, filter.operator, filter.value);
|
|
40
43
|
}
|
|
41
|
-
return appendOrderLimitOffset(qb, query.orderBy, query.by, options.executionLimit ?? query.limit, query.offset);
|
|
44
|
+
return appendOrderLimitOffset(qb, query.orderBy, query.by, options.executionLimit ?? query.limit, query.offset, joinCtx);
|
|
42
45
|
}
|
|
43
46
|
export async function runDatasetQuery(ds, query, options) {
|
|
44
47
|
const start = Date.now();
|
package/dist/dataset.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dataset() — creates a typed semantic model over a physical table.
|
|
3
3
|
*
|
|
4
|
-
* Relationships are modeled on the dataset
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Relationships are modeled on the dataset. To-one relationships (`belongsTo`,
|
|
5
|
+
* `hasOne`) are queryable one hop deep as `<relationship>.<dimension>` and
|
|
6
|
+
* execute as LEFT JOINs; `hasMany` relationships remain metadata-only to avoid
|
|
7
|
+
* fan-out corrupting aggregates.
|
|
7
8
|
*
|
|
8
9
|
* @example
|
|
9
10
|
* ```ts
|
package/dist/dataset.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataset.d.ts","sourceRoot":"","sources":["../src/dataset.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dataset.d.ts","sourceRoot":"","sources":["../src/dataset.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EAKvB,MAAM,YAAY,CAAC;AAkBpB,wBAAgB,OAAO,CACrB,YAAY,SAAS,MAAM,EAC3B,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,EACvD,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAC3E,cAAc,SAAS,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAErF,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,aAAa,CAAC,WAAW,EAAE,SAAS,EAAE,cAAc,CAAC,GAC5D,eAAe,CAAC,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,CAAC,CA2DvE"}
|
package/dist/dataset.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dataset() — creates a typed semantic model over a physical table.
|
|
3
3
|
*
|
|
4
|
-
* Relationships are modeled on the dataset
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Relationships are modeled on the dataset. To-one relationships (`belongsTo`,
|
|
5
|
+
* `hasOne`) are queryable one hop deep as `<relationship>.<dimension>` and
|
|
6
|
+
* execute as LEFT JOINs; `hasMany` relationships remain metadata-only to avoid
|
|
7
|
+
* fan-out corrupting aggregates.
|
|
7
8
|
*
|
|
8
9
|
* @example
|
|
9
10
|
* ```ts
|
|
@@ -35,7 +36,7 @@ export function dataset(name, config) {
|
|
|
35
36
|
const dimensions = normalizeDimensions(config);
|
|
36
37
|
const measures = normalizeMeasures(config.measures);
|
|
37
38
|
const filters = normalizeFilters(dimensions, config.filters);
|
|
38
|
-
const relationships = normalizeRelationships(config.relationships);
|
|
39
|
+
const relationships = normalizeRelationships(config.relationships, config.source);
|
|
39
40
|
function metric(metricName, metricConfig) {
|
|
40
41
|
if (isDerivedMetricConfig(metricConfig)) {
|
|
41
42
|
validateDerivedMetric(ds, metricName, metricConfig);
|
package/dist/executor.d.ts
CHANGED
|
@@ -17,7 +17,13 @@ export interface MetricQueryEngineOptions {
|
|
|
17
17
|
export interface CreateDatasetClientOptions {
|
|
18
18
|
/** Query builder factory for executing semantic metric and dataset queries. */
|
|
19
19
|
queryBuilder?: QueryBuilderFactoryInput;
|
|
20
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Semantic backend for executing neutral semantic plans.
|
|
22
|
+
*
|
|
23
|
+
* @deprecated Use `queryBuilder` instead — the query-builder path is
|
|
24
|
+
* canonical. The plan/backend path is frozen (bug fixes only) and will not
|
|
25
|
+
* gain new features.
|
|
26
|
+
*/
|
|
21
27
|
backend?: SemanticBackend;
|
|
22
28
|
/**
|
|
23
29
|
* Result-cache defaults for this client. Results are keyed by the canonical
|
package/dist/executor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAGhB,kBAAkB,EAClB,eAAe,EAEhB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAEV,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EACV,QAAQ,EACR,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAgB7E,OAAO,EAIL,KAAK,4BAA4B,EAClC,MAAM,oBAAoB,CAAC;AAW5B,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
|
package/dist/executor.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* stays database-agnostic via query-builder and backend protocol interfaces.
|
|
6
6
|
*/
|
|
7
7
|
import { toQueryBuilderFactory } from './query-builder-protocol.js';
|
|
8
|
-
import { validateSQLIdentifier } from './sql-utils.js';
|
|
8
|
+
import { quoteSQLIdentifier, validateSQLIdentifier } from './sql-utils.js';
|
|
9
9
|
import { SUPPORTED_TIME_GRAINS, isSupportedTimeGrain } from './constants.js';
|
|
10
10
|
import { validateFilterValue } from './validation.js';
|
|
11
11
|
import { applyAggregationSpec, appendOrderLimitOffset, buildDimensionSelectionPlan, resolveFilterField, resolveTenantFilterColumn, } from './query-planner.js';
|
|
@@ -17,6 +17,9 @@ import { getRuntimeTenantId, getRuntimeTenantPredicate, validateTenantRuntime, }
|
|
|
17
17
|
import { applyPagination, overfetchLimit } from './utils/pagination.js';
|
|
18
18
|
import { SemanticQueryCache, } from './cache/semantic-query-cache.js';
|
|
19
19
|
import { buildDatasetQuerySignature, buildMetricQuerySignature, } from './cache/query-signature.js';
|
|
20
|
+
import { isQualifiedField, resolveQualifiedField } from './utils/relationship-fields.js';
|
|
21
|
+
import { validateQualifiedFilter } from './utils/relationship-validation.js';
|
|
22
|
+
import { applyRelationshipJoins, buildRelationshipBuilderContext, qualifyBaseColumn, } from './utils/relationship-builder-plan.js';
|
|
20
23
|
function validateQuery(metric, query, context) {
|
|
21
24
|
const errors = [];
|
|
22
25
|
const ref = getMetricRef(metric);
|
|
@@ -40,12 +43,26 @@ function validateQuery(metric, query, context) {
|
|
|
40
43
|
}
|
|
41
44
|
// Validate dimensions
|
|
42
45
|
for (const dim of query.dimensions ?? []) {
|
|
46
|
+
if (isQualifiedField(dim)) {
|
|
47
|
+
const resolution = resolveQualifiedField(ds, dim);
|
|
48
|
+
if (resolution?.error) {
|
|
49
|
+
errors.push(resolution.error);
|
|
50
|
+
}
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
43
53
|
if (!dimensionNames.includes(dim)) {
|
|
44
54
|
errors.push(`Unknown dimension "${dim}". Available: ${dimensionNames.join(', ')}`);
|
|
45
55
|
}
|
|
46
56
|
}
|
|
47
57
|
// Validate filters
|
|
48
58
|
for (const filter of query.filters ?? []) {
|
|
59
|
+
if (isQualifiedField(filter.field)) {
|
|
60
|
+
const filterError = validateQualifiedFilter(ds, filter, context);
|
|
61
|
+
if (filterError) {
|
|
62
|
+
errors.push(filterError);
|
|
63
|
+
}
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
49
66
|
if (!filterNames.includes(filter.field)) {
|
|
50
67
|
errors.push(`Unknown filter field "${filter.field}". Available: ${filterNames.join(', ')}`);
|
|
51
68
|
continue;
|
|
@@ -206,13 +223,15 @@ export class MetricQueryEngine {
|
|
|
206
223
|
}
|
|
207
224
|
buildBaseQuery(ref, spec, ds, query, grain, context) {
|
|
208
225
|
const activeBuilderFactory = resolveBuilderFactory(context, this.builderFactory);
|
|
226
|
+
const joinCtx = buildRelationshipBuilderContext(ds, query, context);
|
|
209
227
|
let qb = activeBuilderFactory.table(ds.source);
|
|
210
|
-
|
|
228
|
+
qb = applyRelationshipJoins(qb, joinCtx);
|
|
229
|
+
const { selectParts, groupByParts } = buildDimensionSelectionPlan(ds, query.dimensions ?? [], grain, joinCtx);
|
|
211
230
|
if (selectParts.length > 0) {
|
|
212
231
|
qb = qb.select(selectParts);
|
|
213
232
|
}
|
|
214
233
|
// Aggregation (appends to select, auto-sets groupBy on non-agg columns)
|
|
215
|
-
qb = applyAggregationSpec(qb, ds, spec, ref.name);
|
|
234
|
+
qb = applyAggregationSpec(qb, ds, spec, ref.name, joinCtx);
|
|
216
235
|
// Explicit groupBy (ensures period + dims are grouped even if aggregation auto-groupBy misses them)
|
|
217
236
|
if (groupByParts.length > 0) {
|
|
218
237
|
qb = qb.groupBy(groupByParts);
|
|
@@ -221,26 +240,28 @@ export class MetricQueryEngine {
|
|
|
221
240
|
const tenantColumn = resolveTenantFilterColumn(ds, context);
|
|
222
241
|
const tenantPredicate = getRuntimeTenantPredicate(context);
|
|
223
242
|
if (tenantPredicate && tenantColumn) {
|
|
224
|
-
qb = qb.where(tenantColumn, tenantPredicate.operator, tenantPredicate.value);
|
|
243
|
+
qb = qb.where(qualifyBaseColumn(joinCtx, tenantColumn), tenantPredicate.operator, tenantPredicate.value);
|
|
225
244
|
}
|
|
226
245
|
// User filters
|
|
227
246
|
for (const filter of query.filters ?? []) {
|
|
228
247
|
if (isTenantScopedFilter(ds, filter, context)) {
|
|
229
248
|
throw new Error(`Cannot filter on tenant field "${filter.field}" when runtime tenancy enforcement is active.`);
|
|
230
249
|
}
|
|
231
|
-
const resolvedField = resolveFilterField(ds, filter.field);
|
|
250
|
+
const resolvedField = resolveFilterField(ds, filter.field, joinCtx);
|
|
232
251
|
qb = qb.where(resolvedField, filter.operator, filter.value);
|
|
233
252
|
}
|
|
234
253
|
// Order, limit, offset
|
|
235
|
-
qb = appendOrderLimitOffset(qb, query.orderBy, grain, query.limit, query.offset);
|
|
254
|
+
qb = appendOrderLimitOffset(qb, query.orderBy, grain, query.limit, query.offset, joinCtx);
|
|
236
255
|
return qb;
|
|
237
256
|
}
|
|
238
257
|
buildDerivedSQLViaBuilder(ref, spec, query, grain, context) {
|
|
239
258
|
const activeBuilderFactory = resolveBuilderFactory(context, this.builderFactory);
|
|
240
259
|
const ds = ref.dataset;
|
|
260
|
+
const joinCtx = buildRelationshipBuilderContext(ds, query, context);
|
|
241
261
|
// Build the CTE inner query using the builder
|
|
242
262
|
let cteBuilder = activeBuilderFactory.table(ds.source);
|
|
243
|
-
|
|
263
|
+
cteBuilder = applyRelationshipJoins(cteBuilder, joinCtx);
|
|
264
|
+
const { selectParts, groupByParts } = buildDimensionSelectionPlan(ds, query.dimensions ?? [], grain, joinCtx);
|
|
244
265
|
if (selectParts.length > 0) {
|
|
245
266
|
cteBuilder = cteBuilder.select(selectParts);
|
|
246
267
|
}
|
|
@@ -252,7 +273,7 @@ export class MetricQueryEngine {
|
|
|
252
273
|
if (baseSpec.__type !== 'aggregation_spec') {
|
|
253
274
|
throw new Error(`Derived metric "${ref.name}" references non-base metric "${alias}".`);
|
|
254
275
|
}
|
|
255
|
-
cteBuilder = applyAggregationSpec(cteBuilder, ds, baseSpec, alias);
|
|
276
|
+
cteBuilder = applyAggregationSpec(cteBuilder, ds, baseSpec, alias, joinCtx);
|
|
256
277
|
refAliases[alias] = alias;
|
|
257
278
|
aggregateAliases.push(alias);
|
|
258
279
|
}
|
|
@@ -263,13 +284,13 @@ export class MetricQueryEngine {
|
|
|
263
284
|
const tenantColumn = resolveTenantFilterColumn(ds, context);
|
|
264
285
|
const tenantPredicate = getRuntimeTenantPredicate(context);
|
|
265
286
|
if (tenantPredicate && tenantColumn) {
|
|
266
|
-
cteBuilder = cteBuilder.where(tenantColumn, tenantPredicate.operator, tenantPredicate.value);
|
|
287
|
+
cteBuilder = cteBuilder.where(qualifyBaseColumn(joinCtx, tenantColumn), tenantPredicate.operator, tenantPredicate.value);
|
|
267
288
|
}
|
|
268
289
|
for (const filter of query.filters ?? []) {
|
|
269
290
|
if (isTenantScopedFilter(ds, filter, context)) {
|
|
270
291
|
throw new Error(`Cannot filter on tenant field "${filter.field}" when runtime tenancy enforcement is active.`);
|
|
271
292
|
}
|
|
272
|
-
const resolvedField = resolveFilterField(ds, filter.field);
|
|
293
|
+
const resolvedField = resolveFilterField(ds, filter.field, joinCtx);
|
|
273
294
|
cteBuilder = cteBuilder.where(resolvedField, filter.operator, filter.value);
|
|
274
295
|
}
|
|
275
296
|
const { sql: cteSql, parameters: cteParams } = cteBuilder.toSQLWithParams();
|
|
@@ -283,6 +304,11 @@ export class MetricQueryEngine {
|
|
|
283
304
|
if (grain)
|
|
284
305
|
outerSelectParts.push('period');
|
|
285
306
|
for (const dim of query.dimensions ?? []) {
|
|
307
|
+
// Joined dimensions surface from the CTE under their quoted qualified alias.
|
|
308
|
+
if (joinCtx && isQualifiedField(dim)) {
|
|
309
|
+
outerSelectParts.push(quoteSQLIdentifier(dim));
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
286
312
|
validateSQLIdentifier(dim, 'dimension name');
|
|
287
313
|
outerSelectParts.push(dim);
|
|
288
314
|
}
|
|
@@ -293,6 +319,9 @@ export class MetricQueryEngine {
|
|
|
293
319
|
// ORDER BY
|
|
294
320
|
if (query.orderBy && query.orderBy.length > 0) {
|
|
295
321
|
const orderParts = query.orderBy.map(o => {
|
|
322
|
+
if (joinCtx && isQualifiedField(o.field)) {
|
|
323
|
+
return `${quoteSQLIdentifier(o.field)} ${o.direction.toUpperCase()}`;
|
|
324
|
+
}
|
|
296
325
|
validateSQLIdentifier(o.field, 'order by field');
|
|
297
326
|
return `${o.field} ${o.direction.toUpperCase()}`;
|
|
298
327
|
});
|
package/dist/field.d.ts
CHANGED
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import type { DimensionDefinition, DimensionOptions } from './types.js';
|
|
19
19
|
export declare const dimension: {
|
|
20
|
-
readonly string: (opts?:
|
|
21
|
-
readonly number: (opts?:
|
|
22
|
-
readonly boolean: (opts?:
|
|
23
|
-
readonly timestamp: (opts?:
|
|
20
|
+
readonly string: <TOptions extends DimensionOptions | undefined = undefined>(opts?: TOptions | undefined) => DimensionDefinition<"string"> & (TOptions extends DimensionOptions ? TOptions : object);
|
|
21
|
+
readonly number: <TOptions extends DimensionOptions | undefined = undefined>(opts?: TOptions | undefined) => DimensionDefinition<"number"> & (TOptions extends DimensionOptions ? TOptions : object);
|
|
22
|
+
readonly boolean: <TOptions extends DimensionOptions | undefined = undefined>(opts?: TOptions | undefined) => DimensionDefinition<"boolean"> & (TOptions extends DimensionOptions ? TOptions : object);
|
|
23
|
+
readonly timestamp: <TOptions extends DimensionOptions | undefined = undefined>(opts?: TOptions | undefined) => DimensionDefinition<"timestamp"> & (TOptions extends DimensionOptions ? TOptions : object);
|
|
24
24
|
};
|
|
25
25
|
//# sourceMappingURL=field.d.ts.map
|
package/dist/field.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../src/field.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAa,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../src/field.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAa,MAAM,YAAY,CAAC;AAiBnF,eAAO,MAAM,SAAS;sBAdZ,QAAQ,SAAS,gBAAgB,GAAG,SAAS;sBAA7C,QAAQ,SAAS,gBAAgB,GAAG,SAAS;uBAA7C,QAAQ,SAAS,gBAAgB,GAAG,SAAS;yBAA7C,QAAQ,SAAS,gBAAgB,GAAG,SAAS;CAmB7C,CAAC"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { SemanticBackend } from './semantic-plan.js';
|
|
2
2
|
export type InMemoryTable = Array<Record<string, unknown>>;
|
|
3
3
|
export type InMemoryTables = Record<string, InMemoryTable>;
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated The plan/backend execution path is frozen (bug fixes only); this
|
|
6
|
+
* backend remains as the test harness for that path. New code should use
|
|
7
|
+
* `createDatasetClient({ queryBuilder })`.
|
|
8
|
+
*/
|
|
4
9
|
export declare function createInMemoryBackend(tables: InMemoryTables): SemanticBackend;
|
|
5
10
|
//# sourceMappingURL=in-memory-backend.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"in-memory-backend.d.ts","sourceRoot":"","sources":["../src/in-memory-backend.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,eAAe,
|
|
1
|
+
{"version":3,"file":"in-memory-backend.d.ts","sourceRoot":"","sources":["../src/in-memory-backend.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,eAAe,EAKhB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAC3D,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AA6O3D;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,GAAG,eAAe,CAwE7E"}
|
|
@@ -44,6 +44,40 @@ function applyTenant(rows, tenant) {
|
|
|
44
44
|
}
|
|
45
45
|
return rows.filter((row) => row[tenant.field] === tenant.value);
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Enriches base rows with columns from to-one joined targets, keyed by the
|
|
49
|
+
* qualified name `<relationship>.<column>`. Mirrors a query-time LEFT JOIN:
|
|
50
|
+
* base rows without a matching target keep the joined columns undefined.
|
|
51
|
+
*/
|
|
52
|
+
function applyJoins(rows, joins, tables) {
|
|
53
|
+
if (!joins || joins.length === 0) {
|
|
54
|
+
return rows;
|
|
55
|
+
}
|
|
56
|
+
const indexes = joins.map((join) => {
|
|
57
|
+
const targetRows = applyTenant(tables[join.source] ?? [], join.tenant);
|
|
58
|
+
const index = new Map();
|
|
59
|
+
for (const row of targetRows) {
|
|
60
|
+
const key = String(row[join.to]);
|
|
61
|
+
// To-one: first matching target wins; a mis-declared to-many still won't fan out.
|
|
62
|
+
if (!index.has(key)) {
|
|
63
|
+
index.set(key, row);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { join, index };
|
|
67
|
+
});
|
|
68
|
+
return rows.map((row) => {
|
|
69
|
+
const enriched = { ...row };
|
|
70
|
+
for (const { join, index } of indexes) {
|
|
71
|
+
const match = index.get(String(row[join.from]));
|
|
72
|
+
if (match) {
|
|
73
|
+
for (const [column, value] of Object.entries(match)) {
|
|
74
|
+
enriched[`${join.relationship}.${column}`] = value;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return enriched;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
47
81
|
function periodForValue(value, grain) {
|
|
48
82
|
const date = new Date(String(value));
|
|
49
83
|
if (Number.isNaN(date.getTime())) {
|
|
@@ -182,10 +216,16 @@ function serializeMeasures(rows, measures) {
|
|
|
182
216
|
return next;
|
|
183
217
|
});
|
|
184
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* @deprecated The plan/backend execution path is frozen (bug fixes only); this
|
|
221
|
+
* backend remains as the test harness for that path. New code should use
|
|
222
|
+
* `createDatasetClient({ queryBuilder })`.
|
|
223
|
+
*/
|
|
185
224
|
export function createInMemoryBackend(tables) {
|
|
186
225
|
function executeAggregate(plan) {
|
|
187
226
|
const table = tables[plan.source] ?? [];
|
|
188
|
-
const
|
|
227
|
+
const joinedRows = applyJoins(table, plan.joins, tables);
|
|
228
|
+
const filteredRows = applyFilters(applyTenant(joinedRows, plan.tenant), plan.filters);
|
|
189
229
|
const groups = new Map();
|
|
190
230
|
for (const row of filteredRows) {
|
|
191
231
|
const key = groupKey(row, plan);
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,8 @@ export { sum, count, countDistinct, avg, min, max } from './aggregations.js';
|
|
|
6
6
|
export { divide, multiply, subtract, add, nullIfZero, coalesce, round, floor, ceil, } from './formulas.js';
|
|
7
7
|
export { eq, neq, gt, gte, lt, lte, inList, notInList, between, like, asc, desc, filter, order, } from './query-helpers.js';
|
|
8
8
|
export { createDatasetRegistry } from './registry.js';
|
|
9
|
-
export { getDatasetCatalog, getDatasetCatalogs } from './catalog.js';
|
|
9
|
+
export { getDatasetCatalog, getDatasetCatalogs, getQueryableRelationshipFields } from './catalog.js';
|
|
10
|
+
export { listQueryableRelationshipFields } from './utils/relationship-fields.js';
|
|
10
11
|
export type { DatasetCatalog, DatasetCatalogMap, DatasetCatalogSource, DimensionCatalogEntry, MeasureCatalogEntry, MetricCatalogEntry, FilterCatalogEntry, RelationshipCatalogEntry, } from './catalog.js';
|
|
11
12
|
export { serializeSemanticContract, contractToStableJson, hashContract, SEMANTIC_CONTRACT_VERSION, } from './contract.js';
|
|
12
13
|
export type { SemanticContract, SerializeSemanticContractOptions, ContractDataset, ContractDimension, ContractMeasure, ContractMetric, ContractFilter, ContractRelationship, } from './contract.js';
|
|
@@ -26,5 +27,5 @@ export type { QueryBuilderLike, QueryBuilderFactoryLike, QueryBuilderFactoryComp
|
|
|
26
27
|
export { toQueryBuilderFactory } from './query-builder-protocol.js';
|
|
27
28
|
export { validateSQLIdentifier, isSafeSQLIdentifier, quoteSQLIdentifier } from './sql-utils.js';
|
|
28
29
|
export { GRAIN_FUNCTIONS, SEMANTIC_FILTER_OPERATORS, SUPPORTED_TIME_GRAINS } from './constants.js';
|
|
29
|
-
export type { FieldType, DimensionType, DimensionOptions, DimensionDefinition, MeasureOptions, MeasureDefinition, InferDimensionType, RelationshipKind, RelationshipDefinition, AggregationType, MeasureAggregation, AggregationSpec, FormulaExpr, DerivedMetricSpec, TimeGrain, MetricRef, BaseMetricRef, DerivedMetricRef, GrainedMetricRef, MetricContract, MetricFilter, MetricOrderBy, MetricQuery, DatasetQuery, MetricResultMeta, MetricResult, DatasetQueryResult, MetricHandle, ExecutionContext, SemanticExecutionRuntime, SemanticTenantRuntime, SemanticFilterDefinition, SemanticFiltersDefinition, DatasetConfig, DatasetLimits, DatasetInstance, AnyDatasetInstance, BaseMetricConfig, DerivedMetricConfig, DatasetRegistryInstance, DatasetFieldNames, DatasetDimensionNames, DatasetMeasureNames, DatasetOrderableNames, DatasetQueryFor, DatasetRow, DatasetRowFor, DatasetQueryResultFor, MetricQueryFor, MetricRow, MetricRowFor, MetricResultFor, KnownStringKeys, } from './types.js';
|
|
30
|
+
export type { FieldType, DimensionType, DimensionOptions, DimensionDefinition, MeasureOptions, MeasureDefinition, InferDimensionType, RelationshipKind, RelationshipDefinition, AggregationType, MeasureAggregation, AggregationSpec, FormulaExpr, DerivedMetricSpec, TimeGrain, MetricRef, BaseMetricRef, DerivedMetricRef, GrainedMetricRef, MetricContract, MetricFilter, MetricOrderBy, MetricQuery, DatasetQuery, MetricResultMeta, MetricResult, DatasetQueryResult, MetricHandle, ExecutionContext, SemanticExecutionRuntime, SemanticTenantRuntime, SemanticFilterDefinition, SemanticFiltersDefinition, DatasetConfig, DatasetLimits, DatasetInstance, AnyDatasetInstance, BaseMetricConfig, DerivedMetricConfig, DatasetRegistryInstance, DatasetFieldNames, DatasetDimensionNames, DatasetQueryableDimensions, DatasetMeasureNames, DatasetOrderableNames, DatasetQueryFor, DatasetRow, DatasetRowFor, DatasetQueryResultFor, MetricQueryFor, MetricRow, MetricRowFor, MetricResultFor, KnownStringKeys, } from './types.js';
|
|
30
31
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAGhE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAG7E,OAAO,EACL,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAC/B,UAAU,EAAE,QAAQ,EACpB,KAAK,EAAE,KAAK,EAAE,IAAI,GACnB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EACzB,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAChC,GAAG,EAAE,IAAI,EACT,MAAM,EAAE,KAAK,GACd,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAGtD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,8 @@ export { eq, neq, gt, gte, lt, lte, inList, notInList, between, like, asc, desc,
|
|
|
15
15
|
// Registry
|
|
16
16
|
export { createDatasetRegistry } from './registry.js';
|
|
17
17
|
// Catalog
|
|
18
|
-
export { getDatasetCatalog, getDatasetCatalogs } from './catalog.js';
|
|
18
|
+
export { getDatasetCatalog, getDatasetCatalogs, getQueryableRelationshipFields } from './catalog.js';
|
|
19
|
+
export { listQueryableRelationshipFields } from './utils/relationship-fields.js';
|
|
19
20
|
// Semantic contract (stable, hashable export for snapshots/diffs/validation)
|
|
20
21
|
export { serializeSemanticContract, contractToStableJson, hashContract, SEMANTIC_CONTRACT_VERSION, } from './contract.js';
|
|
21
22
|
// Agent/tool metadata
|
|
@@ -25,6 +26,9 @@ export { createDatasetClient } from './executor.js';
|
|
|
25
26
|
// Semantic query result cache
|
|
26
27
|
export { createMemoryCacheStore } from './cache/semantic-query-cache.js';
|
|
27
28
|
export { buildDatasetQuerySignature, buildMetricQuerySignature, } from './cache/query-signature.js';
|
|
29
|
+
// Plan/backend protocol — FROZEN. Deprecated in favor of the query-builder
|
|
30
|
+
// path (`createDatasetClient({ queryBuilder })`); bug fixes only, no new
|
|
31
|
+
// features. See the deprecation notes on each declaration.
|
|
28
32
|
export { createInMemoryBackend } from './in-memory-backend.js';
|
|
29
33
|
export { validateFilterValue, matchesFieldType } from './validation.js';
|
|
30
34
|
export { toQueryBuilderFactory } from './query-builder-protocol.js';
|
|
@@ -18,6 +18,13 @@ export interface QueryBuilderLike {
|
|
|
18
18
|
min(column: string, alias?: string): QueryBuilderLike;
|
|
19
19
|
max(column: string, alias?: string): QueryBuilderLike;
|
|
20
20
|
where(column: string, operator: string, value: unknown): QueryBuilderLike;
|
|
21
|
+
leftJoin(table: string, leftColumn: string, rightColumn: string, alias?: string, on?: QueryBuilderJoinCondition | QueryBuilderJoinCondition[]): QueryBuilderLike;
|
|
22
|
+
/**
|
|
23
|
+
* Optional single-match LEFT JOIN (ClickHouse `LEFT ANY JOIN`). When a
|
|
24
|
+
* builder provides it, relationship joins use it so duplicate target join
|
|
25
|
+
* keys cannot fan out aggregates; otherwise `leftJoin` is used.
|
|
26
|
+
*/
|
|
27
|
+
leftAnyJoin?(table: string, leftColumn: string, rightColumn: string, alias?: string, on?: QueryBuilderJoinCondition | QueryBuilderJoinCondition[]): QueryBuilderLike;
|
|
21
28
|
groupBy(columns: string | string[]): QueryBuilderLike;
|
|
22
29
|
orderBy(column: string, direction?: 'ASC' | 'DESC'): QueryBuilderLike;
|
|
23
30
|
limit(count: number): QueryBuilderLike;
|
|
@@ -28,6 +35,11 @@ export interface QueryBuilderLike {
|
|
|
28
35
|
};
|
|
29
36
|
execute<T = Record<string, unknown>>(): Promise<T[]>;
|
|
30
37
|
}
|
|
38
|
+
export interface QueryBuilderJoinCondition {
|
|
39
|
+
column: string;
|
|
40
|
+
operator: string;
|
|
41
|
+
value: unknown;
|
|
42
|
+
}
|
|
31
43
|
/** A query builder factory (what `createQueryBuilder(config)` returns). */
|
|
32
44
|
export interface QueryBuilderFactoryLike {
|
|
33
45
|
table(name: string): QueryBuilderLike;
|