=== modified file 'includes/common.inc'
--- includes/common.inc	2009-12-06 17:01:52 +0000
+++ includes/common.inc	2009-12-06 20:07:13 +0000
@@ -5155,6 +5155,52 @@ function show(&$element) {
 }
 
 /**
+ * Prepare an element for caching based on a query.
+ *
+ * Expensive queries should use the query builder to create the query and then
+ * call this function. Executing the query and formatting results should happen
+ * in pre_render.
+ *
+ * @param $query
+ *   A select query object as returned by db_select().
+ * @param $function
+ *   The name of the function doing this caching. A _pre_render suffix will be
+ *   added to this string and is also part of the cache key in
+ *   drupal_render_cache_set() and drupal_render_cache_get().
+ * @param $args
+ *   Optional arguments which are used when building the cache key. Every
+ *   argument will automatically be cast to string so practically only numbers
+ *   and strings should be passed in here. Use nids instead of nodes and so on.
+ *   Note that the arguments for the query is used in the cache key so usually
+ *   $args is not necessary.
+ * @param $expire
+ *   The cache expire time, passed eventually to cache_set().
+ * @param $granularity
+ *   One or more granularity constants passed to drupal_render_cid_parts().
+ * @return
+ *   A renderable array with the following keys and values:
+ *     #query: the passed in $query.
+ *     #pre_render: $function with a _pre_render suffix.
+ *     #cache: an associative array prepared for drupal_render_cache_set().
+ *   
+ * @see forum_block_view()
+ * @see forum_block_view_pre_render()
+ */
+function drupal_render_cache_by_query($query, $function, $args = array(), $expire = CACHE_TEMPORARY, $granularity = NULL) {
+  $cache_keys = array_merge(array($function), $args, drupal_render_cid_parts($granularity));
+  $query->preExecute();
+  $cache_keys[] = md5(serialize(array((string) $query, $query->getArguments())));
+  return array(
+    '#query' => $query,
+    '#pre_render' => array($function . '_pre_render'),
+    '#cache' => array(
+      'keys' => $cache_keys,
+      'expire' => $expire,
+    ),
+  );
+}
+
+/**
  * Get the rendered output of a renderable element from cache.
  *
  * @see drupal_render()

=== modified file 'modules/forum/forum.module'
--- modules/forum/forum.module	2009-12-04 16:49:45 +0000
+++ modules/forum/forum.module	2009-12-06 20:16:35 +0000
@@ -622,21 +622,9 @@ function forum_block_view($delta = '') {
       break;
   }
 
-  $cache_keys = array_merge(array('forum', $delta), drupal_render_cid_parts());
-  // Cache based on the altered query. Enables us to cache with node access enabled.
-  $query->preExecute();
-  $cache_keys[] = md5(serialize(array((string) $query, $query->getArguments())));
-
   $block['subject'] = $title;
-  $block['content'] = array(
-     '#access' => user_access('access content'),
-     '#pre_render' => array('forum_block_view_pre_render'),
-     '#cache' => array(
-        'keys' => $cache_keys,
-        'expire' => CACHE_TEMPORARY,
-     ),
-     '#query' => $query,
-  );
+  $block['content'] = drupal_render_cache_by_query($query, 'forum_block_view');
+  $block['content']['#access'] = user_access('access content');
   return $block;
 }
 

