@malloydata/malloy 0.0.143-dev240417161322 → 0.0.143-dev240419025427

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.
@@ -55,6 +55,7 @@ export declare abstract class Dialect {
55
55
  supportsSelectReplace: boolean;
56
56
  supportsComplexFilteredSources: boolean;
57
57
  supportsTempTables: boolean;
58
+ hasModOperator: boolean;
58
59
  abstract getGlobalFunctionDef(name: string): DialectFunctionOverloadDef[] | undefined;
59
60
  abstract quoteTablePath(tablePath: string): string;
60
61
  abstract sqlGroupSetTable(groupSetCount: number): string;
@@ -78,6 +78,7 @@ class Dialect {
78
78
  this.supportsComplexFilteredSources = true;
79
79
  // can create temp tables
80
80
  this.supportsTempTables = true;
81
+ this.hasModOperator = true;
81
82
  }
82
83
  sqlFinalStage(_lastStageName, _fields) {
83
84
  throw new Error('Dialect has no final Stage but called Anyway');
@@ -116,6 +117,12 @@ class Dialect {
116
117
  }
117
118
  return (0, malloy_types_1.mkExpr) `${df.numerator}/${df.denominator}`;
118
119
  }
120
+ case 'mod': {
121
+ if (this.hasModOperator) {
122
+ return (0, malloy_types_1.mkExpr) `${df.numerator}%${df.denominator}`;
123
+ }
124
+ return (0, malloy_types_1.mkExpr) `mod(${df.numerator},${df.denominator})`;
125
+ }
119
126
  case 'timeLiteral': {
120
127
  return [
121
128
  this.sqlLiteralTime(qi, df.literal, df.literalType, df.timezone),
@@ -9,6 +9,8 @@ export declare class SnowflakeDialect extends Dialect {
9
9
  hasFinalStage: boolean;
10
10
  divisionIsInteger: boolean;
11
11
  supportsSumDistinctFunction: boolean;
12
+ supportsSafeCast: boolean;
13
+ supportsNesting: boolean;
12
14
  defaultSampling: {
13
15
  rows: number;
14
16
  };
@@ -17,10 +19,8 @@ export declare class SnowflakeDialect extends Dialect {
17
19
  supportUnnestArrayAgg: boolean;
18
20
  supportsAggDistinct: boolean;
19
21
  supportsCTEinCoorelatedSubQueries: boolean;
20
- supportsSafeCast: boolean;
21
22
  dontUnionIndex: boolean;
22
23
  supportsQualify: boolean;
23
- supportsNesting: boolean;
24
24
  supportsPipelinesInViews: boolean;
25
25
  quoteTablePath(tablePath: string): string;
26
26
  sqlGroupSetTable(groupSetCount: number): string;
@@ -81,6 +81,8 @@ class SnowflakeDialect extends dialect_1.Dialect {
81
81
  this.hasFinalStage = false;
82
82
  this.divisionIsInteger = false;
83
83
  this.supportsSumDistinctFunction = false;
84
+ this.supportsSafeCast = true;
85
+ this.supportsNesting = true;
84
86
  this.defaultSampling = { rows: 50000 };
85
87
  this.globalFunctions = functions_1.SNOWFLAKE_FUNCTIONS;
86
88
  // NOTE: safely setting all these to false for now
@@ -89,10 +91,8 @@ class SnowflakeDialect extends dialect_1.Dialect {
89
91
  this.supportUnnestArrayAgg = false;
90
92
  this.supportsAggDistinct = false;
91
93
  this.supportsCTEinCoorelatedSubQueries = false;
92
- this.supportsSafeCast = false;
93
94
  this.dontUnionIndex = false;
94
95
  this.supportsQualify = false;
95
- this.supportsNesting = true;
96
96
  this.supportsPipelinesInViews = false;
97
97
  }
98
98
  // don't mess with the table pathing.
@@ -268,10 +268,12 @@ ${(0, utils_1.indent)(sql)}
268
268
  if (cast.srcType === cast.dstType) {
269
269
  return cast.expr;
270
270
  }
271
- if (cast.safe) {
271
+ if (cast.safe && typeof cast.srcType !== 'string') {
272
272
  // safe cast is only supported for a few combinations of src -> dst types
273
273
  // so we will not support it in the general case
274
- throw new Error("Snowflake dialect doesn't support safe cast for a few types");
274
+ // see: https://docs.snowflake.com/en/sql-reference/functions/try_cast
275
+ throw new Error(`Snowflake dialect doesn't support safe cast for a few types:
276
+ refer to: https://docs.snowflake.com/en/sql-reference/functions/try_cast`);
275
277
  }
276
278
  const tz = (0, dialect_1.qtz)(qi);
277
279
  // casting timestamps and dates
@@ -289,7 +291,8 @@ ${(0, utils_1.indent)(sql)}
289
291
  const dstType = typeof cast.dstType === 'string'
290
292
  ? this.malloyTypeToSQLType({ type: cast.dstType })
291
293
  : cast.dstType.raw;
292
- return (0, malloy_types_1.mkExpr) `CAST(${cast.expr} AS ${dstType})`;
294
+ const castFunc = cast.safe ? 'TRY_CAST' : 'CAST';
295
+ return (0, malloy_types_1.mkExpr) `${castFunc}(${cast.expr} AS ${dstType})`;
293
296
  }
294
297
  sqlLiteralTime(qi, timeString, type, timezone) {
295
298
  const tz = (0, dialect_1.qtz)(qi);
@@ -21,6 +21,7 @@ export declare class StandardSQLDialect extends Dialect {
21
21
  supportsSafeCast: boolean;
22
22
  supportsNesting: boolean;
23
23
  cantPartitionWindowFunctionsOnExpressions: boolean;
24
+ hasModOperator: boolean;
24
25
  quoteTablePath(tablePath: string): string;
25
26
  sqlGroupSetTable(groupSetCount: number): string;
26
27
  sqlAnyValue(groupSet: number, fieldName: string): string;
@@ -93,6 +93,7 @@ class StandardSQLDialect extends dialect_1.Dialect {
93
93
  this.supportsSafeCast = true;
94
94
  this.supportsNesting = true;
95
95
  this.cantPartitionWindowFunctionsOnExpressions = true;
96
+ this.hasModOperator = false;
96
97
  this.keywords = `
97
98
  ALL
98
99
  AND
@@ -399,10 +399,10 @@ function applyBinary(fs, left, op, right) {
399
399
  if (oneOf(op, '+', '-')) {
400
400
  return delta(fs, left, op, right);
401
401
  }
402
- if (oneOf(op, '*', '%')) {
402
+ if (op === '*') {
403
403
  return numeric(fs, left, op, right);
404
404
  }
405
- if (oneOf(op, '/')) {
405
+ if (oneOf(op, '/', '%')) {
406
406
  const num = left.getExpression(fs);
407
407
  const denom = right.getExpression(fs);
408
408
  const noGo = unsupportError(left, num, right, denom);
@@ -414,15 +414,15 @@ function applyBinary(fs, left, op, right) {
414
414
  if (err)
415
415
  return err;
416
416
  if (num.dataType !== 'number') {
417
- left.log('Numerator for division must be a number');
417
+ left.log('Numerator must be a number');
418
418
  }
419
419
  else if (denom.dataType !== 'number') {
420
- right.log('Denominator for division must be a number');
420
+ right.log('Denominator must be a number');
421
421
  }
422
422
  else {
423
423
  const div = {
424
424
  type: 'dialect',
425
- function: 'div',
425
+ function: op === '/' ? 'div' : 'mod',
426
426
  numerator: num.value,
427
427
  denominator: denom.value,
428
428
  };
@@ -1591,6 +1591,7 @@ class QueryQuery extends QueryField {
1591
1591
  case 'now':
1592
1592
  break;
1593
1593
  case 'div':
1594
+ case 'mod':
1594
1595
  expressions.push(expr.denominator);
1595
1596
  expressions.push(expr.numerator);
1596
1597
  break;
@@ -230,8 +230,8 @@ export interface RegexpMatchFragment extends DialectFragmentBase {
230
230
  expr: Expr;
231
231
  regexp: Expr;
232
232
  }
233
- export interface DivFragment extends DialectFragmentBase {
234
- function: 'div';
233
+ export interface DivModFragment extends DialectFragmentBase {
234
+ function: 'div' | 'mod';
235
235
  numerator: Expr;
236
236
  denominator: Expr;
237
237
  }
@@ -253,7 +253,7 @@ export interface NumberLiteralFragment extends DialectFragmentBase {
253
253
  function: 'numberLiteral';
254
254
  literal: string;
255
255
  }
256
- export type DialectFragment = DivFragment | TimeLiteralFragment | NowFragment | TimeDeltaFragment | TimeDiffFragment | TimeTruncFragment | TypecastFragment | TimeExtractFragment | StringLiteralFragment | RegexpLiteralFragment | NumberLiteralFragment | RegexpMatchFragment;
256
+ export type DialectFragment = DivModFragment | TimeLiteralFragment | NowFragment | TimeDeltaFragment | TimeDiffFragment | TimeTruncFragment | TypecastFragment | TimeExtractFragment | StringLiteralFragment | RegexpLiteralFragment | NumberLiteralFragment | RegexpMatchFragment;
257
257
  export type Fragment = string | ApplyFragment | ApplyValueFragment | FieldFragment | SourceReferenceFragment | SqlStringFragment | ParameterFragment | FilterFragment | OutputFieldFragment | AggregateFragment | UngroupFragment | DialectFragment | FunctionParameterFragment | AggregateOrderByFragment | AggregateLimitFragment | FunctionCallFragment | SQLExpressionFragment | SpreadFragment;
258
258
  export type Expr = Fragment[];
259
259
  export interface TypedValue {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.143-dev240417161322",
3
+ "version": "0.0.143-dev240419025427",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./dist/index.js",