@entity-access/entity-access 1.0.169 → 1.0.171

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.
@@ -3,7 +3,7 @@ import type EntityType from "../entity-query/EntityType.js";
3
3
  import type { IEntityQuery, IFilterExpression } from "./IFilterWithParameter.js";
4
4
  import EntityQuery from "./EntityQuery.js";
5
5
  import { contextSymbol, modelSymbol } from "../common/symbols/symbols.js";
6
- import { Expression } from "../query/ast/Expressions.js";
6
+ import { Expression, Identifier } from "../query/ast/Expressions.js";
7
7
  import { DirectSaveType } from "../drivers/base/BaseDriver.js";
8
8
 
9
9
  export class EntitySource<T = any> {
@@ -30,9 +30,66 @@ export class EntitySource<T = any> {
30
30
 
31
31
  }
32
32
 
33
- public async saveDirect(item: Partial<T>, mode: DirectSaveType, keys?: Partial<T>) {
33
+ public async saveDirect({
34
+ test,
35
+ mode,
36
+ changes,
37
+ select
38
+ }: { test?: Partial<T>, changes: Partial<T>, select?: Partial<T>, mode: DirectSaveType }) {
39
+
34
40
  const { driver } = this.context;
35
- const expression = driver.createUpsertExpression(this.model, item, mode, keys);
41
+
42
+ const returnFields = [] as Identifier[];
43
+
44
+ if (!select) {
45
+ for (const iterator of this.model.columns) {
46
+ if(iterator.generated || iterator.key) {
47
+ returnFields.push(Expression.identifier(iterator.columnName));
48
+ }
49
+ }
50
+ } else {
51
+ for (const key in select) {
52
+ if (Object.prototype.hasOwnProperty.call(select, key)) {
53
+ const field = this.model.getField(key);
54
+ if (field) {
55
+ returnFields.push(Expression.identifier(field.columnName));
56
+ }
57
+ }
58
+ }
59
+ }
60
+
61
+ if (mode === "insert-select" || mode === "upsert") {
62
+ // check if it exits..
63
+ if (!test) {
64
+ test = {};
65
+ for (const iterator of this.model.keys) {
66
+ test[iterator.name] = changes[iterator.name];
67
+ }
68
+ }
69
+ const exists = driver.createSelectWithKeysExpression(this.model, test, returnFields);
70
+ const q = driver.compiler.compileExpression(null, exists);
71
+ const er = await this.context.connection.executeQuery(q);
72
+ if (er.rows?.[0]) {
73
+ const fr = er.rows[0];
74
+ for (const key in fr) {
75
+ if (Object.prototype.hasOwnProperty.call(fr, key)) {
76
+ const element = fr[key];
77
+ const name = this.model.getColumn(key).name;
78
+ changes[name] = element;
79
+ }
80
+ }
81
+
82
+ if (mode !== "upsert") {
83
+ return changes;
84
+ }
85
+ mode = "update";
86
+ }
87
+ }
88
+
89
+ const expression = driver.createUpsertExpression(this.model, changes, mode, test, returnFields);
90
+ if (!expression) {
91
+ return changes;
92
+ }
36
93
  const { text, values } = driver.compiler.compileExpression(null, expression);
37
94
  const r = await this.context.connection.executeQuery({ text, values });
38
95
  if(r.rows?.length) {
@@ -41,11 +98,11 @@ export class EntitySource<T = any> {
41
98
  if (Object.prototype.hasOwnProperty.call(first, key)) {
42
99
  const element = first[key];
43
100
  const name = this.model.getColumn(key).name;
44
- item[name] = element;
101
+ changes[name] = element;
45
102
  }
46
103
  }
47
104
  }
48
- return item;
105
+ return changes;
49
106
  }
50
107
 
51
108
  public add(item: Partial<T>): T {
@@ -531,7 +531,6 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
531
531
  return prepare `WITH x AS(
532
532
  INSERT INTO ${table} (${prepareJoin(insertColumns)})
533
533
  VALUES (${prepareJoin(insertValues)})
534
- LIMIT COALESCE((SELECT 1 FROM ${table} WHERE ${prepareJoin(compare, " AND ")}),2)-1
535
534
  ON CONFLICT(${prepareJoin(compareKeys)})
536
535
  DO NOTHING
537
536
  ${returnValues}
@@ -543,38 +542,41 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
543
542
 
544
543
  return prepare `INSERT INTO ${table} (${prepareJoin(insertColumns)})
545
544
  VALUES (${prepareJoin(insertValues)})
546
- LIMIT COALESCE((SELECT 1 FROM ${table} WHERE ${prepareJoin(compare, " AND ")}),2)-1
547
545
  ON CONFLICT(${prepareJoin(compareKeys)})
548
546
  DO NOTHING`;
549
547
  }
550
548
 
551
- const r = prepare `INSERT INTO ${table} (${prepareJoin(insertColumns)})
552
- VALUES (${prepareJoin(insertValues)})
553
- ON CONFLICT(${prepareJoin(compareKeys)})
554
- DO UPDATE SET
555
- ${prepareJoin(updateSet)}
556
- ${returnValues}`;
557
-
558
- return r;
559
-
560
- // return prepare `
561
- // WITH U1 AS(
562
- // UPDATE ${table} SET
563
- // ${prepareJoin(updateSet)}
564
- // WHERE ${prepareJoin(compare, " AND ")}
565
- // ),
566
- // I1 AS(
567
- // INSERT INTO ${table} (${prepareJoin(insertColumns)})
568
- // VALUES (${prepareJoin(insertValues)})
569
- // LIMIT COALESCE((SELECT 1 FROM ${table} WHERE ${prepareJoin(compare, " AND ")}),2)-1
570
- // ON CONFLICT(${prepareJoin(compareKeys)})
571
- // DO UPDATE SET
572
- // ${prepareJoin(updateSet)}
573
- // ${returnValues}
574
- // )
575
- // SELECT * from U1
576
- // UNION
577
- // SELECT * from I1`;
549
+ // const r = prepare `INSERT INTO ${table} (${prepareJoin(insertColumns)})
550
+ // VALUES (${prepareJoin(insertValues)})
551
+ // ON CONFLICT(${prepareJoin(compareKeys)})
552
+ // DO UPDATE SET
553
+ // ${prepareJoin(updateSet)}
554
+ // ${returnValues}`;
555
+
556
+ // return r;
557
+
558
+ if (returnValues.length === 0) {
559
+ returnValues.push([" RETURNING * "]);
560
+ }
561
+
562
+ return prepare `
563
+ WITH U1 AS(
564
+ UPDATE ${table} SET
565
+ ${prepareJoin(updateSet)}
566
+ WHERE ${prepareJoin(compare, " AND ")}
567
+ ${returnValues}
568
+ ),
569
+ I1 AS(
570
+ INSERT INTO ${table} (${prepareJoin(insertColumns)})
571
+ VALUES (${prepareJoin(insertValues)})
572
+ ON CONFLICT(${prepareJoin(compareKeys)})
573
+ DO UPDATE SET
574
+ ${prepareJoin(updateSet)}
575
+ ${returnValues}
576
+ )
577
+ SELECT * from U1
578
+ UNION
579
+ SELECT * from I1`;
578
580
  }
579
581
 
580
582
  visitNewObjectExpression(e: NewObjectExpression): ITextQuery {
@@ -10,15 +10,20 @@ export default async function(this: TestConfig) {
10
10
 
11
11
  const context = await createContext(this.driver);
12
12
 
13
- let e = await context.emailAddresses.saveDirect({ address: "e@e.com"}, "upsert", { address: "e@e.com"});
13
+ let changes = { address: "e@e.com"};
14
+ let test = { ... changes };
15
+
16
+ let e = await context.emailAddresses.saveDirect({ mode: "upsert", changes, test});
14
17
  assert.strictEqual("1", e.id);
15
- e = await context.emailAddresses.saveDirect({ address: "e@e.com"}, "upsert", { address: "e@e.com"});
18
+ e = await context.emailAddresses.saveDirect({ mode: "upsert", changes, test});
16
19
  assert.strictEqual("1", e.id);
17
20
 
18
- e = await context.emailAddresses.saveDirect({ address: "a@e.com"}, "insert-select", { address: "a@e.com"});
21
+ changes = { address: "a@e.com"};
22
+ test = { ... changes };
23
+ e = await context.emailAddresses.saveDirect({ mode: "insert-select", changes, test});
19
24
  assert.strictEqual("2", e.id);
20
25
 
21
- e = await context.emailAddresses.saveDirect({ address: "a@e.com"}, "insert-select", { address: "a@e.com"});
26
+ e = await context.emailAddresses.saveDirect({ mode: "insert-select", changes, test});
22
27
  assert.strictEqual("2", e.id);
23
28
 
24
29
  await context.saveChanges();
@@ -210,9 +210,9 @@ export default class WorkflowStorage {
210
210
  state.taskGroup ||= "default";
211
211
  // await db.saveChanges();
212
212
  if(state[loadedFromDb]) {
213
- await db.workflows.saveDirect(state, "update");
213
+ await db.workflows.saveDirect({ mode: "update", changes: state });
214
214
  } else {
215
- await db.workflows.saveDirect(state, "upsert");
215
+ await db.workflows.saveDirect({ mode: "upsert", changes: state });
216
216
  }
217
217
  });
218
218
  }