@entity-access/entity-access 1.0.166 → 1.0.168

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 (39) hide show
  1. package/README.md +177 -18
  2. package/dist/drivers/base/BaseDriver.d.ts +18 -1
  3. package/dist/drivers/base/BaseDriver.d.ts.map +1 -1
  4. package/dist/drivers/base/BaseDriver.js +21 -3
  5. package/dist/drivers/base/BaseDriver.js.map +1 -1
  6. package/dist/drivers/sql-server/ExpressionToSqlServer.d.ts.map +1 -1
  7. package/dist/drivers/sql-server/ExpressionToSqlServer.js +37 -7
  8. package/dist/drivers/sql-server/ExpressionToSqlServer.js.map +1 -1
  9. package/dist/drivers/sql-server/SqlServerDriver.d.ts.map +1 -1
  10. package/dist/drivers/sql-server/SqlServerDriver.js +10 -1
  11. package/dist/drivers/sql-server/SqlServerDriver.js.map +1 -1
  12. package/dist/model/EntitySource.d.ts +2 -1
  13. package/dist/model/EntitySource.d.ts.map +1 -1
  14. package/dist/model/EntitySource.js +14 -3
  15. package/dist/model/EntitySource.js.map +1 -1
  16. package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
  17. package/dist/query/ast/ExpressionToSql.js +31 -3
  18. package/dist/query/ast/ExpressionToSql.js.map +1 -1
  19. package/dist/query/ast/Expressions.d.ts +1 -0
  20. package/dist/query/ast/Expressions.d.ts.map +1 -1
  21. package/dist/query/ast/Expressions.js.map +1 -1
  22. package/dist/tests/db-tests/tests/upsert-test.d.ts +3 -0
  23. package/dist/tests/db-tests/tests/upsert-test.d.ts.map +1 -0
  24. package/dist/tests/db-tests/tests/upsert-test.js +18 -0
  25. package/dist/tests/db-tests/tests/upsert-test.js.map +1 -0
  26. package/dist/tests/model/ShoppingContext.d.ts +5 -0
  27. package/dist/tests/model/ShoppingContext.d.ts.map +1 -1
  28. package/dist/tests/model/ShoppingContext.js +20 -0
  29. package/dist/tests/model/ShoppingContext.js.map +1 -1
  30. package/dist/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +1 -1
  32. package/src/drivers/base/BaseDriver.ts +44 -3
  33. package/src/drivers/sql-server/ExpressionToSqlServer.ts +42 -7
  34. package/src/drivers/sql-server/SqlServerDriver.ts +10 -1
  35. package/src/model/EntitySource.ts +15 -3
  36. package/src/query/ast/ExpressionToSql.ts +36 -3
  37. package/src/query/ast/Expressions.ts +1 -0
  38. package/src/tests/db-tests/tests/upsert-test.ts +25 -0
  39. package/src/tests/model/ShoppingContext.ts +18 -0
@@ -498,6 +498,7 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
498
498
  const updateSet = [];
499
499
 
500
500
  const compare = [];
501
+ const compareKeys = [];
501
502
 
502
503
  for (const { left, right } of e.insert) {
503
504
  const c = this.visit(left);
@@ -514,15 +515,47 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
514
515
 
515
516
  for (const { left, right } of e.keys) {
516
517
  const c = this.visit(left);
517
- compare.push(c);
518
+ const v = this.visit(right);
519
+ compare.push(prepare `${c}=${v}`);
520
+ compareKeys.push(c);
518
521
  }
519
522
 
523
+ const returnValues = e.returnUpdated ? this.visit(e.returnUpdated) : [];
524
+
525
+ if (!updateSet.length) {
526
+
527
+ if (e.returnUpdated) {
528
+
529
+ const keys = e.returnUpdated.fields.map((x) => this.visit(x));
530
+
531
+ return prepare `WITH x AS(
532
+ INSERT INTO ${table} (${prepareJoin(insertColumns)})
533
+ VALUES (${prepareJoin(insertValues)})
534
+ LIMIT COALESCE((SELECT 1 FROM ${table} WHERE ${prepareJoin(compare, " AND ")}),2)-1
535
+ ON CONFLICT(${prepareJoin(compareKeys)})
536
+ DO NOTHING
537
+ ${returnValues}
538
+ )
539
+ SELECT * FROM x
540
+ UNION
541
+ SELECT ${prepareJoin(keys)} FROM ${table} WHERE ${prepareJoin(compare, " AND ")}`;
542
+ }
543
+
544
+ return prepare `INSERT INTO ${table} (${prepareJoin(insertColumns)})
545
+ VALUES (${prepareJoin(insertValues)})
546
+ LIMIT COALESCE((SELECT 1 FROM ${table} WHERE ${prepareJoin(compare, " AND ")}),2)-1
547
+ ON CONFLICT(${prepareJoin(compareKeys)})
548
+ DO NOTHING
549
+ ${returnValues}`;
550
+ }
520
551
 
521
552
  return prepare `INSERT INTO ${table} (${prepareJoin(insertColumns)})
522
553
  VALUES (${prepareJoin(insertValues)})
523
- ON CONFLICT(${prepareJoin(compare)})
554
+ LIMIT COALESCE((SELECT 1 FROM ${table} WHERE ${prepareJoin(compare, " AND ")}),2)-1
555
+ ON CONFLICT(${prepareJoin(compareKeys)})
524
556
  DO UPDATE SET
525
- ${prepareJoin(updateSet)} `;
557
+ ${prepareJoin(updateSet)}
558
+ ${returnValues}`;
526
559
  }
527
560
 
528
561
  visitNewObjectExpression(e: NewObjectExpression): ITextQuery {
@@ -398,6 +398,7 @@ export class UpsertStatement extends Expression {
398
398
  insert: BinaryExpression[];
399
399
  update: BinaryExpression[];
400
400
  keys: BinaryExpression[];
401
+ returnUpdated: ReturnUpdated;
401
402
  }
402
403
 
403
404
  export class UnionAllStatement extends Expression {
@@ -0,0 +1,25 @@
1
+ import assert from "assert";
2
+ import { TestConfig } from "../../TestConfig.js";
3
+ import { createContext } 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
+ let e = await context.emailAddresses.saveDirect({ address: "e@e.com"}, "upsert", { address: "e@e.com"});
14
+ assert.strictEqual("1", e.id);
15
+ e = await context.emailAddresses.saveDirect({ address: "e@e.com"}, "upsert", { address: "e@e.com"});
16
+ assert.strictEqual("1", e.id);
17
+
18
+ e = await context.emailAddresses.saveDirect({ address: "a@e.com"}, "insert-select", { address: "a@e.com"});
19
+ assert.strictEqual("2", e.id);
20
+
21
+ e = await context.emailAddresses.saveDirect({ address: "a@e.com"}, "insert-select", { address: "a@e.com"});
22
+ assert.strictEqual("2", e.id);
23
+
24
+ await context.saveChanges();
25
+ }
@@ -32,6 +32,8 @@ export class ShoppingContext extends EntityContext {
32
32
  public profilePhotos = this.model.register(ProfilePhoto);
33
33
 
34
34
  public userFiles = this.model.register(UserFile);
35
+
36
+ public emailAddresses = this.model.register(EmailAddress);
35
37
  }
36
38
 
37
39
  @Table("Users")
@@ -72,6 +74,22 @@ export class User {
72
74
  public photo: UserFile;
73
75
  }
74
76
 
77
+ @Table("EmailAddresses")
78
+ @Index({
79
+ name: "IX_Unique_EmailAddress",
80
+ columns: [{ name: (x) => x.address , descending: false }],
81
+ unique: true
82
+ })
83
+ export class EmailAddress {
84
+
85
+ @Column({ key: true, generated: "identity"})
86
+ public id: number;
87
+
88
+ @Column({ dataType: "Char", length: 200 })
89
+ public address: string;
90
+
91
+ }
92
+
75
93
  @Table("Categories")
76
94
  export class Category {
77
95