@duckcodeailabs/dql-cli 1.10.1 → 1.10.3
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/assets/dql-notebook/assets/{index-pl1On-IO.js → index-VvEaTurJ.js} +338 -335
- package/dist/assets/dql-notebook/index.html +1 -1
- package/dist/local-runtime.d.ts.map +1 -1
- package/dist/local-runtime.js +161 -62
- package/dist/local-runtime.js.map +1 -1
- package/dist/package.json +10 -10
- package/dist/semantic-import.d.ts +6 -0
- package/dist/semantic-import.d.ts.map +1 -1
- package/dist/semantic-import.js +45 -13
- package/dist/semantic-import.js.map +1 -1
- package/dist/semantic-runtime.d.ts +107 -11
- package/dist/semantic-runtime.d.ts.map +1 -1
- package/dist/semantic-runtime.js +392 -56
- package/dist/semantic-runtime.js.map +1 -1
- package/package.json +10 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"semantic-runtime.d.ts","sourceRoot":"","sources":["../src/semantic-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"semantic-runtime.d.ts","sourceRoot":"","sources":["../src/semantic-runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/semantic-runtime.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { semanticDimensionReference, } from '@duckcodeailabs/dql-core';
|
|
1
2
|
import { compileDbtCloudSemanticQuery, listDbtCloudCompatibleDimensions, testDbtCloudSemanticConnection, } from './dbt-cloud-semantic.js';
|
|
2
3
|
import { compileMetricFlowQuery, hasDbtSemanticManifest, hasMetricFlowCli, listMetricFlowDimensions, managedMetricFlowBin, MetricFlowUnavailableError, resolveMetricFlowCli } from './metricflow.js';
|
|
3
4
|
import { getEffectiveDbtCloudSemanticSettings, getSemanticRuntimeSettings, semanticRuntimeDraft, } from './semantic-runtime-settings.js';
|
|
@@ -8,6 +9,66 @@ export class SemanticRuntimeRequiredError extends Error {
|
|
|
8
9
|
this.name = 'SemanticRuntimeRequiredError';
|
|
9
10
|
}
|
|
10
11
|
}
|
|
12
|
+
export class SemanticRuntimeCompilationError extends Error {
|
|
13
|
+
code = 'SEMANTIC_COMPILATION_FAILED';
|
|
14
|
+
adapter;
|
|
15
|
+
constructor(adapter, error) {
|
|
16
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
17
|
+
super(`${adapter} semantic compilation failed: ${message}`, {
|
|
18
|
+
cause: error instanceof Error ? error : undefined,
|
|
19
|
+
});
|
|
20
|
+
this.name = 'SemanticRuntimeCompilationError';
|
|
21
|
+
this.adapter = adapter;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export class SemanticRuntimePathAmbiguityError extends Error {
|
|
25
|
+
code = 'SEMANTIC_PATH_AMBIGUOUS';
|
|
26
|
+
adapter;
|
|
27
|
+
details;
|
|
28
|
+
semanticTrace;
|
|
29
|
+
constructor(input) {
|
|
30
|
+
const choices = input.candidates.map((candidate) => candidate.label).join(' or ');
|
|
31
|
+
const message = `The semantic dimension "${input.authoringReference}" is reachable through more than one governed entity path (${choices}). Choose the intended path before DQL compiles or executes the query.`;
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = 'SemanticRuntimePathAmbiguityError';
|
|
34
|
+
this.adapter = input.adapter;
|
|
35
|
+
this.details = {
|
|
36
|
+
authoringReference: input.authoringReference,
|
|
37
|
+
runtimeReference: input.runtimeReference,
|
|
38
|
+
candidates: input.candidates,
|
|
39
|
+
};
|
|
40
|
+
this.semanticTrace = {
|
|
41
|
+
version: 1,
|
|
42
|
+
adapter: input.adapter,
|
|
43
|
+
status: 'ambiguous',
|
|
44
|
+
authoringRequest: input.authoringRequest,
|
|
45
|
+
runtimeRequest: input.runtimeRequest,
|
|
46
|
+
bindings: [
|
|
47
|
+
...input.bindings.filter((binding) => binding.runtimeReference !== input.runtimeReference),
|
|
48
|
+
{
|
|
49
|
+
role: inferSemanticBindingRole(input.authoringRequest, input.authoringReference),
|
|
50
|
+
authoringReference: input.authoringReference,
|
|
51
|
+
runtimeReference: input.runtimeReference,
|
|
52
|
+
entityPath: [],
|
|
53
|
+
status: 'ambiguous',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
warnings: input.warnings,
|
|
57
|
+
steps: [
|
|
58
|
+
{ id: 'resolve_members', label: 'Resolve governed semantic members', status: 'completed', detail: 'Metric and dimension identities resolved from the pinned semantic snapshot.' },
|
|
59
|
+
{ id: 'bind_entity_paths', label: 'Bind metric-relative entity paths', status: 'failed', detail: message },
|
|
60
|
+
{ id: 'compile_semantic_query', label: 'Compile with the selected semantic adapter', status: 'not_started', detail: 'Compilation is gated until one entity path is selected.' },
|
|
61
|
+
{ id: 'execute_query', label: 'Execute the compiled warehouse query', status: 'not_started', detail: 'Nothing was executed.' },
|
|
62
|
+
],
|
|
63
|
+
failure: {
|
|
64
|
+
code: 'SEMANTIC_PATH_AMBIGUOUS',
|
|
65
|
+
phase: 'path_binding',
|
|
66
|
+
message,
|
|
67
|
+
candidates: input.candidates,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
11
72
|
const cloudProbeCache = new Map();
|
|
12
73
|
const OFFSET_PARAMETER_KEYS = new Set(['offsetwindow', 'offsettograin']);
|
|
13
74
|
const METRIC_DEPENDENCY_KEYS = new Set([
|
|
@@ -305,23 +366,67 @@ export async function explainMissingSemanticRuntime(projectRoot, dbtProjectPath)
|
|
|
305
366
|
export function qualifyForMetricFlow(request, semanticLayer) {
|
|
306
367
|
const warnings = [];
|
|
307
368
|
const { compatible } = semanticLayer.explainCompatibleDimensions(request.metrics);
|
|
308
|
-
const
|
|
369
|
+
const qualifiedByReference = new Map();
|
|
309
370
|
for (const dim of compatible) {
|
|
310
|
-
if (dim.qualifiedName)
|
|
311
|
-
|
|
371
|
+
if (!dim.qualifiedName)
|
|
372
|
+
continue;
|
|
373
|
+
for (const reference of [
|
|
374
|
+
dim.name,
|
|
375
|
+
semanticDimensionReference(dim),
|
|
376
|
+
dim.source?.objectId,
|
|
377
|
+
dim.qualifiedName,
|
|
378
|
+
]) {
|
|
379
|
+
if (reference) {
|
|
380
|
+
qualifiedByReference.set(reference.toLowerCase(), {
|
|
381
|
+
runtimeReference: dim.qualifiedName,
|
|
382
|
+
entityPath: dim.entityPath ?? [],
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
}
|
|
312
386
|
}
|
|
313
|
-
const
|
|
387
|
+
const bindings = [];
|
|
388
|
+
const qualify = (name, role) => {
|
|
314
389
|
if (!name)
|
|
315
390
|
return name;
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
391
|
+
const selection = parseSemanticDimensionSelection(name);
|
|
392
|
+
const authoringReference = selection.reference;
|
|
393
|
+
let runtimeReference;
|
|
394
|
+
let entityPath = selection.entityPath ?? [];
|
|
395
|
+
if (authoringReference === 'metric_time' || (authoringReference.includes('__') && !selection.entityPath)) {
|
|
396
|
+
runtimeReference = authoringReference;
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
const exact = semanticLayer.resolveDimension(authoringReference, request.metrics);
|
|
400
|
+
const compatibleBinding = qualifiedByReference.get(authoringReference.toLowerCase());
|
|
401
|
+
const baseRuntimeReference = compatibleBinding?.runtimeReference
|
|
402
|
+
?? exact?.qualifiedName
|
|
403
|
+
?? authoringReference;
|
|
404
|
+
if (selection.entityPath?.length) {
|
|
405
|
+
const prefix = `${selection.entityPath.join('__')}__`;
|
|
406
|
+
runtimeReference = baseRuntimeReference.startsWith(prefix)
|
|
407
|
+
? baseRuntimeReference
|
|
408
|
+
: `${prefix}${baseRuntimeReference}`;
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
runtimeReference = baseRuntimeReference;
|
|
412
|
+
entityPath = compatibleBinding?.entityPath ?? [];
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
bindings.push({
|
|
416
|
+
role,
|
|
417
|
+
authoringReference,
|
|
418
|
+
runtimeReference,
|
|
419
|
+
entityPath,
|
|
420
|
+
status: 'resolved',
|
|
421
|
+
});
|
|
422
|
+
return runtimeReference;
|
|
319
423
|
};
|
|
320
424
|
const timeDimension = request.timeDimension
|
|
321
425
|
? (() => {
|
|
322
|
-
const
|
|
426
|
+
const selection = parseSemanticDimensionSelection(request.timeDimension.name);
|
|
427
|
+
const name = qualify(request.timeDimension.name, 'time_dimension');
|
|
323
428
|
let granularity = request.timeDimension.granularity;
|
|
324
|
-
const td = semanticLayer.getTimeDimension(
|
|
429
|
+
const td = semanticLayer.getTimeDimension(selection.reference);
|
|
325
430
|
if (td?.granularities?.length && !td.granularities.includes(granularity)) {
|
|
326
431
|
const clamped = td.granularities[0];
|
|
327
432
|
warnings.push(`Time grain "${granularity}" is finer than ${request.timeDimension.name}'s base grain; using "${clamped}".`);
|
|
@@ -332,34 +437,158 @@ export function qualifyForMetricFlow(request, semanticLayer) {
|
|
|
332
437
|
: undefined;
|
|
333
438
|
return {
|
|
334
439
|
warnings,
|
|
440
|
+
bindings,
|
|
335
441
|
request: {
|
|
336
442
|
...request,
|
|
337
|
-
dimensions: request.dimensions.map((d) => qualify(d) ?? d),
|
|
338
|
-
...(request.filters ? { filters: request.filters.map((f) => f.dimension ? { ...f, dimension: qualify(f.dimension) } : f) } : {}),
|
|
339
|
-
...(request.orderBy ? { orderBy: request.orderBy.map((o) => ({ ...o, name: qualify(o.name) ?? o.name })) } : {}),
|
|
443
|
+
dimensions: request.dimensions.map((d) => qualify(d, 'dimension') ?? d),
|
|
444
|
+
...(request.filters ? { filters: request.filters.map((f) => f.dimension ? { ...f, dimension: qualify(f.dimension, 'filter') } : f) } : {}),
|
|
445
|
+
...(request.orderBy ? { orderBy: request.orderBy.map((o) => ({ ...o, name: qualify(o.name, 'order_by') ?? o.name })) } : {}),
|
|
340
446
|
...(timeDimension ? { timeDimension } : {}),
|
|
341
447
|
},
|
|
342
448
|
};
|
|
343
449
|
}
|
|
450
|
+
const SEMANTIC_PATH_SELECTION = /^(.*?)@via\(([^)]+)\)$/;
|
|
451
|
+
export function parseSemanticDimensionSelection(value) {
|
|
452
|
+
const match = value.trim().match(SEMANTIC_PATH_SELECTION);
|
|
453
|
+
if (!match)
|
|
454
|
+
return { reference: value };
|
|
455
|
+
const entityPath = match[2]
|
|
456
|
+
.split('>')
|
|
457
|
+
.map((part) => part.trim())
|
|
458
|
+
.filter((part) => /^[A-Za-z0-9_]+$/.test(part));
|
|
459
|
+
return entityPath.length > 0
|
|
460
|
+
? { reference: match[1].trim(), entityPath }
|
|
461
|
+
: { reference: match[1].trim() };
|
|
462
|
+
}
|
|
463
|
+
export function formatSemanticDimensionSelection(reference, entityPath) {
|
|
464
|
+
return entityPath.length > 0 ? `${reference}@via(${entityPath.join('>')})` : reference;
|
|
465
|
+
}
|
|
466
|
+
export function applySemanticPathSelection(request, authoringReference, entityPath) {
|
|
467
|
+
const bind = (value) => {
|
|
468
|
+
const parsed = parseSemanticDimensionSelection(value);
|
|
469
|
+
const selectedReference = parsed.reference.toLowerCase();
|
|
470
|
+
const requestedReference = authoringReference.toLowerCase();
|
|
471
|
+
const sameReference = selectedReference === requestedReference
|
|
472
|
+
|| ((!selectedReference.includes('.') || !requestedReference.includes('.'))
|
|
473
|
+
&& selectedReference.split('.').pop() === requestedReference.split('.').pop());
|
|
474
|
+
return sameReference ? formatSemanticDimensionSelection(parsed.reference, entityPath) : value;
|
|
475
|
+
};
|
|
476
|
+
return {
|
|
477
|
+
...request,
|
|
478
|
+
dimensions: request.dimensions.map(bind),
|
|
479
|
+
...(request.filters ? { filters: request.filters.map((filter) => filter.dimension ? { ...filter, dimension: bind(filter.dimension) } : filter) } : {}),
|
|
480
|
+
...(request.orderBy ? { orderBy: request.orderBy.map((order) => ({ ...order, name: bind(order.name) })) } : {}),
|
|
481
|
+
...(request.timeDimension ? { timeDimension: { ...request.timeDimension, name: bind(request.timeDimension.name) } } : {}),
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
export function encodeSemanticPathEvidenceId(authoringReference, entityPath) {
|
|
485
|
+
return `semantic-path:${encodeURIComponent(authoringReference)}:${encodeURIComponent(entityPath.join('>'))}`;
|
|
486
|
+
}
|
|
487
|
+
export function decodeSemanticPathEvidenceId(value) {
|
|
488
|
+
if (!value?.startsWith('semantic-path:'))
|
|
489
|
+
return undefined;
|
|
490
|
+
const [, encodedReference, encodedPath] = value.split(':');
|
|
491
|
+
if (!encodedReference || !encodedPath)
|
|
492
|
+
return undefined;
|
|
493
|
+
try {
|
|
494
|
+
const entityPath = decodeURIComponent(encodedPath).split('>').filter(Boolean);
|
|
495
|
+
return entityPath.length > 0
|
|
496
|
+
? { authoringReference: decodeURIComponent(encodedReference), entityPath }
|
|
497
|
+
: undefined;
|
|
498
|
+
}
|
|
499
|
+
catch {
|
|
500
|
+
return undefined;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
function inferSemanticBindingRole(request, authoringReference) {
|
|
504
|
+
const matches = (value) => parseSemanticDimensionSelection(value ?? '').reference.toLowerCase() === authoringReference.toLowerCase();
|
|
505
|
+
if (matches(request.timeDimension?.name))
|
|
506
|
+
return 'time_dimension';
|
|
507
|
+
if (request.filters?.some((filter) => matches(filter.dimension)))
|
|
508
|
+
return 'filter';
|
|
509
|
+
if (request.orderBy?.some((order) => matches(order.name)))
|
|
510
|
+
return 'order_by';
|
|
511
|
+
return 'dimension';
|
|
512
|
+
}
|
|
513
|
+
function semanticTraceForSuccess(input) {
|
|
514
|
+
return {
|
|
515
|
+
version: 1,
|
|
516
|
+
adapter: input.adapter,
|
|
517
|
+
status: 'compiled',
|
|
518
|
+
authoringRequest: input.authoringRequest,
|
|
519
|
+
...(input.runtimeRequest ? { runtimeRequest: input.runtimeRequest } : {}),
|
|
520
|
+
bindings: input.bindings,
|
|
521
|
+
warnings: input.warnings,
|
|
522
|
+
steps: [
|
|
523
|
+
{ id: 'resolve_members', label: 'Resolve governed semantic members', status: 'completed', detail: 'Metric and dimension identities resolved from the pinned semantic snapshot.' },
|
|
524
|
+
{ id: 'bind_entity_paths', label: 'Bind metric-relative entity paths', status: 'completed', detail: input.bindings.length > 0 ? `${input.bindings.length} runtime member binding(s) resolved.` : 'No dimension path binding was required.' },
|
|
525
|
+
{ id: 'compile_semantic_query', label: 'Compile with the selected semantic adapter', status: 'completed', detail: `Compiled through ${input.adapter}.` },
|
|
526
|
+
{ id: 'execute_query', label: 'Execute the compiled warehouse query', status: 'not_started', detail: 'Execution is owned by the authorized host after compilation.' },
|
|
527
|
+
],
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
export function semanticPathAmbiguityFromError(input) {
|
|
531
|
+
const message = input.error instanceof Error ? input.error.message : String(input.error);
|
|
532
|
+
if (!/ambiguous and can(?:not|'t) be resolved/i.test(message))
|
|
533
|
+
return undefined;
|
|
534
|
+
const parsedCandidates = [];
|
|
535
|
+
const candidatePattern = /(?:TimeDimension|Dimension)\(\s*['"]([^'"]+)['"][^)]*?entity_path=\[([^\]]*)\]/g;
|
|
536
|
+
for (const match of message.matchAll(candidatePattern)) {
|
|
537
|
+
const entityPath = Array.from(match[2].matchAll(/['"]([^'"]+)['"]/g), (item) => item[1]).filter(Boolean);
|
|
538
|
+
if (entityPath.length > 0)
|
|
539
|
+
parsedCandidates.push({ baseRuntimeReference: match[1], entityPath });
|
|
540
|
+
}
|
|
541
|
+
if (parsedCandidates.length < 2)
|
|
542
|
+
return undefined;
|
|
543
|
+
const runtimeReference = parsedCandidates[0].baseRuntimeReference;
|
|
544
|
+
const matchingBinding = input.bindings.find((binding) => binding.runtimeReference === runtimeReference);
|
|
545
|
+
const authoringReference = matchingBinding?.authoringReference
|
|
546
|
+
?? input.authoringRequest.timeDimension?.name
|
|
547
|
+
?? input.authoringRequest.dimensions[0]
|
|
548
|
+
?? runtimeReference;
|
|
549
|
+
const candidates = parsedCandidates.map((candidate) => {
|
|
550
|
+
const runtimeName = `${candidate.entityPath.join('__')}__${candidate.baseRuntimeReference}`;
|
|
551
|
+
return {
|
|
552
|
+
id: encodeSemanticPathEvidenceId(authoringReference, candidate.entityPath),
|
|
553
|
+
label: `Use ${authoringReference} via ${candidate.entityPath.join(' → ')}`,
|
|
554
|
+
description: `Bind the governed member to ${runtimeName}. No SQL will run until this path is selected.`,
|
|
555
|
+
authoringReference,
|
|
556
|
+
runtimeReference: runtimeName,
|
|
557
|
+
entityPath: candidate.entityPath,
|
|
558
|
+
selectionReference: formatSemanticDimensionSelection(authoringReference, candidate.entityPath),
|
|
559
|
+
};
|
|
560
|
+
});
|
|
561
|
+
return new SemanticRuntimePathAmbiguityError({
|
|
562
|
+
adapter: input.adapter,
|
|
563
|
+
authoringRequest: input.authoringRequest,
|
|
564
|
+
runtimeRequest: input.runtimeRequest,
|
|
565
|
+
bindings: input.bindings,
|
|
566
|
+
warnings: input.warnings,
|
|
567
|
+
authoringReference,
|
|
568
|
+
runtimeReference,
|
|
569
|
+
candidates,
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
function semanticRequestWithoutPathSelectors(request) {
|
|
573
|
+
const strip = (value) => parseSemanticDimensionSelection(value).reference;
|
|
574
|
+
return {
|
|
575
|
+
...request,
|
|
576
|
+
dimensions: request.dimensions.map(strip),
|
|
577
|
+
...(request.filters ? { filters: request.filters.map((filter) => filter.dimension ? { ...filter, dimension: strip(filter.dimension) } : filter) } : {}),
|
|
578
|
+
...(request.orderBy ? { orderBy: request.orderBy.map((order) => ({ ...order, name: strip(order.name) })) } : {}),
|
|
579
|
+
...(request.timeDimension ? { timeDimension: { ...request.timeDimension, name: strip(request.timeDimension.name) } } : {}),
|
|
580
|
+
};
|
|
581
|
+
}
|
|
344
582
|
export async function compileSemanticRuntimeQuery(request, context) {
|
|
345
583
|
const effectiveRequest = normalizeSemanticRuntimeQueryRequest(request, context.semanticLayer);
|
|
346
584
|
const status = await getSemanticRuntimeStatus(context.projectRoot, { probeConfiguredCloud: true });
|
|
347
585
|
const explicit = effectiveRequest.engine;
|
|
348
586
|
const fullRuntimeRequested = explicit === 'metricflow' || explicit === 'metricflow-cli' || explicit === 'dbt-cloud';
|
|
349
|
-
const candidates = explicit
|
|
350
|
-
|
|
351
|
-
: explicit === 'dbt-cloud'
|
|
352
|
-
? ['dbt-cloud']
|
|
353
|
-
: explicit === 'metricflow-cli'
|
|
354
|
-
? ['metricflow-cli']
|
|
355
|
-
: status.active === 'dbt-cloud'
|
|
356
|
-
? ['dbt-cloud', 'metricflow-cli', 'native']
|
|
357
|
-
: status.active === 'metricflow-cli'
|
|
358
|
-
? ['metricflow-cli', 'dbt-cloud', 'native']
|
|
359
|
-
: ['native'];
|
|
587
|
+
const candidates = selectSemanticRuntimeAdapters(explicit, status.active);
|
|
588
|
+
const routeLockedToFullRuntime = candidates.length === 1 && candidates[0] !== 'native';
|
|
360
589
|
// Qualify dimension references to MetricFlow entity-qualified names ONCE, at
|
|
361
590
|
// this boundary, for the full-runtime engines. Native keeps the bare request.
|
|
362
|
-
const { request: runtimeRequest, warnings: qualifyWarnings } = qualifyForMetricFlow(effectiveRequest, context.semanticLayer);
|
|
591
|
+
const { request: runtimeRequest, warnings: qualifyWarnings, bindings, } = qualifyForMetricFlow(effectiveRequest, context.semanticLayer);
|
|
363
592
|
let lastRuntimeError;
|
|
364
593
|
for (const adapter of candidates) {
|
|
365
594
|
if (adapter === 'dbt-cloud') {
|
|
@@ -368,13 +597,38 @@ export async function compileSemanticRuntimeQuery(request, context) {
|
|
|
368
597
|
continue;
|
|
369
598
|
try {
|
|
370
599
|
const result = await compileDbtCloudSemanticQuery(getEffectiveDbtCloudSemanticSettings(context.projectRoot), runtimeRequest);
|
|
371
|
-
return {
|
|
600
|
+
return {
|
|
601
|
+
sql: result.sql,
|
|
602
|
+
joins: [],
|
|
603
|
+
tables: [],
|
|
604
|
+
engine: 'dbt-cloud',
|
|
605
|
+
effectiveRequest,
|
|
606
|
+
runtimeRequest,
|
|
607
|
+
semanticTrace: semanticTraceForSuccess({
|
|
608
|
+
adapter: 'dbt-cloud',
|
|
609
|
+
authoringRequest: effectiveRequest,
|
|
610
|
+
runtimeRequest,
|
|
611
|
+
bindings,
|
|
612
|
+
warnings: qualifyWarnings,
|
|
613
|
+
}),
|
|
614
|
+
warnings: qualifyWarnings,
|
|
615
|
+
};
|
|
372
616
|
}
|
|
373
617
|
catch (error) {
|
|
374
618
|
lastRuntimeError = error instanceof Error ? error : new Error(String(error));
|
|
375
|
-
if (
|
|
376
|
-
throw
|
|
377
|
-
|
|
619
|
+
if (isSemanticRuntimeError(error))
|
|
620
|
+
throw error;
|
|
621
|
+
const ambiguity = semanticPathAmbiguityFromError({
|
|
622
|
+
adapter: 'dbt-cloud',
|
|
623
|
+
error,
|
|
624
|
+
authoringRequest: effectiveRequest,
|
|
625
|
+
runtimeRequest,
|
|
626
|
+
bindings,
|
|
627
|
+
warnings: qualifyWarnings,
|
|
628
|
+
});
|
|
629
|
+
if (ambiguity)
|
|
630
|
+
throw ambiguity;
|
|
631
|
+
throw new SemanticRuntimeCompilationError('dbt-cloud', error);
|
|
378
632
|
}
|
|
379
633
|
}
|
|
380
634
|
if (adapter === 'metricflow-cli') {
|
|
@@ -396,29 +650,70 @@ export async function compileSemanticRuntimeQuery(request, context) {
|
|
|
396
650
|
limit: runtimeRequest.limit,
|
|
397
651
|
savedQuery: runtimeRequest.savedQuery,
|
|
398
652
|
});
|
|
399
|
-
return {
|
|
653
|
+
return {
|
|
654
|
+
sql: compiled.sql,
|
|
655
|
+
joins: [],
|
|
656
|
+
tables: [],
|
|
657
|
+
engine: 'metricflow-cli',
|
|
658
|
+
effectiveRequest,
|
|
659
|
+
runtimeRequest,
|
|
660
|
+
semanticTrace: semanticTraceForSuccess({
|
|
661
|
+
adapter: 'metricflow-cli',
|
|
662
|
+
authoringRequest: effectiveRequest,
|
|
663
|
+
runtimeRequest,
|
|
664
|
+
bindings,
|
|
665
|
+
warnings: qualifyWarnings,
|
|
666
|
+
}),
|
|
667
|
+
warnings: qualifyWarnings,
|
|
668
|
+
};
|
|
400
669
|
}
|
|
401
670
|
catch (error) {
|
|
402
671
|
lastRuntimeError = error instanceof Error ? error : new Error(String(error));
|
|
403
|
-
if (
|
|
404
|
-
throw
|
|
405
|
-
|
|
672
|
+
if (isSemanticRuntimeError(error))
|
|
673
|
+
throw error;
|
|
674
|
+
const ambiguity = semanticPathAmbiguityFromError({
|
|
675
|
+
adapter: 'metricflow-cli',
|
|
676
|
+
error,
|
|
677
|
+
authoringRequest: effectiveRequest,
|
|
678
|
+
runtimeRequest,
|
|
679
|
+
bindings,
|
|
680
|
+
warnings: qualifyWarnings,
|
|
681
|
+
});
|
|
682
|
+
if (ambiguity)
|
|
683
|
+
throw ambiguity;
|
|
684
|
+
throw new SemanticRuntimeCompilationError('metricflow-cli', error);
|
|
406
685
|
}
|
|
407
686
|
}
|
|
687
|
+
const nativeRequest = semanticRequestWithoutPathSelectors(effectiveRequest);
|
|
408
688
|
const composed = context.semanticLayer.composeQuery({
|
|
409
|
-
metrics:
|
|
410
|
-
dimensions:
|
|
411
|
-
filters:
|
|
412
|
-
limit:
|
|
413
|
-
timeDimension:
|
|
414
|
-
orderBy:
|
|
689
|
+
metrics: nativeRequest.metrics,
|
|
690
|
+
dimensions: nativeRequest.dimensions,
|
|
691
|
+
filters: nativeRequest.filters,
|
|
692
|
+
limit: nativeRequest.limit,
|
|
693
|
+
timeDimension: nativeRequest.timeDimension,
|
|
694
|
+
orderBy: nativeRequest.orderBy,
|
|
415
695
|
driver: context.driver,
|
|
416
696
|
tableMapping: context.tableMapping,
|
|
417
697
|
});
|
|
418
|
-
if (composed)
|
|
419
|
-
return {
|
|
698
|
+
if (composed) {
|
|
699
|
+
return {
|
|
700
|
+
...composed,
|
|
701
|
+
engine: 'native',
|
|
702
|
+
effectiveRequest,
|
|
703
|
+
semanticTrace: semanticTraceForSuccess({
|
|
704
|
+
adapter: 'native',
|
|
705
|
+
authoringRequest: effectiveRequest,
|
|
706
|
+
bindings: bindings.map((binding) => ({
|
|
707
|
+
...binding,
|
|
708
|
+
runtimeReference: parseSemanticDimensionSelection(binding.authoringReference).reference,
|
|
709
|
+
entityPath: [],
|
|
710
|
+
})),
|
|
711
|
+
warnings: [],
|
|
712
|
+
}),
|
|
713
|
+
};
|
|
714
|
+
}
|
|
420
715
|
}
|
|
421
|
-
if (fullRuntimeRequested) {
|
|
716
|
+
if (fullRuntimeRequested || routeLockedToFullRuntime) {
|
|
422
717
|
throw lastRuntimeError ?? new SemanticRuntimeRequiredError(status.setup ?? 'The requested semantic runtime is unavailable.');
|
|
423
718
|
}
|
|
424
719
|
if (lastRuntimeError && !context.semanticLayer.canComposeMetric(effectiveRequest.metrics[0] ?? '')) {
|
|
@@ -427,11 +722,22 @@ export async function compileSemanticRuntimeQuery(request, context) {
|
|
|
427
722
|
return null;
|
|
428
723
|
}
|
|
429
724
|
/**
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
725
|
+
* AGT-013/AGT-014/SEC-004: planning selects one adapter. Compilation may not
|
|
726
|
+
* silently downgrade to another semantic engine or native SQL after selection.
|
|
727
|
+
*/
|
|
728
|
+
export function selectSemanticRuntimeAdapters(requested, active) {
|
|
729
|
+
if (requested === 'native')
|
|
730
|
+
return ['native'];
|
|
731
|
+
if (requested === 'dbt-cloud')
|
|
732
|
+
return ['dbt-cloud'];
|
|
733
|
+
if (requested === 'metricflow' || requested === 'metricflow-cli')
|
|
734
|
+
return ['metricflow-cli'];
|
|
735
|
+
return [active];
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* The authoritative per-metric dimension-compatibility answer from the exact
|
|
739
|
+
* adapter selected for execution. A selected adapter failure is preserved; it
|
|
740
|
+
* never becomes a native compatibility answer.
|
|
435
741
|
*/
|
|
436
742
|
export async function describeRuntimeCompatibility(projectRoot, semanticLayer, metrics, projectConfig) {
|
|
437
743
|
if (metrics.length === 0)
|
|
@@ -450,9 +756,8 @@ export async function describeRuntimeCompatibility(projectRoot, semanticLayer, m
|
|
|
450
756
|
if (status.active === 'dbt-cloud') {
|
|
451
757
|
try {
|
|
452
758
|
const cloud = await listDbtCloudCompatibleDimensions(getEffectiveDbtCloudSemanticSettings(projectRoot), metrics);
|
|
453
|
-
const localByName = new Map(semanticLayer.listDimensions().map((d) => [d.name.toLowerCase(), d]));
|
|
454
759
|
const dimensions = cloud.map((dimension) => {
|
|
455
|
-
const local =
|
|
760
|
+
const local = semanticLayer.resolveDimension(dimension.name, metrics);
|
|
456
761
|
const isTime = dimension.type?.toLowerCase() === 'time';
|
|
457
762
|
return {
|
|
458
763
|
...(local ?? {
|
|
@@ -473,8 +778,7 @@ export async function describeRuntimeCompatibility(projectRoot, semanticLayer, m
|
|
|
473
778
|
return { engine: 'dbt-cloud', dimensions, incompatible: [] };
|
|
474
779
|
}
|
|
475
780
|
catch (error) {
|
|
476
|
-
|
|
477
|
-
return { ...native, degraded: `dbt Cloud dimension listing failed (${error instanceof Error ? error.message : String(error)}); showing native compatibility.` };
|
|
781
|
+
throw new SemanticRuntimeRequiredError(`dbt Cloud dimension listing failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
478
782
|
}
|
|
479
783
|
}
|
|
480
784
|
// Local MetricFlow: ask mf itself, then hydrate labels/types from the local
|
|
@@ -485,10 +789,10 @@ export async function describeRuntimeCompatibility(projectRoot, semanticLayer, m
|
|
|
485
789
|
: projectConfig?.dbt?.projectDir;
|
|
486
790
|
const mfDims = listMetricFlowDimensions({ projectRoot, dbtProjectPath, profilesDir: projectConfig?.dbt?.profilesDir, metrics });
|
|
487
791
|
if (mfDims.length > 0) {
|
|
488
|
-
const localByTail = new Map(semanticLayer.listDimensions().map((d) => [d.name.toLowerCase(), d]));
|
|
489
792
|
const dimensions = mfDims.map((mf) => {
|
|
490
793
|
const tail = mf.qualifiedName.split('__').pop().toLowerCase();
|
|
491
|
-
const local =
|
|
794
|
+
const local = semanticLayer.resolveDimension(mf.qualifiedName, metrics)
|
|
795
|
+
?? semanticLayer.resolveDimension(tail, metrics);
|
|
492
796
|
const isTime = Boolean(mf.granularities?.length) || Boolean(local?.isTimeDimension);
|
|
493
797
|
return {
|
|
494
798
|
...(local ?? {
|
|
@@ -508,7 +812,7 @@ export async function describeRuntimeCompatibility(projectRoot, semanticLayer, m
|
|
|
508
812
|
});
|
|
509
813
|
return { engine: 'metricflow-cli', dimensions, incompatible: [] };
|
|
510
814
|
}
|
|
511
|
-
|
|
815
|
+
throw new SemanticRuntimeRequiredError('Local MetricFlow returned no compatible dimensions for the selected metrics.');
|
|
512
816
|
}
|
|
513
817
|
return nativeExplain();
|
|
514
818
|
}
|
|
@@ -583,10 +887,14 @@ async function probeDbtCloudSemanticRuntime(projectRoot) {
|
|
|
583
887
|
return result;
|
|
584
888
|
}
|
|
585
889
|
function selectActiveAdapter(preference, cloudReady, cliReady) {
|
|
890
|
+
// An explicit preference is a route lock, including while setup is broken.
|
|
891
|
+
// Reporting the preferred adapter as active lets every surface return the
|
|
892
|
+
// original readiness/compiler failure instead of silently selecting a
|
|
893
|
+
// different engine with different semantic behavior.
|
|
586
894
|
if (preference === 'dbt-cloud')
|
|
587
|
-
return
|
|
895
|
+
return 'dbt-cloud';
|
|
588
896
|
if (preference === 'metricflow-cli')
|
|
589
|
-
return
|
|
897
|
+
return 'metricflow-cli';
|
|
590
898
|
if (preference === 'native')
|
|
591
899
|
return 'native';
|
|
592
900
|
if (cloudReady)
|
|
@@ -596,6 +904,34 @@ function selectActiveAdapter(preference, cloudReady, cliReady) {
|
|
|
596
904
|
return 'native';
|
|
597
905
|
}
|
|
598
906
|
export function isSemanticRuntimeError(error) {
|
|
599
|
-
return error instanceof SemanticRuntimeRequiredError
|
|
907
|
+
return error instanceof SemanticRuntimeRequiredError
|
|
908
|
+
|| error instanceof SemanticRuntimeCompilationError
|
|
909
|
+
|| error instanceof SemanticRuntimePathAmbiguityError
|
|
910
|
+
|| error instanceof MetricFlowUnavailableError;
|
|
911
|
+
}
|
|
912
|
+
export function semanticRuntimeErrorCode(error) {
|
|
913
|
+
if (error instanceof SemanticRuntimePathAmbiguityError)
|
|
914
|
+
return error.code;
|
|
915
|
+
if (error instanceof SemanticRuntimeCompilationError)
|
|
916
|
+
return error.code;
|
|
917
|
+
if (error instanceof SemanticRuntimeRequiredError || error instanceof MetricFlowUnavailableError) {
|
|
918
|
+
return 'SEMANTIC_RUNTIME_REQUIRED';
|
|
919
|
+
}
|
|
920
|
+
return undefined;
|
|
921
|
+
}
|
|
922
|
+
export function semanticRuntimeErrorDetails(error) {
|
|
923
|
+
if (error instanceof SemanticRuntimePathAmbiguityError) {
|
|
924
|
+
return {
|
|
925
|
+
...error.details,
|
|
926
|
+
semanticTrace: error.semanticTrace,
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
if (error instanceof SemanticRuntimeCompilationError) {
|
|
930
|
+
return {
|
|
931
|
+
adapter: error.adapter,
|
|
932
|
+
phase: 'compilation',
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
return undefined;
|
|
600
936
|
}
|
|
601
937
|
//# sourceMappingURL=semantic-runtime.js.map
|