Failed Conditions
Pull Request — master (#2825)
by Sébastien
10:43
created

createDatabasePlatformForVersion()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 5

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
ccs 8
cts 8
cp 1
rs 8.8571
cc 5
eloc 8
nc 3
nop 1
crap 5
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\DBAL\Driver;
21
22
use Doctrine\DBAL\DBALException;
23
use Doctrine\DBAL\Driver;
24
use Doctrine\DBAL\Exception;
25
use Doctrine\DBAL\Platforms\AbstractPlatform;
26
use Doctrine\DBAL\Platforms\MariaDb102Platform;
27
use Doctrine\DBAL\Platforms\MySQL57Platform;
28
use Doctrine\DBAL\Platforms\MySqlPlatform;
29
use Doctrine\DBAL\Schema\AbstractSchemaManager;
30
use Doctrine\DBAL\Schema\MySqlSchemaManager;
31
use Doctrine\DBAL\VersionAwarePlatformDriver;
32
33
/**
34
 * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for MySQL based drivers.
35
 *
36
 * @author Steve Müller <[email protected]>
37
 * @link   www.doctrine-project.org
38
 * @since  2.5
39
 */
40
abstract class AbstractMySQLDriver implements Driver, ExceptionConverterDriver, VersionAwarePlatformDriver
41
{
42
43
    private const MYSQL_MARIADB_VERSION_REGEXP = '/^(mariadb-)?(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)/';
44
    private const MYSQL_ORACLE_VERSION_REGEXP = '/^(?P<major>\d+)(?:\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?)?/';
45
46
    /**
47
     * {@inheritdoc}
48
     *
49
     * @link http://dev.mysql.com/doc/refman/5.7/en/error-messages-client.html
50
     * @link http://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html
51
     */
52 4
    public function convertException($message, DriverException $exception)
53
    {
54 4
        switch ($exception->getErrorCode()) {
55 4
            case '1213':
56 4
                return new Exception\DeadlockException($message, $exception);
57 4
            case '1205':
58 4
                return new Exception\LockWaitTimeoutException($message, $exception);
59 4
            case '1050':
60 4
                return new Exception\TableExistsException($message, $exception);
61
62 4
            case '1051':
63 4
            case '1146':
64 4
                return new Exception\TableNotFoundException($message, $exception);
65
66 4
            case '1216':
67 4
            case '1217':
68 4
            case '1451':
69 4
            case '1452':
70 4
            case '1701':
71 4
                return new Exception\ForeignKeyConstraintViolationException($message, $exception);
72
73 4
            case '1062':
74 4
            case '1557':
75 4
            case '1569':
76 4
            case '1586':
77 4
                return new Exception\UniqueConstraintViolationException($message, $exception);
78
79 4
            case '1054':
80 4
            case '1166':
81 4
            case '1611':
82 4
                return new Exception\InvalidFieldNameException($message, $exception);
83
84 4
            case '1052':
85 4
            case '1060':
86 4
            case '1110':
87 4
                return new Exception\NonUniqueFieldNameException($message, $exception);
88
89 4
            case '1064':
90 4
            case '1149':
91 4
            case '1287':
92 4
            case '1341':
93 4
            case '1342':
94 4
            case '1343':
95 4
            case '1344':
96 4
            case '1382':
97 4
            case '1479':
98 4
            case '1541':
99 4
            case '1554':
100 4
            case '1626':
101 4
                return new Exception\SyntaxErrorException($message, $exception);
102
103 4
            case '1044':
104 4
            case '1045':
105 4
            case '1046':
106 4
            case '1049':
107 4
            case '1095':
108 4
            case '1142':
109 4
            case '1143':
110 4
            case '1227':
111 4
            case '1370':
112 4
            case '1429':
113 4
            case '2002':
114 4
            case '2005':
115 4
                return new Exception\ConnectionException($message, $exception);
116
117 4
            case '1048':
118 4
            case '1121':
119 4
            case '1138':
120 4
            case '1171':
121 4
            case '1252':
122 4
            case '1263':
123 4
            case '1364':
124 4
            case '1566':
125 4
                return new Exception\NotNullConstraintViolationException($message, $exception);
126
        }
127
128 4
        return new Exception\DriverException($message, $exception);
129
    }
130
131
    /**
132
     * {@inheritdoc}
133
     *
134
     * @return AbstractPlatform|MariaDb102Platform|MySQL57Platform|MySqlPlatform
135
     * @throws DBALException
136
     */
137 6
    public function createDatabasePlatformForVersion($version)
138
    {
139 6
        if (false !== stripos($version, 'mariadb')
140 6
            && version_compare($this->getMariaDbMysqlVersionNumber($version), '10.2.7', '>=')) {
141 3
            return new MariaDb102Platform();
142
        }
143
144 6
        if (false === stripos($version, 'mariadb')
145 6
            && version_compare($this->getOracleMysqlVersionNumber($version), '5.7.9', '>=')) {
146 3
            return new MySQL57Platform();
147
        }
148
149 3
        return $this->getDatabasePlatform();
150
    }
151
152
    /**
153
     * Get a normalized 'version number' from the server string
154
     * returned by Oracle MySQL servers.
155
     *
156
     * @param string $versionString Version string returned by the driver, i.e. '5.7.10'
157
     * @throws DBALException
158
     */
159 6
    private function getOracleMysqlVersionNumber(string $versionString) : string
160
    {
161 6
        if (!preg_match(self::MYSQL_ORACLE_VERSION_REGEXP, $versionString, $versionParts)) {
162 3
            throw DBALException::invalidPlatformVersionSpecified(
163 3
                $versionString,
164 3
                '<major_version>.<minor_version>.<patch_version>'
165
            );
166
        }
167 3
        $majorVersion = $versionParts['major'];
168 3
        $minorVersion = $versionParts['minor'] ?? 0;
169 3
        $patchVersion = $versionParts['patch'] ?? null;
170
171 3
        if ('5' === $majorVersion && '7' === $minorVersion && null === $patchVersion) {
172 3
            $patchVersion = '9';
173
        }
174
175 3
        return $majorVersion . '.' . $minorVersion . '.' . $patchVersion;
176
    }
177
178
    /**
179
     * Detect MariaDB server version, including hack for some mariadb distributions
180
     * that starts with the prefix '5.5.5-'
181
     *
182
     * @param string $versionString Version string as returned by mariadb server, i.e. '5.5.5-Mariadb-10.0.8-xenial'
183
     * @throws DBALException
184
     */
185 3
    private function getMariaDbMysqlVersionNumber(string $versionString) : string
186
    {
187 3
        $version = str_replace('5.5.5-', '', $versionString);
188
189 3
        if (!preg_match(self::MYSQL_MARIADB_VERSION_REGEXP, strtolower($version), $versionParts)) {
190
            throw DBALException::invalidPlatformVersionSpecified(
191
                $version,
192
                '(mariadb-)?<major_version>.<minor_version>.<patch_version>'
193
            );
194
        }
195
196 3
        return $versionParts['major'] . '.' . $versionParts['minor'] . '.' . $versionParts['patch'];
197
    }
198
199
    /**
200
     * {@inheritdoc}
201
     */
202 4
    public function getDatabase(\Doctrine\DBAL\Connection $conn) : ?string
203
    {
204 4
        $params = $conn->getParams();
205
206 4
        if (isset($params['dbname'])) {
207 4
            return $params['dbname'];
208
        }
209
210 4
        return $conn->query('SELECT DATABASE()')->fetchColumn();
0 ignored issues
show
Bug Compatibility introduced by
The expression $conn->query('SELECT DATABASE()')->fetchColumn(); of type string|boolean adds the type boolean to the return on line 210 which is incompatible with the return type declared by the interface Doctrine\DBAL\Driver::getDatabase of type string.
Loading history...
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     * @return MySqlPlatform
216
     */
217 6
    public function getDatabasePlatform() : AbstractPlatform
218
    {
219 6
        return new MySqlPlatform();
220
    }
221
222
    /**
223
     * {@inheritdoc}
224
     * @return MySqlSchemaManager
225
     */
226 3
    public function getSchemaManager(\Doctrine\DBAL\Connection $conn) : AbstractSchemaManager
227
    {
228 3
        return new MySqlSchemaManager($conn);
229
    }
230
}
231