@malloydata/render 0.0.119-dev240116200529 → 0.0.119-dev240118215411

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.
@@ -235,8 +235,8 @@
235
235
  "../malloy/dist/model/malloy_types.js"(exports) {
236
236
  "use strict";
237
237
  Object.defineProperty(exports, "__esModule", { value: true });
238
- exports.isMatrixOperation = exports.isIndexSegment = exports.isRawSegment = exports.isSamplingEnable = exports.isSamplingPercent = exports.isSamplingRows = exports.isQuerySegment = exports.isProjectSegment = exports.isPartialSegment = 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;
239
- exports.isValueDate = exports.isValueTimestamp = exports.isValueBoolean = exports.isValueNumber = exports.isValueString = exports.isMeasureLike = exports.getPhysicalFields = exports.getDimensions = exports.isPhysical = exports.isDimensional = exports.isAtomicField = exports.isTurtleDef = exports.getIdentifier = exports.isFieldStructDef = exports.isFieldTimeBased = exports.isFieldTypeDef = exports.isSQLBlockStruct = exports.mergeEvalSpaces = exports.isSQLFragment = exports.isJoinOn = void 0;
238
+ exports.isSamplingEnable = exports.isSamplingPercent = exports.isSamplingRows = exports.isQuerySegment = exports.isProjectSegment = exports.isPartialSegment = 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.isSourceReferenceFragment = exports.isSqlStringFragment = exports.isFieldReferenceFragment = 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;
239
+ exports.isValueDate = exports.isValueTimestamp = exports.isValueBoolean = exports.isValueNumber = exports.isValueString = exports.isMeasureLike = exports.getPhysicalFields = exports.getDimensions = exports.isPhysical = exports.isDimensional = exports.isAtomicField = exports.isTurtleDef = exports.getIdentifier = exports.isFieldStructDef = exports.isFieldTimeBased = exports.isFieldTypeDef = exports.isSQLBlockStruct = exports.mergeEvalSpaces = exports.isSQLFragment = exports.isJoinOn = exports.isMatrixOperation = exports.isIndexSegment = exports.isRawSegment = void 0;
240
240
  function isValueParameter(p3) {
241
241
  return p3.value !== void 0;
242
242
  }
@@ -303,6 +303,18 @@
303
303
  return (f4 === null || f4 === void 0 ? void 0 : f4.type) === "field";
304
304
  }
305
305
  exports.isFieldFragment = isFieldFragment;
306
+ function isFieldReferenceFragment(f4) {
307
+ return (f4 === null || f4 === void 0 ? void 0 : f4.type) === "field-reference";
308
+ }
309
+ exports.isFieldReferenceFragment = isFieldReferenceFragment;
310
+ function isSqlStringFragment(f4) {
311
+ return (f4 === null || f4 === void 0 ? void 0 : f4.type) === "sql-string";
312
+ }
313
+ exports.isSqlStringFragment = isSqlStringFragment;
314
+ function isSourceReferenceFragment(f4) {
315
+ return (f4 === null || f4 === void 0 ? void 0 : f4.type) === "source-reference";
316
+ }
317
+ exports.isSourceReferenceFragment = isSourceReferenceFragment;
306
318
  function isParameterFragment(f4) {
307
319
  return (f4 === null || f4 === void 0 ? void 0 : f4.type) === "parameter";
308
320
  }
@@ -1349,6 +1361,11 @@
1349
1361
  case "parameter":
1350
1362
  case "outputField":
1351
1363
  return fragment2;
1364
+ case "sql-string":
1365
+ return {
1366
+ ...fragment2,
1367
+ e: exprMap(fragment2.e, func)
1368
+ };
1352
1369
  case "function_call":
1353
1370
  return {
1354
1371
  ...fragment2,
@@ -1455,6 +1472,11 @@
1455
1472
  ...fragment,
1456
1473
  args: fragment.args.map((arg) => exprWalk(arg, func))
1457
1474
  };
1475
+ case "sql-string":
1476
+ return {
1477
+ ...fragment,
1478
+ e: exprWalk(fragment.e, func)
1479
+ };
1458
1480
  case "filterExpression":
1459
1481
  return {
1460
1482
  ...fragment,
@@ -2433,6 +2455,51 @@
2433
2455
  }
2434
2456
  });
2435
2457
 
2458
+ // ../malloy/dist/dialect/functions/sql.js
2459
+ var require_sql = __commonJS({
2460
+ "../malloy/dist/dialect/functions/sql.js"(exports) {
2461
+ "use strict";
2462
+ Object.defineProperty(exports, "__esModule", { value: true });
2463
+ exports.fnSqlBoolean = exports.fnSqlTimestamp = exports.fnSqlDate = exports.fnSqlString = exports.fnSqlNumber = void 0;
2464
+ var util_1 = require_util();
2465
+ function fnSqlNumber() {
2466
+ const value3 = (0, util_1.makeParam)("value", (0, util_1.literal)((0, util_1.maxScalar)("string")));
2467
+ return [
2468
+ (0, util_1.overload)((0, util_1.minScalar)("number"), [value3.param], [{ type: "sql-string", e: [value3.arg] }])
2469
+ ];
2470
+ }
2471
+ exports.fnSqlNumber = fnSqlNumber;
2472
+ function fnSqlString() {
2473
+ const value3 = (0, util_1.makeParam)("value", (0, util_1.literal)((0, util_1.maxScalar)("string")));
2474
+ return [
2475
+ (0, util_1.overload)((0, util_1.minScalar)("string"), [value3.param], [{ type: "sql-string", e: [value3.arg] }])
2476
+ ];
2477
+ }
2478
+ exports.fnSqlString = fnSqlString;
2479
+ function fnSqlDate() {
2480
+ const value3 = (0, util_1.makeParam)("value", (0, util_1.literal)((0, util_1.maxScalar)("string")));
2481
+ return [
2482
+ (0, util_1.overload)((0, util_1.minScalar)("date"), [value3.param], [{ type: "sql-string", e: [value3.arg] }])
2483
+ ];
2484
+ }
2485
+ exports.fnSqlDate = fnSqlDate;
2486
+ function fnSqlTimestamp() {
2487
+ const value3 = (0, util_1.makeParam)("value", (0, util_1.literal)((0, util_1.maxScalar)("string")));
2488
+ return [
2489
+ (0, util_1.overload)((0, util_1.minScalar)("timestamp"), [value3.param], [{ type: "sql-string", e: [value3.arg] }])
2490
+ ];
2491
+ }
2492
+ exports.fnSqlTimestamp = fnSqlTimestamp;
2493
+ function fnSqlBoolean() {
2494
+ const value3 = (0, util_1.makeParam)("value", (0, util_1.literal)((0, util_1.maxScalar)("string")));
2495
+ return [
2496
+ (0, util_1.overload)((0, util_1.minScalar)("boolean"), [value3.param], [{ type: "sql-string", e: [value3.arg] }])
2497
+ ];
2498
+ }
2499
+ exports.fnSqlBoolean = fnSqlBoolean;
2500
+ }
2501
+ });
2502
+
2436
2503
  // ../malloy/dist/dialect/functions/all_functions.js
2437
2504
  var require_all_functions = __commonJS({
2438
2505
  "../malloy/dist/dialect/functions/all_functions.js"(exports) {
@@ -2476,6 +2543,7 @@
2476
2543
  var avg_moving_1 = require_avg_moving();
2477
2544
  var function_map_1 = require_function_map();
2478
2545
  var coalesce_1 = require_coalesce();
2546
+ var sql_1 = require_sql();
2479
2547
  exports.FUNCTIONS = new function_map_1.FunctionMap();
2480
2548
  exports.FUNCTIONS.add("concat", concat_1.fnConcat);
2481
2549
  exports.FUNCTIONS.add("round", round_1.fnRound);
@@ -2538,6 +2606,11 @@
2538
2606
  exports.FUNCTIONS.add("max_window", sum_min_max_window_1.fnMaxWindow);
2539
2607
  exports.FUNCTIONS.add("sum_window", sum_min_max_window_1.fnSumWindow);
2540
2608
  exports.FUNCTIONS.add("avg_moving", avg_moving_1.fnAvgRolling);
2609
+ exports.FUNCTIONS.add("sql_number", sql_1.fnSqlNumber);
2610
+ exports.FUNCTIONS.add("sql_string", sql_1.fnSqlString);
2611
+ exports.FUNCTIONS.add("sql_date", sql_1.fnSqlDate);
2612
+ exports.FUNCTIONS.add("sql_timestamp", sql_1.fnSqlTimestamp);
2613
+ exports.FUNCTIONS.add("sql_boolean", sql_1.fnSqlBoolean);
2541
2614
  exports.FUNCTIONS.seal();
2542
2615
  }
2543
2616
  });
@@ -3612,16 +3685,16 @@ ${(0, utils_1.indent)(sql)}
3612
3685
  return "GEN_RANDOM_UUID()";
3613
3686
  }
3614
3687
  sqlFieldReference(alias, fieldName, fieldType, isNested, _isArray) {
3615
- let ret = `${alias}->>'${fieldName}'`;
3688
+ let ret = `(${alias}->>'${fieldName}')`;
3616
3689
  if (isNested) {
3617
3690
  switch (fieldType) {
3618
3691
  case "string":
3619
3692
  break;
3620
3693
  case "number":
3621
- ret = `(${ret})::double precision`;
3694
+ ret = `${ret}::double precision`;
3622
3695
  break;
3623
3696
  case "struct":
3624
- ret = `(${ret})::jsonb`;
3697
+ ret = `${ret}::jsonb`;
3625
3698
  break;
3626
3699
  }
3627
3700
  return ret;
@@ -4678,6 +4751,16 @@ ${hackSplitComment}
4678
4751
  function identifierNormalize(s8) {
4679
4752
  return s8.replace(/[^a-zA-Z0-9_]/g, "_o_");
4680
4753
  }
4754
+ var UniqueKeyUse = class extends Set {
4755
+ add_use(k2) {
4756
+ if (k2 !== void 0) {
4757
+ return this.add(k2);
4758
+ }
4759
+ }
4760
+ hasAsymetricFunctions() {
4761
+ return this.has("sum") || this.has("avg") || this.has("count");
4762
+ }
4763
+ };
4681
4764
  var StageWriter = class {
4682
4765
  constructor(useCTE = true, parent) {
4683
4766
  this.parent = parent;
@@ -4809,8 +4892,8 @@ ${(0, utils_1.indent)(sql)})
4809
4892
  this.parent = parent;
4810
4893
  this.fieldDef = fieldDef;
4811
4894
  }
4812
- mayNeedUniqueKey() {
4813
- return false;
4895
+ uniqueKeyPossibleUse() {
4896
+ return void 0;
4814
4897
  }
4815
4898
  getJoinableParent() {
4816
4899
  const parent = this.parent;
@@ -5027,10 +5110,18 @@ ${(0, utils_1.indent)(sql)})
5027
5110
  generateCountFragment(resultSet, context3, expr2, state) {
5028
5111
  let func = "COUNT(";
5029
5112
  let thing = "1";
5030
- const distinctKeySQL = this.generateDistinctKeyIfNecessary(resultSet, context3, expr2.structPath);
5031
- if (distinctKeySQL) {
5113
+ let struct = context3;
5114
+ if (expr2.structPath) {
5115
+ struct = this.parent.root().getStructByName(expr2.structPath);
5116
+ }
5117
+ const joinName = struct.getJoinableParent().getIdentifier();
5118
+ const join3 = resultSet.root().joins.get(joinName);
5119
+ if (!join3) {
5120
+ throw new Error(`Join ${joinName} not found in result set`);
5121
+ }
5122
+ if (!join3.leafiest || join3.makeUniqueKey) {
5032
5123
  func = "COUNT(DISTINCT";
5033
- thing = distinctKeySQL;
5124
+ thing = struct.getDistinctKey().generateExpression(resultSet);
5034
5125
  }
5035
5126
  if (state.whereSQL) {
5036
5127
  return `${func} CASE WHEN ${state.whereSQL} THEN ${thing} END)`;
@@ -5041,6 +5132,19 @@ ${(0, utils_1.indent)(sql)})
5041
5132
  generateDialect(resultSet, context3, expr2, state) {
5042
5133
  return this.generateExpressionFromExpr(resultSet, context3, context3.dialect.dialectExpr(resultSet.getQueryInfo(), expr2), state);
5043
5134
  }
5135
+ generateFieldReference(resultSet, context3, expr2, state) {
5136
+ return this.generateFieldFragment(resultSet, context3, { type: "field", path: expr2.path }, state);
5137
+ }
5138
+ generateSqlString(resultSet, context3, expr2, state) {
5139
+ return expr2.e.map((part) => typeof part === "string" ? part : this.generateExpressionFromExpr(resultSet, context3, [part], state)).join("");
5140
+ }
5141
+ generateSourceReference(resultSet, context3, expr2) {
5142
+ if (expr2.path === void 0) {
5143
+ return context3.getSQLIdentifier();
5144
+ } else {
5145
+ return context3.getFieldByName(expr2.path).getIdentifier();
5146
+ }
5147
+ }
5044
5148
  getAnalyticPartitions(resultStruct) {
5045
5149
  const ret = [];
5046
5150
  let p3 = resultStruct.parent;
@@ -5174,6 +5278,12 @@ ${(0, utils_1.indent)(sql)})
5174
5278
  s8 += this.generateSpread(resultSet, context3, expr2, state);
5175
5279
  } else if (expr2.type === "dialect") {
5176
5280
  s8 += this.generateDialect(resultSet, context3, expr2, state);
5281
+ } else if (expr2.type === "sql-string") {
5282
+ s8 += this.generateSqlString(resultSet, context3, expr2, state);
5283
+ } else if (expr2.type === "source-reference") {
5284
+ s8 += this.generateSourceReference(resultSet, context3, expr2);
5285
+ } else if (expr2.type === "field-reference") {
5286
+ s8 += this.generateFieldReference(resultSet, context3, expr2, state);
5177
5287
  } else {
5178
5288
  throw new Error(`Internal Error: Unknown expression fragment ${JSON.stringify(expr2, void 0, 2)}`);
5179
5289
  }
@@ -5293,7 +5403,12 @@ ${(0, utils_1.indent)(sql)})
5293
5403
  return pk.generateExpression(resultSet);
5294
5404
  } else if (this.parent.fieldDef.structSource.type === "nested") {
5295
5405
  const parentKey = (_a = this.parent.parent) === null || _a === void 0 ? void 0 : _a.getDistinctKey().generateExpression(resultSet);
5296
- return `CONCAT(${parentKey}, 'x', ${this.parent.dialect.sqlFieldReference(this.parent.getIdentifier(), "__row_id", "string", true, false)})`;
5406
+ return this.parent.dialect.concat(
5407
+ parentKey || "",
5408
+ // shouldn't have to do this...
5409
+ "'x'",
5410
+ this.parent.dialect.sqlFieldReference(this.parent.getIdentifier(), "__row_id", "string", true, false)
5411
+ );
5297
5412
  } else {
5298
5413
  return this.parent.dialect.sqlFieldReference(this.parent.getIdentifier(), "__distinct_key", "string", this.parent.fieldDef.structRelationship.type === "nested", false);
5299
5414
  }
@@ -5531,7 +5646,7 @@ ${(0, utils_1.indent)(sql)})
5531
5646
  }
5532
5647
  return [];
5533
5648
  }
5534
- addStructToJoin(qs, query, mayNeedUniqueKey, joinStack) {
5649
+ addStructToJoin(qs, query, uniqueKeyPossibleUse, joinStack) {
5535
5650
  var _a;
5536
5651
  const name = qs.getIdentifier();
5537
5652
  if (joinStack.indexOf(name) !== -1) {
@@ -5539,13 +5654,13 @@ ${(0, utils_1.indent)(sql)})
5539
5654
  }
5540
5655
  let join3;
5541
5656
  if (join3 = this.root().joins.get(name)) {
5542
- join3.mayNeedUniqueKey || (join3.mayNeedUniqueKey = mayNeedUniqueKey);
5657
+ join3.uniqueKeyPossibleUses.add_use(uniqueKeyPossibleUse);
5543
5658
  return;
5544
5659
  }
5545
5660
  let parent;
5546
5661
  const parentStruct = (_a = qs.parent) === null || _a === void 0 ? void 0 : _a.getJoinableParent();
5547
5662
  if (parentStruct) {
5548
- this.addStructToJoin(parentStruct, query, false, joinStack);
5663
+ this.addStructToJoin(parentStruct, query, void 0, joinStack);
5549
5664
  parent = this.root().joins.get(parentStruct.getIdentifier());
5550
5665
  }
5551
5666
  const sr = qs.fieldDef.structRelationship;
@@ -5560,11 +5675,11 @@ ${(0, utils_1.indent)(sql)})
5560
5675
  join3 = new JoinInstance(qs, name, parent);
5561
5676
  this.root().joins.set(name, join3);
5562
5677
  }
5563
- join3.mayNeedUniqueKey || (join3.mayNeedUniqueKey = mayNeedUniqueKey);
5678
+ join3.uniqueKeyPossibleUses.add_use(uniqueKeyPossibleUse);
5564
5679
  }
5565
5680
  findJoins(query) {
5566
5681
  for (const dim of this.fields()) {
5567
- this.addStructToJoin(dim.f.getJoinableParent(), query, dim.f.mayNeedUniqueKey(), []);
5682
+ this.addStructToJoin(dim.f.getJoinableParent(), query, dim.f.uniqueKeyPossibleUse(), []);
5568
5683
  }
5569
5684
  for (const s8 of this.structs()) {
5570
5685
  s8.findJoins(query);
@@ -5660,7 +5775,11 @@ ${(0, utils_1.indent)(sql)})
5660
5775
  join3.leafiest = name === leafiest;
5661
5776
  }
5662
5777
  for (const [_name, join3] of this.joins) {
5663
- if (!join3.leafiest && join3.mayNeedUniqueKey) {
5778
+ if (join3.leafiest) {
5779
+ if (join3.parent !== null && join3.uniqueKeyPossibleUses.has("count") && !join3.queryStruct.primaryKey()) {
5780
+ join3.makeUniqueKey = true;
5781
+ }
5782
+ } else if (!join3.leafiest && join3.uniqueKeyPossibleUses.hasAsymetricFunctions()) {
5664
5783
  let j2 = join3;
5665
5784
  while (j2) {
5666
5785
  if (!j2.queryStruct.primaryKey()) {
@@ -5681,7 +5800,7 @@ ${(0, utils_1.indent)(sql)})
5681
5800
  this.queryStruct = queryStruct;
5682
5801
  this.alias = alias;
5683
5802
  this.parent = parent;
5684
- this.mayNeedUniqueKey = false;
5803
+ this.uniqueKeyPossibleUses = new UniqueKeyUse();
5685
5804
  this.makeUniqueKey = false;
5686
5805
  this.leafiest = false;
5687
5806
  this.children = [];
@@ -5914,7 +6033,7 @@ ${(0, utils_1.indent)(sql)})
5914
6033
  }
5915
6034
  return ret;
5916
6035
  }
5917
- addDependantPath(resultStruct, context3, path3, mayNeedUniqueKey, joinStack) {
6036
+ addDependantPath(resultStruct, context3, path3, uniqueKeyPossibleUse, joinStack) {
5918
6037
  const node = context3.getFieldByName(path3);
5919
6038
  let struct;
5920
6039
  if (node instanceof QueryField) {
@@ -5924,7 +6043,7 @@ ${(0, utils_1.indent)(sql)})
5924
6043
  } else {
5925
6044
  throw new Error("Internal Error: Unknown object type");
5926
6045
  }
5927
- resultStruct.root().addStructToJoin(struct.getJoinableParent(), this, mayNeedUniqueKey, joinStack);
6046
+ resultStruct.root().addStructToJoin(struct.getJoinableParent(), this, uniqueKeyPossibleUse, joinStack);
5928
6047
  }
5929
6048
  addDependantExpr(resultStruct, context3, e12, joinStack) {
5930
6049
  for (const expr2 of e12) {
@@ -5952,7 +6071,7 @@ ${(0, utils_1.indent)(sql)})
5952
6071
  if ((0, malloy_types_1.hasExpression)(field3.fieldDef)) {
5953
6072
  this.addDependantExpr(resultStruct, field3.parent, field3.fieldDef.e, joinStack);
5954
6073
  } else {
5955
- resultStruct.root().addStructToJoin(field3.parent.getJoinableParent(), this, false, joinStack);
6074
+ resultStruct.root().addStructToJoin(field3.parent.getJoinableParent(), this, void 0, joinStack);
5956
6075
  }
5957
6076
  } else if ((0, malloy_types_1.isFilterFragment)(expr2)) {
5958
6077
  for (const filterCond of expr2.filterList) {
@@ -5997,15 +6116,15 @@ ${(0, utils_1.indent)(sql)})
5997
6116
  } else if ((0, malloy_types_1.isAggregateFragment)(expr2)) {
5998
6117
  if ((0, malloy_types_1.isAsymmetricFragment)(expr2)) {
5999
6118
  if (expr2.structPath) {
6000
- this.addDependantPath(resultStruct, context3, expr2.structPath, true, joinStack);
6119
+ this.addDependantPath(resultStruct, context3, expr2.structPath, expr2.function, joinStack);
6001
6120
  } else {
6002
- resultStruct.addStructToJoin(context3, this, true, joinStack);
6121
+ resultStruct.addStructToJoin(context3, this, expr2.function, joinStack);
6003
6122
  }
6004
6123
  }
6005
6124
  this.addDependantExpr(resultStruct, context3, expr2.e, joinStack);
6006
6125
  } else if ((0, malloy_types_1.isFunctionCallFragment)(expr2)) {
6007
6126
  if (expr2.structPath) {
6008
- this.addDependantPath(resultStruct, context3, expr2.structPath, true, joinStack);
6127
+ this.addDependantPath(resultStruct, context3, expr2.structPath, "generic_aggregate", joinStack);
6009
6128
  }
6010
6129
  for (const e13 of expr2.args) {
6011
6130
  this.addDependantExpr(resultStruct, context3, e13, joinStack);
@@ -6082,7 +6201,7 @@ ${(0, utils_1.indent)(sql)})
6082
6201
  prepare(_stageWriter) {
6083
6202
  if (!this.prepared) {
6084
6203
  this.expandFields(this.rootResult);
6085
- this.rootResult.addStructToJoin(this.parent, this, false, []);
6204
+ this.rootResult.addStructToJoin(this.parent, this, void 0, []);
6086
6205
  this.rootResult.findJoins(this);
6087
6206
  this.rootResult.calculateSymmetricAggregates();
6088
6207
  this.prepared = true;
@@ -55150,7 +55269,7 @@ QUERY: ${(0, util_1.inspect)(opDesc, { breakLength: 72, depth: Infinity })}`);
55150
55269
  this.log(`Cannot call function ${this.name}(${argExprs.map((e12) => e12.dataType).join(", ")}) with source`);
55151
55270
  return (0, ast_utils_1.errorFor)("cannot call with source");
55152
55271
  }
55153
- const funcCall = [
55272
+ let funcCall = [
55154
55273
  {
55155
55274
  type: "function_call",
55156
55275
  overload,
@@ -55159,6 +55278,36 @@ QUERY: ${(0, util_1.inspect)(opDesc, { breakLength: 72, depth: Infinity })}`);
55159
55278
  structPath
55160
55279
  }
55161
55280
  ];
55281
+ if ([
55282
+ "sql_number",
55283
+ "sql_string",
55284
+ "sql_date",
55285
+ "sql_timestamp",
55286
+ "sql_boolean"
55287
+ ].includes(func.name)) {
55288
+ if (!this.inExperiment("sql_functions", true)) {
55289
+ return (0, ast_utils_1.errorFor)(`Cannot use sql_function \`${func.name}\`; use \`sql_functions\` experiment to enable this behavior`);
55290
+ }
55291
+ const str = argExprs[0].value;
55292
+ if (str.length !== 1 || typeof str[0] === "string" || str[0].type !== "dialect" || str[0].function !== "stringLiteral") {
55293
+ this.log(`Invalid string literal for \`${func.name}\``);
55294
+ } else {
55295
+ const literal = str[0].literal;
55296
+ const parts = parseSQLInterpolation(literal);
55297
+ const unsupportedInterpolations = parts.filter((part) => part.type === "interpolation" && part.name.includes(".")).map((unsupportedPart) => unsupportedPart.type === "interpolation" ? `\${${unsupportedPart.name}}` : `\${${unsupportedPart.value}}`);
55298
+ if (unsupportedInterpolations.length > 0) {
55299
+ const unsupportedInterpolationMsg = unsupportedInterpolations.length === 1 ? `'.' paths are not yet supported in sql interpolations, found ${unsupportedInterpolations.at(0)}` : `'.' paths are not yet supported in sql interpolations, found [${unsupportedInterpolations.join(", ")}]`;
55300
+ this.log(unsupportedInterpolationMsg);
55301
+ return (0, ast_utils_1.errorFor)(`${unsupportedInterpolationMsg}. See LookML \${...} documentation at https://cloud.google.com/looker/docs/reference/param-field-sql#sql_for_dimensions`);
55302
+ }
55303
+ funcCall = [
55304
+ {
55305
+ type: "sql-string",
55306
+ e: parts.map((part) => part.type === "string" ? part.value : part.name === "TABLE" ? { type: "source-reference" } : { type: "field-reference", path: part.name })
55307
+ }
55308
+ ];
55309
+ }
55310
+ }
55162
55311
  if (type3.dataType === "any") {
55163
55312
  this.log(`Invalid return type ${type3.dataType} for function '${this.name}'`);
55164
55313
  return (0, ast_utils_1.errorFor)("invalid return type");
@@ -55251,6 +55400,32 @@ QUERY: ${(0, util_1.inspect)(opDesc, { breakLength: 72, depth: Infinity })}`);
55251
55400
  }
55252
55401
  }
55253
55402
  }
55403
+ function parseSQLInterpolation(template) {
55404
+ const parts = [];
55405
+ let remaining = template;
55406
+ while (remaining.length) {
55407
+ const nextInterp = remaining.indexOf("${");
55408
+ if (nextInterp === -1) {
55409
+ parts.push({ type: "string", value: remaining });
55410
+ break;
55411
+ } else {
55412
+ const interpEnd = remaining.slice(nextInterp).indexOf("}");
55413
+ if (interpEnd === -1) {
55414
+ parts.push({ type: "string", value: remaining });
55415
+ break;
55416
+ }
55417
+ if (nextInterp > 0) {
55418
+ parts.push({ type: "string", value: remaining.slice(0, nextInterp) });
55419
+ }
55420
+ parts.push({
55421
+ type: "interpolation",
55422
+ name: remaining.slice(nextInterp + 2, interpEnd + nextInterp)
55423
+ });
55424
+ remaining = remaining.slice(interpEnd + nextInterp + 1);
55425
+ }
55426
+ }
55427
+ return parts;
55428
+ }
55254
55429
  }
55255
55430
  });
55256
55431
 
@@ -135500,7 +135675,7 @@ ${errText}`, errors);
135500
135675
  const fieldMeta = metadata2.fields[fieldKey2];
135501
135676
  let width2 = 0;
135502
135677
  if (f4.isAtomicField()) {
135503
- const font2 = `12px Inter, sans-serif`;
135678
+ const font2 = "12px Inter, sans-serif";
135504
135679
  const titleWidth = getTextWidth(f4.name, font2);
135505
135680
  if (f4.isAtomicField() && f4.isString()) {
135506
135681
  width2 = Math.max(getTextWidth(fieldMeta.maxString, font2), titleWidth) + COLUMN_BUFFER;