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

typeorm / typeorm / 15558174361

10 Jun 2025 11:24AM UTC coverage: 48.469% (-27.9%) from 76.328%
15558174361

Pull #11422

github

web-flow
Merge 817e6d91c into 86f12c922
Pull Request #11422: fix(tree-entity): closure junction table primary key definition should match parent table

5632 of 12872 branches covered (43.75%)

Branch coverage included in aggregate %.

12323 of 24172 relevant lines covered (50.98%)

35101.77 hits per line

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

9.2
/src/driver/sqlite/SqliteQueryRunner.ts
1
import { ConnectionIsNotSetError } from "../../error/ConnectionIsNotSetError"
8✔
2
import { QueryFailedError } from "../../error/QueryFailedError"
8✔
3
import { QueryRunnerAlreadyReleasedError } from "../../error/QueryRunnerAlreadyReleasedError"
8✔
4
import { QueryResult } from "../../query-runner/QueryResult"
8✔
5
import { Broadcaster } from "../../subscriber/Broadcaster"
8✔
6
import { BroadcasterResult } from "../../subscriber/BroadcasterResult"
8✔
7
import { AbstractSqliteQueryRunner } from "../sqlite-abstract/AbstractSqliteQueryRunner"
8✔
8
import { SqliteConnectionOptions } from "./SqliteConnectionOptions"
9
import { SqliteDriver } from "./SqliteDriver"
10

11
/**
12
 * Runs queries on a single sqlite database connection.
13
 *
14
 * Does not support compose primary keys with autoincrement field.
15
 * todo: need to throw exception for this case.
16
 */
17
export class SqliteQueryRunner extends AbstractSqliteQueryRunner {
8✔
18
    /**
19
     * Database driver used by connection.
20
     */
21
    driver: SqliteDriver
22

23
    // -------------------------------------------------------------------------
24
    // Constructor
25
    // -------------------------------------------------------------------------
26

27
    constructor(driver: SqliteDriver) {
28
        super()
×
29
        this.driver = driver
×
30
        this.connection = driver.connection
×
31
        this.broadcaster = new Broadcaster(this)
×
32
    }
33

34
    /**
35
     * Called before migrations are run.
36
     */
37
    async beforeMigration(): Promise<void> {
38
        await this.query(`PRAGMA foreign_keys = OFF`)
×
39
    }
40

41
    /**
42
     * Called after migrations are run.
43
     */
44
    async afterMigration(): Promise<void> {
45
        await this.query(`PRAGMA foreign_keys = ON`)
×
46
    }
47

48
    /**
49
     * Executes a given SQL query.
50
     */
51
    async query(
52
        query: string,
53
        parameters?: any[],
54
        useStructuredResult = false,
×
55
    ): Promise<any> {
56
        if (this.isReleased) throw new QueryRunnerAlreadyReleasedError()
×
57

58
        const connection = this.driver.connection
×
59
        const options = connection.options as SqliteConnectionOptions
×
60
        const maxQueryExecutionTime = this.driver.options.maxQueryExecutionTime
×
61
        const broadcaster = this.broadcaster
×
62

63
        if (!connection.isInitialized) {
×
64
            throw new ConnectionIsNotSetError("sqlite")
×
65
        }
66

67
        const databaseConnection = await this.connect()
×
68

69
        this.driver.connection.logger.logQuery(query, parameters, this)
×
70
        await broadcaster.broadcast("BeforeQuery", query, parameters)
×
71

72
        const broadcasterResult = new BroadcasterResult()
×
73

74
        return new Promise(async (ok, fail) => {
×
75
            try {
×
76
                const queryStartTime = Date.now()
×
77
                const isInsertQuery = query.startsWith("INSERT ")
×
78
                const isDeleteQuery = query.startsWith("DELETE ")
×
79
                const isUpdateQuery = query.startsWith("UPDATE ")
×
80

81
                const execute = async () => {
×
82
                    if (isInsertQuery || isDeleteQuery || isUpdateQuery) {
×
83
                        await databaseConnection.run(query, parameters, handler)
×
84
                    } else {
85
                        await databaseConnection.all(query, parameters, handler)
×
86
                    }
87
                }
88

89
                const self = this
×
90
                const handler = function (this: any, err: any, rows: any) {
×
91
                    if (err && err.toString().indexOf("SQLITE_BUSY:") !== -1) {
×
92
                        if (
×
93
                            typeof options.busyErrorRetry === "number" &&
×
94
                            options.busyErrorRetry > 0
95
                        ) {
96
                            setTimeout(execute, options.busyErrorRetry)
×
97
                            return
×
98
                        }
99
                    }
100

101
                    // log slow queries if maxQueryExecution time is set
102
                    const queryEndTime = Date.now()
×
103
                    const queryExecutionTime = queryEndTime - queryStartTime
×
104
                    if (
×
105
                        maxQueryExecutionTime &&
×
106
                        queryExecutionTime > maxQueryExecutionTime
107
                    )
108
                        connection.logger.logQuerySlow(
×
109
                            queryExecutionTime,
110
                            query,
111
                            parameters,
112
                            self,
113
                        )
114

115
                    if (err) {
×
116
                        connection.logger.logQueryError(
×
117
                            err,
118
                            query,
119
                            parameters,
120
                            self,
121
                        )
122
                        broadcaster.broadcastAfterQueryEvent(
×
123
                            broadcasterResult,
124
                            query,
125
                            parameters,
126
                            false,
127
                            undefined,
128
                            undefined,
129
                            err,
130
                        )
131

132
                        return fail(
×
133
                            new QueryFailedError(query, parameters, err),
134
                        )
135
                    } else {
136
                        const result = new QueryResult()
×
137

138
                        if (isInsertQuery) {
×
139
                            result.raw = this["lastID"]
×
140
                        } else {
141
                            result.raw = rows
×
142
                        }
143

144
                        broadcaster.broadcastAfterQueryEvent(
×
145
                            broadcasterResult,
146
                            query,
147
                            parameters,
148
                            true,
149
                            queryExecutionTime,
150
                            result.raw,
151
                            undefined,
152
                        )
153

154
                        if (Array.isArray(rows)) {
×
155
                            result.records = rows
×
156
                        }
157

158
                        result.affected = this["changes"]
×
159

160
                        if (useStructuredResult) {
×
161
                            ok(result)
×
162
                        } else {
163
                            ok(result.raw)
×
164
                        }
165
                    }
166
                }
167

168
                await execute()
×
169
            } catch (err) {
170
                fail(err)
×
171
            } finally {
172
                await broadcasterResult.wait()
×
173
            }
174
        })
175
    }
176
}
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