@malloydata/malloy 0.0.219 → 0.0.220-dev241204170603

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 (71) hide show
  1. package/dist/connection/base_connection.js +1 -1
  2. package/dist/dialect/dialect.d.ts +6 -3
  3. package/dist/dialect/dialect.js +4 -11
  4. package/dist/dialect/duckdb/dialect_functions.js +1 -1
  5. package/dist/dialect/duckdb/duckdb.d.ts +4 -4
  6. package/dist/dialect/duckdb/duckdb.js +10 -16
  7. package/dist/dialect/duckdb/function_overrides.js +1 -1
  8. package/dist/dialect/functions/malloy_standard_functions.js +1 -1
  9. package/dist/dialect/index.d.ts +3 -1
  10. package/dist/dialect/index.js +3 -1
  11. package/dist/dialect/mysql/dialect_functions.js +1 -1
  12. package/dist/dialect/mysql/function_overrides.js +1 -1
  13. package/dist/dialect/mysql/index.js +1 -1
  14. package/dist/dialect/mysql/mysql.d.ts +9 -6
  15. package/dist/dialect/mysql/mysql.js +36 -25
  16. package/dist/dialect/pg_impl.d.ts +4 -1
  17. package/dist/dialect/pg_impl.js +11 -1
  18. package/dist/dialect/postgres/dialect_functions.js +1 -1
  19. package/dist/dialect/postgres/function_overrides.js +1 -1
  20. package/dist/dialect/postgres/postgres.d.ts +6 -4
  21. package/dist/dialect/postgres/postgres.js +27 -12
  22. package/dist/dialect/snowflake/dialect_functions.js +1 -1
  23. package/dist/dialect/snowflake/function_overrides.js +1 -1
  24. package/dist/dialect/snowflake/snowflake.d.ts +5 -3
  25. package/dist/dialect/snowflake/snowflake.js +76 -20
  26. package/dist/dialect/standardsql/dialect_functions.js +1 -1
  27. package/dist/dialect/standardsql/function_overrides.js +1 -1
  28. package/dist/dialect/standardsql/standardsql.d.ts +5 -3
  29. package/dist/dialect/standardsql/standardsql.js +16 -101
  30. package/dist/dialect/tiny_parser.d.ts +41 -0
  31. package/dist/dialect/tiny_parser.js +126 -0
  32. package/dist/dialect/trino/dialect_functions.js +1 -1
  33. package/dist/dialect/trino/function_overrides.js +1 -1
  34. package/dist/dialect/trino/trino.d.ts +3 -3
  35. package/dist/dialect/trino/trino.js +40 -16
  36. package/dist/index.d.ts +3 -3
  37. package/dist/index.js +3 -2
  38. package/dist/lang/ast/expressions/case.js +1 -1
  39. package/dist/lang/ast/expressions/expr-array-literal.d.ts +9 -0
  40. package/dist/lang/ast/expressions/expr-array-literal.js +93 -0
  41. package/dist/lang/ast/expressions/expr-record-literal.d.ts +1 -1
  42. package/dist/lang/ast/expressions/expr-record-literal.js +56 -28
  43. package/dist/lang/ast/field-space/join-space-field.d.ts +1 -1
  44. package/dist/lang/ast/field-space/join-space-field.js +2 -2
  45. package/dist/lang/ast/field-space/project-field-space.js +1 -1
  46. package/dist/lang/ast/field-space/reference-field.js +1 -1
  47. package/dist/lang/ast/field-space/static-space.d.ts +1 -2
  48. package/dist/lang/ast/field-space/static-space.js +15 -5
  49. package/dist/lang/ast/field-space/view-field.d.ts +2 -2
  50. package/dist/lang/ast/index.d.ts +1 -0
  51. package/dist/lang/ast/index.js +1 -0
  52. package/dist/lang/ast/query-items/field-declaration.js +25 -11
  53. package/dist/lang/ast/query-properties/filters.js +0 -2
  54. package/dist/lang/ast/source-properties/join.js +1 -1
  55. package/dist/lang/ast/types/binary_operators.js +1 -1
  56. package/dist/lang/ast/types/dialect-name-space.js +1 -1
  57. package/dist/lang/lib/Malloy/MalloyParser.d.ts +1 -1
  58. package/dist/lang/lib/Malloy/MalloyParser.js +12 -16
  59. package/dist/lang/malloy-to-ast.d.ts +1 -1
  60. package/dist/lang/malloy-to-ast.js +3 -3
  61. package/dist/lang/parse-log.d.ts +1 -0
  62. package/dist/lang/test/query.spec.js +6 -0
  63. package/dist/lang/test/test-translator.js +11 -2
  64. package/dist/model/malloy_query.d.ts +29 -24
  65. package/dist/model/malloy_query.js +261 -146
  66. package/dist/model/malloy_types.d.ts +12 -15
  67. package/dist/model/malloy_types.js +2 -7
  68. package/dist/model/materialization/utils.js +1 -1
  69. package/dist/version.d.ts +1 -1
  70. package/dist/version.js +1 -1
  71. package/package.json +1 -1
@@ -142,12 +142,13 @@ class SnowflakeDialect extends dialect_1.Dialect {
142
142
  return `COALESCE(ARRAY_AGG(CASE WHEN group_set=${groupSet} THEN OBJECT_CONSTRUCT_KEEP_NULL(${fields}) END)[0], OBJECT_CONSTRUCT_KEEP_NULL(${nullValues}))`;
143
143
  }
144
144
  sqlUnnestAlias(source, alias, _fieldList, _needDistinctKey, isArray, _isInNestedPipeline) {
145
+ const as = this.sqlMaybeQuoteIdentifier(alias);
145
146
  if (isArray) {
146
- return `,LATERAL FLATTEN(INPUT => ${source}) AS ${alias}_1, LATERAL (SELECT ${alias}_1.INDEX, object_construct('value', ${alias}_1.value) as value ) as ${alias}`;
147
+ return `,LATERAL FLATTEN(INPUT => ${source}) AS ${alias}_1, LATERAL (SELECT ${alias}_1.INDEX, object_construct('value', ${alias}_1.value) as value ) as ${as}`;
147
148
  }
148
149
  else {
149
150
  // have to have a non empty row or it treats it like an inner join :barf-emoji:
150
- return `LEFT JOIN LATERAL FLATTEN(INPUT => ifnull(${source},[1])) AS ${alias}`;
151
+ return `LEFT JOIN LATERAL FLATTEN(INPUT => ifnull(${source},[1])) AS ${as}`;
151
152
  }
152
153
  }
153
154
  /*
@@ -190,23 +191,35 @@ class SnowflakeDialect extends dialect_1.Dialect {
190
191
  sqlGenerateUUID() {
191
192
  return 'UUID_STRING()';
192
193
  }
193
- sqlFieldReference(alias, fieldName, fieldType, isNested, _isArray) {
194
- if (fieldName === '__row_id') {
195
- return `${alias}.INDEX::varchar`;
194
+ sqlFieldReference(parentAlias, parentType, childName, childType) {
195
+ const sqlName = this.sqlMaybeQuoteIdentifier(childName);
196
+ if (childName === '__row_id') {
197
+ return `"${parentAlias}".INDEX::varchar`;
196
198
  }
197
- else if (!isNested) {
198
- return `${alias}."${fieldName}"`;
199
- }
200
- else {
201
- let snowflakeType = fieldType;
202
- if (fieldType === 'string') {
203
- snowflakeType = 'varchar';
204
- }
205
- else if (fieldType === 'struct') {
206
- snowflakeType = 'variant';
199
+ else if (parentType === 'array[scalar]' ||
200
+ parentType === 'array[record]') {
201
+ const arrayRef = `"${parentAlias}".value:${sqlName}`;
202
+ switch (childType) {
203
+ case 'record':
204
+ case 'array':
205
+ childType = 'VARIANT';
206
+ break;
207
+ case 'string':
208
+ childType = 'VARCHAR';
209
+ break;
210
+ case 'number':
211
+ childType = 'DOUBLE';
212
+ break;
213
+ case 'struct':
214
+ throw new Error('NOT STRUCT PLEASE');
215
+ // boolean and timestamp and date are all ok
207
216
  }
208
- return `${alias}.value:"${fieldName}"::${snowflakeType}`;
217
+ return `${arrayRef}::${childType}`;
209
218
  }
219
+ else if (parentType === 'record') {
220
+ return `${parentAlias}:${sqlName}`;
221
+ }
222
+ return `${parentAlias}.${sqlName}`;
210
223
  }
211
224
  sqlUnnestPipelineHead(isSingleton, sourceSQLExpression) {
212
225
  let p = sourceSQLExpression;
@@ -226,7 +239,7 @@ class SnowflakeDialect extends dialect_1.Dialect {
226
239
  return `OBJECT_CONSTRUCT_KEEP_NULL(${alias}.*)`;
227
240
  }
228
241
  sqlMaybeQuoteIdentifier(identifier) {
229
- return `"${identifier}"`;
242
+ return '"' + identifier.replace(/"/g, '""') + '"';
230
243
  }
231
244
  sqlCreateTableAsSelect(tableName, sql) {
232
245
  return `
@@ -368,14 +381,38 @@ ${(0, utils_1.indent)(sql)}
368
381
  return (0, functions_1.expandBlueprintMap)(dialect_functions_1.SNOWFLAKE_DIALECT_FUNCTIONS);
369
382
  }
370
383
  malloyTypeToSQLType(malloyType) {
371
- if (malloyType.type === 'number') {
384
+ if (malloyType.type === 'string') {
385
+ return 'VARCHAR';
386
+ }
387
+ else if (malloyType.type === 'number') {
372
388
  if (malloyType.numberType === 'integer') {
373
- return 'integer';
389
+ return 'INTEGER';
374
390
  }
375
391
  else {
376
- return 'double';
392
+ return 'DOUBLE';
377
393
  }
378
394
  }
395
+ else if (malloyType.type === 'record' ||
396
+ (malloyType.type === 'array' &&
397
+ malloyType.elementTypeDef.type === 'record_element')) {
398
+ const sqlFields = malloyType.fields.reduce((ret, f) => {
399
+ var _a;
400
+ if ((0, malloy_types_1.isAtomic)(f)) {
401
+ const name = (_a = f.as) !== null && _a !== void 0 ? _a : f.name;
402
+ const oneSchema = `${this.sqlMaybeQuoteIdentifier(name)} ${this.malloyTypeToSQLType(f)}`;
403
+ ret.push(oneSchema);
404
+ }
405
+ return ret;
406
+ }, []);
407
+ const recordScehma = `OBJECT(${sqlFields.join(',')})`;
408
+ return malloyType.type === 'record'
409
+ ? recordScehma
410
+ : `ARRAY(${recordScehma})`;
411
+ }
412
+ else if (malloyType.type === 'array' &&
413
+ malloyType.elementTypeDef.type !== 'record_element') {
414
+ return `ARRAY(${this.malloyTypeToSQLType(malloyType.elementTypeDef)})`;
415
+ }
379
416
  return malloyType.type;
380
417
  }
381
418
  sqlTypeToMalloyType(sqlType) {
@@ -401,6 +438,25 @@ ${(0, utils_1.indent)(sql)}
401
438
  // Square Brackets: INT64[]
402
439
  return sqlType.match(/^[A-Za-z\s(),[\]0-9]*$/) !== null;
403
440
  }
441
+ sqlLiteralRecord(lit) {
442
+ var _a, _b;
443
+ const rowVals = [];
444
+ for (const f of lit.typeDef.fields) {
445
+ const name = (_a = f.as) !== null && _a !== void 0 ? _a : f.name;
446
+ const propName = `'${name}'`;
447
+ const propVal = (_b = lit.kids[name].sql) !== null && _b !== void 0 ? _b : 'internal-error-record-literal';
448
+ rowVals.push(`${propName},${propVal}`);
449
+ }
450
+ return `OBJECT_CONSTRUCT_KEEP_NULL(${rowVals.join(',')})`;
451
+ }
452
+ sqlLiteralArray(lit) {
453
+ const array = lit.kids.values.map(val => val.sql);
454
+ const arraySchema = `[${array.join(',')}]`;
455
+ return arraySchema;
456
+ // return lit.typeDef.elementTypeDef.type === 'record_element'
457
+ // ? `${arraySchema}::${this.malloyTypeToSQLType(lit.typeDef)}`
458
+ // : arraySchema;
459
+ }
404
460
  }
405
461
  exports.SnowflakeDialect = SnowflakeDialect;
406
462
  //# sourceMappingURL=snowflake.js.map
@@ -3,7 +3,7 @@
3
3
  * Copyright (c) Meta Platforms, Inc. and affiliates.
4
4
  *
5
5
  * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
6
+ * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.STANDARDSQL_DIALECT_FUNCTIONS = void 0;
@@ -3,7 +3,7 @@
3
3
  * Copyright (c) Meta Platforms, Inc. and affiliates.
4
4
  *
5
5
  * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
6
+ * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.STANDARDSQL_MALLOY_STANDARD_OVERLOADS = void 0;
@@ -1,4 +1,4 @@
1
- import { Sampling, AtomicTypeDef, TimeTruncExpr, TimeExtractExpr, TimeDeltaExpr, TypecastExpr, RegexMatchExpr, TimeLiteralNode, MeasureTimeExpr, LeafAtomicTypeDef } from '../../model/malloy_types';
1
+ import { Sampling, AtomicTypeDef, TimeTruncExpr, TimeExtractExpr, TimeDeltaExpr, TypecastExpr, RegexMatchExpr, TimeLiteralNode, MeasureTimeExpr, LeafAtomicTypeDef, RecordLiteralNode, ArrayLiteralNode } from '../../model/malloy_types';
2
2
  import { DialectFunctionOverloadDef } from '../functions';
3
3
  import { Dialect, DialectFieldList, QueryInfo } from '../dialect';
4
4
  export declare class StandardSQLDialect extends Dialect {
@@ -23,6 +23,7 @@ export declare class StandardSQLDialect extends Dialect {
23
23
  supportsNesting: boolean;
24
24
  cantPartitionWindowFunctionsOnExpressions: boolean;
25
25
  hasModOperator: boolean;
26
+ nestedArrays: boolean;
26
27
  quoteTablePath(tablePath: string): string;
27
28
  sqlGroupSetTable(groupSetCount: number): string;
28
29
  sqlAnyValue(groupSet: number, fieldName: string): string;
@@ -33,13 +34,12 @@ export declare class StandardSQLDialect extends Dialect {
33
34
  sqlUnnestAlias(source: string, alias: string, fieldList: DialectFieldList, needDistinctKey: boolean, isArray: boolean, _isInNestedPipeline: boolean): string;
34
35
  sqlSumDistinctHashedKey(sqlDistinctKey: string): string;
35
36
  sqlGenerateUUID(): string;
36
- sqlFieldReference(alias: string, fieldName: string, _fieldType: string, _isNested: boolean, _isArray: boolean): string;
37
+ sqlFieldReference(parentAlias: string, _parentType: unknown, childName: string, _childType: string): string;
37
38
  sqlUnnestPipelineHead(isSingleton: boolean, sourceSQLExpression: string): string;
38
39
  sqlCreateFunction(id: string, funcText: string): string;
39
40
  sqlCreateTableAsSelect(tableName: string, sql: string): string;
40
41
  sqlCreateFunctionCombineLastStage(lastStageName: string): string;
41
42
  sqlSelectAliasAsStruct(alias: string): string;
42
- keywords: string[];
43
43
  sqlMaybeQuoteIdentifier(identifier: string): string;
44
44
  sqlNowExpr(): string;
45
45
  sqlTruncExpr(qi: QueryInfo, trunc: TimeTruncExpr): string;
@@ -64,4 +64,6 @@ export declare class StandardSQLDialect extends Dialect {
64
64
  castToString(expression: string): string;
65
65
  concat(...values: string[]): string;
66
66
  validateTypeName(sqlType: string): boolean;
67
+ sqlLiteralRecord(lit: RecordLiteralNode): string;
68
+ sqlLiteralArray(lit: ArrayLiteralNode): string;
67
69
  }
@@ -97,102 +97,7 @@ class StandardSQLDialect extends dialect_1.Dialect {
97
97
  this.supportsNesting = true;
98
98
  this.cantPartitionWindowFunctionsOnExpressions = true;
99
99
  this.hasModOperator = false;
100
- this.keywords = `
101
- ALL
102
- AND
103
- ANY
104
- ARRAY
105
- AS
106
- ASC
107
- ASSERT_ROWS_MODIFIED
108
- AT
109
- BETWEEN
110
- BY
111
- CASE
112
- CAST
113
- COLLATE
114
- CONTAINS
115
- CREATE
116
- CROSS
117
- CUBE
118
- CURRENT
119
- DEFAULT
120
- DEFINE
121
- DESC
122
- DISTINCT
123
- ELSE
124
- END
125
- ENUM
126
- ESCAPE
127
- EXCEPT
128
- EXCLUDE
129
- EXISTS
130
- EXTRACT
131
- FALSE
132
- FETCH
133
- FOLLOWING
134
- FOR
135
- FROM
136
- FULL
137
- GROUP
138
- GROUPING
139
- GROUPS
140
- HASH
141
- HAVING
142
- IF
143
- IGNORE
144
- IN
145
- INNER
146
- INTERSECT
147
- INTERVAL
148
- INTO
149
- IS
150
- JOIN
151
- LATERAL
152
- LEFT
153
- LIKE
154
- LIMIT
155
- LOOKUP
156
- MERGE
157
- NATURAL
158
- NEW
159
- NO
160
- NOT
161
- NULL
162
- NULLS
163
- OF
164
- ON
165
- OR
166
- ORDER
167
- OUTER
168
- OVER
169
- PARTITION
170
- PRECEDING
171
- PROTO
172
- RANGE
173
- RECURSIVE
174
- RESPECT
175
- RIGHT
176
- ROLLUP
177
- ROWS
178
- SELECT
179
- SET
180
- SOME
181
- STRUCT
182
- TABLESAMPLE
183
- THEN
184
- TO
185
- TREAT
186
- TRUE
187
- UNBOUNDED
188
- UNION
189
- UNNEST
190
- USING
191
- WHEN
192
- WHERE
193
- WINDOW
194
- WITH
195
- WITHIN`.split(/\s/);
100
+ this.nestedArrays = false; // Can't have an array of arrays for some reason
196
101
  }
197
102
  quoteTablePath(tablePath) {
198
103
  return `\`${tablePath}\``;
@@ -266,8 +171,9 @@ class StandardSQLDialect extends dialect_1.Dialect {
266
171
  sqlGenerateUUID() {
267
172
  return 'GENERATE_UUID()';
268
173
  }
269
- sqlFieldReference(alias, fieldName, _fieldType, _isNested, _isArray) {
270
- return `${alias}.${fieldName}`;
174
+ sqlFieldReference(parentAlias, _parentType, childName, _childType) {
175
+ const child = this.sqlMaybeQuoteIdentifier(childName);
176
+ return `${parentAlias}.${child}`;
271
177
  }
272
178
  sqlUnnestPipelineHead(isSingleton, sourceSQLExpression) {
273
179
  let p = sourceSQLExpression;
@@ -297,9 +203,6 @@ ${(0, utils_1.indent)(sql)}
297
203
  return `(SELECT AS STRUCT ${alias}.*)`;
298
204
  }
299
205
  sqlMaybeQuoteIdentifier(identifier) {
300
- // return this.keywords.indexOf(identifier.toUpperCase()) > 0
301
- // ? '`' + identifier + '`'
302
- // : identifier;
303
206
  return '`' + identifier + '`';
304
207
  }
305
208
  sqlNowExpr() {
@@ -479,6 +382,18 @@ ${(0, utils_1.indent)(sql)}
479
382
  // Angle Brackets: ARRAY<INT64>
480
383
  return sqlType.match(/^[A-Za-z\s(),<>0-9]*$/) !== null;
481
384
  }
385
+ sqlLiteralRecord(lit) {
386
+ const ents = [];
387
+ for (const [name, val] of Object.entries(lit.kids)) {
388
+ const expr = val.sql || 'internal-error-literal-record';
389
+ ents.push(`${expr} AS ${this.sqlMaybeQuoteIdentifier(name)}`);
390
+ }
391
+ return `STRUCT(${ents.join(',')})`;
392
+ }
393
+ sqlLiteralArray(lit) {
394
+ const array = lit.kids.values.map(val => val.sql);
395
+ return '[' + array.join(',') + ']';
396
+ }
482
397
  }
483
398
  exports.StandardSQLDialect = StandardSQLDialect;
484
399
  //# sourceMappingURL=standardsql.js.map
@@ -0,0 +1,41 @@
1
+ export interface TinyToken {
2
+ type: string;
3
+ text: string;
4
+ }
5
+ /**
6
+ * Simple framework for writing schema parsers. The parsers using this felt
7
+ * better than the more ad-hoc code they replaced, and are smaller than
8
+ * using a parser generator.
9
+ *
10
+ * NOTE: All parse errors are exceptions.
11
+ */
12
+ export declare class TinyParser {
13
+ readonly input: string;
14
+ private tokens;
15
+ private parseCursor;
16
+ private lookAhead?;
17
+ private tokenMap;
18
+ /**
19
+ * The token map is tested in order. Return TinyToken
20
+ * is {type: tokenMapKey, text: matchingText }, except
21
+ * for the special tokenMapKeys:
22
+ * * space: skipped and never returned
23
+ * * char: matched string return in both .type and .text
24
+ * * q*: any token name starting with 'q' is assumed to be
25
+ * a quoted string and the text will have the first and
26
+ * last characters stripped
27
+ */
28
+ constructor(input: string, tokenMap?: Record<string, RegExp>);
29
+ parseError(str: string): Error;
30
+ peek(): TinyToken;
31
+ private getNext;
32
+ /**
33
+ * Return next token, if any token types are passed, read and require those
34
+ * tokens, then return the last one.
35
+ * @param types list of token types
36
+ * @returns The last token read
37
+ */
38
+ next(...types: string[]): TinyToken;
39
+ skipTo(type: string): void;
40
+ private tokenize;
41
+ }
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.TinyParser = void 0;
10
+ /**
11
+ * Simple framework for writing schema parsers. The parsers using this felt
12
+ * better than the more ad-hoc code they replaced, and are smaller than
13
+ * using a parser generator.
14
+ *
15
+ * NOTE: All parse errors are exceptions.
16
+ */
17
+ class TinyParser {
18
+ /**
19
+ * The token map is tested in order. Return TinyToken
20
+ * is {type: tokenMapKey, text: matchingText }, except
21
+ * for the special tokenMapKeys:
22
+ * * space: skipped and never returned
23
+ * * char: matched string return in both .type and .text
24
+ * * q*: any token name starting with 'q' is assumed to be
25
+ * a quoted string and the text will have the first and
26
+ * last characters stripped
27
+ */
28
+ constructor(input, tokenMap) {
29
+ this.input = input;
30
+ this.parseCursor = 0;
31
+ this.tokens = this.tokenize(input);
32
+ this.tokenMap = tokenMap !== null && tokenMap !== void 0 ? tokenMap : {
33
+ space: /^\s+/,
34
+ char: /^[,:[\]()-]/,
35
+ id: /^\w+/,
36
+ qstr: /^"\w+"/,
37
+ };
38
+ }
39
+ parseError(str) {
40
+ const errText = `INTERNAL ERROR parsing schema: ${str}\n` +
41
+ `${this.input}\n` +
42
+ `${' '.repeat(this.parseCursor)}^`;
43
+ return new Error(errText);
44
+ }
45
+ peek() {
46
+ if (this.lookAhead) {
47
+ return this.lookAhead;
48
+ }
49
+ else {
50
+ const { value } = this.tokens.next();
51
+ const peekVal = value !== null && value !== void 0 ? value : { type: 'eof', text: '' };
52
+ this.lookAhead = peekVal;
53
+ return peekVal;
54
+ }
55
+ }
56
+ getNext() {
57
+ var _a;
58
+ const next = (_a = this.lookAhead) !== null && _a !== void 0 ? _a : this.peek();
59
+ this.lookAhead = undefined;
60
+ return next;
61
+ }
62
+ /**
63
+ * Return next token, if any token types are passed, read and require those
64
+ * tokens, then return the last one.
65
+ * @param types list of token types
66
+ * @returns The last token read
67
+ */
68
+ next(...types) {
69
+ if (types.length === 0)
70
+ return this.getNext();
71
+ let next = undefined;
72
+ let expected = types[0];
73
+ for (const typ of types) {
74
+ next = this.getNext();
75
+ expected = typ;
76
+ if (next.type !== typ) {
77
+ next = undefined;
78
+ break;
79
+ }
80
+ }
81
+ if (next)
82
+ return next;
83
+ throw this.parseError(`Expected ${expected}`);
84
+ }
85
+ skipTo(type) {
86
+ for (;;) {
87
+ const next = this.next();
88
+ if (next.type === 'eof') {
89
+ throw this.parseError(`Expected token '${type}`);
90
+ }
91
+ if (next.type === type) {
92
+ return;
93
+ }
94
+ }
95
+ }
96
+ *tokenize(src) {
97
+ const tokenList = this.tokenMap;
98
+ while (this.parseCursor < src.length) {
99
+ let notFound = true;
100
+ for (const tokenType in tokenList) {
101
+ const srcAtCursor = src.slice(this.parseCursor);
102
+ const foundToken = srcAtCursor.match(tokenList[tokenType]);
103
+ if (foundToken) {
104
+ notFound = false;
105
+ let tokenText = foundToken[0];
106
+ this.parseCursor += tokenText.length;
107
+ if (tokenType !== 'space') {
108
+ if (tokenType[0] === 'q') {
109
+ tokenText = tokenText.slice(1, -1); // strip quotes
110
+ }
111
+ yield {
112
+ type: tokenType === 'char' ? tokenText : tokenType,
113
+ text: tokenText,
114
+ };
115
+ }
116
+ }
117
+ }
118
+ if (notFound) {
119
+ yield { type: 'unexpected token', text: src };
120
+ return;
121
+ }
122
+ }
123
+ }
124
+ }
125
+ exports.TinyParser = TinyParser;
126
+ //# sourceMappingURL=tiny_parser.js.map
@@ -3,7 +3,7 @@
3
3
  * Copyright (c) Meta Platforms, Inc. and affiliates.
4
4
  *
5
5
  * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
6
+ * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.TRINO_DIALECT_FUNCTIONS = void 0;
@@ -3,7 +3,7 @@
3
3
  * Copyright (c) Meta Platforms, Inc. and affiliates.
4
4
  *
5
5
  * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
6
+ * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.TRINO_MALLOY_STANDARD_OVERLOADS = void 0;
@@ -1,4 +1,4 @@
1
- import { Expr, Sampling, AtomicTypeDef, TimeDeltaExpr, TypecastExpr, RegexMatchExpr, MeasureTimeExpr, TimeLiteralNode, TimeExtractExpr, LeafAtomicTypeDef } from '../../model/malloy_types';
1
+ import { Expr, Sampling, AtomicTypeDef, TimeDeltaExpr, TypecastExpr, RegexMatchExpr, MeasureTimeExpr, TimeLiteralNode, TimeExtractExpr, LeafAtomicTypeDef, RecordLiteralNode } from '../../model/malloy_types';
2
2
  import { DialectFunctionOverloadDef } from '../functions';
3
3
  import { DialectFieldList, OrderByClauseType, QueryInfo } from '../dialect';
4
4
  import { PostgresBase } from '../pg_impl';
@@ -43,14 +43,13 @@ export declare class TrinoDialect extends PostgresBase {
43
43
  sqlSumDistinctHashedKey(sqlDistinctKey: string): string;
44
44
  sqlSumDistinct(key: string, value: string, funcName: string): string;
45
45
  sqlGenerateUUID(): string;
46
- sqlFieldReference(alias: string, fieldName: string, _fieldType: string, _isNested: boolean, _isArray: boolean): string;
46
+ sqlFieldReference(parentAlias: string, _parentType: unknown, childName: string, _childType: string): string;
47
47
  sqlUnnestPipelineHead(isSingleton: boolean, sourceSQLExpression: string): string;
48
48
  sqlCreateFunction(id: string, funcText: string): string;
49
49
  sqlCreateTableAsSelect(tableName: string, sql: string): string;
50
50
  sqlCreateFunctionCombineLastStage(lastStageName: string, fieldList: DialectFieldList): string;
51
51
  sqlSelectAliasAsStruct(alias: string, fieldList: any): string;
52
52
  keywords: string[];
53
- sqlMaybeQuoteIdentifier(identifier: string): string;
54
53
  sqlAlterTimeExpr(df: TimeDeltaExpr): string;
55
54
  sqlCast(qi: QueryInfo, cast: TypecastExpr): string;
56
55
  sqlRegexpMatch(reCmp: RegexMatchExpr): string;
@@ -73,6 +72,7 @@ export declare class TrinoDialect extends PostgresBase {
73
72
  validateTypeName(sqlType: string): boolean;
74
73
  sqlLiteralTime(qi: QueryInfo, lit: TimeLiteralNode): string;
75
74
  sqlTimeExtractExpr(qi: QueryInfo, from: TimeExtractExpr): string;
75
+ sqlLiteralRecord(lit: RecordLiteralNode): string;
76
76
  }
77
77
  export declare class PrestoDialect extends TrinoDialect {
78
78
  name: string;
@@ -312,12 +312,12 @@ class TrinoDialect extends pg_impl_1.PostgresBase {
312
312
  sqlGenerateUUID() {
313
313
  return 'UUID()';
314
314
  }
315
- sqlFieldReference(alias, fieldName, _fieldType, _isNested, _isArray) {
315
+ sqlFieldReference(parentAlias, _parentType, childName, _childType) {
316
316
  // LTNOTE: hack, in duckdb we can't have structs as tables so we kind of simulate it.
317
- if (fieldName === '__row_id') {
318
- return `__row_id_from_${alias}`;
317
+ if (childName === '__row_id') {
318
+ return `__row_id_from_${parentAlias}`;
319
319
  }
320
- return `${alias}.${this.sqlMaybeQuoteIdentifier(fieldName)}`;
320
+ return `${parentAlias}.${this.sqlMaybeQuoteIdentifier(childName)}`;
321
321
  }
322
322
  sqlUnnestPipelineHead(isSingleton, sourceSQLExpression) {
323
323
  let p = sourceSQLExpression;
@@ -350,9 +350,6 @@ ${(0, utils_1.indent)(sql)}
350
350
  const definitions = this.buildTypeExpression(fieldList);
351
351
  return `CAST(ROW(${fields}) as ROW(${definitions})`;
352
352
  }
353
- sqlMaybeQuoteIdentifier(identifier) {
354
- return '"' + identifier + '"';
355
- }
356
353
  sqlAlterTimeExpr(df) {
357
354
  let timeframe = df.units;
358
355
  let n = df.kids.delta.sql;
@@ -450,18 +447,31 @@ ${(0, utils_1.indent)(sql)}
450
447
  return (0, functions_1.expandBlueprintMap)(dialect_functions_1.TRINO_DIALECT_FUNCTIONS);
451
448
  }
452
449
  malloyTypeToSQLType(malloyType) {
453
- if (malloyType.type === 'number') {
454
- if (malloyType.numberType === 'integer') {
455
- return 'BIGINT';
450
+ switch (malloyType.type) {
451
+ case 'number':
452
+ return malloyType.numberType === 'integer' ? 'BIGINT' : 'DOUBLE';
453
+ case 'string':
454
+ return 'VARCHAR';
455
+ case 'record': {
456
+ const typeSpec = [];
457
+ for (const f of malloyType.fields) {
458
+ if ((0, malloy_types_1.isAtomic)(f)) {
459
+ typeSpec.push(`${f.name} ${this.malloyTypeToSQLType(f)}`);
460
+ }
461
+ }
462
+ return `ROW(${typeSpec.join(',')})`;
456
463
  }
457
- else {
458
- return 'DOUBLE';
464
+ case 'sql native':
465
+ return malloyType.rawType || 'UNKNOWN-NATIVE';
466
+ case 'array': {
467
+ if (malloyType.elementTypeDef.type !== 'record_element') {
468
+ return `ARRAY<${this.malloyTypeToSQLType(malloyType.elementTypeDef)}>`;
469
+ }
470
+ return malloyType.type.toUpperCase();
459
471
  }
472
+ default:
473
+ return malloyType.type.toUpperCase();
460
474
  }
461
- else if (malloyType.type === 'string') {
462
- return 'VARCHAR';
463
- }
464
- return malloyType.type;
465
475
  }
466
476
  sqlTypeToMalloyType(sqlType) {
467
477
  var _a, _b, _c;
@@ -514,6 +524,20 @@ ${(0, utils_1.indent)(sql)}
514
524
  const extracted = `EXTRACT(${pgUnits} FROM ${extractFrom})`;
515
525
  return from.units === 'day_of_week' ? `mod(${extracted}+1,7)` : extracted;
516
526
  }
527
+ sqlLiteralRecord(lit) {
528
+ var _a, _b;
529
+ const rowVals = [];
530
+ const rowTypes = [];
531
+ for (const f of lit.typeDef.fields) {
532
+ if ((0, malloy_types_1.isAtomic)(f)) {
533
+ const name = (_a = f.as) !== null && _a !== void 0 ? _a : f.name;
534
+ rowVals.push((_b = lit.kids[name].sql) !== null && _b !== void 0 ? _b : 'internal-error-record-literal');
535
+ const elType = this.malloyTypeToSQLType(f);
536
+ rowTypes.push(`${name} ${elType}`);
537
+ }
538
+ }
539
+ return `CAST(ROW(${rowVals.join(',')}) AS ROW(${rowTypes.join(',')}))`;
540
+ }
517
541
  }
518
542
  exports.TrinoDialect = TrinoDialect;
519
543
  TrinoDialect.dtype = 'DECIMAL(38,0)';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { DuckDBDialect, StandardSQLDialect, TrinoDialect, PostgresDialect, SnowflakeDialect, MySQLDialect, registerDialect, arg, qtz, overload, minScalar, anyExprType, minAggregate, maxScalar, sql, makeParam, param, variadicParam, literal, spread, Dialect, } from './dialect';
2
- export type { DialectFieldList, DialectFunctionOverloadDef, QueryInfo, MalloyStandardFunctionImplementations, DefinitionBlueprint, DefinitionBlueprintMap, OverloadedDefinitionBlueprint, } from './dialect';
3
- export type { QueryDataRow, StructDef, TableSourceDef, SQLSourceDef, SourceDef, JoinFieldDef, NamedSourceDefs, MalloyQueryData, DateUnit, ExtractUnit, TimestampUnit, TemporalFieldType, QueryData, QueryValue, Expr, FilterCondition, SQLSentence, FieldDef, PipeSegment, QueryFieldDef, IndexFieldDef, TurtleDef, SearchValueMapResult, SearchIndexResult, ModelDef, Query, QueryResult, QueryRunStats, NamedQuery, NamedModelObject, ExpressionType, FunctionDef, FunctionOverloadDef, FunctionParameterDef, ExpressionValueType, TypeDesc, FunctionParamTypeDesc, DocumentLocation, DocumentRange, DocumentPosition, Sampling, Annotation, LeafAtomicTypeDef, LeafAtomicDef, AtomicTypeDef, AtomicFieldDef, ArrayDef, ArrayTypeDef, RecordTypeDef, RepeatedRecordTypeDef, } from './model';
1
+ export { DuckDBDialect, StandardSQLDialect, TrinoDialect, PostgresDialect, SnowflakeDialect, MySQLDialect, registerDialect, arg, qtz, overload, minScalar, anyExprType, minAggregate, maxScalar, sql, makeParam, param, variadicParam, literal, spread, Dialect, TinyParser, } from './dialect';
2
+ export type { DialectFieldList, DialectFunctionOverloadDef, QueryInfo, MalloyStandardFunctionImplementations, DefinitionBlueprint, DefinitionBlueprintMap, OverloadedDefinitionBlueprint, TinyToken, } from './dialect';
3
+ export type { QueryDataRow, StructDef, TableSourceDef, SQLSourceDef, SourceDef, JoinFieldDef, NamedSourceDefs, MalloyQueryData, DateUnit, ExtractUnit, TimestampUnit, TemporalFieldType, QueryData, QueryValue, Expr, FilterCondition, SQLSentence, FieldDef, PipeSegment, QueryFieldDef, IndexFieldDef, TurtleDef, SearchValueMapResult, SearchIndexResult, ModelDef, Query, QueryResult, QueryRunStats, NamedQuery, NamedModelObject, ExpressionType, FunctionDef, FunctionOverloadDef, FunctionParameterDef, ExpressionValueType, TypeDesc, FunctionParamTypeDesc, DocumentLocation, DocumentRange, DocumentPosition, Sampling, Annotation, LeafAtomicTypeDef, LeafAtomicDef, AtomicTypeDef, AtomicFieldDef, ArrayDef, ArrayTypeDef, RecordTypeDef, RepeatedRecordTypeDef, RecordDef, RepeatedRecordDef, RecordLiteralNode, ArrayLiteralNode, } from './model';
4
4
  export { arrayEachFields, isRepeatedRecord, isSourceDef, Segment, isLeafAtomic, isJoined, isJoinedSource, isSamplingEnable, isSamplingPercent, isSamplingRows, expressionIsAggregate, expressionIsAnalytic, expressionIsCalculation, expressionIsScalar, expressionIsUngroupedAggregate, indent, composeSQLExpr, } from './model';
5
5
  export { MalloyTranslator, } from './lang';
6
6
  export type { LogMessage, TranslateResponse } from './lang';