@malloydata/malloy 0.0.22-dev230119001546 → 0.0.22-dev230119193053

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.
@@ -24,7 +24,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.TurtleHeadedPipe = exports.ExistingQuery = exports.Index = exports.Turtles = exports.Limit = exports.Ordering = exports.OrderBy = exports.WildcardFieldReference = exports.RenameField = exports.PrimaryKey = exports.Document = exports.QOPDesc = exports.Aggregate = exports.GroupBy = exports.FieldListEdit = exports.ProjectStatement = exports.isFieldCollectionMember = exports.FieldReferences = exports.FieldReference = exports.FieldName = exports.Renames = exports.Dimensions = exports.Measures = exports.DeclareFields = exports.Filter = exports.FilterElement = exports.ExploreDesc = exports.isExploreProperty = exports.isQueryProperty = exports.Joins = exports.ExpressionJoin = exports.KeyJoin = exports.Join = exports.QuerySource = exports.SQLSource = exports.NamedSource = exports.ModelEntryReference = exports.IsValueBlock = exports.TableSource = exports.RefinedExplore = exports.DefineSourceList = exports.DefineExplore = exports.isDocStatement = exports.RunList = exports.Mallobj = exports.isExploreField = exports.Unimplemented = exports.ListOf = exports.MalloyElement = exports.ErrorFactory = void 0;
27
- exports.Range = exports.ExprTime = exports.ExprDuration = exports.TypeMistmatch = exports.ExprGranularTime = exports.ExprCompare = exports.BinaryBoolean = exports.applyBinary = exports.FieldDeclaration = exports.ConstantSubExpression = exports.ExpressionDef = exports.SampleProperty = exports.SQLStatement = exports.SQLString = exports.ConstantParameter = exports.HasParameter = exports.ImportStatement = exports.JSONStructDef = exports.JSONElement = exports.Top = exports.AnonymousQuery = exports.DefineQuery = exports.DefineQueryList = exports.isQueryElement = exports.Nests = exports.isNestedQuery = exports.NestDefinition = exports.NestRefinement = exports.NestReference = exports.TurtleDecl = exports.FullQuery = void 0;
27
+ exports.RenameSpaceField = exports.QueryFieldAST = exports.ExpressionFieldFromAst = exports.AbstractParameter = exports.SpaceSeed = exports.DefinedParameter = exports.SpaceParam = exports.ColumnSpaceField = exports.QueryFieldStruct = exports.QueryField = exports.StructSpaceField = exports.SpaceField = exports.SpaceEntry = exports.ProjectFieldSpace = exports.ReduceFieldSpace = exports.ResultSpace = exports.DynamicSpace = exports.StaticSpace = exports.DefSpace = exports.Range = exports.ExprTime = exports.ExprDuration = exports.TypeMistmatch = exports.ExprGranularTime = exports.ExprCompare = exports.BinaryBoolean = exports.applyBinary = exports.FieldDeclaration = exports.ConstantSubExpression = exports.ExpressionDef = exports.SampleProperty = exports.SQLStatement = exports.SQLString = exports.ConstantParameter = exports.HasParameter = exports.ImportStatement = exports.JSONStructDef = exports.JSONElement = exports.Top = exports.AnonymousQuery = exports.DefineQuery = exports.DefineQueryList = exports.isQueryElement = exports.Nests = exports.isNestedQuery = exports.NestDefinition = exports.NestRefinement = exports.NestReference = exports.TurtleDecl = exports.FullQuery = void 0;
28
+ exports.IndexFieldSpace = exports.WildSpaceField = exports.ReferenceField = exports.QuerySpace = exports.JoinSpaceField = void 0;
28
29
  /*
29
30
  * Copyright 2023 Google LLC
30
31
  *
@@ -49,15 +50,15 @@ exports.Range = exports.ExprTime = exports.ExprDuration = exports.TypeMistmatch
49
50
  */
50
51
  const lodash_1 = require("lodash");
51
52
  const model = __importStar(require("../../model/malloy_types"));
53
+ const dialect_map_1 = require("../../dialect/dialect_map");
52
54
  const malloy_types_1 = require("../../model/malloy_types");
53
55
  const malloy_query_1 = require("../../model/malloy_query");
54
- const field_space_1 = require("../field-space");
55
56
  const ast_types_1 = require("./ast-types");
56
- const space_field_1 = require("../space-field");
57
57
  const sql_block_1 = require("../../model/sql_block");
58
58
  const util_1 = require("util");
59
59
  const time_utils_1 = require("./time-utils");
60
60
  const apply_expr_1 = require("./apply-expr");
61
+ const field_utils_1 = require("../field-utils");
61
62
  /*
62
63
  ** For times when there is a code generation error but your function needs
63
64
  ** to return some kind of object to type properly, the ErrorFactory is
@@ -541,7 +542,7 @@ class RefinedExplore extends Mallobj {
541
542
  if (primaryKey) {
542
543
  from.primaryKey = primaryKey.field.name;
543
544
  }
544
- const fs = field_space_1.DynamicSpace.filteredFrom(from, fieldListEdit);
545
+ const fs = DynamicSpace.filteredFrom(from, fieldListEdit);
545
546
  fs.addField(...fields);
546
547
  if (pList) {
547
548
  fs.addParameters(pList);
@@ -1115,7 +1116,7 @@ class ReduceExecutor {
1115
1116
  this.inputFS = this.resultFS.exprSpace;
1116
1117
  }
1117
1118
  getResultSpace(fs) {
1118
- return new field_space_1.ReduceFieldSpace(fs);
1119
+ return new ReduceFieldSpace(fs);
1119
1120
  }
1120
1121
  execute(qp) {
1121
1122
  if (qp instanceof GroupBy ||
@@ -1219,7 +1220,7 @@ class ReduceExecutor {
1219
1220
  }
1220
1221
  class ProjectExecutor extends ReduceExecutor {
1221
1222
  getResultSpace(fs) {
1222
- return new field_space_1.ProjectFieldSpace(fs);
1223
+ return new ProjectFieldSpace(fs);
1223
1224
  }
1224
1225
  execute(qp) {
1225
1226
  if (qp instanceof ProjectStatement) {
@@ -1253,7 +1254,7 @@ class ProjectExecutor extends ReduceExecutor {
1253
1254
  class IndexExecutor {
1254
1255
  constructor(inputFS) {
1255
1256
  this.filters = [];
1256
- this.resultFS = new field_space_1.IndexFieldSpace(inputFS);
1257
+ this.resultFS = new IndexFieldSpace(inputFS);
1257
1258
  this.inputFS = this.resultFS.exprSpace;
1258
1259
  }
1259
1260
  execute(qp) {
@@ -1394,7 +1395,7 @@ class QOPDesc extends ListOf {
1394
1395
  const segment = qex.finalize(this.refineThis);
1395
1396
  return {
1396
1397
  segment,
1397
- outputSpace: () => new field_space_1.DynamicSpace(opOutputStruct(this, inputFS.structDef(), segment)),
1398
+ outputSpace: () => new DynamicSpace(opOutputStruct(this, inputFS.structDef(), segment)),
1398
1399
  };
1399
1400
  }
1400
1401
  }
@@ -1692,10 +1693,10 @@ class ExistingQuery extends PipelineDesc {
1692
1693
  const queryHead = new QueryHeadStruct(seedQuery.structRef);
1693
1694
  this.has({ queryHead });
1694
1695
  const exploreStruct = queryHead.structDef();
1695
- const exploreFS = new field_space_1.DynamicSpace(exploreStruct);
1696
+ const exploreFS = new DynamicSpace(exploreStruct);
1696
1697
  const sourcePipe = this.refinePipeline(exploreFS, seedQuery);
1697
1698
  const walkStruct = this.getOutputStruct(exploreStruct, sourcePipe.pipeline);
1698
- const appended = this.appendOps(sourcePipe.pipeline, new field_space_1.DynamicSpace(walkStruct));
1699
+ const appended = this.appendOps(sourcePipe.pipeline, new DynamicSpace(walkStruct));
1699
1700
  const destPipe = { ...sourcePipe, pipeline: appended.opList };
1700
1701
  const query = {
1701
1702
  type: "query",
@@ -1736,7 +1737,7 @@ class FullQuery extends TurtleHeadedPipe {
1736
1737
  const structDef = model.refIsStructDef(structRef)
1737
1738
  ? structRef
1738
1739
  : this.explore.structDef();
1739
- let pipeFs = new field_space_1.DynamicSpace(structDef);
1740
+ let pipeFs = new DynamicSpace(structDef);
1740
1741
  if (ErrorFactory.isErrorStructDef(structDef)) {
1741
1742
  return {
1742
1743
  outputStruct: structDef,
@@ -1764,7 +1765,7 @@ class FullQuery extends TurtleHeadedPipe {
1764
1765
  destQuery.pipeHead = { name };
1765
1766
  }
1766
1767
  const pipeStruct = this.getOutputStruct(structDef, refined);
1767
- pipeFs = new field_space_1.DynamicSpace(pipeStruct);
1768
+ pipeFs = new DynamicSpace(pipeStruct);
1768
1769
  }
1769
1770
  const appended = this.appendOps(destQuery.pipeline, pipeFs);
1770
1771
  destQuery.pipeline = appended.opList;
@@ -1789,7 +1790,7 @@ class TurtleDecl extends TurtleHeadedPipe {
1789
1790
  this.log(headEnt.error);
1790
1791
  reportWrongType = false;
1791
1792
  }
1792
- else if (headEnt.found instanceof space_field_1.QueryField) {
1793
+ else if (headEnt.found instanceof QueryField) {
1793
1794
  const headDef = headEnt.found.getQueryFieldDef(fs);
1794
1795
  if (isTurtle(headDef)) {
1795
1796
  const newPipe = this.refinePipeline(fs, headDef);
@@ -1810,7 +1811,7 @@ class TurtleDecl extends TurtleHeadedPipe {
1810
1811
  for (const existingSeg of modelPipe.pipeline) {
1811
1812
  endStruct = opOutputStruct(this, endStruct, existingSeg);
1812
1813
  }
1813
- appendInput = new field_space_1.DynamicSpace(endStruct);
1814
+ appendInput = new DynamicSpace(endStruct);
1814
1815
  }
1815
1816
  const appended = this.appendOps(modelPipe.pipeline, appendInput);
1816
1817
  modelPipe.pipeline = appended.opList;
@@ -2325,7 +2326,7 @@ class FieldDeclaration extends MalloyElement {
2325
2326
  * a refactor of QueryFieldSpace might someday be the place where this should
2326
2327
  * happen.
2327
2328
  */
2328
- return this.queryFieldDef(new field_space_1.DefSpace(fs, this), exprName);
2329
+ return this.queryFieldDef(new DefSpace(fs, this), exprName);
2329
2330
  }
2330
2331
  queryFieldDef(exprFS, exprName) {
2331
2332
  let exprValue;
@@ -2362,7 +2363,7 @@ class FieldDeclaration extends MalloyElement {
2362
2363
  }
2363
2364
  return template;
2364
2365
  }
2365
- const circularDef = exprFS instanceof field_space_1.DefSpace && exprFS.foundCircle;
2366
+ const circularDef = exprFS instanceof DefSpace && exprFS.foundCircle;
2366
2367
  if (!circularDef) {
2367
2368
  if (exprValue.dataType == "unknown") {
2368
2369
  this.log(`Cannot define '${exprName}', value has unknown type`);
@@ -2855,4 +2856,817 @@ class Range extends ExpressionDef {
2855
2856
  }
2856
2857
  }
2857
2858
  exports.Range = Range;
2859
+ /**
2860
+ * Used to detect references to fields in the statement which defines them
2861
+ */
2862
+ class DefSpace {
2863
+ constructor(realFS, circular) {
2864
+ this.realFS = realFS;
2865
+ this.circular = circular;
2866
+ this.type = "fieldSpace";
2867
+ this.foundCircle = false;
2868
+ }
2869
+ structDef() {
2870
+ return this.realFS.structDef();
2871
+ }
2872
+ emptyStructDef() {
2873
+ return this.realFS.emptyStructDef();
2874
+ }
2875
+ lookup(symbol) {
2876
+ if (symbol[0] && symbol[0].refString === this.circular.defineName) {
2877
+ this.foundCircle = true;
2878
+ return {
2879
+ error: `Circular reference to '${this.circular.defineName}' in definition`,
2880
+ found: undefined,
2881
+ };
2882
+ }
2883
+ return this.realFS.lookup(symbol);
2884
+ }
2885
+ dialectObj() {
2886
+ return this.realFS.dialectObj();
2887
+ }
2888
+ whenComplete(step) {
2889
+ this.realFS.whenComplete(step);
2890
+ }
2891
+ }
2892
+ exports.DefSpace = DefSpace;
2893
+ class StaticSpace {
2894
+ constructor(sourceStructDef) {
2895
+ this.type = "fieldSpace";
2896
+ this.fromStruct = sourceStructDef;
2897
+ }
2898
+ whenComplete(step) {
2899
+ step();
2900
+ }
2901
+ dialectObj() {
2902
+ try {
2903
+ return (0, dialect_map_1.getDialect)(this.fromStruct.dialect);
2904
+ }
2905
+ catch {
2906
+ return undefined;
2907
+ }
2908
+ }
2909
+ fromFieldDef(from) {
2910
+ if (from.type === "struct") {
2911
+ return new StructSpaceField(from);
2912
+ }
2913
+ else if (model.isTurtleDef(from)) {
2914
+ return new QueryFieldStruct(this, from);
2915
+ }
2916
+ // TODO field has a filter and needs to be a filteredalias
2917
+ return new ColumnSpaceField(from);
2918
+ }
2919
+ get map() {
2920
+ if (this.memoMap === undefined) {
2921
+ this.memoMap = {};
2922
+ for (const f of this.fromStruct.fields) {
2923
+ const name = f.as || f.name;
2924
+ this.memoMap[name] = this.fromFieldDef(f);
2925
+ }
2926
+ if (this.fromStruct.parameters) {
2927
+ for (const [paramName, paramDef] of Object.entries(this.fromStruct.parameters)) {
2928
+ if (this.memoMap[paramName]) {
2929
+ throw new Error(`In struct '${this.fromStruct.as || this.fromStruct.name}': ` +
2930
+ ` : Field and parameter name conflict '${paramName}`);
2931
+ }
2932
+ this.memoMap[paramName] = new DefinedParameter(paramDef);
2933
+ }
2934
+ }
2935
+ }
2936
+ return this.memoMap;
2937
+ }
2938
+ dropEntries() {
2939
+ this.memoMap = {};
2940
+ }
2941
+ dropEntry(name) {
2942
+ delete this.map[name];
2943
+ }
2944
+ entry(name) {
2945
+ return this.map[name];
2946
+ }
2947
+ setEntry(name, value) {
2948
+ this.map[name] = value;
2949
+ }
2950
+ entries() {
2951
+ return Object.entries(this.map);
2952
+ }
2953
+ structDef() {
2954
+ return this.fromStruct;
2955
+ }
2956
+ emptyStructDef() {
2957
+ return { ...this.fromStruct, fields: [] };
2958
+ }
2959
+ lookup(path) {
2960
+ const head = path[0];
2961
+ const rest = path.slice(1);
2962
+ const found = this.entry(head.refString);
2963
+ if (!found) {
2964
+ return { error: `'${head}' is not defined`, found };
2965
+ }
2966
+ if (found instanceof SpaceField) {
2967
+ /*
2968
+ * TODO cache defs, post the addReference call to whenComplete
2969
+ *
2970
+ * In the cleanup phase of query space construction, it may check
2971
+ * the output space for ungrouping variables. However if an
2972
+ * ungrouping variable is a measure, the field expression value
2973
+ * needed to get the definition needs to be computed in the
2974
+ * input space of the query. There is a test which failed which
2975
+ * caused this code to be here, but this is really a bandaid.
2976
+ *
2977
+ * Some re-work of how to get the definition of a SpaceField
2978
+ * no matter what it is contained in needs to be thought out.
2979
+ *
2980
+ * ... or this check would look at the finalized output of
2981
+ * the namespace and not re-compile ...
2982
+ */
2983
+ const definition = found.fieldDef();
2984
+ if (definition) {
2985
+ head.addReference({
2986
+ type: found instanceof StructSpaceField
2987
+ ? "joinReference"
2988
+ : "fieldReference",
2989
+ definition,
2990
+ location: head.location,
2991
+ text: head.refString,
2992
+ });
2993
+ }
2994
+ }
2995
+ if (rest.length) {
2996
+ if (found instanceof StructSpaceField) {
2997
+ return found.fieldSpace.lookup(rest);
2998
+ }
2999
+ return {
3000
+ error: `'${head}' cannot contain a '${rest[0]}'`,
3001
+ found: undefined,
3002
+ };
3003
+ }
3004
+ return { found, error: undefined };
3005
+ }
3006
+ }
3007
+ exports.StaticSpace = StaticSpace;
3008
+ /**
3009
+ * A FieldSpace which may undergo modification
3010
+ */
3011
+ class DynamicSpace extends StaticSpace {
3012
+ constructor(extending) {
3013
+ const source = new SpaceSeed(extending);
3014
+ super((0, lodash_1.cloneDeep)(source.structDef));
3015
+ this.completions = [];
3016
+ this.complete = false;
3017
+ this.final = undefined;
3018
+ this.source = source;
3019
+ }
3020
+ /**
3021
+ * Factory for DynamicSpace when there are accept/except edits
3022
+ * @param from A structdef which seeds this space
3023
+ * @param choose A accept/except edit of the "from" fields
3024
+ */
3025
+ static filteredFrom(from, choose) {
3026
+ const edited = new DynamicSpace(from);
3027
+ if (choose) {
3028
+ const names = choose.refs.list;
3029
+ const oldMap = edited.entries();
3030
+ edited.dropEntries();
3031
+ for (const [symbol, value] of oldMap) {
3032
+ const included = !!names.find((f) => f.refString === symbol);
3033
+ const accepting = choose.edit === "accept";
3034
+ if (included === accepting) {
3035
+ edited.setEntry(symbol, value);
3036
+ }
3037
+ }
3038
+ }
3039
+ return edited;
3040
+ }
3041
+ whenComplete(finalizeStep) {
3042
+ if (this.complete) {
3043
+ finalizeStep();
3044
+ }
3045
+ else {
3046
+ this.completions.push(finalizeStep);
3047
+ }
3048
+ }
3049
+ isComplete() {
3050
+ this.complete = true;
3051
+ for (const step of this.completions) {
3052
+ step();
3053
+ }
3054
+ this.completions = [];
3055
+ }
3056
+ setEntry(name, value) {
3057
+ if (this.final) {
3058
+ throw new Error("Space already final");
3059
+ }
3060
+ super.setEntry(name, value);
3061
+ }
3062
+ addParameters(params) {
3063
+ for (const oneP of params) {
3064
+ this.setEntry(oneP.name, new AbstractParameter(oneP));
3065
+ }
3066
+ return this;
3067
+ }
3068
+ newEntry(name, astEl, entry) {
3069
+ if (this.entry(name)) {
3070
+ astEl.log(`Cannot redefine '${name}'`);
3071
+ return;
3072
+ }
3073
+ this.setEntry(name, entry);
3074
+ }
3075
+ addField(...defs) {
3076
+ for (const def of defs) {
3077
+ // TODO express the "three fields kinds" in a typesafe way
3078
+ // one of three kinds of fields are legal in an explore: expressions ...
3079
+ const elseLog = def.log;
3080
+ const elseType = def.elementType;
3081
+ if (def instanceof FieldDeclaration) {
3082
+ const exprField = new ExpressionFieldFromAst(this, def);
3083
+ this.newEntry(exprField.name, def, exprField);
3084
+ // querry (turtle) fields
3085
+ }
3086
+ else if (def instanceof TurtleDecl) {
3087
+ const name = def.name;
3088
+ this.newEntry(name, def, new QueryFieldAST(this, def, name));
3089
+ }
3090
+ else if (def instanceof RenameField) {
3091
+ if (def.oldName.refString === def.newName) {
3092
+ def.log("Can't rename field to itself");
3093
+ continue;
3094
+ }
3095
+ const oldValue = def.oldName.getField(this);
3096
+ if (oldValue.found) {
3097
+ if (oldValue.found instanceof SpaceField) {
3098
+ this.setEntry(def.newName, new RenameSpaceField(oldValue.found, def.newName, def.location));
3099
+ this.dropEntry(def.oldName.refString);
3100
+ }
3101
+ else {
3102
+ def.log(`'${def.oldName}' cannot be renamed`);
3103
+ }
3104
+ }
3105
+ else {
3106
+ def.log(`Can't rename '${def.oldName}', no such field`);
3107
+ }
3108
+ }
3109
+ else if (def instanceof Join) {
3110
+ this.newEntry(def.name.refString, def, new JoinSpaceField(this, def));
3111
+ }
3112
+ else {
3113
+ elseLog(`Internal error: Expected expression, query, or rename, got '${elseType}'`);
3114
+ }
3115
+ }
3116
+ }
3117
+ addFieldDef(fd) {
3118
+ this.setEntry((0, field_utils_1.nameOf)(fd), this.fromFieldDef(fd));
3119
+ }
3120
+ structDef() {
3121
+ const parameters = this.fromStruct.parameters || {};
3122
+ if (this.final === undefined) {
3123
+ this.final = {
3124
+ ...this.fromStruct,
3125
+ fields: [],
3126
+ };
3127
+ // Need to process the entities in specific order
3128
+ const fields = [];
3129
+ const joins = [];
3130
+ const turtles = [];
3131
+ const fixupJoins = [];
3132
+ for (const [name, spaceEntry] of this.entries()) {
3133
+ if (spaceEntry instanceof StructSpaceField) {
3134
+ joins.push([name, spaceEntry]);
3135
+ }
3136
+ else if (spaceEntry instanceof QueryField) {
3137
+ turtles.push([name, spaceEntry]);
3138
+ }
3139
+ else if (spaceEntry instanceof SpaceField) {
3140
+ fields.push([name, spaceEntry]);
3141
+ }
3142
+ else if (spaceEntry instanceof SpaceParam) {
3143
+ parameters[name] = spaceEntry.parameter();
3144
+ }
3145
+ }
3146
+ const reorderFields = [...fields, ...joins, ...turtles];
3147
+ for (const [fieldName, field] of reorderFields) {
3148
+ if (field instanceof JoinSpaceField) {
3149
+ const joinStruct = field.join.structDef();
3150
+ if (!ErrorFactory.isErrorStructDef(joinStruct)) {
3151
+ this.final.fields.push(joinStruct);
3152
+ fixupJoins.push([field.join, joinStruct]);
3153
+ }
3154
+ }
3155
+ else {
3156
+ const fieldDef = field.fieldDef();
3157
+ if (fieldDef) {
3158
+ this.final.fields.push(fieldDef);
3159
+ }
3160
+ else {
3161
+ throw new Error(`'${fieldName}' doesn't have a FieldDef`);
3162
+ }
3163
+ }
3164
+ }
3165
+ if (Object.entries(parameters).length > 0) {
3166
+ this.final.parameters = parameters;
3167
+ }
3168
+ // If we have join expressions, we need to now go back and fill them in
3169
+ for (const [join, missingOn] of fixupJoins) {
3170
+ join.fixupJoinOn(this, missingOn);
3171
+ }
3172
+ }
3173
+ this.isComplete();
3174
+ return this.final;
3175
+ }
3176
+ }
3177
+ exports.DynamicSpace = DynamicSpace;
3178
+ class ResultSpace extends DynamicSpace {
3179
+ constructor(queryInputSpace) {
3180
+ super(queryInputSpace.emptyStructDef());
3181
+ this.queryInputSpace = queryInputSpace;
3182
+ this.exprSpace = new QuerySpace(queryInputSpace, this);
3183
+ }
3184
+ log(s) {
3185
+ if (this.astEl) {
3186
+ this.astEl.log(s);
3187
+ }
3188
+ }
3189
+ addMembers(members) {
3190
+ for (const member of members) {
3191
+ if (member instanceof FieldReference) {
3192
+ this.addReference(member);
3193
+ }
3194
+ else if (member instanceof WildcardFieldReference) {
3195
+ this.addWild(member);
3196
+ }
3197
+ else {
3198
+ this.addField(member);
3199
+ }
3200
+ }
3201
+ }
3202
+ addReference(ref) {
3203
+ const refName = ref.outputName;
3204
+ if (this.entry(refName)) {
3205
+ ref.log(`Output already has a field named '${refName}'`);
3206
+ }
3207
+ else {
3208
+ this.setEntry(refName, new ReferenceField(ref));
3209
+ }
3210
+ }
3211
+ addWild(wild) {
3212
+ this.setEntry(wild.refString, new WildSpaceField(wild.refString));
3213
+ }
3214
+ /**
3215
+ * Check for the definition of an ungrouping reference in the result space,
3216
+ * or in the case of an exclude reference, if this query is nested
3217
+ * in another query, in the result space of a query that this query
3218
+ * is nested inside of.
3219
+ */
3220
+ checkUngroup(fn, isExclude) {
3221
+ if (!this.entry(fn.refString)) {
3222
+ if (isExclude && this.exprSpace.nestParent) {
3223
+ const parent = this.exprSpace.nestParent;
3224
+ parent.whenComplete(() => {
3225
+ parent.result.checkUngroup(fn, isExclude);
3226
+ });
3227
+ }
3228
+ else {
3229
+ const uName = isExclude ? "exclude()" : "all()";
3230
+ fn.log(`${uName} '${fn.refString}' is missing from query output`);
3231
+ }
3232
+ }
3233
+ }
3234
+ addQueryItems(...qiList) {
3235
+ for (const qi of qiList) {
3236
+ if (qi instanceof FieldReference || qi instanceof NestReference) {
3237
+ this.addReference(qi);
3238
+ }
3239
+ else if (qi instanceof FieldDeclaration) {
3240
+ this.addField(qi);
3241
+ }
3242
+ else if (isNestedQuery(qi)) {
3243
+ const qf = new QueryFieldAST(this, qi, qi.name);
3244
+ qf.nestParent = this.exprSpace;
3245
+ this.setEntry(qi.name, qf);
3246
+ }
3247
+ else {
3248
+ // Compiler will error if we don't handle all cases
3249
+ const _itemNotHandled = qi;
3250
+ }
3251
+ }
3252
+ }
3253
+ canContain(_qd) {
3254
+ return true;
3255
+ }
3256
+ queryFieldDefs() {
3257
+ const fields = [];
3258
+ for (const [name, field] of this.entries()) {
3259
+ if (field instanceof SpaceField) {
3260
+ const fieldQueryDef = field.getQueryFieldDef(this.exprSpace);
3261
+ if (fieldQueryDef) {
3262
+ if (this.canContain(fieldQueryDef)) {
3263
+ fields.push(fieldQueryDef);
3264
+ }
3265
+ else {
3266
+ this.log(`'${name}' not legal in ${this.segmentType}`);
3267
+ }
3268
+ }
3269
+ else {
3270
+ throw new Error(`'${name}' does not have a QueryFieldDef`);
3271
+ }
3272
+ }
3273
+ }
3274
+ this.isComplete();
3275
+ return fields;
3276
+ }
3277
+ getQuerySegment(rf) {
3278
+ const p = this.getPipeSegment(rf);
3279
+ if (model.isQuerySegment(p)) {
3280
+ return p;
3281
+ }
3282
+ throw new Error("TODO NOT POSSIBLE");
3283
+ }
3284
+ getPipeSegment(refineFrom) {
3285
+ if (this.segmentType == "index") {
3286
+ // TODO ... should make this go away
3287
+ throw new Error("INDEX FIELD PIPE SEGMENT MIS HANDLED");
3288
+ }
3289
+ if (refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.extendSource) {
3290
+ for (const xField of refineFrom.extendSource) {
3291
+ this.exprSpace.addFieldDef(xField);
3292
+ }
3293
+ }
3294
+ const segment = {
3295
+ type: this.segmentType,
3296
+ fields: this.queryFieldDefs(),
3297
+ };
3298
+ segment.fields = (0, field_utils_1.mergeFields)(refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.fields, segment.fields);
3299
+ if (refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.extendSource) {
3300
+ segment.extendSource = refineFrom.extendSource;
3301
+ }
3302
+ if (this.exprSpace.extendList.length > 0) {
3303
+ const newExtends = [];
3304
+ const extendedStruct = this.exprSpace.structDef();
3305
+ for (const extendName of this.exprSpace.extendList) {
3306
+ const extendEnt = extendedStruct.fields.find((f) => (0, field_utils_1.nameOf)(f) == extendName);
3307
+ if (extendEnt) {
3308
+ newExtends.push(extendEnt);
3309
+ }
3310
+ }
3311
+ segment.extendSource = (0, field_utils_1.mergeFields)(segment.extendSource, newExtends);
3312
+ }
3313
+ this.isComplete();
3314
+ return segment;
3315
+ }
3316
+ }
3317
+ exports.ResultSpace = ResultSpace;
3318
+ /**
3319
+ * Reduce and project queries use a "QuerySpace"
3320
+ */
3321
+ class ReduceFieldSpace extends ResultSpace {
3322
+ constructor() {
3323
+ super(...arguments);
3324
+ this.segmentType = "reduce";
3325
+ }
3326
+ }
3327
+ exports.ReduceFieldSpace = ReduceFieldSpace;
3328
+ class ProjectFieldSpace extends ResultSpace {
3329
+ constructor() {
3330
+ super(...arguments);
3331
+ this.segmentType = "project";
3332
+ }
3333
+ canContain(qd) {
3334
+ if (typeof qd !== "string") {
3335
+ if (model.isFilteredAliasedName(qd)) {
3336
+ return true;
3337
+ }
3338
+ if (qd.type === "turtle") {
3339
+ this.log("Cannot nest queries in project");
3340
+ return false;
3341
+ }
3342
+ if (model.expressionIsAggregate(qd.expressionType)) {
3343
+ this.log("Cannot add aggregate measures to project");
3344
+ return false;
3345
+ }
3346
+ }
3347
+ return true;
3348
+ }
3349
+ }
3350
+ exports.ProjectFieldSpace = ProjectFieldSpace;
3351
+ class SpaceEntry {
3352
+ }
3353
+ exports.SpaceEntry = SpaceEntry;
3354
+ class SpaceField extends SpaceEntry {
3355
+ constructor() {
3356
+ super(...arguments);
3357
+ this.refType = "field";
3358
+ }
3359
+ fieldTypeFromFieldDef(def) {
3360
+ const ref = { type: def.type };
3361
+ if (model.isFieldTypeDef(def) && def.expressionType) {
3362
+ ref.expressionType = def.expressionType;
3363
+ }
3364
+ return ref;
3365
+ }
3366
+ getQueryFieldDef(_fs) {
3367
+ return undefined;
3368
+ }
3369
+ fieldDef() {
3370
+ return undefined;
3371
+ }
3372
+ }
3373
+ exports.SpaceField = SpaceField;
3374
+ class StructSpaceField extends SpaceField {
3375
+ constructor(sourceDef) {
3376
+ super();
3377
+ this.sourceDef = sourceDef;
3378
+ }
3379
+ get fieldSpace() {
3380
+ if (!this.space) {
3381
+ this.space = new StaticSpace(this.sourceDef);
3382
+ }
3383
+ return this.space;
3384
+ }
3385
+ fieldDef() {
3386
+ return this.sourceDef;
3387
+ }
3388
+ type() {
3389
+ return { type: "struct" };
3390
+ }
3391
+ }
3392
+ exports.StructSpaceField = StructSpaceField;
3393
+ class QueryField extends SpaceField {
3394
+ constructor(inSpace) {
3395
+ super();
3396
+ this.inSpace = inSpace;
3397
+ }
3398
+ type() {
3399
+ return { type: "turtle" };
3400
+ }
3401
+ }
3402
+ exports.QueryField = QueryField;
3403
+ class QueryFieldStruct extends QueryField {
3404
+ constructor(fs, turtleDef) {
3405
+ super(fs);
3406
+ this.turtleDef = turtleDef;
3407
+ }
3408
+ rename(name) {
3409
+ this.turtleDef = {
3410
+ ...this.turtleDef,
3411
+ as: name,
3412
+ };
3413
+ }
3414
+ fieldDef() {
3415
+ return this.turtleDef;
3416
+ }
3417
+ getQueryFieldDef(_fs) {
3418
+ return this.fieldDef();
3419
+ }
3420
+ }
3421
+ exports.QueryFieldStruct = QueryFieldStruct;
3422
+ class ColumnSpaceField extends SpaceField {
3423
+ constructor(def) {
3424
+ super();
3425
+ this.def = def;
3426
+ }
3427
+ fieldDef() {
3428
+ return this.def;
3429
+ }
3430
+ type() {
3431
+ return this.fieldTypeFromFieldDef(this.def);
3432
+ }
3433
+ }
3434
+ exports.ColumnSpaceField = ColumnSpaceField;
3435
+ class SpaceParam extends SpaceEntry {
3436
+ constructor() {
3437
+ super(...arguments);
3438
+ this.refType = "parameter";
3439
+ }
3440
+ }
3441
+ exports.SpaceParam = SpaceParam;
3442
+ class DefinedParameter extends SpaceParam {
3443
+ constructor(paramDef) {
3444
+ super();
3445
+ this.paramDef = paramDef;
3446
+ }
3447
+ parameter() {
3448
+ return this.paramDef;
3449
+ }
3450
+ type() {
3451
+ return { type: this.paramDef.type };
3452
+ }
3453
+ }
3454
+ exports.DefinedParameter = DefinedParameter;
3455
+ /**
3456
+ * Based on how things are constructed, the starting field space
3457
+ * can either be another field space or an existing structdef.
3458
+ * Using a SpaceSeed allows a class to accept either one
3459
+ * and use either version at some future time.
3460
+ */
3461
+ class SpaceSeed {
3462
+ constructor(sourceSpec) {
3463
+ this.sourceSpec = sourceSpec;
3464
+ this.spaceSpec = sourceSpec;
3465
+ }
3466
+ get structDef() {
3467
+ if (isFieldSpace(this.spaceSpec)) {
3468
+ if (!this.asStruct) {
3469
+ this.asStruct = this.spaceSpec.structDef();
3470
+ }
3471
+ return this.asStruct;
3472
+ }
3473
+ return this.spaceSpec;
3474
+ }
3475
+ get fieldSpace() {
3476
+ if (isFieldSpace(this.spaceSpec)) {
3477
+ return this.spaceSpec;
3478
+ }
3479
+ if (!this.asFS) {
3480
+ this.asFS = new StaticSpace(this.spaceSpec);
3481
+ }
3482
+ return this.asFS;
3483
+ }
3484
+ }
3485
+ exports.SpaceSeed = SpaceSeed;
3486
+ function isFieldSpace(x) {
3487
+ return x.type == "fieldSpace";
3488
+ }
3489
+ class AbstractParameter extends SpaceParam {
3490
+ constructor(astParam) {
3491
+ super();
3492
+ this.astParam = astParam;
3493
+ }
3494
+ parameter() {
3495
+ return this.astParam.parameter();
3496
+ }
3497
+ type() {
3498
+ const type = this.astParam.type || "unknown";
3499
+ return { type };
3500
+ }
3501
+ }
3502
+ exports.AbstractParameter = AbstractParameter;
3503
+ class ExpressionFieldFromAst extends SpaceField {
3504
+ constructor(space, exprDef) {
3505
+ super();
3506
+ this.space = space;
3507
+ this.exprDef = exprDef;
3508
+ this.fieldName = exprDef.defineName;
3509
+ }
3510
+ get name() {
3511
+ return this.fieldName;
3512
+ }
3513
+ fieldDef() {
3514
+ const def = this.exprDef.fieldDef(this.space, this.name);
3515
+ this.defType = this.fieldTypeFromFieldDef(def);
3516
+ return def;
3517
+ }
3518
+ getQueryFieldDef(fs) {
3519
+ const def = this.exprDef.queryFieldDef(fs, this.name);
3520
+ this.defType = this.fieldTypeFromFieldDef(def);
3521
+ return def;
3522
+ }
3523
+ type() {
3524
+ if (this.defType) {
3525
+ return this.defType;
3526
+ }
3527
+ return this.fieldTypeFromFieldDef(this.fieldDef());
3528
+ }
3529
+ }
3530
+ exports.ExpressionFieldFromAst = ExpressionFieldFromAst;
3531
+ class QueryFieldAST extends QueryField {
3532
+ constructor(fs, turtle, name) {
3533
+ super(fs);
3534
+ this.turtle = turtle;
3535
+ this.name = name;
3536
+ }
3537
+ getQueryFieldDef(fs) {
3538
+ const def = this.turtle.getFieldDef(fs, this.nestParent);
3539
+ if (this.renameAs) {
3540
+ def.as = this.renameAs;
3541
+ }
3542
+ return def;
3543
+ }
3544
+ fieldDef() {
3545
+ const def = this.turtle.getFieldDef(this.inSpace, this.nestParent);
3546
+ if (this.renameAs) {
3547
+ def.as = this.renameAs;
3548
+ }
3549
+ return def;
3550
+ }
3551
+ }
3552
+ exports.QueryFieldAST = QueryFieldAST;
3553
+ class RenameSpaceField extends SpaceField {
3554
+ constructor(otherField, newName, location) {
3555
+ super();
3556
+ this.otherField = otherField;
3557
+ this.newName = newName;
3558
+ this.location = location;
3559
+ }
3560
+ fieldDef() {
3561
+ const renamedFieldRaw = this.otherField.fieldDef();
3562
+ if (renamedFieldRaw === undefined) {
3563
+ return undefined;
3564
+ }
3565
+ return {
3566
+ ...renamedFieldRaw,
3567
+ as: this.newName,
3568
+ location: this.location,
3569
+ };
3570
+ }
3571
+ type() {
3572
+ return this.otherField.type();
3573
+ }
3574
+ }
3575
+ exports.RenameSpaceField = RenameSpaceField;
3576
+ class JoinSpaceField extends StructSpaceField {
3577
+ constructor(intoFS, join) {
3578
+ super(join.structDef());
3579
+ this.intoFS = intoFS;
3580
+ this.join = join;
3581
+ }
3582
+ }
3583
+ exports.JoinSpaceField = JoinSpaceField;
3584
+ /**
3585
+ * Unlike a source, which is a refinement of a namespace, a query
3586
+ * is creating a new unrelated namespace. The query starts with a
3587
+ * source, which it might modify. This set of fields used to resolve
3588
+ * expressions in the query is called the "input space". There is a
3589
+ * specialized QuerySpace for each type of query operation.
3590
+ *
3591
+ * The query output is managed by an instance of ResultSpace.
3592
+ */
3593
+ class QuerySpace extends DynamicSpace {
3594
+ constructor(input, result) {
3595
+ const inputSpace = new SpaceSeed(input);
3596
+ super(inputSpace.structDef);
3597
+ this.result = result;
3598
+ this.extendList = [];
3599
+ }
3600
+ extendSource(extendField) {
3601
+ this.addField(extendField);
3602
+ if (extendField instanceof Join) {
3603
+ this.extendList.push(extendField.name.refString);
3604
+ }
3605
+ else {
3606
+ this.extendList.push(extendField.defineName);
3607
+ }
3608
+ }
3609
+ }
3610
+ exports.QuerySpace = QuerySpace;
3611
+ class ReferenceField extends SpaceField {
3612
+ constructor(fieldRef) {
3613
+ super();
3614
+ this.fieldRef = fieldRef;
3615
+ }
3616
+ getQueryFieldDef(fs) {
3617
+ // Lookup string and generate error if it isn't defined.
3618
+ const check = this.fieldRef.getField(fs);
3619
+ if (check.error) {
3620
+ this.fieldRef.log(check.error);
3621
+ }
3622
+ return this.fieldRef.refString;
3623
+ }
3624
+ type() {
3625
+ return { type: "unknown" };
3626
+ }
3627
+ }
3628
+ exports.ReferenceField = ReferenceField;
3629
+ class WildSpaceField extends SpaceField {
3630
+ constructor(wildText) {
3631
+ super();
3632
+ this.wildText = wildText;
3633
+ }
3634
+ type() {
3635
+ throw new Error("should never ask a wild field for its type");
3636
+ }
3637
+ getQueryFieldDef(_fs) {
3638
+ return this.wildText;
3639
+ }
3640
+ }
3641
+ exports.WildSpaceField = WildSpaceField;
3642
+ class IndexFieldSpace extends ResultSpace {
3643
+ constructor() {
3644
+ super(...arguments);
3645
+ this.segmentType = "index";
3646
+ this.fieldList = new Set();
3647
+ }
3648
+ addReference(ref) {
3649
+ if (ref.getField(this.exprSpace).found) {
3650
+ this.fieldList.add(ref.refString);
3651
+ }
3652
+ }
3653
+ addWild(wild) {
3654
+ this.fieldList.add(wild.refString);
3655
+ }
3656
+ getPipeSegment(refineIndex) {
3657
+ if (refineIndex && refineIndex.fields) {
3658
+ for (const exists of refineIndex.fields) {
3659
+ if (typeof exists == "string") {
3660
+ this.fieldList.add(exists);
3661
+ }
3662
+ }
3663
+ }
3664
+ this.isComplete();
3665
+ return {
3666
+ type: "index",
3667
+ fields: Array.from(this.fieldList.values()),
3668
+ };
3669
+ }
3670
+ }
3671
+ exports.IndexFieldSpace = IndexFieldSpace;
2858
3672
  //# sourceMappingURL=ast-main.js.map