Index: fooaggregator_feed.inc
===================================================================
--- fooaggregator_feed.inc	(revision 5)
+++ fooaggregator_feed.inc	(working copy)
@@ -127,6 +127,20 @@
 function fooaggregator_feed_delete(&$node) {
   // todo: what if the cron is running and it updated the feed after we deleted it ?
   db_query("delete from {fooaggregator_feed} where nid=%d", $node->nid);
+
+  // For mysql, we have to keep the table that maps feeds to their children
+  // up-to-date.  For postgres, this is not a materialized table, but a VIEW
+  // instead.  So in postgres, it will be kept up-to-date automatically,
+  // without the need to store redundant information in the database.
+  // We keep this table in order to integrate with views_fusion.
+  switch ($GLOBALS['db_type']) {
+  case 'mysql':
+  case 'mysqli':
+    db_query("DELETE FROM {fooaggregator_feed_children} (nid, itemid) 
+	          WHERE nid=%d",
+			  $node->nid);
+    break;
+  }
 }
 
 /**
Index: fooaggregator.install
===================================================================
--- fooaggregator.install	(revision 5)
+++ fooaggregator.install	(working copy)
@@ -39,11 +39,57 @@
 }
 
 /**
+ * This table maps a feed to each of its children.
+ * It's totally redundant, because it could be calculated by looking at the fid
+ * of each feed item.  But it is required by views_fusion in order to map feeds
+ * to their children.
+ * In postgres, we will use a VIEW, so that this table is not actually
+ * materialized, but is instead calculated.
+ */
+function fooaggregator_update_1() {
+  $ret = array();
+  switch ($GLOBALS['db_type']) {
+  case 'mysql':
+  case 'mysqli':
+  	$ret[] = update_sql("CREATE TABLE {fooaggregator_feed_children} (
+      nid int unsigned not null, 
+      itemid int unsigned not null, 
+      primary key(nid, itemid)
+      ) /*!40100 DEFAULT CHARACTER SET UTF8 */ ");
+
+	$ret[] = update_sql("INSERT INTO {fooaggregator_feed_children}
+	  SELECT {fooaggregator_feed}.nid AS nid,
+	         {fooaggregator_item}.nid AS itemid
+	  FROM {fooaggregator_feed}, {fooaggregator_item}
+	  WHERE {fooaggregator_feed}.nid = {fooaggregator_item}.fid");
+    break;
+  case 'pgsql':
+    $ret[] = update_sql("CREATE VIEW {fooaggregator_feed_children} AS
+	  SELECT {fooaggregator_feed}.nid AS nid,
+	         {fooaggregator_item}.nid AS itemid
+	  FROM {fooaggregator_feed}, {fooaggregator_item}
+	  WHERE {fooaggregator_feed}.nid = {fooaggregator_item}.fid");
+    break;
+  }
+
+  return $ret;
+}
+
+/**
  * Implementation of hook_uninstall().
  */
 function fooaggregator_uninstall() {
   db_query('DROP TABLE {fooaggregator_item}');
   db_query('DROP TABLE {fooaggregator_feed}');
+  switch ($GLOBALS['db_type']) {
+  case 'mysql':
+  case 'mysqli':
+    db_query("DROP TABLE {fooaggregator_feed_children}");
+	break;
+  case 'pgsql':
+    db_query("DROP VIEW {fooaggregator_feed_childrean}");
+    break;
+  }
 
   variable_del('fooaggregator_per_page');
   variable_del('fooaggregator_uid');
Index: fooaggregator_views.inc
===================================================================
--- fooaggregator_views.inc	(revision 5)
+++ fooaggregator_views.inc	(working copy)
@@ -25,6 +25,34 @@
   $tables['fooaggregator_item'] = _fooaggregator_item_views_tables();
   $tables['fooaggregator_count'] = _fooaggregator_count_views_tables();
   $tables['fooaggregator_latest'] = _fooaggregator_latest_views_tables();
+
+  $tables['fooaggregator_feed_children'] = array(
+    'name' => 'fooaggregator_feed_children',
+    'join' => array(
+      'left' => array(
+        'table' => 'node',
+        'field' => 'nid',
+      ),
+      'right' => array(
+        'field' => 'nid'
+      ),
+      'type' => 'inner',
+    ),
+	/*
+    'filters' => array(
+      'child_nid' => array(
+        'name' => t('Feed: Child Item Id'),
+        'operator' => 'views_handler_operator_eqneq',
+        'option' => array(
+            '#type' => 'select',
+            '#options' => node_get_types('names'),
+        ),
+        'handler' => 'nodefamily_views_filter',
+        'help' => t('This allows you to filter by child item ID.  You can optionally restrict the filter to a certain content type, which makes sense to use in conjunctions with the NOT EQUAL operator.'),
+      ),
+    ),
+	*/
+  );
 					 
   return $tables;
 }
@@ -482,4 +510,21 @@
   views_ui_plugin_validate_table($type, $view, $form);
 }
 
+
+/**
+ * Implementation of hook_views_fusion().
+ */
+function fooaggregator_views_fusion() {
+  
+  return array('fooaggregator_item' => array(
+                 'title' => t('fooaggregator: item - feed'),
+                 'field' => 'fid',
+               ),
+	           'fooaggregator_feed_children' => array(
+		         'title' => t('fooaggregator: feed - item'),
+				 'field' => 'itemid',
+			  ),
+         );
+}
+
 ?>
Index: fooaggregator_item.inc
===================================================================
--- fooaggregator_item.inc	(revision 5)
+++ fooaggregator_item.inc	(working copy)
@@ -75,6 +75,20 @@
  */
 function fooaggregator_item_insert(&$node) {
   db_query("INSERT INTO {fooaggregator_item} (nid, fid, guid, link, author) VALUES(%d, %d, '%s', '%s', '%s')", $node->nid, $node->fid, $node->guid, $node->link, $node->author);
+
+  // For mysql, we have to keep the table that maps feeds to their children
+  // up-to-date.  For postgres, this is not a materialized table, but a VIEW
+  // instead.  So in postgres, it will be kept up-to-date automatically,
+  // without the need to store redundant information in the database.
+  // We keep this table in order to integrate with views_fusion.
+  switch ($GLOBALS['db_type']) {
+  case 'mysql':
+  case 'mysqli':
+    db_query("INSERT INTO {fooaggregator_feed_children} (nid, itemid) 
+	          VALUES (%d, %d)",
+			  $node->fid, $node->nid);
+    break;
+  }
 }
 
 /**
@@ -91,6 +105,20 @@
  */
 function fooaggregator_item_delete(&$node) {
   db_query("DELETE FROM {fooaggregator_item} WHERE nid=%d", $node->nid);
+
+  // For mysql, we have to keep the table that maps feeds to their children
+  // up-to-date.  For postgres, this is not a materialized table, but a VIEW
+  // instead.  So in postgres, it will be kept up-to-date automatically,
+  // without the need to store redundant information in the database.
+  // We keep this table in order to integrate with views_fusion.
+  switch ($GLOBALS['db_type']) {
+  case 'mysql':
+  case 'mysqli':
+    db_query("DELETE FROM {fooaggregator_feed_children} (nid, itemid) 
+	          WHERE itemid=%d",
+			  $node->nid);
+    break;
+  }
 }
 
 /**
