--- 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);
+}