@entity-access/entity-access 1.0.303 → 1.0.305
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/README.md +1 -1
- package/dist/compiler/ISqlHelpers.d.ts +2 -0
- package/dist/compiler/ISqlHelpers.d.ts.map +1 -1
- package/dist/compiler/ISqlHelpers.js +26 -0
- package/dist/compiler/ISqlHelpers.js.map +1 -1
- package/dist/compiler/QueryCompiler.js +1 -1
- package/dist/compiler/QueryCompiler.js.map +1 -1
- package/dist/compiler/postgres/PostgreSqlMethodTransformer.d.ts +1 -2
- package/dist/compiler/postgres/PostgreSqlMethodTransformer.d.ts.map +1 -1
- package/dist/compiler/postgres/PostgreSqlMethodTransformer.js +18 -16
- package/dist/compiler/postgres/PostgreSqlMethodTransformer.js.map +1 -1
- package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.d.ts +1 -2
- package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.d.ts.map +1 -1
- package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.js +18 -16
- package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.js.map +1 -1
- package/dist/drivers/sql-server/SqlServerQueryCompiler.js +1 -1
- package/dist/drivers/sql-server/SqlServerQueryCompiler.js.map +1 -1
- package/dist/query/ast/DebugStringVisitor.d.ts +2 -1
- package/dist/query/ast/DebugStringVisitor.d.ts.map +1 -1
- package/dist/query/ast/DebugStringVisitor.js +3 -0
- package/dist/query/ast/DebugStringVisitor.js.map +1 -1
- package/dist/query/ast/ExpressionToSql.d.ts +2 -1
- package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
- package/dist/query/ast/ExpressionToSql.js +20 -6
- package/dist/query/ast/ExpressionToSql.js.map +1 -1
- package/dist/query/ast/Expressions.d.ts +6 -1
- package/dist/query/ast/Expressions.d.ts.map +1 -1
- package/dist/query/ast/Expressions.js +6 -0
- package/dist/query/ast/Expressions.js.map +1 -1
- package/dist/query/ast/IStringTransformer.d.ts +1 -1
- package/dist/query/ast/IStringTransformer.d.ts.map +1 -1
- package/dist/query/ast/Visitor.d.ts +2 -1
- package/dist/query/ast/Visitor.d.ts.map +1 -1
- package/dist/query/ast/Visitor.js +5 -0
- package/dist/query/ast/Visitor.js.map +1 -1
- package/dist/query/parser/ArrowToExpression.d.ts +10 -2
- package/dist/query/parser/ArrowToExpression.d.ts.map +1 -1
- package/dist/query/parser/ArrowToExpression.js +68 -2
- package/dist/query/parser/ArrowToExpression.js.map +1 -1
- package/dist/tests/db-tests/tests/select-inverse-one-to-one.js +2 -2
- package/dist/tests/db-tests/tests/select-inverse-one-to-one.js.map +1 -1
- package/dist/tests/db-tests/tests/select-items-sum.d.ts.map +1 -1
- package/dist/tests/db-tests/tests/select-items-sum.js +5 -1
- package/dist/tests/db-tests/tests/select-items-sum.js.map +1 -1
- package/dist/tests/model/ShoppingContext.d.ts +1 -0
- package/dist/tests/model/ShoppingContext.d.ts.map +1 -1
- package/dist/tests/model/ShoppingContext.js +4 -0
- package/dist/tests/model/ShoppingContext.js.map +1 -1
- package/dist/tests/security/events/UserFileEvents.js +1 -1
- package/dist/tests/security/events/UserFileEvents.js.map +1 -1
- package/dist/tests/security/tests/test-events.js +1 -1
- package/dist/tests/security/tests/test-events.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/workflows/WorkflowStorage.js +3 -3
- package/dist/workflows/WorkflowStorage.js.map +1 -1
- package/package.json +1 -1
- package/src/compiler/ISqlHelpers.ts +33 -0
- package/src/compiler/QueryCompiler.ts +1 -1
- package/src/compiler/postgres/PostgreSqlMethodTransformer.ts +19 -17
- package/src/compiler/sql-server/SqlServerSqlMethodTransformer.ts +19 -17
- package/src/drivers/sql-server/SqlServerQueryCompiler.ts +1 -1
- package/src/query/ast/DebugStringVisitor.ts +5 -1
- package/src/query/ast/ExpressionToSql.ts +38 -20
- package/src/query/ast/Expressions.ts +7 -0
- package/src/query/ast/IStringTransformer.ts +1 -1
- package/src/query/ast/Visitor.ts +6 -1
- package/src/query/parser/ArrowToExpression.ts +81 -2
- package/src/tests/db-tests/tests/select-inverse-one-to-one.ts +2 -2
- package/src/tests/db-tests/tests/select-items-sum.ts +6 -1
- package/src/tests/model/ShoppingContext.ts +3 -0
- package/src/tests/security/events/UserFileEvents.ts +1 -1
- package/src/tests/security/tests/test-events.ts +1 -1
- package/src/workflows/WorkflowStorage.ts +3 -3
package/package.json
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import EntityAccessError from "../common/EntityAccessError.js";
|
|
2
|
+
import type { ISqlMethodTransformer } from "../query/ast/IStringTransformer.js";
|
|
1
3
|
import { ISql } from "../sql/ISql.js";
|
|
4
|
+
import type QueryCompiler from "./QueryCompiler.js";
|
|
2
5
|
|
|
3
6
|
type IFunction = ( ... a: any[]) => any;
|
|
4
7
|
|
|
@@ -28,3 +31,33 @@ export const flattenHelpers = (f, name, target = {}) => {
|
|
|
28
31
|
}
|
|
29
32
|
return target;
|
|
30
33
|
};
|
|
34
|
+
|
|
35
|
+
export const flattenMethods = (m: any): ISqlMethodTransformer => {
|
|
36
|
+
|
|
37
|
+
const map = new Map<string, (...a) => any>();
|
|
38
|
+
|
|
39
|
+
const fillMap = (target, root = "Sql") => {
|
|
40
|
+
for (const key in target) {
|
|
41
|
+
if (Object.prototype.hasOwnProperty.call(target, key)) {
|
|
42
|
+
const element = target[key];
|
|
43
|
+
if (typeof element === "object") {
|
|
44
|
+
fillMap(element, root + "." + key);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (typeof element === "function") {
|
|
48
|
+
map.set(root + "." + key, element);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
fillMap(m);
|
|
55
|
+
|
|
56
|
+
return (compiler: QueryCompiler, method: string, args: string[]) => {
|
|
57
|
+
const fx = map.get(method);
|
|
58
|
+
if (!fx) {
|
|
59
|
+
throw new EntityAccessError(`Invalid method ${method}`);
|
|
60
|
+
}
|
|
61
|
+
return fx.apply(compiler, args);
|
|
62
|
+
};
|
|
63
|
+
};
|
|
@@ -3,7 +3,7 @@ import { ISqlMethodTransformer, IStringTransformer, ITextQuery } from "../query/
|
|
|
3
3
|
import { Expression, ParameterExpression, SelectStatement } from "../query/ast/Expressions.js";
|
|
4
4
|
import SqlLiteral from "../query/ast/SqlLiteral.js";
|
|
5
5
|
import ArrowToExpression from "../query/parser/ArrowToExpression.js";
|
|
6
|
-
import PostgreSqlMethodTransformer from "./postgres/PostgreSqlMethodTransformer.js";
|
|
6
|
+
import { PostgreSqlMethodTransformer } from "./postgres/PostgreSqlMethodTransformer.js";
|
|
7
7
|
import EntityQuery from "../model/EntityQuery.js";
|
|
8
8
|
import { NamingConventions } from "./NamingConventions.js";
|
|
9
9
|
import RawQuery from "./RawQuery.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { joinAny, joinMap, prepareAny } from "../../query/ast/IStringTransformer.js";
|
|
2
2
|
import { NotSupportedError } from "../../query/parser/NotSupportedError.js";
|
|
3
3
|
import Sql from "../../sql/Sql.js";
|
|
4
|
-
import { ISqlHelpers } from "../ISqlHelpers.js";
|
|
4
|
+
import { ISqlHelpers, flattenMethods } from "../ISqlHelpers.js";
|
|
5
5
|
import type QueryCompiler from "../QueryCompiler.js";
|
|
6
6
|
|
|
7
7
|
const onlyAlphaNumeric = (x: string) => x.replace(/\W/g, "");
|
|
@@ -13,13 +13,13 @@ export const PostgreSqlHelper: ISqlHelpers = {
|
|
|
13
13
|
},
|
|
14
14
|
coll: {
|
|
15
15
|
sum(a) {
|
|
16
|
-
return prepareAny `
|
|
16
|
+
return prepareAny `SUM(${a})`;
|
|
17
17
|
},
|
|
18
18
|
count(a) {
|
|
19
19
|
return prepareAny `COUNT(${a})`;
|
|
20
20
|
},
|
|
21
21
|
avg(a) {
|
|
22
|
-
return prepareAny `
|
|
22
|
+
return prepareAny `AVG(${a})`;
|
|
23
23
|
},
|
|
24
24
|
},
|
|
25
25
|
math: {
|
|
@@ -204,18 +204,20 @@ export const PostgreSqlHelper: ISqlHelpers = {
|
|
|
204
204
|
}
|
|
205
205
|
};
|
|
206
206
|
|
|
207
|
-
export
|
|
207
|
+
export const PostgreSqlMethodTransformer = flattenMethods(PostgreSqlHelper);
|
|
208
208
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
209
|
+
// export default function PostgreSqlMethodTransformer(compiler: QueryCompiler, method: string, args: any[]): string {
|
|
210
|
+
|
|
211
|
+
// let start = PostgreSqlHelper;
|
|
212
|
+
// for (const iterator of callee) {
|
|
213
|
+
// start = start[iterator];
|
|
214
|
+
// if (!start) {
|
|
215
|
+
// return;
|
|
216
|
+
// }
|
|
217
|
+
// }
|
|
218
|
+
// if (!start) {
|
|
219
|
+
// return;
|
|
220
|
+
// }
|
|
221
|
+
// // eslint-disable-next-line @typescript-eslint/ban-types
|
|
222
|
+
// return (start as unknown as Function).apply(compiler, args);
|
|
223
|
+
// }
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import { joinAny, joinMap, prepareAny } from "../../query/ast/IStringTransformer.js";
|
|
3
3
|
import Sql from "../../sql/Sql.js";
|
|
4
|
-
import { ISqlHelpers } from "../ISqlHelpers.js";
|
|
4
|
+
import { ISqlHelpers, flattenMethods } from "../ISqlHelpers.js";
|
|
5
5
|
import type QueryCompiler from "../QueryCompiler.js";
|
|
6
6
|
|
|
7
7
|
export const SqlServerSqlHelper: ISqlHelpers = {
|
|
@@ -11,13 +11,13 @@ export const SqlServerSqlHelper: ISqlHelpers = {
|
|
|
11
11
|
},
|
|
12
12
|
coll: {
|
|
13
13
|
sum(a) {
|
|
14
|
-
return prepareAny `
|
|
14
|
+
return prepareAny `SUM(${a})`;
|
|
15
15
|
},
|
|
16
16
|
count(a) {
|
|
17
17
|
return prepareAny `COUNT(${a})`;
|
|
18
18
|
},
|
|
19
19
|
avg(a) {
|
|
20
|
-
return prepareAny `
|
|
20
|
+
return prepareAny `AVG(${a})`;
|
|
21
21
|
},
|
|
22
22
|
},
|
|
23
23
|
cast: {
|
|
@@ -207,18 +207,20 @@ export const SqlServerSqlHelper: ISqlHelpers = {
|
|
|
207
207
|
}
|
|
208
208
|
};
|
|
209
209
|
|
|
210
|
-
export
|
|
210
|
+
export const SqlServerSqlMethodTransformer = flattenMethods(SqlServerSqlHelper);
|
|
211
211
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
212
|
+
// export default function SqlServerSqlMethodTransformer(compiler: QueryCompiler, method: string, args: any[]): string {
|
|
213
|
+
|
|
214
|
+
// let start = SqlServerSqlHelper;
|
|
215
|
+
// for (const iterator of callee) {
|
|
216
|
+
// start = start[iterator];
|
|
217
|
+
// if (!start) {
|
|
218
|
+
// return;
|
|
219
|
+
// }
|
|
220
|
+
// }
|
|
221
|
+
// if (!start) {
|
|
222
|
+
// return;
|
|
223
|
+
// }
|
|
224
|
+
// // eslint-disable-next-line @typescript-eslint/ban-types
|
|
225
|
+
// return (start as unknown as Function).apply(compiler, args);
|
|
226
|
+
// }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NamingConventions } from "../../compiler/NamingConventions.js";
|
|
2
2
|
import QueryCompiler from "../../compiler/QueryCompiler.js";
|
|
3
|
-
import SqlServerSqlMethodTransformer from "../../compiler/sql-server/SqlServerSqlMethodTransformer.js";
|
|
3
|
+
import { SqlServerSqlMethodTransformer } from "../../compiler/sql-server/SqlServerSqlMethodTransformer.js";
|
|
4
4
|
import ArrowToExpression from "../../query/parser/ArrowToExpression.js";
|
|
5
5
|
import ExpressionToSqlServer from "./ExpressionToSqlServer.js";
|
|
6
6
|
import { SqlServerLiteral } from "./SqlServerLiteral.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ArrayExpression, ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, Identifier, InsertStatement, JoinExpression, MemberExpression, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateElement, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement } from "./Expressions.js";
|
|
1
|
+
import { ArrayExpression, ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, BracketExpression, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, Identifier, InsertStatement, JoinExpression, MemberExpression, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateElement, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement } from "./Expressions.js";
|
|
2
2
|
import Visitor from "./Visitor.js";
|
|
3
3
|
|
|
4
4
|
const isBinary = (type) => /^(BinaryExpression|CoalesceExpression)$/.test(type);
|
|
@@ -58,6 +58,10 @@ export default class DebugStringVisitor extends Visitor<string> {
|
|
|
58
58
|
return `"Constant:${e.value}"`;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
visitBracketExpression(e: BracketExpression): string {
|
|
62
|
+
return `(${this.visit(e.target)})`;
|
|
63
|
+
}
|
|
64
|
+
|
|
61
65
|
visitExpressionAs(e: ExpressionAs): string {
|
|
62
66
|
return `${this.visit(e.expression)} as ${this.visit(e.alias)}`;
|
|
63
67
|
}
|
|
@@ -4,7 +4,7 @@ import EntityType, { IEntityProperty } from "../../entity-query/EntityType.js";
|
|
|
4
4
|
import EntityQuery from "../../model/EntityQuery.js";
|
|
5
5
|
import { FilteredExpression, filteredSymbol } from "../../model/events/FilteredExpression.js";
|
|
6
6
|
import { NotSupportedError } from "../parser/NotSupportedError.js";
|
|
7
|
-
import { ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, UpsertStatement, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement, NotExpression, ArrayExpression } from "./Expressions.js";
|
|
7
|
+
import { ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, UpsertStatement, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement, NotExpression, ArrayExpression, BracketExpression } from "./Expressions.js";
|
|
8
8
|
import { ITextQuery, QueryParameter, joinMap, prepare, prepareJoin } from "./IStringTransformer.js";
|
|
9
9
|
import ParameterScope from "./ParameterScope.js";
|
|
10
10
|
import Visitor from "./Visitor.js";
|
|
@@ -12,7 +12,7 @@ import Visitor from "./Visitor.js";
|
|
|
12
12
|
interface IPropertyChain {
|
|
13
13
|
identifier?: Identifier,
|
|
14
14
|
parameter?: ParameterExpression,
|
|
15
|
-
chain: { member: string, args?: Expression[] }[]
|
|
15
|
+
chain: { member: string, args?: Expression[], isCollectionMethod?: boolean }[]
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
interface IPropertyMethods {
|
|
@@ -163,6 +163,10 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
|
|
|
163
163
|
return prepare `CONCAT(${args})`;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
+
visitBracketExpression(e: BracketExpression): ITextQuery {
|
|
167
|
+
return prepare `(${this.visit(e.target)})`;
|
|
168
|
+
}
|
|
169
|
+
|
|
166
170
|
visitCallExpression(e: CallExpression): ITextQuery {
|
|
167
171
|
// let us check if we are using any of array extension methods...
|
|
168
172
|
// .some alias .any
|
|
@@ -209,33 +213,45 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
|
|
|
209
213
|
if (/^(some|any)$/.test(lastMethod.member)) {
|
|
210
214
|
return this.visit(exists);
|
|
211
215
|
}
|
|
212
|
-
if (/^(map|select)$/.test(lastMethod.member)) {
|
|
216
|
+
if (/^(map|select)$/.test(lastMethod.member) || lastMethod.isCollectionMethod ) {
|
|
213
217
|
const select = this.expandCollection(relation, e, parameter, targetType);
|
|
214
218
|
const p1 = body.params[0];
|
|
215
219
|
this.scope.alias(select.sourceParameter, p1, select);
|
|
216
220
|
|
|
217
221
|
let where = select.where;
|
|
218
222
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
224
|
-
const filterArrow = last.args[0] as ArrowFunctionExpression;
|
|
225
|
-
this.scope.alias(select.sourceParameter, filterArrow.params[0], select);
|
|
226
|
-
if (where) {
|
|
227
|
-
where = Expression.logicalAnd(where, filterArrow.body);
|
|
228
|
-
} else {
|
|
229
|
-
where = filterArrow.body;
|
|
230
|
-
}
|
|
223
|
+
while(methods.length) {
|
|
224
|
+
const last = methods.pop();
|
|
225
|
+
if (last.member !== "filter") {
|
|
226
|
+
throw new EntityAccessError(`Invalid method ${last.member}`);
|
|
231
227
|
}
|
|
228
|
+
const filterArrow = last.args[0] as ArrowFunctionExpression;
|
|
229
|
+
this.scope.alias(select.sourceParameter, filterArrow.params[0], select);
|
|
230
|
+
if (where) {
|
|
231
|
+
where = Expression.logicalAnd(where, filterArrow.body);
|
|
232
|
+
} else {
|
|
233
|
+
where = filterArrow.body;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
232
236
|
|
|
233
237
|
if (body.body.type === "NewObjectExpression") {
|
|
234
238
|
const noe = body.body as NewObjectExpression;
|
|
235
239
|
const fields = noe.properties as ExpressionAs[];
|
|
236
240
|
return this.visit({ ... select, where, fields } as SelectStatement);
|
|
237
241
|
}
|
|
238
|
-
|
|
242
|
+
|
|
243
|
+
if (lastMethod.isCollectionMethod) {
|
|
244
|
+
return this.visit({ ... select, where, fields: [
|
|
245
|
+
CallExpression.create({
|
|
246
|
+
callee: Expression.identifier("Sql.coll." + lastMethod.member),
|
|
247
|
+
arguments: [body.body]
|
|
248
|
+
})
|
|
249
|
+
] } as SelectStatement);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return this.visit({ ... select, where, fields: [
|
|
253
|
+
body.body
|
|
254
|
+
] } as SelectStatement);
|
|
239
255
|
}
|
|
240
256
|
}
|
|
241
257
|
|
|
@@ -243,9 +259,11 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
|
|
|
243
259
|
}
|
|
244
260
|
}
|
|
245
261
|
|
|
246
|
-
|
|
262
|
+
const identifierValue = identifier?.value;
|
|
263
|
+
|
|
264
|
+
if (identifierValue?.startsWith("Sql")) {
|
|
247
265
|
const argList = e.arguments?.map((x) => this.visit(x)) ?? [];
|
|
248
|
-
const transformedCallee = this.compiler.sqlMethodTransformer(this.compiler,
|
|
266
|
+
const transformedCallee = this.compiler.sqlMethodTransformer(this.compiler, identifierValue, argList.map((al) => al.flat(2)) as any[]);
|
|
249
267
|
if (transformedCallee) {
|
|
250
268
|
return prepare `${transformedCallee}`;
|
|
251
269
|
}
|
|
@@ -854,7 +872,7 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
|
|
|
854
872
|
x = resolved;
|
|
855
873
|
}
|
|
856
874
|
|
|
857
|
-
const chain = [] as { member: string, args?: Expression[]}[];
|
|
875
|
+
const chain = [] as { member: string, args?: Expression[], isCollectionMethod?: boolean}[];
|
|
858
876
|
while (x) {
|
|
859
877
|
if (x.type === "ParameterExpression") {
|
|
860
878
|
return { parameter: x as ParameterExpression, chain };
|
|
@@ -865,7 +883,7 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
|
|
|
865
883
|
if (x.type === "MemberExpression") {
|
|
866
884
|
const me = x as MemberExpression;
|
|
867
885
|
x = me.target;
|
|
868
|
-
chain.unshift({ member: (me.property as Identifier).value });
|
|
886
|
+
chain.unshift({ member: (me.property as Identifier).value , isCollectionMethod: me.isCollectionMethod });
|
|
869
887
|
continue;
|
|
870
888
|
}
|
|
871
889
|
if (x.type === "CallExpression") {
|
|
@@ -214,6 +214,11 @@ export class CallExpression extends Expression {
|
|
|
214
214
|
arguments: Expression[];
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
export class BracketExpression extends Expression {
|
|
218
|
+
readonly type = "BracketExpression";
|
|
219
|
+
target: Expression;
|
|
220
|
+
}
|
|
221
|
+
|
|
217
222
|
export class ParameterExpression extends Expression {
|
|
218
223
|
readonly type = "ParameterExpression";
|
|
219
224
|
name: string;
|
|
@@ -239,6 +244,7 @@ export class MemberExpression extends Expression {
|
|
|
239
244
|
target: Expression;
|
|
240
245
|
property: Expression;
|
|
241
246
|
computed: boolean;
|
|
247
|
+
isCollectionMethod: boolean;
|
|
242
248
|
}
|
|
243
249
|
|
|
244
250
|
export class ArrowFunctionExpression extends Expression {
|
|
@@ -477,5 +483,6 @@ export type ExpressionType =
|
|
|
477
483
|
NotExits |
|
|
478
484
|
UnionAllStatement |
|
|
479
485
|
NotExpression |
|
|
486
|
+
BracketExpression |
|
|
480
487
|
TemplateElement
|
|
481
488
|
;
|
|
@@ -5,7 +5,7 @@ export type ITextQuery = ITextQueryFragment[];
|
|
|
5
5
|
|
|
6
6
|
export type IStringTransformer = (s: string) => string;
|
|
7
7
|
|
|
8
|
-
export type ISqlMethodTransformer = (compiler: QueryCompiler,
|
|
8
|
+
export type ISqlMethodTransformer = (compiler: QueryCompiler, method: string, args: string[]) => string;
|
|
9
9
|
|
|
10
10
|
export class QueryParameter {
|
|
11
11
|
|
package/src/query/ast/Visitor.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NotSupportedError } from "../parser/NotSupportedError.js";
|
|
2
|
-
import { ArrayExpression, ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, UpsertStatement, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateElement, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement, NotExpression } from "./Expressions.js";
|
|
2
|
+
import { ArrayExpression, ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, UpsertStatement, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateElement, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement, NotExpression, BracketExpression } from "./Expressions.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
export default abstract class Visitor<T = any> {
|
|
@@ -75,10 +75,15 @@ export default abstract class Visitor<T = any> {
|
|
|
75
75
|
return this.visitUpsertStatement(e);
|
|
76
76
|
case "NotExpression":
|
|
77
77
|
return this.visitNotExpression(e);
|
|
78
|
+
case "BracketExpression":
|
|
79
|
+
return this.visitBracketExpression(e);
|
|
78
80
|
}
|
|
79
81
|
const c: never = e;
|
|
80
82
|
throw new Error(`${e1.type} Not implemented`);
|
|
81
83
|
}
|
|
84
|
+
visitBracketExpression(e: BracketExpression): T {
|
|
85
|
+
throw new Error("Method not implemented.");
|
|
86
|
+
}
|
|
82
87
|
visitNotExpression(e: NotExpression): T {
|
|
83
88
|
throw new Error("Method not implemented.");
|
|
84
89
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseExpression } from "@babel/parser";
|
|
2
|
-
import { ArrowFunctionExpression, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, Expression, ExpressionAs, Identifier, MemberExpression, NewObjectExpression, NotExpression, NullExpression, NumberLiteral, ParameterExpression, StringLiteral, TemplateLiteral } from "../ast/Expressions.js";
|
|
2
|
+
import { ArrowFunctionExpression, BinaryExpression, BooleanLiteral, BracketExpression, CallExpression, CoalesceExpression, ConditionalExpression, Constant, Expression, ExpressionAs, Identifier, MemberExpression, NewObjectExpression, NotExpression, NullExpression, NumberLiteral, ParameterExpression, StringLiteral, TemplateLiteral } from "../ast/Expressions.js";
|
|
3
3
|
import { BabelVisitor } from "./BabelVisitor.js";
|
|
4
4
|
import * as bpe from "@babel/types";
|
|
5
5
|
import Restructure from "./Restructure.js";
|
|
@@ -217,10 +217,89 @@ export default class ArrowToExpression extends BabelVisitor<Expression> {
|
|
|
217
217
|
|
|
218
218
|
// change Sql.coll. with arrow functions to move it inside
|
|
219
219
|
|
|
220
|
-
|
|
220
|
+
const ce = CallExpression.create({
|
|
221
221
|
callee: callee ? this.visit(callee) : void 0,
|
|
222
222
|
arguments: args ? args.map((x) => this.visit(x)) : []
|
|
223
223
|
});
|
|
224
|
+
|
|
225
|
+
// for Sql.Coll. , change it to coalesce
|
|
226
|
+
// and move Sql.Coll. inside the first map..
|
|
227
|
+
return this.reAssignCollectionMethods(ce);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* We need to change Sql.coll.sum(p.orders.map((o) => o.total)
|
|
232
|
+
* to
|
|
233
|
+
* p.orders.sum((o) => o.total) ?? 0
|
|
234
|
+
* @param ce
|
|
235
|
+
* @returns
|
|
236
|
+
*/
|
|
237
|
+
reAssignCollectionMethods(ce: CallExpression) {
|
|
238
|
+
|
|
239
|
+
if (ce.callee.type !== "MemberExpression") {
|
|
240
|
+
return ce;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
let callee = ce.callee as MemberExpression;
|
|
244
|
+
const name = [];
|
|
245
|
+
while(callee) {
|
|
246
|
+
name.splice(0, 0, (callee.property as Identifier)?.value);
|
|
247
|
+
const target = callee.target;
|
|
248
|
+
switch(target.type) {
|
|
249
|
+
case "MemberExpression":
|
|
250
|
+
callee = target as MemberExpression;
|
|
251
|
+
continue;
|
|
252
|
+
case "Identifier":
|
|
253
|
+
name.splice(0, 0, (target as Identifier).value);
|
|
254
|
+
callee = null;
|
|
255
|
+
break;
|
|
256
|
+
default:
|
|
257
|
+
return ce;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (name[0] !== "Sql") {
|
|
262
|
+
return ce;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const method = name[2];
|
|
266
|
+
|
|
267
|
+
const reWrittenCe = CallExpression.create({
|
|
268
|
+
callee: Expression.identifier(name.join(".")),
|
|
269
|
+
arguments: ce.arguments
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
if (name[1] !== "coll") {
|
|
274
|
+
// rewrite...
|
|
275
|
+
return reWrittenCe;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const firstArg = ce.arguments[0] as CallExpression;
|
|
279
|
+
if (firstArg?.type !== "CallExpression") {
|
|
280
|
+
return reWrittenCe;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const mapCallee = firstArg.callee as MemberExpression;
|
|
284
|
+
if (mapCallee?.type !== "MemberExpression") {
|
|
285
|
+
return reWrittenCe;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const left = CallExpression.create({
|
|
289
|
+
callee: MemberExpression.create({
|
|
290
|
+
target: mapCallee.target,
|
|
291
|
+
property: Expression.identifier(method),
|
|
292
|
+
isCollectionMethod: true
|
|
293
|
+
}),
|
|
294
|
+
arguments: firstArg.arguments
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
// move it inside...
|
|
298
|
+
const rewritten = CoalesceExpression.create({
|
|
299
|
+
left: BracketExpression.create({ target: left }) ,
|
|
300
|
+
right: NumberLiteral.zero
|
|
301
|
+
});
|
|
302
|
+
return rewritten;
|
|
224
303
|
}
|
|
225
304
|
|
|
226
305
|
visitIdentifier({ name: value }: bpe.Identifier): Expression {
|
|
@@ -19,14 +19,14 @@ export default async function(this: TestConfig) {
|
|
|
19
19
|
|
|
20
20
|
// include inverse...
|
|
21
21
|
let all = await context.users.all()
|
|
22
|
-
.where({} , (p) => (x) => x.profile.photos.some((a) =>
|
|
22
|
+
.where({} , (p) => (x) => x.profile.photos.some((a) => a.photoID > 0) || x.profile.photos.some((a) => a.photoID > 0))
|
|
23
23
|
.include((x) => x.profile.photos)
|
|
24
24
|
.first();
|
|
25
25
|
|
|
26
26
|
assert.equal(null, all);
|
|
27
27
|
|
|
28
28
|
all = await context.users.all()
|
|
29
|
-
.where({} , (p) => (x) => x.files.some((a) =>
|
|
29
|
+
.where({} , (p) => (x) => x.files.some((a) => a.fileID > 0))
|
|
30
30
|
.include((x) => x.files)
|
|
31
31
|
.first();
|
|
32
32
|
|
|
@@ -31,12 +31,17 @@ export default async function(this: TestConfig) {
|
|
|
31
31
|
|
|
32
32
|
// assert.notEqual(null, report);
|
|
33
33
|
|
|
34
|
+
await context.orders.asQuery()
|
|
35
|
+
.update(void 0, (p) => (x) => ({
|
|
36
|
+
total: Sql.coll.sum(x.orderItems.map((o) => o.amount ))
|
|
37
|
+
}));
|
|
38
|
+
|
|
34
39
|
report = await context.users.all()
|
|
35
40
|
.where({}, (p) => (x) => x.orders.some((oi) => oi.customerID > 0))
|
|
36
41
|
.map({}, (p) => (x) => ({
|
|
37
42
|
total: Sql.coll.sum(x.orders
|
|
38
43
|
.filter((o) => o.status === "pending")
|
|
39
|
-
.map((o) =>
|
|
44
|
+
.map((o) => o.total))
|
|
40
45
|
})
|
|
41
46
|
)
|
|
42
47
|
.trace(console.log)
|
|
@@ -345,6 +345,9 @@ export class Order {
|
|
|
345
345
|
@Column({ dataType: "Char", length: 20, default: () => "pending"})
|
|
346
346
|
public status: string;
|
|
347
347
|
|
|
348
|
+
@Column({ dataType: "Decimal", default: () => 0})
|
|
349
|
+
public total: number;
|
|
350
|
+
|
|
348
351
|
public orderItems: OrderItem[];
|
|
349
352
|
|
|
350
353
|
public customer: User;
|
|
@@ -5,7 +5,7 @@ import { UserFile } from "../../model/UseFile.js";
|
|
|
5
5
|
export class UserFileEvents extends EntityEvents<UserFile> {
|
|
6
6
|
|
|
7
7
|
filter(query: IEntityQuery<UserFile>): IEntityQuery<UserFile> {
|
|
8
|
-
return query.where({}, (p) => (x) => x.photoUsers.some((p1) => p1.orders.some((o1) => true)));
|
|
8
|
+
return query.where({}, (p) => (x) => x.photoUsers.some((p1) => p1.orders.some((o1) => true === true)));
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
}
|
|
@@ -48,7 +48,7 @@ export default async function (this: TestConfig) {
|
|
|
48
48
|
await context.saveChanges();
|
|
49
49
|
assert.equal(true, p.afterInsertInvoked);
|
|
50
50
|
|
|
51
|
-
await context.userFiles.filtered("read").where({}, (_) => (x) => x.photoUsers.some((p1) => true))
|
|
51
|
+
await context.userFiles.filtered("read").where({}, (_) => (x) => x.photoUsers.some((p1) => true === true))
|
|
52
52
|
.include((x) => x.user.profile).toArray();
|
|
53
53
|
|
|
54
54
|
|
|
@@ -274,9 +274,9 @@ export default class WorkflowStorage {
|
|
|
274
274
|
Expression.assign(
|
|
275
275
|
Expression.identifier(lockTTLField),
|
|
276
276
|
CallExpression.create({
|
|
277
|
-
callee: Expression.
|
|
277
|
+
callee: Expression.identifier("Sql.date.addMinutes"),
|
|
278
278
|
arguments: [CallExpression.create({
|
|
279
|
-
callee: Expression.
|
|
279
|
+
callee: Expression.identifier("Sql.date.now")
|
|
280
280
|
}),
|
|
281
281
|
NumberLiteral.create({ value: 15 })
|
|
282
282
|
]
|
|
@@ -294,7 +294,7 @@ export default class WorkflowStorage {
|
|
|
294
294
|
Expression.lessOrEqual(
|
|
295
295
|
Expression.identifier(lockTTLField),
|
|
296
296
|
CallExpression.create({
|
|
297
|
-
callee: Expression.
|
|
297
|
+
callee: Expression.identifier("Sql.date.now")
|
|
298
298
|
})
|
|
299
299
|
)
|
|
300
300
|
))
|