@malloydata/malloy 0.0.433 → 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 (74) hide show
  1. package/dist/api/foundation/compile.d.ts +2 -2
  2. package/dist/api/foundation/compile.js +8 -9
  3. package/dist/api/foundation/config.js +6 -15
  4. package/dist/api/foundation/runtime.d.ts +2 -8
  5. package/dist/api/foundation/runtime.js +11 -39
  6. package/dist/api/foundation/types.d.ts +1 -1
  7. package/dist/connection/validate_table_path.d.ts +1 -2
  8. package/dist/connection/validate_table_path.js +1 -2
  9. package/dist/dialect/databricks/databricks.js +6 -6
  10. package/dist/dialect/dialect.d.ts +35 -3
  11. package/dist/dialect/dialect.js +67 -5
  12. package/dist/dialect/dialect_map.js +2 -0
  13. package/dist/dialect/duckdb/duckdb.js +7 -21
  14. package/dist/dialect/index.d.ts +2 -1
  15. package/dist/dialect/index.js +3 -1
  16. package/dist/dialect/mysql/mysql.js +8 -8
  17. package/dist/dialect/pg_impl.js +12 -12
  18. package/dist/dialect/postgres/postgres.js +3 -3
  19. package/dist/dialect/snowflake/snowflake.js +12 -12
  20. package/dist/dialect/sqlserver/dialect_functions.d.ts +2 -0
  21. package/dist/dialect/sqlserver/dialect_functions.js +42 -0
  22. package/dist/dialect/sqlserver/function_overrides.d.ts +2 -0
  23. package/dist/dialect/sqlserver/function_overrides.js +55 -0
  24. package/dist/dialect/sqlserver/index.d.ts +1 -0
  25. package/dist/dialect/sqlserver/index.js +22 -0
  26. package/dist/dialect/sqlserver/sqlserver.d.ts +102 -0
  27. package/dist/dialect/sqlserver/sqlserver.js +538 -0
  28. package/dist/dialect/sqlserver/windows_zones.d.ts +1 -0
  29. package/dist/dialect/sqlserver/windows_zones.js +613 -0
  30. package/dist/dialect/standardsql/standardsql.d.ts +1 -1
  31. package/dist/dialect/standardsql/standardsql.js +16 -13
  32. package/dist/dialect/trino/trino.d.ts +3 -3
  33. package/dist/dialect/trino/trino.js +32 -28
  34. package/dist/index.d.ts +1 -1
  35. package/dist/index.js +5 -3
  36. package/dist/lang/ast/source-elements/named-source.js +0 -2
  37. package/dist/lang/ast/source-elements/refined-source.js +1 -1
  38. package/dist/lang/ast/source-elements/sql-source.js +2 -4
  39. package/dist/lang/ast/source-elements/table-source.js +1 -2
  40. package/dist/lang/ast/source-properties/timezone-statement.d.ts +4 -3
  41. package/dist/lang/ast/source-properties/timezone-statement.js +14 -12
  42. package/dist/lang/ast/statements/import-statement.js +4 -0
  43. package/dist/lang/ast/types/malloy-element.d.ts +0 -7
  44. package/dist/lang/ast/types/malloy-element.js +0 -18
  45. package/dist/lang/composite-source-utils.js +10 -3
  46. package/dist/lang/malloy-to-ast.js +2 -8
  47. package/dist/lang/parse-malloy.d.ts +20 -4
  48. package/dist/lang/parse-malloy.js +50 -15
  49. package/dist/lang/parse-tree-walkers/find-external-references.d.ts +3 -3
  50. package/dist/lang/parse-tree-walkers/find-external-references.js +17 -16
  51. package/dist/lang/test/test-translator.d.ts +12 -2
  52. package/dist/lang/test/test-translator.js +16 -2
  53. package/dist/model/expression_compiler.js +1 -1
  54. package/dist/model/join_instance.d.ts +1 -0
  55. package/dist/model/join_instance.js +9 -1
  56. package/dist/model/query_query.d.ts +28 -1
  57. package/dist/model/query_query.js +299 -156
  58. package/dist/model/source_def_utils.d.ts +7 -1
  59. package/dist/model/source_def_utils.js +20 -0
  60. package/dist/model/sql_block.d.ts +2 -2
  61. package/dist/model/sql_block.js +11 -47
  62. package/dist/model/sql_compiled.d.ts +3 -1
  63. package/dist/model/sql_compiled.js +8 -6
  64. package/dist/model/stage_writer.js +3 -3
  65. package/dist/model/utils.d.ts +2 -2
  66. package/dist/model/utils.js +2 -3
  67. package/dist/test/index.js +16 -8
  68. package/dist/test/matchers.d.ts +1 -1
  69. package/dist/test/matchers.js +1 -1
  70. package/dist/test/test-models.js +6 -13
  71. package/dist/version.d.ts +1 -1
  72. package/dist/version.js +1 -1
  73. package/femto-config.motly +15 -1
  74. package/package.json +7 -5
@@ -1,6 +1,7 @@
1
- import type { DocumentLocation, DocumentPosition, DocumentReference, ImportLocation, ModelDef, SourceDef, SQLSourceDef, DependencyTree, DocumentRange } from '../model/malloy_types';
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;
@@ -186,6 +201,7 @@ export declare class MalloyChildTranslator extends MalloyTranslation {
186
201
  export declare class MalloyTranslator extends MalloyTranslation {
187
202
  private readonly eventStream;
188
203
  readonly restrictedMode: boolean;
204
+ virtualMap?: VirtualMap | undefined;
189
205
  schemaZone: Zone<SourceDef>;
190
206
  importZone: Zone<string>;
191
207
  pretranslatedModels: Map<string, ModelDef>;
@@ -193,7 +209,7 @@ export declare class MalloyTranslator extends MalloyTranslation {
193
209
  connectionDialectZone: Zone<string>;
194
210
  logger: BaseMessageLogger;
195
211
  readonly root: MalloyTranslator;
196
- constructor(rootURL: string, importURL?: string | null, preload?: ParseUpdate | null, eventStream?: EventStream | null, restrictedMode?: boolean);
212
+ constructor(rootURL: string, importURL?: string | null, preload?: ParseUpdate | null, eventStream?: EventStream | null, restrictedMode?: boolean, virtualMap?: VirtualMap | undefined);
197
213
  update(dd: ParseUpdate): void;
198
214
  private lockZonesIfRestricted;
199
215
  translate(extendingModel?: ModelDef): TranslateResponse;
@@ -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 {
@@ -780,10 +814,11 @@ exports.MalloyChildTranslator = MalloyChildTranslator;
780
814
  * no need to call again, the translation is finished or error'd.
781
815
  */
782
816
  class MalloyTranslator extends MalloyTranslation {
783
- constructor(rootURL, importURL = null, preload = null, eventStream = null, restrictedMode = false) {
817
+ constructor(rootURL, importURL = null, preload = null, eventStream = null, restrictedMode = false, virtualMap) {
784
818
  super(rootURL, importURL);
785
819
  this.eventStream = eventStream;
786
820
  this.restrictedMode = restrictedMode;
821
+ this.virtualMap = virtualMap;
787
822
  this.schemaZone = new zone_1.Zone();
788
823
  this.importZone = new zone_1.Zone();
789
824
  this.pretranslatedModels = new Map();
@@ -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
  }
@@ -1,8 +1,9 @@
1
- import type { DocumentLocation, FieldDef, ModelDef, NamedModelObject, PipeSegment, Query, QueryFieldDef, StructDef, TurtleDef, SourceDef, TableSourceDef, SQLSourceDef, UserTypeDef } from '../../model/malloy_types';
1
+ import type { DocumentLocation, FieldDef, ModelDef, NamedModelObject, PipeSegment, Query, QueryFieldDef, StructDef, TurtleDef, SourceDef, TableSourceDef, SQLSourceDef, UserTypeDef, VirtualMap } from '../../model/malloy_types';
2
2
  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';
@@ -56,6 +57,7 @@ export interface TestTranslatorOptions {
56
57
  eventStream?: EventStream | null;
57
58
  internalModel?: ModelDef;
58
59
  restrictedMode?: boolean;
60
+ virtualMap?: VirtualMap;
59
61
  /**
60
62
  * Each entry is a compiler-flag tag fragment — the content that
61
63
  * would follow `##! ` in a Malloy source annotation. Rendered to
@@ -65,10 +67,18 @@ export interface TestTranslatorOptions {
65
67
  */
66
68
  compilerFlags?: string[];
67
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
+ }
68
78
  export declare class TestTranslator extends MalloyTranslator {
69
79
  readonly testSrc: string;
70
- allDialectsEnabled: boolean;
71
80
  testRoot?: TestRoot;
81
+ connectionDialectZone: TestConnectionDialectZone;
72
82
  internalModel: ModelDef;
73
83
  constructor(testSrc: string, options?: TestTranslatorOptions);
74
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
- 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);
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':
@@ -12,6 +12,7 @@ export declare class JoinInstance {
12
12
  joinFilterConditions?: QueryFieldBoolean[];
13
13
  children: JoinInstance[];
14
14
  constructor(queryStruct: QueryStruct, alias: string, parent: JoinInstance | undefined);
15
+ isSubquery(): boolean;
15
16
  parentRelationship(): 'root' | JoinRelationship;
16
17
  forceAllSymmetricCalculations(): boolean;
17
18
  getDialectFieldList(): DialectFieldList;
@@ -30,6 +30,14 @@ class JoinInstance {
30
30
  }, this.queryStruct));
31
31
  }
32
32
  }
33
+ // A filtered join whose own joins go inside its subquery, so that the
34
+ // subquery has to project them back out for anything outside to name them.
35
+ isSubquery() {
36
+ return (this.children.length > 0 &&
37
+ this.joinFilterConditions !== undefined &&
38
+ (0, malloy_types_1.isJoinedSource)(this.queryStruct.structDef) &&
39
+ this.queryStruct.dialect.supportsComplexFilteredSources);
40
+ }
33
41
  parentRelationship() {
34
42
  if (this.queryStruct.parent === undefined) {
35
43
  return 'root';
@@ -64,7 +72,7 @@ class JoinInstance {
64
72
  }
65
73
  // postgres unnest needs to know the names of the physical fields.
66
74
  getDialectFieldList() {
67
- return (0, utils_1.getDialectFieldList)(this.queryStruct.structDef);
75
+ return (0, utils_1.getDialectFieldList)(this.queryStruct.structDef, this.queryStruct.dialect);
68
76
  }
69
77
  }
70
78
  exports.JoinInstance = JoinInstance;
@@ -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[];
@@ -34,6 +36,7 @@ export declare class QueryQuery extends QueryField {
34
36
  maxDepth: number;
35
37
  maxGroupSet: number;
36
38
  rootResult: FieldInstanceResultRoot;
39
+ private packedColumns;
37
40
  resultStage: string | undefined;
38
41
  stageWriter: StageWriter | undefined;
39
42
  isJoinedSubquery: boolean;
@@ -90,6 +93,30 @@ export declare class QueryQuery extends QueryField {
90
93
  sql?: string;
91
94
  };
92
95
  generateSQLJoinBlock(stageWriter: StageWriter, ji: JoinInstance, depth: number): string;
96
+ /**
97
+ * Which column of which join a reference needs, or undefined when it needs
98
+ * none. Walking `path` from `from`, the answer is the member of the
99
+ * innermost join along it -- a record is kept whole, since a reference into
100
+ * one is a reference to the column holding it.
101
+ *
102
+ * Two kinds of path need no column. One ending at a computed field
103
+ * contributes that field's name, which is no column of the source; the
104
+ * columns the computation reads arrive as references of their own. And a
105
+ * `having:` or `calculate:` names an *output* field, so its path is rooted
106
+ * in the query's output rather than its source and need not resolve here at
107
+ * all. An output name which happens to match a source column resolves as
108
+ * though it were one, which costs nothing: a query's own source is never
109
+ * packed, only the joins beneath a filtered one.
110
+ */
111
+ private packedColumnFor;
112
+ /**
113
+ * Which columns of each join have to survive being packed into a struct:
114
+ * every column the segment's field usage names, plus each join's primary
115
+ * key, which the compiler reaches for as a distinct key without any
116
+ * expression in the query naming it.
117
+ */
118
+ private packedColumnsByJoin;
119
+ private joinProjectionFieldList;
93
120
  generateSQLPassthroughKeys(qs: QueryStruct): string;
94
121
  generateSQLJoins(stageWriter: StageWriter): string;
95
122
  /**
@@ -97,7 +124,7 @@ export declare class QueryQuery extends QueryField {
97
124
  * This ordering ensures parent arrays are ordered before child arrays.
98
125
  */
99
126
  collectArrayJoins(ji: JoinInstance): JoinInstance[];
100
- genereateSQLOrderBy(queryDef: QuerySegment, resultStruct: FieldInstanceResult): string;
127
+ genereateSQLOrderBy(queryDef: QuerySegment, resultStruct: FieldInstanceResult): string[];
101
128
  /**
102
129
  * The single-scan form, with no `group_set` fan-out: one `SELECT` over the
103
130
  * scan, grouped by the dimensions. Used both for a query with no nests and --