@malloydata/malloy 0.0.299 → 0.0.301

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.
Files changed (62) hide show
  1. package/dist/api/asynchronous.d.ts +1 -1
  2. package/dist/api/core.js +14 -10
  3. package/dist/api/sessioned.js +5 -1
  4. package/dist/dialect/functions/util.js +8 -2
  5. package/dist/lang/ast/error-factory.js +17 -3
  6. package/dist/lang/ast/expressions/constant-expression.d.ts +1 -0
  7. package/dist/lang/ast/expressions/constant-expression.js +3 -0
  8. package/dist/lang/ast/expressions/expr-props.d.ts +12 -0
  9. package/dist/lang/ast/field-space/dynamic-space.js +1 -1
  10. package/dist/lang/ast/field-space/index-field-space.d.ts +2 -1
  11. package/dist/lang/ast/field-space/index-field-space.js +20 -2
  12. package/dist/lang/ast/field-space/join-space-field.d.ts +1 -1
  13. package/dist/lang/ast/field-space/join-space-field.js +2 -2
  14. package/dist/lang/ast/field-space/parameter-space.d.ts +1 -0
  15. package/dist/lang/ast/field-space/parameter-space.js +3 -0
  16. package/dist/lang/ast/field-space/passthrough-space.d.ts +1 -0
  17. package/dist/lang/ast/field-space/passthrough-space.js +3 -0
  18. package/dist/lang/ast/field-space/query-input-space.d.ts +1 -0
  19. package/dist/lang/ast/field-space/query-input-space.js +3 -0
  20. package/dist/lang/ast/field-space/query-spaces.d.ts +13 -1
  21. package/dist/lang/ast/field-space/query-spaces.js +128 -29
  22. package/dist/lang/ast/field-space/refine-from-space-field.d.ts +9 -0
  23. package/dist/lang/ast/field-space/refine-from-space-field.js +24 -0
  24. package/dist/lang/ast/field-space/static-space.d.ts +6 -3
  25. package/dist/lang/ast/field-space/static-space.js +13 -10
  26. package/dist/lang/ast/field-space/view-field.d.ts +2 -108
  27. package/dist/lang/ast/field-space/view-field.js +1 -40
  28. package/dist/lang/ast/query-builders/reduce-builder.js +1 -0
  29. package/dist/lang/ast/query-elements/query-raw.js +1 -1
  30. package/dist/lang/ast/query-elements/query-reference.js +1 -2
  31. package/dist/lang/ast/query-elements/query-refine.js +5 -5
  32. package/dist/lang/ast/query-items/field-declaration.js +7 -2
  33. package/dist/lang/ast/query-items/field-references.d.ts +4 -0
  34. package/dist/lang/ast/query-items/field-references.js +12 -1
  35. package/dist/lang/ast/query-properties/qop-desc.js +1 -7
  36. package/dist/lang/ast/source-elements/query-source.js +1 -0
  37. package/dist/lang/ast/source-elements/refined-source.js +2 -2
  38. package/dist/lang/ast/source-properties/join.js +1 -1
  39. package/dist/lang/ast/statements/define-source.js +25 -23
  40. package/dist/lang/ast/typedesc-utils.d.ts +0 -1
  41. package/dist/lang/ast/typedesc-utils.js +1 -2
  42. package/dist/lang/ast/types/field-space.d.ts +2 -0
  43. package/dist/lang/ast/types/malloy-element.js +2 -2
  44. package/dist/lang/ast/types/op-desc.d.ts +1 -1
  45. package/dist/lang/ast/types/space-field.d.ts +3 -1
  46. package/dist/lang/ast/types/space-field.js +22 -0
  47. package/dist/lang/ast/view-elements/qop-desc-view.js +8 -4
  48. package/dist/lang/ast/view-elements/reference-view.js +9 -7
  49. package/dist/lang/ast/view-elements/view-refine.js +1 -2
  50. package/dist/lang/parse-log.d.ts +1 -0
  51. package/dist/lang/test/test-translator.js +11 -0
  52. package/dist/malloy.js +8 -6
  53. package/dist/model/composite_source_utils.d.ts +3 -2
  54. package/dist/model/composite_source_utils.js +115 -5
  55. package/dist/model/malloy_query.js +19 -4
  56. package/dist/model/malloy_types.d.ts +22 -4
  57. package/dist/model/malloy_types.js +1 -1
  58. package/dist/version.d.ts +1 -1
  59. package/dist/version.js +1 -1
  60. package/package.json +4 -4
  61. package/dist/lang/ast/struct-utils.d.ts +0 -5
  62. package/dist/lang/ast/struct-utils.js +0 -69
@@ -10,4 +10,4 @@ export interface CompilerNeedFetch<T extends InfoConnection> {
10
10
  export declare function compileModel(request: Malloy.CompileModelRequest, fetchers: CompilerNeedFetch<InfoConnection>): Promise<Malloy.CompileModelResponse>;
11
11
  export declare function compileSource(request: Malloy.CompileSourceRequest, fetchers: CompilerNeedFetch<InfoConnection>): Promise<Malloy.CompileSourceResponse>;
12
12
  export declare function compileQuery(request: Malloy.CompileQueryRequest, fetchers: CompilerNeedFetch<InfoConnection>): Promise<Malloy.CompileQueryResponse>;
13
- export declare function runQuery(request: Malloy.CompileQueryRequest, fetchers: CompilerNeedFetch<Connection>): Promise<Malloy.CompileQueryResponse>;
13
+ export declare function runQuery(request: Malloy.RunQueryRequest, fetchers: CompilerNeedFetch<Connection>): Promise<Malloy.RunQueryResponse>;
package/dist/api/core.js CHANGED
@@ -258,14 +258,15 @@ function updateCompileModelState(state, needs) {
258
258
  const update = compilerNeedsToUpdate(needs);
259
259
  performUpdate(state, update);
260
260
  }
261
- function _newCompileModelState(modelURL, compilerNeeds, extendURL, excludeReferences = false) {
261
+ function _newCompileModelState(modelURL, compilerNeeds, parseUpdate, extendURL, excludeReferences = false) {
262
262
  var _a, _b, _c, _d;
263
- const translator = new lang_1.MalloyTranslator(modelURL, null, compilerNeedsToUpdate(compilerNeeds));
263
+ parseUpdate !== null && parseUpdate !== void 0 ? parseUpdate : (parseUpdate = compilerNeedsToUpdate(compilerNeeds));
264
+ const translator = new lang_1.MalloyTranslator(modelURL, null, parseUpdate);
264
265
  const hasSource = ((_b = (_a = compilerNeeds === null || compilerNeeds === void 0 ? void 0 : compilerNeeds.files) === null || _a === void 0 ? void 0 : _a.some(f => f.url === modelURL)) !== null && _b !== void 0 ? _b : false) ||
265
266
  ((_d = (_c = compilerNeeds === null || compilerNeeds === void 0 ? void 0 : compilerNeeds.translations) === null || _c === void 0 ? void 0 : _c.some(t => t.url === modelURL)) !== null && _d !== void 0 ? _d : false);
266
267
  if (extendURL) {
267
268
  return {
268
- extending: _newCompileModelState(extendURL, compilerNeeds, undefined, excludeReferences),
269
+ extending: _newCompileModelState(extendURL, compilerNeeds, parseUpdate, undefined, excludeReferences),
269
270
  translator,
270
271
  done: false,
271
272
  hasSource,
@@ -282,10 +283,10 @@ function _newCompileModelState(modelURL, compilerNeeds, extendURL, excludeRefere
282
283
  }
283
284
  }
284
285
  function newCompileModelState(request) {
285
- return _newCompileModelState(request.model_url, request.compiler_needs, request.extend_model_url, request.exclude_references);
286
+ return _newCompileModelState(request.model_url, request.compiler_needs, undefined, request.extend_model_url, request.exclude_references);
286
287
  }
287
288
  function newCompileSourceState(request) {
288
- return _newCompileModelState(request.model_url, request.compiler_needs, request.extend_model_url, request.exclude_references);
289
+ return _newCompileModelState(request.model_url, request.compiler_needs, undefined, request.extend_model_url, request.exclude_references);
289
290
  }
290
291
  // function hasNeeds(needs: Malloy.CompilerNeeds | undefined): boolean {
291
292
  // if (needs === undefined) return false;
@@ -427,10 +428,13 @@ function hasErrors(log) {
427
428
  return (_a = log === null || log === void 0 ? void 0 : log.some(m => m.severity === 'error')) !== null && _a !== void 0 ? _a : false;
428
429
  }
429
430
  function newCompileQueryState(request) {
430
- var _a, _b;
431
- const queryMalloy = Malloy.queryToMalloy(request.query);
431
+ var _a, _b, _c;
432
+ const queryMalloy = (_a = request.query_malloy) !== null && _a !== void 0 ? _a : (request.query ? Malloy.queryToMalloy(request.query) : undefined);
433
+ if (queryMalloy === undefined) {
434
+ throw new Error('Expected either query or query_malloy');
435
+ }
432
436
  const needs = {
433
- ...((_a = request.compiler_needs) !== null && _a !== void 0 ? _a : {}),
437
+ ...((_b = request.compiler_needs) !== null && _b !== void 0 ? _b : {}),
434
438
  };
435
439
  const queryURL = 'internal://query.malloy';
436
440
  needs.files = [
@@ -438,10 +442,10 @@ function newCompileQueryState(request) {
438
442
  url: queryURL,
439
443
  contents: queryMalloy,
440
444
  },
441
- ...((_b = needs.files) !== null && _b !== void 0 ? _b : []),
445
+ ...((_c = needs.files) !== null && _c !== void 0 ? _c : []),
442
446
  ];
443
447
  return {
444
- ..._newCompileModelState(queryURL, needs, request.model_url, request.exclude_references),
448
+ ..._newCompileModelState(queryURL, needs, undefined, request.model_url, request.exclude_references),
445
449
  defaultRowLimit: request.default_row_limit,
446
450
  };
447
451
  }
@@ -242,7 +242,11 @@ class SessionManager {
242
242
  }
243
243
  }
244
244
  compileQuery(request, options) {
245
- const queryString = Malloy.queryToMalloy(request.query);
245
+ var _a;
246
+ const queryString = (_a = request.query_malloy) !== null && _a !== void 0 ? _a : (request.query ? Malloy.queryToMalloy(request.query) : undefined);
247
+ if (queryString === undefined) {
248
+ throw new Error('Expected query_malloy or query');
249
+ }
246
250
  const sessionInfo = {
247
251
  type: 'compile_query',
248
252
  modelURL: request.model_url,
@@ -233,9 +233,12 @@ function expandReturnTypeBlueprint(blueprint) {
233
233
  else if ('sql_native' in blueprint) {
234
234
  return anyExprType({ type: 'sql native', rawType: blueprint.sql_native });
235
235
  }
236
- else {
236
+ else if ('calculation' in blueprint) {
237
237
  return minAnalytic(expandTypeDescElementBlueprint(blueprint.calculation, false));
238
238
  }
239
+ else {
240
+ throw new Error('Invalid function blueprint');
241
+ }
239
242
  }
240
243
  function isTypeDescBlueprint(blueprint) {
241
244
  return (typeof blueprint === 'string' ||
@@ -291,9 +294,12 @@ function expandParamTypeBlueprint(blueprint) {
291
294
  else if ('sql_native' in blueprint) {
292
295
  return anyExprType({ type: 'sql native', rawType: blueprint.sql_native });
293
296
  }
294
- else {
297
+ else if ('calculation' in blueprint) {
295
298
  return maxAnalytic(expandTypeDescElementBlueprint(blueprint.calculation));
296
299
  }
300
+ else {
301
+ throw new Error('Invalid function blueprint');
302
+ }
297
303
  }
298
304
  function expandParamTypeBlueprints(blueprints) {
299
305
  return blueprints.map(blueprint => expandParamTypeBlueprint(blueprint));
@@ -61,13 +61,27 @@ class ErrorFactory {
61
61
  };
62
62
  }
63
63
  static get reduceSegment() {
64
- return { type: 'reduce', queryFields: [] };
64
+ return {
65
+ type: 'reduce',
66
+ queryFields: [],
67
+ outputStruct: ErrorFactory.structDef,
68
+ isRepeated: false,
69
+ };
65
70
  }
66
71
  static get projectSegment() {
67
- return { type: 'project', queryFields: [] };
72
+ return {
73
+ type: 'project',
74
+ queryFields: [],
75
+ outputStruct: ErrorFactory.structDef,
76
+ isRepeated: true,
77
+ };
68
78
  }
69
79
  static get indexSegment() {
70
- return { type: 'index', indexFields: [] };
80
+ return {
81
+ type: 'index',
82
+ indexFields: [],
83
+ outputStruct: ErrorFactory.structDef,
84
+ };
71
85
  }
72
86
  }
73
87
  exports.ErrorFactory = ErrorFactory;
@@ -14,6 +14,7 @@ export declare class ConstantFieldSpace implements FieldSpace {
14
14
  entry(): undefined;
15
15
  dialectName(): string;
16
16
  dialectObj(): undefined;
17
+ connectionName(): string;
17
18
  isQueryFieldSpace(): this is QueryFieldSpace;
18
19
  accessProtectionLevel(): AccessModifierLabel;
19
20
  }
@@ -55,6 +55,9 @@ class ConstantFieldSpace {
55
55
  dialectObj() {
56
56
  return undefined;
57
57
  }
58
+ connectionName() {
59
+ return '~constant-space-unknown-connection~';
60
+ }
58
61
  isQueryFieldSpace() {
59
62
  return false;
60
63
  }
@@ -153,6 +153,18 @@ export declare class ExprProps extends ExpressionDef {
153
153
  morphic?: {
154
154
  [x: string]: import("../../../model/malloy_types").Expr;
155
155
  };
156
+ } | {
157
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
158
+ type: "turtle";
159
+ pipeline: import("../../../model/malloy_types").PipeSegment[];
160
+ expressionType: import("../../../model/malloy_types").ExpressionType;
161
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
162
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
163
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[];
164
+ value: import("../../../model/malloy_types").Expr;
165
+ morphic?: {
166
+ [x: string]: import("../../../model/malloy_types").Expr;
167
+ };
156
168
  } | {
157
169
  requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
158
170
  type: "date";
@@ -68,7 +68,7 @@ const struct_space_field_base_1 = require("./struct-space-field-base");
68
68
  const parameter_space_1 = require("./parameter-space");
69
69
  class DynamicSpace extends static_space_1.StaticSpace {
70
70
  constructor(extending) {
71
- super(structuredClone(extending), extending.dialect);
71
+ super({ ...extending }, extending.dialect, extending.connection);
72
72
  this.complete = false;
73
73
  this.parameters = [];
74
74
  this.newAccessModifiers = new Map();
@@ -1,10 +1,11 @@
1
- import type { IndexSegment, PipeSegment } from '../../../model/malloy_types';
1
+ import type { IndexSegment, PipeSegment, SourceDef } from '../../../model/malloy_types';
2
2
  import { WildcardFieldReference } from '../query-items/field-references';
3
3
  import type { MalloyElement } from '../types/malloy-element';
4
4
  import { QueryOperationSpace } from './query-spaces';
5
5
  export declare class IndexFieldSpace extends QueryOperationSpace {
6
6
  readonly segmentType = "index";
7
7
  pushFields(...defs: MalloyElement[]): void;
8
+ structDef(): SourceDef;
8
9
  getPipeSegment(refineIndex?: PipeSegment): IndexSegment;
9
10
  addRefineFromFields(_refineThis: never): void;
10
11
  protected addWild(wild: WildcardFieldReference): void;
@@ -25,6 +25,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.IndexFieldSpace = void 0;
26
26
  const composite_source_utils_1 = require("../../../model/composite_source_utils");
27
27
  const malloy_types_1 = require("../../../model/malloy_types");
28
+ const error_factory_1 = require("../error-factory");
28
29
  const field_references_1 = require("../query-items/field-references");
29
30
  const space_field_1 = require("../types/space-field");
30
31
  const query_spaces_1 = require("./query-spaces");
@@ -48,11 +49,27 @@ class IndexFieldSpace extends query_spaces_1.QueryOperationSpace {
48
49
  }
49
50
  }
50
51
  }
52
+ structDef() {
53
+ const connection = this.inputSpace().connectionName();
54
+ return {
55
+ type: 'query_result',
56
+ name: 'result',
57
+ dialect: this.dialectName(),
58
+ fields: [
59
+ { type: 'string', name: 'fieldName' },
60
+ { type: 'string', name: 'fieldPath' },
61
+ { type: 'string', name: 'fieldValue' },
62
+ { type: 'string', name: 'fieldType' },
63
+ { type: 'number', name: 'weight', numberType: 'integer' },
64
+ ],
65
+ connection,
66
+ };
67
+ }
51
68
  getPipeSegment(refineIndex) {
52
69
  var _a;
53
70
  if (refineIndex) {
54
71
  this.logError('refinement-of-index-segment', 'index query operations cannot be refined');
55
- return { type: 'index', indexFields: [] };
72
+ return error_factory_1.ErrorFactory.indexSegment;
56
73
  }
57
74
  let fieldUsage = (0, composite_source_utils_1.emptyFieldUsage)();
58
75
  const indexFields = [];
@@ -80,7 +97,8 @@ class IndexFieldSpace extends query_spaces_1.QueryOperationSpace {
80
97
  }
81
98
  }
82
99
  this._fieldUsage = fieldUsage;
83
- return { type: 'index', indexFields };
100
+ const outputStruct = this.structDef();
101
+ return { type: 'index', indexFields, outputStruct };
84
102
  }
85
103
  addRefineFromFields(_refineThis) { }
86
104
  addWild(wild) {
@@ -4,5 +4,5 @@ import { StructSpaceField } from './static-space';
4
4
  export declare class JoinSpaceField extends StructSpaceField {
5
5
  readonly parameterSpace: ParameterSpace;
6
6
  readonly join: Join;
7
- constructor(parameterSpace: ParameterSpace, join: Join, forDialect: string);
7
+ constructor(parameterSpace: ParameterSpace, join: Join, forDialect: string, forConnection: string);
8
8
  }
@@ -25,8 +25,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.JoinSpaceField = void 0;
26
26
  const static_space_1 = require("./static-space");
27
27
  class JoinSpaceField extends static_space_1.StructSpaceField {
28
- constructor(parameterSpace, join, forDialect) {
29
- super(join.getStructDef(parameterSpace), forDialect);
28
+ constructor(parameterSpace, join, forDialect, forConnection) {
29
+ super(join.getStructDef(parameterSpace), forDialect, forConnection);
30
30
  this.parameterSpace = parameterSpace;
31
31
  this.join = join;
32
32
  }
@@ -14,6 +14,7 @@ export declare class ParameterSpace implements FieldSpace {
14
14
  lookup(symbol: FieldName[]): LookupResult;
15
15
  entries(): [string, SpaceEntry][];
16
16
  dialectName(): string;
17
+ connectionName(): string;
17
18
  dialectObj(): Dialect | undefined;
18
19
  isQueryFieldSpace(): this is QueryFieldSpace;
19
20
  accessProtectionLevel(): AccessModifierLabel;
@@ -70,6 +70,9 @@ class ParameterSpace {
70
70
  dialectName() {
71
71
  return '~parameter-space-unknown-dialect~';
72
72
  }
73
+ connectionName() {
74
+ return '~parameter-space-unknown-connection~';
75
+ }
73
76
  dialectObj() {
74
77
  return undefined;
75
78
  }
@@ -18,4 +18,5 @@ export declare class PassthroughSpace implements FieldSpace {
18
18
  outputSpace(): import("./query-spaces").QueryOperationSpace;
19
19
  inputSpace(): import("../types/field-space").SourceFieldSpace;
20
20
  accessProtectionLevel(): AccessModifierLabel;
21
+ connectionName(): string;
21
22
  }
@@ -51,6 +51,9 @@ class PassthroughSpace {
51
51
  accessProtectionLevel() {
52
52
  return this.realFS.accessProtectionLevel();
53
53
  }
54
+ connectionName() {
55
+ return this.realFS.connectionName();
56
+ }
54
57
  }
55
58
  exports.PassthroughSpace = PassthroughSpace;
56
59
  //# sourceMappingURL=passthrough-space.js.map
@@ -27,4 +27,5 @@ export declare class QueryInputSpace extends RefinedSpace implements QueryFieldS
27
27
  outputSpace(): QueryOperationSpace;
28
28
  inputSpace(): this;
29
29
  accessProtectionLevel(): AccessModifierLabel;
30
+ isQueryOutputSpace(): boolean;
30
31
  }
@@ -59,6 +59,9 @@ class QueryInputSpace extends refined_space_1.RefinedSpace {
59
59
  accessProtectionLevel() {
60
60
  return this._accessProtectionLevel;
61
61
  }
62
+ isQueryOutputSpace() {
63
+ return false;
64
+ }
62
65
  }
63
66
  exports.QueryInputSpace = QueryInputSpace;
64
67
  //# sourceMappingURL=query-input-space.js.map
@@ -9,6 +9,10 @@ import type { LookupResult } from '../types/lookup-result';
9
9
  import { QueryInputSpace } from './query-input-space';
10
10
  import type { SpaceEntry } from '../types/space-entry';
11
11
  import type { LogMessageOptions, MessageCode, MessageParameterType } from '../../parse-log';
12
+ type TranslatedQueryField = {
13
+ queryFieldDef: model.QueryFieldDef;
14
+ typeDesc: model.TypeDesc;
15
+ };
12
16
  /**
13
17
  * The output space of a query operation. It is not named "QueryOutputSpace"
14
18
  * because this is the namespace of the Query which is a layer of an output and
@@ -48,21 +52,29 @@ export declare abstract class QueryOperationSpace extends RefinedSpace implement
48
52
  accessProtectionLevel(): model.AccessModifierLabel;
49
53
  inputSpace(): QueryInputSpace;
50
54
  outputSpace(): QueryOperationSpace;
55
+ isQueryOutputSpace(): boolean;
51
56
  protected addWild(wild: WildcardFieldReference): void;
52
57
  protected addValidatedCompositeFieldUserFromEntry(name: string, entry: SpaceEntry): void;
53
58
  addFieldUserFromFilter(filter: model.FilterCondition): void;
54
59
  newEntry(name: string, logTo: MalloyElement, entry: SpaceEntry): void;
60
+ isQueryFieldSpace(): this is QueryFieldSpace;
55
61
  }
56
62
  export declare abstract class QuerySpace extends QueryOperationSpace {
57
63
  addRefineFromFields(refineThis: model.PipeSegment): void;
58
64
  pushFields(...defs: MalloyElement[]): void;
59
65
  canContain(_typeDescResult: model.TypeDesc | undefined): boolean;
60
66
  protected queryFieldDefs(): model.QueryFieldDef[];
67
+ protected getOutputFieldDef(queryFieldDef: model.QueryFieldDef, typeDesc: model.TypeDesc): model.FieldDef;
68
+ protected getPrimaryKey(fields: TranslatedQueryField[]): string | undefined;
69
+ structDef(): model.SourceDef;
70
+ translatedQueryFields: TranslatedQueryField[] | undefined;
71
+ protected translateQueryFields(): TranslatedQueryField[];
61
72
  getQuerySegment(rf: model.QuerySegment | undefined): model.QuerySegment;
73
+ protected isRepeated(): boolean;
62
74
  getPipeSegment(refineFrom: model.QuerySegment | undefined): model.PipeSegment;
63
75
  lookup(path: FieldName[]): LookupResult;
64
- isQueryFieldSpace(): this is QueryFieldSpace;
65
76
  }
66
77
  export declare class ReduceFieldSpace extends QuerySpace {
67
78
  readonly segmentType = "reduce";
68
79
  }
80
+ export {};
@@ -62,10 +62,12 @@ const field_space_1 = require("../types/field-space");
62
62
  const space_field_1 = require("../types/space-field");
63
63
  const field_references_1 = require("../query-items/field-references");
64
64
  const refined_space_1 = require("./refined-space");
65
- const column_space_field_1 = require("./column-space-field");
66
65
  const static_space_1 = require("./static-space");
67
66
  const query_input_space_1 = require("./query-input-space");
68
67
  const composite_source_utils_1 = require("../../../model/composite_source_utils");
68
+ const error_factory_1 = require("../error-factory");
69
+ const reference_field_1 = require("./reference-field");
70
+ const refine_from_space_field_1 = require("./refine-from-space-field");
69
71
  /**
70
72
  * The output space of a query operation. It is not named "QueryOutputSpace"
71
73
  * because this is the namespace of the Query which is a layer of an output and
@@ -110,6 +112,9 @@ class QueryOperationSpace extends refined_space_1.RefinedSpace {
110
112
  outputSpace() {
111
113
  return this;
112
114
  }
115
+ isQueryOutputSpace() {
116
+ return true;
117
+ }
113
118
  addWild(wild) {
114
119
  var _a;
115
120
  let current = this.exprSpace;
@@ -187,6 +192,9 @@ class QueryOperationSpace extends refined_space_1.RefinedSpace {
187
192
  }
188
193
  super.newEntry(name, logTo, entry);
189
194
  }
195
+ isQueryFieldSpace() {
196
+ return true;
197
+ }
190
198
  }
191
199
  exports.QueryOperationSpace = QueryOperationSpace;
192
200
  // Project and Reduce or "QuerySegments" are built from a QuerySpace
@@ -204,17 +212,15 @@ class QuerySpace extends QueryOperationSpace {
204
212
  }
205
213
  for (const field of refineThis.queryFields) {
206
214
  if (field.type === 'fieldref') {
207
- const refTo = this.exprSpace.lookup(field.path.map(f => new field_space_1.FieldName(f)));
208
- if (refTo.found) {
209
- const name = field.path[field.path.length - 1];
210
- this.setEntry(name, refTo.found);
211
- this.addValidatedCompositeFieldUserFromEntry(name, refTo.found);
212
- }
215
+ const fieldReference = new field_references_1.RefineFromFieldReference(field.path.map(f => new field_space_1.FieldName(f)));
216
+ this.astEl.has({ fieldReference });
217
+ const referenceField = new reference_field_1.ReferenceField(fieldReference, this.exprSpace);
218
+ const name = field.path[field.path.length - 1];
219
+ this.setEntry(name, referenceField);
220
+ this.addValidatedCompositeFieldUserFromEntry(name, referenceField);
213
221
  }
214
- else if (field.type !== 'turtle') {
215
- // TODO can you reference fields in a turtle as fields in the output space,
216
- // e.g. order_by: my_turtle.foo, or lag(my_turtle.foo)
217
- const entry = new column_space_field_1.ColumnSpaceField(field);
222
+ else {
223
+ const entry = new refine_from_space_field_1.RefineFromSpaceField(field);
218
224
  const name = (_a = field.as) !== null && _a !== void 0 ? _a : field.name;
219
225
  this.setEntry(name, entry);
220
226
  this.addValidatedCompositeFieldUserFromEntry(name, entry);
@@ -235,7 +241,91 @@ class QuerySpace extends QueryOperationSpace {
235
241
  return true;
236
242
  }
237
243
  queryFieldDefs() {
244
+ const fields = this.translateQueryFields();
245
+ return fields.map(f => f.queryFieldDef);
246
+ }
247
+ getOutputFieldDef(queryFieldDef, typeDesc) {
248
+ var _a, _b;
249
+ const name = queryFieldDef.type === 'fieldref'
250
+ ? queryFieldDef.path[queryFieldDef.path.length - 1]
251
+ : (_a = queryFieldDef.as) !== null && _a !== void 0 ? _a : queryFieldDef.name;
252
+ if (typeDesc.type === 'turtle') {
253
+ const pipeline = typeDesc.pipeline;
254
+ const lastSegment = pipeline[pipeline.length - 1];
255
+ const outputStruct = (_b = lastSegment === null || lastSegment === void 0 ? void 0 : lastSegment.outputStruct) !== null && _b !== void 0 ? _b : error_factory_1.ErrorFactory.structDef;
256
+ const isRepeated = lastSegment
257
+ ? model.isQuerySegment(lastSegment)
258
+ ? lastSegment.isRepeated
259
+ : true
260
+ : true;
261
+ if (isRepeated) {
262
+ return {
263
+ ...outputStruct,
264
+ elementTypeDef: { type: 'record_element' },
265
+ name: name,
266
+ type: 'array',
267
+ join: 'many',
268
+ as: undefined,
269
+ };
270
+ }
271
+ else {
272
+ return {
273
+ ...outputStruct,
274
+ name: name,
275
+ type: 'record',
276
+ join: 'one',
277
+ as: undefined,
278
+ };
279
+ }
280
+ }
281
+ else if (model.TD.isAtomic(typeDesc)) {
282
+ const td = model.mkFieldDef(typeDesc, name);
283
+ return {
284
+ ...td,
285
+ expressionType: 'scalar',
286
+ e: undefined,
287
+ };
288
+ }
289
+ else {
290
+ throw new Error('Invalid type for fieldref');
291
+ }
292
+ }
293
+ // Gets the primary key field for the output struct of this query;
294
+ // If there is exactly one scalar field, that is the primary key
295
+ getPrimaryKey(fields) {
296
+ var _a;
297
+ const dimensions = fields.filter(f => model.TD.isAtomic(f.typeDesc) &&
298
+ model.expressionIsScalar(f.typeDesc.expressionType));
299
+ if (dimensions.length !== 1)
300
+ return undefined;
301
+ const primaryKeyField = dimensions[0].queryFieldDef;
302
+ if (primaryKeyField.type === 'fieldref') {
303
+ return primaryKeyField.path[primaryKeyField.path.length - 1];
304
+ }
305
+ else {
306
+ return (_a = primaryKeyField.as) !== null && _a !== void 0 ? _a : primaryKeyField.name;
307
+ }
308
+ }
309
+ // This returns the OUTPUT struct of this query space
310
+ structDef() {
311
+ const fields = this.translateQueryFields();
312
+ const sourceDef = {
313
+ type: 'query_result',
314
+ // TODO to match the compiler, does this need to be the name of the query?
315
+ name: 'query_result',
316
+ dialect: this.dialectName(),
317
+ // TODO need to get this in a less expensive way?
318
+ connection: this.inputSpace().connectionName(),
319
+ fields: fields.map(f => this.getOutputFieldDef(f.queryFieldDef, f.typeDesc)),
320
+ primaryKey: this.getPrimaryKey(fields),
321
+ };
322
+ return sourceDef;
323
+ }
324
+ translateQueryFields() {
238
325
  var _a;
326
+ if (this.translatedQueryFields) {
327
+ return this.translatedQueryFields;
328
+ }
239
329
  const fields = [];
240
330
  let fieldUsage = (0, composite_source_utils_1.emptyFieldUsage)();
241
331
  for (const user of this.compositeFieldUsers) {
@@ -249,12 +339,20 @@ class QuerySpace extends QueryOperationSpace {
249
339
  const { name, field } = user;
250
340
  const wildPath = this.expandedWild[name];
251
341
  if (wildPath) {
252
- fields.push({ type: 'fieldref', path: wildPath.path, at: wildPath.at });
253
- nextFieldUsage = wildPath.entry.typeDesc().fieldUsage;
342
+ const typeDesc = wildPath.entry.typeDesc();
343
+ fields.push({
344
+ queryFieldDef: {
345
+ type: 'fieldref',
346
+ path: wildPath.path,
347
+ at: wildPath.at,
348
+ },
349
+ typeDesc,
350
+ });
351
+ nextFieldUsage = typeDesc.fieldUsage;
254
352
  }
255
353
  else {
256
- const fieldQueryDef = field.getQueryFieldDef(this.exprSpace);
257
- if (fieldQueryDef) {
354
+ const queryFieldDef = field.getQueryFieldDef(this.exprSpace);
355
+ if (queryFieldDef) {
258
356
  const typeDesc = field.typeDesc();
259
357
  nextFieldUsage = typeDesc.fieldUsage;
260
358
  // Filter out fields whose type is 'error', which means that a totally bad field
@@ -264,17 +362,13 @@ class QuerySpace extends QueryOperationSpace {
264
362
  if (typeDesc &&
265
363
  typeDesc.type !== 'error' &&
266
364
  this.canContain(typeDesc) &&
267
- !isEmptyNest(fieldQueryDef)) {
268
- fields.push(fieldQueryDef);
365
+ !isEmptyNest(queryFieldDef)) {
366
+ fields.push({ queryFieldDef, typeDesc });
269
367
  }
270
368
  }
271
- // TODO I removed the error here because during calculation of the refinement space,
272
- // (see creation of a QuerySpace) we add references to all the fields from
273
- // the refinement, but they don't have definitions. So in the case where we
274
- // don't have a field def, we "know" that that field is already in the query,
275
- // and we don't need to worry about actually adding it. Previously, this was also true for
276
- // project statements, where we added "*" as a field and also all the individual
277
- // fields, but the individual fields didn't have field defs.
369
+ else {
370
+ throw new Error('Expected query field to have a definition');
371
+ }
278
372
  }
279
373
  }
280
374
  fieldUsage = (_a = (0, composite_source_utils_1.mergeFieldUsage)(fieldUsage, nextFieldUsage)) !== null && _a !== void 0 ? _a : [];
@@ -285,6 +379,7 @@ class QuerySpace extends QueryOperationSpace {
285
379
  drillDimension.firstDrill.logError('illegal-drill', `Must provide a value for all dimensions in a view when drilling: missing \`${drillDimension.dimensionPath.join('.')}\``);
286
380
  }
287
381
  }
382
+ this.translatedQueryFields = fields;
288
383
  return fields;
289
384
  }
290
385
  getQuerySegment(rf) {
@@ -294,17 +389,24 @@ class QuerySpace extends QueryOperationSpace {
294
389
  }
295
390
  throw new Error('TODO NOT POSSIBLE');
296
391
  }
392
+ isRepeated() {
393
+ const fields = this.translateQueryFields();
394
+ const dimensions = fields.filter(f => model.TD.isAtomic(f.typeDesc) &&
395
+ model.expressionIsScalar(f.typeDesc.expressionType));
396
+ return dimensions.length > 0;
397
+ }
297
398
  getPipeSegment(refineFrom) {
298
399
  if (this.segmentType === 'index') {
299
400
  // come coding error made this "impossible" thing happen
300
401
  this.logError('unexpected-index-segment', 'internal error generating index segment from non index query');
301
- return { type: 'reduce', queryFields: [] };
402
+ return error_factory_1.ErrorFactory.reduceSegment;
302
403
  }
303
404
  const segment = {
304
405
  type: this.segmentType,
305
406
  queryFields: this.queryFieldDefs(),
407
+ outputStruct: this.structDef(),
408
+ isRepeated: this.isRepeated(),
306
409
  };
307
- segment.queryFields = (0, field_utils_1.mergeFields)(refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.queryFields, segment.queryFields);
308
410
  if (refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.extendSource) {
309
411
  segment.extendSource = refineFrom.extendSource;
310
412
  }
@@ -331,9 +433,6 @@ class QuerySpace extends QueryOperationSpace {
331
433
  }
332
434
  return this.exprSpace.lookup(path);
333
435
  }
334
- isQueryFieldSpace() {
335
- return true;
336
- }
337
436
  }
338
437
  exports.QuerySpace = QuerySpace;
339
438
  class ReduceFieldSpace extends QuerySpace {
@@ -0,0 +1,9 @@
1
+ import type { TypeDesc, AtomicFieldDef, QueryFieldDef, TurtleDef } from '../../../model/malloy_types';
2
+ import type { FieldSpace } from '../types/field-space';
3
+ import { SpaceField } from '../types/space-field';
4
+ export declare class RefineFromSpaceField extends SpaceField {
5
+ private readonly refineFromFieldDef;
6
+ constructor(refineFromFieldDef: AtomicFieldDef | TurtleDef);
7
+ getQueryFieldDef(_fs: FieldSpace): QueryFieldDef | undefined;
8
+ typeDesc(): TypeDesc;
9
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.RefineFromSpaceField = void 0;
10
+ const space_field_1 = require("../types/space-field");
11
+ class RefineFromSpaceField extends space_field_1.SpaceField {
12
+ constructor(refineFromFieldDef) {
13
+ super();
14
+ this.refineFromFieldDef = refineFromFieldDef;
15
+ }
16
+ getQueryFieldDef(_fs) {
17
+ return this.refineFromFieldDef;
18
+ }
19
+ typeDesc() {
20
+ return this.typeFromFieldDef(this.refineFromFieldDef);
21
+ }
22
+ }
23
+ exports.RefineFromSpaceField = RefineFromSpaceField;
24
+ //# sourceMappingURL=refine-from-space-field.js.map