--- a/src/rcldb/rcldb.cpp
+++ b/src/rcldb/rcldb.cpp
@@ -1,5 +1,5 @@
 #ifndef lint
-static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.136 2008-07-28 12:24:15 dockes Exp $ (C) 2004 J.F.Dockes";
+static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.137 2008-07-29 06:25:29 dockes Exp $ (C) 2004 J.F.Dockes";
 #endif
 /*
  *   This program is free software; you can redistribute it and/or modify
@@ -80,39 +80,41 @@
 // found in document)
 const static string rclSyntAbs("?!#@");
 
-// Compute the unique term used to link documents to their file-system source:
-// Hashed path + possible internal path
+// Compute the unique term used to link documents to their origin. 
+// "Q" + external udi
 static inline string make_uniterm(const string& udi)
 {
     string uniterm("Q");
     uniterm.append(udi);
     return uniterm;
 }
+// Compute parent term used to link documents to their parent document (if any)
+// "" + parent external udi
+static inline string make_parentterm(const string& udi)
+{
+    // I prefer to be in possible conflict with omega than with
+    // user-defined fields (Xxxx) that we also allow. "F" is currently
+    // not used by omega (2008-07)
+    string pterm("F");
+    pterm.append(udi);
+    return pterm;
+}
 
 /* See comment in class declaration: return all subdocuments of a
- * document given by its unique path id */
-bool Db::Native::subDocs(const string &uniterm, vector<Xapian::docid>& docids) 
+ * document given by its unique id. 
+*/
+bool Db::Native::subDocs(const string &udi, vector<Xapian::docid>& docids) 
 {
     LOGDEB2(("subDocs: [%s]\n", uniterm.c_str()));
-    docids.clear();
-
     string ermsg;
+    string pterm = make_parentterm(udi);
     for (int tries = 0; tries < 2; tries++) {
 	try {
-	    Xapian::TermIterator it = db.allterms_begin(); 
-	    it.skip_to(uniterm);
-	    // Don't return the doc itself:
-	    it++;
-	    for (; it != db.allterms_end(); it++) {
-		LOGDEB2(("subDocs: testing [%s]\n", (*it).c_str()));
-		// If current term does not begin with uniterm or has
-		// another |, not the same file
-		if ((*it).find(uniterm) != 0 || 
-		    (*it).find_last_of("|") != uniterm.length()-1)
-		    break;
-		docids.push_back(*(db.postlist_begin(*it)));
-	    }
-	    LOGDEB2(("Db::Native::subDocs: returning %d ids\n", docids.size()));
+	    Xapian::PostingIterator it = db.postlist_begin(pterm);
+	    for (; it != db.postlist_end(pterm); it++) {
+		docids.push_back(*it);
+	    }
+	    LOGDEB(("Db::Native::subDocs: returning %d ids\n", docids.size()));
 	    return true;
 	} catch (const Xapian::DatabaseModifiedError &e) {
 	    LOGDEB(("Db::subDocs: got modified error. reopen/retry\n"));
@@ -800,9 +802,11 @@
 // the title abstract and body and add special terms for file name,
 // date, mime type ... , create the document data record (more
 // metadata), and update database
-bool Db::add(const string &udi, const Doc &idoc)
-{
-    LOGDEB1(("Db::add: udi %s\n", udi.c_str()));
+bool Db::addOrUpdate(const string &udi, const string &parent_udi,
+		     const Doc &idoc)
+{
+    LOGDEB(("Db::add: udi [%s] parent [%s]\n", 
+	     udi.c_str(), parent_udi.c_str()));
     if (m_ndb == 0)
 	return false;
     static int first = 1;
@@ -927,7 +931,11 @@
     // checks, and unique id for the replace_document() call.
     string uniterm = make_uniterm(udi);
     newdocument.add_term(uniterm);
-
+    // Parent term. This is used to find all descendents, mostly to delete them 
+    // when the parent goes away
+    if (!parent_udi.empty()) {
+	newdocument.add_term(make_parentterm(parent_udi));
+    }
     // Dates etc...
     time_t mtime = atol(doc.dmtime.empty() ? doc.fmtime.c_str() : 
 			doc.dmtime.c_str());
@@ -1091,7 +1099,7 @@
 
 	    // Set the existence flag for all the subdocs (if any)
 	    vector<Xapian::docid> docids;
-	    if (!m_ndb->subDocs(uniterm, docids)) {
+	    if (!m_ndb->subDocs(udi, docids)) {
 		LOGERR(("Rcl::Db::needUpdate: can't get subdocs list\n"));
 		return true;
 	    }
@@ -1193,9 +1201,9 @@
 	    } catch (const Xapian::DocNotFoundError &) {
 		LOGDEB(("Db::purge: document #%d not found\n", docid));
 	    } catch (const Xapian::Error &e) {
-		LOGERR(("Db::purge: document #%d: %s\n", e.get_msg().c_str()));
+		LOGERR(("Db::purge: document #%d: %s\n", docid, e.get_msg().c_str()));
 	    } catch (...) {
-		LOGERR(("Db::purge: document #%d: unknown error\n"));
+		LOGERR(("Db::purge: document #%d: unknown error\n", docid));
 	    }
 	}
     }
@@ -1224,7 +1232,7 @@
 	LOGDEB(("purgeFile: delete docid %d\n", *docid));
 	db.delete_document(*docid);
 	vector<Xapian::docid> docids;
-	m_ndb->subDocs(uniterm, docids);
+	m_ndb->subDocs(udi, docids);
 	LOGDEB(("purgeFile: subdocs cnt %d\n", docids.size()));
 	for (vector<Xapian::docid>::iterator it = docids.begin();
 	     it != docids.end(); it++) {