@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.
- package/README.md +177 -18
- package/dist/drivers/base/BaseDriver.d.ts +18 -1
- package/dist/drivers/base/BaseDriver.d.ts.map +1 -1
- package/dist/drivers/base/BaseDriver.js +21 -3
- package/dist/drivers/base/BaseDriver.js.map +1 -1
- package/dist/drivers/sql-server/ExpressionToSqlServer.d.ts.map +1 -1
- package/dist/drivers/sql-server/ExpressionToSqlServer.js +37 -7
- package/dist/drivers/sql-server/ExpressionToSqlServer.js.map +1 -1
- package/dist/drivers/sql-server/SqlServerDriver.d.ts.map +1 -1
- package/dist/drivers/sql-server/SqlServerDriver.js +10 -1
- package/dist/drivers/sql-server/SqlServerDriver.js.map +1 -1
- package/dist/model/EntitySource.d.ts +2 -1
- package/dist/model/EntitySource.d.ts.map +1 -1
- package/dist/model/EntitySource.js +14 -3
- package/dist/model/EntitySource.js.map +1 -1
- package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
- package/dist/query/ast/ExpressionToSql.js +31 -3
- package/dist/query/ast/ExpressionToSql.js.map +1 -1
- package/dist/query/ast/Expressions.d.ts +1 -0
- package/dist/query/ast/Expressions.d.ts.map +1 -1
- package/dist/query/ast/Expressions.js.map +1 -1
- package/dist/tests/db-tests/tests/upsert-test.d.ts +3 -0
- package/dist/tests/db-tests/tests/upsert-test.d.ts.map +1 -0
- package/dist/tests/db-tests/tests/upsert-test.js +18 -0
- package/dist/tests/db-tests/tests/upsert-test.js.map +1 -0
- package/dist/tests/model/ShoppingContext.d.ts +5 -0
- package/dist/tests/model/ShoppingContext.d.ts.map +1 -1
- package/dist/tests/model/ShoppingContext.js +20 -0
- package/dist/tests/model/ShoppingContext.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/drivers/base/BaseDriver.ts +44 -3
- package/src/drivers/sql-server/ExpressionToSqlServer.ts +42 -7
- package/src/drivers/sql-server/SqlServerDriver.ts +10 -1
- package/src/model/EntitySource.ts +15 -3
- package/src/query/ast/ExpressionToSql.ts +36 -3
- package/src/query/ast/Expressions.ts +1 -0
- package/src/tests/db-tests/tests/upsert-test.ts +25 -0
- 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
|
-
|
|
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
|
-
|
|
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 {
|
|
@@ -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
|
|