• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

typeorm / typeorm / 19549987525

20 Nov 2025 08:11PM UTC coverage: 80.769% (+4.3%) from 76.433%
19549987525

push

github

web-flow
ci: run tests on commits to master and next (#11783)

Co-authored-by: Oleg "OSA413" Sokolov <OSA413@users.noreply.github.com>

26500 of 32174 branches covered (82.36%)

Branch coverage included in aggregate %.

91252 of 113615 relevant lines covered (80.32%)

88980.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.06
/src/driver/oracle/OracleQueryRunner.ts
1
import { ObjectLiteral } from "../../common/ObjectLiteral"
26✔
2
import { TypeORMError } from "../../error"
26✔
3
import { QueryFailedError } from "../../error/QueryFailedError"
26✔
4
import { QueryRunnerAlreadyReleasedError } from "../../error/QueryRunnerAlreadyReleasedError"
26✔
5
import { TransactionNotStartedError } from "../../error/TransactionNotStartedError"
26✔
6
import { ReadStream } from "../../platform/PlatformTools"
26✔
7
import { BaseQueryRunner } from "../../query-runner/BaseQueryRunner"
26✔
8
import { QueryResult } from "../../query-runner/QueryResult"
26✔
9
import { QueryRunner } from "../../query-runner/QueryRunner"
26✔
10
import { Table } from "../../schema-builder/table/Table"
26✔
11
import { TableCheck } from "../../schema-builder/table/TableCheck"
26✔
12
import { TableColumn } from "../../schema-builder/table/TableColumn"
26✔
13
import { TableExclusion } from "../../schema-builder/table/TableExclusion"
26✔
14
import { TableForeignKey } from "../../schema-builder/table/TableForeignKey"
26✔
15
import { TableIndex } from "../../schema-builder/table/TableIndex"
26✔
16
import { TableUnique } from "../../schema-builder/table/TableUnique"
26✔
17
import { View } from "../../schema-builder/view/View"
26✔
18
import { Broadcaster } from "../../subscriber/Broadcaster"
26✔
19
import { BroadcasterResult } from "../../subscriber/BroadcasterResult"
26✔
20
import { InstanceChecker } from "../../util/InstanceChecker"
26✔
21
import { OrmUtils } from "../../util/OrmUtils"
26✔
22
import { Query } from "../Query"
26✔
23
import { ColumnType } from "../types/ColumnTypes"
26✔
24
import { IsolationLevel } from "../types/IsolationLevel"
26✔
25
import { MetadataTableType } from "../types/MetadataTableType"
26✔
26
import { ReplicationMode } from "../types/ReplicationMode"
26✔
27
import { OracleDriver } from "./OracleDriver"
26✔
28

26✔
29
/**
26✔
30
 * Runs queries on a single oracle database connection.
26✔
31
 */
26✔
32
export class OracleQueryRunner extends BaseQueryRunner implements QueryRunner {
26✔
33
    // -------------------------------------------------------------------------
26✔
34
    // Public Implemented Properties
26✔
35
    // -------------------------------------------------------------------------
26✔
36

26✔
37
    /**
26✔
38
     * Database driver used by connection.
26✔
39
     */
26✔
40
    driver: OracleDriver
26✔
41

26✔
42
    // -------------------------------------------------------------------------
26✔
43
    // Protected Properties
26✔
44
    // -------------------------------------------------------------------------
26✔
45

26✔
46
    /**
26✔
47
     * Promise used to obtain a database connection for a first time.
26✔
48
     */
26✔
49
    protected databaseConnectionPromise: Promise<any>
26✔
50

26✔
51
    // -------------------------------------------------------------------------
26✔
52
    // Constructor
26✔
53
    // -------------------------------------------------------------------------
26✔
54

26✔
55
    constructor(driver: OracleDriver, mode: ReplicationMode) {
26✔
56
        super()
23,034✔
57
        this.driver = driver
23,034✔
58
        this.connection = driver.connection
23,034✔
59
        this.broadcaster = new Broadcaster(this)
23,034✔
60
        this.mode = mode
23,034✔
61
    }
23,034✔
62

26✔
63
    // -------------------------------------------------------------------------
26✔
64
    // Public Methods
26✔
65
    // -------------------------------------------------------------------------
26✔
66

26✔
67
    /**
26✔
68
     * Creates/uses database connection from the connection pool to perform further operations.
26✔
69
     * Returns obtained database connection.
26✔
70
     */
26✔
71
    connect(): Promise<any> {
26✔
72
        if (this.databaseConnection)
120,482✔
73
            return Promise.resolve(this.databaseConnection)
120,482✔
74

22,228✔
75
        if (this.databaseConnectionPromise)
22,228✔
76
            return this.databaseConnectionPromise
120,482✔
77

22,102✔
78
        if (this.mode === "slave" && this.driver.isReplicated) {
120,482!
79
            this.databaseConnectionPromise = this.driver
×
80
                .obtainSlaveConnection()
×
81
                .then((connection) => {
×
82
                    this.databaseConnection = connection
×
83
                    return this.databaseConnection
×
84
                })
×
85
        } else {
120,482✔
86
            // master
22,102✔
87
            this.databaseConnectionPromise = this.driver
22,102✔
88
                .obtainMasterConnection()
22,102✔
89
                .then((connection) => {
22,102✔
90
                    this.databaseConnection = connection
22,102✔
91
                    return this.databaseConnection
22,102✔
92
                })
22,102✔
93
        }
22,102✔
94

22,102✔
95
        return this.databaseConnectionPromise
22,102✔
96
    }
22,102✔
97

26✔
98
    /**
26✔
99
     * Releases used database connection.
26✔
100
     * You cannot use query runner methods once its released.
26✔
101
     */
26✔
102
    async release(): Promise<void> {
26✔
103
        this.isReleased = true
23,034✔
104

23,034✔
105
        if (!this.databaseConnection) {
23,034✔
106
            return
932✔
107
        }
932✔
108

22,102✔
109
        await this.databaseConnection.close()
22,102✔
110
    }
22,102✔
111

26✔
112
    /**
26✔
113
     * Starts transaction.
26✔
114
     */
26✔
115
    async startTransaction(
26✔
116
        isolationLevel: IsolationLevel = "READ COMMITTED",
17,286✔
117
    ): Promise<void> {
17,286✔
118
        if (this.isReleased) throw new QueryRunnerAlreadyReleasedError()
17,286!
119

17,286✔
120
        // await this.query("START TRANSACTION");
17,286✔
121
        if (
17,286✔
122
            isolationLevel !== "SERIALIZABLE" &&
17,286✔
123
            isolationLevel !== "READ COMMITTED"
17,282✔
124
        ) {
17,286!
125
            throw new TypeORMError(
×
126
                `Oracle only supports SERIALIZABLE and READ COMMITTED isolation`,
×
127
            )
×
128
        }
×
129

17,286✔
130
        this.isTransactionActive = true
17,286✔
131
        try {
17,286✔
132
            await this.broadcaster.broadcast("BeforeTransactionStart")
17,286✔
133
        } catch (err) {
17,286!
134
            this.isTransactionActive = false
×
135
            throw err
×
136
        }
×
137

17,286✔
138
        if (this.transactionDepth === 0) {
17,286✔
139
            await this.query(
17,254✔
140
                "SET TRANSACTION ISOLATION LEVEL " + isolationLevel,
17,254✔
141
            )
17,254✔
142
        } else {
17,286✔
143
            await this.query(`SAVEPOINT typeorm_${this.transactionDepth}`)
32✔
144
        }
32✔
145
        this.transactionDepth += 1
17,286✔
146

17,286✔
147
        await this.broadcaster.broadcast("AfterTransactionStart")
17,286✔
148
    }
17,286✔
149

26✔
150
    /**
26✔
151
     * Commits transaction.
26✔
152
     * Error will be thrown if transaction was not started.
26✔
153
     */
26✔
154
    async commitTransaction(): Promise<void> {
26✔
155
        if (!this.isTransactionActive) throw new TransactionNotStartedError()
17,240!
156

17,240✔
157
        await this.broadcaster.broadcast("BeforeTransactionCommit")
17,240✔
158

17,240✔
159
        if (this.transactionDepth === 1) {
17,240✔
160
            await this.query("COMMIT")
17,220✔
161
            this.isTransactionActive = false
17,220✔
162
        }
17,220✔
163
        this.transactionDepth -= 1
17,240✔
164

17,240✔
165
        await this.broadcaster.broadcast("AfterTransactionCommit")
17,240✔
166
    }
17,240✔
167

26✔
168
    /**
26✔
169
     * Rollbacks transaction.
26✔
170
     * Error will be thrown if transaction was not started.
26✔
171
     */
26✔
172
    async rollbackTransaction(): Promise<void> {
26✔
173
        if (!this.isTransactionActive) throw new TransactionNotStartedError()
46!
174

46✔
175
        await this.broadcaster.broadcast("BeforeTransactionRollback")
46✔
176

46✔
177
        if (this.transactionDepth > 1) {
46✔
178
            await this.query(
12✔
179
                `ROLLBACK TO SAVEPOINT typeorm_${this.transactionDepth - 1}`,
12✔
180
            )
12✔
181
        } else {
46✔
182
            await this.query("ROLLBACK")
34✔
183
            this.isTransactionActive = false
34✔
184
        }
34✔
185
        this.transactionDepth -= 1
46✔
186

46✔
187
        await this.broadcaster.broadcast("AfterTransactionRollback")
46✔
188
    }
46✔
189

26✔
190
    /**
26✔
191
     * Executes a given SQL query.
26✔
192
     */
26✔
193
    async query(
26✔
194
        query: string,
120,472✔
195
        parameters?: any[],
120,472✔
196
        useStructuredResult = false,
120,472✔
197
    ): Promise<any> {
120,472✔
198
        if (this.isReleased) throw new QueryRunnerAlreadyReleasedError()
120,472!
199

120,472✔
200
        const databaseConnection = await this.connect()
120,472✔
201

120,472✔
202
        this.driver.connection.logger.logQuery(query, parameters, this)
120,472✔
203
        await this.broadcaster.broadcast("BeforeQuery", query, parameters)
120,472✔
204

120,472✔
205
        const broadcasterResult = new BroadcasterResult()
120,472✔
206
        const queryStartTime = Date.now()
120,472✔
207

120,472✔
208
        try {
120,472✔
209
            const executionOptions = {
120,472✔
210
                autoCommit: !this.isTransactionActive,
120,472✔
211
                outFormat: this.driver.oracle.OUT_FORMAT_OBJECT,
120,472✔
212
            }
120,472✔
213

120,472✔
214
            const raw = await databaseConnection.execute(
120,472✔
215
                query,
120,472✔
216
                parameters || {},
120,472✔
217
                executionOptions,
120,472✔
218
            )
120,472✔
219

120,458✔
220
            // log slow queries if maxQueryExecution time is set
120,458✔
221
            const maxQueryExecutionTime =
120,458✔
222
                this.driver.options.maxQueryExecutionTime
120,458✔
223
            const queryEndTime = Date.now()
120,458✔
224
            const queryExecutionTime = queryEndTime - queryStartTime
120,458✔
225

120,458✔
226
            this.broadcaster.broadcastAfterQueryEvent(
120,458✔
227
                broadcasterResult,
120,458✔
228
                query,
120,458✔
229
                parameters,
120,458✔
230
                true,
120,458✔
231
                queryExecutionTime,
120,458✔
232
                raw,
120,458✔
233
                undefined,
120,458✔
234
            )
120,458✔
235

120,458✔
236
            if (
120,458✔
237
                maxQueryExecutionTime &&
120,458!
238
                queryExecutionTime > maxQueryExecutionTime
×
239
            )
120,472✔
240
                this.driver.connection.logger.logQuerySlow(
120,472!
241
                    queryExecutionTime,
×
242
                    query,
×
243
                    parameters,
×
244
                    this,
×
245
                )
×
246

120,458✔
247
            const result = new QueryResult()
120,458✔
248

120,458✔
249
            result.raw =
120,458✔
250
                raw.rows ||
120,458✔
251
                raw.outBinds ||
120,472✔
252
                raw.rowsAffected ||
120,472✔
253
                raw.implicitResults
61,760✔
254

120,472✔
255
            if (raw?.hasOwnProperty("rows") && Array.isArray(raw.rows)) {
120,472✔
256
                result.records = raw.rows
37,952✔
257
            }
37,952✔
258

120,458✔
259
            if (
120,458✔
260
                raw?.hasOwnProperty("outBinds") &&
120,472✔
261
                Array.isArray(raw.outBinds)
7,162✔
262
            ) {
120,472✔
263
                result.records = raw.outBinds
7,162✔
264
            }
7,162✔
265

120,458✔
266
            if (
120,458✔
267
                raw?.hasOwnProperty("implicitResults") &&
120,472✔
268
                Array.isArray(raw.implicitResults)
2✔
269
            ) {
120,472✔
270
                result.records = raw.implicitResults
2✔
271
            }
2✔
272

120,458✔
273
            if (raw?.hasOwnProperty("rowsAffected")) {
120,472✔
274
                result.affected = raw.rowsAffected
82,504✔
275
            }
82,504✔
276

120,458✔
277
            if (useStructuredResult) {
120,472✔
278
                return result
33,514✔
279
            } else {
120,472✔
280
                return result.raw
86,944✔
281
            }
86,944✔
282
        } catch (err) {
120,472✔
283
            this.driver.connection.logger.logQueryError(
14✔
284
                err,
14✔
285
                query,
14✔
286
                parameters,
14✔
287
                this,
14✔
288
            )
14✔
289
            this.broadcaster.broadcastAfterQueryEvent(
14✔
290
                broadcasterResult,
14✔
291
                query,
14✔
292
                parameters,
14✔
293
                false,
14✔
294
                undefined,
14✔
295
                undefined,
14✔
296
                err,
14✔
297
            )
14✔
298

14✔
299
            throw new QueryFailedError(query, parameters, err)
14✔
300
        } finally {
120,472!
301
            await broadcasterResult.wait()
120,472✔
302
        }
120,472✔
303
    }
120,472✔
304

26✔
305
    /**
26✔
306
     * Returns raw data stream.
26✔
307
     */
26✔
308
    async stream(
26✔
309
        query: string,
2✔
310
        parameters?: any[],
2✔
311
        onEnd?: Function,
2✔
312
        onError?: Function,
2✔
313
    ): Promise<ReadStream> {
2✔
314
        if (this.isReleased) {
2!
315
            throw new QueryRunnerAlreadyReleasedError()
×
316
        }
×
317

2✔
318
        const executionOptions = {
2✔
319
            autoCommit: !this.isTransactionActive,
2✔
320
            outFormat: this.driver.oracle.OUT_FORMAT_OBJECT,
2✔
321
        }
2✔
322

2✔
323
        const databaseConnection = await this.connect()
2✔
324

2✔
325
        this.driver.connection.logger.logQuery(query, parameters, this)
2✔
326

2✔
327
        try {
2✔
328
            const stream = databaseConnection.queryStream(
2✔
329
                query,
2✔
330
                parameters,
2✔
331
                executionOptions,
2✔
332
            )
2✔
333
            if (onEnd) {
2!
334
                stream.on("end", onEnd)
×
335
            }
×
336

2✔
337
            if (onError) {
2!
338
                stream.on("error", onError)
×
339
            }
×
340

2✔
341
            return stream
2✔
342
        } catch (err) {
2!
343
            this.driver.connection.logger.logQueryError(
×
344
                err,
×
345
                query,
×
346
                parameters,
×
347
                this,
×
348
            )
×
349
            throw new QueryFailedError(query, parameters, err)
×
350
        }
×
351
    }
2✔
352

26✔
353
    /**
26✔
354
     * Returns all available database names including system databases.
26✔
355
     */
26✔
356
    async getDatabases(): Promise<string[]> {
26✔
357
        return Promise.resolve([])
×
358
    }
×
359

26✔
360
    /**
26✔
361
     * Returns all available schema names including system schemas.
26✔
362
     * If database parameter specified, returns schemas of that database.
26✔
363
     */
26✔
364
    async getSchemas(database?: string): Promise<string[]> {
26✔
365
        return Promise.resolve([])
×
366
    }
×
367

26✔
368
    /**
26✔
369
     * Checks if database with the given name exist.
26✔
370
     */
26✔
371
    async hasDatabase(database: string): Promise<boolean> {
26✔
372
        try {
×
373
            const query = await this.query(
×
374
                `SELECT 1 AS "exists" FROM global_name@"${database}"`,
×
375
            )
×
376

×
377
            return query.length > 0
×
378
        } catch (e) {
×
379
            return false
×
380
        }
×
381
    }
×
382

26✔
383
    /**
26✔
384
     * Loads currently using database
26✔
385
     */
26✔
386
    async getCurrentDatabase(): Promise<undefined> {
26✔
387
        const query = await this.query(
4,190✔
388
            `SELECT SYS_CONTEXT('USERENV','DB_NAME') AS "db_name" FROM dual`,
4,190✔
389
        )
4,190✔
390
        return query[0]["db_name"]
4,190✔
391
    }
4,190✔
392

26✔
393
    /**
26✔
394
     * Checks if schema with the given name exist.
26✔
395
     */
26✔
396
    async hasSchema(schema: string): Promise<boolean> {
26✔
397
        return Promise.resolve(false)
×
398
    }
×
399

26✔
400
    /**
26✔
401
     * Loads currently using database schema
26✔
402
     */
26✔
403
    async getCurrentSchema(): Promise<string> {
26✔
404
        const query = await this.query(
4,190✔
405
            `SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') AS "schema_name" FROM dual`,
4,190✔
406
        )
4,190✔
407
        return query[0]["schema_name"]
4,190✔
408
    }
4,190✔
409

26✔
410
    /**
26✔
411
     * Checks if table with the given name exist in the database.
26✔
412
     */
26✔
413
    async hasTable(tableOrName: Table | string): Promise<boolean> {
26✔
414
        const { tableName } = this.driver.parseTableName(tableOrName)
2,844✔
415
        const sql = `SELECT "TABLE_NAME" FROM "USER_TABLES" WHERE "TABLE_NAME" = '${tableName}'`
2,844✔
416
        const result = await this.query(sql)
2,844✔
417
        return result.length ? true : false
2,844✔
418
    }
2,844✔
419

26✔
420
    /**
26✔
421
     * Checks if column with the given name exist in the given table.
26✔
422
     */
26✔
423
    async hasColumn(
26✔
424
        tableOrName: Table | string,
8✔
425
        columnName: string,
8✔
426
    ): Promise<boolean> {
8✔
427
        const { tableName } = this.driver.parseTableName(tableOrName)
8✔
428
        const sql = `SELECT "COLUMN_NAME" FROM "USER_TAB_COLS" WHERE "TABLE_NAME" = '${tableName}' AND "COLUMN_NAME" = '${columnName}'`
8✔
429
        const result = await this.query(sql)
8✔
430
        return result.length ? true : false
8✔
431
    }
8✔
432

26✔
433
    /**
26✔
434
     * Creates a new database.
26✔
435
     */
26✔
436
    async createDatabase(
26✔
437
        database: string,
×
438
        ifNotExist?: boolean,
×
439
    ): Promise<void> {
×
440
        // Even with `IF NOT EXISTS` we get:
×
441
        //   ORA-01501: CREATE DATABASE failed
×
442
        //   ORA-01100: database already mounted
×
443
        if (ifNotExist) {
×
444
            try {
×
445
                await this.query(`CREATE DATABASE IF NOT EXISTS "${database}";`)
×
446
            } catch (e) {
×
447
                // if (e instanceof QueryFailedError) {
×
448
                if (e.message.includes("ORA-01100: database already mounted")) {
×
449
                    return
×
450
                }
×
451
                // }
×
452

×
453
                throw e
×
454
            }
×
455
        } else {
×
456
            await this.query(`CREATE DATABASE "${database}"`)
×
457
        }
×
458
    }
×
459

26✔
460
    /**
26✔
461
     * Drops database.
26✔
462
     */
26✔
463
    async dropDatabase(database: string, ifExist?: boolean): Promise<void> {
26✔
464
        return Promise.resolve()
×
465
    }
×
466

26✔
467
    /**
26✔
468
     * Creates a new table schema.
26✔
469
     */
26✔
470
    async createSchema(
26✔
471
        schemaPath: string,
2✔
472
        ifNotExist?: boolean,
2✔
473
    ): Promise<void> {
2✔
474
        throw new TypeORMError(
2✔
475
            `Schema create queries are not supported by Oracle driver.`,
2✔
476
        )
2✔
477
    }
2✔
478

26✔
479
    /**
26✔
480
     * Drops table schema.
26✔
481
     */
26✔
482
    async dropSchema(schemaPath: string, ifExist?: boolean): Promise<void> {
26✔
483
        throw new TypeORMError(
×
484
            `Schema drop queries are not supported by Oracle driver.`,
×
485
        )
×
486
    }
×
487

26✔
488
    /**
26✔
489
     * Creates a new table.
26✔
490
     */
26✔
491
    async createTable(
26✔
492
        table: Table,
8,876✔
493
        ifNotExist: boolean = false,
8,876✔
494
        createForeignKeys: boolean = true,
8,876✔
495
        createIndices: boolean = true,
8,876✔
496
    ): Promise<void> {
8,876✔
497
        if (ifNotExist) {
8,876✔
498
            const isTableExist = await this.hasTable(table)
80✔
499
            if (isTableExist) return Promise.resolve()
80✔
500
        }
80✔
501
        const upQueries: Query[] = []
8,874✔
502
        const downQueries: Query[] = []
8,874✔
503

8,874✔
504
        upQueries.push(this.createTableSql(table, createForeignKeys))
8,874✔
505
        downQueries.push(this.dropTableSql(table))
8,874✔
506

8,874✔
507
        // if createForeignKeys is true, we must drop created foreign keys in down query.
8,874✔
508
        // createTable does not need separate method to create foreign keys, because it create fk's in the same query with table creation.
8,874✔
509
        if (createForeignKeys)
8,874✔
510
            table.foreignKeys.forEach((foreignKey) =>
8,876✔
511
                downQueries.push(this.dropForeignKeySql(table, foreignKey)),
122✔
512
            )
122✔
513

8,874✔
514
        if (createIndices) {
8,874✔
515
            table.indices.forEach((index) => {
8,874✔
516
                // new index may be passed without name. In this case we generate index name manually.
3,116✔
517
                if (!index.name)
3,116✔
518
                    index.name = this.connection.namingStrategy.indexName(
3,116✔
519
                        table,
6✔
520
                        index.columnNames,
6✔
521
                        index.where,
6✔
522
                    )
6✔
523
                upQueries.push(this.createIndexSql(table, index))
3,116✔
524
                downQueries.push(this.dropIndexSql(index))
3,116✔
525
            })
8,874✔
526
        }
8,874✔
527

8,874✔
528
        // if table have column with generated type, we must add the expression to the metadata table
8,874✔
529
        const generatedColumns = table.columns.filter(
8,874✔
530
            (column) => column.generatedType && column.asExpression,
8,874✔
531
        )
8,874✔
532

8,874✔
533
        for (const column of generatedColumns) {
8,876✔
534
            const insertQuery = this.insertTypeormMetadataSql({
42✔
535
                table: table.name,
42✔
536
                type: MetadataTableType.GENERATED_COLUMN,
42✔
537
                name: column.name,
42✔
538
                value: column.asExpression,
42✔
539
            })
42✔
540

42✔
541
            const deleteQuery = this.deleteTypeormMetadataSql({
42✔
542
                table: table.name,
42✔
543
                type: MetadataTableType.GENERATED_COLUMN,
42✔
544
                name: column.name,
42✔
545
            })
42✔
546

42✔
547
            upQueries.push(insertQuery)
42✔
548
            downQueries.push(deleteQuery)
42✔
549
        }
42✔
550

8,874✔
551
        await this.executeQueries(upQueries, downQueries)
8,874✔
552
    }
8,874✔
553

26✔
554
    /**
26✔
555
     * Drops the table.
26✔
556
     */
26✔
557
    async dropTable(
26✔
558
        tableOrName: Table | string,
20✔
559
        ifExist?: boolean,
20✔
560
        dropForeignKeys: boolean = true,
20✔
561
        dropIndices: boolean = true,
20✔
562
    ): Promise<void> {
20✔
563
        // It needs because if table does not exist and dropForeignKeys or dropIndices is true, we don't need
20✔
564
        // to perform drop queries for foreign keys and indices.
20✔
565
        if (ifExist) {
20!
566
            const isTableExist = await this.hasTable(tableOrName)
×
567
            if (!isTableExist) return Promise.resolve()
×
568
        }
×
569

20✔
570
        // if dropTable called with dropForeignKeys = true, we must create foreign keys in down query.
20✔
571
        const createForeignKeys: boolean = dropForeignKeys
20✔
572
        const table = InstanceChecker.isTable(tableOrName)
20✔
573
            ? tableOrName
20✔
574
            : await this.getCachedTable(tableOrName)
20✔
575
        const upQueries: Query[] = []
12✔
576
        const downQueries: Query[] = []
12✔
577

12✔
578
        if (dropIndices) {
20✔
579
            table.indices.forEach((index) => {
20✔
580
                upQueries.push(this.dropIndexSql(index))
2✔
581
                downQueries.push(this.createIndexSql(table, index))
2✔
582
            })
20✔
583
        }
20✔
584

20✔
585
        // if dropForeignKeys is true, we just drop the table, otherwise we also drop table foreign keys.
20✔
586
        // createTable does not need separate method to create foreign keys, because it create fk's in the same query with table creation.
20✔
587
        if (dropForeignKeys)
20✔
588
            table.foreignKeys.forEach((foreignKey) =>
20✔
589
                upQueries.push(this.dropForeignKeySql(table, foreignKey)),
20✔
590
            )
20✔
591

20✔
592
        upQueries.push(this.dropTableSql(table))
20✔
593
        downQueries.push(this.createTableSql(table, createForeignKeys))
20✔
594

20✔
595
        // if table had columns with generated type, we must remove the expression from the metadata table
20✔
596
        const generatedColumns = table.columns.filter(
20✔
597
            (column) => column.generatedType && column.asExpression,
20✔
598
        )
20✔
599

20✔
600
        for (const column of generatedColumns) {
20✔
601
            const deleteQuery = this.deleteTypeormMetadataSql({
6✔
602
                table: table.name,
6✔
603
                type: MetadataTableType.GENERATED_COLUMN,
6✔
604
                name: column.name,
6✔
605
            })
6✔
606

6✔
607
            const insertQuery = this.insertTypeormMetadataSql({
6✔
608
                table: table.name,
6✔
609
                type: MetadataTableType.GENERATED_COLUMN,
6✔
610
                name: column.name,
6✔
611
                value: column.asExpression,
6✔
612
            })
6✔
613

6✔
614
            upQueries.push(deleteQuery)
6✔
615
            downQueries.push(insertQuery)
6✔
616
        }
6✔
617

20✔
618
        await this.executeQueries(upQueries, downQueries)
20✔
619
    }
20✔
620

26✔
621
    /**
26✔
622
     * Creates a new view.
26✔
623
     */
26✔
624
    async createView(
26✔
625
        view: View,
52✔
626
        syncWithMetadata: boolean = false,
52✔
627
    ): Promise<void> {
52✔
628
        const upQueries: Query[] = []
52✔
629
        const downQueries: Query[] = []
52✔
630
        upQueries.push(this.createViewSql(view))
52✔
631
        if (syncWithMetadata) upQueries.push(this.insertViewDefinitionSql(view))
52✔
632
        downQueries.push(this.dropViewSql(view))
52✔
633
        if (syncWithMetadata)
52✔
634
            downQueries.push(this.deleteViewDefinitionSql(view))
52✔
635
        await this.executeQueries(upQueries, downQueries)
52✔
636
    }
52✔
637

26✔
638
    /**
26✔
639
     * Drops the view.
26✔
640
     */
26✔
641
    async dropView(target: View | string): Promise<void> {
26✔
642
        const viewName = InstanceChecker.isView(target) ? target.name : target
4!
643
        const view = await this.getCachedView(viewName)
4✔
644

4✔
645
        const upQueries: Query[] = []
4✔
646
        const downQueries: Query[] = []
4✔
647
        upQueries.push(this.deleteViewDefinitionSql(view))
4✔
648
        upQueries.push(this.dropViewSql(view))
4✔
649
        downQueries.push(this.insertViewDefinitionSql(view))
4✔
650
        downQueries.push(this.createViewSql(view))
4✔
651
        await this.executeQueries(upQueries, downQueries)
4✔
652
    }
4✔
653

26✔
654
    /**
26✔
655
     * Renames the given table.
26✔
656
     */
26✔
657
    async renameTable(
26✔
658
        oldTableOrName: Table | string,
34✔
659
        newTableName: string,
34✔
660
    ): Promise<void> {
34✔
661
        const upQueries: Query[] = []
34✔
662
        const downQueries: Query[] = []
34✔
663
        const oldTable = InstanceChecker.isTable(oldTableOrName)
34✔
664
            ? oldTableOrName
34✔
665
            : await this.getCachedTable(oldTableOrName)
34✔
666
        const newTable = oldTable.clone()
30✔
667

30✔
668
        const { database: dbName, tableName: oldTableName } =
30✔
669
            this.driver.parseTableName(oldTable)
30✔
670

30✔
671
        newTable.name = dbName ? `${dbName}.${newTableName}` : newTableName
34!
672

34✔
673
        // rename table
34✔
674
        upQueries.push(
34✔
675
            new Query(
34✔
676
                `ALTER TABLE ${this.escapePath(
34✔
677
                    oldTable,
34✔
678
                )} RENAME TO "${newTableName}"`,
34✔
679
            ),
34✔
680
        )
34✔
681
        downQueries.push(
34✔
682
            new Query(
34✔
683
                `ALTER TABLE ${this.escapePath(
34✔
684
                    newTable,
34✔
685
                )} RENAME TO "${oldTableName}"`,
34✔
686
            ),
34✔
687
        )
34✔
688

34✔
689
        // rename primary key constraint
34✔
690
        if (
34✔
691
            newTable.primaryColumns.length > 0 &&
34✔
692
            !newTable.primaryColumns[0].primaryKeyConstraintName
34✔
693
        ) {
34✔
694
            const columnNames = newTable.primaryColumns.map(
26✔
695
                (column) => column.name,
26✔
696
            )
26✔
697

26✔
698
            const oldPkName = this.connection.namingStrategy.primaryKeyName(
26✔
699
                oldTable,
26✔
700
                columnNames,
26✔
701
            )
26✔
702
            const newPkName = this.connection.namingStrategy.primaryKeyName(
26✔
703
                newTable,
26✔
704
                columnNames,
26✔
705
            )
26✔
706

26✔
707
            // build queries
26✔
708
            upQueries.push(
26✔
709
                new Query(
26✔
710
                    `ALTER TABLE ${this.escapePath(
26✔
711
                        newTable,
26✔
712
                    )} RENAME CONSTRAINT "${oldPkName}" TO "${newPkName}"`,
26✔
713
                ),
26✔
714
            )
26✔
715
            downQueries.push(
26✔
716
                new Query(
26✔
717
                    `ALTER TABLE ${this.escapePath(
26✔
718
                        newTable,
26✔
719
                    )} RENAME CONSTRAINT "${newPkName}" TO "${oldPkName}"`,
26✔
720
                ),
26✔
721
            )
26✔
722
        }
26✔
723

34✔
724
        // rename unique constraints
34✔
725
        newTable.uniques.forEach((unique) => {
34✔
726
            const oldUniqueName =
14✔
727
                this.connection.namingStrategy.uniqueConstraintName(
14✔
728
                    oldTable,
14✔
729
                    unique.columnNames,
14✔
730
                )
14✔
731

14✔
732
            // Skip renaming if Unique has user defined constraint name
14✔
733
            if (unique.name !== oldUniqueName) return
14✔
734

6✔
735
            // build new constraint name
6✔
736
            const newUniqueName =
6✔
737
                this.connection.namingStrategy.uniqueConstraintName(
6✔
738
                    newTable,
6✔
739
                    unique.columnNames,
6✔
740
                )
6✔
741

6✔
742
            // build queries
6✔
743
            upQueries.push(
6✔
744
                new Query(
6✔
745
                    `ALTER TABLE ${this.escapePath(
6✔
746
                        newTable,
6✔
747
                    )} RENAME CONSTRAINT "${
6✔
748
                        unique.name
6✔
749
                    }" TO "${newUniqueName}"`,
6✔
750
                ),
6✔
751
            )
6✔
752
            downQueries.push(
6✔
753
                new Query(
6✔
754
                    `ALTER TABLE ${this.escapePath(
6✔
755
                        newTable,
6✔
756
                    )} RENAME CONSTRAINT "${newUniqueName}" TO "${
6✔
757
                        unique.name
6✔
758
                    }"`,
6✔
759
                ),
6✔
760
            )
6✔
761

6✔
762
            // replace constraint name
6✔
763
            unique.name = newUniqueName
6✔
764
        })
34✔
765

34✔
766
        // rename index constraints
34✔
767
        newTable.indices.forEach((index) => {
34✔
768
            const oldIndexName = this.connection.namingStrategy.indexName(
20✔
769
                oldTable,
20✔
770
                index.columnNames,
20✔
771
                index.where,
20✔
772
            )
20✔
773

20✔
774
            // Skip renaming if Index has user defined constraint name
20✔
775
            if (index.name !== oldIndexName) return
20✔
776

10✔
777
            // build new constraint name
10✔
778
            const newIndexName = this.connection.namingStrategy.indexName(
10✔
779
                newTable,
10✔
780
                index.columnNames,
10✔
781
                index.where,
10✔
782
            )
10✔
783

10✔
784
            // build queries
10✔
785
            upQueries.push(
10✔
786
                new Query(
10✔
787
                    `ALTER INDEX "${index.name}" RENAME TO "${newIndexName}"`,
10✔
788
                ),
10✔
789
            )
10✔
790
            downQueries.push(
10✔
791
                new Query(
10✔
792
                    `ALTER INDEX "${newIndexName}" RENAME TO "${index.name}"`,
10✔
793
                ),
10✔
794
            )
10✔
795

10✔
796
            // replace constraint name
10✔
797
            index.name = newIndexName
10✔
798
        })
34✔
799

34✔
800
        // rename foreign key constraints
34✔
801
        newTable.foreignKeys.forEach((foreignKey) => {
34✔
802
            const oldForeignKeyName =
18✔
803
                this.connection.namingStrategy.foreignKeyName(
18✔
804
                    oldTable,
18✔
805
                    foreignKey.columnNames,
18✔
806
                    this.getTablePath(foreignKey),
18✔
807
                    foreignKey.referencedColumnNames,
18✔
808
                )
18✔
809

18✔
810
            // Skip renaming if foreign key has user defined constraint name
18✔
811
            if (foreignKey.name !== oldForeignKeyName) return
18✔
812

2✔
813
            // build new constraint name
2✔
814
            const newForeignKeyName =
2✔
815
                this.connection.namingStrategy.foreignKeyName(
2✔
816
                    newTable,
2✔
817
                    foreignKey.columnNames,
2✔
818
                    this.getTablePath(foreignKey),
2✔
819
                    foreignKey.referencedColumnNames,
2✔
820
                )
2✔
821

2✔
822
            // build queries
2✔
823
            upQueries.push(
2✔
824
                new Query(
2✔
825
                    `ALTER TABLE ${this.escapePath(
2✔
826
                        newTable,
2✔
827
                    )} RENAME CONSTRAINT "${
2✔
828
                        foreignKey.name
2✔
829
                    }" TO "${newForeignKeyName}"`,
2✔
830
                ),
2✔
831
            )
2✔
832
            downQueries.push(
2✔
833
                new Query(
2✔
834
                    `ALTER TABLE ${this.escapePath(
2✔
835
                        newTable,
2✔
836
                    )} RENAME CONSTRAINT "${newForeignKeyName}" TO "${
2✔
837
                        foreignKey.name
2✔
838
                    }"`,
2✔
839
                ),
2✔
840
            )
2✔
841

2✔
842
            // replace constraint name
2✔
843
            foreignKey.name = newForeignKeyName
2✔
844
        })
34✔
845

34✔
846
        await this.executeQueries(upQueries, downQueries)
34✔
847

34✔
848
        // rename old table and replace it in cached tabled;
34✔
849
        oldTable.name = newTable.name
34✔
850
        this.replaceCachedTable(oldTable, newTable)
34✔
851
    }
34✔
852

26✔
853
    /**
26✔
854
     * Creates a new column from the column in the table.
26✔
855
     */
26✔
856
    async addColumn(
26✔
857
        tableOrName: Table | string,
50✔
858
        column: TableColumn,
50✔
859
    ): Promise<void> {
50✔
860
        const table = InstanceChecker.isTable(tableOrName)
50✔
861
            ? tableOrName
50✔
862
            : await this.getCachedTable(tableOrName)
50✔
863
        const clonedTable = table.clone()
4✔
864
        const upQueries: Query[] = []
4✔
865
        const downQueries: Query[] = []
4✔
866

4✔
867
        upQueries.push(
4✔
868
            new Query(
4✔
869
                `ALTER TABLE ${this.escapePath(
4✔
870
                    table,
4✔
871
                )} ADD ${this.buildCreateColumnSql(column)}`,
4✔
872
            ),
4✔
873
        )
4✔
874
        downQueries.push(
4✔
875
            new Query(
4✔
876
                `ALTER TABLE ${this.escapePath(table)} DROP COLUMN "${
4✔
877
                    column.name
4✔
878
                }"`,
4✔
879
            ),
4✔
880
        )
4✔
881

4✔
882
        // create or update primary key constraint
4✔
883
        if (column.isPrimary) {
50✔
884
            const primaryColumns = clonedTable.primaryColumns
14✔
885
            // if table already have primary key, me must drop it and recreate again
14✔
886
            if (primaryColumns.length > 0) {
14✔
887
                const pkName = primaryColumns[0].primaryKeyConstraintName
2✔
888
                    ? primaryColumns[0].primaryKeyConstraintName
2!
889
                    : this.connection.namingStrategy.primaryKeyName(
2✔
890
                          clonedTable,
2✔
891
                          primaryColumns.map((column) => column.name),
2✔
892
                      )
2✔
893

2✔
894
                const columnNames = primaryColumns
2✔
895
                    .map((column) => `"${column.name}"`)
2✔
896
                    .join(", ")
2✔
897

2✔
898
                upQueries.push(
2✔
899
                    new Query(
2✔
900
                        `ALTER TABLE ${this.escapePath(
2✔
901
                            table,
2✔
902
                        )} DROP CONSTRAINT "${pkName}"`,
2✔
903
                    ),
2✔
904
                )
2✔
905
                downQueries.push(
2✔
906
                    new Query(
2✔
907
                        `ALTER TABLE ${this.escapePath(
2✔
908
                            table,
2✔
909
                        )} ADD CONSTRAINT "${pkName}" PRIMARY KEY (${columnNames})`,
2✔
910
                    ),
2✔
911
                )
2✔
912
            }
2✔
913

14✔
914
            primaryColumns.push(column)
14✔
915
            const pkName = primaryColumns[0].primaryKeyConstraintName
14✔
916
                ? primaryColumns[0].primaryKeyConstraintName
14!
917
                : this.connection.namingStrategy.primaryKeyName(
14✔
918
                      clonedTable,
14✔
919
                      primaryColumns.map((column) => column.name),
14✔
920
                  )
14✔
921

14✔
922
            const columnNames = primaryColumns
14✔
923
                .map((column) => `"${column.name}"`)
14✔
924
                .join(", ")
14✔
925

14✔
926
            upQueries.push(
14✔
927
                new Query(
14✔
928
                    `ALTER TABLE ${this.escapePath(
14✔
929
                        table,
14✔
930
                    )} ADD CONSTRAINT "${pkName}" PRIMARY KEY (${columnNames})`,
14✔
931
                ),
14✔
932
            )
14✔
933
            downQueries.push(
14✔
934
                new Query(
14✔
935
                    `ALTER TABLE ${this.escapePath(
14✔
936
                        table,
14✔
937
                    )} DROP CONSTRAINT "${pkName}"`,
14✔
938
                ),
14✔
939
            )
14✔
940
        }
14✔
941

50✔
942
        // create column index
50✔
943
        const columnIndex = clonedTable.indices.find(
50✔
944
            (index) =>
50✔
945
                index.columnNames.length === 1 &&
2✔
946
                index.columnNames[0] === column.name,
50✔
947
        )
50✔
948
        if (columnIndex) {
50!
949
            clonedTable.indices.splice(
×
950
                clonedTable.indices.indexOf(columnIndex),
×
951
                1,
×
952
            )
×
953
            upQueries.push(this.createIndexSql(table, columnIndex))
×
954
            downQueries.push(this.dropIndexSql(columnIndex))
×
955
        }
×
956

50✔
957
        // create unique constraint
50✔
958
        if (column.isUnique) {
50✔
959
            const uniqueConstraint = new TableUnique({
6✔
960
                name: this.connection.namingStrategy.uniqueConstraintName(
6✔
961
                    table,
6✔
962
                    [column.name],
6✔
963
                ),
6✔
964
                columnNames: [column.name],
6✔
965
            })
6✔
966
            clonedTable.uniques.push(uniqueConstraint)
6✔
967
            upQueries.push(
6✔
968
                new Query(
6✔
969
                    `ALTER TABLE ${this.escapePath(table)} ADD CONSTRAINT "${
6✔
970
                        uniqueConstraint.name
6✔
971
                    }" UNIQUE ("${column.name}")`,
6✔
972
                ),
6✔
973
            )
6✔
974
            downQueries.push(
6✔
975
                new Query(
6✔
976
                    `ALTER TABLE ${this.escapePath(table)} DROP CONSTRAINT "${
6✔
977
                        uniqueConstraint.name
6✔
978
                    }"`,
6✔
979
                ),
6✔
980
            )
6✔
981
        }
6✔
982

50✔
983
        if (column.generatedType && column.asExpression) {
50✔
984
            const insertQuery = this.insertTypeormMetadataSql({
4✔
985
                table: table.name,
4✔
986
                type: MetadataTableType.GENERATED_COLUMN,
4✔
987
                name: column.name,
4✔
988
                value: column.asExpression,
4✔
989
            })
4✔
990

4✔
991
            const deleteQuery = this.deleteTypeormMetadataSql({
4✔
992
                table: table.name,
4✔
993
                type: MetadataTableType.GENERATED_COLUMN,
4✔
994
                name: column.name,
4✔
995
            })
4✔
996

4✔
997
            upQueries.push(insertQuery)
4✔
998
            downQueries.push(deleteQuery)
4✔
999
        }
4✔
1000

50✔
1001
        await this.executeQueries(upQueries, downQueries)
50✔
1002

48✔
1003
        clonedTable.addColumn(column)
48✔
1004
        this.replaceCachedTable(table, clonedTable)
48✔
1005
    }
48✔
1006

26✔
1007
    /**
26✔
1008
     * Creates a new columns from the column in the table.
26✔
1009
     */
26✔
1010
    async addColumns(
26✔
1011
        tableOrName: Table | string,
8✔
1012
        columns: TableColumn[],
8✔
1013
    ): Promise<void> {
8✔
1014
        for (const column of columns) {
8✔
1015
            await this.addColumn(tableOrName, column)
10✔
1016
        }
10✔
1017
    }
8✔
1018

26✔
1019
    /**
26✔
1020
     * Renames column in the given table.
26✔
1021
     */
26✔
1022
    async renameColumn(
26✔
1023
        tableOrName: Table | string,
26✔
1024
        oldTableColumnOrName: TableColumn | string,
26✔
1025
        newTableColumnOrName: TableColumn | string,
26✔
1026
    ): Promise<void> {
26✔
1027
        const table = InstanceChecker.isTable(tableOrName)
26✔
1028
            ? tableOrName
26✔
1029
            : await this.getCachedTable(tableOrName)
26✔
1030
        const oldColumn = InstanceChecker.isTableColumn(oldTableColumnOrName)
4✔
1031
            ? oldTableColumnOrName
26✔
1032
            : table.columns.find((c) => c.name === oldTableColumnOrName)
26✔
1033
        if (!oldColumn)
26✔
1034
            throw new TypeORMError(
26!
1035
                `Column "${oldTableColumnOrName}" was not found in the ${this.escapePath(
×
1036
                    table,
×
1037
                )} table.`,
×
1038
            )
×
1039

26✔
1040
        let newColumn: TableColumn | undefined = undefined
26✔
1041
        if (InstanceChecker.isTableColumn(newTableColumnOrName)) {
26✔
1042
            newColumn = newTableColumnOrName
16✔
1043
        } else {
26✔
1044
            newColumn = oldColumn.clone()
10✔
1045
            newColumn.name = newTableColumnOrName
10✔
1046
        }
10✔
1047

26✔
1048
        await this.changeColumn(table, oldColumn, newColumn)
26✔
1049
    }
26✔
1050

26✔
1051
    /**
26✔
1052
     * Changes a column in the table.
26✔
1053
     */
26✔
1054
    async changeColumn(
26✔
1055
        tableOrName: Table | string,
96✔
1056
        oldTableColumnOrName: TableColumn | string,
96✔
1057
        newColumn: TableColumn,
96✔
1058
    ): Promise<void> {
96✔
1059
        const table = InstanceChecker.isTable(tableOrName)
96✔
1060
            ? tableOrName
96✔
1061
            : await this.getCachedTable(tableOrName)
96!
1062
        let clonedTable = table.clone()
×
1063
        const upQueries: Query[] = []
×
1064
        const downQueries: Query[] = []
×
1065

×
1066
        const oldColumn = InstanceChecker.isTableColumn(oldTableColumnOrName)
×
1067
            ? oldTableColumnOrName
96✔
1068
            : table.columns.find(
96!
1069
                  (column) => column.name === oldTableColumnOrName,
×
1070
              )
96✔
1071
        if (!oldColumn)
96✔
1072
            throw new TypeORMError(
96!
1073
                `Column "${oldTableColumnOrName}" was not found in the ${this.escapePath(
×
1074
                    table,
×
1075
                )} table.`,
×
1076
            )
×
1077

96✔
1078
        if (
96✔
1079
            (newColumn.isGenerated !== oldColumn.isGenerated &&
96✔
1080
                newColumn.generationStrategy !== "uuid") ||
96✔
1081
            oldColumn.type !== newColumn.type ||
96✔
1082
            oldColumn.length !== newColumn.length ||
96✔
1083
            oldColumn.generatedType !== newColumn.generatedType ||
96✔
1084
            oldColumn.asExpression !== newColumn.asExpression
66✔
1085
        ) {
96✔
1086
            // Oracle does not support changing of IDENTITY column, so we must drop column and recreate it again.
32✔
1087
            // Also, we recreate column if column type changed
32✔
1088
            await this.dropColumn(table, oldColumn)
32✔
1089
            await this.addColumn(table, newColumn)
32✔
1090

32✔
1091
            // update cloned table
32✔
1092
            clonedTable = table.clone()
32✔
1093
        } else {
96✔
1094
            if (newColumn.name !== oldColumn.name) {
64✔
1095
                // rename column
44✔
1096
                upQueries.push(
44✔
1097
                    new Query(
44✔
1098
                        `ALTER TABLE ${this.escapePath(table)} RENAME COLUMN "${
44✔
1099
                            oldColumn.name
44✔
1100
                        }" TO "${newColumn.name}"`,
44✔
1101
                    ),
44✔
1102
                )
44✔
1103
                downQueries.push(
44✔
1104
                    new Query(
44✔
1105
                        `ALTER TABLE ${this.escapePath(table)} RENAME COLUMN "${
44✔
1106
                            newColumn.name
44✔
1107
                        }" TO "${oldColumn.name}"`,
44✔
1108
                    ),
44✔
1109
                )
44✔
1110

44✔
1111
                // rename column primary key constraint
44✔
1112
                if (
44✔
1113
                    oldColumn.isPrimary === true &&
44✔
1114
                    !oldColumn.primaryKeyConstraintName
14✔
1115
                ) {
44✔
1116
                    const primaryColumns = clonedTable.primaryColumns
10✔
1117

10✔
1118
                    // build old primary constraint name
10✔
1119
                    const columnNames = primaryColumns.map(
10✔
1120
                        (column) => column.name,
10✔
1121
                    )
10✔
1122
                    const oldPkName =
10✔
1123
                        this.connection.namingStrategy.primaryKeyName(
10✔
1124
                            clonedTable,
10✔
1125
                            columnNames,
10✔
1126
                        )
10✔
1127

10✔
1128
                    // replace old column name with new column name
10✔
1129
                    columnNames.splice(columnNames.indexOf(oldColumn.name), 1)
10✔
1130
                    columnNames.push(newColumn.name)
10✔
1131

10✔
1132
                    // build new primary constraint name
10✔
1133
                    const newPkName =
10✔
1134
                        this.connection.namingStrategy.primaryKeyName(
10✔
1135
                            clonedTable,
10✔
1136
                            columnNames,
10✔
1137
                        )
10✔
1138

10✔
1139
                    upQueries.push(
10✔
1140
                        new Query(
10✔
1141
                            `ALTER TABLE ${this.escapePath(
10✔
1142
                                table,
10✔
1143
                            )} RENAME CONSTRAINT "${oldPkName}" TO "${newPkName}"`,
10✔
1144
                        ),
10✔
1145
                    )
10✔
1146
                    downQueries.push(
10✔
1147
                        new Query(
10✔
1148
                            `ALTER TABLE ${this.escapePath(
10✔
1149
                                table,
10✔
1150
                            )} RENAME CONSTRAINT "${newPkName}" TO "${oldPkName}"`,
10✔
1151
                        ),
10✔
1152
                    )
10✔
1153
                }
10✔
1154

44✔
1155
                // rename unique constraints
44✔
1156
                clonedTable.findColumnUniques(oldColumn).forEach((unique) => {
44✔
1157
                    const oldUniqueName =
16✔
1158
                        this.connection.namingStrategy.uniqueConstraintName(
16✔
1159
                            clonedTable,
16✔
1160
                            unique.columnNames,
16✔
1161
                        )
16✔
1162

16✔
1163
                    // Skip renaming if Unique has user defined constraint name
16✔
1164
                    if (unique.name !== oldUniqueName) return
16✔
1165

8✔
1166
                    // build new constraint name
8✔
1167
                    unique.columnNames.splice(
8✔
1168
                        unique.columnNames.indexOf(oldColumn.name),
8✔
1169
                        1,
8✔
1170
                    )
8✔
1171
                    unique.columnNames.push(newColumn.name)
8✔
1172
                    const newUniqueName =
8✔
1173
                        this.connection.namingStrategy.uniqueConstraintName(
8✔
1174
                            clonedTable,
8✔
1175
                            unique.columnNames,
8✔
1176
                        )
8✔
1177

8✔
1178
                    // build queries
8✔
1179
                    upQueries.push(
8✔
1180
                        new Query(
8✔
1181
                            `ALTER TABLE ${this.escapePath(
8✔
1182
                                table,
8✔
1183
                            )} RENAME CONSTRAINT "${
8✔
1184
                                unique.name
8✔
1185
                            }" TO "${newUniqueName}"`,
8✔
1186
                        ),
8✔
1187
                    )
8✔
1188
                    downQueries.push(
8✔
1189
                        new Query(
8✔
1190
                            `ALTER TABLE ${this.escapePath(
8✔
1191
                                table,
8✔
1192
                            )} RENAME CONSTRAINT "${newUniqueName}" TO "${
8✔
1193
                                unique.name
8✔
1194
                            }"`,
8✔
1195
                        ),
8✔
1196
                    )
8✔
1197

8✔
1198
                    // replace constraint name
8✔
1199
                    unique.name = newUniqueName
8✔
1200
                })
44✔
1201

44✔
1202
                // rename index constraints
44✔
1203
                clonedTable.findColumnIndices(oldColumn).forEach((index) => {
44✔
1204
                    const oldIndexName =
14✔
1205
                        this.connection.namingStrategy.indexName(
14✔
1206
                            clonedTable,
14✔
1207
                            index.columnNames,
14✔
1208
                            index.where,
14✔
1209
                        )
14✔
1210

14✔
1211
                    // Skip renaming if Index has user defined constraint name
14✔
1212
                    if (index.name !== oldIndexName) return
14✔
1213

10✔
1214
                    // build new constraint name
10✔
1215
                    index.columnNames.splice(
10✔
1216
                        index.columnNames.indexOf(oldColumn.name),
10✔
1217
                        1,
10✔
1218
                    )
10✔
1219
                    index.columnNames.push(newColumn.name)
10✔
1220
                    const newIndexName =
10✔
1221
                        this.connection.namingStrategy.indexName(
10✔
1222
                            clonedTable,
10✔
1223
                            index.columnNames,
10✔
1224
                            index.where,
10✔
1225
                        )
10✔
1226

10✔
1227
                    // build queries
10✔
1228
                    upQueries.push(
10✔
1229
                        new Query(
10✔
1230
                            `ALTER INDEX "${index.name}" RENAME TO "${newIndexName}"`,
10✔
1231
                        ),
10✔
1232
                    )
10✔
1233
                    downQueries.push(
10✔
1234
                        new Query(
10✔
1235
                            `ALTER INDEX "${newIndexName}" RENAME TO "${index.name}"`,
10✔
1236
                        ),
10✔
1237
                    )
10✔
1238

10✔
1239
                    // replace constraint name
10✔
1240
                    index.name = newIndexName
10✔
1241
                })
44✔
1242

44✔
1243
                // rename foreign key constraints
44✔
1244
                clonedTable
44✔
1245
                    .findColumnForeignKeys(oldColumn)
44✔
1246
                    .forEach((foreignKey) => {
44✔
1247
                        const foreignKeyName =
18✔
1248
                            this.connection.namingStrategy.foreignKeyName(
18✔
1249
                                clonedTable,
18✔
1250
                                foreignKey.columnNames,
18✔
1251
                                this.getTablePath(foreignKey),
18✔
1252
                                foreignKey.referencedColumnNames,
18✔
1253
                            )
18✔
1254

18✔
1255
                        // Skip renaming if foreign key has user defined constraint name
18✔
1256
                        if (foreignKey.name !== foreignKeyName) return
18✔
1257

2✔
1258
                        // build new constraint name
2✔
1259
                        foreignKey.columnNames.splice(
2✔
1260
                            foreignKey.columnNames.indexOf(oldColumn.name),
2✔
1261
                            1,
2✔
1262
                        )
2✔
1263
                        foreignKey.columnNames.push(newColumn.name)
2✔
1264
                        const newForeignKeyName =
2✔
1265
                            this.connection.namingStrategy.foreignKeyName(
2✔
1266
                                clonedTable,
2✔
1267
                                foreignKey.columnNames,
2✔
1268
                                this.getTablePath(foreignKey),
2✔
1269
                                foreignKey.referencedColumnNames,
2✔
1270
                            )
2✔
1271

2✔
1272
                        // build queries
2✔
1273
                        upQueries.push(
2✔
1274
                            new Query(
2✔
1275
                                `ALTER TABLE ${this.escapePath(
2✔
1276
                                    table,
2✔
1277
                                )} RENAME CONSTRAINT "${
2✔
1278
                                    foreignKey.name
2✔
1279
                                }" TO "${newForeignKeyName}"`,
2✔
1280
                            ),
2✔
1281
                        )
2✔
1282
                        downQueries.push(
2✔
1283
                            new Query(
2✔
1284
                                `ALTER TABLE ${this.escapePath(
2✔
1285
                                    table,
2✔
1286
                                )} RENAME CONSTRAINT "${newForeignKeyName}" TO "${
2✔
1287
                                    foreignKey.name
2✔
1288
                                }"`,
2✔
1289
                            ),
2✔
1290
                        )
2✔
1291

2✔
1292
                        // replace constraint name
2✔
1293
                        foreignKey.name = newForeignKeyName
2✔
1294
                    })
44✔
1295

44✔
1296
                // rename old column in the Table object
44✔
1297
                const oldTableColumn = clonedTable.columns.find(
44✔
1298
                    (column) => column.name === oldColumn.name,
44✔
1299
                )
44✔
1300
                clonedTable.columns[
44✔
1301
                    clonedTable.columns.indexOf(oldTableColumn!)
44✔
1302
                ].name = newColumn.name
44✔
1303
                oldColumn.name = newColumn.name
44✔
1304
            }
44✔
1305

64✔
1306
            if (this.isColumnChanged(oldColumn, newColumn, true)) {
64✔
1307
                let defaultUp: string = ""
4✔
1308
                let defaultDown: string = ""
4✔
1309
                let nullableUp: string = ""
4✔
1310
                let nullableDown: string = ""
4✔
1311

4✔
1312
                // changing column default
4✔
1313
                if (
4✔
1314
                    newColumn.default !== null &&
4✔
1315
                    newColumn.default !== undefined
4✔
1316
                ) {
4✔
1317
                    defaultUp = `DEFAULT ${newColumn.default}`
4✔
1318

4✔
1319
                    if (
4✔
1320
                        oldColumn.default !== null &&
4✔
1321
                        oldColumn.default !== undefined
4✔
1322
                    ) {
4✔
1323
                        defaultDown = `DEFAULT ${oldColumn.default}`
2✔
1324
                    } else {
2✔
1325
                        defaultDown = "DEFAULT NULL"
2✔
1326
                    }
2✔
1327
                } else if (
4!
1328
                    oldColumn.default !== null &&
×
1329
                    oldColumn.default !== undefined
×
1330
                ) {
×
1331
                    defaultUp = "DEFAULT NULL"
×
1332
                    defaultDown = `DEFAULT ${oldColumn.default}`
×
1333
                }
×
1334

4✔
1335
                // changing column isNullable property
4✔
1336
                if (newColumn.isNullable !== oldColumn.isNullable) {
4!
1337
                    if (newColumn.isNullable === true) {
×
1338
                        nullableUp = "NULL"
×
1339
                        nullableDown = "NOT NULL"
×
1340
                    } else {
×
1341
                        nullableUp = "NOT NULL"
×
1342
                        nullableDown = "NULL"
×
1343
                    }
×
1344
                }
×
1345

4✔
1346
                upQueries.push(
4✔
1347
                    new Query(
4✔
1348
                        `ALTER TABLE ${this.escapePath(table)} MODIFY "${
4✔
1349
                            oldColumn.name
4✔
1350
                        }" ${this.connection.driver.createFullType(
4✔
1351
                            newColumn,
4✔
1352
                        )} ${defaultUp} ${nullableUp}`,
4✔
1353
                    ),
4✔
1354
                )
4✔
1355
                downQueries.push(
4✔
1356
                    new Query(
4✔
1357
                        `ALTER TABLE ${this.escapePath(table)} MODIFY "${
4✔
1358
                            oldColumn.name
4✔
1359
                        }" ${this.connection.driver.createFullType(
4✔
1360
                            oldColumn,
4✔
1361
                        )} ${defaultDown} ${nullableDown}`,
4✔
1362
                    ),
4✔
1363
                )
4✔
1364
            }
4✔
1365

64✔
1366
            if (newColumn.isPrimary !== oldColumn.isPrimary) {
64✔
1367
                const primaryColumns = clonedTable.primaryColumns
6✔
1368

6✔
1369
                // if primary column state changed, we must always drop existed constraint.
6✔
1370
                if (primaryColumns.length > 0) {
6✔
1371
                    const pkName = primaryColumns[0].primaryKeyConstraintName
6✔
1372
                        ? primaryColumns[0].primaryKeyConstraintName
6!
1373
                        : this.connection.namingStrategy.primaryKeyName(
6✔
1374
                              clonedTable,
6✔
1375
                              primaryColumns.map((column) => column.name),
6✔
1376
                          )
6✔
1377

6✔
1378
                    const columnNames = primaryColumns
6✔
1379
                        .map((column) => `"${column.name}"`)
6✔
1380
                        .join(", ")
6✔
1381

6✔
1382
                    upQueries.push(
6✔
1383
                        new Query(
6✔
1384
                            `ALTER TABLE ${this.escapePath(
6✔
1385
                                table,
6✔
1386
                            )} DROP CONSTRAINT "${pkName}"`,
6✔
1387
                        ),
6✔
1388
                    )
6✔
1389
                    downQueries.push(
6✔
1390
                        new Query(
6✔
1391
                            `ALTER TABLE ${this.escapePath(
6✔
1392
                                table,
6✔
1393
                            )} ADD CONSTRAINT "${pkName}" PRIMARY KEY (${columnNames})`,
6✔
1394
                        ),
6✔
1395
                    )
6✔
1396
                }
6✔
1397

6✔
1398
                if (newColumn.isPrimary === true) {
6✔
1399
                    primaryColumns.push(newColumn)
2✔
1400
                    // update column in table
2✔
1401
                    const column = clonedTable.columns.find(
2✔
1402
                        (column) => column.name === newColumn.name,
2✔
1403
                    )
2✔
1404
                    column!.isPrimary = true
2✔
1405
                    const pkName = primaryColumns[0].primaryKeyConstraintName
2✔
1406
                        ? primaryColumns[0].primaryKeyConstraintName
2!
1407
                        : this.connection.namingStrategy.primaryKeyName(
2✔
1408
                              clonedTable,
2✔
1409
                              primaryColumns.map((column) => column.name),
2✔
1410
                          )
2✔
1411

2✔
1412
                    const columnNames = primaryColumns
2✔
1413
                        .map((column) => `"${column.name}"`)
2✔
1414
                        .join(", ")
2✔
1415

2✔
1416
                    upQueries.push(
2✔
1417
                        new Query(
2✔
1418
                            `ALTER TABLE ${this.escapePath(
2✔
1419
                                table,
2✔
1420
                            )} ADD CONSTRAINT "${pkName}" PRIMARY KEY (${columnNames})`,
2✔
1421
                        ),
2✔
1422
                    )
2✔
1423
                    downQueries.push(
2✔
1424
                        new Query(
2✔
1425
                            `ALTER TABLE ${this.escapePath(
2✔
1426
                                table,
2✔
1427
                            )} DROP CONSTRAINT "${pkName}"`,
2✔
1428
                        ),
2✔
1429
                    )
2✔
1430
                } else {
6✔
1431
                    const primaryColumn = primaryColumns.find(
4✔
1432
                        (c) => c.name === newColumn.name,
4✔
1433
                    )
4✔
1434
                    primaryColumns.splice(
4✔
1435
                        primaryColumns.indexOf(primaryColumn!),
4✔
1436
                        1,
4✔
1437
                    )
4✔
1438

4✔
1439
                    // update column in table
4✔
1440
                    const column = clonedTable.columns.find(
4✔
1441
                        (column) => column.name === newColumn.name,
4✔
1442
                    )
4✔
1443
                    column!.isPrimary = false
4✔
1444

4✔
1445
                    // if we have another primary keys, we must recreate constraint.
4✔
1446
                    if (primaryColumns.length > 0) {
4✔
1447
                        const pkName = primaryColumns[0]
2✔
1448
                            .primaryKeyConstraintName
2✔
1449
                            ? primaryColumns[0].primaryKeyConstraintName
2!
1450
                            : this.connection.namingStrategy.primaryKeyName(
2✔
1451
                                  clonedTable,
2✔
1452
                                  primaryColumns.map((column) => column.name),
2✔
1453
                              )
2✔
1454

2✔
1455
                        const columnNames = primaryColumns
2✔
1456
                            .map((column) => `"${column.name}"`)
2✔
1457
                            .join(", ")
2✔
1458

2✔
1459
                        upQueries.push(
2✔
1460
                            new Query(
2✔
1461
                                `ALTER TABLE ${this.escapePath(
2✔
1462
                                    table,
2✔
1463
                                )} ADD CONSTRAINT "${pkName}" PRIMARY KEY (${columnNames})`,
2✔
1464
                            ),
2✔
1465
                        )
2✔
1466
                        downQueries.push(
2✔
1467
                            new Query(
2✔
1468
                                `ALTER TABLE ${this.escapePath(
2✔
1469
                                    table,
2✔
1470
                                )} DROP CONSTRAINT "${pkName}"`,
2✔
1471
                            ),
2✔
1472
                        )
2✔
1473
                    }
2✔
1474
                }
4✔
1475
            }
6✔
1476

64✔
1477
            if (newColumn.isUnique !== oldColumn.isUnique) {
64✔
1478
                if (newColumn.isUnique === true) {
2✔
1479
                    const uniqueConstraint = new TableUnique({
2✔
1480
                        name: this.connection.namingStrategy.uniqueConstraintName(
2✔
1481
                            table,
2✔
1482
                            [newColumn.name],
2✔
1483
                        ),
2✔
1484
                        columnNames: [newColumn.name],
2✔
1485
                    })
2✔
1486
                    clonedTable.uniques.push(uniqueConstraint)
2✔
1487
                    upQueries.push(
2✔
1488
                        new Query(
2✔
1489
                            `ALTER TABLE ${this.escapePath(
2✔
1490
                                table,
2✔
1491
                            )} ADD CONSTRAINT "${
2✔
1492
                                uniqueConstraint.name
2✔
1493
                            }" UNIQUE ("${newColumn.name}")`,
2✔
1494
                        ),
2✔
1495
                    )
2✔
1496
                    downQueries.push(
2✔
1497
                        new Query(
2✔
1498
                            `ALTER TABLE ${this.escapePath(
2✔
1499
                                table,
2✔
1500
                            )} DROP CONSTRAINT "${uniqueConstraint.name}"`,
2✔
1501
                        ),
2✔
1502
                    )
2✔
1503
                } else {
2!
1504
                    const uniqueConstraint = clonedTable.uniques.find(
×
1505
                        (unique) => {
×
1506
                            return (
×
1507
                                unique.columnNames.length === 1 &&
×
1508
                                !!unique.columnNames.find(
×
1509
                                    (columnName) =>
×
1510
                                        columnName === newColumn.name,
×
1511
                                )
×
1512
                            )
×
1513
                        },
×
1514
                    )
×
1515
                    clonedTable.uniques.splice(
×
1516
                        clonedTable.uniques.indexOf(uniqueConstraint!),
×
1517
                        1,
×
1518
                    )
×
1519
                    upQueries.push(
×
1520
                        new Query(
×
1521
                            `ALTER TABLE ${this.escapePath(
×
1522
                                table,
×
1523
                            )} DROP CONSTRAINT "${uniqueConstraint!.name}"`,
×
1524
                        ),
×
1525
                    )
×
1526
                    downQueries.push(
×
1527
                        new Query(
×
1528
                            `ALTER TABLE ${this.escapePath(
×
1529
                                table,
×
1530
                            )} ADD CONSTRAINT "${
×
1531
                                uniqueConstraint!.name
×
1532
                            }" UNIQUE ("${newColumn.name}")`,
×
1533
                        ),
×
1534
                    )
×
1535
                }
×
1536
            }
2✔
1537

64✔
1538
            await this.executeQueries(upQueries, downQueries)
64✔
1539
            this.replaceCachedTable(table, clonedTable)
64✔
1540
        }
64✔
1541
    }
96✔
1542

26✔
1543
    /**
26✔
1544
     * Changes a column in the table.
26✔
1545
     */
26✔
1546
    async changeColumns(
26✔
1547
        tableOrName: Table | string,
46✔
1548
        changedColumns: { newColumn: TableColumn; oldColumn: TableColumn }[],
46✔
1549
    ): Promise<void> {
46✔
1550
        for (const { oldColumn, newColumn } of changedColumns) {
46✔
1551
            await this.changeColumn(tableOrName, oldColumn, newColumn)
58✔
1552
        }
58✔
1553
    }
46✔
1554

26✔
1555
    /**
26✔
1556
     * Drops column in the table.
26✔
1557
     */
26✔
1558
    async dropColumn(
26✔
1559
        tableOrName: Table | string,
66✔
1560
        columnOrName: TableColumn | string,
66✔
1561
    ): Promise<void> {
66✔
1562
        const table = InstanceChecker.isTable(tableOrName)
66✔
1563
            ? tableOrName
66✔
1564
            : await this.getCachedTable(tableOrName)
66✔
1565
        const column = InstanceChecker.isTableColumn(columnOrName)
6✔
1566
            ? columnOrName
66✔
1567
            : table.findColumnByName(columnOrName)
66✔
1568
        if (!column)
66✔
1569
            throw new TypeORMError(
66✔
1570
                `Column "${columnOrName}" was not found in table ${this.escapePath(
2✔
1571
                    table,
2✔
1572
                )}`,
2✔
1573
            )
2✔
1574

64✔
1575
        const clonedTable = table.clone()
64✔
1576
        const upQueries: Query[] = []
64✔
1577
        const downQueries: Query[] = []
64✔
1578

64✔
1579
        // drop primary key constraint
64✔
1580
        if (column.isPrimary) {
66✔
1581
            const pkName = column.primaryKeyConstraintName
14✔
1582
                ? column.primaryKeyConstraintName
14!
1583
                : this.connection.namingStrategy.primaryKeyName(
14✔
1584
                      clonedTable,
14✔
1585
                      clonedTable.primaryColumns.map((column) => column.name),
14✔
1586
                  )
14✔
1587

14✔
1588
            const columnNames = clonedTable.primaryColumns
14✔
1589
                .map((primaryColumn) => `"${primaryColumn.name}"`)
14✔
1590
                .join(", ")
14✔
1591

14✔
1592
            upQueries.push(
14✔
1593
                new Query(
14✔
1594
                    `ALTER TABLE ${this.escapePath(
14✔
1595
                        clonedTable,
14✔
1596
                    )} DROP CONSTRAINT "${pkName}"`,
14✔
1597
                ),
14✔
1598
            )
14✔
1599
            downQueries.push(
14✔
1600
                new Query(
14✔
1601
                    `ALTER TABLE ${this.escapePath(
14✔
1602
                        clonedTable,
14✔
1603
                    )} ADD CONSTRAINT "${pkName}" PRIMARY KEY (${columnNames})`,
14✔
1604
                ),
14✔
1605
            )
14✔
1606

14✔
1607
            // update column in table
14✔
1608
            const tableColumn = clonedTable.findColumnByName(column.name)
14✔
1609
            tableColumn!.isPrimary = false
14✔
1610

14✔
1611
            // if primary key have multiple columns, we must recreate it without dropped column
14✔
1612
            if (clonedTable.primaryColumns.length > 0) {
14!
1613
                const pkName = clonedTable.primaryColumns[0]
×
1614
                    .primaryKeyConstraintName
×
1615
                    ? clonedTable.primaryColumns[0].primaryKeyConstraintName
×
1616
                    : this.connection.namingStrategy.primaryKeyName(
×
1617
                          clonedTable,
×
1618
                          clonedTable.primaryColumns.map(
×
1619
                              (column) => column.name,
×
1620
                          ),
×
1621
                      )
×
1622

×
1623
                const columnNames = clonedTable.primaryColumns
×
1624
                    .map((primaryColumn) => `"${primaryColumn.name}"`)
×
1625
                    .join(", ")
×
1626

×
1627
                upQueries.push(
×
1628
                    new Query(
×
1629
                        `ALTER TABLE ${this.escapePath(
×
1630
                            clonedTable,
×
1631
                        )} ADD CONSTRAINT "${pkName}" PRIMARY KEY (${columnNames})`,
×
1632
                    ),
×
1633
                )
×
1634
                downQueries.push(
×
1635
                    new Query(
×
1636
                        `ALTER TABLE ${this.escapePath(
×
1637
                            clonedTable,
×
1638
                        )} DROP CONSTRAINT "${pkName}"`,
×
1639
                    ),
×
1640
                )
×
1641
            }
×
1642
        }
14✔
1643

64✔
1644
        // drop column index
64✔
1645
        const columnIndex = clonedTable.indices.find(
64✔
1646
            (index) =>
64✔
1647
                index.columnNames.length === 1 &&
2✔
1648
                index.columnNames[0] === column.name,
64✔
1649
        )
64✔
1650
        if (columnIndex) {
66!
1651
            upQueries.push(this.dropIndexSql(columnIndex))
×
1652
            downQueries.push(this.createIndexSql(table, columnIndex))
×
1653
        }
×
1654

64✔
1655
        // drop column check
64✔
1656
        const columnCheck = clonedTable.checks.find(
64✔
1657
            (check) =>
64✔
1658
                !!check.columnNames &&
32✔
1659
                check.columnNames.length === 1 &&
32✔
1660
                check.columnNames[0] === column.name,
64✔
1661
        )
64✔
1662
        if (columnCheck) {
66✔
1663
            clonedTable.checks.splice(
4✔
1664
                clonedTable.checks.indexOf(columnCheck),
4✔
1665
                1,
4✔
1666
            )
4✔
1667
            upQueries.push(this.dropCheckConstraintSql(table, columnCheck))
4✔
1668
            downQueries.push(this.createCheckConstraintSql(table, columnCheck))
4✔
1669
        }
4✔
1670

64✔
1671
        // drop column unique
64✔
1672
        const columnUnique = clonedTable.uniques.find(
64✔
1673
            (unique) =>
64✔
1674
                unique.columnNames.length === 1 &&
54✔
1675
                unique.columnNames[0] === column.name,
64✔
1676
        )
64✔
1677
        if (columnUnique) {
66✔
1678
            clonedTable.uniques.splice(
6✔
1679
                clonedTable.uniques.indexOf(columnUnique),
6✔
1680
                1,
6✔
1681
            )
6✔
1682
            upQueries.push(this.dropUniqueConstraintSql(table, columnUnique))
6✔
1683
            downQueries.push(
6✔
1684
                this.createUniqueConstraintSql(table, columnUnique),
6✔
1685
            )
6✔
1686
        }
6✔
1687

64✔
1688
        upQueries.push(
64✔
1689
            new Query(
64✔
1690
                `ALTER TABLE ${this.escapePath(table)} DROP COLUMN "${
64✔
1691
                    column.name
64✔
1692
                }"`,
64✔
1693
            ),
64✔
1694
        )
64✔
1695
        downQueries.push(
64✔
1696
            new Query(
64✔
1697
                `ALTER TABLE ${this.escapePath(
64✔
1698
                    table,
64✔
1699
                )} ADD ${this.buildCreateColumnSql(column)}`,
64✔
1700
            ),
64✔
1701
        )
64✔
1702

64✔
1703
        if (column.generatedType && column.asExpression) {
66✔
1704
            const deleteQuery = this.deleteTypeormMetadataSql({
6✔
1705
                table: table.name,
6✔
1706
                type: MetadataTableType.GENERATED_COLUMN,
6✔
1707
                name: column.name,
6✔
1708
            })
6✔
1709
            const insertQuery = this.insertTypeormMetadataSql({
6✔
1710
                table: table.name,
6✔
1711
                type: MetadataTableType.GENERATED_COLUMN,
6✔
1712
                name: column.name,
6✔
1713
                value: column.asExpression,
6✔
1714
            })
6✔
1715

6✔
1716
            upQueries.push(deleteQuery)
6✔
1717
            downQueries.push(insertQuery)
6✔
1718
        }
6✔
1719

64✔
1720
        await this.executeQueries(upQueries, downQueries)
64✔
1721

64✔
1722
        clonedTable.removeColumn(column)
64✔
1723
        this.replaceCachedTable(table, clonedTable)
64✔
1724
    }
64✔
1725

26✔
1726
    /**
26✔
1727
     * Drops the columns in the table.
26✔
1728
     */
26✔
1729
    async dropColumns(
26✔
1730
        tableOrName: Table | string,
10✔
1731
        columns: TableColumn[] | string[],
10✔
1732
    ): Promise<void> {
10✔
1733
        for (const column of [...columns]) {
10✔
1734
            await this.dropColumn(tableOrName, column)
26✔
1735
        }
26✔
1736
    }
10✔
1737

26✔
1738
    /**
26✔
1739
     * Creates a new primary key.
26✔
1740
     */
26✔
1741
    async createPrimaryKey(
26✔
1742
        tableOrName: Table | string,
4✔
1743
        columnNames: string[],
4✔
1744
        constraintName?: string,
4✔
1745
    ): Promise<void> {
4✔
1746
        const table = InstanceChecker.isTable(tableOrName)
4✔
1747
            ? tableOrName
4!
1748
            : await this.getCachedTable(tableOrName)
4✔
1749
        const clonedTable = table.clone()
4✔
1750

4✔
1751
        const up = this.createPrimaryKeySql(table, columnNames, constraintName)
4✔
1752

4✔
1753
        // mark columns as primary, because dropPrimaryKeySql build constraint name from table primary column names.
4✔
1754
        clonedTable.columns.forEach((column) => {
4✔
1755
            if (columnNames.find((columnName) => columnName === column.name))
10✔
1756
                column.isPrimary = true
10✔
1757
        })
4✔
1758
        const down = this.dropPrimaryKeySql(clonedTable)
4✔
1759

4✔
1760
        await this.executeQueries(up, down)
4✔
1761
        this.replaceCachedTable(table, clonedTable)
4✔
1762
    }
4✔
1763

26✔
1764
    /**
26✔
1765
     * Updates composite primary keys.
26✔
1766
     */
26✔
1767
    async updatePrimaryKeys(
26✔
1768
        tableOrName: Table | string,
4✔
1769
        columns: TableColumn[],
4✔
1770
    ): Promise<void> {
4✔
1771
        const table = InstanceChecker.isTable(tableOrName)
4✔
1772
            ? tableOrName
4✔
1773
            : await this.getCachedTable(tableOrName)
4!
1774
        const columnNames = columns.map((column) => column.name)
×
1775
        const clonedTable = table.clone()
×
1776
        const upQueries: Query[] = []
×
1777
        const downQueries: Query[] = []
×
1778

×
1779
        // if table already have primary columns, we must drop them.
×
1780
        const primaryColumns = clonedTable.primaryColumns
×
1781
        if (primaryColumns.length > 0) {
4✔
1782
            const pkName = primaryColumns[0].primaryKeyConstraintName
4✔
1783
                ? primaryColumns[0].primaryKeyConstraintName
4!
1784
                : this.connection.namingStrategy.primaryKeyName(
4✔
1785
                      clonedTable,
4✔
1786
                      primaryColumns.map((column) => column.name),
4✔
1787
                  )
4✔
1788

4✔
1789
            const columnNamesString = primaryColumns
4✔
1790
                .map((column) => `"${column.name}"`)
4✔
1791
                .join(", ")
4✔
1792

4✔
1793
            upQueries.push(
4✔
1794
                new Query(
4✔
1795
                    `ALTER TABLE ${this.escapePath(
4✔
1796
                        table,
4✔
1797
                    )} DROP CONSTRAINT "${pkName}"`,
4✔
1798
                ),
4✔
1799
            )
4✔
1800
            downQueries.push(
4✔
1801
                new Query(
4✔
1802
                    `ALTER TABLE ${this.escapePath(
4✔
1803
                        table,
4✔
1804
                    )} ADD CONSTRAINT "${pkName}" PRIMARY KEY (${columnNamesString})`,
4✔
1805
                ),
4✔
1806
            )
4✔
1807
        }
4✔
1808

4✔
1809
        // update columns in table.
4✔
1810
        clonedTable.columns
4✔
1811
            .filter((column) => columnNames.indexOf(column.name) !== -1)
4✔
1812
            .forEach((column) => (column.isPrimary = true))
4✔
1813

4✔
1814
        const pkName = primaryColumns[0].primaryKeyConstraintName
4✔
1815
            ? primaryColumns[0].primaryKeyConstraintName
4!
1816
            : this.connection.namingStrategy.primaryKeyName(
4✔
1817
                  clonedTable,
4✔
1818
                  columnNames,
4✔
1819
              )
4✔
1820

4✔
1821
        const columnNamesString = columnNames
4✔
1822
            .map((columnName) => `"${columnName}"`)
4✔
1823
            .join(", ")
4✔
1824
        upQueries.push(
4✔
1825
            new Query(
4✔
1826
                `ALTER TABLE ${this.escapePath(
4✔
1827
                    table,
4✔
1828
                )} ADD CONSTRAINT "${pkName}" PRIMARY KEY (${columnNamesString})`,
4✔
1829
            ),
4✔
1830
        )
4✔
1831
        downQueries.push(
4✔
1832
            new Query(
4✔
1833
                `ALTER TABLE ${this.escapePath(
4✔
1834
                    table,
4✔
1835
                )} DROP CONSTRAINT "${pkName}"`,
4✔
1836
            ),
4✔
1837
        )
4✔
1838

4✔
1839
        await this.executeQueries(upQueries, downQueries)
4✔
1840
        this.replaceCachedTable(table, clonedTable)
4✔
1841
    }
4✔
1842

26✔
1843
    /**
26✔
1844
     * Drops a primary key.
26✔
1845
     */
26✔
1846
    async dropPrimaryKey(
26✔
1847
        tableOrName: Table | string,
6✔
1848
        constraintName?: string,
6✔
1849
    ): Promise<void> {
6✔
1850
        const table = InstanceChecker.isTable(tableOrName)
6✔
1851
            ? tableOrName
6✔
1852
            : await this.getCachedTable(tableOrName)
6!
1853
        const up = this.dropPrimaryKeySql(table)
×
1854
        const down = this.createPrimaryKeySql(
×
1855
            table,
×
1856
            table.primaryColumns.map((column) => column.name),
✔
1857
            constraintName,
×
1858
        )
×
1859
        await this.executeQueries(up, down)
×
1860
        table.primaryColumns.forEach((column) => {
6✔
1861
            column.isPrimary = false
6✔
1862
        })
6✔
1863
    }
6✔
1864

26✔
1865
    /**
26✔
1866
     * Creates a new unique constraint.
26✔
1867
     */
26✔
1868
    async createUniqueConstraint(
26✔
1869
        tableOrName: Table | string,
16✔
1870
        uniqueConstraint: TableUnique,
16✔
1871
    ): Promise<void> {
16✔
1872
        const table = InstanceChecker.isTable(tableOrName)
16✔
1873
            ? tableOrName
16✔
1874
            : await this.getCachedTable(tableOrName)
16✔
1875

12✔
1876
        // new unique constraint may be passed without name. In this case we generate unique name manually.
12✔
1877
        if (!uniqueConstraint.name)
12✔
1878
            uniqueConstraint.name =
16✔
1879
                this.connection.namingStrategy.uniqueConstraintName(
4✔
1880
                    table,
4✔
1881
                    uniqueConstraint.columnNames,
4✔
1882
                )
4✔
1883

16✔
1884
        const up = this.createUniqueConstraintSql(table, uniqueConstraint)
16✔
1885
        const down = this.dropUniqueConstraintSql(table, uniqueConstraint)
16✔
1886
        await this.executeQueries(up, down)
16✔
1887
        table.addUniqueConstraint(uniqueConstraint)
16✔
1888
    }
16✔
1889

26✔
1890
    /**
26✔
1891
     * Creates a new unique constraints.
26✔
1892
     */
26✔
1893
    async createUniqueConstraints(
26✔
1894
        tableOrName: Table | string,
6✔
1895
        uniqueConstraints: TableUnique[],
6✔
1896
    ): Promise<void> {
6✔
1897
        const promises = uniqueConstraints.map((uniqueConstraint) =>
6✔
1898
            this.createUniqueConstraint(tableOrName, uniqueConstraint),
6✔
1899
        )
6✔
1900
        await Promise.all(promises)
6✔
1901
    }
6✔
1902

26✔
1903
    /**
26✔
1904
     * Drops a unique constraint.
26✔
1905
     */
26✔
1906
    async dropUniqueConstraint(
26✔
1907
        tableOrName: Table | string,
16✔
1908
        uniqueOrName: TableUnique | string,
16✔
1909
    ): Promise<void> {
16✔
1910
        const table = InstanceChecker.isTable(tableOrName)
16✔
1911
            ? tableOrName
16✔
1912
            : await this.getCachedTable(tableOrName)
16✔
1913
        const uniqueConstraint = InstanceChecker.isTableUnique(uniqueOrName)
8✔
1914
            ? uniqueOrName
16✔
1915
            : table.uniques.find((u) => u.name === uniqueOrName)
16!
1916
        if (!uniqueConstraint)
16✔
1917
            throw new TypeORMError(
16!
1918
                `Supplied unique constraint was not found in table ${table.name}`,
×
1919
            )
×
1920

16✔
1921
        const up = this.dropUniqueConstraintSql(table, uniqueConstraint)
16✔
1922
        const down = this.createUniqueConstraintSql(table, uniqueConstraint)
16✔
1923
        await this.executeQueries(up, down)
16✔
1924
        table.removeUniqueConstraint(uniqueConstraint)
16✔
1925
    }
16✔
1926

26✔
1927
    /**
26✔
1928
     * Creates a unique constraints.
26✔
1929
     */
26✔
1930
    async dropUniqueConstraints(
26✔
1931
        tableOrName: Table | string,
8✔
1932
        uniqueConstraints: TableUnique[],
8✔
1933
    ): Promise<void> {
8✔
1934
        const promises = uniqueConstraints.map((uniqueConstraint) =>
8✔
1935
            this.dropUniqueConstraint(tableOrName, uniqueConstraint),
8✔
1936
        )
8✔
1937
        await Promise.all(promises)
8✔
1938
    }
8✔
1939

26✔
1940
    /**
26✔
1941
     * Creates new check constraint.
26✔
1942
     */
26✔
1943
    async createCheckConstraint(
26✔
1944
        tableOrName: Table | string,
10✔
1945
        checkConstraint: TableCheck,
10✔
1946
    ): Promise<void> {
10✔
1947
        const table = InstanceChecker.isTable(tableOrName)
10✔
1948
            ? tableOrName
10✔
1949
            : await this.getCachedTable(tableOrName)
10✔
1950

6✔
1951
        // new unique constraint may be passed without name. In this case we generate unique name manually.
6✔
1952
        if (!checkConstraint.name)
6✔
1953
            checkConstraint.name =
6✔
1954
                this.connection.namingStrategy.checkConstraintName(
6✔
1955
                    table,
6✔
1956
                    checkConstraint.expression!,
6✔
1957
                )
6✔
1958

10✔
1959
        const up = this.createCheckConstraintSql(table, checkConstraint)
10✔
1960
        const down = this.dropCheckConstraintSql(table, checkConstraint)
10✔
1961
        await this.executeQueries(up, down)
10✔
1962
        table.addCheckConstraint(checkConstraint)
10✔
1963
    }
10✔
1964

26✔
1965
    /**
26✔
1966
     * Creates new check constraints.
26✔
1967
     */
26✔
1968
    async createCheckConstraints(
26✔
1969
        tableOrName: Table | string,
4✔
1970
        checkConstraints: TableCheck[],
4✔
1971
    ): Promise<void> {
4✔
1972
        const promises = checkConstraints.map((checkConstraint) =>
4✔
1973
            this.createCheckConstraint(tableOrName, checkConstraint),
4✔
1974
        )
4✔
1975
        await Promise.all(promises)
4✔
1976
    }
4✔
1977

26✔
1978
    /**
26✔
1979
     * Drops check constraint.
26✔
1980
     */
26✔
1981
    async dropCheckConstraint(
26✔
1982
        tableOrName: Table | string,
6✔
1983
        checkOrName: TableCheck | string,
6✔
1984
    ): Promise<void> {
6✔
1985
        const table = InstanceChecker.isTable(tableOrName)
6✔
1986
            ? tableOrName
6✔
1987
            : await this.getCachedTable(tableOrName)
6!
1988
        const checkConstraint = InstanceChecker.isTableCheck(checkOrName)
×
1989
            ? checkOrName
6✔
1990
            : table.checks.find((c) => c.name === checkOrName)
6!
1991
        if (!checkConstraint)
6✔
1992
            throw new TypeORMError(
6!
1993
                `Supplied check constraint was not found in table ${table.name}`,
×
1994
            )
×
1995

6✔
1996
        const up = this.dropCheckConstraintSql(table, checkConstraint)
6✔
1997
        const down = this.createCheckConstraintSql(table, checkConstraint)
6✔
1998
        await this.executeQueries(up, down)
6✔
1999
        table.removeCheckConstraint(checkConstraint)
6✔
2000
    }
6✔
2001

26✔
2002
    /**
26✔
2003
     * Drops check constraints.
26✔
2004
     */
26✔
2005
    async dropCheckConstraints(
26✔
2006
        tableOrName: Table | string,
4✔
2007
        checkConstraints: TableCheck[],
4✔
2008
    ): Promise<void> {
4✔
2009
        const promises = checkConstraints.map((checkConstraint) =>
4✔
2010
            this.dropCheckConstraint(tableOrName, checkConstraint),
4✔
2011
        )
4✔
2012
        await Promise.all(promises)
4✔
2013
    }
4✔
2014

26✔
2015
    /**
26✔
2016
     * Creates a new exclusion constraint.
26✔
2017
     */
26✔
2018
    async createExclusionConstraint(
26✔
2019
        tableOrName: Table | string,
×
2020
        exclusionConstraint: TableExclusion,
×
2021
    ): Promise<void> {
×
2022
        throw new TypeORMError(`Oracle does not support exclusion constraints.`)
×
2023
    }
×
2024

26✔
2025
    /**
26✔
2026
     * Creates a new exclusion constraints.
26✔
2027
     */
26✔
2028
    async createExclusionConstraints(
26✔
2029
        tableOrName: Table | string,
×
2030
        exclusionConstraints: TableExclusion[],
×
2031
    ): Promise<void> {
×
2032
        throw new TypeORMError(`Oracle does not support exclusion constraints.`)
×
2033
    }
×
2034

26✔
2035
    /**
26✔
2036
     * Drops exclusion constraint.
26✔
2037
     */
26✔
2038
    async dropExclusionConstraint(
26✔
2039
        tableOrName: Table | string,
×
2040
        exclusionOrName: TableExclusion | string,
×
2041
    ): Promise<void> {
×
2042
        throw new TypeORMError(`Oracle does not support exclusion constraints.`)
×
2043
    }
×
2044

26✔
2045
    /**
26✔
2046
     * Drops exclusion constraints.
26✔
2047
     */
26✔
2048
    async dropExclusionConstraints(
26✔
2049
        tableOrName: Table | string,
×
2050
        exclusionConstraints: TableExclusion[],
×
2051
    ): Promise<void> {
×
2052
        throw new TypeORMError(`Oracle does not support exclusion constraints.`)
×
2053
    }
×
2054

26✔
2055
    /**
26✔
2056
     * Creates a new foreign key.
26✔
2057
     */
26✔
2058
    async createForeignKey(
26✔
2059
        tableOrName: Table | string,
5,614✔
2060
        foreignKey: TableForeignKey,
5,614✔
2061
    ): Promise<void> {
5,614✔
2062
        const table = InstanceChecker.isTable(tableOrName)
5,614✔
2063
            ? tableOrName
5,614✔
2064
            : await this.getCachedTable(tableOrName)
5,614✔
2065

10✔
2066
        // new FK may be passed without name. In this case we generate FK name manually.
10✔
2067
        if (!foreignKey.name)
10✔
2068
            foreignKey.name = this.connection.namingStrategy.foreignKeyName(
5,614✔
2069
                table,
2✔
2070
                foreignKey.columnNames,
2✔
2071
                this.getTablePath(foreignKey),
2✔
2072
                foreignKey.referencedColumnNames,
2✔
2073
            )
2✔
2074

5,614✔
2075
        const up = this.createForeignKeySql(table, foreignKey)
5,614✔
2076
        const down = this.dropForeignKeySql(table, foreignKey)
5,614✔
2077
        await this.executeQueries(up, down)
5,614✔
2078
        table.addForeignKey(foreignKey)
5,614✔
2079
    }
5,614✔
2080

26✔
2081
    /**
26✔
2082
     * Creates a new foreign keys.
26✔
2083
     */
26✔
2084
    async createForeignKeys(
26✔
2085
        tableOrName: Table | string,
3,230✔
2086
        foreignKeys: TableForeignKey[],
3,230✔
2087
    ): Promise<void> {
3,230✔
2088
        const promises = foreignKeys.map((foreignKey) =>
3,230✔
2089
            this.createForeignKey(tableOrName, foreignKey),
3,230✔
2090
        )
3,230✔
2091
        await Promise.all(promises)
3,230✔
2092
    }
3,230✔
2093

26✔
2094
    /**
26✔
2095
     * Drops a foreign key from the table.
26✔
2096
     */
26✔
2097
    async dropForeignKey(
26✔
2098
        tableOrName: Table | string,
20✔
2099
        foreignKeyOrName: TableForeignKey | string,
20✔
2100
    ): Promise<void> {
20✔
2101
        const table = InstanceChecker.isTable(tableOrName)
20✔
2102
            ? tableOrName
20✔
2103
            : await this.getCachedTable(tableOrName)
20✔
2104
        const foreignKey = InstanceChecker.isTableForeignKey(foreignKeyOrName)
8✔
2105
            ? foreignKeyOrName
20✔
2106
            : table.foreignKeys.find((fk) => fk.name === foreignKeyOrName)
20!
2107
        if (!foreignKey)
20✔
2108
            throw new TypeORMError(
20!
2109
                `Supplied foreign key was not found in table ${table.name}`,
×
2110
            )
×
2111

20✔
2112
        const up = this.dropForeignKeySql(table, foreignKey)
20✔
2113
        const down = this.createForeignKeySql(table, foreignKey)
20✔
2114
        await this.executeQueries(up, down)
20✔
2115
        table.removeForeignKey(foreignKey)
20✔
2116
    }
20✔
2117

26✔
2118
    /**
26✔
2119
     * Drops a foreign keys from the table.
26✔
2120
     */
26✔
2121
    async dropForeignKeys(
26✔
2122
        tableOrName: Table | string,
12✔
2123
        foreignKeys: TableForeignKey[],
12✔
2124
    ): Promise<void> {
12✔
2125
        const promises = foreignKeys.map((foreignKey) =>
12✔
2126
            this.dropForeignKey(tableOrName, foreignKey),
12✔
2127
        )
12✔
2128
        await Promise.all(promises)
12✔
2129
    }
12✔
2130

26✔
2131
    /**
26✔
2132
     * Creates a new index.
26✔
2133
     */
26✔
2134
    async createIndex(
26✔
2135
        tableOrName: Table | string,
28✔
2136
        index: TableIndex,
28✔
2137
    ): Promise<void> {
28✔
2138
        const table = InstanceChecker.isTable(tableOrName)
28✔
2139
            ? tableOrName
28✔
2140
            : await this.getCachedTable(tableOrName)
28✔
2141

14✔
2142
        // new index may be passed without name. In this case we generate index name manually.
14✔
2143
        if (!index.name) index.name = this.generateIndexName(table, index)
28✔
2144

28✔
2145
        const up = this.createIndexSql(table, index)
28✔
2146
        const down = this.dropIndexSql(index)
28✔
2147
        await this.executeQueries(up, down)
28✔
2148
        table.addIndex(index)
28✔
2149
    }
28✔
2150

26✔
2151
    /**
26✔
2152
     * Creates a new indices
26✔
2153
     */
26✔
2154
    async createIndices(
26✔
2155
        tableOrName: Table | string,
14✔
2156
        indices: TableIndex[],
14✔
2157
    ): Promise<void> {
14✔
2158
        const promises = indices.map((index) =>
14✔
2159
            this.createIndex(tableOrName, index),
14✔
2160
        )
14✔
2161
        await Promise.all(promises)
14✔
2162
    }
14✔
2163

26✔
2164
    /**
26✔
2165
     * Drops an index from the table.
26✔
2166
     */
26✔
2167
    async dropIndex(
26✔
2168
        tableOrName: Table | string,
28✔
2169
        indexOrName: TableIndex | string,
28✔
2170
    ): Promise<void> {
28✔
2171
        const table = InstanceChecker.isTable(tableOrName)
28✔
2172
            ? tableOrName
28✔
2173
            : await this.getCachedTable(tableOrName)
28✔
2174
        const index = InstanceChecker.isTableIndex(indexOrName)
10✔
2175
            ? indexOrName
28✔
2176
            : table.indices.find((i) => i.name === indexOrName)
28!
2177
        if (!index)
28✔
2178
            throw new TypeORMError(
28!
2179
                `Supplied index ${indexOrName} was not found in table ${table.name}`,
×
2180
            )
×
2181
        // old index may be passed without name. In this case we generate index name manually.
28✔
2182
        if (!index.name) index.name = this.generateIndexName(table, index)
28✔
2183

28✔
2184
        const up = this.dropIndexSql(index)
28✔
2185
        const down = this.createIndexSql(table, index)
28✔
2186
        await this.executeQueries(up, down)
28✔
2187
        table.removeIndex(index)
28✔
2188
    }
28✔
2189

26✔
2190
    /**
26✔
2191
     * Drops an indices from the table.
26✔
2192
     */
26✔
2193
    async dropIndices(
26✔
2194
        tableOrName: Table | string,
2✔
2195
        indices: TableIndex[],
2✔
2196
    ): Promise<void> {
2✔
2197
        const promises = indices.map((index) =>
2✔
2198
            this.dropIndex(tableOrName, index),
2✔
2199
        )
2✔
2200
        await Promise.all(promises)
2✔
2201
    }
2✔
2202

26✔
2203
    /**
26✔
2204
     * Clears all table contents.
26✔
2205
     * Note: this operation uses SQL's TRUNCATE query which cannot be reverted in transactions.
26✔
2206
     */
26✔
2207
    async clearTable(tableName: string): Promise<void> {
26✔
2208
        await this.query(`TRUNCATE TABLE ${this.escapePath(tableName)}`)
4✔
2209
    }
4✔
2210

26✔
2211
    /**
26✔
2212
     * Removes all tables from the currently connected database.
26✔
2213
     */
26✔
2214
    async clearDatabase(): Promise<void> {
26✔
2215
        const isAnotherTransactionActive = this.isTransactionActive
2,586✔
2216
        if (!isAnotherTransactionActive) await this.startTransaction()
2,586✔
2217
        try {
2,586✔
2218
            // drop views
2,586✔
2219
            const dropViewsQuery = `SELECT 'DROP VIEW "' || VIEW_NAME || '"' AS "query" FROM "USER_VIEWS"`
2,586✔
2220
            const dropViewQueries: ObjectLiteral[] = await this.query(
2,586✔
2221
                dropViewsQuery,
2,586✔
2222
            )
2,586✔
2223
            await Promise.all(
2,586✔
2224
                dropViewQueries.map((query) => this.query(query["query"])),
2,586✔
2225
            )
2,586✔
2226

2,586✔
2227
            // drop materialized views
2,586✔
2228
            const dropMatViewsQuery = `SELECT 'DROP MATERIALIZED VIEW "' || MVIEW_NAME || '"' AS "query" FROM "USER_MVIEWS"`
2,586✔
2229
            const dropMatViewQueries: ObjectLiteral[] = await this.query(
2,586✔
2230
                dropMatViewsQuery,
2,586✔
2231
            )
2,586✔
2232
            await Promise.all(
2,586✔
2233
                dropMatViewQueries.map((query) => this.query(query["query"])),
2,586✔
2234
            )
2,586✔
2235

2,586✔
2236
            // drop tables
2,586✔
2237
            const dropTablesQuery = `SELECT 'DROP TABLE "' || TABLE_NAME || '" CASCADE CONSTRAINTS' AS "query" FROM "USER_TABLES"`
2,586✔
2238
            const dropTableQueries: ObjectLiteral[] = await this.query(
2,586✔
2239
                dropTablesQuery,
2,586✔
2240
            )
2,586✔
2241
            await Promise.all(
2,586✔
2242
                dropTableQueries.map((query) => this.query(query["query"])),
2,586✔
2243
            )
2,586✔
2244
            if (!isAnotherTransactionActive) await this.commitTransaction()
2,586✔
2245
        } catch (error) {
2,586!
2246
            try {
×
2247
                // we throw original error even if rollback thrown an error
×
2248
                if (!isAnotherTransactionActive)
×
2249
                    await this.rollbackTransaction()
×
2250
            } catch (rollbackError) {}
×
2251
            throw error
×
2252
        }
×
2253
    }
2,586✔
2254

26✔
2255
    // -------------------------------------------------------------------------
26✔
2256
    // Protected Methods
26✔
2257
    // -------------------------------------------------------------------------
26✔
2258

26✔
2259
    protected async loadViews(viewNames?: string[]): Promise<View[]> {
26✔
2260
        const hasTable = await this.hasTable(this.getTypeormMetadataTableName())
2,718✔
2261
        if (!hasTable) {
2,718✔
2262
            return []
2,650✔
2263
        }
2,650✔
2264

68✔
2265
        if (!viewNames) {
2,718!
2266
            viewNames = []
×
2267
        }
×
2268

68✔
2269
        const currentDatabase = await this.getCurrentDatabase()
68✔
2270
        const currentSchema = await this.getCurrentSchema()
68✔
2271

68✔
2272
        const viewsCondition = viewNames
68✔
2273
            .map((viewName) => this.driver.parseTableName(viewName))
68✔
2274
            .map(({ schema, tableName }) => {
68✔
2275
                if (!schema) {
74!
2276
                    schema = this.driver.options.schema || currentSchema
×
2277
                }
×
2278

74✔
2279
                return `("T"."schema" = '${schema}' AND "T"."name" = '${tableName}')`
74✔
2280
            })
68✔
2281
            .join(" OR ")
68✔
2282

68✔
2283
        let query =
68✔
2284
            `SELECT "T".* FROM ${this.escapePath(
68✔
2285
                this.getTypeormMetadataTableName(),
68✔
2286
            )} "T" ` +
68✔
2287
            `INNER JOIN "USER_OBJECTS" "O" ON "O"."OBJECT_NAME" = "T"."name" AND "O"."OBJECT_TYPE" IN ( 'MATERIALIZED VIEW', 'VIEW' ) ` +
68✔
2288
            `WHERE "T"."type" IN ('${MetadataTableType.MATERIALIZED_VIEW}', '${MetadataTableType.VIEW}')`
68✔
2289
        if (viewsCondition.length > 0) query += ` AND ${viewsCondition}`
2,718✔
2290

68✔
2291
        const dbViews = await this.query(query)
68✔
2292
        return dbViews.map((dbView: any) => {
68✔
2293
            const parsedName = this.driver.parseTableName(dbView["name"])
20✔
2294

20✔
2295
            const view = new View()
20✔
2296
            view.database =
20✔
2297
                parsedName.database || dbView["database"] || currentDatabase
20!
2298
            view.schema = parsedName.schema || dbView["schema"] || currentSchema
20!
2299
            view.name = parsedName.tableName
20✔
2300
            view.expression = dbView["value"]
20✔
2301
            view.materialized =
20✔
2302
                dbView["type"] === MetadataTableType.MATERIALIZED_VIEW
20✔
2303
            return view
20✔
2304
        })
68✔
2305
    }
68✔
2306

26✔
2307
    /**
26✔
2308
     * Loads all tables (with given names) from the database and creates a Table from them.
26✔
2309
     */
26✔
2310
    protected async loadTables(tableNames?: string[]): Promise<Table[]> {
26✔
2311
        if (tableNames && tableNames.length === 0) {
3,230✔
2312
            return []
12✔
2313
        }
12✔
2314

3,218✔
2315
        const dbTables: { TABLE_NAME: string; OWNER: string }[] = []
3,218✔
2316

3,218✔
2317
        const currentSchema = await this.getCurrentSchema()
3,218✔
2318
        const currentDatabase = await this.getCurrentDatabase()
3,218✔
2319

3,218✔
2320
        if (!tableNames) {
3,230!
2321
            const tablesSql = `SELECT "TABLE_NAME", "OWNER" FROM "ALL_TABLES"`
×
2322
            dbTables.push(...(await this.query(tablesSql)))
×
2323
        } else {
3,230✔
2324
            const tablesCondition = tableNames
3,218✔
2325
                .map((tableName) => {
3,218✔
2326
                    const parts = tableName.split(".")
9,722✔
2327

9,722✔
2328
                    if (parts.length >= 3) {
9,722!
2329
                        const [, schema, name] = parts
×
2330
                        return `("OWNER" = '${schema}' AND "TABLE_NAME" = '${name}')`
×
2331
                    } else if (parts.length === 2) {
9,722✔
2332
                        const [schema, name] = parts
9,184✔
2333
                        return `("OWNER" = '${schema}' AND "TABLE_NAME" = '${name}')`
9,184✔
2334
                    } else if (parts.length === 1) {
9,722✔
2335
                        const [name] = parts
538✔
2336
                        return `("TABLE_NAME" = '${name}')`
538✔
2337
                    } else {
538!
2338
                        return `(1=0)`
×
2339
                    }
×
2340
                })
3,218✔
2341
                .join(" OR ")
3,218✔
2342
            const tablesSql = `SELECT "TABLE_NAME", "OWNER" FROM "ALL_TABLES" WHERE ${tablesCondition}`
3,218✔
2343
            dbTables.push(...(await this.query(tablesSql)))
3,218✔
2344
        }
3,218✔
2345

3,218✔
2346
        // if tables were not found in the db, no need to proceed
3,218✔
2347
        if (dbTables.length === 0) {
3,230✔
2348
            return []
2,614✔
2349
        }
2,614✔
2350

604✔
2351
        // load tables, columns, indices and foreign keys
604✔
2352
        const columnsCondition = dbTables
604✔
2353
            .map(({ TABLE_NAME, OWNER }) => {
604✔
2354
                return `("C"."OWNER" = '${OWNER}' AND "C"."TABLE_NAME" = '${TABLE_NAME}')`
920✔
2355
            })
604✔
2356
            .join(" OR ")
604✔
2357
        const columnsSql = `SELECT * FROM "ALL_TAB_COLS" "C" WHERE (${columnsCondition})`
604✔
2358

604✔
2359
        const indicesSql =
604✔
2360
            `SELECT "C"."INDEX_NAME", "C"."OWNER", "C"."TABLE_NAME", "C"."UNIQUENESS", ` +
604✔
2361
            `LISTAGG ("COL"."COLUMN_NAME", ',') WITHIN GROUP (ORDER BY "COL"."COLUMN_NAME") AS "COLUMN_NAMES" ` +
604✔
2362
            `FROM "ALL_INDEXES" "C" ` +
604✔
2363
            `INNER JOIN "ALL_IND_COLUMNS" "COL" ON "COL"."INDEX_OWNER" = "C"."OWNER" AND "COL"."INDEX_NAME" = "C"."INDEX_NAME" ` +
604✔
2364
            `LEFT JOIN "ALL_CONSTRAINTS" "CON" ON "CON"."OWNER" = "C"."OWNER" AND "CON"."CONSTRAINT_NAME" = "C"."INDEX_NAME" ` +
604✔
2365
            `WHERE (${columnsCondition}) AND "CON"."CONSTRAINT_NAME" IS NULL ` +
604✔
2366
            `GROUP BY "C"."INDEX_NAME", "C"."OWNER", "C"."TABLE_NAME", "C"."UNIQUENESS"`
604✔
2367

604✔
2368
        const foreignKeysSql =
604✔
2369
            `SELECT "C"."CONSTRAINT_NAME", "C"."OWNER", "C"."TABLE_NAME", "COL"."COLUMN_NAME", "REF_COL"."TABLE_NAME" AS "REFERENCED_TABLE_NAME", ` +
604✔
2370
            `"REF_COL"."COLUMN_NAME" AS "REFERENCED_COLUMN_NAME", "C"."DELETE_RULE" AS "ON_DELETE" ` +
604✔
2371
            `FROM "ALL_CONSTRAINTS" "C" ` +
604✔
2372
            `INNER JOIN "ALL_CONS_COLUMNS" "COL" ON "COL"."OWNER" = "C"."OWNER" AND "COL"."CONSTRAINT_NAME" = "C"."CONSTRAINT_NAME" ` +
604✔
2373
            `INNER JOIN "ALL_CONS_COLUMNS" "REF_COL" ON "REF_COL"."OWNER" = "C"."R_OWNER" AND "REF_COL"."CONSTRAINT_NAME" = "C"."R_CONSTRAINT_NAME" AND "REF_COL"."POSITION" = "COL"."POSITION" ` +
604✔
2374
            `WHERE (${columnsCondition}) AND "C"."CONSTRAINT_TYPE" = 'R'`
604✔
2375

604✔
2376
        const constraintsSql =
604✔
2377
            `SELECT "C"."CONSTRAINT_NAME", "C"."CONSTRAINT_TYPE", "C"."OWNER", "C"."TABLE_NAME", "COL"."COLUMN_NAME", "C"."SEARCH_CONDITION" ` +
604✔
2378
            `FROM "ALL_CONSTRAINTS" "C" ` +
604✔
2379
            `INNER JOIN "ALL_CONS_COLUMNS" "COL" ON "COL"."OWNER" = "C"."OWNER" AND "COL"."CONSTRAINT_NAME" = "C"."CONSTRAINT_NAME" ` +
604✔
2380
            `WHERE (${columnsCondition}) AND "C"."CONSTRAINT_TYPE" IN ('C', 'U', 'P') AND "C"."GENERATED" = 'USER NAME'`
604✔
2381

604✔
2382
        const [
604✔
2383
            dbColumns,
604✔
2384
            dbIndices,
604✔
2385
            dbForeignKeys,
604✔
2386
            dbConstraints,
604✔
2387
        ]: ObjectLiteral[][] = await Promise.all([
604✔
2388
            this.query(columnsSql),
604✔
2389
            this.query(indicesSql),
604✔
2390
            this.query(foreignKeysSql),
604✔
2391
            this.query(constraintsSql),
604✔
2392
        ])
604✔
2393

604✔
2394
        // create tables for loaded tables
604✔
2395
        return await Promise.all(
604✔
2396
            dbTables.map(async (dbTable) => {
604✔
2397
                const table = new Table()
920✔
2398
                const owner =
920✔
2399
                    dbTable["OWNER"] === currentSchema &&
920✔
2400
                    (!this.driver.options.schema ||
920!
2401
                        this.driver.options.schema === currentSchema)
920✔
2402
                        ? undefined
920✔
2403
                        : dbTable["OWNER"]
920!
2404
                table.database = currentDatabase
920✔
2405
                table.schema = dbTable["OWNER"]
920✔
2406
                table.name = this.driver.buildTableName(
920✔
2407
                    dbTable["TABLE_NAME"],
920✔
2408
                    owner,
920✔
2409
                )
920✔
2410

920✔
2411
                // create columns from the loaded columns
920✔
2412
                table.columns = await Promise.all(
920✔
2413
                    dbColumns
920✔
2414
                        .filter(
920✔
2415
                            (dbColumn) =>
920✔
2416
                                dbColumn["OWNER"] === dbTable["OWNER"] &&
10,276✔
2417
                                dbColumn["TABLE_NAME"] ===
10,276✔
2418
                                    dbTable["TABLE_NAME"] &&
10,276✔
2419
                                // Filter out auto-generated virtual columns,
3,328✔
2420
                                // since TypeORM will have no info about them.
3,328✔
2421
                                !(
3,328✔
2422
                                    dbColumn["VIRTUAL_COLUMN"] === "YES" &&
3,328✔
2423
                                    dbColumn["USER_GENERATED"] === "NO"
74✔
2424
                                ),
920✔
2425
                        )
920✔
2426
                        .map(async (dbColumn) => {
920✔
2427
                            const columnConstraints = dbConstraints.filter(
3,324✔
2428
                                (dbConstraint) =>
3,324✔
2429
                                    dbConstraint["OWNER"] ===
18,012✔
2430
                                        dbColumn["OWNER"] &&
18,012✔
2431
                                    dbConstraint["TABLE_NAME"] ===
18,012✔
2432
                                        dbColumn["TABLE_NAME"] &&
18,012✔
2433
                                    dbConstraint["COLUMN_NAME"] ===
7,436✔
2434
                                        dbColumn["COLUMN_NAME"],
3,324✔
2435
                            )
3,324✔
2436

3,324✔
2437
                            const uniqueConstraints = columnConstraints.filter(
3,324✔
2438
                                (constraint) =>
3,324✔
2439
                                    constraint["CONSTRAINT_TYPE"] === "U",
3,324✔
2440
                            )
3,324✔
2441
                            const isConstraintComposite =
3,324✔
2442
                                uniqueConstraints.every((uniqueConstraint) => {
3,324✔
2443
                                    return dbConstraints.some(
616✔
2444
                                        (dbConstraint) =>
616✔
2445
                                            dbConstraint["OWNER"] ===
2,932✔
2446
                                                dbColumn["OWNER"] &&
2,932✔
2447
                                            dbConstraint["TABLE_NAME"] ===
2,932✔
2448
                                                dbColumn["TABLE_NAME"] &&
2,932✔
2449
                                            dbConstraint["COLUMN_NAME"] !==
2,534✔
2450
                                                dbColumn["COLUMN_NAME"] &&
2,932✔
2451
                                            dbConstraint["CONSTRAINT_NAME"] ===
1,988✔
2452
                                                uniqueConstraint[
1,988✔
2453
                                                    "CONSTRAINT_NAME"
1,988✔
2454
                                                ] &&
2,932✔
2455
                                            dbConstraint["CONSTRAINT_TYPE"] ===
348✔
2456
                                                "U",
616✔
2457
                                    )
616✔
2458
                                })
3,324✔
2459

3,324✔
2460
                            const tableColumn = new TableColumn()
3,324✔
2461
                            tableColumn.name = dbColumn["COLUMN_NAME"]
3,324✔
2462
                            tableColumn.type =
3,324✔
2463
                                dbColumn["DATA_TYPE"].toLowerCase()
3,324✔
2464
                            if (tableColumn.type.indexOf("(") !== -1)
3,324✔
2465
                                tableColumn.type = tableColumn.type.replace(
3,324✔
2466
                                    /\([0-9]*\)/,
100✔
2467
                                    "",
100✔
2468
                                )
100✔
2469

3,324✔
2470
                            // check only columns that have length property
3,324✔
2471
                            if (
3,324✔
2472
                                this.driver.withLengthColumnTypes.indexOf(
3,324✔
2473
                                    tableColumn.type as ColumnType,
3,324✔
2474
                                ) !== -1
3,324✔
2475
                            ) {
3,324✔
2476
                                const length =
1,756✔
2477
                                    tableColumn.type === "raw"
1,756✔
2478
                                        ? dbColumn["DATA_LENGTH"]
1,756✔
2479
                                        : dbColumn["CHAR_COL_DECL_LENGTH"]
1,756✔
2480
                                tableColumn.length =
1,756✔
2481
                                    length &&
1,756✔
2482
                                    !this.isDefaultColumnLength(
1,756✔
2483
                                        table,
1,756✔
2484
                                        tableColumn,
1,756✔
2485
                                        length,
1,756✔
2486
                                    )
1,756✔
2487
                                        ? length.toString()
1,756✔
2488
                                        : ""
1,756✔
2489
                            }
1,756✔
2490

3,324✔
2491
                            if (
3,324✔
2492
                                tableColumn.type === "number" ||
3,324✔
2493
                                tableColumn.type === "float"
1,884✔
2494
                            ) {
3,324✔
2495
                                if (
1,448✔
2496
                                    dbColumn["DATA_PRECISION"] !== null &&
1,448✔
2497
                                    !this.isDefaultColumnPrecision(
18✔
2498
                                        table,
18✔
2499
                                        tableColumn,
18✔
2500
                                        dbColumn["DATA_PRECISION"],
18✔
2501
                                    )
1,448✔
2502
                                )
1,448✔
2503
                                    tableColumn.precision =
1,448✔
2504
                                        dbColumn["DATA_PRECISION"]
12✔
2505
                                if (
1,448✔
2506
                                    dbColumn["DATA_SCALE"] !== null &&
1,448✔
2507
                                    !this.isDefaultColumnScale(
222✔
2508
                                        table,
222✔
2509
                                        tableColumn,
222✔
2510
                                        dbColumn["DATA_SCALE"],
222✔
2511
                                    )
1,448✔
2512
                                )
1,448✔
2513
                                    tableColumn.scale = dbColumn["DATA_SCALE"]
1,448✔
2514
                            } else if (
3,324✔
2515
                                (tableColumn.type === "timestamp" ||
1,876✔
2516
                                    tableColumn.type ===
1,786✔
2517
                                        "timestamp with time zone" ||
1,876✔
2518
                                    tableColumn.type ===
1,780✔
2519
                                        "timestamp with local time zone") &&
1,876✔
2520
                                dbColumn["DATA_SCALE"] !== null
100✔
2521
                            ) {
1,876✔
2522
                                tableColumn.precision =
100✔
2523
                                    !this.isDefaultColumnPrecision(
100✔
2524
                                        table,
100✔
2525
                                        tableColumn,
100✔
2526
                                        dbColumn["DATA_SCALE"],
100✔
2527
                                    )
100✔
2528
                                        ? dbColumn["DATA_SCALE"]
100✔
2529
                                        : undefined
100✔
2530
                            }
100✔
2531

3,324✔
2532
                            tableColumn.default =
3,324✔
2533
                                dbColumn["DATA_DEFAULT"] !== null &&
3,324✔
2534
                                dbColumn["DATA_DEFAULT"] !== undefined &&
3,324✔
2535
                                dbColumn["VIRTUAL_COLUMN"] === "NO" &&
3,324✔
2536
                                dbColumn["DATA_DEFAULT"].trim() !== "NULL"
788✔
2537
                                    ? (tableColumn.default =
3,324✔
2538
                                          dbColumn["DATA_DEFAULT"].trim())
772✔
2539
                                    : undefined
3,324✔
2540

3,324✔
2541
                            const primaryConstraint = columnConstraints.find(
3,324✔
2542
                                (constraint) =>
3,324✔
2543
                                    constraint["CONSTRAINT_TYPE"] === "P",
3,324✔
2544
                            )
3,324✔
2545
                            if (primaryConstraint) {
3,324✔
2546
                                tableColumn.isPrimary = true
962✔
2547
                                // find another columns involved in primary key constraint
962✔
2548
                                const anotherPrimaryConstraints =
962✔
2549
                                    dbConstraints.filter(
962✔
2550
                                        (constraint) =>
962✔
2551
                                            constraint["OWNER"] ===
5,312✔
2552
                                                dbColumn["OWNER"] &&
5,312✔
2553
                                            constraint["TABLE_NAME"] ===
5,312✔
2554
                                                dbColumn["TABLE_NAME"] &&
5,312✔
2555
                                            constraint["COLUMN_NAME"] !==
1,872✔
2556
                                                dbColumn["COLUMN_NAME"] &&
5,312✔
2557
                                            constraint["CONSTRAINT_TYPE"] ===
892✔
2558
                                                "P",
962✔
2559
                                    )
962✔
2560

962✔
2561
                                // collect all column names
962✔
2562
                                const columnNames =
962✔
2563
                                    anotherPrimaryConstraints.map(
962✔
2564
                                        (constraint) =>
962✔
2565
                                            constraint["COLUMN_NAME"],
962✔
2566
                                    )
962✔
2567
                                columnNames.push(dbColumn["COLUMN_NAME"])
962✔
2568

962✔
2569
                                // build default primary key constraint name
962✔
2570
                                const pkName =
962✔
2571
                                    this.connection.namingStrategy.primaryKeyName(
962✔
2572
                                        table,
962✔
2573
                                        columnNames,
962✔
2574
                                    )
962✔
2575

962✔
2576
                                // if primary key has user-defined constraint name, write it in table column
962✔
2577
                                if (
962✔
2578
                                    primaryConstraint["CONSTRAINT_NAME"] !==
962✔
2579
                                    pkName
962✔
2580
                                ) {
962✔
2581
                                    tableColumn.primaryKeyConstraintName =
52✔
2582
                                        primaryConstraint["CONSTRAINT_NAME"]
52✔
2583
                                }
52✔
2584
                            }
962✔
2585

3,324✔
2586
                            tableColumn.isNullable =
3,324✔
2587
                                dbColumn["NULLABLE"] === "Y"
3,324✔
2588
                            tableColumn.isUnique =
3,324✔
2589
                                uniqueConstraints.length > 0 &&
3,324✔
2590
                                !isConstraintComposite
610✔
2591
                            tableColumn.isGenerated =
3,324✔
2592
                                dbColumn["IDENTITY_COLUMN"] === "YES"
3,324✔
2593
                            if (tableColumn.isGenerated) {
3,324✔
2594
                                tableColumn.generationStrategy = "increment"
516✔
2595
                                tableColumn.default = undefined
516✔
2596
                            }
516✔
2597
                            tableColumn.comment = "" // todo
3,324✔
2598

3,324✔
2599
                            if (dbColumn["VIRTUAL_COLUMN"] === "YES") {
3,324✔
2600
                                tableColumn.generatedType = "VIRTUAL"
70✔
2601

70✔
2602
                                const asExpressionQuery =
70✔
2603
                                    this.selectTypeormMetadataSql({
70✔
2604
                                        table: dbTable["TABLE_NAME"],
70✔
2605
                                        type: MetadataTableType.GENERATED_COLUMN,
70✔
2606
                                        name: tableColumn.name,
70✔
2607
                                    })
70✔
2608

70✔
2609
                                const results = await this.query(
70✔
2610
                                    asExpressionQuery.query,
70✔
2611
                                    asExpressionQuery.parameters,
70✔
2612
                                )
70✔
2613
                                if (results[0] && results[0].value) {
70✔
2614
                                    tableColumn.asExpression = results[0].value
70✔
2615
                                } else {
70!
2616
                                    tableColumn.asExpression = ""
×
2617
                                }
×
2618
                            }
70✔
2619

3,324✔
2620
                            return tableColumn
3,324✔
2621
                        }),
920✔
2622
                )
920✔
2623

920✔
2624
                // find unique constraints of table, group them by constraint name and build TableUnique.
920✔
2625
                const tableUniqueConstraints = OrmUtils.uniq(
920✔
2626
                    dbConstraints.filter((dbConstraint) => {
920✔
2627
                        return (
5,174✔
2628
                            dbConstraint["TABLE_NAME"] ===
5,174✔
2629
                                dbTable["TABLE_NAME"] &&
5,174✔
2630
                            dbConstraint["OWNER"] === dbTable["OWNER"] &&
5,174✔
2631
                            dbConstraint["CONSTRAINT_TYPE"] === "U"
1,758✔
2632
                        )
5,174✔
2633
                    }),
920✔
2634
                    (dbConstraint) => dbConstraint["CONSTRAINT_NAME"],
920✔
2635
                )
920✔
2636

920✔
2637
                table.uniques = tableUniqueConstraints.map((constraint) => {
920✔
2638
                    const uniques = dbConstraints.filter(
442✔
2639
                        (dbC) =>
442✔
2640
                            dbC["CONSTRAINT_NAME"] ===
2,656✔
2641
                            constraint["CONSTRAINT_NAME"],
442✔
2642
                    )
442✔
2643
                    return new TableUnique({
442✔
2644
                        name: constraint["CONSTRAINT_NAME"],
442✔
2645
                        columnNames: uniques.map((u) => u["COLUMN_NAME"]),
442✔
2646
                    })
442✔
2647
                })
920✔
2648

920✔
2649
                // find check constraints of table, group them by constraint name and build TableCheck.
920✔
2650
                const tableCheckConstraints = OrmUtils.uniq(
920✔
2651
                    dbConstraints.filter((dbConstraint) => {
920✔
2652
                        return (
5,174✔
2653
                            dbConstraint["TABLE_NAME"] ===
5,174✔
2654
                                dbTable["TABLE_NAME"] &&
5,174✔
2655
                            dbConstraint["OWNER"] === dbTable["OWNER"] &&
5,174✔
2656
                            dbConstraint["CONSTRAINT_TYPE"] === "C"
1,758✔
2657
                        )
5,174✔
2658
                    }),
920✔
2659
                    (dbConstraint) => dbConstraint["CONSTRAINT_NAME"],
920✔
2660
                )
920✔
2661

920✔
2662
                table.checks = tableCheckConstraints.map((constraint) => {
920✔
2663
                    const checks = dbConstraints.filter(
172✔
2664
                        (dbC) =>
172✔
2665
                            dbC["TABLE_NAME"] === constraint["TABLE_NAME"] &&
1,198✔
2666
                            dbC["OWNER"] === constraint["OWNER"] &&
1,198✔
2667
                            dbC["CONSTRAINT_NAME"] ===
848✔
2668
                                constraint["CONSTRAINT_NAME"],
172✔
2669
                    )
172✔
2670
                    return new TableCheck({
172✔
2671
                        name: constraint["CONSTRAINT_NAME"],
172✔
2672
                        columnNames: checks.map((c) => c["COLUMN_NAME"]),
172✔
2673
                        expression: constraint["SEARCH_CONDITION"],
172✔
2674
                    })
172✔
2675
                })
920✔
2676

920✔
2677
                // find foreign key constraints of table, group them by constraint name and build TableForeignKey.
920✔
2678
                const tableForeignKeyConstraints = OrmUtils.uniq(
920✔
2679
                    dbForeignKeys.filter(
920✔
2680
                        (dbForeignKey) =>
920✔
2681
                            dbForeignKey["OWNER"] === dbTable["OWNER"] &&
1,274✔
2682
                            dbForeignKey["TABLE_NAME"] ===
1,274✔
2683
                                dbTable["TABLE_NAME"],
920✔
2684
                    ),
920✔
2685
                    (dbForeignKey) => dbForeignKey["CONSTRAINT_NAME"],
920✔
2686
                )
920✔
2687

920✔
2688
                table.foreignKeys = tableForeignKeyConstraints.map(
920✔
2689
                    (dbForeignKey) => {
920✔
2690
                        const foreignKeys = dbForeignKeys.filter(
358✔
2691
                            (dbFk) =>
358✔
2692
                                dbFk["TABLE_NAME"] ===
954✔
2693
                                    dbForeignKey["TABLE_NAME"] &&
954✔
2694
                                dbFk["OWNER"] === dbForeignKey["OWNER"] &&
954✔
2695
                                dbFk["CONSTRAINT_NAME"] ===
758✔
2696
                                    dbForeignKey["CONSTRAINT_NAME"],
358✔
2697
                        )
358✔
2698
                        return new TableForeignKey({
358✔
2699
                            name: dbForeignKey["CONSTRAINT_NAME"],
358✔
2700
                            columnNames: foreignKeys.map(
358✔
2701
                                (dbFk) => dbFk["COLUMN_NAME"],
358✔
2702
                            ),
358✔
2703
                            referencedDatabase: table.database,
358✔
2704
                            referencedSchema: dbForeignKey["OWNER"],
358✔
2705
                            referencedTableName:
358✔
2706
                                dbForeignKey["REFERENCED_TABLE_NAME"],
358✔
2707
                            referencedColumnNames: foreignKeys.map(
358✔
2708
                                (dbFk) => dbFk["REFERENCED_COLUMN_NAME"],
358✔
2709
                            ),
358✔
2710
                            onDelete: dbForeignKey["ON_DELETE"],
358✔
2711
                            onUpdate: "NO ACTION", // Oracle does not have onUpdate option in FK's, but we need it for proper synchronization
358✔
2712
                        })
358✔
2713
                    },
920✔
2714
                )
920✔
2715

920✔
2716
                // Attempt to map auto-generated virtual columns to their
920✔
2717
                // referenced columns, through its 'DATA_DEFAULT' property.
920✔
2718
                //
920✔
2719
                // An example of this happening is when a column of type
920✔
2720
                // TIMESTAMP WITH TIME ZONE is indexed. Oracle will create a
920✔
2721
                // virtual column of type TIMESTAMP with a default value of
920✔
2722
                // SYS_EXTRACT_UTC(<column>).
920✔
2723
                const autoGenVirtualDbColumns = dbColumns
920✔
2724
                    .filter(
920✔
2725
                        (dbColumn) =>
920✔
2726
                            dbColumn["OWNER"] === dbTable["OWNER"] &&
10,276✔
2727
                            dbColumn["TABLE_NAME"] === dbTable["TABLE_NAME"] &&
10,276✔
2728
                            dbColumn["VIRTUAL_COLUMN"] === "YES" &&
10,276✔
2729
                            dbColumn["USER_GENERATED"] === "NO",
920✔
2730
                    )
920✔
2731
                    .reduce((acc, x) => {
920✔
2732
                        const referencedDbColumn = dbColumns.find((dbColumn) =>
4✔
2733
                            x["DATA_DEFAULT"].includes(dbColumn["COLUMN_NAME"]),
4✔
2734
                        )
4✔
2735

4✔
2736
                        if (!referencedDbColumn) return acc
4!
2737

4✔
2738
                        return {
4✔
2739
                            ...acc,
4✔
2740
                            [x["COLUMN_NAME"]]:
4✔
2741
                                referencedDbColumn["COLUMN_NAME"],
4✔
2742
                        }
4✔
2743
                    }, {})
920✔
2744

920✔
2745
                // create TableIndex objects from the loaded indices
920✔
2746
                table.indices = dbIndices
920✔
2747
                    .filter(
920✔
2748
                        (dbIndex) =>
920✔
2749
                            dbIndex["TABLE_NAME"] === dbTable["TABLE_NAME"] &&
620✔
2750
                            dbIndex["OWNER"] === dbTable["OWNER"],
920✔
2751
                    )
920✔
2752
                    .map((dbIndex) => {
920✔
2753
                        //
288✔
2754
                        const columnNames = dbIndex["COLUMN_NAMES"]
288✔
2755
                            .split(",")
288✔
2756
                            .map(
288✔
2757
                                (
288✔
2758
                                    columnName: keyof typeof autoGenVirtualDbColumns,
330✔
2759
                                ) =>
330✔
2760
                                    autoGenVirtualDbColumns[columnName] ??
330✔
2761
                                    columnName,
288✔
2762
                            )
288✔
2763

288✔
2764
                        return new TableIndex({
288✔
2765
                            name: dbIndex["INDEX_NAME"],
288✔
2766
                            columnNames,
288✔
2767
                            isUnique: dbIndex["UNIQUENESS"] === "UNIQUE",
288✔
2768
                        })
288✔
2769
                    })
920✔
2770

920✔
2771
                return table
920✔
2772
            }),
604✔
2773
        )
604✔
2774
    }
604✔
2775

26✔
2776
    /**
26✔
2777
     * Builds and returns SQL for create table.
26✔
2778
     */
26✔
2779
    protected createTableSql(table: Table, createForeignKeys?: boolean): Query {
26✔
2780
        const columnDefinitions = table.columns
8,894✔
2781
            .map((column) => this.buildCreateColumnSql(column))
8,894✔
2782
            .join(", ")
8,894✔
2783
        let sql = `CREATE TABLE ${this.escapePath(table)} (${columnDefinitions}`
8,894✔
2784

8,894✔
2785
        table.columns
8,894✔
2786
            .filter((column) => column.isUnique)
8,894✔
2787
            .forEach((column) => {
8,894✔
2788
                const isUniqueExist = table.uniques.some(
1,282✔
2789
                    (unique) =>
1,282✔
2790
                        unique.columnNames.length === 1 &&
1,720✔
2791
                        unique.columnNames[0] === column.name,
1,282✔
2792
                )
1,282✔
2793
                if (!isUniqueExist)
1,282✔
2794
                    table.uniques.push(
1,282✔
2795
                        new TableUnique({
10✔
2796
                            name: this.connection.namingStrategy.uniqueConstraintName(
10✔
2797
                                table,
10✔
2798
                                [column.name],
10✔
2799
                            ),
10✔
2800
                            columnNames: [column.name],
10✔
2801
                        }),
10✔
2802
                    )
10✔
2803
            })
8,894✔
2804

8,894✔
2805
        if (table.uniques.length > 0) {
8,894✔
2806
            const uniquesSql = table.uniques
1,142✔
2807
                .map((unique) => {
1,142✔
2808
                    const uniqueName = unique.name
1,678✔
2809
                        ? unique.name
1,678✔
2810
                        : this.connection.namingStrategy.uniqueConstraintName(
1,678✔
2811
                              table,
4✔
2812
                              unique.columnNames,
4✔
2813
                          )
1,678✔
2814
                    const columnNames = unique.columnNames
1,678✔
2815
                        .map((columnName) => `"${columnName}"`)
1,678✔
2816
                        .join(", ")
1,678✔
2817
                    return `CONSTRAINT "${uniqueName}" UNIQUE (${columnNames})`
1,678✔
2818
                })
1,142✔
2819
                .join(", ")
1,142✔
2820

1,142✔
2821
            sql += `, ${uniquesSql}`
1,142✔
2822
        }
1,142✔
2823

8,894✔
2824
        if (table.checks.length > 0) {
8,894✔
2825
            const checksSql = table.checks
140✔
2826
                .map((check) => {
140✔
2827
                    const checkName = check.name
142✔
2828
                        ? check.name
142✔
2829
                        : this.connection.namingStrategy.checkConstraintName(
142✔
2830
                              table,
2✔
2831
                              check.expression!,
2✔
2832
                          )
142✔
2833
                    return `CONSTRAINT "${checkName}" CHECK (${check.expression})`
142✔
2834
                })
140✔
2835
                .join(", ")
140✔
2836

140✔
2837
            sql += `, ${checksSql}`
140✔
2838
        }
140✔
2839

8,894✔
2840
        if (table.foreignKeys.length > 0 && createForeignKeys) {
8,894✔
2841
            const foreignKeysSql = table.foreignKeys
10✔
2842
                .map((fk) => {
10✔
2843
                    const columnNames = fk.columnNames
12✔
2844
                        .map((columnName) => `"${columnName}"`)
12✔
2845
                        .join(", ")
12✔
2846
                    if (!fk.name)
12✔
2847
                        fk.name = this.connection.namingStrategy.foreignKeyName(
12✔
2848
                            table,
8✔
2849
                            fk.columnNames,
8✔
2850
                            this.getTablePath(fk),
8✔
2851
                            fk.referencedColumnNames,
8✔
2852
                        )
8✔
2853
                    const referencedColumnNames = fk.referencedColumnNames
12✔
2854
                        .map((columnName) => `"${columnName}"`)
12✔
2855
                        .join(", ")
12✔
2856
                    let constraint = `CONSTRAINT "${
12✔
2857
                        fk.name
12✔
2858
                    }" FOREIGN KEY (${columnNames}) REFERENCES ${this.escapePath(
12✔
2859
                        this.getTablePath(fk),
12✔
2860
                    )} (${referencedColumnNames})`
12✔
2861
                    if (fk.onDelete && fk.onDelete !== "NO ACTION") {
12!
2862
                        // Oracle does not support NO ACTION, but we set NO ACTION by default in EntityMetadata
×
2863
                        constraint += ` ON DELETE ${fk.onDelete}`
×
2864
                    }
×
2865
                    return constraint
12✔
2866
                })
10✔
2867
                .join(", ")
10✔
2868

10✔
2869
            sql += `, ${foreignKeysSql}`
10✔
2870
        }
10✔
2871

8,894✔
2872
        const primaryColumns = table.columns.filter(
8,894✔
2873
            (column) => column.isPrimary,
8,894✔
2874
        )
8,894✔
2875
        if (primaryColumns.length > 0) {
8,894✔
2876
            const primaryKeyName = primaryColumns[0].primaryKeyConstraintName
8,852✔
2877
                ? primaryColumns[0].primaryKeyConstraintName
8,852✔
2878
                : this.connection.namingStrategy.primaryKeyName(
8,852✔
2879
                      table,
8,820✔
2880
                      primaryColumns.map((column) => column.name),
8,820✔
2881
                  )
8,852✔
2882

8,852✔
2883
            const columnNames = primaryColumns
8,852✔
2884
                .map((column) => `"${column.name}"`)
8,852✔
2885
                .join(", ")
8,852✔
2886
            sql += `, CONSTRAINT "${primaryKeyName}" PRIMARY KEY (${columnNames})`
8,852✔
2887
        }
8,852✔
2888

8,894✔
2889
        sql += `)`
8,894✔
2890

8,894✔
2891
        return new Query(sql)
8,894✔
2892
    }
8,894✔
2893

26✔
2894
    /**
26✔
2895
     * Builds drop table sql.
26✔
2896
     */
26✔
2897
    protected dropTableSql(
26✔
2898
        tableOrName: Table | string,
8,894✔
2899
        ifExist?: boolean,
8,894✔
2900
    ): Query {
8,894✔
2901
        const query = ifExist
8,894✔
2902
            ? `DROP TABLE IF EXISTS ${this.escapePath(tableOrName)}`
8,894!
2903
            : `DROP TABLE ${this.escapePath(tableOrName)}`
8,894✔
2904
        return new Query(query)
8,894✔
2905
    }
8,894✔
2906

26✔
2907
    protected createViewSql(view: View): Query {
26✔
2908
        const materializedClause = view.materialized ? "MATERIALIZED " : ""
56✔
2909
        if (typeof view.expression === "string") {
56✔
2910
            return new Query(
40✔
2911
                `CREATE ${materializedClause}VIEW ${this.escapePath(view)} AS ${
40✔
2912
                    view.expression
40✔
2913
                }`,
40✔
2914
            )
40✔
2915
        } else {
56✔
2916
            return new Query(
16✔
2917
                `CREATE ${materializedClause}VIEW ${this.escapePath(
16✔
2918
                    view,
16✔
2919
                )} AS ${view.expression(this.connection).getQuery()}`,
16✔
2920
            )
16✔
2921
        }
16✔
2922
    }
56✔
2923

26✔
2924
    protected insertViewDefinitionSql(view: View): Query {
26✔
2925
        const expression =
56✔
2926
            typeof view.expression === "string"
56✔
2927
                ? view.expression.trim()
56✔
2928
                : view.expression(this.connection).getQuery()
56✔
2929
        const type = view.materialized
56✔
2930
            ? MetadataTableType.MATERIALIZED_VIEW
56✔
2931
            : MetadataTableType.VIEW
56✔
2932
        const { schema, tableName } = this.driver.parseTableName(view)
56✔
2933
        return this.insertTypeormMetadataSql({
56✔
2934
            type: type,
56✔
2935
            name: tableName,
56✔
2936
            schema: schema,
56✔
2937
            value: expression,
56✔
2938
        })
56✔
2939
    }
56✔
2940

26✔
2941
    /**
26✔
2942
     * Builds drop view sql.
26✔
2943
     */
26✔
2944
    protected dropViewSql(view: View): Query {
26✔
2945
        const materializedClause = view.materialized ? "MATERIALIZED " : ""
56✔
2946
        return new Query(
56✔
2947
            `DROP ${materializedClause}VIEW ${this.escapePath(view)}`,
56✔
2948
        )
56✔
2949
    }
56✔
2950

26✔
2951
    /**
26✔
2952
     * Builds remove view sql.
26✔
2953
     */
26✔
2954
    protected deleteViewDefinitionSql(view: View): Query {
26✔
2955
        const type = view.materialized
56✔
2956
            ? MetadataTableType.MATERIALIZED_VIEW
56✔
2957
            : MetadataTableType.VIEW
56✔
2958
        return this.deleteTypeormMetadataSql({ type, name: view.name })
56✔
2959
    }
56✔
2960

26✔
2961
    /**
26✔
2962
     * Builds create index sql.
26✔
2963
     */
26✔
2964
    protected createIndexSql(table: Table, index: TableIndex): Query {
26✔
2965
        const columns = index.columnNames
3,174✔
2966
            .map((columnName) => `"${columnName}"`)
3,174✔
2967
            .join(", ")
3,174✔
2968
        return new Query(
3,174✔
2969
            `CREATE ${index.isUnique ? "UNIQUE " : ""}INDEX "${
3,174✔
2970
                index.name
3,174✔
2971
            }" ON ${this.escapePath(table)} (${columns})`,
3,174✔
2972
        )
3,174✔
2973
    }
3,174✔
2974

26✔
2975
    /**
26✔
2976
     * Builds drop index sql.
26✔
2977
     */
26✔
2978
    protected dropIndexSql(indexOrName: TableIndex | string): Query {
26✔
2979
        const indexName = InstanceChecker.isTableIndex(indexOrName)
3,174✔
2980
            ? indexOrName.name
3,174✔
2981
            : indexOrName
3,174!
2982
        return new Query(`DROP INDEX "${indexName}"`)
3,174✔
2983
    }
3,174✔
2984

26✔
2985
    /**
26✔
2986
     * Builds create primary key sql.
26✔
2987
     */
26✔
2988
    protected createPrimaryKeySql(
26✔
2989
        table: Table,
10✔
2990
        columnNames: string[],
10✔
2991
        constraintName?: string,
10✔
2992
    ): Query {
10✔
2993
        const primaryKeyName = constraintName
10✔
2994
            ? constraintName
10!
2995
            : this.connection.namingStrategy.primaryKeyName(table, columnNames)
10✔
2996

10✔
2997
        const columnNamesString = columnNames
10✔
2998
            .map((columnName) => `"${columnName}"`)
10✔
2999
            .join(", ")
10✔
3000

10✔
3001
        return new Query(
10✔
3002
            `ALTER TABLE ${this.escapePath(
10✔
3003
                table,
10✔
3004
            )} ADD CONSTRAINT "${primaryKeyName}" PRIMARY KEY (${columnNamesString})`,
10✔
3005
        )
10✔
3006
    }
10✔
3007

26✔
3008
    /**
26✔
3009
     * Builds drop primary key sql.
26✔
3010
     */
26✔
3011
    protected dropPrimaryKeySql(table: Table): Query {
26✔
3012
        if (!table.primaryColumns.length)
10✔
3013
            throw new TypeORMError(`Table ${table} has no primary keys.`)
10!
3014

10✔
3015
        const columnNames = table.primaryColumns.map((column) => column.name)
10✔
3016
        const constraintName = table.primaryColumns[0].primaryKeyConstraintName
10✔
3017
        const primaryKeyName = constraintName
10✔
3018
            ? constraintName
10!
3019
            : this.connection.namingStrategy.primaryKeyName(table, columnNames)
10✔
3020

10✔
3021
        return new Query(
10✔
3022
            `ALTER TABLE ${this.escapePath(
10✔
3023
                table,
10✔
3024
            )} DROP CONSTRAINT "${primaryKeyName}"`,
10✔
3025
        )
10✔
3026
    }
10✔
3027

26✔
3028
    /**
26✔
3029
     * Builds create unique constraint sql.
26✔
3030
     */
26✔
3031
    protected createUniqueConstraintSql(
26✔
3032
        table: Table,
38✔
3033
        uniqueConstraint: TableUnique,
38✔
3034
    ): Query {
38✔
3035
        const columnNames = uniqueConstraint.columnNames
38✔
3036
            .map((column) => `"` + column + `"`)
38✔
3037
            .join(", ")
38✔
3038
        return new Query(
38✔
3039
            `ALTER TABLE ${this.escapePath(table)} ADD CONSTRAINT "${
38✔
3040
                uniqueConstraint.name
38✔
3041
            }" UNIQUE (${columnNames})`,
38✔
3042
        )
38✔
3043
    }
38✔
3044

26✔
3045
    /**
26✔
3046
     * Builds drop unique constraint sql.
26✔
3047
     */
26✔
3048
    protected dropUniqueConstraintSql(
26✔
3049
        table: Table,
38✔
3050
        uniqueOrName: TableUnique | string,
38✔
3051
    ): Query {
38✔
3052
        const uniqueName = InstanceChecker.isTableUnique(uniqueOrName)
38✔
3053
            ? uniqueOrName.name
38✔
3054
            : uniqueOrName
38!
3055
        return new Query(
38✔
3056
            `ALTER TABLE ${this.escapePath(
38✔
3057
                table,
38✔
3058
            )} DROP CONSTRAINT "${uniqueName}"`,
38✔
3059
        )
38✔
3060
    }
38✔
3061

26✔
3062
    /**
26✔
3063
     * Builds create check constraint sql.
26✔
3064
     */
26✔
3065
    protected createCheckConstraintSql(
26✔
3066
        table: Table,
20✔
3067
        checkConstraint: TableCheck,
20✔
3068
    ): Query {
20✔
3069
        return new Query(
20✔
3070
            `ALTER TABLE ${this.escapePath(table)} ADD CONSTRAINT "${
20✔
3071
                checkConstraint.name
20✔
3072
            }" CHECK (${checkConstraint.expression})`,
20✔
3073
        )
20✔
3074
    }
20✔
3075

26✔
3076
    /**
26✔
3077
     * Builds drop check constraint sql.
26✔
3078
     */
26✔
3079
    protected dropCheckConstraintSql(
26✔
3080
        table: Table,
20✔
3081
        checkOrName: TableCheck | string,
20✔
3082
    ): Query {
20✔
3083
        const checkName = InstanceChecker.isTableCheck(checkOrName)
20✔
3084
            ? checkOrName.name
20✔
3085
            : checkOrName
20!
3086
        return new Query(
20✔
3087
            `ALTER TABLE ${this.escapePath(
20✔
3088
                table,
20✔
3089
            )} DROP CONSTRAINT "${checkName}"`,
20✔
3090
        )
20✔
3091
    }
20✔
3092

26✔
3093
    /**
26✔
3094
     * Builds create foreign key sql.
26✔
3095
     */
26✔
3096
    protected createForeignKeySql(
26✔
3097
        table: Table,
5,634✔
3098
        foreignKey: TableForeignKey,
5,634✔
3099
    ): Query {
5,634✔
3100
        const columnNames = foreignKey.columnNames
5,634✔
3101
            .map((column) => `"` + column + `"`)
5,634✔
3102
            .join(", ")
5,634✔
3103
        const referencedColumnNames = foreignKey.referencedColumnNames
5,634✔
3104
            .map((column) => `"` + column + `"`)
5,634✔
3105
            .join(",")
5,634✔
3106
        let sql =
5,634✔
3107
            `ALTER TABLE ${this.escapePath(table)} ADD CONSTRAINT "${
5,634✔
3108
                foreignKey.name
5,634✔
3109
            }" FOREIGN KEY (${columnNames}) ` +
5,634✔
3110
            `REFERENCES ${this.escapePath(
5,634✔
3111
                this.getTablePath(foreignKey),
5,634✔
3112
            )} (${referencedColumnNames})`
5,634✔
3113
        // Oracle does not support NO ACTION, but we set NO ACTION by default in EntityMetadata
5,634✔
3114
        if (foreignKey.onDelete && foreignKey.onDelete !== "NO ACTION") {
5,634✔
3115
            sql += ` ON DELETE ${foreignKey.onDelete}`
2,004✔
3116
        }
2,004✔
3117
        return new Query(sql)
5,634✔
3118
    }
5,634✔
3119

26✔
3120
    /**
26✔
3121
     * Builds drop foreign key sql.
26✔
3122
     */
26✔
3123
    protected dropForeignKeySql(
26✔
3124
        table: Table,
5,646✔
3125
        foreignKeyOrName: TableForeignKey | string,
5,646✔
3126
    ): Query {
5,646✔
3127
        const foreignKeyName = InstanceChecker.isTableForeignKey(
5,646✔
3128
            foreignKeyOrName,
5,646✔
3129
        )
5,646✔
3130
            ? foreignKeyOrName.name
5,646✔
3131
            : foreignKeyOrName
5,646!
3132
        return new Query(
5,646✔
3133
            `ALTER TABLE ${this.escapePath(
5,646✔
3134
                table,
5,646✔
3135
            )} DROP CONSTRAINT "${foreignKeyName}"`,
5,646✔
3136
        )
5,646✔
3137
    }
5,646✔
3138

26✔
3139
    /**
26✔
3140
     * Builds a query for create column.
26✔
3141
     */
26✔
3142
    protected buildCreateColumnSql(column: TableColumn) {
26✔
3143
        let c =
28,160✔
3144
            `"${column.name}" ` + this.connection.driver.createFullType(column)
28,160✔
3145
        if (column.charset) c += " CHARACTER SET " + column.charset
28,160!
3146
        if (column.collation) c += " COLLATE " + column.collation
28,160!
3147

28,160✔
3148
        if (column.asExpression) c += ` AS (${column.asExpression}) VIRTUAL`
28,160✔
3149

28,160✔
3150
        if (column.default !== undefined && column.default !== null)
28,160✔
3151
            // DEFAULT must be placed before NOT NULL
28,160✔
3152
            c += " DEFAULT " + column.default
28,160✔
3153
        if (column.isNullable !== true && !column.isGenerated)
28,160✔
3154
            // NOT NULL is not supported with GENERATED
28,160✔
3155
            c += " NOT NULL"
28,160✔
3156
        if (
28,160✔
3157
            column.isGenerated === true &&
28,160✔
3158
            column.generationStrategy === "increment"
5,416✔
3159
        )
28,160✔
3160
            c += " GENERATED BY DEFAULT AS IDENTITY"
28,160✔
3161

28,160✔
3162
        return c
28,160✔
3163
    }
28,160✔
3164

26✔
3165
    /**
26✔
3166
     * Escapes given table or view path.
26✔
3167
     */
26✔
3168
    protected escapePath(target: Table | View | string): string {
26✔
3169
        // Ignore database when escaping paths
38,822✔
3170
        const { schema, tableName } = this.driver.parseTableName(target)
38,822✔
3171

38,822✔
3172
        if (schema && schema !== this.driver.schema) {
38,822!
3173
            return `"${schema}"."${tableName}"`
×
3174
        }
×
3175

38,822✔
3176
        return `"${tableName}"`
38,822✔
3177
    }
38,822✔
3178

26✔
3179
    /**
26✔
3180
     * Change table comment.
26✔
3181
     */
26✔
3182
    changeTableComment(
26✔
3183
        tableOrName: Table | string,
×
3184
        comment?: string,
×
3185
    ): Promise<void> {
×
3186
        throw new TypeORMError(
×
3187
            `oracle driver does not support change table comment.`,
×
3188
        )
×
3189
    }
×
3190
}
26✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc