@malloydata/malloy 0.0.434 → 0.0.436

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 (103) hide show
  1. package/dist/api/foundation/build_targets.d.ts +5 -6
  2. package/dist/api/foundation/build_targets.js +74 -6
  3. package/dist/api/foundation/compile.d.ts +0 -1
  4. package/dist/api/foundation/compile.js +0 -3
  5. package/dist/api/foundation/core.d.ts +16 -4
  6. package/dist/api/foundation/core.js +23 -23
  7. package/dist/api/foundation/index.d.ts +1 -1
  8. package/dist/api/foundation/runtime.d.ts +21 -3
  9. package/dist/api/foundation/runtime.js +45 -54
  10. package/dist/api/foundation/types.d.ts +43 -4
  11. package/dist/connection/dbmeta.d.ts +29 -0
  12. package/dist/connection/dbmeta.js +46 -0
  13. package/dist/connection/index.d.ts +1 -0
  14. package/dist/connection/index.js +1 -0
  15. package/dist/dialect/databricks/databricks.d.ts +11 -12
  16. package/dist/dialect/databricks/databricks.js +24 -36
  17. package/dist/dialect/dialect.d.ts +70 -171
  18. package/dist/dialect/dialect.js +123 -92
  19. package/dist/dialect/dialect_map.js +2 -0
  20. package/dist/dialect/duckdb/duckdb.d.ts +2 -2
  21. package/dist/dialect/duckdb/duckdb.js +1 -1
  22. package/dist/dialect/index.d.ts +3 -2
  23. package/dist/dialect/index.js +4 -2
  24. package/dist/dialect/mysql/mysql.d.ts +11 -12
  25. package/dist/dialect/mysql/mysql.js +20 -32
  26. package/dist/dialect/pg_impl.d.ts +9 -10
  27. package/dist/dialect/pg_impl.js +27 -73
  28. package/dist/dialect/postgres/postgres.d.ts +4 -4
  29. package/dist/dialect/postgres/postgres.js +4 -12
  30. package/dist/dialect/snowflake/snowflake.d.ts +11 -13
  31. package/dist/dialect/snowflake/snowflake.js +30 -82
  32. package/dist/dialect/sqlserver/dialect_functions.d.ts +2 -0
  33. package/dist/dialect/sqlserver/dialect_functions.js +42 -0
  34. package/dist/dialect/sqlserver/function_overrides.d.ts +2 -0
  35. package/dist/dialect/sqlserver/function_overrides.js +55 -0
  36. package/dist/dialect/sqlserver/index.d.ts +1 -0
  37. package/dist/dialect/sqlserver/index.js +22 -0
  38. package/dist/dialect/sqlserver/sqlserver.d.ts +101 -0
  39. package/dist/dialect/sqlserver/sqlserver.js +537 -0
  40. package/dist/dialect/sqlserver/windows_zones.d.ts +1 -0
  41. package/dist/dialect/sqlserver/windows_zones.js +613 -0
  42. package/dist/dialect/standardsql/standardsql.d.ts +11 -16
  43. package/dist/dialect/standardsql/standardsql.js +22 -73
  44. package/dist/dialect/trino/trino.d.ts +16 -18
  45. package/dist/dialect/trino/trino.js +127 -181
  46. package/dist/index.d.ts +2 -2
  47. package/dist/index.js +6 -4
  48. package/dist/lang/ast/expressions/boolean-value.d.ts +24 -0
  49. package/dist/lang/ast/expressions/boolean-value.js +41 -0
  50. package/dist/lang/ast/expressions/case.js +7 -0
  51. package/dist/lang/ast/expressions/expr-alternation-tree.js +11 -0
  52. package/dist/lang/ast/expressions/expr-cast.js +5 -0
  53. package/dist/lang/ast/expressions/expr-coalesce.js +4 -0
  54. package/dist/lang/ast/expressions/expr-func.js +13 -2
  55. package/dist/lang/ast/expressions/expr-minus.js +5 -2
  56. package/dist/lang/ast/expressions/expr-null.js +4 -0
  57. package/dist/lang/ast/expressions/pick-when.js +7 -0
  58. package/dist/lang/ast/field-space/index-field-space.js +13 -1
  59. package/dist/lang/ast/field-space/query-spaces.js +11 -0
  60. package/dist/lang/ast/query-builders/reduce-builder.js +1 -1
  61. package/dist/lang/ast/query-items/field-declaration.d.ts +5 -0
  62. package/dist/lang/ast/query-items/field-declaration.js +22 -16
  63. package/dist/lang/ast/query-items/field-references.d.ts +6 -0
  64. package/dist/lang/ast/query-items/field-references.js +23 -0
  65. package/dist/lang/ast/query-properties/filters.js +3 -1
  66. package/dist/lang/ast/source-elements/named-source.js +0 -2
  67. package/dist/lang/ast/source-elements/sql-source.js +0 -3
  68. package/dist/lang/ast/source-elements/table-source.js +1 -2
  69. package/dist/lang/ast/statements/import-statement.js +17 -0
  70. package/dist/lang/ast/types/expression-def.js +17 -2
  71. package/dist/lang/ast/types/malloy-element.d.ts +24 -8
  72. package/dist/lang/ast/types/malloy-element.js +63 -44
  73. package/dist/lang/ast/view-elements/reference-view.js +4 -0
  74. package/dist/lang/ast/view-elements/refine-utils.js +1 -0
  75. package/dist/lang/composite-source-utils.js +10 -17
  76. package/dist/lang/parse-log.d.ts +12 -0
  77. package/dist/lang/parse-log.js +2 -0
  78. package/dist/lang/parse-malloy.d.ts +17 -2
  79. package/dist/lang/parse-malloy.js +48 -14
  80. package/dist/lang/parse-tree-walkers/find-external-references.d.ts +3 -3
  81. package/dist/lang/parse-tree-walkers/find-external-references.js +17 -16
  82. package/dist/lang/test/test-translator.d.ts +11 -1
  83. package/dist/lang/test/test-translator.js +51 -3
  84. package/dist/model/expression_compiler.js +9 -8
  85. package/dist/model/filter_compilers.js +13 -12
  86. package/dist/model/given_binding.d.ts +8 -0
  87. package/dist/model/given_binding.js +13 -0
  88. package/dist/model/index.d.ts +1 -1
  89. package/dist/model/index.js +2 -1
  90. package/dist/model/query_query.d.ts +3 -1
  91. package/dist/model/query_query.js +157 -139
  92. package/dist/model/source_def_utils.d.ts +7 -1
  93. package/dist/model/source_def_utils.js +20 -0
  94. package/dist/model/sql_compiled.d.ts +19 -20
  95. package/dist/model/sql_compiled.js +29 -17
  96. package/dist/test/index.js +16 -8
  97. package/dist/test/matchers.d.ts +1 -1
  98. package/dist/test/matchers.js +1 -1
  99. package/dist/test/test-models.js +6 -13
  100. package/dist/version.d.ts +1 -1
  101. package/dist/version.js +1 -1
  102. package/femto-config.motly +13 -1
  103. package/package.json +7 -5
@@ -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';
@@ -28,6 +29,7 @@ export declare const aTableDef: TableSourceDef;
28
29
  export declare const db2TableDef: TableSourceDef;
29
30
  export declare const bqTableDef: SourceDef;
30
31
  export declare const pgTableDef: SourceDef;
32
+ export declare const mssqlTableDef: SourceDef;
31
33
  /**
32
34
  * A TestTranlator never actually talks to connection, instead uses
33
35
  * some mocked schema definitions.
@@ -66,10 +68,18 @@ export interface TestTranslatorOptions {
66
68
  */
67
69
  compilerFlags?: string[];
68
70
  }
71
+ /**
72
+ * Every connection name a test mentions resolves to a dialect, as it would
73
+ * through a host's connection lookup: the five listed below to theirs, and
74
+ * any other name to `TEST_DIALECT`.
75
+ */
76
+ declare class TestConnectionDialectZone extends Zone<string> {
77
+ reference(str: string, loc: DocumentLocation): void;
78
+ }
69
79
  export declare class TestTranslator extends MalloyTranslator {
70
80
  readonly testSrc: string;
71
- allDialectsEnabled: boolean;
72
81
  testRoot?: TestRoot;
82
+ connectionDialectZone: TestConnectionDialectZone;
73
83
  internalModel: ModelDef;
74
84
  constructor(testSrc: string, options?: TestTranslatorOptions);
75
85
  translate(): TranslateResponse;
@@ -5,7 +5,7 @@
5
5
  * SPDX-License-Identifier: MIT
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.BetaExpression = exports.TestTranslator = exports.TestChildTranslator = exports.mockSchema = exports.pgTableDef = exports.bqTableDef = exports.db2TableDef = exports.aTableDef = exports.TEST_DIALECT = void 0;
8
+ exports.BetaExpression = exports.TestTranslator = exports.TestChildTranslator = exports.mockSchema = exports.mssqlTableDef = exports.pgTableDef = exports.bqTableDef = exports.db2TableDef = exports.aTableDef = exports.TEST_DIALECT = void 0;
9
9
  exports.pretty = pretty;
10
10
  exports.humanify = humanify;
11
11
  exports.getExplore = getExplore;
@@ -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");
@@ -193,6 +194,16 @@ exports.pgTableDef = {
193
194
  connection: '_pg_',
194
195
  fields: baseFields,
195
196
  };
197
+ // SQL Server has no boolean values (booleanType 'none'), so no column of
198
+ // its table is a boolean
199
+ exports.mssqlTableDef = {
200
+ type: 'table',
201
+ name: 'aTable',
202
+ dialect: 'sqlserver',
203
+ tablePath: 'aTable',
204
+ connection: '_mssql_',
205
+ fields: baseFields.filter(f => f.name !== 'abool'),
206
+ };
196
207
  /**
197
208
  * A TestTranlator never actually talks to connection, instead uses
198
209
  * some mocked schema definitions.
@@ -202,6 +213,7 @@ exports.mockSchema = [
202
213
  exports.db2TableDef,
203
214
  exports.bqTableDef,
204
215
  exports.pgTableDef,
216
+ exports.mssqlTableDef,
205
217
  {
206
218
  type: 'table',
207
219
  name: 'carriers',
@@ -336,14 +348,27 @@ class TestChildTranslator extends parse_malloy_1.MalloyChildTranslator {
336
348
  }
337
349
  exports.TestChildTranslator = TestChildTranslator;
338
350
  const testURI = 'internal://test/langtests/root.malloy';
351
+ /**
352
+ * Every connection name a test mentions resolves to a dialect, as it would
353
+ * through a host's connection lookup: the five listed below to theirs, and
354
+ * any other name to `TEST_DIALECT`.
355
+ */
356
+ class TestConnectionDialectZone extends zone_1.Zone {
357
+ reference(str, loc) {
358
+ super.reference(str, loc);
359
+ if (this.getEntry(str).status === 'reference') {
360
+ this.define(str, exports.TEST_DIALECT);
361
+ }
362
+ }
363
+ }
339
364
  class TestTranslator extends parse_malloy_1.MalloyTranslator {
340
365
  constructor(testSrc, options = {}) {
341
366
  var _a, _b, _c, _d, _e;
342
367
  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
368
  this.testSrc = testSrc;
344
- this.allDialectsEnabled = true;
369
+ this.connectionDialectZone = new TestConnectionDialectZone();
345
370
  /*
346
- * There are four connections:
371
+ * There are five connections:
347
372
  * _db_ - duckdb dialect, with the following tables ...
348
373
  * aTable, malloytest.carriers, malloytest.flights, malloytest.airports
349
374
  * _db2_ - duckdb dialect, with one table, aTable. A second connection
@@ -352,6 +377,8 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
352
377
  * aTable
353
378
  * _pg_ - postgres dialect, with one table
354
379
  * aTable
380
+ * _mssql_ - sqlserver dialect, which has no boolean values, with one
381
+ * table, aTable
355
382
  *
356
383
  * The "aTable" table is a mocked table with one column of each type.
357
384
  * The _bq_ version does not have the timestamptz column, and when
@@ -380,6 +407,7 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
380
407
  _db2_: { type: 'connection', name: '_db2_' },
381
408
  _bq_: { type: 'connection', name: '_bq_' },
382
409
  _pg_: { type: 'connection', name: '_pg_' },
410
+ _mssql_: { type: 'connection', name: '_mssql_' },
383
411
  a: { ...exports.aTableDef, primaryKey: 'astr', name: 'a' },
384
412
  b: { ...exports.aTableDef, primaryKey: 'astr', name: 'b' },
385
413
  bq_a: { ...exports.bqTableDef, primaryKey: 'astr', name: 'bq_a' },
@@ -437,6 +465,7 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
437
465
  this.connectionDialectZone.define('_db2_', exports.TEST_DIALECT);
438
466
  this.connectionDialectZone.define('_bq_', 'standardsql');
439
467
  this.connectionDialectZone.define('_pg_', 'postgres');
468
+ this.connectionDialectZone.define('_mssql_', 'sqlserver');
440
469
  for (const flag of (_e = options.compilerFlags) !== null && _e !== void 0 ? _e : []) {
441
470
  this.compilerFlagSrc.push(`##! ${flag}\n`);
442
471
  }
@@ -644,10 +673,29 @@ function makeModelFunc(options) {
644
673
  const { prefix, wrap, ...ttOptions } = options;
645
674
  return {
646
675
  ...ms,
676
+ // A marked location is where the mark sits in the whole source, after
677
+ // the prefix. A wrap could put the code anywhere, so marks stay as
678
+ // they are.
679
+ locations: wrap ? ms.locations : ms.locations.map(l => after(prefix, l)),
647
680
  translator: new TestTranslator((prefix !== null && prefix !== void 0 ? prefix : '') + (wrap ? wrap(ms.code) : ms.code), ttOptions),
648
681
  };
649
682
  };
650
683
  }
684
+ function after(prefix, l) {
685
+ if (!prefix)
686
+ return l;
687
+ const lines = prefix.split('\n');
688
+ const dLine = lines.length - 1;
689
+ const dChar = lines[dLine].length;
690
+ const shift = (p) => ({
691
+ line: p.line + dLine,
692
+ character: p.line === 0 ? p.character + dChar : p.character,
693
+ });
694
+ return {
695
+ ...l,
696
+ range: { start: shift(l.range.start), end: shift(l.range.end) },
697
+ };
698
+ }
651
699
  function makeExprFunc(model, sourceName = 'ab', options = {}) {
652
700
  return function expr(unmarked, ...marked) {
653
701
  const ms = markSource(unmarked, ...marked);
@@ -109,7 +109,7 @@ function compileExpr(resultSet, context, expr, state = new utils_1.GenerateState
109
109
  return expr;
110
110
  }
111
111
  const sql = (() => {
112
- var _a;
112
+ var _a, _b;
113
113
  switch (expr.node) {
114
114
  case 'field':
115
115
  return generateFieldFragment(resultSet, context, expr, state);
@@ -176,7 +176,7 @@ function compileExpr(resultSet, context, expr, state = new utils_1.GenerateState
176
176
  // Malloy inequality comparisons always return a boolean
177
177
  case '!=': {
178
178
  const notEqual = `${expr.kids.left.sql}!=${expr.kids.right.sql}`;
179
- return `COALESCE(${notEqual},true)`;
179
+ return context.dialect.sqlNullIsTrue(notEqual);
180
180
  }
181
181
  case 'and':
182
182
  case 'or':
@@ -192,13 +192,13 @@ function compileExpr(resultSet, context, expr, state = new utils_1.GenerateState
192
192
  // null binding collapses to empty-set semantics — not the SQL
193
193
  // `IN (NULL)` shape, which has confusing NULL-membership rules.
194
194
  if (bound.node === 'null') {
195
- return expr.not ? 'TRUE' : 'FALSE';
195
+ return context.dialect.sqlBoolean(expr.not);
196
196
  }
197
197
  if (bound.node !== 'arrayLiteral') {
198
198
  throw new Error(`Internal compiler error: 'inGiven' bound to '${bound.node}', expected 'arrayLiteral'. The translator should have rejected a non-array given here.`);
199
199
  }
200
200
  if (bound.kids.values.length === 0) {
201
- return expr.not ? 'TRUE' : 'FALSE';
201
+ return context.dialect.sqlBoolean(expr.not);
202
202
  }
203
203
  const elemSqls = bound.kids.values.map(v => exprToSQL(resultSet, context, v, state));
204
204
  const verb = expr.not ? 'NOT IN' : 'IN';
@@ -210,13 +210,14 @@ function compileExpr(resultSet, context, expr, state = new utils_1.GenerateState
210
210
  const compare = expr.kids.right.node === 'stringLiteral'
211
211
  ? context.dialect.sqlLike(likeIt, (_a = expr.kids.left.sql) !== null && _a !== void 0 ? _a : '', expr.kids.right.literal)
212
212
  : `${expr.kids.left.sql} ${likeIt} ${expr.kids.right.sql}`;
213
- return expr.node === 'like' ? compare : `COALESCE(${compare},true)`;
213
+ return expr.node === 'like'
214
+ ? compare
215
+ : context.dialect.sqlNullIsTrue(compare);
214
216
  }
215
217
  case '()':
216
218
  return `(${expr.e.sql})`;
217
219
  case 'not':
218
- // Malloy not operator always returns a boolean
219
- return `COALESCE(NOT ${expr.e.sql},TRUE)`;
220
+ return context.dialect.sqlNot((_b = expr.e.sql) !== null && _b !== void 0 ? _b : '');
220
221
  case 'unary-':
221
222
  return `-${expr.e.sql}`;
222
223
  case 'is-null':
@@ -225,7 +226,7 @@ function compileExpr(resultSet, context, expr, state = new utils_1.GenerateState
225
226
  return `${expr.e.sql} IS NOT NULL`;
226
227
  case 'true':
227
228
  case 'false':
228
- return expr.node;
229
+ return context.dialect.sqlBoolean(expr.node === 'true');
229
230
  case 'null':
230
231
  return 'NULL';
231
232
  case 'case':
@@ -34,13 +34,13 @@ function unlike(disLiked, x) {
34
34
  // The `none` filter ("always false") compiles to a constant, independent of
35
35
  // column type or value; `not none` is "always true". Shared by the top-level
36
36
  // guard and every per-type compiler so the constant lives in one place.
37
- function noneToSQL(not) {
38
- return not ? 'true' : 'false';
37
+ function noneToSQL(not, d) {
38
+ return d.sqlBoolean(not === true);
39
39
  }
40
40
  exports.FilterCompilers = {
41
41
  compile(t, c, x, d, qi = {}) {
42
42
  if (c === null) {
43
- return 'true';
43
+ return d.sqlBoolean(true);
44
44
  }
45
45
  // `none` is the always-false filter (companion to the empty/`null` filter,
46
46
  // which is always-true above). It compiles to a constant independent of
@@ -48,7 +48,7 @@ exports.FilterCompilers = {
48
48
  // also the primary path for boolean, whose compiler has no switch and
49
49
  // would otherwise route `none` through the null/false truth-table.
50
50
  if (c.operator === 'none') {
51
- return noneToSQL(c.not);
51
+ return noneToSQL(c.not, d);
52
52
  }
53
53
  if (t === 'string' && (0, malloy_filter_1.isStringFilter)(c)) {
54
54
  return exports.FilterCompilers.stringCompile(c, x, d);
@@ -102,7 +102,7 @@ exports.FilterCompilers = {
102
102
  case 'null':
103
103
  return nc.not ? `${x} IS NOT NULL` : `${x} IS NULL`;
104
104
  case 'none':
105
- return noneToSQL(nc.not);
105
+ return noneToSQL(nc.not, d);
106
106
  case '()': {
107
107
  const wrapped = '(' + exports.FilterCompilers.numberCompile(nc.expr, x, d) + ')';
108
108
  return nc.not ? `NOT ${wrapped}` : wrapped;
@@ -135,7 +135,7 @@ exports.FilterCompilers = {
135
135
  // Normally intercepted by compile()'s top-level guard; handled here too so
136
136
  // booleanCompile is self-safe (this if-chain has no default, and `none`
137
137
  // must not fall through to the null/false truth-table below).
138
- return noneToSQL(bc.not);
138
+ return noneToSQL(bc.not, d);
139
139
  }
140
140
  else if (bc.operator === '=true') {
141
141
  return bc.not ? `NOT ${px}` : x;
@@ -172,7 +172,7 @@ exports.FilterCompilers = {
172
172
  case 'null':
173
173
  return sc.not ? `${x} IS NOT NULL` : `${x} IS NULL`;
174
174
  case 'none':
175
- return noneToSQL(sc.not);
175
+ return noneToSQL(sc.not, d);
176
176
  case 'empty':
177
177
  return sc.not ? `COALESCE(${x},'') != ''` : `COALESCE(${x},'') = ''`;
178
178
  case '=': {
@@ -267,7 +267,7 @@ exports.FilterCompilers = {
267
267
  }
268
268
  }
269
269
  if ((includeEmpty && excludeEmpty) || (includeNull && excludeNull)) {
270
- return 'false';
270
+ return d.sqlBoolean(false);
271
271
  }
272
272
  let includeSQL = '';
273
273
  if (includes.length > 0 || includeNull || includeEmpty) {
@@ -298,7 +298,7 @@ exports.FilterCompilers = {
298
298
  ? `(${includeSQL}) AND (${excludeSQL})`
299
299
  : includeSQL;
300
300
  }
301
- return excludeSQL !== '' ? excludeSQL : 'true';
301
+ return excludeSQL !== '' ? excludeSQL : d.sqlBoolean(true);
302
302
  }
303
303
  }
304
304
  },
@@ -331,7 +331,7 @@ class TemporalFilterCompiler {
331
331
  if (this.timetype !== 'date') {
332
332
  return timeSQL;
333
333
  }
334
- return this.d.sqlCast({}, {
334
+ const toDate = {
335
335
  node: 'cast',
336
336
  e: {
337
337
  node: 'genericSQLExpr',
@@ -342,7 +342,8 @@ class TemporalFilterCompiler {
342
342
  srcType: { type: 'timestamp' },
343
343
  dstType: { type: 'date' },
344
344
  safe: false,
345
- });
345
+ };
346
+ return this.d.sqlTimeCast(this.qi, toDate);
346
347
  }
347
348
  compile(tc) {
348
349
  const x = this.expr;
@@ -421,7 +422,7 @@ class TemporalFilterCompiler {
421
422
  case 'null':
422
423
  return tc.not ? `${x} IS NOT NULL` : `${x} IS NULL`;
423
424
  case 'none':
424
- return noneToSQL(tc.not);
425
+ return noneToSQL(tc.not, this.d);
425
426
  case '()': {
426
427
  const wrapped = '(' + this.compile(tc.expr) + ')';
427
428
  return tc.not ? `NOT ${wrapped}` : wrapped;
@@ -27,3 +27,11 @@ export declare function resolveSuppliedGivens(supplied: Record<string, GivenValu
27
27
  * `resolveGiven`), which needs no ordering.
28
28
  */
29
29
  export declare function evaluateInlineGivens(bound: Map<GivenID, Expr>, modelDef: ModelDef | undefined): Map<GivenID, Expr>;
30
+ /**
31
+ * Binds the givens a compile runs under: the supplied values, then each
32
+ * `inline` given's default folded against them. Queries and persistence builds
33
+ * both bind here, so the same values always compile to the same SQL and a
34
+ * persisted table's key is the key a query recomputes. Undefined when nothing
35
+ * binds, which the compiler reads as "no givens".
36
+ */
37
+ export declare function bindGivens(supplied: Record<string, GivenValue> | undefined, modelDef: ModelDef | undefined): Map<GivenID, Expr> | undefined;
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.lookupGivenValue = lookupGivenValue;
8
8
  exports.resolveSuppliedGivens = resolveSuppliedGivens;
9
9
  exports.evaluateInlineGivens = evaluateInlineGivens;
10
+ exports.bindGivens = bindGivens;
10
11
  const luxon_1 = require("luxon");
11
12
  const closest_match_1 = require("../util/closest_match");
12
13
  const inline_expr_1 = require("./inline_expr");
@@ -106,6 +107,18 @@ function evaluateInlineGivens(bound, modelDef) {
106
107
  }
107
108
  return bound;
108
109
  }
110
+ /**
111
+ * Binds the givens a compile runs under: the supplied values, then each
112
+ * `inline` given's default folded against them. Queries and persistence builds
113
+ * both bind here, so the same values always compile to the same SQL and a
114
+ * persisted table's key is the key a query recomputes. Undefined when nothing
115
+ * binds, which the compiler reads as "no givens".
116
+ */
117
+ function bindGivens(supplied, modelDef) {
118
+ const bound = resolveSuppliedGivens(supplied, modelDef);
119
+ evaluateInlineGivens(bound, modelDef);
120
+ return bound.size > 0 ? bound : undefined;
121
+ }
109
122
  function valueToExpr(path, type, value) {
110
123
  var _a, _b;
111
124
  if (value === null) {
@@ -7,7 +7,7 @@ export { getResultStructDefForQuery, getResultStructDefForView, } from './query_
7
7
  export { indent, composeSQLExpr, makeDigest, mkModelDef, mkModelID, pathToKey, typeDefToString, } from './utils';
8
8
  export { getModelAnnotations } from './annotation_utils';
9
9
  export { constantExprToSQL } from './constant_expression_compiler';
10
- export { getCompiledSQL, buildIdOptions } from './sql_compiled';
10
+ export { getCompiledSQL, buildIdOptions, givenUsageOfRelation, } from './sql_compiled';
11
11
  export type { BuildIdOptions } from './sql_compiled';
12
12
  export { MalloyCompileError } from './malloy_compile_error';
13
13
  export { mkSourceID, mkBuildID, mkQuerySourceDef, mkSQLSourceDef, mkTableSourceDef, resolveSourceID, resolveSourceRef, sourceNamespaceReference, registerSource, hasSourceRegistryEntry, } from './source_def_utils';
@@ -18,7 +18,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
18
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.hasSourceRegistryEntry = exports.registerSource = exports.sourceNamespaceReference = exports.resolveSourceRef = exports.resolveSourceID = exports.mkTableSourceDef = exports.mkSQLSourceDef = exports.mkQuerySourceDef = exports.mkBuildID = exports.mkSourceID = exports.MalloyCompileError = exports.buildIdOptions = exports.getCompiledSQL = exports.constantExprToSQL = exports.getModelAnnotations = exports.typeDefToString = exports.pathToKey = exports.mkModelID = exports.mkModelDef = exports.makeDigest = exports.composeSQLExpr = exports.indent = exports.getResultStructDefForView = exports.getResultStructDefForQuery = exports.QueryModel = exports.QueryQuery = exports.QueryStruct = exports.QueryField = void 0;
21
+ exports.hasSourceRegistryEntry = exports.registerSource = exports.sourceNamespaceReference = exports.resolveSourceRef = exports.resolveSourceID = exports.mkTableSourceDef = exports.mkSQLSourceDef = exports.mkQuerySourceDef = exports.mkBuildID = exports.mkSourceID = exports.MalloyCompileError = exports.givenUsageOfRelation = exports.buildIdOptions = exports.getCompiledSQL = exports.constantExprToSQL = exports.getModelAnnotations = exports.typeDefToString = exports.pathToKey = exports.mkModelID = exports.mkModelDef = exports.makeDigest = exports.composeSQLExpr = exports.indent = exports.getResultStructDefForView = exports.getResultStructDefForQuery = exports.QueryModel = exports.QueryQuery = exports.QueryStruct = exports.QueryField = void 0;
22
22
  __exportStar(require("./malloy_types"), exports);
23
23
  const query_node_1 = require("./query_node");
24
24
  Object.defineProperty(exports, "QueryField", { enumerable: true, get: function () { return query_node_1.QueryField; } });
@@ -52,6 +52,7 @@ Object.defineProperty(exports, "constantExprToSQL", { enumerable: true, get: fun
52
52
  var sql_compiled_1 = require("./sql_compiled");
53
53
  Object.defineProperty(exports, "getCompiledSQL", { enumerable: true, get: function () { return sql_compiled_1.getCompiledSQL; } });
54
54
  Object.defineProperty(exports, "buildIdOptions", { enumerable: true, get: function () { return sql_compiled_1.buildIdOptions; } });
55
+ Object.defineProperty(exports, "givenUsageOfRelation", { enumerable: true, get: function () { return sql_compiled_1.givenUsageOfRelation; } });
55
56
  var malloy_compile_error_1 = require("./malloy_compile_error");
56
57
  Object.defineProperty(exports, "MalloyCompileError", { enumerable: true, get: function () { return malloy_compile_error_1.MalloyCompileError; } });
57
58
  var source_def_utils_1 = require("./source_def_utils");
@@ -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 --