@malloydata/malloy 0.0.335 → 0.0.337

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.
Files changed (88) hide show
  1. package/CONTEXT.md +4 -3
  2. package/MALLOY_API.md +129 -0
  3. package/dist/annotation.d.ts +0 -2
  4. package/dist/annotation.js +29 -23
  5. package/dist/api/asynchronous.d.ts +1 -1
  6. package/dist/api/foundation/cache.d.ts +32 -0
  7. package/dist/api/foundation/cache.js +92 -0
  8. package/dist/api/foundation/compile.d.ts +201 -0
  9. package/dist/api/foundation/compile.js +429 -0
  10. package/dist/api/foundation/core.d.ts +493 -0
  11. package/dist/api/foundation/core.js +1247 -0
  12. package/dist/api/foundation/document.d.ts +167 -0
  13. package/dist/api/foundation/document.js +206 -0
  14. package/dist/api/foundation/index.d.ts +10 -0
  15. package/dist/api/foundation/index.js +77 -0
  16. package/dist/api/foundation/readers.d.ts +53 -0
  17. package/dist/api/foundation/readers.js +134 -0
  18. package/dist/api/foundation/result.d.ts +185 -0
  19. package/dist/api/foundation/result.js +704 -0
  20. package/dist/api/foundation/runtime.d.ts +361 -0
  21. package/dist/api/foundation/runtime.js +733 -0
  22. package/dist/api/foundation/types.d.ts +54 -0
  23. package/dist/api/foundation/types.js +7 -0
  24. package/dist/api/foundation/writers.d.ts +42 -0
  25. package/dist/api/foundation/writers.js +230 -0
  26. package/dist/api/util.d.ts +1 -1
  27. package/dist/connection/base_connection.d.ts +5 -0
  28. package/dist/connection/index.d.ts +1 -0
  29. package/dist/connection/index.js +1 -0
  30. package/dist/connection/registry.d.ts +73 -0
  31. package/dist/connection/registry.js +106 -0
  32. package/dist/connection/types.d.ts +5 -15
  33. package/dist/dialect/duckdb/duckdb.js +2 -1
  34. package/dist/dialect/snowflake/snowflake.js +7 -1
  35. package/dist/dialect/trino/trino.js +7 -2
  36. package/dist/index.d.ts +9 -4
  37. package/dist/index.js +37 -26
  38. package/dist/lang/ast/error-factory.js +3 -5
  39. package/dist/lang/ast/source-elements/query-source.js +2 -7
  40. package/dist/lang/ast/source-elements/refined-source.js +11 -1
  41. package/dist/lang/ast/source-elements/sql-source.d.ts +1 -1
  42. package/dist/lang/ast/source-elements/sql-source.js +18 -3
  43. package/dist/lang/ast/sql-elements/sql-string.d.ts +2 -2
  44. package/dist/lang/ast/sql-elements/sql-string.js +18 -1
  45. package/dist/lang/ast/statements/define-source.js +7 -2
  46. package/dist/lang/ast/statements/import-statement.js +53 -21
  47. package/dist/lang/ast/types/document-compile-result.d.ts +1 -0
  48. package/dist/lang/ast/types/malloy-element.d.ts +3 -1
  49. package/dist/lang/ast/types/malloy-element.js +23 -7
  50. package/dist/lang/malloy-to-ast.d.ts +1 -1
  51. package/dist/lang/malloy-to-ast.js +1 -1
  52. package/dist/lang/parse-malloy.d.ts +3 -2
  53. package/dist/lang/parse-malloy.js +14 -25
  54. package/dist/lang/test/test-translator.js +1 -0
  55. package/dist/lang/translate-response.d.ts +1 -0
  56. package/dist/model/constant_expression_compiler.js +6 -7
  57. package/dist/model/index.d.ts +3 -1
  58. package/dist/model/index.js +15 -9
  59. package/dist/model/malloy_types.d.ts +89 -15
  60. package/dist/model/malloy_types.js +12 -0
  61. package/dist/model/persist_utils.d.ts +47 -0
  62. package/dist/model/persist_utils.js +257 -0
  63. package/dist/model/query_model_impl.d.ts +2 -4
  64. package/dist/model/query_model_impl.js +5 -13
  65. package/dist/model/query_node.d.ts +1 -2
  66. package/dist/model/query_node.js +3 -13
  67. package/dist/model/query_query.d.ts +17 -1
  68. package/dist/model/query_query.js +81 -36
  69. package/dist/model/source_def_utils.d.ts +50 -0
  70. package/dist/model/source_def_utils.js +154 -0
  71. package/dist/model/sql_block.d.ts +5 -1
  72. package/dist/model/sql_block.js +29 -4
  73. package/dist/model/sql_compiled.d.ts +29 -0
  74. package/dist/model/sql_compiled.js +102 -0
  75. package/dist/model/stage_writer.d.ts +1 -3
  76. package/dist/model/stage_writer.js +7 -25
  77. package/dist/model/utils.d.ts +20 -1
  78. package/dist/model/utils.js +40 -0
  79. package/dist/run_sql_options.d.ts +0 -1
  80. package/dist/taggable.d.ts +10 -0
  81. package/dist/taggable.js +7 -0
  82. package/dist/version.d.ts +1 -1
  83. package/dist/version.js +1 -1
  84. package/package.json +6 -4
  85. package/dist/malloy.d.ts +0 -1365
  86. package/dist/malloy.js +0 -3421
  87. package/dist/model/materialization/utils.d.ts +0 -3
  88. package/dist/model/materialization/utils.js +0 -41
@@ -0,0 +1,1247 @@
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.PreparedResult = exports.PreparedQuery = exports.PersistSource = exports.Model = exports.ExploreField = exports.QueryField = exports.Query = exports.StringField = exports.UnsupportedField = exports.JSONField = exports.BooleanField = exports.NumberField = exports.TimestampField = exports.DateField = exports.AtomicField = exports.Explore = exports.JoinRelationship = exports.TimestampTimeframe = exports.DateTimeframe = exports.AtomicFieldType = exports.SourceRelationship = void 0;
8
+ const model_1 = require("../../model");
9
+ const utils_1 = require("../../model/utils");
10
+ const dialect_1 = require("../../dialect");
11
+ const persist_utils_1 = require("../../model/persist_utils");
12
+ const source_def_utils_1 = require("../../model/source_def_utils");
13
+ const annotation_1 = require("../../annotation");
14
+ const utils_2 = require("../../lang/utils");
15
+ const reference_list_1 = require("../../lang/reference-list");
16
+ function isSourceComponent(source) {
17
+ return (source.type === 'table' ||
18
+ source.type === 'sql_select' ||
19
+ source.type === 'query_source');
20
+ }
21
+ // =============================================================================
22
+ // Entity - Base class for Explore and Field types
23
+ // =============================================================================
24
+ class Entity {
25
+ constructor(name, parent, source) {
26
+ this._name = name;
27
+ this._parent = parent;
28
+ this._source = source;
29
+ }
30
+ get source() {
31
+ return this._source;
32
+ }
33
+ get name() {
34
+ return this._name;
35
+ }
36
+ get sourceClasses() {
37
+ const sourceClasses = [];
38
+ if (this.source) {
39
+ sourceClasses.push(this.source.name);
40
+ }
41
+ sourceClasses.push(this.name);
42
+ return sourceClasses;
43
+ }
44
+ get fieldPath() {
45
+ const path = [this.name];
46
+ let f = this._parent;
47
+ while (f) {
48
+ path.unshift(f.name);
49
+ f = f._parent;
50
+ }
51
+ return path;
52
+ }
53
+ hasParentExplore() {
54
+ return this._parent !== undefined;
55
+ }
56
+ isExplore() {
57
+ return this instanceof Explore;
58
+ }
59
+ isQuery() {
60
+ return this instanceof QueryField;
61
+ }
62
+ }
63
+ // =============================================================================
64
+ // Enums
65
+ // =============================================================================
66
+ /**
67
+ * The relationship of an `Explore` to its source.
68
+ */
69
+ var SourceRelationship;
70
+ (function (SourceRelationship) {
71
+ /**
72
+ * The `Explore` is nested data within the source's rows.
73
+ */
74
+ SourceRelationship["Nested"] = "nested";
75
+ /**
76
+ * The `Explore` is the base table.
77
+ */
78
+ SourceRelationship["BaseTable"] = "base_table";
79
+ /**
80
+ * The `Explore` is joined to its source
81
+ */
82
+ SourceRelationship["Cross"] = "cross";
83
+ SourceRelationship["One"] = "one";
84
+ SourceRelationship["Many"] = "many";
85
+ // TODO document this
86
+ SourceRelationship["Inline"] = "inline";
87
+ })(SourceRelationship || (exports.SourceRelationship = SourceRelationship = {}));
88
+ var AtomicFieldType;
89
+ (function (AtomicFieldType) {
90
+ AtomicFieldType["String"] = "string";
91
+ AtomicFieldType["Number"] = "number";
92
+ AtomicFieldType["Boolean"] = "boolean";
93
+ AtomicFieldType["Date"] = "date";
94
+ AtomicFieldType["Timestamp"] = "timestamp";
95
+ AtomicFieldType["Timestamptz"] = "timestamptz";
96
+ AtomicFieldType["Json"] = "json";
97
+ AtomicFieldType["NativeUnsupported"] = "sql native";
98
+ AtomicFieldType["Error"] = "error";
99
+ })(AtomicFieldType || (exports.AtomicFieldType = AtomicFieldType = {}));
100
+ var DateTimeframe;
101
+ (function (DateTimeframe) {
102
+ DateTimeframe["Day"] = "day";
103
+ DateTimeframe["Week"] = "week";
104
+ DateTimeframe["Month"] = "month";
105
+ DateTimeframe["Quarter"] = "quarter";
106
+ DateTimeframe["Year"] = "year";
107
+ })(DateTimeframe || (exports.DateTimeframe = DateTimeframe = {}));
108
+ var TimestampTimeframe;
109
+ (function (TimestampTimeframe) {
110
+ TimestampTimeframe["Day"] = "day";
111
+ TimestampTimeframe["Week"] = "week";
112
+ TimestampTimeframe["Month"] = "month";
113
+ TimestampTimeframe["Quarter"] = "quarter";
114
+ TimestampTimeframe["Year"] = "year";
115
+ TimestampTimeframe["Second"] = "second";
116
+ TimestampTimeframe["Hour"] = "hour";
117
+ TimestampTimeframe["Minute"] = "minute";
118
+ })(TimestampTimeframe || (exports.TimestampTimeframe = TimestampTimeframe = {}));
119
+ var JoinRelationship;
120
+ (function (JoinRelationship) {
121
+ JoinRelationship["OneToOne"] = "one_to_one";
122
+ JoinRelationship["OneToMany"] = "one_to_many";
123
+ JoinRelationship["ManyToOne"] = "many_to_one";
124
+ })(JoinRelationship || (exports.JoinRelationship = JoinRelationship = {}));
125
+ // =============================================================================
126
+ // Explore
127
+ // =============================================================================
128
+ class Explore extends Entity {
129
+ constructor(structDef, parentExplore, source) {
130
+ super(structDef.as || structDef.name, parentExplore, source);
131
+ this._structDef = structDef;
132
+ this._parentExplore = parentExplore;
133
+ this.sourceExplore = source;
134
+ }
135
+ get source() {
136
+ return this.sourceExplore;
137
+ }
138
+ isIntrinsic() {
139
+ if ((0, model_1.isAtomicFieldType)(this._structDef.type)) {
140
+ return !('e' in this._structDef);
141
+ }
142
+ return false;
143
+ }
144
+ isExploreField() {
145
+ return false;
146
+ }
147
+ tagParse(spec) {
148
+ return (0, annotation_1.annotationToTag)(this._structDef.annotation, spec);
149
+ }
150
+ getTaglines(prefix) {
151
+ return (0, annotation_1.annotationToTaglines)(this._structDef.annotation, prefix);
152
+ }
153
+ get modelTag() {
154
+ this.parsedModelTag || (this.parsedModelTag = (0, annotation_1.annotationToTag)(this._structDef.modelAnnotation).tag);
155
+ return this.parsedModelTag;
156
+ }
157
+ /**
158
+ * @return The name of the entity.
159
+ */
160
+ get name() {
161
+ return this.structDef.as || this.structDef.name;
162
+ }
163
+ getQueryByName(name) {
164
+ const structRef = this.sourceStructDef;
165
+ if (!structRef) {
166
+ throw new Error(`Cannot get query by name from a struct of type ${this.structDef.type}`);
167
+ }
168
+ const view = structRef.fields.find(f => { var _a; return ((_a = f.as) !== null && _a !== void 0 ? _a : f.name) === name; });
169
+ if (view === undefined) {
170
+ throw new Error(`No such view named \`${name}\``);
171
+ }
172
+ if (view.type !== 'turtle') {
173
+ throw new Error(`\`${name}\` is not a view`);
174
+ }
175
+ const internalQuery = {
176
+ type: 'query',
177
+ structRef,
178
+ pipeline: view.pipeline,
179
+ };
180
+ return new PreparedQuery(internalQuery, this.getSingleExploreModel(), [], name);
181
+ }
182
+ get modelDef() {
183
+ if (!(0, model_1.isSourceDef)(this.structDef)) {
184
+ throw new Error(`Cannot create pseudo model for struct type ${this.structDef.type}`);
185
+ }
186
+ const def = (0, utils_1.mkModelDef)('generated_model');
187
+ def.contents[this.structDef.name] = this.structDef;
188
+ return def;
189
+ }
190
+ getSingleExploreModel() {
191
+ return new Model(this.modelDef, [], []);
192
+ }
193
+ get fieldMap() {
194
+ var _a;
195
+ if (this._fieldMap === undefined) {
196
+ const sourceFields = ((_a = this.source) === null || _a === void 0 ? void 0 : _a.fieldMap) || new Map();
197
+ this._fieldMap = new Map(this.structDef.fields.map(fieldDef => {
198
+ const name = fieldDef.as || fieldDef.name;
199
+ const sourceField = sourceFields.get(fieldDef.name);
200
+ if ((0, model_1.isJoined)(fieldDef)) {
201
+ return [name, new ExploreField(fieldDef, this, sourceField)];
202
+ }
203
+ else if (fieldDef.type === 'turtle') {
204
+ return [name, new QueryField(fieldDef, this, sourceField)];
205
+ }
206
+ else {
207
+ if (fieldDef.type === 'string') {
208
+ return [name, new StringField(fieldDef, this, sourceField)];
209
+ }
210
+ else if (fieldDef.type === 'number') {
211
+ return [name, new NumberField(fieldDef, this, sourceField)];
212
+ }
213
+ else if (fieldDef.type === 'date') {
214
+ // TODO this is a hack
215
+ if (fieldDef.timeframe &&
216
+ ['day_of_month', 'day_of_week', 'day_of_year'].includes(fieldDef.timeframe)) {
217
+ return [
218
+ name,
219
+ new NumberField({ ...fieldDef, type: 'number' }, this, sourceField),
220
+ ];
221
+ }
222
+ return [name, new DateField(fieldDef, this, sourceField)];
223
+ }
224
+ else if (fieldDef.type === 'timestamp') {
225
+ return [name, new TimestampField(fieldDef, this, sourceField)];
226
+ }
227
+ else if (fieldDef.type === 'timestamptz') {
228
+ return [name, new TimestampField(fieldDef, this, sourceField)];
229
+ }
230
+ else if (fieldDef.type === 'boolean') {
231
+ return [name, new BooleanField(fieldDef, this, sourceField)];
232
+ }
233
+ else if (fieldDef.type === 'json') {
234
+ return [name, new JSONField(fieldDef, this, sourceField)];
235
+ }
236
+ else if (fieldDef.type === 'sql native') {
237
+ return [name, new UnsupportedField(fieldDef, this, sourceField)];
238
+ }
239
+ }
240
+ }));
241
+ }
242
+ return this._fieldMap;
243
+ }
244
+ get allFields() {
245
+ return [...this.fieldMap.values()];
246
+ }
247
+ get allFieldsWithOrder() {
248
+ var _a, _b, _c;
249
+ if (!this._allFieldsWithOrder) {
250
+ const orderByFields = [
251
+ ...(((_c = (_b = (_a = this.sourceStructDef) === null || _a === void 0 ? void 0 : _a.resultMetadata) === null || _b === void 0 ? void 0 : _b.orderBy) === null || _c === void 0 ? void 0 : _c.map(f => {
252
+ if (typeof f.field === 'string') {
253
+ const a = {
254
+ field: this.fieldMap.get(f.field),
255
+ dir: f.dir,
256
+ };
257
+ return a;
258
+ }
259
+ throw new Error('Does not support mapping order by from number.');
260
+ })) || []),
261
+ ];
262
+ const orderByFieldSet = new Set(orderByFields.map(f => f.field.name));
263
+ this._allFieldsWithOrder = [
264
+ ...orderByFields,
265
+ ...this.allFields
266
+ .filter(f => !orderByFieldSet.has(f.name))
267
+ .map(field => {
268
+ return {
269
+ field,
270
+ dir: 'asc',
271
+ };
272
+ }),
273
+ ];
274
+ }
275
+ return this._allFieldsWithOrder;
276
+ }
277
+ get intrinsicFields() {
278
+ return [...this.fieldMap.values()].filter(f => f.isIntrinsic());
279
+ }
280
+ get dimensions() {
281
+ return [...this.allFieldsWithOrder].filter(f => f.field.isAtomicField() && f.field.sourceWasDimension());
282
+ }
283
+ getFieldByName(fieldName) {
284
+ const field = this.fieldMap.get(fieldName);
285
+ if (field === undefined) {
286
+ throw new Error(`No such field ${fieldName}.`);
287
+ }
288
+ return field;
289
+ }
290
+ getFieldByNameIfExists(fieldName) {
291
+ return this.fieldMap.get(fieldName);
292
+ }
293
+ get primaryKey() {
294
+ var _a;
295
+ return (_a = this.sourceStructDef) === null || _a === void 0 ? void 0 : _a.primaryKey;
296
+ }
297
+ get parentExplore() {
298
+ return this._parentExplore;
299
+ }
300
+ hasParentExplore() {
301
+ return this instanceof ExploreField;
302
+ }
303
+ get filters() {
304
+ var _a;
305
+ if ((0, model_1.isSourceDef)(this.structDef)) {
306
+ return ((_a = this.structDef.resultMetadata) === null || _a === void 0 ? void 0 : _a.filterList) || [];
307
+ }
308
+ return [];
309
+ }
310
+ get limit() {
311
+ var _a, _b;
312
+ return (_b = (_a = this.sourceStructDef) === null || _a === void 0 ? void 0 : _a.resultMetadata) === null || _b === void 0 ? void 0 : _b.limit;
313
+ }
314
+ get structDef() {
315
+ return this._structDef;
316
+ }
317
+ get queryTimezone() {
318
+ var _a;
319
+ return (_a = this.sourceStructDef) === null || _a === void 0 ? void 0 : _a.queryTimezone;
320
+ }
321
+ get sourceStructDef() {
322
+ if ((0, model_1.isSourceDef)(this.structDef)) {
323
+ return this.structDef;
324
+ }
325
+ }
326
+ toJSON() {
327
+ var _a, _b;
328
+ return {
329
+ _structDef: this._structDef,
330
+ sourceExplore: (_a = this.sourceExplore) === null || _a === void 0 ? void 0 : _a.toJSON(),
331
+ _parentExplore: (_b = this._parentExplore) === null || _b === void 0 ? void 0 : _b.toJSON(),
332
+ };
333
+ }
334
+ static fromJSON(main_explore) {
335
+ const parentExplore = main_explore._parentExplore !== undefined
336
+ ? Explore.fromJSON(main_explore._parentExplore)
337
+ : undefined;
338
+ const sourceExplore = main_explore.sourceExplore !== undefined
339
+ ? Explore.fromJSON(main_explore.sourceExplore)
340
+ : undefined;
341
+ return new Explore(main_explore._structDef, parentExplore, sourceExplore);
342
+ }
343
+ get location() {
344
+ return this.structDef.location;
345
+ }
346
+ collectSourceComponents(structDef) {
347
+ const sources = [];
348
+ if (structDef.type === 'composite') {
349
+ for (const source of structDef.sources) {
350
+ sources.push(...this.collectSourceComponents(source));
351
+ }
352
+ return sources;
353
+ }
354
+ if (isSourceComponent(structDef)) {
355
+ if (structDef.type === 'table') {
356
+ sources.push({
357
+ type: 'table',
358
+ tableName: structDef.tablePath,
359
+ componentID: `${structDef.connection}:${structDef.tablePath}`,
360
+ sourceID: `${structDef.connection}:${structDef.tablePath}`,
361
+ });
362
+ }
363
+ else if (structDef.type === 'sql_select') {
364
+ sources.push({
365
+ type: 'sql',
366
+ selectStatement: structDef.selectStr,
367
+ componentID: `${structDef.connection}:${structDef.selectStr}`,
368
+ sourceID: `${structDef.connection}:${structDef.selectStr}`,
369
+ });
370
+ }
371
+ else if (structDef.type === 'query_source') {
372
+ let sql;
373
+ try {
374
+ const preparedQuery = new PreparedQuery(structDef.query, this.getSingleExploreModel(), []);
375
+ const preparedResult = preparedQuery.getPreparedResult();
376
+ sql = preparedResult.sql;
377
+ }
378
+ catch (error) {
379
+ sql = `-- Could not compile SQL for query ${structDef.query.name || 'unnamed query'}: ${error instanceof Error ? error.message : String(error)}`;
380
+ }
381
+ const componentID = `${structDef.connection}:${sql}`;
382
+ sources.push({
383
+ type: 'sql',
384
+ selectStatement: sql,
385
+ componentID: componentID,
386
+ sourceID: componentID,
387
+ });
388
+ }
389
+ }
390
+ else {
391
+ return [];
392
+ }
393
+ for (const field of structDef.fields) {
394
+ if ((0, model_1.isJoined)(field)) {
395
+ sources.push(...this.collectSourceComponents(field));
396
+ }
397
+ }
398
+ return sources;
399
+ }
400
+ /**
401
+ * THIS IS A HIGHLY EXPERIMENTAL API AND MAY VANISH OR CHANGE WITHOUT NOTICE
402
+ */
403
+ getSourceComponents() {
404
+ const uniqueSources = {};
405
+ if ((0, model_1.isSourceDef)(this.structDef)) {
406
+ const allSources = this.collectSourceComponents(this.structDef);
407
+ for (const source of allSources) {
408
+ if (source.componentID) {
409
+ uniqueSources[source.componentID] = source;
410
+ }
411
+ else if (source.sourceID) {
412
+ uniqueSources[source.sourceID] = source;
413
+ }
414
+ }
415
+ }
416
+ return Object.values(uniqueSources);
417
+ }
418
+ }
419
+ exports.Explore = Explore;
420
+ // =============================================================================
421
+ // AtomicField and subclasses
422
+ // =============================================================================
423
+ class AtomicField extends Entity {
424
+ constructor(fieldTypeDef, parent, source) {
425
+ super(fieldTypeDef.as || fieldTypeDef.name, parent, source);
426
+ this.fieldTypeDef = fieldTypeDef;
427
+ this.parent = parent;
428
+ }
429
+ get type() {
430
+ switch (this.fieldTypeDef.type) {
431
+ case 'string':
432
+ return AtomicFieldType.String;
433
+ case 'boolean':
434
+ return AtomicFieldType.Boolean;
435
+ case 'date':
436
+ return AtomicFieldType.Date;
437
+ case 'timestamp':
438
+ return AtomicFieldType.Timestamp;
439
+ case 'timestamptz':
440
+ return AtomicFieldType.Timestamptz;
441
+ case 'number':
442
+ return AtomicFieldType.Number;
443
+ case 'json':
444
+ return AtomicFieldType.Json;
445
+ case 'sql native':
446
+ return AtomicFieldType.NativeUnsupported;
447
+ case 'error':
448
+ return AtomicFieldType.Error;
449
+ case 'record':
450
+ case 'array':
451
+ throw new Error(`MTOY TODO IMPLEMENT Atomic ${this.fieldTypeDef.type}`);
452
+ default: {
453
+ const x = this.fieldTypeDef;
454
+ throw new Error(`Can't make an atomic field from ${x}`);
455
+ }
456
+ }
457
+ }
458
+ tagParse(spec) {
459
+ return (0, annotation_1.annotationToTag)(this.fieldTypeDef.annotation, spec);
460
+ }
461
+ getTaglines(prefix) {
462
+ return (0, annotation_1.annotationToTaglines)(this.fieldTypeDef.annotation, prefix);
463
+ }
464
+ isIntrinsic() {
465
+ return (0, model_1.fieldIsIntrinsic)(this.fieldTypeDef);
466
+ }
467
+ isQueryField() {
468
+ return false;
469
+ }
470
+ isExploreField() {
471
+ return false;
472
+ }
473
+ isAtomicField() {
474
+ return true;
475
+ }
476
+ isCalculation() {
477
+ return (0, model_1.expressionIsCalculation)(this.fieldTypeDef.expressionType);
478
+ }
479
+ get sourceField() {
480
+ throw new Error();
481
+ }
482
+ get sourceClasses() {
483
+ const sourceField = this.fieldTypeDef.name || this.fieldTypeDef.as;
484
+ return sourceField ? [sourceField] : [];
485
+ }
486
+ get referenceId() {
487
+ var _a;
488
+ return (_a = this.fieldTypeDef.resultMetadata) === null || _a === void 0 ? void 0 : _a.referenceId;
489
+ }
490
+ sourceWasMeasure() {
491
+ var _a;
492
+ return ((_a = this.fieldTypeDef.resultMetadata) === null || _a === void 0 ? void 0 : _a.fieldKind) === 'measure';
493
+ }
494
+ sourceWasMeasureLike() {
495
+ var _a, _b;
496
+ return (((_a = this.fieldTypeDef.resultMetadata) === null || _a === void 0 ? void 0 : _a.fieldKind) === 'measure' ||
497
+ ((_b = this.fieldTypeDef.resultMetadata) === null || _b === void 0 ? void 0 : _b.fieldKind) === 'struct');
498
+ }
499
+ sourceWasDimension() {
500
+ var _a;
501
+ return ((_a = this.fieldTypeDef.resultMetadata) === null || _a === void 0 ? void 0 : _a.fieldKind) === 'dimension';
502
+ }
503
+ hasParentExplore() {
504
+ return true;
505
+ }
506
+ isString() {
507
+ return this instanceof StringField;
508
+ }
509
+ isNumber() {
510
+ return this instanceof NumberField;
511
+ }
512
+ isDate() {
513
+ return this instanceof DateField;
514
+ }
515
+ isBoolean() {
516
+ return this instanceof BooleanField;
517
+ }
518
+ isJSON() {
519
+ return this instanceof JSONField;
520
+ }
521
+ isTimestamp() {
522
+ return this instanceof TimestampField;
523
+ }
524
+ isUnsupported() {
525
+ return this instanceof UnsupportedField;
526
+ }
527
+ get parentExplore() {
528
+ return this.parent;
529
+ }
530
+ get expression() {
531
+ const dot = '.';
532
+ const resultMetadata = this.fieldTypeDef.resultMetadata;
533
+ return ((resultMetadata === null || resultMetadata === void 0 ? void 0 : resultMetadata.sourceExpression) ||
534
+ ((resultMetadata === null || resultMetadata === void 0 ? void 0 : resultMetadata.sourceField.includes(dot))
535
+ ? resultMetadata === null || resultMetadata === void 0 ? void 0 : resultMetadata.sourceField
536
+ : this.name));
537
+ }
538
+ get location() {
539
+ return this.fieldTypeDef.location;
540
+ }
541
+ }
542
+ exports.AtomicField = AtomicField;
543
+ class DateField extends AtomicField {
544
+ constructor(fieldDateDef, parent, source) {
545
+ super(fieldDateDef, parent, source);
546
+ this.fieldDateDef = fieldDateDef;
547
+ }
548
+ get timeframe() {
549
+ if (this.fieldDateDef.timeframe === undefined) {
550
+ return undefined;
551
+ }
552
+ switch (this.fieldDateDef.timeframe) {
553
+ case 'day':
554
+ return DateTimeframe.Day;
555
+ case 'week':
556
+ return DateTimeframe.Week;
557
+ case 'month':
558
+ return DateTimeframe.Month;
559
+ case 'quarter':
560
+ return DateTimeframe.Quarter;
561
+ case 'year':
562
+ return DateTimeframe.Year;
563
+ }
564
+ }
565
+ }
566
+ exports.DateField = DateField;
567
+ class TimestampField extends AtomicField {
568
+ constructor(fieldTimestampDef, parent, source) {
569
+ super(fieldTimestampDef, parent, source);
570
+ this.fieldTimestampDef = fieldTimestampDef;
571
+ }
572
+ get timeframe() {
573
+ if (this.fieldTimestampDef.timeframe === undefined) {
574
+ return undefined;
575
+ }
576
+ switch (this.fieldTimestampDef.timeframe) {
577
+ case 'day':
578
+ return TimestampTimeframe.Day;
579
+ case 'week':
580
+ return TimestampTimeframe.Week;
581
+ case 'month':
582
+ return TimestampTimeframe.Month;
583
+ case 'quarter':
584
+ return TimestampTimeframe.Quarter;
585
+ case 'year':
586
+ return TimestampTimeframe.Year;
587
+ case 'second':
588
+ return TimestampTimeframe.Second;
589
+ case 'hour':
590
+ return TimestampTimeframe.Hour;
591
+ case 'minute':
592
+ return TimestampTimeframe.Minute;
593
+ }
594
+ }
595
+ }
596
+ exports.TimestampField = TimestampField;
597
+ class NumberField extends AtomicField {
598
+ constructor(fieldNumberDef, parent, source) {
599
+ super(fieldNumberDef, parent, source);
600
+ this.fieldNumberDef = fieldNumberDef;
601
+ }
602
+ }
603
+ exports.NumberField = NumberField;
604
+ class BooleanField extends AtomicField {
605
+ constructor(fieldBooleanDef, parent, source) {
606
+ super(fieldBooleanDef, parent, source);
607
+ this.fieldBooleanDef = fieldBooleanDef;
608
+ }
609
+ }
610
+ exports.BooleanField = BooleanField;
611
+ class JSONField extends AtomicField {
612
+ constructor(fieldJSONDef, parent, source) {
613
+ super(fieldJSONDef, parent, source);
614
+ this.fieldJSONDef = fieldJSONDef;
615
+ }
616
+ }
617
+ exports.JSONField = JSONField;
618
+ class UnsupportedField extends AtomicField {
619
+ constructor(fieldUnsupportedDef, parent, source) {
620
+ super(fieldUnsupportedDef, parent, source);
621
+ this.fieldUnsupportedDef = fieldUnsupportedDef;
622
+ }
623
+ get rawType() {
624
+ return this.fieldUnsupportedDef.rawType;
625
+ }
626
+ }
627
+ exports.UnsupportedField = UnsupportedField;
628
+ class StringField extends AtomicField {
629
+ constructor(fieldStringDef, parent, source) {
630
+ super(fieldStringDef, parent, source);
631
+ this.fieldStringDef = fieldStringDef;
632
+ }
633
+ }
634
+ exports.StringField = StringField;
635
+ // =============================================================================
636
+ // Query and QueryField
637
+ // =============================================================================
638
+ class Query extends Entity {
639
+ constructor(turtleDef, parent, source) {
640
+ super(turtleDef.as || turtleDef.name, parent, source);
641
+ this.turtleDef = turtleDef;
642
+ }
643
+ get source() {
644
+ return this.sourceQuery;
645
+ }
646
+ isIntrinsic() {
647
+ return false;
648
+ }
649
+ get location() {
650
+ return this.turtleDef.location;
651
+ }
652
+ }
653
+ exports.Query = Query;
654
+ class QueryField extends Query {
655
+ constructor(turtleDef, parent, source) {
656
+ super(turtleDef, parent, source);
657
+ this.parent = parent;
658
+ }
659
+ tagParse(spec) {
660
+ return (0, annotation_1.annotationToTag)(this.turtleDef.annotation, spec);
661
+ }
662
+ getTaglines(prefix) {
663
+ return (0, annotation_1.annotationToTaglines)(this.turtleDef.annotation, prefix);
664
+ }
665
+ isQueryField() {
666
+ return true;
667
+ }
668
+ isExploreField() {
669
+ return false;
670
+ }
671
+ isAtomicField() {
672
+ return false;
673
+ }
674
+ get sourceClasses() {
675
+ const sourceField = this.turtleDef.name || this.turtleDef.as;
676
+ return sourceField ? [sourceField] : [];
677
+ }
678
+ hasParentExplore() {
679
+ return true;
680
+ }
681
+ get parentExplore() {
682
+ return this.parent;
683
+ }
684
+ get expression() {
685
+ return this.name;
686
+ }
687
+ }
688
+ exports.QueryField = QueryField;
689
+ // =============================================================================
690
+ // ExploreField
691
+ // =============================================================================
692
+ class ExploreField extends Explore {
693
+ constructor(structDef, parentExplore, source) {
694
+ super(structDef, parentExplore, source);
695
+ this._parentExplore = parentExplore;
696
+ }
697
+ get joinRelationship() {
698
+ if ((0, model_1.isJoined)(this.structDef)) {
699
+ switch (this.structDef.join) {
700
+ case 'one':
701
+ return JoinRelationship.OneToOne;
702
+ case 'many':
703
+ case 'cross':
704
+ return JoinRelationship.ManyToOne;
705
+ }
706
+ }
707
+ throw new Error('A source field must have a join relationship.');
708
+ }
709
+ get isRecord() {
710
+ return this.joinRelationship === JoinRelationship.OneToOne;
711
+ }
712
+ get isArray() {
713
+ return this.joinRelationship !== JoinRelationship.OneToOne;
714
+ }
715
+ tagParse(spec) {
716
+ return (0, annotation_1.annotationToTag)(this._structDef.annotation, spec);
717
+ }
718
+ isQueryField() {
719
+ return false;
720
+ }
721
+ isExploreField() {
722
+ return true;
723
+ }
724
+ isAtomicField() {
725
+ return false;
726
+ }
727
+ get parentExplore() {
728
+ return this._parentExplore;
729
+ }
730
+ get sourceClasses() {
731
+ const sourceField = this.structDef.name || this.structDef.as;
732
+ return sourceField ? [sourceField] : [];
733
+ }
734
+ get queryTimezone() {
735
+ if ((0, model_1.isRecordOrRepeatedRecord)(this._structDef)) {
736
+ return this._structDef.queryTimezone;
737
+ }
738
+ return super.queryTimezone;
739
+ }
740
+ }
741
+ exports.ExploreField = ExploreField;
742
+ // =============================================================================
743
+ // Model
744
+ // =============================================================================
745
+ class Model {
746
+ constructor(modelDef, problems, fromSources, existingQueryModel) {
747
+ var _a, _b;
748
+ this.modelDef = modelDef;
749
+ this.problems = problems;
750
+ this.fromSources = fromSources;
751
+ this.references = new reference_list_1.ReferenceList((_a = fromSources[0]) !== null && _a !== void 0 ? _a : '', (_b = modelDef.references) !== null && _b !== void 0 ? _b : []);
752
+ this._queryModel = existingQueryModel;
753
+ }
754
+ get queryModel() {
755
+ if (!this._queryModel) {
756
+ this._queryModel = new model_1.QueryModel(this.modelDef);
757
+ }
758
+ return this._queryModel;
759
+ }
760
+ /**
761
+ * Returns the cached QueryModel if it exists, without creating one.
762
+ * Used internally to share QueryModel between Model instances when
763
+ * the model wasn't modified (only queries were added).
764
+ */
765
+ getExistingQueryModel() {
766
+ return this._queryModel;
767
+ }
768
+ tagParse(spec) {
769
+ return (0, annotation_1.annotationToTag)(this.modelDef.annotation, spec);
770
+ }
771
+ getTaglines(prefix) {
772
+ return (0, annotation_1.annotationToTaglines)(this.modelDef.annotation, prefix);
773
+ }
774
+ /**
775
+ * Retrieve a document reference for the token at the given position within
776
+ * the document that produced this model.
777
+ *
778
+ * @param position A position within the document.
779
+ * @return A `DocumentReference` at that position if one exists.
780
+ */
781
+ getReference(position) {
782
+ return this.references.find(position);
783
+ }
784
+ /**
785
+ * Retrieve an import for the token at the given position within
786
+ * the document that produced this model.
787
+ *
788
+ * @param position A position within the document.
789
+ * @return An `ImportLocation` at that position if one exists.
790
+ */
791
+ getImport(position) {
792
+ var _a;
793
+ return (_a = this.modelDef.imports) === null || _a === void 0 ? void 0 : _a.find(i => (0, utils_2.locationContainsPosition)(i.location, position));
794
+ }
795
+ /**
796
+ * Retrieve a prepared query by the name of a query at the top level of the model.
797
+ *
798
+ * @param queryName Name of the query to retrieve.
799
+ * @return A prepared query.
800
+ */
801
+ getPreparedQueryByName(queryName) {
802
+ const query = this.modelDef.contents[queryName];
803
+ if ((query === null || query === void 0 ? void 0 : query.type) === 'query') {
804
+ return new PreparedQuery(query, this, this.problems, queryName);
805
+ }
806
+ throw new Error('Given query name does not refer to a named query.');
807
+ }
808
+ /**
809
+ * Retrieve a prepared query by the index of an unnamed query at the top level of a model.
810
+ *
811
+ * @param index The index of the query to retrieve.
812
+ * @return A prepared query.
813
+ */
814
+ getPreparedQueryByIndex(index) {
815
+ if (index < 0) {
816
+ throw new Error(`Invalid index ${index}.`);
817
+ }
818
+ else if (index >= this.modelDef.queryList.length) {
819
+ throw new Error(`Query index ${index} is out of bounds.`);
820
+ }
821
+ return new PreparedQuery(this.modelDef.queryList[index], this, this.problems);
822
+ }
823
+ /**
824
+ * Retrieve a prepared query for the final unnamed query at the top level of a model.
825
+ *
826
+ * @return A prepared query.
827
+ */
828
+ get preparedQuery() {
829
+ return this.getPreparedQuery();
830
+ }
831
+ /**
832
+ * Retrieve a prepared query for the final unnamed query at the top level of a model.
833
+ *
834
+ * @return A prepared query.
835
+ */
836
+ getPreparedQuery() {
837
+ if (this.modelDef.queryList.length === 0) {
838
+ throw new Error('Model has no queries.');
839
+ }
840
+ return new PreparedQuery(this.modelDef.queryList[this.modelDef.queryList.length - 1], this, this.problems);
841
+ }
842
+ /**
843
+ * Retrieve an `Explore` from the model by name.
844
+ *
845
+ * @param name The name of the `Explore` to retrieve.
846
+ * @return An `Explore`.
847
+ */
848
+ getExploreByName(name) {
849
+ const struct = this.modelDef.contents[name];
850
+ if (struct && (0, model_1.isSourceDef)(struct)) {
851
+ return new Explore(struct);
852
+ }
853
+ throw new Error("'name' is not an explore");
854
+ }
855
+ /**
856
+ * Get an array of `Explore`s contained in the model.
857
+ *
858
+ * @return An array of `Explore`s contained in the model.
859
+ */
860
+ get explores() {
861
+ return Object.values(this.modelDef.contents)
862
+ .filter(model_1.isSourceDef)
863
+ .map(structDef => new Explore(structDef));
864
+ }
865
+ /**
866
+ * Get an array of `NamedQueryDef`s contained in the model.
867
+ *
868
+ * @return An array of `NamedQueryDef`s contained in the model.
869
+ */
870
+ get namedQueries() {
871
+ const isNamedQueryDef = (object) => object.type === 'query';
872
+ return Object.values(this.modelDef.contents).filter(isNamedQueryDef);
873
+ }
874
+ get exportedExplores() {
875
+ return this.explores.filter(explore => this.modelDef.exports.includes(explore.name));
876
+ }
877
+ get _modelDef() {
878
+ return this.modelDef;
879
+ }
880
+ /**
881
+ * Get the build plan for all #@ persist sources.
882
+ *
883
+ * Walks through ALL queries and sources in the model, finding any persistent
884
+ * dependencies they reference (including hidden dependencies from imports).
885
+ *
886
+ * Returns a BuildPlan containing:
887
+ * - `graphs`: Build graphs for root sources only (minimal build set)
888
+ * - `sources`: Map from sourceId to PersistSource (all persist sources)
889
+ *
890
+ * The minimal build set contains only "root" sources - those not depended
891
+ * on by any other persist source. Each root includes its transitive
892
+ * dependencies in the dependsOn field, preserving the tree structure
893
+ * for parallel building.
894
+ *
895
+ * @return BuildPlan with graphs and sources map
896
+ */
897
+ getBuildPlan() {
898
+ // Require experimental.persistence compiler flag
899
+ const modelTag = this.tagParse({ prefix: /^##! / }).tag;
900
+ if (!modelTag.has('experimental', 'persistence')) {
901
+ throw new Error('Model must have ##! experimental.persistence to use getBuildPlan()');
902
+ }
903
+ const allDeps = [];
904
+ // Walk all objects in the model to find persistent dependencies
905
+ for (const obj of Object.values(this.modelDef.contents)) {
906
+ if (obj.type === 'query' || (0, model_1.isSourceDef)(obj)) {
907
+ allDeps.push(...(0, persist_utils_1.findPersistentDependencies)(obj, this.modelDef));
908
+ }
909
+ }
910
+ // Also walk queryList (unnamed queries)
911
+ for (const query of this.modelDef.queryList) {
912
+ allDeps.push(...(0, persist_utils_1.findPersistentDependencies)(query, this.modelDef));
913
+ }
914
+ if (allDeps.length === 0) {
915
+ return { graphs: [], sources: {} };
916
+ }
917
+ // Find the minimal set of root graphs
918
+ const rootNodes = (0, persist_utils_1.minimalBuildGraph)(allDeps);
919
+ // Build the sources map from all persistent sourceIDs encountered
920
+ const sourcesMap = {};
921
+ const collectSources = (nodes) => {
922
+ for (const node of nodes) {
923
+ if (!(node.sourceID in sourcesMap)) {
924
+ const sourceDef = (0, source_def_utils_1.resolveSourceID)(this.modelDef, node.sourceID);
925
+ if (sourceDef) {
926
+ sourcesMap[node.sourceID] = new PersistSource(new Explore(sourceDef), this);
927
+ }
928
+ }
929
+ collectSources(node.dependsOn);
930
+ }
931
+ };
932
+ collectSources(rootNodes);
933
+ // Group root nodes by connection
934
+ const graphsByConnection = new Map();
935
+ for (const node of rootNodes) {
936
+ const persistSource = sourcesMap[node.sourceID];
937
+ if (!persistSource)
938
+ continue;
939
+ const connName = persistSource.connectionName;
940
+ if (!graphsByConnection.has(connName)) {
941
+ graphsByConnection.set(connName, []);
942
+ }
943
+ graphsByConnection.get(connName).push(node);
944
+ }
945
+ // Convert to BuildGraph array
946
+ const graphs = [];
947
+ for (const [connectionName, nodes] of graphsByConnection) {
948
+ graphs.push({ connectionName, nodes: [nodes] });
949
+ }
950
+ return { graphs, sources: sourcesMap };
951
+ }
952
+ }
953
+ exports.Model = Model;
954
+ // =============================================================================
955
+ // PersistSource
956
+ // =============================================================================
957
+ /**
958
+ * A wrapper around a source that has #@ persist annotation.
959
+ *
960
+ * Only sources backed by queries can be persisted:
961
+ * - `query_source`: `source: x is y -> {...}`
962
+ * - `sql_select`: `source: x is conn.sql("...")`
963
+ *
964
+ * Provides access to source identity, SQL generation, and metadata needed
965
+ * for building and caching source results.
966
+ */
967
+ class PersistSource {
968
+ constructor(explore, model) {
969
+ this.explore = explore;
970
+ this.model = model;
971
+ const sd = explore.structDef;
972
+ if (!(0, model_1.isSourceDef)(sd)) {
973
+ throw new Error('Cannot create PersistSource from non-source type');
974
+ }
975
+ if (!(0, model_1.isPersistableSourceDef)(sd)) {
976
+ throw new Error(`Cannot persist source '${explore.name}' of type '${sd.type}'. ` +
977
+ 'Only query_source and sql_select sources can be persisted.');
978
+ }
979
+ this.persistableDef = sd;
980
+ }
981
+ /**
982
+ * The name of this source.
983
+ */
984
+ get name() {
985
+ return this.explore.name;
986
+ }
987
+ /**
988
+ * The stable identity of this source: "sourceName@modelURL".
989
+ * Used as lookup key during compilation and in build graphs.
990
+ */
991
+ get sourceID() {
992
+ const id = this.persistableDef.sourceID;
993
+ if (!id) {
994
+ throw new Error(`PersistSource '${this.name}' has no sourceID. ` +
995
+ 'This should not happen - sourceID is set at translation time.');
996
+ }
997
+ return id;
998
+ }
999
+ /**
1000
+ * The underlying Explore.
1001
+ */
1002
+ get _explore() {
1003
+ return this.explore;
1004
+ }
1005
+ /**
1006
+ * The annotation on this source.
1007
+ */
1008
+ get annotation() {
1009
+ return this.persistableDef.annotation;
1010
+ }
1011
+ /**
1012
+ * Parse the source's tags.
1013
+ */
1014
+ tagParse(spec) {
1015
+ return this.explore.tagParse(spec);
1016
+ }
1017
+ /**
1018
+ * Get annotation taglines matching an optional prefix.
1019
+ */
1020
+ getTaglines(prefix) {
1021
+ return this.explore.getTaglines(prefix);
1022
+ }
1023
+ /**
1024
+ * The connection name for this source.
1025
+ */
1026
+ get connectionName() {
1027
+ return this.persistableDef.connection;
1028
+ }
1029
+ /**
1030
+ * The dialect name for this source.
1031
+ */
1032
+ get dialectName() {
1033
+ return this.persistableDef.dialect;
1034
+ }
1035
+ /**
1036
+ * The dialect for this source.
1037
+ */
1038
+ get dialect() {
1039
+ return (0, dialect_1.getDialect)(this.dialectName);
1040
+ }
1041
+ /**
1042
+ * Compute the BuildID for this source.
1043
+ *
1044
+ * BuildID is a hash of the connection config and SQL content.
1045
+ * Different connection configs or SQL changes produce different BuildIDs.
1046
+ *
1047
+ * @param connectionDigest - Digest from connection.getDigest()
1048
+ * @param sql - The SQL for this source (from getSQL())
1049
+ * @return The BuildID for manifest lookup
1050
+ */
1051
+ makeBuildId(connectionDigest, sql) {
1052
+ return (0, source_def_utils_1.mkBuildID)(connectionDigest, sql);
1053
+ }
1054
+ /**
1055
+ * Get the SQL for this persist source.
1056
+ *
1057
+ * For sql_select sources, returns the SQL string (with segment expansion).
1058
+ * For query_source sources, compiles the inner query to SQL.
1059
+ *
1060
+ * @param options - Compile options including buildManifest for persistence.
1061
+ * @return The SQL string for this source.
1062
+ */
1063
+ getSQL(options) {
1064
+ const sd = this.persistableDef;
1065
+ const queryModel = this.model.queryModel;
1066
+ if (sd.type === 'sql_select') {
1067
+ return (0, model_1.getCompiledSQL)(sd, options !== null && options !== void 0 ? options : {}, path => this.dialect.quoteTablePath(path), (query, opts) => queryModel.compileQuery(query, opts).sql);
1068
+ }
1069
+ else {
1070
+ const compiled = queryModel.compileQuery(sd.query, options);
1071
+ return compiled.sql;
1072
+ }
1073
+ }
1074
+ /**
1075
+ * Get the underlying persistable source definition.
1076
+ */
1077
+ get _sourceDef() {
1078
+ return this.persistableDef;
1079
+ }
1080
+ /**
1081
+ * Get the Model this source belongs to.
1082
+ */
1083
+ get _model() {
1084
+ return this.model;
1085
+ }
1086
+ }
1087
+ exports.PersistSource = PersistSource;
1088
+ // =============================================================================
1089
+ // PreparedQuery
1090
+ // =============================================================================
1091
+ class PreparedQuery {
1092
+ constructor(query, _model, problems, name) {
1093
+ this._model = _model;
1094
+ this.problems = problems;
1095
+ this.name = name;
1096
+ this._query = query;
1097
+ }
1098
+ get _modelDef() {
1099
+ return this._model._modelDef;
1100
+ }
1101
+ tagParse(spec) {
1102
+ return (0, annotation_1.annotationToTag)(this._query.annotation, spec);
1103
+ }
1104
+ getTaglines(prefix) {
1105
+ return (0, annotation_1.annotationToTaglines)(this._query.annotation, prefix);
1106
+ }
1107
+ /**
1108
+ * Generate the SQL for this query.
1109
+ *
1110
+ * @return A fully-prepared query (which contains the generated SQL).
1111
+ */
1112
+ get preparedResult() {
1113
+ return this.getPreparedResult();
1114
+ }
1115
+ /**
1116
+ * Generate the SQL for this query.
1117
+ *
1118
+ * @return A fully-prepared query (which contains the generated SQL).
1119
+ * @param options.eventStream An event stream to use when compiling the SQL
1120
+ */
1121
+ getPreparedResult(options) {
1122
+ const queryModel = this._model.queryModel;
1123
+ const translatedQuery = queryModel.compileQuery(this._query, options);
1124
+ return new PreparedResult({
1125
+ ...translatedQuery,
1126
+ queryName: this.name || translatedQuery.queryName,
1127
+ }, this._modelDef);
1128
+ }
1129
+ get dialect() {
1130
+ const sourceRef = this._query.structRef;
1131
+ const source = typeof sourceRef === 'string'
1132
+ ? this._modelDef.contents[sourceRef]
1133
+ : sourceRef;
1134
+ if (!(0, model_1.isSourceDef)(source)) {
1135
+ throw new Error('Invalid source for query');
1136
+ }
1137
+ return source.dialect;
1138
+ }
1139
+ /**
1140
+ * Get the flattened version of a query -- one that does not have a `pipeHead`.
1141
+ * @deprecated Because queries can no longer have `pipeHead`s.
1142
+ */
1143
+ getFlattenedQuery(_defaultName) {
1144
+ return this;
1145
+ }
1146
+ /**
1147
+ * Get the Model this query belongs to.
1148
+ */
1149
+ get model() {
1150
+ return this._model;
1151
+ }
1152
+ }
1153
+ exports.PreparedQuery = PreparedQuery;
1154
+ // =============================================================================
1155
+ // PreparedResult
1156
+ // =============================================================================
1157
+ class PreparedResult {
1158
+ constructor(query, modelDef) {
1159
+ this.modelDef = modelDef;
1160
+ this.inner = query;
1161
+ }
1162
+ static fromJson({ query, modelDef, }) {
1163
+ if (!query || !modelDef) {
1164
+ throw new Error('Missing required properties in JSON data');
1165
+ }
1166
+ return new PreparedResult(query, modelDef);
1167
+ }
1168
+ tagParse(spec) {
1169
+ return (0, annotation_1.annotationToTag)(this.inner.annotation, spec);
1170
+ }
1171
+ getTaglines(prefix) {
1172
+ return (0, annotation_1.annotationToTaglines)(this.inner.annotation, prefix);
1173
+ }
1174
+ get annotation() {
1175
+ return this.inner.annotation;
1176
+ }
1177
+ get modelAnnotation() {
1178
+ return this.modelDef.annotation;
1179
+ }
1180
+ get modelTag() {
1181
+ return (0, annotation_1.annotationToTag)(this.modelDef.annotation).tag;
1182
+ }
1183
+ /**
1184
+ * @return The name of the connection this query should be run against.
1185
+ */
1186
+ get connectionName() {
1187
+ return this.inner.connectionName;
1188
+ }
1189
+ get _rawQuery() {
1190
+ return this.inner;
1191
+ }
1192
+ get _modelDef() {
1193
+ return this.modelDef;
1194
+ }
1195
+ /**
1196
+ * @return The SQL that should be run against the SQL runner
1197
+ * with the connection name `this.getConnectionName()`.
1198
+ */
1199
+ get sql() {
1200
+ return this.inner.sql;
1201
+ }
1202
+ /**
1203
+ * @return The `Explore` representing the data that will be returned by running this query.
1204
+ */
1205
+ get resultExplore() {
1206
+ if (this.inner.structs.length === 0) {
1207
+ throw new Error('Malformed query result.');
1208
+ }
1209
+ const explore = this.inner.structs[this.inner.structs.length - 1];
1210
+ const namedExplore = {
1211
+ ...explore,
1212
+ annotation: this.inner.annotation,
1213
+ name: this.inner.queryName || explore.name,
1214
+ };
1215
+ try {
1216
+ return new Explore(namedExplore, this.sourceExplore);
1217
+ }
1218
+ catch (error) {
1219
+ return new Explore(namedExplore);
1220
+ }
1221
+ }
1222
+ get sourceExplore() {
1223
+ const name = this.inner.sourceExplore;
1224
+ const explore = this.modelDef.contents[name];
1225
+ if (explore && (0, model_1.isSourceDef)(explore)) {
1226
+ return new Explore(explore);
1227
+ }
1228
+ }
1229
+ get _sourceExploreName() {
1230
+ return this.inner.sourceExplore;
1231
+ }
1232
+ get _sourceArguments() {
1233
+ return this.inner.sourceArguments;
1234
+ }
1235
+ get _sourceFilters() {
1236
+ return this.inner.sourceFilters || [];
1237
+ }
1238
+ /**
1239
+ * @return Whether this result has a schema. DDL statements (INSTALL, LOAD,
1240
+ * CREATE SECRET, etc.) do not return a schema.
1241
+ */
1242
+ get hasSchema() {
1243
+ return this.inner.structs.length > 0;
1244
+ }
1245
+ }
1246
+ exports.PreparedResult = PreparedResult;
1247
+ //# sourceMappingURL=core.js.map