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

typeorm / typeorm / 15219332477

23 May 2025 09:13PM UTC coverage: 17.216% (-59.1%) from 76.346%
15219332477

Pull #11332

github

naorpeled
cr comments - move if block
Pull Request #11332: feat: add new undefined and null behavior flags

1603 of 12759 branches covered (12.56%)

Branch coverage included in aggregate %.

0 of 31 new or added lines in 3 files covered. (0.0%)

14132 existing lines in 166 files now uncovered.

4731 of 24033 relevant lines covered (19.69%)

60.22 hits per line

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

8.24
/src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts
1
import { QueryRunnerAlreadyReleasedError } from "../../error/QueryRunnerAlreadyReleasedError"
1✔
2
import { QueryFailedError } from "../../error/QueryFailedError"
1✔
3
import { AbstractSqliteQueryRunner } from "../sqlite-abstract/AbstractSqliteQueryRunner"
1✔
4
import { Broadcaster } from "../../subscriber/Broadcaster"
1✔
5
import { BetterSqlite3Driver } from "./BetterSqlite3Driver"
6
import { QueryResult } from "../../query-runner/QueryResult"
1✔
7
import { BroadcasterResult } from "../../subscriber/BroadcasterResult"
1✔
8

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

21
    // -------------------------------------------------------------------------
22
    // Constructor
23
    // -------------------------------------------------------------------------
24

25
    constructor(driver: BetterSqlite3Driver) {
UNCOV
26
        super()
×
UNCOV
27
        this.driver = driver
×
UNCOV
28
        this.connection = driver.connection
×
UNCOV
29
        this.broadcaster = new Broadcaster(this)
×
UNCOV
30
        if (typeof this.driver.options.statementCacheSize === "number") {
×
31
            this.cacheSize = this.driver.options.statementCacheSize
×
32
        } else {
UNCOV
33
            this.cacheSize = 100
×
34
        }
35
    }
36

37
    private cacheSize: number
UNCOV
38
    private stmtCache = new Map<string, any>()
×
39

40
    private async getStmt(query: string) {
UNCOV
41
        if (this.cacheSize > 0) {
×
UNCOV
42
            let stmt = this.stmtCache.get(query)
×
UNCOV
43
            if (!stmt) {
×
UNCOV
44
                const databaseConnection = await this.connect()
×
UNCOV
45
                stmt = databaseConnection.prepare(query)
×
UNCOV
46
                this.stmtCache.set(query, stmt)
×
UNCOV
47
                while (this.stmtCache.size > this.cacheSize) {
×
48
                    // since es6 map keeps the insertion order,
49
                    // it comes to be FIFO cache
UNCOV
50
                    const key = this.stmtCache.keys().next().value!
×
UNCOV
51
                    this.stmtCache.delete(key)
×
52
                }
53
            }
UNCOV
54
            return stmt
×
55
        } else {
56
            const databaseConnection = await this.connect()
×
57
            return databaseConnection.prepare(query)
×
58
        }
59
    }
60

61
    /**
62
     * Called before migrations are run.
63
     */
64
    async beforeMigration(): Promise<void> {
UNCOV
65
        await this.query(`PRAGMA foreign_keys = OFF`)
×
66
    }
67

68
    /**
69
     * Called after migrations are run.
70
     */
71
    async afterMigration(): Promise<void> {
UNCOV
72
        await this.query(`PRAGMA foreign_keys = ON`)
×
73
    }
74

75
    /**
76
     * Executes a given SQL query.
77
     */
78
    async query(
79
        query: string,
80
        parameters?: any[],
81
        useStructuredResult = false,
×
82
    ): Promise<any> {
UNCOV
83
        if (this.isReleased) throw new QueryRunnerAlreadyReleasedError()
×
84

UNCOV
85
        const connection = this.driver.connection
×
86

UNCOV
87
        const broadcasterResult = new BroadcasterResult()
×
88

UNCOV
89
        this.driver.connection.logger.logQuery(query, parameters, this)
×
UNCOV
90
        this.broadcaster.broadcastBeforeQueryEvent(
×
91
            broadcasterResult,
92
            query,
93
            parameters,
94
        )
UNCOV
95
        const queryStartTime = Date.now()
×
96

UNCOV
97
        const stmt = await this.getStmt(query)
×
98

UNCOV
99
        try {
×
UNCOV
100
            const result = new QueryResult()
×
101

UNCOV
102
            if (stmt.reader) {
×
UNCOV
103
                const raw = stmt.all.apply(stmt, parameters)
×
104

UNCOV
105
                result.raw = raw
×
106

UNCOV
107
                if (Array.isArray(raw)) {
×
UNCOV
108
                    result.records = raw
×
109
                }
110
            } else {
UNCOV
111
                const raw = stmt.run.apply(stmt, parameters)
×
UNCOV
112
                result.affected = raw.changes
×
UNCOV
113
                result.raw = raw.lastInsertRowid
×
114
            }
115

116
            // log slow queries if maxQueryExecution time is set
117
            const maxQueryExecutionTime =
UNCOV
118
                this.driver.options.maxQueryExecutionTime
×
UNCOV
119
            const queryEndTime = Date.now()
×
UNCOV
120
            const queryExecutionTime = queryEndTime - queryStartTime
×
UNCOV
121
            if (
×
122
                maxQueryExecutionTime &&
×
123
                queryExecutionTime > maxQueryExecutionTime
124
            )
125
                connection.logger.logQuerySlow(
×
126
                    queryExecutionTime,
127
                    query,
128
                    parameters,
129
                    this,
130
                )
131

UNCOV
132
            this.broadcaster.broadcastAfterQueryEvent(
×
133
                broadcasterResult,
134
                query,
135
                parameters,
136
                true,
137
                queryExecutionTime,
138
                result.raw,
139
                undefined,
140
            )
141

UNCOV
142
            if (!useStructuredResult) {
×
UNCOV
143
                return result.raw
×
144
            }
145

UNCOV
146
            return result
×
147
        } catch (err) {
UNCOV
148
            connection.logger.logQueryError(err, query, parameters, this)
×
UNCOV
149
            throw new QueryFailedError(query, parameters, err)
×
150
        }
151
    }
152

153
    // -------------------------------------------------------------------------
154
    // Protected Methods
155
    // -------------------------------------------------------------------------
156

157
    protected async loadTableRecords(
158
        tablePath: string,
159
        tableOrIndex: "table" | "index",
160
    ) {
UNCOV
161
        const [database, tableName] = this.splitTablePath(tablePath)
×
UNCOV
162
        const res = await this.query(
×
163
            `SELECT ${
164
                database ? `'${database}'` : null
×
165
            } as database, * FROM ${this.escapePath(
166
                `${database ? `${database}.` : ""}sqlite_master`,
×
167
            )} WHERE "type" = '${tableOrIndex}' AND "${
168
                tableOrIndex === "table" ? "name" : "tbl_name"
×
169
            }" IN ('${tableName}')`,
170
        )
UNCOV
171
        return res
×
172
    }
173
    protected async loadPragmaRecords(tablePath: string, pragma: string) {
UNCOV
174
        const [database, tableName] = this.splitTablePath(tablePath)
×
UNCOV
175
        const res = await this.query(
×
176
            `PRAGMA ${
177
                database ? `"${database}".` : ""
×
178
            }${pragma}("${tableName}")`,
179
        )
UNCOV
180
        return res
×
181
    }
182
}
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

© 2025 Coveralls, Inc