@cheetah.js/orm 0.1.14 → 0.1.15
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/SqlBuilder.d.ts +19 -4
- package/dist/SqlBuilder.js +291 -69
- package/dist/SqlBuilder.js.map +1 -1
- package/dist/bun/index.js +225061 -0
- package/dist/bun/index.js.map +315 -0
- package/dist/decorators/one-many.decorator.js +2 -2
- package/dist/decorators/one-many.decorator.js.map +1 -1
- package/dist/domain/base-entity.js +8 -0
- package/dist/domain/base-entity.js.map +1 -1
- package/dist/driver/driver.interface.d.ts +17 -4
- package/dist/driver/pg-driver.js +1 -0
- package/dist/driver/pg-driver.js.map +1 -1
- package/package.json +1 -1
- package/test/domain/base-entity.spec.ts +81 -39
- package/test/domain/relationship.spec.ts +173 -0
package/dist/SqlBuilder.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AutoPath, FilterQuery, QueryOrderMap, ValueOrInstance } from './driver/driver.interface';
|
|
1
|
+
import { AutoPath, FilterQuery, QueryOrderMap, Statement, ValueOrInstance } from './driver/driver.interface';
|
|
2
2
|
export declare class SqlBuilder<T> {
|
|
3
3
|
private readonly driver;
|
|
4
4
|
private entityStorage;
|
|
@@ -9,8 +9,10 @@ export declare class SqlBuilder<T> {
|
|
|
9
9
|
private lastKeyNotOperator;
|
|
10
10
|
private logger;
|
|
11
11
|
private updatedColumns;
|
|
12
|
+
private originalColumns;
|
|
12
13
|
constructor(model: new () => T);
|
|
13
14
|
select(columns?: AutoPath<T, never, '*'>[]): SqlBuilder<T>;
|
|
15
|
+
setStrategy(strategy?: 'joined' | 'select'): SqlBuilder<T>;
|
|
14
16
|
insert(values: Partial<{
|
|
15
17
|
[K in keyof T]: ValueOrInstance<T[K]>;
|
|
16
18
|
}>): SqlBuilder<T>;
|
|
@@ -23,14 +25,27 @@ export declare class SqlBuilder<T> {
|
|
|
23
25
|
}) | QueryOrderMap<T>[]): SqlBuilder<T>;
|
|
24
26
|
limit(limit: number | undefined): SqlBuilder<T>;
|
|
25
27
|
offset(offset: number | undefined): SqlBuilder<T>;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
load(load: string[]): SqlBuilder<T>;
|
|
29
|
+
private addJoinForRelationshipPath;
|
|
30
|
+
private getPrimaryKeyColumnName;
|
|
29
31
|
execute(): Promise<{
|
|
30
32
|
query: any;
|
|
31
33
|
startTime: number;
|
|
32
34
|
sql: string;
|
|
33
35
|
}>;
|
|
36
|
+
executeAndReturnFirst(): Promise<T | undefined>;
|
|
37
|
+
executeAndReturnFirstOrFail(): Promise<T>;
|
|
38
|
+
executeAndReturnAll(): Promise<T[]>;
|
|
39
|
+
private handleSelectJoin;
|
|
40
|
+
getPathForSelectJoin(selectJoin: Statement<any>): string[] | null;
|
|
41
|
+
private setValueByPath;
|
|
42
|
+
private getPathForSelectJoinRecursive;
|
|
43
|
+
private findIdRecursively;
|
|
44
|
+
private generateColumns;
|
|
45
|
+
private extractAliasForColumns;
|
|
46
|
+
private filterInvalidColumns;
|
|
47
|
+
private includeUpdatedColumns;
|
|
48
|
+
private logExecution;
|
|
34
49
|
startTransaction(): Promise<void>;
|
|
35
50
|
commit(): Promise<void>;
|
|
36
51
|
rollback(): Promise<void>;
|
package/dist/SqlBuilder.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EntityStorage } from './domain/entities';
|
|
2
2
|
import { Orm } from './orm';
|
|
3
3
|
import { ValueObject } from './common/value-object';
|
|
4
|
+
import { BaseEntity } from '@cheetah.js/orm/domain/base-entity';
|
|
4
5
|
export class SqlBuilder {
|
|
5
6
|
driver;
|
|
6
7
|
entityStorage;
|
|
@@ -11,6 +12,7 @@ export class SqlBuilder {
|
|
|
11
12
|
lastKeyNotOperator = '';
|
|
12
13
|
logger;
|
|
13
14
|
updatedColumns = [];
|
|
15
|
+
originalColumns = [];
|
|
14
16
|
constructor(model) {
|
|
15
17
|
const orm = Orm.getInstance();
|
|
16
18
|
this.driver = orm.driverInstance;
|
|
@@ -23,17 +25,18 @@ export class SqlBuilder {
|
|
|
23
25
|
const schema = this.entity.schema || 'public';
|
|
24
26
|
this.statements.statement = 'select';
|
|
25
27
|
this.statements.columns = columns;
|
|
28
|
+
this.originalColumns = columns || [];
|
|
26
29
|
this.statements.alias = this.getAlias(tableName);
|
|
27
30
|
this.statements.table = `"${schema}"."${tableName}"`;
|
|
28
31
|
return this;
|
|
29
32
|
}
|
|
33
|
+
setStrategy(strategy = 'joined') {
|
|
34
|
+
this.statements.strategy = strategy;
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
30
37
|
insert(values) {
|
|
31
38
|
const { tableName, schema } = this.getTableName();
|
|
32
|
-
|
|
33
|
-
if (this.extendsFrom(ValueObject, values[value].constructor.prototype)) {
|
|
34
|
-
values[value] = values[value].getValue();
|
|
35
|
-
}
|
|
36
|
-
}
|
|
39
|
+
processValuesForInsert(values);
|
|
37
40
|
this.statements.statement = 'insert';
|
|
38
41
|
this.statements.alias = this.getAlias(tableName);
|
|
39
42
|
this.statements.table = `"${schema}"."${tableName}"`;
|
|
@@ -42,11 +45,7 @@ export class SqlBuilder {
|
|
|
42
45
|
}
|
|
43
46
|
update(values) {
|
|
44
47
|
const { tableName, schema } = this.getTableName();
|
|
45
|
-
|
|
46
|
-
if (this.extendsFrom(ValueObject, values[value].constructor.prototype)) {
|
|
47
|
-
values[value] = values[value].getValue();
|
|
48
|
-
}
|
|
49
|
-
}
|
|
48
|
+
processValuesForUpdate(values);
|
|
50
49
|
this.statements.statement = 'update';
|
|
51
50
|
this.statements.alias = this.getAlias(tableName);
|
|
52
51
|
this.statements.table = `${schema}.${tableName}`;
|
|
@@ -54,14 +53,14 @@ export class SqlBuilder {
|
|
|
54
53
|
return this;
|
|
55
54
|
}
|
|
56
55
|
where(where) {
|
|
57
|
-
if (
|
|
56
|
+
if (!where || Object.keys(where).length === 0) {
|
|
58
57
|
return this;
|
|
59
58
|
}
|
|
60
|
-
this.statements.where = this.conditionToSql(where, this.statements.alias);
|
|
59
|
+
this.statements.where = this.conditionToSql(where, this.statements.alias, this.model);
|
|
61
60
|
return this;
|
|
62
61
|
}
|
|
63
62
|
orderBy(orderBy) {
|
|
64
|
-
if (
|
|
63
|
+
if (!orderBy) {
|
|
65
64
|
return this;
|
|
66
65
|
}
|
|
67
66
|
this.statements.orderBy = this.objectToStringMap(orderBy);
|
|
@@ -75,13 +74,77 @@ export class SqlBuilder {
|
|
|
75
74
|
this.statements.offset = offset;
|
|
76
75
|
return this;
|
|
77
76
|
}
|
|
77
|
+
load(load) {
|
|
78
|
+
load?.forEach(relationshipPath => {
|
|
79
|
+
this.addJoinForRelationshipPath(this.entity, relationshipPath);
|
|
80
|
+
});
|
|
81
|
+
if (this.statements.join) {
|
|
82
|
+
this.statements.join = this.statements.join?.reverse();
|
|
83
|
+
}
|
|
84
|
+
if (this.statements.selectJoin) {
|
|
85
|
+
this.statements.selectJoin = this.statements.selectJoin?.reverse();
|
|
86
|
+
}
|
|
87
|
+
return this;
|
|
88
|
+
}
|
|
89
|
+
addJoinForRelationshipPath(entity, relationshipPath) {
|
|
90
|
+
const relationshipNames = relationshipPath.split('.');
|
|
91
|
+
let currentEntity = entity;
|
|
92
|
+
let currentAlias = this.statements.alias;
|
|
93
|
+
let statement = this.statements.strategy === 'joined' ? this.statements.join : this.statements.selectJoin;
|
|
94
|
+
let nameAliasProperty = this.statements.strategy === 'joined' ? 'joinAlias' : 'alias';
|
|
95
|
+
relationshipNames.forEach((relationshipName, index) => {
|
|
96
|
+
const relationship = currentEntity.relations.find(rel => rel.propertyKey === relationshipName);
|
|
97
|
+
if (!relationship) {
|
|
98
|
+
// @ts-ignore
|
|
99
|
+
throw new Error(`Relationship "${relationshipName}" not found in entity "${currentEntity.name}"`);
|
|
100
|
+
}
|
|
101
|
+
const isLastRelationship = index === relationshipNames.length - 1;
|
|
102
|
+
if (index === (relationshipNames.length - 2 >= 0 ? relationshipNames.length - 2 : 0)) {
|
|
103
|
+
const join = statement?.find(j => j.joinProperty === relationshipName);
|
|
104
|
+
if (join) {
|
|
105
|
+
// @ts-ignore
|
|
106
|
+
currentAlias = join[nameAliasProperty];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (relationship.relation === 'many-to-one' && isLastRelationship) {
|
|
110
|
+
this.applyJoin(relationship, {}, currentAlias);
|
|
111
|
+
statement = this.statements.strategy === 'joined' ? this.statements.join : this.statements.selectJoin;
|
|
112
|
+
currentAlias = statement[statement.length - 1][nameAliasProperty];
|
|
113
|
+
}
|
|
114
|
+
currentEntity = this.entityStorage.get(relationship.entity());
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
getPrimaryKeyColumnName(entity) {
|
|
118
|
+
// Lógica para obter o nome da coluna de chave primária da entidade
|
|
119
|
+
// Aqui você pode substituir por sua própria lógica, dependendo da estrutura do seu projeto
|
|
120
|
+
// Por exemplo, se a chave primária for sempre 'id', você pode retornar 'id'.
|
|
121
|
+
// Se a lógica for mais complexa, você pode adicionar um método na classe Options para obter a chave primária.
|
|
122
|
+
return 'id';
|
|
123
|
+
}
|
|
124
|
+
async execute() {
|
|
125
|
+
if (!this.statements.columns) {
|
|
126
|
+
this.statements.columns = this.generateColumns();
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
this.extractAliasForColumns();
|
|
130
|
+
this.filterInvalidColumns();
|
|
131
|
+
}
|
|
132
|
+
this.statements.join = this.statements.join?.reverse();
|
|
133
|
+
this.includeUpdatedColumns();
|
|
134
|
+
const result = await this.driver.executeStatement(this.statements);
|
|
135
|
+
this.logExecution(result);
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
78
138
|
async executeAndReturnFirst() {
|
|
79
139
|
this.statements.limit = 1;
|
|
80
140
|
const result = await this.execute();
|
|
81
141
|
if (result.query.rows.length === 0) {
|
|
82
142
|
return undefined;
|
|
83
143
|
}
|
|
84
|
-
|
|
144
|
+
const entities = result.query.rows[0];
|
|
145
|
+
const model = await this.transformToModel(this.model, this.statements, entities);
|
|
146
|
+
await this.handleSelectJoin(entities, model);
|
|
147
|
+
return model;
|
|
85
148
|
}
|
|
86
149
|
async executeAndReturnFirstOrFail() {
|
|
87
150
|
this.statements.limit = 1;
|
|
@@ -89,40 +152,126 @@ export class SqlBuilder {
|
|
|
89
152
|
if (result.query.rows.length === 0) {
|
|
90
153
|
throw new Error('Result not found');
|
|
91
154
|
}
|
|
92
|
-
|
|
155
|
+
const entities = result.query.rows[0];
|
|
156
|
+
const model = await this.transformToModel(this.model, this.statements, entities);
|
|
157
|
+
await this.handleSelectJoin(entities, model);
|
|
158
|
+
return model;
|
|
93
159
|
}
|
|
94
|
-
// TODO: Corrigir tipagem do retorno de acordo com o driver
|
|
95
160
|
async executeAndReturnAll() {
|
|
96
161
|
const result = await this.execute();
|
|
97
162
|
if (result.query.rows.length === 0) {
|
|
98
163
|
return [];
|
|
99
164
|
}
|
|
100
|
-
|
|
165
|
+
const rows = result.query.rows;
|
|
166
|
+
const results = [];
|
|
167
|
+
for (const row of rows) {
|
|
168
|
+
const models = this.transformToModel(this.model, this.statements, row);
|
|
169
|
+
await this.handleSelectJoin(row, models);
|
|
170
|
+
results.push(models);
|
|
171
|
+
}
|
|
172
|
+
return results;
|
|
101
173
|
}
|
|
102
|
-
async
|
|
103
|
-
if (!this.statements.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
174
|
+
async handleSelectJoin(entities, models) {
|
|
175
|
+
if (!this.statements.selectJoin || this.statements.selectJoin.length === 0) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
for (const join of this.statements.selectJoin.reverse()) {
|
|
179
|
+
let ids = entities[`${join.originAlias}_${join.primaryKey}`];
|
|
180
|
+
if (typeof ids === 'undefined') {
|
|
181
|
+
// get of models
|
|
182
|
+
const selectJoined = this.statements.selectJoin.find(j => j.joinEntity === join.originEntity);
|
|
183
|
+
if (!selectJoined) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
ids = this.findIdRecursively(models, selectJoined, join);
|
|
187
|
+
}
|
|
188
|
+
if (Array.isArray(ids)) {
|
|
189
|
+
ids = ids.map((id) => this.t(id)).join(', ');
|
|
190
|
+
}
|
|
191
|
+
if (join.where) {
|
|
192
|
+
join.where = `${join.where} AND ${join.alias}."${join.fkKey}" IN (${ids})`;
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
join.where = `${join.alias}."${join.fkKey}" IN (${ids})`;
|
|
112
196
|
}
|
|
113
|
-
|
|
197
|
+
if (join.columns && join.columns.length > 0) {
|
|
198
|
+
join.columns = join.columns.map(
|
|
199
|
+
// @ts-ignore
|
|
200
|
+
(column) => `${join.alias}."${column}" as "${join.alias}_${column}"`);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
join.columns = this.getColumnsEntity(join.joinEntity, join.alias);
|
|
204
|
+
}
|
|
205
|
+
const child = await this.driver.executeStatement(join);
|
|
206
|
+
this.logger.debug(`SQL: ${child.sql} [${Date.now() - child.startTime}ms]`);
|
|
207
|
+
const property = this.entityStorage.get(this.model).relations.find((rel) => rel.propertyKey === join.joinProperty);
|
|
208
|
+
const values = child.query.rows.map((row) => this.transformToModel(join.joinEntity, join, row));
|
|
209
|
+
const path = this.getPathForSelectJoin(join);
|
|
210
|
+
this.setValueByPath(models, path, property?.type === Array ? [...values] : values[0]);
|
|
114
211
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
212
|
+
return models;
|
|
213
|
+
}
|
|
214
|
+
getPathForSelectJoin(selectJoin) {
|
|
215
|
+
const path = this.getPathForSelectJoinRecursive(this.statements, selectJoin);
|
|
216
|
+
return path.reverse();
|
|
217
|
+
}
|
|
218
|
+
setValueByPath(obj, path, value) {
|
|
219
|
+
let currentObj = obj;
|
|
220
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
221
|
+
const key = path[i];
|
|
222
|
+
currentObj[key] = currentObj[key] || {};
|
|
223
|
+
currentObj = currentObj[key];
|
|
224
|
+
}
|
|
225
|
+
currentObj[path[path.length - 1]] = value;
|
|
226
|
+
}
|
|
227
|
+
getPathForSelectJoinRecursive(statements, selectJoin) {
|
|
228
|
+
const originJoin = this.statements.selectJoin.find(j => j.joinEntity === selectJoin.originEntity);
|
|
229
|
+
let pathInJoin = [];
|
|
230
|
+
if (!originJoin) {
|
|
231
|
+
return [selectJoin.joinProperty];
|
|
232
|
+
}
|
|
233
|
+
if (originJoin.originEntity !== statements.originEntity) {
|
|
234
|
+
pathInJoin = this.getPathForSelectJoinRecursive(statements, originJoin);
|
|
235
|
+
}
|
|
236
|
+
return [selectJoin.joinProperty, ...pathInJoin];
|
|
237
|
+
}
|
|
238
|
+
findIdRecursively(models, selectJoined, join) {
|
|
239
|
+
let ids = models[selectJoined.originProperty][join.primaryKey];
|
|
240
|
+
if (typeof ids === 'undefined') {
|
|
241
|
+
const nextSelectJoined = this.statements.selectJoin.find(j => j.joinEntity === selectJoined.originEntity);
|
|
242
|
+
if (nextSelectJoined) {
|
|
243
|
+
// Chamada recursiva para a próxima camada
|
|
244
|
+
ids = this.findIdRecursively(models, nextSelectJoined, join);
|
|
245
|
+
}
|
|
120
246
|
}
|
|
247
|
+
return ids;
|
|
248
|
+
}
|
|
249
|
+
generateColumns() {
|
|
250
|
+
let columns = [
|
|
251
|
+
...this.getColumnsEntity(this.model, this.statements.alias),
|
|
252
|
+
];
|
|
253
|
+
if (this.statements.join) {
|
|
254
|
+
columns = [
|
|
255
|
+
...columns,
|
|
256
|
+
...this.statements.join.flatMap(join => this.getColumnsEntity(join.joinEntity, join.joinAlias)),
|
|
257
|
+
];
|
|
258
|
+
}
|
|
259
|
+
return columns;
|
|
260
|
+
}
|
|
261
|
+
extractAliasForColumns() {
|
|
262
|
+
// @ts-ignore
|
|
263
|
+
this.statements.columns = this.statements.columns.map((column) => {
|
|
264
|
+
return this.discoverColumnAlias(column);
|
|
265
|
+
}).flat();
|
|
266
|
+
}
|
|
267
|
+
filterInvalidColumns() {
|
|
268
|
+
this.statements.columns = this.statements.columns.filter(Boolean);
|
|
269
|
+
}
|
|
270
|
+
includeUpdatedColumns() {
|
|
121
271
|
this.statements.columns.push(...this.updatedColumns);
|
|
122
|
-
|
|
123
|
-
|
|
272
|
+
}
|
|
273
|
+
logExecution(result) {
|
|
124
274
|
this.logger.debug(`SQL: ${result.sql} [${Date.now() - result.startTime}ms]`);
|
|
125
|
-
return result;
|
|
126
275
|
}
|
|
127
276
|
startTransaction() {
|
|
128
277
|
return this.driver.startTransaction();
|
|
@@ -169,20 +318,29 @@ export class SqlBuilder {
|
|
|
169
318
|
}
|
|
170
319
|
return `${this.statements.alias}."${column}" as ${this.statements.alias}_${column}`;
|
|
171
320
|
}
|
|
172
|
-
if (typeof this.statements.join === 'undefined') {
|
|
321
|
+
if (typeof this.statements.join === 'undefined' && typeof this.statements.selectJoin === 'undefined') {
|
|
173
322
|
throw new Error('Join not found');
|
|
174
323
|
}
|
|
175
324
|
const entities = column.split('.');
|
|
176
325
|
let lastEntity = this.model;
|
|
177
326
|
let lastAlias = this.statements.alias;
|
|
178
327
|
const relationsMap = new Map(this.entity.relations.map(rel => [rel.propertyKey, rel]));
|
|
179
|
-
const joinMap = new Map(
|
|
328
|
+
const joinMap = new Map();
|
|
329
|
+
const joinSelectMap = new Map();
|
|
330
|
+
this.statements.join?.forEach(join => joinMap.set(join.joinProperty, join));
|
|
331
|
+
this.statements.selectJoin?.forEach(join => joinSelectMap.set(join.joinProperty, join));
|
|
180
332
|
for (let i = 0; i < entities.length; i++) {
|
|
181
333
|
if (i === 0) {
|
|
182
334
|
const relation = relationsMap.get(entities[i]);
|
|
183
335
|
lastEntity = relation?.entity();
|
|
184
336
|
// @ts-ignore
|
|
185
|
-
|
|
337
|
+
if (joinMap.has(entities[i])) {
|
|
338
|
+
lastAlias = joinMap.get(entities[i]).joinAlias;
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
lastAlias = joinSelectMap.get(entities[i])?.alias;
|
|
342
|
+
return undefined;
|
|
343
|
+
}
|
|
186
344
|
}
|
|
187
345
|
else {
|
|
188
346
|
if ((i + 1) === entities.length) {
|
|
@@ -216,7 +374,7 @@ export class SqlBuilder {
|
|
|
216
374
|
addLogicalOperatorToSql(conditions, operator) {
|
|
217
375
|
return `(${conditions.join(` ${operator} `)})`;
|
|
218
376
|
}
|
|
219
|
-
conditionToSql(condition, alias) {
|
|
377
|
+
conditionToSql(condition, alias, model) {
|
|
220
378
|
const sqlParts = [];
|
|
221
379
|
const operators = ['$eq', '$ne', '$in', '$nin', '$like', '$gt', '$gte', '$lt', '$lte', '$and', '$or'];
|
|
222
380
|
for (let [key, value] of Object.entries(condition)) {
|
|
@@ -226,9 +384,13 @@ export class SqlBuilder {
|
|
|
226
384
|
if (!operators.includes(key)) {
|
|
227
385
|
this.lastKeyNotOperator = key;
|
|
228
386
|
}
|
|
229
|
-
const
|
|
387
|
+
const entity = this.entityStorage.get(model);
|
|
388
|
+
const relationShip = entity.relations?.find(rel => rel.propertyKey === key);
|
|
230
389
|
if (relationShip) {
|
|
231
|
-
|
|
390
|
+
const sql = this.applyJoin(relationShip, value, alias);
|
|
391
|
+
if (this.statements.strategy === 'joined') {
|
|
392
|
+
sqlParts.push(sql);
|
|
393
|
+
}
|
|
232
394
|
}
|
|
233
395
|
else if (typeof value !== 'object' || value === null) {
|
|
234
396
|
if (key === '$eq') {
|
|
@@ -242,7 +404,7 @@ export class SqlBuilder {
|
|
|
242
404
|
}
|
|
243
405
|
else {
|
|
244
406
|
if (['$or', '$and'].includes(key)) {
|
|
245
|
-
sqlParts.push(this.addLogicalOperatorToSql(value.map((cond) => this.conditionToSql(cond, alias)), key.toUpperCase().replace('$', '')));
|
|
407
|
+
sqlParts.push(this.addLogicalOperatorToSql(value.map((cond) => this.conditionToSql(cond, alias, model)), key.toUpperCase().replace('$', '')));
|
|
246
408
|
}
|
|
247
409
|
for (const operator of operators) {
|
|
248
410
|
if (operator in value) {
|
|
@@ -276,7 +438,7 @@ export class SqlBuilder {
|
|
|
276
438
|
break;
|
|
277
439
|
case '$and':
|
|
278
440
|
case '$or':
|
|
279
|
-
const parts = value[operator].map((cond) => this.conditionToSql(cond, alias));
|
|
441
|
+
const parts = value[operator].map((cond) => this.conditionToSql(cond, alias, model));
|
|
280
442
|
sqlParts.push(this.addLogicalOperatorToSql(parts, operator.toUpperCase().replace('$', '')));
|
|
281
443
|
break;
|
|
282
444
|
}
|
|
@@ -284,6 +446,9 @@ export class SqlBuilder {
|
|
|
284
446
|
}
|
|
285
447
|
}
|
|
286
448
|
}
|
|
449
|
+
if (sqlParts.length === 0) {
|
|
450
|
+
return '';
|
|
451
|
+
}
|
|
287
452
|
return this.addLogicalOperatorToSql(sqlParts, 'AND');
|
|
288
453
|
}
|
|
289
454
|
t(value) {
|
|
@@ -303,33 +468,52 @@ export class SqlBuilder {
|
|
|
303
468
|
}
|
|
304
469
|
}
|
|
305
470
|
const joinAlias = `${this.getAlias(joinTableName)}`;
|
|
306
|
-
const joinWhere = this.conditionToSql(value, joinAlias);
|
|
307
|
-
this.statements.join = this.statements.join || [];
|
|
471
|
+
const joinWhere = this.conditionToSql(value, joinAlias, relationShip.entity());
|
|
308
472
|
let on = '';
|
|
309
473
|
switch (relationShip.relation) {
|
|
310
474
|
case "one-to-many":
|
|
311
|
-
on = `${joinAlias}
|
|
475
|
+
on = `${joinAlias}."${this.getFkKey(relationShip)}" = ${alias}."${originPrimaryKey}"`;
|
|
312
476
|
break;
|
|
313
477
|
case "many-to-one":
|
|
314
|
-
on = `${alias}
|
|
478
|
+
on = `${alias}."${relationShip.propertyKey}" = ${joinAlias}."${this.getFkKey(relationShip)}"`;
|
|
315
479
|
break;
|
|
316
480
|
}
|
|
317
|
-
this.statements.
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
481
|
+
if (this.statements.strategy === 'joined') {
|
|
482
|
+
this.statements.join = this.statements.join || [];
|
|
483
|
+
this.statements.join.push({
|
|
484
|
+
joinAlias: joinAlias,
|
|
485
|
+
joinTable: joinTableName,
|
|
486
|
+
joinSchema: joinSchema || 'public',
|
|
487
|
+
joinWhere: joinWhere,
|
|
488
|
+
joinProperty: relationShip.propertyKey,
|
|
489
|
+
originAlias: alias,
|
|
490
|
+
originSchema: schema,
|
|
491
|
+
originTable: tableName,
|
|
492
|
+
propertyKey: relationShip.propertyKey,
|
|
493
|
+
joinEntity: relationShip.entity(),
|
|
494
|
+
type: 'LEFT',
|
|
495
|
+
// @ts-ignore
|
|
496
|
+
on,
|
|
497
|
+
originalEntity: relationShip.originalEntity,
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
this.statements.selectJoin = this.statements.selectJoin || [];
|
|
502
|
+
this.statements.selectJoin.push({
|
|
503
|
+
statement: 'select',
|
|
504
|
+
columns: this.originalColumns.filter(column => column.startsWith(`${relationShip.propertyKey}`)).map(column => column.split('.')[1]) || [],
|
|
505
|
+
table: `"${joinSchema || 'public'}"."${joinTableName}"`,
|
|
506
|
+
alias: joinAlias,
|
|
507
|
+
where: joinWhere,
|
|
508
|
+
joinProperty: relationShip.propertyKey,
|
|
509
|
+
fkKey: this.getFkKey(relationShip),
|
|
510
|
+
primaryKey: originPrimaryKey,
|
|
511
|
+
originAlias: alias,
|
|
512
|
+
originProperty: relationShip.propertyKey,
|
|
513
|
+
joinEntity: relationShip.entity(),
|
|
514
|
+
originEntity: relationShip.originalEntity,
|
|
515
|
+
});
|
|
516
|
+
}
|
|
333
517
|
return joinWhere;
|
|
334
518
|
}
|
|
335
519
|
getFkKey(relationShip) {
|
|
@@ -357,14 +541,14 @@ export class SqlBuilder {
|
|
|
357
541
|
}
|
|
358
542
|
this.entity = entity;
|
|
359
543
|
}
|
|
360
|
-
transformToModel(data) {
|
|
361
|
-
const instance = new
|
|
544
|
+
transformToModel(model, statement, data) {
|
|
545
|
+
const instance = new model();
|
|
362
546
|
instance.$_isPersisted = true;
|
|
363
547
|
const entitiesByAlias = {
|
|
364
|
-
[
|
|
548
|
+
[statement.alias]: instance,
|
|
365
549
|
};
|
|
366
550
|
const entitiesOptions = new Map();
|
|
367
|
-
entitiesOptions.set(
|
|
551
|
+
entitiesOptions.set(statement.alias, this.entityStorage.get(instance.constructor));
|
|
368
552
|
if (this.statements.join) {
|
|
369
553
|
this.statements.join.forEach(join => {
|
|
370
554
|
const joinInstance = new join.joinEntity();
|
|
@@ -428,7 +612,16 @@ export class SqlBuilder {
|
|
|
428
612
|
if (!e) {
|
|
429
613
|
throw new Error('Entity not found');
|
|
430
614
|
}
|
|
431
|
-
|
|
615
|
+
const columns = Object.keys(e.showProperties).map(key => `${alias}."${key}" as "${alias}_${key}"`);
|
|
616
|
+
if (e.relations) {
|
|
617
|
+
for (const relation of e.relations) {
|
|
618
|
+
if (relation.relation === 'many-to-one') {
|
|
619
|
+
// @ts-ignore
|
|
620
|
+
columns.push(`${alias}."${relation.propertyKey}" as "${alias}_${relation.propertyKey}"`);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
return columns;
|
|
432
625
|
}
|
|
433
626
|
withDefaultValues(values, entityOptions) {
|
|
434
627
|
const property = Object.entries(entityOptions.showProperties).filter(([_, value]) => value.options.onInsert);
|
|
@@ -468,4 +661,33 @@ export class SqlBuilder {
|
|
|
468
661
|
return false;
|
|
469
662
|
}
|
|
470
663
|
}
|
|
664
|
+
function processValuesForInsert(values) {
|
|
665
|
+
for (const value in values) {
|
|
666
|
+
if (extendsFrom(ValueObject, values[value].constructor.prototype)) {
|
|
667
|
+
values[value] = values[value].getValue();
|
|
668
|
+
continue;
|
|
669
|
+
}
|
|
670
|
+
if (values[value] instanceof BaseEntity) {
|
|
671
|
+
// @ts-ignore
|
|
672
|
+
values[value] = values[value].id; // TODO: get primary key
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
function processValuesForUpdate(values) {
|
|
677
|
+
for (const value in values) {
|
|
678
|
+
if (extendsFrom(ValueObject, values[value].constructor.prototype)) {
|
|
679
|
+
values[value] = values[value].getValue();
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
function extendsFrom(baseClass, instance) {
|
|
684
|
+
let proto = Object.getPrototypeOf(instance);
|
|
685
|
+
while (proto) {
|
|
686
|
+
if (proto === baseClass.prototype) {
|
|
687
|
+
return true;
|
|
688
|
+
}
|
|
689
|
+
proto = Object.getPrototypeOf(proto);
|
|
690
|
+
}
|
|
691
|
+
return false;
|
|
692
|
+
}
|
|
471
693
|
//# sourceMappingURL=SqlBuilder.js.map
|