define new searchdataclausepath to replace the old dir: filtering mechanism. ORing dirs now works

This commit is contained in:
Jean-Francois Dockes
2013-01-05 16:21:30 +01:00
parent 9e88426d13
commit cbc269abb1
10 changed files with 200 additions and 164 deletions
+7 -5
View File
@@ -64,10 +64,11 @@ void WasaQuery::describe(string &desc) const
desc += "NULL";
break;
case OP_LEAF:
if (m_exclude)
desc += "NOT (";
desc += fieldspec + m_value;
break;
case OP_EXCL:
desc += string("NOT (" ) + fieldspec + m_value + ") ";
if (m_exclude)
desc += ")";
break;
case OP_OR:
case OP_AND:
@@ -429,11 +430,12 @@ StringToWasaQuery::Internal::stringToQuery(const string& str, string& reason)
}
}
nclause->m_op = WasaQuery::OP_LEAF;
// +- indicator ?
if (checkSubMatch(SMI_PM, match, reason) && match[0] == '-') {
nclause->m_op = WasaQuery::OP_EXCL;
nclause->m_exclude = true;
} else {
nclause->m_op = WasaQuery::OP_LEAF;
nclause->m_exclude = false;
}
if (prev_or) {
+6 -2
View File
@@ -48,7 +48,7 @@ using std::vector;
class WasaQuery {
public:
/** Type of this element: leaf or AND/OR chain */
enum Op {OP_NULL, OP_LEAF, OP_EXCL, OP_OR, OP_AND};
enum Op {OP_NULL, OP_LEAF, OP_OR, OP_AND};
/** Relation to be searched between field and value. Recoll actually only
supports "contain" except for a size field */
enum Rel {REL_NULL, REL_EQUALS, REL_CONTAINS, REL_LT, REL_LTE,
@@ -63,7 +63,8 @@ public:
typedef vector<WasaQuery*> subqlist_t;
WasaQuery()
: m_op(OP_NULL), m_modifiers(0), m_slack(0), m_weight(1.0)
: m_op(OP_NULL), m_rel(REL_NULL), m_exclude(false),
m_modifiers(0), m_slack(0), m_weight(1.0)
{}
~WasaQuery();
@@ -79,6 +80,9 @@ public:
/** Relation between field and value: =, :, <,>,<=, >= */
WasaQuery::Rel m_rel;
/* Negating flag */
bool m_exclude;
/* String value. Valid for op == OP_LEAF or EXCL */
string m_value;
+51 -61
View File
@@ -64,11 +64,13 @@ static Rcl::SearchData *wasaQueryToRcl(const RclConfig *config,
if (!stringicmp("mime", (*it)->m_fieldspec) ||
!stringicmp("format", (*it)->m_fieldspec)) {
if ((*it)->m_op == WasaQuery::OP_LEAF) {
sdata->addFiletype((*it)->m_value);
} else if ((*it)->m_op == WasaQuery::OP_EXCL) {
sdata->remFiletype((*it)->m_value);
if ((*it)->m_exclude) {
sdata->remFiletype((*it)->m_value);
} else {
sdata->addFiletype((*it)->m_value);
}
} else {
reason = "internal error: mime clause neither leaf not excl??";
reason = "internal error: mime clause not leaf??";
return 0;
}
continue;
@@ -78,10 +80,8 @@ static Rcl::SearchData *wasaQueryToRcl(const RclConfig *config,
// categories like "audio", "presentation", etc.
if (!stringicmp("rclcat", (*it)->m_fieldspec) ||
!stringicmp("type", (*it)->m_fieldspec)) {
if ((*it)->m_op != WasaQuery::OP_LEAF &&
(*it)->m_op != WasaQuery::OP_EXCL) {
reason = "internal error: rclcat/type clause neither leaf"
"nor excl??";
if ((*it)->m_op != WasaQuery::OP_LEAF) {
reason = "internal error: rclcat/type clause not leaf??";
return 0;
}
vector<string> mtypes;
@@ -89,10 +89,11 @@ static Rcl::SearchData *wasaQueryToRcl(const RclConfig *config,
&& !mtypes.empty()) {
for (vector<string>::iterator mit = mtypes.begin();
mit != mtypes.end(); mit++) {
if ((*it)->m_op == WasaQuery::OP_LEAF)
sdata->addFiletype(*mit);
else
if ((*it)->m_exclude) {
sdata->remFiletype(*mit);
} else {
sdata->addFiletype(*mit);
}
}
} else {
reason = "Unknown rclcat/type value: no mime types found";
@@ -101,14 +102,6 @@ static Rcl::SearchData *wasaQueryToRcl(const RclConfig *config,
continue;
}
// Filtering on location
if (!stringicmp("dir", (*it)->m_fieldspec)) {
string dir = path_tildexpand((*it)->m_value);
sdata->addDirSpec(dir, (*it)->m_op == WasaQuery::OP_EXCL,
(*it)->m_weight);
continue;
}
// Handle "date" spec
if (!stringicmp("date", (*it)->m_fieldspec)) {
if ((*it)->m_op != WasaQuery::OP_LEAF) {
@@ -181,9 +174,9 @@ static Rcl::SearchData *wasaQueryToRcl(const RclConfig *config,
continue;
case WasaQuery::OP_LEAF: {
LOGDEB0(("wasaQueryToRcl: leaf clause [%s]:[%s] slack %d\n",
(*it)->m_fieldspec.c_str(), (*it)->m_value.c_str(),
(*it)->m_slack));
LOGDEB0(("wasaQueryToRcl: leaf clause [%s:%s] slack %d excl %d\n",
(*it)->m_fieldspec.c_str(), (*it)->m_value.c_str(),
(*it)->m_slack, (*it)->m_exclude));
// Change terms found in the "autosuffs" list into "ext"
// field queries
@@ -198,23 +191,45 @@ static Rcl::SearchData *wasaQueryToRcl(const RclConfig *config,
}
}
// I'm not sure I understand the phrase/near detection
// thereafter anymore, maybe it would be better to have an
// explicit flag. Mods can only be set after a double
// quote.
if (TextSplit::hasVisibleWhite((*it)->m_value) || mods) {
Rcl::SClType tp = Rcl::SCLT_PHRASE;
if (mods & WasaQuery::WQM_PROX) {
tp = Rcl::SCLT_NEAR;
if (!stringicmp("dir", (*it)->m_fieldspec)) {
// dir filtering special case
nclause = new Rcl::SearchDataClausePath((*it)->m_value,
(*it)->m_exclude);
} else if ((*it)->m_exclude) {
if (wasa->m_op != WasaQuery::OP_AND) {
LOGERR(("wasaQueryToRcl: excl clause inside OR list!\n"));
continue;
}
nclause = new Rcl::SearchDataClauseDist(tp, (*it)->m_value,
(*it)->m_slack,
(*it)->m_fieldspec);
} else {
nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_AND,
(*it)->m_value,
// Note: have to add dquotes which will be translated to
// phrase if there are several words in there. Not pretty
// 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);
} else {
// I'm not sure I understand the phrase/near detection
// thereafter anymore, maybe it would be better to have an
// explicit flag. Mods can only be set after a double
// quote.
if (TextSplit::hasVisibleWhite((*it)->m_value) || mods) {
Rcl::SClType tp = Rcl::SCLT_PHRASE;
if (mods & WasaQuery::WQM_PROX) {
tp = Rcl::SCLT_NEAR;
}
nclause = new Rcl::SearchDataClauseDist(tp, (*it)->m_value,
(*it)->m_slack,
(*it)->m_fieldspec);
} else {
nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_AND,
(*it)->m_value,
(*it)->m_fieldspec);
}
}
if (nclause == 0) {
reason = "Out of memory";
LOGERR(("wasaQueryToRcl: out of memory\n"));
@@ -223,31 +238,6 @@ static Rcl::SearchData *wasaQueryToRcl(const RclConfig *config,
}
break;
case WasaQuery::OP_EXCL:
LOGDEB2(("wasaQueryToRcl: excl clause [%s]:[%s]\n",
(*it)->m_fieldspec.c_str(), (*it)->m_value.c_str()));
if (wasa->m_op != WasaQuery::OP_AND) {
LOGERR(("wasaQueryToRcl: negative clause inside OR list!\n"));
continue;
}
// Note: have to add dquotes which will be translated to
// phrase if there are several words in there. Not pretty
// 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;
}
break;
case WasaQuery::OP_OR:
LOGDEB2(("wasaQueryToRcl: OR clause [%s]:[%s]\n",
(*it)->m_fieldspec.c_str(), (*it)->m_value.c_str()));