@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
@@ -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.BaseConnection = void 0;
@@ -25,6 +25,7 @@ export interface QueryInfo {
25
25
  queryTimezone?: string;
26
26
  systemTimezone?: string;
27
27
  }
28
+ export type FieldReferenceType = 'table' | 'nest source' | 'array[scalar]' | 'array[record]' | 'record';
28
29
  export declare const dayIndex: number;
29
30
  export declare function inDays(units: string): boolean;
30
31
  export declare function qtz(qi: QueryInfo): string | undefined;
@@ -61,6 +62,8 @@ export declare abstract class Dialect {
61
62
  supportsCountApprox: boolean;
62
63
  supportsFullJoin: boolean;
63
64
  nativeBoolean: boolean;
65
+ nestedArrays: boolean;
66
+ compoundObjectInSchema: boolean;
64
67
  abstract getDialectFunctionOverrides(): {
65
68
  [name: string]: DialectFunctionOverloadDef[];
66
69
  };
@@ -77,7 +80,7 @@ export declare abstract class Dialect {
77
80
  abstract sqlUnnestAlias(source: string, alias: string, fieldList: DialectFieldList, needDistinctKey: boolean, isArray: boolean, isInNestedPipeline: boolean): string;
78
81
  abstract sqlSumDistinctHashedKey(sqlDistinctKey: string): string;
79
82
  abstract sqlGenerateUUID(): string;
80
- abstract sqlFieldReference(alias: string, fieldName: string, fieldType: string, isNested: boolean, isArray: boolean): string;
83
+ abstract sqlFieldReference(parentAlias: string, parentType: FieldReferenceType, childName: string, childType: string): string;
81
84
  abstract sqlUnnestPipelineHead(isSingleton: boolean, sourceSQLExpression: string, fieldList?: DialectFieldList): string;
82
85
  abstract sqlCreateFunction(id: string, funcText: string): string;
83
86
  abstract sqlCreateFunctionCombineLastStage(lastStageName: string, fieldList: DialectFieldList, orderBy: OrderBy[] | undefined): string;
@@ -100,8 +103,8 @@ export declare abstract class Dialect {
100
103
  abstract sqlLiteralString(literal: string): string;
101
104
  abstract sqlLiteralRegexp(literal: string): string;
102
105
  abstract sqlRegexpMatch(df: RegexMatchExpr): string;
103
- sqlLiteralArray(lit: ArrayLiteralNode): string;
104
- sqlLiteralRecord(lit: RecordLiteralNode): string;
106
+ abstract sqlLiteralArray(lit: ArrayLiteralNode): string;
107
+ abstract sqlLiteralRecord(lit: RecordLiteralNode): string;
105
108
  /**
106
109
  * The dialect has a chance to over-ride how expressions are translated. If
107
110
  * "undefined" is returned then the translation is left to the query translator.
@@ -85,6 +85,10 @@ class Dialect {
85
85
  // MYSQL doesn't have full join, maybe others.
86
86
  this.supportsFullJoin = true;
87
87
  this.nativeBoolean = true;
88
+ // Can have arrays of arrays
89
+ this.nestedArrays = true;
90
+ // An array or record will reveal type of contents on schema read
91
+ this.compoundObjectInSchema = true;
88
92
  }
89
93
  sqlFinalStage(_lastStageName, _fields) {
90
94
  throw new Error('Dialect has no final Stage but called Anyway');
@@ -101,17 +105,6 @@ class Dialect {
101
105
  ignoreInProject(_fieldName) {
102
106
  return false;
103
107
  }
104
- // abstract sqlLiteralRecord(lit: RecordLiteralNode): string;
105
- // abstract sqlLiteralArray(lit: ArrayLiteralNode): string;
106
- // SHOULD BE ABSTRACT BUT A PLACEHOLDER FOR NOW
107
- sqlLiteralArray(lit) {
108
- const array = lit.kids.values.map(val => val.sql);
109
- return '[' + array.join(',') + ']';
110
- }
111
- sqlLiteralRecord(lit) {
112
- const pairs = Object.entries(lit.kids).map(([propName, propVal]) => `${this.sqlMaybeQuoteIdentifier(propName)}:${propVal.sql}`);
113
- return '{' + pairs.join(',') + '}';
114
- }
115
108
  /**
116
109
  * The dialect has a chance to over-ride how expressions are translated. If
117
110
  * "undefined" is returned then the translation is left to the query translator.
@@ -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.DUCKDB_DIALECT_FUNCTIONS = void 0;
@@ -1,6 +1,6 @@
1
- import { Sampling, AtomicTypeDef, TimeDeltaExpr, RegexMatchExpr, MeasureTimeExpr, LeafAtomicTypeDef, OrderBy } from '../../model/malloy_types';
1
+ import { Sampling, AtomicTypeDef, TimeDeltaExpr, RegexMatchExpr, MeasureTimeExpr, LeafAtomicTypeDef, RecordLiteralNode, OrderBy } from '../../model/malloy_types';
2
2
  import { DialectFunctionOverloadDef } from '../functions';
3
- import { DialectFieldList } from '../dialect';
3
+ import { DialectFieldList, FieldReferenceType } from '../dialect';
4
4
  import { PostgresBase } from '../pg_impl';
5
5
  export declare class DuckDBDialect extends PostgresBase {
6
6
  name: string;
@@ -36,12 +36,11 @@ export declare class DuckDBDialect extends PostgresBase {
36
36
  sqlSumDistinctHashedKey(_sqlDistinctKey: string): string;
37
37
  sqlGenerateUUID(): string;
38
38
  sqlDateToString(sqlDateExp: string): string;
39
- sqlFieldReference(alias: string, fieldName: string, _fieldType: string, _isNested: boolean, isArray: boolean): string;
39
+ sqlFieldReference(parentAlias: string, parentType: FieldReferenceType, childName: string, _childType: string): string;
40
40
  sqlUnnestPipelineHead(isSingleton: boolean, sourceSQLExpression: string): string;
41
41
  sqlCreateFunction(id: string, funcText: string): string;
42
42
  sqlCreateFunctionCombineLastStage(lastStageName: string, dialectFieldList: DialectFieldList, orderBy: OrderBy[] | undefined): string;
43
43
  sqlSelectAliasAsStruct(alias: string, dialectFieldList: DialectFieldList): string;
44
- sqlMaybeQuoteIdentifier(identifier: string): string;
45
44
  sqlCreateTableAsSelect(_tableName: string, _sql: string): string;
46
45
  sqlSumDistinct(key: string, value: string, funcName: string): string;
47
46
  sqlAggDistinct(key: string, values: string[], func: (valNames: string[]) => string): string;
@@ -63,4 +62,5 @@ export declare class DuckDBDialect extends PostgresBase {
63
62
  sqlAlterTimeExpr(df: TimeDeltaExpr): string;
64
63
  sqlRegexpMatch(df: RegexMatchExpr): string;
65
64
  sqlMeasureTimeExpr(df: MeasureTimeExpr): string;
65
+ sqlLiteralRecord(lit: RecordLiteralNode): string;
66
66
  }
@@ -163,16 +163,16 @@ class DuckDBDialect extends pg_impl_1.PostgresBase {
163
163
  sqlDateToString(sqlDateExp) {
164
164
  return `(${sqlDateExp})::date::varchar`;
165
165
  }
166
- sqlFieldReference(alias, fieldName, _fieldType, _isNested, isArray) {
166
+ sqlFieldReference(parentAlias, parentType, childName, _childType) {
167
167
  // LTNOTE: hack, in duckdb we can't have structs as tables so we kind of simulate it.
168
- if (!this.unnestWithNumbers && fieldName === '__row_id') {
169
- return `${alias}_outer.__row_id`;
168
+ if (!this.unnestWithNumbers && childName === '__row_id') {
169
+ return `${parentAlias}_outer.__row_id`;
170
170
  }
171
- else if (isArray) {
172
- return alias;
171
+ else if (parentType === 'array[scalar]') {
172
+ return parentAlias;
173
173
  }
174
174
  else {
175
- return `${alias}.${this.sqlMaybeQuoteIdentifier(fieldName)}`;
175
+ return `${parentAlias}.${this.sqlMaybeQuoteIdentifier(childName)}`;
176
176
  }
177
177
  }
178
178
  sqlUnnestPipelineHead(isSingleton, sourceSQLExpression) {
@@ -210,16 +210,6 @@ class DuckDBDialect extends pg_impl_1.PostgresBase {
210
210
  .map(d => `${alias}.${d.sqlOutputName}`)
211
211
  .join(', ')})`;
212
212
  }
213
- // TODO
214
- // sqlMaybeQuoteIdentifier(identifier: string): string {
215
- // return keywords.indexOf(identifier.toUpperCase()) > 0 ||
216
- // identifier.match(/[a-zA-Z][a-zA-Z0-9]*/) === null || true
217
- // ? '"' + identifier + '"'
218
- // : identifier;
219
- // }
220
- sqlMaybeQuoteIdentifier(identifier) {
221
- return '"' + identifier + '"';
222
- }
223
213
  // The simple way to do this is to add a comment on the table
224
214
  // with the expiration time. https://www.postgresql.org/docs/current/sql-comment.html
225
215
  // and have a reaper that read comments.
@@ -354,6 +344,10 @@ class DuckDBDialect extends pg_impl_1.PostgresBase {
354
344
  }
355
345
  return `DATE_SUB('${df.units}', ${lVal}, ${rVal})`;
356
346
  }
347
+ sqlLiteralRecord(lit) {
348
+ const pairs = Object.entries(lit.kids).map(([propName, propVal]) => `${this.sqlMaybeQuoteIdentifier(propName)}:${propVal.sql}`);
349
+ return '{' + pairs.join(',') + '}';
350
+ }
357
351
  }
358
352
  exports.DuckDBDialect = DuckDBDialect;
359
353
  //# sourceMappingURL=duckdb.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.DUCKDB_MALLOY_STANDARD_OVERLOADS = 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.expandOverrideMap = exports.getMalloyStandardFunctions = exports.MALLOY_STANDARD_FUNCTIONS = void 0;
@@ -1,7 +1,7 @@
1
1
  export type { DialectFunctionOverloadDef, DefinitionBlueprint, DefinitionBlueprintMap, OverloadedDefinitionBlueprint, } from './functions/util';
2
2
  export { arg, anyExprType, makeParam, overload, minScalar, minAggregate, maxScalar, spread, param, variadicParam, literal, sql, } from './functions/util';
3
3
  export { Dialect, qtz } from './dialect';
4
- export type { DialectFieldList, QueryInfo } from './dialect';
4
+ export type { DialectFieldList, QueryInfo, FieldReferenceType } from './dialect';
5
5
  export { StandardSQLDialect } from './standardsql';
6
6
  export { PostgresDialect } from './postgres';
7
7
  export { DuckDBDialect } from './duckdb';
@@ -11,3 +11,5 @@ export { MySQLDialect } from './mysql';
11
11
  export { getDialect, registerDialect } from './dialect_map';
12
12
  export { getMalloyStandardFunctions } from './functions';
13
13
  export type { MalloyStandardFunctionImplementations } from './functions';
14
+ export type { TinyToken } from './tiny_parser';
15
+ export { TinyParser } from './tiny_parser';
@@ -22,7 +22,7 @@
22
22
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.getMalloyStandardFunctions = exports.registerDialect = exports.getDialect = exports.MySQLDialect = exports.TrinoDialect = exports.SnowflakeDialect = exports.DuckDBDialect = exports.PostgresDialect = exports.StandardSQLDialect = exports.qtz = exports.Dialect = exports.sql = exports.literal = exports.variadicParam = exports.param = exports.spread = exports.maxScalar = exports.minAggregate = exports.minScalar = exports.overload = exports.makeParam = exports.anyExprType = exports.arg = void 0;
25
+ exports.TinyParser = exports.getMalloyStandardFunctions = exports.registerDialect = exports.getDialect = exports.MySQLDialect = exports.TrinoDialect = exports.SnowflakeDialect = exports.DuckDBDialect = exports.PostgresDialect = exports.StandardSQLDialect = exports.qtz = exports.Dialect = exports.sql = exports.literal = exports.variadicParam = exports.param = exports.spread = exports.maxScalar = exports.minAggregate = exports.minScalar = exports.overload = exports.makeParam = exports.anyExprType = exports.arg = void 0;
26
26
  var util_1 = require("./functions/util");
27
27
  Object.defineProperty(exports, "arg", { enumerable: true, get: function () { return util_1.arg; } });
28
28
  Object.defineProperty(exports, "anyExprType", { enumerable: true, get: function () { return util_1.anyExprType; } });
@@ -56,4 +56,6 @@ Object.defineProperty(exports, "getDialect", { enumerable: true, get: function (
56
56
  Object.defineProperty(exports, "registerDialect", { enumerable: true, get: function () { return dialect_map_1.registerDialect; } });
57
57
  var functions_1 = require("./functions");
58
58
  Object.defineProperty(exports, "getMalloyStandardFunctions", { enumerable: true, get: function () { return functions_1.getMalloyStandardFunctions; } });
59
+ var tiny_parser_1 = require("./tiny_parser");
60
+ Object.defineProperty(exports, "TinyParser", { enumerable: true, get: function () { return tiny_parser_1.TinyParser; } });
59
61
  //# sourceMappingURL=index.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.MYSQL_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.MYSQL_MALLOY_STANDARD_OVERLOADS = 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
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
9
  if (k2 === undefined) k2 = k;
@@ -1,5 +1,5 @@
1
- import { Sampling, MeasureTimeExpr, TimeLiteralNode, RegexMatchExpr, TimeDeltaExpr, TimeTruncExpr, TimeExtractExpr, TypecastExpr, LeafAtomicTypeDef, AtomicTypeDef } from '../../model/malloy_types';
2
- import { Dialect, DialectFieldList, QueryInfo } from '../dialect';
1
+ import { Sampling, MeasureTimeExpr, TimeLiteralNode, RegexMatchExpr, TimeDeltaExpr, TimeTruncExpr, TimeExtractExpr, TypecastExpr, LeafAtomicTypeDef, AtomicTypeDef, ArrayLiteralNode, RecordLiteralNode } from '../../model/malloy_types';
2
+ import { Dialect, DialectFieldList, FieldReferenceType, QueryInfo } from '../dialect';
3
3
  import { DialectFunctionOverloadDef } from '../functions';
4
4
  export declare class MySQLDialect extends Dialect {
5
5
  name: string;
@@ -28,6 +28,7 @@ export declare class MySQLDialect extends Dialect {
28
28
  readsNestedData: boolean;
29
29
  supportsComplexFilteredSources: boolean;
30
30
  supportsArraysInData: boolean;
31
+ compoundObjectInSchema: boolean;
31
32
  malloyTypeToSQLType(malloyType: AtomicTypeDef): string;
32
33
  sqlTypeToMalloyType(sqlType: string): LeafAtomicTypeDef;
33
34
  quoteTablePath(tablePath: string): string;
@@ -40,13 +41,13 @@ export declare class MySQLDialect extends Dialect {
40
41
  sqlCoaleseMeasuresInline(groupSet: number, fieldList: DialectFieldList): string;
41
42
  malloyToSQL(t: string): string;
42
43
  unnestColumns(fieldList: DialectFieldList): string;
43
- jsonTable(source: string, fieldList: DialectFieldList): string;
44
- sqlUnnestAlias(source: string, alias: string, fieldList: DialectFieldList, _needDistinctKey: boolean, _isArray: boolean, _isInNestedPipeline: boolean): string;
45
- sqlUnnestPipelineHead(_isSingleton: boolean, sourceSQLExpression: string, fieldList: DialectFieldList): string;
44
+ jsonTable(source: string, fieldList: DialectFieldList, isSingleton: boolean): string;
45
+ sqlUnnestAlias(source: string, alias: string, fieldList: DialectFieldList, _needDistinctKey: boolean, isArray: boolean, _isInNestedPipeline: boolean): string;
46
+ sqlUnnestPipelineHead(isSingleton: boolean, sourceSQLExpression: string, fieldList: DialectFieldList): string;
46
47
  sqlSumDistinctHashedKey(_sqlDistinctKey: string): string;
47
48
  sqlSumDistinct(key: string, value: string, funcName: string): string;
48
49
  sqlGenerateUUID(): string;
49
- sqlFieldReference(alias: string, fieldName: string, fieldType: string, isNested: boolean, _isArray: boolean): string;
50
+ sqlFieldReference(parentAlias: string, parentType: FieldReferenceType, childName: string, childType: string): string;
50
51
  sqlCreateFunction(id: string, funcText: string): string;
51
52
  sqlCreateFunctionCombineLastStage(lastStageName: string): string;
52
53
  sqlSelectAliasAsStruct(_alias: string, _fieldList: DialectFieldList): string;
@@ -76,4 +77,6 @@ export declare class MySQLDialect extends Dialect {
76
77
  castToString(expression: string): string;
77
78
  concat(...values: string[]): string;
78
79
  validateTypeName(sqlType: string): boolean;
80
+ sqlLiteralArray(lit: ArrayLiteralNode): string;
81
+ sqlLiteralRecord(lit: RecordLiteralNode): string;
79
82
  }
@@ -100,6 +100,7 @@ class MySQLDialect extends dialect_1.Dialect {
100
100
  this.readsNestedData = false;
101
101
  this.supportsComplexFilteredSources = false;
102
102
  this.supportsArraysInData = false;
103
+ this.compoundObjectInSchema = false;
103
104
  }
104
105
  malloyTypeToSQLType(malloyType) {
105
106
  switch (malloyType.type) {
@@ -186,21 +187,25 @@ class MySQLDialect extends dialect_1.Dialect {
186
187
  }
187
188
  return fields.join(',\n');
188
189
  }
189
- jsonTable(source, fieldList) {
190
- return `JSON_TABLE(${source}, '$[*]'
190
+ jsonTable(source, fieldList, isSingleton) {
191
+ let fields = this.unnestColumns(fieldList);
192
+ if (isSingleton) {
193
+ // LTNOTE: we need the type of array here.
194
+ fields = "`value` JSON PATH '$'";
195
+ }
196
+ return `JSON_TABLE(CAST(${source} AS JSON), '$[*]'
191
197
  COLUMNS (
192
198
  __row_id FOR ORDINALITY,
193
- ${this.unnestColumns(fieldList)}
199
+ ${fields}
194
200
  )
195
201
  )`;
196
202
  }
197
- // LTNOTE: We'll make this work with Arrays once MToy's changes land.
198
- sqlUnnestAlias(source, alias, fieldList, _needDistinctKey, _isArray, _isInNestedPipeline) {
203
+ sqlUnnestAlias(source, alias, fieldList, _needDistinctKey, isArray, _isInNestedPipeline) {
199
204
  return `
200
- LEFT JOIN ${this.jsonTable(source, fieldList)} as ${alias} ON 1=1`;
205
+ LEFT JOIN ${this.jsonTable(source, fieldList, isArray)} as ${alias} ON 1=1`;
201
206
  }
202
- sqlUnnestPipelineHead(_isSingleton, sourceSQLExpression, fieldList) {
203
- return this.jsonTable(sourceSQLExpression, fieldList);
207
+ sqlUnnestPipelineHead(isSingleton, sourceSQLExpression, fieldList) {
208
+ return this.jsonTable(sourceSQLExpression, fieldList, isSingleton);
204
209
  }
205
210
  sqlSumDistinctHashedKey(_sqlDistinctKey) {
206
211
  return 'UNUSED';
@@ -224,26 +229,24 @@ class MySQLDialect extends dialect_1.Dialect {
224
229
  // TODO: This causes the query to become slow, figure out another way to make UUID deterministic.
225
230
  return 'CONCAT(ROW_NUMBER() OVER(), UUID())';
226
231
  }
227
- sqlFieldReference(alias, fieldName, fieldType, isNested, _isArray) {
228
- let ret = `${alias}.\`${fieldName}\``;
229
- if (isNested) {
230
- switch (fieldType) {
232
+ sqlFieldReference(parentAlias, parentType, childName, childType) {
233
+ if (parentType === 'array[scalar]' || parentType === 'record') {
234
+ let ret = `JSON_UNQUOTE(JSON_EXTRACT(${parentAlias},'$.${childName}'))`;
235
+ if (parentType === 'array[scalar]') {
236
+ ret = `JSON_UNQUOTE(${parentAlias}.\`value\`)`;
237
+ }
238
+ switch (childType) {
231
239
  case 'string':
232
- ret = `CONCAT(${ret}, '')`;
233
- break;
234
- // TODO: Fix this.
240
+ return `CONCAT(${ret}, '')`;
235
241
  case 'number':
236
- ret = `CAST(${ret} as double)`;
237
- break;
238
- case 'struct':
239
- ret = `CAST(${ret} as JSON)`;
240
- break;
242
+ return `CAST(${ret} as double)`;
243
+ case 'record':
244
+ case 'array':
245
+ return `CAST(${ret} as JSON)`;
241
246
  }
242
- return ret;
243
- }
244
- else {
245
- return `${alias}.\`${fieldName}\``;
246
247
  }
248
+ const child = this.sqlMaybeQuoteIdentifier(childName);
249
+ return `${parentAlias}.${child}`;
247
250
  }
248
251
  sqlCreateFunction(id, funcText) {
249
252
  // TODO:
@@ -260,7 +263,7 @@ class MySQLDialect extends dialect_1.Dialect {
260
263
  // .join(',')})`;
261
264
  }
262
265
  sqlMaybeQuoteIdentifier(identifier) {
263
- return `\`${identifier}\``;
266
+ return '`' + identifier.replace(/`/g, '``') + '`';
264
267
  }
265
268
  // TODO: Check what this is.
266
269
  sqlCreateTableAsSelect(_tableName, _sql) {
@@ -440,6 +443,14 @@ class MySQLDialect extends dialect_1.Dialect {
440
443
  // Parentheses, Commas: NUMERIC(5, 2)
441
444
  return sqlType.match(/^[A-Za-z\s(),0-9]*$/) !== null;
442
445
  }
446
+ sqlLiteralArray(lit) {
447
+ const array = lit.kids.values.map(val => val.sql);
448
+ return `JSON_ARRAY(${array.join(',')})`;
449
+ }
450
+ sqlLiteralRecord(lit) {
451
+ const pairs = Object.entries(lit.kids).map(([propName, propVal]) => `${this.sqlLiteralString(propName)},${propVal.sql}`);
452
+ return `JSON_OBJECT(${pairs.join(', ')})`;
453
+ }
443
454
  }
444
455
  exports.MySQLDialect = MySQLDialect;
445
456
  //# sourceMappingURL=mysql.js.map
@@ -1,4 +1,4 @@
1
- import { RegexMatchExpr, TimeExtractExpr, TimeLiteralNode, TimeTruncExpr, TypecastExpr } from '../model/malloy_types';
1
+ import { ArrayLiteralNode, RecordLiteralNode, RegexMatchExpr, TimeExtractExpr, TimeLiteralNode, TimeTruncExpr, TypecastExpr } from '../model/malloy_types';
2
2
  import { Dialect, QueryInfo } from './dialect';
3
3
  export declare const timeExtractMap: Record<string, string>;
4
4
  /**
@@ -12,4 +12,7 @@ export declare abstract class PostgresBase extends Dialect {
12
12
  sqlCast(qi: QueryInfo, cast: TypecastExpr): string;
13
13
  sqlRegexpMatch(df: RegexMatchExpr): string;
14
14
  sqlLiteralTime(qi: QueryInfo, lt: TimeLiteralNode): string;
15
+ sqlLiteralRecord(_lit: RecordLiteralNode): string;
16
+ sqlLiteralArray(lit: ArrayLiteralNode): string;
17
+ sqlMaybeQuoteIdentifier(identifier: string): string;
15
18
  }
@@ -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.PostgresBase = exports.timeExtractMap = void 0;
@@ -84,6 +84,16 @@ class PostgresBase extends dialect_1.Dialect {
84
84
  }
85
85
  return `TIMESTAMP '${lt.literal}'`;
86
86
  }
87
+ sqlLiteralRecord(_lit) {
88
+ throw new Error('Cannot create a record literal for postgres base dialect');
89
+ }
90
+ sqlLiteralArray(lit) {
91
+ const array = lit.kids.values.map(val => val.sql);
92
+ return 'ARRAY[' + array.join(',') + ']';
93
+ }
94
+ sqlMaybeQuoteIdentifier(identifier) {
95
+ return '"' + identifier.replace(/"/g, '""') + '"';
96
+ }
87
97
  }
88
98
  exports.PostgresBase = PostgresBase;
89
99
  //# sourceMappingURL=pg_impl.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.POSTGRES_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.POSTGRES_MALLOY_STANDARD_OVERLOADS = void 0;
@@ -1,6 +1,6 @@
1
- import { Sampling, AtomicTypeDef, TimeDeltaExpr, TypecastExpr, MeasureTimeExpr, LeafAtomicTypeDef } from '../../model/malloy_types';
1
+ import { Sampling, AtomicTypeDef, TimeDeltaExpr, TypecastExpr, MeasureTimeExpr, LeafAtomicTypeDef, RecordLiteralNode, ArrayLiteralNode } from '../../model/malloy_types';
2
2
  import { DialectFunctionOverloadDef } from '../functions';
3
- import { DialectFieldList, QueryInfo } from '../dialect';
3
+ import { DialectFieldList, FieldReferenceType, QueryInfo } from '../dialect';
4
4
  import { PostgresBase } from '../pg_impl';
5
5
  export declare class PostgresDialect extends PostgresBase {
6
6
  name: string;
@@ -24,6 +24,7 @@ export declare class PostgresDialect extends PostgresBase {
24
24
  experimental: boolean;
25
25
  readsNestedData: boolean;
26
26
  supportsComplexFilteredSources: boolean;
27
+ compoundObjectInSchema: boolean;
27
28
  quoteTablePath(tablePath: string): string;
28
29
  sqlGroupSetTable(groupSetCount: number): string;
29
30
  sqlAnyValue(groupSet: number, fieldName: string): string;
@@ -35,13 +36,12 @@ export declare class PostgresDialect extends PostgresBase {
35
36
  sqlUnnestAlias(source: string, alias: string, fieldList: DialectFieldList, needDistinctKey: boolean, isArray: boolean, _isInNestedPipeline: boolean): string;
36
37
  sqlSumDistinctHashedKey(sqlDistinctKey: string): string;
37
38
  sqlGenerateUUID(): string;
38
- sqlFieldReference(alias: string, fieldName: string, fieldType: string, isNested: boolean, _isArray: boolean): string;
39
+ sqlFieldReference(parentAlias: string, parentType: FieldReferenceType, childName: string, childType: string): string;
39
40
  sqlUnnestPipelineHead(isSingleton: boolean, sourceSQLExpression: string): string;
40
41
  sqlCreateFunction(id: string, funcText: string): string;
41
42
  sqlCreateFunctionCombineLastStage(lastStageName: string): string;
42
43
  sqlFinalStage(lastStageName: string, _fields: string[]): string;
43
44
  sqlSelectAliasAsStruct(alias: string): string;
44
- sqlMaybeQuoteIdentifier(identifier: string): string;
45
45
  sqlCreateTableAsSelect(_tableName: string, _sql: string): string;
46
46
  sqlAlterTimeExpr(df: TimeDeltaExpr): string;
47
47
  sqlCast(qi: QueryInfo, cast: TypecastExpr): string;
@@ -63,4 +63,6 @@ export declare class PostgresDialect extends PostgresBase {
63
63
  castToString(expression: string): string;
64
64
  concat(...values: string[]): string;
65
65
  validateTypeName(sqlType: string): boolean;
66
+ sqlLiteralRecord(lit: RecordLiteralNode): string;
67
+ sqlLiteralArray(lit: ArrayLiteralNode): string;
66
68
  }
@@ -93,6 +93,7 @@ class PostgresDialect extends pg_impl_1.PostgresBase {
93
93
  this.experimental = false;
94
94
  this.readsNestedData = false;
95
95
  this.supportsComplexFilteredSources = false;
96
+ this.compoundObjectInSchema = false;
96
97
  }
97
98
  quoteTablePath(tablePath) {
98
99
  return tablePath
@@ -171,10 +172,10 @@ class PostgresDialect extends pg_impl_1.PostgresBase {
171
172
  sqlUnnestAlias(source, alias, fieldList, needDistinctKey, isArray, _isInNestedPipeline) {
172
173
  if (isArray) {
173
174
  if (needDistinctKey) {
174
- return `LEFT JOIN UNNEST(ARRAY((SELECT jsonb_build_object('__row_id', row_number() over (), 'value', v) FROM UNNEST(${source}) as v))) as ${alias} ON true`;
175
+ return `LEFT JOIN UNNEST(ARRAY((SELECT jsonb_build_object('__row_id', row_number() over (), 'value', v) FROM JSONB_ARRAY_ELEMENTS(TO_JSONB(${source})) as v))) as ${alias} ON true`;
175
176
  }
176
177
  else {
177
- return `LEFT JOIN UNNEST(ARRAY((SELECT jsonb_build_object('value', v) FROM UNNEST(${source}) as v))) as ${alias} ON true`;
178
+ return `LEFT JOIN UNNEST(ARRAY((SELECT jsonb_build_object('value', v) FROM JSONB_ARRAY_ELEMENTS(TO_JSONB(${source})) as v))) as ${alias} ON true`;
178
179
  }
179
180
  }
180
181
  else if (needDistinctKey) {
@@ -192,23 +193,30 @@ class PostgresDialect extends pg_impl_1.PostgresBase {
192
193
  sqlGenerateUUID() {
193
194
  return 'GEN_RANDOM_UUID()';
194
195
  }
195
- sqlFieldReference(alias, fieldName, fieldType, isNested, _isArray) {
196
- let ret = `(${alias}->>'${fieldName}')`;
197
- if (isNested) {
198
- switch (fieldType) {
196
+ sqlFieldReference(parentAlias, parentType, childName, childType) {
197
+ if (childName === '__row_id') {
198
+ return `(${parentAlias}->>'__row_id')`;
199
+ }
200
+ if (parentType !== 'table') {
201
+ let ret = `JSONB_EXTRACT_PATH_TEXT(${parentAlias},'${childName}')`;
202
+ switch (childType) {
199
203
  case 'string':
200
204
  break;
201
205
  case 'number':
202
206
  ret = `${ret}::double precision`;
203
207
  break;
204
208
  case 'struct':
205
- ret = `${ret}::jsonb`;
209
+ case 'array':
210
+ case 'record':
211
+ case 'array[record]':
212
+ ret = `JSONB_EXTRACT_PATH(${parentAlias},'${childName}')`;
206
213
  break;
207
214
  }
208
215
  return ret;
209
216
  }
210
217
  else {
211
- return `${alias}."${fieldName}"`;
218
+ const child = this.sqlMaybeQuoteIdentifier(childName);
219
+ return `${parentAlias}.${child}`;
212
220
  }
213
221
  }
214
222
  sqlUnnestPipelineHead(isSingleton, sourceSQLExpression) {
@@ -231,10 +239,6 @@ class PostgresDialect extends pg_impl_1.PostgresBase {
231
239
  sqlSelectAliasAsStruct(alias) {
232
240
  return `ROW(${alias})`;
233
241
  }
234
- // TODO
235
- sqlMaybeQuoteIdentifier(identifier) {
236
- return `"${identifier}"`;
237
- }
238
242
  // The simple way to do this is to add a comment on the table
239
243
  // with the expiration time. https://www.postgresql.org/docs/current/sql-comment.html
240
244
  // and have a reaper that read comments.
@@ -362,6 +366,17 @@ class PostgresDialect extends pg_impl_1.PostgresBase {
362
366
  // Square Brackets: INT64[]
363
367
  return sqlType.match(/^[A-Za-z\s(),[\]0-9]*$/) !== null;
364
368
  }
369
+ sqlLiteralRecord(lit) {
370
+ const props = [];
371
+ for (const [kName, kVal] of Object.entries(lit.kids)) {
372
+ props.push(`'${kName}',${kVal.sql}`);
373
+ }
374
+ return `JSONB_BUILD_OBJECT(${props.join(', ')})`;
375
+ }
376
+ sqlLiteralArray(lit) {
377
+ const array = lit.kids.values.map(val => val.sql);
378
+ return 'JSONB_BUILD_ARRAY(' + array.join(',') + ')';
379
+ }
365
380
  }
366
381
  exports.PostgresDialect = PostgresDialect;
367
382
  //# sourceMappingURL=postgres.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.SNOWFLAKE_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.SNOWFLAKE_MALLOY_STANDARD_OVERLOADS = void 0;
@@ -1,6 +1,6 @@
1
- import { Sampling, AtomicTypeDef, TimeTruncExpr, TimeExtractExpr, TimeDeltaExpr, TypecastExpr, TimeLiteralNode, MeasureTimeExpr, RegexMatchExpr, LeafAtomicTypeDef } from '../../model/malloy_types';
1
+ import { Sampling, AtomicTypeDef, TimeTruncExpr, TimeExtractExpr, TimeDeltaExpr, TypecastExpr, TimeLiteralNode, MeasureTimeExpr, RegexMatchExpr, LeafAtomicTypeDef, ArrayLiteralNode, RecordLiteralNode } from '../../model/malloy_types';
2
2
  import { DialectFunctionOverloadDef } from '../functions';
3
- import { Dialect, DialectFieldList, QueryInfo } from '../dialect';
3
+ import { Dialect, DialectFieldList, FieldReferenceType, QueryInfo } from '../dialect';
4
4
  export declare class SnowflakeDialect extends Dialect {
5
5
  name: string;
6
6
  experimental: boolean;
@@ -36,7 +36,7 @@ export declare class SnowflakeDialect extends Dialect {
36
36
  sqlSumDistinctHashedKey(sqlDistinctKey: string): string;
37
37
  sqlSumDistinct(key: string, value: string, funcName: string): string;
38
38
  sqlGenerateUUID(): string;
39
- sqlFieldReference(alias: string, fieldName: string, fieldType: string, isNested: boolean, _isArray: boolean): string;
39
+ sqlFieldReference(parentAlias: string, parentType: FieldReferenceType, childName: string, childType: string): string;
40
40
  sqlUnnestPipelineHead(isSingleton: boolean, sourceSQLExpression: string): string;
41
41
  sqlCreateFunction(_id: string, _funcText: string): string;
42
42
  sqlCreateFunctionCombineLastStage(_lastStageName: string): string;
@@ -67,4 +67,6 @@ export declare class SnowflakeDialect extends Dialect {
67
67
  castToString(expression: string): string;
68
68
  concat(...values: string[]): string;
69
69
  validateTypeName(sqlType: string): boolean;
70
+ sqlLiteralRecord(lit: RecordLiteralNode): string;
71
+ sqlLiteralArray(lit: ArrayLiteralNode): string;
70
72
  }