@malloydata/malloy 0.0.146 → 0.0.147-dev240521202508

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.
@@ -46,6 +46,7 @@ export declare abstract class Dialect {
46
46
  abstract supportsQualify: boolean;
47
47
  abstract supportsSafeCast: boolean;
48
48
  abstract supportsNesting: boolean;
49
+ abstract experimental: boolean;
49
50
  cantPartitionWindowFunctionsOnExpressions: boolean;
50
51
  supportsPipelinesInViews: boolean;
51
52
  supportsArraysInData: boolean;
@@ -3,6 +3,7 @@ import { DialectFunctionOverloadDef } from '../functions';
3
3
  import { Dialect, DialectFieldList, QueryInfo } from '../dialect';
4
4
  export declare class DuckDBDialect extends Dialect {
5
5
  name: string;
6
+ experimental: boolean;
6
7
  defaultNumberType: string;
7
8
  defaultDecimalType: string;
8
9
  hasFinalStage: boolean;
@@ -56,6 +56,7 @@ class DuckDBDialect extends dialect_1.Dialect {
56
56
  constructor() {
57
57
  super(...arguments);
58
58
  this.name = 'duckdb';
59
+ this.experimental = false;
59
60
  this.defaultNumberType = 'DOUBLE';
60
61
  this.defaultDecimalType = 'NUMERIC';
61
62
  this.hasFinalStage = false;
@@ -21,6 +21,7 @@ export declare class PostgresDialect extends Dialect {
21
21
  supportsQualify: boolean;
22
22
  globalFunctions: import("../functions/function_map").FunctionMap;
23
23
  supportsNesting: boolean;
24
+ experimental: boolean;
24
25
  readsNestedData: boolean;
25
26
  quoteTablePath(tablePath: string): string;
26
27
  sqlGroupSetTable(groupSetCount: number): string;
@@ -93,6 +93,7 @@ class PostgresDialect extends dialect_1.Dialect {
93
93
  this.supportsQualify = false;
94
94
  this.globalFunctions = functions_1.POSTGRES_FUNCTIONS;
95
95
  this.supportsNesting = true;
96
+ this.experimental = false;
96
97
  this.readsNestedData = false;
97
98
  }
98
99
  quoteTablePath(tablePath) {
@@ -3,6 +3,7 @@ import { DialectFunctionOverloadDef } from '../functions';
3
3
  import { Dialect, DialectFieldList, QueryInfo } from '../dialect';
4
4
  export declare class SnowflakeDialect extends Dialect {
5
5
  name: string;
6
+ experimental: boolean;
6
7
  defaultNumberType: string;
7
8
  defaultDecimalType: string;
8
9
  udfPrefix: string;
@@ -75,6 +75,7 @@ class SnowflakeDialect extends dialect_1.Dialect {
75
75
  constructor() {
76
76
  super(...arguments);
77
77
  this.name = 'snowflake';
78
+ this.experimental = false;
78
79
  this.defaultNumberType = 'NUMBER';
79
80
  this.defaultDecimalType = 'NUMBER';
80
81
  this.udfPrefix = '__udf';
@@ -3,6 +3,7 @@ import { DialectFunctionOverloadDef } from '../functions';
3
3
  import { Dialect, DialectFieldList, QueryInfo } from '../dialect';
4
4
  export declare class StandardSQLDialect extends Dialect {
5
5
  name: string;
6
+ experimental: boolean;
6
7
  defaultNumberType: string;
7
8
  defaultDecimalType: string;
8
9
  udfPrefix: string;
@@ -77,6 +77,7 @@ class StandardSQLDialect extends dialect_1.Dialect {
77
77
  constructor() {
78
78
  super(...arguments);
79
79
  this.name = 'standardsql';
80
+ this.experimental = false;
80
81
  this.defaultNumberType = 'FLOAT64';
81
82
  this.defaultDecimalType = 'NUMERIC';
82
83
  this.udfPrefix = '__udf';
@@ -3,6 +3,7 @@ import { DialectFunctionOverloadDef } from '../functions';
3
3
  import { Dialect, DialectFieldList, OrderByClauseType, QueryInfo } from '../dialect';
4
4
  export declare class TrinoDialect extends Dialect {
5
5
  name: string;
6
+ experimental: boolean;
6
7
  defaultNumberType: string;
7
8
  defaultDecimalType: string;
8
9
  udfPrefix: string;
@@ -59,6 +59,7 @@ class TrinoDialect extends dialect_1.Dialect {
59
59
  constructor() {
60
60
  super(...arguments);
61
61
  this.name = 'trino';
62
+ this.experimental = false;
62
63
  this.defaultNumberType = 'DOUBLE';
63
64
  this.defaultDecimalType = 'DECIMAL';
64
65
  this.udfPrefix = '__udf';
@@ -66,6 +66,7 @@ class NamedSource extends source_1.Source {
66
66
  return this.refName;
67
67
  }
68
68
  modelStruct() {
69
+ var _a;
69
70
  const modelEnt = this.modelEntry(this.ref);
70
71
  const entry = modelEnt === null || modelEnt === void 0 ? void 0 : modelEnt.entry;
71
72
  if (!entry) {
@@ -89,6 +90,9 @@ class NamedSource extends source_1.Source {
89
90
  this.log(`Must use 'from_sql()' for sql source '${this.refName}'`);
90
91
  return;
91
92
  }
93
+ else {
94
+ (_a = this.document()) === null || _a === void 0 ? void 0 : _a.checkExperimentalDialect(this, entry.dialect);
95
+ }
92
96
  return { ...entry };
93
97
  }
94
98
  structDef() {
@@ -82,6 +82,9 @@ class SQLSource extends source_1.Source {
82
82
  partialModel: this.select.containsQueries ? doc.modelDef() : undefined,
83
83
  };
84
84
  }
85
+ else if (lookup.status === 'present') {
86
+ doc.checkExperimentalDialect(this, lookup.value.dialect);
87
+ }
85
88
  }
86
89
  structDef() {
87
90
  var _a;
@@ -28,7 +28,7 @@ const source_1 = require("./source");
28
28
  const error_factory_1 = require("../error-factory");
29
29
  class TableSource extends source_1.Source {
30
30
  structDef() {
31
- var _a, _b;
31
+ var _a, _b, _c;
32
32
  const info = this.getTableInfo();
33
33
  if (info === undefined) {
34
34
  return error_factory_1.ErrorFactory.structDef;
@@ -39,6 +39,7 @@ class TableSource extends source_1.Source {
39
39
  let msg = `Schema read failure for table '${tablePath}' for connection '${connectionName}'`;
40
40
  if (tableDefEntry) {
41
41
  if (tableDefEntry.status === 'present') {
42
+ (_b = this.document()) === null || _b === void 0 ? void 0 : _b.checkExperimentalDialect(this, tableDefEntry.value.dialect);
42
43
  tableDefEntry.value.location = this.location;
43
44
  tableDefEntry.value.fields.forEach(field => {
44
45
  field.location = this.location;
@@ -51,7 +52,7 @@ class TableSource extends source_1.Source {
51
52
  })),
52
53
  location: this.location,
53
54
  };
54
- (_b = this.document()) === null || _b === void 0 ? void 0 : _b.rememberToAddModelAnnotations(ret);
55
+ (_c = this.document()) === null || _c === void 0 ? void 0 : _c.rememberToAddModelAnnotations(ret);
55
56
  return ret;
56
57
  }
57
58
  if (tableDefEntry.status === 'error') {
@@ -133,5 +133,12 @@ export declare class Document extends MalloyElement implements NameSpace {
133
133
  defineSQL(sql: SQLBlockStructDef, name?: string): boolean;
134
134
  getEntry(str: string): ModelEntry;
135
135
  setEntry(str: string, ent: ModelEntry): void;
136
+ /**
137
+ * Return an error message if this dialect is the first reference to this particular
138
+ * dialect, and the dialect is marked as experimental, and we are not running tests.
139
+ * @param dialect The dialect name
140
+ * @returns The error message or undefined
141
+ */
142
+ checkExperimentalDialect(me: MalloyElement, dialect: string): void;
136
143
  }
137
144
  export {};
@@ -23,6 +23,7 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.Document = exports.DocStatementList = exports.ListOf = exports.isDocStatementOrDocStatementList = exports.isDocStatement = exports.ExperimentalExperiment = exports.ModelEntryReference = exports.Unimplemented = exports.MalloyElement = void 0;
26
+ const dialect_1 = require("../../../dialect");
26
27
  const malloy_types_1 = require("../../../model/malloy_types");
27
28
  const tags_1 = require("../../../tags");
28
29
  const global_name_space_1 = require("./global-name-space");
@@ -546,8 +547,26 @@ class Document extends MalloyElement {
546
547
  if (this.globalNameSpace.getEntry(str) !== undefined) {
547
548
  this.log(`Cannot redefine '${str}', which is in global namespace`);
548
549
  }
550
+ if (ent.entry.type === 'struct') {
551
+ this.checkExperimentalDialect(this, ent.entry.dialect);
552
+ }
549
553
  this.documentModel[str] = ent;
550
554
  }
555
+ /**
556
+ * Return an error message if this dialect is the first reference to this particular
557
+ * dialect, and the dialect is marked as experimental, and we are not running tests.
558
+ * @param dialect The dialect name
559
+ * @returns The error message or undefined
560
+ */
561
+ checkExperimentalDialect(me, dialect) {
562
+ const t = this.translator();
563
+ if (t &&
564
+ t.firstReferenceToDialect(dialect) &&
565
+ (0, dialect_1.getDialect)(dialect).experimental &&
566
+ !t.experimentalDialectEnabled(dialect)) {
567
+ me.log(`Requires compiler flag '##! experimental.dialect.${dialect}'`, 'error');
568
+ }
569
+ }
551
570
  }
552
571
  exports.Document = Document;
553
572
  //# sourceMappingURL=malloy-element.js.map
@@ -156,6 +156,10 @@ export declare abstract class MalloyTranslation {
156
156
  rangeFromContext(pcx: ParserRuleContext): DocumentRange;
157
157
  rangeFromTokens(startToken: Token, stopToken: Token): DocumentRange;
158
158
  rangeFromToken(token: Token): DocumentRange;
159
+ private dialectAlreadyChecked;
160
+ firstReferenceToDialect(dialect: string): boolean;
161
+ allDialectsEnabled: boolean;
162
+ experimentalDialectEnabled(dialect: string): boolean;
159
163
  }
160
164
  export declare class MalloyChildTranslator extends MalloyTranslation {
161
165
  readonly root: MalloyTranslator;
@@ -519,6 +519,18 @@ class MalloyTranslation {
519
519
  this.sqlBlocks = [];
520
520
  this.imports = [];
521
521
  this.compilerFlags = new tags_1.Tag();
522
+ /*
523
+ Experimental dialect support, not confident this is how this should work.
524
+
525
+ To prevent cascading errors, each translator will only warn once about use of an experimental dialect.
526
+
527
+ To enable tests to run without having to enabled experimental dialects, there is a hook here for
528
+ the owner of a Translator object to decide if we check the experimental flag.
529
+
530
+ Not sure where the logic for this needs to go, this is just my first guess
531
+ */
532
+ this.dialectAlreadyChecked = {};
533
+ this.allDialectsEnabled = false;
522
534
  this.childTranslators = new Map();
523
535
  this.modelDef = {
524
536
  name: sourceURL,
@@ -748,6 +760,21 @@ class MalloyTranslation {
748
760
  rangeFromToken(token) {
749
761
  return this.rangeFromTokens(token, token);
750
762
  }
763
+ firstReferenceToDialect(dialect) {
764
+ if (this.dialectAlreadyChecked[dialect]) {
765
+ return false;
766
+ }
767
+ this.dialectAlreadyChecked[dialect] = true;
768
+ return true;
769
+ }
770
+ experimentalDialectEnabled(dialect) {
771
+ if (this.allDialectsEnabled) {
772
+ return true;
773
+ }
774
+ const experimental = this.compilerFlags.tag('experimental');
775
+ return (experimental !== undefined &&
776
+ (experimental.bare() || experimental.has('dialect', dialect)));
777
+ }
751
778
  }
752
779
  exports.MalloyTranslation = MalloyTranslation;
753
780
  class MalloyChildTranslator extends MalloyTranslation {
@@ -28,7 +28,7 @@ const sql_block_1 = require("../../model/sql_block");
28
28
  const test_translator_1 = require("./test-translator");
29
29
  require("./parse-expects");
30
30
  const parse_malloy_1 = require("../parse-malloy");
31
- describe('sql blocks in malloy', () => {
31
+ describe('connection sql()', () => {
32
32
  const selStmt = 'SELECT * FROM aTable';
33
33
  function makeSchemaResponse(sql) {
34
34
  const cname = sql.connection || 'bigquery';
@@ -142,7 +142,7 @@ describe('sql blocks in malloy', () => {
142
142
  const model = new test_translator_1.TestTranslator(`
143
143
  source: sql_block is aConnection.sql("""${selStmt}""")
144
144
  source: malloy_source is sql_block extend { primary_key: ai }
145
- `);
145
+ `);
146
146
  const sql = (0, sql_block_1.makeSQLBlock)([{ sql: selStmt }], 'aConnection');
147
147
  model.update({ compileSQL: { [sql.name]: makeSchemaResponse(sql) } });
148
148
  expect(model).toTranslate();
@@ -26,6 +26,7 @@ export declare class TestChildTranslator extends MalloyChildTranslator {
26
26
  }
27
27
  export declare class TestTranslator extends MalloyTranslator {
28
28
  readonly testSrc: string;
29
+ allDialectsEnabled: boolean;
29
30
  testRoot?: TestRoot;
30
31
  internalModel: ModelDef;
31
32
  constructor(testSrc: string, importBaseURL?: string | null, rootRule?: string, internalModel?: ModelDef);
@@ -207,6 +207,7 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
207
207
  constructor(testSrc, importBaseURL = null, rootRule = 'malloyDocument', internalModel) {
208
208
  super(testURI, importBaseURL);
209
209
  this.testSrc = testSrc;
210
+ this.allDialectsEnabled = true;
210
211
  /*
211
212
  * All test source files can assume that an import of this
212
213
  * model has already happened.
package/dist/malloy.d.ts CHANGED
@@ -14,6 +14,7 @@ export interface Loggable {
14
14
  }
15
15
  export interface ParseOptions {
16
16
  importBaseURL?: URL;
17
+ testEnvironment?: boolean;
17
18
  }
18
19
  export interface CompileOptions {
19
20
  refreshSchemaCache?: boolean | number;
@@ -690,6 +691,7 @@ export declare class ExploreField extends Explore {
690
691
  * An environment for compiling and running Malloy queries.
691
692
  */
692
693
  export declare class Runtime {
694
+ isTestRuntime: boolean;
693
695
  private _urlReader;
694
696
  private _connections;
695
697
  constructor(runtime: LookupConnection<Connection> & URLReader);
package/dist/malloy.js CHANGED
@@ -50,6 +50,9 @@ class Malloy {
50
50
  const translator = new lang_1.MalloyTranslator(url.toString(), importBaseURL.toString(), {
51
51
  urls: { [url.toString()]: source },
52
52
  });
53
+ if (options === null || options === void 0 ? void 0 : options.testEnvironment) {
54
+ translator.allDialectsEnabled = true;
55
+ }
53
56
  return new Parse(translator);
54
57
  }
55
58
  static parse({ url, urlReader, source, options, }) {
@@ -1490,6 +1493,7 @@ exports.ExploreField = ExploreField;
1490
1493
  */
1491
1494
  class Runtime {
1492
1495
  constructor(...args) {
1496
+ this.isTestRuntime = false;
1493
1497
  let urlReader;
1494
1498
  let connections;
1495
1499
  for (const arg of args) {
@@ -1535,6 +1539,14 @@ class Runtime {
1535
1539
  */
1536
1540
  loadModel(source, options) {
1537
1541
  const { refreshSchemaCache, noThrowOnError } = options || {};
1542
+ if (this.isTestRuntime) {
1543
+ if (options === undefined) {
1544
+ options = { testEnvironment: true };
1545
+ }
1546
+ else {
1547
+ options = { ...options, testEnvironment: true };
1548
+ }
1549
+ }
1538
1550
  return new ModelMaterializer(this, async () => {
1539
1551
  const parse = source instanceof URL
1540
1552
  ? await Malloy.parse({
@@ -1811,6 +1823,14 @@ class ModelMaterializer extends FluentState {
1811
1823
  return this.makeQueryMaterializer(async () => {
1812
1824
  const urlReader = this.runtime.urlReader;
1813
1825
  const connections = this.runtime.connections;
1826
+ if (this.runtime.isTestRuntime) {
1827
+ if (options === undefined) {
1828
+ options = { testEnvironment: true };
1829
+ }
1830
+ else {
1831
+ options = { ...options, testEnvironment: true };
1832
+ }
1833
+ }
1814
1834
  const parse = query instanceof URL
1815
1835
  ? await Malloy.parse({
1816
1836
  url: query,
@@ -1841,6 +1861,14 @@ class ModelMaterializer extends FluentState {
1841
1861
  * or loading further related objects.
1842
1862
  */
1843
1863
  extendModel(query, options) {
1864
+ if (this.runtime.isTestRuntime) {
1865
+ if (options === undefined) {
1866
+ options = { testEnvironment: true };
1867
+ }
1868
+ else {
1869
+ options = { ...options, testEnvironment: true };
1870
+ }
1871
+ }
1844
1872
  return new ModelMaterializer(this.runtime, async () => {
1845
1873
  const urlReader = this.runtime.urlReader;
1846
1874
  const connections = this.runtime.connections;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.146",
3
+ "version": "0.0.147-dev240521202508",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./dist/index.js",