@malloydata/malloy 0.0.334 → 0.0.336
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/CONTEXT.md +4 -3
- package/MALLOY_API.md +129 -0
- package/dist/annotation.d.ts +0 -2
- package/dist/annotation.js +29 -23
- package/dist/api/asynchronous.d.ts +1 -1
- package/dist/api/foundation/cache.d.ts +32 -0
- package/dist/api/foundation/cache.js +92 -0
- package/dist/api/foundation/compile.d.ts +175 -0
- package/dist/api/foundation/compile.js +391 -0
- package/dist/api/foundation/core.d.ts +493 -0
- package/dist/api/foundation/core.js +1247 -0
- package/dist/api/foundation/document.d.ts +167 -0
- package/dist/api/foundation/document.js +206 -0
- package/dist/api/foundation/index.d.ts +10 -0
- package/dist/api/foundation/index.js +77 -0
- package/dist/api/foundation/readers.d.ts +53 -0
- package/dist/api/foundation/readers.js +134 -0
- package/dist/api/foundation/result.d.ts +185 -0
- package/dist/api/foundation/result.js +704 -0
- package/dist/api/foundation/runtime.d.ts +361 -0
- package/dist/api/foundation/runtime.js +733 -0
- package/dist/api/foundation/types.d.ts +54 -0
- package/dist/api/foundation/types.js +7 -0
- package/dist/api/foundation/writers.d.ts +42 -0
- package/dist/api/foundation/writers.js +230 -0
- package/dist/api/util.d.ts +1 -1
- package/dist/connection/base_connection.d.ts +5 -0
- package/dist/connection/types.d.ts +5 -0
- package/dist/dialect/duckdb/duckdb.js +2 -1
- package/dist/dialect/snowflake/snowflake.js +7 -1
- package/dist/dialect/trino/trino.js +7 -2
- package/dist/index.d.ts +6 -3
- package/dist/index.js +30 -26
- package/dist/lang/ast/error-factory.js +3 -5
- package/dist/lang/ast/expressions/expr-count-distinct.js +7 -1
- package/dist/lang/ast/expressions/expr-granular-time.js +1 -1
- package/dist/lang/ast/expressions/expr-max.js +7 -1
- package/dist/lang/ast/expressions/expr-min.js +7 -1
- package/dist/lang/ast/expressions/for-range.js +1 -1
- package/dist/lang/ast/source-elements/query-source.js +2 -7
- package/dist/lang/ast/source-elements/refined-source.js +11 -1
- package/dist/lang/ast/source-elements/sql-source.d.ts +1 -1
- package/dist/lang/ast/source-elements/sql-source.js +18 -3
- package/dist/lang/ast/sql-elements/sql-string.d.ts +2 -2
- package/dist/lang/ast/sql-elements/sql-string.js +18 -1
- package/dist/lang/ast/statements/define-source.js +7 -2
- package/dist/lang/ast/statements/import-statement.js +53 -21
- package/dist/lang/ast/types/document-compile-result.d.ts +1 -0
- package/dist/lang/ast/types/expression-def.js +1 -1
- package/dist/lang/ast/types/malloy-element.d.ts +3 -1
- package/dist/lang/ast/types/malloy-element.js +23 -7
- package/dist/lang/malloy-to-ast.d.ts +1 -1
- package/dist/lang/malloy-to-ast.js +1 -1
- package/dist/lang/parse-malloy.d.ts +3 -2
- package/dist/lang/parse-malloy.js +14 -25
- package/dist/lang/test/test-translator.d.ts +9 -2
- package/dist/lang/test/test-translator.js +103 -77
- package/dist/lang/translate-response.d.ts +1 -0
- package/dist/model/constant_expression_compiler.js +6 -7
- package/dist/model/index.d.ts +3 -1
- package/dist/model/index.js +15 -9
- package/dist/model/malloy_types.d.ts +89 -15
- package/dist/model/malloy_types.js +12 -0
- package/dist/model/persist_utils.d.ts +47 -0
- package/dist/model/persist_utils.js +257 -0
- package/dist/model/query_model_impl.d.ts +2 -4
- package/dist/model/query_model_impl.js +5 -13
- package/dist/model/query_node.d.ts +1 -2
- package/dist/model/query_node.js +3 -13
- package/dist/model/query_query.d.ts +17 -1
- package/dist/model/query_query.js +81 -36
- package/dist/model/source_def_utils.d.ts +50 -0
- package/dist/model/source_def_utils.js +154 -0
- package/dist/model/sql_block.d.ts +5 -1
- package/dist/model/sql_block.js +29 -4
- package/dist/model/sql_compiled.d.ts +29 -0
- package/dist/model/sql_compiled.js +102 -0
- package/dist/model/stage_writer.d.ts +1 -3
- package/dist/model/stage_writer.js +7 -25
- package/dist/model/utils.d.ts +20 -1
- package/dist/model/utils.js +40 -0
- package/dist/run_sql_options.d.ts +0 -1
- package/dist/taggable.d.ts +10 -0
- package/dist/taggable.js +7 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +6 -4
- package/dist/malloy.d.ts +0 -1365
- package/dist/malloy.js +0 -3421
- package/dist/model/materialization/utils.d.ts +0 -3
- package/dist/model/materialization/utils.js +0 -41
|
@@ -0,0 +1,391 @@
|
|
|
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.Malloy = exports.MalloyError = void 0;
|
|
8
|
+
const lang_1 = require("../../lang");
|
|
9
|
+
const model_1 = require("../../model");
|
|
10
|
+
const sql_block_1 = require("../../model/sql_block");
|
|
11
|
+
const version_1 = require("../../version");
|
|
12
|
+
const readers_1 = require("./readers");
|
|
13
|
+
const document_1 = require("./document");
|
|
14
|
+
const core_1 = require("./core");
|
|
15
|
+
const result_1 = require("./result");
|
|
16
|
+
const MALLOY_INTERNAL_URL = 'internal://internal.malloy';
|
|
17
|
+
// =============================================================================
|
|
18
|
+
// Helper Functions
|
|
19
|
+
// =============================================================================
|
|
20
|
+
function flatDeps(tree) {
|
|
21
|
+
return [...Object.keys(tree), ...Object.values(tree).map(flatDeps).flat()];
|
|
22
|
+
}
|
|
23
|
+
// =============================================================================
|
|
24
|
+
// MalloyError
|
|
25
|
+
// =============================================================================
|
|
26
|
+
/**
|
|
27
|
+
* A Malloy error, which may contain log messages produced during compilation.
|
|
28
|
+
*/
|
|
29
|
+
class MalloyError extends Error {
|
|
30
|
+
/**
|
|
31
|
+
* An array of log messages produced during compilation.
|
|
32
|
+
*/
|
|
33
|
+
constructor(message, problems = []) {
|
|
34
|
+
super(message);
|
|
35
|
+
this.problems = problems;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.MalloyError = MalloyError;
|
|
39
|
+
// =============================================================================
|
|
40
|
+
// Malloy Static Class
|
|
41
|
+
// =============================================================================
|
|
42
|
+
class Malloy {
|
|
43
|
+
static get version() {
|
|
44
|
+
return version_1.MALLOY_VERSION;
|
|
45
|
+
}
|
|
46
|
+
static _parse(source, url, eventStream, options, invalidationKey) {
|
|
47
|
+
if (url === undefined) {
|
|
48
|
+
url = new URL(MALLOY_INTERNAL_URL);
|
|
49
|
+
}
|
|
50
|
+
let importBaseURL = url;
|
|
51
|
+
if (options === null || options === void 0 ? void 0 : options.importBaseURL) {
|
|
52
|
+
importBaseURL = options === null || options === void 0 ? void 0 : options.importBaseURL;
|
|
53
|
+
}
|
|
54
|
+
const translator = new lang_1.MalloyTranslator(url.toString(), importBaseURL.toString(), {
|
|
55
|
+
urls: { [url.toString()]: source },
|
|
56
|
+
}, eventStream);
|
|
57
|
+
if (options === null || options === void 0 ? void 0 : options.testEnvironment) {
|
|
58
|
+
translator.allDialectsEnabled = true;
|
|
59
|
+
}
|
|
60
|
+
return new document_1.Parse(translator, invalidationKey);
|
|
61
|
+
}
|
|
62
|
+
static parse({ url, urlReader, source, eventStream, options, }) {
|
|
63
|
+
if (source !== undefined) {
|
|
64
|
+
return Malloy._parse(source, url, eventStream, options);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
if (urlReader === undefined) {
|
|
68
|
+
throw new Error('Internal Error: urlReader is required.');
|
|
69
|
+
}
|
|
70
|
+
if (url === undefined) {
|
|
71
|
+
throw new Error('Internal Error: url is required if source not present.');
|
|
72
|
+
}
|
|
73
|
+
return (0, readers_1.readURL)(urlReader, url).then(({ contents, invalidationKey }) => {
|
|
74
|
+
return Malloy._parse(contents, url, eventStream, options, invalidationKey);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Compile a parsed Malloy document.
|
|
80
|
+
*
|
|
81
|
+
* @param urlReader Object capable of reading contents of a URL.
|
|
82
|
+
* @param connections Mapping of connection names to objects capable of reading Malloy schemas.
|
|
83
|
+
* @param parse The parsed Malloy document.
|
|
84
|
+
* @param model A compiled model to build upon (optional).
|
|
85
|
+
* @return A (promise of a) compiled `Model`.
|
|
86
|
+
*/
|
|
87
|
+
static async compile({ url, source, parse, urlReader, connections, model, refreshSchemaCache, noThrowOnError, eventStream, importBaseURL, cacheManager, }) {
|
|
88
|
+
var _a, _b, _c, _d, _e;
|
|
89
|
+
let refreshTimestamp;
|
|
90
|
+
if (refreshSchemaCache) {
|
|
91
|
+
refreshTimestamp =
|
|
92
|
+
typeof refreshSchemaCache === 'number'
|
|
93
|
+
? refreshSchemaCache
|
|
94
|
+
: Date.now();
|
|
95
|
+
}
|
|
96
|
+
if (url === undefined && source === undefined && parse === undefined) {
|
|
97
|
+
throw new Error('Internal Error: url, source, or parse required.');
|
|
98
|
+
}
|
|
99
|
+
if (url === undefined) {
|
|
100
|
+
if (parse !== undefined) {
|
|
101
|
+
url = new URL(parse._translator.sourceURL);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
url = new URL(MALLOY_INTERNAL_URL);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const invalidationKeys = {};
|
|
108
|
+
// Before anything, if we have a URL and not source code, we check if that URL
|
|
109
|
+
// is cached.
|
|
110
|
+
if (source === undefined && cacheManager !== undefined) {
|
|
111
|
+
const cached = await cacheManager.getCachedModelDef(urlReader, url.toString());
|
|
112
|
+
if (cached) {
|
|
113
|
+
return new core_1.Model(cached.modelDef, [], // TODO when using a model from cache, should we also store the problems??
|
|
114
|
+
[url.toString(), ...flatDeps(cached.modelDef.dependencies)]);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
importBaseURL !== null && importBaseURL !== void 0 ? importBaseURL : (importBaseURL = url);
|
|
118
|
+
let translator;
|
|
119
|
+
// It's not cached, so we may need to get the actual source
|
|
120
|
+
const _url = url.toString();
|
|
121
|
+
if (parse !== undefined) {
|
|
122
|
+
translator = parse._translator;
|
|
123
|
+
const invalidationKey = (_a = parse._invalidationKey) !== null && _a !== void 0 ? _a : (await (0, readers_1.getInvalidationKey)(urlReader, url));
|
|
124
|
+
invalidationKeys[_url] = invalidationKey;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
if (source === undefined) {
|
|
128
|
+
const { contents, invalidationKey } = await (0, readers_1.readURL)(urlReader, url);
|
|
129
|
+
invalidationKeys[_url] = invalidationKey;
|
|
130
|
+
source = contents;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
const invalidationKey = await (0, readers_1.getInvalidationKey)(urlReader, url);
|
|
134
|
+
invalidationKeys[_url] = invalidationKey;
|
|
135
|
+
}
|
|
136
|
+
translator = new lang_1.MalloyTranslator(_url, importBaseURL.toString(), {
|
|
137
|
+
urls: { [_url]: source },
|
|
138
|
+
}, eventStream);
|
|
139
|
+
}
|
|
140
|
+
for (;;) {
|
|
141
|
+
const result = translator.translate(model === null || model === void 0 ? void 0 : model._modelDef);
|
|
142
|
+
if (result.final) {
|
|
143
|
+
if (result.modelDef) {
|
|
144
|
+
await (cacheManager === null || cacheManager === void 0 ? void 0 : cacheManager.setCachedModelDef(url.toString(), {
|
|
145
|
+
modelDef: result.modelDef,
|
|
146
|
+
invalidationKeys,
|
|
147
|
+
}));
|
|
148
|
+
for (const m of translator.newlyTranslatedDependencies()) {
|
|
149
|
+
await (cacheManager === null || cacheManager === void 0 ? void 0 : cacheManager.setCachedModelDef(m.url, {
|
|
150
|
+
modelDef: m.modelDef,
|
|
151
|
+
invalidationKeys,
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
// If the model wasn't modified, create new Model with result's modelDef
|
|
155
|
+
// (which has the queryList) but share the cached QueryModel from input model
|
|
156
|
+
const existingQueryModel = !result.modelWasModified && model
|
|
157
|
+
? model.getExistingQueryModel()
|
|
158
|
+
: undefined;
|
|
159
|
+
return new core_1.Model(result.modelDef, result.problems || [], [...((_b = model === null || model === void 0 ? void 0 : model.fromSources) !== null && _b !== void 0 ? _b : []), ...((_c = result.fromSources) !== null && _c !== void 0 ? _c : [])], existingQueryModel);
|
|
160
|
+
}
|
|
161
|
+
else if (noThrowOnError) {
|
|
162
|
+
const emptyModel = (0, model_1.mkModelDef)('modelDidNotCompile');
|
|
163
|
+
const modelFromCompile = (model === null || model === void 0 ? void 0 : model._modelDef) || emptyModel;
|
|
164
|
+
return new core_1.Model(modelFromCompile, result.problems || [], [
|
|
165
|
+
...((_d = model === null || model === void 0 ? void 0 : model.fromSources) !== null && _d !== void 0 ? _d : []),
|
|
166
|
+
...((_e = result.fromSources) !== null && _e !== void 0 ? _e : []),
|
|
167
|
+
]);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
const errors = result.problems || [];
|
|
171
|
+
const errText = translator.prettyErrors();
|
|
172
|
+
throw new MalloyError(`Error(s) compiling model:\n${errText}`, errors);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// Parse incomplete because some external information is required,
|
|
177
|
+
// there might be more than one of these in a single reply ...
|
|
178
|
+
if (result.urls) {
|
|
179
|
+
for (const neededUrl of result.urls) {
|
|
180
|
+
try {
|
|
181
|
+
if ((0, readers_1.isInternalURL)(neededUrl)) {
|
|
182
|
+
throw new Error('In order to use relative imports, you must compile a file via a URL.');
|
|
183
|
+
}
|
|
184
|
+
// First, check the cache
|
|
185
|
+
if (cacheManager !== undefined) {
|
|
186
|
+
const cached = await cacheManager.getCachedModelDef(urlReader, neededUrl);
|
|
187
|
+
if (cached) {
|
|
188
|
+
for (const dependency in cached.invalidationKeys) {
|
|
189
|
+
invalidationKeys[dependency] =
|
|
190
|
+
cached.invalidationKeys[dependency];
|
|
191
|
+
}
|
|
192
|
+
translator.update({
|
|
193
|
+
translations: { [neededUrl]: cached.modelDef },
|
|
194
|
+
});
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Otherwise, fetch the URL contents
|
|
199
|
+
const { contents, invalidationKey } = await (0, readers_1.readURL)(urlReader, new URL(neededUrl));
|
|
200
|
+
const urls = { [neededUrl]: contents };
|
|
201
|
+
invalidationKeys[neededUrl] = invalidationKey;
|
|
202
|
+
translator.update({ urls });
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
translator.update({
|
|
206
|
+
errors: { urls: { [neededUrl]: error.message } },
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const { modelAnnotation } = translator.modelAnnotation(model === null || model === void 0 ? void 0 : model._modelDef);
|
|
212
|
+
if (result.tables) {
|
|
213
|
+
// collect tables by connection name since there may be multiple connections
|
|
214
|
+
const tablesByConnection = new Map();
|
|
215
|
+
for (const tableKey in result.tables) {
|
|
216
|
+
const { connectionName, tablePath } = result.tables[tableKey];
|
|
217
|
+
const connectionToTablesMap = tablesByConnection.get(connectionName);
|
|
218
|
+
if (connectionToTablesMap === undefined) {
|
|
219
|
+
tablesByConnection.set(connectionName, { [tableKey]: tablePath });
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
connectionToTablesMap[tableKey] = tablePath;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// iterate over connections, fetching schema for all missing tables
|
|
226
|
+
for (const [connectionName, tablePathByKey] of tablesByConnection) {
|
|
227
|
+
try {
|
|
228
|
+
const connection = await connections.lookupConnection(connectionName);
|
|
229
|
+
// TODO detect if the union of `Object.keys(tables)` and `Object.keys(errors)` is not the same
|
|
230
|
+
// as `Object.keys(tablePathByKey)`, i.e. that all tables are accounted for. Otherwise
|
|
231
|
+
// the translator runs into an infinite loop fetching tables.
|
|
232
|
+
const { schemas: tables, errors } = await Malloy.safelyFetchTableSchema(connection, tablePathByKey, {
|
|
233
|
+
refreshTimestamp,
|
|
234
|
+
modelAnnotation,
|
|
235
|
+
});
|
|
236
|
+
translator.update({ tables, errors: { tables: errors } });
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
// There was an exception getting the connection, associate that error
|
|
240
|
+
// with all its tables
|
|
241
|
+
const tables = {};
|
|
242
|
+
const errors = {};
|
|
243
|
+
for (const tableKey in tablePathByKey) {
|
|
244
|
+
errors[tableKey] = error.toString();
|
|
245
|
+
}
|
|
246
|
+
translator.update({ tables, errors: { tables: errors } });
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (result.compileSQL) {
|
|
251
|
+
// Unlike other requests, these do not come in batches
|
|
252
|
+
const toCompile = result.compileSQL;
|
|
253
|
+
const connectionName = toCompile.connection;
|
|
254
|
+
const key = (0, sql_block_1.sqlKey)(toCompile.connection, toCompile.selectStr);
|
|
255
|
+
try {
|
|
256
|
+
const conn = await connections.lookupConnection(connectionName);
|
|
257
|
+
const resolved = await conn.fetchSchemaForSQLStruct(toCompile, {
|
|
258
|
+
refreshTimestamp,
|
|
259
|
+
modelAnnotation,
|
|
260
|
+
});
|
|
261
|
+
if (resolved.error) {
|
|
262
|
+
translator.update({
|
|
263
|
+
errors: {
|
|
264
|
+
compileSQL: {
|
|
265
|
+
[key]: resolved.error,
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
if (resolved.structDef) {
|
|
271
|
+
translator.update({
|
|
272
|
+
compileSQL: { [key]: resolved.structDef },
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
const errors = {};
|
|
278
|
+
errors[key] = error.toString();
|
|
279
|
+
translator.update({ errors: { compileSQL: errors } });
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* A dialect must provide a response for every table, or the translator loop
|
|
287
|
+
* will never exit. Because there was a time when this happened, we throw
|
|
288
|
+
* instead of looping forever, but the fix is to correct the dialect.
|
|
289
|
+
*/
|
|
290
|
+
static async safelyFetchTableSchema(connection, toFetch, opts) {
|
|
291
|
+
const ret = await connection.fetchSchemaForTables(toFetch, opts);
|
|
292
|
+
for (const req of Object.keys(toFetch)) {
|
|
293
|
+
if (ret.schemas[req] === undefined && ret.errors[req] === undefined) {
|
|
294
|
+
throw new Error(`Schema fetch error for ${connection.name}, no response for ${req} from ${connection.dialectName}`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return ret;
|
|
298
|
+
}
|
|
299
|
+
static async run({ connections, preparedResult, sqlStruct, connection, options, }) {
|
|
300
|
+
if (!connection) {
|
|
301
|
+
if (!connections) {
|
|
302
|
+
throw new Error('Internal Error: Connection or LookupConnection<Connection> must be provided.');
|
|
303
|
+
}
|
|
304
|
+
const connectionName = (sqlStruct === null || sqlStruct === void 0 ? void 0 : sqlStruct.connection) || (preparedResult === null || preparedResult === void 0 ? void 0 : preparedResult.connectionName);
|
|
305
|
+
connection = await connections.lookupConnection(connectionName);
|
|
306
|
+
}
|
|
307
|
+
if (sqlStruct) {
|
|
308
|
+
const data = await connection.runSQL(sqlStruct.selectStr);
|
|
309
|
+
return new result_1.Result({
|
|
310
|
+
structs: [sqlStruct],
|
|
311
|
+
sql: sqlStruct.selectStr,
|
|
312
|
+
result: data.rows,
|
|
313
|
+
totalRows: data.totalRows,
|
|
314
|
+
runStats: data.runStats,
|
|
315
|
+
lastStageName: sqlStruct.name,
|
|
316
|
+
// TODO feature-sql-block There is no malloy code...
|
|
317
|
+
malloy: '',
|
|
318
|
+
connectionName: sqlStruct.connection,
|
|
319
|
+
// TODO feature-sql-block There is no source explore...
|
|
320
|
+
sourceExplore: '',
|
|
321
|
+
sourceFilters: [],
|
|
322
|
+
profilingUrl: data.profilingUrl,
|
|
323
|
+
}, (0, model_1.mkModelDef)('empty_model'));
|
|
324
|
+
}
|
|
325
|
+
else if (preparedResult) {
|
|
326
|
+
const result = await connection.runSQL(preparedResult.sql, options);
|
|
327
|
+
return new result_1.Result({
|
|
328
|
+
...preparedResult._rawQuery,
|
|
329
|
+
result: result.rows,
|
|
330
|
+
totalRows: result.totalRows,
|
|
331
|
+
runStats: result.runStats,
|
|
332
|
+
profilingUrl: result.profilingUrl,
|
|
333
|
+
}, preparedResult._modelDef);
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
throw new Error('Internal error: sqlStruct or preparedResult must be provided.');
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
static async *runStream({ connections, preparedResult, sqlStruct, connection, options, }) {
|
|
340
|
+
if (sqlStruct === undefined && preparedResult === undefined) {
|
|
341
|
+
throw new Error('Internal error: sqlBlock or preparedResult must be provided.');
|
|
342
|
+
}
|
|
343
|
+
const connectionName = (sqlStruct === null || sqlStruct === void 0 ? void 0 : sqlStruct.connection) || (preparedResult === null || preparedResult === void 0 ? void 0 : preparedResult.connectionName);
|
|
344
|
+
if (connection === undefined) {
|
|
345
|
+
if (connections === undefined) {
|
|
346
|
+
throw new Error('Internal Error: Connection or LookupConnection<Connection> must be provided.');
|
|
347
|
+
}
|
|
348
|
+
connection = await connections.lookupConnection(connectionName);
|
|
349
|
+
}
|
|
350
|
+
// TODO is there a better way to handle this case? Just require StreamingConnections?
|
|
351
|
+
if (!connection.canStream()) {
|
|
352
|
+
throw new Error(`Connection '${connectionName}' cannot stream results.`);
|
|
353
|
+
}
|
|
354
|
+
let sql;
|
|
355
|
+
let resultExplore;
|
|
356
|
+
if (sqlStruct) {
|
|
357
|
+
resultExplore = new core_1.Explore(sqlStruct);
|
|
358
|
+
sql = sqlStruct.selectStr;
|
|
359
|
+
}
|
|
360
|
+
else if (preparedResult !== undefined) {
|
|
361
|
+
resultExplore = preparedResult.resultExplore;
|
|
362
|
+
sql = preparedResult.sql;
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
throw new Error('Internal error: sqlStruct or preparedResult must be provided.');
|
|
366
|
+
}
|
|
367
|
+
let index = 0;
|
|
368
|
+
for await (const row of connection.runSQLStream(sql, options)) {
|
|
369
|
+
yield new result_1.DataRecord(row, index, resultExplore, undefined, undefined);
|
|
370
|
+
index += 1;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
static async estimateQueryCost({ connections, preparedResult, sqlStruct, }) {
|
|
374
|
+
if (!connections) {
|
|
375
|
+
throw new Error('Internal Error: Connection or LookupConnection<Connection> must be provided.');
|
|
376
|
+
}
|
|
377
|
+
const connectionName = (sqlStruct === null || sqlStruct === void 0 ? void 0 : sqlStruct.connection) || (preparedResult === null || preparedResult === void 0 ? void 0 : preparedResult.connectionName);
|
|
378
|
+
const connection = await connections.lookupConnection(connectionName);
|
|
379
|
+
if (sqlStruct) {
|
|
380
|
+
return await connection.estimateQueryCost(sqlStruct.selectStr);
|
|
381
|
+
}
|
|
382
|
+
else if (preparedResult) {
|
|
383
|
+
return await connection.estimateQueryCost(preparedResult.sql);
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
throw new Error('Internal error: sqlStruct or preparedResult must be provided.');
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
exports.Malloy = Malloy;
|
|
391
|
+
//# sourceMappingURL=compile.js.map
|