Switch to side-by-side view

--- a/src/query/wasatorcl.cpp
+++ b/src/query/wasatorcl.cpp
@@ -35,28 +35,15 @@
 #include "refcntr.h"
 #include "textsplit.h"
 
-Rcl::SearchData *wasaStringToRcl(RclConfig *config, 
-				 const string &qs, string &reason, 
-                                 const string& autosuffs)
+static Rcl::SearchData *wasaQueryToRcl(RclConfig *config, WasaQuery *wasa, 
+				       const string& autosuffs, string& reason)
 {
-    StringToWasaQuery parser;
-    WasaQuery *wq = parser.stringToQuery(qs, reason);
-    if (wq == 0) 
-	return 0;
-    Rcl::SearchData *rq = wasaQueryToRcl(config, wq, autosuffs);
-    if (rq == 0) {
-	reason = "Failed translating xesam query structure to recoll";
+    if (wasa == 0) {
+	reason = "NULL query";
 	return 0;
     }
-    return rq;
-}
-
-Rcl::SearchData *wasaQueryToRcl(RclConfig *config,
-				WasaQuery *wasa, const string& autosuffs)
-{
-    if (wasa == 0)
-	return 0;
     if (wasa->m_op != WasaQuery::OP_AND && wasa->m_op != WasaQuery::OP_OR) {
+	reason = "Top query neither AND nor OR ?";
 	LOGERR(("wasaQueryToRcl: top query neither AND nor OR!\n"));
 	return 0;
     }
@@ -70,43 +57,79 @@
     WasaQuery::subqlist_t::iterator it;
     Rcl::SearchDataClause *nclause;
 
+    // Walk the list of clauses. Some pseudo-field types need special
+    // processing, which results in setting data in the top struct
+    // instead of adding a clause. We check for these first
     for (it = wasa->m_subs.begin(); it != wasa->m_subs.end(); it++) {
+
+	if (!stringicmp("mime", (*it)->m_fieldspec) ||
+	    !stringicmp("format", (*it)->m_fieldspec)) {
+	    if ((*it)->m_op != WasaQuery::OP_LEAF) {
+		reason = "Negative mime/format clauses not supported yet";
+		return 0;
+	    }
+	    sdata->addFiletype((*it)->m_value);
+	    continue;
+	} 
+
+	// Xesam uses "type", we also support "rclcat", for broad
+	// categories like "audio", "presentation", etc.
+	if (!stringicmp("rclcat", (*it)->m_fieldspec) ||
+	    !stringicmp("type", (*it)->m_fieldspec)) {
+	    if ((*it)->m_op != WasaQuery::OP_LEAF) {
+		reason = "Negative rclcat/type clauses not supported yet";
+		return 0;
+	    }
+	    list<string> mtypes;
+	    if (config && config->getMimeCatTypes((*it)->m_value, mtypes)
+		&& !mtypes.empty()) {
+		for (list<string>::iterator mit = mtypes.begin();
+		     mit != mtypes.end(); mit++) {
+		    sdata->addFiletype(*mit);
+		}
+	    } else {
+		reason = "Unknown rclcat/type value: no mime types found";
+		return 0;
+	    }
+	    continue;
+	}
+
+	// Filtering on location
+	if (!stringicmp("dir", (*it)->m_fieldspec)) {
+	    sdata->setTopdir((*it)->m_value, (*it)->m_op == WasaQuery::OP_EXCL);
+	    continue;
+	} 
+
+	// Handle "date" spec
+	if (!stringicmp("date", (*it)->m_fieldspec)) {
+	    if ((*it)->m_op != WasaQuery::OP_LEAF) {
+		reason = "Negative date filtering not supported";
+		return 0;
+	    }
+	    DateInterval di;
+	    if (!parsedateinterval((*it)->m_value, &di)) {
+		LOGERR(("wasaQueryToRcl: bad date interval format\n"));
+		reason = "Bad date interval format";
+		return 0;
+	    }
+	    LOGDEB(("wasaQueryToRcl:: date span:  %d-%d-%d/%d-%d-%d\n",
+		    di.y1,di.m1,di.d1, di.y2,di.m2,di.d2));
+	    sdata->setDateSpan(&di);
+	    continue;
+	} 
+
+	// "Regular" processing follows:
 	switch ((*it)->m_op) {
 	case WasaQuery::OP_NULL:
 	case WasaQuery::OP_AND:
 	default:
-	    LOGINFO(("wasaQueryToRcl: found bad NULL or AND q type in list\n"));
-	    continue;
+	    reason = "Found bad NULL or AND query type in list";
+	    LOGERR(("wasaQueryToRcl: found bad NULL or AND q type in list\n"));
+	    continue;
+
 	case WasaQuery::OP_LEAF: {
 	    LOGDEB2(("wasaQueryToRcl: leaf clause [%s]:[%s]\n", 
 		     (*it)->m_fieldspec.c_str(), (*it)->m_value.c_str()));
-
-	    // Special cases (mime, category, dir filter ...). Not pretty.
-
-	    if (!stringicmp("mime", (*it)->m_fieldspec) ||
-		!stringicmp("format", (*it)->m_fieldspec)
-		) {
-		sdata->addFiletype((*it)->m_value);
-		break;
-	    } 
-
-	    // Xesam uses "type", we also support "rclcat", for broad
-	    // categories like "audio", "presentation", etc.
-	    if (!stringicmp("rclcat", (*it)->m_fieldspec) ||
-		!stringicmp("type", (*it)->m_fieldspec)) {
-		list<string> mtypes;
-		if (config && config->getMimeCatTypes((*it)->m_value, mtypes)) {
-		    for (list<string>::iterator mit = mtypes.begin();
-			 mit != mtypes.end(); mit++) {
-			sdata->addFiletype(*mit);
-		    }
-		}
-		break;
-	    } 
-	    if (!stringicmp("dir", (*it)->m_fieldspec)) {
-		sdata->setTopdir((*it)->m_value);
-		break;
-	    } 
 
             // Change terms found in the "autosuffs" list into "ext"
             // field queries
@@ -121,21 +144,6 @@
                 }
             }
 
-            // Handle "date" spec
-	    if (!stringicmp("date", (*it)->m_fieldspec)) {
-                DateInterval di;
-                if (!parsedateinterval((*it)->m_value, &di)) {
-                    LOGERR(("wasaQueryToRcl: bad date interval format\n"));
-                    // Process rest of query anyway ?
-                    break;
-                }
-                LOGDEB(("wasaQueryToRcl:: date span:  %d-%d-%d/%d-%d-%d\n",
-                        di.y1,di.m1,di.d1, di.y2,di.m2,di.d2))
-		sdata->setDateSpan(&di);
-		break;
-	    } 
-
-            // "Regular" processing follows:
 	    unsigned int mods = (unsigned int)(*it)->m_modifiers;
 
 	    if (TextSplit::hasVisibleWhite((*it)->m_value)) {
@@ -154,6 +162,7 @@
 							  (*it)->m_fieldspec);
 	    }
 	    if (nclause == 0) {
+		reason = "Out of memory";
 		LOGERR(("wasaQueryToRcl: out of memory\n"));
 		return 0;
 	    }
@@ -176,12 +185,14 @@
 	    // but should work. If there is actually a single
 	    // word, it will not be taken as a phrase, and
 	    // stem-expansion will work normally
+            // Have to do this because searchdata has nothing like and_not
 	    nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_EXCL, 
 						      string("\"") + 
 						      (*it)->m_value + "\"",
 						      (*it)->m_fieldspec);
 	    
 	    if (nclause == 0) {
+		reason = "Out of memory";
 		LOGERR(("wasaQueryToRcl: out of memory\n"));
 		return 0;
 	    }
@@ -194,7 +205,8 @@
 	    LOGDEB2(("wasaQueryToRcl: OR clause [%s]:[%s]\n", 
 		     (*it)->m_fieldspec.c_str(), (*it)->m_value.c_str()));
 	    // Create a subquery.
-	    Rcl::SearchData *sub = wasaQueryToRcl(config, *it);
+	    Rcl::SearchData *sub = 
+		wasaQueryToRcl(config, *it, autosuffs, reason);
 	    if (sub == 0) {
 		continue;
 	    }
@@ -203,6 +215,7 @@
 					     RefCntr<Rcl::SearchData>(sub));
 	    if (nclause == 0) {
 		LOGERR(("wasaQueryToRcl: out of memory\n"));
+		reason = "Out of memory";
 		return 0;
 	    }
 	    if ((*it)->m_modifiers & WasaQuery::WQM_NOSTEM)
@@ -213,3 +226,14 @@
 
     return sdata;
 }
+
+Rcl::SearchData *wasaStringToRcl(RclConfig *config, 
+				 const string &qs, string &reason, 
+                                 const string& autosuffs)
+{
+    StringToWasaQuery parser;
+    WasaQuery *wq = parser.stringToQuery(qs, reason);
+    if (wq == 0) 
+	return 0;
+    return wasaQueryToRcl(config, wq, autosuffs, reason);
+}