@hypequery/datasets 0.17.1 → 0.19.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/agent-catalog.d.ts +9 -0
- package/dist/agent-catalog.d.ts.map +1 -1
- package/dist/aggregations.d.ts +2 -0
- package/dist/aggregations.d.ts.map +1 -1
- package/dist/aggregations.js +4 -0
- package/dist/api.type-test.js +40 -1
- package/dist/cache/query-signature.d.ts.map +1 -1
- package/dist/cache/query-signature.js +17 -0
- package/dist/catalog.d.ts +11 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +12 -2
- package/dist/cloud-publishing.d.ts +23 -0
- package/dist/cloud-publishing.d.ts.map +1 -0
- package/dist/cloud-publishing.js +57 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +2 -0
- package/dist/contract.d.ts +5 -1
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +7 -0
- package/dist/dataset-query.d.ts.map +1 -1
- package/dist/dataset-query.js +6 -1
- package/dist/dataset.d.ts +2 -2
- package/dist/dataset.d.ts.map +1 -1
- package/dist/dataset.js +3 -0
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +15 -4
- package/dist/in-memory-backend.d.ts.map +1 -1
- package/dist/in-memory-backend.js +34 -7
- package/dist/index.d.ts +10 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/measure.d.ts +5 -0
- package/dist/measure.d.ts.map +1 -1
- package/dist/measure.js +5 -0
- package/dist/portable-execution-errors.d.ts +4 -0
- package/dist/portable-execution-errors.d.ts.map +1 -1
- package/dist/portable-execution-errors.js +4 -1
- package/dist/portable-executor.d.ts.map +1 -1
- package/dist/portable-executor.js +6 -3
- package/dist/protocol-adapter.d.ts.map +1 -1
- package/dist/protocol-adapter.js +15 -7
- package/dist/protocol-rehydrate.d.ts +5 -1
- package/dist/protocol-rehydrate.d.ts.map +1 -1
- package/dist/protocol-rehydrate.js +20 -10
- package/dist/query-builder-protocol.d.ts +7 -3
- package/dist/query-builder-protocol.d.ts.map +1 -1
- package/dist/query-planner.d.ts.map +1 -1
- package/dist/query-planner.js +5 -0
- package/dist/relationship-check.d.ts +47 -0
- package/dist/relationship-check.d.ts.map +1 -0
- package/dist/relationship-check.js +59 -0
- package/dist/relationships.d.ts +10 -10
- package/dist/relationships.js +10 -10
- package/dist/semantic-planner.d.ts.map +1 -1
- package/dist/semantic-planner.js +5 -1
- package/dist/semantic-query-schema.d.ts.map +1 -1
- package/dist/semantic-query-schema.js +5 -0
- package/dist/sql-portability.d.ts.map +1 -1
- package/dist/sql-portability.js +88 -19
- package/dist/types.d.ts +39 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/agent-catalog-projection.d.ts +6 -0
- package/dist/utils/agent-catalog-projection.d.ts.map +1 -1
- package/dist/utils/agent-catalog-projection.js +4 -0
- package/dist/utils/approximate-measures.d.ts +10 -0
- package/dist/utils/approximate-measures.d.ts.map +1 -0
- package/dist/utils/approximate-measures.js +15 -0
- package/dist/utils/collect-cloud-datasets.d.ts +3 -0
- package/dist/utils/collect-cloud-datasets.d.ts.map +1 -0
- package/dist/utils/collect-cloud-datasets.js +12 -0
- package/dist/utils/dataset-contract.d.ts.map +1 -1
- package/dist/utils/dataset-contract.js +2 -2
- package/dist/utils/dataset-metric-ref.d.ts.map +1 -1
- package/dist/utils/dataset-metric-ref.js +5 -0
- package/dist/utils/dataset-query-validation.d.ts.map +1 -1
- package/dist/utils/dataset-query-validation.js +6 -3
- package/dist/utils/dataset-time-grains.d.ts +15 -0
- package/dist/utils/dataset-time-grains.d.ts.map +1 -0
- package/dist/utils/dataset-time-grains.js +17 -0
- package/dist/utils/filtered-aggregation-sql.d.ts.map +1 -1
- package/dist/utils/filtered-aggregation-sql.js +1 -0
- package/dist/utils/portable-aggregations.d.ts +14 -0
- package/dist/utils/portable-aggregations.d.ts.map +1 -0
- package/dist/utils/portable-aggregations.js +15 -0
- package/dist/utils/portable-grains.d.ts +22 -0
- package/dist/utils/portable-grains.d.ts.map +1 -0
- package/dist/utils/portable-grains.js +35 -0
- package/dist/utils/portable-semantic-query.d.ts.map +1 -1
- package/dist/utils/portable-semantic-query.js +2 -1
- package/dist/utils/protocol-metric-expressions.d.ts.map +1 -1
- package/dist/utils/protocol-metric-expressions.js +2 -1
- package/dist/utils/relationship-builder-plan.d.ts +6 -3
- package/dist/utils/relationship-builder-plan.d.ts.map +1 -1
- package/dist/utils/relationship-builder-plan.js +13 -5
- package/dist/utils/relationship-key-check.d.ts +43 -0
- package/dist/utils/relationship-key-check.d.ts.map +1 -0
- package/dist/utils/relationship-key-check.js +72 -0
- package/dist/utils/segments.d.ts +31 -0
- package/dist/utils/segments.d.ts.map +1 -0
- package/dist/utils/segments.js +91 -0
- package/dist/utils/semantic-metadata-validation.d.ts.map +1 -1
- package/dist/utils/semantic-metadata-validation.js +22 -1
- package/dist/utils/unsupported-contract-reasons.d.ts +32 -0
- package/dist/utils/unsupported-contract-reasons.d.ts.map +1 -0
- package/dist/utils/unsupported-contract-reasons.js +30 -0
- package/package.json +3 -3
|
@@ -48,7 +48,12 @@ function applyTenant(rows, tenant) {
|
|
|
48
48
|
/**
|
|
49
49
|
* Enriches base rows with columns from to-one joined targets, keyed by the
|
|
50
50
|
* qualified name `<relationship>.<column>`. Mirrors a query-time LEFT JOIN:
|
|
51
|
-
* base rows without a matching target keep the joined columns undefined
|
|
51
|
+
* base rows without a matching target keep the joined columns undefined, and
|
|
52
|
+
* NULL keys never match.
|
|
53
|
+
*
|
|
54
|
+
* A duplicate target key means the relationship is not really to-one. Rather
|
|
55
|
+
* than silently picking one of the matches, the join is refused so the
|
|
56
|
+
* mis-declaration surfaces in tests.
|
|
52
57
|
*/
|
|
53
58
|
function applyJoins(rows, joins, tables) {
|
|
54
59
|
if (!joins || joins.length === 0) {
|
|
@@ -58,18 +63,24 @@ function applyJoins(rows, joins, tables) {
|
|
|
58
63
|
const targetRows = applyTenant(tables[join.source] ?? [], join.tenant);
|
|
59
64
|
const index = new Map();
|
|
60
65
|
for (const row of targetRows) {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
const value = row[join.to];
|
|
67
|
+
if (value == null) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const key = String(value);
|
|
71
|
+
if (index.has(key)) {
|
|
72
|
+
throw new Error(`Relationship "${join.relationship}" is declared to-one, but "${join.source}.${join.to}" ` +
|
|
73
|
+
`has more than one row with key ${JSON.stringify(key)}. Declare it as hasMany or make the key unique.`);
|
|
65
74
|
}
|
|
75
|
+
index.set(key, row);
|
|
66
76
|
}
|
|
67
77
|
return { join, index };
|
|
68
78
|
});
|
|
69
79
|
return rows.map((row) => {
|
|
70
80
|
const enriched = { ...row };
|
|
71
81
|
for (const { join, index } of indexes) {
|
|
72
|
-
const
|
|
82
|
+
const key = row[join.from];
|
|
83
|
+
const match = key == null ? undefined : index.get(String(key));
|
|
73
84
|
if (match) {
|
|
74
85
|
for (const [column, value] of Object.entries(match)) {
|
|
75
86
|
enriched[`${join.relationship}.${column}`] = value;
|
|
@@ -84,6 +95,20 @@ function periodForValue(value, grain) {
|
|
|
84
95
|
if (Number.isNaN(date.getTime())) {
|
|
85
96
|
return String(value);
|
|
86
97
|
}
|
|
98
|
+
// Sub-day buckets keep their time of day, in the form a ClickHouse DateTime
|
|
99
|
+
// takes in JSON (RFC 0015).
|
|
100
|
+
if (grain.unit === 'minute' || grain.unit === 'hour') {
|
|
101
|
+
// ClickHouse DateTime strings have no offset. Keep their wall-clock hour
|
|
102
|
+
// instead of interpreting them in the Node process's local time zone.
|
|
103
|
+
const naive = typeof value === 'string'
|
|
104
|
+
? /^(\d{4}-\d{2}-\d{2})[ T](\d{2}):(\d{2})(?::\d{2}(?:\.\d+)?)?$/.exec(value)
|
|
105
|
+
: null;
|
|
106
|
+
if (naive) {
|
|
107
|
+
return `${naive[1]} ${naive[2]}:${grain.unit === 'hour' ? '00' : naive[3]}:00`;
|
|
108
|
+
}
|
|
109
|
+
const iso = date.toISOString();
|
|
110
|
+
return `${iso.slice(0, 10)} ${grain.unit === 'hour' ? `${iso.slice(11, 13)}:00` : iso.slice(11, 16)}:00`;
|
|
111
|
+
}
|
|
87
112
|
if (grain.unit === 'year') {
|
|
88
113
|
return `${date.getUTCFullYear()}-01-01`;
|
|
89
114
|
}
|
|
@@ -172,8 +197,10 @@ function aggregateRows(rows, aggregation) {
|
|
|
172
197
|
return values.reduce((total, value) => total + Number(value ?? 0), 0);
|
|
173
198
|
case 'count':
|
|
174
199
|
return filteredRows.length;
|
|
200
|
+
// Exact computation is a faithful approxCountDistinct (RFC 0015).
|
|
175
201
|
case 'countDistinct':
|
|
176
|
-
|
|
202
|
+
case 'approxCountDistinct':
|
|
203
|
+
return new Set(values.filter(value => value != null)).size;
|
|
177
204
|
case 'avg':
|
|
178
205
|
return values.length === 0
|
|
179
206
|
? 0
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,9 @@ export { dataset } from './dataset.js';
|
|
|
2
2
|
export { dimension } from './field.js';
|
|
3
3
|
export { measure } from './measure.js';
|
|
4
4
|
export { belongsTo, hasMany, hasOne } from './relationships.js';
|
|
5
|
-
export {
|
|
5
|
+
export { checkRelationships } from './relationship-check.js';
|
|
6
|
+
export type { CheckRelationshipsOptions, CheckRelationshipsResult, RelationshipKeyIssue, } from './relationship-check.js';
|
|
7
|
+
export { sum, count, countDistinct, approxCountDistinct, avg, min, max, percentile, median, argMax, argMin, stddev, variance, } from './aggregations.js';
|
|
6
8
|
export { divide, multiply, subtract, add, nullIfZero, coalesce, round, floor, ceil, } from './formulas.js';
|
|
7
9
|
export { eq, neq, gt, gte, lt, lte, inList, notInList, between, like, asc, desc, filter, order, } from './query-helpers.js';
|
|
8
10
|
export { createDatasetRegistry } from './registry.js';
|
|
@@ -11,17 +13,19 @@ export type { DatasetPublisher } from './publishing/publisher.js';
|
|
|
11
13
|
export type { PublishableMetric, PublishedMetricHandle, PublishedMetricMap, PublishedMetrics, PublishedDataset, PublishedDatasetRegistry, PublishDatasetOptions, } from './publishing/types.js';
|
|
12
14
|
export { getDatasetCatalog, getDatasetCatalogs, getQueryableRelationshipFields } from './catalog.js';
|
|
13
15
|
export { listQueryableRelationshipFields } from './utils/relationship-fields.js';
|
|
14
|
-
export type { DatasetCatalog, DatasetCatalogMap, DatasetCatalogSource, DimensionCatalogEntry, MeasureCatalogEntry, MetricCatalogEntry, FilterCatalogEntry, RelationshipCatalogEntry, } from './catalog.js';
|
|
16
|
+
export type { DatasetCatalog, DatasetCatalogMap, DatasetCatalogSource, DimensionCatalogEntry, MeasureCatalogEntry, SegmentCatalogEntry, MetricCatalogEntry, FilterCatalogEntry, RelationshipCatalogEntry, } from './catalog.js';
|
|
15
17
|
export { DEFAULT_AGENT_CATALOG_MAX_BYTES, assertAgentSafeCatalogBudget, projectAgentSafeCatalog, projectTrustedDebugCatalog, } from './agent-catalog.js';
|
|
16
|
-
export type { AgentCatalogDataset, AgentCatalogDatasetRegistry, AgentCatalogProjectionOptions, AgentCatalogDimension, AgentCatalogFilter, AgentCatalogMeasure, AgentCatalogMetric, AgentCatalogRelationship, AgentCatalogSource, AgentSafeCatalog, TrustedDebugCatalog, TrustedDebugCatalogAuthorization, } from './agent-catalog.js';
|
|
18
|
+
export type { AgentCatalogDataset, AgentCatalogDatasetRegistry, AgentCatalogProjectionOptions, AgentCatalogDimension, AgentCatalogFilter, AgentCatalogMeasure, AgentCatalogSegment, AgentCatalogMetric, AgentCatalogRelationship, AgentCatalogSource, AgentSafeCatalog, TrustedDebugCatalog, TrustedDebugCatalogAuthorization, } from './agent-catalog.js';
|
|
17
19
|
export { serializeSemanticContract, contractToStableJson, hashContract, SEMANTIC_CONTRACT_VERSION, } from './contract.js';
|
|
18
|
-
export { rehydrateProtocolDatasets, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
|
|
19
|
-
export type { RehydratedDataset, RehydrateProtocolDatasetsOptions, } from './protocol-rehydrate.js';
|
|
20
|
+
export { rehydrateProtocolDatasets, UNSUPPORTED_CONTRACT_REASONS, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
|
|
21
|
+
export type { RehydratedDataset, RehydrateProtocolDatasetsOptions, UnsupportedContractReason, } from './protocol-rehydrate.js';
|
|
20
22
|
export { buildProtocolDatasetContract } from './protocol-adapter.js';
|
|
21
23
|
export { buildProtocolDeploymentContract } from './protocol-deployment-adapter.js';
|
|
22
24
|
export type { BuildProtocolDeploymentContractOptions } from './protocol-deployment-adapter.js';
|
|
23
25
|
export { rehydrateProtocolDeploymentContract } from './protocol-rehydrate.js';
|
|
24
26
|
export type { BuildProtocolDatasetContractOptions } from './protocol-adapter.js';
|
|
27
|
+
export { publishToCloud } from './cloud-publishing.js';
|
|
28
|
+
export type { CloudPublishingOptions } from './cloud-publishing.js';
|
|
25
29
|
export { createPortableSemanticExecutor, PortableExecutionBudgetError, PortableExecutionTenantError, PortableExecutionUnsupportedError, } from './portable-executor.js';
|
|
26
30
|
export type { PortableSemanticBudget, PortableSemanticExecutionInput, PortableSemanticExecutorOptions, } from './portable-executor.js';
|
|
27
31
|
export { compilePortableSqlExpression, DEFAULT_SQL_PORTABILITY_LIMITS, } from './sql-portability.js';
|
|
@@ -45,6 +49,6 @@ export type { QueryBuilderLike, QueryBuilderFactoryLike, QueryBuilderFactoryComp
|
|
|
45
49
|
export { toQueryBuilderFactory } from './query-builder-protocol.js';
|
|
46
50
|
export { validateSQLIdentifier, isSafeSQLIdentifier, quoteSQLIdentifier } from './sql-utils.js';
|
|
47
51
|
export { GRAIN_FUNCTIONS, SEMANTIC_FILTER_OPERATORS, SUPPORTED_TIME_GRAINS } from './constants.js';
|
|
48
|
-
export type { FieldType, DimensionType, DimensionOptions, DimensionDefinition, MeasureOptions, MeasureDefinition, DatasetMeasureDefinition, DerivedMeasureDefinition, DerivedMeasureOptions, DerivedMeasureUses, 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, DatasetDefaults, DatasetFreshness, DatasetLimits, DatasetCachePolicy, SemanticMetadata, SemanticSensitivity, DatasetInstance, AnyDatasetInstance, BaseMetricConfig, DerivedMetricConfig, DatasetRegistryInstance, DatasetFieldNames, DatasetDimensionNames, DatasetQueryableDimensions, DatasetMeasureNames, DatasetOrderableNames, DatasetQueryFor, DatasetRow, DatasetRowFor, DatasetQueryResultFor, MetricQueryFor, MetricRow, MetricRowFor, MetricResultFor, KnownStringKeys, } from './types.js';
|
|
52
|
+
export type { FieldType, DimensionType, DimensionOptions, DimensionDefinition, MeasureOptions, MeasureDefinition, DatasetMeasureDefinition, DerivedMeasureDefinition, DerivedMeasureOptions, DerivedMeasureUses, 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, SegmentDefinition, SemanticFiltersDefinition, DatasetConfig, DatasetDefaults, DatasetFreshness, DatasetLimits, DatasetCachePolicy, SemanticMetadata, SemanticSensitivity, DatasetInstance, AnyDatasetInstance, BaseMetricConfig, DerivedMetricConfig, DatasetRegistryInstance, DatasetFieldNames, DatasetDimensionNames, DatasetQueryableDimensions, DatasetMeasureNames, DatasetSegmentNames, DatasetOrderableNames, DatasetQueryFor, DatasetRow, DatasetRowFor, DatasetQueryResultFor, MetricQueryFor, MetricRow, MetricRowFor, MetricResultFor, KnownStringKeys, } from './types.js';
|
|
49
53
|
export { ProtocolSchemaAdapterError, zodToProtocolSchema } from './protocol-schema-adapter.js';
|
|
50
54
|
//# 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;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -6,8 +6,9 @@ export { dimension } from './field.js';
|
|
|
6
6
|
export { measure } from './measure.js';
|
|
7
7
|
// Relationship helpers
|
|
8
8
|
export { belongsTo, hasMany, hasOne } from './relationships.js';
|
|
9
|
+
export { checkRelationships } from './relationship-check.js';
|
|
9
10
|
// Aggregation helpers
|
|
10
|
-
export { sum, count, countDistinct, avg, min, max, percentile, median, argMax, argMin, stddev, variance } from './aggregations.js';
|
|
11
|
+
export { sum, count, countDistinct, approxCountDistinct, avg, min, max, percentile, median, argMax, argMin, stddev, variance, } from './aggregations.js';
|
|
11
12
|
// Formula helpers
|
|
12
13
|
export { divide, multiply, subtract, add, nullIfZero, coalesce, round, floor, ceil, } from './formulas.js';
|
|
13
14
|
// Semantic query helpers
|
|
@@ -24,10 +25,11 @@ export { DEFAULT_AGENT_CATALOG_MAX_BYTES, assertAgentSafeCatalogBudget, projectA
|
|
|
24
25
|
// Semantic contract (stable, hashable export for snapshots/diffs/validation)
|
|
25
26
|
export { serializeSemanticContract, contractToStableJson, hashContract, SEMANTIC_CONTRACT_VERSION, } from './contract.js';
|
|
26
27
|
// Portable deployment contract adapter
|
|
27
|
-
export { rehydrateProtocolDatasets, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
|
|
28
|
+
export { rehydrateProtocolDatasets, UNSUPPORTED_CONTRACT_REASONS, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
|
|
28
29
|
export { buildProtocolDatasetContract } from './protocol-adapter.js';
|
|
29
30
|
export { buildProtocolDeploymentContract } from './protocol-deployment-adapter.js';
|
|
30
31
|
export { rehydrateProtocolDeploymentContract } from './protocol-rehydrate.js';
|
|
32
|
+
export { publishToCloud } from './cloud-publishing.js';
|
|
31
33
|
// Portable native execution of a semantic invocation (decision 0005).
|
|
32
34
|
export { createPortableSemanticExecutor, PortableExecutionBudgetError, PortableExecutionTenantError, PortableExecutionUnsupportedError, } from './portable-executor.js';
|
|
33
35
|
// SQL portability compiler (R1A-07)
|
package/dist/measure.d.ts
CHANGED
|
@@ -6,6 +6,11 @@ export declare const measure: {
|
|
|
6
6
|
readonly sum: (field: string, opts?: MeasureOptions) => MeasureDefinition;
|
|
7
7
|
readonly count: (field: string, opts?: MeasureOptions) => MeasureDefinition;
|
|
8
8
|
readonly countDistinct: (field: string, opts?: MeasureOptions) => MeasureDefinition;
|
|
9
|
+
/**
|
|
10
|
+
* Estimated number of distinct values (ClickHouse `uniq`). Uses bounded
|
|
11
|
+
* memory on high-cardinality columns; catalogs mark it `approximate`.
|
|
12
|
+
*/
|
|
13
|
+
readonly approxCountDistinct: (field: string, opts?: MeasureOptions) => MeasureDefinition;
|
|
9
14
|
readonly avg: (field: string, opts?: MeasureOptions) => MeasureDefinition;
|
|
10
15
|
readonly min: (field: string, opts?: MeasureOptions) => MeasureDefinition;
|
|
11
16
|
readonly max: (field: string, opts?: MeasureOptions) => MeasureDefinition;
|
package/dist/measure.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"measure.d.ts","sourceRoot":"","sources":["../src/measure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EAEf,MAAM,YAAY,CAAC;AAiBpB,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI3D;AAqBD,iBAAS,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,iBAAiB,CAcvG;AAED,iBAAS,oBAAoB,CAAC,KAAK,CAAC,KAAK,SAAS,kBAAkB,EAClE,OAAO,EAAE,qBAAqB,CAAC,KAAK,CAAC,GACpC,wBAAwB,CAAC,KAAK,CAAC,CASjC;AAED,eAAO,MAAM,OAAO;0BAnEH,MAAM,SAAS,cAAc,KAAG,iBAAiB;4BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;oCAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;0BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;0BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;0BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;
|
|
1
|
+
{"version":3,"file":"measure.d.ts","sourceRoot":"","sources":["../src/measure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EAEf,MAAM,YAAY,CAAC;AAiBpB,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI3D;AAqBD,iBAAS,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,iBAAiB,CAcvG;AAED,iBAAS,oBAAoB,CAAC,KAAK,CAAC,KAAK,SAAS,kBAAkB,EAClE,OAAO,EAAE,qBAAqB,CAAC,KAAK,CAAC,GACpC,wBAAwB,CAAC,KAAK,CAAC,CASjC;AAED,eAAO,MAAM,OAAO;0BAnEH,MAAM,SAAS,cAAc,KAAG,iBAAiB;4BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;oCAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;IAuEhE;;;OAGG;0CA1EY,MAAM,SAAS,cAAc,KAAG,iBAAiB;0BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;0BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;0BAAjD,MAAM,SAAS,cAAc,KAAG,iBAAiB;IA+EhE,gFAAgF;;IAEhF,mDAAmD;6BACnC,MAAM,SAAS,cAAc,KAAG,iBAAiB;IAEjE;;;;;OAKG;6BArEY,MAAM,MAAM,MAAM,SAAS,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,KAAG,iBAAiB;IAuE7F,gFAAgF;6BAvEjE,MAAM,MAAM,MAAM,SAAS,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,KAAG,iBAAiB;IAyE7F,2DAA2D;6BA7F5C,MAAM,SAAS,cAAc,KAAG,iBAAiB;IA+FhE,8CAA8C;+BA/F/B,MAAM,SAAS,cAAc,KAAG,iBAAiB;IAiGhE,0DAA0D;;CAElD,CAAC"}
|
package/dist/measure.js
CHANGED
|
@@ -64,6 +64,11 @@ export const measure = {
|
|
|
64
64
|
sum: createMeasureHelper('sum'),
|
|
65
65
|
count: createMeasureHelper('count'),
|
|
66
66
|
countDistinct: createMeasureHelper('countDistinct'),
|
|
67
|
+
/**
|
|
68
|
+
* Estimated number of distinct values (ClickHouse `uniq`). Uses bounded
|
|
69
|
+
* memory on high-cardinality columns; catalogs mark it `approximate`.
|
|
70
|
+
*/
|
|
71
|
+
approxCountDistinct: createMeasureHelper('approxCountDistinct'),
|
|
67
72
|
avg: createMeasureHelper('avg'),
|
|
68
73
|
min: createMeasureHelper('min'),
|
|
69
74
|
max: createMeasureHelper('max'),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { UnsupportedContractReason } from './utils/unsupported-contract-reasons.js';
|
|
1
2
|
/**
|
|
2
3
|
* An error that deliberately claims a portable failure category.
|
|
3
4
|
*
|
|
@@ -25,8 +26,11 @@ declare abstract class PortableExecutionError extends Error {
|
|
|
25
26
|
export declare class PortableExecutionUnsupportedError extends PortableExecutionError {
|
|
26
27
|
readonly code = "HQ_SEMANTIC_UNSUPPORTED_CAPABILITY";
|
|
27
28
|
readonly category = "unsupported-capability";
|
|
29
|
+
/** Which excluded surface this is; see `UNSUPPORTED_CONTRACT_REASONS`. */
|
|
30
|
+
readonly reason: UnsupportedContractReason | undefined;
|
|
28
31
|
constructor(message: string, options?: {
|
|
29
32
|
cause?: unknown;
|
|
33
|
+
reason?: UnsupportedContractReason;
|
|
30
34
|
});
|
|
31
35
|
}
|
|
32
36
|
export declare class PortableExecutionBudgetError extends PortableExecutionError {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portable-execution-errors.d.ts","sourceRoot":"","sources":["../src/portable-execution-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,uBAAe,sBAAuB,SAAQ,KAAK;IACjD,wEAAwE;IACxE,QAAQ,CAAC,wBAAwB,EAAG,IAAI,CAAU;IAClD,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CACpC;AAED,0EAA0E;AAC1E,qBAAa,iCAAkC,SAAQ,sBAAsB;IAC3E,QAAQ,CAAC,IAAI,wCAAwC;IACrD,QAAQ,CAAC,QAAQ,4BAA4B;
|
|
1
|
+
{"version":3,"file":"portable-execution-errors.d.ts","sourceRoot":"","sources":["../src/portable-execution-errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAC;AAEzF;;;;;;;;;;;;;;;;GAgBG;AACH,uBAAe,sBAAuB,SAAQ,KAAK;IACjD,wEAAwE;IACxE,QAAQ,CAAC,wBAAwB,EAAG,IAAI,CAAU;IAClD,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CACpC;AAED,0EAA0E;AAC1E,qBAAa,iCAAkC,SAAQ,sBAAsB;IAC3E,QAAQ,CAAC,IAAI,wCAAwC;IACrD,QAAQ,CAAC,QAAQ,4BAA4B;IAC7C,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,yBAAyB,GAAG,SAAS,CAAC;gBAGrD,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,yBAAyB,CAAA;KAAO;CAMxE;AAED,qBAAa,4BAA6B,SAAQ,sBAAsB;IACtE,QAAQ,CAAC,IAAI,iCAAiC;IAC9C,QAAQ,CAAC,QAAQ,qBAAqB;gBAE1B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;GAKG;AACH,qBAAa,4BAA6B,SAAQ,sBAAsB;IACtE,QAAQ,CAAC,IAAI,sCAAsC;IACnD,QAAQ,CAAC,QAAQ,2BAA2B;gBAEhC,OAAO,EAAE,MAAM;CAI5B"}
|
|
@@ -23,9 +23,12 @@ class PortableExecutionError extends Error {
|
|
|
23
23
|
export class PortableExecutionUnsupportedError extends PortableExecutionError {
|
|
24
24
|
code = 'HQ_SEMANTIC_UNSUPPORTED_CAPABILITY';
|
|
25
25
|
category = 'unsupported-capability';
|
|
26
|
+
/** Which excluded surface this is; see `UNSUPPORTED_CONTRACT_REASONS`. */
|
|
27
|
+
reason;
|
|
26
28
|
constructor(message, options = {}) {
|
|
27
|
-
super(message, options);
|
|
29
|
+
super(message, options.cause === undefined ? {} : { cause: options.cause });
|
|
28
30
|
this.name = 'PortableExecutionUnsupportedError';
|
|
31
|
+
this.reason = options.reason;
|
|
29
32
|
}
|
|
30
33
|
}
|
|
31
34
|
export class PortableExecutionBudgetError extends PortableExecutionError {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portable-executor.d.ts","sourceRoot":"","sources":["../src/portable-executor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iCAAiC,EAAE,4BAA4B,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAK/I;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EACV,yBAAyB,EACzB,gCAAgC,EAChC,qBAAqB,EACtB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"portable-executor.d.ts","sourceRoot":"","sources":["../src/portable-executor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iCAAiC,EAAE,4BAA4B,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAK/I;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EACV,yBAAyB,EACzB,gCAAgC,EAChC,qBAAqB,EACtB,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,6EAA6E;AAC7E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,UAAU,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,yBAAyB,EAAE,CAAA;KAAE,CAAC;IACjF,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,qBAAqB,CAAC;IAC1C,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,sBAAsB,CAAC;IACxC,yEAAyE;IACzE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,YAAY,EAAE,wBAAwB,CAAC;IAChD;;;;;OAKG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CACzC;AAID;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,+BAA+B,GACvC,CAAC,KAAK,EAAE,8BAA8B,KAAK,OAAO,CAAC,gCAAgC,CAAC,CA4EtF"}
|
|
@@ -4,7 +4,7 @@ import { tenantRuntime, semanticQuery } from './utils/portable-semantic-query.js
|
|
|
4
4
|
import { bounded } from './utils/portable-result-budget.js';
|
|
5
5
|
import { withDeadline } from './utils/portable-execution-deadline.js';
|
|
6
6
|
import { createDatasetClient } from './executor.js';
|
|
7
|
-
import { rehydrateProtocolDatasets, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
|
|
7
|
+
import { rehydrateProtocolDatasets, UNSUPPORTED_CONTRACT_REASONS, UnsupportedContractFeatureError, } from './protocol-rehydrate.js';
|
|
8
8
|
/**
|
|
9
9
|
* Build the executor the deployment data plane injects.
|
|
10
10
|
*
|
|
@@ -26,7 +26,10 @@ export function createPortableSemanticExecutor(options) {
|
|
|
26
26
|
if (error instanceof UnsupportedContractFeatureError) {
|
|
27
27
|
// Decision 0005: a surface portable execution cannot reproduce is
|
|
28
28
|
// excluded from it, never approximated.
|
|
29
|
-
throw new PortableExecutionUnsupportedError(error.message, {
|
|
29
|
+
throw new PortableExecutionUnsupportedError(error.message, {
|
|
30
|
+
cause: error,
|
|
31
|
+
...(error.reason === undefined ? {} : { reason: error.reason }),
|
|
32
|
+
});
|
|
30
33
|
}
|
|
31
34
|
throw error;
|
|
32
35
|
}
|
|
@@ -37,7 +40,7 @@ export function createPortableSemanticExecutor(options) {
|
|
|
37
40
|
const registry = registryFor(input);
|
|
38
41
|
const rebuilt = registry[String(input.dataset.name)];
|
|
39
42
|
if (rebuilt === undefined) {
|
|
40
|
-
throw new PortableExecutionUnsupportedError(`Dataset "${String(input.dataset.name)}" is not part of the activated contract
|
|
43
|
+
throw new PortableExecutionUnsupportedError(`Dataset "${String(input.dataset.name)}" is not part of the activated contract.`, { reason: UNSUPPORTED_CONTRACT_REASONS.datasetNotActivated });
|
|
41
44
|
}
|
|
42
45
|
const target = rebuilt;
|
|
43
46
|
const tenant = tenantRuntime(input.tenant);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol-adapter.d.ts","sourceRoot":"","sources":["../src/protocol-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,uBAAuB,EAE5B,KAAK,sBAAsB,
|
|
1
|
+
{"version":3,"file":"protocol-adapter.d.ts","sourceRoot":"","sources":["../src/protocol-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,uBAAuB,EAE5B,KAAK,sBAAsB,EAI5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EACV,kBAAkB,EAElB,YAAY,EAEb,MAAM,YAAY,CAAC;AAMpB,MAAM,WAAW,mCAAmC;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAC3C,QAAQ,CAAC,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC;CAC7E;AAuFD;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,kBAAkB,EAC3B,OAAO,GAAE,mCAAwC,GAChD,uBAAuB,CA0HzB"}
|
package/dist/protocol-adapter.js
CHANGED
|
@@ -2,6 +2,9 @@ import { filterExpression, metricExpression, metricDerivation } from './utils/pr
|
|
|
2
2
|
import { parseProtocolIdentifier, parseProtocolQualifiedIdentifier, validateProtocolDatasetContract, } from '@hypequery/protocol';
|
|
3
3
|
import { SEMANTIC_FILTER_OPERATORS } from './constants.js';
|
|
4
4
|
import { toProtocolSemanticMetadata } from './utils/protocol-semantic-metadata.js';
|
|
5
|
+
import { assertPublishableTimeGrains, isPortableTimeGrain, requirePortableTimeGrain } from './utils/portable-grains.js';
|
|
6
|
+
import { requirePortableAggregation } from './utils/portable-aggregations.js';
|
|
7
|
+
import { assertNoPublishedSegments } from './utils/segments.js';
|
|
5
8
|
function byName(left, right) {
|
|
6
9
|
return left.name.localeCompare(right.name);
|
|
7
10
|
}
|
|
@@ -18,13 +21,13 @@ function fieldSchema(type) {
|
|
|
18
21
|
return { kind: 'any' };
|
|
19
22
|
}
|
|
20
23
|
}
|
|
21
|
-
function unwrapMetric(metric) {
|
|
24
|
+
function unwrapMetric(metric, exposedName) {
|
|
22
25
|
return metric.__type === 'grained_metric_ref'
|
|
23
|
-
? { ref: metric.metric, grain: metric.grain }
|
|
26
|
+
? { ref: metric.metric, grain: requirePortableTimeGrain(metric.grain, `Metric "${exposedName}"`) }
|
|
24
27
|
: { ref: metric };
|
|
25
28
|
}
|
|
26
29
|
function metricContract(exposedName, metric, endpoint) {
|
|
27
|
-
const { ref, grain } = unwrapMetric(metric);
|
|
30
|
+
const { ref, grain } = unwrapMetric(metric, exposedName);
|
|
28
31
|
const contract = metric.contract();
|
|
29
32
|
const result = {
|
|
30
33
|
name: parseProtocolIdentifier(exposedName),
|
|
@@ -39,7 +42,8 @@ function metricContract(exposedName, metric, endpoint) {
|
|
|
39
42
|
: {}),
|
|
40
43
|
dimensions: [...contract.dimensions].sort().map(parseProtocolQualifiedIdentifier),
|
|
41
44
|
filters: [...contract.filters].sort().map(parseProtocolIdentifier),
|
|
42
|
-
grains
|
|
45
|
+
// Only grains the published contract can carry are advertised there.
|
|
46
|
+
grains: contract.grains.filter(isPortableTimeGrain).sort(),
|
|
43
47
|
...(grain !== undefined ? { grain } : {}),
|
|
44
48
|
...(ref.label !== undefined ? { label: ref.label } : {}),
|
|
45
49
|
...(ref.description !== undefined ? { description: ref.description } : {}),
|
|
@@ -68,8 +72,10 @@ function requiredSqlDependencies(kind, name, dependencies) {
|
|
|
68
72
|
* Deployment assembly selects the fields supported by the deployment contract.
|
|
69
73
|
*/
|
|
70
74
|
export function buildProtocolDatasetContract(dataset, options = {}) {
|
|
75
|
+
assertNoPublishedSegments(dataset);
|
|
76
|
+
assertPublishableTimeGrains(dataset);
|
|
71
77
|
const metrics = Object.entries(options.metrics ?? {})
|
|
72
|
-
.filter(([, metric]) =>
|
|
78
|
+
.filter(([, metric]) => (metric.__type === 'grained_metric_ref' ? metric.metric : metric).datasetName === dataset.name)
|
|
73
79
|
.map(([name, metric]) => {
|
|
74
80
|
const endpoint = options.metricEndpoints?.[name];
|
|
75
81
|
if (!endpoint) {
|
|
@@ -92,7 +98,9 @@ export function buildProtocolDatasetContract(dataset, options = {}) {
|
|
|
92
98
|
? { dimensions: [...dataset.defaults.dimensions].map(parseProtocolIdentifier) }
|
|
93
99
|
: {}),
|
|
94
100
|
...(dataset.defaults.timeGrain !== undefined
|
|
95
|
-
? {
|
|
101
|
+
? {
|
|
102
|
+
timeGrain: requirePortableTimeGrain(dataset.defaults.timeGrain, `Dataset "${dataset.name}" defaults.timeGrain`),
|
|
103
|
+
}
|
|
96
104
|
: {}),
|
|
97
105
|
},
|
|
98
106
|
}
|
|
@@ -115,7 +123,7 @@ export function buildProtocolDatasetContract(dataset, options = {}) {
|
|
|
115
123
|
})).sort(byName),
|
|
116
124
|
measures: Object.entries(dataset.measures).map(([name, measure]) => ({
|
|
117
125
|
name,
|
|
118
|
-
aggregation: measure.aggregation,
|
|
126
|
+
aggregation: requirePortableAggregation(measure.aggregation, `Measure "${dataset.name}.${name}"`),
|
|
119
127
|
field: measure.field,
|
|
120
128
|
...(measure.argField !== undefined ? { argField: measure.argField } : {}),
|
|
121
129
|
...(measure.level !== undefined ? { level: measure.level } : {}),
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import type { ProtocolDatasetContract, ProtocolDeploymentDataset } from '@hypequery/protocol';
|
|
15
15
|
import type { AnyDatasetInstance, DatasetCachePolicy, MetricHandle } from './types.js';
|
|
16
|
+
import { type UnsupportedContractReason } from './utils/unsupported-contract-reasons.js';
|
|
17
|
+
export { UNSUPPORTED_CONTRACT_REASONS, type UnsupportedContractReason, } from './utils/unsupported-contract-reasons.js';
|
|
16
18
|
/** A rebuilt dataset in the registry shape Serve, MCP, and the planner accept. */
|
|
17
19
|
export type RehydratedDataset = AnyDatasetInstance & {
|
|
18
20
|
readonly metrics: Readonly<Record<string, MetricHandle>>;
|
|
@@ -43,7 +45,9 @@ export interface RehydrateProtocolDatasetsOptions {
|
|
|
43
45
|
export declare class UnsupportedContractFeatureError extends Error {
|
|
44
46
|
readonly dataset: string;
|
|
45
47
|
readonly feature: string;
|
|
46
|
-
|
|
48
|
+
/** Which excluded surface this is; see `UNSUPPORTED_CONTRACT_REASONS`. */
|
|
49
|
+
readonly reason: UnsupportedContractReason | undefined;
|
|
50
|
+
constructor(datasetName: string, feature: string, detail: string, reason?: UnsupportedContractReason);
|
|
47
51
|
}
|
|
48
52
|
/**
|
|
49
53
|
* Rebuild every dataset in a validated deployment contract.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol-rehydrate.d.ts","sourceRoot":"","sources":["../src/protocol-rehydrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,uBAAuB,EAEvB,yBAAyB,EAM1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EAMlB,YAAY,EAIb,MAAM,YAAY,CAAC;AAMpB,kFAAkF;AAClF,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,GAAG;IACnD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;CAC1D,CAAC;AAEF,MAAM,WAAW,gCAAgC;IAC/C;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,kBAAkB,CAAC;IACpC;;;;;;;;OAQG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CACjD;AAED;;;;;GAKG;AACH,qBAAa,+BAAgC,SAAQ,KAAK;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"protocol-rehydrate.d.ts","sourceRoot":"","sources":["../src/protocol-rehydrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,uBAAuB,EAEvB,yBAAyB,EAM1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EAMlB,YAAY,EAIb,MAAM,YAAY,CAAC;AAMpB,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,yCAAyC,CAAC;AAEjD,OAAO,EACL,4BAA4B,EAC5B,KAAK,yBAAyB,GAC/B,MAAM,yCAAyC,CAAC;AAEjD,kFAAkF;AAClF,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,GAAG;IACnD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;CAC1D,CAAC;AAEF,MAAM,WAAW,gCAAgC;IAC/C;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,kBAAkB,CAAC;IACpC;;;;;;;;OAQG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CACjD;AAED;;;;;GAKG;AACH,qBAAa,+BAAgC,SAAQ,KAAK;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,yBAAyB,GAAG,SAAS,CAAC;gBAGrD,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,yBAAyB;CAQrC;AAoQD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,SAAS,CAAC,uBAAuB,GAAG,yBAAyB,CAAC,EAAE,EAC3E,OAAO,GAAE,gCAAqC,GAC7C,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAwF7C;AAED,gFAAgF;AAChF,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,gCAAqC,GAC7C,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAG7C"}
|
|
@@ -17,6 +17,9 @@ import { snapshotSemanticMetadata } from './utils/semantic-metadata.js';
|
|
|
17
17
|
import { withContractCapabilities } from './utils/protocol-metric-capabilities.js';
|
|
18
18
|
import { rehydrateDerivedFormula } from './utils/protocol-rehydrate-derivation.js';
|
|
19
19
|
import { rehydrateMeasureFilter } from './utils/protocol-rehydrate-filters.js';
|
|
20
|
+
import { PORTABLE_TIME_GRAINS } from './utils/portable-grains.js';
|
|
21
|
+
import { UNSUPPORTED_CONTRACT_REASONS, } from './utils/unsupported-contract-reasons.js';
|
|
22
|
+
export { UNSUPPORTED_CONTRACT_REASONS, } from './utils/unsupported-contract-reasons.js';
|
|
20
23
|
/**
|
|
21
24
|
* Thrown when a contract describes something portable execution cannot rebuild.
|
|
22
25
|
*
|
|
@@ -26,11 +29,14 @@ import { rehydrateMeasureFilter } from './utils/protocol-rehydrate-filters.js';
|
|
|
26
29
|
export class UnsupportedContractFeatureError extends Error {
|
|
27
30
|
dataset;
|
|
28
31
|
feature;
|
|
29
|
-
|
|
32
|
+
/** Which excluded surface this is; see `UNSUPPORTED_CONTRACT_REASONS`. */
|
|
33
|
+
reason;
|
|
34
|
+
constructor(datasetName, feature, detail, reason) {
|
|
30
35
|
super(`Cannot rebuild ${feature} on dataset "${datasetName}": ${detail}`);
|
|
31
36
|
this.name = 'UnsupportedContractFeatureError';
|
|
32
37
|
this.dataset = datasetName;
|
|
33
38
|
this.feature = feature;
|
|
39
|
+
this.reason = reason;
|
|
34
40
|
}
|
|
35
41
|
}
|
|
36
42
|
function rehydrateDimensions(contract) {
|
|
@@ -57,7 +63,7 @@ function rehydrateDimensions(contract) {
|
|
|
57
63
|
return dimensions;
|
|
58
64
|
}
|
|
59
65
|
function rehydrateMeasure(datasetName, measure) {
|
|
60
|
-
const filters = measure.filters.map((expression, index) => rehydrateMeasureFilter(expression, () => new UnsupportedContractFeatureError(datasetName, `measure "${String(measure.name)}"`, `fixed filter ${index} is not a field/operator/value comparison
|
|
66
|
+
const filters = measure.filters.map((expression, index) => rehydrateMeasureFilter(expression, () => new UnsupportedContractFeatureError(datasetName, `measure "${String(measure.name)}"`, `fixed filter ${index} is not a field/operator/value comparison`, UNSUPPORTED_CONTRACT_REASONS.measureFilterNotComparison)));
|
|
61
67
|
return {
|
|
62
68
|
__type: 'measure_definition',
|
|
63
69
|
...snapshotSemanticMetadata(measure),
|
|
@@ -78,7 +84,7 @@ function rehydrateDerivedMeasure(datasetName, measure) {
|
|
|
78
84
|
__type: 'derived_measure_definition',
|
|
79
85
|
...snapshotSemanticMetadata(measure),
|
|
80
86
|
uses: Object.fromEntries(measure.uses.map(input => [String(input.alias), String(input.measure)])),
|
|
81
|
-
formula: rehydrateDerivedFormula({ inputs: [], expression: measure.expression }, reason => new UnsupportedContractFeatureError(datasetName, `measure "${measure.name}"`, reason)),
|
|
87
|
+
formula: rehydrateDerivedFormula({ inputs: [], expression: measure.expression }, reason => new UnsupportedContractFeatureError(datasetName, `measure "${measure.name}"`, reason, UNSUPPORTED_CONTRACT_REASONS.unsupportedFormula)),
|
|
82
88
|
...(measure.label !== undefined ? { label: measure.label } : {}),
|
|
83
89
|
...(measure.description !== undefined ? { description: measure.description } : {}),
|
|
84
90
|
};
|
|
@@ -139,12 +145,12 @@ function aggregationKey(value) {
|
|
|
139
145
|
*/
|
|
140
146
|
function measureForAggregate(instance, contract, subject, expression) {
|
|
141
147
|
if (expression.kind !== 'aggregate') {
|
|
142
|
-
throw new UnsupportedContractFeatureError(instance.name, subject, `expected an aggregate expression, received "${expression.kind}"
|
|
148
|
+
throw new UnsupportedContractFeatureError(instance.name, subject, `expected an aggregate expression, received "${expression.kind}"`, UNSUPPORTED_CONTRACT_REASONS.expressionNotAggregate);
|
|
143
149
|
}
|
|
144
150
|
const field = String(expression.field);
|
|
145
151
|
const candidates = contract.measures.filter(measure => (aggregationKey(measure) === aggregationKey(expression)));
|
|
146
152
|
if (candidates.length === 0) {
|
|
147
|
-
throw new UnsupportedContractFeatureError(instance.name, subject, `no declared measure matches ${expression.aggregation}(${field})
|
|
153
|
+
throw new UnsupportedContractFeatureError(instance.name, subject, `no declared measure matches ${expression.aggregation}(${field})`, UNSUPPORTED_CONTRACT_REASONS.noMatchingMeasure);
|
|
148
154
|
}
|
|
149
155
|
// A metric expression carries no raw SQL, so two measures that share an
|
|
150
156
|
// aggregation identity but override SQL differently are indistinguishable in
|
|
@@ -153,7 +159,7 @@ function measureForAggregate(instance, contract, subject, expression) {
|
|
|
153
159
|
if (distinctSql.size > 1) {
|
|
154
160
|
throw new UnsupportedContractFeatureError(instance.name, subject, `${candidates.map(measure => `"${String(measure.name)}"`).join(' and ')} share `
|
|
155
161
|
+ `${expression.aggregation}(${field}) but emit different SQL, so the contract cannot `
|
|
156
|
-
+ 'say which one this metric was built from');
|
|
162
|
+
+ 'say which one this metric was built from', UNSUPPORTED_CONTRACT_REASONS.ambiguousMeasureSql);
|
|
157
163
|
}
|
|
158
164
|
return String(candidates[0].name);
|
|
159
165
|
}
|
|
@@ -164,7 +170,7 @@ function measureForAggregate(instance, contract, subject, expression) {
|
|
|
164
170
|
* what both plan builders emit as the column of the intermediate aggregate.
|
|
165
171
|
*/
|
|
166
172
|
function derivedMetricConfig(instance, contract, subject, derivation) {
|
|
167
|
-
const unsupported = (reason) => new UnsupportedContractFeatureError(instance.name, subject, reason);
|
|
173
|
+
const unsupported = (reason) => new UnsupportedContractFeatureError(instance.name, subject, reason, UNSUPPORTED_CONTRACT_REASONS.unsupportedFormula);
|
|
168
174
|
const uses = Object.fromEntries(derivation.inputs.map(input => {
|
|
169
175
|
const alias = String(input.alias);
|
|
170
176
|
return [
|
|
@@ -184,7 +190,7 @@ function rehydrateMetric(instance, contract, metric) {
|
|
|
184
190
|
// The inlined expression states what a derived metric means but drops the
|
|
185
191
|
// aliases its SQL is written in terms of. Without them a rebuild computes
|
|
186
192
|
// the same number through different SQL, which decision 0005 excludes.
|
|
187
|
-
throw new UnsupportedContractFeatureError(instance.name, subject, 'a derived metric requires its authored formula, which this contract does not carry');
|
|
193
|
+
throw new UnsupportedContractFeatureError(instance.name, subject, 'a derived metric requires its authored formula, which this contract does not carry', UNSUPPORTED_CONTRACT_REASONS.derivedMetricWithoutFormula);
|
|
188
194
|
}
|
|
189
195
|
const metadata = {
|
|
190
196
|
...snapshotSemanticMetadata(metric),
|
|
@@ -234,7 +240,7 @@ export function rehydrateProtocolDatasets(contracts, options = {}) {
|
|
|
234
240
|
if (!instance) {
|
|
235
241
|
// The deployment validator already rejects a dangling relationship, so
|
|
236
242
|
// reaching this means the caller passed a partial contract.
|
|
237
|
-
throw new UnsupportedContractFeatureError(target, 'relationship target', `dataset "${target}" is not part of the supplied contract
|
|
243
|
+
throw new UnsupportedContractFeatureError(target, 'relationship target', `dataset "${target}" is not part of the supplied contract`, UNSUPPORTED_CONTRACT_REASONS.relationshipTargetMissing);
|
|
238
244
|
}
|
|
239
245
|
return instance;
|
|
240
246
|
};
|
|
@@ -251,7 +257,11 @@ export function rehydrateProtocolDatasets(contracts, options = {}) {
|
|
|
251
257
|
...(contract.defaults.dimensions !== undefined ? { dimensions: [...contract.defaults.dimensions] } : {}),
|
|
252
258
|
} } : {}),
|
|
253
259
|
...(contract.tenant.kind === 'required' ? { tenantKey: contract.tenant.field } : {}),
|
|
254
|
-
|
|
260
|
+
// A published dataset supports only the grains its contract can carry,
|
|
261
|
+
// so its catalog never advertises a grain the portable path would refuse.
|
|
262
|
+
...(contract.timeField !== undefined
|
|
263
|
+
? { timeKey: String(contract.timeField), timeGrains: PORTABLE_TIME_GRAINS }
|
|
264
|
+
: {}),
|
|
255
265
|
dimensions: rehydrateDimensions(contract),
|
|
256
266
|
measures: Object.fromEntries([
|
|
257
267
|
...contract.measures.map(measure => [
|
|
@@ -27,12 +27,16 @@ export interface QueryBuilderLike {
|
|
|
27
27
|
stddev?(column: string, alias?: string): QueryBuilderLike;
|
|
28
28
|
/** Sample variance of `column`. */
|
|
29
29
|
variance?(column: string, alias?: string): QueryBuilderLike;
|
|
30
|
+
/** Estimated number of distinct non-NULL values of `column`. */
|
|
31
|
+
approxCountDistinct?(column: string, alias?: string): QueryBuilderLike;
|
|
30
32
|
where(column: string, operator: string, value: unknown): QueryBuilderLike;
|
|
31
33
|
leftJoin(table: string, leftColumn: string, rightColumn: string, alias?: string, on?: QueryBuilderJoinCondition | QueryBuilderJoinCondition[]): QueryBuilderLike;
|
|
32
34
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
35
|
+
* Single-match LEFT JOIN (ClickHouse `LEFT ANY JOIN`). Required to query
|
|
36
|
+
* relationship-qualified fields: duplicate target join keys cannot fan out
|
|
37
|
+
* aggregates. A builder without it can still run every query that does not
|
|
38
|
+
* traverse a relationship; one that does is rejected with a clear error
|
|
39
|
+
* instead of falling back to `leftJoin`.
|
|
36
40
|
*/
|
|
37
41
|
leftAnyJoin?(table: string, leftColumn: string, rightColumn: string, alias?: string, on?: QueryBuilderJoinCondition | QueryBuilderJoinCondition[]): QueryBuilderLike;
|
|
38
42
|
groupBy(columns: string | string[]): QueryBuilderLike;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-builder-protocol.d.ts","sourceRoot":"","sources":["../src/query-builder-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,gBAAgB,CAAC;IAGrD,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IACtD,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IACxD,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAChE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IACtD,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IACtD,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAGtD,kEAAkE;IAClE,MAAM,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC7E,kEAAkE;IAClE,MAAM,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC7E,+DAA+D;IAC/D,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC3E,6CAA6C;IAC7C,MAAM,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC1D,mCAAmC;IACnC,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"query-builder-protocol.d.ts","sourceRoot":"","sources":["../src/query-builder-protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-planner.d.ts","sourceRoot":"","sources":["../src/query-planner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,SAAS,EACV,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAMpE,OAAO,EAGL,KAAK,0BAA0B,EAChC,MAAM,sCAAsC,CAAC;AAI9C,KAAK,YAAY,GAAG,kBAAkB,CAAC;AA6BvC,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,YAAY,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,0BAA0B,GACnC,MAAM,CAUR;AAED,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,YAAY,EAChB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,0BAA0B,GACnC,MAAM,CAMR;AAED,wBAAgB,2BAA2B,CACzC,EAAE,EAAE,YAAY,EAChB,UAAU,EAAE,MAAM,EAAE,EACpB,KAAK,EAAE,SAAS,GAAG,SAAS,EAC5B,OAAO,CAAC,EAAE,0BAA0B,GACnC;IAAE,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAkCnD;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,gBAAgB,EACpB,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,0BAA0B,GACnC,gBAAgB,
|
|
1
|
+
{"version":3,"file":"query-planner.d.ts","sourceRoot":"","sources":["../src/query-planner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,SAAS,EACV,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAMpE,OAAO,EAGL,KAAK,0BAA0B,EAChC,MAAM,sCAAsC,CAAC;AAI9C,KAAK,YAAY,GAAG,kBAAkB,CAAC;AA6BvC,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,YAAY,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,0BAA0B,GACnC,MAAM,CAUR;AAED,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,YAAY,EAChB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,0BAA0B,GACnC,MAAM,CAMR;AAED,wBAAgB,2BAA2B,CACzC,EAAE,EAAE,YAAY,EAChB,UAAU,EAAE,MAAM,EAAE,EACpB,KAAK,EAAE,SAAS,GAAG,SAAS,EAC5B,OAAO,CAAC,EAAE,0BAA0B,GACnC;IAAE,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAkCnD;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,gBAAgB,EACpB,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,0BAA0B,GACnC,gBAAgB,CAqElB;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,gBAAgB,EACpB,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,iBAAiB,EAC7B,OAAO,CAAC,EAAE,0BAA0B,GACnC,gBAAgB,CAElB;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,gBAAgB,EACpB,OAAO,EAAE,aAAa,EAAE,GAAG,SAAS,EACpC,KAAK,EAAE,SAAS,GAAG,SAAS,EAC5B,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,0BAA0B,GACnC,gBAAgB,CAoBlB;AAED,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,YAAY,EAChB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,GAAG,SAAS,CAMpB"}
|
package/dist/query-planner.js
CHANGED
|
@@ -120,6 +120,11 @@ export function applyAggregationSpec(qb, ds, spec, alias, joinCtx) {
|
|
|
120
120
|
}
|
|
121
121
|
return qb.quantile(fieldOrExpr, spec.level, alias);
|
|
122
122
|
}
|
|
123
|
+
case "approxCountDistinct":
|
|
124
|
+
if (!qb.approxCountDistinct) {
|
|
125
|
+
throw new Error('Query builder does not support approxCountDistinct aggregations.');
|
|
126
|
+
}
|
|
127
|
+
return qb.approxCountDistinct(fieldOrExpr, alias);
|
|
123
128
|
case "stddev":
|
|
124
129
|
if (!qb.stddev) {
|
|
125
130
|
throw new Error('Query builder does not support stddev aggregations.');
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verifies declared to-one relationships against the data.
|
|
3
|
+
*
|
|
4
|
+
* `belongsTo` and `hasOne` are declarations: nothing at query time proves the
|
|
5
|
+
* target join column is unique. Relationship joins are single-match, so a
|
|
6
|
+
* duplicate key cannot inflate an aggregate, but the join then takes an
|
|
7
|
+
* arbitrary one of the matching rows and grouped values drift without any
|
|
8
|
+
* error. `checkRelationships` counts rows and distinct keys on each target so a
|
|
9
|
+
* mis-declaration is caught in CI or at deploy time rather than in a report.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const result = await checkRelationships(Orders, { queryBuilder: db });
|
|
14
|
+
* if (!result.ok) {
|
|
15
|
+
* throw new Error(result.issues.map((issue) => issue.message).join('\n'));
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
import type { AnyDatasetInstance, ExecutionContext } from './types.js';
|
|
20
|
+
import { type QueryBuilderFactoryInput } from './query-builder-protocol.js';
|
|
21
|
+
import { type RelationshipKeyIssue } from './utils/relationship-key-check.js';
|
|
22
|
+
export type { RelationshipKeyIssue } from './utils/relationship-key-check.js';
|
|
23
|
+
export interface CheckRelationshipsOptions {
|
|
24
|
+
/** Query builder factory used to count target keys. */
|
|
25
|
+
queryBuilder: QueryBuilderFactoryInput;
|
|
26
|
+
/**
|
|
27
|
+
* Runtime context. A tenant-scoped target is checked within the runtime
|
|
28
|
+
* tenant, the same scope its join uses, so it requires tenant runtime.
|
|
29
|
+
*/
|
|
30
|
+
context?: ExecutionContext;
|
|
31
|
+
/** Restrict the check to these to-one relationship names. */
|
|
32
|
+
relationships?: readonly string[];
|
|
33
|
+
}
|
|
34
|
+
export interface CheckRelationshipsResult {
|
|
35
|
+
/** True when every checked relationship has a unique target key. */
|
|
36
|
+
ok: boolean;
|
|
37
|
+
/** Relationship names that were checked. */
|
|
38
|
+
checked: string[];
|
|
39
|
+
issues: RelationshipKeyIssue[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Checks that the target join column of each `belongsTo` and `hasOne`
|
|
43
|
+
* relationship on `ds` is unique. NULL keys are ignored because they never
|
|
44
|
+
* match a join. `hasMany` relationships are skipped.
|
|
45
|
+
*/
|
|
46
|
+
export declare function checkRelationships(ds: AnyDatasetInstance, options: CheckRelationshipsOptions): Promise<CheckRelationshipsResult>;
|
|
47
|
+
//# sourceMappingURL=relationship-check.d.ts.map
|