summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2009-07-27 19:42:56 +0000
committerDries Buytaert <dries@buytaert.net>2009-07-27 19:42:56 +0000
commit1aec298314454b67fbc18738c3ffa6f12a14dd59 (patch)
treebd84dbcdf3593e276d6d3c352feff460be716762
parenta7e7c0a9e73f71f8de0db084e194647237fab298 (diff)
downloadbrdo-1aec298314454b67fbc18738c3ffa6f12a14dd59.tar.gz
brdo-1aec298314454b67fbc18738c3ffa6f12a14dd59.tar.bz2
- Patch #349508 by Josh Waihi: make sure that the database is installed using UTF-8 on PostgreSQL.
-rw-r--r--INSTALL.pgsql.txt8
-rw-r--r--includes/database/database.inc15
-rw-r--r--includes/database/mysql/install.inc2
-rw-r--r--includes/database/pgsql/install.inc33
-rw-r--r--includes/database/sqlite/install.inc2
-rw-r--r--includes/install.inc169
-rw-r--r--install.php19
7 files changed, 181 insertions, 67 deletions
diff --git a/INSTALL.pgsql.txt b/INSTALL.pgsql.txt
index 20705478f..f5f276e58 100644
--- a/INSTALL.pgsql.txt
+++ b/INSTALL.pgsql.txt
@@ -12,9 +12,9 @@ Note that the database must be created with UTF-8 (Unicode) encoding.
following command creates a new user named "username" and asks for a
password for that user:
- createuser --pwprompt --encrypted --no-adduser --no-createdb username
+ createuser --pwprompt --encrypted --no-createrole --no-createdb username
- If everything works correctly, you'll see a "CREATE USER" notice.
+ If there are no errors then the command was successful
2. CREATE THE DRUPAL DATABASE
@@ -23,6 +23,6 @@ Note that the database must be created with UTF-8 (Unicode) encoding.
The following command creates a new database named "databasename", which is
owned by previously created "username":
- createdb --encoding=UNICODE --owner=username databasename
+ createdb --encoding=UTF8 --owner=username databasename
- If everything works correctly, you'll see a "CREATE DATABASE" notice.
+ If there are no errors then the command was successful
diff --git a/includes/database/database.inc b/includes/database/database.inc
index 9da091231..ce470789a 100644
--- a/includes/database/database.inc
+++ b/includes/database/database.inc
@@ -2694,5 +2694,20 @@ function db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $
}
/**
+ * Ensures the environment for a Drupal database on a predefined connection.
+ *
+ * This will run tasks that check that Drupal can perform all of the functions
+ * on a database, that Drupal needs. Tasks include simple checks like CREATE
+ * TABLE to database specfic functions like stored procedures and client
+ * encoding.
+ */
+function db_run_tasks($driver) {
+ $task_class = 'DatabaseTasks_' . $driver;
+ $DatabaseTasks = new $task_class();
+ $DatabaseTasks->runTasks();
+ return true;
+}
+
+/**
* @} End of "ingroup database-legacy".
*/
diff --git a/includes/database/mysql/install.inc b/includes/database/mysql/install.inc
index cee986225..f443944d8 100644
--- a/includes/database/mysql/install.inc
+++ b/includes/database/mysql/install.inc
@@ -9,7 +9,7 @@
// MySQL specific install functions
-class DatabaseInstaller_mysql extends DatabaseInstaller {
+class DatabaseTasks_mysql extends DatabaseTasks {
protected $pdoDriver = 'mysql';
public function name() {
return 'MySQL';
diff --git a/includes/database/pgsql/install.inc b/includes/database/pgsql/install.inc
index b301cb672..222d7e734 100644
--- a/includes/database/pgsql/install.inc
+++ b/includes/database/pgsql/install.inc
@@ -9,10 +9,41 @@
// PostgreSQL specific install functions
-class DatabaseInstaller_pgsql extends DatabaseInstaller {
+class DatabaseTasks_pgsql extends DatabaseTasks {
protected $pdoDriver = 'pgsql';
+
+ public function __construct() {
+ $this->tasks[] = array(
+ 'function' => 'checkEncoding',
+ 'arguments' => array(),
+ );
+ }
+
public function name() {
return 'PostgreSQL';
}
+
+ /**
+ * Check encoding is UTF8.
+ */
+ protected function checkEncoding() {
+ try {
+ if (db_query('SHOW server_encoding')->fetchField() == 'UTF8') {
+ $this->pass(st('Database is encoded in UTF-8'));
+ }
+ else {
+ $replacements = array(
+ '%encoding' => 'UTF8',
+ '%driver' => $this->name(),
+ '!link' => '<a href="INSTALL.pgsql.txt">INSTALL.pgsql.txt</a>'
+ );
+ $text = 'The %driver database must use %encoding encoding to work with Drupal.';
+ $text .= 'Please recreate the database with %encoding encoding. See !link for more details.';
+ $this->fail(st($text, $replacements));
+ }
+ } catch (Exception $e) {
+ $this->fail(st('Drupal could not determine the encoding of the database was set to UTF-8'));
+ }
+ }
}
diff --git a/includes/database/sqlite/install.inc b/includes/database/sqlite/install.inc
index 096c20901..334e09dfd 100644
--- a/includes/database/sqlite/install.inc
+++ b/includes/database/sqlite/install.inc
@@ -6,7 +6,7 @@
* SQLite specific install functions
*/
-class DatabaseInstaller_sqlite extends DatabaseInstaller {
+class DatabaseTasks_sqlite extends DatabaseTasks {
protected $pdoDriver = 'sqlite';
public function name() {
return 'SQLite';
diff --git a/includes/install.inc b/includes/install.inc
index 0b5f0b8f9..bfa39d067 100644
--- a/includes/install.inc
+++ b/includes/install.inc
@@ -222,7 +222,7 @@ function drupal_detect_database_types() {
}
foreach ($drivers as $driver => $file) {
- $class = 'DatabaseInstaller_' . $driver;
+ $class = 'DatabaseTasks_' . $driver;
$installer = new $class();
if ($installer->installable()) {
$databases[$driver] = $installer->name();
@@ -239,96 +239,167 @@ function drupal_detect_database_types() {
return $databases;
}
-abstract class DatabaseInstaller {
- protected $success = array();
- protected $tests = array(
- 'testCreate' => array(
- 'query' => 'CREATE TABLE drupal_install_test (id int NULL)',
- 'success' => 'CREATE',
- 'message' => 'Failed to create a test table on your %name database server with the command %query. %name reports the following message: %error.<ul><li>Are you sure the configured username has the necessary %name permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.',
- 'fatal' => TRUE,
+/**
+ * Database installer structure.
+ *
+ * Defines basic Drupal requirements for databases.
+ */
+abstract class DatabaseTasks {
+
+ /**
+ * Structure that describes each task to run.
+ *
+ * @var array
+ *
+ * Each value of the tasks array is an associative array defining the function
+ * to call (optional) and any arguments to be passed to the function.
+ */
+ protected $tasks = array(
+ array(
+ 'arguments' => array(
+ 'CREATE TABLE drupal_install_test (id int NULL)',
+ 'Drupal can use CREATE TABLE database commands.',
+ 'Failed to <strong>CREATE</strong> a test table on your %name database server with the command %query. %name reports the following message: %error.<p>Are you sure the configured username has the necessary %name permissions to create tables in the database?</p>',
+ TRUE,
+ ),
),
- 'testInsert' => array(
- 'query' => 'INSERT INTO drupal_install_test (id) VALUES (1)',
- 'success' => 'INSERT',
- 'message' => 'Failed to insert a value into a test table on your %name database server. We tried inserting a value with the command %query and %name reported the following error: %error.',
+ array(
+ 'arguments' => array(
+ 'INSERT INTO drupal_install_test (id) VALUES (1)',
+ 'Drupal can use INSERT database commands.',
+ 'Failed to <strong>INSERT</strong> a value into a test table on your %name database server. We tried inserting a value with the command %query and %name reported the following error: %error.',
+ ),
),
- 'testUpdate' => array(
- 'query' => 'UPDATE drupal_install_test SET id = 2',
- 'success' => 'UPDATE',
- 'message' => 'Failed to update a value in a test table on your %name database server. We tried updating a value with the command %query and %name reported the following error: %error.',
+ array(
+ 'arguments' => array(
+ 'UPDATE drupal_install_test SET id = 2',
+ 'Drupal can use UPDATE database commands.',
+ 'Failed to <strong>UPDATE</strong> a value in a test table on your %name database server. We tried updating a value with the command %query and %name reported the following error: %error.',
+ ),
),
- 'testDelete' => array(
- 'query' => 'DELETE FROM drupal_install_test',
- 'success' => 'DELETE',
- 'message' => 'Failed to delete a value from a test table on your %name database server. We tried deleting a value with the command %query and %name reported the following error: %error.',
+ array(
+ 'arguments' => array(
+ 'DELETE FROM drupal_install_test',
+ 'Drupal can use DELETE database commands.',
+ 'Failed to <strong>DELETE</strong> a value from a test table on your %name database server. We tried deleting a value with the command %query and %name reported the following error: %error.',
+ ),
),
- 'testDrop' => array(
- 'query' => 'DROP TABLE drupal_install_test',
- 'success' => 'DELETE',
- 'message' => 'Failed to drop a test table from your %name database server. We tried dropping a table with the command %query and %name reported the following error %error.',
+ array(
+ 'arguments' => array(
+ 'DROP TABLE drupal_install_test',
+ 'Drupal can use DROP TABLE database commands.',
+ 'Failed to <strong>DROP</strong> a test table from your %name database server. We tried dropping a table with the command %query and %name reported the following error %error.',
+ ),
),
);
- public $error = FALSE;
+ /**
+ * Results from tasks.
+ *
+ * @var array
+ */
+ protected $results = array();
+ /**
+ * Ensure the PDO driver is supported by the version of PHP in use.
+ */
protected function hasPdoDriver() {
return in_array($this->pdoDriver, PDO::getAvailableDrivers());
}
+ /**
+ * Assert test as failed.
+ */
+ protected function fail($message) {
+ $this->results[$message] = FALSE;
+ }
+
+ /**
+ * Assert test as a pass.
+ */
+ protected function pass($message) {
+ $this->results[$message] = TRUE;
+ }
+
+ /**
+ * Check whether Drupal is installable on the database.
+ */
public function installable() {
- return $this->hasPdoDriver();
+ return $this->hasPdoDriver() && empty($this->error);
}
abstract public function name();
- public function test() {
- $return = $this->testConnect();
- if ($return === FALSE) {
- return FALSE;
+ /**
+ * Run database tasks and tests to see if Drupal can run on the database.
+ */
+ public function runTasks() {
+ // We need to establish a connection before we can run tests.
+ if ($this->connect()) {
+ foreach ($this->tasks as $task) {
+ if (!isset($task['function'])) {
+ $task['function'] = 'runTestQuery';
+ }
+ if (method_exists($this, $task['function'])) {
+ // Returning false is fatal. No other tasks can run.
+ if (FALSE === call_user_func_array(array($this, $task['function']), $task['arguments'])) {
+ break;
+ }
+ }
+ else {
+ drupal_set_message(st('Failed to run all tasks against the database server. The task %task wasn\'t found.', array('%task' => $task['function'])), 'error');
+ }
+ }
}
- foreach ($this->tests as $test) {
- $return = $this->runTestQuery($test['query'], $test['success'], $test['message'], !empty($test['fatal']));
- if ($return === FALSE) {
- return FALSE;
+ // Check for failed results and compile message
+ $message = '';
+ foreach ($this->results as $result => $success) {
+ if (!$success) {
+ $message .= '<p class="error">' . $result . '</p>';
}
}
- return $this->success;
+ if (!empty($message)) {
+ $message = '<p>In order for Drupal to work, and to continue with the installation process, you must resolve all issues reported below. For more help with configuring your database server, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what any of this means you should probably contact your hosting provider.</p>' . $message;
+ throw new DatabaseTaskException($message);
+ }
}
/**
* Check if we can connect to the database.
- *
- * @return
- * FALSE on failure.
*/
- protected function testConnect() {
+ protected function connect() {
try {
// This doesn't actually test the connection.
db_set_active();
// Now actually do a check.
Database::getConnection();
- $this->success[] = 'CONNECT';
+ $this->pass('Drupal can CONNECT to the database ok.');
}
catch (Exception $e) {
- drupal_set_message(st('Failed to connect to your %name database server. %name reports the following message: <strong>%error</strong>.<ul><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li><li>Are you sure you have the correct database name?</li><li>Are you sure you have the correct username and password?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => $e->getMessage(), '%name' => $this->name())), 'error');
+ $this->fail(st('Failed to connect to your %name database server. %name reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => $e->getMessage(), '%name' => $this->name())));
return FALSE;
}
+ return TRUE;
}
- protected function runTestQuery($query, $success, $message, $fatal = FALSE) {
+ /**
+ * Run SQL tests to ensure the database can execute commands with the current user.
+ */
+ protected function runTestQuery($query, $pass, $fail, $fatal = FALSE) {
try {
db_query($query);
- $this->success[] = $success;
+ $this->pass(st($pass));
}
catch (Exception $e) {
- drupal_set_message(st($message, array('%query' => $query, '%error' => $e->getMessage(), '%name' => $this->name())), 'error');
- $this->error = TRUE;
- if ($fatal) {
- return FALSE;
- }
+ $this->fail(st($fail, array('%query' => $query, '%error' => $e->getMessage(), '%name' => $this->name())));
+ return !$fatal;
}
}
}
+/**
+ * @class Exception class used to throw error if the DatabaseInstaller fails.
+ */
+class DatabaseTaskException extends Exception {
+}
/**
* Replace values in settings.php with values in the submitted array.
diff --git a/install.php b/install.php
index ce0b3c6dc..c9babe4d9 100644
--- a/install.php
+++ b/install.php
@@ -336,7 +336,6 @@ function install_settings_form(&$form_state, $profile, $install_locale, $setting
* Form API validate for install_settings form.
*/
function install_settings_form_validate($form, &$form_state) {
- global $db_url;
_install_settings_form_validate($form_state['values'], $form_state['values']['settings_file'], $form_state, $form);
}
@@ -364,17 +363,15 @@ function _install_settings_form_validate($database, $settings_file, &$form_state
if (isset($form)) {
form_set_value($form['_database'], $database, $form_state);
}
- $class = "DatabaseInstaller_$driver";
- $test = new $class;
+
+ // Run tasks associated with the database type. Any errors are caught in the
+ // calling function
$databases['default']['default'] = $database;
- $return = $test->test();
- if (!$return || $test->error) {
- if (!empty($test->success)) {
- form_set_error('db_type', st('In order for Drupal to work, and to continue with the installation process, you must resolve all permission issues reported above. We were able to verify that we have permission for the following commands: %commands. For more help with configuring your database server, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what any of this means you should probably contact your hosting provider.', array('%commands' => implode($test->success, ', '))));
- }
- else {
- form_set_error('driver', '');
- }
+ try {
+ db_run_tasks($database['driver']);
+ }
+ catch (DatabaseTaskException $e) {
+ form_set_error('db_type', $e->getMessage());
}
}
}