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

typeorm / typeorm / 20153290793

12 Dec 2025 01:29AM UTC coverage: 80.807% (+0.04%) from 80.764%
20153290793

push

github

alumni
refactor(mysql)!: drop support for mysql package and default to mysql2 (#11766)

Co-authored-by: Lucian Mocanu <alumni@users.noreply.github.com>

26912 of 32666 branches covered (82.39%)

Branch coverage included in aggregate %.

13 of 15 new or added lines in 2 files covered. (86.67%)

694 existing lines in 23 files now uncovered.

91350 of 113685 relevant lines covered (80.35%)

68942.63 hits per line

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

93.87
/src/query-runner/BaseQueryRunner.ts
1
import { PostgresConnectionOptions } from "../driver/postgres/PostgresConnectionOptions"
26✔
2
import { Query } from "../driver/Query"
26✔
3
import { SqlInMemory } from "../driver/SqlInMemory"
26✔
4
import { SqlServerConnectionOptions } from "../driver/sqlserver/SqlServerConnectionOptions"
26✔
5
import { TableIndex } from "../schema-builder/table/TableIndex"
26✔
6
import { View } from "../schema-builder/view/View"
26✔
7
import { DataSource } from "../data-source/DataSource"
26✔
8
import { Table } from "../schema-builder/table/Table"
26✔
9
import { EntityManager } from "../entity-manager/EntityManager"
26✔
10
import { TableColumn } from "../schema-builder/table/TableColumn"
26✔
11
import { Broadcaster } from "../subscriber/Broadcaster"
26✔
12
import { ReplicationMode } from "../driver/types/ReplicationMode"
26✔
13
import { TypeORMError } from "../error/TypeORMError"
26✔
14
import { EntityMetadata } from "../metadata/EntityMetadata"
26✔
15
import { TableForeignKey } from "../schema-builder/table/TableForeignKey"
26✔
16
import { OrmUtils } from "../util/OrmUtils"
26✔
17
import { MetadataTableType } from "../driver/types/MetadataTableType"
26✔
18
import { InstanceChecker } from "../util/InstanceChecker"
26✔
19
import { buildSqlTag } from "../util/SqlTagUtils"
26✔
20

26✔
21
export abstract class BaseQueryRunner implements AsyncDisposable {
245,811✔
22
    // -------------------------------------------------------------------------
245,811✔
23
    // Public Properties
245,811✔
24
    // -------------------------------------------------------------------------
245,811✔
25

245,811✔
26
    /**
245,811✔
27
     * Connection used by this query runner.
245,811✔
28
     */
245,811✔
29
    connection: DataSource
245,811✔
30

245,811✔
31
    /**
245,811✔
32
     * Entity manager working only with current query runner.
245,811✔
33
     */
245,811✔
34
    manager: EntityManager
245,811✔
35

245,811✔
36
    /**
245,811✔
37
     * Indicates if connection for this query runner is released.
245,811✔
38
     * Once its released, query runner cannot run queries anymore.
245,811✔
39
     */
245,811✔
40
    isReleased = false
245,811✔
41

245,811✔
42
    /**
245,811✔
43
     * Indicates if transaction is in progress.
245,811✔
44
     */
245,811✔
45
    isTransactionActive = false
245,811✔
46

245,811✔
47
    /**
245,811✔
48
     * Stores temporarily user data.
245,811✔
49
     * Useful for sharing data with subscribers.
245,811✔
50
     */
245,811✔
51
    data = {}
245,811✔
52

245,811✔
53
    /**
245,811✔
54
     * All synchronized tables in the database.
245,811✔
55
     */
245,811✔
56
    loadedTables: Table[] = []
245,811✔
57

245,811✔
58
    /**
245,811✔
59
     * All synchronized views in the database.
245,811✔
60
     */
245,811✔
61
    loadedViews: View[] = []
245,811✔
62

245,811✔
63
    /**
245,811✔
64
     * Broadcaster used on this query runner to broadcast entity events.
245,811✔
65
     */
245,811✔
66
    broadcaster: Broadcaster
245,811✔
67

245,811✔
68
    // -------------------------------------------------------------------------
245,811✔
69
    // Protected Properties
245,811✔
70
    // -------------------------------------------------------------------------
245,811✔
71

245,811✔
72
    /**
245,811✔
73
     * Real database connection from a connection pool used to perform queries.
245,811✔
74
     */
245,811✔
75
    protected databaseConnection: any
245,811✔
76

245,811✔
77
    /**
245,811✔
78
     * Indicates if special query runner mode in which sql queries won't be executed is enabled.
245,811✔
79
     */
245,811✔
80
    protected sqlMemoryMode: boolean = false
245,811✔
81

245,811✔
82
    /**
245,811✔
83
     * Sql-s stored if "sql in memory" mode is enabled.
245,811✔
84
     */
245,811✔
85
    protected sqlInMemory: SqlInMemory = new SqlInMemory()
245,811✔
86

245,811✔
87
    /**
245,811✔
88
     * Mode in which query runner executes.
245,811✔
89
     * Used for replication.
245,811✔
90
     * If replication is not setup its value is ignored.
245,811✔
91
     */
245,811✔
92
    protected mode: ReplicationMode
245,811✔
93

245,811✔
94
    /**
245,811✔
95
     * current depth of transaction.
245,811✔
96
     * for transactionDepth > 0 will use SAVEPOINT to start and commit/rollback transaction blocks
245,811✔
97
     */
245,811✔
98
    protected transactionDepth = 0
245,811✔
99

245,811✔
100
    private cachedTablePaths: Record<string, string> = {}
245,811✔
101

245,811✔
102
    // -------------------------------------------------------------------------
245,811✔
103
    // Public Abstract Methods
245,811✔
104
    // -------------------------------------------------------------------------
245,811✔
105

245,811✔
106
    /**
245,811✔
107
     * Releases used database connection.
245,811✔
108
     * You cannot use query runner methods after connection is released.
245,811✔
109
     */
245,811✔
110
    abstract release(): Promise<void>
245,811✔
111

245,811✔
112
    async [Symbol.asyncDispose](): Promise<void> {
245,811✔
113
        try {
10✔
114
            if (this.isTransactionActive) {
10✔
115
                this.transactionDepth = 1 // ignore all savepoints and commit directly
4✔
116
                await this.commitTransaction()
4✔
UNCOV
117
            }
×
118
        } finally {
10✔
119
            await this.release()
10✔
120
        }
10✔
121
    }
10✔
122

245,811✔
123
    /**
245,811✔
124
     * Commits transaction.
245,811✔
125
     * Error will be thrown if transaction was not started.
245,811✔
126
     */
245,811✔
127
    abstract commitTransaction(): Promise<void>
245,811✔
128

245,811✔
129
    /**
245,811✔
130
     * Executes a given SQL query.
245,811✔
131
     */
245,811✔
132
    abstract query(
245,811✔
133
        query: string,
245,811✔
134
        parameters?: any[],
245,811✔
135
        useStructuredResult?: boolean,
245,811✔
136
    ): Promise<any>
245,811✔
137

245,811✔
138
    /**
245,811✔
139
     * Tagged template function that executes raw SQL query and returns raw database results.
245,811✔
140
     * Template expressions are automatically transformed into database parameters.
245,811✔
141
     * Raw query execution is supported only by relational databases (MongoDB is not supported).
245,811✔
142
     * Note: Don't call this as a regular function, it is meant to be used with backticks to tag a template literal.
245,811✔
143
     * Example: queryRunner.sql`SELECT * FROM table_name WHERE id = ${id}`
245,811✔
144
     */
245,811✔
145
    async sql<T = any>(
245,811✔
146
        strings: TemplateStringsArray,
10✔
147
        ...values: unknown[]
10✔
148
    ): Promise<T> {
10✔
149
        const { query, parameters } = buildSqlTag({
10✔
150
            driver: this.connection.driver,
10✔
151
            strings: strings,
10✔
152
            expressions: values,
10✔
153
        })
10✔
154

10✔
155
        return await this.query(query, parameters)
10✔
156
    }
10✔
157

245,811✔
158
    // -------------------------------------------------------------------------
245,811✔
159
    // Protected Abstract Methods
245,811✔
160
    // -------------------------------------------------------------------------
245,811✔
161

245,811✔
162
    protected abstract loadTables(tablePaths?: string[]): Promise<Table[]>
245,811✔
163

245,811✔
164
    protected abstract loadViews(tablePaths?: string[]): Promise<View[]>
245,811✔
165

245,811✔
166
    // -------------------------------------------------------------------------
245,811✔
167
    // Public Methods
245,811✔
168
    // -------------------------------------------------------------------------
245,811✔
169

245,811✔
170
    /**
245,811✔
171
     * Called before migrations are run.
245,811✔
172
     */
245,811✔
173
    async beforeMigration(): Promise<void> {
245,811✔
174
        // Do nothing
28,960✔
175
    }
28,960✔
176

245,811✔
177
    /**
245,811✔
178
     * Called after migrations are run.
245,811✔
179
     */
245,811✔
180
    async afterMigration(): Promise<void> {
245,811✔
181
        // Do nothing
28,899✔
182
    }
28,899✔
183

245,811✔
184
    /**
245,811✔
185
     * Loads given table's data from the database.
245,811✔
186
     */
245,811✔
187
    async getTable(tablePath: string): Promise<Table | undefined> {
245,811✔
188
        this.loadedTables = await this.loadTables([tablePath])
6,603✔
189
        return this.loadedTables.length > 0 ? this.loadedTables[0] : undefined
6,603✔
190
    }
6,603✔
191

245,811✔
192
    /**
245,811✔
193
     * Loads all tables (with given names) from the database.
245,811✔
194
     */
245,811✔
195
    async getTables(tableNames?: string[]): Promise<Table[]> {
245,811✔
196
        if (!tableNames) {
42,136!
197
            // Don't cache in this case.
6✔
198
            // This is the new case & isn't used anywhere else anyway.
6✔
199
            return await this.loadTables(tableNames)
6✔
200
        }
6✔
201

42,130✔
202
        this.loadedTables = await this.loadTables(tableNames)
42,130✔
203
        return this.loadedTables
42,130✔
204
    }
42,130✔
205

245,811✔
206
    /**
245,811✔
207
     * Loads given view's data from the database.
245,811✔
208
     */
245,811✔
209
    async getView(viewPath: string): Promise<View | undefined> {
245,811✔
210
        this.loadedViews = await this.loadViews([viewPath])
170✔
211
        return this.loadedViews.length > 0 ? this.loadedViews[0] : undefined
170!
212
    }
170✔
213

245,811✔
214
    /**
245,811✔
215
     * Loads given view's data from the database.
245,811✔
216
     */
245,811✔
217
    async getViews(viewPaths?: string[]): Promise<View[]> {
245,811✔
218
        this.loadedViews = await this.loadViews(viewPaths)
42,098✔
219
        return this.loadedViews
42,098✔
220
    }
42,098✔
221

245,811✔
222
    /**
245,811✔
223
     * Enables special query runner mode in which sql queries won't be executed,
245,811✔
224
     * instead they will be memorized into a special variable inside query runner.
245,811✔
225
     * You can get memorized sql using getMemorySql() method.
245,811✔
226
     */
245,811✔
227
    enableSqlMemory(): void {
245,811✔
228
        this.sqlInMemory = new SqlInMemory()
959✔
229
        this.sqlMemoryMode = true
959✔
230
    }
959✔
231

245,811✔
232
    /**
245,811✔
233
     * Disables special query runner mode in which sql queries won't be executed
245,811✔
234
     * started by calling enableSqlMemory() method.
245,811✔
235
     *
245,811✔
236
     * Previously memorized sql will be flushed.
245,811✔
237
     */
245,811✔
238
    disableSqlMemory(): void {
245,811✔
239
        this.sqlInMemory = new SqlInMemory()
959✔
240
        this.sqlMemoryMode = false
959✔
241
    }
959✔
242

245,811✔
243
    /**
245,811✔
244
     * Flushes all memorized sqls.
245,811✔
245
     */
245,811✔
246
    clearSqlMemory(): void {
245,811✔
247
        this.sqlInMemory = new SqlInMemory()
107,865✔
248
    }
107,865✔
249

245,811✔
250
    /**
245,811✔
251
     * Gets sql stored in the memory. Parameters in the sql are already replaced.
245,811✔
252
     */
245,811✔
253
    getMemorySql(): SqlInMemory {
245,811✔
254
        return this.sqlInMemory
963✔
255
    }
963✔
256

245,811✔
257
    /**
245,811✔
258
     * Executes up sql queries.
245,811✔
259
     */
245,811✔
260
    async executeMemoryUpSql(): Promise<void> {
245,811✔
UNCOV
261
        for (const { query, parameters } of this.sqlInMemory.upQueries) {
×
UNCOV
262
            await this.query(query, parameters)
×
UNCOV
263
        }
×
UNCOV
264
    }
×
265

245,811✔
266
    /**
245,811✔
267
     * Executes down sql queries.
245,811✔
268
     */
245,811✔
269
    async executeMemoryDownSql(): Promise<void> {
245,811✔
270
        for (const {
1,020✔
271
            query,
1,020✔
272
            parameters,
1,020✔
273
        } of this.sqlInMemory.downQueries.reverse()) {
1,020✔
274
            await this.query(query, parameters)
4,158✔
275
        }
4,158✔
276
    }
1,020✔
277

245,811✔
278
    getReplicationMode(): ReplicationMode {
245,811✔
279
        return this.mode
428✔
280
    }
428✔
281

245,811✔
282
    // -------------------------------------------------------------------------
245,811✔
283
    // Protected Methods
245,811✔
284
    // -------------------------------------------------------------------------
245,811✔
285

245,811✔
286
    /**
245,811✔
287
     * Gets view from previously loaded views, otherwise loads it from database.
245,811✔
288
     */
245,811✔
289
    protected async getCachedView(viewName: string): Promise<View> {
245,811✔
290
        const view = this.loadedViews.find((view) => view.name === viewName)
24✔
291
        if (view) return view
24✔
UNCOV
292

×
UNCOV
293
        const foundViews = await this.loadViews([viewName])
×
UNCOV
294
        if (foundViews.length > 0) {
×
UNCOV
295
            this.loadedViews.push(foundViews[0])
×
UNCOV
296
            return foundViews[0]
×
UNCOV
297
        } else {
×
UNCOV
298
            throw new TypeORMError(`View "${viewName}" does not exist.`)
×
UNCOV
299
        }
×
300
    }
24✔
301

245,811✔
302
    /**
245,811✔
303
     * Gets table from previously loaded tables, otherwise loads it from database.
245,811✔
304
     */
245,811✔
305
    protected async getCachedTable(tableName: string): Promise<Table> {
245,811✔
306
        if (tableName in this.cachedTablePaths) {
1,582✔
307
            const tablePath = this.cachedTablePaths[tableName]
441✔
308
            const table = this.loadedTables.find(
441✔
309
                (table) => this.getTablePath(table) === tablePath,
441✔
310
            )
441✔
311

441✔
312
            if (table) {
441✔
313
                return table
423✔
314
            }
423✔
315
        }
441✔
316

1,159✔
317
        const foundTables = await this.loadTables([tableName])
1,159✔
318

1,159✔
319
        if (foundTables.length > 0) {
1,159✔
320
            const foundTablePath = this.getTablePath(foundTables[0])
1,159✔
321

1,159✔
322
            const cachedTable = this.loadedTables.find(
1,159✔
323
                (table) => this.getTablePath(table) === foundTablePath,
1,159✔
324
            )
1,159✔
325

1,159✔
326
            if (!cachedTable) {
1,159✔
327
                this.cachedTablePaths[tableName] = this.getTablePath(
852✔
328
                    foundTables[0],
852✔
329
                )
852✔
330
                this.loadedTables.push(foundTables[0])
852✔
331
                return foundTables[0]
852✔
332
            } else {
1,159✔
333
                return cachedTable
307✔
334
            }
307✔
335
        } else {
1,582!
UNCOV
336
            throw new TypeORMError(`Table "${tableName}" does not exist.`)
×
UNCOV
337
        }
×
338
    }
1,582✔
339

245,811✔
340
    /**
245,811✔
341
     * Replaces loaded table with given changed table.
245,811✔
342
     */
245,811✔
343
    protected replaceCachedTable(table: Table, changedTable: Table): void {
245,811✔
344
        const oldTablePath = this.getTablePath(table)
19,095✔
345
        const foundTable = this.loadedTables.find(
19,095✔
346
            (loadedTable) => this.getTablePath(loadedTable) === oldTablePath,
19,095✔
347
        )
19,095✔
348

19,095✔
349
        // Clean up the lookup cache..
19,095✔
350
        for (const [key, cachedPath] of Object.entries(this.cachedTablePaths)) {
19,095✔
351
            if (cachedPath === oldTablePath) {
815✔
352
                this.cachedTablePaths[key] = this.getTablePath(changedTable)
379✔
353
            }
379✔
354
        }
815✔
355

19,095✔
356
        if (foundTable) {
19,095✔
357
            foundTable.database = changedTable.database
19,095✔
358
            foundTable.schema = changedTable.schema
19,095✔
359
            foundTable.name = changedTable.name
19,095✔
360
            foundTable.columns = changedTable.columns
19,095✔
361
            foundTable.indices = changedTable.indices
19,095✔
362
            foundTable.foreignKeys = changedTable.foreignKeys
19,095✔
363
            foundTable.uniques = changedTable.uniques
19,095✔
364
            foundTable.checks = changedTable.checks
19,095✔
365
            foundTable.justCreated = changedTable.justCreated
19,095✔
366
            foundTable.engine = changedTable.engine
19,095✔
367
            foundTable.comment = changedTable.comment
19,095✔
368
        }
19,095✔
369
    }
19,095✔
370

245,811✔
371
    protected getTablePath(
245,811✔
372
        target: EntityMetadata | Table | View | TableForeignKey | string,
276,820✔
373
    ): string {
276,820✔
374
        const parsed = this.connection.driver.parseTableName(target)
276,820✔
375

276,820✔
376
        return this.connection.driver.buildTableName(
276,820✔
377
            parsed.tableName,
276,820✔
378
            parsed.schema,
276,820✔
379
            parsed.database,
276,820✔
380
        )
276,820✔
381
    }
276,820✔
382

245,811✔
383
    protected getTypeormMetadataTableName(): string {
245,811✔
384
        const options = <
46,280✔
385
            SqlServerConnectionOptions | PostgresConnectionOptions
46,280✔
386
        >this.connection.driver.options
46,280✔
387
        return this.connection.driver.buildTableName(
46,280✔
388
            this.connection.metadataTableName,
46,280✔
389
            options.schema,
46,280✔
390
            options.database,
46,280✔
391
        )
46,280✔
392
    }
46,280✔
393

245,811✔
394
    /**
245,811✔
395
     * Generates SQL query to select record from typeorm metadata table.
245,811✔
396
     */
245,811✔
397
    protected selectTypeormMetadataSql({
245,811✔
398
        database,
1,044✔
399
        schema,
1,044✔
400
        table,
1,044✔
401
        type,
1,044✔
402
        name,
1,044✔
403
    }: {
1,044✔
404
        database?: string
1,044✔
405
        schema?: string
1,044✔
406
        table?: string
1,044✔
407
        type: MetadataTableType
1,044✔
408
        name: string
1,044✔
409
    }): Query {
1,044✔
410
        const qb = this.connection.createQueryBuilder()
1,044✔
411
        const selectQb = qb
1,044✔
412
            .select()
1,044✔
413
            .from(this.getTypeormMetadataTableName(), "t")
1,044✔
414
            .where(`${qb.escape("type")} = :type`, { type })
1,044✔
415
            .andWhere(`${qb.escape("name")} = :name`, { name })
1,044✔
416

1,044✔
417
        if (database) {
1,044!
418
            selectQb.andWhere(`${qb.escape("database")} = :database`, {
262✔
419
                database,
262✔
420
            })
262✔
421
        }
262✔
422

1,044✔
423
        if (schema) {
1,044!
424
            selectQb.andWhere(`${qb.escape("schema")} = :schema`, { schema })
869✔
425
        }
869✔
426

1,044✔
427
        if (table) {
1,044✔
428
            selectQb.andWhere(`${qb.escape("table")} = :table`, { table })
1,044✔
429
        }
1,044✔
430

1,044✔
431
        const [query, parameters] = selectQb.getQueryAndParameters()
1,044✔
432
        return new Query(query, parameters)
1,044✔
433
    }
1,044✔
434

245,811✔
435
    /**
245,811✔
436
     * Generates SQL query to insert a record into typeorm metadata table.
245,811✔
437
     */
245,811✔
438
    protected insertTypeormMetadataSql({
245,811✔
439
        database,
1,196✔
440
        schema,
1,196✔
441
        table,
1,196✔
442
        type,
1,196✔
443
        name,
1,196✔
444
        value,
1,196✔
445
    }: {
1,196✔
446
        database?: string
1,196✔
447
        schema?: string
1,196✔
448
        table?: string
1,196✔
449
        type: MetadataTableType
1,196✔
450
        name: string
1,196✔
451
        value?: string
1,196✔
452
    }): Query {
1,196✔
453
        const [query, parameters] = this.connection
1,196✔
454
            .createQueryBuilder()
1,196✔
455
            .insert()
1,196✔
456
            .into(this.getTypeormMetadataTableName())
1,196✔
457
            .values({
1,196✔
458
                database: database,
1,196✔
459
                schema: schema,
1,196✔
460
                table: table,
1,196✔
461
                type: type,
1,196✔
462
                name: name,
1,196✔
463
                value: value,
1,196✔
464
            })
1,196✔
465
            .getQueryAndParameters()
1,196✔
466

1,196✔
467
        return new Query(query, parameters)
1,196✔
468
    }
1,196✔
469

245,811✔
470
    /**
245,811✔
471
     * Generates SQL query to delete a record from typeorm metadata table.
245,811✔
472
     */
245,811✔
473
    protected deleteTypeormMetadataSql({
245,811✔
474
        database,
1,196✔
475
        schema,
1,196✔
476
        table,
1,196✔
477
        type,
1,196✔
478
        name,
1,196✔
479
    }: {
1,196✔
480
        database?: string
1,196✔
481
        schema?: string
1,196✔
482
        table?: string
1,196✔
483
        type: MetadataTableType
1,196✔
484
        name: string
1,196✔
485
    }): Query {
1,196✔
486
        const qb = this.connection.createQueryBuilder()
1,196✔
487
        const deleteQb = qb
1,196✔
488
            .delete()
1,196✔
489
            .from(this.getTypeormMetadataTableName())
1,196✔
490
            .where(`${qb.escape("type")} = :type`, { type })
1,196✔
491
            .andWhere(`${qb.escape("name")} = :name`, { name })
1,196✔
492

1,196✔
493
        if (database) {
1,196!
494
            deleteQb.andWhere(`${qb.escape("database")} = :database`, {
226✔
495
                database,
226✔
496
            })
226✔
497
        }
226✔
498

1,196✔
499
        if (schema) {
1,196!
500
            deleteQb.andWhere(`${qb.escape("schema")} = :schema`, { schema })
923✔
501
        }
923✔
502

1,196✔
503
        if (table) {
1,196!
504
            deleteQb.andWhere(`${qb.escape("table")} = :table`, { table })
800✔
505
        }
800✔
506

1,196✔
507
        const [query, parameters] = deleteQb.getQueryAndParameters()
1,196✔
508
        return new Query(query, parameters)
1,196✔
509
    }
1,196✔
510

245,811✔
511
    /**
245,811✔
512
     * Checks if at least one of column properties was changed.
245,811✔
513
     * Does not checks column type, length and autoincrement, because these properties changes separately.
245,811✔
514
     */
245,811✔
515
    protected isColumnChanged(
245,811✔
516
        oldColumn: TableColumn,
692✔
517
        newColumn: TableColumn,
692✔
518
        checkDefault?: boolean,
692✔
519
        checkComment?: boolean,
692✔
520
        checkEnum = true,
692✔
521
    ): boolean {
692✔
522
        // this logs need to debug issues in column change detection. Do not delete it!
692✔
523

692✔
524
        // console.log("charset ---------------");
692✔
525
        // console.log(oldColumn.charset !== newColumn.charset);
692✔
526
        // console.log(oldColumn.charset, newColumn.charset);
692✔
527
        // console.log("collation ---------------");
692✔
528
        // console.log(oldColumn.collation !== newColumn.collation);
692✔
529
        // console.log(oldColumn.collation, newColumn.collation);
692✔
530
        // console.log("precision ---------------");
692✔
531
        // console.log(oldColumn.precision !== newColumn.precision);
692✔
532
        // console.log(oldColumn.precision, newColumn.precision);
692✔
533
        // console.log("scale ---------------");
692✔
534
        // console.log(oldColumn.scale !== newColumn.scale);
692✔
535
        // console.log(oldColumn.scale, newColumn.scale);
692✔
536
        // console.log("default ---------------");
692✔
537
        // console.log((checkDefault && oldColumn.default !== newColumn.default));
692✔
538
        // console.log(oldColumn.default, newColumn.default);
692✔
539
        // console.log("isNullable ---------------");
692✔
540
        // console.log(oldColumn.isNullable !== newColumn.isNullable);
692✔
541
        // console.log(oldColumn.isNullable, newColumn.isNullable);
692✔
542
        // console.log("comment ---------------");
692✔
543
        // console.log((checkComment && oldColumn.comment !== newColumn.comment));
692✔
544
        // console.log(oldColumn.comment, newColumn.comment);
692✔
545
        // console.log("enum ---------------");
692✔
546
        // console.log(!OrmUtils.isArraysEqual(oldColumn.enum || [], newColumn.enum || []));
692✔
547
        // console.log(oldColumn.enum, newColumn.enum);
692✔
548

692✔
549
        return (
692✔
550
            oldColumn.charset !== newColumn.charset ||
692✔
551
            oldColumn.collation !== newColumn.collation ||
692✔
552
            oldColumn.precision !== newColumn.precision ||
692✔
553
            oldColumn.scale !== newColumn.scale ||
692✔
554
            oldColumn.width !== newColumn.width || // MySQL only
692✔
555
            oldColumn.zerofill !== newColumn.zerofill || // MySQL only
692✔
556
            oldColumn.unsigned !== newColumn.unsigned || // MySQL only
692✔
557
            oldColumn.asExpression !== newColumn.asExpression ||
692✔
558
            (checkDefault && oldColumn.default !== newColumn.default) ||
692!
559
            oldColumn.onUpdate !== newColumn.onUpdate || // MySQL only
692✔
560
            oldColumn.isNullable !== newColumn.isNullable ||
692✔
561
            (checkComment && oldColumn.comment !== newColumn.comment) ||
692!
562
            (checkEnum && this.isEnumChanged(oldColumn, newColumn))
558!
563
        )
692✔
564
    }
692✔
565

245,811✔
566
    protected isEnumChanged(oldColumn: TableColumn, newColumn: TableColumn) {
245,811✔
567
        return !OrmUtils.isArraysEqual(
558✔
568
            oldColumn.enum || [],
558✔
569
            newColumn.enum || [],
558✔
570
        )
558✔
571
    }
558✔
572

245,811✔
573
    /**
245,811✔
574
     * Checks if column length is by default.
245,811✔
575
     */
245,811✔
576
    protected isDefaultColumnLength(
245,811✔
577
        table: Table,
12,932✔
578
        column: TableColumn,
12,932✔
579
        length: string,
12,932✔
580
    ): boolean {
12,932✔
581
        // if table have metadata, we check if length is specified in column metadata
12,932✔
582
        if (this.connection.hasMetadata(table.name)) {
12,932✔
583
            const metadata = this.connection.getMetadata(table.name)
11,551✔
584
            const columnMetadata = metadata.findColumnWithDatabaseName(
11,551✔
585
                column.name,
11,551✔
586
            )
11,551✔
587

11,551✔
588
            if (columnMetadata) {
11,551✔
589
                const columnMetadataLength =
11,304✔
590
                    this.connection.driver.getColumnLength(columnMetadata)
11,304✔
591
                if (columnMetadataLength) return false
11,304✔
592
            }
11,304✔
593
        }
11,551✔
594

1,746✔
595
        if (
1,746✔
596
            this.connection.driver.dataTypeDefaults &&
1,746✔
597
            this.connection.driver.dataTypeDefaults[column.type] &&
12,932✔
598
            this.connection.driver.dataTypeDefaults[column.type].length
1,522✔
599
        ) {
12,932✔
600
            return (
1,522✔
601
                this.connection.driver.dataTypeDefaults[
1,522✔
602
                    column.type
1,522✔
603
                ].length!.toString() === length.toString()
1,522✔
604
            )
1,522✔
605
        }
1,522✔
606

224!
607
        return false
224✔
608
    }
224✔
609

245,811✔
610
    /**
245,811✔
611
     * Checks if column precision is by default.
245,811✔
612
     */
245,811✔
613
    protected isDefaultColumnPrecision(
245,811✔
614
        table: Table,
1,047✔
615
        column: TableColumn,
1,047✔
616
        precision: number,
1,047✔
617
    ): boolean {
1,047✔
618
        // if table have metadata, we check if length is specified in column metadata
1,047✔
619
        if (this.connection.hasMetadata(table.name)) {
1,047✔
620
            const metadata = this.connection.getMetadata(table.name)
1,047✔
621
            const columnMetadata = metadata.findColumnWithDatabaseName(
1,047✔
622
                column.name,
1,047✔
623
            )
1,047✔
624
            if (
1,047✔
625
                columnMetadata &&
1,047✔
626
                columnMetadata.precision !== null &&
1,047✔
627
                columnMetadata.precision !== undefined
1,031✔
628
            )
1,047✔
629
                return false
1,047✔
630
        }
1,047✔
631

650!
632
        if (
650✔
633
            this.connection.driver.dataTypeDefaults &&
650✔
634
            this.connection.driver.dataTypeDefaults[column.type] &&
1,047!
635
            this.connection.driver.dataTypeDefaults[column.type].precision !==
650✔
636
                null &&
1,047!
637
            this.connection.driver.dataTypeDefaults[column.type].precision !==
650✔
638
                undefined
650✔
639
        )
1,047✔
640
            return (
1,047!
641
                this.connection.driver.dataTypeDefaults[column.type]
650✔
642
                    .precision === precision
650✔
643
            )
650✔
UNCOV
644

×
UNCOV
645
        return false
×
UNCOV
646
    }
×
647

245,811✔
648
    /**
245,811✔
649
     * Checks if column scale is by default.
245,811✔
650
     */
245,811✔
651
    protected isDefaultColumnScale(
245,811✔
652
        table: Table,
351✔
653
        column: TableColumn,
351✔
654
        scale: number,
351✔
655
    ): boolean {
351✔
656
        // if table have metadata, we check if length is specified in column metadata
351✔
657
        if (this.connection.hasMetadata(table.name)) {
351✔
658
            const metadata = this.connection.getMetadata(table.name)
143✔
659
            const columnMetadata = metadata.findColumnWithDatabaseName(
143✔
660
                column.name,
143✔
661
            )
143✔
662
            if (
143✔
663
                columnMetadata &&
143✔
664
                columnMetadata.scale !== null &&
143✔
665
                columnMetadata.scale !== undefined
139✔
666
            )
143✔
667
                return false
143✔
668
        }
143✔
669

263✔
670
        if (
263✔
671
            this.connection.driver.dataTypeDefaults &&
263✔
672
            this.connection.driver.dataTypeDefaults[column.type] &&
351!
673
            this.connection.driver.dataTypeDefaults[column.type].scale !==
46✔
674
                null &&
351!
675
            this.connection.driver.dataTypeDefaults[column.type].scale !==
46✔
676
                undefined
46✔
677
        )
351✔
678
            return (
351!
679
                this.connection.driver.dataTypeDefaults[column.type].scale ===
46✔
680
                scale
46✔
681
            )
46✔
682

217!
683
        return false
217✔
684
    }
217✔
685

245,811✔
686
    /**
245,811✔
687
     * Executes sql used special for schema build.
245,811✔
688
     */
245,811✔
689
    protected async executeQueries(
245,811✔
690
        upQueries: Query | Query[],
218,443✔
691
        downQueries: Query | Query[],
218,443✔
692
    ): Promise<void> {
218,443✔
693
        if (InstanceChecker.isQuery(upQueries)) upQueries = [upQueries]
218,443✔
694
        if (InstanceChecker.isQuery(downQueries)) downQueries = [downQueries]
218,443✔
695

218,443✔
696
        this.sqlInMemory.upQueries.push(...upQueries)
218,443✔
697
        this.sqlInMemory.downQueries.push(...downQueries)
218,443✔
698

218,443✔
699
        // if sql-in-memory mode is enabled then simply store sql in memory and return
218,443✔
700
        if (this.sqlMemoryMode === true)
218,443✔
701
            return Promise.resolve() as Promise<any>
218,443✔
702

217,634✔
703
        for (const { query, parameters } of upQueries) {
218,443✔
704
            await this.query(query, parameters)
335,351✔
705
        }
335,321✔
706
    }
217,604✔
707

245,811✔
708
    /**
245,811✔
709
     * Generated an index name for a table and index
245,811✔
710
     */
245,811✔
711
    protected generateIndexName(
245,811✔
712
        table: Table | View,
104✔
713
        index: TableIndex,
104✔
714
    ): string {
104✔
715
        // new index may be passed without name. In this case we generate index name manually.
104✔
716
        return this.connection.namingStrategy.indexName(
104✔
717
            table,
104✔
718
            index.columnNames,
104✔
719
            index.where,
104✔
720
        )
104✔
721
    }
104✔
722
}
245,811✔
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