diff --git a/core/lib/Drupal/Core/Database/Connection.php b/core/lib/Drupal/Core/Database/Connection.php index 94a23fb..e9a3c2d 100644 --- a/core/lib/Drupal/Core/Database/Connection.php +++ b/core/lib/Drupal/Core/Database/Connection.php @@ -1072,6 +1072,16 @@ abstract class Connection extends PDO { */ abstract public function databaseType(); + /** + * Creates a database. + * + * In order to use this method, you must be connected without a database + * specified. + * + * @param $database + * Desired name of database. + */ + abstract public function createDatabase($database); /** * Gets any special processing requirements for the condition operator. diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php index fbbff42..c878c4b 100644 --- a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php +++ b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php @@ -47,7 +47,9 @@ class Connection extends DatabaseConnection { // Default to TCP connection on port 3306. $dsn = 'mysql:host=' . $connection_options['host'] . ';port=' . (empty($connection_options['port']) ? 3306 : $connection_options['port']); } - $dsn .= ';dbname=' . $connection_options['database']; + if (!empty($connection_options['database'])) { + $dsn .= ';dbname=' . $connection_options['database']; + } // Allow PDO options to be overridden. $connection_options += array( 'pdo' => array(), @@ -107,6 +109,24 @@ class Connection extends DatabaseConnection { return 'mysql'; } + public function createDatabase($database) { + // Escape the database name. + // $this->quote() is intended for field values, not database names. It will + // therefore put the database name in "quotes" which causes a syntax error + // when used here. Use substr() fanciness to remove the beginning and + // trailing quotes while leaving the rest of the escaping intact. + $database = substr($this->quote($database), 1, -1); + + try { + // Create the database and set it as active. + $this->exec("CREATE DATABASE $database"); + $this->exec("USE $database"); + } + catch (\Exception $e) { + throw $e; + } + } + public function mapConditionOperator($operator) { // We don't want to override any of the defaults. return NULL; diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php b/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php index 4835103..e821438 100644 --- a/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php +++ b/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php @@ -8,6 +8,13 @@ namespace Drupal\Core\Database\Driver\mysql\Install; use Drupal\Core\Database\Install\Tasks as InstallTasks; +use Drupal\Core\Database\Database; +use Drupal\Core\Database\Driver\mysql\Connection; + +/** + * Error code for "Unknown database" error. + */ +const MYSQL_DATABASE_NOT_FOUND = 1049; /** * Specifies installation tasks for MySQL and equivalent databases. @@ -33,4 +40,40 @@ class Tasks extends InstallTasks { public function minimumVersion() { return '5.0.15'; } + + /** + * Check if we can connect to the database. + */ + protected function connect() { + try { + // This doesn't actually test the connection. + db_set_active(); + // Now actually do a check. + Database::getConnection(); + $this->pass('Drupal can CONNECT to the database ok.'); + } + catch (\Exception $e) { + // Attempt to create the database if it is not found. + if ($e->getCode() == MYSQL_DATABASE_NOT_FOUND) { + // Remove the database string from connection info. + $connection_info = Database::getConnectionInfo(); + $database = $connection_info['default']['database']; + unset($connection_info['default']['database']); + + // In order to change the Database::$databaseInfo array, need to remove + // the active connection, then re-add it with the new info. + Database::removeConnection('default'); + Database::addConnectionInfo('default', 'default', $connection_info['default']); + + // Now, attempt the connection again; if it's successful, attempt to + // create the database. + Database::getConnection()->createDatabase($database); + } + else { + throw($e); + return FALSE; + } + } + return TRUE; + } }