=== modified file 'includes/update.inc'
--- includes/update.inc	2009-08-22 18:24:14 +0000
+++ includes/update.inc	2009-09-01 12:54:32 +0000
@@ -273,7 +273,7 @@ function update_fix_d7_requirements() {
  *
  * Install profiles are now treated as modules by Drupal, and have an upgrade path
  * based on their schema version in the system table.
- * 
+ *
  * The install profile will be set to schema_version 0, as it has already been
  * installed. Any other hook_update_N functions provided by the install profile
  * will be run by update.php.
@@ -365,13 +365,28 @@ function update_parse_db_url($db_url) {
  * Perform one update and store the results which will later be displayed on
  * the finished page.
  *
- * An update function can force the current and all later updates for this
- * module to abort by returning a $ret array with an element like:
- * $ret['#abort'] = array('success' => FALSE, 'query' => 'What went wrong');
- * The schema version will not be updated in this case, and all the
- * aborted updates will continue to appear on update.php as updates that
+ * If an update function completes successfully, it should return a message
+ * as a string indicating success, for example:
+ * @code
+ * return t('New index added successfully.');
+ * @endcode
+ *
+ * If it fails for whatever reason, it should throw an instance of
+ * DrupalUpdateException with an appropriate error message, for example:
+ * @code
+ * throw new DrupalUpdateException(t('Description of what went wrong'));
+ * @endcode
+ *
+ * If an exception is thrown, the current and all later updates for this module
+ * will be aborted. The schema version will not be updated in this case, and all
+ * the aborted updates will continue to appear on update.php as updates that
  * have not yet been run.
  *
+ * If an update function needs to be re-run as part of a batch process, it
+ * should accept the $sandbox array by reference as its first parameter
+ * and set the #finished property to the percentage completed that it is, as a
+ * fraction of 1.
+ *
  * @param $module
  *   The module whose update will be run.
  * @param $number
@@ -386,16 +401,50 @@ function update_do_one($module, $number,
     return;
   }
 
+  if (!isset($context['log'])) {
+    $context['log'] = variable_get('update_log_queries', 0);
+  }
+
+  $ret = array();
   $function = $module . '_update_' . $number;
   if (function_exists($function)) {
-    $ret = $function($context['sandbox']);
+    try {
+      if ($context['log']) {
+        Database::startLog($function);
+      }
+      $ret['results']['query'] = $function($context['sandbox']);
+      $ret['results']['success'] = TRUE;
+
+      // @TODO Remove this block after all updates have been converted to
+      // return only strings.
+      if (is_array($ret['results']['query'])) {
+        $ret = $ret['results']['query'];
+      }
+    }
+    // @TODO We may want to do different error handling for different exception
+    // types, but for now we'll just print the message.
+    catch (Exception $e) {
+      $ret['results'] = array('success' => FALSE, 'query' => $e->getMessage());
+      $ret['#abort'] = TRUE;
+    }
+
+    if ($context['log']) {
+      $ret['queries'] = Database::getLog($function);
+    }
   }
 
+  // @TODO Remove this block after all updates have been converted to return
+  // only strings.
   if (isset($ret['#finished'])) {
     $context['finished'] = $ret['#finished'];
     unset($ret['#finished']);
   }
 
+  if (isset($context['sandbox']['#finished'])) {
+    $context['finished'] = $context['sandbox']['#finished'];
+    unset($context['sandbox']['#finished']);
+  }
+
   if (!isset($context['results'][$module])) {
     $context['results'][$module] = array();
   }
@@ -406,6 +455,7 @@ function update_do_one($module, $number,
 
   if (!empty($ret['#abort'])) {
     $context['results'][$module]['#abort'] = TRUE;
+    unset ($context['results'][$module][$number]['#abort']);
   }
   // Record the schema update if it was completed successfully.
   if ($context['finished'] == 1 && empty($context['results'][$module]['#abort'])) {
@@ -416,6 +466,11 @@ function update_do_one($module, $number,
 }
 
 /**
+ * @class Exception class used to throw error if a module update fails.
+ */
+class DrupalUpdateException extends Exception { }
+
+/**
  * Start the database update batch process.
  *
  * @param $start
@@ -516,7 +571,7 @@ function update_finished($success, $resu
 function update_get_update_list() {
   // Make sure that the system module is first in the list of updates.
   $ret = array('system' => array());
-  
+
   $modules = drupal_get_installed_schema_version(NULL, FALSE, TRUE);
   foreach ($modules as $module => $schema_version) {
     $pending = array();
@@ -530,7 +585,7 @@ function update_get_update_list() {
         $ret[$module]['warning'] = '<em>' . $module . '</em> module can not be updated. Its schema version is ' . $schema_version . '. Updates up to and including ' . $last_removed . ' have been removed in this release. In order to update <em>' . $module . '</em> module, you will first <a href="http://drupal.org/upgrade">need to upgrade</a> to the last version in which these updates were available.';
         continue;
       }
-      
+
       $updates = drupal_map_assoc($updates);
       foreach (array_keys($updates) as $update) {
         if ($update > $schema_version) {
@@ -548,7 +603,7 @@ function update_get_update_list() {
       }
     }
   }
-  
+
   if (empty($ret['system'])) {
     unset($ret['system']);
   }
