@entity-access/entity-access 1.0.55 → 1.0.56

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 (127) hide show
  1. package/dist/compiler/NamingConventions.d.ts +7 -0
  2. package/dist/compiler/NamingConventions.d.ts.map +1 -0
  3. package/dist/compiler/NamingConventions.js +7 -0
  4. package/dist/compiler/NamingConventions.js.map +1 -0
  5. package/dist/compiler/QueryCompiler.d.ts +2 -2
  6. package/dist/compiler/QueryCompiler.d.ts.map +1 -1
  7. package/dist/compiler/QueryCompiler.js +8 -3
  8. package/dist/compiler/QueryCompiler.js.map +1 -1
  9. package/dist/decorators/Column.d.ts.map +1 -1
  10. package/dist/decorators/Column.js +3 -0
  11. package/dist/decorators/Column.js.map +1 -1
  12. package/dist/decorators/IColumn.d.ts +5 -0
  13. package/dist/decorators/IColumn.d.ts.map +1 -1
  14. package/dist/drivers/base/BaseDriver.d.ts.map +1 -1
  15. package/dist/drivers/base/BaseDriver.js +7 -7
  16. package/dist/drivers/base/BaseDriver.js.map +1 -1
  17. package/dist/drivers/postgres/PostgreSqlDriver.js +1 -1
  18. package/dist/drivers/postgres/PostgreSqlDriver.js.map +1 -1
  19. package/dist/drivers/sql-server/ExpressionToSqlServer.d.ts.map +1 -1
  20. package/dist/drivers/sql-server/ExpressionToSqlServer.js +2 -2
  21. package/dist/drivers/sql-server/ExpressionToSqlServer.js.map +1 -1
  22. package/dist/drivers/sql-server/SqlServerQueryCompiler.d.ts +1 -1
  23. package/dist/drivers/sql-server/SqlServerQueryCompiler.d.ts.map +1 -1
  24. package/dist/drivers/sql-server/SqlServerQueryCompiler.js +6 -2
  25. package/dist/drivers/sql-server/SqlServerQueryCompiler.js.map +1 -1
  26. package/dist/entity-query/EntityType.d.ts +7 -5
  27. package/dist/entity-query/EntityType.d.ts.map +1 -1
  28. package/dist/entity-query/EntityType.js +31 -14
  29. package/dist/entity-query/EntityType.js.map +1 -1
  30. package/dist/eternity/EternityStorage.d.ts +1 -1
  31. package/dist/eternity/EternityStorage.d.ts.map +1 -1
  32. package/dist/eternity/EternityStorage.js +4 -4
  33. package/dist/eternity/EternityStorage.js.map +1 -1
  34. package/dist/migrations/Migrations.d.ts.map +1 -1
  35. package/dist/migrations/Migrations.js +5 -4
  36. package/dist/migrations/Migrations.js.map +1 -1
  37. package/dist/migrations/postgres/PostgresAutomaticMigrations.d.ts.map +1 -1
  38. package/dist/migrations/postgres/PostgresAutomaticMigrations.js +17 -14
  39. package/dist/migrations/postgres/PostgresAutomaticMigrations.js.map +1 -1
  40. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js +12 -12
  41. package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js.map +1 -1
  42. package/dist/model/EntityContext.js.map +1 -1
  43. package/dist/model/EntityModel.d.ts +4 -1
  44. package/dist/model/EntityModel.d.ts.map +1 -1
  45. package/dist/model/EntityModel.js +36 -5
  46. package/dist/model/EntityModel.js.map +1 -1
  47. package/dist/model/EntityQuery.d.ts.map +1 -1
  48. package/dist/model/EntityQuery.js +7 -7
  49. package/dist/model/EntityQuery.js.map +1 -1
  50. package/dist/model/SourceExpression.d.ts.map +1 -1
  51. package/dist/model/SourceExpression.js +3 -4
  52. package/dist/model/SourceExpression.js.map +1 -1
  53. package/dist/model/changes/ChangeEntry.js +2 -2
  54. package/dist/model/changes/ChangeEntry.js.map +1 -1
  55. package/dist/model/changes/ChangeSet.js +1 -2
  56. package/dist/model/changes/ChangeSet.js.map +1 -1
  57. package/dist/model/verification/VerificationSession.d.ts.map +1 -1
  58. package/dist/model/verification/VerificationSession.js +6 -6
  59. package/dist/model/verification/VerificationSession.js.map +1 -1
  60. package/dist/query/ast/DebugStringVisitor.d.ts +1 -2
  61. package/dist/query/ast/DebugStringVisitor.d.ts.map +1 -1
  62. package/dist/query/ast/DebugStringVisitor.js +0 -3
  63. package/dist/query/ast/DebugStringVisitor.js.map +1 -1
  64. package/dist/query/ast/ExpressionToSql.d.ts +1 -2
  65. package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
  66. package/dist/query/ast/ExpressionToSql.js +16 -14
  67. package/dist/query/ast/ExpressionToSql.js.map +1 -1
  68. package/dist/query/ast/Expressions.d.ts +15 -20
  69. package/dist/query/ast/Expressions.d.ts.map +1 -1
  70. package/dist/query/ast/Expressions.js +17 -19
  71. package/dist/query/ast/Expressions.js.map +1 -1
  72. package/dist/query/ast/IStringTransformer.d.ts +2 -3
  73. package/dist/query/ast/IStringTransformer.d.ts.map +1 -1
  74. package/dist/query/ast/IStringTransformer.js +4 -6
  75. package/dist/query/ast/IStringTransformer.js.map +1 -1
  76. package/dist/query/ast/Visitor.d.ts +1 -2
  77. package/dist/query/ast/Visitor.d.ts.map +1 -1
  78. package/dist/query/ast/Visitor.js +0 -5
  79. package/dist/query/ast/Visitor.js.map +1 -1
  80. package/dist/query/expander/QueryExpander.js +2 -2
  81. package/dist/query/expander/QueryExpander.js.map +1 -1
  82. package/dist/query/parser/ArrowToExpression.d.ts.map +1 -1
  83. package/dist/query/parser/ArrowToExpression.js +2 -2
  84. package/dist/query/parser/ArrowToExpression.js.map +1 -1
  85. package/dist/tests/eternity/eternity-tests.d.ts.map +1 -1
  86. package/dist/tests/eternity/eternity-tests.js +1 -1
  87. package/dist/tests/eternity/eternity-tests.js.map +1 -1
  88. package/dist/tests/expressions/left-joins/child-joins.js +41 -41
  89. package/dist/tests/expressions/left-joins/child-joins.js.map +1 -1
  90. package/dist/tests/expressions/select/select.d.ts.map +1 -1
  91. package/dist/tests/expressions/select/select.js +2 -2
  92. package/dist/tests/expressions/select/select.js.map +1 -1
  93. package/dist/tests/expressions/simple/parse-arrow.js +10 -10
  94. package/dist/tests/expressions/simple/parse-arrow.js.map +1 -1
  95. package/dist/tsconfig.tsbuildinfo +1 -1
  96. package/package.json +1 -1
  97. package/src/compiler/NamingConventions.ts +6 -0
  98. package/src/compiler/QueryCompiler.ts +7 -5
  99. package/src/decorators/Column.ts +3 -0
  100. package/src/decorators/IColumn.ts +7 -0
  101. package/src/drivers/base/BaseDriver.ts +9 -9
  102. package/src/drivers/postgres/PostgreSqlDriver.ts +1 -1
  103. package/src/drivers/sql-server/ExpressionToSqlServer.ts +2 -2
  104. package/src/drivers/sql-server/SqlServerQueryCompiler.ts +5 -2
  105. package/src/entity-query/EntityType.ts +34 -13
  106. package/src/eternity/EternityStorage.ts +3 -3
  107. package/src/migrations/Migrations.ts +5 -3
  108. package/src/migrations/postgres/PostgresAutomaticMigrations.ts +17 -14
  109. package/src/migrations/sql-server/SqlServerAutomaticMigrations.ts +12 -12
  110. package/src/model/EntityContext.ts +1 -1
  111. package/src/model/EntityModel.ts +41 -7
  112. package/src/model/EntityQuery.ts +7 -7
  113. package/src/model/SourceExpression.ts +3 -4
  114. package/src/model/changes/ChangeEntry.ts +2 -2
  115. package/src/model/changes/ChangeSet.ts +1 -1
  116. package/src/model/verification/VerificationSession.ts +6 -7
  117. package/src/query/ast/DebugStringVisitor.ts +1 -5
  118. package/src/query/ast/ExpressionToSql.ts +18 -15
  119. package/src/query/ast/Expressions.ts +33 -34
  120. package/src/query/ast/IStringTransformer.ts +4 -4
  121. package/src/query/ast/Visitor.ts +1 -7
  122. package/src/query/expander/QueryExpander.ts +4 -4
  123. package/src/query/parser/ArrowToExpression.ts +2 -2
  124. package/src/tests/eternity/eternity-tests.ts +2 -1
  125. package/src/tests/expressions/left-joins/child-joins.ts +41 -41
  126. package/src/tests/expressions/select/select.ts +2 -5
  127. package/src/tests/expressions/simple/parse-arrow.ts +10 -10
@@ -3,7 +3,7 @@ import { IClassOf } from "../decorators/IClassOf.js";
3
3
  import { Query } from "../query/Query.js";
4
4
  import NameParser from "../decorators/parser/NameParser.js";
5
5
  import SchemaRegistry from "../decorators/SchemaRegistry.js";
6
- import { Expression, ExpressionAs, QuotedLiteral, SelectStatement, TableLiteral } from "../query/ast/Expressions.js";
6
+ import { Expression, ExpressionAs, NumberLiteral, SelectStatement, TableLiteral } from "../query/ast/Expressions.js";
7
7
  import InstanceCache from "../common/cache/InstanceCache.js";
8
8
  import { IIndex } from "../decorators/IIndex.js";
9
9
 
@@ -37,10 +37,10 @@ export default class EntityType {
37
37
  public get fullyQualifiedName() {
38
38
  return this.schema
39
39
  ? TableLiteral.create({
40
- schema: QuotedLiteral.create({literal: this.schema}) ,
41
- name: QuotedLiteral.create({ literal: this.name })
40
+ schema: Expression.identifier(this.schema) ,
41
+ name: Expression.identifier(this.name)
42
42
  })
43
- : QuotedLiteral.create({ literal: this.name });
43
+ : Expression.identifier(this.name);
44
44
  }
45
45
 
46
46
  private fieldMap: Map<string, IColumn> = new Map();
@@ -50,6 +50,16 @@ export default class EntityType {
50
50
  private selectAll: SelectStatement;
51
51
  private selectOne: SelectStatement;
52
52
 
53
+ constructor(original?: EntityType) {
54
+ if (!original) {
55
+ return;
56
+ }
57
+ this.typeClass = original.typeClass;
58
+ this.name = original.name;
59
+ this.schema = original.schema;
60
+ this.entityName = original.entityName;
61
+ }
62
+
53
63
  [addOrCreateColumnSymbol](name: string): IColumn {
54
64
  return this.fieldMap.get(name) ?? { name };
55
65
  }
@@ -86,7 +96,7 @@ export default class EntityType {
86
96
  return this.fieldMap.get(name);
87
97
  }
88
98
 
89
- addRelation(relation: IEntityRelation) {
99
+ addRelation(relation: IEntityRelation, getInverseModel?: (t) => EntityType) {
90
100
  // we will also set fk to the corresponding column
91
101
  this.relations.push(relation);
92
102
  this.relationMap.set(relation.name, relation);
@@ -108,8 +118,12 @@ export default class EntityType {
108
118
  fkColumn.dataType = "BigInt";
109
119
  }
110
120
 
121
+ if (!getInverseModel) {
122
+ return relation;
123
+ }
124
+
111
125
  // let us set inverse relations...
112
- const relatedType = SchemaRegistry.model(relation.relatedTypeClass);
126
+ const relatedType = getInverseModel(relation.relatedTypeClass);
113
127
  relation.relatedEntity = relatedType;
114
128
  const inverseRelation: IEntityRelation = {
115
129
  name: relation.relatedName,
@@ -137,12 +151,7 @@ export default class EntityType {
137
151
  }
138
152
  const source = this.fullyQualifiedName;
139
153
  const as = Expression.parameter(this.name[0] + "1");
140
- const fields = this.columns.map((c) => c.name !== c.columnName
141
- ? ExpressionAs.create({
142
- expression: Expression.member(as, c.columnName),
143
- alias: QuotedLiteral.create({ literal: c.name })
144
- })
145
- : Expression.member(as, c.columnName));
154
+ const fields = this.columns.map((c) => Expression.member(as, c.columnName));
146
155
  this.selectAll = SelectStatement.create({
147
156
  source,
148
157
  model: this,
@@ -159,7 +168,7 @@ export default class EntityType {
159
168
  const source = this.fullyQualifiedName;
160
169
  const as = Expression.parameter(this.name[0] + "1");
161
170
  const fields = [
162
- Expression.identifier("1")
171
+ NumberLiteral.one
163
172
  ];
164
173
  this.selectOne = SelectStatement.create({
165
174
  source,
@@ -169,4 +178,16 @@ export default class EntityType {
169
178
  });
170
179
  return { ... this.selectOne };
171
180
  }
181
+
182
+ public map(row: any) {
183
+ const c = new this.typeClass();
184
+ for (const iterator of this.columns) {
185
+ const value = row[iterator.columnName];
186
+ if (value === void 0) {
187
+ continue;
188
+ }
189
+ c[iterator.name] = value;
190
+ }
191
+ return c;
192
+ }
172
193
  }
@@ -10,8 +10,8 @@ import WorkflowClock from "./WorkflowClock.js";
10
10
  @Table("Workflows")
11
11
  @Index({
12
12
  name: "IX_Workflows_Group",
13
- columns: [{ name: (x) => x.group, descending: false }],
14
- filter: (x) => x.group !== null
13
+ columns: [{ name: (x) => x.groupName, descending: false }],
14
+ filter: (x) => x.groupName !== null
15
15
  })
16
16
  @Index({
17
17
  name: "IX_Workflows_ETA",
@@ -30,7 +30,7 @@ export class WorkflowStorage {
30
30
  public name: string;
31
31
 
32
32
  @Column({ dataType: "Char", length: 200, nullable: true })
33
- public group: string;
33
+ public groupName: string;
34
34
 
35
35
  @Column({ dataType: "Char"})
36
36
  public input: string;
@@ -1,3 +1,4 @@
1
+ import { modelSymbol } from "../common/symbols/symbols.js";
1
2
  import type QueryCompiler from "../compiler/QueryCompiler.js";
2
3
  import { IIndex } from "../decorators/IIndex.js";
3
4
  import SchemaRegistry from "../decorators/SchemaRegistry.js";
@@ -10,8 +11,9 @@ export default abstract class Migrations {
10
11
  constructor(protected compiler: QueryCompiler) {}
11
12
 
12
13
  public async migrate(context: EntityContext) {
13
- for (const iterator of context.model.entities.keys()) {
14
- const type = SchemaRegistry.model(iterator);
14
+ const { model } = context;
15
+ for (const s of model.sources.values()) {
16
+ const type = s[modelSymbol] as EntityType;
15
17
  await this.migrateTable(context, type);
16
18
 
17
19
  for (const index of type.indexes) {
@@ -30,7 +32,7 @@ export default abstract class Migrations {
30
32
  // parse..
31
33
  const source = context.query(type.typeClass) as EntityQuery<any>;
32
34
  const { target , textQuery } = this.compiler.compileToSql(source, `(p) => ${index.filter}` as any);
33
- index.filter = textQuery.join("").split( this.compiler.quotedLiteral(source.selectStatement.sourceParameter.name) + ".").join("");
35
+ index.filter = textQuery.join("").split( source.selectStatement.sourceParameter.name + ".").join("");
34
36
  }
35
37
 
36
38
  this.migrateIndex(context, index, type);
@@ -28,7 +28,7 @@ export default class PostgresAutomaticMigrations extends PostgresMigrations {
28
28
  async createIndexes(context: EntityContext, type: EntityType, fkColumns: IColumn[]) {
29
29
  for (const iterator of fkColumns) {
30
30
  const filter = iterator.nullable
31
- ? `${ JSON.stringify(iterator.columnName)} IS NOT NULL`
31
+ ? `${iterator.columnName} IS NOT NULL`
32
32
  : "";
33
33
  const indexDef: IIndex = {
34
34
  name: `IX_${type.name}_${iterator.columnName}`,
@@ -42,15 +42,15 @@ export default class PostgresAutomaticMigrations extends PostgresMigrations {
42
42
  async createColumns(driver: BaseDriver, type: EntityType, nonKeyColumns: IColumn[]) {
43
43
 
44
44
  const name = type.schema
45
- ? JSON.stringify(type.schema) + "." + JSON.stringify(type.name)
46
- : JSON.stringify(type.name);
45
+ ? type.schema + "." + type.name
46
+ : type.name;
47
47
 
48
48
  if (nonKeyColumns.length > 1) {
49
49
  nonKeyColumns.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
50
50
  }
51
51
 
52
52
  for (const iterator of nonKeyColumns) {
53
- const columnName = JSON.stringify(iterator.columnName);
53
+ const columnName = iterator.columnName;
54
54
  let def = `ALTER TABLE ${name} ADD COLUMN IF NOT EXISTS ${columnName} `;
55
55
  def += this.getColumnDefinition(iterator);
56
56
  if (iterator.nullable !== true) {
@@ -67,8 +67,8 @@ export default class PostgresAutomaticMigrations extends PostgresMigrations {
67
67
  async createTable(driver: BaseDriver, type: EntityType, keys: IColumn[]) {
68
68
 
69
69
  const name = type.schema
70
- ? JSON.stringify(type.schema) + "." + JSON.stringify(type.name)
71
- : JSON.stringify(type.name);
70
+ ? type.schema + "." + type.name
71
+ : type.name;
72
72
 
73
73
  if (keys.length > 1) {
74
74
  keys.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
@@ -77,29 +77,32 @@ export default class PostgresAutomaticMigrations extends PostgresMigrations {
77
77
  const fields = [];
78
78
 
79
79
  for (const iterator of keys) {
80
- let def = JSON.stringify(iterator.columnName) + " ";
80
+ let def = iterator.columnName + " ";
81
81
  if (iterator.autoGenerate) {
82
- def += iterator.dataType === "BigInt" ? "bigserial " : "serial ";
82
+ def += iterator.dataType === "BigInt" ? "bigint " : "int ";
83
+ def += " not null GENERATED BY DEFAULT AS IDENTITY\r\n\t";
83
84
  } else {
84
85
  def += this.getColumnDefinition(iterator);
86
+ def += " not null \r\n\t";
85
87
  }
86
- def += " not null primary key\r\n\t";
87
88
  fields.push(def);
88
89
  }
89
90
 
90
- await driver.executeQuery(`CREATE TABLE IF NOT EXISTS ${name} (${fields.join(",")})`);
91
+ await driver.executeQuery(`CREATE TABLE IF NOT EXISTS ${name} (${fields.join(",")}
92
+ ,CONSTRAINT PK_${name} PRIMARY KEY (${keys.map((x) => x.columnName).join(",")})
93
+ )`);
91
94
 
92
95
  }
93
96
 
94
97
  async migrateIndex(context: EntityContext, index: IIndex, type: EntityType) {
95
98
  const driver = context.driver;
96
99
  const name = type.schema
97
- ? JSON.stringify(type.schema) + "." + JSON.stringify(type.name)
98
- : JSON.stringify(type.name);
99
- const indexName = JSON.stringify(index.name);
100
+ ? type.schema + "." + type.name
101
+ : type.name;
102
+ const indexName = index.name;
100
103
  const columns = [];
101
104
  for (const column of index.columns) {
102
- const columnName = JSON.stringify(column.name);
105
+ const columnName = column.name;
103
106
  columns.push(`${columnName} ${column.descending ? "DESC" : "ASC"}`);
104
107
  }
105
108
  let query = `CREATE ${index.unique ? "UNIQUE" : ""} INDEX IF NOT EXISTS ${indexName} ON ${name} ( ${columns.join(", ")})`;
@@ -29,10 +29,10 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
29
29
  async createIndexes(context: EntityContext, type: EntityType, fkColumns: IColumn[]) {
30
30
  for (const iterator of fkColumns) {
31
31
  const filter = iterator.nullable
32
- ? `${ SqlServerLiteral.quotedLiteral(iterator.columnName)} IS NOT NULL`
32
+ ? `${ iterator.columnName} IS NOT NULL`
33
33
  : "";
34
34
  const indexDef: IIndex = {
35
- name: `IX_${type.name}_${iterator.columnName}`,
35
+ name: `IX_${type.name}_${iterator.name}`,
36
36
  columns: [{ name: iterator.columnName, descending: iterator.indexOrder !== "ascending"}],
37
37
  filter
38
38
  };
@@ -43,15 +43,15 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
43
43
  async createColumns(driver: BaseDriver, type: EntityType, nonKeyColumns: IColumn[]) {
44
44
 
45
45
  const name = type.schema
46
- ? SqlServerLiteral.quotedLiteral(type.schema) + "." + SqlServerLiteral.quotedLiteral(type.name)
47
- : SqlServerLiteral.quotedLiteral(type.name);
46
+ ? type.schema + "." + type.name
47
+ : type.name;
48
48
 
49
49
  if (nonKeyColumns.length > 1) {
50
50
  nonKeyColumns.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
51
51
  }
52
52
 
53
53
  for (const iterator of nonKeyColumns) {
54
- const columnName = SqlServerLiteral.quotedLiteral(iterator.columnName);
54
+ const columnName = iterator.columnName;
55
55
  let def = `IF COL_LENGTH(${ SqlServerLiteral.escapeLiteral(name)}, ${ SqlServerLiteral.escapeLiteral(columnName)}) IS NULL ALTER TABLE ${name} ADD ${columnName} `;
56
56
  def += this.getColumnDefinition(iterator);
57
57
  if (iterator.nullable === true) {
@@ -70,8 +70,8 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
70
70
  async createTable(driver: BaseDriver, type: EntityType, keys: IColumn[]) {
71
71
 
72
72
  const name = type.schema
73
- ? SqlServerLiteral.quotedLiteral(type.schema) + "." + SqlServerLiteral.quotedLiteral(type.name)
74
- : SqlServerLiteral.quotedLiteral(type.name);
73
+ ? type.schema + "." + type.name
74
+ : type.name;
75
75
 
76
76
  if (keys.length > 1) {
77
77
  keys.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
@@ -80,7 +80,7 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
80
80
  const fields = [];
81
81
 
82
82
  for (const iterator of keys) {
83
- let def = SqlServerLiteral.quotedLiteral(iterator.columnName) + " ";
83
+ let def = iterator.columnName + " ";
84
84
  if (iterator.autoGenerate) {
85
85
  def += this.getColumnDefinition(iterator) + " IDENTITY(1,1)";
86
86
  } else {
@@ -99,12 +99,12 @@ export default class SqlServerAutomaticMigrations extends SqlServerMigrations {
99
99
  async migrateIndex(context: EntityContext, index: IIndex, type: EntityType) {
100
100
  const driver = context.driver;
101
101
  const name = type.schema
102
- ? SqlServerLiteral.quotedLiteral(type.schema) + "." + SqlServerLiteral.quotedLiteral(type.name)
103
- : SqlServerLiteral.quotedLiteral(type.name);
104
- const indexName = SqlServerLiteral.quotedLiteral(index.name);
102
+ ? type.schema + "." + type.name
103
+ : type.name;
104
+ const indexName = index.name;
105
105
  const columns = [];
106
106
  for (const column of index.columns) {
107
- const columnName = SqlServerLiteral.quotedLiteral(column.name);
107
+ const columnName = column.name;
108
108
  columns.push(`${columnName} ${column.descending ? "DESC" : "ASC"}`);
109
109
  }
110
110
  let query = `IF NOT EXISTS(SELECT * FROM sys.indexes WHERE name = '${indexName}' AND object_id = OBJECT_ID('${name}'))
@@ -181,7 +181,7 @@ export default class EntityContext {
181
181
 
182
182
  protected async saveChangesWithoutEvents(signal: AbortSignal) {
183
183
  return this.driver.runInTransaction(async () => {
184
- const copy = [].concat(this.changeSet.entries);
184
+ const copy = [].concat(this.changeSet.entries) as ChangeEntry[];
185
185
  for (const iterator of copy) {
186
186
  switch (iterator.status) {
187
187
  case "inserted":
@@ -1,27 +1,61 @@
1
1
  import type EntityContext from "./EntityContext.js";
2
2
  import { IClassOf } from "../decorators/IClassOf.js";
3
3
  import SchemaRegistry from "../decorators/SchemaRegistry.js";
4
- import EntityQuery from "./EntityQuery.js";
5
- import { Expression } from "@babel/types";
6
4
  import { EntitySource } from "./EntitySource.js";
5
+ import { BaseDriver } from "../drivers/base/BaseDriver.js";
6
+ import EntityType from "../entity-query/EntityType.js";
7
+ import { IStringTransformer } from "../query/ast/IStringTransformer.js";
8
+ import { IEntityRelation } from "../decorators/IColumn.js";
7
9
 
10
+ const driverModelCache = Symbol("driverModelCache");
8
11
 
12
+ const getOrCreateModel = (map: Map<any, EntityType>, type: IClassOf<any>, namingConvention: IStringTransformer) => {
13
+ let t = map.get(type);
14
+ if (t) {
15
+ return t;
16
+ }
17
+ const original = SchemaRegistry.model(type);
18
+ t = new EntityType(original);
19
+ map.set(type, t);
20
+ for (const iterator of original.columns) {
21
+ const column = { ... iterator };
22
+ column.columnName = column.explicitName ? column.columnName : (namingConvention ? namingConvention(column.columnName) : column.columnName);
23
+ t.addColumn(column);
24
+ column.entityType = t;
25
+ }
26
+ for (const iterator of original.relations) {
27
+ if (iterator.isInverseRelation) {
28
+ continue;
29
+ }
30
+ const relation: IEntityRelation = { ... iterator, fkColumn: void 0, relatedEntity: void 0,type: t };
31
+ t.addRelation(relation, (tc) => getOrCreateModel(map, tc, namingConvention));
32
+ }
33
+ return t;
34
+ };
9
35
 
10
36
  export default class EntityModel {
11
37
 
12
- public entities: Map<IClassOf<any>, EntitySource> = new Map();
38
+ public sources: Map<IClassOf<any>, EntitySource> = new Map();
39
+
40
+ public types: Map<IClassOf<any>, EntityType> = new Map();
13
41
 
14
42
  constructor(private context: EntityContext) {
15
43
  }
16
44
 
17
45
  register<T>(type: IClassOf<T>) {
18
- let source = this.entities.get(type);
46
+ let source = this.sources.get(type);
19
47
  if (!source) {
20
- const model = SchemaRegistry.model(type);
21
- source = new EntitySource(model, this.context);
22
- this.entities.set(type, source);
48
+ const cache = (this.context.driver[driverModelCache] ??= new Map());
49
+ const entityType = getOrCreateModel(cache, type, this.context.driver.compiler.namingConvention);
50
+ this.types.set(type, entityType);
51
+ source = new EntitySource(entityType, this.context);
52
+ this.sources.set(type, source);
23
53
  }
24
54
  return source as EntitySource<T>;
25
55
  }
26
56
 
57
+ getEntityType<T>(type: IClassOf<T>): EntityType{
58
+ return this.types.get(type);
59
+ }
60
+
27
61
  }
@@ -2,7 +2,7 @@ import Logger from "../common/Logger.js";
2
2
  import { DisposableScope } from "../common/usingAsync.js";
3
3
  import { ServiceProvider } from "../di/di.js";
4
4
  import EntityType from "../entity-query/EntityType.js";
5
- import { CallExpression, Expression, ExpressionAs, Identifier, OrderByExpression, QuotedLiteral, SelectStatement } from "../query/ast/Expressions.js";
5
+ import { CallExpression, Expression, ExpressionAs, Identifier, OrderByExpression, SelectStatement } from "../query/ast/Expressions.js";
6
6
  import { QueryExpander } from "../query/expander/QueryExpander.js";
7
7
  import EntityContext from "./EntityContext.js";
8
8
  import { IOrderedEntityQuery, IEntityQuery } from "./IFilterWithParameter.js";
@@ -95,9 +95,9 @@ export default class EntityQuery<T = any>
95
95
  scope.register(reader);
96
96
  for await (const iterator of reader.next(10, signal)) {
97
97
  if (type) {
98
- Object.setPrototypeOf(iterator, type.typeClass.prototype);
98
+ const item = type?.map(iterator) ?? iterator;
99
99
  // set identity...
100
- const entry = this.context.changeSet.getEntry(iterator, iterator);
100
+ const entry = this.context.changeSet.getEntry(item, item);
101
101
  relationMapper.fix(entry);
102
102
  yield entry.entity;
103
103
  continue;
@@ -118,8 +118,8 @@ export default class EntityQuery<T = any>
118
118
  const reader = await this.context.driver.executeReader(query, signal);
119
119
  try {
120
120
  for await (const iterator of reader.next(10, signal)) {
121
- Object.setPrototypeOf(iterator, select.model.typeClass.prototype);
122
- const entry = this.context.changeSet.getEntry(iterator, iterator);
121
+ const item = select.model?.map(iterator) ?? iterator;
122
+ const entry = this.context.changeSet.getEntry(item, item);
123
123
  relationMapper.fix(entry);
124
124
  }
125
125
  } catch (error) {
@@ -183,7 +183,7 @@ export default class EntityQuery<T = any>
183
183
  callee: Identifier.create({ value: "COUNT"}),
184
184
  arguments: [ Identifier.create({ value: "*"})]
185
185
  }),
186
- alias: QuotedLiteral.create({ literal: "count" })
186
+ alias: Expression.identifier("c1")
187
187
  })
188
188
  ] };
189
189
 
@@ -194,7 +194,7 @@ export default class EntityQuery<T = any>
194
194
 
195
195
  try {
196
196
  for await (const iterator of reader.next()) {
197
- return iterator.count as number;
197
+ return iterator.c1 as number;
198
198
  }
199
199
  } finally {
200
200
  await reader.dispose();
@@ -1,6 +1,6 @@
1
1
  import { modelSymbol } from "../common/symbols/symbols.js";
2
2
  import EntityType from "../entity-query/EntityType.js";
3
- import { BinaryExpression, Expression, ExpressionAs, Identifier, JoinExpression, MemberExpression, ParameterExpression, QuotedLiteral, SelectStatement } from "../query/ast/Expressions.js";
3
+ import { Expression, JoinExpression, ParameterExpression, SelectStatement } from "../query/ast/Expressions.js";
4
4
  import { ITextQueryFragment, QueryParameter } from "../query/ast/IStringTransformer.js";
5
5
  import EntityContext from "./EntityContext.js";
6
6
 
@@ -64,7 +64,7 @@ export class SourceExpression {
64
64
  as: source.alias,
65
65
  joinType: column.nullable ? "LEFT" : "INNER",
66
66
  model,
67
- source: QuotedLiteral.create({ literal: model.name }),
67
+ source: Expression.identifier(model.name),
68
68
  where: Expression.logicalAnd(
69
69
  Expression.member(
70
70
  this.alias,
@@ -121,9 +121,8 @@ export class SourceExpression {
121
121
 
122
122
  prepareNames([property , ... others]: string[]): ITextQueryFragment {
123
123
  const p = this.model.getProperty(property);
124
- const quotedLiteral = this.context.driver.compiler.quotedLiteral;
125
124
  if (others.length === 0) {
126
- return `${ QueryParameter.create(() => this.alias.name, quotedLiteral)}.${quotedLiteral(p.field.columnName)}`;
125
+ return `${ QueryParameter.create(() => this.alias.name)}.${p.field.columnName}`;
127
126
  }
128
127
 
129
128
  // this must be a navigation...
@@ -89,9 +89,9 @@ export default class ChangeEntry<T = any> implements IChanges {
89
89
  this.detectDependencies();
90
90
 
91
91
  for (const iterator of columns) {
92
- const oldValue = original[iterator.columnName];
92
+ const oldValue = original[iterator.name];
93
93
  const newValue = entity[iterator.name];
94
- if (entity[iterator.name] !== original[iterator.columnName]) {
94
+ if (entity[iterator.name] !== original[iterator.name]) {
95
95
  let modifiedEntry = this.modified.get(iterator);
96
96
  if (!modifiedEntry) {
97
97
  modifiedEntry = { column: iterator, oldValue, newValue };
@@ -52,7 +52,7 @@ export default class ChangeSet {
52
52
  if (c === Object) {
53
53
  throw new EntityAccessError("Entity type not set");
54
54
  }
55
- const type = SchemaRegistry.model(c);
55
+ const type = this.context.model.getEntityType(c);
56
56
  const jsonKey = IdentityService.getIdentity(entity);
57
57
  if (jsonKey) {
58
58
  const existing = this.identityMap.get(jsonKey);
@@ -3,8 +3,7 @@ import Logger from "../../common/Logger.js";
3
3
  import { TypeInfo } from "../../common/TypeInfo.js";
4
4
  import { IEntityRelation } from "../../decorators/IColumn.js";
5
5
  import { ServiceProvider } from "../../di/di.js";
6
- import EntityType from "../../entity-query/EntityType.js";
7
- import { ConditionalExpression, Constant, ExistsExpression, Expression, Identifier, ParameterExpression, QuotedLiteral, SelectStatement, TemplateLiteral, ValuesStatement } from "../../query/ast/Expressions.js";
6
+ import { ConditionalExpression, ExistsExpression, Expression, NumberLiteral, ParameterExpression, SelectStatement, ValuesStatement } from "../../query/ast/Expressions.js";
8
7
  import EntityContext from "../EntityContext.js";
9
8
  import EntityQuery from "../EntityQuery.js";
10
9
  import ChangeEntry from "../changes/ChangeEntry.js";
@@ -106,7 +105,7 @@ export default class VerificationSession {
106
105
  const eq = query as EntityQuery;
107
106
  for (const [key, value] of keys) {
108
107
  const test = Expression.equal(
109
- Expression.member(eq.selectStatement.sourceParameter, Expression.quotedLiteral(key)),
108
+ Expression.member(eq.selectStatement.sourceParameter, Expression.identifier(key)),
110
109
  Expression.constant(value)
111
110
  );
112
111
  compare = compare
@@ -127,10 +126,10 @@ export default class VerificationSession {
127
126
  this.select.sourceParameter = ParameterExpression.create({ name: "x"});
128
127
  const source = ValuesStatement.create({
129
128
  values: [
130
- [Identifier.create({ value: "1"})]
129
+ [NumberLiteral.one]
131
130
  ],
132
- as: QuotedLiteral.create({ literal: "a"}),
133
- fields: [QuotedLiteral.create({ literal: "a"})]
131
+ as: Expression.identifier("a"),
132
+ fields: [Expression.identifier("a")]
134
133
  });
135
134
  this.select.source = source;
136
135
  const compiler = this.context.driver.compiler;
@@ -151,7 +150,7 @@ export default class VerificationSession {
151
150
  addError(query: EntityQuery, compare: Expression, error: string) {
152
151
  const select = { ... query.selectStatement};
153
152
  select.fields = [
154
- Expression.identifier("1")
153
+ NumberLiteral.one
155
154
  ];
156
155
 
157
156
  const where = select.where
@@ -1,4 +1,4 @@
1
- import { ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, Identifier, InsertStatement, JoinExpression, MemberExpression, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, QuotedLiteral, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateElement, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement } from "./Expressions.js";
1
+ import { ArrowFunctionExpression, BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, Identifier, InsertStatement, JoinExpression, MemberExpression, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateElement, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement } from "./Expressions.js";
2
2
  import Visitor from "./Visitor.js";
3
3
 
4
4
  const isBinary = (type) => /^(BinaryExpression|CoalesceExpression)$/.test(type);
@@ -89,10 +89,6 @@ export default class DebugStringVisitor extends Visitor<string> {
89
89
  return e.name;
90
90
  }
91
91
 
92
- visitQuotedLiteral(e: QuotedLiteral): string {
93
- return `"${e.literal}"`;
94
- }
95
-
96
92
  visitStringLiteral(e: StringLiteral): string {
97
93
  return `'${e.value}'`;
98
94
  }
@@ -2,7 +2,7 @@ import QueryCompiler from "../../compiler/QueryCompiler.js";
2
2
  import EntityType from "../../entity-query/EntityType.js";
3
3
  import EntityQuery from "../../model/EntityQuery.js";
4
4
  import { filteredSymbol } from "../../model/events/EntityEvents.js";
5
- import { BigIntLiteral, BinaryExpression, BooleanLiteral, CallExpression, CoalesceExpression, ConditionalExpression, Constant, DeleteStatement, ExistsExpression, Expression, ExpressionAs, ExpressionType, Identifier, InsertStatement, JoinExpression, MemberExpression, NewObjectExpression, NotExits, NullExpression, NumberLiteral, OrderByExpression, ParameterExpression, QuotedLiteral, ReturnUpdated, SelectStatement, StringLiteral, TableLiteral, TemplateLiteral, UnionAllStatement, UpdateStatement, ValuesStatement } from "./Expressions.js";
5
+ 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";
6
6
  import { ITextQuery, QueryParameter, prepare, prepareJoin } from "./IStringTransformer.js";
7
7
  import ParameterScope from "./ParameterScope.js";
8
8
  import Visitor from "./Visitor.js";
@@ -75,7 +75,7 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
75
75
  const source = e.source.type === "ValuesStatement"
76
76
  ? prepare `(${this.visit(e.source)})`
77
77
  : this.visit(e.source);
78
- const as = e.sourceParameter ? prepare ` AS ${this.compiler.quotedLiteral( this.scope.nameOf(e.sourceParameter))}` : "";
78
+ const as = e.sourceParameter ? prepare ` AS ${this.scope.nameOf(e.sourceParameter)}` : "";
79
79
  const fields = this.visitArray(e.fields, ",\n\t\t");
80
80
  return prepare `SELECT
81
81
  ${fields}
@@ -100,10 +100,6 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
100
100
  }
101
101
  }
102
102
 
103
- visitQuotedLiteral(e: QuotedLiteral): ITextQuery {
104
- return [this.compiler.quotedLiteral(e.literal)];
105
- }
106
-
107
103
  visitExpressionAs(e: ExpressionAs): ITextQuery {
108
104
  return prepare `${this.visit(e.expression)} AS ${this.visit(e.alias)}`;
109
105
  }
@@ -113,16 +109,16 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
113
109
  }
114
110
 
115
111
  visitBigIntLiteral({ value }: BigIntLiteral): ITextQuery {
116
- return [() => value];
112
+ return [value.toString()];
117
113
  }
118
114
 
119
115
  visitNumberLiteral( { value }: NumberLiteral): ITextQuery {
120
- return [() => value];
116
+ return [value.toString()];
121
117
  }
122
118
 
123
119
  visitStringLiteral({ value }: StringLiteral): ITextQuery {
124
120
  const escapeLiteral = this.compiler.escapeLiteral;
125
- return [() => escapeLiteral(value)];
121
+ return [escapeLiteral(value)];
126
122
  }
127
123
 
128
124
  visitBooleanLiteral( { value }: BooleanLiteral): ITextQuery {
@@ -171,7 +167,7 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
171
167
  // }
172
168
  select = { ... (query as EntityQuery).selectStatement };
173
169
  select.fields = [
174
- Identifier.create({ value: "1"})
170
+ NumberLiteral.create({ value: 1})
175
171
  ];
176
172
  } else {
177
173
  select = relatedModel.selectOneNumber();
@@ -273,7 +269,14 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
273
269
  return [(p) => p[chain[0]]];
274
270
  }
275
271
  const name = this.scope.nameOf(parameter);
276
- return [ QueryParameter.create(() => name, this.compiler.quotedLiteral) , "." , chain.map((x) => this.compiler.quotedLiteral(x)).join(".")];
272
+
273
+ // need to change name as per naming convention here...
274
+ const namingConvention = this.compiler.namingConvention;
275
+ if (scope.model && namingConvention) {
276
+ chain[0] = namingConvention(chain[0]);
277
+ }
278
+
279
+ return [ QueryParameter.create(() => name) , "." , chain.join(".")];
277
280
  }
278
281
 
279
282
  const { target, computed, property } = me;
@@ -395,9 +398,9 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
395
398
  }
396
399
  const table = this.visit(e.source);
397
400
  const where = this.visit(e.where);
398
- const as = e.as ? prepare ` AS ${ e.as.type === "QuotedLiteral"
399
- ? this.compiler.quotedLiteral(e.as.literal)
400
- : this.compiler.quotedLiteral( this.scope.nameOf(e.as) )}` : "";
401
+ const as = e.as ? prepare ` AS ${ e.as.type === "Identifier"
402
+ ? e.as.value
403
+ : this.scope.nameOf(e.as )}` : "";
401
404
  return prepare ` ${e.joinType || "LEFT"} JOIN ${table}${as} ON ${where}`;
402
405
  }
403
406
 
@@ -519,7 +522,7 @@ export default class ExpressionToSql extends Visitor<ITextQuery> {
519
522
  as: joinParameter,
520
523
  joinType,
521
524
  model: joinParameter.model,
522
- source: Expression.quotedLiteral(relation.relatedEntity.name),
525
+ source: Expression.identifier(relation.relatedEntity.name),
523
526
  where: Expression.equal(
524
527
  Expression.member(parameter, fkColumn.columnName),
525
528
  Expression.member(joinParameter, relation.relatedEntity.keys[0].columnName)