@malloydata/malloy 0.0.395 → 0.0.396
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/api/foundation/compile.d.ts +7 -6
- package/dist/api/foundation/compile.js +22 -6
- package/dist/api/foundation/runtime.d.ts +85 -5
- package/dist/api/foundation/runtime.js +183 -13
- package/dist/api/foundation/types.d.ts +2 -0
- package/dist/lang/ast/expressions/expr-func.js +30 -11
- package/dist/lang/ast/expressions/expr-given.js +1 -0
- package/dist/lang/ast/field-space/reference-field.js +1 -1
- package/dist/lang/ast/source-elements/sql-source.js +4 -0
- package/dist/lang/ast/source-elements/table-source.js +4 -0
- package/dist/lang/ast/statements/define-given.d.ts +1 -0
- package/dist/lang/ast/statements/define-given.js +7 -0
- package/dist/lang/ast/statements/import-statement.js +4 -0
- package/dist/lang/ast/types/annotation-elements.d.ts +1 -0
- package/dist/lang/ast/types/annotation-elements.js +10 -3
- package/dist/lang/ast/types/malloy-element.d.ts +1 -0
- package/dist/lang/ast/types/malloy-element.js +4 -0
- package/dist/lang/malloy-to-ast.d.ts +2 -1
- package/dist/lang/malloy-to-ast.js +11 -1
- package/dist/lang/parse-log.d.ts +1 -0
- package/dist/lang/parse-log.js +4 -0
- package/dist/lang/parse-malloy.d.ts +4 -1
- package/dist/lang/parse-malloy.js +26 -4
- package/dist/lang/test/test-translator.d.ts +19 -5
- package/dist/lang/test/test-translator.js +15 -12
- package/dist/lang/zone.d.ts +2 -0
- package/dist/lang/zone.js +10 -0
- package/dist/model/constant_expression_compiler.js +14 -5
- package/dist/model/expression_compiler.js +19 -17
- package/dist/model/field_instance.js +7 -3
- package/dist/model/given_binding.js +26 -21
- package/dist/model/index.d.ts +1 -0
- package/dist/model/index.js +3 -1
- package/dist/model/malloy_compile_error.d.ts +13 -0
- package/dist/model/malloy_compile_error.js +23 -0
- package/dist/model/malloy_types.d.ts +2 -0
- package/dist/model/query_model_impl.js +2 -1
- package/dist/model/query_node.d.ts +5 -5
- package/dist/model/query_node.js +21 -16
- package/dist/model/query_query.js +23 -11
- package/dist/model/sql_compiled.js +6 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
|
@@ -10,6 +10,7 @@ const luxon_1 = require("luxon");
|
|
|
10
10
|
const closest_match_1 = require("../util/closest_match");
|
|
11
11
|
const inline_expr_1 = require("./inline_expr");
|
|
12
12
|
const malloy_types_1 = require("./malloy_types");
|
|
13
|
+
const malloy_compile_error_1 = require("./malloy_compile_error");
|
|
13
14
|
function resolveSuppliedGivens(supplied, modelDef) {
|
|
14
15
|
var _a;
|
|
15
16
|
const out = new Map();
|
|
@@ -20,9 +21,9 @@ function resolveSuppliedGivens(supplied, modelDef) {
|
|
|
20
21
|
// prototype pollution from e.g. an Object.create(...)-derived input.
|
|
21
22
|
for (const [name, value] of Object.entries(supplied)) {
|
|
22
23
|
if (value === undefined) {
|
|
23
|
-
throw new
|
|
24
|
+
throw new malloy_compile_error_1.MalloyCompileError(`givens.${name}: explicit undefined is not a valid value. ` +
|
|
24
25
|
'Omit the key to defer to declaration default or a lower supply ' +
|
|
25
|
-
'layer; use null for an explicit null value.');
|
|
26
|
+
'layer; use null for an explicit null value.', 'runtime-given-undefined', undefined);
|
|
26
27
|
}
|
|
27
28
|
const entry = modelDef.contents[name];
|
|
28
29
|
if (!entry || entry.type !== 'given') {
|
|
@@ -33,7 +34,8 @@ function resolveSuppliedGivens(supplied, modelDef) {
|
|
|
33
34
|
}
|
|
34
35
|
const suggestion = (0, closest_match_1.closestMatch)(name, surfaceNames);
|
|
35
36
|
const hint = suggestion ? ` (did you mean '${suggestion}'?)` : '';
|
|
36
|
-
throw new
|
|
37
|
+
throw new malloy_compile_error_1.MalloyCompileError(`givens: unknown given '${name}'${hint}. ` +
|
|
38
|
+
`Model surfaces [${surfaceNames.join(', ')}]`, 'runtime-given-unknown', undefined);
|
|
37
39
|
}
|
|
38
40
|
const decl = givens[entry.id];
|
|
39
41
|
if (!decl) {
|
|
@@ -83,10 +85,13 @@ function valueToExpr(path, type, value) {
|
|
|
83
85
|
if (value === null) {
|
|
84
86
|
return { node: 'null' };
|
|
85
87
|
}
|
|
88
|
+
function bad(msg, code = 'runtime-given-bad-value') {
|
|
89
|
+
throw new malloy_compile_error_1.MalloyCompileError(`givens.${path}: ${msg}`, code, undefined);
|
|
90
|
+
}
|
|
86
91
|
switch (type.type) {
|
|
87
92
|
case 'string': {
|
|
88
93
|
if (typeof value !== 'string') {
|
|
89
|
-
|
|
94
|
+
bad(`expected string, got ${describeJs(value)}`);
|
|
90
95
|
}
|
|
91
96
|
return { node: 'stringLiteral', literal: value };
|
|
92
97
|
}
|
|
@@ -94,7 +99,7 @@ function valueToExpr(path, type, value) {
|
|
|
94
99
|
let lit;
|
|
95
100
|
if (typeof value === 'number') {
|
|
96
101
|
if (!Number.isFinite(value)) {
|
|
97
|
-
|
|
102
|
+
bad(`number must be finite, got ${value}`);
|
|
98
103
|
}
|
|
99
104
|
lit = String(value);
|
|
100
105
|
}
|
|
@@ -103,27 +108,27 @@ function valueToExpr(path, type, value) {
|
|
|
103
108
|
}
|
|
104
109
|
else if (typeof value === 'string') {
|
|
105
110
|
if (!/^-?(\d+(\.\d+)?|\.\d+)([eE][+-]?\d+)?$/.test(value)) {
|
|
106
|
-
|
|
111
|
+
bad(`number-as-string must be numeric, got '${value}'`);
|
|
107
112
|
}
|
|
108
113
|
lit = value;
|
|
109
114
|
}
|
|
110
115
|
else {
|
|
111
|
-
|
|
116
|
+
bad(`expected number | bigint | string, got ${describeJs(value)}`);
|
|
112
117
|
}
|
|
113
118
|
return { node: 'numberLiteral', literal: lit };
|
|
114
119
|
}
|
|
115
120
|
case 'boolean': {
|
|
116
121
|
if (typeof value !== 'boolean') {
|
|
117
|
-
|
|
122
|
+
bad(`expected boolean, got ${describeJs(value)}`);
|
|
118
123
|
}
|
|
119
124
|
return { node: value ? 'true' : 'false' };
|
|
120
125
|
}
|
|
121
126
|
case 'date': {
|
|
122
127
|
if (typeof value !== 'string') {
|
|
123
|
-
|
|
128
|
+
bad(`expected ISO date string 'YYYY-MM-DD', got ${describeJs(value)}`);
|
|
124
129
|
}
|
|
125
130
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
126
|
-
|
|
131
|
+
bad(`date must match 'YYYY-MM-DD', got '${value}'`);
|
|
127
132
|
}
|
|
128
133
|
return { node: 'dateLiteral', literal: value, typeDef: { type: 'date' } };
|
|
129
134
|
}
|
|
@@ -133,17 +138,17 @@ function valueToExpr(path, type, value) {
|
|
|
133
138
|
// strings (those want 'timestamptz'). Parse the rest with Luxon and
|
|
134
139
|
// emit canonical "YYYY-MM-DD HH:MM:SS.sss" for the dialect.
|
|
135
140
|
if (typeof value !== 'string') {
|
|
136
|
-
|
|
141
|
+
bad(`expected ISO timestamp string (no offset), got ${describeJs(value)}`);
|
|
137
142
|
}
|
|
138
143
|
if (/Z$|[+-]\d{2}:?\d{2}$/.test(value)) {
|
|
139
|
-
|
|
144
|
+
bad(`'timestamp' is naive — use 'timestamptz' for offset/zoned values, got '${value}'`);
|
|
140
145
|
}
|
|
141
146
|
// ISO uses T-separator; SQL form uses space. Accept both.
|
|
142
147
|
let dt = luxon_1.DateTime.fromISO(value, { zone: 'utc' });
|
|
143
148
|
if (!dt.isValid)
|
|
144
149
|
dt = luxon_1.DateTime.fromSQL(value, { zone: 'utc' });
|
|
145
150
|
if (!dt.isValid) {
|
|
146
|
-
|
|
151
|
+
bad(`invalid timestamp value '${value}': ${(_a = dt.invalidReason) !== null && _a !== void 0 ? _a : 'unknown'}`);
|
|
147
152
|
}
|
|
148
153
|
return {
|
|
149
154
|
node: 'timestampLiteral',
|
|
@@ -162,10 +167,10 @@ function valueToExpr(path, type, value) {
|
|
|
162
167
|
dt = dt.toUTC();
|
|
163
168
|
}
|
|
164
169
|
else {
|
|
165
|
-
|
|
170
|
+
bad(`expected JS Date or ISO timestamptz string, got ${describeJs(value)}`);
|
|
166
171
|
}
|
|
167
172
|
if (!dt.isValid) {
|
|
168
|
-
|
|
173
|
+
bad(`invalid timestamptz value '${value}': ${(_b = dt.invalidReason) !== null && _b !== void 0 ? _b : 'unknown'}`);
|
|
169
174
|
}
|
|
170
175
|
return {
|
|
171
176
|
node: 'timestamptzLiteral',
|
|
@@ -176,13 +181,13 @@ function valueToExpr(path, type, value) {
|
|
|
176
181
|
}
|
|
177
182
|
case 'filter expression': {
|
|
178
183
|
if (typeof value !== 'string') {
|
|
179
|
-
|
|
184
|
+
bad(`filter<T> givens require a JS string of Malloy filter source, got ${describeJs(value)}`);
|
|
180
185
|
}
|
|
181
186
|
return { node: 'filterLiteral', filterSrc: value };
|
|
182
187
|
}
|
|
183
188
|
case 'array': {
|
|
184
189
|
if (!Array.isArray(value)) {
|
|
185
|
-
|
|
190
|
+
bad(`expected array, got ${describeJs(value)}`);
|
|
186
191
|
}
|
|
187
192
|
// RepeatedRecord (array of records) carries `record_element` as its
|
|
188
193
|
// element type and the record's schema in `fields`. Each element is
|
|
@@ -198,19 +203,19 @@ function valueToExpr(path, type, value) {
|
|
|
198
203
|
if (typeof value !== 'object' ||
|
|
199
204
|
Array.isArray(value) ||
|
|
200
205
|
value instanceof Date) {
|
|
201
|
-
|
|
206
|
+
bad(`expected object, got ${describeJs(value)}`);
|
|
202
207
|
}
|
|
203
208
|
const obj = value;
|
|
204
209
|
const declared = new Set(type.fields.map(f => f.name));
|
|
205
210
|
for (const k of Object.keys(obj)) {
|
|
206
211
|
if (!declared.has(k)) {
|
|
207
|
-
throw new
|
|
212
|
+
throw new malloy_compile_error_1.MalloyCompileError(`givens.${path}.${k}: unexpected key (not in record type [${[...declared].join(', ')}])`, 'runtime-given-record-extra-key', undefined);
|
|
208
213
|
}
|
|
209
214
|
}
|
|
210
215
|
const kids = (0, malloy_types_1.mkSafeRecord)();
|
|
211
216
|
for (const field of type.fields) {
|
|
212
217
|
if (!(field.name in obj)) {
|
|
213
|
-
throw new
|
|
218
|
+
throw new malloy_compile_error_1.MalloyCompileError(`givens.${path}.${field.name}: missing required key`, 'runtime-given-record-missing-key', undefined);
|
|
214
219
|
}
|
|
215
220
|
kids[field.name] = valueToExpr(`${path}.${field.name}`, malloy_types_1.TD.atomicDef(field), obj[field.name]);
|
|
216
221
|
}
|
|
@@ -219,7 +224,7 @@ function valueToExpr(path, type, value) {
|
|
|
219
224
|
case 'json':
|
|
220
225
|
case 'sql native':
|
|
221
226
|
case 'error':
|
|
222
|
-
throw new
|
|
227
|
+
throw new malloy_compile_error_1.MalloyCompileError(`givens.${path}: type '${type.type}' is not bindable as a given value.`, 'runtime-given-type-not-bindable', undefined);
|
|
223
228
|
default: {
|
|
224
229
|
// Exhaustiveness: future GivenTypeDef additions will trip this.
|
|
225
230
|
const _x = type;
|
package/dist/model/index.d.ts
CHANGED
|
@@ -7,4 +7,5 @@ export { getResultStructDefForQuery, getResultStructDefForView, } from './query_
|
|
|
7
7
|
export { indent, composeSQLExpr, makeDigest, mkModelDef, pathToKey, typeDefToString, } from './utils';
|
|
8
8
|
export { constantExprToSQL } from './constant_expression_compiler';
|
|
9
9
|
export { getCompiledSQL } from './sql_compiled';
|
|
10
|
+
export { MalloyCompileError } from './malloy_compile_error';
|
|
10
11
|
export { mkSourceID, mkBuildID, mkQuerySourceDef, mkSQLSourceDef, mkTableSourceDef, resolveSourceID, registerSource, hasSourceRegistryEntry, } from './source_def_utils';
|
package/dist/model/index.js
CHANGED
|
@@ -36,7 +36,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
36
36
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.hasSourceRegistryEntry = exports.registerSource = exports.resolveSourceID = exports.mkTableSourceDef = exports.mkSQLSourceDef = exports.mkQuerySourceDef = exports.mkBuildID = exports.mkSourceID = exports.getCompiledSQL = exports.constantExprToSQL = exports.typeDefToString = exports.pathToKey = exports.mkModelDef = exports.makeDigest = exports.composeSQLExpr = exports.indent = exports.getResultStructDefForView = exports.getResultStructDefForQuery = exports.QueryModel = exports.QueryQuery = exports.QueryStruct = exports.QueryField = void 0;
|
|
39
|
+
exports.hasSourceRegistryEntry = exports.registerSource = exports.resolveSourceID = exports.mkTableSourceDef = exports.mkSQLSourceDef = exports.mkQuerySourceDef = exports.mkBuildID = exports.mkSourceID = exports.MalloyCompileError = exports.getCompiledSQL = exports.constantExprToSQL = exports.typeDefToString = exports.pathToKey = exports.mkModelDef = exports.makeDigest = exports.composeSQLExpr = exports.indent = exports.getResultStructDefForView = exports.getResultStructDefForQuery = exports.QueryModel = exports.QueryQuery = exports.QueryStruct = exports.QueryField = void 0;
|
|
40
40
|
__exportStar(require("./malloy_types"), exports);
|
|
41
41
|
const query_node_1 = require("./query_node");
|
|
42
42
|
Object.defineProperty(exports, "QueryField", { enumerable: true, get: function () { return query_node_1.QueryField; } });
|
|
@@ -66,6 +66,8 @@ var constant_expression_compiler_1 = require("./constant_expression_compiler");
|
|
|
66
66
|
Object.defineProperty(exports, "constantExprToSQL", { enumerable: true, get: function () { return constant_expression_compiler_1.constantExprToSQL; } });
|
|
67
67
|
var sql_compiled_1 = require("./sql_compiled");
|
|
68
68
|
Object.defineProperty(exports, "getCompiledSQL", { enumerable: true, get: function () { return sql_compiled_1.getCompiledSQL; } });
|
|
69
|
+
var malloy_compile_error_1 = require("./malloy_compile_error");
|
|
70
|
+
Object.defineProperty(exports, "MalloyCompileError", { enumerable: true, get: function () { return malloy_compile_error_1.MalloyCompileError; } });
|
|
69
71
|
var source_def_utils_1 = require("./source_def_utils");
|
|
70
72
|
Object.defineProperty(exports, "mkSourceID", { enumerable: true, get: function () { return source_def_utils_1.mkSourceID; } });
|
|
71
73
|
Object.defineProperty(exports, "mkBuildID", { enumerable: true, get: function () { return source_def_utils_1.mkBuildID; } });
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DocumentLocation } from './malloy_types';
|
|
2
|
+
/**
|
|
3
|
+
* Thrown by the SQL compiler (`src/model/`) for user-actionable errors the
|
|
4
|
+
* translator didn't catch. Caught at the materializer boundary and turned
|
|
5
|
+
* into a `LogMessage`. Singular `at` reflects the fail-fast contract — the
|
|
6
|
+
* first such error stops compilation. Invariant violations stay as bare
|
|
7
|
+
* `Error` and surface as `code: 'compiler-bug'` instead.
|
|
8
|
+
*/
|
|
9
|
+
export declare class MalloyCompileError extends Error {
|
|
10
|
+
readonly code: string;
|
|
11
|
+
readonly at: DocumentLocation | undefined;
|
|
12
|
+
constructor(message: string, code: string, at: DocumentLocation | undefined);
|
|
13
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright Contributors to the Malloy project
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.MalloyCompileError = void 0;
|
|
8
|
+
/**
|
|
9
|
+
* Thrown by the SQL compiler (`src/model/`) for user-actionable errors the
|
|
10
|
+
* translator didn't catch. Caught at the materializer boundary and turned
|
|
11
|
+
* into a `LogMessage`. Singular `at` reflects the fail-fast contract — the
|
|
12
|
+
* first such error stops compilation. Invariant violations stay as bare
|
|
13
|
+
* `Error` and surface as `code: 'compiler-bug'` instead.
|
|
14
|
+
*/
|
|
15
|
+
class MalloyCompileError extends Error {
|
|
16
|
+
constructor(message, code, at) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.code = code;
|
|
19
|
+
this.at = at;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.MalloyCompileError = MalloyCompileError;
|
|
23
|
+
//# sourceMappingURL=malloy_compile_error.js.map
|
|
@@ -127,11 +127,13 @@ export interface SourceReferenceNode extends ExprLeaf {
|
|
|
127
127
|
export interface ParameterNode extends ExprLeaf {
|
|
128
128
|
node: 'parameter';
|
|
129
129
|
path: string[];
|
|
130
|
+
at?: DocumentLocation;
|
|
130
131
|
}
|
|
131
132
|
export interface GivenRefNode extends ExprLeaf {
|
|
132
133
|
node: 'given';
|
|
133
134
|
id: GivenID;
|
|
134
135
|
refName: string;
|
|
136
|
+
at?: DocumentLocation;
|
|
135
137
|
}
|
|
136
138
|
export interface NowNode extends ExprLeaf {
|
|
137
139
|
node: 'now';
|
|
@@ -14,6 +14,7 @@ const stage_writer_1 = require("./stage_writer");
|
|
|
14
14
|
const dialect_1 = require("../dialect");
|
|
15
15
|
const query_node_1 = require("./query_node");
|
|
16
16
|
const row_data_utils_1 = require("../api/row_data_utils");
|
|
17
|
+
const malloy_compile_error_1 = require("./malloy_compile_error");
|
|
17
18
|
function makeQueryModel(modelDef) {
|
|
18
19
|
return new QueryModelImpl(modelDef);
|
|
19
20
|
}
|
|
@@ -66,7 +67,7 @@ class QueryModelImpl {
|
|
|
66
67
|
if (s) {
|
|
67
68
|
return s;
|
|
68
69
|
}
|
|
69
|
-
throw new
|
|
70
|
+
throw new malloy_compile_error_1.MalloyCompileError(`Source '${name}' is not defined in this model.`, 'compiler-undefined-source', undefined);
|
|
70
71
|
}
|
|
71
72
|
getStructFromRef(structRef, sourceArguments, prepareResultOptions) {
|
|
72
73
|
prepareResultOptions !== null && prepareResultOptions !== void 0 ? prepareResultOptions : (prepareResultOptions = {});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FieldDef, BooleanFieldDef, DateFieldDef, StringFieldDef, JSONFieldDef, NumberFieldDef, ATimestampFieldDef, NativeUnsupportedFieldDef, JoinFieldDef, Argument, Given, GivenID, PrepareResultOptions, AtomicFieldDef, BasicAtomicDef, FilterCondition, RefToField, StructDef, TurtleDef, TurtleDefPlusFilters, SourceDef, Query } from './malloy_types';
|
|
1
|
+
import type { FieldDef, BooleanFieldDef, DateFieldDef, DocumentLocation, StringFieldDef, JSONFieldDef, NumberFieldDef, ATimestampFieldDef, NativeUnsupportedFieldDef, JoinFieldDef, Argument, Given, GivenID, PrepareResultOptions, AtomicFieldDef, BasicAtomicDef, FilterCondition, RefToField, StructDef, TurtleDef, TurtleDefPlusFilters, SourceDef, Query } from './malloy_types';
|
|
2
2
|
import type { EventStream } from '../runtime_types';
|
|
3
3
|
import type { Tag } from '@malloydata/malloy-tag';
|
|
4
4
|
import type { Dialect } from '../dialect';
|
|
@@ -106,7 +106,7 @@ export declare class QueryStruct {
|
|
|
106
106
|
getFullOutputName(): string;
|
|
107
107
|
unnestWithNumbers(): boolean;
|
|
108
108
|
getJoinableParent(): QueryStruct;
|
|
109
|
-
addFieldToNameMap(as: string, n: QueryField): void;
|
|
109
|
+
addFieldToNameMap(as: string, n: QueryField, at?: DocumentLocation): void;
|
|
110
110
|
/** the the primary key or throw an error. */
|
|
111
111
|
getPrimaryKeyField(fieldDef: FieldDef): QueryBasicField;
|
|
112
112
|
/**
|
|
@@ -126,14 +126,14 @@ export declare class QueryStruct {
|
|
|
126
126
|
primaryKey(): QueryBasicField | undefined;
|
|
127
127
|
getChildByName(name: string): QueryField | undefined;
|
|
128
128
|
/** convert a path into a field reference */
|
|
129
|
-
getFieldByName(path: string[]): QueryField;
|
|
130
|
-
getQueryFieldByName(name: string[]): QueryField;
|
|
129
|
+
getFieldByName(path: string[], at?: DocumentLocation): QueryField;
|
|
130
|
+
getQueryFieldByName(name: string[], at?: DocumentLocation): QueryField;
|
|
131
131
|
getQueryFieldReference(f: RefToField): QueryField;
|
|
132
132
|
getDimensionOrMeasureByName(name: string[]): QueryField;
|
|
133
133
|
/** returns a query object for the given name */
|
|
134
134
|
getDimensionByName(name: string[]): QueryBasicField;
|
|
135
135
|
/** returns a query object for the given name */
|
|
136
|
-
getStructByName(name: string[]): QueryStruct;
|
|
136
|
+
getStructByName(name: string[], at?: DocumentLocation): QueryStruct;
|
|
137
137
|
getDistinctKey(): QueryBasicField;
|
|
138
138
|
applyStructFiltersToTurtleDef(turtleDef: TurtleDef | TurtleDefPlusFilters): TurtleDef;
|
|
139
139
|
}
|
package/dist/model/query_node.js
CHANGED
|
@@ -12,6 +12,7 @@ exports.isBasicAggregate = isBasicAggregate;
|
|
|
12
12
|
exports.isBasicCalculation = isBasicCalculation;
|
|
13
13
|
exports.isBasicScalar = isBasicScalar;
|
|
14
14
|
const uuid_1 = require("uuid");
|
|
15
|
+
const malloy_compile_error_1 = require("./malloy_compile_error");
|
|
15
16
|
const malloy_types_1 = require("./malloy_types");
|
|
16
17
|
const annotation_1 = require("../annotation");
|
|
17
18
|
const dialect_1 = require("../dialect");
|
|
@@ -245,7 +246,8 @@ class QueryStruct {
|
|
|
245
246
|
? this.parent.resolveParentParameterReferences(resolved1)
|
|
246
247
|
: resolved1;
|
|
247
248
|
if (resolved2.value === null) {
|
|
248
|
-
throw new
|
|
249
|
+
throw new malloy_compile_error_1.MalloyCompileError(`Parameter '${frag.path[0]}' resolves to a null value chain; ` +
|
|
250
|
+
'this parameter was not supplied.', 'compiler-parameter-no-value', undefined);
|
|
249
251
|
}
|
|
250
252
|
else {
|
|
251
253
|
return resolved2.value;
|
|
@@ -284,10 +286,10 @@ class QueryStruct {
|
|
|
284
286
|
if (!QueryStruct.turtleFieldMaker) {
|
|
285
287
|
throw new Error('INTERNAL ERROR: QueryQuery must initialize QueryStruct nested factory method');
|
|
286
288
|
}
|
|
287
|
-
this.addFieldToNameMap(as, QueryStruct.turtleFieldMaker(field, this));
|
|
289
|
+
this.addFieldToNameMap(as, QueryStruct.turtleFieldMaker(field, this), field.location);
|
|
288
290
|
}
|
|
289
291
|
else if ((0, malloy_types_1.isAtomic)(field) || (0, malloy_types_1.isJoinedSource)(field)) {
|
|
290
|
-
this.addFieldToNameMap(as, this.makeQueryField(field));
|
|
292
|
+
this.addFieldToNameMap(as, this.makeQueryField(field), field.location);
|
|
291
293
|
}
|
|
292
294
|
else {
|
|
293
295
|
// According to the type system this should be impossible, but we have seen this happen
|
|
@@ -413,9 +415,9 @@ class QueryStruct {
|
|
|
413
415
|
}
|
|
414
416
|
return this;
|
|
415
417
|
}
|
|
416
|
-
addFieldToNameMap(as, n) {
|
|
418
|
+
addFieldToNameMap(as, n, at) {
|
|
417
419
|
if (this.nameMap.has(as)) {
|
|
418
|
-
throw new
|
|
420
|
+
throw new malloy_compile_error_1.MalloyCompileError(`Field name '${as}' is defined more than once in this scope.`, 'compiler-name-redefined', at);
|
|
419
421
|
}
|
|
420
422
|
this.nameMap.set(as, n);
|
|
421
423
|
}
|
|
@@ -426,7 +428,9 @@ class QueryStruct {
|
|
|
426
428
|
return pk;
|
|
427
429
|
}
|
|
428
430
|
else {
|
|
429
|
-
throw new
|
|
431
|
+
throw new malloy_compile_error_1.MalloyCompileError(`Source '${(0, malloy_types_1.getIdentifier)(this.structDef)}' has no primary key; ` +
|
|
432
|
+
`cannot compute a unique key for field '${(0, malloy_types_1.getIdentifier)(fieldDef)}'. ` +
|
|
433
|
+
'Add `primary_key: <field>` to the source definition.', 'compiler-missing-primary-key', fieldDef.location);
|
|
430
434
|
}
|
|
431
435
|
}
|
|
432
436
|
/**
|
|
@@ -528,7 +532,7 @@ class QueryStruct {
|
|
|
528
532
|
return this.nameMap.get(name);
|
|
529
533
|
}
|
|
530
534
|
/** convert a path into a field reference */
|
|
531
|
-
getFieldByName(path) {
|
|
535
|
+
getFieldByName(path, at) {
|
|
532
536
|
let found = undefined;
|
|
533
537
|
let lookIn = this;
|
|
534
538
|
let notFound = path[0];
|
|
@@ -542,22 +546,23 @@ class QueryStruct {
|
|
|
542
546
|
found instanceof QueryFieldStruct ? found.queryStruct : undefined;
|
|
543
547
|
}
|
|
544
548
|
if (found === undefined) {
|
|
545
|
-
const pathErr = path.length > 1 ? ` in ${path.join('.')}` : '';
|
|
546
|
-
throw new
|
|
549
|
+
const pathErr = path.length > 1 ? ` in path '${path.join('.')}'` : '';
|
|
550
|
+
throw new malloy_compile_error_1.MalloyCompileError(`Field '${notFound}' not found${pathErr}.`, 'compiler-field-not-found', at);
|
|
547
551
|
}
|
|
548
552
|
return found;
|
|
549
553
|
}
|
|
550
554
|
// structs referenced in queries are converted to fields.
|
|
551
|
-
getQueryFieldByName(name) {
|
|
552
|
-
const field = this.getFieldByName(name);
|
|
555
|
+
getQueryFieldByName(name, at) {
|
|
556
|
+
const field = this.getFieldByName(name, at);
|
|
553
557
|
if (field instanceof QueryFieldStruct) {
|
|
554
|
-
throw new
|
|
558
|
+
throw new malloy_compile_error_1.MalloyCompileError(`'${name.join('.')}' refers to a source or join, not a scalar field. ` +
|
|
559
|
+
'Use `source.field` to reference fields inside it.', 'compiler-cannot-reference-as-scalar', at);
|
|
555
560
|
}
|
|
556
561
|
return field;
|
|
557
562
|
}
|
|
558
563
|
getQueryFieldReference(f) {
|
|
559
564
|
const { path, annotation, drillExpression } = f;
|
|
560
|
-
const field = this.getFieldByName(path);
|
|
565
|
+
const field = this.getFieldByName(path, f.at);
|
|
561
566
|
if (annotation || drillExpression) {
|
|
562
567
|
if (field.parent === undefined) {
|
|
563
568
|
throw new Error('Inconcievable, field reference to orphaned query field');
|
|
@@ -591,15 +596,15 @@ class QueryStruct {
|
|
|
591
596
|
throw new Error(`${name} is not an atomic scalar field? Inconceivable!`);
|
|
592
597
|
}
|
|
593
598
|
/** returns a query object for the given name */
|
|
594
|
-
getStructByName(name) {
|
|
599
|
+
getStructByName(name, at) {
|
|
595
600
|
if (name.length === 0) {
|
|
596
601
|
return this;
|
|
597
602
|
}
|
|
598
|
-
const struct = this.getFieldByName(name);
|
|
603
|
+
const struct = this.getFieldByName(name, at);
|
|
599
604
|
if (struct instanceof QueryFieldStruct) {
|
|
600
605
|
return struct.queryStruct;
|
|
601
606
|
}
|
|
602
|
-
throw new
|
|
607
|
+
throw new malloy_compile_error_1.MalloyCompileError(`'${name.join('.')}' is not a source or join.`, 'compiler-struct-not-found', at);
|
|
603
608
|
}
|
|
604
609
|
getDistinctKey() {
|
|
605
610
|
if (this.structDef.type !== 'record') {
|
|
@@ -13,6 +13,7 @@ const stage_writer_1 = require("./stage_writer");
|
|
|
13
13
|
const field_instance_1 = require("./field_instance");
|
|
14
14
|
const sql_compiled_1 = require("./sql_compiled");
|
|
15
15
|
const source_def_utils_1 = require("./source_def_utils");
|
|
16
|
+
const malloy_compile_error_1 = require("./malloy_compile_error");
|
|
16
17
|
function pathToCol(path) {
|
|
17
18
|
return path.map(el => encodeURIComponent(el)).join('/');
|
|
18
19
|
}
|
|
@@ -142,7 +143,8 @@ class QueryQuery extends query_node_1.QueryField {
|
|
|
142
143
|
for (const pathSegment of ungrouping.path) {
|
|
143
144
|
const nextStruct = destResult.allFields.get(pathSegment);
|
|
144
145
|
if (!(nextStruct instanceof field_instance_1.FieldInstanceResult)) {
|
|
145
|
-
throw new
|
|
146
|
+
throw new malloy_compile_error_1.MalloyCompileError(`Ungrouping path '${ungrouping.path.join('.')}' references ` +
|
|
147
|
+
`'${pathSegment}', which is not a nested view at this level.`, 'compiler-ungrouped-invalid-path', this.fieldDef.location);
|
|
146
148
|
}
|
|
147
149
|
destResult = nextStruct;
|
|
148
150
|
}
|
|
@@ -192,7 +194,9 @@ class QueryQuery extends query_node_1.QueryField {
|
|
|
192
194
|
const drillExpression = this.getDrillExpression(f);
|
|
193
195
|
if (field instanceof QueryQuery) {
|
|
194
196
|
if (this.firstSegment.type === 'project') {
|
|
195
|
-
throw new
|
|
197
|
+
throw new malloy_compile_error_1.MalloyCompileError(`Cannot include nested view '${field.fieldDef.name}' in a ` +
|
|
198
|
+
"'select:' stage. Nested views require `group_by:` or " +
|
|
199
|
+
'`aggregate:` to be included in output.', 'compiler-nested-view-in-select', field.fieldDef.location);
|
|
196
200
|
}
|
|
197
201
|
const fir = new field_instance_1.FieldInstanceResult(field.fieldDef, resultStruct);
|
|
198
202
|
this.expandFields(fir);
|
|
@@ -212,7 +216,8 @@ class QueryQuery extends query_node_1.QueryField {
|
|
|
212
216
|
}
|
|
213
217
|
if ((0, query_node_1.isBasicAggregate)(field)) {
|
|
214
218
|
if (this.firstSegment.type === 'project') {
|
|
215
|
-
throw new
|
|
219
|
+
throw new malloy_compile_error_1.MalloyCompileError(`Cannot include aggregate field '${field.fieldDef.name}' in ` +
|
|
220
|
+
"a 'select:' stage. Use `aggregate:` instead to compute aggregates.", 'compiler-aggregate-in-select', field.fieldDef.location);
|
|
216
221
|
}
|
|
217
222
|
}
|
|
218
223
|
}
|
|
@@ -523,7 +528,9 @@ class QueryQuery extends query_node_1.QueryField {
|
|
|
523
528
|
const virtualMap = (_a = qs.prepareResultOptions) === null || _a === void 0 ? void 0 : _a.virtualMap;
|
|
524
529
|
const tablePath = (_b = virtualMap === null || virtualMap === void 0 ? void 0 : virtualMap.get(qs.structDef.connection)) === null || _b === void 0 ? void 0 : _b.get(qs.structDef.name);
|
|
525
530
|
if (!tablePath) {
|
|
526
|
-
throw new
|
|
531
|
+
throw new malloy_compile_error_1.MalloyCompileError(`No virtual-map entry for virtual source '${qs.structDef.name}' ` +
|
|
532
|
+
`on connection '${qs.structDef.connection}'. ` +
|
|
533
|
+
'Add a virtual-map entry via the `virtualMap` runtime option.', 'runtime-virtual-map-missing', qs.structDef.location);
|
|
527
534
|
}
|
|
528
535
|
// virtualMap entries are application-supplied — assumed already
|
|
529
536
|
// canonical SQL.
|
|
@@ -559,10 +566,12 @@ class QueryQuery extends query_node_1.QueryField {
|
|
|
559
566
|
return entry.tableName;
|
|
560
567
|
}
|
|
561
568
|
if (buildManifest.strict) {
|
|
562
|
-
const base = `Persist source '${qs.structDef.sourceID}' not found
|
|
563
|
-
|
|
569
|
+
const base = `Persist source '${qs.structDef.sourceID}' not found ` +
|
|
570
|
+
`in manifest (buildId: ${buildId}); strict manifest mode ` +
|
|
571
|
+
'forbids fallback to live compilation.';
|
|
572
|
+
throw new malloy_compile_error_1.MalloyCompileError(buildManifest.loadError
|
|
564
573
|
? `${base}\n ${buildManifest.loadError}`
|
|
565
|
-
: base);
|
|
574
|
+
: base, 'runtime-manifest-strict-miss', qs.structDef.location);
|
|
566
575
|
}
|
|
567
576
|
}
|
|
568
577
|
}
|
|
@@ -598,7 +607,8 @@ class QueryQuery extends query_node_1.QueryField {
|
|
|
598
607
|
if (typeof structRef === 'string') {
|
|
599
608
|
const struct = this.structRefToQueryStruct(structRef);
|
|
600
609
|
if (!struct) {
|
|
601
|
-
throw new
|
|
610
|
+
throw new malloy_compile_error_1.MalloyCompileError(`Query references source '${structRef}', ` +
|
|
611
|
+
'which is not defined in this model.', 'compiler-undefined-source', undefined);
|
|
602
612
|
}
|
|
603
613
|
sourceStruct = struct;
|
|
604
614
|
}
|
|
@@ -858,7 +868,7 @@ class QueryQuery extends query_node_1.QueryField {
|
|
|
858
868
|
}
|
|
859
869
|
}
|
|
860
870
|
else {
|
|
861
|
-
throw new
|
|
871
|
+
throw new malloy_compile_error_1.MalloyCompileError(`ORDER BY references unknown field '${f.field}'.`, 'compiler-orderby-field-not-found', queryDef.referencedAt);
|
|
862
872
|
}
|
|
863
873
|
}
|
|
864
874
|
else {
|
|
@@ -1210,7 +1220,9 @@ class QueryQuery extends query_node_1.QueryField {
|
|
|
1210
1220
|
this.generateStage0Fields(this.rootResult, f, stageWriter);
|
|
1211
1221
|
if (this.firstSegment.type === 'project' &&
|
|
1212
1222
|
!this.parent.modelCompilerFlags().has('unsafe_complex_select_query')) {
|
|
1213
|
-
throw new
|
|
1223
|
+
throw new malloy_compile_error_1.MalloyCompileError("Cannot use 'select:' in a stage that contains nested views. " +
|
|
1224
|
+
'Use `group_by:` or restructure the pipeline. ' +
|
|
1225
|
+
'Set `##! unsafe_complex_select_query` to bypass at your own risk.', 'compiler-project-with-turtles', this.fieldDef.location);
|
|
1214
1226
|
}
|
|
1215
1227
|
const groupBy = 'GROUP BY ' + f.dimensionIndexes.join(',') + '\n';
|
|
1216
1228
|
from += this.parent.dialect.sqlGroupSetTable(this.maxGroupSet) + '\n';
|
|
@@ -1611,7 +1623,7 @@ class QueryQueryIndexStage extends QueryQuery {
|
|
|
1611
1623
|
}
|
|
1612
1624
|
expandField(f) {
|
|
1613
1625
|
const as = f.path.join('.');
|
|
1614
|
-
const field = this.parent.getQueryFieldByName(f.path);
|
|
1626
|
+
const field = this.parent.getQueryFieldByName(f.path, f.at);
|
|
1615
1627
|
return { as, field };
|
|
1616
1628
|
}
|
|
1617
1629
|
expandFields(resultStruct) {
|
|
@@ -8,6 +8,7 @@ exports.getCompiledSQL = getCompiledSQL;
|
|
|
8
8
|
exports.getSourceSQL = getSourceSQL;
|
|
9
9
|
const malloy_types_1 = require("./malloy_types");
|
|
10
10
|
const source_def_utils_1 = require("./source_def_utils");
|
|
11
|
+
const malloy_compile_error_1 = require("./malloy_compile_error");
|
|
11
12
|
/**
|
|
12
13
|
* Compile a SQLSourceDef to its final SQL string.
|
|
13
14
|
*
|
|
@@ -66,10 +67,12 @@ function expandPersistableSource(source, opts, compileQuery) {
|
|
|
66
67
|
}
|
|
67
68
|
// Not in manifest
|
|
68
69
|
if (buildManifest.strict) {
|
|
69
|
-
const base = `Persist source '${source.sourceID}' not found in manifest
|
|
70
|
-
|
|
70
|
+
const base = `Persist source '${source.sourceID}' not found in manifest ` +
|
|
71
|
+
`(buildId: ${buildId}); strict manifest mode forbids fallback ` +
|
|
72
|
+
'to live compilation.';
|
|
73
|
+
throw new malloy_compile_error_1.MalloyCompileError(buildManifest.loadError
|
|
71
74
|
? `${base}\n ${buildManifest.loadError}`
|
|
72
|
-
: base);
|
|
75
|
+
: base, 'runtime-manifest-strict-miss', source.location);
|
|
73
76
|
}
|
|
74
77
|
}
|
|
75
78
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const MALLOY_VERSION = "0.0.
|
|
1
|
+
export declare const MALLOY_VERSION = "0.0.396";
|
package/dist/version.js
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MALLOY_VERSION = void 0;
|
|
4
4
|
// generated with 'generate-version-file' script; do not edit manually
|
|
5
|
-
exports.MALLOY_VERSION = '0.0.
|
|
5
|
+
exports.MALLOY_VERSION = '0.0.396';
|
|
6
6
|
//# sourceMappingURL=version.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloydata/malloy",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.396",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/index.js",
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
"generate-version-file": "VERSION=$(npm pkg get version --workspaces=false | tr -d \\\")\necho \"// generated with 'generate-version-file' script; do not edit manually\\nexport const MALLOY_VERSION = '$VERSION';\" > src/version.ts"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@malloydata/malloy-filter": "0.0.
|
|
55
|
-
"@malloydata/malloy-interfaces": "0.0.
|
|
56
|
-
"@malloydata/malloy-tag": "0.0.
|
|
54
|
+
"@malloydata/malloy-filter": "0.0.396",
|
|
55
|
+
"@malloydata/malloy-interfaces": "0.0.396",
|
|
56
|
+
"@malloydata/malloy-tag": "0.0.396",
|
|
57
57
|
"@noble/hashes": "^1.8.0",
|
|
58
58
|
"antlr4ts": "^0.5.0-alpha.4",
|
|
59
59
|
"assert": "^2.0.0",
|