Completed
Pull Request — 2.10.x (#4009)
by Grégoire
08:50
created

createDatabasePlatformForVersion()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 11
cts 11
cp 1
rs 8.9777
c 0
b 0
f 0
cc 6
nc 5
nop 1
crap 6
1
<?php
2
3
namespace Doctrine\DBAL\Driver;
4
5
use Doctrine\DBAL\Connection;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Doctrine\DBAL\Driver\Connection.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
6
use Doctrine\DBAL\DBALException;
7
use Doctrine\DBAL\Driver;
8
use Doctrine\DBAL\Exception;
9
use Doctrine\DBAL\Platforms\MariaDb1027Platform;
10
use Doctrine\DBAL\Platforms\MySQL57Platform;
11
use Doctrine\DBAL\Platforms\MySQL80Platform;
12
use Doctrine\DBAL\Platforms\MySqlPlatform;
13
use Doctrine\DBAL\Schema\MySqlSchemaManager;
14
use Doctrine\DBAL\VersionAwarePlatformDriver;
15
use function preg_match;
16
use function stripos;
17
use function version_compare;
18
19
/**
20
 * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for MySQL based drivers.
21
 */
22
abstract class AbstractMySQLDriver implements Driver, ExceptionConverterDriver, VersionAwarePlatformDriver
23
{
24
    /**
25
     * {@inheritdoc}
26
     *
27
     * @link http://dev.mysql.com/doc/refman/5.7/en/error-messages-client.html
28
     * @link http://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html
29
     */
30 6956
    public function convertException($message, DriverException $exception)
31
    {
32 6956
        switch ($exception->getErrorCode()) {
33 6956
            case '1213':
34 5652
                return new Exception\DeadlockException($message, $exception);
35
36 6952
            case '1205':
37 5629
                return new Exception\LockWaitTimeoutException($message, $exception);
38
39 6948
            case '1050':
40 5813
                return new Exception\TableExistsException($message, $exception);
41
42 6944
            case '1051':
43 6940
            case '1146':
44 5794
                return new Exception\TableNotFoundException($message, $exception);
45
46 6936
            case '1216':
47 6932
            case '1217':
48 6928
            case '1451':
49 6924
            case '1452':
50 6920
            case '1701':
51 6515
                return new Exception\ForeignKeyConstraintViolationException($message, $exception);
52
53 6920
            case '1062':
54 6916
            case '1557':
55 6912
            case '1569':
56 6908
            case '1586':
57 5756
                return new Exception\UniqueConstraintViolationException($message, $exception);
58
59 6904
            case '1054':
60 6900
            case '1166':
61 6896
            case '1611':
62 6419
                return new Exception\InvalidFieldNameException($message, $exception);
63
64 6892
            case '1052':
65 6888
            case '1060':
66 6884
            case '1110':
67 6350
                return new Exception\NonUniqueFieldNameException($message, $exception);
68
69 6880
            case '1064':
70 6876
            case '1149':
71 6872
            case '1287':
72 6868
            case '1341':
73 6864
            case '1342':
74 6860
            case '1343':
75 6856
            case '1344':
76 6852
            case '1382':
77 6848
            case '1479':
78 6844
            case '1541':
79 6840
            case '1554':
80 6836
            case '1626':
81 6133
                return new Exception\SyntaxErrorException($message, $exception);
82
83 6832
            case '1044':
84 6805
            case '1045':
85 6778
            case '1046':
86 6751
            case '1049':
87 6724
            case '1095':
88 6697
            case '1142':
89 6670
            case '1143':
90 6643
            case '1227':
91 6616
            case '1370':
92 6589
            case '1429':
93 6589
            case '2002':
94 6562
            case '2005':
95 6796
                return new Exception\ConnectionException($message, $exception);
96
97 6305
            case '1048':
98 6278
            case '1121':
99 6251
            case '1138':
100 6224
            case '1171':
101 6197
            case '1252':
102 6170
            case '1263':
103 6143
            case '1364':
104 6116
            case '1566':
105 6301
                return new Exception\NotNullConstraintViolationException($message, $exception);
106
        }
107
108 5606
        return new Exception\DriverException($message, $exception);
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     *
114
     * @throws DBALException
115
     */
116 5585
    public function createDatabasePlatformForVersion($version)
117
    {
118 5585
        $mariadb = stripos($version, 'mariadb') !== false;
119 5585
        if ($mariadb && version_compare($this->getMariaDbMysqlVersionNumber($version), '10.2.7', '>=')) {
120 5582
            return new MariaDb1027Platform();
121
        }
122
123 5585
        if (! $mariadb) {
124 5585
            $oracleMysqlVersion = $this->getOracleMysqlVersionNumber($version);
125 5582
            if (version_compare($oracleMysqlVersion, '8', '>=')) {
126 5582
                return new MySQL80Platform();
127
            }
128
129 5582
            if (version_compare($oracleMysqlVersion, '5.7.9', '>=')) {
130 5582
                return new MySQL57Platform();
131
            }
132
        }
133
134 5582
        return $this->getDatabasePlatform();
135
    }
136
137
    /**
138
     * Get a normalized 'version number' from the server string
139
     * returned by Oracle MySQL servers.
140
     *
141
     * @param string $versionString Version string returned by the driver, i.e. '5.7.10'
142
     *
143
     * @throws DBALException
144
     */
145 5585
    private function getOracleMysqlVersionNumber(string $versionString) : string
146
    {
147 5585
        if (! preg_match(
148 6
            '/^(?P<major>\d+)(?:\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?)?/',
149 5585
            $versionString,
150 5585
            $versionParts
151
        )) {
152 5559
            throw DBALException::invalidPlatformVersionSpecified(
153 3
                $versionString,
154 5559
                '<major_version>.<minor_version>.<patch_version>'
155
            );
156
        }
157
158 5582
        $majorVersion = $versionParts['major'];
159 5582
        $minorVersion = $versionParts['minor'] ?? 0;
160 5582
        $patchVersion = $versionParts['patch'] ?? null;
161
162 5582
        if ($majorVersion === '5' && $minorVersion === '7' && $patchVersion === null) {
163 5582
            $patchVersion = '9';
164
        }
165
166 5582
        return $majorVersion . '.' . $minorVersion . '.' . $patchVersion;
167
    }
168
169
    /**
170
     * Detect MariaDB server version, including hack for some mariadb distributions
171
     * that starts with the prefix '5.5.5-'
172
     *
173
     * @param string $versionString Version string as returned by mariadb server, i.e. '5.5.5-Mariadb-10.0.8-xenial'
174
     *
175
     * @throws DBALException
176
     */
177 5582
    private function getMariaDbMysqlVersionNumber(string $versionString) : string
178
    {
179 5582
        if (! preg_match(
180 3
            '/^(?:5\.5\.5-)?(mariadb-)?(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)/i',
181 5582
            $versionString,
182 5582
            $versionParts
183
        )) {
184
            throw DBALException::invalidPlatformVersionSpecified(
185
                $versionString,
186
                '^(?:5\.5\.5-)?(mariadb-)?<major_version>.<minor_version>.<patch_version>'
187
            );
188
        }
189
190 5582
        return $versionParts['major'] . '.' . $versionParts['minor'] . '.' . $versionParts['patch'];
191
    }
192
193
    /**
194
     * {@inheritdoc}
195
     */
196 6779
    public function getDatabase(Connection $conn)
197
    {
198 6779
        $params = $conn->getParams();
199
200 6779
        return $params['dbname'] ?? $conn->query('SELECT DATABASE()')->fetchColumn();
201
    }
202
203
    /**
204
     * {@inheritdoc}
205
     *
206
     * @return MySqlPlatform
207
     */
208 5585
    public function getDatabasePlatform()
209
    {
210 5585
        return new MySqlPlatform();
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     *
216
     * @return MySqlSchemaManager
217
     */
218 5513
    public function getSchemaManager(Connection $conn)
219
    {
220 5513
        return new MySqlSchemaManager($conn);
221
    }
222
}
223