AbstractPostgreSQLDriver.php 5.7 KB

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