@malloydata/malloy 0.0.434 → 0.0.435

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 (47) hide show
  1. package/dist/api/foundation/compile.d.ts +0 -1
  2. package/dist/api/foundation/compile.js +0 -3
  3. package/dist/api/foundation/runtime.d.ts +0 -1
  4. package/dist/api/foundation/runtime.js +1 -23
  5. package/dist/api/foundation/types.d.ts +0 -1
  6. package/dist/dialect/dialect.d.ts +14 -1
  7. package/dist/dialect/dialect.js +34 -2
  8. package/dist/dialect/dialect_map.js +2 -0
  9. package/dist/dialect/index.d.ts +2 -1
  10. package/dist/dialect/index.js +3 -1
  11. package/dist/dialect/sqlserver/dialect_functions.d.ts +2 -0
  12. package/dist/dialect/sqlserver/dialect_functions.js +42 -0
  13. package/dist/dialect/sqlserver/function_overrides.d.ts +2 -0
  14. package/dist/dialect/sqlserver/function_overrides.js +55 -0
  15. package/dist/dialect/sqlserver/index.d.ts +1 -0
  16. package/dist/dialect/sqlserver/index.js +22 -0
  17. package/dist/dialect/sqlserver/sqlserver.d.ts +102 -0
  18. package/dist/dialect/sqlserver/sqlserver.js +538 -0
  19. package/dist/dialect/sqlserver/windows_zones.d.ts +1 -0
  20. package/dist/dialect/sqlserver/windows_zones.js +613 -0
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.js +5 -3
  23. package/dist/lang/ast/source-elements/named-source.js +0 -2
  24. package/dist/lang/ast/source-elements/sql-source.js +0 -3
  25. package/dist/lang/ast/source-elements/table-source.js +1 -2
  26. package/dist/lang/ast/statements/import-statement.js +4 -0
  27. package/dist/lang/ast/types/malloy-element.d.ts +0 -7
  28. package/dist/lang/ast/types/malloy-element.js +0 -18
  29. package/dist/lang/parse-malloy.d.ts +17 -2
  30. package/dist/lang/parse-malloy.js +48 -14
  31. package/dist/lang/parse-tree-walkers/find-external-references.d.ts +3 -3
  32. package/dist/lang/parse-tree-walkers/find-external-references.js +17 -16
  33. package/dist/lang/test/test-translator.d.ts +10 -1
  34. package/dist/lang/test/test-translator.js +15 -1
  35. package/dist/model/expression_compiler.js +1 -1
  36. package/dist/model/query_query.d.ts +3 -1
  37. package/dist/model/query_query.js +157 -139
  38. package/dist/model/source_def_utils.d.ts +7 -1
  39. package/dist/model/source_def_utils.js +20 -0
  40. package/dist/test/index.js +16 -8
  41. package/dist/test/matchers.d.ts +1 -1
  42. package/dist/test/matchers.js +1 -1
  43. package/dist/test/test-models.js +6 -13
  44. package/dist/version.d.ts +1 -1
  45. package/dist/version.js +1 -1
  46. package/femto-config.motly +13 -1
  47. package/package.json +7 -5
package/dist/index.js CHANGED
@@ -37,9 +37,9 @@ var __importStar = (this && this.__importStar) || (function () {
37
37
  };
38
38
  })();
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
- exports.Model = exports.MalloyTranslator = exports.malloyToQuery = exports.constantExprToSQL = exports.isDateUnit = exports.isTimestampUnit = exports.composeSQLExpr = exports.indent = exports.expressionIsUngroupedAggregate = exports.expressionIsScalar = exports.expressionIsCalculation = exports.expressionIsAnalytic = exports.expressionIsAggregate = exports.mkFieldDef = exports.mkArrayDef = exports.isBasicArray = exports.isRepeatedRecord = exports.isSamplingRows = exports.isSamplingPercent = exports.isSamplingEnable = exports.isJoinedSource = exports.isJoined = exports.isCompoundArrayData = exports.isBasicAtomic = exports.isAtomic = exports.isSourceDef = exports.validateDottedTablePath = exports.decodeDottedTablePath = exports.Dialect = exports.spread = exports.literal = exports.variadicParam = exports.param = exports.makeParam = exports.sql = exports.maxScalar = exports.minAggregate = exports.anyExprType = exports.minScalar = exports.overload = exports.qtz = exports.arg = exports.registerDialect = exports.DatabricksDialect = exports.MySQLDialect = exports.SnowflakeDialect = exports.PostgresDialect = exports.TrinoDialect = exports.StandardSQLDialect = exports.DuckDBDialect = void 0;
41
- exports.Reference = exports.EMPTY_BUILD_MANIFEST = exports.PersistSource = exports.annotationToTaglines = exports.annotationToTag = exports.tagFromAnnotations = exports.annotationsForRoute = exports.payloadOf = exports.routeOf = exports.RoutedNote = exports.Annotations = exports.sqlKey = exports.API = exports.sourceDefToSourceInfo = exports.modelDefToModelInfo = exports.toAsyncGenerator = exports.createConnectionsFromConfig = exports.getRegisteredConnectionTypes = exports.getConnectionTypeDisplayName = exports.getConnectionProperties = exports.registerConnectionType = exports.discoverConfig = exports.defaultConfigOverlays = exports.contextOverlay = exports.envOverlay = exports.MalloyConfig = exports.Manifest = exports.CacheManager = exports.InMemoryModelCache = exports.Explore = exports.DataWriter = exports.Parse = exports.JSONWriter = exports.CSVWriter = exports.QueryMaterializer = exports.Result = exports.PreparedResult = exports.TimestampTimeframe = exports.DateTimeframe = exports.SourceRelationship = exports.JoinRelationship = exports.MalloyError = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.AtomicFieldType = exports.Runtime = exports.Malloy = void 0;
42
- exports.makeDigest = void 0;
40
+ exports.malloyToQuery = exports.constantExprToSQL = exports.isDateUnit = exports.isTimestampUnit = exports.composeSQLExpr = exports.indent = exports.expressionIsUngroupedAggregate = exports.expressionIsScalar = exports.expressionIsCalculation = exports.expressionIsAnalytic = exports.expressionIsAggregate = exports.mkFieldDef = exports.mkArrayDef = exports.isBasicArray = exports.isRepeatedRecord = exports.isSamplingRows = exports.isSamplingPercent = exports.isSamplingEnable = exports.isJoinedSource = exports.isJoined = exports.isCompoundArrayData = exports.isBasicAtomic = exports.isAtomic = exports.isSourceDef = exports.validateDottedTablePath = exports.decodeDottedTablePath = exports.Dialect = exports.spread = exports.literal = exports.variadicParam = exports.param = exports.makeParam = exports.sql = exports.maxScalar = exports.minAggregate = exports.anyExprType = exports.minScalar = exports.overload = exports.qtz = exports.arg = exports.getDialect = exports.registerDialect = exports.SQLServerDialect = exports.DatabricksDialect = exports.MySQLDialect = exports.SnowflakeDialect = exports.PostgresDialect = exports.TrinoDialect = exports.StandardSQLDialect = exports.DuckDBDialect = void 0;
41
+ exports.PersistSource = exports.annotationToTaglines = exports.annotationToTag = exports.tagFromAnnotations = exports.annotationsForRoute = exports.payloadOf = exports.routeOf = exports.RoutedNote = exports.Annotations = exports.sqlKey = exports.API = exports.sourceDefToSourceInfo = exports.modelDefToModelInfo = exports.toAsyncGenerator = exports.createConnectionsFromConfig = exports.getRegisteredConnectionTypes = exports.getConnectionTypeDisplayName = exports.getConnectionProperties = exports.registerConnectionType = exports.discoverConfig = exports.defaultConfigOverlays = exports.contextOverlay = exports.envOverlay = exports.MalloyConfig = exports.Manifest = exports.CacheManager = exports.InMemoryModelCache = exports.Explore = exports.DataWriter = exports.Parse = exports.JSONWriter = exports.CSVWriter = exports.QueryMaterializer = exports.Result = exports.PreparedResult = exports.TimestampTimeframe = exports.DateTimeframe = exports.SourceRelationship = exports.JoinRelationship = exports.MalloyError = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.AtomicFieldType = exports.Runtime = exports.Malloy = exports.Model = exports.MalloyTranslator = void 0;
42
+ exports.makeDigest = exports.Reference = exports.EMPTY_BUILD_MANIFEST = void 0;
43
43
  var dialect_1 = require("./dialect");
44
44
  Object.defineProperty(exports, "DuckDBDialect", { enumerable: true, get: function () { return dialect_1.DuckDBDialect; } });
45
45
  Object.defineProperty(exports, "StandardSQLDialect", { enumerable: true, get: function () { return dialect_1.StandardSQLDialect; } });
@@ -48,7 +48,9 @@ Object.defineProperty(exports, "PostgresDialect", { enumerable: true, get: funct
48
48
  Object.defineProperty(exports, "SnowflakeDialect", { enumerable: true, get: function () { return dialect_1.SnowflakeDialect; } });
49
49
  Object.defineProperty(exports, "MySQLDialect", { enumerable: true, get: function () { return dialect_1.MySQLDialect; } });
50
50
  Object.defineProperty(exports, "DatabricksDialect", { enumerable: true, get: function () { return dialect_1.DatabricksDialect; } });
51
+ Object.defineProperty(exports, "SQLServerDialect", { enumerable: true, get: function () { return dialect_1.SQLServerDialect; } });
51
52
  Object.defineProperty(exports, "registerDialect", { enumerable: true, get: function () { return dialect_1.registerDialect; } });
53
+ Object.defineProperty(exports, "getDialect", { enumerable: true, get: function () { return dialect_1.getDialect; } });
52
54
  Object.defineProperty(exports, "arg", { enumerable: true, get: function () { return dialect_1.arg; } });
53
55
  Object.defineProperty(exports, "qtz", { enumerable: true, get: function () { return dialect_1.qtz; } });
54
56
  Object.defineProperty(exports, "overload", { enumerable: true, get: function () { return dialect_1.overload; } });
@@ -52,7 +52,6 @@ class NamedSource extends source_1.Source {
52
52
  }
53
53
  }
54
54
  modelStruct() {
55
- var _a;
56
55
  const modelEnt = this.modelEntry(this.ref);
57
56
  const entry = modelEnt === null || modelEnt === void 0 ? void 0 : modelEnt.entry;
58
57
  if (!entry) {
@@ -89,7 +88,6 @@ class NamedSource extends source_1.Source {
89
88
  return;
90
89
  }
91
90
  else {
92
- (_a = this.document()) === null || _a === void 0 ? void 0 : _a.checkExperimentalDialect(this, entry.dialect);
93
91
  if ((0, malloy_types_1.isSourceDef)(entry)) {
94
92
  // This struct is created as an unmodified reference to `entry`. Mark it
95
93
  // with entry's own identity; the modification path (DynamicSpace) clears
@@ -78,9 +78,6 @@ class SQLSource extends source_1.Source {
78
78
  compileSQL: sql,
79
79
  };
80
80
  }
81
- else if (lookup.status === 'present') {
82
- doc.checkExperimentalDialect(this, lookup.value.dialect);
83
- }
84
81
  }
85
82
  getSourceDef() {
86
83
  var _a;
@@ -12,7 +12,7 @@ const error_factory_1 = require("../error-factory");
12
12
  const dialect_1 = require("../../../dialect");
13
13
  class TableSource extends source_1.Source {
14
14
  getSourceDef() {
15
- var _a, _b, _c;
15
+ var _a, _b;
16
16
  const info = this.getTableInfo();
17
17
  if (info === undefined) {
18
18
  return error_factory_1.ErrorFactory.structDef;
@@ -36,7 +36,6 @@ class TableSource extends source_1.Source {
36
36
  let msg = `Schema read failure for table '${tablePath}' for connection '${connectionName}'`;
37
37
  if (tableDefEntry) {
38
38
  if (tableDefEntry.status === 'present') {
39
- (_c = this.document()) === null || _c === void 0 ? void 0 : _c.checkExperimentalDialect(this, tableDefEntry.value.dialect);
40
39
  tableDefEntry.value.location = this.location;
41
40
  tableDefEntry.value.fields.forEach(field => {
42
41
  field.location = this.location;
@@ -152,6 +152,10 @@ class ImportStatement extends malloy_element_1.ListOf {
152
152
  }
153
153
  const importMe = { ...sourceEntry };
154
154
  importMe.as = dstName;
155
+ const dialect = (0, source_def_utils_1.dialectOfEntry)(importMe, importedModel);
156
+ if (dialect !== undefined) {
157
+ trans.checkExperimentalDialect(dialect, this.location);
158
+ }
155
159
  doc.setEntry(dstName, { entry: importMe, exported: false });
156
160
  // Every source the walk touched, routes included — not just the
157
161
  // persistent ones. A `#@ -persist` wrapper that adds a join is
@@ -152,13 +152,6 @@ export declare class Document extends MalloyElement implements NameSpace {
152
152
  modelDef(): ModelDef;
153
153
  getEntry(str: string): ModelEntry | undefined;
154
154
  setEntry(str: string, ent: ModelEntry): void;
155
- /**
156
- * Return an error message if this dialect is the first reference to this particular
157
- * dialect, and the dialect is marked as experimental, and we are not running tests.
158
- * @param dialect The dialect name
159
- * @returns The error message or undefined
160
- */
161
- checkExperimentalDialect(me: MalloyElement, dialect: string): void;
162
155
  private readonly dialectNameSpaces;
163
156
  getDialectNamespace(dialectName: string): NameSpace | undefined;
164
157
  }
@@ -656,9 +656,6 @@ class Document extends MalloyElement {
656
656
  if (this.globalNameSpace.getEntry(str) !== undefined) {
657
657
  this.logError('name-conflict-with-global', `Cannot redefine '${str}', which is in global namespace`);
658
658
  }
659
- if ((0, malloy_types_1.isSourceDef)(ent.entry)) {
660
- this.checkExperimentalDialect(this, ent.entry.dialect);
661
- }
662
659
  // Track if the model was modified after initialization
663
660
  if (this.didInitModel) {
664
661
  this.modelWasModified = true;
@@ -675,21 +672,6 @@ class Document extends MalloyElement {
675
672
  };
676
673
  }
677
674
  }
678
- /**
679
- * Return an error message if this dialect is the first reference to this particular
680
- * dialect, and the dialect is marked as experimental, and we are not running tests.
681
- * @param dialect The dialect name
682
- * @returns The error message or undefined
683
- */
684
- checkExperimentalDialect(me, dialect) {
685
- const t = this.translator();
686
- if (t &&
687
- t.firstReferenceToDialect(dialect) &&
688
- (0, dialect_1.getDialect)(dialect).experimental &&
689
- !t.experimentalDialectEnabled(dialect)) {
690
- me.logError('experimental-dialect-not-enabled', { dialect });
691
- }
692
- }
693
675
  getDialectNamespace(dialectName) {
694
676
  if (this.dialectNameSpaces.has(dialectName)) {
695
677
  return this.dialectNameSpaces.get(dialectName);
@@ -1,6 +1,7 @@
1
1
  import type { DocumentLocation, DocumentPosition, DocumentReference, ImportLocation, ModelDef, SourceDef, SQLSourceDef, DependencyTree, DocumentRange, VirtualMap } from '../model/malloy_types';
2
2
  import type { LogMessage, LogMessageOptions, MessageCode, MessageParameterType } from './parse-log';
3
3
  import { BaseMessageLogger } from './parse-log';
4
+ import type { FindReferencesData } from './parse-tree-walkers/find-external-references';
4
5
  import type { ZoneData } from './zone';
5
6
  import { Zone } from './zone';
6
7
  import { ReferenceList } from './reference-list';
@@ -52,7 +53,7 @@ declare class ParseStep implements TranslationStep {
52
53
  }
53
54
  declare class ImportsAndTablesStep implements TranslationStep {
54
55
  readonly parseStep: ParseStep;
55
- private parseReferences;
56
+ parseReferences: FindReferencesData | undefined;
56
57
  constructor(parseStep: ParseStep);
57
58
  step(that: MalloyTranslation): DataRequestResponse | ParseResponse;
58
59
  }
@@ -61,6 +62,16 @@ declare class ASTStep implements TranslationStep {
61
62
  response?: ASTResponse;
62
63
  private walked;
63
64
  constructor(importStep: ImportsAndTablesStep);
65
+ /**
66
+ * A file acknowledges an experimental dialect with
67
+ * `##! experimental.dialect.NAME` wherever it names a connection on that
68
+ * dialect. Every connection name in this file is already resolved to a
69
+ * dialect by the time the AST exists, and the file's compiler flags are
70
+ * known only now, so this is the first moment the check can run. The
71
+ * other place a file takes on a dialect is `import`, checked by
72
+ * `ImportStatement`.
73
+ */
74
+ private checkExperimentalDialects;
64
75
  step(that: MalloyTranslation): ASTResponse;
65
76
  }
66
77
  declare class MetadataStep implements TranslationStep {
@@ -166,8 +177,12 @@ export declare abstract class MalloyTranslation {
166
177
  rangeFromContext(pcx: ParserRuleContext): DocumentRange;
167
178
  private dialectAlreadyChecked;
168
179
  firstReferenceToDialect(dialect: string): boolean;
169
- allDialectsEnabled: boolean;
170
180
  experimentalDialectEnabled(dialect: string): boolean;
181
+ /**
182
+ * Log, once per dialect per file, that this file uses an experimental
183
+ * dialect without acknowledging it.
184
+ */
185
+ checkExperimentalDialect(dialect: string, at: DocumentLocation): void;
171
186
  }
172
187
  export declare class MalloyChildTranslator extends MalloyTranslation {
173
188
  readonly root: MalloyTranslator;
@@ -38,6 +38,7 @@ var __importStar = (this && this.__importStar) || (function () {
38
38
  })();
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.MalloyTranslator = exports.MalloyChildTranslator = exports.MalloyTranslation = void 0;
41
+ const malloy_types_1 = require("../model/malloy_types");
41
42
  const utils_1 = require("../model/utils");
42
43
  const annotation_utils_1 = require("../model/annotation_utils");
43
44
  const ast = __importStar(require("./ast"));
@@ -132,14 +133,13 @@ class ImportsAndTablesStep {
132
133
  // Register connection dialects and imports immediately. Table
133
134
  // references are deferred until dialects are resolved, because
134
135
  // validating a table path requires knowing its dialect's grammar.
135
- for (const connName in this.parseReferences.connectionDialects) {
136
+ for (const [connName, need] of this.parseReferences.connectionDialects) {
136
137
  that.root.connectionDialectZone.reference(connName, {
137
138
  url: that.sourceURL,
138
- range: this.parseReferences.connectionDialects[connName].firstReference,
139
+ range: need.firstReference,
139
140
  });
140
141
  }
141
- for (const relativeRef in this.parseReferences.urls) {
142
- const firstRef = this.parseReferences.urls[relativeRef];
142
+ for (const [relativeRef, firstRef] of this.parseReferences.urls) {
143
143
  try {
144
144
  const ref = decodeURI(new URL(relativeRef, that.importBaseURL || that.sourceURL).toString());
145
145
  that.addChild(ref);
@@ -171,8 +171,7 @@ class ImportsAndTablesStep {
171
171
  // Invalid paths are dropped here and re-reported by the AST step.
172
172
  // tableRequests feeds the missing-table loop below.
173
173
  const tableRequests = {};
174
- for (const rawKey in this.parseReferences.tables) {
175
- const info = this.parseReferences.tables[rawKey];
174
+ for (const info of this.parseReferences.tables.values()) {
176
175
  const dialectName = that.root.connectionDialectZone.get(info.connectionName);
177
176
  if (dialectName === undefined)
178
177
  continue;
@@ -204,7 +203,9 @@ class ImportsAndTablesStep {
204
203
  }
205
204
  const missingDialects = that.root.connectionDialectZone.getUndefined();
206
205
  if (missingDialects) {
207
- const connectionDialects = {};
206
+ // Keyed by connection name, user text: a plain `{}` would turn a
207
+ // connection named `__proto__` into a prototype and drop the request.
208
+ const connectionDialects = (0, malloy_types_1.mkSafeRecord)();
208
209
  for (const connName of missingDialects) {
209
210
  connectionDialects[connName] = { connectionName: connName };
210
211
  }
@@ -237,6 +238,31 @@ class ASTStep {
237
238
  this.importStep = importStep;
238
239
  this.walked = false;
239
240
  }
241
+ /**
242
+ * A file acknowledges an experimental dialect with
243
+ * `##! experimental.dialect.NAME` wherever it names a connection on that
244
+ * dialect. Every connection name in this file is already resolved to a
245
+ * dialect by the time the AST exists, and the file's compiler flags are
246
+ * known only now, so this is the first moment the check can run. The
247
+ * other place a file takes on a dialect is `import`, checked by
248
+ * `ImportStatement`.
249
+ */
250
+ checkExperimentalDialects(that) {
251
+ var _a;
252
+ const connections = (_a = this.importStep.parseReferences) === null || _a === void 0 ? void 0 : _a.connectionDialects;
253
+ if (!connections) {
254
+ return;
255
+ }
256
+ for (const [connName, need] of connections) {
257
+ const dialect = that.root.connectionDialectZone.get(connName);
258
+ if (dialect !== undefined) {
259
+ that.checkExperimentalDialect(dialect, {
260
+ url: that.sourceURL,
261
+ range: need.firstReference,
262
+ });
263
+ }
264
+ }
265
+ }
240
266
  step(that) {
241
267
  const stepTimer = new timing_1.Timer('ast_step');
242
268
  if (this.response) {
@@ -262,6 +288,7 @@ class ASTStep {
262
288
  const { ast: newAST, compilerFlagSrc, timingInfo } = secondPass.run();
263
289
  stepTimer.contribute([timingInfo]);
264
290
  that.compilerFlagSrc = compilerFlagSrc;
291
+ this.checkExperimentalDialects(that);
265
292
  if (newAST.elementType === 'unimplemented') {
266
293
  newAST.logError('untranslated-parse-node', 'INTERNAL COMPILER ERROR: Untranslated parse node');
267
294
  }
@@ -429,9 +456,9 @@ class TranslateStep {
429
456
  // seeding (e.g. TestTranslator's compilerFlags option) survive.
430
457
  if (extendingModel && !this.importedAnnotations) {
431
458
  const parseCompilerFlagsTimer = new timing_1.Timer('parse_compiler_flags');
432
- // Compiler flags from the extending base's `##` annotations. NOTE: `##!`
433
- // flag semantics are still to be settled; this keeps the existing
434
- // behavior (flags from the base model) green and is not the final design.
459
+ // `##!` is a pragma: it governs the file it sits in and does not cross
460
+ // `import`. An extension is a continuation of the base's text, so the
461
+ // base's flags are in force here.
435
462
  that.compilerFlagSrc.push(...new annotation_1.Annotations((0, annotation_utils_1.getModelAnnotations)(extendingModel)).texts('!'));
436
463
  stepTimer.contribute([parseCompilerFlagsTimer.stop()]);
437
464
  this.importedAnnotations = true;
@@ -515,7 +542,6 @@ class MalloyTranslation {
515
542
  Not sure where the logic for this needs to go, this is just my first guess
516
543
  */
517
544
  this.dialectAlreadyChecked = {};
518
- this.allDialectsEnabled = false;
519
545
  this.childTranslators = new Map();
520
546
  this.modelDef = (0, utils_1.mkModelDef)(sourceURL, (0, utils_1.mkModelID)(sourceURL));
521
547
  /**
@@ -753,13 +779,21 @@ class MalloyTranslation {
753
779
  return true;
754
780
  }
755
781
  experimentalDialectEnabled(dialect) {
756
- if (this.allDialectsEnabled) {
757
- return true;
758
- }
759
782
  const experimental = this.getCompilerFlags().tag('experimental');
760
783
  return (experimental !== undefined &&
761
784
  (experimental.bare() || experimental.has('dialect', dialect)));
762
785
  }
786
+ /**
787
+ * Log, once per dialect per file, that this file uses an experimental
788
+ * dialect without acknowledging it.
789
+ */
790
+ checkExperimentalDialect(dialect, at) {
791
+ if (this.firstReferenceToDialect(dialect) &&
792
+ (0, dialect_1.getDialect)(dialect).isExperimental() &&
793
+ !this.experimentalDialectEnabled(dialect)) {
794
+ this.root.logError('experimental-dialect-not-enabled', { dialect }, { at });
795
+ }
796
+ }
763
797
  }
764
798
  exports.MalloyTranslation = MalloyTranslation;
765
799
  class MalloyChildTranslator extends MalloyTranslation {
@@ -2,13 +2,13 @@ import type { CommonTokenStream } from 'antlr4ts';
2
2
  import type { ParseTree } from 'antlr4ts/tree';
3
3
  import type { DocumentRange } from '../../model/malloy_types';
4
4
  import type { MalloyTranslation } from '../parse-malloy';
5
- type NeedImports = Record<string, DocumentRange>;
6
- type NeedTables = Record<string, {
5
+ type NeedImports = Map<string, DocumentRange>;
6
+ type NeedTables = Map<string, {
7
7
  connectionName: string;
8
8
  tablePath: string;
9
9
  firstReference: DocumentRange;
10
10
  }>;
11
- type NeedConnectionDialects = Record<string, {
11
+ type NeedConnectionDialects = Map<string, {
12
12
  firstReference: DocumentRange;
13
13
  }>;
14
14
  export declare function constructTableKey(connectionName: string, tablePath: string): string;
@@ -32,18 +32,18 @@ class FindExternalReferences {
32
32
  constructor(trans, tokens) {
33
33
  this.trans = trans;
34
34
  this.tokens = tokens;
35
- this.needTables = {};
36
- this.needImports = {};
37
- this.needConnectionDialects = {};
35
+ this.needTables = new Map();
36
+ this.needImports = new Map();
37
+ this.needConnectionDialects = new Map();
38
38
  }
39
39
  registerTableReference(connectionName, tablePath, reference) {
40
40
  const key = constructTableKey(connectionName, tablePath);
41
- if (!this.needTables[key]) {
42
- this.needTables[key] = {
41
+ if (!this.needTables.has(key)) {
42
+ this.needTables.set(key, {
43
43
  connectionName,
44
44
  tablePath,
45
45
  firstReference: reference,
46
- };
46
+ });
47
47
  }
48
48
  }
49
49
  enterExploreTable(pcx) {
@@ -53,22 +53,23 @@ class FindExternalReferences {
53
53
  this.registerTableReference(connId, tablePath, reference);
54
54
  // Register a need for the connection's dialect so the validator in
55
55
  // ImportsAndTablesStep can run against it.
56
- if (!this.needConnectionDialects[connId]) {
57
- this.needConnectionDialects[connId] = { firstReference: reference };
56
+ this.registerConnection(connId, reference);
57
+ }
58
+ registerConnection(connId, reference) {
59
+ if (connId && !this.needConnectionDialects.has(connId)) {
60
+ this.needConnectionDialects.set(connId, { firstReference: reference });
58
61
  }
59
62
  }
63
+ enterSqlSource(pcx) {
64
+ this.registerConnection((0, parse_utils_1.getId)(pcx.connectionId()), this.trans.rangeFromContext(pcx));
65
+ }
60
66
  enterVirtualSource(pcx) {
61
- const connId = (0, parse_utils_1.getId)(pcx.connectionId());
62
- if (connId && !this.needConnectionDialects[connId]) {
63
- this.needConnectionDialects[connId] = {
64
- firstReference: this.trans.rangeFromContext(pcx),
65
- };
66
- }
67
+ this.registerConnection((0, parse_utils_1.getId)(pcx.connectionId()), this.trans.rangeFromContext(pcx));
67
68
  }
68
69
  enterImportURL(pcx) {
69
70
  const url = getPlainString(pcx);
70
- if (!this.needImports[url]) {
71
- this.needImports[url] = this.trans.rangeFromContext(pcx);
71
+ if (!this.needImports.has(url)) {
72
+ this.needImports.set(url, this.trans.rangeFromContext(pcx));
72
73
  }
73
74
  }
74
75
  }
@@ -3,6 +3,7 @@ import { MalloyElement } from '../ast';
3
3
  import type { NameSpace } from '../ast/types/name-space';
4
4
  import type { ModelEntry } from '../ast/types/model-entry';
5
5
  import { MalloyChildTranslator, MalloyTranslator } from '../parse-malloy';
6
+ import { Zone } from '../zone';
6
7
  import type { DataRequestResponse, SQLSourceRequest, TranslateResponse } from '../translate-response';
7
8
  import type { ExprValue } from '../ast/types/expr-value';
8
9
  import type { LogSeverity, MessageCode, MessageParameterType } from '../parse-log';
@@ -66,10 +67,18 @@ export interface TestTranslatorOptions {
66
67
  */
67
68
  compilerFlags?: string[];
68
69
  }
70
+ /**
71
+ * Every connection name a test mentions resolves to a dialect, as it would
72
+ * through a host's connection lookup: the four listed below to theirs, and
73
+ * any other name to `TEST_DIALECT`.
74
+ */
75
+ declare class TestConnectionDialectZone extends Zone<string> {
76
+ reference(str: string, loc: DocumentLocation): void;
77
+ }
69
78
  export declare class TestTranslator extends MalloyTranslator {
70
79
  readonly testSrc: string;
71
- allDialectsEnabled: boolean;
72
80
  testRoot?: TestRoot;
81
+ connectionDialectZone: TestConnectionDialectZone;
73
82
  internalModel: ModelDef;
74
83
  constructor(testSrc: string, options?: TestTranslatorOptions);
75
84
  translate(): TranslateResponse;
@@ -29,6 +29,7 @@ const util_1 = require("util");
29
29
  const malloy_types_1 = require("../../model/malloy_types");
30
30
  const ast_1 = require("../ast");
31
31
  const parse_malloy_1 = require("../parse-malloy");
32
+ const zone_1 = require("../zone");
32
33
  const static_space_1 = require("../ast/field-space/static-space");
33
34
  const global_name_space_1 = require("../ast/types/global-name-space");
34
35
  const sql_block_1 = require("../../model/sql_block");
@@ -336,12 +337,25 @@ class TestChildTranslator extends parse_malloy_1.MalloyChildTranslator {
336
337
  }
337
338
  exports.TestChildTranslator = TestChildTranslator;
338
339
  const testURI = 'internal://test/langtests/root.malloy';
340
+ /**
341
+ * Every connection name a test mentions resolves to a dialect, as it would
342
+ * through a host's connection lookup: the four listed below to theirs, and
343
+ * any other name to `TEST_DIALECT`.
344
+ */
345
+ class TestConnectionDialectZone extends zone_1.Zone {
346
+ reference(str, loc) {
347
+ super.reference(str, loc);
348
+ if (this.getEntry(str).status === 'reference') {
349
+ this.define(str, exports.TEST_DIALECT);
350
+ }
351
+ }
352
+ }
339
353
  class TestTranslator extends parse_malloy_1.MalloyTranslator {
340
354
  constructor(testSrc, options = {}) {
341
355
  var _a, _b, _c, _d, _e;
342
356
  super(testURI, (_a = options.importBaseURL) !== null && _a !== void 0 ? _a : null, null, (_b = options.eventStream) !== null && _b !== void 0 ? _b : null, (_c = options.restrictedMode) !== null && _c !== void 0 ? _c : false, options.virtualMap);
343
357
  this.testSrc = testSrc;
344
- this.allDialectsEnabled = true;
358
+ this.connectionDialectZone = new TestConnectionDialectZone();
345
359
  /*
346
360
  * There are four connections:
347
361
  * _db_ - duckdb dialect, with the following tables ...
@@ -225,7 +225,7 @@ function compileExpr(resultSet, context, expr, state = new utils_1.GenerateState
225
225
  return `${expr.e.sql} IS NOT NULL`;
226
226
  case 'true':
227
227
  case 'false':
228
- return expr.node;
228
+ return context.dialect.sqlBoolean(expr.node === 'true');
229
229
  case 'null':
230
230
  return 'NULL';
231
231
  case 'case':
@@ -17,8 +17,10 @@ type StageGroupMaping = {
17
17
  };
18
18
  interface StageOutputColumn {
19
19
  sql: string;
20
+ expr: string;
20
21
  name: string;
21
22
  isDimension: boolean;
23
+ constant?: boolean;
22
24
  }
23
25
  type StageOutputContext = {
24
26
  columns: StageOutputColumn[];
@@ -122,7 +124,7 @@ export declare class QueryQuery extends QueryField {
122
124
  * This ordering ensures parent arrays are ordered before child arrays.
123
125
  */
124
126
  collectArrayJoins(ji: JoinInstance): JoinInstance[];
125
- genereateSQLOrderBy(queryDef: QuerySegment, resultStruct: FieldInstanceResult): string;
127
+ genereateSQLOrderBy(queryDef: QuerySegment, resultStruct: FieldInstanceResult): string[];
126
128
  /**
127
129
  * The single-scan form, with no `group_set` fan-out: one `SELECT` over the
128
130
  * scan, grouped by the dimensions. Used both for a query with no nests and --