@malloydata/malloy 0.0.79 → 0.0.80-dev230824170739

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.
@@ -185,6 +185,7 @@ import { TableURIContext } from "./MalloyParser";
185
185
  import { IdContext } from "./MalloyParser";
186
186
  import { TimeframeContext } from "./MalloyParser";
187
187
  import { UngroupContext } from "./MalloyParser";
188
+ import { MalloyOrSQLTypeContext } from "./MalloyParser";
188
189
  import { FieldExprContext } from "./MalloyParser";
189
190
  import { PartialAllowedFieldExprContext } from "./MalloyParser";
190
191
  import { PickStatementContext } from "./MalloyParser";
@@ -2226,6 +2227,16 @@ export interface MalloyParserListener extends ParseTreeListener {
2226
2227
  * @param ctx the parse tree
2227
2228
  */
2228
2229
  exitUngroup?: (ctx: UngroupContext) => void;
2230
+ /**
2231
+ * Enter a parse tree produced by `MalloyParser.malloyOrSQLType`.
2232
+ * @param ctx the parse tree
2233
+ */
2234
+ enterMalloyOrSQLType?: (ctx: MalloyOrSQLTypeContext) => void;
2235
+ /**
2236
+ * Exit a parse tree produced by `MalloyParser.malloyOrSQLType`.
2237
+ * @param ctx the parse tree
2238
+ */
2239
+ exitMalloyOrSQLType?: (ctx: MalloyOrSQLTypeContext) => void;
2229
2240
  /**
2230
2241
  * Enter a parse tree produced by `MalloyParser.fieldExpr`.
2231
2242
  * @param ctx the parse tree
@@ -185,6 +185,7 @@ import { TableURIContext } from "./MalloyParser";
185
185
  import { IdContext } from "./MalloyParser";
186
186
  import { TimeframeContext } from "./MalloyParser";
187
187
  import { UngroupContext } from "./MalloyParser";
188
+ import { MalloyOrSQLTypeContext } from "./MalloyParser";
188
189
  import { FieldExprContext } from "./MalloyParser";
189
190
  import { PartialAllowedFieldExprContext } from "./MalloyParser";
190
191
  import { PickStatementContext } from "./MalloyParser";
@@ -1406,6 +1407,12 @@ export interface MalloyParserVisitor<Result> extends ParseTreeVisitor<Result> {
1406
1407
  * @return the visitor result
1407
1408
  */
1408
1409
  visitUngroup?: (ctx: UngroupContext) => Result;
1410
+ /**
1411
+ * Visit a parse tree produced by `MalloyParser.malloyOrSQLType`.
1412
+ * @param ctx the parse tree
1413
+ * @return the visitor result
1414
+ */
1415
+ visitMalloyOrSQLType?: (ctx: MalloyOrSQLTypeContext) => Result;
1409
1416
  /**
1410
1417
  * Visit a parse tree produced by `MalloyParser.fieldExpr`.
1411
1418
  * @param ctx the parse tree
@@ -8,8 +8,9 @@ import { LogSeverity, MessageLogger } from './parse-log';
8
8
  import { MalloyParseInfo } from './malloy-parse-info';
9
9
  import { FieldDeclarationConstructor } from './ast';
10
10
  import { HasString, HasID } from './parse-utils';
11
- import { Tag } from '../tags';
11
+ import { CastType } from '../model';
12
12
  import { DocumentLocation, Note } from '../model/malloy_types';
13
+ import { Tag } from '../tags';
13
14
  declare class IgnoredElement extends ast.MalloyElement {
14
15
  elementType: string;
15
16
  malloySrc: string;
@@ -178,6 +179,9 @@ export declare class MalloyToAST extends AbstractParseTreeVisitor<ast.MalloyElem
178
179
  visitExprApply(pcx: parse.ExprApplyContext): ast.Apply;
179
180
  visitExprRange(pcx: parse.ExprRangeContext): ast.Range;
180
181
  visitExprCast(pcx: parse.ExprCastContext): ast.ExpressionDef;
182
+ getMalloyOrSQLType(pcx: parse.MalloyOrSQLTypeContext): CastType | {
183
+ raw: string;
184
+ };
181
185
  visitExprSafeCast(pcx: parse.ExprSafeCastContext): ast.ExpressionDef;
182
186
  visitExprTimeTrunc(pcx: parse.ExprTimeTruncContext): ast.ExprGranularTime;
183
187
  visitTimeframe(pcx: parse.TimeframeContext): ast.Timeframe;
@@ -52,6 +52,7 @@ const ast = __importStar(require("./ast"));
52
52
  const Interval_1 = require("antlr4ts/misc/Interval");
53
53
  const ast_1 = require("./ast");
54
54
  const parse_utils_1 = require("./parse-utils");
55
+ const malloy_types_1 = require("../model/malloy_types");
55
56
  const tags_1 = require("../tags");
56
57
  class IgnoredElement extends ast.MalloyElement {
57
58
  constructor(src) {
@@ -1067,20 +1068,27 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
1067
1068
  return new ast.Range(this.getFieldExpr(pcx.fieldExpr(0)), this.getFieldExpr(pcx.fieldExpr(1)));
1068
1069
  }
1069
1070
  visitExprCast(pcx) {
1070
- const type = pcx.malloyType().text;
1071
- if (ast.isCastType(type)) {
1072
- return new ast.ExprCast(this.getFieldExpr(pcx.fieldExpr()), type);
1071
+ const type = this.getMalloyOrSQLType(pcx.malloyOrSQLType());
1072
+ return new ast.ExprCast(this.getFieldExpr(pcx.fieldExpr()), type);
1073
+ }
1074
+ getMalloyOrSQLType(pcx) {
1075
+ const mtcx = pcx.malloyType();
1076
+ if (mtcx) {
1077
+ const type = mtcx.text;
1078
+ if ((0, malloy_types_1.isCastType)(type)) {
1079
+ return type;
1080
+ }
1081
+ throw this.internalError(pcx, `unknown type '${type}'`);
1073
1082
  }
1074
- this.contextError(pcx, `CAST to unknown type '${type}'`);
1075
- return new ast.ExprNULL();
1083
+ const rtcx = pcx.string();
1084
+ if (rtcx) {
1085
+ return { raw: this.getPlainString({ string: () => rtcx }) };
1086
+ }
1087
+ throw this.internalError(pcx, 'Expected Malloy or SQL type to either be a Malloy type or a string');
1076
1088
  }
1077
1089
  visitExprSafeCast(pcx) {
1078
- const type = pcx.malloyType().text;
1079
- if (ast.isCastType(type)) {
1080
- return new ast.ExprCast(this.getFieldExpr(pcx.fieldExpr()), type, true);
1081
- }
1082
- this.contextError(pcx, `'::' cast to unknown type '${type}'`);
1083
- return new ast.ExprNULL();
1090
+ const type = this.getMalloyOrSQLType(pcx.malloyOrSQLType());
1091
+ return new ast.ExprCast(this.getFieldExpr(pcx.fieldExpr()), type, true);
1084
1092
  }
1085
1093
  visitExprTimeTrunc(pcx) {
1086
1094
  return new ast.ExprGranularTime(this.getFieldExpr(pcx.fieldExpr()), this.visitTimeframe(pcx.timeframe()).text, true);
@@ -1116,7 +1124,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
1116
1124
  const rawRawType = (_a = pcx.malloyType()) === null || _a === void 0 ? void 0 : _a.text;
1117
1125
  let rawType = undefined;
1118
1126
  if (rawRawType) {
1119
- if (ast.isCastType(rawRawType)) {
1127
+ if ((0, malloy_types_1.isCastType)(rawRawType)) {
1120
1128
  rawType = rawRawType;
1121
1129
  }
1122
1130
  else {
@@ -9,7 +9,7 @@ import { StringContext, ShortStringContext, SqlStringContext, IdContext } from '
9
9
  */
10
10
  export declare function getShortString(scx: ShortStringContext): string;
11
11
  export declare function getStringIfShort(cx: HasString): string | undefined;
12
- export type HasString = ParserRuleContext & {
12
+ export type HasString = {
13
13
  string: () => StringContext;
14
14
  };
15
15
  type StringPart = ParserRuleContext | string;
@@ -1645,6 +1645,28 @@ describe('unspported fields in schema', () => {
1645
1645
  expect(uModel).toTranslate();
1646
1646
  });
1647
1647
  });
1648
+ describe('cast', () => {
1649
+ // The "+ 1"s are there to make sure the result is of type 'number'
1650
+ test('sql cast', () => {
1651
+ expect((0, test_translator_1.expr) `ai::'integer' + 1`).toTranslate();
1652
+ expect((0, test_translator_1.expr) `ai::"integer" + 1`).toTranslate();
1653
+ expect((0, test_translator_1.expr) `ai::"""integer""" + 1`).toTranslate();
1654
+ });
1655
+ test('sql safe cast', () => {
1656
+ expect((0, test_translator_1.expr) `astr:::'integer' + 1`).toTranslate();
1657
+ expect((0, test_translator_1.expr) `astr:::"integer" + 1`).toTranslate();
1658
+ expect((0, test_translator_1.expr) `astr:::"""integer""" + 1`).toTranslate();
1659
+ });
1660
+ test('malloy cast', () => {
1661
+ expect((0, test_translator_1.expr) `astr::number + 1`).toTranslate();
1662
+ });
1663
+ test('malloy safe cast', () => {
1664
+ expect((0, test_translator_1.expr) `astr:::number + 1`).toTranslate();
1665
+ });
1666
+ test('sql cast illegal type name', () => {
1667
+ expect((0, test_translator_1.expr) `astr::"stuff 'n' things"`).translationToFailWith("Cast type `stuff 'n' things` is invalid for standardsql dialect");
1668
+ });
1669
+ });
1648
1670
  describe('error handling', () => {
1649
1671
  test('field and query with same name does not overflow', () => {
1650
1672
  expect(`
@@ -7,6 +7,7 @@ type ConstantExpr = Expr;
7
7
  type Condition = Expr;
8
8
  interface ParamCondition extends ParamBase {
9
9
  condition: Condition | null;
10
+ type: CastType;
10
11
  }
11
12
  interface ParamValue extends ParamBase {
12
13
  value: ConstantExpr | null;
@@ -198,7 +199,9 @@ export interface TypecastFragment extends DialectFragmentBase {
198
199
  function: 'cast';
199
200
  safe: boolean;
200
201
  expr: Expr;
201
- dstType: AtomicFieldType;
202
+ dstType: CastType | {
203
+ raw: string;
204
+ };
202
205
  srcType?: AtomicFieldType;
203
206
  }
204
207
  export interface RegexpMatchFragment extends DialectFragmentBase {
@@ -274,8 +277,10 @@ type HasExpression = FieldDef & JustExpression;
274
277
  export declare function hasExpression(f: FieldDef): f is HasExpression;
275
278
  export type TimeFieldType = 'date' | 'timestamp';
276
279
  export declare function isTimeFieldType(s: string): s is TimeFieldType;
277
- export type AtomicFieldType = 'string' | 'number' | TimeFieldType | 'boolean' | 'unsupported' | 'json' | 'error';
280
+ export type CastType = 'string' | 'number' | TimeFieldType | 'boolean' | 'json';
281
+ export type AtomicFieldType = CastType | 'unsupported' | 'error';
278
282
  export declare function isAtomicFieldType(s: string): s is AtomicFieldType;
283
+ export declare function isCastType(s: string): s is CastType;
279
284
  /**
280
285
  * Fields which contain scalar data all inherit from this. The field
281
286
  * value could be an expression, and this is one of the objects
@@ -286,31 +291,49 @@ export interface FieldAtomicDef extends NamedObject, Expression, ResultMetadata
286
291
  annotation?: Annotation;
287
292
  }
288
293
  export declare function FieldIsIntrinsic(f: FieldDef): boolean;
289
- /** Scalar String Field */
290
- export interface FieldStringDef extends FieldAtomicDef {
294
+ export interface FieldStringTypeDef {
291
295
  type: 'string';
292
296
  bucketFilter?: string;
293
297
  bucketOther?: string;
294
298
  }
295
- /** Scalar Numeric String Field */
296
- export interface FieldNumberDef extends FieldAtomicDef {
299
+ /** Scalar String Field */
300
+ export interface FieldStringDef extends FieldAtomicDef, FieldStringTypeDef {
301
+ type: 'string';
302
+ }
303
+ export interface FieldNumberTypeDef {
297
304
  type: 'number';
298
305
  numberType?: 'integer' | 'float';
299
306
  }
307
+ /** Scalar Numeric String Field */
308
+ export interface FieldNumberDef extends FieldAtomicDef, FieldNumberTypeDef {
309
+ type: 'number';
310
+ }
311
+ export interface FieldBooleanTypeDef {
312
+ type: 'boolean';
313
+ }
300
314
  /** Scalar Boolean Field */
301
- export interface FieldBooleanDef extends FieldAtomicDef {
315
+ export interface FieldBooleanDef extends FieldAtomicDef, FieldBooleanTypeDef {
302
316
  type: 'boolean';
303
317
  }
318
+ export interface FieldJSONTypeDef {
319
+ type: 'json';
320
+ }
304
321
  /** Scalar JSON Field */
305
- export interface FieldJSONDef extends FieldAtomicDef {
322
+ export interface FieldJSONDef extends FieldAtomicDef, FieldJSONTypeDef {
306
323
  type: 'json';
307
324
  }
308
- /** Scalar unsupported Field */
309
- export interface FieldUnsupportedDef extends FieldAtomicDef {
325
+ export interface FieldUnsupportedTypeDef {
310
326
  type: 'unsupported';
311
327
  rawType?: string;
312
328
  }
313
- export interface FieldErrorDef extends FieldAtomicDef {
329
+ /** Scalar unsupported Field */
330
+ export interface FieldUnsupportedDef extends FieldAtomicDef, FieldUnsupportedTypeDef {
331
+ type: 'unsupported';
332
+ }
333
+ export interface FieldErrorTypeDef {
334
+ type: 'error';
335
+ }
336
+ export interface FieldErrorDef extends FieldAtomicDef, FieldErrorTypeDef {
314
337
  type: 'error';
315
338
  }
316
339
  export type DateUnit = 'day' | 'week' | 'month' | 'quarter' | 'year';
@@ -327,16 +350,22 @@ export declare enum ValueType {
327
350
  String = "string"
328
351
  }
329
352
  export type TimeValueType = ValueType.Date | ValueType.Timestamp;
330
- /** Scalar Date Field. */
331
- export interface FieldDateDef extends FieldAtomicDef {
353
+ export interface FieldDateTypeDef {
332
354
  type: 'date';
333
355
  timeframe?: DateUnit;
334
356
  }
335
- /** Scalar Timestamp Field */
336
- export interface FieldTimestampDef extends FieldAtomicDef {
357
+ /** Scalar Date Field. */
358
+ export interface FieldDateDef extends FieldAtomicDef, FieldDateTypeDef {
359
+ type: 'date';
360
+ }
361
+ export interface FieldTimestampTypeDef {
337
362
  type: 'timestamp';
338
363
  timeframe?: TimestampUnit;
339
364
  }
365
+ /** Scalar Timestamp Field */
366
+ export interface FieldTimestampDef extends FieldAtomicDef, FieldTimestampTypeDef {
367
+ type: 'timestamp';
368
+ }
340
369
  /** parameter to order a query */
341
370
  export interface OrderBy {
342
371
  field: string | number;
@@ -550,6 +579,7 @@ export interface SQLBlockStructDef extends StructDef {
550
579
  export declare function isSQLBlockStruct(sd: StructDef): sd is SQLBlockStructDef;
551
580
  /** any of the different field types */
552
581
  export type FieldTypeDef = FieldStringDef | FieldDateDef | FieldTimestampDef | FieldNumberDef | FieldBooleanDef | FieldJSONDef | FieldUnsupportedDef | FieldErrorDef;
582
+ export type FieldAtomicTypeDef = FieldStringTypeDef | FieldDateTypeDef | FieldTimestampTypeDef | FieldNumberTypeDef | FieldBooleanTypeDef | FieldJSONTypeDef | FieldUnsupportedTypeDef | FieldErrorTypeDef;
553
583
  export declare function isFieldTypeDef(f: FieldDef): f is FieldTypeDef;
554
584
  export declare function isFieldTimeBased(f: FieldDef): f is FieldTimestampDef | FieldDateDef;
555
585
  export declare function isFieldStructDef(f: FieldDef): f is StructDef;
@@ -22,8 +22,8 @@
22
22
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.isSQLBlockStruct = exports.mergeEvalSpaces = exports.isSQLFragment = exports.isJoinOn = exports.isIndexSegment = exports.isSamplingEnable = exports.isSamplingPercent = exports.isSamplingRows = exports.isQuerySegment = exports.isProjectSegment = exports.isReduceSegment = exports.refIsStructDef = exports.isByExpression = exports.isByName = exports.ValueType = exports.isExtractUnit = exports.isTimestampUnit = exports.isDateUnit = exports.FieldIsIntrinsic = exports.isAtomicFieldType = exports.isTimeFieldType = exports.hasExpression = exports.maxOfExpressionTypes = exports.maxExpressionType = exports.isExpressionTypeLEQ = exports.expressionIsAnalytic = exports.expressionIsCalculation = exports.expressionInvolvesAggregate = exports.expressionIsUngroupedAggregate = exports.expressionIsAggregate = exports.expressionIsScalar = exports.mkExpr = exports.isApplyFragment = exports.isApplyValue = exports.isParameterFragment = exports.isFieldFragment = exports.isSpreadFragment = exports.isSQLExpressionFragment = exports.isFunctionCallFragment = exports.isFunctionParameterFragment = exports.isUngroupFragment = exports.isAsymmetricFragment = exports.isAggregateFragment = exports.isDialectFragment = exports.isFilterFragment = exports.isOutputFieldFragment = exports.isFilteredAliasedName = exports.paramHasValue = exports.isConditionParameter = exports.isValueParameter = void 0;
26
- exports.isValueDate = exports.isValueTimestamp = exports.isValueBoolean = exports.isValueNumber = exports.isValueString = exports.isMeasureLike = exports.getPhysicalFields = exports.getDimensions = exports.isPhysical = exports.isDimensional = exports.isTurtleDef = exports.getIdentifier = exports.isFieldStructDef = exports.isFieldTimeBased = exports.isFieldTypeDef = void 0;
25
+ exports.mergeEvalSpaces = exports.isSQLFragment = exports.isJoinOn = exports.isIndexSegment = exports.isSamplingEnable = exports.isSamplingPercent = exports.isSamplingRows = exports.isQuerySegment = exports.isProjectSegment = exports.isReduceSegment = exports.refIsStructDef = exports.isByExpression = exports.isByName = exports.ValueType = exports.isExtractUnit = exports.isTimestampUnit = exports.isDateUnit = exports.FieldIsIntrinsic = exports.isCastType = exports.isAtomicFieldType = exports.isTimeFieldType = exports.hasExpression = exports.maxOfExpressionTypes = exports.maxExpressionType = exports.isExpressionTypeLEQ = exports.expressionIsAnalytic = exports.expressionIsCalculation = exports.expressionInvolvesAggregate = exports.expressionIsUngroupedAggregate = exports.expressionIsAggregate = exports.expressionIsScalar = exports.mkExpr = exports.isApplyFragment = exports.isApplyValue = exports.isParameterFragment = exports.isFieldFragment = exports.isSpreadFragment = exports.isSQLExpressionFragment = exports.isFunctionCallFragment = exports.isFunctionParameterFragment = exports.isUngroupFragment = exports.isAsymmetricFragment = exports.isAggregateFragment = exports.isDialectFragment = exports.isFilterFragment = exports.isOutputFieldFragment = exports.isFilteredAliasedName = exports.paramHasValue = exports.isConditionParameter = exports.isValueParameter = void 0;
26
+ exports.isValueDate = exports.isValueTimestamp = exports.isValueBoolean = exports.isValueNumber = exports.isValueString = exports.isMeasureLike = exports.getPhysicalFields = exports.getDimensions = exports.isPhysical = exports.isDimensional = exports.isTurtleDef = exports.getIdentifier = exports.isFieldStructDef = exports.isFieldTimeBased = exports.isFieldTypeDef = exports.isSQLBlockStruct = void 0;
27
27
  function isValueParameter(p) {
28
28
  return p.value !== undefined;
29
29
  }
@@ -222,9 +222,14 @@ function isAtomicFieldType(s) {
222
222
  'boolean',
223
223
  'json',
224
224
  'unsupported',
225
+ 'error',
225
226
  ].includes(s);
226
227
  }
227
228
  exports.isAtomicFieldType = isAtomicFieldType;
229
+ function isCastType(s) {
230
+ return ['string', 'number', 'date', 'timestamp', 'boolean', 'json'].includes(s);
231
+ }
232
+ exports.isCastType = isCastType;
228
233
  // this field definition represents something in the database.
229
234
  function FieldIsIntrinsic(f) {
230
235
  if (isAtomicFieldType(f.type) && !hasExpression(f)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.79",
3
+ "version": "0.0.80-dev230824170739",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",