@entity-access/entity-access 1.0.251 → 1.0.253
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/launch.json +2 -1
- package/dist/common/symbols/symbols.d.ts +1 -0
- package/dist/common/symbols/symbols.d.ts.map +1 -1
- package/dist/common/symbols/symbols.js +1 -0
- package/dist/common/symbols/symbols.js.map +1 -1
- package/dist/compiler/QueryCompiler.d.ts +3 -3
- package/dist/decorators/ForeignKey.d.ts +8 -7
- package/dist/decorators/ForeignKey.d.ts.map +1 -1
- package/dist/decorators/ForeignKey.js +43 -8
- package/dist/decorators/ForeignKey.js.map +1 -1
- package/dist/decorators/IColumn.d.ts +6 -3
- package/dist/decorators/IColumn.d.ts.map +1 -1
- package/dist/decorators/Relate.d.ts.map +1 -1
- package/dist/decorators/Relate.js +8 -6
- package/dist/decorators/Relate.js.map +1 -1
- package/dist/entity-query/EntityType.d.ts +5 -1
- package/dist/entity-query/EntityType.d.ts.map +1 -1
- package/dist/entity-query/EntityType.js +57 -25
- package/dist/entity-query/EntityType.js.map +1 -1
- package/dist/migrations/postgres/PostgresAutomaticMigrations.js +1 -1
- package/dist/migrations/postgres/PostgresAutomaticMigrations.js.map +1 -1
- package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js +1 -1
- package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js.map +1 -1
- package/dist/model/EntityModel.js +2 -2
- package/dist/model/EntityModel.js.map +1 -1
- package/dist/model/EntitySource.d.ts +6 -1
- package/dist/model/EntitySource.d.ts.map +1 -1
- package/dist/model/EntitySource.js.map +1 -1
- package/dist/model/SourceExpression.d.ts +1 -22
- package/dist/model/SourceExpression.d.ts.map +1 -1
- package/dist/model/SourceExpression.js +116 -98
- package/dist/model/SourceExpression.js.map +1 -1
- package/dist/model/changes/ChangeEntry.d.ts.map +1 -1
- package/dist/model/changes/ChangeEntry.js +62 -25
- package/dist/model/changes/ChangeEntry.js.map +1 -1
- package/dist/model/changes/ChangeSet.d.ts +2 -1
- package/dist/model/changes/ChangeSet.d.ts.map +1 -1
- package/dist/model/changes/ChangeSet.js +4 -3
- package/dist/model/changes/ChangeSet.js.map +1 -1
- package/dist/model/identity/IdentityMap.d.ts +23 -0
- package/dist/model/identity/IdentityMap.d.ts.map +1 -0
- package/dist/model/identity/IdentityMap.js +113 -0
- package/dist/model/identity/IdentityMap.js.map +1 -0
- package/dist/model/identity/RelationMapper.d.ts +2 -3
- package/dist/model/identity/RelationMapper.d.ts.map +1 -1
- package/dist/model/identity/RelationMapper.js +60 -27
- package/dist/model/identity/RelationMapper.js.map +1 -1
- package/dist/model/identity/SearchIndex.d.ts +17 -0
- package/dist/model/identity/SearchIndex.d.ts.map +1 -0
- package/dist/model/identity/SearchIndex.js +109 -0
- package/dist/model/identity/SearchIndex.js.map +1 -0
- package/dist/model/verification/VerificationSession.d.ts +1 -1
- package/dist/model/verification/VerificationSession.d.ts.map +1 -1
- package/dist/model/verification/VerificationSession.js +18 -16
- package/dist/model/verification/VerificationSession.js.map +1 -1
- package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
- package/dist/query/ast/ExpressionToSql.js +74 -52
- package/dist/query/ast/ExpressionToSql.js.map +1 -1
- package/dist/query/expander/QueryExpander.d.ts.map +1 -1
- package/dist/query/expander/QueryExpander.js +41 -10
- package/dist/query/expander/QueryExpander.js.map +1 -1
- package/dist/query/parser/ArrowToExpression.d.ts +16 -5
- package/dist/query/parser/ArrowToExpression.d.ts.map +1 -1
- package/dist/query/parser/ArrowToExpression.js +45 -25
- package/dist/query/parser/ArrowToExpression.js.map +1 -1
- package/dist/tests/db-tests/tests/multi-fk-tests.d.ts +3 -0
- package/dist/tests/db-tests/tests/multi-fk-tests.d.ts.map +1 -0
- package/dist/tests/db-tests/tests/multi-fk-tests.js +38 -0
- package/dist/tests/db-tests/tests/multi-fk-tests.js.map +1 -0
- package/dist/tests/expressions/left-joins/child-joins.js +7 -7
- package/dist/tests/model/ShoppingContext.d.ts +9 -0
- package/dist/tests/model/ShoppingContext.d.ts.map +1 -1
- package/dist/tests/model/ShoppingContext.js +34 -0
- package/dist/tests/model/ShoppingContext.js.map +1 -1
- package/dist/tests/security/tests/include-items.d.ts.map +1 -1
- package/dist/tests/security/tests/include-items.js +1 -0
- package/dist/tests/security/tests/include-items.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/common/symbols/symbols.ts +2 -1
- package/src/decorators/ForeignKey.ts +66 -28
- package/src/decorators/IColumn.ts +4 -3
- package/src/decorators/Relate.ts +8 -6
- package/src/entity-query/EntityType.ts +60 -26
- package/src/migrations/postgres/PostgresAutomaticMigrations.ts +1 -1
- package/src/migrations/sql-server/SqlServerAutomaticMigrations.ts +1 -1
- package/src/model/EntityModel.ts +2 -2
- package/src/model/EntitySource.ts +6 -1
- package/src/model/SourceExpression.ts +132 -132
- package/src/model/changes/ChangeEntry.ts +68 -25
- package/src/model/changes/ChangeSet.ts +4 -3
- package/src/model/identity/IdentityMap.ts +126 -0
- package/src/model/identity/RelationMapper.ts +71 -27
- package/src/model/identity/SearchIndex.ts +120 -0
- package/src/model/verification/VerificationSession.ts +19 -16
- package/src/query/ast/ExpressionToSql.ts +77 -61
- package/src/query/expander/QueryExpander.ts +52 -28
- package/src/query/parser/ArrowToExpression.ts +50 -26
- package/src/tests/db-tests/tests/multi-fk-tests.ts +46 -0
- package/src/tests/expressions/left-joins/child-joins.ts +7 -7
- package/src/tests/model/ShoppingContext.ts +32 -0
- package/src/tests/security/tests/include-items.ts +1 -0
|
@@ -82,8 +82,27 @@ export default class EntityType {
|
|
|
82
82
|
|
|
83
83
|
const existing = this.fieldMap.get(c.name);
|
|
84
84
|
if (existing) {
|
|
85
|
-
c.fkRelation = existing.fkRelation;
|
|
86
|
-
|
|
85
|
+
const fkRelation = c.fkRelation = existing.fkRelation;
|
|
86
|
+
if(fkRelation) {
|
|
87
|
+
fkRelation.fkMap = [{ fkColumn: c, relatedKeyColumn: null }];
|
|
88
|
+
// if(!fkRelation.fkMap?.length) {
|
|
89
|
+
// fkRelation.fkMap = [{ fkColumn: c, relatedKeyColumn: null}];
|
|
90
|
+
// } else {
|
|
91
|
+
// if(fkRelation.fkMap.length === 1) {
|
|
92
|
+
// fkRelation.fkMap[0].fkColumn = c;
|
|
93
|
+
// }
|
|
94
|
+
// }
|
|
95
|
+
}
|
|
96
|
+
// if (fkRelation?.fkMap) {
|
|
97
|
+
// if (!c.fkRelation.fkMap.length) {
|
|
98
|
+
// c.fkRelation.fkMap = [{ fkColumn: c, relatedKeyColumn: null }];
|
|
99
|
+
// } else {
|
|
100
|
+
// c.fkRelation.fkMap[0].fkColumn = c;
|
|
101
|
+
// }
|
|
102
|
+
// } else {
|
|
103
|
+
// c
|
|
104
|
+
// }
|
|
105
|
+
// c.fkRelation.fkColumn = c;
|
|
87
106
|
}
|
|
88
107
|
|
|
89
108
|
this.fieldMap.set(c.name, c);
|
|
@@ -109,26 +128,29 @@ export default class EntityType {
|
|
|
109
128
|
}
|
|
110
129
|
|
|
111
130
|
|
|
112
|
-
addRelation(relation: IEntityRelation, getInverseModel?: (t) => EntityType) {
|
|
131
|
+
addRelation(relation: IEntityRelation & { fkName?: string }, getInverseModel?: (t) => EntityType) {
|
|
113
132
|
// we will also set fk to the corresponding column
|
|
114
133
|
this.relations.push(relation);
|
|
115
134
|
this.relationMap.set(relation.name, relation);
|
|
116
135
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
fkColumn
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
fkColumn
|
|
136
|
+
if (!relation.fkMap) {
|
|
137
|
+
// find fk...
|
|
138
|
+
let fkColumn = this.fieldMap.get(relation.fkName);
|
|
139
|
+
if(!fkColumn) {
|
|
140
|
+
fkColumn = {
|
|
141
|
+
name: relation.fkName,
|
|
142
|
+
// columnName: relation.foreignKey,
|
|
143
|
+
fkRelation: relation,
|
|
144
|
+
dataType: "BigInt"
|
|
145
|
+
};
|
|
146
|
+
this.fieldMap.set(relation.fkName, fkColumn);
|
|
147
|
+
relation.fkMap = [ { fkColumn, relatedKeyColumn: null} ];
|
|
148
|
+
}
|
|
149
|
+
fkColumn.fkRelation = relation;
|
|
150
|
+
// relation.fkColumn = fkColumn;
|
|
151
|
+
if (fkColumn.dataType === "Double") {
|
|
152
|
+
fkColumn.dataType = "BigInt";
|
|
153
|
+
}
|
|
132
154
|
}
|
|
133
155
|
|
|
134
156
|
if (!getInverseModel) {
|
|
@@ -137,14 +159,23 @@ export default class EntityType {
|
|
|
137
159
|
|
|
138
160
|
// let us set inverse relations...
|
|
139
161
|
const relatedType = getInverseModel(relation.relatedTypeClass);
|
|
162
|
+
|
|
163
|
+
relation.fkMap[0].relatedKeyColumn ??= relatedType.keys[0];
|
|
164
|
+
relation.fkMap = [ ... relation.fkMap.map((x) => ({ ... x}))];
|
|
165
|
+
for (const iterator of relation.fkMap) {
|
|
166
|
+
iterator.fkColumn = this.getField(iterator.fkColumn.name);
|
|
167
|
+
// iterator.fkColumn.fkRelation = relation;
|
|
168
|
+
iterator.relatedKeyColumn = relatedType.getField(iterator.relatedKeyColumn.name);
|
|
169
|
+
iterator.relatedKeyColumn.entityType = relatedType;
|
|
170
|
+
}
|
|
171
|
+
|
|
140
172
|
relation.relatedEntity = relatedType;
|
|
141
173
|
const inverseRelation: IEntityRelation = {
|
|
142
174
|
name: relation.relatedName,
|
|
143
|
-
foreignKey: "",
|
|
144
175
|
relatedName: relation.name,
|
|
145
176
|
relatedTypeClass: this.typeClass,
|
|
146
|
-
|
|
147
|
-
|
|
177
|
+
doNotCreateIndex: true,
|
|
178
|
+
fkMap: null,
|
|
148
179
|
isInverseRelation: true,
|
|
149
180
|
isCollection: relation.singleInverseRelation ? false : true,
|
|
150
181
|
relatedRelation: relation,
|
|
@@ -158,11 +189,14 @@ export default class EntityType {
|
|
|
158
189
|
|
|
159
190
|
let { foreignKeyConstraint } = relation;
|
|
160
191
|
if(foreignKeyConstraint) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
192
|
+
if (relation.fkMap.length === 1) {
|
|
193
|
+
const { fkColumn } = relation.fkMap[0];
|
|
194
|
+
foreignKeyConstraint = { ... foreignKeyConstraint};
|
|
195
|
+
relation.foreignKeyConstraint = foreignKeyConstraint;
|
|
196
|
+
foreignKeyConstraint.name ||= `FK_${this.name}_${fkColumn.name}_${this.typeClass.name}_${relatedType.keys[0].name}`;
|
|
197
|
+
foreignKeyConstraint.column = fkColumn;
|
|
198
|
+
foreignKeyConstraint.refColumns = relatedType.keys;
|
|
199
|
+
}
|
|
166
200
|
}
|
|
167
201
|
return relation;
|
|
168
202
|
}
|
|
@@ -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?.
|
|
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?.
|
|
29
|
+
&& !x.fkRelation?.doNotCreateIndex));
|
|
30
30
|
|
|
31
31
|
}
|
|
32
32
|
|
package/src/model/EntityModel.ts
CHANGED
|
@@ -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,
|
|
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"
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
+
// }
|
|
@@ -168,14 +168,16 @@ export default class ChangeEntry<T = any> implements IChanges {
|
|
|
168
168
|
// this is tricky as we need to build inverse query...
|
|
169
169
|
const { relatedRelation } = relation;
|
|
170
170
|
const filter = [];
|
|
171
|
-
for (const
|
|
172
|
-
filter.push(`x.${relatedRelation.name}.${
|
|
171
|
+
for (const { fkColumn, relatedKeyColumn } of relatedRelation.fkMap) {
|
|
172
|
+
filter.push(`x.${relatedRelation.name}.${fkColumn.name} === p.${relatedKeyColumn.name}`);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
await context.model.register(relatedEntity.typeClass)
|
|
176
176
|
.where(this.entity, `(p) => (x) => ${filter.join(" && ")}` as any)
|
|
177
177
|
.toArray();
|
|
178
178
|
|
|
179
|
+
return;
|
|
180
|
+
|
|
179
181
|
}
|
|
180
182
|
|
|
181
183
|
if (this.entity[relation.name]) {
|
|
@@ -183,9 +185,13 @@ export default class ChangeEntry<T = any> implements IChanges {
|
|
|
183
185
|
}
|
|
184
186
|
|
|
185
187
|
|
|
186
|
-
|
|
188
|
+
// need to setup inverse key check
|
|
189
|
+
// const key = relatedEntity.keys[0];
|
|
187
190
|
const keys = {} as any;
|
|
188
|
-
keys[key.name] = this.entity[relation.fkColumn.name];
|
|
191
|
+
// keys[key.name] = this.entity[relation.fkColumn.name];
|
|
192
|
+
for (const { fkColumn, relatedKeyColumn } of relation.fkMap) {
|
|
193
|
+
keys[relatedKeyColumn.name] = this.entity[fkColumn.name];
|
|
194
|
+
}
|
|
189
195
|
this.entity[relation.name] = await context.model.register(relatedEntity.typeClass).loadByKeys(keys);
|
|
190
196
|
}
|
|
191
197
|
|
|
@@ -281,7 +287,7 @@ export default class ChangeEntry<T = any> implements IChanges {
|
|
|
281
287
|
}
|
|
282
288
|
|
|
283
289
|
// if related has key defined.. set it...
|
|
284
|
-
const rKey = iterator.relatedEntity.keys[0];
|
|
290
|
+
// const rKey = iterator.relatedEntity.keys[0];
|
|
285
291
|
|
|
286
292
|
// lets set the prototype...
|
|
287
293
|
const prototype = iterator.relatedTypeClass.prototype;
|
|
@@ -290,38 +296,75 @@ export default class ChangeEntry<T = any> implements IChanges {
|
|
|
290
296
|
}
|
|
291
297
|
const relatedChanges = this.changeSet.getEntry(related);
|
|
292
298
|
|
|
293
|
-
const
|
|
294
|
-
|
|
299
|
+
for (const { fkColumn, relatedKeyColumn } of iterator.fkMap) {
|
|
300
|
+
const keyValue = related[relatedKeyColumn.name];
|
|
301
|
+
if (keyValue === void 0) {
|
|
295
302
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
303
|
+
if(relatedChanges.dependents.has(this)) {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
relatedChanges.dependents.add(this);
|
|
300
307
|
|
|
301
|
-
|
|
308
|
+
this.order++;
|
|
302
309
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
310
|
+
for (const d of this.dependents) {
|
|
311
|
+
d.order++;
|
|
312
|
+
}
|
|
306
313
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
314
|
+
if (!fkColumn.columnName) {
|
|
315
|
+
throw new EntityAccessError(`Configuration error, fk not set for ${fkColumn.name}`);
|
|
316
|
+
}
|
|
317
|
+
relatedChanges.pending.push(() => {
|
|
318
|
+
this.entity[fkColumn.name] = related[relatedKeyColumn.name];
|
|
319
|
+
});
|
|
320
|
+
if (this.status !== "inserted") {
|
|
321
|
+
this.modified.set(iterator, { column: fkColumn, oldValue: void 0, newValue: void 0});
|
|
322
|
+
}
|
|
316
323
|
}
|
|
317
324
|
continue;
|
|
318
325
|
}
|
|
319
326
|
|
|
327
|
+
// const keyValue = related[rKey.name];
|
|
328
|
+
// if (keyValue === void 0) {
|
|
329
|
+
|
|
330
|
+
// if(relatedChanges.dependents.has(this)) {
|
|
331
|
+
// continue;
|
|
332
|
+
// }
|
|
333
|
+
// relatedChanges.dependents.add(this);
|
|
334
|
+
|
|
335
|
+
// this.order++;
|
|
336
|
+
|
|
337
|
+
// for (const d of this.dependents) {
|
|
338
|
+
// d.order++;
|
|
339
|
+
// }
|
|
340
|
+
|
|
341
|
+
// const fk = iterator;
|
|
342
|
+
// if (!fk.fkMap?.length) {
|
|
343
|
+
// throw new EntityAccessError(`Configuration error, fk not set for ${fk.name}`);
|
|
344
|
+
// }
|
|
345
|
+
// relatedChanges.pending.push(() => {
|
|
346
|
+
// for (const { fkColumn, relatedKeyColumn } of fk.fkMap) {
|
|
347
|
+
// this.entity[fkColumn.name] = related[relatedKeyColumn.name];
|
|
348
|
+
// }
|
|
349
|
+
// // this.entity[fk.fkColumn.name] = related[rKey.name];
|
|
350
|
+
// });
|
|
351
|
+
// if (this.status !== "inserted") {
|
|
352
|
+
// for (const { fkColumn } of fk.fkMap) {
|
|
353
|
+
// this.modified.set(iterator, { column: fkColumn, oldValue: void 0, newValue: void 0});
|
|
354
|
+
// }
|
|
355
|
+
// // this.modified.set(iterator, { column: iterator.fkColumn, oldValue: void 0, newValue: void 0});
|
|
356
|
+
// }
|
|
357
|
+
// continue;
|
|
358
|
+
// }
|
|
359
|
+
|
|
320
360
|
if(!relatedChanges.dependents.has(this)) {
|
|
321
361
|
relatedChanges.dependents.add(this);
|
|
322
362
|
this.order += relatedChanges.order;
|
|
323
363
|
}
|
|
324
|
-
|
|
364
|
+
for (const { fkColumn, relatedKeyColumn } of iterator.fkMap) {
|
|
365
|
+
this.entity[fkColumn.name] = related[relatedKeyColumn.name];
|
|
366
|
+
}
|
|
367
|
+
// this.entity[iterator.fkColumn.name] = related[rKey.name];
|
|
325
368
|
}
|
|
326
369
|
}
|
|
327
370
|
|
|
@@ -3,6 +3,7 @@ import EntityAccessError from "../../common/EntityAccessError.js";
|
|
|
3
3
|
import EventSet from "../../common/EventSet.js";
|
|
4
4
|
import SchemaRegistry from "../../decorators/SchemaRegistry.js";
|
|
5
5
|
import EntityContext from "../EntityContext.js";
|
|
6
|
+
import IdentityMap from "../identity/IdentityMap.js";
|
|
6
7
|
import IdentityService, { identityMapSymbol } from "../identity/IdentityService.js";
|
|
7
8
|
import ChangeEntry, { privateUpdateEntry, getContext } from "./ChangeEntry.js";
|
|
8
9
|
|
|
@@ -26,7 +27,7 @@ export default class ChangeSet {
|
|
|
26
27
|
/**
|
|
27
28
|
* This will provide new entity for same key
|
|
28
29
|
*/
|
|
29
|
-
private identityMap
|
|
30
|
+
private identityMap = new IdentityMap();
|
|
30
31
|
|
|
31
32
|
private nextId = 1;
|
|
32
33
|
|
|
@@ -70,7 +71,7 @@ export default class ChangeSet {
|
|
|
70
71
|
this.entryMap.delete(entry.entity);
|
|
71
72
|
return;
|
|
72
73
|
}
|
|
73
|
-
this.identityMap.set(jsonKey, entry.entity);
|
|
74
|
+
this.identityMap.set(jsonKey, entry.entity, entry.type);
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
|
|
@@ -101,7 +102,7 @@ export default class ChangeSet {
|
|
|
101
102
|
return entry.updateValues(original);
|
|
102
103
|
}
|
|
103
104
|
} else {
|
|
104
|
-
this.identityMap.set(jsonKey, entity);
|
|
105
|
+
this.identityMap.set(jsonKey, entity, type);
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
108
|
entry = new ChangeEntry({
|