@malloydata/malloy 0.0.436 → 0.0.437

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.
@@ -281,14 +281,18 @@ class PostgresDialect extends pg_impl_1.PostgresBase {
281
281
  // PostgreSQL requires CAST to NUMERIC before ROUND, which is different
282
282
  // than the generic implementation of sqlSumDistinct, but is OK in
283
283
  // PostgreSQL because NUMERIC has arbitrary precision.
284
+ // The sum stays NUMERIC so later stages and derived expressions see the
285
+ // exact value. A DOUBLE PRECISION cast would keep only ~16 digits. The
286
+ // ROUND(..., 9) leaves a scale of 9, which would show up in string
287
+ // conversions as trailing zeros; trim_scale removes it.
284
288
  const roundedValue = `ROUND(CAST(COALESCE(${value}, 0) AS NUMERIC), 9)`;
285
289
  const sumSQL = `SUM(DISTINCT ${roundedValue} + ${hashKey}) - SUM(DISTINCT ${hashKey})`;
286
- const ret = `CAST(${sumSQL} AS DOUBLE PRECISION)`;
290
+ const ret = `trim_scale(${sumSQL})`;
287
291
  if (funcName === 'SUM') {
288
292
  return ret;
289
293
  }
290
294
  else if (funcName === 'AVG') {
291
- return `(${ret})/NULLIF(COUNT(DISTINCT CASE WHEN ${value} IS NOT NULL THEN ${key} END), 0)`;
295
+ return `trim_scale((${sumSQL})/NULLIF(COUNT(DISTINCT CASE WHEN ${value} IS NOT NULL THEN ${key} END), 0))`;
292
296
  }
293
297
  throw new Error(`Unknown Symmetric Aggregate function ${funcName}`);
294
298
  }
@@ -67,7 +67,7 @@ class ExprProps extends expression_def_1.ExpressionDef {
67
67
  for (const where of wheres) {
68
68
  const testList = where.getFilterList(fs);
69
69
  if (testList.find(cond => (0, malloy_types_1.expressionIsCalculation)(cond.expressionType))) {
70
- where.logError('aggregate-filter-expression-not-scalar', 'Cannot filter an expresion with an aggregate or analytical computation');
70
+ where.logError('aggregate-filter-expression-not-scalar', 'Cannot filter an expression with an aggregate or analytical computation');
71
71
  return expr;
72
72
  }
73
73
  filterList.push(...testList);
@@ -53,7 +53,12 @@ class TimeLiteral extends expression_def_1.ExpressionDef {
53
53
  }
54
54
  }
55
55
  makeLiteral(fs, val, typ, units) {
56
- return dialect_1.Dialect.makeTimeLiteralNode(fs.dialectObj(), val, this.timeZone, units, typ);
56
+ let timeZone = this.timeZone;
57
+ if (timeZone !== undefined && !dialect_1.Dialect.isSafeTimezoneName(timeZone)) {
58
+ this.logError('invalid-timezone', { timezone: timeZone });
59
+ timeZone = undefined;
60
+ }
61
+ return dialect_1.Dialect.makeTimeLiteralNode(fs.dialectObj(), val, timeZone, units, typ);
57
62
  }
58
63
  makeValue(fs, val, dataType) {
59
64
  const value = this.makeLiteral(fs, val, dataType, this.units);
@@ -89,6 +89,7 @@ class Drill extends filters_1.Filter {
89
89
  let previousName = viewName;
90
90
  let fieldDef = undefined;
91
91
  let compareField = undefined;
92
+ let compareUsage = undefined;
92
93
  const requiredDimensions = [];
93
94
  const pathSoFar = [viewName.name];
94
95
  for (const name of path) {
@@ -189,6 +190,9 @@ class Drill extends filters_1.Filter {
189
190
  if (theFieldDef === undefined || (0, malloy_types_1.isAtomic)(theFieldDef)) {
190
191
  fieldDef = theFieldDef;
191
192
  compareField = { node: 'field', path: field.path };
193
+ // theFieldDef's refSummary is relative to the struct it lives in;
194
+ // use the full path, as `where:` does, so joins along it activate.
195
+ compareUsage = [{ path: field.path, at: reference.location }];
192
196
  }
193
197
  else {
194
198
  name.logError('drill-field-reference-not-field', 'Final element of drill path must be a field');
@@ -268,7 +272,9 @@ class Drill extends filters_1.Filter {
268
272
  ...fieldDef,
269
273
  evalSpace: 'output',
270
274
  expressionType: (_b = fieldDef.expressionType) !== null && _b !== void 0 ? _b : 'scalar',
271
- refSummary: fieldDef.refSummary,
275
+ refSummary: compareUsage
276
+ ? (0, malloy_types_1.mkRefSummary)({ fieldUsage: compareUsage })
277
+ : fieldDef.refSummary,
272
278
  });
273
279
  filter.has({ drillField });
274
280
  const fExpression = new expr_compare_1.ExprCompare(drillField, '=', value);