diff -urp --strip-trailing-cr ../category/category_display/category_display.module ./category_display/category_display.module
--- ../category/category_display/category_display.module	2009-06-08 21:46:26.000000000 +0200
+++ ./category_display/category_display.module	2009-06-26 01:52:25.000000000 +0200
@@ -321,14 +321,19 @@ function category_display_category_legac
  *   The display settings for the specified node.
  */
 function category_display_get_container($nid) {
-  $result = db_query("SELECT * FROM {category_display} WHERE cid = %d", $nid);
+  $cache_key = 'cdisp_get_cont';
+  $container = category_cache_op('get', $nid, $cache_key);
+  if (!isset($container)) {
 
-  if ($container = db_fetch_object($result)) {
-    return $container;
-  }
-  else {
-    return (object) _category_display_defaults();
+    $result = db_query("SELECT * FROM {category_display} WHERE cid = %d", $nid);
+    $container = db_fetch_object($result);
+    if (empty($container)) {
+      $container = (object) _category_display_defaults();
+    }
+
+    category_cache_op('set', $nid, $cache_key, $container);
   }
+  return $container;
 }
 
 /**
@@ -351,6 +356,7 @@ function category_display_save_container
     $status = SAVED_UPDATED;
   }
 
+  category_cache_op('flush', $node->nid);
   return $status;
 }
 
@@ -363,6 +369,7 @@ function category_display_save_container
  */
 function category_display_del_container($nid) {
   db_query('DELETE FROM {category_display} WHERE cid = %d', $nid);
+  category_cache_op('flush', $nid);
 }
 
 /**
@@ -509,85 +516,93 @@ function category_display_next($book_lin
  * Format the menu links for the child pages of the current page.
  */
 function category_display_children($book_link, $container_info) {
-  $book_link_orig = $book_link;
+  $cache_key = 'cdisp_children'. $container_info->cid .':'. $book_link['mlid'];
+  $output = category_cache_op('get', 0, $cache_key);
+  if (!isset($output)) {
 
-  // If the TOC has more than one level, then we need to find a menu item with
-  // a specific depth. For example, if we want the TOC to be five levels deep,
-  // then we need to find a menu item at the fifth level of the hierarchy (or
-  // as close to it as possible). This menu item then gets passed to
-  // category_menu_tree_all_data(), so that it retrieves a menu hierarchy
-  // with the depth we need.
-  if ($container_info->toc_depth != 0 && isset($book_link)) {
-    if ($container_info->toc_depth == -1 || $container_info->toc_depth > MENU_MAX_DEPTH) {
-      $container_info->toc_depth = MENU_MAX_DEPTH;
-    }
-    $container_info->toc_depth += $book_link['depth'];
-    if ($book_link_new = _category_display_children_recurse($book_link, $container_info)) {
-      $book_link = $book_link_new;
+    $book_link_orig = $book_link;
+
+    // If the TOC has more than one level, then we need to find a menu item with
+    // a specific depth. For example, if we want the TOC to be five levels deep,
+    // then we need to find a menu item at the fifth level of the hierarchy (or
+    // as close to it as possible). This menu item then gets passed to
+    // category_menu_tree_all_data(), so that it retrieves a menu hierarchy
+    // with the depth we need.
+    if ($container_info->toc_depth != 0 && isset($book_link)) {
+      if ($container_info->toc_depth == -1 || $container_info->toc_depth > MENU_MAX_DEPTH) {
+        $container_info->toc_depth = MENU_MAX_DEPTH;
+      }
+      $container_info->toc_depth += $book_link['depth'];
+      if ($book_link_new = _category_display_children_recurse($book_link, $container_info)) {
+        $book_link = $book_link_new;
+      }
     }
-  }
 
-  $book_link = $book_link_orig;
+    $book_link = $book_link_orig;
 
-  $tree = array();
+    $tree = array();
 
-  if (isset($book_link)) {
-    $tree = category_menu_tree_all_data($book_link_orig['menu_name'], $book_link, $container_info->toc_depth);
-  }
-  // When no menu link is provided to this function, we're generating a TOC
-  // for a hidden container. This is typically useful for things such as a site
-  // map. All of the below code is for the special case of hidden containers
-  // that have no menu link.
-  else {
-    $children = category_get_children($container_info->cid);
-    $containers_map = array();
-    if (!empty($children)) {
-      foreach (array_keys($children) as $child_cid) {
-        $child_cnid = !empty($children[$child_cid]->cnid) ? $children[$child_cid]->cnid : $child_cid;
-        $child_menu = category_menu_get_container($child_cnid);
-        $child_display = category_display_get_container($child_cnid);
-        $child_menu_map = _category_display_children_get_menu_map($children[$child_cid], $child_cnid);
-
-        if ($container_info->toc_depth != 0) {
-          if ($container_info->toc_depth == -1 || $container_info->toc_depth > MENU_MAX_DEPTH) {
-            $container_info->toc_depth = MENU_MAX_DEPTH;
+    if (isset($book_link)) {
+      $tree = category_menu_tree_all_data($book_link_orig['menu_name'], $book_link, $container_info->toc_depth);
+    }
+    // When no menu link is provided to this function, we're generating a TOC
+    // for a hidden container. This is typically useful for things such as a site
+    // map. All of the below code is for the special case of hidden containers
+    // that have no menu link.
+    else {
+      $children = category_get_children($container_info->cid);
+      $containers_map = array();
+      if (!empty($children)) {
+        foreach (array_keys($children) as $child_cid) {
+          $child_cnid = !empty($children[$child_cid]->cnid) ? $children[$child_cid]->cnid : $child_cid;
+          $child_menu = category_menu_get_container($child_cnid);
+          $child_display = category_display_get_container($child_cnid);
+          $child_menu_map = _category_display_children_get_menu_map($children[$child_cid], $child_cnid);
+
+          if ($container_info->toc_depth != 0) {
+            if ($container_info->toc_depth == -1 || $container_info->toc_depth > MENU_MAX_DEPTH) {
+              $container_info->toc_depth = MENU_MAX_DEPTH;
+            }
+            $container_info->toc_depth += $child_menu_map['depth'];
+            $container_info->toc_depth--;
+            if ($child_menu_map_new = _category_display_children_recurse($child_menu_map, $container_info, 1, TRUE)) {
+              $child_menu_map = $child_menu_map_new;
+            }
           }
-          $container_info->toc_depth += $child_menu_map['depth'];
-          $container_info->toc_depth--;
-          if ($child_menu_map_new = _category_display_children_recurse($child_menu_map, $container_info, 1, TRUE)) {
-            $child_menu_map = $child_menu_map_new;
+          else {
+            $container_info->toc_depth = $child_menu_map['depth'];
+            $container_info->toc_depth--;
           }
-        }
-        else {
-          $container_info->toc_depth = $child_menu_map['depth'];
-          $container_info->toc_depth--;
-        }
 
-        if ($child_menu->links_for_cats && !isset($containers_map[$child_cnid])) {
-          $tree_new = category_menu_tree_all_data('category-menu-toc-'. $child_cnid, $child_menu_map, $container_info->toc_depth);
-          _category_display_children_prune_tagged_content($tree_new, $container_info);
-          $tree += $tree_new;
-          $containers_map[$child_cnid] = TRUE;
+          if ($child_menu->links_for_cats && !isset($containers_map[$child_cnid])) {
+            $tree_new = category_menu_tree_all_data('category-menu-toc-'. $child_cnid, $child_menu_map, $container_info->toc_depth);
+            _category_display_children_prune_tagged_content($tree_new, $container_info);
+            $tree += $tree_new;
+            $containers_map[$child_cnid] = TRUE;
+          }
         }
-      }
 
-      if (!$container_info->toc_depth) {
-        foreach (array_keys($tree) as $key) {
-          unset($tree[$key]['below']);
+        if (!$container_info->toc_depth) {
+          foreach (array_keys($tree) as $key) {
+            unset($tree[$key]['below']);
+          }
         }
       }
     }
-  }
 
-  // We've retrieved a menu hierarchy with the desired depth. Now we set the
-  // menu link back to what it was originally, and we reduce the hierarchy so
-  // that it doesn't include the parents of the current page, or any menu links
-  // for assigned content.
-  if (isset($book_link)) {
-    $tree = _category_display_children_reduce($tree, $book_link, $container_info);
-  }
+    // We've retrieved a menu hierarchy with the desired depth. Now we set the
+    // menu link back to what it was originally, and we reduce the hierarchy so
+    // that it doesn't include the parents of the current page, or any menu links
+    // for assigned content.
+    if (isset($book_link)) {
+      $tree = _category_display_children_reduce($tree, $book_link, $container_info);
+    }
 
-  return $tree ? ($container_info->toc_nodecount ? category_display_menu_tree_output($tree) : menu_tree_output($tree)) : '';
+    $output = $tree ? ($container_info->toc_nodecount ? category_display_menu_tree_output($tree) : menu_tree_output($tree)) : '';
+
+  category_cache_op('set', 0, $cache_key, $output);
+  }
+  return $output;
 }
 
 /**
@@ -688,7 +703,7 @@ function _category_display_children_prun
         preg_match('/^node\/(\d+)$/', $tree[$key]['link']['link_path'], $matches);
         if (!empty($matches[1]) && $type = db_result(db_query("SELECT type FROM {node} WHERE nid = %d", $matches[1]))) {
           $behavior = variable_get('category_behavior_'. $type, 0);
-          if (empty($behavior) && db_result(db_query("SELECT n.nid FROM {node} n INNER JOIN {category_node} cn ON n.nid = cn.nid WHERE n.type = '%s'", $type))) {
+          if (empty($behavior)) {
             $include_link = FALSE;
           }
         }
diff -urp --strip-trailing-cr ../category/category.inc ./category.inc
--- ../category/category.inc	2008-07-21 11:30:48.000000000 +0200
+++ ./category.inc	2009-06-26 21:31:34.000000000 +0200
@@ -18,31 +18,38 @@
  *   If set, return only those containers associated with this node type.
  */
 function category_get_containers($type = NULL) {
-  $type_sql = $type ? " WHERE nt.type = '%s'" : "";
-  $result = db_query(db_rewrite_sql("SELECT n.nid, n.title, cn.*, c.weight, c.depth, n.status, nt.type FROM {category_cont} cn INNER JOIN {category} c ON cn.cid = c.cid INNER JOIN {node} n ON cn.cid = n.nid LEFT JOIN {category_cont_node_types} nt ON cn.cid = nt.cid". $type_sql ." ORDER BY c.weight, n.title", 'n', 'nid'), $type);
+  $cache_key = 'c_get_conts'. $type;
+  $containers = category_cache_op('get', 0, $cache_key);
+  if (!isset($containers)) {
 
-  $containers = array();
-  $node_types = array();
-  while ($container = db_fetch_object($result)) {
-    // If no node types are associated with a container, the LEFT JOIN will
-    // return a NULL value for type.
-    if (isset($container->type)) {
-      $node_types[$container->cid][$container->type] = $container->type;
-      unset($container->type);
-      $container->nodes = $node_types[$container->cid];
-    }
-    elseif (!isset($container->nodes)) {
-      $container->nodes = array();
-    }
-
-    if (empty($container->admin_title)) {
-      $container->admin_title = '';
-      $container->has_admin_title = FALSE;
-    }
-    else {
-      $container->has_admin_title = TRUE;
+    $type_sql = $type ? " WHERE nt.type = '%s'" : "";
+    $result = db_query(db_rewrite_sql("SELECT n.nid, n.title, cn.*, c.weight, c.depth, n.status, nt.type FROM {category_cont} cn INNER JOIN {category} c ON cn.cid = c.cid INNER JOIN {node} n ON cn.cid = n.nid LEFT JOIN {category_cont_node_types} nt ON cn.cid = nt.cid". $type_sql ." ORDER BY c.weight, n.title", 'n', 'nid'), $type);
+
+    $containers = array();
+    $node_types = array();
+    while ($container = db_fetch_object($result)) {
+      // If no node types are associated with a container, the LEFT JOIN will
+      // return a NULL value for type.
+      if (isset($container->type)) {
+        $node_types[$container->cid][$container->type] = $container->type;
+        unset($container->type);
+        $container->nodes = $node_types[$container->cid];
+      }
+      elseif (!isset($container->nodes)) {
+        $container->nodes = array();
+      }
+
+      if (empty($container->admin_title)) {
+        $container->admin_title = '';
+        $container->has_admin_title = FALSE;
+      }
+      else {
+        $container->has_admin_title = TRUE;
+      }
+      $containers[$container->cid] = $container;
     }
-    $containers[$container->cid] = $container;
+
+    category_cache_op('set', 0, $cache_key, $containers);
   }
 
   return $containers;
@@ -52,10 +59,17 @@ function category_get_containers($type =
  * Find all categories associated to the given node, within one container.
  */
 function category_node_get_categories_by_container($node, $cnid, $key = 'cid') {
-  $result = db_query(db_rewrite_sql('SELECT c.*, n.title FROM {category} c INNER JOIN {category_node} r ON c.cid = r.cid INNER JOIN {node} n ON c.cid = n.nid WHERE c.cnid = %d AND r.vid = %d AND n.status = 1 ORDER BY c.weight'), $cnid, $node->vid);
-  $categories = array();
-  while ($category = db_fetch_object($result)) {
-    $categories[$category->$key] = $category;
+  $cache_key = 'c_node_get_cats_by_cont'. $node->vid .':'. $cnid .':'. $key;
+  $categories = category_cache_op('get', $node->nid, $cache_key);
+  if (!isset($categories)) {
+
+    $result = db_query(db_rewrite_sql('SELECT c.*, n.title FROM {category} c INNER JOIN {category_node} r ON c.cid = r.cid INNER JOIN {node} n ON c.cid = n.nid WHERE c.cnid = %d AND r.vid = %d AND n.status = 1 ORDER BY c.weight'), $cnid, $node->vid);
+    $categories = array();
+    while ($category = db_fetch_object($result)) {
+      $categories[$category->$key] = $category;
+    }
+
+    category_cache_op('set', $node->nid, $cache_key, $categories);
   }
   return $categories;
 }
@@ -63,20 +77,23 @@ function category_node_get_categories_by
 /**
  * Find all categories associated to the given node, ordered by container and category weight.
  */
-function category_node_get_categories($node, $key = 'cid', $reset = FALSE) {
-  static $categories = array();
+function category_node_get_categories($node, $key = 'cid') {
+  $cache_key = 'cat_node_get_cats'. $node->vid .':'. $key;
+  $categories = category_cache_op('get', $node->nid, $cache_key);
+  if (!isset($categories)) {
 
-  if (!isset($categories[$node->vid]) || $reset) {
-    $categories[$node->vid] = array();
+    $categories = array();
 
     $result = db_query(db_rewrite_sql('SELECT n.nid, nr.teaser AS description, r.vid AS node_id, c.*, n.title FROM {category} c INNER JOIN {category_node} r ON c.cid = r.cid INNER JOIN {category} cn ON c.cnid = cn.cid INNER JOIN {node} n ON c.cid = n.nid INNER JOIN {node_revisions} nr ON n.vid = nr.vid INNER JOIN {node} cnn ON cn.cid = cnn.nid WHERE n.status = 1 AND r.vid = %d ORDER BY cn.weight, cnn.title, c.weight, n.title', 'n', 'nid'), $node->vid);
 
     while ($category = db_fetch_object($result)) {
-      $categories[$node->vid][$category->$key] = $category;
+      $categories[$category->$key] = $category;
     }
+
+    category_cache_op('set', $node->nid, $cache_key, $categories);
   }
 
-  return $categories[$node->vid];
+  return $categories;
 }
 
 /**
@@ -84,10 +101,17 @@ function category_node_get_categories($n
  */
 function category_get_related($cid, $key = 'cid') {
   if ($cid) {
-    $result = db_query(db_rewrite_sql('SELECT c.*, n.title, cid1, cid2 FROM {category_relation}, {category} c, {node} n WHERE (c.cid = cid1 OR c.cid = cid2) AND (cid1 = %d OR cid2 = %d) AND c.cid = n.nid AND c.cid != %d AND n.status = 1 ORDER BY c.weight, n.title'), $cid, $cid, $cid);
-    $related = array();
-    while ($category = db_fetch_object($result)) {
-      $related[$category->$key] = $category;
+    $cache_key = 'cat_get_related'. $key;
+    $related = category_cache_op('get', $cid, $cache_key);
+    if (!isset($related)) {
+
+      $result = db_query(db_rewrite_sql('SELECT c.*, n.title, cid1, cid2 FROM {category_relation}, {category} c, {node} n WHERE (c.cid = cid1 OR c.cid = cid2) AND (cid1 = %d OR cid2 = %d) AND c.cid = n.nid AND c.cid != %d AND n.status = 1 ORDER BY c.weight, n.title'), $cid, $cid, $cid);
+      $related = array();
+      while ($category = db_fetch_object($result)) {
+        $related[$category->$key] = $category;
+      }
+
+      category_cache_op('set', $cid, $cache_key, $related);
     }
     return $related;
   }
@@ -100,33 +124,26 @@ function category_get_related($cid, $key
  * Find all parents of a given category ID.
  * This function will return the parents in an indexed array sorted by the parents' weight and title.
  */
-function category_get_parents($cid, $key = 'cid', $distant = TRUE, $reset = FALSE) {
-  static $parents, $distant_parents;
-
+function category_get_parents($cid, $key = 'cid', $distant = TRUE) {
   if (!$cid) {
     return array();
   }
 
-  if (($distant && !isset($distant_parents)) || (!$distant && !isset($parents)) || $reset) {
+  $cache_key = 'cat_get_parents'. ($distant ? 'd' : 'n');
+  $parents = category_cache_op('get', 0, $cache_key);
+  if (!isset($parents)) {
+
     $distant_sql = $distant ? '' : ' AND (c.cnid = cc.cnid OR c.cnid = 0)';
     $result = db_query(db_rewrite_sql('SELECT c.*, h.cid AS child, n.title, cn.admin_title FROM {category} c INNER JOIN {category_hierarchy} h ON c.cid = h.parent INNER JOIN {node} n ON c.cid = n.nid LEFT JOIN {category_cont} cn ON c.cid = cn.cid INNER JOIN {category} cc ON h.cid = cc.cid WHERE n.status = 1'. $distant_sql .' ORDER BY c.weight, n.title'), $cid);
-    if ($distant) {
-      $distant_parents = array();
-    }
-    else {
-      $parents = array();
-    }
+    $parents = array();
     while ($parent = db_fetch_object($result)) {
       if (empty($parent->admin_title)) {
         $parent->admin_title = $parent->title;
       }
-      if ($distant) {
-        $distant_parents[$parent->child][$parent->$key] = $parent;
-      }
-      else {
-        $parents[$parent->child][$parent->$key] = $parent;
-      }
+      $parents[$parent->child][$parent->$key] = $parent;
     }
+
+    category_cache_op('set', 0, $cache_key, $parents);
   }
 
   $no_parent = new StdClass();
@@ -137,7 +154,7 @@ function category_get_parents($cid, $key
   $no_parent->title = '';
   $no_parent->admin_title = '';
   $no_parent->child = $cid;
-  return $distant ? (isset($distant_parents[$cid]) ? $distant_parents[$cid] : array(0 => $no_parent)) : (isset($parents[$cid]) ? $parents[$cid] : array(0 => $no_parent));
+  return isset($parents[$cid]) ? $parents[$cid] : array(0 => $no_parent);
 }
 
 /**
@@ -159,26 +176,37 @@ function category_get_parents_all($cid, 
 /**
  * Find all children of a category ID.
  */
-function category_get_children($cid, $cnid = 0, $key = 'cid', $reset = FALSE) {
-  static $children;
+function category_get_children($cid, $cnid = 0, $key = 'cid') {
 
   if ($cnid) {
-    $result = db_query(db_rewrite_sql('SELECT c.*, n.title FROM {category} c INNER JOIN {category_hierarchy} h ON c.cid = h.cid INNER JOIN {node} n ON c.cid = n.nid WHERE h.parent = %d AND n.status = 1 AND c.cnid = %d ORDER BY c.weight, n.title'), $cid, $cnid);
+    $cache_key = 'cat_get_children_cn'. $cnid .':'. $key;
+    $children = category_cache_op('get', $cid, $cache_key);
+    if (!isset($children)) {
+
+      $result = db_query(db_rewrite_sql('SELECT c.*, n.title FROM {category} c INNER JOIN {category_hierarchy} h ON c.cid = h.cid INNER JOIN {node} n ON c.cid = n.nid WHERE h.parent = %d AND n.status = 1 AND c.cnid = %d ORDER BY c.weight, n.title'), $cid, $cnid);
+
+      $children = array();
+      while ($category = db_fetch_object($result)) {
+        $children[$category->$key] = $category;
+      }
 
-    $results = array();
-    while ($category = db_fetch_object($result)) {
-      $results[$category->$key] = $category;
+      category_cache_op('set', $cid, $cache_key, $children);
     }
-
-    return $results;
+    return $children;
   }
-  elseif (!isset($children) || $reset) {
+
+  $cache_key = 'cat_get_children_c0'. $key;
+  $children = category_cache_op('get', 0, $cache_key);
+  if (!isset($children)) {
+
     $result = db_query(db_rewrite_sql('SELECT c.*, h.parent, n.title FROM {category} c INNER JOIN {category_hierarchy} h ON c.cid = h.cid INNER JOIN {node} n ON c.cid = n.nid WHERE n.status = 1 ORDER BY c.weight, n.title'), $cid);
 
     $children = array();
     while ($category = db_fetch_object($result)) {
       $children[$category->parent][$category->$key] = $category;
     }
+
+    category_cache_op('set', 0, $cache_key, $children);
   }
 
   return isset($children[$cid]) ? $children[$cid] : array();
@@ -222,10 +250,20 @@ function category_get_tree($cnid, $paren
 
   // We cache trees, so it's not CPU-intensive to call get_tree() on a category
   // and its children, too.
-  if (!isset($children[$cnid])) {
+  $cache_key = 'cat_get_tree'. $depth .':'. ($distant ? 'd' : 'n');
+  $data = category_cache_op('get', $cnid, $cache_key);
+  if (isset($data)) {
+    $children = $data['children'];
+    $categories = $data['categories'];
+    $parents = $data['parents'];
+  }
+  else {
+
     $distant_sql = ($distant) ? '' : 'AND c.cnid = %d ';
 
-    $children[$cnid] = array();
+    $children = array();
+    $categories = array();
+    $parents = array();
     $result = db_query(db_rewrite_sql('SELECT c.cid, c.cnid, c.weight, c.depth, h.parent, n.title, cn.admin_title FROM {category} c INNER JOIN {category_hierarchy} h ON c.cid = h.cid INNER JOIN {node} n ON c.cid = n.nid LEFT JOIN {category_cont} cn ON c.cid = cn.cid LEFT JOIN {category} c2 ON h.parent = c2.cid WHERE (c2.cid IS NOT NULL OR h.parent = 0) AND n.status = 1 '. $distant_sql .'ORDER BY c.weight, n.title', 'n', 'nid'), $cnid);
 
     while ($category = db_fetch_object($result)) {
@@ -236,10 +274,11 @@ function category_get_tree($cnid, $paren
         }
       }
 
-      $children[$cnid][$category->parent][] = $category->cid;
-      $categories[$cnid][$category->cid] = $category;
-      $parents[$cnid][$category->cid][] = $category->parent;
+      $children[$category->parent][] = $category->cid;
+      $categories[$category->cid] = $category;
+      $parents[$category->cid][] = $category->parent;
     }
+    category_cache_op('set', $cnid, $cache_key, array('children' => $children, 'categories' => $categories, 'parents' => $parents));
   }
 
   $max_depth = (is_null($max_depth) && isset($children[$cnid])) ? count($children[$cnid]) : $max_depth;
@@ -273,10 +312,17 @@ function category_get_tree($cnid, $paren
  */
 function category_get_synonyms($cid) {
   if ($cid) {
-    $synonyms = array();
-    $result = db_query('SELECT name FROM {category_synonym} WHERE cid = %d', $cid);
-    while ($synonym = db_fetch_array($result)) {
-      $synonyms[] = $synonym['name'];
+    $cache_key = 'cat_get_synonyms';
+    $synonyms = category_cache_op('get', $cid, $cache_key);
+    if (!isset($synonyms)) {
+
+      $synonyms = array();
+      $result = db_query('SELECT name FROM {category_synonym} WHERE cid = %d', $cid);
+      while ($synonym = db_fetch_array($result)) {
+        $synonyms[] = $synonym['name'];
+      }
+
+    category_cache_op('set', $cid, $cache_key, $synonyms);
     }
     return $synonyms;
   }
@@ -296,9 +342,9 @@ function category_get_synonym_root($syno
  * Given a category id, count the number of published nodes in it.
  */
 function category_category_count_nodes($cid, $type = 0) {
-  static $count;
-
-  if (!isset($count[$type])) {
+  $cache_key = 'cat_cat_count_nodes'. $type;
+  $count = category_cache_op('get', 0, $cache_key);
+  if (!isset($count)) {
     // $type == 0 always evaluates true if $type is a string
     if (is_numeric($type)) {
       $result = db_query(db_rewrite_sql('SELECT c.cid, COUNT(n.nid) AS cnt FROM {category_node} c INNER JOIN {node} n ON c.nid = n.nid WHERE n.status = 1 GROUP BY c.cid'));
@@ -307,27 +353,29 @@ function category_category_count_nodes($
       $result = db_query(db_rewrite_sql("SELECT c.cid, COUNT(n.nid) AS cnt FROM {category_node} c INNER JOIN {node} n ON c.nid = n.nid WHERE n.status = 1 AND n.type = '%s' GROUP BY c.cid"), $type);
     }
     while ($category = db_fetch_object($result)) {
-      $count[$type][$category->cid] = $category->cnt;
+      $count[$category->cid] = $category->cnt;
     }
+    category_cache_op('set', 0, $cache_key, $count);
   }
   $children_count = 0;
   foreach (_category_category_children($cid) as $c) {
     $children_count += category_category_count_nodes($c, $type);
   }
-  return $children_count + (isset($count[$type][$cid]) ? $count[$type][$cid] : 0);
+  return $children_count + (isset($count[$cid]) ? $count[$cid] : 0);
 }
 
 /**
  * Helper for category_category_count_nodes().
  */
 function _category_category_children($cid) {
-  static $children;
-
+  $cache_key = 'cat_cat_childr';
+  $children = category_cache_op('get', 0, $cache_key);
   if (!isset($children)) {
     $result = db_query('SELECT cid, parent FROM {category_hierarchy}');
     while ($category = db_fetch_object($result)) {
       $children[$category->parent][] = $category->cid;
     }
+    category_cache_op('set', 0, $cache_key, $children);
   }
   return isset($children[$cid]) ? $children[$cid] : array();
 }
@@ -362,15 +410,15 @@ function category_get_category_by_name($
  *
  * @return
  *   The container object with all of its metadata, if exists, NULL otherwise.
- *   Results are statically cached.
+ *   Results are cached.
  */
 function category_get_container($cnid) {
-  static $containers = array();
-
-  if (!isset($containers[$cnid])) {
+  $cache_key = 'cat_get_cont';
+  $container = category_cache_op('get', $cnid, $cache_key);
+  if (!isset($container)) {
     // Initialize so if this container does not exist, we have
     // that cached, and we will not try to load this later.
-    $containers[$cnid] = FALSE;
+    $container = FALSE;
     // Try to load the data and fill up the object.
     $result = db_query(db_rewrite_sql('SELECT n.nid, cn.*, n.title, c.weight, c.depth, ct.type, c.weight AS cont_weight, c.depth AS cont_depth FROM {category} c INNER JOIN {category_cont} cn ON c.cid = cn.cid INNER JOIN {node} n ON c.cid = n.nid LEFT JOIN {category_cont_node_types} ct ON c.cid = ct.cid WHERE c.cid = %d ORDER BY c.weight, n.title', 'n', 'nid'), $cnid);
     $node_types = array();
@@ -392,12 +440,13 @@ function category_get_container($cnid) {
         $cont->has_admin_title = TRUE;
       }
 
-      $containers[$cnid] = $cont;
+      $container = $cont;
     }
+    category_cache_op('set', $cnid, $cache_key, $container);
   }
 
   // Return NULL if this vocabulary does not exist.
-  return (isset($containers[$cnid]) ? $containers[$cnid] : NULL);
+  return (!empty($container) ? $container : NULL);
 }
 
 /**
@@ -405,20 +454,22 @@ function category_get_container($cnid) {
  *
  * @param $cid
  *   The node/category ID of the category to be retrieved.
- * @param $reset
- *   Whether or not to reset the cache of categories. Default is FALSE.
  *
  * @return
  *   Populated category object if the category is found, NULL otherwise.
  */
-function category_get_category($cid, $reset = FALSE) {
-  static $categories = array();
-
-  if (!isset($categories[$cid])) {
-    $categories[$cid] = db_fetch_object(db_query('SELECT n.nid, n.title, c.* FROM {category} c INNER JOIN {node} n ON c.cid = n.nid WHERE cid = %d', $cid));
+function category_get_category($cid) {
+  $cache_key = 'cat_get_cat';
+  $category = category_cache_op('get', $cid, $cache_key);
+  if (!isset($category)) {
+    $category = db_fetch_object(db_query('SELECT n.nid, n.title, c.* FROM {category} c INNER JOIN {node} n ON c.cid = n.nid WHERE cid = %d', $cid));
+    if (empty($category)) {
+      $category = FALSE;
+    }
+    category_cache_op('set', $cid, $cache_key, $category);
   }
 
-  return (isset($categories[$cid]) ? $categories[$cid] : NULL);
+  return (!empty($category) ? $category : NULL);
 }
 
 /**
@@ -490,7 +541,7 @@ function category_select_nodes($cids = a
 /**
  * Accepts the result of a pager_query() call, such as that performed by
  * category_select_nodes(), and formats each node along with a pager.
-*/
+ */
 function category_render_nodes($result, $category_display) {
   $output = '';
   $has_rows = FALSE;
@@ -534,3 +585,83 @@ function category_categories_parse_strin
   }
   return $categories;
 }
+
+/**
+ * Central caching function for all kinds of node-related category data,
+ * so that all data for a given node may be loaded by single query from
+ * cache table into static variable, and then returned by various API
+ * functions without any queries needed. The cache is stored per-node,
+ * and flushed only when given node is saved or deleted. The $nid of '0'
+ * is used for global summary-data, and flushed on every node save.
+ * While saving a category or container, we flush the whole cache, as
+ * this affects the whole hiearchy, and happens rarely. This should not
+ * be used for data affected by other factors (such as current user's
+ * permissions), unless the condition is incorporated into the cache key.
+ *
+ * @param op
+ *   Operation to be performed - either 'get', 'set', or 'flush'.
+ *
+ * @param nid
+ *   Node id to handle data for. 0 is general data, 'all' flushes all.
+ *
+ * @param key
+ *   Name of node-data subset to work with. (Usually an API function identificator.)
+ *
+ * @param data
+ *   Data for the 'set' operation (will get added to the existing per-node record).
+ *
+ * @return
+ *   Cached data, or NULL if none.
+ */
+function category_cache_op($op, $nid, $key = '', $data = NULL) {
+  static $cache;
+  if (!isset($cache)) {
+    $cache = array('n' => array(), 'g' => array());
+  }
+
+  // Flush cache if requested
+  if ($op == 'flush') {
+    if ($nid === 'all') {
+      // Total flush: Empty {cache_category} and static cache entirely
+      cache_clear_all('*', 'cache_category', TRUE);
+      $cache = array('n' => array(), 'g' => array());
+    }
+    else {
+      // Node flush: Delete entries for given node
+      cache_clear_all('n'. $nid, 'cache_category');
+      unset($cache['n'][$nid]);
+      // Delete also all entries for global data, because we don't really
+      // know how these might be affected.
+      cache_clear_all('g', 'cache_category', TRUE);
+      $cache['g'] = array();
+    }
+    return;
+  }
+
+  // For global data, we use the $key instead of $nid as identificator, for
+  // better granularity of data loading (as these are larger pieces). Both
+  // node/global parts of the cache are separated, to allow for all-global
+  // flush.
+  $part = ($nid == 0) ? 'g' : 'n';
+  $id = ($nid == 0) ? $key : $nid;
+
+  // Load existing record, if not available in static variable already.
+  if (!isset($cache[$part][$id])) {
+    $entry = cache_get($part . $id, 'cache_category');
+    if ($entry) {
+      $cache[$part][$id] = $entry->data;
+    }
+    else {
+      $cache[$part][$id] = array();
+    }
+  }
+
+  // Save new data if required.
+  if ($op == 'set') {
+    $cache[$part][$id][$key] = $data;
+    cache_set($part . $id, $cache[$part][$id], 'cache_category');
+  }
+
+  // Return data for given node/key combination.
+  return isset($cache[$part][$id][$key]) ? $cache[$part][$id][$key] : NULL;
+}
diff -urp --strip-trailing-cr ../category/category.install ./category.install
--- ../category/category.install	2009-06-08 21:46:41.000000000 +0200
+++ ./category.install	2009-06-26 21:54:02.000000000 +0200
@@ -379,6 +379,9 @@ function category_schema() {
     ),
   );
 
+  $schema['cache_category'] = drupal_get_schema_unprocessed('system', 'cache');
+  $schema['cache_category']['description'] = 'Cache table for category module, to store various preprocessed data, both per-node and global.';
+
   return $schema;
 }
 
@@ -511,3 +514,48 @@ function category_update_6002() {
 
   return $ret;
 }
+
+/**
+ * Add cache table.
+ */
+function category_update_6003() {
+  $ret = array();
+
+  // This is verbatim from system module (minus descriptions), to avoid call to
+  // drupal_get_schema_unprocessed() which may change in future, per schema/updates
+  // guidelines.
+  $schema = array(
+    'fields' => array(
+      'cid' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => ''),
+      'data' => array(
+        'type' => 'blob',
+        'not null' => FALSE,
+        'size' => 'big'),
+      'expire' => array(
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0),
+      'created' => array(
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0),
+      'headers' => array(
+        'type' => 'text',
+        'not null' => FALSE),
+      'serialized' => array(
+        'type' => 'int',
+        'size' => 'small',
+        'not null' => TRUE,
+        'default' => 0)
+      ),
+    'indexes' => array('expire' => array('expire')),
+    'primary key' => array('cid'),
+  );
+
+  db_create_table($ret, 'cache_category', $schema);
+  return $ret;
+}
diff -urp --strip-trailing-cr ../category/category_menu/category_menu.module ./category_menu/category_menu.module
--- ../category/category_menu/category_menu.module	2009-06-21 17:25:42.000000000 +0200
+++ ./category_menu/category_menu.module	2009-06-26 01:43:10.000000000 +0200
@@ -142,6 +142,7 @@ function category_menu_menu_link_alter(&
       $node = db_fetch_array(db_query("SELECT * FROM {category_menu_map} WHERE mlid = %d", $item['mlid']));
       if (!empty($node['nid'])) {
         db_query("UPDATE {category} SET weight = %d WHERE cid = %d", $item['weight'], $node['nid']);
+        category_cache_op('flush', 'all');
       }
     }
   }
@@ -581,23 +582,29 @@ function category_menu_category_legacy($
  *   The menu settings for the specified node.
  */
 function category_menu_get_container($nid) {
-  $result = db_query("SELECT * FROM {category_menu} WHERE cid = %d", $nid);
+  $cache_key = 'cmenu_get_cont';
+  $container = category_cache_op('get', $nid, $cache_key);
+  if (!isset($container)) {
 
-  if ($container = db_fetch_object($result)) {
-    $links_for_nodes = array();
-    foreach (array_keys(node_get_types('names')) as $type) {
-      $links_setting = variable_get('category_menu_links_'. $type, 0);
-      if (!empty($links_setting) && $links_setting == $nid) {
-        $links_for_nodes[$type] = $type;
+    $result = db_query("SELECT * FROM {category_menu} WHERE cid = %d", $nid);
+
+    if ($container = db_fetch_object($result)) {
+      $links_for_nodes = array();
+      foreach (array_keys(node_get_types('names')) as $type) {
+        $links_setting = variable_get('category_menu_links_'. $type, 0);
+        if (!empty($links_setting) && $links_setting == $nid) {
+          $links_for_nodes[$type] = $type;
+        }
       }
+      $container->links_for_nodes = $links_for_nodes;
+    }
+    else {
+      $container = (object) array();
     }
-    $container->links_for_nodes = $links_for_nodes;
 
-    return $container;
-  }
-  else {
-    return (object) array();
+    category_cache_op('set', $nid, $cache_key, $container);
   }
+  return $container;
 }
 
 /**
@@ -632,6 +639,7 @@ function category_menu_save_container(&$
     }
   }
 
+  category_cache_op('flush', 'all');
   return $status;
 }
 
@@ -651,6 +659,7 @@ function category_menu_del_container($ni
       variable_del('category_menu_links_'. $type);
     }
   }
+  category_cache_op('flush', 'all');
 }
 
 /**
@@ -671,12 +680,20 @@ function category_menu_map_load($mlid) {
  * during hook_nodeapi('load').
  */
 function category_menu_map_load_by_nid($nid) {
-  if ($item = db_fetch_array(db_query('SELECT m.*, cmm.nid, ml.* FROM {menu_links} ml INNER JOIN {category_menu_map} cmm ON cmm.mlid = ml.mlid LEFT JOIN {menu_router} m ON m.path = ml.router_path WHERE cmm.nid = %d', $nid))) {
+  $cache_key = 'cmenu_map_load_nid';
+  $item = category_cache_op('get', $nid, $cache_key);
+  if (!isset($item)) {
 
-    $item['options'] = unserialize($item['options']);
-    return $item;
+    if ($item = db_fetch_array(db_query('SELECT m.*, cmm.nid, ml.* FROM {menu_links} ml INNER JOIN {category_menu_map} cmm ON cmm.mlid = ml.mlid LEFT JOIN {menu_router} m ON m.path = ml.router_path WHERE cmm.nid = %d', $nid))) {
+      $item['options'] = unserialize($item['options']);
+    }
+    else {
+      $item = FALSE;
+    }
+
+    category_cache_op('set', $nid, $cache_key, $item);
   }
-  return FALSE;
+  return $item;
 }
 
 /**
@@ -830,7 +847,8 @@ function category_menu_map_save($node) {
  *   by the category hierarchy), or 0 if no suitable menu link was found.
  */
 function _category_menu_map_save_category($nid) {
-  $parents = category_get_parents($nid, 'cid', TRUE, TRUE);
+  category_cache_op('flush', 'all');
+  $parents = category_get_parents($nid, 'cid', TRUE);
   $parent = reset($parents);
 
   if (empty($parent->cid)) {
@@ -922,72 +940,80 @@ function category_menu_build_active_trai
  * children of bottom-level menu items.
  */
 function category_menu_tree_all_data($menu_name, &$item, $max_depth = NULL, $cache_prefix = 'category-menu-') {
-  // Start with a regular tree, based on the specified item, containing
-  // items local to the $menu_name menu.
-  $tree = _category_menu_tree_all_data($menu_name, $item, $cache_prefix, $max_depth);
-
-  // Next, find top-level items with defined parents, and extend the tree
-  // to include such parents and their ancestors.
-  $parent_link = reset($tree);
-  $parent_link_key = key($tree);
-  while ($parent_link['link']['plid']) {
-    $item['has_children'] = 1;
-    $ancestor_link = menu_link_load($parent_link['link']['plid']);
-    if ($ancestor_link['menu_name'] != $menu_name) {
-      $tree = _category_menu_tree_all_data($ancestor_link['menu_name'], $ancestor_link, $cache_prefix);
-      _category_menu_tree_above($tree, array(
-        'key' => $parent_link_key,
-        'value' => $parent_link,
-      ));
 
-      $parent_link = reset($tree);
-      $parent_link_key = key($tree);
-    }
-    else {
-      $parent_link['link']['plid'] = 0;
-    }
-  };
+  $cache_key = 'cmenu_tree_all_data'. $menu_name .':'. $item[$mlid] .':'. $max_depth;
+  $tree = category_cache_op('get', 0, $cache_key);
+  if (!isset($tree)) {
+
+    // Start with a regular tree, based on the specified item, containing
+    // items local to the $menu_name menu.
+    $tree = _category_menu_tree_all_data($menu_name, $item, $cache_prefix, $max_depth);
+
+    // Next, find top-level items with defined parents, and extend the tree
+    // to include such parents and their ancestors.
+    $parent_link = reset($tree);
+    $parent_link_key = key($tree);
+    while ($parent_link['link']['plid']) {
+      $item['has_children'] = 1;
+      $ancestor_link = menu_link_load($parent_link['link']['plid']);
+      if ($ancestor_link['menu_name'] != $menu_name) {
+        $tree = _category_menu_tree_all_data($ancestor_link['menu_name'], $ancestor_link, $cache_prefix);
+        _category_menu_tree_above($tree, array(
+          'key' => $parent_link_key,
+          'value' => $parent_link,
+        ));
 
-  $query_nodetypes1 = '';
-  $query_nodetypes2 = '';
-  $args = array($item['mlid'], $menu_name);
-  if ($category = db_fetch_object(db_query('SELECT c.* FROM {category} c INNER JOIN {category_menu_map} cmm ON c.cid = cmm.nid WHERE cmm.mlid = %d', $item['mlid']))) {
-    $cnid = !empty($category->cnid) ? $category->cnid : $category->cid;
-    $node_types = array();
-    $query_nodetypes = db_query('SELECT type FROM {category_cont_node_types} WHERE cid = %d', $cnid);
+        $parent_link = reset($tree);
+        $parent_link_key = key($tree);
+      }
+      else {
+        $parent_link['link']['plid'] = 0;
+      }
+    };
 
-    while ($node_type = db_fetch_object($query_nodetypes)) {
-      $node_types[] = 'category-menu-toc-'. $node_type->type;
-    }
+    $query_nodetypes1 = '';
+    $query_nodetypes2 = '';
+    $args = array($item['mlid'], $menu_name);
+    if ($category = db_fetch_object(db_query('SELECT c.* FROM {category} c INNER JOIN {category_menu_map} cmm ON c.cid = cmm.nid WHERE cmm.mlid = %d', $item['mlid']))) {
+      $cnid = !empty($category->cnid) ? $category->cnid : $category->cid;
+      $node_types = array();
+      $query_nodetypes = db_query('SELECT type FROM {category_cont_node_types} WHERE cid = %d', $cnid);
+
+      while ($node_type = db_fetch_object($query_nodetypes)) {
+        $node_types[] = 'category-menu-toc-'. $node_type->type;
+      }
 
-    if (!empty($node_types)) {
-      $query_nodetypes1 = ' LEFT JOIN {category_menu_map} cmm ON ml.mlid = cmm.mlid LEFT JOIN {node} n ON cmm.nid = n.nid';
+      if (!empty($node_types)) {
+        $query_nodetypes1 = ' LEFT JOIN {category_menu_map} cmm ON ml.mlid = cmm.mlid LEFT JOIN {node} n ON cmm.nid = n.nid';
 
-      $placeholders = db_placeholders($node_types, 'varchar');
-      $query_nodetypes2 = ' AND ml.menu_name NOT IN('. $placeholders .')';
-      $args = array_merge($args, $node_types);
+        $placeholders = db_placeholders($node_types, 'varchar');
+        $query_nodetypes2 = ' AND ml.menu_name NOT IN('. $placeholders .')';
+        $args = array_merge($args, $node_types);
+      }
     }
-  }
 
-  $query = "SELECT m.*, ml.* FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path". $query_nodetypes1 ." WHERE ml.plid = %d AND ml.menu_name != '%s'". $query_nodetypes2;
+    $query = "SELECT m.*, ml.* FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path". $query_nodetypes1 ." WHERE ml.plid = %d AND ml.menu_name != '%s'". $query_nodetypes2;
 
-  if (isset($max_depth)) {
-    $query .= ' AND ml.depth < %d';
-    $args[] = $max_depth - 1;
-  }
-  // Finally, find distant children with the specified item as their parent,
-  // and extend the tree to include such children and their descendants.
-  $children = db_query($query, $args);
-  $child_tree_prev = array();
+    if (isset($max_depth)) {
+      $query .= ' AND ml.depth < %d';
+      $args[] = $max_depth - 1;
+    }
+    // Finally, find distant children with the specified item as their parent,
+    // and extend the tree to include such children and their descendants.
+    $children = db_query($query, $args);
+    $child_tree_prev = array();
 
-  while ($child_link = db_fetch_array($children)) {
-    $item['has_children'] = 1;
-    _menu_link_translate($child_link);
-    $child_tree = _category_menu_tree_all_data($child_link['menu_name'], $child_link, $cache_prefix);
-    if (!empty($child_tree) && $child_tree != $child_tree_prev) {
-      _category_menu_tree_below($tree, $child_tree, $item);
-      $child_tree_prev = $child_tree;
+    while ($child_link = db_fetch_array($children)) {
+      $item['has_children'] = 1;
+      _menu_link_translate($child_link);
+      $child_tree = _category_menu_tree_all_data($child_link['menu_name'], $child_link, $cache_prefix);
+      if (!empty($child_tree) && $child_tree != $child_tree_prev) {
+        _category_menu_tree_below($tree, $child_tree, $item);
+        $child_tree_prev = $child_tree;
+      }
     }
+
+  category_cache_op('set', 0, $cache_key, $tree);
   }
 
   return $tree;
diff -urp --strip-trailing-cr ../category/category.module ./category.module
--- ../category/category.module	2009-06-21 18:42:02.000000000 +0200
+++ ./category.module	2009-06-26 19:56:46.000000000 +0200
@@ -37,6 +37,13 @@ function category_theme() {
 }
 
 /**
+ * Implementation of hook_flush_caches()
+ */
+function category_flush_caches() {
+  return array('cache_category');
+}
+
+/**
  * Implementation of hook_link().
  *
  * This hook is extended with $type = 'categories' to allow themes to
@@ -816,6 +823,7 @@ function category_node_save($node, $cate
  */
 function category_node_delete($node) {
   db_query('DELETE FROM {category_node} WHERE nid = %d', $node->nid);
+  category_cache_op('flush', $node->nid);
 }
 
 /**
@@ -823,6 +831,7 @@ function category_node_delete($node) {
  */
 function category_node_delete_revision($node) {
   db_query('DELETE FROM {category_node} WHERE vid = %d', $node->vid);
+  category_cache_op('flush', $node->nid);
 }
 
 /**
@@ -1082,6 +1091,7 @@ function category_save_container(&$node)
     }
   }
 
+  category_cache_op('flush', 'all');
   return $status;
 }
 
@@ -1111,6 +1121,7 @@ function category_del_container($cid) {
     }
   }
 
+  category_cache_op('flush', 'all');
   return SAVED_DELETED;
 }
 
@@ -1226,6 +1237,7 @@ function category_save_category(&$node) 
     }
   }
 
+  category_cache_op('flush', 'all');
   return $status;
 }
 
@@ -1244,6 +1256,7 @@ function category_del_category($cid) {
   db_query('DELETE FROM {category_synonym} WHERE cid = %d', $cid);
   db_query('DELETE FROM {category_node} WHERE cid = %d', $cid);
 
+  category_cache_op('flush', 'all');
   return SAVED_DELETED;
 }
 
@@ -1692,7 +1705,6 @@ function category_form_category_submit($
  *   Rendered node listing, or FALSE if no listing should be displayed.
  */
 function category_node_listing($node) {
-  $nodes = category_select_nodes(array($node->category['cid']), 'or', $node->category['depth'], TRUE, TRUE);
   $is_container = empty($node->category['cnid']);
   $show_nodes = FALSE;
   $category_display = NULL;
@@ -1733,6 +1745,7 @@ function category_node_listing($node) {
       return category_views_render_nodes($node);
     }
     else {
+      $nodes = category_select_nodes(array($node->category['cid']), 'or', $node->category['depth'], TRUE, TRUE);
       return category_render_nodes($nodes, $category_display);
     }
   }
diff -urp --strip-trailing-cr ../category/contrib/category_views/category_views.module ./contrib/category_views/category_views.module
--- ../category/contrib/category_views/category_views.module	2009-06-08 20:50:03.000000000 +0200
+++ ./contrib/category_views/category_views.module	2009-06-26 01:15:51.000000000 +0200
@@ -26,17 +26,23 @@ function category_views_nodeapi(&$node, 
       if (!empty($behavior)) {
         // This is a container or category. Load the view settings from database.
         // No category information is available in the $node object yet.
-        if ($behavior === 'container') {
-          $result = db_query('SELECT * FROM {category_views} WHERE cid = %d', $node->nid);
-        }
-        else {
-          $result = db_query('SELECT v.* FROM {category_views} v INNER JOIN {category} c ON v.cid = c.cnid WHERE c.cid = %d', $node->nid);
+        $cache_key = 'cview_node_load';
+        $output = category_cache_op('get', $node->nid, $cache_key);
+        if (!isset($output)) {
+          if ($behavior === 'container') {
+            $result = db_query('SELECT * FROM {category_views} WHERE cid = %d', $node->nid);
+          }
+          else {
+            $result = db_query('SELECT v.* FROM {category_views} v INNER JOIN {category} c ON v.cid = c.cnid WHERE c.cid = %d', $node->nid);
+          }
+          $settings = db_fetch_array($result);
+          $output = array(
+            'view_for_cats' => $settings['view_name'],
+            'view_display' => array('cont' => $settings['display_cont'], 'cat' => $settings['display_cat']),
+          );
+          category_cache_op('set', $node->nid, $cache_key, $output);
         }
-        $settings = db_fetch_array($result);
-        return array(
-          'view_for_cats' => $settings['view_name'],
-          'view_display' => array('cont' => $settings['display_cont'], 'cat' => $settings['display_cat']),
-        );
+        return $output;
       }
       break;
 
