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

getMariaDbMysqlVersionNumber()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 13
ccs 1
cts 1
cp 1
rs 9.4285
cc 2
eloc 7
nc 2
nop 1
crap 2
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
     * {@inheritdoc}
44
     *
45 4
     * @link http://dev.mysql.com/doc/refman/5.7/en/error-messages-client.html
46
     * @link http://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html
47 4
     */
48 4
    public function convertException($message, DriverException $exception)
49 4
    {
50 4
        switch ($exception->getErrorCode()) {
51 4
            case '1213':
52 4
                return new Exception\DeadlockException($message, $exception);
53 4
            case '1205':
54
                return new Exception\LockWaitTimeoutException($message, $exception);
55 4
            case '1050':
56 4
                return new Exception\TableExistsException($message, $exception);
57 4
58
            case '1051':
59 4
            case '1146':
60 4
                return new Exception\TableNotFoundException($message, $exception);
61 4
62 4
            case '1216':
63 4
            case '1217':
64 4
            case '1451':
65
            case '1452':
66 4
            case '1701':
67 4
                return new Exception\ForeignKeyConstraintViolationException($message, $exception);
68 4
69 4
            case '1062':
70 4
            case '1557':
71
            case '1569':
72 4
            case '1586':
73 4
                return new Exception\UniqueConstraintViolationException($message, $exception);
74 4
75 4
            case '1054':
76
            case '1166':
77 4
            case '1611':
78 4
                return new Exception\InvalidFieldNameException($message, $exception);
79 4
80 4
            case '1052':
81
            case '1060':
82 4
            case '1110':
83 4
                return new Exception\NonUniqueFieldNameException($message, $exception);
84 4
85 4
            case '1064':
86 4
            case '1149':
87 4
            case '1287':
88 4
            case '1341':
89 4
            case '1342':
90 4
            case '1343':
91 4
            case '1344':
92 4
            case '1382':
93 4
            case '1479':
94 4
            case '1541':
95
            case '1554':
96 4
            case '1626':
97 4
                return new Exception\SyntaxErrorException($message, $exception);
98 4
99 4
            case '1044':
100 4
            case '1045':
101 4
            case '1046':
102 4
            case '1049':
103 4
            case '1095':
104 4
            case '1142':
105 4
            case '1143':
106 4
            case '1227':
107 4
            case '1370':
108 4
            case '1429':
109
            case '2002':
110 4
            case '2005':
111 4
                return new Exception\ConnectionException($message, $exception);
112 4
113 4
            case '1048':
114 4
            case '1121':
115 4
            case '1138':
116 4
            case '1171':
117 4
            case '1252':
118 4
            case '1263':
119
            case '1364':
120
            case '1566':
121 4
                return new Exception\NotNullConstraintViolationException($message, $exception);
122
        }
123
124
        return new Exception\DriverException($message, $exception);
125
    }
126
127 6
    /**
128
     * {@inheritdoc}
129 6
     *
130 3
     * @return AbstractPlatform|MariaDb102Platform|MySQL57Platform|MySqlPlatform
131 3
     * @throws DBALException
132 3
     */
133
    public function createDatabasePlatformForVersion($version): AbstractPlatform
134
    {
135
        if (false !== stripos($version, 'mariadb')) {
136 3
            $versionNumber = $this->getMariaDbMysqlVersionNumber($version);
137 3
            if (version_compare($versionNumber, '10.2.7', '>=')) {
138
                return new MariaDb102Platform();
139
            }
140 3
        } else {
141 3
            $versionNumber = $this->getOracleMysqlVersionNumber($version);
142 3
            if (version_compare($versionNumber, '5.7.9', '>=')) {
143
                return new MySQL57Platform();
144 3
            }
145 3
        }
146
147
        return $this->getDatabasePlatform();
148 3
    }
149
150 3
    /**
151 3
     * Get a normalized 'version number' from the server string
152
     * returned by Oracle MySQL servers.
153
     *
154 3
     * @param string $versionString Version string returned by the driver, i.e. '5.7.10'
155
     * @throws DBALException
156
     */
157
    private function getOracleMysqlVersionNumber(string $versionString): string
158
    {
159
        if (!preg_match('/^(?P<major>\d+)(?:\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?)?/', $versionString, $versionParts)) {
160 4
            throw DBALException::invalidPlatformVersionSpecified(
161
                $versionString,
162 4
                '<major_version>.<minor_version>.<patch_version>'
163
            );
164 4
        }
165 4
        $majorVersion = $versionParts['major'];
166
        $minorVersion = $versionParts['minor'] ?? 0;
167
        $patchVersion = $versionParts['patch'] ?? null;
168 4
169
        if ('5' === $majorVersion && '7' === $minorVersion && null === $patchVersion) {
170
            $patchVersion = '9';
171
        }
172
173
        return $majorVersion . '.' . $minorVersion . '.' . $patchVersion;
174 6
    }
175
176 6
    /**
177
     * Detect MariaDB server version, including hack for some mariadb distributions
178
     * that starts with the prefix '5.5.5-'
179
     *
180
     * @param string $versionString Version string as returned by mariadb server, i.e. '5.5.5-Mariadb-10.0.8-xenial'
181
     * @throws DBALException
182 3
     */
183
    private function getMariaDbMysqlVersionNumber(string $versionString): string
184 3
    {
185
        $version = str_replace('5.5.5-', '', $versionString);
186
187
        if (!preg_match('/^(mariadb-)?(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)/', strtolower($version), $versionParts)) {
188
            throw DBALException::invalidPlatformVersionSpecified(
189
                $version,
190
                '(mariadb-)?<major_version>.<minor_version>.<patch_version>'
191
            );
192
        }
193
194
        return $versionParts['major'] . '.' . $versionParts['minor'] . '.' . $versionParts['patch'];
195
    }
196
197
    /**
198
     * {@inheritdoc}
199
     */
200
    public function getDatabase(\Doctrine\DBAL\Connection $conn): ?string
201
    {
202
        $params = $conn->getParams();
203
204
        if (isset($params['dbname'])) {
205
            return $params['dbname'];
206
        }
207
208
        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 208 which is incompatible with the return type declared by the interface Doctrine\DBAL\Driver::getDatabase of type string.
Loading history...
209
    }
210
211
    /**
212
     * {@inheritdoc}
213
     * @return MySqlPlatform
214
     */
215
    public function getDatabasePlatform(): AbstractPlatform
216
    {
217
        return new MySqlPlatform();
218
    }
219
220
    /**
221
     * {@inheritdoc}
222
     * @return MySqlSchemaManager
223
     */
224
    public function getSchemaManager(\Doctrine\DBAL\Connection $conn): AbstractSchemaManager
225
    {
226
        return new MySqlSchemaManager($conn);
227
    }
228
}
229