@malloydata/malloy 0.0.421 → 0.0.423

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 (70) hide show
  1. package/README.md +3 -3
  2. package/dist/api/foundation/core.js +7 -2
  3. package/dist/dialect/databricks/databricks.js +9 -2
  4. package/dist/dialect/mysql/mysql.js +9 -2
  5. package/dist/dialect/postgres/postgres.js +26 -0
  6. package/dist/dialect/snowflake/snowflake.js +30 -1
  7. package/dist/dialect/standardsql/standardsql.js +15 -0
  8. package/dist/dialect/trino/trino.js +5 -0
  9. package/dist/lang/ast/expressions/expr-time-extract.js +3 -2
  10. package/dist/lang/ast/field-space/include-utils.js +5 -5
  11. package/dist/lang/ast/field-space/query-spaces.js +1 -0
  12. package/dist/lang/ast/field-space/reference-field.js +1 -1
  13. package/dist/lang/ast/query-builders/project-builder.js +1 -2
  14. package/dist/lang/ast/query-elements/anonymous-query.d.ts +1 -3
  15. package/dist/lang/ast/query-elements/anonymous-query.js +1 -3
  16. package/dist/lang/ast/query-items/field-declaration.d.ts +1 -3
  17. package/dist/lang/ast/query-items/field-declaration.js +2 -4
  18. package/dist/lang/ast/query-items/field-references.d.ts +2 -5
  19. package/dist/lang/ast/query-items/field-references.js +2 -5
  20. package/dist/lang/ast/query-properties/aggregate.d.ts +1 -0
  21. package/dist/lang/ast/query-properties/aggregate.js +1 -0
  22. package/dist/lang/ast/query-properties/group-by.d.ts +1 -0
  23. package/dist/lang/ast/query-properties/group-by.js +1 -0
  24. package/dist/lang/ast/query-properties/indexing.d.ts +1 -0
  25. package/dist/lang/ast/query-properties/indexing.js +1 -0
  26. package/dist/lang/ast/query-properties/nest.d.ts +1 -0
  27. package/dist/lang/ast/query-properties/nest.js +2 -1
  28. package/dist/lang/ast/query-properties/nests.d.ts +1 -0
  29. package/dist/lang/ast/query-properties/nests.js +1 -0
  30. package/dist/lang/ast/query-properties/project-statement.d.ts +1 -0
  31. package/dist/lang/ast/query-properties/project-statement.js +1 -0
  32. package/dist/lang/ast/query-properties/qop-desc.js +12 -1
  33. package/dist/lang/ast/query-properties/sampling.d.ts +1 -0
  34. package/dist/lang/ast/query-properties/sampling.js +1 -0
  35. package/dist/lang/ast/source-properties/join.d.ts +1 -3
  36. package/dist/lang/ast/source-properties/join.js +4 -6
  37. package/dist/lang/ast/source-properties/renames.d.ts +2 -3
  38. package/dist/lang/ast/source-properties/renames.js +1 -3
  39. package/dist/lang/ast/source-properties/user-type-shape.d.ts +1 -3
  40. package/dist/lang/ast/source-properties/user-type-shape.js +5 -7
  41. package/dist/lang/ast/source-properties/view-field-declaration.d.ts +1 -3
  42. package/dist/lang/ast/source-properties/view-field-declaration.js +1 -3
  43. package/dist/lang/ast/source-query-elements/include-item.d.ts +2 -5
  44. package/dist/lang/ast/source-query-elements/include-item.js +0 -3
  45. package/dist/lang/ast/statements/define-given.d.ts +1 -3
  46. package/dist/lang/ast/statements/define-given.js +2 -4
  47. package/dist/lang/ast/statements/define-query.d.ts +1 -3
  48. package/dist/lang/ast/statements/define-query.js +3 -5
  49. package/dist/lang/ast/statements/define-source.d.ts +1 -3
  50. package/dist/lang/ast/statements/define-source.js +4 -6
  51. package/dist/lang/ast/statements/define-user-type.d.ts +1 -3
  52. package/dist/lang/ast/statements/define-user-type.js +2 -4
  53. package/dist/lang/ast/types/definition-list.d.ts +2 -4
  54. package/dist/lang/ast/types/definition-list.js +6 -11
  55. package/dist/lang/ast/types/malloy-element.d.ts +1 -3
  56. package/dist/lang/ast/types/malloy-element.js +2 -3
  57. package/dist/lang/ast/types/noteable.d.ts +3 -4
  58. package/dist/lang/ast/types/noteable.js +5 -7
  59. package/dist/lang/ast/types/query-property-interface.d.ts +1 -0
  60. package/dist/lang/composite-source-utils.js +1 -2
  61. package/dist/lang/malloy-to-ast.js +33 -32
  62. package/dist/lang/test/test-translator.d.ts +1 -0
  63. package/dist/lang/test/test-translator.js +15 -1
  64. package/dist/model/filter_compilers.js +27 -1
  65. package/dist/model/malloy_types.d.ts +3 -3
  66. package/dist/model/query_query.d.ts +1 -1
  67. package/dist/model/query_query.js +7 -3
  68. package/dist/version.d.ts +1 -1
  69. package/dist/version.js +1 -1
  70. package/package.json +4 -4
package/README.md CHANGED
@@ -34,8 +34,8 @@ In practice, much of this loop is handled by various database plugins:
34
34
  - [Postgres](https://github.com/malloydata/malloy/tree/main/packages/malloy-db-postgres)
35
35
  - [Snowflake](https://github.com/malloydata/malloy/tree/main/packages/malloy-db-snowflake)
36
36
 
37
- ## Do you have any examples?
37
+ ## What's built with these libraries?
38
38
 
39
- You can find a (very) simple example of writing a CLI for executing Malloy queries [here](https://github.com/malloydata/malloy/tree/main/demo/malloy-demo-bq-cli)
39
+ The [Malloy CLI](https://github.com/malloydata/malloy-cli) uses them to run Malloy queries from the command line.
40
40
 
41
- A more realistic and complex use case - we use these libraries to power our VSCode Extension. Some examples can be found [here](https://github.com/malloydata/malloy-vscode-extension/tree/main/src/extension/commands)
41
+ For a more complex use case, our [VS Code extension](https://github.com/malloydata/malloy-vscode-extension) uses them to power a full Malloy editing and query experience.
@@ -1300,11 +1300,16 @@ class PersistSource {
1300
1300
  getSQL(options) {
1301
1301
  const sd = this.persistableDef;
1302
1302
  const queryModel = this.model.queryModel;
1303
+ // Compile with finalize=false so this SQL is the bare source SELECT.
1304
+ // The build-time key (makeBuildId over this SQL) must equal the serve-time
1305
+ // manifest lookup key, which query_query.ts recomputes from the same
1306
+ // unfinalized SELECT; finalizing would diverge the two on dialects with a
1307
+ // final stage (Postgres) and mis-materialize the table.
1303
1308
  if (sd.type === 'sql_select') {
1304
- return (0, model_1.getCompiledSQL)(sd, options !== null && options !== void 0 ? options : {}, (query, opts) => queryModel.compileQuery(query, opts).sql);
1309
+ return (0, model_1.getCompiledSQL)(sd, options !== null && options !== void 0 ? options : {}, (query, opts) => queryModel.compileQuery(query, opts, false).sql);
1305
1310
  }
1306
1311
  else {
1307
- const compiled = queryModel.compileQuery(sd.query, options);
1312
+ const compiled = queryModel.compileQuery(sd.query, options, false);
1308
1313
  return compiled.sql;
1309
1314
  }
1310
1315
  }
@@ -389,8 +389,15 @@ class DatabricksDialect extends dialect_1.Dialect {
389
389
  throw new Error('Databricks does not support timestamptz');
390
390
  }
391
391
  sqlMeasureTimeExpr(df) {
392
- let lVal = df.kids.left.sql;
393
- let rVal = df.kids.right.sql;
392
+ const from = df.kids.left;
393
+ const to = df.kids.right;
394
+ let lVal = from.sql;
395
+ let rVal = to.sql;
396
+ if (malloy_types_1.TD.isDate(from.typeDef) &&
397
+ malloy_types_1.TD.isDate(to.typeDef) &&
398
+ ['week', 'month', 'quarter', 'year'].includes(df.units)) {
399
+ return `TIMESTAMPDIFF(${df.units.toUpperCase()}, ${lVal}, ${rVal})`;
400
+ }
394
401
  if (inSeconds[df.units]) {
395
402
  lVal = `UNIX_MICROS(CAST(${lVal} AS TIMESTAMP))`;
396
403
  rVal = `UNIX_MICROS(CAST(${rVal} AS TIMESTAMP))`;
@@ -415,8 +415,15 @@ class MySQLDialect extends dialect_1.Dialect {
415
415
  throw new Error('MySQL does not support timestamptz');
416
416
  }
417
417
  sqlMeasureTimeExpr(df) {
418
- let lVal = df.kids.left.sql;
419
- let rVal = df.kids.right.sql;
418
+ const from = df.kids.left;
419
+ const to = df.kids.right;
420
+ let lVal = from.sql;
421
+ let rVal = to.sql;
422
+ if (malloy_types_1.TD.isDate(from.typeDef) &&
423
+ malloy_types_1.TD.isDate(to.typeDef) &&
424
+ ['week', 'month', 'quarter', 'year'].includes(df.units)) {
425
+ return `TIMESTAMPDIFF(${df.units.toUpperCase()}, ${lVal}, ${rVal})`;
426
+ }
420
427
  if (inSeconds[df.units]) {
421
428
  lVal = `UNIX_TIMESTAMP(${lVal})`;
422
429
  rVal = `UNIX_TIMESTAMP(${rVal})`;
@@ -228,6 +228,32 @@ class PostgresDialect extends pg_impl_1.PostgresBase {
228
228
  const to = df.kids.right;
229
229
  let lVal = from.sql;
230
230
  let rVal = to.sql;
231
+ if (malloy_types_1.TD.isDate(from.typeDef) &&
232
+ malloy_types_1.TD.isDate(to.typeDef) &&
233
+ ['week', 'month', 'quarter', 'year'].includes(df.units)) {
234
+ const earlier = `LEAST(${lVal}, ${rVal})`;
235
+ const later = `GREATEST(${lVal}, ${rVal})`;
236
+ const age = `AGE(${later}, ${earlier})`;
237
+ const months = `(EXTRACT(YEAR FROM ${age}) * 12 + EXTRACT(MONTH FROM ${age}))`;
238
+ let measured;
239
+ if (df.units === 'week') {
240
+ measured = `TRUNC((${later} - ${earlier}) / 7.0)`;
241
+ }
242
+ else if (df.units === 'month') {
243
+ measured = months;
244
+ }
245
+ else if (df.units === 'quarter') {
246
+ measured = `TRUNC(${months} / 3.0)`;
247
+ }
248
+ else {
249
+ measured = `EXTRACT(YEAR FROM ${age})`;
250
+ }
251
+ return `CASE
252
+ WHEN ${lVal} IS NULL OR ${rVal} IS NULL THEN NULL
253
+ WHEN ${rVal} >= ${lVal} THEN ${measured}
254
+ ELSE -(${measured})
255
+ END`;
256
+ }
231
257
  if (inSeconds[df.units]) {
232
258
  lVal = `EXTRACT(EPOCH FROM ${lVal})`;
233
259
  rVal = `EXTRACT(EPOCH FROM ${rVal})`;
@@ -52,7 +52,12 @@ const snowflakeToMalloyTypes = {
52
52
  'timestamptz': { type: 'timestamptz' },
53
53
  'timestamp_tz': { type: 'timestamptz' },
54
54
  'timestamp with time zone': { type: 'timestamptz' },
55
- /* timestamp_ltz is not supported in malloy snowflake dialect */
55
+ // TIMESTAMP_LTZ is a genuine instant (persisted UTC); under Malloy's UTC
56
+ // session pin it is indistinguishable from NTZ, so it maps to `timestamp`
57
+ // like NTZ. malloyTypeToSQLType writes instants here too.
58
+ 'timestampltz': { type: 'timestamp' },
59
+ 'timestamp_ltz': { type: 'timestamp' },
60
+ 'timestamp with local time zone': { type: 'timestamp' },
56
61
  };
57
62
  class SnowflakeDialect extends dialect_1.Dialect {
58
63
  constructor() {
@@ -374,6 +379,22 @@ ${(0, utils_1.indent)(sql)}
374
379
  sqlMeasureTimeExpr(df) {
375
380
  const from = df.kids.left;
376
381
  const to = df.kids.right;
382
+ if (malloy_types_1.TD.isDate(from.typeDef) &&
383
+ malloy_types_1.TD.isDate(to.typeDef) &&
384
+ ['week', 'month', 'quarter', 'year'].includes(df.units)) {
385
+ const lVal = from.sql;
386
+ const rVal = to.sql;
387
+ const earlier = `LEAST(${lVal}, ${rVal})`;
388
+ const later = `GREATEST(${lVal}, ${rVal})`;
389
+ const candidate = `DATEDIFF(${df.units}, ${earlier}, ${later})`;
390
+ const anniversary = `DATEADD(${df.units}, ${candidate}, ${earlier})`;
391
+ const measured = `(${candidate} - CASE WHEN ${anniversary} > ${later} THEN 1 ELSE 0 END)`;
392
+ return `CASE
393
+ WHEN ${lVal} IS NULL OR ${rVal} IS NULL THEN NULL
394
+ WHEN ${rVal} >= ${lVal} THEN ${measured}
395
+ ELSE -(${measured})
396
+ END`;
397
+ }
377
398
  let extractUnits = 'nanoseconds';
378
399
  if (malloy_types_1.TD.isDate(from.typeDef) || malloy_types_1.TD.isDate(to.typeDef)) {
379
400
  extractUnits = 'seconds';
@@ -447,6 +468,14 @@ ${(0, utils_1.indent)(sql)}
447
468
  else if (malloyType.type === 'timestamptz') {
448
469
  return 'TIMESTAMP_TZ';
449
470
  }
471
+ else if (malloyType.type === 'timestamp') {
472
+ // A Malloy `timestamp` is an instant, and TIMESTAMP_LTZ is Snowflake's
473
+ // instant type. Emit it explicitly rather than the bare word TIMESTAMP,
474
+ // whose type is decided per account (TIMESTAMP_TYPE_MAPPING: NTZ or LTZ).
475
+ // NTZ only reads as an instant under the UTC session pin; LTZ is correct
476
+ // without it, and leaves NTZ for the future `datetime` type.
477
+ return 'TIMESTAMP_LTZ';
478
+ }
450
479
  return malloyType.type;
451
480
  }
452
481
  sqlTypeToMalloyType(sqlType) {
@@ -341,6 +341,21 @@ ${(0, utils_1.indent)(sql)}
341
341
  const to = measure.kids.right;
342
342
  let lVal = from.sql;
343
343
  let rVal = to.sql;
344
+ if (malloy_types_1.TD.isDate(from.typeDef) &&
345
+ malloy_types_1.TD.isDate(to.typeDef) &&
346
+ ['week', 'month', 'quarter', 'year'].includes(measure.units)) {
347
+ const earlier = `LEAST(${lVal},${rVal})`;
348
+ const later = `GREATEST(${lVal},${rVal})`;
349
+ const unit = measure.units.toUpperCase();
350
+ const candidate = `DATE_DIFF(${later},${earlier},${unit})`;
351
+ const anniversary = `DATE_ADD(${earlier}, INTERVAL ${candidate} ${unit})`;
352
+ const measured = `(${candidate} - CASE WHEN ${anniversary} > ${later} THEN 1 ELSE 0 END)`;
353
+ return `CASE
354
+ WHEN ${lVal} IS NULL OR ${rVal} IS NULL THEN NULL
355
+ WHEN ${rVal} >= ${lVal} THEN ${measured}
356
+ ELSE -(${measured})
357
+ END`;
358
+ }
344
359
  if (measureMap[measure.units]) {
345
360
  const { use: measureIn, ratio } = measureMap[measure.units];
346
361
  if (!timestampMeasureable(measureIn)) {
@@ -439,6 +439,11 @@ ${(0, utils_1.indent)(sql)}
439
439
  const to = mf.kids.right;
440
440
  let lVal = from.sql;
441
441
  let rVal = to.sql;
442
+ if (malloy_types_1.TD.isDate(from.typeDef) &&
443
+ malloy_types_1.TD.isDate(to.typeDef) &&
444
+ ['week', 'month', 'quarter', 'year'].includes(mf.units)) {
445
+ return `DATE_DIFF('${mf.units}',${lVal},${rVal})`;
446
+ }
442
447
  if (measureMap[mf.units]) {
443
448
  const { use: measureIn, ratio } = measureMap[mf.units];
444
449
  if (!timestampMeasureable(measureIn)) {
@@ -70,8 +70,9 @@ class ExprTimeExtract extends expression_def_1.ExpressionDef {
70
70
  return from.first.loggedErrorExpr('invalid-types-for-time-measurement', `Cannot measure from ${first.type} to ${last.type}`);
71
71
  }
72
72
  }
73
- if (['week', 'month', 'quarter', 'year'].includes(extractTo)) {
74
- return this.loggedErrorExpr('invalid-timeframe-for-time-measurement', `Cannot measure interval using '${extractTo}'`);
73
+ if (['week', 'month', 'quarter', 'year'].includes(extractTo) &&
74
+ (first.type !== 'date' || last.type !== 'date')) {
75
+ return this.loggedErrorExpr('invalid-timeframe-for-time-measurement', `Cannot measure interval using '${extractTo}' for '${first.type}' values; calendar interval measurement requires dates`);
75
76
  }
76
77
  if (!(0, malloy_types_1.isTimestampUnit)(extractTo)) {
77
78
  return this.loggedErrorExpr('invalid-time-extraction-unit', `Cannot extract ${extractTo} from a range`);
@@ -114,8 +114,8 @@ function processIncludeList(includeItems, from) {
114
114
  else {
115
115
  joinState.star = (_c = item.kind) !== null && _c !== void 0 ? _c : 'inherit';
116
116
  joinState.starNote = {
117
- notes: (_e = (_d = f.note) === null || _d === void 0 ? void 0 : _d.notes) !== null && _e !== void 0 ? _e : [],
118
- blockNotes: (_g = (_f = item.note) === null || _f === void 0 ? void 0 : _f.blockNotes) !== null && _g !== void 0 ? _g : [],
117
+ notes: (_e = (_d = f.ownAnnotation) === null || _d === void 0 ? void 0 : _d.notes) !== null && _e !== void 0 ? _e : [],
118
+ blockNotes: (_g = (_f = item.ownAnnotation) === null || _f === void 0 ? void 0 : _f.blockNotes) !== null && _g !== void 0 ? _g : [],
119
119
  };
120
120
  }
121
121
  }
@@ -149,10 +149,10 @@ function processIncludeList(includeItems, from) {
149
149
  joinState.modifiers.set((_h = f.as) !== null && _h !== void 0 ? _h : name, item.kind);
150
150
  }
151
151
  joinState.fieldsIncluded.add(name);
152
- if (f.note || item.note) {
152
+ if (f.ownAnnotation || item.ownAnnotation) {
153
153
  joinState.notes.set(name, {
154
- notes: (_k = (_j = f.note) === null || _j === void 0 ? void 0 : _j.notes) !== null && _k !== void 0 ? _k : [],
155
- blockNotes: (_m = (_l = item.note) === null || _l === void 0 ? void 0 : _l.blockNotes) !== null && _m !== void 0 ? _m : [],
154
+ notes: (_k = (_j = f.ownAnnotation) === null || _j === void 0 ? void 0 : _j.notes) !== null && _k !== void 0 ? _k : [],
155
+ blockNotes: (_m = (_l = item.ownAnnotation) === null || _l === void 0 ? void 0 : _l.blockNotes) !== null && _m !== void 0 ? _m : [],
156
156
  });
157
157
  }
158
158
  }
@@ -211,6 +211,7 @@ class QuerySpace extends QueryOperationSpace {
211
211
  for (const field of refineThis.queryFields) {
212
212
  if (field.type === 'fieldref') {
213
213
  const fieldReference = new field_references_1.RefineFromFieldReference(field.path.map(f => new field_space_1.FieldName(f)));
214
+ fieldReference.ownAnnotation = field.annotations;
214
215
  this.astEl.has({ fieldReference });
215
216
  const referenceField = new reference_field_1.ReferenceField(fieldReference, this.exprSpace);
216
217
  const name = field.path[field.path.length - 1];
@@ -94,7 +94,7 @@ class ReferenceField extends space_field_1.SpaceField {
94
94
  if (refTo instanceof space_field_1.SpaceField) {
95
95
  const origFd = refTo.constructorFieldDef();
96
96
  if (origFd) {
97
- const notes = this.fieldRef.note;
97
+ const notes = this.fieldRef.ownAnnotation;
98
98
  if (origFd.annotations || notes) {
99
99
  const annotations = {
100
100
  ...(notes !== null && notes !== void 0 ? notes : {}),
@@ -7,7 +7,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.ProjectBuilder = void 0;
8
8
  const malloy_types_1 = require("../../../model/malloy_types");
9
9
  const error_factory_1 = require("../error-factory");
10
- const group_by_1 = require("../query-properties/group-by");
11
10
  const project_field_space_1 = require("../field-space/project-field-space");
12
11
  const reduce_builder_1 = require("./reduce-builder");
13
12
  class ProjectBuilder extends reduce_builder_1.QuerySegmentBuilder {
@@ -18,7 +17,7 @@ class ProjectBuilder extends reduce_builder_1.QuerySegmentBuilder {
18
17
  this.inputFS = this.resultFS.inputSpace();
19
18
  }
20
19
  execute(qp) {
21
- if (qp.elementType === 'having' || qp instanceof group_by_1.GroupBy) {
20
+ if (qp.elementType === 'having') {
22
21
  qp.logError('illegal-operation-in-select-segment', 'Illegal statement in a select query operation');
23
22
  }
24
23
  else {
@@ -2,14 +2,12 @@ import type { AnnotationsDef } from '../../../model';
2
2
  import type { DocStatement, Document } from '../types/malloy-element';
3
3
  import { MalloyElement } from '../types/malloy-element';
4
4
  import type { Noteable } from '../types/noteable';
5
- import { extendNoteMethod } from '../types/noteable';
6
5
  import type { SourceQueryElement } from '../source-query-elements/source-query-element';
7
6
  export declare class AnonymousQuery extends MalloyElement implements DocStatement, Noteable {
8
7
  readonly queryExpr: SourceQueryElement;
9
8
  elementType: string;
10
9
  constructor(queryExpr: SourceQueryElement);
11
10
  readonly isNoteableObj = true;
12
- extendNote: typeof extendNoteMethod;
13
- note?: AnnotationsDef;
11
+ ownAnnotation?: AnnotationsDef;
14
12
  execute(doc: Document): void;
15
13
  }
@@ -6,14 +6,12 @@
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.AnonymousQuery = void 0;
8
8
  const malloy_element_1 = require("../types/malloy-element");
9
- const noteable_1 = require("../types/noteable");
10
9
  class AnonymousQuery extends malloy_element_1.MalloyElement {
11
10
  constructor(queryExpr) {
12
11
  super();
13
12
  this.queryExpr = queryExpr;
14
13
  this.elementType = 'anonymousQuery';
15
14
  this.isNoteableObj = true;
16
- this.extendNote = noteable_1.extendNoteMethod;
17
15
  this.has({ queryExpr });
18
16
  }
19
17
  execute(doc) {
@@ -23,7 +21,7 @@ class AnonymousQuery extends malloy_element_1.MalloyElement {
23
21
  return;
24
22
  }
25
23
  const modelQuery = { ...queryObj.query() };
26
- const annotation = this.note || {};
24
+ const annotation = this.ownAnnotation || {};
27
25
  if (modelQuery.annotations) {
28
26
  annotation.inherits = modelQuery.annotations;
29
27
  }
@@ -5,7 +5,6 @@ import type { FieldSpace } from '../types/field-space';
5
5
  import { MalloyElement } from '../types/malloy-element';
6
6
  import type { MakeEntry } from '../types/space-entry';
7
7
  import type { Noteable } from '../types/noteable';
8
- import { extendNoteMethod } from '../types/noteable';
9
8
  import type { DynamicSpace } from '../field-space/dynamic-space';
10
9
  import { SpaceField } from '../types/space-field';
11
10
  export type FieldDeclarationConstructor = new (expr: ExpressionDef, defineName: string, exprSrc?: string) => AtomicFieldDeclaration;
@@ -14,8 +13,7 @@ export declare abstract class AtomicFieldDeclaration extends MalloyElement imple
14
13
  readonly defineName: string;
15
14
  readonly exprSrc?: string | undefined;
16
15
  readonly isNoteableObj = true;
17
- extendNote: typeof extendNoteMethod;
18
- note?: AnnotationsDef;
16
+ ownAnnotation?: AnnotationsDef;
19
17
  constructor(expr: ExpressionDef, defineName: string, exprSrc?: string | undefined);
20
18
  getName(): string;
21
19
  fieldDef(fs: FieldSpace, exprName: string): FieldDef;
@@ -43,7 +43,6 @@ const TDU = __importStar(require("../typedesc-utils"));
43
43
  const granular_result_1 = require("../types/granular-result");
44
44
  const malloy_element_1 = require("../types/malloy-element");
45
45
  const typecheck_utils_1 = require("./typecheck_utils");
46
- const noteable_1 = require("../types/noteable");
47
46
  const space_field_1 = require("../types/space-field");
48
47
  const def_space_1 = require("../field-space/def-space");
49
48
  class AtomicFieldDeclaration extends malloy_element_1.MalloyElement {
@@ -53,7 +52,6 @@ class AtomicFieldDeclaration extends malloy_element_1.MalloyElement {
53
52
  this.defineName = defineName;
54
53
  this.exprSrc = exprSrc;
55
54
  this.isNoteableObj = true;
56
- this.extendNote = noteable_1.extendNoteMethod;
57
55
  }
58
56
  getName() {
59
57
  return this.defineName;
@@ -138,8 +136,8 @@ class AtomicFieldDeclaration extends malloy_element_1.MalloyElement {
138
136
  if (this.exprSrc) {
139
137
  ret.code = this.exprSrc;
140
138
  }
141
- if (this.note) {
142
- ret.annotations = { ...this.note };
139
+ if (this.ownAnnotation) {
140
+ ret.annotations = { ...this.ownAnnotation };
143
141
  }
144
142
  return ret;
145
143
  }
@@ -6,15 +6,13 @@ import { FieldName } from '../types/field-space';
6
6
  import type { LookupResult } from '../types/lookup-result';
7
7
  import { ListOf, MalloyElement } from '../types/malloy-element';
8
8
  import type { Noteable } from '../types/noteable';
9
- import { extendNoteMethod } from '../types/noteable';
10
9
  import type { MakeEntry } from '../types/space-entry';
11
10
  import type { FieldDeclarationConstructor } from './field-declaration';
12
11
  import { AggregateFieldDeclaration, CalculateFieldDeclaration, GroupByFieldDeclaration, ProjectFieldDeclaration } from './field-declaration';
13
12
  export type FieldReferenceConstructor = new (names: FieldName[]) => FieldReference;
14
13
  export declare abstract class FieldReference extends ListOf<FieldName> implements Noteable, MakeEntry {
15
14
  readonly isNoteableObj = true;
16
- note?: AnnotationsDef;
17
- extendNote: typeof extendNoteMethod;
15
+ ownAnnotation?: AnnotationsDef;
18
16
  constructor(names: FieldName[]);
19
17
  protected autoRenameDeclarationCtor(): FieldDeclarationConstructor | undefined;
20
18
  makeEntry(fs: DynamicSpace): void;
@@ -106,9 +104,8 @@ export declare class ViewOrScalarFieldReference extends FieldReference {
106
104
  export declare class WildcardFieldReference extends MalloyElement implements Noteable {
107
105
  readonly joinPath: FieldReference | undefined;
108
106
  elementType: string;
109
- note?: AnnotationsDef;
107
+ ownAnnotation?: AnnotationsDef;
110
108
  readonly isNoteableObj = true;
111
- extendNote: typeof extendNoteMethod;
112
109
  except: Set<string>;
113
110
  constructor(joinPath: FieldReference | undefined);
114
111
  getFieldDef(): FieldDef;
@@ -9,7 +9,6 @@ const reference_field_1 = require("../field-space/reference-field");
9
9
  const definition_list_1 = require("../types/definition-list");
10
10
  const field_space_1 = require("../types/field-space");
11
11
  const malloy_element_1 = require("../types/malloy-element");
12
- const noteable_1 = require("../types/noteable");
13
12
  const expr_id_reference_1 = require("../expressions/expr-id-reference");
14
13
  const field_declaration_1 = require("./field-declaration");
15
14
  const typecheck_utils_1 = require("./typecheck_utils");
@@ -17,7 +16,6 @@ class FieldReference extends malloy_element_1.ListOf {
17
16
  constructor(names) {
18
17
  super(names);
19
18
  this.isNoteableObj = true;
20
- this.extendNote = noteable_1.extendNoteMethod;
21
19
  }
22
20
  // The `name is path` declaration constructor used to auto-resolve an output
23
21
  // name collision for this kind of reference, or undefined if this reference
@@ -70,8 +68,8 @@ class FieldReference extends malloy_element_1.ListOf {
70
68
  'to set the name explicitly and silence this warning.');
71
69
  const renamedRef = new ExpressionFieldReference(this.list.map(n => new field_space_1.FieldName(n.refString)));
72
70
  const decl = new declCtor(new expr_id_reference_1.ExprIdReference(renamedRef), autoName);
73
- if (this.note) {
74
- decl.note = this.note;
71
+ if (this.ownAnnotation) {
72
+ decl.ownAnnotation = this.ownAnnotation;
75
73
  }
76
74
  // Attach under this reference so the synthetic nodes inherit its location
77
75
  // and resolve back to the translator for logging.
@@ -320,7 +318,6 @@ class WildcardFieldReference extends malloy_element_1.MalloyElement {
320
318
  this.joinPath = joinPath;
321
319
  this.elementType = 'wildcardFieldReference';
322
320
  this.isNoteableObj = true;
323
- this.extendNote = noteable_1.extendNoteMethod;
324
321
  this.except = new Set();
325
322
  this.has({ joinPath });
326
323
  }
@@ -6,4 +6,5 @@ export declare class Aggregate extends DefinitionList<QueryItem> implements Quer
6
6
  elementType: string;
7
7
  readonly queryRefinementStage = LegalRefinementStage.Single;
8
8
  readonly forceQueryClass = QueryClass.Grouping;
9
+ readonly statement = "aggregate:";
9
10
  }
@@ -13,6 +13,7 @@ class Aggregate extends definition_list_1.DefinitionList {
13
13
  this.elementType = 'aggregateList';
14
14
  this.queryRefinementStage = query_property_interface_1.LegalRefinementStage.Single;
15
15
  this.forceQueryClass = query_property_interface_1.QueryClass.Grouping;
16
+ this.statement = 'aggregate:';
16
17
  }
17
18
  }
18
19
  exports.Aggregate = Aggregate;
@@ -6,4 +6,5 @@ export declare class GroupBy extends DefinitionList<QueryItem> implements QueryP
6
6
  elementType: string;
7
7
  queryRefinementStage: LegalRefinementStage;
8
8
  forceQueryClass: QueryClass;
9
+ statement: string;
9
10
  }
@@ -13,6 +13,7 @@ class GroupBy extends definition_list_1.DefinitionList {
13
13
  this.elementType = 'groupBy';
14
14
  this.queryRefinementStage = query_property_interface_1.LegalRefinementStage.Single;
15
15
  this.forceQueryClass = query_property_interface_1.QueryClass.Grouping;
16
+ this.statement = 'group_by:';
16
17
  }
17
18
  }
18
19
  exports.GroupBy = GroupBy;
@@ -8,6 +8,7 @@ export declare class Index extends MalloyElement implements QueryPropertyInterfa
8
8
  elementType: string;
9
9
  weightBy?: FieldName;
10
10
  forceQueryClass: QueryClass;
11
+ statement: string;
11
12
  queryRefinementStage: undefined;
12
13
  constructor(fields: FieldReferences);
13
14
  useWeight(fn: FieldName): void;
@@ -13,6 +13,7 @@ class Index extends malloy_element_1.MalloyElement {
13
13
  this.fields = fields;
14
14
  this.elementType = 'index';
15
15
  this.forceQueryClass = query_property_interface_1.QueryClass.Index;
16
+ this.statement = 'index:';
16
17
  this.queryRefinementStage = undefined;
17
18
  }
18
19
  useWeight(fn) {
@@ -8,6 +8,7 @@ export declare class NestFieldDeclaration extends ViewFieldDeclaration implement
8
8
  elementType: string;
9
9
  queryRefinementStage: LegalRefinementStage;
10
10
  forceQueryClass: QueryClass;
11
+ statement: string;
11
12
  turtleDef: model.TurtleDef | undefined;
12
13
  queryExecute(executeFor: QueryBuilder): void;
13
14
  getFieldDef(fs: FieldSpace): model.TurtleDef;
@@ -50,6 +50,7 @@ class NestFieldDeclaration extends view_field_declaration_1.ViewFieldDeclaration
50
50
  this.elementType = 'nest-field-declaration';
51
51
  this.queryRefinementStage = query_property_interface_1.LegalRefinementStage.Single;
52
52
  this.forceQueryClass = query_property_interface_1.QueryClass.Grouping;
53
+ this.statement = 'nest:';
53
54
  this.turtleDef = undefined;
54
55
  }
55
56
  queryExecute(executeFor) {
@@ -84,7 +85,7 @@ class NestFieldDeclaration extends view_field_declaration_1.ViewFieldDeclaration
84
85
  name: this.name,
85
86
  pipeline: pipelineWithDrillPaths,
86
87
  annotations: {
87
- ...this.note,
88
+ ...this.ownAnnotation,
88
89
  inherits: annotations,
89
90
  },
90
91
  location: this.location,
@@ -6,5 +6,6 @@ export declare class Nests extends DefinitionList<NestFieldDeclaration> implemen
6
6
  elementType: string;
7
7
  queryRefinementStage: LegalRefinementStage;
8
8
  forceQueryClass: QueryClass;
9
+ statement: string;
9
10
  constructor(nests: NestFieldDeclaration[]);
10
11
  }
@@ -13,6 +13,7 @@ class Nests extends definition_list_1.DefinitionList {
13
13
  this.elementType = 'nestedQueries';
14
14
  this.queryRefinementStage = query_property_interface_1.LegalRefinementStage.Single;
15
15
  this.forceQueryClass = query_property_interface_1.QueryClass.Grouping;
16
+ this.statement = 'nest:';
16
17
  }
17
18
  }
18
19
  exports.Nests = Nests;
@@ -6,6 +6,7 @@ import { LegalRefinementStage, QueryClass } from '../types/query-property-interf
6
6
  export declare class ProjectStatement extends DefinitionList<FieldCollectionMember> implements QueryPropertyInterface {
7
7
  elementType: string;
8
8
  forceQueryClass: QueryClass;
9
+ statement: string;
9
10
  queryRefinementStage: LegalRefinementStage;
10
11
  queryExecute(executeFor: QueryBuilder): void;
11
12
  }
@@ -12,6 +12,7 @@ class ProjectStatement extends definition_list_1.DefinitionList {
12
12
  super(...arguments);
13
13
  this.elementType = 'projectStatement';
14
14
  this.forceQueryClass = query_property_interface_1.QueryClass.Project;
15
+ this.statement = 'select:';
15
16
  this.queryRefinementStage = query_property_interface_1.LegalRefinementStage.Single;
16
17
  }
17
18
  queryExecute(executeFor) {
@@ -12,6 +12,11 @@ const malloy_element_1 = require("../types/malloy-element");
12
12
  const query_property_interface_1 = require("../types/query-property-interface");
13
13
  const partial_builder_1 = require("../query-builders/partial-builder");
14
14
  const utils_1 = require("../../utils");
15
+ function queryContextName(queryClass) {
16
+ const className = (0, utils_1.modernizeTermsForUserText)(queryClass);
17
+ const article = className === 'index' ? 'an' : 'a';
18
+ return `${article} ${className} query`;
19
+ }
15
20
  class QOpDesc extends malloy_element_1.ListOf {
16
21
  constructor() {
17
22
  super(...arguments);
@@ -36,7 +41,8 @@ class QOpDesc extends malloy_element_1.ListOf {
36
41
  if (el.forceQueryClass) {
37
42
  if (guessType) {
38
43
  if (guessType !== el.forceQueryClass) {
39
- el.logError(`illegal-${guessType}-operation`, `Use of ${(0, utils_1.modernizeTermsForUserText)(el.forceQueryClass)} is not allowed in a ${(0, utils_1.modernizeTermsForUserText)(guessType)} query`);
44
+ const operationName = el.statement;
45
+ el.logError(`illegal-${guessType}-operation`, `Use of ${operationName} is not allowed in ${queryContextName(guessType)}`);
40
46
  }
41
47
  }
42
48
  else {
@@ -70,6 +76,11 @@ class QOpDesc extends malloy_element_1.ListOf {
70
76
  getOp(inputFS, isNestIn) {
71
77
  const build = this.getBuilder(inputFS, isNestIn, this);
72
78
  for (const qp of this.list) {
79
+ if (this.opClass &&
80
+ qp.forceQueryClass &&
81
+ qp.forceQueryClass !== this.opClass) {
82
+ continue;
83
+ }
73
84
  build.execute(qp);
74
85
  }
75
86
  const segment = build.finalize(this.refineThis);
@@ -7,6 +7,7 @@ export declare class SampleProperty extends MalloyElement implements QueryProper
7
7
  elementType: string;
8
8
  queryRefinementStage: LegalRefinementStage;
9
9
  forceQueryClass: QueryClass;
10
+ statement: string;
10
11
  constructor(sample: Sampling);
11
12
  sampling(): Sampling;
12
13
  }
@@ -14,6 +14,7 @@ class SampleProperty extends malloy_element_1.MalloyElement {
14
14
  this.elementType = 'sampleProperty';
15
15
  this.queryRefinementStage = query_property_interface_1.LegalRefinementStage.Tail;
16
16
  this.forceQueryClass = query_property_interface_1.QueryClass.Index;
17
+ this.statement = 'sample:';
17
18
  }
18
19
  sampling() {
19
20
  return this.sample;
@@ -7,7 +7,6 @@ import type { FieldSpace } from '../types/field-space';
7
7
  import type { ModelEntryReference } from '../types/malloy-element';
8
8
  import { MalloyElement } from '../types/malloy-element';
9
9
  import type { Noteable } from '../types/noteable';
10
- import { extendNoteMethod } from '../types/noteable';
11
10
  import type { MakeEntry } from '../types/space-entry';
12
11
  import type { SourceQueryElement } from '../source-query-elements/source-query-element';
13
12
  import type { ParameterSpace } from '../field-space/parameter-space';
@@ -18,9 +17,8 @@ export declare abstract class Join extends MalloyElement implements Noteable, Ma
18
17
  abstract getStructDef(parameterSpace: ParameterSpace): JoinFieldDef;
19
18
  abstract fixupJoinOn(outer: FieldSpace, inStruct: JoinFieldDef): void;
20
19
  readonly isNoteableObj = true;
21
- extendNote: typeof extendNoteMethod;
22
20
  abstract sourceExpr: SourceQueryElement;
23
- note?: AnnotationsDef;
21
+ ownAnnotation?: AnnotationsDef;
24
22
  makeEntry(fs: DynamicSpace): void;
25
23
  getName(): string;
26
24
  protected getStructDefFromExpr(parameterSpace: ParameterSpace): SourceDef;