@entity-access/entity-access 1.0.252 → 1.0.254

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 (98) hide show
  1. package/.vscode/launch.json +2 -1
  2. package/dist/common/symbols/symbols.d.ts +1 -0
  3. package/dist/common/symbols/symbols.d.ts.map +1 -1
  4. package/dist/common/symbols/symbols.js +1 -0
  5. package/dist/common/symbols/symbols.js.map +1 -1
  6. package/dist/decorators/ForeignKey.d.ts +8 -7
  7. package/dist/decorators/ForeignKey.d.ts.map +1 -1
  8. package/dist/decorators/ForeignKey.js +43 -8
  9. package/dist/decorators/ForeignKey.js.map +1 -1
  10. package/dist/decorators/IColumn.d.ts +6 -3
  11. package/dist/decorators/IColumn.d.ts.map +1 -1
  12. package/dist/decorators/Relate.d.ts.map +1 -1
  13. package/dist/decorators/Relate.js +8 -6
  14. package/dist/decorators/Relate.js.map +1 -1
  15. package/dist/entity-query/EntityType.d.ts +5 -1
  16. package/dist/entity-query/EntityType.d.ts.map +1 -1
  17. package/dist/entity-query/EntityType.js +61 -25
  18. package/dist/entity-query/EntityType.js.map +1 -1
  19. package/dist/migrations/postgres/PostgresAutomaticMigrations.js +1 -1
  20. package/dist/migrations/postgres/PostgresAutomaticMigrations.js.map +1 -1
  21. package/dist/migrations/postgres/PostgresMigrations.d.ts +1 -1
  22. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js +1 -1
  23. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js.map +1 -1
  24. package/dist/migrations/sql-server/SqlServerMigrations.d.ts +1 -1
  25. package/dist/model/EntityModel.js +2 -2
  26. package/dist/model/EntityModel.js.map +1 -1
  27. package/dist/model/EntitySource.d.ts +6 -1
  28. package/dist/model/EntitySource.d.ts.map +1 -1
  29. package/dist/model/EntitySource.js.map +1 -1
  30. package/dist/model/SourceExpression.d.ts +1 -22
  31. package/dist/model/SourceExpression.d.ts.map +1 -1
  32. package/dist/model/SourceExpression.js +116 -98
  33. package/dist/model/SourceExpression.js.map +1 -1
  34. package/dist/model/changes/ChangeEntry.d.ts.map +1 -1
  35. package/dist/model/changes/ChangeEntry.js +62 -25
  36. package/dist/model/changes/ChangeEntry.js.map +1 -1
  37. package/dist/model/changes/ChangeSet.d.ts +2 -1
  38. package/dist/model/changes/ChangeSet.d.ts.map +1 -1
  39. package/dist/model/changes/ChangeSet.js +4 -3
  40. package/dist/model/changes/ChangeSet.js.map +1 -1
  41. package/dist/model/identity/IdentityMap.d.ts +23 -0
  42. package/dist/model/identity/IdentityMap.d.ts.map +1 -0
  43. package/dist/model/identity/IdentityMap.js +113 -0
  44. package/dist/model/identity/IdentityMap.js.map +1 -0
  45. package/dist/model/identity/RelationMapper.d.ts +2 -3
  46. package/dist/model/identity/RelationMapper.d.ts.map +1 -1
  47. package/dist/model/identity/RelationMapper.js +60 -27
  48. package/dist/model/identity/RelationMapper.js.map +1 -1
  49. package/dist/model/identity/SearchIndex.d.ts +17 -0
  50. package/dist/model/identity/SearchIndex.d.ts.map +1 -0
  51. package/dist/model/identity/SearchIndex.js +109 -0
  52. package/dist/model/identity/SearchIndex.js.map +1 -0
  53. package/dist/model/verification/VerificationSession.d.ts +1 -1
  54. package/dist/model/verification/VerificationSession.d.ts.map +1 -1
  55. package/dist/model/verification/VerificationSession.js +18 -16
  56. package/dist/model/verification/VerificationSession.js.map +1 -1
  57. package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
  58. package/dist/query/ast/ExpressionToSql.js +74 -52
  59. package/dist/query/ast/ExpressionToSql.js.map +1 -1
  60. package/dist/query/expander/QueryExpander.d.ts.map +1 -1
  61. package/dist/query/expander/QueryExpander.js +41 -10
  62. package/dist/query/expander/QueryExpander.js.map +1 -1
  63. package/dist/tests/db-tests/tests/multi-fk-tests.d.ts +3 -0
  64. package/dist/tests/db-tests/tests/multi-fk-tests.d.ts.map +1 -0
  65. package/dist/tests/db-tests/tests/multi-fk-tests.js +38 -0
  66. package/dist/tests/db-tests/tests/multi-fk-tests.js.map +1 -0
  67. package/dist/tests/expressions/left-joins/child-joins.js +7 -7
  68. package/dist/tests/model/ShoppingContext.d.ts +9 -0
  69. package/dist/tests/model/ShoppingContext.d.ts.map +1 -1
  70. package/dist/tests/model/ShoppingContext.js +34 -0
  71. package/dist/tests/model/ShoppingContext.js.map +1 -1
  72. package/dist/tests/security/tests/include-items.d.ts.map +1 -1
  73. package/dist/tests/security/tests/include-items.js +1 -0
  74. package/dist/tests/security/tests/include-items.js.map +1 -1
  75. package/dist/tsconfig.tsbuildinfo +1 -1
  76. package/package.json +1 -1
  77. package/src/common/symbols/symbols.ts +2 -1
  78. package/src/decorators/ForeignKey.ts +66 -28
  79. package/src/decorators/IColumn.ts +4 -3
  80. package/src/decorators/Relate.ts +8 -6
  81. package/src/entity-query/EntityType.ts +64 -26
  82. package/src/migrations/postgres/PostgresAutomaticMigrations.ts +1 -1
  83. package/src/migrations/sql-server/SqlServerAutomaticMigrations.ts +1 -1
  84. package/src/model/EntityModel.ts +2 -2
  85. package/src/model/EntitySource.ts +6 -1
  86. package/src/model/SourceExpression.ts +132 -132
  87. package/src/model/changes/ChangeEntry.ts +68 -25
  88. package/src/model/changes/ChangeSet.ts +4 -3
  89. package/src/model/identity/IdentityMap.ts +126 -0
  90. package/src/model/identity/RelationMapper.ts +71 -27
  91. package/src/model/identity/SearchIndex.ts +120 -0
  92. package/src/model/verification/VerificationSession.ts +19 -16
  93. package/src/query/ast/ExpressionToSql.ts +77 -61
  94. package/src/query/expander/QueryExpander.ts +52 -28
  95. package/src/tests/db-tests/tests/multi-fk-tests.ts +46 -0
  96. package/src/tests/expressions/left-joins/child-joins.ts +7 -7
  97. package/src/tests/model/ShoppingContext.ts +32 -0
  98. package/src/tests/security/tests/include-items.ts +1 -0
@@ -3,6 +3,7 @@ import { IClassOf } from "./IClassOf.js";
3
3
  import { IForeignKeyConstraint } from "./IForeignKeyConstraint.js";
4
4
  import { ISqlType } from "./ISqlType.js";
5
5
 
6
+ export type FKType = { fkColumn: IColumn, relatedKeyColumn: IColumn };
6
7
 
7
8
  export interface IColumn {
8
9
  name?: string;
@@ -87,13 +88,13 @@ export interface IEntityRelation {
87
88
  singleInverseRelation?
88
89
 
89
90
 
90
- foreignKey: string;
91
+ // foreignKey: string;
91
92
 
92
93
  relatedTypeClass: IClassOf<any>;
93
94
 
94
95
  relatedTypeClassFactory?: () => IClassOf<any>;
95
96
 
96
- fkColumn?: IColumn;
97
+ fkMap: FKType[];
97
98
 
98
99
 
99
100
  relatedName: string;
@@ -105,7 +106,7 @@ export interface IEntityRelation {
105
106
 
106
107
  relatedRelation?: IEntityRelation;
107
108
 
108
- dotNotCreateIndex?: boolean;
109
+ doNotCreateIndex?: boolean;
109
110
 
110
111
  foreignKeyConstraint?: IForeignKeyConstraint;
111
112
 
@@ -51,7 +51,7 @@ export function RelateTo(c, p?): any {
51
51
 
52
52
  const { property, inverseKey: invKey, inverseProperty, dotNotCreateIndex, foreignKeyConstraint } = p;
53
53
 
54
- return (target: any, foreignKey: string): any => {
54
+ return (target: any, fkName: string): any => {
55
55
 
56
56
  const cn = target.constructor ?? target;
57
57
  const entityType = SchemaRegistry.model(cn);
@@ -61,13 +61,14 @@ export function RelateTo(c, p?): any {
61
61
  entityType.addRelation({
62
62
  type: entityType,
63
63
  name,
64
- foreignKey,
64
+ fkName,
65
+ fkMap: null,
65
66
  relatedTypeClass: c,
66
67
  relatedTypeClassFactory: p.type,
67
68
  relatedName: NameParser.parseMember(inverseProperty),
68
69
  relatedKey: invKey ? NameParser.parseMember(invKey) : void 0,
69
70
  foreignKeyConstraint,
70
- dotNotCreateIndex
71
+ doNotCreateIndex: dotNotCreateIndex
71
72
  });
72
73
 
73
74
  };
@@ -87,7 +88,7 @@ export function RelateToOne(c, p?): any {
87
88
 
88
89
  const { property, inverseKey: invKey, inverseProperty, dotNotCreateIndex } = p;
89
90
 
90
- return (target: any, foreignKey: string): any => {
91
+ return (target: any, fkName: string): any => {
91
92
 
92
93
  const cn = target.constructor ?? target;
93
94
  const entityType = SchemaRegistry.model(cn);
@@ -97,12 +98,13 @@ export function RelateToOne(c, p?): any {
97
98
  entityType.addRelation({
98
99
  type: entityType,
99
100
  name,
100
- foreignKey,
101
+ fkName,
102
+ fkMap:null,
101
103
  relatedTypeClass: c,
102
104
  relatedTypeClassFactory: p.type,
103
105
  relatedName: NameParser.parseMember(inverseProperty),
104
106
  relatedKey: invKey ? NameParser.parseMember(invKey) : void 0,
105
- dotNotCreateIndex,
107
+ doNotCreateIndex: dotNotCreateIndex,
106
108
  singleInverseRelation: true
107
109
  });
108
110
 
@@ -7,6 +7,7 @@ import { Expression, ExpressionAs, NumberLiteral, ParameterExpression, SelectSta
7
7
  import InstanceCache from "../common/cache/InstanceCache.js";
8
8
  import { IIndex } from "../decorators/IIndex.js";
9
9
  import { IStringTransformer } from "../query/ast/IStringTransformer.js";
10
+ import { EntityAccessError } from "../index.js";
10
11
 
11
12
  export const addOrCreateColumnSymbol = Symbol("addOrCreateColumn");
12
13
  export const addColumnSymbol = Symbol("addOrCreateColumn");
@@ -82,8 +83,27 @@ export default class EntityType {
82
83
 
83
84
  const existing = this.fieldMap.get(c.name);
84
85
  if (existing) {
85
- c.fkRelation = existing.fkRelation;
86
- c.fkRelation.fkColumn = c;
86
+ const fkRelation = c.fkRelation = existing.fkRelation;
87
+ if(fkRelation) {
88
+ fkRelation.fkMap = [{ fkColumn: c, relatedKeyColumn: null }];
89
+ // if(!fkRelation.fkMap?.length) {
90
+ // fkRelation.fkMap = [{ fkColumn: c, relatedKeyColumn: null}];
91
+ // } else {
92
+ // if(fkRelation.fkMap.length === 1) {
93
+ // fkRelation.fkMap[0].fkColumn = c;
94
+ // }
95
+ // }
96
+ }
97
+ // if (fkRelation?.fkMap) {
98
+ // if (!c.fkRelation.fkMap.length) {
99
+ // c.fkRelation.fkMap = [{ fkColumn: c, relatedKeyColumn: null }];
100
+ // } else {
101
+ // c.fkRelation.fkMap[0].fkColumn = c;
102
+ // }
103
+ // } else {
104
+ // c
105
+ // }
106
+ // c.fkRelation.fkColumn = c;
87
107
  }
88
108
 
89
109
  this.fieldMap.set(c.name, c);
@@ -109,26 +129,29 @@ export default class EntityType {
109
129
  }
110
130
 
111
131
 
112
- addRelation(relation: IEntityRelation, getInverseModel?: (t) => EntityType) {
132
+ addRelation(relation: IEntityRelation & { fkName?: string }, getInverseModel?: (t) => EntityType) {
113
133
  // we will also set fk to the corresponding column
114
134
  this.relations.push(relation);
115
135
  this.relationMap.set(relation.name, relation);
116
136
 
117
- // find fk...
118
- let fkColumn = this.fieldMap.get(relation.foreignKey);
119
- if(!fkColumn) {
120
- fkColumn = {
121
- name: relation.foreignKey,
122
- // columnName: relation.foreignKey,
123
- fkRelation: relation,
124
- dataType: "BigInt"
125
- };
126
- this.fieldMap.set(relation.foreignKey, fkColumn);
127
- }
128
- fkColumn.fkRelation = relation;
129
- relation.fkColumn = fkColumn;
130
- if (fkColumn.dataType === "Double") {
131
- fkColumn.dataType = "BigInt";
137
+ if (!relation.fkMap) {
138
+ // find fk...
139
+ let fkColumn = this.fieldMap.get(relation.fkName);
140
+ if(!fkColumn) {
141
+ fkColumn = {
142
+ name: relation.fkName,
143
+ // columnName: relation.foreignKey,
144
+ fkRelation: relation,
145
+ dataType: "BigInt"
146
+ };
147
+ this.fieldMap.set(relation.fkName, fkColumn);
148
+ relation.fkMap = [ { fkColumn, relatedKeyColumn: null} ];
149
+ }
150
+ fkColumn.fkRelation = relation;
151
+ // relation.fkColumn = fkColumn;
152
+ if (fkColumn.dataType === "Double") {
153
+ fkColumn.dataType = "BigInt";
154
+ }
132
155
  }
133
156
 
134
157
  if (!getInverseModel) {
@@ -137,14 +160,26 @@ export default class EntityType {
137
160
 
138
161
  // let us set inverse relations...
139
162
  const relatedType = getInverseModel(relation.relatedTypeClass);
163
+
164
+ relation.fkMap[0].relatedKeyColumn ??= relatedType.keys[0];
165
+ relation.fkMap = [ ... relation.fkMap.map((x) => ({ ... x}))];
166
+ for (const iterator of relation.fkMap) {
167
+ iterator.fkColumn = this.getField(iterator.fkColumn.name);
168
+ // iterator.fkColumn.fkRelation = relation;
169
+ if (!iterator.relatedKeyColumn) {
170
+ throw new EntityAccessError(`Not key set for ${iterator.fkColumn.name} with keys in ${relatedType.name} `);
171
+ }
172
+ iterator.relatedKeyColumn = relatedType.getField(iterator.relatedKeyColumn.name);
173
+ iterator.relatedKeyColumn.entityType = relatedType;
174
+ }
175
+
140
176
  relation.relatedEntity = relatedType;
141
177
  const inverseRelation: IEntityRelation = {
142
178
  name: relation.relatedName,
143
- foreignKey: "",
144
179
  relatedName: relation.name,
145
180
  relatedTypeClass: this.typeClass,
146
- dotNotCreateIndex: true,
147
- fkColumn,
181
+ doNotCreateIndex: true,
182
+ fkMap: null,
148
183
  isInverseRelation: true,
149
184
  isCollection: relation.singleInverseRelation ? false : true,
150
185
  relatedRelation: relation,
@@ -158,11 +193,14 @@ export default class EntityType {
158
193
 
159
194
  let { foreignKeyConstraint } = relation;
160
195
  if(foreignKeyConstraint) {
161
- foreignKeyConstraint = { ... foreignKeyConstraint};
162
- relation.foreignKeyConstraint = foreignKeyConstraint;
163
- foreignKeyConstraint.name ||= `FK_${this.name}_${fkColumn.name}_${this.typeClass.name}_${relatedType.keys[0].name}`;
164
- foreignKeyConstraint.column = fkColumn;
165
- foreignKeyConstraint.refColumns = relatedType.keys;
196
+ if (relation.fkMap.length === 1) {
197
+ const { fkColumn } = relation.fkMap[0];
198
+ foreignKeyConstraint = { ... foreignKeyConstraint};
199
+ relation.foreignKeyConstraint = foreignKeyConstraint;
200
+ foreignKeyConstraint.name ||= `FK_${this.name}_${fkColumn.name}_${this.typeClass.name}_${relatedType.keys[0].name}`;
201
+ foreignKeyConstraint.column = fkColumn;
202
+ foreignKeyConstraint.refColumns = relatedType.keys;
203
+ }
166
204
  }
167
205
  return relation;
168
206
  }
@@ -26,7 +26,7 @@ export default class PostgresAutomaticMigrations extends PostgresMigrations {
26
26
  await this.createIndexes(context, type, nonKeyColumns.filter((x) =>
27
27
  x.fkRelation
28
28
  && (!x.key || type.keys.indexOf(x) !== 0)
29
- && !x.fkRelation?.dotNotCreateIndex));
29
+ && !x.fkRelation?.doNotCreateIndex));
30
30
 
31
31
  }
32
32
 
@@ -26,7 +26,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
26
26
  await this.createIndexes(context, type, nonKeyColumns.filter((x) =>
27
27
  x.fkRelation
28
28
  && (!x.key || type.keys.indexOf(x) !== 0)
29
- && !x.fkRelation?.dotNotCreateIndex));
29
+ && !x.fkRelation?.doNotCreateIndex));
30
30
 
31
31
  }
32
32
 
@@ -23,8 +23,8 @@ const getOrCreateModel = (map: Map<any, EntityType>, type: IClassOf<any>, naming
23
23
  ? column.columnName
24
24
  : (namingConvention
25
25
  ? namingConvention(column.columnName) : column.columnName);
26
- t.addColumn(column);
27
26
  column.entityType = t;
27
+ t.addColumn(column);
28
28
  }
29
29
  t.indexes.push(... original.indexes.map((i) => ({ ... i, columns: [ ... i.columns.map((c) => ( { ... c}))] })));
30
30
  // sort keys...
@@ -38,7 +38,7 @@ const getOrCreateModel = (map: Map<any, EntityType>, type: IClassOf<any>, naming
38
38
  if (iterator.isInverseRelation) {
39
39
  continue;
40
40
  }
41
- const relation: IEntityRelation = { ... iterator, fkColumn: void 0, relatedEntity: void 0,type: t };
41
+ const relation: IEntityRelation = { ... iterator, relatedEntity: void 0,type: t };
42
42
  t.addRelation(relation, (tc) => getOrCreateModel(map, tc, namingConvention));
43
43
  }
44
44
  return t;
@@ -28,8 +28,13 @@ export type ISaveDirect<T> = {
28
28
  keys: Partial<T>,
29
29
  changes: Partial<T>,
30
30
  // select?: Partial<T>,
31
- mode: "selectOrInsert" | "insert",
31
+ mode: "selectOrInsert",
32
32
  updateAfterSelect?: never
33
+ } | {
34
+ keys?: never,
35
+ mode: "insert",
36
+ changes: Partial<T>,
37
+ updateAfterSelect?: never,
33
38
  } | {
34
39
  keys?: Partial<T>,
35
40
  changes: Partial<T>,
@@ -1,132 +1,132 @@
1
- import { modelSymbol } from "../common/symbols/symbols.js";
2
- import EntityType from "../entity-query/EntityType.js";
3
- import { Expression, JoinExpression, ParameterExpression, SelectStatement } from "../query/ast/Expressions.js";
4
- import { ITextQueryFragment, QueryParameter } from "../query/ast/IStringTransformer.js";
5
- import EntityContext from "./EntityContext.js";
6
-
7
- const sourceSymbol = Symbol("source");
8
-
9
- export class SourceExpression {
10
-
11
- public static create(p: Partial<SourceExpression>) {
12
- return new SourceExpression(p);
13
- }
14
-
15
- alias: ParameterExpression;
16
- parameter?: ParameterExpression;
17
- context: EntityContext;
18
- model?: EntityType;
19
- include?: EntityType[];
20
- select: SelectStatement;
21
- parent?: SourceExpression;
22
-
23
- private map: Map<string,SourceExpression>;
24
- private paramMap: Map<string, SourceExpression>;
25
-
26
- private constructor(p: Partial<SourceExpression>) {
27
- Object.setPrototypeOf(p, SourceExpression.prototype);
28
- const r = p as SourceExpression;
29
- if (r.parent) {
30
- r.map = r.parent.map;
31
- r.paramMap = r.parent.paramMap;
32
- } else {
33
- r.paramMap = new Map();
34
- r.map = new Map();
35
- }
36
- return r;
37
- }
38
-
39
- copy() {
40
- const r = { ... this } as SourceExpression;
41
- Object.setPrototypeOf(r, Object.getPrototypeOf(this));
42
- r.map = new Map(this.map.entries());
43
- r.paramMap = new Map(this.paramMap.entries());
44
- r.select = Expression.clone(this.select);
45
- return r;
46
- }
47
-
48
- addJoin(property: string) {
49
- const { select } = this;
50
- select.joins ??= [];
51
-
52
- const relation = this.model.getProperty(property);
53
- const model = this.context.model.register(relation.relation.relatedTypeClass)[modelSymbol];
54
-
55
- for (const iterator of select.joins) {
56
- if (model === iterator.model) {
57
- return iterator[sourceSymbol] as SourceExpression;
58
- }
59
- }
60
- const column = relation.relation.fkColumn;
61
- const parameter = ParameterExpression.create({ name: this.parameter + "." + property, model });
62
- const source = this.addSource(model, parameter);
63
- const join = JoinExpression.create({
64
- as: source.alias,
65
- joinType: column.nullable ? "LEFT" : "INNER",
66
- model,
67
- source: Expression.identifier(model.name),
68
- where: Expression.logicalAnd(
69
- Expression.member(
70
- this.alias,
71
- column.columnName),
72
- Expression.member(
73
- source.alias,
74
- model.keys[0].columnName)
75
- )
76
- });
77
- select.joins.push(join);
78
- join[sourceSymbol] = source;
79
- return source;
80
- }
81
-
82
- addSource(model: EntityType, parameter: ParameterExpression) {
83
-
84
- const { context } = this;
85
- const source = SourceExpression.create({
86
- model,
87
- parameter,
88
- context,
89
- parent: this
90
- });
91
-
92
- source.map = this.map;
93
- source.paramMap = this.paramMap;
94
-
95
- let id = 0;
96
- let alias: string;
97
- do {
98
- alias = model.name[0] + id++;
99
- const exists = this.map.get(alias);
100
- if (exists === null || exists === void 0) {
101
- break;
102
- }
103
- }while (true);
104
- source.alias = ParameterExpression.create({ name: alias, model });
105
- this.map.set(alias, source);
106
- this.paramMap.set(parameter.name, source);
107
- return source;
108
- }
109
-
110
- flatten(chain: string[]): ITextQueryFragment {
111
- const [start, ... others ] = chain;
112
- if (start === this.parameter.name) {
113
- return this.prepareNames(others);
114
- }
115
- const mapped = this.paramMap.get(start);
116
- if (mapped) {
117
- return mapped.prepareNames(others);
118
- }
119
- throw new Error("Not found");
120
- }
121
-
122
- prepareNames([property , ... others]: string[]): ITextQueryFragment {
123
- const p = this.model.getProperty(property);
124
- if (others.length === 0) {
125
- return `${ QueryParameter.create(() => this.alias.name)}.${p.field.columnName}`;
126
- }
127
-
128
- // this must be a navigation...
129
- const source = this.addJoin(property);
130
- return source.prepareNames(others);
131
- }
132
- }
1
+ // import { modelSymbol } from "../common/symbols/symbols.js";
2
+ // import EntityType from "../entity-query/EntityType.js";
3
+ // import { Expression, JoinExpression, ParameterExpression, SelectStatement } from "../query/ast/Expressions.js";
4
+ // import { ITextQueryFragment, QueryParameter } from "../query/ast/IStringTransformer.js";
5
+ // import EntityContext from "./EntityContext.js";
6
+
7
+ // const sourceSymbol = Symbol("source");
8
+
9
+ // export class SourceExpression {
10
+
11
+ // public static create(p: Partial<SourceExpression>) {
12
+ // return new SourceExpression(p);
13
+ // }
14
+
15
+ // alias: ParameterExpression;
16
+ // parameter?: ParameterExpression;
17
+ // context: EntityContext;
18
+ // model?: EntityType;
19
+ // include?: EntityType[];
20
+ // select: SelectStatement;
21
+ // parent?: SourceExpression;
22
+
23
+ // private map: Map<string,SourceExpression>;
24
+ // private paramMap: Map<string, SourceExpression>;
25
+
26
+ // private constructor(p: Partial<SourceExpression>) {
27
+ // Object.setPrototypeOf(p, SourceExpression.prototype);
28
+ // const r = p as SourceExpression;
29
+ // if (r.parent) {
30
+ // r.map = r.parent.map;
31
+ // r.paramMap = r.parent.paramMap;
32
+ // } else {
33
+ // r.paramMap = new Map();
34
+ // r.map = new Map();
35
+ // }
36
+ // return r;
37
+ // }
38
+
39
+ // copy() {
40
+ // const r = { ... this } as SourceExpression;
41
+ // Object.setPrototypeOf(r, Object.getPrototypeOf(this));
42
+ // r.map = new Map(this.map.entries());
43
+ // r.paramMap = new Map(this.paramMap.entries());
44
+ // r.select = Expression.clone(this.select);
45
+ // return r;
46
+ // }
47
+
48
+ // addJoin(property: string) {
49
+ // const { select } = this;
50
+ // select.joins ??= [];
51
+
52
+ // const relation = this.model.getProperty(property);
53
+ // const model = this.context.model.register(relation.relation.relatedTypeClass)[modelSymbol];
54
+
55
+ // for (const iterator of select.joins) {
56
+ // if (model === iterator.model) {
57
+ // return iterator[sourceSymbol] as SourceExpression;
58
+ // }
59
+ // }
60
+ // const column = relation.relation.fkColumn;
61
+ // const parameter = ParameterExpression.create({ name: this.parameter + "." + property, model });
62
+ // const source = this.addSource(model, parameter);
63
+ // const join = JoinExpression.create({
64
+ // as: source.alias,
65
+ // joinType: column.nullable ? "LEFT" : "INNER",
66
+ // model,
67
+ // source: Expression.identifier(model.name),
68
+ // where: Expression.logicalAnd(
69
+ // Expression.member(
70
+ // this.alias,
71
+ // column.columnName),
72
+ // Expression.member(
73
+ // source.alias,
74
+ // model.keys[0].columnName)
75
+ // )
76
+ // });
77
+ // select.joins.push(join);
78
+ // join[sourceSymbol] = source;
79
+ // return source;
80
+ // }
81
+
82
+ // addSource(model: EntityType, parameter: ParameterExpression) {
83
+
84
+ // const { context } = this;
85
+ // const source = SourceExpression.create({
86
+ // model,
87
+ // parameter,
88
+ // context,
89
+ // parent: this
90
+ // });
91
+
92
+ // source.map = this.map;
93
+ // source.paramMap = this.paramMap;
94
+
95
+ // let id = 0;
96
+ // let alias: string;
97
+ // do {
98
+ // alias = model.name[0] + id++;
99
+ // const exists = this.map.get(alias);
100
+ // if (exists === null || exists === void 0) {
101
+ // break;
102
+ // }
103
+ // }while (true);
104
+ // source.alias = ParameterExpression.create({ name: alias, model });
105
+ // this.map.set(alias, source);
106
+ // this.paramMap.set(parameter.name, source);
107
+ // return source;
108
+ // }
109
+
110
+ // flatten(chain: string[]): ITextQueryFragment {
111
+ // const [start, ... others ] = chain;
112
+ // if (start === this.parameter.name) {
113
+ // return this.prepareNames(others);
114
+ // }
115
+ // const mapped = this.paramMap.get(start);
116
+ // if (mapped) {
117
+ // return mapped.prepareNames(others);
118
+ // }
119
+ // throw new Error("Not found");
120
+ // }
121
+
122
+ // prepareNames([property , ... others]: string[]): ITextQueryFragment {
123
+ // const p = this.model.getProperty(property);
124
+ // if (others.length === 0) {
125
+ // return `${ QueryParameter.create(() => this.alias.name)}.${p.field.columnName}`;
126
+ // }
127
+
128
+ // // this must be a navigation...
129
+ // const source = this.addJoin(property);
130
+ // return source.prepareNames(others);
131
+ // }
132
+ // }