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

typeorm / typeorm / 14764529297

30 Apr 2025 09:16PM UTC coverage: 76.309% (+0.002%) from 76.307%
14764529297

push

github

web-flow
fix: beforeQuery promises not awaited before query execution (#11086)

* fix: beforeQuery promises not awaited before query execution

Closes: #11085

* fix: run format

Closes: #11085

* fix: apply same beforeQuery & afterQuery logic to all drivers

* fix: use a different broadcaster for BeforeQuery / AfterQuery

* fix: BeforeQuery / AfterQuery event types

* fix: move broadCasterResult.wait in finally block

* fix: remove duplicated broadcasterResult.wait in ReactNativeQueryRunner

* fix: fix prettier issue

* fix: implemented requested changes

* fix: broken sqlite tests

* Revert "fix: broken sqlite tests"

This reverts commit 4bacd5f4b.

* Revert "fix: implemented requested changes"

This reverts commit 1d2f59bf2.

* review: undefined type at the end

* fix: move database connection logic outside of the promise bloc

---------

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

9201 of 12761 branches covered (72.1%)

Branch coverage included in aggregate %.

100 of 142 new or added lines in 14 files covered. (70.42%)

4 existing lines in 3 files now uncovered.

18802 of 23936 relevant lines covered (78.55%)

197469.14 hits per line

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

11.29
/src/driver/react-native/ReactNativeQueryRunner.ts
1
import { ObjectLiteral } from "../../common/ObjectLiteral"
2
import { QueryFailedError } from "../../error/QueryFailedError"
40✔
3
import { QueryRunnerAlreadyReleasedError } from "../../error/QueryRunnerAlreadyReleasedError"
40✔
4
import { QueryResult } from "../../query-runner/QueryResult"
40✔
5
import { Broadcaster } from "../../subscriber/Broadcaster"
40✔
6
import { BroadcasterResult } from "../../subscriber/BroadcasterResult"
40✔
7
import { AbstractSqliteQueryRunner } from "../sqlite-abstract/AbstractSqliteQueryRunner"
40✔
8
import { ReactNativeDriver } from "./ReactNativeDriver"
9

10
/**
11
 * Runs queries on a single sqlite database connection.
12
 */
13
export class ReactNativeQueryRunner extends AbstractSqliteQueryRunner {
40✔
14
    /**
15
     * Database driver used by connection.
16
     */
17
    // @ts-ignore temporary, we need to fix the issue with the AbstractSqliteDriver and circular errors
18
    driver: ReactNativeDriver
19

20
    // -------------------------------------------------------------------------
21
    // Constructor
22
    // -------------------------------------------------------------------------
23

24
    constructor(driver: ReactNativeDriver) {
25
        super()
×
26
        this.driver = driver
×
27
        this.connection = driver.connection
×
28
        this.broadcaster = new Broadcaster(this)
×
29
    }
30

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

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

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

NEW
55
        const databaseConnection = await this.connect()
×
56

NEW
57
        this.driver.connection.logger.logQuery(query, parameters, this)
×
NEW
58
        await this.broadcaster.broadcast("BeforeQuery", query, parameters)
×
59

NEW
60
        const broadcasterResult = new BroadcasterResult()
×
61

NEW
62
        const queryStartTime = Date.now()
×
63

64
        return new Promise(async (ok, fail) => {
×
NEW
65
            try {
×
NEW
66
                databaseConnection.executeSql(
×
67
                    query,
68
                    parameters,
69
                    async (raw: any) => {
70
                        // log slow queries if maxQueryExecution time is set
71
                        const maxQueryExecutionTime =
NEW
72
                            this.driver.options.maxQueryExecutionTime
×
NEW
73
                        const queryEndTime = Date.now()
×
NEW
74
                        const queryExecutionTime = queryEndTime - queryStartTime
×
NEW
75
                        this.broadcaster.broadcastAfterQueryEvent(
×
76
                            broadcasterResult,
77
                            query,
78
                            parameters,
79
                            true,
80
                            queryExecutionTime,
81
                            raw,
82
                            undefined,
83
                        )
84

NEW
85
                        if (
×
86
                            maxQueryExecutionTime &&
×
87
                            queryExecutionTime > maxQueryExecutionTime
88
                        )
NEW
89
                            this.driver.connection.logger.logQuerySlow(
×
90
                                queryExecutionTime,
91
                                query,
92
                                parameters,
93
                                this,
94
                            )
95

NEW
96
                        if (broadcasterResult.promises.length > 0)
×
NEW
97
                            await Promise.all(broadcasterResult.promises)
×
98

NEW
99
                        const result = new QueryResult()
×
100

NEW
101
                        if (raw?.hasOwnProperty("rowsAffected")) {
×
NEW
102
                            result.affected = raw.rowsAffected
×
103
                        }
104

NEW
105
                        if (raw?.hasOwnProperty("rows")) {
×
NEW
106
                            const records = []
×
NEW
107
                            for (let i = 0; i < raw.rows.length; i++) {
×
NEW
108
                                records.push(raw.rows.item(i))
×
109
                            }
110

NEW
111
                            result.raw = records
×
NEW
112
                            result.records = records
×
113
                        }
114

115
                        // return id of inserted row, if query was insert statement.
NEW
116
                        if (query.substr(0, 11) === "INSERT INTO") {
×
NEW
117
                            result.raw = raw.insertId
×
118
                        }
119

NEW
120
                        if (useStructuredResult) {
×
NEW
121
                            ok(result)
×
122
                        } else {
NEW
123
                            ok(result.raw)
×
124
                        }
125
                    },
126
                    async (err: any) => {
NEW
127
                        this.driver.connection.logger.logQueryError(
×
128
                            err,
129
                            query,
130
                            parameters,
131
                            this,
132
                        )
NEW
133
                        this.broadcaster.broadcastAfterQueryEvent(
×
134
                            broadcasterResult,
135
                            query,
136
                            parameters,
137
                            false,
138
                            undefined,
139
                            undefined,
140
                            err,
141
                        )
142

NEW
143
                        fail(new QueryFailedError(query, parameters, err))
×
144
                    },
145
                )
146
            } catch (err) {
NEW
147
                fail(err)
×
148
            } finally {
NEW
149
                await broadcasterResult.wait()
×
150
            }
151
        })
152
    }
153

154
    // -------------------------------------------------------------------------
155
    // Protected Methods
156
    // -------------------------------------------------------------------------
157

158
    /**
159
     * Parametrizes given object of values. Used to create column=value queries.
160
     */
161
    protected parametrize(
162
        objectLiteral: ObjectLiteral,
163
        startIndex: number = 0,
×
164
    ): string[] {
165
        return Object.keys(objectLiteral).map((key, index) => `"${key}"` + "=?")
×
166
    }
167
}
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