@entity-access/entity-access 1.0.54 → 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.
- package/dist/compiler/NamingConventions.d.ts +7 -0
- package/dist/compiler/NamingConventions.d.ts.map +1 -0
- package/dist/compiler/NamingConventions.js +7 -0
- package/dist/compiler/NamingConventions.js.map +1 -0
- package/dist/compiler/QueryCompiler.d.ts +2 -2
- package/dist/compiler/QueryCompiler.d.ts.map +1 -1
- package/dist/compiler/QueryCompiler.js +8 -3
- package/dist/compiler/QueryCompiler.js.map +1 -1
- package/dist/decorators/Column.d.ts.map +1 -1
- package/dist/decorators/Column.js +3 -0
- package/dist/decorators/Column.js.map +1 -1
- package/dist/decorators/IColumn.d.ts +5 -0
- package/dist/decorators/IColumn.d.ts.map +1 -1
- package/dist/drivers/base/BaseDriver.d.ts.map +1 -1
- package/dist/drivers/base/BaseDriver.js +7 -7
- package/dist/drivers/base/BaseDriver.js.map +1 -1
- package/dist/drivers/postgres/PostgreSqlDriver.js +1 -1
- package/dist/drivers/postgres/PostgreSqlDriver.js.map +1 -1
- package/dist/drivers/sql-server/ExpressionToSqlServer.d.ts.map +1 -1
- package/dist/drivers/sql-server/ExpressionToSqlServer.js +2 -2
- package/dist/drivers/sql-server/ExpressionToSqlServer.js.map +1 -1
- package/dist/drivers/sql-server/SqlServerQueryCompiler.d.ts +1 -1
- package/dist/drivers/sql-server/SqlServerQueryCompiler.d.ts.map +1 -1
- package/dist/drivers/sql-server/SqlServerQueryCompiler.js +6 -2
- package/dist/drivers/sql-server/SqlServerQueryCompiler.js.map +1 -1
- package/dist/entity-query/EntityType.d.ts +7 -5
- package/dist/entity-query/EntityType.d.ts.map +1 -1
- package/dist/entity-query/EntityType.js +31 -14
- package/dist/entity-query/EntityType.js.map +1 -1
- package/dist/eternity/EternityStorage.d.ts +1 -1
- package/dist/eternity/EternityStorage.d.ts.map +1 -1
- package/dist/eternity/EternityStorage.js +4 -4
- package/dist/eternity/EternityStorage.js.map +1 -1
- package/dist/migrations/Migrations.d.ts.map +1 -1
- package/dist/migrations/Migrations.js +5 -4
- package/dist/migrations/Migrations.js.map +1 -1
- package/dist/migrations/postgres/PostgresAutomaticMigrations.d.ts.map +1 -1
- package/dist/migrations/postgres/PostgresAutomaticMigrations.js +17 -14
- package/dist/migrations/postgres/PostgresAutomaticMigrations.js.map +1 -1
- package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js +12 -12
- package/dist/migrations/sql-server/SqlServerAutomaticMigrations.js.map +1 -1
- package/dist/model/EntityContext.d.ts +1 -0
- package/dist/model/EntityContext.d.ts.map +1 -1
- package/dist/model/EntityContext.js +20 -0
- package/dist/model/EntityContext.js.map +1 -1
- package/dist/model/EntityModel.d.ts +4 -1
- package/dist/model/EntityModel.d.ts.map +1 -1
- package/dist/model/EntityModel.js +36 -5
- package/dist/model/EntityModel.js.map +1 -1
- package/dist/model/EntityQuery.d.ts.map +1 -1
- package/dist/model/EntityQuery.js +7 -7
- package/dist/model/EntityQuery.js.map +1 -1
- package/dist/model/SourceExpression.d.ts.map +1 -1
- package/dist/model/SourceExpression.js +3 -4
- package/dist/model/SourceExpression.js.map +1 -1
- package/dist/model/changes/ChangeEntry.js +2 -2
- package/dist/model/changes/ChangeEntry.js.map +1 -1
- package/dist/model/changes/ChangeSet.js +1 -2
- package/dist/model/changes/ChangeSet.js.map +1 -1
- package/dist/model/verification/VerificationSession.d.ts.map +1 -1
- package/dist/model/verification/VerificationSession.js +6 -6
- package/dist/model/verification/VerificationSession.js.map +1 -1
- package/dist/query/ast/DebugStringVisitor.d.ts +1 -2
- package/dist/query/ast/DebugStringVisitor.d.ts.map +1 -1
- package/dist/query/ast/DebugStringVisitor.js +0 -3
- package/dist/query/ast/DebugStringVisitor.js.map +1 -1
- package/dist/query/ast/ExpressionToSql.d.ts +1 -2
- package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
- package/dist/query/ast/ExpressionToSql.js +22 -20
- package/dist/query/ast/ExpressionToSql.js.map +1 -1
- package/dist/query/ast/Expressions.d.ts +15 -20
- package/dist/query/ast/Expressions.d.ts.map +1 -1
- package/dist/query/ast/Expressions.js +17 -19
- package/dist/query/ast/Expressions.js.map +1 -1
- package/dist/query/ast/IStringTransformer.d.ts +2 -3
- package/dist/query/ast/IStringTransformer.d.ts.map +1 -1
- package/dist/query/ast/IStringTransformer.js +4 -6
- package/dist/query/ast/IStringTransformer.js.map +1 -1
- package/dist/query/ast/Visitor.d.ts +1 -2
- package/dist/query/ast/Visitor.d.ts.map +1 -1
- package/dist/query/ast/Visitor.js +0 -5
- package/dist/query/ast/Visitor.js.map +1 -1
- package/dist/query/expander/QueryExpander.js +7 -7
- package/dist/query/expander/QueryExpander.js.map +1 -1
- package/dist/query/parser/ArrowToExpression.d.ts.map +1 -1
- package/dist/query/parser/ArrowToExpression.js +2 -2
- package/dist/query/parser/ArrowToExpression.js.map +1 -1
- package/dist/tests/eternity/eternity-tests.d.ts.map +1 -1
- package/dist/tests/eternity/eternity-tests.js +1 -1
- package/dist/tests/eternity/eternity-tests.js.map +1 -1
- package/dist/tests/expressions/left-joins/child-joins.js +41 -41
- package/dist/tests/expressions/left-joins/child-joins.js.map +1 -1
- package/dist/tests/expressions/select/select.d.ts.map +1 -1
- package/dist/tests/expressions/select/select.js +2 -2
- package/dist/tests/expressions/select/select.js.map +1 -1
- package/dist/tests/expressions/simple/parse-arrow.js +10 -10
- package/dist/tests/expressions/simple/parse-arrow.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/compiler/NamingConventions.ts +6 -0
- package/src/compiler/QueryCompiler.ts +7 -5
- package/src/decorators/Column.ts +3 -0
- package/src/decorators/IColumn.ts +7 -0
- package/src/drivers/base/BaseDriver.ts +9 -9
- package/src/drivers/postgres/PostgreSqlDriver.ts +1 -1
- package/src/drivers/sql-server/ExpressionToSqlServer.ts +2 -2
- package/src/drivers/sql-server/SqlServerQueryCompiler.ts +5 -2
- package/src/entity-query/EntityType.ts +34 -13
- package/src/eternity/EternityStorage.ts +3 -3
- package/src/migrations/Migrations.ts +5 -3
- package/src/migrations/postgres/PostgresAutomaticMigrations.ts +17 -14
- package/src/migrations/sql-server/SqlServerAutomaticMigrations.ts +12 -12
- package/src/model/EntityContext.ts +22 -1
- package/src/model/EntityModel.ts +41 -7
- package/src/model/EntityQuery.ts +7 -7
- package/src/model/SourceExpression.ts +3 -4
- package/src/model/changes/ChangeEntry.ts +2 -2
- package/src/model/changes/ChangeSet.ts +1 -1
- package/src/model/verification/VerificationSession.ts +6 -7
- package/src/query/ast/DebugStringVisitor.ts +1 -5
- package/src/query/ast/ExpressionToSql.ts +24 -21
- package/src/query/ast/Expressions.ts +33 -34
- package/src/query/ast/IStringTransformer.ts +4 -4
- package/src/query/ast/Visitor.ts +1 -7
- package/src/query/expander/QueryExpander.ts +9 -9
- package/src/query/parser/ArrowToExpression.ts +2 -2
- package/src/tests/eternity/eternity-tests.ts +2 -1
- package/src/tests/expressions/left-joins/child-joins.ts +41 -41
- package/src/tests/expressions/select/select.ts +2 -5
- 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,
|
|
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:
|
|
41
|
-
name:
|
|
40
|
+
schema: Expression.identifier(this.schema) ,
|
|
41
|
+
name: Expression.identifier(this.name)
|
|
42
42
|
})
|
|
43
|
-
:
|
|
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 =
|
|
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) =>
|
|
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
|
-
|
|
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.
|
|
14
|
-
filter: (x) => x.
|
|
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
|
|
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
|
-
|
|
14
|
-
|
|
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(
|
|
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
|
-
? `${
|
|
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
|
-
?
|
|
46
|
-
:
|
|
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 =
|
|
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
|
-
?
|
|
71
|
-
:
|
|
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 =
|
|
80
|
+
let def = iterator.columnName + " ";
|
|
81
81
|
if (iterator.autoGenerate) {
|
|
82
|
-
def += iterator.dataType === "BigInt" ? "
|
|
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
|
-
?
|
|
98
|
-
:
|
|
99
|
-
const indexName =
|
|
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 =
|
|
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
|
-
? `${
|
|
32
|
+
? `${ iterator.columnName} IS NOT NULL`
|
|
33
33
|
: "";
|
|
34
34
|
const indexDef: IIndex = {
|
|
35
|
-
name: `IX_${type.name}_${iterator.
|
|
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
|
-
?
|
|
47
|
-
:
|
|
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 =
|
|
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
|
-
?
|
|
74
|
-
:
|
|
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 =
|
|
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
|
-
?
|
|
103
|
-
:
|
|
104
|
-
const indexName =
|
|
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 =
|
|
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}'))
|
|
@@ -56,6 +56,27 @@ export default class EntityContext {
|
|
|
56
56
|
return query;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
filteredQuery<T>(type: IClassOf<T>, mode: "read" | "include" | "modify" | "delete", fail = false, parentType?, key?) {
|
|
60
|
+
const query = this.model.register(type).asQuery();
|
|
61
|
+
if (!this.verifyFilters) {
|
|
62
|
+
return query;
|
|
63
|
+
}
|
|
64
|
+
const events = this.eventsFor(type, fail);
|
|
65
|
+
if (events) {
|
|
66
|
+
switch(mode) {
|
|
67
|
+
case "read":
|
|
68
|
+
return events.filter(query) ?? query;
|
|
69
|
+
case "include":
|
|
70
|
+
return events.includeFilter(query, parentType, key) ?? query;
|
|
71
|
+
case "modify":
|
|
72
|
+
return events.modify(query) ?? query;
|
|
73
|
+
case "delete":
|
|
74
|
+
return events.delete(query) ?? query;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return query;
|
|
78
|
+
}
|
|
79
|
+
|
|
59
80
|
public async saveChanges(signal?: AbortSignal) {
|
|
60
81
|
|
|
61
82
|
if (this[isChanging]) {
|
|
@@ -160,7 +181,7 @@ export default class EntityContext {
|
|
|
160
181
|
|
|
161
182
|
protected async saveChangesWithoutEvents(signal: AbortSignal) {
|
|
162
183
|
return this.driver.runInTransaction(async () => {
|
|
163
|
-
const copy = [].concat(this.changeSet.entries);
|
|
184
|
+
const copy = [].concat(this.changeSet.entries) as ChangeEntry[];
|
|
164
185
|
for (const iterator of copy) {
|
|
165
186
|
switch (iterator.status) {
|
|
166
187
|
case "inserted":
|
package/src/model/EntityModel.ts
CHANGED
|
@@ -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
|
|
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.
|
|
46
|
+
let source = this.sources.get(type);
|
|
19
47
|
if (!source) {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
this.
|
|
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
|
}
|
package/src/model/EntityQuery.ts
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
98
|
+
const item = type?.map(iterator) ?? iterator;
|
|
99
99
|
// set identity...
|
|
100
|
-
const entry = this.context.changeSet.getEntry(
|
|
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
|
-
|
|
122
|
-
const entry = this.context.changeSet.getEntry(
|
|
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:
|
|
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.
|
|
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 {
|
|
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:
|
|
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
|
|
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.
|
|
92
|
+
const oldValue = original[iterator.name];
|
|
93
93
|
const newValue = entity[iterator.name];
|
|
94
|
-
if (entity[iterator.name] !== original[iterator.
|
|
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 =
|
|
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
|
|
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.
|
|
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
|
-
[
|
|
129
|
+
[NumberLiteral.one]
|
|
131
130
|
],
|
|
132
|
-
as:
|
|
133
|
-
fields: [
|
|
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
|
-
|
|
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,
|
|
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
|
}
|