@malloydata/malloy 0.0.348 → 0.0.350
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/config.d.ts +22 -7
- package/dist/api/foundation/config.js +66 -24
- package/dist/api/foundation/index.d.ts +1 -0
- package/dist/api/foundation/index.js +4 -2
- package/dist/api/foundation/runtime.js +9 -4
- package/dist/api/foundation/types.d.ts +10 -3
- package/dist/api/foundation/types.js +13 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/model/malloy_types.d.ts +11 -7
- package/dist/model/query_query.js +3 -3
- package/dist/model/sql_compiled.js +3 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
|
@@ -13,12 +13,19 @@ export interface MalloyProjectConfig {
|
|
|
13
13
|
* In-memory manifest store. Reads, updates, and serializes manifest data.
|
|
14
14
|
*
|
|
15
15
|
* Always valid — starts empty, call load() to populate from a file.
|
|
16
|
-
* The
|
|
17
|
-
* the same object, so any reference obtained
|
|
16
|
+
* The BuildManifest object returned by `buildManifest` is stable: load()
|
|
17
|
+
* and update() mutate the same entries object, so any reference obtained
|
|
18
|
+
* via `buildManifest` stays current without re-assignment.
|
|
19
|
+
*
|
|
20
|
+
* The `strict` flag controls what happens when a persist source's BuildID
|
|
21
|
+
* is not found in the manifest. When strict, the compiler throws an error
|
|
22
|
+
* instead of falling through to inline SQL. The flag is loaded from the
|
|
23
|
+
* manifest file and can be overridden by the application before creating
|
|
24
|
+
* a Runtime.
|
|
18
25
|
*/
|
|
19
26
|
export declare class Manifest {
|
|
20
27
|
private readonly _urlReader?;
|
|
21
|
-
private readonly
|
|
28
|
+
private readonly _manifest;
|
|
22
29
|
private readonly _touched;
|
|
23
30
|
constructor(urlReader?: URLReader);
|
|
24
31
|
/**
|
|
@@ -36,9 +43,15 @@ export declare class Manifest {
|
|
|
36
43
|
/**
|
|
37
44
|
* The live BuildManifest. This is a stable reference — load() and update()
|
|
38
45
|
* mutate the same object, so passing this to a Runtime means the Runtime
|
|
39
|
-
* always sees current data.
|
|
46
|
+
* always sees current data including the strict flag.
|
|
40
47
|
*/
|
|
41
48
|
get buildManifest(): BuildManifest;
|
|
49
|
+
/**
|
|
50
|
+
* Whether missing manifest entries should cause errors.
|
|
51
|
+
* Loaded from the manifest file; can be overridden by the application.
|
|
52
|
+
*/
|
|
53
|
+
get strict(): boolean;
|
|
54
|
+
set strict(value: boolean);
|
|
42
55
|
/**
|
|
43
56
|
* Add or replace a manifest entry. Also marks it as touched.
|
|
44
57
|
*/
|
|
@@ -49,11 +62,13 @@ export declare class Manifest {
|
|
|
49
62
|
*/
|
|
50
63
|
touch(buildId: BuildID): void;
|
|
51
64
|
/**
|
|
52
|
-
* Returns only entries that were update()d or touch()ed.
|
|
53
|
-
* This is the manifest a builder should write — it reflects
|
|
54
|
-
*
|
|
65
|
+
* Returns a BuildManifest with only entries that were update()d or touch()ed.
|
|
66
|
+
* This is the manifest a builder should write — it reflects exactly what the
|
|
67
|
+
* current build references. Preserves the strict flag.
|
|
55
68
|
*/
|
|
56
69
|
get activeEntries(): BuildManifest;
|
|
70
|
+
private _clearEntries;
|
|
71
|
+
private _loadParsed;
|
|
57
72
|
}
|
|
58
73
|
/**
|
|
59
74
|
* Loads and holds a Malloy project configuration (connections + manifest).
|
|
@@ -12,12 +12,19 @@ const MANIFEST_FILENAME = 'malloy-manifest.json';
|
|
|
12
12
|
* In-memory manifest store. Reads, updates, and serializes manifest data.
|
|
13
13
|
*
|
|
14
14
|
* Always valid — starts empty, call load() to populate from a file.
|
|
15
|
-
* The
|
|
16
|
-
* the same object, so any reference obtained
|
|
15
|
+
* The BuildManifest object returned by `buildManifest` is stable: load()
|
|
16
|
+
* and update() mutate the same entries object, so any reference obtained
|
|
17
|
+
* via `buildManifest` stays current without re-assignment.
|
|
18
|
+
*
|
|
19
|
+
* The `strict` flag controls what happens when a persist source's BuildID
|
|
20
|
+
* is not found in the manifest. When strict, the compiler throws an error
|
|
21
|
+
* instead of falling through to inline SQL. The flag is loaded from the
|
|
22
|
+
* manifest file and can be overridden by the application before creating
|
|
23
|
+
* a Runtime.
|
|
17
24
|
*/
|
|
18
25
|
class Manifest {
|
|
19
26
|
constructor(urlReader) {
|
|
20
|
-
this.
|
|
27
|
+
this._manifest = { entries: {}, strict: false };
|
|
21
28
|
this._touched = new Set();
|
|
22
29
|
this._urlReader = urlReader;
|
|
23
30
|
}
|
|
@@ -28,11 +35,9 @@ class Manifest {
|
|
|
28
35
|
* is available, clears to empty.
|
|
29
36
|
*/
|
|
30
37
|
async load(manifestRoot) {
|
|
31
|
-
|
|
32
|
-
for (const key of Object.keys(this._data)) {
|
|
33
|
-
delete this._data[key];
|
|
34
|
-
}
|
|
38
|
+
this._clearEntries();
|
|
35
39
|
this._touched.clear();
|
|
40
|
+
this._manifest.strict = false;
|
|
36
41
|
if (!this._urlReader)
|
|
37
42
|
return;
|
|
38
43
|
const dir = manifestRoot.toString().endsWith('/')
|
|
@@ -48,34 +53,42 @@ class Manifest {
|
|
|
48
53
|
// No manifest file — stay empty
|
|
49
54
|
return;
|
|
50
55
|
}
|
|
51
|
-
|
|
52
|
-
Object.assign(this._data, loaded);
|
|
56
|
+
this._loadParsed(JSON.parse(contents));
|
|
53
57
|
}
|
|
54
58
|
/**
|
|
55
59
|
* Load manifest data from a JSON string.
|
|
56
60
|
* Replaces any existing data.
|
|
57
61
|
*/
|
|
58
62
|
loadText(jsonText) {
|
|
59
|
-
|
|
60
|
-
delete this._data[key];
|
|
61
|
-
}
|
|
63
|
+
this._clearEntries();
|
|
62
64
|
this._touched.clear();
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
this._manifest.strict = false;
|
|
66
|
+
this._loadParsed(JSON.parse(jsonText));
|
|
65
67
|
}
|
|
66
68
|
/**
|
|
67
69
|
* The live BuildManifest. This is a stable reference — load() and update()
|
|
68
70
|
* mutate the same object, so passing this to a Runtime means the Runtime
|
|
69
|
-
* always sees current data.
|
|
71
|
+
* always sees current data including the strict flag.
|
|
70
72
|
*/
|
|
71
73
|
get buildManifest() {
|
|
72
|
-
return this.
|
|
74
|
+
return this._manifest;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Whether missing manifest entries should cause errors.
|
|
78
|
+
* Loaded from the manifest file; can be overridden by the application.
|
|
79
|
+
*/
|
|
80
|
+
get strict() {
|
|
81
|
+
var _a;
|
|
82
|
+
return (_a = this._manifest.strict) !== null && _a !== void 0 ? _a : false;
|
|
83
|
+
}
|
|
84
|
+
set strict(value) {
|
|
85
|
+
this._manifest.strict = value;
|
|
73
86
|
}
|
|
74
87
|
/**
|
|
75
88
|
* Add or replace a manifest entry. Also marks it as touched.
|
|
76
89
|
*/
|
|
77
90
|
update(buildId, entry) {
|
|
78
|
-
this.
|
|
91
|
+
this._manifest.entries[buildId] = entry;
|
|
79
92
|
this._touched.add(buildId);
|
|
80
93
|
}
|
|
81
94
|
/**
|
|
@@ -86,18 +99,47 @@ class Manifest {
|
|
|
86
99
|
this._touched.add(buildId);
|
|
87
100
|
}
|
|
88
101
|
/**
|
|
89
|
-
* Returns only entries that were update()d or touch()ed.
|
|
90
|
-
* This is the manifest a builder should write — it reflects
|
|
91
|
-
*
|
|
102
|
+
* Returns a BuildManifest with only entries that were update()d or touch()ed.
|
|
103
|
+
* This is the manifest a builder should write — it reflects exactly what the
|
|
104
|
+
* current build references. Preserves the strict flag.
|
|
92
105
|
*/
|
|
93
106
|
get activeEntries() {
|
|
94
|
-
const
|
|
107
|
+
const entries = {};
|
|
95
108
|
for (const id of this._touched) {
|
|
96
|
-
if (this.
|
|
97
|
-
|
|
109
|
+
if (this._manifest.entries[id]) {
|
|
110
|
+
entries[id] = this._manifest.entries[id];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return { entries, strict: this._manifest.strict };
|
|
114
|
+
}
|
|
115
|
+
_clearEntries() {
|
|
116
|
+
for (const key of Object.keys(this._manifest.entries)) {
|
|
117
|
+
delete this._manifest.entries[key];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
_loadParsed(parsed) {
|
|
121
|
+
if (typeof parsed['strict'] === 'boolean') {
|
|
122
|
+
this._manifest.strict = parsed['strict'];
|
|
123
|
+
}
|
|
124
|
+
// New format: {entries: {...}, strict?: boolean}
|
|
125
|
+
// Old format: {buildId: {tableName}, ...} (flat record, no "entries" key)
|
|
126
|
+
let entries;
|
|
127
|
+
if (parsed['entries'] && typeof parsed['entries'] === 'object') {
|
|
128
|
+
entries = parsed['entries'];
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
// Treat as old flat-record format: every key with a tableName is an entry
|
|
132
|
+
entries = {};
|
|
133
|
+
for (const [key, val] of Object.entries(parsed)) {
|
|
134
|
+
if (key !== 'strict' &&
|
|
135
|
+
val &&
|
|
136
|
+
typeof val === 'object' &&
|
|
137
|
+
'tableName' in val) {
|
|
138
|
+
entries[key] = val;
|
|
139
|
+
}
|
|
98
140
|
}
|
|
99
141
|
}
|
|
100
|
-
|
|
142
|
+
Object.assign(this._manifest.entries, entries);
|
|
101
143
|
}
|
|
102
144
|
}
|
|
103
145
|
exports.Manifest = Manifest;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type { Taggable, Loggable, ParseOptions, CompileOptions, CompileQueryOptions, BuildNode, BuildGraph, } from './types';
|
|
2
|
+
export { EMPTY_BUILD_MANIFEST } from './types';
|
|
2
3
|
export { EmptyURLReader, InMemoryURLReader, FixedConnectionMap, hashForInvalidationKey, isInternalURL, readURL, getInvalidationKey, } from './readers';
|
|
3
4
|
export type { ModelCache, CachedModel } from './cache';
|
|
4
5
|
export { CacheManager, InMemoryModelCache } from './cache';
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* SPDX-License-Identifier: MIT
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.
|
|
8
|
-
exports.MalloyError = exports.Malloy = exports.MalloyConfig = void 0;
|
|
7
|
+
exports.ExploreMaterializer = exports.PreparedResultMaterializer = exports.QueryMaterializer = exports.ModelMaterializer = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.Runtime = exports.CSVWriter = exports.JSONWriter = exports.DataWriter = exports.DataRecord = exports.DataArray = exports.Result = exports.PreparedResult = exports.PreparedQuery = exports.PersistSource = exports.Model = exports.QueryField = exports.Query = exports.StringField = exports.UnsupportedField = exports.JSONField = exports.BooleanField = exports.NumberField = exports.TimestampField = exports.DateField = exports.AtomicField = exports.ExploreField = exports.Explore = exports.JoinRelationship = exports.TimestampTimeframe = exports.DateTimeframe = exports.AtomicFieldType = exports.SourceRelationship = exports.DocumentCompletion = exports.DocumentSymbol = exports.DocumentPosition = exports.DocumentRange = exports.DocumentTablePath = exports.Parse = exports.InMemoryModelCache = exports.CacheManager = exports.getInvalidationKey = exports.readURL = exports.isInternalURL = exports.hashForInvalidationKey = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.EMPTY_BUILD_MANIFEST = void 0;
|
|
8
|
+
exports.MalloyError = exports.Malloy = exports.MalloyConfig = exports.Manifest = void 0;
|
|
9
|
+
var types_1 = require("./types");
|
|
10
|
+
Object.defineProperty(exports, "EMPTY_BUILD_MANIFEST", { enumerable: true, get: function () { return types_1.EMPTY_BUILD_MANIFEST; } });
|
|
9
11
|
// URL readers and connection helpers
|
|
10
12
|
var readers_1 = require("./readers");
|
|
11
13
|
Object.defineProperty(exports, "EmptyURLReader", { enumerable: true, get: function () { return readers_1.EmptyURLReader; } });
|
|
@@ -577,18 +577,24 @@ class QueryMaterializer extends FluentState {
|
|
|
577
577
|
...options,
|
|
578
578
|
};
|
|
579
579
|
// Use manifest from options if provided, otherwise fall back to Runtime's manifest.
|
|
580
|
-
// Pass
|
|
580
|
+
// Pass EMPTY_BUILD_MANIFEST in options to explicitly suppress manifest substitution.
|
|
581
581
|
const explicitManifest = mergedOptions.buildManifest !== undefined;
|
|
582
582
|
let buildManifest = (_a = mergedOptions.buildManifest) !== null && _a !== void 0 ? _a : this.runtime.buildManifest;
|
|
583
|
-
// If we have a manifest, compute connectionDigests for
|
|
583
|
+
// If we have a manifest with entries, compute connectionDigests for lookups.
|
|
584
584
|
// TODO: This is inefficient - we call getBuildPlan just to find connection names.
|
|
585
585
|
// Consider adding a listConnections() method to LookupConnection, or caching this.
|
|
586
586
|
let connectionDigests;
|
|
587
|
+
if (buildManifest &&
|
|
588
|
+
Object.keys(buildManifest.entries).length === 0 &&
|
|
589
|
+
!buildManifest.strict) {
|
|
590
|
+
// Empty non-strict manifest — nothing to substitute, skip persistence checks
|
|
591
|
+
buildManifest = undefined;
|
|
592
|
+
}
|
|
587
593
|
if (buildManifest) {
|
|
588
594
|
const modelTag = preparedQuery.model.tagParse({ prefix: /^##! / }).tag;
|
|
589
595
|
if (!modelTag.has('experimental', 'persistence')) {
|
|
590
596
|
if (explicitManifest) {
|
|
591
|
-
// Explicitly passed manifest requires persistence support
|
|
597
|
+
// Explicitly passed non-empty manifest requires persistence support
|
|
592
598
|
throw new Error('Model must have ##! experimental.persistence to use buildManifest');
|
|
593
599
|
}
|
|
594
600
|
// Runtime-level manifest (e.g. from config): silently ignore
|
|
@@ -609,7 +615,6 @@ class QueryMaterializer extends FluentState {
|
|
|
609
615
|
defaultRowLimit: mergedOptions.defaultRowLimit,
|
|
610
616
|
buildManifest,
|
|
611
617
|
connectionDigests,
|
|
612
|
-
strictPersist: mergedOptions.strictPersist,
|
|
613
618
|
};
|
|
614
619
|
return preparedQuery.getPreparedResult({
|
|
615
620
|
...mergedOptions,
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type { EventStream } from '../../runtime_types';
|
|
2
2
|
import type { BuildManifest } from '../../model';
|
|
3
|
+
/**
|
|
4
|
+
* An empty BuildManifest with no entries and strict mode off.
|
|
5
|
+
* Use this to explicitly suppress manifest substitution in a query:
|
|
6
|
+
*
|
|
7
|
+
* runtime.loadQuery(url, {buildManifest: EMPTY_BUILD_MANIFEST}).getSQL()
|
|
8
|
+
*
|
|
9
|
+
* Frozen to prevent accidental mutation of the shared sentinel.
|
|
10
|
+
*/
|
|
11
|
+
export declare const EMPTY_BUILD_MANIFEST: BuildManifest;
|
|
3
12
|
export type { Taggable } from '../../taggable';
|
|
4
13
|
export interface Loggable {
|
|
5
14
|
debug: (message?: any, ...optionalParams: any[]) => void;
|
|
@@ -20,12 +29,10 @@ export interface CompileOptions {
|
|
|
20
29
|
export interface CompileQueryOptions {
|
|
21
30
|
eventStream?: EventStream;
|
|
22
31
|
defaultRowLimit?: number;
|
|
23
|
-
/** Manifest of built tables
|
|
32
|
+
/** Manifest of built tables for persist source substitution */
|
|
24
33
|
buildManifest?: BuildManifest;
|
|
25
34
|
/** Map from connectionName to connectionDigest (from Connection.getDigest()) */
|
|
26
35
|
connectionDigests?: Record<string, string>;
|
|
27
|
-
/** If true, throw when a persist source's BuildID is not in the manifest */
|
|
28
|
-
strictPersist?: boolean;
|
|
29
36
|
}
|
|
30
37
|
/**
|
|
31
38
|
* A node in the build graph (recursive DAG structure).
|
|
@@ -4,4 +4,17 @@
|
|
|
4
4
|
* SPDX-License-Identifier: MIT
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.EMPTY_BUILD_MANIFEST = void 0;
|
|
8
|
+
/**
|
|
9
|
+
* An empty BuildManifest with no entries and strict mode off.
|
|
10
|
+
* Use this to explicitly suppress manifest substitution in a query:
|
|
11
|
+
*
|
|
12
|
+
* runtime.loadQuery(url, {buildManifest: EMPTY_BUILD_MANIFEST}).getSQL()
|
|
13
|
+
*
|
|
14
|
+
* Frozen to prevent accidental mutation of the shared sentinel.
|
|
15
|
+
*/
|
|
16
|
+
exports.EMPTY_BUILD_MANIFEST = Object.freeze({
|
|
17
|
+
entries: Object.freeze({}),
|
|
18
|
+
strict: false,
|
|
19
|
+
});
|
|
7
20
|
//# sourceMappingURL=types.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -18,5 +18,5 @@ export type { SQLSourceRequest } from './lang/translate-response';
|
|
|
18
18
|
export { sqlKey } from './model/sql_block';
|
|
19
19
|
export { annotationToTag, annotationToTaglines } from './annotation';
|
|
20
20
|
export type { BuildGraph, BuildNode, BuildPlan } from './api/foundation';
|
|
21
|
-
export { PersistSource } from './api/foundation';
|
|
21
|
+
export { PersistSource, EMPTY_BUILD_MANIFEST } from './api/foundation';
|
|
22
22
|
export { makeDigest } from './model';
|
package/dist/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.Runtime = exports.Malloy = exports.Model = exports.MalloyTranslator = exports.malloyToQuery = exports.constantExprToSQL = exports.isDateUnit = exports.isTimestampUnit = exports.composeSQLExpr = exports.indent = exports.expressionIsUngroupedAggregate = exports.expressionIsScalar = exports.expressionIsCalculation = exports.expressionIsAnalytic = exports.expressionIsAggregate = exports.mkFieldDef = exports.mkArrayDef = exports.isBasicArray = exports.isRepeatedRecord = exports.isSamplingRows = exports.isSamplingPercent = exports.isSamplingEnable = exports.isJoinedSource = exports.isJoined = exports.isCompoundArrayData = exports.isBasicAtomic = exports.isAtomic = exports.isSourceDef = exports.TinyParser = exports.Dialect = exports.spread = exports.literal = exports.variadicParam = exports.param = exports.makeParam = exports.sql = exports.maxScalar = exports.minAggregate = exports.anyExprType = exports.minScalar = exports.overload = exports.qtz = exports.arg = exports.registerDialect = exports.MySQLDialect = exports.SnowflakeDialect = exports.PostgresDialect = exports.TrinoDialect = exports.StandardSQLDialect = exports.DuckDBDialect = void 0;
|
|
37
|
-
exports.makeDigest = exports.PersistSource = exports.annotationToTaglines = exports.annotationToTag = exports.sqlKey = exports.API = exports.sourceDefToSourceInfo = exports.modelDefToModelInfo = exports.toAsyncGenerator = exports.resolveValue = exports.isValueRef = exports.getRegisteredConnectionTypes = exports.getConnectionTypeDisplayName = exports.getConnectionProperties = exports.registerConnectionType = exports.MalloyConfig = exports.Manifest = exports.CacheManager = exports.InMemoryModelCache = exports.Explore = exports.DataWriter = exports.Parse = exports.JSONWriter = exports.CSVWriter = exports.QueryMaterializer = exports.Result = exports.PreparedResult = exports.TimestampTimeframe = exports.DateTimeframe = exports.SourceRelationship = exports.JoinRelationship = exports.MalloyError = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.AtomicFieldType = void 0;
|
|
37
|
+
exports.makeDigest = exports.EMPTY_BUILD_MANIFEST = exports.PersistSource = exports.annotationToTaglines = exports.annotationToTag = exports.sqlKey = exports.API = exports.sourceDefToSourceInfo = exports.modelDefToModelInfo = exports.toAsyncGenerator = exports.resolveValue = exports.isValueRef = exports.getRegisteredConnectionTypes = exports.getConnectionTypeDisplayName = exports.getConnectionProperties = exports.registerConnectionType = exports.MalloyConfig = exports.Manifest = exports.CacheManager = exports.InMemoryModelCache = exports.Explore = exports.DataWriter = exports.Parse = exports.JSONWriter = exports.CSVWriter = exports.QueryMaterializer = exports.Result = exports.PreparedResult = exports.TimestampTimeframe = exports.DateTimeframe = exports.SourceRelationship = exports.JoinRelationship = exports.MalloyError = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.AtomicFieldType = void 0;
|
|
38
38
|
/*
|
|
39
39
|
* Copyright 2023 Google LLC
|
|
40
40
|
*
|
|
@@ -157,6 +157,7 @@ Object.defineProperty(exports, "annotationToTag", { enumerable: true, get: funct
|
|
|
157
157
|
Object.defineProperty(exports, "annotationToTaglines", { enumerable: true, get: function () { return annotation_1.annotationToTaglines; } });
|
|
158
158
|
var foundation_2 = require("./api/foundation");
|
|
159
159
|
Object.defineProperty(exports, "PersistSource", { enumerable: true, get: function () { return foundation_2.PersistSource; } });
|
|
160
|
+
Object.defineProperty(exports, "EMPTY_BUILD_MANIFEST", { enumerable: true, get: function () { return foundation_2.EMPTY_BUILD_MANIFEST; } });
|
|
160
161
|
var model_2 = require("./model");
|
|
161
162
|
Object.defineProperty(exports, "makeDigest", { enumerable: true, get: function () { return model_2.makeDigest; } });
|
|
162
163
|
//# sourceMappingURL=index.js.map
|
|
@@ -1073,12 +1073,10 @@ export interface PrepareResultOptions {
|
|
|
1073
1073
|
defaultRowLimit?: number;
|
|
1074
1074
|
isPartialQuery?: boolean;
|
|
1075
1075
|
eventStream?: EventStream;
|
|
1076
|
-
/** Manifest of built tables
|
|
1076
|
+
/** Manifest of built tables for persist source substitution */
|
|
1077
1077
|
buildManifest?: BuildManifest;
|
|
1078
1078
|
/** Map from connectionName to connectionDigest (from Connection.getDigest()) */
|
|
1079
1079
|
connectionDigests?: SafeRecord<string>;
|
|
1080
|
-
/** If true, throw when a persist query's digest is not in the manifest */
|
|
1081
|
-
strictPersist?: boolean;
|
|
1082
1080
|
}
|
|
1083
1081
|
type UTD = AtomicTypeDef | TypedDef | FunctionParameterTypeDef | FunctionReturnTypeDef | undefined;
|
|
1084
1082
|
/**
|
|
@@ -1124,9 +1122,15 @@ export interface BuildManifestEntry {
|
|
|
1124
1122
|
}
|
|
1125
1123
|
/**
|
|
1126
1124
|
* Manifest of persisted build results (the build cache).
|
|
1127
|
-
*
|
|
1128
|
-
*
|
|
1129
|
-
*
|
|
1125
|
+
* Used by compileQuery to substitute persist sources with table references.
|
|
1126
|
+
* Content-addressable: same SQL + same connection digest = same BuildID
|
|
1127
|
+
* regardless of which model produced it.
|
|
1128
|
+
*
|
|
1129
|
+
* When `strict` is true, a missing entry for a persist source throws an error
|
|
1130
|
+
* instead of falling through to inline SQL.
|
|
1130
1131
|
*/
|
|
1131
|
-
export
|
|
1132
|
+
export interface BuildManifest {
|
|
1133
|
+
entries: Record<BuildID, BuildManifestEntry>;
|
|
1134
|
+
strict?: boolean;
|
|
1135
|
+
}
|
|
1132
1136
|
export {};
|
|
@@ -534,7 +534,7 @@ class QueryQuery extends query_node_1.QueryField {
|
|
|
534
534
|
case 'nest_source':
|
|
535
535
|
return qs.structDef.pipeSQL;
|
|
536
536
|
case 'query_source': {
|
|
537
|
-
const { buildManifest, connectionDigests
|
|
537
|
+
const { buildManifest, connectionDigests } = (_b = qs.prepareResultOptions) !== null && _b !== void 0 ? _b : {};
|
|
538
538
|
// Check manifest for this source
|
|
539
539
|
if (buildManifest && connectionDigests) {
|
|
540
540
|
const connDigest = (0, malloy_types_1.safeRecordGet)(connectionDigests, qs.structDef.connection);
|
|
@@ -542,12 +542,12 @@ class QueryQuery extends query_node_1.QueryField {
|
|
|
542
542
|
// Compile with empty opts to get manifest-ignorant SQL for BuildID
|
|
543
543
|
const fullRet = this.compileQueryToStages(qs.structDef.query, {}, undefined, false);
|
|
544
544
|
const buildId = (0, source_def_utils_1.mkBuildID)(connDigest, fullRet.sql);
|
|
545
|
-
const entry = buildManifest[buildId];
|
|
545
|
+
const entry = buildManifest.entries[buildId];
|
|
546
546
|
if (entry) {
|
|
547
547
|
// Found in manifest - use persisted table
|
|
548
548
|
return this.parent.dialect.quoteTablePath(entry.tableName);
|
|
549
549
|
}
|
|
550
|
-
if (
|
|
550
|
+
if (buildManifest.strict) {
|
|
551
551
|
throw new Error(`Persist source '${qs.structDef.sourceID}' not found in manifest (buildId: ${buildId})`);
|
|
552
552
|
}
|
|
553
553
|
}
|
|
@@ -51,7 +51,7 @@ function expandSegment(segment, opts, quoteTablePath, compileQuery) {
|
|
|
51
51
|
* Always returns a subquery form: (SELECT * FROM table) or (inline SQL)
|
|
52
52
|
*/
|
|
53
53
|
function expandPersistableSource(source, opts, quoteTablePath, compileQuery) {
|
|
54
|
-
const { buildManifest, connectionDigests
|
|
54
|
+
const { buildManifest, connectionDigests } = opts;
|
|
55
55
|
// Try manifest lookup if we have the required info
|
|
56
56
|
if (buildManifest && connectionDigests) {
|
|
57
57
|
const connDigest = (0, malloy_types_1.safeRecordGet)(connectionDigests, source.connection);
|
|
@@ -59,13 +59,13 @@ function expandPersistableSource(source, opts, quoteTablePath, compileQuery) {
|
|
|
59
59
|
// Get the SQL for this source to compute BuildID (no opts = full SQL)
|
|
60
60
|
const sql = getSourceSQL(source, quoteTablePath, compileQuery);
|
|
61
61
|
const buildId = (0, source_def_utils_1.mkBuildID)(connDigest, sql);
|
|
62
|
-
const entry = buildManifest[buildId];
|
|
62
|
+
const entry = buildManifest.entries[buildId];
|
|
63
63
|
if (entry) {
|
|
64
64
|
// Found in manifest - substitute with subquery from persisted table
|
|
65
65
|
return `(SELECT * FROM ${quoteTablePath(entry.tableName)})`;
|
|
66
66
|
}
|
|
67
67
|
// Not in manifest
|
|
68
|
-
if (
|
|
68
|
+
if (buildManifest.strict) {
|
|
69
69
|
throw new Error(`Persist source '${source.sourceID}' not found in manifest (buildId: ${buildId})`);
|
|
70
70
|
}
|
|
71
71
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const MALLOY_VERSION = "0.0.
|
|
1
|
+
export declare const MALLOY_VERSION = "0.0.350";
|
package/dist/version.js
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MALLOY_VERSION = void 0;
|
|
4
4
|
// generated with 'generate-version-file' script; do not edit manually
|
|
5
|
-
exports.MALLOY_VERSION = '0.0.
|
|
5
|
+
exports.MALLOY_VERSION = '0.0.350';
|
|
6
6
|
//# sourceMappingURL=version.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloydata/malloy",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.350",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/index.js",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"generate-version-file": "VERSION=$(npm pkg get version --workspaces=false | tr -d \\\")\necho \"// generated with 'generate-version-file' script; do not edit manually\\nexport const MALLOY_VERSION = '$VERSION';\" > src/version.ts"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@malloydata/malloy-filter": "0.0.
|
|
49
|
-
"@malloydata/malloy-interfaces": "0.0.
|
|
50
|
-
"@malloydata/malloy-tag": "0.0.
|
|
48
|
+
"@malloydata/malloy-filter": "0.0.350",
|
|
49
|
+
"@malloydata/malloy-interfaces": "0.0.350",
|
|
50
|
+
"@malloydata/malloy-tag": "0.0.350",
|
|
51
51
|
"@noble/hashes": "^1.8.0",
|
|
52
52
|
"antlr4ts": "^0.5.0-alpha.4",
|
|
53
53
|
"assert": "^2.0.0",
|