Issues (43)

src/Debug/DatabaseCollector.php (1 issue)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Debug;
6
7
use Throwable;
8
use Yiisoft\Yii\Debug\Collector\CollectorTrait;
9
use Yiisoft\Yii\Debug\Collector\SummaryCollectorInterface;
10
11
final class DatabaseCollector implements SummaryCollectorInterface
12
{
13
    use CollectorTrait;
14
15
    private const ACTION_QUERY_START = 'query.start';
16
    private const ACTION_QUERY_END = 'query.end';
17
    private const ACTION_QUERY_ERROR = 'query.error';
18
19
    private const ACTION_TRANSACTION_START = 'transaction.start';
20
    private const ACTION_TRANSACTION_ROLLBACK = 'transaction.rollback';
21
    private const ACTION_TRANSACTION_COMMIT = 'transaction.commit';
22
23
    private const TRANSACTION_STATUS_COMMIT = 'commit';
24
    private const TRANSACTION_STATUS_ROLLBACK = 'rollback';
25
    private const TRANSACTION_STATUS_START = 'start';
26
27
    private const QUERY_STATUS_INITIALIZED = 'initialized';
28
    private const QUERY_STATUS_ERROR = 'error';
29
    private const QUERY_STATUS_SUCCESS = 'success';
30
31
    /**
32
     * @psalm-var array<string, array{
33
     *     rowNumber: int,
34
     *     transactionId: int,
35
     *     sql: string,
36
     *     rawSql: string,
37
     *     params: array,
38
     *     line: string,
39
     *     status: string,
40
     *     actions: array<string, mixed>
41
     *     }>
42
     */
43
    private array $queries = [];
44
    /**
45
     * @psalm-var array<int, array{
46
     *     id: int,
47
     *     position: int,
48
     *     status: string,
49
     *     line: string,
50
     *     level: string|null,
51
     *     actions: array<string, mixed>,
52
     *     exception: Throwable|null,
53
     *     }>
54
     */
55
    private array $transactions = [];
56
57
    private int $position = 0;
58
    private int $currentTransactionId = 0;
59
60
    /**
61
     * @psalm-suppress InvalidPropertyAssignmentValue
62
     */
63
    public function collectQueryStart(
64
        string $id,
65
        string $sql,
66
        string $rawSql,
67
        array $params,
68
        string $line,
69
    ): void {
70
        $this->queries[$id] = [
71
            'position' => $this->position++,
72
            'transactionId' => $this->currentTransactionId,
73
            'sql' => $sql,
74
            'rawSql' => $rawSql,
75
            'params' => $params,
76
            'line' => $line,
77
            'status' => self::QUERY_STATUS_INITIALIZED,
78
            'actions' => [
79
                [
80
                    'action' => self::ACTION_QUERY_START,
81
                    'time' => microtime(true),
82
                ],
83
            ],
84
        ];
85
    }
86
87
    /**
88
     * @psalm-suppress InvalidPropertyAssignmentValue
89
     */
90
    public function collectQueryEnd(
91
        string $id,
92
        int $rowsNumber,
93
    ): void {
94
        $this->queries[$id]['rowsNumber'] = $rowsNumber;
95
        $this->queries[$id]['status'] = self::QUERY_STATUS_SUCCESS;
96
        $this->queries[$id]['actions'][] = [
97
            'action' => self::ACTION_QUERY_END,
98
            'time' => microtime(true),
99
        ];
100
    }
101
102
    /**
103
     * @psalm-suppress InvalidPropertyAssignmentValue
104
     */
105
    public function collectQueryError(
106
        string $id,
107
        Throwable $exception,
108
    ): void {
109
        $this->queries[$id]['exception'] = $exception;
110
        $this->queries[$id]['status'] = self::QUERY_STATUS_ERROR;
111
        $this->queries[$id]['actions'][] = [
112
            'action' => self::ACTION_QUERY_ERROR,
113
            'time' => microtime(true),
114
        ];
115
    }
116
117
    /**
118
     * @psalm-suppress InvalidPropertyAssignmentValue
119
     */
120
    public function collectTransactionStart(
121
        ?string $isolationLevel,
122
        string $line,
123
    ): void {
124
        $id = ++$this->currentTransactionId;
125
        $this->transactions[$id] = [
126
            'id' => $id,
127
            'position' => $this->position++,
128
            'status' => self::TRANSACTION_STATUS_START,
129
            'line' => $line,
130
            'level' => $isolationLevel,
131
            'actions' => [
132
                [
133
                    'action' => self::ACTION_TRANSACTION_START,
134
                    'time' => microtime(true),
135
                ],
136
            ],
137
        ];
138
    }
139
140
    /**
141
     * @psalm-suppress InvalidPropertyAssignmentValue
142
     */
143
    public function collectTransactionRollback(
144
        string $line,
145
    ): void {
146
        $this->transactions[$this->currentTransactionId]['status'] = self::TRANSACTION_STATUS_ROLLBACK;
147
        $this->transactions[$this->currentTransactionId]['actions'][] = [
148
            'action' => self::ACTION_TRANSACTION_ROLLBACK,
149
            'line' => $line,
150
            'time' => microtime(true),
151
        ];
152
        ++$this->currentTransactionId;
153
    }
154
155
    /**
156
     * @psalm-suppress InvalidPropertyAssignmentValue
157
     */
158
    public function collectTransactionCommit(
159
        string $line,
160
    ): void {
161
        $this->transactions[$this->currentTransactionId]['status'] = self::TRANSACTION_STATUS_COMMIT;
162
        $this->transactions[$this->currentTransactionId]['actions'][] = [
163
            'action' => self::ACTION_TRANSACTION_COMMIT,
164
            'line' => $line,
165
            'time' => microtime(true),
166
        ];
167
        ++$this->currentTransactionId;
168
    }
169
170
    public function getCollected(): array
171
    {
172
        $queries = array_values($this->queries);
173
        usort($queries, fn (array $a, array $b) => $a['position'] <=> $b['position']);
174
175
        return [
176
            'queries' => $this->queries,
177
            'transactions' => $this->transactions,
178
        ];
179
    }
180
181
    public function getSummary(): array
182
    {
183
        return [
184
            'db' => [
185
                'queries' => [
186
                    'error' => count(
187
                        array_filter($this->queries, fn (array $query) => $query['status'] === self::QUERY_STATUS_ERROR)
188
                    ),
189
                    'total' => count($this->queries),
190
                ],
191
                'transactions' => [
192
                    'error' => count(
193
                        array_filter(
194
                            $this->transactions,
195
                            fn (array $query) => $query['status'] === self::TRANSACTION_STATUS_ROLLBACK
196
                        )
197
                    ),
198
                    'total' => count($this->transactions),
199
                ],
200
            ],
201
        ];
202
    }
203
204
    private function reset(): void
0 ignored issues
show
The method reset() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
205
    {
206
        $this->queries = [];
207
        $this->transactions = [];
208
        $this->position = 0;
209
        $this->currentTransactionId = 0;
210
    }
211
}
212