@malloydata/malloy 0.0.23 → 0.0.24-dev230215185525

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.
@@ -41,10 +41,8 @@ class ExprIdReference extends expression_def_1.ExpressionDef {
41
41
  const def = this.fieldReference.getField(fs);
42
42
  if (def.found) {
43
43
  const value = [{ "type": def.found.refType, "path": this.refString }];
44
- return {
45
- ...def.found.typeDesc(),
46
- value
47
- };
44
+ const td = def.found.typeDesc();
45
+ return { ...td, value };
48
46
  }
49
47
  this.log(def.error);
50
48
  return (0, ast_utils_1.errorFor)(def.error);
@@ -5,5 +5,6 @@ export declare class ExprLogicalOp extends BinaryBoolean<"and" | "or"> {
5
5
  aggregate: boolean;
6
6
  dataType: import("../types/type-desc").FieldValueType;
7
7
  expressionType: import("../../..").ExpressionType;
8
+ rawType?: string | undefined;
8
9
  })[];
9
10
  }
@@ -23,7 +23,6 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.ExprNot = void 0;
26
- const ast_utils_1 = require("../ast-utils");
27
26
  const fragtype_utils_1 = require("../fragtype-utils");
28
27
  const unary_1 = require("./unary");
29
28
  const utils_1 = require("./utils");
@@ -35,14 +34,12 @@ class ExprNot extends unary_1.Unary {
35
34
  }
36
35
  getExpression(fs) {
37
36
  const notThis = this.expr.getExpression(fs);
38
- if (this.typeCheck(this.expr, notThis)) {
39
- return {
40
- ...notThis,
41
- "dataType": "boolean",
42
- "value": (0, utils_1.nullsafeNot)(notThis.value)
43
- };
44
- }
45
- return (0, ast_utils_1.errorFor)("not requires boolean");
37
+ const doNot = this.typeCheck(this.expr, notThis);
38
+ return {
39
+ ...notThis,
40
+ "dataType": "boolean",
41
+ "value": doNot ? (0, utils_1.nullsafeNot)(notThis.value) : ["false"]
42
+ };
46
43
  }
47
44
  }
48
45
  exports.ExprNot = ExprNot;
@@ -197,6 +197,18 @@ function nullCompare(left, op, right) {
197
197
  function equality(fs, left, op, right) {
198
198
  const lhs = left.getExpression(fs);
199
199
  const rhs = right.getExpression(fs);
200
+ // Unsupported types can be compare with null
201
+ const checkUnsupport = lhs.dataType === "unsupported" || rhs.dataType === "unsupported";
202
+ if (checkUnsupport) {
203
+ const oneNull = lhs.dataType === "null" || rhs.dataType === "null";
204
+ const rawMatch = lhs.rawType && lhs.rawType === rhs.rawType;
205
+ if (!(oneNull || rawMatch)) {
206
+ const noGo = unsupportError(left, lhs, right, rhs);
207
+ if (noGo) {
208
+ return { ...noGo, "dataType": "boolean" };
209
+ }
210
+ }
211
+ }
200
212
  let value = timeCompare(lhs, op, rhs) || (0, utils_1.compose)(lhs.value, op, rhs.value);
201
213
  if (lhs.dataType != "unknown" && rhs.dataType != "unknown") {
202
214
  switch (op) {
@@ -238,6 +250,10 @@ function compare(fs, left, op, right) {
238
250
  const lhs = left.getExpression(fs);
239
251
  const rhs = right.getExpression(fs);
240
252
  const expressionType = (0, malloy_types_1.maxExpressionType)(lhs.expressionType, rhs.expressionType);
253
+ const noCompare = unsupportError(left, lhs, right, rhs);
254
+ if (noCompare) {
255
+ return { ...noCompare, "dataType": "boolean" };
256
+ }
241
257
  const value = timeCompare(lhs, op, rhs) || (0, utils_1.compose)(lhs.value, op, rhs.value);
242
258
  return {
243
259
  "dataType": "boolean",
@@ -259,6 +275,10 @@ function allAre(oneType, ...values) {
259
275
  function numeric(fs, left, op, right) {
260
276
  const lhs = left.getExpression(fs);
261
277
  const rhs = right.getExpression(fs);
278
+ const noGo = unsupportError(left, lhs, right, rhs);
279
+ if (noGo) {
280
+ return noGo;
281
+ }
262
282
  const expressionType = (0, malloy_types_1.maxExpressionType)(lhs.expressionType, rhs.expressionType);
263
283
  if (allAre("number", lhs, rhs)) {
264
284
  return {
@@ -273,6 +293,10 @@ function numeric(fs, left, op, right) {
273
293
  function delta(fs, left, op, right) {
274
294
  const lhs = left.getExpression(fs);
275
295
  const rhs = right.getExpression(fs);
296
+ const noGo = unsupportError(left, lhs, right, rhs);
297
+ if (noGo) {
298
+ return noGo;
299
+ }
276
300
  if ((0, malloy_types_1.isTimeFieldType)(lhs.dataType)) {
277
301
  let duration = right;
278
302
  if (rhs.dataType !== "duration") {
@@ -318,6 +342,11 @@ function applyBinary(fs, left, op, right) {
318
342
  if (oneOf(op, "/")) {
319
343
  const num = left.getExpression(fs);
320
344
  const denom = right.getExpression(fs);
345
+ const noGo = unsupportError(left, num, right, denom);
346
+ if (noGo) {
347
+ left.log("Cannot operate with unsupported type");
348
+ return noGo;
349
+ }
321
350
  if (num.dataType != "number") {
322
351
  left.log("Numerator for division must be a number");
323
352
  }
@@ -343,4 +372,23 @@ function applyBinary(fs, left, op, right) {
343
372
  return (0, ast_utils_1.errorFor)("applybinary bad operator");
344
373
  }
345
374
  exports.applyBinary = applyBinary;
375
+ /**
376
+ * Return an error if an binary operation includes unsupported types.
377
+ */
378
+ function unsupportError(l, lhs, r, rhs) {
379
+ const ret = {
380
+ "dataType": lhs.dataType,
381
+ "expressionType": (0, malloy_types_1.maxExpressionType)(lhs.expressionType, rhs.expressionType),
382
+ "value": ["'unsupported operation'"]
383
+ };
384
+ if (lhs.dataType === "unsupported") {
385
+ l.log("Unsupported type not allowed in expression");
386
+ return { ...ret, "dataType": rhs.dataType };
387
+ }
388
+ if (rhs.dataType === "unsupported") {
389
+ r.log("Unsupported type not allowed in expression");
390
+ return ret;
391
+ }
392
+ return undefined;
393
+ }
346
394
  //# sourceMappingURL=expression-def.js.map
@@ -35,6 +35,11 @@ class SpaceField extends space_entry_1.SpaceEntry {
35
35
  if ((0, malloy_types_1.isFieldTypeDef)(def) && def.expressionType) {
36
36
  ref.expressionType = def.expressionType;
37
37
  }
38
+ if (ref.dataType === "unsupported" &&
39
+ def.type === "unsupported" &&
40
+ def.rawType) {
41
+ ref.rawType = def.rawType;
42
+ }
38
43
  return ref;
39
44
  }
40
45
  getQueryFieldDef(_fs) {
@@ -4,4 +4,5 @@ export declare type FieldValueType = ExpressionValueType | "turtle" | "struct";
4
4
  export interface TypeDesc {
5
5
  dataType: FieldValueType;
6
6
  expressionType: ExpressionType;
7
+ rawType?: string;
7
8
  }
@@ -91,6 +91,17 @@ describe("structdef comprehension", () => {
91
91
  const oField = space.structDef().fields[0];
92
92
  expect(oField).toEqual(field);
93
93
  });
94
+ test(`import unsupported field`, () => {
95
+ const field = {
96
+ "name": "t",
97
+ "type": "unsupported"
98
+ };
99
+ const struct = mkStructDef(field);
100
+ const space = new static_space_1.StaticSpace(struct);
101
+ expect(space.lookup(fieldRef("t")).found).toBeInstanceOf(column_space_field_1.ColumnSpaceField);
102
+ const oField = space.structDef().fields[0];
103
+ expect(oField).toEqual(field);
104
+ });
94
105
  test(`import nested field`, () => {
95
106
  const field = {
96
107
  "name": "t",
@@ -1088,6 +1088,38 @@ describe("expressions", () => {
1088
1088
  }
1089
1089
  });
1090
1090
  });
1091
+ describe("unspported fields in schema", () => {
1092
+ test("unsupported reference in result allowed", () => {
1093
+ const uModel = new BetaModel(`query: a->{ group_by: aun }`);
1094
+ expect(uModel).modelCompiled();
1095
+ });
1096
+ test("unsupported reference can be compared to NULL", () => {
1097
+ const uModel = new BetaModel(`query: a->{ where: aun != NULL; project: * }`);
1098
+ expect(uModel).modelCompiled();
1099
+ });
1100
+ test("flag unsupported equality", () => {
1101
+ // because we don't know if the two unsupported types are comparable
1102
+ const uModel = new BetaModel(`query: ab->{ where: aun = b.aun project: * }`);
1103
+ expect(uModel).compileToFailWith("Unsupported type not allowed in expression");
1104
+ });
1105
+ test("flag unsupported compare", () => {
1106
+ // because we don't know if the two unsupported types are comparable
1107
+ const uModel = new BetaModel(`query: ab->{ where: aun > b.aun project: * }`);
1108
+ expect(uModel).compileToFailWith("Unsupported type not allowed in expression");
1109
+ });
1110
+ test("allow unsupported equality when raw types match", () => {
1111
+ const uModel = new BetaModel(`query: ab->{ where: aweird = b.aweird project: * }`);
1112
+ expect(uModel).modelCompiled();
1113
+ });
1114
+ test("flag not applied to unsupported", () => {
1115
+ const uModel = new BetaModel(`source: x is a { dimension: notUn is not aun }`);
1116
+ expect(uModel).compileToFailWith("'not' Can't use type unsupported");
1117
+ });
1118
+ test("allow unsupported to be cast", () => {
1119
+ const uModel = new BetaModel(`source: x is a { dimension: notUn is aun::string }`);
1120
+ expect(uModel).modelCompiled();
1121
+ });
1122
+ });
1091
1123
  describe("sql:", () => {
1092
1124
  function makeSchemaResponse(sql) {
1093
1125
  const cname = sql.connection || "bigquery";
@@ -45,7 +45,9 @@ const mockSchema = {
45
45
  { "type": "number", "name": "ai", "numberType": "integer" },
46
46
  { "type": "date", "name": "ad" },
47
47
  { "type": "boolean", "name": "abool" },
48
- { "type": "timestamp", "name": "ats" }
48
+ { "type": "timestamp", "name": "ats" },
49
+ { "type": "unsupported", "name": "aun" },
50
+ { "type": "unsupported", "name": "aweird", "rawType": "weird" }
49
51
  ]
50
52
  },
51
53
  "malloytest.carriers": {
package/dist/malloy.d.ts CHANGED
@@ -494,7 +494,8 @@ export declare enum AtomicFieldType {
494
494
  Boolean = "boolean",
495
495
  Date = "date",
496
496
  Timestamp = "timestamp",
497
- Json = "json"
497
+ Json = "json",
498
+ Unsupported = "unsupported"
498
499
  }
499
500
  export declare class AtomicField extends Entity {
500
501
  protected fieldTypeDef: FieldTypeDef;
package/dist/malloy.js CHANGED
@@ -986,6 +986,7 @@ var AtomicFieldType;
986
986
  AtomicFieldType["Date"] = "date";
987
987
  AtomicFieldType["Timestamp"] = "timestamp";
988
988
  AtomicFieldType["Json"] = "json";
989
+ AtomicFieldType["Unsupported"] = "unsupported";
989
990
  })(AtomicFieldType = exports.AtomicFieldType || (exports.AtomicFieldType = {}));
990
991
  class AtomicField extends Entity {
991
992
  constructor(fieldTypeDef, parent, source) {
@@ -1007,6 +1008,8 @@ class AtomicField extends Entity {
1007
1008
  return AtomicFieldType.Number;
1008
1009
  case "json":
1009
1010
  return AtomicFieldType.Json;
1011
+ case "unsupported":
1012
+ return AtomicFieldType.Unsupported;
1010
1013
  }
1011
1014
  }
1012
1015
  isIntrinsic() {
@@ -519,6 +519,8 @@ class QueryFieldBoolean extends QueryAtomicField {
519
519
  }
520
520
  class QueryFieldJSON extends QueryAtomicField {
521
521
  }
522
+ class QueryFieldUnsupported extends QueryAtomicField {
523
+ }
522
524
  // in a query a struct can be referenced. The struct will
523
525
  // emit the primary key field in the actual result set and
524
526
  // will include the StructDef as a foreign key join in the output
@@ -1638,6 +1640,9 @@ class QueryQuery extends QueryField {
1638
1640
  location
1639
1641
  });
1640
1642
  break;
1643
+ case "unsupported":
1644
+ fields.push({ ...fi.f.fieldDef, resultMetadata, location });
1645
+ break;
1641
1646
  default:
1642
1647
  throw new Error(`unknown Field Type in query ${JSON.stringify(fi.f.fieldDef)}`);
1643
1648
  }
@@ -2791,6 +2796,8 @@ class QueryStruct extends QueryNode {
2791
2796
  return new QueryFieldBoolean(field, this);
2792
2797
  case "json":
2793
2798
  return new QueryFieldJSON(field, this);
2799
+ case "unsupported":
2800
+ return new QueryFieldUnsupported(field, this);
2794
2801
  // case "reduce":
2795
2802
  // case "project":
2796
2803
  // case "index":
@@ -241,7 +241,7 @@ declare type HasExpression = FieldDef & JustExpression;
241
241
  export declare function hasExpression(f: FieldDef): f is HasExpression;
242
242
  export declare type TimeFieldType = "date" | "timestamp";
243
243
  export declare function isTimeFieldType(s: string): s is TimeFieldType;
244
- export declare type AtomicFieldType = "string" | "number" | TimeFieldType | "boolean" | "json";
244
+ export declare type AtomicFieldType = "string" | "number" | TimeFieldType | "boolean" | "unsupported" | "json";
245
245
  export declare function isAtomicFieldType(s: string): s is AtomicFieldType;
246
246
  /** All scalars can have an optional expression */
247
247
  export interface FieldAtomicDef extends NamedObject, Expression, ResultMetadata {
@@ -267,6 +267,11 @@ export interface FieldBooleanDef extends FieldAtomicDef {
267
267
  export interface FieldJSONDef extends FieldAtomicDef {
268
268
  type: "json";
269
269
  }
270
+ /** Scalar unsupported Field */
271
+ export interface FieldUnsupportedDef extends FieldAtomicDef {
272
+ type: "unsupported";
273
+ rawType?: string;
274
+ }
270
275
  export declare type DateUnit = "day" | "week" | "month" | "quarter" | "year";
271
276
  export declare function isDateUnit(str: string): str is DateUnit;
272
277
  export declare type TimestampUnit = DateUnit | "hour" | "minute" | "second";
@@ -450,7 +455,7 @@ export interface SQLBlockStructDef extends StructDef {
450
455
  }
451
456
  export declare function isSQLBlock(sd: StructDef): sd is SQLBlockStructDef;
452
457
  /** any of the different field types */
453
- export declare type FieldTypeDef = FieldStringDef | FieldDateDef | FieldTimestampDef | FieldNumberDef | FieldBooleanDef | FieldJSONDef;
458
+ export declare type FieldTypeDef = FieldStringDef | FieldDateDef | FieldTimestampDef | FieldNumberDef | FieldBooleanDef | FieldJSONDef | FieldUnsupportedDef;
454
459
  export declare function isFieldTypeDef(f: FieldDef): f is FieldTypeDef;
455
460
  export declare function isFieldTimeBased(f: FieldDef): f is FieldTimestampDef | FieldDateDef;
456
461
  export declare function isFieldStructDef(f: FieldDef): f is StructDef;
@@ -197,7 +197,15 @@ function isTimeFieldType(s) {
197
197
  }
198
198
  exports.isTimeFieldType = isTimeFieldType;
199
199
  function isAtomicFieldType(s) {
200
- return ["string", "number", "date", "timestamp", "boolean", "json"].includes(s);
200
+ return [
201
+ "string",
202
+ "number",
203
+ "date",
204
+ "timestamp",
205
+ "boolean",
206
+ "json",
207
+ "unsupported"
208
+ ].includes(s);
201
209
  }
202
210
  exports.isAtomicFieldType = isAtomicFieldType;
203
211
  // this field definition represents something in the database.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.23",
3
+ "version": "0.0.24-dev230215185525",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",