@entity-access/entity-access 1.0.98 → 1.0.100
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/compiler/postgres/PostgreSqlMethodTransformer.d.ts.map +1 -1
- package/dist/compiler/postgres/PostgreSqlMethodTransformer.js +3 -0
- package/dist/compiler/postgres/PostgreSqlMethodTransformer.js.map +1 -1
- package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.d.ts.map +1 -1
- package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.js +3 -0
- package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.js.map +1 -1
- package/dist/drivers/postgres/PostgreSqlDriver.d.ts.map +1 -1
- package/dist/drivers/postgres/PostgreSqlDriver.js +4 -6
- package/dist/drivers/postgres/PostgreSqlDriver.js.map +1 -1
- package/dist/drivers/sql-server/SqlServerDriver.d.ts +1 -1
- package/dist/drivers/sql-server/SqlServerDriver.d.ts.map +1 -1
- package/dist/drivers/sql-server/SqlServerDriver.js +16 -5
- package/dist/drivers/sql-server/SqlServerDriver.js.map +1 -1
- package/dist/entity-query/EntityType.d.ts +5 -4
- package/dist/entity-query/EntityType.d.ts.map +1 -1
- package/dist/entity-query/EntityType.js.map +1 -1
- package/dist/model/EntityQuery.d.ts +2 -1
- package/dist/model/EntityQuery.d.ts.map +1 -1
- package/dist/model/EntityQuery.js +58 -4
- package/dist/model/EntityQuery.js.map +1 -1
- package/dist/model/IFilterWithParameter.d.ts +2 -0
- package/dist/model/IFilterWithParameter.d.ts.map +1 -1
- package/dist/query/ast/ExpressionToSql.d.ts +4 -2
- package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
- package/dist/query/ast/ExpressionToSql.js +114 -53
- package/dist/query/ast/ExpressionToSql.js.map +1 -1
- package/dist/sql/ISql.d.ts +1 -0
- package/dist/sql/ISql.d.ts.map +1 -1
- package/dist/tests/db-tests/tests/select-items-map.d.ts +3 -0
- package/dist/tests/db-tests/tests/select-items-map.d.ts.map +1 -0
- package/dist/tests/db-tests/tests/select-items-map.js +14 -0
- package/dist/tests/db-tests/tests/select-items-map.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/compiler/postgres/PostgreSqlMethodTransformer.ts +3 -0
- package/src/compiler/sql-server/SqlServerSqlMethodTransformer.ts +3 -0
- package/src/drivers/postgres/PostgreSqlDriver.ts +5 -6
- package/src/drivers/sql-server/SqlServerDriver.ts +15 -6
- package/src/entity-query/EntityType.ts +6 -1
- package/src/model/EntityQuery.ts +63 -5
- package/src/model/IFilterWithParameter.ts +3 -0
- package/src/query/ast/ExpressionToSql.ts +141 -68
- package/src/sql/ISql.ts +1 -0
- package/src/tests/db-tests/tests/select-items-map.ts +20 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import EntityAccessError from "../../common/EntityAccessError.js";
|
|
1
2
|
import { DisposableScope } from "../../common/usingAsync.js";
|
|
2
3
|
import QueryCompiler from "../../compiler/QueryCompiler.js";
|
|
3
|
-
import EntityType from "../../entity-query/EntityType.js";
|
|
4
|
+
import EntityType, { IEntityProperty } from "../../entity-query/EntityType.js";
|
|
4
5
|
import EntityQuery from "../../model/EntityQuery.js";
|
|
5
6
|
import { FilteredExpression, filteredSymbol } from "../../model/events/FilteredExpression.js";
|
|
6
7
|
import { NotSupportedError } from "../parser/NotSupportedError.js";
|
|
7
|
-
import { BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement } from "./Expressions.js";
|
|
8
|
+
import { ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement } from "./Expressions.js";
|
|
8
9
|
import { ITextQuery, QueryParameter, prepare, prepareJoin } from "./IStringTransformer.js";
|
|
9
10
|
import ParameterScope from "./ParameterScope.js";
|
|
10
11
|
import Visitor from "./Visitor.js";
|
|
@@ -166,74 +167,15 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
|
|
|
166
167
|
|
|
167
168
|
const body = e.arguments[0] as ExpressionType;
|
|
168
169
|
if (body.type === "ArrowFunctionExpression") {
|
|
169
|
-
|
|
170
|
-
const param1 = body.params[0];
|
|
171
|
-
const relatedModel = relation.relation.relatedEntity;
|
|
172
|
-
const relatedType = relatedModel.typeClass;
|
|
173
|
-
|
|
174
|
-
let select: SelectStatement;
|
|
175
|
-
|
|
176
|
-
if (this.source?.context) {
|
|
177
|
-
const query = FilteredExpression.isFiltered(e)
|
|
178
|
-
? this.source.context.query(relatedType)
|
|
179
|
-
: this.source.context.filteredQuery(relatedType, "include", false);
|
|
180
|
-
select = { ... (query as EntityQuery).selectStatement };
|
|
181
|
-
select.fields = [
|
|
182
|
-
NumberLiteral.create({ value: 1})
|
|
183
|
-
];
|
|
184
|
-
} else {
|
|
185
|
-
select = relatedModel.selectOneNumber();
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
param1.model = relatedModel;
|
|
189
|
-
this.scope.create({ parameter: param1, model: relatedModel, selectStatement: select });
|
|
190
|
-
this.scope.alias(param1, select.sourceParameter, select);
|
|
191
|
-
select.sourceParameter = param1;
|
|
192
|
-
select[filteredSymbol] = true;
|
|
193
|
-
const targetKey = MemberExpression.create({
|
|
194
|
-
target: parameter,
|
|
195
|
-
property: Identifier.create({
|
|
196
|
-
value: targetType.keys[0].columnName
|
|
197
|
-
})
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
const relatedKey = MemberExpression.create({
|
|
201
|
-
target: param1,
|
|
202
|
-
property: Identifier.create({
|
|
203
|
-
value: relation.relation.fkColumn.columnName
|
|
204
|
-
})
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const join = Expression.logicalAnd(
|
|
209
|
-
Expression.equal(targetKey, relatedKey),
|
|
210
|
-
body.body
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
let where = select.where;
|
|
214
|
-
|
|
215
|
-
if(where) {
|
|
216
|
-
where = BinaryExpression.create({
|
|
217
|
-
left: select.where,
|
|
218
|
-
operator: "AND",
|
|
219
|
-
right: join
|
|
220
|
-
});
|
|
221
|
-
} else {
|
|
222
|
-
where = join;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
select.where = where;
|
|
226
|
-
|
|
227
|
-
const exists = ExistsExpression.create({
|
|
228
|
-
target: select
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
const r = this.visit(exists);
|
|
232
|
-
this.scope.delete(param1);
|
|
233
|
-
this.scope.delete(select.sourceParameter);
|
|
234
|
-
return r;
|
|
170
|
+
return this.expandSome(body, relation, e, parameter, targetType);
|
|
235
171
|
}
|
|
172
|
+
}
|
|
173
|
+
if (/^(map|select)$/i.test(chain[1])) {
|
|
236
174
|
|
|
175
|
+
const body = e.arguments[0] as ExpressionType;
|
|
176
|
+
if (body.type === "ArrowFunctionExpression") {
|
|
177
|
+
return this.expandMap(body, relation, e, parameter, targetType);
|
|
178
|
+
}
|
|
237
179
|
}
|
|
238
180
|
}
|
|
239
181
|
}
|
|
@@ -250,6 +192,137 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
|
|
|
250
192
|
return prepare `${this.visit(e.callee)}(${args})`;
|
|
251
193
|
}
|
|
252
194
|
|
|
195
|
+
expandMap(body: ArrowFunctionExpression, relation: IEntityProperty, e: CallExpression, parameter: ParameterExpression, targetType: EntityType): ITextQuery {
|
|
196
|
+
throw new EntityAccessError(`Nested map/select not yet supported`);
|
|
197
|
+
// const param1 = body.params[0];
|
|
198
|
+
// const relatedModel = relation.relation.relatedEntity;
|
|
199
|
+
// const relatedType = relatedModel.typeClass;
|
|
200
|
+
|
|
201
|
+
// let select: SelectStatement;
|
|
202
|
+
|
|
203
|
+
// if (this.source?.context) {
|
|
204
|
+
// const query = FilteredExpression.isFiltered(e)
|
|
205
|
+
// ? this.source.context.query(relatedType)
|
|
206
|
+
// : this.source.context.filteredQuery(relatedType, "include", false);
|
|
207
|
+
// select = { ...(query as EntityQuery).selectStatement };
|
|
208
|
+
// } else {
|
|
209
|
+
// select = relatedModel.selectOneNumber();
|
|
210
|
+
// }
|
|
211
|
+
|
|
212
|
+
// param1.model = relatedModel;
|
|
213
|
+
// this.scope.create({ parameter: param1, model: relatedModel, selectStatement: select });
|
|
214
|
+
// this.scope.alias(param1, select.sourceParameter, select);
|
|
215
|
+
// select.sourceParameter = param1;
|
|
216
|
+
// select[filteredSymbol] = true;
|
|
217
|
+
// const targetKey = MemberExpression.create({
|
|
218
|
+
// target: parameter,
|
|
219
|
+
// property: Identifier.create({
|
|
220
|
+
// value: targetType.keys[0].columnName
|
|
221
|
+
// })
|
|
222
|
+
// });
|
|
223
|
+
|
|
224
|
+
// const relatedKey = MemberExpression.create({
|
|
225
|
+
// target: param1,
|
|
226
|
+
// property: Identifier.create({
|
|
227
|
+
// value: relation.relation.fkColumn.columnName
|
|
228
|
+
// })
|
|
229
|
+
// });
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
// const join = Expression.equal(targetKey, relatedKey);
|
|
233
|
+
|
|
234
|
+
// let where = select.where;
|
|
235
|
+
|
|
236
|
+
// if (where) {
|
|
237
|
+
// where = BinaryExpression.create({
|
|
238
|
+
// left: select.where,
|
|
239
|
+
// operator: "AND",
|
|
240
|
+
// right: join
|
|
241
|
+
// });
|
|
242
|
+
// } else {
|
|
243
|
+
// where = join;
|
|
244
|
+
// }
|
|
245
|
+
|
|
246
|
+
// select.where = where;
|
|
247
|
+
|
|
248
|
+
// const exists = ExistsExpression.create({
|
|
249
|
+
// target: select
|
|
250
|
+
// });
|
|
251
|
+
|
|
252
|
+
// const r = this.visit(exists);
|
|
253
|
+
// this.scope.delete(param1);
|
|
254
|
+
// this.scope.delete(select.sourceParameter);
|
|
255
|
+
// return r;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
expandSome(body: ArrowFunctionExpression, relation: IEntityProperty, e: CallExpression, parameter: ParameterExpression, targetType: EntityType) {
|
|
259
|
+
const param1 = body.params[0];
|
|
260
|
+
const relatedModel = relation.relation.relatedEntity;
|
|
261
|
+
const relatedType = relatedModel.typeClass;
|
|
262
|
+
|
|
263
|
+
let select: SelectStatement;
|
|
264
|
+
|
|
265
|
+
if (this.source?.context) {
|
|
266
|
+
const query = FilteredExpression.isFiltered(e)
|
|
267
|
+
? this.source.context.query(relatedType)
|
|
268
|
+
: this.source.context.filteredQuery(relatedType, "include", false);
|
|
269
|
+
select = { ...(query as EntityQuery).selectStatement };
|
|
270
|
+
select.fields = [
|
|
271
|
+
NumberLiteral.create({ value: 1 })
|
|
272
|
+
];
|
|
273
|
+
} else {
|
|
274
|
+
select = relatedModel.selectOneNumber();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
param1.model = relatedModel;
|
|
278
|
+
this.scope.create({ parameter: param1, model: relatedModel, selectStatement: select });
|
|
279
|
+
this.scope.alias(param1, select.sourceParameter, select);
|
|
280
|
+
select.sourceParameter = param1;
|
|
281
|
+
select[filteredSymbol] = true;
|
|
282
|
+
const targetKey = MemberExpression.create({
|
|
283
|
+
target: parameter,
|
|
284
|
+
property: Identifier.create({
|
|
285
|
+
value: targetType.keys[0].columnName
|
|
286
|
+
})
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
const relatedKey = MemberExpression.create({
|
|
290
|
+
target: param1,
|
|
291
|
+
property: Identifier.create({
|
|
292
|
+
value: relation.relation.fkColumn.columnName
|
|
293
|
+
})
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
const join = Expression.logicalAnd(
|
|
298
|
+
Expression.equal(targetKey, relatedKey),
|
|
299
|
+
body.body
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
let where = select.where;
|
|
303
|
+
|
|
304
|
+
if (where) {
|
|
305
|
+
where = BinaryExpression.create({
|
|
306
|
+
left: select.where,
|
|
307
|
+
operator: "AND",
|
|
308
|
+
right: join
|
|
309
|
+
});
|
|
310
|
+
} else {
|
|
311
|
+
where = join;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
select.where = where;
|
|
315
|
+
|
|
316
|
+
const exists = ExistsExpression.create({
|
|
317
|
+
target: select
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
const r = this.visit(exists);
|
|
321
|
+
this.scope.delete(param1);
|
|
322
|
+
this.scope.delete(select.sourceParameter);
|
|
323
|
+
return r;
|
|
324
|
+
}
|
|
325
|
+
|
|
253
326
|
visitIdentifier(e: Identifier): ITextQuery {
|
|
254
327
|
// need to visit parameters
|
|
255
328
|
return [e.value];
|
package/src/sql/ISql.ts
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
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 sum = await context.orderItems.all()
|
|
14
|
+
.where({}, (p) => (x) => x.order.orderID > 0)
|
|
15
|
+
.map({}, (p) => ({ amount }) => amount)
|
|
16
|
+
.sum();
|
|
17
|
+
|
|
18
|
+
assert.notEqual(0, sum);
|
|
19
|
+
|
|
20
|
+
}
|