• 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

14.29
/src/driver/expo/ExpoQueryRunner.ts
1
import { QueryFailedError } from "../../error/QueryFailedError"
40✔
2
import { QueryRunnerAlreadyReleasedError } from "../../error/QueryRunnerAlreadyReleasedError"
40✔
3
import { QueryResult } from "../../query-runner/QueryResult"
40✔
4
import { Broadcaster } from "../../subscriber/Broadcaster"
40✔
5
import { BroadcasterResult } from "../../subscriber/BroadcasterResult"
40✔
6
import { AbstractSqliteQueryRunner } from "../sqlite-abstract/AbstractSqliteQueryRunner"
40✔
7
import { ExpoDriver } from "./ExpoDriver"
8

9
export class ExpoQueryRunner extends AbstractSqliteQueryRunner {
40✔
10
    driver: ExpoDriver
11

12
    constructor(driver: ExpoDriver) {
13
        super()
×
14
        this.driver = driver
×
15
        this.connection = driver.connection
×
16
        this.broadcaster = new Broadcaster(this)
×
17
    }
18

19
    async beforeMigration(): Promise<void> {
20
        await this.query("PRAGMA foreign_keys = OFF")
×
21
    }
22

23
    async afterMigration(): Promise<void> {
24
        await this.query("PRAGMA foreign_keys = ON")
×
25
    }
26

27
    async query(
28
        query: string,
29
        parameters?: any[],
30
        useStructuredResult = false,
×
31
    ): Promise<any> {
32
        if (this.isReleased) throw new QueryRunnerAlreadyReleasedError()
×
33

34
        const databaseConnection = await this.connect()
×
35
        const broadcasterResult = new BroadcasterResult()
×
36

37
        this.driver.connection.logger.logQuery(query, parameters, this)
×
NEW
38
        await this.broadcaster.broadcast("BeforeQuery", query, parameters)
×
39

40
        const queryStartTime = Date.now()
×
41

42
        const statement = await databaseConnection.prepareAsync(query)
×
43
        try {
×
44
            const rawResult = await statement.executeAsync(parameters)
×
45

46
            const maxQueryExecutionTime =
47
                this.driver.options.maxQueryExecutionTime
×
48
            const queryEndTime = Date.now()
×
49
            const queryExecutionTime = queryEndTime - queryStartTime
×
50

51
            this.broadcaster.broadcastAfterQueryEvent(
×
52
                broadcasterResult,
53
                query,
54
                parameters,
55
                true,
56
                queryExecutionTime,
57
                rawResult,
58
                undefined,
59
            )
60
            await broadcasterResult.wait()
×
61

62
            if (
×
63
                maxQueryExecutionTime &&
×
64
                queryExecutionTime > maxQueryExecutionTime
65
            ) {
66
                this.driver.connection.logger.logQuerySlow(
×
67
                    queryExecutionTime,
68
                    query,
69
                    parameters,
70
                    this,
71
                )
72
            }
73

74
            const result = new QueryResult()
×
75
            result.affected = rawResult.changes
×
76
            result.records = await rawResult.getAllAsync()
×
77
            result.raw = query.startsWith("INSERT INTO")
×
78
                ? rawResult.lastInsertRowId
79
                : result.records
80

81
            return useStructuredResult ? result : result.raw
×
82
        } catch (err) {
83
            this.driver.connection.logger.logQueryError(
×
84
                err,
85
                query,
86
                parameters,
87
                this,
88
            )
89
            this.broadcaster.broadcastAfterQueryEvent(
×
90
                broadcasterResult,
91
                query,
92
                parameters,
93
                false,
94
                0,
95
                undefined,
96
                err,
97
            )
98
            await broadcasterResult.wait()
×
99

100
            throw new QueryFailedError(query, parameters, err)
×
101
        } finally {
NEW
102
            await broadcasterResult.wait()
×
UNCOV
103
            await statement.finalizeAsync()
×
104
        }
105
    }
106
}
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