@entity-access/entity-access 1.0.104 → 1.0.108
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common/cache/TimedCache.d.ts.map +1 -1
- package/dist/common/cache/TimedCache.js +2 -4
- package/dist/common/cache/TimedCache.js.map +1 -1
- package/dist/common/cloner.d.ts +4 -0
- package/dist/common/cloner.d.ts.map +1 -0
- package/dist/common/cloner.js +24 -0
- package/dist/common/cloner.js.map +1 -0
- package/dist/drivers/base/BaseDriver.d.ts +2 -0
- package/dist/drivers/base/BaseDriver.d.ts.map +1 -1
- package/dist/drivers/base/BaseDriver.js.map +1 -1
- package/dist/drivers/postgres/PostgreSqlDriver.d.ts +2 -0
- package/dist/drivers/postgres/PostgreSqlDriver.d.ts.map +1 -1
- package/dist/drivers/postgres/PostgreSqlDriver.js +49 -29
- package/dist/drivers/postgres/PostgreSqlDriver.js.map +1 -1
- package/dist/drivers/sql-server/SqlServerDriver.d.ts +1 -0
- package/dist/drivers/sql-server/SqlServerDriver.d.ts.map +1 -1
- package/dist/drivers/sql-server/SqlServerDriver.js +3 -0
- package/dist/drivers/sql-server/SqlServerDriver.js.map +1 -1
- package/dist/entity-query/EntityType.js +6 -6
- package/dist/entity-query/EntityType.js.map +1 -1
- package/dist/eternity/EternityContext.js +1 -1
- package/dist/eternity/EternityContext.js.map +1 -1
- package/dist/query/ast/DebugStringVisitor.js +1 -1
- package/dist/query/ast/DebugStringVisitor.js.map +1 -1
- package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
- package/dist/query/ast/ExpressionToSql.js +8 -5
- package/dist/query/ast/ExpressionToSql.js.map +1 -1
- package/dist/query/ast/ParameterScope.js +2 -2
- package/dist/query/ast/ParameterScope.js.map +1 -1
- package/dist/query/expander/QueryExpander.d.ts.map +1 -1
- package/dist/query/expander/QueryExpander.js +21 -9
- package/dist/query/expander/QueryExpander.js.map +1 -1
- package/dist/tests/db-tests/tests/select-inverse-one-to-one.js +4 -4
- package/dist/tests/db-tests/tests/select-inverse-one-to-one.js.map +1 -1
- package/dist/tests/db-tests/tests/select-items-map.d.ts.map +1 -1
- package/dist/tests/db-tests/tests/select-items-map.js +9 -0
- package/dist/tests/db-tests/tests/select-items-map.js.map +1 -1
- package/dist/tests/db-tests/tests/select-nested.d.ts +3 -0
- package/dist/tests/db-tests/tests/select-nested.d.ts.map +1 -0
- package/dist/tests/db-tests/tests/select-nested.js +16 -0
- package/dist/tests/db-tests/tests/select-nested.js.map +1 -0
- package/dist/tests/model/ShoppingContext.d.ts +3 -0
- package/dist/tests/model/ShoppingContext.d.ts.map +1 -1
- package/dist/tests/model/ShoppingContext.js +14 -2
- package/dist/tests/model/ShoppingContext.js.map +1 -1
- package/dist/tests/model/createContext.js +7 -1
- package/dist/tests/model/createContext.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/common/cache/TimedCache.ts +2 -4
- package/src/common/cloner.ts +23 -0
- package/src/drivers/base/BaseDriver.ts +2 -0
- package/src/drivers/postgres/PostgreSqlDriver.ts +52 -31
- package/src/drivers/sql-server/SqlServerDriver.ts +4 -0
- package/src/entity-query/EntityType.ts +6 -6
- package/src/eternity/EternityContext.ts +1 -1
- package/src/query/ast/DebugStringVisitor.ts +1 -1
- package/src/query/ast/ExpressionToSql.ts +9 -5
- package/src/query/ast/ParameterScope.ts +2 -2
- package/src/query/expander/QueryExpander.ts +27 -10
- package/src/tests/db-tests/tests/select-inverse-one-to-one.ts +4 -4
- package/src/tests/db-tests/tests/select-items-map.ts +12 -0
- package/src/tests/db-tests/tests/select-nested.ts +23 -0
- package/src/tests/model/ShoppingContext.ts +11 -0
- package/src/tests/model/createContext.ts +7 -1
|
@@ -33,7 +33,7 @@ function bindStep(context: EternityContext, store: WorkflowStorage, name: string
|
|
|
33
33
|
throw new Error(existing.error);
|
|
34
34
|
}
|
|
35
35
|
if (existing.state === "done") {
|
|
36
|
-
(this as any).currentTime = existing.updated;
|
|
36
|
+
(this as any).currentTime = DateTime.from(existing.updated);
|
|
37
37
|
return JSON.parse(existing.output);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -134,7 +134,7 @@ export default class DebugStringVisitor extends Visitor<string> {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
visitJoinExpression(e: JoinExpression): string {
|
|
137
|
-
return `\n${e.joinType} JOIN ${this.visit(e.source)}\n\t\tON ${this.visit(e.where)}\n`;
|
|
137
|
+
return `\n${e.joinType} JOIN ${this.visit(e.source)} ${this.visit(e.as)} \n\t\tON ${this.visit(e.where)}\n`;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
visitOrderByExpression(e: OrderByExpression): string {
|
|
@@ -172,11 +172,14 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
|
|
|
172
172
|
}
|
|
173
173
|
if (/^(map|select)$/.test(chain[1])) {
|
|
174
174
|
const select = this.expandCollection(relation, e, parameter, targetType);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
175
|
+
if (body.body.type === "NewObjectExpression") {
|
|
176
|
+
const noe = body.body as NewObjectExpression;
|
|
177
|
+
const p1 = body.params[0];
|
|
178
|
+
this.scope.alias(select.sourceParameter, p1, select);
|
|
179
|
+
const fields = noe.properties as ExpressionAs[];
|
|
180
|
+
return this.visit({ ... select, fields } as SelectStatement);
|
|
181
|
+
}
|
|
182
|
+
return this.visit({ ... select, fields: [body.body] } as SelectStatement);
|
|
180
183
|
}
|
|
181
184
|
}
|
|
182
185
|
|
|
@@ -350,6 +353,7 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
|
|
|
350
353
|
if (scope.isRuntimeParam) {
|
|
351
354
|
return [(p) => p[chain[0]]];
|
|
352
355
|
}
|
|
356
|
+
|
|
353
357
|
const name = this.scope.nameOf(parameter);
|
|
354
358
|
|
|
355
359
|
// need to change name as per naming convention here...
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { cloner } from "../../common/cloner.js";
|
|
1
2
|
import EntityType from "../../entity-query/EntityType.js";
|
|
2
3
|
import EntityContext from "../../model/EntityContext.js";
|
|
3
4
|
import EntityQuery from "../../model/EntityQuery.js";
|
|
5
|
+
import DebugStringVisitor from "../ast/DebugStringVisitor.js";
|
|
4
6
|
import { ArrowFunctionExpression, ExistsExpression, Expression, ExpressionType, JoinExpression, NumberLiteral, ParameterExpression, SelectStatement, TableSource } from "../ast/Expressions.js";
|
|
5
7
|
import ReplaceParameter from "../ast/ReplaceParameter.js";
|
|
6
8
|
import ArrowToExpression from "../parser/ArrowToExpression.js";
|
|
@@ -24,6 +26,8 @@ export class QueryExpander {
|
|
|
24
26
|
|
|
25
27
|
expandNode(parent: SelectStatement, model: EntityType, node: ExpressionType): [SelectStatement, EntityType] {
|
|
26
28
|
|
|
29
|
+
parent = cloner.clone(parent);
|
|
30
|
+
|
|
27
31
|
if (node.type === "ArrayExpression") {
|
|
28
32
|
for (const iterator of node.elements) {
|
|
29
33
|
this.expandNode(parent, model, iterator as ExpressionType);
|
|
@@ -83,7 +87,7 @@ export class QueryExpander {
|
|
|
83
87
|
// query = events.includeFilter(query, model, p.value) ?? query;
|
|
84
88
|
// }
|
|
85
89
|
// }
|
|
86
|
-
const select =
|
|
90
|
+
const select = cloner.clone((query as EntityQuery).selectStatement);
|
|
87
91
|
|
|
88
92
|
let where: Expression;
|
|
89
93
|
let joinWhere: Expression;
|
|
@@ -108,17 +112,18 @@ export class QueryExpander {
|
|
|
108
112
|
// ? Expression.logicalAnd(joinWhere, parent.where)
|
|
109
113
|
// : joinWhere;
|
|
110
114
|
|
|
111
|
-
|
|
115
|
+
const keyColumn = model.keys[0].columnName;
|
|
112
116
|
let columnName = fk.columnName;
|
|
113
117
|
// for inverse relation, we need to
|
|
114
118
|
// use primary key of current model
|
|
115
119
|
if (!relation.isCollection) {
|
|
116
|
-
columnName = model.keys[0].columnName;
|
|
117
|
-
keyColumn = select.model.keys[0].columnName;
|
|
120
|
+
columnName = select.model.keys[0].columnName;
|
|
118
121
|
}
|
|
119
122
|
|
|
120
123
|
|
|
121
124
|
const joins = (select.joins ??= []);
|
|
125
|
+
// const joinParameter = Expression.parameter(parent.sourceParameter.name);
|
|
126
|
+
// joinParameter.model = parent.sourceParameter.model;
|
|
122
127
|
joins.push(JoinExpression.create({
|
|
123
128
|
joinType: "LEFT",
|
|
124
129
|
source: parent.source as TableSource,
|
|
@@ -127,21 +132,33 @@ export class QueryExpander {
|
|
|
127
132
|
where: Expression.equal(
|
|
128
133
|
Expression.member(
|
|
129
134
|
parent.sourceParameter,
|
|
130
|
-
Expression.identifier(
|
|
135
|
+
Expression.identifier(keyColumn)
|
|
131
136
|
),
|
|
132
137
|
Expression.member(
|
|
133
138
|
select.sourceParameter,
|
|
134
|
-
Expression.identifier(
|
|
139
|
+
Expression.identifier(columnName)
|
|
135
140
|
)
|
|
136
141
|
)
|
|
137
142
|
}));
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
143
|
+
|
|
144
|
+
if (parent.where) {
|
|
145
|
+
select.where = select.where
|
|
146
|
+
? Expression.logicalAnd(select.where, parent.where)
|
|
147
|
+
: parent.where;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (parent.joins?.length) {
|
|
151
|
+
joins.push(... parent.joins);
|
|
152
|
+
}
|
|
153
|
+
// Object.setPrototypeOf(select, SelectStatement.prototype);
|
|
154
|
+
// const text = DebugStringVisitor.expressionToString(select);
|
|
155
|
+
// console.log(text);
|
|
141
156
|
(this.select.include ??= []).push(select);
|
|
142
157
|
return [select, relation.relatedEntity];
|
|
143
158
|
}
|
|
144
159
|
|
|
160
|
+
// if we can skip this if join already exists !!
|
|
161
|
+
|
|
145
162
|
joinWhere = Expression.equal(
|
|
146
163
|
Expression.member(
|
|
147
164
|
parent.sourceParameter,
|
|
@@ -153,7 +170,7 @@ export class QueryExpander {
|
|
|
153
170
|
)
|
|
154
171
|
);
|
|
155
172
|
|
|
156
|
-
parent = { ... parent, fields: [ NumberLiteral.one ]
|
|
173
|
+
parent = cloner.clone({ ... parent, fields: [ NumberLiteral.one ]});
|
|
157
174
|
|
|
158
175
|
parent.where = parent.where
|
|
159
176
|
? Expression.logicalAnd(parent.where, joinWhere)
|
|
@@ -10,11 +10,11 @@ export default async function(this: TestConfig) {
|
|
|
10
10
|
|
|
11
11
|
const context = await createContext(this.driver);
|
|
12
12
|
|
|
13
|
-
const count = await context.users.all()
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
// const count = await context.users.all()
|
|
14
|
+
// .where({} , (p) => (x) => x.profile.photos.some((a) => true) || x.profile.photos.some((a) => true))
|
|
15
|
+
// .count();
|
|
16
16
|
|
|
17
|
-
assert.equal(0, count);
|
|
17
|
+
// assert.equal(0, count);
|
|
18
18
|
|
|
19
19
|
// include inverse...
|
|
20
20
|
const all = await context.users.all()
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import assert from "assert";
|
|
2
2
|
import { TestConfig } from "../../TestConfig.js";
|
|
3
3
|
import { createContext, headPhoneCategory } from "../../model/createContext.js";
|
|
4
|
+
import Sql from "../../../sql/Sql.js";
|
|
4
5
|
|
|
5
6
|
export default async function(this: TestConfig) {
|
|
6
7
|
|
|
@@ -23,4 +24,15 @@ export default async function(this: TestConfig) {
|
|
|
23
24
|
.sum();
|
|
24
25
|
|
|
25
26
|
assert.notEqual(0, sum);
|
|
27
|
+
|
|
28
|
+
// const report = await context.users.all()
|
|
29
|
+
// .where({}, (p) => (x) => x.orders.some((oi) => oi.customerID > 0))
|
|
30
|
+
// .map({}, (p) => (x) => ({
|
|
31
|
+
// all: Sql.coll.count(x.orders),
|
|
32
|
+
// total: Sql.coll.sum(x.orders.map((o) => Sql.coll.sum(o.orderItems.map((oi) => oi.amount))))
|
|
33
|
+
// })
|
|
34
|
+
// )
|
|
35
|
+
// .first();
|
|
36
|
+
|
|
37
|
+
// assert.notEqual(null, report);
|
|
26
38
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import { TestConfig } from "../../TestConfig.js";
|
|
3
|
+
import { createContext, headPhoneCategory } from "../../model/createContext.js";
|
|
4
|
+
|
|
5
|
+
export default async function(this: TestConfig) {
|
|
6
|
+
|
|
7
|
+
if (!this.db) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const context = await createContext(this.driver);
|
|
12
|
+
|
|
13
|
+
const headphone = await context.products
|
|
14
|
+
.where({ name: "Jabber Head Phones" }, (p) => (x) => x.name === p.name)
|
|
15
|
+
.include((x) => x.categories.forEach((c) => c.category.children))
|
|
16
|
+
.first();
|
|
17
|
+
|
|
18
|
+
assert.notEqual(null, headphone);
|
|
19
|
+
|
|
20
|
+
const child = headphone.categories[0].category.children[0];
|
|
21
|
+
assert.notEqual(null, child);
|
|
22
|
+
|
|
23
|
+
}
|
|
@@ -66,10 +66,21 @@ export class Category {
|
|
|
66
66
|
@Column({ length: 200 })
|
|
67
67
|
public name: string;
|
|
68
68
|
|
|
69
|
+
@Column({ dataType: "Char", length: 200, nullable: true })
|
|
70
|
+
@RelateTo(Category, {
|
|
71
|
+
property: (c) => c.parent,
|
|
72
|
+
inverseProperty: (c) => c.children
|
|
73
|
+
})
|
|
74
|
+
public parentID: string;
|
|
75
|
+
|
|
69
76
|
public productCategories: ProductCategory[];
|
|
70
77
|
|
|
71
78
|
public users: UserCategory[];
|
|
72
79
|
|
|
80
|
+
public children: Category[];
|
|
81
|
+
|
|
82
|
+
public parent: Category;
|
|
83
|
+
|
|
73
84
|
}
|
|
74
85
|
|
|
75
86
|
@Table("UserProfile")
|
|
@@ -236,7 +236,13 @@ export const headPhoneCategory = "head-phones";
|
|
|
236
236
|
function addHeadPhones(context: ShoppingContext, now: Date, owner: User) {
|
|
237
237
|
const category = context.categories.add({
|
|
238
238
|
name: "Headphones",
|
|
239
|
-
categoryID: headPhoneCategory
|
|
239
|
+
categoryID: headPhoneCategory,
|
|
240
|
+
children: [
|
|
241
|
+
context.categories.add({
|
|
242
|
+
name: "Bluetooth",
|
|
243
|
+
categoryID: `${headPhoneCategory}/blue-tooth`
|
|
244
|
+
})
|
|
245
|
+
]
|
|
240
246
|
});
|
|
241
247
|
|
|
242
248
|
const startDate = new Date();
|