Skip to content
Snippets Groups Projects
Verified Commit 9a625bf8 authored by Lee Rowlands's avatar Lee Rowlands
Browse files

Issue #2610858 by cilefen, ravi.shankar, Cameron Tod, shubham.prakash,...

Issue #2610858 by cilefen, ravi.shankar, Cameron Tod, shubham.prakash, joachim, mohit_aghera, Madhura BK, kostajh, asvira, vacho, Grevil, daffie, dawehner, mradcliffe: Add informative error message for 'Connection refused' errors in MySQL

(cherry picked from commit 442c0e41)
parent dee1512f
No related branches found
No related tags found
5 merge requests!8506Draft: Issue #3456536 by ibrahim tameme,!5646Issue #3350972 by nod_: [random test failure]...,!5600Issue #3350972 by nod_: [random test failure]...,!5343Issue #3305066 by quietone, Rename RedirectLeadingSlashesSubscriber,!3603#ISSUE 3346218 Add a different message on edit comment
<?php
namespace Drupal\Core\Database;
/**
* Exception thrown if server refuses connection.
*/
class DatabaseConnectionRefusedException extends \RuntimeException implements DatabaseException {}
......@@ -9,6 +9,7 @@
use Drupal\Core\Database\DatabaseNotFoundException;
use Drupal\Core\Database\DatabaseException;
use Drupal\Core\Database\Connection as DatabaseConnection;
use Drupal\Core\Database\DatabaseConnectionRefusedException;
use Drupal\Core\Database\SupportsTemporaryTablesInterface;
use Drupal\Core\Database\TransactionNoActiveException;
......@@ -32,6 +33,11 @@ class Connection extends DatabaseConnection implements SupportsTemporaryTablesIn
*/
const ACCESS_DENIED = 1045;
/**
* Error code for "Connection refused".
*/
const CONNECTION_REFUSED = 2002;
/**
* Error code for "Can't initialize character set" error.
*/
......@@ -165,13 +171,36 @@ public static function open(array &$connection_options = []) {
$pdo = new \PDO($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
}
catch (\PDOException $e) {
if ($e->getCode() == static::DATABASE_NOT_FOUND) {
throw new DatabaseNotFoundException($e->getMessage(), $e->getCode(), $e);
}
if ($e->getCode() == static::ACCESS_DENIED) {
throw new DatabaseAccessDeniedException($e->getMessage(), $e->getCode(), $e);
switch ($e->getCode()) {
case static::CONNECTION_REFUSED:
if (isset($connection_options['unix_socket'])) {
// Show message for socket connection via 'unix_socket' option.
$message = 'Drupal is configured to connect to the database server via a socket, but the socket file could not be found.';
$message .= ' This message normally means that there is no MySQL server running on the system or that you are using an incorrect Unix socket file name when trying to connect to the server.';
throw new DatabaseConnectionRefusedException($e->getMessage() . ' [Tip: ' . $message . '] ', $e->getCode(), $e);
}
if (isset($connection_options['host']) && in_array(strtolower($connection_options['host']), ['', 'localhost'], TRUE)) {
// Show message for socket connection via 'host' option.
$message = 'Drupal was attempting to connect to the database server via a socket, but the socket file could not be found.';
$message .= ' A Unix socket file is used if you do not specify a host name or if you specify the special host name localhost.';
$message .= ' To connect via TPC/IP use an IP address (127.0.0.1 for IPv4) instead of "localhost".';
$message .= ' This message normally means that there is no MySQL server running on the system or that you are using an incorrect Unix socket file name when trying to connect to the server.';
throw new DatabaseConnectionRefusedException($e->getMessage() . ' [Tip: ' . $message . '] ', $e->getCode(), $e);
}
// Show message for TCP/IP connection.
$message = 'This message normally means that there is no MySQL server running on the system or that you are using an incorrect host name or port number when trying to connect to the server.';
$message .= ' You should also check that the TCP/IP port you are using has not been blocked by a firewall or port blocking service.';
throw new DatabaseConnectionRefusedException($e->getMessage() . ' [Tip: ' . $message . '] ', $e->getCode(), $e);
case static::DATABASE_NOT_FOUND:
throw new DatabaseNotFoundException($e->getMessage(), $e->getCode(), $e);
case static::ACCESS_DENIED:
throw new DatabaseAccessDeniedException($e->getMessage(), $e->getCode(), $e);
default:
throw $e;
}
throw $e;
}
// Force MySQL to use the UTF-8 character set. Also set the collation, if a
......
<?php
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\Database\Database;
/**
* Tests the installer with incorrect connection info in settings.php.
*
* @group Installer
*/
class InstallerBrokenDatabaseCredentialsTest extends InstallerTestBase {
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*/
protected function prepareEnvironment() {
parent::prepareEnvironment();
// Pre-configure database credentials in settings.php.
$connection_info = Database::getConnectionInfo();
if ($connection_info['default']['driver'] !== 'mysql') {
$this->markTestSkipped('This test relies on overriding the mysql driver');
}
// Provide incorrect host name and test the new error messages.
$connection_info['default']['host'] = 'localhost';
$this->settings['databases']['default'] = (object) [
'value' => $connection_info,
'required' => TRUE,
];
}
/**
* {@inheritdoc}
*/
protected function setUpSettings() {
// This form will never be reached.
}
/**
* {@inheritdoc}
*/
protected function setUpSite() {
// This form will never be reached.
}
/**
* Tests the expected requirements problem.
*/
public function testRequirementsProblem() {
$this->assertSession()->titleEquals('Requirements problem | Drupal');
$this->assertSession()->pageTextContains('Database settings');
$this->assertSession()->pageTextContains('Resolve all issues below to continue the installation. For help configuring your database server,');
$this->assertSession()->pageTextContains('[Tip: Drupal was attempting to connect to the database server via a socket, but the socket file could not be found. A Unix socket file is used if you do not specify a host name or if you specify the special host name localhost. To connect via TPC/IP use an IP address (127.0.0.1 for IPv4) instead of "localhost". This message normally means that there is no MySQL server running on the system or that you are using an incorrect Unix socket file name when trying to connect to the server.]');
}
}
<?php
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\Database\Database;
/**
* Tests the installer with incorrect connection info in settings.php.
*
* @group Installer
*/
class InstallerBrokenDatabasePortSettingsTest extends InstallerTestBase {
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*/
protected function prepareEnvironment() {
parent::prepareEnvironment();
// Pre-configure database credentials in settings.php.
$connection_info = Database::getConnectionInfo();
if ($connection_info['default']['driver'] !== 'mysql') {
$this->markTestSkipped('This test relies on overriding the mysql driver');
}
// Override the port number to random port.
$connection_info['default']['port'] = 1234;
$this->settings['databases']['default'] = (object) [
'value' => $connection_info,
'required' => TRUE,
];
}
/**
* {@inheritdoc}
*/
protected function setUpSettings() {
// This form will never be reached.
}
/**
* {@inheritdoc}
*/
protected function setUpSite() {
// This form will never be reached.
}
/**
* Tests the expected requirements problem.
*/
public function testRequirementsProblem() {
$this->assertSession()->titleEquals('Requirements problem | Drupal');
$this->assertSession()->pageTextContains('Database settings');
$this->assertSession()->pageTextContains('Resolve all issues below to continue the installation. For help configuring your database server,');
$this->assertSession()->pageTextContains("[Tip: This message normally means that there is no MySQL server running on the system or that you are using an incorrect host name or port number when trying to connect to the server. You should also check that the TCP/IP port you are using has not been blocked by a firewall or port blocking service.]");
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment