@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.
Files changed (44) hide show
  1. package/dist/compiler/postgres/PostgreSqlMethodTransformer.d.ts.map +1 -1
  2. package/dist/compiler/postgres/PostgreSqlMethodTransformer.js +3 -0
  3. package/dist/compiler/postgres/PostgreSqlMethodTransformer.js.map +1 -1
  4. package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.d.ts.map +1 -1
  5. package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.js +3 -0
  6. package/dist/compiler/sql-server/SqlServerSqlMethodTransformer.js.map +1 -1
  7. package/dist/drivers/postgres/PostgreSqlDriver.d.ts.map +1 -1
  8. package/dist/drivers/postgres/PostgreSqlDriver.js +4 -6
  9. package/dist/drivers/postgres/PostgreSqlDriver.js.map +1 -1
  10. package/dist/drivers/sql-server/SqlServerDriver.d.ts +1 -1
  11. package/dist/drivers/sql-server/SqlServerDriver.d.ts.map +1 -1
  12. package/dist/drivers/sql-server/SqlServerDriver.js +16 -5
  13. package/dist/drivers/sql-server/SqlServerDriver.js.map +1 -1
  14. package/dist/entity-query/EntityType.d.ts +5 -4
  15. package/dist/entity-query/EntityType.d.ts.map +1 -1
  16. package/dist/entity-query/EntityType.js.map +1 -1
  17. package/dist/model/EntityQuery.d.ts +2 -1
  18. package/dist/model/EntityQuery.d.ts.map +1 -1
  19. package/dist/model/EntityQuery.js +58 -4
  20. package/dist/model/EntityQuery.js.map +1 -1
  21. package/dist/model/IFilterWithParameter.d.ts +2 -0
  22. package/dist/model/IFilterWithParameter.d.ts.map +1 -1
  23. package/dist/query/ast/ExpressionToSql.d.ts +4 -2
  24. package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
  25. package/dist/query/ast/ExpressionToSql.js +114 -53
  26. package/dist/query/ast/ExpressionToSql.js.map +1 -1
  27. package/dist/sql/ISql.d.ts +1 -0
  28. package/dist/sql/ISql.d.ts.map +1 -1
  29. package/dist/tests/db-tests/tests/select-items-map.d.ts +3 -0
  30. package/dist/tests/db-tests/tests/select-items-map.d.ts.map +1 -0
  31. package/dist/tests/db-tests/tests/select-items-map.js +14 -0
  32. package/dist/tests/db-tests/tests/select-items-map.js.map +1 -0
  33. package/dist/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +1 -1
  35. package/src/compiler/postgres/PostgreSqlMethodTransformer.ts +3 -0
  36. package/src/compiler/sql-server/SqlServerSqlMethodTransformer.ts +3 -0
  37. package/src/drivers/postgres/PostgreSqlDriver.ts +5 -6
  38. package/src/drivers/sql-server/SqlServerDriver.ts +15 -6
  39. package/src/entity-query/EntityType.ts +6 -1
  40. package/src/model/EntityQuery.ts +63 -5
  41. package/src/model/IFilterWithParameter.ts +3 -0
  42. package/src/query/ast/ExpressionToSql.ts +141 -68
  43. package/src/sql/ISql.ts +1 -0
  44. 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
@@ -3,6 +3,7 @@ import DateTime from "../types/DateTime.js";
3
3
  export interface ISql {
4
4
 
5
5
  in<T>(a: T, array: T[]): boolean;
6
+ sum<T>(a: number[]): number;
6
7
 
7
8
  cast: {
8
9
  asNumber(a: any): number;
@@ -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
+ }