@malloydata/malloy 0.0.296 → 0.0.297
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/asynchronous.js +39 -8
- package/dist/api/core.d.ts +3 -0
- package/dist/api/core.js +47 -9
- package/dist/api/sessioned.js +53 -6
- package/dist/dialect/trino/dialect_functions.js +107 -62
- package/dist/lang/malloy-to-ast.d.ts +9 -0
- package/dist/lang/malloy-to-ast.js +19 -1
- package/dist/lang/parse-malloy.d.ts +2 -2
- package/dist/lang/parse-malloy.js +42 -24
- package/dist/lang/translate-response.d.ts +12 -8
- package/dist/timing.d.ts +11 -0
- package/dist/timing.js +33 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
package/dist/api/asynchronous.js
CHANGED
|
@@ -45,16 +45,20 @@ exports.compileQuery = compileQuery;
|
|
|
45
45
|
exports.runQuery = runQuery;
|
|
46
46
|
const Core = __importStar(require("./core"));
|
|
47
47
|
const util_1 = require("./util");
|
|
48
|
+
const timing_1 = require("../timing");
|
|
48
49
|
async function fetchNeeds(needs, fetchers) {
|
|
49
50
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
50
51
|
var _h, _j;
|
|
52
|
+
const timer = new timing_1.Timer('fetch_needs');
|
|
51
53
|
if (needs === undefined) {
|
|
52
54
|
throw new Error("Expected compiler to have needs because it didn't return a result");
|
|
53
55
|
}
|
|
54
56
|
const result = {};
|
|
55
57
|
if (needs.connections) {
|
|
56
58
|
for (const connection of needs.connections) {
|
|
59
|
+
const t = new timing_1.Timer('lookup_connection');
|
|
57
60
|
const info = await fetchers.connections.lookupConnection(connection.name);
|
|
61
|
+
timer.contribute([t.stop()]);
|
|
58
62
|
(_a = result.connections) !== null && _a !== void 0 ? _a : (result.connections = []);
|
|
59
63
|
result.connections.push({
|
|
60
64
|
...connection,
|
|
@@ -65,7 +69,9 @@ async function fetchNeeds(needs, fetchers) {
|
|
|
65
69
|
if (needs.files) {
|
|
66
70
|
for (const file of needs.files) {
|
|
67
71
|
// TODO handle checking if the cache has the file...
|
|
72
|
+
const t = new timing_1.Timer('read_url');
|
|
68
73
|
const info = await fetchers.urls.readURL(new URL(file.url));
|
|
74
|
+
timer.contribute([t.stop()]);
|
|
69
75
|
(_b = result.files) !== null && _b !== void 0 ? _b : (result.files = []);
|
|
70
76
|
if (typeof info === 'string') {
|
|
71
77
|
result.files.push({
|
|
@@ -89,12 +95,16 @@ async function fetchNeeds(needs, fetchers) {
|
|
|
89
95
|
tableSchemasByConnection[tableSchema.connection_name].push(tableSchema);
|
|
90
96
|
}
|
|
91
97
|
for (const connectionName in tableSchemasByConnection) {
|
|
98
|
+
const t1 = new timing_1.Timer('lookup_connection');
|
|
92
99
|
const connection = await fetchers.connections.lookupConnection(connectionName);
|
|
100
|
+
timer.contribute([t1.stop()]);
|
|
93
101
|
const tableNames = tableSchemasByConnection[connectionName].map(t => t.name);
|
|
102
|
+
const t2 = new timing_1.Timer('fetch_table_schemas');
|
|
94
103
|
const schemas = await Promise.all(tableNames.map(async (tableName) => ({
|
|
95
104
|
name: tableName,
|
|
96
105
|
schema: await connection.fetchSchemaForTable(tableName),
|
|
97
106
|
})));
|
|
107
|
+
timer.contribute([t2.stop()]);
|
|
98
108
|
(_e = result.table_schemas) !== null && _e !== void 0 ? _e : (result.table_schemas = []);
|
|
99
109
|
for (const schema of schemas) {
|
|
100
110
|
result.table_schemas.push({
|
|
@@ -112,12 +122,16 @@ async function fetchNeeds(needs, fetchers) {
|
|
|
112
122
|
sqlSchemasByConnectionName[sqlSchema.connection_name].push(sqlSchema);
|
|
113
123
|
}
|
|
114
124
|
for (const connectionName in sqlSchemasByConnectionName) {
|
|
125
|
+
const t1 = new timing_1.Timer('lookup_connection');
|
|
115
126
|
const connection = await fetchers.connections.lookupConnection(connectionName);
|
|
127
|
+
timer.contribute([t1.stop()]);
|
|
116
128
|
const sqlQueries = sqlSchemasByConnectionName[connectionName].map(t => t.sql);
|
|
129
|
+
const t2 = new timing_1.Timer('lookup_sql_schemas');
|
|
117
130
|
const schemas = await Promise.all(sqlQueries.map(async (sql) => ({
|
|
118
131
|
sql,
|
|
119
132
|
schema: await connection.fetchSchemaForSQLQuery(sql),
|
|
120
133
|
})));
|
|
134
|
+
timer.contribute([t2.stop()]);
|
|
121
135
|
(_g = result.sql_schemas) !== null && _g !== void 0 ? _g : (result.sql_schemas = []);
|
|
122
136
|
for (const schema of schemas) {
|
|
123
137
|
result.sql_schemas.push({
|
|
@@ -128,49 +142,60 @@ async function fetchNeeds(needs, fetchers) {
|
|
|
128
142
|
}
|
|
129
143
|
}
|
|
130
144
|
}
|
|
131
|
-
return result;
|
|
145
|
+
return { needs: result, timingInfo: timer.stop() };
|
|
132
146
|
}
|
|
133
147
|
async function compileModel(request, fetchers) {
|
|
148
|
+
const timer = new timing_1.Timer('compile_model');
|
|
134
149
|
const state = Core.newCompileModelState(request);
|
|
135
150
|
// eslint-disable-next-line no-constant-condition
|
|
136
151
|
while (true) {
|
|
137
152
|
const result = Core.statedCompileModel(state);
|
|
153
|
+
timer.incorporate(result.timing_info);
|
|
138
154
|
if (result.model || Core.hasErrors(result.logs)) {
|
|
139
|
-
return result;
|
|
155
|
+
return { ...result, timing_info: timer.stop() };
|
|
140
156
|
}
|
|
141
|
-
const needs = await fetchNeeds(result.compiler_needs, fetchers);
|
|
157
|
+
const { needs, timingInfo } = await fetchNeeds(result.compiler_needs, fetchers);
|
|
158
|
+
timer.incorporate(timingInfo);
|
|
142
159
|
Core.updateCompileModelState(state, needs);
|
|
143
160
|
}
|
|
144
161
|
}
|
|
145
162
|
async function compileSource(request, fetchers) {
|
|
163
|
+
const timer = new timing_1.Timer('compile_source');
|
|
146
164
|
const state = Core.newCompileSourceState(request);
|
|
147
165
|
// eslint-disable-next-line no-constant-condition
|
|
148
166
|
while (true) {
|
|
149
167
|
const result = Core.statedCompileSource(state, request.name);
|
|
168
|
+
timer.incorporate(result.timing_info);
|
|
150
169
|
if (result.source || Core.hasErrors(result.logs)) {
|
|
151
|
-
return result;
|
|
170
|
+
return { ...result, timing_info: timer.stop() };
|
|
152
171
|
}
|
|
153
|
-
const needs = await fetchNeeds(result.compiler_needs, fetchers);
|
|
172
|
+
const { needs, timingInfo } = await fetchNeeds(result.compiler_needs, fetchers);
|
|
173
|
+
timer.incorporate(timingInfo);
|
|
154
174
|
Core.updateCompileModelState(state, needs);
|
|
155
175
|
}
|
|
156
176
|
}
|
|
157
177
|
async function compileQuery(request, fetchers) {
|
|
178
|
+
const timer = new timing_1.Timer('compile_query');
|
|
158
179
|
const state = Core.newCompileQueryState(request);
|
|
159
180
|
// eslint-disable-next-line no-constant-condition
|
|
160
181
|
while (true) {
|
|
161
182
|
const result = Core.statedCompileQuery(state);
|
|
183
|
+
timer.incorporate(result.timing_info);
|
|
162
184
|
if (result.result || Core.hasErrors(result.logs)) {
|
|
163
|
-
return result;
|
|
185
|
+
return { ...result, timing_info: timer.stop() };
|
|
164
186
|
}
|
|
165
|
-
const needs = await fetchNeeds(result.compiler_needs, fetchers);
|
|
187
|
+
const { needs, timingInfo } = await fetchNeeds(result.compiler_needs, fetchers);
|
|
188
|
+
timer.incorporate(timingInfo);
|
|
166
189
|
Core.updateCompileModelState(state, needs);
|
|
167
190
|
}
|
|
168
191
|
}
|
|
169
192
|
async function runQuery(request, fetchers) {
|
|
170
193
|
var _a, _b;
|
|
194
|
+
const timer = new timing_1.Timer('run_query');
|
|
171
195
|
const compiled = await compileQuery(request, fetchers);
|
|
196
|
+
timer.incorporate(compiled.timing_info);
|
|
172
197
|
if (compiled.result === undefined) {
|
|
173
|
-
return compiled;
|
|
198
|
+
return { ...compiled, timing_info: timer.stop() };
|
|
174
199
|
}
|
|
175
200
|
const defaultURL = request.model_url;
|
|
176
201
|
if (compiled.result.sql === undefined) {
|
|
@@ -187,14 +212,19 @@ async function runQuery(request, fetchers) {
|
|
|
187
212
|
};
|
|
188
213
|
}
|
|
189
214
|
try {
|
|
215
|
+
const t1 = new timing_1.Timer('lookup_connection');
|
|
190
216
|
const connection = await fetchers.connections.lookupConnection(compiled.result.connection_name);
|
|
217
|
+
timer.contribute([t1.stop()]);
|
|
218
|
+
const t2 = new timing_1.Timer('run_sql');
|
|
191
219
|
const data = await connection.runSQL(compiled.result.sql, compiled.result.schema);
|
|
220
|
+
timer.contribute([t2.stop()]);
|
|
192
221
|
return {
|
|
193
222
|
...compiled,
|
|
194
223
|
result: {
|
|
195
224
|
...compiled.result,
|
|
196
225
|
data,
|
|
197
226
|
},
|
|
227
|
+
timing_info: timer.stop(),
|
|
198
228
|
};
|
|
199
229
|
}
|
|
200
230
|
catch (error) {
|
|
@@ -209,6 +239,7 @@ async function runQuery(request, fetchers) {
|
|
|
209
239
|
range: util_1.DEFAULT_LOG_RANGE,
|
|
210
240
|
},
|
|
211
241
|
],
|
|
242
|
+
timing_info: timer.stop(),
|
|
212
243
|
};
|
|
213
244
|
}
|
|
214
245
|
}
|
package/dist/api/core.d.ts
CHANGED
|
@@ -7,16 +7,19 @@ export type CompileResponse = {
|
|
|
7
7
|
modelDef: ModelDef;
|
|
8
8
|
compilerNeeds?: undefined;
|
|
9
9
|
logs?: LogMessage[];
|
|
10
|
+
timingInfo: Malloy.TimingInfo;
|
|
10
11
|
} | {
|
|
11
12
|
model?: undefined;
|
|
12
13
|
modelDef?: undefined;
|
|
13
14
|
compilerNeeds: Malloy.CompilerNeeds;
|
|
14
15
|
logs?: LogMessage[];
|
|
16
|
+
timingInfo: Malloy.TimingInfo;
|
|
15
17
|
} | {
|
|
16
18
|
model?: undefined;
|
|
17
19
|
modelDef?: undefined;
|
|
18
20
|
compilerNeeds?: undefined;
|
|
19
21
|
logs: LogMessage[];
|
|
22
|
+
timingInfo: Malloy.TimingInfo;
|
|
20
23
|
};
|
|
21
24
|
export declare function compileQuery(request: Malloy.CompileQueryRequest, state?: CompileQueryState): Malloy.CompileQueryResponse;
|
|
22
25
|
export interface CompileModelState {
|
package/dist/api/core.js
CHANGED
|
@@ -59,6 +59,7 @@ const sql_block_1 = require("../model/sql_block");
|
|
|
59
59
|
const annotation_1 = require("../annotation");
|
|
60
60
|
const malloy_tag_1 = require("@malloydata/malloy-tag");
|
|
61
61
|
const util_1 = require("./util");
|
|
62
|
+
const timing_1 = require("../timing");
|
|
62
63
|
// TODO find where this should go...
|
|
63
64
|
function tableKey(connectionName, tablePath) {
|
|
64
65
|
return `${connectionName}:${tablePath}`;
|
|
@@ -299,12 +300,15 @@ function statedCompileSource(state, name) {
|
|
|
299
300
|
return extractSource(_statedCompileModel(state), name, state.translator.sourceURL);
|
|
300
301
|
}
|
|
301
302
|
function _statedCompileModel(state) {
|
|
303
|
+
const timer = new timing_1.Timer('compile_model');
|
|
302
304
|
let extendingModel = undefined;
|
|
305
|
+
let extendingResult = undefined;
|
|
303
306
|
if (state.extending) {
|
|
304
307
|
if (!state.extending.done) {
|
|
305
|
-
|
|
308
|
+
extendingResult = _statedCompileModel(state.extending);
|
|
309
|
+
timer.contribute([extendingResult.timingInfo]);
|
|
306
310
|
if (!state.extending.done) {
|
|
307
|
-
return extendingResult;
|
|
311
|
+
return { ...extendingResult, timingInfo: timer.stop() };
|
|
308
312
|
}
|
|
309
313
|
}
|
|
310
314
|
extendingModel = state.extending.translator.modelDef;
|
|
@@ -312,15 +316,20 @@ function _statedCompileModel(state) {
|
|
|
312
316
|
if (!state.hasSource) {
|
|
313
317
|
return {
|
|
314
318
|
compilerNeeds: convertCompilerNeeds(undefined, [state.translator.sourceURL], undefined),
|
|
319
|
+
timingInfo: timer.stop(),
|
|
315
320
|
};
|
|
316
321
|
}
|
|
317
322
|
const result = state.translator.translate(extendingModel);
|
|
323
|
+
timer.incorporate(result.timingInfo);
|
|
318
324
|
if (result.final) {
|
|
319
325
|
state.done = true;
|
|
326
|
+
const timingInfo = timer.stop();
|
|
320
327
|
if (result.modelDef) {
|
|
328
|
+
const model = (0, to_stable_1.modelDefToModelInfo)(result.modelDef);
|
|
321
329
|
return {
|
|
322
|
-
model
|
|
330
|
+
model,
|
|
323
331
|
modelDef: result.modelDef,
|
|
332
|
+
timingInfo,
|
|
324
333
|
};
|
|
325
334
|
}
|
|
326
335
|
else {
|
|
@@ -329,18 +338,24 @@ function _statedCompileModel(state) {
|
|
|
329
338
|
}
|
|
330
339
|
return {
|
|
331
340
|
logs: result.problems,
|
|
341
|
+
timingInfo,
|
|
332
342
|
};
|
|
333
343
|
}
|
|
334
344
|
}
|
|
335
345
|
else {
|
|
336
346
|
const compilerNeeds = convertCompilerNeeds(result.compileSQL, result.urls, result.tables);
|
|
337
|
-
|
|
347
|
+
const timingInfo = timer.stop();
|
|
348
|
+
return { compilerNeeds, logs: result.problems, timingInfo };
|
|
338
349
|
}
|
|
339
350
|
}
|
|
340
351
|
function wrapResponse(response, defaultURL) {
|
|
341
352
|
const logs = response.logs ? (0, util_1.mapLogs)(response.logs, defaultURL) : undefined;
|
|
342
353
|
if (response.compilerNeeds) {
|
|
343
|
-
return {
|
|
354
|
+
return {
|
|
355
|
+
compiler_needs: response.compilerNeeds,
|
|
356
|
+
logs,
|
|
357
|
+
timing_info: response.timingInfo,
|
|
358
|
+
};
|
|
344
359
|
}
|
|
345
360
|
else {
|
|
346
361
|
let translations = undefined;
|
|
@@ -352,7 +367,12 @@ function wrapResponse(response, defaultURL) {
|
|
|
352
367
|
},
|
|
353
368
|
];
|
|
354
369
|
}
|
|
355
|
-
return {
|
|
370
|
+
return {
|
|
371
|
+
model: response.model,
|
|
372
|
+
logs,
|
|
373
|
+
translations,
|
|
374
|
+
timing_info: response.timingInfo,
|
|
375
|
+
};
|
|
356
376
|
}
|
|
357
377
|
}
|
|
358
378
|
function _compileModel(modelURL, compilerNeeds, extendURL, state) {
|
|
@@ -383,12 +403,17 @@ function extractSource(result, name, defaultURL) {
|
|
|
383
403
|
range: util_1.DEFAULT_LOG_RANGE,
|
|
384
404
|
},
|
|
385
405
|
],
|
|
406
|
+
timing_info: result.timingInfo,
|
|
386
407
|
};
|
|
387
408
|
}
|
|
388
|
-
return { source, logs };
|
|
409
|
+
return { source, logs, timing_info: result.timingInfo };
|
|
389
410
|
}
|
|
390
411
|
else {
|
|
391
|
-
return {
|
|
412
|
+
return {
|
|
413
|
+
compiler_needs: result.compilerNeeds,
|
|
414
|
+
logs,
|
|
415
|
+
timing_info: result.timingInfo,
|
|
416
|
+
};
|
|
392
417
|
}
|
|
393
418
|
}
|
|
394
419
|
function hasErrors(log) {
|
|
@@ -416,7 +441,9 @@ function newCompileQueryState(request) {
|
|
|
416
441
|
}
|
|
417
442
|
function statedCompileQuery(state) {
|
|
418
443
|
var _a, _b;
|
|
444
|
+
const timer = new timing_1.Timer('compile_query');
|
|
419
445
|
const result = _statedCompileModel(state);
|
|
446
|
+
timer.incorporate(result.timingInfo);
|
|
420
447
|
// TODO this can expose the internal URL... is there a better way to handle URL-less errors from the compiler?
|
|
421
448
|
const defaultURL = state.translator.sourceURL;
|
|
422
449
|
const logs = result.logs ? (0, util_1.mapLogs)(result.logs, defaultURL) : undefined;
|
|
@@ -424,6 +451,7 @@ function statedCompileQuery(state) {
|
|
|
424
451
|
const queries = result.modelDef.queryList;
|
|
425
452
|
if (queries.length === 0) {
|
|
426
453
|
return {
|
|
454
|
+
timing_info: timer.stop(),
|
|
427
455
|
logs: [
|
|
428
456
|
...(logs !== null && logs !== void 0 ? logs : []),
|
|
429
457
|
{
|
|
@@ -440,10 +468,12 @@ function statedCompileQuery(state) {
|
|
|
440
468
|
const schema = result.model.anonymous_queries[index].schema;
|
|
441
469
|
const annotations = (_a = result.model.anonymous_queries[index].annotations) !== null && _a !== void 0 ? _a : [];
|
|
442
470
|
try {
|
|
471
|
+
const sqlTimer = new timing_1.Timer('generate_sql');
|
|
443
472
|
const queryModel = new model_1.QueryModel(result.modelDef);
|
|
444
473
|
const translatedQuery = queryModel.compileQuery(query, {
|
|
445
474
|
defaultRowLimit: state.defaultRowLimit,
|
|
446
475
|
});
|
|
476
|
+
timer.contribute([sqlTimer.stop()]);
|
|
447
477
|
const modelAnnotations = (0, annotation_1.annotationToTaglines)(result.modelDef.annotation).map(l => ({
|
|
448
478
|
value: l,
|
|
449
479
|
}));
|
|
@@ -486,6 +516,7 @@ function statedCompileQuery(state) {
|
|
|
486
516
|
.toString(),
|
|
487
517
|
});
|
|
488
518
|
}
|
|
519
|
+
const timingInfo = timer.stop();
|
|
489
520
|
return {
|
|
490
521
|
result: {
|
|
491
522
|
sql: translatedQuery.sql,
|
|
@@ -497,9 +528,11 @@ function statedCompileQuery(state) {
|
|
|
497
528
|
source_annotations: annotationsOrUndefined(sourceAnnotations),
|
|
498
529
|
},
|
|
499
530
|
default_row_limit_added: translatedQuery.defaultRowLimitAdded,
|
|
531
|
+
timing_info: timingInfo,
|
|
500
532
|
};
|
|
501
533
|
}
|
|
502
534
|
catch (error) {
|
|
535
|
+
const timingInfo = timer.stop();
|
|
503
536
|
return {
|
|
504
537
|
logs: [
|
|
505
538
|
...(logs !== null && logs !== void 0 ? logs : []),
|
|
@@ -510,11 +543,16 @@ function statedCompileQuery(state) {
|
|
|
510
543
|
range: util_1.DEFAULT_LOG_RANGE,
|
|
511
544
|
},
|
|
512
545
|
],
|
|
546
|
+
timing_info: timingInfo,
|
|
513
547
|
};
|
|
514
548
|
}
|
|
515
549
|
}
|
|
516
550
|
else {
|
|
517
|
-
return {
|
|
551
|
+
return {
|
|
552
|
+
compiler_needs: result.compilerNeeds,
|
|
553
|
+
logs,
|
|
554
|
+
timing_info: timer.stop(),
|
|
555
|
+
};
|
|
518
556
|
}
|
|
519
557
|
}
|
|
520
558
|
function annotationsOrUndefined(annotations) {
|
package/dist/api/sessioned.js
CHANGED
|
@@ -45,6 +45,7 @@ exports.compileQuery = compileQuery;
|
|
|
45
45
|
const Malloy = __importStar(require("@malloydata/malloy-interfaces"));
|
|
46
46
|
const Core = __importStar(require("./core"));
|
|
47
47
|
const uuid_1 = require("uuid");
|
|
48
|
+
const timing_1 = require("../timing");
|
|
48
49
|
function sessionInfosMatch(a, b) {
|
|
49
50
|
if (a.type === 'compile_model') {
|
|
50
51
|
if (b.type !== 'compile_model')
|
|
@@ -109,6 +110,7 @@ class SessionManager {
|
|
|
109
110
|
state,
|
|
110
111
|
expires,
|
|
111
112
|
sessionId: this.newSessionId(),
|
|
113
|
+
timer: new timing_1.Timer('compile_model'),
|
|
112
114
|
};
|
|
113
115
|
}
|
|
114
116
|
newCompileSourceSession(request, sessionInfo, options) {
|
|
@@ -120,6 +122,7 @@ class SessionManager {
|
|
|
120
122
|
state,
|
|
121
123
|
expires,
|
|
122
124
|
sessionId: this.newSessionId(),
|
|
125
|
+
timer: new timing_1.Timer('compile_source'),
|
|
123
126
|
};
|
|
124
127
|
}
|
|
125
128
|
newCompileQuerySession(request, sessionInfo, options) {
|
|
@@ -131,6 +134,7 @@ class SessionManager {
|
|
|
131
134
|
state,
|
|
132
135
|
expires,
|
|
133
136
|
sessionId: this.newSessionId(),
|
|
137
|
+
timer: new timing_1.Timer('compile_query'),
|
|
134
138
|
};
|
|
135
139
|
}
|
|
136
140
|
findCompileModelSession(sessionId, sessionInfo) {
|
|
@@ -155,6 +159,10 @@ class SessionManager {
|
|
|
155
159
|
this.findCompileModelSession(options.session_id, sessionInfo);
|
|
156
160
|
this.purgeExpired({ except: options === null || options === void 0 ? void 0 : options.session_id });
|
|
157
161
|
if (session) {
|
|
162
|
+
if (session.waitingTimer) {
|
|
163
|
+
session.timer.contribute([session.waitingTimer.stop()]);
|
|
164
|
+
session.waitingTimer = undefined;
|
|
165
|
+
}
|
|
158
166
|
if (options === null || options === void 0 ? void 0 : options.ttl) {
|
|
159
167
|
session.expires = this.getExpires(options.ttl);
|
|
160
168
|
}
|
|
@@ -165,10 +173,21 @@ class SessionManager {
|
|
|
165
173
|
this.sessions.set(session.sessionId, session);
|
|
166
174
|
}
|
|
167
175
|
const result = Core.statedCompileModel(session.state);
|
|
168
|
-
|
|
176
|
+
session.timer.incorporate(result.timing_info);
|
|
177
|
+
const done = result.model || this.hasErrors(result.logs);
|
|
178
|
+
if (done) {
|
|
169
179
|
this.killSession(session.sessionId);
|
|
170
180
|
}
|
|
171
|
-
|
|
181
|
+
// TODO not really using it as "stop", but more like "current"
|
|
182
|
+
const timingInfo = session.timer.stop();
|
|
183
|
+
if (!done) {
|
|
184
|
+
session.waitingTimer = new timing_1.Timer('session_wait');
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
...result,
|
|
188
|
+
session_id: session.sessionId,
|
|
189
|
+
timing_info: timingInfo,
|
|
190
|
+
};
|
|
172
191
|
}
|
|
173
192
|
findCompileSourceSession(sessionId, sessionInfo) {
|
|
174
193
|
const session = this.findSession(sessionId, sessionInfo);
|
|
@@ -187,6 +206,10 @@ class SessionManager {
|
|
|
187
206
|
this.findCompileSourceSession(options.session_id, sessionInfo);
|
|
188
207
|
this.purgeExpired({ except: options === null || options === void 0 ? void 0 : options.session_id });
|
|
189
208
|
if (session) {
|
|
209
|
+
if (session.waitingTimer) {
|
|
210
|
+
session.timer.contribute([session.waitingTimer.stop()]);
|
|
211
|
+
session.waitingTimer = undefined;
|
|
212
|
+
}
|
|
190
213
|
if (options === null || options === void 0 ? void 0 : options.ttl) {
|
|
191
214
|
session.expires = this.getExpires(options.ttl);
|
|
192
215
|
}
|
|
@@ -197,10 +220,20 @@ class SessionManager {
|
|
|
197
220
|
this.sessions.set(session.sessionId, session);
|
|
198
221
|
}
|
|
199
222
|
const result = Core.statedCompileSource(session.state, request.name);
|
|
200
|
-
|
|
223
|
+
session.timer.incorporate(result.timing_info);
|
|
224
|
+
const done = result.source || this.hasErrors(result.logs);
|
|
225
|
+
if (done) {
|
|
201
226
|
this.killSession(session.sessionId);
|
|
202
227
|
}
|
|
203
|
-
|
|
228
|
+
const timingInfo = session.timer.stop();
|
|
229
|
+
if (!done) {
|
|
230
|
+
session.waitingTimer = new timing_1.Timer('session_wait');
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
...result,
|
|
234
|
+
session_id: session.sessionId,
|
|
235
|
+
timing_info: timingInfo,
|
|
236
|
+
};
|
|
204
237
|
}
|
|
205
238
|
findCompileQuerySession(sessionId, sessionInfo) {
|
|
206
239
|
const session = this.findSession(sessionId, sessionInfo);
|
|
@@ -220,6 +253,10 @@ class SessionManager {
|
|
|
220
253
|
this.findCompileQuerySession(options.session_id, sessionInfo);
|
|
221
254
|
this.purgeExpired({ except: options === null || options === void 0 ? void 0 : options.session_id });
|
|
222
255
|
if (session) {
|
|
256
|
+
if (session.waitingTimer) {
|
|
257
|
+
session.timer.contribute([session.waitingTimer.stop()]);
|
|
258
|
+
session.waitingTimer = undefined;
|
|
259
|
+
}
|
|
223
260
|
if (options === null || options === void 0 ? void 0 : options.ttl) {
|
|
224
261
|
session.expires = this.getExpires(options.ttl);
|
|
225
262
|
}
|
|
@@ -230,10 +267,20 @@ class SessionManager {
|
|
|
230
267
|
this.sessions.set(session.sessionId, session);
|
|
231
268
|
}
|
|
232
269
|
const result = Core.statedCompileQuery(session.state);
|
|
233
|
-
|
|
270
|
+
session.timer.incorporate(result.timing_info);
|
|
271
|
+
const done = result.result || this.hasErrors(result.logs);
|
|
272
|
+
if (done) {
|
|
234
273
|
this.killSession(session.sessionId);
|
|
235
274
|
}
|
|
236
|
-
|
|
275
|
+
const timingInfo = session.timer.stop();
|
|
276
|
+
if (!done) {
|
|
277
|
+
session.waitingTimer = new timing_1.Timer('session_wait');
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
...result,
|
|
281
|
+
session_id: session.sessionId,
|
|
282
|
+
timing_info: timingInfo,
|
|
283
|
+
};
|
|
237
284
|
}
|
|
238
285
|
}
|
|
239
286
|
const SESSION_MANAGER = new SessionManager();
|
|
@@ -15,7 +15,7 @@ const util_1 = require("../functions/util");
|
|
|
15
15
|
* So in this file we are experimenting with various ways to define things.
|
|
16
16
|
* The most general and powerful is to write a DefinitionBlueprint or
|
|
17
17
|
* OverloadedDefinitionBlueprint, naming it with the name of the function
|
|
18
|
-
* you want to add, and then to add that name to the
|
|
18
|
+
* you want to add, and then to add that name to the dialect function list.
|
|
19
19
|
*
|
|
20
20
|
* Experimentally, there is also a function def which creates a
|
|
21
21
|
* DefinitionBlueprint for you. For simple blueprints, you can use the wrapper
|
|
@@ -235,7 +235,7 @@ const hll_accumulate_moving = {
|
|
|
235
235
|
'T': ['string', 'number', 'date', 'timestamp', 'boolean', 'json'],
|
|
236
236
|
},
|
|
237
237
|
impl: {
|
|
238
|
-
|
|
238
|
+
sql: 'APPROX_SET(${value}, 0.0040625)',
|
|
239
239
|
needsWindowOrderBy: true,
|
|
240
240
|
between: { preceding: 'preceding', following: 0 },
|
|
241
241
|
},
|
|
@@ -251,7 +251,7 @@ const hll_accumulate_moving = {
|
|
|
251
251
|
'T': ['string', 'number', 'date', 'timestamp', 'boolean', 'json'],
|
|
252
252
|
},
|
|
253
253
|
impl: {
|
|
254
|
-
|
|
254
|
+
sql: 'APPROX_SET(${value}, 0.0040625)',
|
|
255
255
|
needsWindowOrderBy: true,
|
|
256
256
|
between: { preceding: 'preceding', following: 'following' },
|
|
257
257
|
},
|
|
@@ -265,7 +265,7 @@ const hll_combine_moving = {
|
|
|
265
265
|
},
|
|
266
266
|
returns: { calculation: { sql_native: 'hyperloglog' } },
|
|
267
267
|
impl: {
|
|
268
|
-
|
|
268
|
+
sql: 'MERGE(${value})',
|
|
269
269
|
needsWindowOrderBy: true,
|
|
270
270
|
between: { preceding: 'preceding', following: 0 },
|
|
271
271
|
},
|
|
@@ -284,32 +284,100 @@ const hll_combine_moving = {
|
|
|
284
284
|
},
|
|
285
285
|
},
|
|
286
286
|
};
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
},
|
|
293
|
-
|
|
294
|
-
impl: {
|
|
295
|
-
function: 'CARDINALITY',
|
|
296
|
-
needsWindowOrderBy: true,
|
|
297
|
-
between: { preceding: 'preceding', following: 0 },
|
|
298
|
-
},
|
|
287
|
+
// T-Digest functions for approximate quantile analytics
|
|
288
|
+
const tdigest_agg = {
|
|
289
|
+
default: {
|
|
290
|
+
takes: { 'value': { dimension: 'number' } },
|
|
291
|
+
returns: { measure: { sql_native: 'tdigest' } },
|
|
292
|
+
impl: { function: 'TDIGEST_AGG' },
|
|
293
|
+
isSymmetric: true,
|
|
299
294
|
},
|
|
300
|
-
|
|
295
|
+
with_weight: {
|
|
296
|
+
takes: { 'value': { dimension: 'number' }, 'weight': { dimension: 'number' } },
|
|
297
|
+
returns: { measure: { sql_native: 'tdigest' } },
|
|
298
|
+
impl: { function: 'TDIGEST_AGG' },
|
|
299
|
+
isSymmetric: true,
|
|
300
|
+
},
|
|
301
|
+
with_weight_and_compression: {
|
|
301
302
|
takes: {
|
|
302
|
-
'value': {
|
|
303
|
-
'
|
|
304
|
-
'
|
|
305
|
-
},
|
|
306
|
-
returns: { calculation: 'number' },
|
|
307
|
-
impl: {
|
|
308
|
-
function: 'CARDINALITY',
|
|
309
|
-
needsWindowOrderBy: true,
|
|
310
|
-
between: { preceding: 'preceding', following: 'following' },
|
|
303
|
+
'value': { dimension: 'number' },
|
|
304
|
+
'weight': { dimension: 'number' },
|
|
305
|
+
'compression': { literal: 'number' },
|
|
311
306
|
},
|
|
307
|
+
returns: { measure: { sql_native: 'tdigest' } },
|
|
308
|
+
impl: { function: 'TDIGEST_AGG' },
|
|
309
|
+
isSymmetric: true,
|
|
310
|
+
},
|
|
311
|
+
};
|
|
312
|
+
const merge_tdigest = {
|
|
313
|
+
takes: { 'tdigest_val': { sql_native: 'tdigest' } },
|
|
314
|
+
returns: { measure: { sql_native: 'tdigest' } },
|
|
315
|
+
impl: { function: 'MERGE' },
|
|
316
|
+
isSymmetric: true,
|
|
317
|
+
};
|
|
318
|
+
const value_at_quantile = {
|
|
319
|
+
takes: { 'tdigest_val': { sql_native: 'tdigest' }, 'quantile': 'number' },
|
|
320
|
+
returns: 'number',
|
|
321
|
+
impl: { function: 'VALUE_AT_QUANTILE' },
|
|
322
|
+
};
|
|
323
|
+
const quantile_at_value = {
|
|
324
|
+
takes: { 'tdigest_val': { sql_native: 'tdigest' }, 'value': 'number' },
|
|
325
|
+
returns: 'number',
|
|
326
|
+
impl: { function: 'QUANTILE_AT_VALUE' },
|
|
327
|
+
};
|
|
328
|
+
const scale_tdigest = {
|
|
329
|
+
takes: { 'tdigest_val': { sql_native: 'tdigest' }, 'scale_factor': 'number' },
|
|
330
|
+
returns: { sql_native: 'tdigest' },
|
|
331
|
+
impl: { function: 'SCALE_TDIGEST' },
|
|
332
|
+
};
|
|
333
|
+
const values_at_quantiles = {
|
|
334
|
+
takes: {
|
|
335
|
+
'tdigest_val': { sql_native: 'tdigest' },
|
|
336
|
+
'quantiles': { array: 'number' },
|
|
312
337
|
},
|
|
338
|
+
returns: { array: 'number' },
|
|
339
|
+
impl: { function: 'VALUES_AT_QUANTILES' },
|
|
340
|
+
};
|
|
341
|
+
const trimmed_mean = {
|
|
342
|
+
takes: {
|
|
343
|
+
'tdigest_val': { sql_native: 'tdigest' },
|
|
344
|
+
'lower_quantile': 'number',
|
|
345
|
+
'upper_quantile': 'number',
|
|
346
|
+
},
|
|
347
|
+
returns: 'number',
|
|
348
|
+
impl: { function: 'TRIMMED_MEAN' },
|
|
349
|
+
};
|
|
350
|
+
const destructure_tdigest = {
|
|
351
|
+
takes: { 'tdigest_val': { sql_native: 'tdigest' } },
|
|
352
|
+
returns: {
|
|
353
|
+
record: {
|
|
354
|
+
'centroid_means': { array: 'number' },
|
|
355
|
+
'centroid_weights': { array: 'number' },
|
|
356
|
+
'min_value': 'number',
|
|
357
|
+
'max_value': 'number',
|
|
358
|
+
'sum_value': 'number',
|
|
359
|
+
'count_value': 'number',
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
impl: { function: 'DESTRUCTURE_TDIGEST' },
|
|
363
|
+
};
|
|
364
|
+
const construct_tdigest = {
|
|
365
|
+
takes: {
|
|
366
|
+
'centroid_means': { array: 'number' },
|
|
367
|
+
'centroid_weights': { array: 'number' },
|
|
368
|
+
'min_value': 'number',
|
|
369
|
+
'max_value': 'number',
|
|
370
|
+
'sum_value': 'number',
|
|
371
|
+
'count_value': 'number',
|
|
372
|
+
'compression': 'number',
|
|
373
|
+
},
|
|
374
|
+
returns: { sql_native: 'tdigest' },
|
|
375
|
+
impl: { function: 'CONSTRUCT_TDIGEST' },
|
|
376
|
+
};
|
|
377
|
+
const merge_tdigest_array = {
|
|
378
|
+
takes: { 'tdigest_array': { array: { sql_native: 'tdigest' } } },
|
|
379
|
+
returns: { sql_native: 'tdigest' },
|
|
380
|
+
impl: { function: 'MERGE_TDIGEST' },
|
|
313
381
|
};
|
|
314
382
|
/**
|
|
315
383
|
* This map is for functions which exist in both Presto and Trino.
|
|
@@ -388,9 +456,6 @@ exports.TRINO_DIALECT_FUNCTIONS = {
|
|
|
388
456
|
returns: { dimension: { sql_native: 'hyperloglog' } },
|
|
389
457
|
impl: { sql: 'CAST(${value} AS HyperLogLog)' },
|
|
390
458
|
},
|
|
391
|
-
hll_accumulate_moving,
|
|
392
|
-
hll_combine_moving,
|
|
393
|
-
hll_estimate_moving,
|
|
394
459
|
...(0, util_1.def)('variance', { 'n': 'number' }, { measure: 'number' }),
|
|
395
460
|
// scalar functions
|
|
396
461
|
...(0, util_1.def)('bitwise_and', { 'val1': 'number', 'val2': 'number' }, 'number'),
|
|
@@ -507,38 +572,18 @@ exports.PRESTO_DIALECT_FUNCTIONS = {
|
|
|
507
572
|
impl: { sql: 'APPROX_SET(${value}, 0.0040625)' },
|
|
508
573
|
},
|
|
509
574
|
},
|
|
510
|
-
hll_accumulate_moving
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
between: { preceding: 'preceding', following: 0 },
|
|
524
|
-
},
|
|
525
|
-
},
|
|
526
|
-
following: {
|
|
527
|
-
takes: {
|
|
528
|
-
'value': { dimension: T },
|
|
529
|
-
'preceding': { literal: 'number' },
|
|
530
|
-
'following': { literal: 'number' },
|
|
531
|
-
},
|
|
532
|
-
returns: { calculation: { sql_native: 'hyperloglog' } },
|
|
533
|
-
generic: {
|
|
534
|
-
'T': ['string', 'number', 'date', 'timestamp', 'boolean', 'json'],
|
|
535
|
-
},
|
|
536
|
-
impl: {
|
|
537
|
-
sql: 'APPROX_SET(${value}, 0.0040625)',
|
|
538
|
-
needsWindowOrderBy: true,
|
|
539
|
-
between: { preceding: 'preceding', following: 'following' },
|
|
540
|
-
},
|
|
541
|
-
},
|
|
542
|
-
},
|
|
575
|
+
hll_accumulate_moving,
|
|
576
|
+
hll_combine_moving,
|
|
577
|
+
// T-Digest functions
|
|
578
|
+
tdigest_agg,
|
|
579
|
+
merge_tdigest,
|
|
580
|
+
value_at_quantile,
|
|
581
|
+
quantile_at_value,
|
|
582
|
+
scale_tdigest,
|
|
583
|
+
values_at_quantiles,
|
|
584
|
+
trimmed_mean,
|
|
585
|
+
destructure_tdigest,
|
|
586
|
+
construct_tdigest,
|
|
587
|
+
merge_tdigest_array,
|
|
543
588
|
};
|
|
544
589
|
//# sourceMappingURL=dialect_functions.js.map
|
|
@@ -11,6 +11,8 @@ import type { HasString, HasID } from './parse-utils';
|
|
|
11
11
|
import type { CastType } from '../model';
|
|
12
12
|
import type { AccessModifierLabel, DocumentLocation, DocumentRange, Note } from '../model/malloy_types';
|
|
13
13
|
import { Tag } from '@malloydata/malloy-tag';
|
|
14
|
+
import type * as Malloy from '@malloydata/malloy-interfaces';
|
|
15
|
+
import { Timer } from '../timing';
|
|
14
16
|
declare class ErrorNode extends ast.SourceQueryElement {
|
|
15
17
|
elementType: string;
|
|
16
18
|
}
|
|
@@ -30,7 +32,13 @@ export declare class MalloyToAST extends AbstractParseTreeVisitor<ast.MalloyElem
|
|
|
30
32
|
readonly parseInfo: MalloyParseInfo;
|
|
31
33
|
readonly msgLog: MessageLogger;
|
|
32
34
|
compilerFlags: Tag;
|
|
35
|
+
readonly timer: Timer;
|
|
33
36
|
constructor(parseInfo: MalloyParseInfo, msgLog: MessageLogger, compilerFlags: Tag);
|
|
37
|
+
run(): {
|
|
38
|
+
ast: ast.MalloyElement;
|
|
39
|
+
compilerFlags: Tag;
|
|
40
|
+
timingInfo: Malloy.TimingInfo;
|
|
41
|
+
};
|
|
34
42
|
/**
|
|
35
43
|
* Mostly used to flag a case where the grammar and the type system are
|
|
36
44
|
* no longer in sync. A visitor was written based on a grammar which
|
|
@@ -205,6 +213,7 @@ export declare class MalloyToAST extends AbstractParseTreeVisitor<ast.MalloyElem
|
|
|
205
213
|
visitImportStatement(pcx: parse.ImportStatementContext): ast.ImportStatement;
|
|
206
214
|
visitDebugExpr(pcx: parse.DebugExprContext): ast.ExpressionDef;
|
|
207
215
|
visitSampleStatement(pcx: parse.SampleStatementContext): ast.SampleProperty;
|
|
216
|
+
updateCompilerFlags(tags: ast.ModelAnnotation): void;
|
|
208
217
|
visitDocAnnotations(pcx: parse.DocAnnotationsContext): ast.ModelAnnotation;
|
|
209
218
|
visitIgnoredObjectAnnotations(pcx: parse.IgnoredObjectAnnotationsContext): IgnoredElement;
|
|
210
219
|
visitIgnoredModelAnnotations(pcx: parse.IgnoredModelAnnotationsContext): IgnoredElement;
|
|
@@ -68,6 +68,7 @@ const malloy_types_1 = require("../model/malloy_types");
|
|
|
68
68
|
const malloy_tag_1 = require("@malloydata/malloy-tag");
|
|
69
69
|
const utils_1 = require("./utils");
|
|
70
70
|
const malloy_filter_1 = require("@malloydata/malloy-filter");
|
|
71
|
+
const timing_1 = require("../timing");
|
|
71
72
|
class ErrorNode extends ast.SourceQueryElement {
|
|
72
73
|
constructor() {
|
|
73
74
|
super(...arguments);
|
|
@@ -92,10 +93,22 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
92
93
|
this.parseInfo = parseInfo;
|
|
93
94
|
this.msgLog = msgLog;
|
|
94
95
|
this.compilerFlags = compilerFlags;
|
|
96
|
+
this.timer = new timing_1.Timer('generate_ast');
|
|
97
|
+
const parseCompilerFlagsTimer = new timing_1.Timer('parse_compiler_flags');
|
|
95
98
|
for (const flag of DEFAULT_COMPILER_FLAGS) {
|
|
96
99
|
const withNewTag = malloy_tag_1.Tag.fromTagLine(flag, 0, this.compilerFlags);
|
|
97
100
|
this.compilerFlags = withNewTag.tag;
|
|
98
101
|
}
|
|
102
|
+
this.timer.contribute([parseCompilerFlagsTimer.stop()]);
|
|
103
|
+
}
|
|
104
|
+
run() {
|
|
105
|
+
const ast = this.visit(this.parseInfo.root);
|
|
106
|
+
const compilerFlags = this.compilerFlags;
|
|
107
|
+
return {
|
|
108
|
+
ast,
|
|
109
|
+
compilerFlags,
|
|
110
|
+
timingInfo: this.timer.stop(),
|
|
111
|
+
};
|
|
99
112
|
}
|
|
100
113
|
/**
|
|
101
114
|
* Mostly used to flag a case where the grammar and the type system are
|
|
@@ -1254,6 +1267,11 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
1254
1267
|
const enabled = pcx.sampleSpec().TRUE() !== undefined;
|
|
1255
1268
|
return new ast.SampleProperty({ enable: enabled });
|
|
1256
1269
|
}
|
|
1270
|
+
updateCompilerFlags(tags) {
|
|
1271
|
+
const parseCompilerFlagsTimer = new timing_1.Timer('parse_compiler_flags');
|
|
1272
|
+
this.compilerFlags = tags.getCompilerFlags(this.compilerFlags, this.msgLog);
|
|
1273
|
+
this.timer.contribute([parseCompilerFlagsTimer.stop()]);
|
|
1274
|
+
}
|
|
1257
1275
|
visitDocAnnotations(pcx) {
|
|
1258
1276
|
const allNotes = pcx.DOC_ANNOTATION().map(note => {
|
|
1259
1277
|
return {
|
|
@@ -1262,7 +1280,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
1262
1280
|
};
|
|
1263
1281
|
});
|
|
1264
1282
|
const tags = new ast.ModelAnnotation(allNotes);
|
|
1265
|
-
this.
|
|
1283
|
+
this.updateCompilerFlags(tags);
|
|
1266
1284
|
return tags;
|
|
1267
1285
|
}
|
|
1268
1286
|
visitIgnoredObjectAnnotations(pcx) {
|
|
@@ -4,7 +4,7 @@ import { BaseMessageLogger } from './parse-log';
|
|
|
4
4
|
import type { ZoneData } from './zone';
|
|
5
5
|
import { Zone } from './zone';
|
|
6
6
|
import { ReferenceList } from './reference-list';
|
|
7
|
-
import type { ASTResponse, CompletionsResponse, DataRequestResponse, ProblemResponse, FatalResponse, FinalResponse, HelpContextResponse, MetadataResponse, ModelDataRequest, NeedURLData, TranslateResponse, ModelAnnotationResponse, TablePathResponse } from './translate-response';
|
|
7
|
+
import type { ResponseBase, ASTResponse, CompletionsResponse, DataRequestResponse, ProblemResponse, FatalResponse, FinalResponse, HelpContextResponse, MetadataResponse, ModelDataRequest, NeedURLData, TranslateResponse, ModelAnnotationResponse, TablePathResponse } from './translate-response';
|
|
8
8
|
import { Tag } from '@malloydata/malloy-tag';
|
|
9
9
|
import type { MalloyParseInfo } from './malloy-parse-info';
|
|
10
10
|
import type { EventStream } from '../runtime_types';
|
|
@@ -25,7 +25,7 @@ export type StepResponses = DataRequestResponse | ASTResponse | TranslateRespons
|
|
|
25
25
|
interface TranslationStep {
|
|
26
26
|
step(that: MalloyTranslation): StepResponses;
|
|
27
27
|
}
|
|
28
|
-
interface ParseData extends ProblemResponse, NeedURLData, FinalResponse {
|
|
28
|
+
interface ParseData extends ResponseBase, ProblemResponse, NeedURLData, FinalResponse {
|
|
29
29
|
parse: MalloyParseInfo;
|
|
30
30
|
}
|
|
31
31
|
export type ParseResponse = Partial<ParseData>;
|
|
@@ -73,8 +73,10 @@ const model_annotation_walker_1 = require("./parse-tree-walkers/model-annotation
|
|
|
73
73
|
const find_table_path_walker_1 = require("./parse-tree-walkers/find-table-path-walker");
|
|
74
74
|
const annotation_1 = require("../annotation");
|
|
75
75
|
const run_malloy_parser_1 = require("./run-malloy-parser");
|
|
76
|
+
const timing_1 = require("../timing");
|
|
76
77
|
class ParseStep {
|
|
77
78
|
step(that) {
|
|
79
|
+
const stepTimer = new timing_1.Timer('parse_step');
|
|
78
80
|
if (this.response) {
|
|
79
81
|
return this.response;
|
|
80
82
|
}
|
|
@@ -94,6 +96,7 @@ class ParseStep {
|
|
|
94
96
|
}
|
|
95
97
|
return { urls: [that.sourceURL] };
|
|
96
98
|
}
|
|
99
|
+
const parseModelTimer = new timing_1.Timer('parse_malloy');
|
|
97
100
|
const source = srcEnt.value === '' ? '\n' : srcEnt.value;
|
|
98
101
|
this.sourceInfo = (0, utils_1.getSourceInfo)(source);
|
|
99
102
|
let parse;
|
|
@@ -104,6 +107,7 @@ class ParseStep {
|
|
|
104
107
|
that.root.logError('parse-exception', { message: parseException.message });
|
|
105
108
|
parse = undefined;
|
|
106
109
|
}
|
|
110
|
+
stepTimer.contribute([parseModelTimer.stop()]);
|
|
107
111
|
if (that.root.logger.hasErrors()) {
|
|
108
112
|
this.response = {
|
|
109
113
|
parse,
|
|
@@ -113,7 +117,7 @@ class ParseStep {
|
|
|
113
117
|
else {
|
|
114
118
|
this.response = { parse };
|
|
115
119
|
}
|
|
116
|
-
return this.response;
|
|
120
|
+
return { ...this.response, timingInfo: stepTimer.stop() };
|
|
117
121
|
}
|
|
118
122
|
runParser(source, sourceInfo, that) {
|
|
119
123
|
const parse = (0, run_malloy_parser_1.runMalloyParser)(source, that.sourceURL, sourceInfo, that.root.logger, that.grammarRule);
|
|
@@ -167,7 +171,7 @@ class ImportsAndTablesStep {
|
|
|
167
171
|
if (that.root.logger.hasErrors()) {
|
|
168
172
|
// Since we knew we parsed without errors, this would only be from
|
|
169
173
|
// having a malformed URL on an import reference.
|
|
170
|
-
return
|
|
174
|
+
return { timingInfo: parseReq.timingInfo };
|
|
171
175
|
}
|
|
172
176
|
let allMissing = {};
|
|
173
177
|
const missingTables = that.root.schemaZone.getUndefined();
|
|
@@ -184,10 +188,13 @@ class ImportsAndTablesStep {
|
|
|
184
188
|
}
|
|
185
189
|
const missingImports = ((_a = that.root.importZone.getUndefined()) !== null && _a !== void 0 ? _a : []).filter(url => that.root.pretranslatedModels.get(url) === undefined);
|
|
186
190
|
if (missingImports.length > 0) {
|
|
187
|
-
allMissing = {
|
|
191
|
+
allMissing = {
|
|
192
|
+
...allMissing,
|
|
193
|
+
urls: missingImports,
|
|
194
|
+
};
|
|
188
195
|
}
|
|
189
196
|
if ((0, translate_response_1.isNeedResponse)(allMissing)) {
|
|
190
|
-
return allMissing;
|
|
197
|
+
return { ...allMissing, timingInfo: parseReq.timingInfo };
|
|
191
198
|
}
|
|
192
199
|
for (const child of that.childTranslators.values()) {
|
|
193
200
|
if (that.root.pretranslatedModels.get(child.sourceURL)) {
|
|
@@ -198,7 +205,7 @@ class ImportsAndTablesStep {
|
|
|
198
205
|
return kidNeeds;
|
|
199
206
|
}
|
|
200
207
|
}
|
|
201
|
-
return
|
|
208
|
+
return { timingInfo: parseReq.timingInfo };
|
|
202
209
|
}
|
|
203
210
|
}
|
|
204
211
|
class ASTStep {
|
|
@@ -207,11 +214,13 @@ class ASTStep {
|
|
|
207
214
|
this.walked = false;
|
|
208
215
|
}
|
|
209
216
|
step(that) {
|
|
217
|
+
const stepTimer = new timing_1.Timer('ast_step');
|
|
210
218
|
if (this.response) {
|
|
211
219
|
return this.response;
|
|
212
220
|
}
|
|
213
221
|
const mustResolve = this.importStep.step(that);
|
|
214
|
-
|
|
222
|
+
stepTimer.incorporate(mustResolve === null || mustResolve === void 0 ? void 0 : mustResolve.timingInfo);
|
|
223
|
+
if ((0, translate_response_1.isNeedResponse)(mustResolve)) {
|
|
215
224
|
return mustResolve;
|
|
216
225
|
}
|
|
217
226
|
const parseResponse = that.parseStep.response;
|
|
@@ -224,17 +233,19 @@ class ASTStep {
|
|
|
224
233
|
if (!parse) {
|
|
225
234
|
throw new Error('TRANSLATOR INTERNAL ERROR: Translator parse response had no errors, but also no parser');
|
|
226
235
|
}
|
|
236
|
+
stepTimer.incorporate(parseResponse.timingInfo);
|
|
227
237
|
const secondPass = new malloy_to_ast_1.MalloyToAST(parse, that.root.logger, that.compilerFlags);
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
238
|
+
const { ast: newAST, compilerFlags, timingInfo } = secondPass.run();
|
|
239
|
+
stepTimer.contribute([timingInfo]);
|
|
240
|
+
that.compilerFlags = compilerFlags;
|
|
241
|
+
if (newAST.elementType === 'unimplemented') {
|
|
242
|
+
newAST.logError('untranslated-parse-node', 'INTERNAL COMPILER ERROR: Untranslated parse node');
|
|
232
243
|
}
|
|
233
244
|
if (!this.walked) {
|
|
234
245
|
// The DocumentStatement.needs method has largely replaced the need to walk
|
|
235
246
|
// the AST once it has been translated, this one check remains, though
|
|
236
247
|
// it should probably never be hit
|
|
237
|
-
for (const walkedTo of
|
|
248
|
+
for (const walkedTo of newAST.walk()) {
|
|
238
249
|
if (walkedTo instanceof ast.Unimplemented) {
|
|
239
250
|
walkedTo.logError('untranslated-parse-node', 'INTERNAL COMPILER ERROR: Untranslated parse node');
|
|
240
251
|
}
|
|
@@ -256,13 +267,13 @@ class ASTStep {
|
|
|
256
267
|
return kidNeeds;
|
|
257
268
|
}
|
|
258
269
|
}
|
|
259
|
-
|
|
270
|
+
newAST.setTranslator(that);
|
|
260
271
|
this.response = {
|
|
261
272
|
...that.problemResponse(), // these problems will by definition all be warnings
|
|
262
|
-
ast:
|
|
273
|
+
ast: newAST,
|
|
263
274
|
final: true,
|
|
264
275
|
};
|
|
265
|
-
return this.response;
|
|
276
|
+
return { ...this.response, timingInfo: stepTimer.stop() };
|
|
266
277
|
}
|
|
267
278
|
}
|
|
268
279
|
class MetadataStep {
|
|
@@ -397,6 +408,7 @@ class TranslateStep {
|
|
|
397
408
|
this.importedAnnotations = false;
|
|
398
409
|
}
|
|
399
410
|
step(that, extendingModel) {
|
|
411
|
+
const stepTimer = new timing_1.Timer('translate_step');
|
|
400
412
|
if (this.response) {
|
|
401
413
|
return this.response;
|
|
402
414
|
}
|
|
@@ -411,13 +423,16 @@ class TranslateStep {
|
|
|
411
423
|
}
|
|
412
424
|
// begin with the compiler flags of the model we are extending
|
|
413
425
|
if (extendingModel && !this.importedAnnotations) {
|
|
426
|
+
const parseCompilerFlagsTimer = new timing_1.Timer('parse_compiler_flags');
|
|
414
427
|
const tagParse = (0, annotation_1.annotationToTag)(extendingModel.annotation, {
|
|
415
428
|
prefix: /^##! /,
|
|
416
429
|
});
|
|
430
|
+
stepTimer.contribute([parseCompilerFlagsTimer.stop()]);
|
|
417
431
|
that.compilerFlags = tagParse.tag;
|
|
418
432
|
this.importedAnnotations = true;
|
|
419
433
|
}
|
|
420
434
|
const astResponse = this.astStep.step(that);
|
|
435
|
+
stepTimer.incorporate(astResponse.timingInfo);
|
|
421
436
|
if ((0, translate_response_1.isNeedResponse)(astResponse)) {
|
|
422
437
|
return astResponse;
|
|
423
438
|
}
|
|
@@ -429,15 +444,18 @@ class TranslateStep {
|
|
|
429
444
|
if (astResponse.ast instanceof ast.Document) {
|
|
430
445
|
const doc = astResponse.ast;
|
|
431
446
|
doc.initModelDef(extendingModel);
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
}
|
|
447
|
+
const translateModelTimer = new timing_1.Timer('compile_malloy');
|
|
448
|
+
const docCompile = doc.compile();
|
|
449
|
+
const translateTiming = translateModelTimer.stop();
|
|
450
|
+
stepTimer.contribute([translateTiming]);
|
|
451
|
+
if (docCompile.needs) {
|
|
452
|
+
return {
|
|
453
|
+
...docCompile.needs,
|
|
454
|
+
timingInfo: stepTimer.stop(),
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
that.modelDef = docCompile.modelDef;
|
|
441
459
|
}
|
|
442
460
|
}
|
|
443
461
|
else {
|
|
@@ -463,7 +481,7 @@ class TranslateStep {
|
|
|
463
481
|
final: true,
|
|
464
482
|
};
|
|
465
483
|
}
|
|
466
|
-
return this.response;
|
|
484
|
+
return { ...this.response, timingInfo: stepTimer.stop() };
|
|
467
485
|
}
|
|
468
486
|
}
|
|
469
487
|
class MalloyTranslation {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type * as Malloy from '@malloydata/malloy-interfaces';
|
|
1
2
|
import type { Annotation, ModelDef } from '../model/malloy_types';
|
|
2
3
|
import type { MalloyElement } from './ast';
|
|
3
4
|
import type { LogMessage } from './parse-log';
|
|
@@ -5,6 +6,9 @@ import type { DocumentSymbol } from './parse-tree-walkers/document-symbol-walker
|
|
|
5
6
|
import type { DocumentCompletion } from './parse-tree-walkers/document-completion-walker';
|
|
6
7
|
import type { DocumentHelpContext } from './parse-tree-walkers/document-help-context-walker';
|
|
7
8
|
import type { PathInfo } from './parse-tree-walkers/find-table-path-walker';
|
|
9
|
+
export interface ResponseBase {
|
|
10
|
+
timingInfo?: Malloy.TimingInfo;
|
|
11
|
+
}
|
|
8
12
|
/**
|
|
9
13
|
* The translation interface is essentially a request/response protocol, and
|
|
10
14
|
* this is the list of all the "protocol" messages.
|
|
@@ -34,34 +38,34 @@ export interface NeedCompileSQL {
|
|
|
34
38
|
}
|
|
35
39
|
interface NeededData extends NeedURLData, NeedSchemaData, NeedCompileSQL {
|
|
36
40
|
}
|
|
37
|
-
export type DataRequestResponse = Partial<NeededData>
|
|
41
|
+
export type DataRequestResponse = Partial<NeededData> & ResponseBase;
|
|
38
42
|
export declare function isNeedResponse(dr: DataRequestResponse): dr is NeededData;
|
|
39
43
|
export type ModelDataRequest = NeedCompileSQL | undefined;
|
|
40
|
-
interface ASTData extends ProblemResponse, NeededData, FinalResponse {
|
|
44
|
+
interface ASTData extends ResponseBase, ProblemResponse, NeededData, FinalResponse {
|
|
41
45
|
ast: MalloyElement;
|
|
42
46
|
}
|
|
43
47
|
export type ASTResponse = Partial<ASTData>;
|
|
44
|
-
interface Metadata extends NeededData, ProblemResponse, FinalResponse {
|
|
48
|
+
interface Metadata extends ResponseBase, NeededData, ProblemResponse, FinalResponse {
|
|
45
49
|
symbols: DocumentSymbol[];
|
|
46
50
|
}
|
|
47
51
|
export type MetadataResponse = Partial<Metadata>;
|
|
48
|
-
interface ModelAnnotationData extends NeededData, ProblemResponse, FinalResponse {
|
|
52
|
+
interface ModelAnnotationData extends ResponseBase, NeededData, ProblemResponse, FinalResponse {
|
|
49
53
|
modelAnnotation: Annotation;
|
|
50
54
|
}
|
|
51
55
|
export type ModelAnnotationResponse = Partial<ModelAnnotationData>;
|
|
52
|
-
interface Completions extends NeededData, ProblemResponse, FinalResponse {
|
|
56
|
+
interface Completions extends ResponseBase, NeededData, ProblemResponse, FinalResponse {
|
|
53
57
|
completions: DocumentCompletion[];
|
|
54
58
|
}
|
|
55
59
|
export type CompletionsResponse = Partial<Completions>;
|
|
56
|
-
interface HelpContext extends NeededData, ProblemResponse, FinalResponse {
|
|
60
|
+
interface HelpContext extends ResponseBase, NeededData, ProblemResponse, FinalResponse {
|
|
57
61
|
helpContext: DocumentHelpContext | undefined;
|
|
58
62
|
}
|
|
59
63
|
export type HelpContextResponse = Partial<HelpContext>;
|
|
60
|
-
interface TranslatedResponseData extends NeededData, ProblemResponse, FinalResponse {
|
|
64
|
+
interface TranslatedResponseData extends ResponseBase, NeededData, ProblemResponse, FinalResponse {
|
|
61
65
|
modelDef: ModelDef;
|
|
62
66
|
fromSources: string[];
|
|
63
67
|
}
|
|
64
|
-
interface TablePath extends NeededData, ProblemResponse, FinalResponse {
|
|
68
|
+
interface TablePath extends ResponseBase, NeededData, ProblemResponse, FinalResponse {
|
|
65
69
|
pathInfo: PathInfo[];
|
|
66
70
|
}
|
|
67
71
|
export type TablePathResponse = Partial<TablePath>;
|
package/dist/timing.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type * as Malloy from '@malloydata/malloy-interfaces';
|
|
2
|
+
export declare class Timer {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly startTime: number;
|
|
5
|
+
private endTime;
|
|
6
|
+
private detailedTiming;
|
|
7
|
+
constructor(name: string);
|
|
8
|
+
incorporate(timing: Malloy.TimingInfo | undefined): void;
|
|
9
|
+
contribute(timings: Malloy.TimingInfo[] | undefined): void;
|
|
10
|
+
stop(): Malloy.TimingInfo;
|
|
11
|
+
}
|
package/dist/timing.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.Timer = void 0;
|
|
10
|
+
class Timer {
|
|
11
|
+
constructor(name) {
|
|
12
|
+
this.name = name;
|
|
13
|
+
this.endTime = undefined;
|
|
14
|
+
this.detailedTiming = [];
|
|
15
|
+
this.startTime = performance.now();
|
|
16
|
+
}
|
|
17
|
+
incorporate(timing) {
|
|
18
|
+
this.contribute(timing === null || timing === void 0 ? void 0 : timing.detailed_timing);
|
|
19
|
+
}
|
|
20
|
+
contribute(timings) {
|
|
21
|
+
this.detailedTiming.push(...(timings !== null && timings !== void 0 ? timings : []));
|
|
22
|
+
}
|
|
23
|
+
stop() {
|
|
24
|
+
this.endTime = performance.now();
|
|
25
|
+
return {
|
|
26
|
+
name: this.name,
|
|
27
|
+
duration_ms: this.endTime - this.startTime,
|
|
28
|
+
detailed_timing: [...this.detailedTiming.values()],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.Timer = Timer;
|
|
33
|
+
//# sourceMappingURL=timing.js.map
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const MALLOY_VERSION = "0.0.
|
|
1
|
+
export declare const MALLOY_VERSION = "0.0.297";
|
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.297';
|
|
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.297",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/index.js",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"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"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@malloydata/malloy-filter": "0.0.
|
|
45
|
-
"@malloydata/malloy-interfaces": "0.0.
|
|
46
|
-
"@malloydata/malloy-tag": "0.0.
|
|
44
|
+
"@malloydata/malloy-filter": "0.0.297",
|
|
45
|
+
"@malloydata/malloy-interfaces": "0.0.297",
|
|
46
|
+
"@malloydata/malloy-tag": "0.0.297",
|
|
47
47
|
"antlr4ts": "^0.5.0-alpha.4",
|
|
48
48
|
"assert": "^2.0.0",
|
|
49
49
|
"jaro-winkler": "^0.2.8",
|