Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 27 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
ChangedTablesTracker | |
0.00% |
0 / 27 |
|
0.00% |
0 / 4 |
156 | |
0.00% |
0 / 1 |
startTracking | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
getTables | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
stopTracking | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
recordQuery | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
42 |
1 | <?php |
2 | |
3 | namespace Wikimedia\Rdbms; |
4 | |
5 | use RuntimeException; |
6 | |
7 | /** |
8 | * Utility class that keeps a list of DB tables that were (presumably) changed by write queries. This should only be |
9 | * used in PHPUnit tests. |
10 | * This class should remain a static util class, because it must never be replaced by a mock in tests. |
11 | * |
12 | * @ingroup Database |
13 | * @internal |
14 | */ |
15 | class ChangedTablesTracker { |
16 | private const TRACKED_VERBS = [ 'INSERT', 'UPDATE', 'REPLACE' ]; |
17 | private static bool $trackingEnabled = false; |
18 | /** @var array<string,array<string,true>> Map of [ domain => [ table name => true ] ] */ |
19 | private static array $tableMap = []; |
20 | |
21 | /** |
22 | * Enables query tracking and resets the list of changed tables. |
23 | */ |
24 | public static function startTracking(): void { |
25 | if ( !defined( 'MW_PHPUNIT_TEST' ) ) { |
26 | throw new RuntimeException( "This class is internal and should only be used in tests." ); |
27 | } |
28 | if ( self::$trackingEnabled ) { |
29 | throw new RuntimeException( "Tracking is already enabled" ); |
30 | } |
31 | self::$trackingEnabled = true; |
32 | self::$tableMap = []; |
33 | } |
34 | |
35 | /** |
36 | * Get the tables for a given domain ID |
37 | * |
38 | * @param string $domainId |
39 | * @return string[] |
40 | */ |
41 | public static function getTables( string $domainId ): array { |
42 | $tableMap = self::$tableMap[$domainId] ?? []; |
43 | return array_keys( $tableMap ); |
44 | } |
45 | |
46 | /** |
47 | * Reset the internal list and disable tracking. |
48 | */ |
49 | public static function stopTracking(): void { |
50 | if ( !self::$trackingEnabled ) { |
51 | throw new RuntimeException( "Tracking is not enabled" ); |
52 | } |
53 | self::$tableMap = []; |
54 | self::$trackingEnabled = false; |
55 | } |
56 | |
57 | /** |
58 | * When tracking is enabled and a query alters tables, record the list of tables that are altered. |
59 | * Any table that gets dropped gets removed from the list of altered tables. |
60 | */ |
61 | public static function recordQuery( DatabaseDomain $domain, Query $query ): void { |
62 | if ( !self::$trackingEnabled ) { |
63 | return; |
64 | } |
65 | if ( !$query->isWriteQuery() ) { |
66 | return; |
67 | } |
68 | $domainId = $domain->getId(); |
69 | $queryVerb = $query->getVerb(); |
70 | $tableName = $query->getWriteTable(); |
71 | if ( $tableName === null ) { |
72 | return; |
73 | } |
74 | if ( $queryVerb === 'DROP' ) { |
75 | // Special case: if a table is being dropped, forget about it. |
76 | unset( self::$tableMap[$domainId][$tableName] ); |
77 | return; |
78 | } |
79 | if ( !in_array( $queryVerb, self::TRACKED_VERBS, true ) ) { |
80 | return; |
81 | } |
82 | |
83 | self::$tableMap[$domainId][$tableName] = true; |
84 | } |
85 | } |