@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.
- package/dist/dialect/postgres/postgres.js +6 -2
- package/dist/lang/ast/expressions/expr-props.js +1 -1
- package/dist/lang/ast/expressions/time-literal.js +6 -1
- package/dist/lang/ast/query-properties/drill.js +7 -1
- package/dist/lang/lib/Malloy/MalloyLexer.js +976 -978
- package/dist/model/query_query.js +11 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
|
@@ -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 = `
|
|
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 `(${
|
|
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
|
|
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
|
-
|
|
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:
|
|
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);
|