@travetto/model-sql 7.0.0-rc.1 → 7.0.0-rc.3
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/package.json +7 -7
- package/src/config.ts +5 -5
- package/src/connection/base.ts +30 -30
- package/src/connection/decorator.ts +17 -17
- package/src/dialect/base.ts +225 -157
- package/src/service.ts +52 -59
- package/src/table-manager.ts +91 -61
- package/src/types.ts +1 -1
- package/src/util.ts +75 -75
- package/support/test/query.ts +2 -2
package/src/service.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ModelType,
|
|
3
|
-
|
|
3
|
+
BulkOperation, BulkResponse, ModelCrudSupport, ModelStorageSupport, ModelBulkSupport,
|
|
4
4
|
NotFoundError, ModelRegistryIndex, ExistsError, OptionalId, ModelIdSource,
|
|
5
5
|
ModelExpiryUtil, ModelCrudUtil, ModelStorageUtil, ModelBulkUtil,
|
|
6
6
|
} from '@travetto/model';
|
|
7
7
|
import { castTo, Class } from '@travetto/runtime';
|
|
8
|
-
import { DataUtil
|
|
8
|
+
import { DataUtil } from '@travetto/schema';
|
|
9
9
|
import { AsyncContext } from '@travetto/context';
|
|
10
10
|
import { Injectable } from '@travetto/di';
|
|
11
11
|
import {
|
|
@@ -72,11 +72,11 @@ export class SQLModelService implements
|
|
|
72
72
|
)
|
|
73
73
|
)).records : [];
|
|
74
74
|
|
|
75
|
-
const allIds = new Set(all.map(
|
|
75
|
+
const allIds = new Set(all.map(type => type.id));
|
|
76
76
|
|
|
77
|
-
for (const [
|
|
78
|
-
if (!allIds.has(
|
|
79
|
-
addedIds.set(idx,
|
|
77
|
+
for (const [id, idx] of toCheck.entries()) {
|
|
78
|
+
if (!allIds.has(id)) { // If not found
|
|
79
|
+
addedIds.set(idx, id);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -99,31 +99,23 @@ export class SQLModelService implements
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
async postConstruct(): Promise<void> {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.#manager = new TableManager(this.#context, this.#dialect);
|
|
108
|
-
await ModelStorageUtil.registerModelChangeListener(this);
|
|
109
|
-
ModelExpiryUtil.registerCull(this);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
get conn(): Connection {
|
|
114
|
-
return this.#dialect.conn;
|
|
102
|
+
await this.#dialect.connection.init?.();
|
|
103
|
+
this.idSource = ModelCrudUtil.uuidSource(this.#dialect.ID_LENGTH);
|
|
104
|
+
this.#manager = new TableManager(this.#context, this.#dialect);
|
|
105
|
+
await ModelStorageUtil.storageInitialization(this);
|
|
106
|
+
ModelExpiryUtil.registerCull(this);
|
|
115
107
|
}
|
|
116
108
|
|
|
117
|
-
|
|
118
|
-
return
|
|
109
|
+
get connection(): Connection {
|
|
110
|
+
return this.#dialect.connection;
|
|
119
111
|
}
|
|
120
112
|
|
|
121
|
-
async
|
|
122
|
-
await this.#manager.
|
|
113
|
+
async exportModel<T extends ModelType>(cls: Class<T>): Promise<string> {
|
|
114
|
+
return (await this.#manager.exportTables(cls)).join('\n');
|
|
123
115
|
}
|
|
124
116
|
|
|
125
|
-
async
|
|
126
|
-
await this.#manager.
|
|
117
|
+
async upsertModel(cls: Class): Promise<void> {
|
|
118
|
+
await this.#manager.upsertTables(cls);
|
|
127
119
|
}
|
|
128
120
|
|
|
129
121
|
async deleteModel(cls: Class): Promise<void> {
|
|
@@ -144,11 +136,11 @@ export class SQLModelService implements
|
|
|
144
136
|
for (const ins of this.#dialect.getAllInsertSQL(cls, prepped)) {
|
|
145
137
|
await this.#exec(ins);
|
|
146
138
|
}
|
|
147
|
-
} catch (
|
|
148
|
-
if (
|
|
139
|
+
} catch (error) {
|
|
140
|
+
if (error instanceof ExistsError) {
|
|
149
141
|
throw new ExistsError(cls, prepped.id);
|
|
150
142
|
} else {
|
|
151
|
-
throw
|
|
143
|
+
throw error;
|
|
152
144
|
}
|
|
153
145
|
}
|
|
154
146
|
return prepped;
|
|
@@ -166,9 +158,9 @@ export class SQLModelService implements
|
|
|
166
158
|
if (item.id) {
|
|
167
159
|
await this.#deleteRaw(cls, item.id, {}, false);
|
|
168
160
|
}
|
|
169
|
-
} catch (
|
|
170
|
-
if (!(
|
|
171
|
-
throw
|
|
161
|
+
} catch (error) {
|
|
162
|
+
if (!(error instanceof NotFoundError)) {
|
|
163
|
+
throw error;
|
|
172
164
|
}
|
|
173
165
|
}
|
|
174
166
|
return await this.create(cls, item);
|
|
@@ -203,7 +195,7 @@ export class SQLModelService implements
|
|
|
203
195
|
}
|
|
204
196
|
|
|
205
197
|
@Transactional()
|
|
206
|
-
async processBulk<T extends ModelType>(cls: Class<T>, operations:
|
|
198
|
+
async processBulk<T extends ModelType>(cls: Class<T>, operations: BulkOperation<T>[]): Promise<BulkResponse> {
|
|
207
199
|
|
|
208
200
|
const { insertedIds, upsertedIds, existingUpsertedIds } = await ModelBulkUtil.preStore(cls, operations, this);
|
|
209
201
|
|
|
@@ -211,16 +203,17 @@ export class SQLModelService implements
|
|
|
211
203
|
|
|
212
204
|
await this.#checkUpsertedIds(cls,
|
|
213
205
|
addedIds,
|
|
214
|
-
new Map([...existingUpsertedIds.entries()].map(([
|
|
206
|
+
new Map([...existingUpsertedIds.entries()].map(([key, value]) => [value, key]))
|
|
215
207
|
);
|
|
216
208
|
|
|
217
|
-
const get = <K extends keyof
|
|
218
|
-
operations.map(
|
|
209
|
+
const get = <K extends keyof BulkOperation<T>>(key: K): Required<BulkOperation<T>>[K][] =>
|
|
210
|
+
operations.map(item => item[key]).filter((item): item is Required<BulkOperation<T>>[K] => !!item);
|
|
219
211
|
|
|
220
|
-
const getStatements = async (
|
|
221
|
-
(await SQLModelUtil.getInserts(cls, get(
|
|
212
|
+
const getStatements = async (key: keyof BulkOperation<T>): Promise<InsertWrapper[]> =>
|
|
213
|
+
(await SQLModelUtil.getInserts(cls, get(key))).filter(wrapper => !!wrapper.records.length);
|
|
222
214
|
|
|
223
|
-
const deletes = [{ stack: SQLModelUtil.classToStack(cls), ids: get('delete').map(
|
|
215
|
+
const deletes = [{ stack: SQLModelUtil.classToStack(cls), ids: get('delete').map(wrapper => wrapper.id) }]
|
|
216
|
+
.filter(wrapper => !!wrapper.ids.length);
|
|
224
217
|
|
|
225
218
|
const [inserts, upserts, updates] = await Promise.all([
|
|
226
219
|
getStatements('insert'),
|
|
@@ -242,19 +235,19 @@ export class SQLModelService implements
|
|
|
242
235
|
@Connected()
|
|
243
236
|
async query<T extends ModelType>(cls: Class<T>, query: PageableModelQuery<T>): Promise<T[]> {
|
|
244
237
|
await QueryVerifier.verify(cls, query);
|
|
245
|
-
const { records
|
|
238
|
+
const { records } = await this.#exec<T>(this.#dialect.getQuerySQL(cls, query, ModelQueryUtil.getWhereClause(cls, query.where)));
|
|
246
239
|
if (ModelRegistryIndex.has(cls)) {
|
|
247
|
-
await this.#dialect.fetchDependents(cls,
|
|
240
|
+
await this.#dialect.fetchDependents(cls, records, query && query.select);
|
|
248
241
|
}
|
|
249
242
|
|
|
250
|
-
const cleaned = SQLModelUtil.cleanResults<T>(this.#dialect,
|
|
251
|
-
return await Promise.all(cleaned.map(
|
|
243
|
+
const cleaned = SQLModelUtil.cleanResults<T>(this.#dialect, records);
|
|
244
|
+
return await Promise.all(cleaned.map(item => ModelCrudUtil.load(cls, item)));
|
|
252
245
|
}
|
|
253
246
|
|
|
254
247
|
@Connected()
|
|
255
248
|
async queryOne<T extends ModelType>(cls: Class<T>, builder: ModelQuery<T>, failOnMany = true): Promise<T> {
|
|
256
|
-
const
|
|
257
|
-
return ModelQueryUtil.verifyGetSingleCounts<T>(cls, failOnMany,
|
|
249
|
+
const results = await this.query<T>(cls, { ...builder, limit: failOnMany ? 2 : 1 });
|
|
250
|
+
return ModelQueryUtil.verifyGetSingleCounts<T>(cls, failOnMany, results, builder.where);
|
|
258
251
|
}
|
|
259
252
|
|
|
260
253
|
@Connected()
|
|
@@ -294,43 +287,43 @@ export class SQLModelService implements
|
|
|
294
287
|
@Connected()
|
|
295
288
|
async suggest<T extends ModelType>(cls: Class<T>, field: ValidStringFields<T>, prefix?: string, query?: PageableModelQuery<T>): Promise<T[]> {
|
|
296
289
|
await QueryVerifier.verify(cls, query);
|
|
297
|
-
const
|
|
298
|
-
const results = await this.query<T>(cls,
|
|
290
|
+
const resolvedQuery = ModelQuerySuggestUtil.getSuggestQuery<T>(cls, field, prefix, query);
|
|
291
|
+
const results = await this.query<T>(cls, resolvedQuery);
|
|
299
292
|
return ModelQuerySuggestUtil.combineSuggestResults(cls, field, prefix, results, (a, b) => b, query?.limit);
|
|
300
293
|
}
|
|
301
294
|
|
|
302
295
|
@Connected()
|
|
303
296
|
async suggestValues<T extends ModelType>(cls: Class<T>, field: ValidStringFields<T>, prefix?: string, query?: PageableModelQuery<T>): Promise<string[]> {
|
|
304
297
|
await QueryVerifier.verify(cls, query);
|
|
305
|
-
const
|
|
306
|
-
const results = await this.query(cls,
|
|
298
|
+
const resolvedQuery = ModelQuerySuggestUtil.getSuggestFieldQuery(cls, field, prefix, query);
|
|
299
|
+
const results = await this.query(cls, resolvedQuery);
|
|
307
300
|
|
|
308
301
|
const modelTypeField: ValidStringFields<ModelType> = castTo(field);
|
|
309
|
-
return ModelQuerySuggestUtil.combineSuggestResults(cls, modelTypeField, prefix, results,
|
|
302
|
+
return ModelQuerySuggestUtil.combineSuggestResults(cls, modelTypeField, prefix, results, result => result, query?.limit);
|
|
310
303
|
}
|
|
311
304
|
|
|
312
305
|
@Connected()
|
|
313
306
|
async facet<T extends ModelType>(cls: Class<T>, field: ValidStringFields<T>, query?: ModelQuery<T>): Promise<ModelQueryFacet[]> {
|
|
314
307
|
await QueryVerifier.verify(cls, query);
|
|
315
|
-
const col = this.#dialect.
|
|
316
|
-
const ttl = this.#dialect.
|
|
317
|
-
const key = this.#dialect.
|
|
318
|
-
const
|
|
308
|
+
const col = this.#dialect.identifier(field);
|
|
309
|
+
const ttl = this.#dialect.identifier('count');
|
|
310
|
+
const key = this.#dialect.identifier('key');
|
|
311
|
+
const sql = [
|
|
319
312
|
`SELECT ${col} as ${key}, COUNT(${col}) as ${ttl}`,
|
|
320
313
|
this.#dialect.getFromSQL(cls),
|
|
321
314
|
];
|
|
322
|
-
|
|
315
|
+
sql.push(
|
|
323
316
|
this.#dialect.getWhereSQL(cls, ModelQueryUtil.getWhereClause(cls, query?.where))
|
|
324
317
|
);
|
|
325
|
-
|
|
318
|
+
sql.push(
|
|
326
319
|
`GROUP BY ${col}`,
|
|
327
320
|
`ORDER BY ${ttl} DESC`
|
|
328
321
|
);
|
|
329
322
|
|
|
330
|
-
const results = await this.#exec<{ key: string, count: number }>(
|
|
331
|
-
return results.records.map(
|
|
332
|
-
|
|
333
|
-
return
|
|
323
|
+
const results = await this.#exec<{ key: string, count: number }>(sql.join('\n'));
|
|
324
|
+
return results.records.map(result => {
|
|
325
|
+
result.count = DataUtil.coerceType(result.count, Number);
|
|
326
|
+
return result;
|
|
334
327
|
});
|
|
335
328
|
}
|
|
336
329
|
}
|
package/src/table-manager.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { AsyncContext, WithAsyncContext } from '@travetto/context';
|
|
2
2
|
import { ModelRegistryIndex } from '@travetto/model';
|
|
3
3
|
import { Class } from '@travetto/runtime';
|
|
4
|
-
import {
|
|
5
|
-
import { SchemaChange } from '@travetto/schema';
|
|
4
|
+
import { SchemaRegistryIndex, type SchemaFieldConfig } from '@travetto/schema';
|
|
6
5
|
|
|
7
6
|
import { Connected, Transactional } from './connection/decorator.ts';
|
|
8
7
|
import { SQLDialect } from './dialect/base.ts';
|
|
@@ -10,6 +9,10 @@ import { SQLModelUtil } from './util.ts';
|
|
|
10
9
|
import { Connection } from './connection/base.ts';
|
|
11
10
|
import { VisitStack } from './types.ts';
|
|
12
11
|
|
|
12
|
+
type UpsertStructure = { dropIndex: string[], createIndex: string[], table: string[] };
|
|
13
|
+
const isSimpleField = (input: VisitStack | undefined): input is SchemaFieldConfig =>
|
|
14
|
+
!!input && (!('type' in input) || (input.type && !SchemaRegistryIndex.has(input.type)));
|
|
15
|
+
|
|
13
16
|
/**
|
|
14
17
|
* Manage creation/updating of all tables
|
|
15
18
|
*/
|
|
@@ -27,59 +30,108 @@ export class TableManager {
|
|
|
27
30
|
return this.#dialect.executeSQL<T>(sql);
|
|
28
31
|
}
|
|
29
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Get a valid connection
|
|
35
|
+
*/
|
|
36
|
+
get connection(): Connection {
|
|
37
|
+
return this.#dialect.connection;
|
|
38
|
+
}
|
|
39
|
+
|
|
30
40
|
/**
|
|
31
41
|
* Create all needed tables for a given class
|
|
32
42
|
*/
|
|
33
43
|
async exportTables(cls: Class): Promise<string[]> {
|
|
34
44
|
const out: string[] = [];
|
|
35
|
-
for (const
|
|
36
|
-
out.push(
|
|
45
|
+
for (const command of this.#dialect.getCreateAllTablesSQL(cls)) {
|
|
46
|
+
out.push(command);
|
|
37
47
|
}
|
|
38
48
|
const indices = ModelRegistryIndex.getConfig(cls).indices;
|
|
39
49
|
if (indices) {
|
|
40
|
-
for (const
|
|
41
|
-
out.push(
|
|
50
|
+
for (const command of this.#dialect.getCreateAllIndicesSQL(cls, indices)) {
|
|
51
|
+
out.push(command);
|
|
42
52
|
}
|
|
43
53
|
}
|
|
44
54
|
return out;
|
|
45
55
|
}
|
|
46
56
|
|
|
47
|
-
/**
|
|
48
|
-
* Create all needed tables for a given class
|
|
49
|
-
*/
|
|
50
57
|
@WithAsyncContext()
|
|
51
58
|
@Connected()
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
async getUpsertTablesSQL(cls: Class): Promise<UpsertStructure> {
|
|
60
|
+
const sqlCommands: UpsertStructure = { dropIndex: [], createIndex: [], table: [] };
|
|
61
|
+
|
|
62
|
+
const onVisit = async (type: Class, fields: SchemaFieldConfig[], path: VisitStack[]): Promise<void> => {
|
|
63
|
+
const found = await this.#dialect.describeTable(this.#dialect.namespace(path));
|
|
64
|
+
const existingFields = new Map(found?.columns.map(column => [column.name, column]) ?? []);
|
|
65
|
+
const existingIndices = new Map(found?.indices.map(index => [index.name, index]) ?? []);
|
|
66
|
+
const model = path.length === 1 ? ModelRegistryIndex.getConfig(type) : undefined;
|
|
67
|
+
const requestedIndices = new Map((model?.indices ?? []).map(index => [this.#dialect.getIndexName(type, index), index]) ?? []);
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
// Manage fields
|
|
71
|
+
if (!existingFields.size) {
|
|
72
|
+
sqlCommands.table.push(this.#dialect.getCreateTableSQL(path));
|
|
73
|
+
} else { // Existing
|
|
74
|
+
// Fields
|
|
75
|
+
const requestedFields = new Map(fields.map(field => [field.name, field]));
|
|
76
|
+
const top = path.at(-1);
|
|
77
|
+
|
|
78
|
+
if (isSimpleField(top)) {
|
|
79
|
+
requestedFields.set(top.name, top);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
for (const [column, field] of requestedFields.entries()) {
|
|
83
|
+
if (!existingFields.has(column)) {
|
|
84
|
+
sqlCommands.table.push(this.#dialect.getAddColumnSQL([...path, field]));
|
|
85
|
+
} else if (this.#dialect.isColumnChanged(field, existingFields.get(column)!)) {
|
|
86
|
+
sqlCommands.table.push(this.#dialect.getModifyColumnSQL([...path, field]));
|
|
65
87
|
}
|
|
66
|
-
|
|
67
|
-
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// TODO: Handle dropping tables that are FK'd when no longer in use
|
|
91
|
+
|
|
92
|
+
for (const column of existingFields.keys()) {
|
|
93
|
+
if (!requestedFields.has(column)) {
|
|
94
|
+
sqlCommands.table.push(this.#dialect.getDropColumnSQL([...path, { name: column, type: undefined!, array: false }]));
|
|
68
95
|
}
|
|
69
96
|
}
|
|
70
97
|
}
|
|
71
|
-
|
|
98
|
+
|
|
99
|
+
// Manage indices
|
|
100
|
+
for (const index of requestedIndices.keys()) {
|
|
101
|
+
if (!existingIndices.has(index)) {
|
|
102
|
+
sqlCommands.createIndex.push(this.#dialect.getCreateIndexSQL(type, requestedIndices.get(index)!));
|
|
103
|
+
} else if (this.#dialect.isIndexChanged(requestedIndices.get(index)!, existingIndices.get(index)!)) {
|
|
104
|
+
sqlCommands.dropIndex.push(this.#dialect.getDropIndexSQL(type, existingIndices.get(index)!.name));
|
|
105
|
+
sqlCommands.createIndex.push(this.#dialect.getCreateIndexSQL(type, requestedIndices.get(index)!));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
for (const index of existingIndices.keys()) {
|
|
110
|
+
if (!requestedIndices.has(index)) {
|
|
111
|
+
sqlCommands.dropIndex.push(this.#dialect.getDropIndexSQL(type, existingIndices.get(index)!.name));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const schema = SchemaRegistryIndex.getConfig(cls);
|
|
117
|
+
await SQLModelUtil.visitSchema(schema, {
|
|
118
|
+
onRoot: async ({ config, path, fields, descend }) => { await onVisit(config.class, fields, path); return descend(); },
|
|
119
|
+
onSub: async ({ config, path, fields, descend }) => { await onVisit(config.type, fields, path); return descend(); },
|
|
120
|
+
onSimple: async ({ config, path, fields }) => { await onVisit(config.type, fields, path); }
|
|
121
|
+
});
|
|
122
|
+
return sqlCommands;
|
|
72
123
|
}
|
|
73
124
|
|
|
74
|
-
/**
|
|
75
|
-
* Drop all tables for a given class
|
|
76
|
-
*/
|
|
77
125
|
@WithAsyncContext()
|
|
78
126
|
@Connected()
|
|
79
127
|
@Transactional()
|
|
80
|
-
async
|
|
81
|
-
|
|
82
|
-
|
|
128
|
+
async upsertTables(cls: Class): Promise<void> {
|
|
129
|
+
// Enforce id length
|
|
130
|
+
this.#dialect.enforceIdLength(cls);
|
|
131
|
+
|
|
132
|
+
const sqlCommands = await this.getUpsertTablesSQL(cls);
|
|
133
|
+
for (const key of ['dropIndex', 'table', 'createIndex'] as const) {
|
|
134
|
+
await Promise.all(sqlCommands[key].map(command => this.#exec(command)));
|
|
83
135
|
}
|
|
84
136
|
}
|
|
85
137
|
|
|
@@ -89,43 +141,21 @@ export class TableManager {
|
|
|
89
141
|
@WithAsyncContext()
|
|
90
142
|
@Connected()
|
|
91
143
|
@Transactional()
|
|
92
|
-
async
|
|
93
|
-
for (const
|
|
94
|
-
await this.#exec(
|
|
144
|
+
async dropTables(cls: Class): Promise<void> {
|
|
145
|
+
for (const command of this.#dialect.getDropAllTablesSQL(cls)) {
|
|
146
|
+
await this.#exec(command);
|
|
95
147
|
}
|
|
96
148
|
}
|
|
97
149
|
|
|
98
150
|
/**
|
|
99
|
-
*
|
|
100
|
-
*/
|
|
101
|
-
get conn(): Connection {
|
|
102
|
-
return this.#dialect.conn;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* When the schema changes, update SQL
|
|
151
|
+
* Drop all tables for a given class
|
|
107
152
|
*/
|
|
108
153
|
@WithAsyncContext()
|
|
109
|
-
@Transactional()
|
|
110
154
|
@Connected()
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const changes = change.subs.reduce<Record<ChangeEvent<unknown>['type'], VisitStack[][]>>((acc, v) => {
|
|
116
|
-
const path = v.path.map(f => ({ ...f }));
|
|
117
|
-
for (const ev of v.fields) {
|
|
118
|
-
acc[ev.type].push([...rootStack, ...path, { ...(ev.type === 'removing' ? ev.prev : ev.curr)! }]);
|
|
119
|
-
}
|
|
120
|
-
return acc;
|
|
121
|
-
}, { added: [], changed: [], removing: [] });
|
|
122
|
-
|
|
123
|
-
await Promise.all(changes.added.map(v => this.#dialect.executeSQL(this.#dialect.getAddColumnSQL(v))));
|
|
124
|
-
await Promise.all(changes.changed.map(v => this.#dialect.executeSQL(this.#dialect.getModifyColumnSQL(v))));
|
|
125
|
-
await Promise.all(changes.removing.map(v => this.#dialect.executeSQL(this.#dialect.getDropColumnSQL(v))));
|
|
126
|
-
} catch (err) {
|
|
127
|
-
// Failed to change
|
|
128
|
-
console.error('Unable to change field', { error: err });
|
|
155
|
+
@Transactional()
|
|
156
|
+
async truncateTables(cls: Class): Promise<void> {
|
|
157
|
+
for (const command of this.#dialect.getTruncateAllTablesSQL(cls)) {
|
|
158
|
+
await this.#exec(command);
|
|
129
159
|
}
|
|
130
160
|
}
|
|
131
161
|
}
|