? sites/default/files
? sites/default/settings.php
Index: install.php
===================================================================
RCS file: /cvs/drupal/drupal/install.php,v
retrieving revision 1.174
diff -u -p -r1.174 install.php
--- install.php	28 May 2009 08:34:14 -0000	1.174
+++ install.php	1 Jun 2009 08:58:46 -0000
@@ -362,17 +362,12 @@ function _install_settings_form_validate
     if (isset($form)) {
       form_set_value($form['_database'], $database, $form_state);
     }
-    $class = "DatabaseInstaller_$driver";
-    $test = new $class;
-    $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 {
+      $databases['default']['default'] = $database;
+      db_run_tasks();
+    }
+    catch (DatabaseInstallerException $e) {
+      form_set_error('db_type', $e->getMessage());
     }
   }
 }
Index: includes/install.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/install.inc,v
retrieving revision 1.91
diff -u -p -r1.91 install.inc
--- includes/install.inc	24 May 2009 17:39:30 -0000	1.91
+++ includes/install.inc	1 Jun 2009 08:58:48 -0000
@@ -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,60 +239,130 @@ 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(
+      'function' => 'testConnect',
+      'arguments'   => 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() {
+    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($tests['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 permission 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);
+    }
   }
 
   /**
@@ -304,30 +374,36 @@ abstract class DatabaseInstaller {
   protected function testConnect() {
     try {
       db_set_active();
-      $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: %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())), '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;
     }
   }
-
-  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.
  *
  * @param $settings
Index: includes/database/database.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/database.inc,v
retrieving revision 1.53
diff -u -p -r1.53 database.inc
--- includes/database/database.inc	3 May 2009 08:55:06 -0000	1.53
+++ includes/database/database.inc	1 Jun 2009 08:58:53 -0000
@@ -2685,6 +2685,21 @@ function db_rewrite_sql($query, $primary
   return $query;
 }
 
+/**
+ * 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($connection = 'default') {
+  $task_class = 'DatabaseTasks_' . Database::getConnection($connection)->driver();
+  $DatabaseTasks = new $task_class();
+  $DatabaseTasks->runTasks();
+  return TRUE;
+}
+
 
 /**
  * @} End of "ingroup database-legacy".
Index: includes/database/mysql/install.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/mysql/install.inc,v
retrieving revision 1.2
diff -u -p -r1.2 install.inc
--- includes/database/mysql/install.inc	20 Apr 2009 20:02:30 -0000	1.2
+++ includes/database/mysql/install.inc	1 Jun 2009 08:58:53 -0000
@@ -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';
Index: includes/database/pgsql/install.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/pgsql/install.inc,v
retrieving revision 1.2
diff -u -p -r1.2 install.inc
--- includes/database/pgsql/install.inc	20 Apr 2009 20:02:30 -0000	1.2
+++ includes/database/pgsql/install.inc	1 Jun 2009 08:58:53 -0000
@@ -9,10 +9,34 @@
 
 // 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 {
+        $this->fail(st('Drupal uses %encoding encoding with %driver however, %driver is not set to use UTF-8 encoding. Please create the database with %encoding encoding.', array('%driver' => $this->name())));
+      }
+    } catch (Exception $e) {
+      $this->fail(st('Drupal could not determine the encoding of the database was set to UTF-8'));
+    }  
+  }
 }
 
Index: includes/database/sqlite/install.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/sqlite/install.inc,v
retrieving revision 1.1
diff -u -p -r1.1 install.inc
--- includes/database/sqlite/install.inc	23 Nov 2008 06:06:15 -0000	1.1
+++ includes/database/sqlite/install.inc	1 Jun 2009 08:58:54 -0000
@@ -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';
