Index: modules/system/system.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.api.php,v
retrieving revision 1.103
diff -u -r1.103 system.api.php
--- modules/system/system.api.php	15 Nov 2009 08:48:39 -0000	1.103
+++ modules/system/system.api.php	15 Nov 2009 16:01:19 -0000
@@ -1911,17 +1911,21 @@
 }
 
 /**
- * Perform a single update. For each patch which requires a database change add
- * a new hook_update_N() which will be called by update.php.
+ * Perform a single update.
  *
- * The database updates are numbered sequentially according to the version of Drupal you are compatible with.
+ * For each patch which requires a database change, add a new hook_update_N()
+ * which will be called by update.php.
+ *
+ * The database updates are numbered sequentially according to the version of
+ * Drupal the module is compatible with.
  *
  * Schema updates should adhere to the Schema API:
  * @link http://drupal.org/node/150215 http://drupal.org/node/150215 @endlink
  *
  * Database updates consist of 3 parts:
  * - 1 digit for Drupal core compatibility
- * - 1 digit for your module's major release version (e.g. is this the 5.x-1.* (1) or 5.x-2.* (2) series of your module?)
+ * - 1 digit for your module's major release version (e.g. is this the
+ *   5.x-1.* (1) or 5.x-2.* (2) series of the module?)
  * - 2 digits for sequential counting starting with 00
  *
  * The 2nd digit should be 0 for initial porting of your module to a new Drupal
@@ -1951,71 +1955,85 @@
  * - @link http://drupal.org/handbook/cvs/releases http://drupal.org/handbook/cvs/releases @endlink
  *
  * Implementations of this hook should be placed in a mymodule.install file in
- * the same directory as mymodule.module. Drupal core's updates are implemented
- * using the system module as a name and stored in database/updates.inc.
- *
- * If your update task is potentially time-consuming, you'll need to implement a
- * multipass update to avoid PHP timeouts. Multipass updates use the $sandbox
- * parameter provided by the batch API (normally, $context['sandbox']) to store
- * information between successive calls, and the $sandbox['#finished'] value
- * to provide feedback regarding completion level.
- *
- * See the batch operations page for more information on how to use the batch API:
- * @link http://drupal.org/node/146843 http://drupal.org/node/146843 @endlink
+ * the same directory as mymodule.module.
  *
+ * Time-consuming update tasks should be implemented using a multipass update
+ * to avoid PHP timeouts. Such update functions are called repeatedly by
+ * update.php until they report they are finished. See the $context parameter
+ * below.
+ *
+ * @param $sandbox
+ *   Array of persistent data for multipass updates. Single pass updates (most
+ *   common case) should simply overlook this parameter and go with:
+ *   function mymodule_update_N() { ... }.
+ *   Multipass updates can freely use the $sandbox array to store information
+ *   between successive calls. $sandbox['#finished'] should be set to a
+ *   float value between 0 and 1 to inform the update engine that the update
+ *   hook should be called again. A value of 1 ('finished') is assumed and is
+ *   thus optional.
  * @throws DrupalUpdateException, PDOException
- *   In case of error, update hooks should throw an instance of DrupalUpdateException
- *   with a meaningful message for the user. If a database query fails for whatever
- *   reason, it will throw a PDOException.
- *
+ *   In case of error, update hooks should throw an instance of
+ *   DrupalUpdateExceptionwith a meaningful message for the user. If a database
+ *   query fails for whatever reason, it will throw a PDOException.
+ *   When an exception is raised in an update hook, the update process for the
+ *   module is aborted and subsequent update hooks for the module will not be
+ *   executed. The updates will still be marked as 'pending', and will run be
+ *   tried again on the next execution of update.php.
  * @return
- *   Optionally update hooks may return a translated string that will be displayed
- *   to the user. If no message is returned, no message will be presented to the
- *   user.
+ *   Update hooks may optionally return a translated string to be displayed on
+ *   the update results page.
  */
 function hook_update_N(&$sandbox) {
-  // For non-multipass updates, the signature can simply be;
-  // function hook_update_N() {
-
   // For most updates, the following is sufficient.
   db_add_field('mytable1', 'newcol', array('type' => 'int', 'not null' => TRUE, 'description' => 'My new integer column.'));
 
-  // However, for more complex operations that may take a long time,
-  // you may hook into Batch API as in the following example.
+  // To display a message to the user when the update is completed, return it.
+  // If you do not want to display a completion message, simply return nothing.
+  return t('The update did what it was supposed to do.');
+
+  // In case of an error, simply throw an exception with an error message.
+  throw new DrupalUpdateException('Something went wrong; here is what you should do.');
+
 
-  // Update 3 users at a time to have an exclamation point after their names.
-  // (They're really happy that we can do batch API in this hook!)
+  // For more complex operations that may take a long time, the update should
+  // be multipass, as in the following example.
+
+  // Append an exclamation mark to all user names. Users will be processed by
+  // groups of 3.
+
+  // First call: initialize some internal information to let us track our
+  // progress.
   if (!isset($sandbox['progress'])) {
     $sandbox['progress'] = 0;
     $sandbox['current_uid'] = 0;
-    // We'll -1 to disregard the uid 0...
+    // Substract 1 to disregard uid 0...
     $sandbox['max'] = db_query('SELECT COUNT(DISTINCT uid) FROM {users}')->fetchField() - 1;
   }
-  db_select('users', 'u')
-    ->fields('u', array('uid', 'name'))
-    ->condition('uid', $sandbox['current_uid'], '>')
-    ->range(0, 3)
-    ->orderBy('uid', 'ASC')
-    ->execute();
-  foreach ($users as $user) {
-    $user->name .= '!';
-    db_update('users')
-      ->fields(array('name' => $user->name))
-      ->condition('uid', $user->uid)
+
+  // If there are actually users to process...
+  if ($sandbox['max']) {
+    // Retrieve the next 3 users. Note the 'uid > $sandbox['current_uid']' condition.
+    $users = db_select('users', 'u')
+      ->fields('u', array('uid', 'name'))
+      ->condition('uid', $sandbox['current_uid'], '>')
+      ->range(0, 3)
+      ->orderBy('uid', 'ASC')
       ->execute();
+    foreach ($users as $user) {
+      $user->name .= '!';
+      db_update('users')
+        ->fields(array('name' => $user->name))
+        ->condition('uid', $user->uid)
+        ->execute();
+
+      // Update our progress information.
+      $sandbox['progress']++;
+      $sandbox['current_uid'] = $user->uid;
+    }
 
-    $sandbox['progress']++;
-    $sandbox['current_uid'] = $user->uid;
+    // Report our completion level.
+    $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max'];
   }
-
-  $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);
-
-  // To display a message to the user when the update is completed, return it.
-  // If you do not want to display a completion message, simply return nothing.
-  return t('The update did what it was supposed to do.');
-
-  // In case of an error, simply throw an exception with an error message.
-  throw new DrupalUpdateException('Something went wrong; here is what you should do.');
 }
 
 /**
