@malloydata/malloy 0.0.435 → 0.0.436
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/foundation/build_targets.d.ts +5 -6
- package/dist/api/foundation/build_targets.js +74 -6
- package/dist/api/foundation/core.d.ts +16 -4
- package/dist/api/foundation/core.js +23 -23
- package/dist/api/foundation/index.d.ts +1 -1
- package/dist/api/foundation/runtime.d.ts +21 -2
- package/dist/api/foundation/runtime.js +44 -31
- package/dist/api/foundation/types.d.ts +43 -3
- package/dist/connection/dbmeta.d.ts +29 -0
- package/dist/connection/dbmeta.js +46 -0
- package/dist/connection/index.d.ts +1 -0
- package/dist/connection/index.js +1 -0
- package/dist/dialect/databricks/databricks.d.ts +11 -12
- package/dist/dialect/databricks/databricks.js +24 -36
- package/dist/dialect/dialect.d.ts +56 -170
- package/dist/dialect/dialect.js +89 -90
- package/dist/dialect/duckdb/duckdb.d.ts +2 -2
- package/dist/dialect/duckdb/duckdb.js +1 -1
- package/dist/dialect/index.d.ts +1 -1
- package/dist/dialect/index.js +2 -2
- package/dist/dialect/mysql/mysql.d.ts +11 -12
- package/dist/dialect/mysql/mysql.js +20 -32
- package/dist/dialect/pg_impl.d.ts +9 -10
- package/dist/dialect/pg_impl.js +27 -73
- package/dist/dialect/postgres/postgres.d.ts +4 -4
- package/dist/dialect/postgres/postgres.js +4 -12
- package/dist/dialect/snowflake/snowflake.d.ts +11 -13
- package/dist/dialect/snowflake/snowflake.js +30 -82
- package/dist/dialect/sqlserver/sqlserver.d.ts +12 -13
- package/dist/dialect/sqlserver/sqlserver.js +46 -47
- package/dist/dialect/standardsql/standardsql.d.ts +11 -16
- package/dist/dialect/standardsql/standardsql.js +22 -73
- package/dist/dialect/trino/trino.d.ts +16 -18
- package/dist/dialect/trino/trino.js +127 -181
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/lang/ast/expressions/boolean-value.d.ts +24 -0
- package/dist/lang/ast/expressions/boolean-value.js +41 -0
- package/dist/lang/ast/expressions/case.js +7 -0
- package/dist/lang/ast/expressions/expr-alternation-tree.js +11 -0
- package/dist/lang/ast/expressions/expr-cast.js +5 -0
- package/dist/lang/ast/expressions/expr-coalesce.js +4 -0
- package/dist/lang/ast/expressions/expr-func.js +13 -2
- package/dist/lang/ast/expressions/expr-minus.js +5 -2
- package/dist/lang/ast/expressions/expr-null.js +4 -0
- package/dist/lang/ast/expressions/pick-when.js +7 -0
- package/dist/lang/ast/field-space/index-field-space.js +13 -1
- package/dist/lang/ast/field-space/query-spaces.js +11 -0
- package/dist/lang/ast/query-builders/reduce-builder.js +1 -1
- package/dist/lang/ast/query-items/field-declaration.d.ts +5 -0
- package/dist/lang/ast/query-items/field-declaration.js +22 -16
- package/dist/lang/ast/query-items/field-references.d.ts +6 -0
- package/dist/lang/ast/query-items/field-references.js +23 -0
- package/dist/lang/ast/query-properties/filters.js +3 -1
- package/dist/lang/ast/statements/import-statement.js +13 -0
- package/dist/lang/ast/types/expression-def.js +17 -2
- package/dist/lang/ast/types/malloy-element.d.ts +24 -1
- package/dist/lang/ast/types/malloy-element.js +63 -26
- package/dist/lang/ast/view-elements/reference-view.js +4 -0
- package/dist/lang/ast/view-elements/refine-utils.js +1 -0
- package/dist/lang/composite-source-utils.js +10 -17
- package/dist/lang/parse-log.d.ts +12 -0
- package/dist/lang/parse-log.js +2 -0
- package/dist/lang/test/test-translator.d.ts +2 -1
- package/dist/lang/test/test-translator.js +37 -3
- package/dist/model/expression_compiler.js +8 -7
- package/dist/model/filter_compilers.js +13 -12
- package/dist/model/given_binding.d.ts +8 -0
- package/dist/model/given_binding.js +13 -0
- package/dist/model/index.d.ts +1 -1
- package/dist/model/index.js +2 -1
- package/dist/model/sql_compiled.d.ts +19 -20
- package/dist/model/sql_compiled.js +29 -17
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
|
@@ -2,7 +2,7 @@ import type { BuildIdOptions } from '../../model';
|
|
|
2
2
|
import type { LogMessage } from '../../lang';
|
|
3
3
|
import type { PersistNode } from '../../model/persist_utils';
|
|
4
4
|
import type { Model, PersistSource } from './core';
|
|
5
|
-
import type {
|
|
5
|
+
import type { BuildTargets } from './types';
|
|
6
6
|
/**
|
|
7
7
|
* A walk node with its source already resolved.
|
|
8
8
|
*
|
|
@@ -47,9 +47,8 @@ export declare function resolvePersistWalk(model: Model, tagParseLog: LogMessage
|
|
|
47
47
|
*
|
|
48
48
|
* @param walk A resolved walk from {@link resolvePersistWalk}, in order
|
|
49
49
|
* @param connectionDigests One digest per connection named by a persist source
|
|
50
|
-
* @param buildIdOpts What
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* looks up.
|
|
50
|
+
* @param buildIdOpts What every BuildID's SQL is generated under.
|
|
51
|
+
* `BuildTarget.buildSQL` generates its SQL under the same options, and
|
|
52
|
+
* `persistedTableFor` recomputes the key under a query's.
|
|
54
53
|
*/
|
|
55
|
-
export declare function mkBuildTargets(walk: ResolvedNode[], connectionDigests: Record<string, string>, buildIdOpts: BuildIdOptions):
|
|
54
|
+
export declare function mkBuildTargets(walk: ResolvedNode[], connectionDigests: Record<string, string>, buildIdOpts: BuildIdOptions): Pick<BuildTargets, 'connections' | 'unbuildable'>;
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.resolvePersistWalk = resolvePersistWalk;
|
|
8
8
|
exports.mkBuildTargets = mkBuildTargets;
|
|
9
|
+
const model_1 = require("../../model");
|
|
10
|
+
const given_binding_1 = require("../../model/given_binding");
|
|
9
11
|
/**
|
|
10
12
|
* Read a key this function's own construction guarantees is present.
|
|
11
13
|
*
|
|
@@ -38,6 +40,54 @@ function resolvePersistWalk(model, tagParseLog) {
|
|
|
38
40
|
}
|
|
39
41
|
return resolved;
|
|
40
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Describes a given that `source` reads and this build has no value for.
|
|
45
|
+
* Names it by the name this model surfaces it under, since that is the name a
|
|
46
|
+
* builder supplies a value by: under `import { T is TENANT }` it is `T`.
|
|
47
|
+
*/
|
|
48
|
+
function unvaluedGivenProblem(source, use) {
|
|
49
|
+
var _a, _b, _c, _d, _e;
|
|
50
|
+
const modelDef = source._model._modelDef;
|
|
51
|
+
const surfaced = Object.entries(modelDef.contents).find(([, entry]) => entry.type === 'given' && entry.id === use.id);
|
|
52
|
+
const name = (_d = (_a = surfaced === null || surfaced === void 0 ? void 0 : surfaced[0]) !== null && _a !== void 0 ? _a : (_c = (_b = modelDef.givens) === null || _b === void 0 ? void 0 : _b[use.id]) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : use.id;
|
|
53
|
+
return {
|
|
54
|
+
severity: 'error',
|
|
55
|
+
code: 'runtime-persist-given-no-value',
|
|
56
|
+
at: (_e = use.at) !== null && _e !== void 0 ? _e : source.location,
|
|
57
|
+
message: `Persisted source '${source.sourceID}' reads given '${name}', which ` +
|
|
58
|
+
`has no value in this build and no default. Supply '${name}' to the ` +
|
|
59
|
+
'build, or give it a default at its declaration.',
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Generates the SQL that keys `source`'s table, or returns why no key can be
|
|
64
|
+
* computed. A `MalloyCompileError` is a problem with the source; any other
|
|
65
|
+
* error is the compiler's own and propagates.
|
|
66
|
+
*/
|
|
67
|
+
function buildIdSQL(source, opts) {
|
|
68
|
+
var _a;
|
|
69
|
+
const reads = (0, model_1.givenUsageOfRelation)(source._sourceDef);
|
|
70
|
+
const givens = source._model._modelDef.givens;
|
|
71
|
+
const unvalued = reads.find(use => (0, given_binding_1.lookupGivenValue)(opts.resolvedGivens, givens, use.id) === undefined);
|
|
72
|
+
if (unvalued !== undefined) {
|
|
73
|
+
return { problem: unvaluedGivenProblem(source, unvalued) };
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
return { sql: source._compileSQL(opts), readsGivens: reads.length > 0 };
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
if (!(e instanceof model_1.MalloyCompileError))
|
|
80
|
+
throw e;
|
|
81
|
+
return {
|
|
82
|
+
problem: {
|
|
83
|
+
message: e.message,
|
|
84
|
+
severity: 'error',
|
|
85
|
+
code: e.code,
|
|
86
|
+
at: (_a = e.at) !== null && _a !== void 0 ? _a : source.location,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
41
91
|
/** A BuildID is a hex digest, so it cannot contain the separator. */
|
|
42
92
|
function targetKey(connectionName, buildId) {
|
|
43
93
|
return `${connectionName}:${buildId}`;
|
|
@@ -75,14 +125,14 @@ function addUnique(into, seen, keys) {
|
|
|
75
125
|
*
|
|
76
126
|
* @param walk A resolved walk from {@link resolvePersistWalk}, in order
|
|
77
127
|
* @param connectionDigests One digest per connection named by a persist source
|
|
78
|
-
* @param buildIdOpts What
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* looks up.
|
|
128
|
+
* @param buildIdOpts What every BuildID's SQL is generated under.
|
|
129
|
+
* `BuildTarget.buildSQL` generates its SQL under the same options, and
|
|
130
|
+
* `persistedTableFor` recomputes the key under a query's.
|
|
82
131
|
*/
|
|
83
132
|
function mkBuildTargets(walk, connectionDigests, buildIdOpts) {
|
|
84
133
|
var _a;
|
|
85
134
|
const targets = new Map();
|
|
135
|
+
const unbuildable = [];
|
|
86
136
|
// What each source hands to whoever referenced it: its own target if it is
|
|
87
137
|
// one, otherwise whatever it was a route to.
|
|
88
138
|
const contributes = new Map();
|
|
@@ -105,7 +155,15 @@ function mkBuildTargets(walk, connectionDigests, buildIdOpts) {
|
|
|
105
155
|
`BuildID of '${node.sourceID}'. Supply a digest for every connection ` +
|
|
106
156
|
'named by a persist source.');
|
|
107
157
|
}
|
|
108
|
-
const
|
|
158
|
+
const keyed = buildIdSQL(source, buildIdOpts);
|
|
159
|
+
if ('problem' in keyed) {
|
|
160
|
+
// No key, so no table: pass its dependencies up as a route does.
|
|
161
|
+
// Whatever reads it inlines its SQL and ends up here too.
|
|
162
|
+
unbuildable.push({ source, problem: keyed.problem });
|
|
163
|
+
contributes.set(node.sourceID, childKeys);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const { sql, readsGivens } = keyed;
|
|
109
167
|
const buildId = source.makeBuildId(digest, sql);
|
|
110
168
|
const key = targetKey(connectionName, buildId);
|
|
111
169
|
let target = targets.get(key);
|
|
@@ -114,6 +172,7 @@ function mkBuildTargets(walk, connectionDigests, buildIdOpts) {
|
|
|
114
172
|
buildId,
|
|
115
173
|
connectionName,
|
|
116
174
|
sql,
|
|
175
|
+
readsGivens,
|
|
117
176
|
sources: [],
|
|
118
177
|
dependsOn: new Set(),
|
|
119
178
|
};
|
|
@@ -164,10 +223,19 @@ function mkBuildTargets(walk, connectionDigests, buildIdOpts) {
|
|
|
164
223
|
// point both ways round a diamond.
|
|
165
224
|
const built = new Map();
|
|
166
225
|
for (const [key, partial] of targets) {
|
|
226
|
+
// Every source on a target compiles to the same SQL, so any of them can
|
|
227
|
+
// produce the build SQL; the manifest is the only thing the builder adds.
|
|
228
|
+
const [source] = partial.sources;
|
|
167
229
|
built.set(key, {
|
|
168
230
|
buildId: partial.buildId,
|
|
169
231
|
connectionName: partial.connectionName,
|
|
170
232
|
sql: partial.sql,
|
|
233
|
+
buildSQL: (manifest) => source._compileSQL({
|
|
234
|
+
...buildIdOpts,
|
|
235
|
+
buildManifest: manifest,
|
|
236
|
+
connectionDigests,
|
|
237
|
+
}),
|
|
238
|
+
readsGivens: partial.readsGivens,
|
|
171
239
|
sources: partial.sources,
|
|
172
240
|
dependsOn: [],
|
|
173
241
|
});
|
|
@@ -220,6 +288,6 @@ function mkBuildTargets(walk, connectionDigests, buildIdOpts) {
|
|
|
220
288
|
for (const [connectionName, connectionTargets] of byConnection) {
|
|
221
289
|
connections.push({ connectionName, targets: connectionTargets });
|
|
222
290
|
}
|
|
223
|
-
return connections;
|
|
291
|
+
return { connections, unbuildable };
|
|
224
292
|
}
|
|
225
293
|
//# sourceMappingURL=build_targets.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LogMessage } from '../../lang';
|
|
2
|
-
import type { BuildID, CompiledQuery, ConstantExpr, DocumentLocation, BooleanFieldDef, JSONFieldDef, NumberFieldDef, StringFieldDef, FilterCondition, Given as InternalGiven, GivenID, GivenTypeDef, Query as InternalQuery, Pipeline, ModelDef, DocumentPosition as ModelDocumentPosition, NamedQueryDef, StructDef, TurtleDef, NativeUnsupportedFieldDef, ImportLocation, AnnotationsDef, ModelAnnotationEntry, ModelID, NamedModelObject, AtomicFieldDef, DateFieldDef, ATimestampFieldDef, SourceDef, Argument, SourceComponentInfo, DocumentReference, PersistableSourceDef } from '../../model';
|
|
2
|
+
import type { BuildID, CompiledQuery, ConstantExpr, DocumentLocation, BooleanFieldDef, JSONFieldDef, NumberFieldDef, StringFieldDef, FilterCondition, Given as InternalGiven, GivenID, GivenTypeDef, Query as InternalQuery, Pipeline, ModelDef, DocumentPosition as ModelDocumentPosition, NamedQueryDef, StructDef, TurtleDef, NativeUnsupportedFieldDef, ImportLocation, AnnotationsDef, ModelAnnotationEntry, ModelID, NamedModelObject, AtomicFieldDef, DateFieldDef, ATimestampFieldDef, SourceDef, Argument, SourceComponentInfo, DocumentReference, PersistableSourceDef, PrepareResultOptions } from '../../model';
|
|
3
3
|
import { QueryModel } from '../../model';
|
|
4
4
|
import type { Dialect } from '../../dialect';
|
|
5
5
|
import type { BuildGraph, CompileQueryOptions } from './types';
|
|
@@ -603,6 +603,8 @@ export declare class PersistSource implements Taggable {
|
|
|
603
603
|
* @param connectionDigest - Digest from connection.getDigest()
|
|
604
604
|
* @param sql - The SQL for this source (from getSQL())
|
|
605
605
|
* @return The BuildID for manifest lookup
|
|
606
|
+
* @deprecated `BuildTarget.buildId` is already computed, under the build's
|
|
607
|
+
* own givens and `virtualMap`. Used only with `Model.getBuildPlan`.
|
|
606
608
|
*/
|
|
607
609
|
makeBuildId(connectionDigest: string, sql: string): BuildID;
|
|
608
610
|
/**
|
|
@@ -613,12 +615,22 @@ export declare class PersistSource implements Taggable {
|
|
|
613
615
|
*
|
|
614
616
|
* @param options - Compile options. `buildManifest` and `connectionDigests`
|
|
615
617
|
* substitute already-built dependencies, giving the SQL to execute.
|
|
616
|
-
* Anything that changes the SQL without them — `virtualMap` — must match
|
|
617
|
-
* what the compiler will use, or the table is built under a key nothing
|
|
618
|
-
* looks up.
|
|
619
618
|
* @return The SQL string for this source.
|
|
619
|
+
* @deprecated Read `BuildTarget.sql` and call `BuildTarget.buildSQL()`. This
|
|
620
|
+
* generates SQL under whatever `options` say, so it can disagree with the key
|
|
621
|
+
* the build computed; the target's methods cannot. Used only with
|
|
622
|
+
* `Model.getBuildPlan`.
|
|
620
623
|
*/
|
|
621
624
|
getSQL(options?: CompileQueryOptions): string;
|
|
625
|
+
/**
|
|
626
|
+
* This source's SQL under `opts`: the bare `SELECT`, not finalized, because
|
|
627
|
+
* `persistedTableFor` hashes the same unfinalized SELECT to look the table
|
|
628
|
+
* up, and a dialect with a final stage (Postgres) would hash differently.
|
|
629
|
+
*
|
|
630
|
+
* @internal `opts` is whatever the caller passes; `BuildTarget.sql` and
|
|
631
|
+
* `buildSQL()` pass the build's own.
|
|
632
|
+
*/
|
|
633
|
+
_compileSQL(opts: PrepareResultOptions): string;
|
|
622
634
|
/**
|
|
623
635
|
* Get the underlying persistable source definition.
|
|
624
636
|
*/
|
|
@@ -1347,6 +1347,8 @@ class PersistSource {
|
|
|
1347
1347
|
* @param connectionDigest - Digest from connection.getDigest()
|
|
1348
1348
|
* @param sql - The SQL for this source (from getSQL())
|
|
1349
1349
|
* @return The BuildID for manifest lookup
|
|
1350
|
+
* @deprecated `BuildTarget.buildId` is already computed, under the build's
|
|
1351
|
+
* own givens and `virtualMap`. Used only with `Model.getBuildPlan`.
|
|
1350
1352
|
*/
|
|
1351
1353
|
makeBuildId(connectionDigest, sql) {
|
|
1352
1354
|
return (0, source_def_utils_1.mkBuildID)(connectionDigest, sql);
|
|
@@ -1359,26 +1361,33 @@ class PersistSource {
|
|
|
1359
1361
|
*
|
|
1360
1362
|
* @param options - Compile options. `buildManifest` and `connectionDigests`
|
|
1361
1363
|
* substitute already-built dependencies, giving the SQL to execute.
|
|
1362
|
-
* Anything that changes the SQL without them — `virtualMap` — must match
|
|
1363
|
-
* what the compiler will use, or the table is built under a key nothing
|
|
1364
|
-
* looks up.
|
|
1365
1364
|
* @return The SQL string for this source.
|
|
1365
|
+
* @deprecated Read `BuildTarget.sql` and call `BuildTarget.buildSQL()`. This
|
|
1366
|
+
* generates SQL under whatever `options` say, so it can disagree with the key
|
|
1367
|
+
* the build computed; the target's methods cannot. Used only with
|
|
1368
|
+
* `Model.getBuildPlan`.
|
|
1366
1369
|
*/
|
|
1367
1370
|
getSQL(options) {
|
|
1371
|
+
return this._compileSQL({
|
|
1372
|
+
...options,
|
|
1373
|
+
resolvedGivens: (0, given_binding_1.bindGivens)(options === null || options === void 0 ? void 0 : options.givens, this.model._modelDef),
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* This source's SQL under `opts`: the bare `SELECT`, not finalized, because
|
|
1378
|
+
* `persistedTableFor` hashes the same unfinalized SELECT to look the table
|
|
1379
|
+
* up, and a dialect with a final stage (Postgres) would hash differently.
|
|
1380
|
+
*
|
|
1381
|
+
* @internal `opts` is whatever the caller passes; `BuildTarget.sql` and
|
|
1382
|
+
* `buildSQL()` pass the build's own.
|
|
1383
|
+
*/
|
|
1384
|
+
_compileSQL(opts) {
|
|
1368
1385
|
const sd = this.persistableDef;
|
|
1369
1386
|
const queryModel = this.model.queryModel;
|
|
1370
|
-
// Compile with finalize=false so this SQL is the bare source SELECT.
|
|
1371
|
-
// The build-time key (makeBuildId over this SQL) must equal the serve-time
|
|
1372
|
-
// manifest lookup key, which persistedTableFor recomputes from the same
|
|
1373
|
-
// unfinalized SELECT; finalizing would diverge the two on dialects with a
|
|
1374
|
-
// final stage (Postgres) and mis-materialize the table.
|
|
1375
1387
|
if (sd.type === 'sql_select') {
|
|
1376
|
-
return (0, model_1.getCompiledSQL)(sd,
|
|
1377
|
-
}
|
|
1378
|
-
else {
|
|
1379
|
-
const compiled = queryModel.compileQuery(sd.query, options, false);
|
|
1380
|
-
return compiled.sql;
|
|
1388
|
+
return (0, model_1.getCompiledSQL)(sd, opts, (query, o) => queryModel.compileQuery(query, o, false).sql);
|
|
1381
1389
|
}
|
|
1390
|
+
return queryModel.compileQuery(sd.query, opts, false).sql;
|
|
1382
1391
|
}
|
|
1383
1392
|
/**
|
|
1384
1393
|
* Get the underlying persistable source definition.
|
|
@@ -1503,18 +1512,9 @@ class PreparedQuery extends PipelineBase {
|
|
|
1503
1512
|
*/
|
|
1504
1513
|
getPreparedResult(options) {
|
|
1505
1514
|
const queryModel = this._model.queryModel;
|
|
1506
|
-
// Build the resolved-givens map in two phases:
|
|
1507
|
-
// 1. caller-supplied values (resolveSuppliedGivens)
|
|
1508
|
-
// 2. inline-given defaults eager-evaluated against the map
|
|
1509
|
-
// Result is undefined when no values land — preserves the previous
|
|
1510
|
-
// "no givens path" downstream.
|
|
1511
|
-
const resolved = (options === null || options === void 0 ? void 0 : options.givens)
|
|
1512
|
-
? (0, given_binding_1.resolveSuppliedGivens)(options.givens, this._modelDef)
|
|
1513
|
-
: new Map();
|
|
1514
|
-
(0, given_binding_1.evaluateInlineGivens)(resolved, this._modelDef);
|
|
1515
1515
|
const prepareResultOptions = {
|
|
1516
1516
|
...options,
|
|
1517
|
-
resolvedGivens:
|
|
1517
|
+
resolvedGivens: (0, given_binding_1.bindGivens)(options === null || options === void 0 ? void 0 : options.givens, this._modelDef),
|
|
1518
1518
|
};
|
|
1519
1519
|
const translatedQuery = queryModel.compileQuery(this._query, prepareResultOptions);
|
|
1520
1520
|
return new PreparedResult({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { Taggable, Loggable, ParseOptions, CompileOptions, CompileQueryOptions, BuildNode, BuildGraph, BuildTarget, BuildTargets, ConnectionBuild, } from './types';
|
|
1
|
+
export type { Taggable, Loggable, ParseOptions, CompileOptions, CompileQueryOptions, BuildNode, BuildGraph, BuildTarget, BuildTargetOptions, BuildTargets, ConnectionBuild, UnbuildableSource, } from './types';
|
|
2
2
|
export { EMPTY_BUILD_MANIFEST } from './types';
|
|
3
3
|
export { EmptyURLReader, InMemoryURLReader, FixedConnectionMap, hashForInvalidationKey, isInternalURL, readURL, getInvalidationKey, } from './readers';
|
|
4
4
|
export type { ModelCache, CachedModel } from './cache';
|
|
@@ -6,7 +6,7 @@ import type { Dialect } from '../../dialect';
|
|
|
6
6
|
import type { RunSQLOptions } from '../../run_sql_options';
|
|
7
7
|
import type { CacheManager } from './cache';
|
|
8
8
|
import type { MalloyConfig } from './config';
|
|
9
|
-
import type { ParseOptions, CompileOptions, CompileQueryOptions, BuildTargets } from './types';
|
|
9
|
+
import type { ParseOptions, CompileOptions, CompileQueryOptions, BuildTargets, BuildTargetOptions } from './types';
|
|
10
10
|
import type { PreparedResult, Explore } from './core';
|
|
11
11
|
import { Model, PreparedQuery } from './core';
|
|
12
12
|
import type { DataRecord, Result } from './result';
|
|
@@ -102,6 +102,18 @@ export declare class Runtime {
|
|
|
102
102
|
* the cached promise.
|
|
103
103
|
*/
|
|
104
104
|
getGivens(): Promise<ReadonlyMap<string, GivenValue>>;
|
|
105
|
+
/**
|
|
106
|
+
* The given values one compile runs under: the config file's, then the
|
|
107
|
+
* constructor's, then `perCall`, each winning per key over the one before.
|
|
108
|
+
* Undefined when no layer supplies anything.
|
|
109
|
+
*
|
|
110
|
+
* A per-call value for a finalized given is refused before anything else
|
|
111
|
+
* happens: finalizing means the Runtime decides, and that holds for a build
|
|
112
|
+
* as it does for a query.
|
|
113
|
+
*
|
|
114
|
+
* @internal Accessed from QueryMaterializer and getBuildTargets.
|
|
115
|
+
*/
|
|
116
|
+
_givensFor(perCall: Record<string, GivenValue> | undefined): Promise<Record<string, GivenValue> | undefined>;
|
|
105
117
|
/**
|
|
106
118
|
* Surface names of givens locked at the runtime layer (the resolved set
|
|
107
119
|
* the `config.finalizeGivens` directive produced). Per-query supply for
|
|
@@ -292,10 +304,17 @@ export declare class Runtime {
|
|
|
292
304
|
* in dependency order and each carries its own `dependsOn`. See
|
|
293
305
|
* {@link BuildTargets}.
|
|
294
306
|
*
|
|
307
|
+
* The build generates SQL under this Runtime's givens and `virtualMap`, with
|
|
308
|
+
* `options` layered over them, exactly as a query would; a persisted table
|
|
309
|
+
* is therefore found by the queries that run under the same values. A
|
|
310
|
+
* source whose SQL needs a value this build does not have is reported in
|
|
311
|
+
* `unbuildable`, not thrown.
|
|
312
|
+
*
|
|
295
313
|
* @param model A compiled model with `##! experimental.persistence`
|
|
314
|
+
* @param options Given values and a `virtualMap` for this build
|
|
296
315
|
* @return The targets to build, with any annotation parse messages
|
|
297
316
|
*/
|
|
298
|
-
getBuildTargets(model: Model): Promise<BuildTargets>;
|
|
317
|
+
getBuildTargets(model: Model, options?: BuildTargetOptions): Promise<BuildTargets>;
|
|
299
318
|
}
|
|
300
319
|
export declare class ConnectionRuntime extends Runtime {
|
|
301
320
|
readonly rawConnections: Connection[];
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.ExploreMaterializer = exports.PreparedResultMaterializer = exports.QueryMaterializer = exports.ModelMaterializer = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.Runtime = void 0;
|
|
8
8
|
const model_1 = require("../../model");
|
|
9
|
+
const given_binding_1 = require("../../model/given_binding");
|
|
9
10
|
const dialect_1 = require("../../dialect");
|
|
10
11
|
const validate_table_path_1 = require("../../connection/validate_table_path");
|
|
11
12
|
const config_1 = require("./config");
|
|
@@ -141,6 +142,33 @@ class Runtime {
|
|
|
141
142
|
merged.set(k, v);
|
|
142
143
|
return merged;
|
|
143
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* The given values one compile runs under: the config file's, then the
|
|
147
|
+
* constructor's, then `perCall`, each winning per key over the one before.
|
|
148
|
+
* Undefined when no layer supplies anything.
|
|
149
|
+
*
|
|
150
|
+
* A per-call value for a finalized given is refused before anything else
|
|
151
|
+
* happens: finalizing means the Runtime decides, and that holds for a build
|
|
152
|
+
* as it does for a query.
|
|
153
|
+
*
|
|
154
|
+
* @internal Accessed from QueryMaterializer and getBuildTargets.
|
|
155
|
+
*/
|
|
156
|
+
async _givensFor(perCall) {
|
|
157
|
+
if (this._finalizedGivensSet.size > 0 && perCall) {
|
|
158
|
+
for (const name of Object.keys(perCall)) {
|
|
159
|
+
if (this._finalizedGivensSet.has(name)) {
|
|
160
|
+
throw new model_1.MalloyCompileError(`Cannot supply given '${name}' per call: it is finalized at ` +
|
|
161
|
+
'the runtime layer via `config.finalizeGivens`.', 'runtime-given-finalized', undefined);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const fileGivens = await this._resolveGivens();
|
|
166
|
+
const constructorGivens = mapToRecord(this._constructorGivensMap);
|
|
167
|
+
const haveAny = fileGivens || constructorGivens || perCall;
|
|
168
|
+
return haveAny
|
|
169
|
+
? { ...fileGivens, ...constructorGivens, ...perCall }
|
|
170
|
+
: undefined;
|
|
171
|
+
}
|
|
144
172
|
/**
|
|
145
173
|
* Surface names of givens locked at the runtime layer (the resolved set
|
|
146
174
|
* the `config.finalizeGivens` directive produced). Per-query supply for
|
|
@@ -481,10 +509,18 @@ class Runtime {
|
|
|
481
509
|
* in dependency order and each carries its own `dependsOn`. See
|
|
482
510
|
* {@link BuildTargets}.
|
|
483
511
|
*
|
|
512
|
+
* The build generates SQL under this Runtime's givens and `virtualMap`, with
|
|
513
|
+
* `options` layered over them, exactly as a query would; a persisted table
|
|
514
|
+
* is therefore found by the queries that run under the same values. A
|
|
515
|
+
* source whose SQL needs a value this build does not have is reported in
|
|
516
|
+
* `unbuildable`, not thrown.
|
|
517
|
+
*
|
|
484
518
|
* @param model A compiled model with `##! experimental.persistence`
|
|
519
|
+
* @param options Given values and a `virtualMap` for this build
|
|
485
520
|
* @return The targets to build, with any annotation parse messages
|
|
486
521
|
*/
|
|
487
|
-
async getBuildTargets(model) {
|
|
522
|
+
async getBuildTargets(model, options) {
|
|
523
|
+
var _a;
|
|
488
524
|
const tagParseLog = [];
|
|
489
525
|
const walk = (0, build_targets_1.resolvePersistWalk)(model, tagParseLog);
|
|
490
526
|
const connectionDigests = (0, model_1.mkSafeRecord)();
|
|
@@ -497,12 +533,12 @@ class Runtime {
|
|
|
497
533
|
connectionDigests[connectionName] = connection.getDigest();
|
|
498
534
|
}
|
|
499
535
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
};
|
|
536
|
+
const givens = await this._givensFor(options === null || options === void 0 ? void 0 : options.givens);
|
|
537
|
+
const { connections, unbuildable } = (0, build_targets_1.mkBuildTargets)(walk, connectionDigests, {
|
|
538
|
+
virtualMap: (_a = options === null || options === void 0 ? void 0 : options.virtualMap) !== null && _a !== void 0 ? _a : this.virtualMap,
|
|
539
|
+
resolvedGivens: (0, given_binding_1.bindGivens)(givens, model._modelDef),
|
|
540
|
+
});
|
|
541
|
+
return { connections, tagParseLog, unbuildable };
|
|
506
542
|
}
|
|
507
543
|
}
|
|
508
544
|
exports.Runtime = Runtime;
|
|
@@ -1045,31 +1081,8 @@ class QueryMaterializer extends FluentState {
|
|
|
1045
1081
|
}
|
|
1046
1082
|
}
|
|
1047
1083
|
const virtualMap = (_b = mergedOptions.virtualMap) !== null && _b !== void 0 ? _b : this.runtime.virtualMap;
|
|
1048
|
-
|
|
1049
|
-
// — the finalized-givens set is the runtime's "this can't be
|
|
1050
|
-
// overridden by the caller" guarantee. Fail before any IO so misuse
|
|
1051
|
-
// is loud.
|
|
1084
|
+
const mergedGivens = await this.runtime._givensFor(mergedOptions.givens);
|
|
1052
1085
|
const finalizedSet = this.runtime._finalizedGivens;
|
|
1053
|
-
if (finalizedSet.size > 0 && mergedOptions.givens) {
|
|
1054
|
-
for (const name of Object.keys(mergedOptions.givens)) {
|
|
1055
|
-
if (finalizedSet.has(name)) {
|
|
1056
|
-
throw new model_1.MalloyCompileError(`Cannot supply given '${name}' per-query: it is finalized at ` +
|
|
1057
|
-
'the runtime layer via `config.finalizeGivens`.', 'runtime-given-finalized', undefined);
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
// Three layers of givens, merged per-key in precedence order:
|
|
1062
|
-
// 1. config.givensURL file (lazy + cached)
|
|
1063
|
-
// 2. Runtime constructor `givens:` option
|
|
1064
|
-
// 3. Per-query supply via `.run({givens: ...})`
|
|
1065
|
-
// Higher-numbered layers win on collision. Each layer is optional;
|
|
1066
|
-
// the merge collapses to undefined when all three are absent.
|
|
1067
|
-
const fileGivens = await this.runtime._resolveGivens();
|
|
1068
|
-
const constructorGivens = mapToRecord(this.runtime._constructorGivens);
|
|
1069
|
-
const haveAny = fileGivens || constructorGivens || mergedOptions.givens;
|
|
1070
|
-
const mergedGivens = haveAny
|
|
1071
|
-
? { ...fileGivens, ...constructorGivens, ...mergedOptions.givens }
|
|
1072
|
-
: undefined;
|
|
1073
1086
|
// Query-scoped validation: of the givens THIS query references,
|
|
1074
1087
|
// any that are finalized must have a value somewhere (file or
|
|
1075
1088
|
// constructor). One config covers a project; individual files
|
|
@@ -107,11 +107,23 @@ export interface BuildTarget {
|
|
|
107
107
|
* The SQL the BuildID is computed from: fully inlined, no manifest
|
|
108
108
|
* substitution, so it is the same string whatever else has been built.
|
|
109
109
|
*
|
|
110
|
-
* It is not the SQL to execute
|
|
111
|
-
* — `source.getSQL({buildManifest, connectionDigests})` — so it can only be
|
|
112
|
-
* computed as the build walks, and only by the builder holding the manifest.
|
|
110
|
+
* It is not the SQL to execute; that is {@link buildSQL}.
|
|
113
111
|
*/
|
|
114
112
|
sql: string;
|
|
113
|
+
/**
|
|
114
|
+
* The SQL to execute, for a `CREATE TABLE`. Dependencies already in
|
|
115
|
+
* `manifest` are read from their tables rather than recomputed, which is
|
|
116
|
+
* why it is a call made as the build proceeds and not a string computed up
|
|
117
|
+
* front. Generated under the same givens and `virtualMap` as `sql`, so the
|
|
118
|
+
* table that is built is the one the key describes.
|
|
119
|
+
*/
|
|
120
|
+
buildSQL(manifest: BuildManifest): string;
|
|
121
|
+
/**
|
|
122
|
+
* True when the SQL reads a given, supplied or defaulted. The table is then
|
|
123
|
+
* one of possibly several for this source, one per value, and a builder
|
|
124
|
+
* naming it by `name=` alone would build every variant under one name.
|
|
125
|
+
*/
|
|
126
|
+
readsGivens: boolean;
|
|
115
127
|
/** Targets that must exist before this one can be built */
|
|
116
128
|
dependsOn: BuildTarget[];
|
|
117
129
|
/** Every persist source in the model that maps onto this artifact */
|
|
@@ -152,6 +164,32 @@ export interface ConnectionBuild {
|
|
|
152
164
|
/** Every table to build, dependencies before dependents */
|
|
153
165
|
targets: BuildTarget[];
|
|
154
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* A persist source with no BuildID, because its SQL cannot be written: it
|
|
169
|
+
* reads a given that has no value in this build, a virtual source the build's
|
|
170
|
+
* `virtualMap` has no entry for, or anything else the compiler reports as a
|
|
171
|
+
* problem with the source rather than with itself. A source that reads it
|
|
172
|
+
* inlines its SQL, so is reported here too.
|
|
173
|
+
*/
|
|
174
|
+
export interface UnbuildableSource {
|
|
175
|
+
source: PersistSource;
|
|
176
|
+
/** Why no BuildID could be computed, as a query would report it */
|
|
177
|
+
problem: LogMessage;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* What a build generates SQL under, over the Runtime's own values.
|
|
181
|
+
*
|
|
182
|
+
* `givens` layers over the Runtime's file and constructor givens the way a
|
|
183
|
+
* query's do, and a finalized given is refused here the same way. Running
|
|
184
|
+
* `getBuildTargets` once per set of values is how a model whose persisted
|
|
185
|
+
* sources read a given gets one table per value.
|
|
186
|
+
*/
|
|
187
|
+
export interface BuildTargetOptions {
|
|
188
|
+
/** Given values for this build, by surface name, over the Runtime's */
|
|
189
|
+
givens?: Record<string, GivenValue>;
|
|
190
|
+
/** Which table each virtual source reads; the Runtime's when omitted */
|
|
191
|
+
virtualMap?: VirtualMap;
|
|
192
|
+
}
|
|
155
193
|
/**
|
|
156
194
|
* The build schedule for a model.
|
|
157
195
|
*
|
|
@@ -165,4 +203,6 @@ export interface BuildTargets {
|
|
|
165
203
|
connections: ConnectionBuild[];
|
|
166
204
|
/** Errors and warnings from parsing `#@` annotations on persistable sources */
|
|
167
205
|
tagParseLog: LogMessage[];
|
|
206
|
+
/** Persist sources with no table to build, each with the reason */
|
|
207
|
+
unbuildable: UnbuildableSource[];
|
|
168
208
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { AnnotationsDef } from '../model/malloy_types';
|
|
2
|
+
import type { ConnectionPropertyDefinition } from './registry';
|
|
3
|
+
/**
|
|
4
|
+
* The annotation route a connection writes database metadata to:
|
|
5
|
+
* `#(dbmeta) description="..."`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DBMETA_ROUTE = "dbmeta";
|
|
8
|
+
/**
|
|
9
|
+
* The connection property that turns on database metadata. Connections that
|
|
10
|
+
* support it register this definition, so the option has the same name and
|
|
11
|
+
* meaning on every backend. Off unless set.
|
|
12
|
+
*/
|
|
13
|
+
export declare const dbmetaProperty: ConnectionPropertyDefinition;
|
|
14
|
+
/**
|
|
15
|
+
* Metadata a connection read from the database for one table or column.
|
|
16
|
+
* Keys are normalized across databases: whatever a database calls it (a
|
|
17
|
+
* description, a COMMENT), it arrives here as `description`.
|
|
18
|
+
*/
|
|
19
|
+
export interface DbMeta {
|
|
20
|
+
description?: string | null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The `#(dbmeta)` annotation for a table or column, as a fragment to spread
|
|
24
|
+
* into its field or table def: `{annotations}`, or `{}` when there is nothing
|
|
25
|
+
* to say.
|
|
26
|
+
*/
|
|
27
|
+
export declare function dbmetaAnnotations(meta: DbMeta): {
|
|
28
|
+
annotations?: AnnotationsDef;
|
|
29
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright Contributors to the Malloy project
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.dbmetaProperty = exports.DBMETA_ROUTE = void 0;
|
|
8
|
+
exports.dbmetaAnnotations = dbmetaAnnotations;
|
|
9
|
+
const malloy_tag_1 = require("@malloydata/malloy-tag");
|
|
10
|
+
/**
|
|
11
|
+
* The annotation route a connection writes database metadata to:
|
|
12
|
+
* `#(dbmeta) description="..."`.
|
|
13
|
+
*/
|
|
14
|
+
exports.DBMETA_ROUTE = 'dbmeta';
|
|
15
|
+
const DBMETA_LOCATION = {
|
|
16
|
+
url: `internal://${exports.DBMETA_ROUTE}`,
|
|
17
|
+
range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* The connection property that turns on database metadata. Connections that
|
|
21
|
+
* support it register this definition, so the option has the same name and
|
|
22
|
+
* meaning on every backend. Off unless set.
|
|
23
|
+
*/
|
|
24
|
+
exports.dbmetaProperty = {
|
|
25
|
+
name: 'dbmeta',
|
|
26
|
+
displayName: 'Database Metadata',
|
|
27
|
+
type: 'boolean',
|
|
28
|
+
optional: true,
|
|
29
|
+
advanced: true,
|
|
30
|
+
description: 'Copy table and column descriptions from the database onto the schema, ' +
|
|
31
|
+
'as #(dbmeta) description annotations.',
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The `#(dbmeta)` annotation for a table or column, as a fragment to spread
|
|
35
|
+
* into its field or table def: `{annotations}`, or `{}` when there is nothing
|
|
36
|
+
* to say.
|
|
37
|
+
*/
|
|
38
|
+
function dbmetaAnnotations(meta) {
|
|
39
|
+
var _a;
|
|
40
|
+
const description = (_a = meta.description) === null || _a === void 0 ? void 0 : _a.trim();
|
|
41
|
+
if (!description)
|
|
42
|
+
return {};
|
|
43
|
+
const text = `#(${exports.DBMETA_ROUTE}) description=${(0, malloy_tag_1.quoteString)(description)}\n`;
|
|
44
|
+
return { annotations: { notes: [{ text, at: DBMETA_LOCATION }] } };
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=dbmeta.js.map
|
package/dist/connection/index.js
CHANGED
|
@@ -17,4 +17,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./types"), exports);
|
|
18
18
|
__exportStar(require("./base_connection"), exports);
|
|
19
19
|
__exportStar(require("./registry"), exports);
|
|
20
|
+
__exportStar(require("./dbmeta"), exports);
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Sampling, MeasureTimeExpr, RegexMatchExpr,
|
|
2
|
-
import type { BooleanTypeSupport, CompiledOrderBy, DialectFieldList, FieldReferenceType, LateralJoinExpression, OrderByClauseType, OrderByRequest, QueryInfo } from '../dialect';
|
|
1
|
+
import type { Sampling, MeasureTimeExpr, RegexMatchExpr, TypecastExpr, BasicAtomicTypeDef, AtomicTypeDef, ArrayLiteralNode, RecordLiteralNode, ATimestampTypeDef, TimestampUnit, ExtractUnit } from '../../model/malloy_types';
|
|
2
|
+
import type { CivilTime, BooleanTypeSupport, CompiledOrderBy, DialectFieldList, FieldReferenceType, LateralJoinExpression, OrderByClauseType, OrderByRequest, QueryInfo } from '../dialect';
|
|
3
3
|
import { Dialect } from '../dialect';
|
|
4
4
|
import type { DialectFunctionOverloadDef } from '../functions';
|
|
5
5
|
export declare class DatabricksDialect extends Dialect {
|
|
@@ -66,18 +66,17 @@ export declare class DatabricksDialect extends Dialect {
|
|
|
66
66
|
sqlSelectAliasAsStruct(alias: string, fieldList: DialectFieldList): string;
|
|
67
67
|
sqlCreateTableAsSelect(tableName: string, sql: string): string;
|
|
68
68
|
sqlNowExpr(): string;
|
|
69
|
-
sqlConvertToCivilTime(expr: string, timezone: string, _typeDef:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
sqlCast(qi: QueryInfo, cast: TypecastExpr): string;
|
|
69
|
+
sqlConvertToCivilTime(expr: string, timezone: string, _typeDef: ATimestampTypeDef): string;
|
|
70
|
+
sqlConvertFromCivilTime(expr: string, timezone: string, _destTypeDef: ATimestampTypeDef): string;
|
|
71
|
+
sqlTruncate(expr: string, unit: TimestampUnit, _civilType: CivilTime): string;
|
|
72
|
+
sqlOffsetTime(expr: string, op: '+' | '-', magnitude: string, unit: TimestampUnit, _civilType: CivilTime): string;
|
|
73
|
+
sqlCivilExtract(expr: string, units: ExtractUnit, _civilType: CivilTime): string;
|
|
74
|
+
sqlCivilToDate(expr: string): string;
|
|
75
|
+
sqlDateToCivil(expr: string): string;
|
|
76
|
+
sqlCast(_qi: QueryInfo, cast: TypecastExpr): string;
|
|
78
77
|
sqlRegexpMatch(df: RegexMatchExpr): string;
|
|
79
78
|
sqlDateLiteral(_qi: QueryInfo, literal: string): string;
|
|
80
|
-
|
|
79
|
+
sqlCivilLiteral(literal: string): string;
|
|
81
80
|
sqlTimestamptzLiteral(_qi: QueryInfo, _literal: string, _timezone: string): string;
|
|
82
81
|
sqlMeasureTimeExpr(df: MeasureTimeExpr): string;
|
|
83
82
|
sqlSampleTable(tableSQL: string, sample: Sampling | undefined): string;
|