AbstractPostgreSQLDriver.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <?php
  2. namespace Doctrine\DBAL\Driver;
  3. use Doctrine\DBAL\Connection;
  4. use Doctrine\DBAL\DBALException;
  5. use Doctrine\DBAL\Driver;
  6. use Doctrine\DBAL\Exception;
  7. use Doctrine\DBAL\Platforms\PostgreSQL100Platform;
  8. use Doctrine\DBAL\Platforms\PostgreSQL91Platform;
  9. use Doctrine\DBAL\Platforms\PostgreSQL92Platform;
  10. use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
  11. use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
  12. use Doctrine\DBAL\Schema\PostgreSqlSchemaManager;
  13. use Doctrine\DBAL\VersionAwarePlatformDriver;
  14. use function preg_match;
  15. use function strpos;
  16. use function version_compare;
  17. /**
  18. * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for PostgreSQL based drivers.
  19. */
  20. abstract class AbstractPostgreSQLDriver implements Driver, ExceptionConverterDriver, VersionAwarePlatformDriver
  21. {
  22. /**
  23. * {@inheritdoc}
  24. *
  25. * @link http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html
  26. */
  27. public function convertException($message, DriverException $exception)
  28. {
  29. switch ($exception->getSQLState()) {
  30. case '40001':
  31. case '40P01':
  32. return new Exception\DeadlockException($message, $exception);
  33. case '0A000':
  34. // Foreign key constraint violations during a TRUNCATE operation
  35. // are considered "feature not supported" in PostgreSQL.
  36. if (strpos($exception->getMessage(), 'truncate') !== false) {
  37. return new Exception\ForeignKeyConstraintViolationException($message, $exception);
  38. }
  39. break;
  40. case '23502':
  41. return new Exception\NotNullConstraintViolationException($message, $exception);
  42. case '23503':
  43. return new Exception\ForeignKeyConstraintViolationException($message, $exception);
  44. case '23505':
  45. return new Exception\UniqueConstraintViolationException($message, $exception);
  46. case '42601':
  47. return new Exception\SyntaxErrorException($message, $exception);
  48. case '42702':
  49. return new Exception\NonUniqueFieldNameException($message, $exception);
  50. case '42703':
  51. return new Exception\InvalidFieldNameException($message, $exception);
  52. case '42P01':
  53. return new Exception\TableNotFoundException($message, $exception);
  54. case '42P07':
  55. return new Exception\TableExistsException($message, $exception);
  56. case '7':
  57. // In some case (mainly connection errors) the PDO exception does not provide a SQLSTATE via its code.
  58. // The exception code is always set to 7 here.
  59. // We have to match against the SQLSTATE in the error message in these cases.
  60. if (strpos($exception->getMessage(), 'SQLSTATE[08006]') !== false) {
  61. return new Exception\ConnectionException($message, $exception);
  62. }
  63. break;
  64. }
  65. return new Exception\DriverException($message, $exception);
  66. }
  67. /**
  68. * {@inheritdoc}
  69. */
  70. public function createDatabasePlatformForVersion($version)
  71. {
  72. if (! preg_match('/^(?P<major>\d+)(?:\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?)?/', $version, $versionParts)) {
  73. throw DBALException::invalidPlatformVersionSpecified(
  74. $version,
  75. '<major_version>.<minor_version>.<patch_version>'
  76. );
  77. }
  78. $majorVersion = $versionParts['major'];
  79. $minorVersion = $versionParts['minor'] ?? 0;
  80. $patchVersion = $versionParts['patch'] ?? 0;
  81. $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion;
  82. switch (true) {
  83. case version_compare($version, '10.0', '>='):
  84. return new PostgreSQL100Platform();
  85. case version_compare($version, '9.4', '>='):
  86. return new PostgreSQL94Platform();
  87. case version_compare($version, '9.2', '>='):
  88. return new PostgreSQL92Platform();
  89. case version_compare($version, '9.1', '>='):
  90. return new PostgreSQL91Platform();
  91. default:
  92. return new PostgreSqlPlatform();
  93. }
  94. }
  95. /**
  96. * {@inheritdoc}
  97. */
  98. public function getDatabase(Connection $conn)
  99. {
  100. $params = $conn->getParams();
  101. return $params['dbname'] ?? $conn->query('SELECT CURRENT_DATABASE()')->fetchColumn();
  102. }
  103. /**
  104. * {@inheritdoc}
  105. */
  106. public function getDatabasePlatform()
  107. {
  108. return new PostgreSqlPlatform();
  109. }
  110. /**
  111. * {@inheritdoc}
  112. */
  113. public function getSchemaManager(Connection $conn)
  114. {
  115. return new PostgreSqlSchemaManager($conn);
  116. }
  117. }