AbstractPostgreSQLDriver.php 4.17 KB
Newer Older
1 2 3 4
<?php

namespace Doctrine\DBAL\Driver;

5
use Doctrine\DBAL\Connection;
6 7
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Exception;
8
use Doctrine\DBAL\Platforms\PostgreSQL100Platform;
9
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
10 11
use Doctrine\DBAL\Schema\PostgreSqlSchemaManager;
use Doctrine\DBAL\VersionAwarePlatformDriver;
12

13 14 15
use function preg_match;
use function strpos;
use function version_compare;
16 17 18 19

/**
 * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for PostgreSQL based drivers.
 */
20
abstract class AbstractPostgreSQLDriver implements ExceptionConverterDriver, VersionAwarePlatformDriver
21 22 23 24
{
    /**
     * {@inheritdoc}
     *
25
     * @link http://www.postgresql.org/docs/9.4/static/errcodes-appendix.html
26 27 28 29
     */
    public function convertException($message, DriverException $exception)
    {
        switch ($exception->getSQLState()) {
30 31 32
            case '40001':
            case '40P01':
                return new Exception\DeadlockException($message, $exception);
Sergei Morozov's avatar
Sergei Morozov committed
33

34 35 36 37 38 39 40 41
            case '0A000':
                // Foreign key constraint violations during a TRUNCATE operation
                // are considered "feature not supported" in PostgreSQL.
                if (strpos($exception->getMessage(), 'truncate') !== false) {
                    return new Exception\ForeignKeyConstraintViolationException($message, $exception);
                }

                break;
Sergei Morozov's avatar
Sergei Morozov committed
42

43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
            case '23502':
                return new Exception\NotNullConstraintViolationException($message, $exception);

            case '23503':
                return new Exception\ForeignKeyConstraintViolationException($message, $exception);

            case '23505':
                return new Exception\UniqueConstraintViolationException($message, $exception);

            case '42601':
                return new Exception\SyntaxErrorException($message, $exception);

            case '42702':
                return new Exception\NonUniqueFieldNameException($message, $exception);

            case '42703':
                return new Exception\InvalidFieldNameException($message, $exception);

            case '42P01':
                return new Exception\TableNotFoundException($message, $exception);

            case '42P07':
                return new Exception\TableExistsException($message, $exception);

            case '7':
                // In some case (mainly connection errors) the PDO exception does not provide a SQLSTATE via its code.
                // The exception code is always set to 7 here.
                // We have to match against the SQLSTATE in the error message in these cases.
                if (strpos($exception->getMessage(), 'SQLSTATE[08006]') !== false) {
                    return new Exception\ConnectionException($message, $exception);
                }
74

75 76 77 78 79 80 81 82 83 84 85
                break;
        }

        return new Exception\DriverException($message, $exception);
    }

    /**
     * {@inheritdoc}
     */
    public function createDatabasePlatformForVersion($version)
    {
86
        if (preg_match('/^(?P<major>\d+)(?:\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?)?/', $version, $versionParts) === 0) {
87 88 89 90 91 92 93
            throw DBALException::invalidPlatformVersionSpecified(
                $version,
                '<major_version>.<minor_version>.<patch_version>'
            );
        }

        $majorVersion = $versionParts['major'];
94 95
        $minorVersion = $versionParts['minor'] ?? 0;
        $patchVersion = $versionParts['patch'] ?? 0;
96 97
        $version      = $majorVersion . '.' . $minorVersion . '.' . $patchVersion;

98 99
        if (version_compare($version, '10.0', '>=')) {
            return new PostgreSQL100Platform();
100
        }
101

102
        return new PostgreSQL94Platform();
103 104 105 106 107
    }

    /**
     * {@inheritdoc}
     */
108
    public function getDatabase(Connection $conn)
109 110 111
    {
        $params = $conn->getParams();

112
        return $params['dbname'] ?? $conn->query('SELECT CURRENT_DATABASE()')->fetchOne();
113 114 115 116 117 118 119
    }

    /**
     * {@inheritdoc}
     */
    public function getDatabasePlatform()
    {
120
        return new PostgreSQL94Platform();
121 122 123 124 125
    }

    /**
     * {@inheritdoc}
     */
126
    public function getSchemaManager(Connection $conn)
127 128 129 130
    {
        return new PostgreSqlSchemaManager($conn);
    }
}