diff --git a/src/query/wasatorcl.cpp b/src/query/wasatorcl.cpp index 1b7a6e00..e32b5322 100644 --- a/src/query/wasatorcl.cpp +++ b/src/query/wasatorcl.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: wasatorcl.cpp,v 1.7 2007-02-07 12:00:17 dockes Exp $ (C) 2006 J.F.Dockes"; +static char rcsid[] = "@(#$Id: wasatorcl.cpp,v 1.8 2007-02-13 10:58:31 dockes Exp $ (C) 2006 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -21,6 +21,7 @@ static char rcsid[] = "@(#$Id: wasatorcl.cpp,v 1.7 2007-02-07 12:00:17 dockes Ex #include "rcldb.h" #include "searchdata.h" #include "wasatorcl.h" +#include "debuglog.h" Rcl::SearchData *wasaStringToRcl(const string &qs, string &reason) { @@ -44,6 +45,8 @@ Rcl::SearchData *wasaQueryToRcl(WasaQuery *wasa) Rcl::SearchData *sdata = new Rcl::SearchData(Rcl::SCLT_AND); WasaQuery::subqlist_t::iterator it; + Rcl::SearchDataClause *nclause; + for (it = wasa->m_subs.begin(); it != wasa->m_subs.end(); it++) { switch ((*it)->m_op) { case WasaQuery::OP_NULL: @@ -53,16 +56,23 @@ Rcl::SearchData *wasaQueryToRcl(WasaQuery *wasa) continue; case WasaQuery::OP_LEAF: if ((*it)->m_value.find_first_of(" \t\n\r") != string::npos) { - sdata->addClause - (new Rcl::SearchDataClauseDist(Rcl::SCLT_PHRASE, - (*it)->m_value, 0, - (*it)->m_fieldspec)); + nclause = new Rcl::SearchDataClauseDist(Rcl::SCLT_PHRASE, + (*it)->m_value, 0, + (*it)->m_fieldspec); } else { - sdata->addClause - (new Rcl::SearchDataClauseSimple(Rcl::SCLT_AND, - (*it)->m_value, - (*it)->m_fieldspec)); + nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_AND, + (*it)->m_value, + (*it)->m_fieldspec); } + if (nclause == 0) { + LOGERR(("wasaQueryToRcl: out of memory\n")); + return 0; + } + if ((*it)->m_modifiers & WasaQuery::WQM_NOSTEM) { + fprintf(stderr, "Setting NOSTEM\n"); + nclause->setModifiers(Rcl::SearchDataClause::SDCM_NOSTEMMING); + } + sdata->addClause(nclause); break; case WasaQuery::OP_EXCL: // Note: have to add dquotes which will be translated to @@ -70,15 +80,24 @@ Rcl::SearchData *wasaQueryToRcl(WasaQuery *wasa) // but should work. If there is actually a single // word, it will not be taken as a phrase, and // stem-expansion will work normally - sdata->addClause - (new Rcl::SearchDataClauseSimple(Rcl::SCLT_EXCL, - string("\"") + - (*it)->m_value + "\"", - (*it)->m_fieldspec)); + nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_EXCL, + string("\"") + + (*it)->m_value + "\"", + (*it)->m_fieldspec); + + if (nclause == 0) { + LOGERR(("wasaQueryToRcl: out of memory\n")); + return 0; + } + if ((*it)->m_modifiers & WasaQuery::WQM_NOSTEM) + nclause->setModifiers(Rcl::SearchDataClause::SDCM_NOSTEMMING); + sdata->addClause(nclause); break; case WasaQuery::OP_OR: // Concatenate all OR values as phrases. Hope there are no - // stray dquotes in there + // stray dquotes in there. Note that single terms won't be + // handled as real phrases inside searchdata.cpp (so the + // added dquotes won't interfer with stemming) { string orvalue; WasaQuery::subqlist_t::iterator orit; @@ -86,20 +105,19 @@ Rcl::SearchData *wasaQueryToRcl(WasaQuery *wasa) orit != (*it)->m_subs.end(); orit++) { orvalue += string("\"") + (*orit)->m_value + "\" "; } - sdata->addClause - (new Rcl::SearchDataClauseSimple(Rcl::SCLT_OR, - orvalue, - (*it)->m_fieldspec)); + nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_OR, + orvalue, + (*it)->m_fieldspec); + if (nclause == 0) { + LOGERR(("wasaQueryToRcl: out of memory\n")); + return 0; + } + if ((*it)->m_modifiers & WasaQuery::WQM_NOSTEM) + nclause->setModifiers(Rcl::SearchDataClause::SDCM_NOSTEMMING); + sdata->addClause(nclause); } } } - // File type and sort specs. We only know about mime types for now. - if (wasa->m_typeKind == WasaQuery::WQTK_MIME) { - for (vector::const_iterator it = wasa->m_types.begin(); - it != wasa->m_types.end(); it++) { - sdata->addFiletype(*it); - } - } return sdata; } diff --git a/src/rcldb/searchdata.cpp b/src/rcldb/searchdata.cpp index f519156a..d01dc87b 100644 --- a/src/rcldb/searchdata.cpp +++ b/src/rcldb/searchdata.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: searchdata.cpp,v 1.12 2007-01-29 13:51:08 dockes Exp $ (C) 2006 J.F.Dockes"; +static char rcsid[] = "@(#$Id: searchdata.cpp,v 1.13 2007-02-13 10:58:31 dockes Exp $ (C) 2006 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -310,10 +310,10 @@ static void addPrefix(list& terms, const string& prefix) * count) */ bool StringToXapianQ::processUserString(const string &iq, - const string &prefix, - string &ermsg, - list &pqueries, - int slack, bool useNear) + const string &prefix, + string &ermsg, + list &pqueries, + int slack, bool useNear) { LOGDEB(("StringToXapianQ:: query string: [%s]\n", iq.c_str())); ermsg.erase(); @@ -400,8 +400,8 @@ bool StringToXapianQ::processUserString(const string &iq, // Some version of xapian will accept only one OR clause // inside NEAR, all others must be leafs bool nostemexp = - (op == Xapian::Query::OP_PHRASE || hadmultiple) ? - true : false; + op == Xapian::Query::OP_PHRASE || hadmultiple; + string sterm; listexp; stripExpandTerm(nostemexp, *it, exp, sterm); @@ -472,10 +472,15 @@ static string fieldToPrefix(const string& i_field) return ""; } +static const string nullstemlang; + // Translate a simple OR, AND, or EXCL search clause. bool SearchDataClauseSimple::toNativeQuery(Rcl::Db &db, void *p, const string& stemlang) { + const string& l_stemlang = (m_modifiers&SDCM_NOSTEMMING)? nullstemlang: + stemlang; + m_terms.clear(); m_groups.clear(); Xapian::Query *qp = (Xapian::Query *)p; @@ -502,7 +507,7 @@ bool SearchDataClauseSimple::toNativeQuery(Rcl::Db &db, void *p, (m_parentSearch && !m_parentSearch->haveWildCards()) || (m_parentSearch == 0 && !m_haveWildCards); - StringToXapianQ tr(db, stemlang, doBoostUserTerm); + StringToXapianQ tr(db, l_stemlang, doBoostUserTerm); if (!tr.processUserString(m_text, prefix, m_reason, pqueries)) return false; if (pqueries.empty()) { @@ -516,7 +521,7 @@ bool SearchDataClauseSimple::toNativeQuery(Rcl::Db &db, void *p, // Translate a FILENAME search clause. bool SearchDataClauseFilename::toNativeQuery(Rcl::Db &db, void *p, - const string& stemlang) + const string&) { Xapian::Query *qp = (Xapian::Query *)p; *qp = Xapian::Query(); @@ -532,6 +537,8 @@ bool SearchDataClauseFilename::toNativeQuery(Rcl::Db &db, void *p, bool SearchDataClauseDist::toNativeQuery(Rcl::Db &db, void *p, const string& stemlang) { + const string& l_stemlang = (m_modifiers&SDCM_NOSTEMMING)? nullstemlang: + stemlang; LOGDEB(("SearchDataClauseDist::toNativeQuery\n")); m_terms.clear(); m_groups.clear(); @@ -562,7 +569,7 @@ bool SearchDataClauseDist::toNativeQuery(Rcl::Db &db, void *p, } string s = string("\"") + m_text + string("\""); bool useNear = (m_tp == SCLT_NEAR); - StringToXapianQ tr(db, stemlang, doBoostUserTerm); + StringToXapianQ tr(db, l_stemlang, doBoostUserTerm); if (!tr.processUserString(s, prefix, m_reason, pqueries, m_slack, useNear)) return false; if (pqueries.empty()) { diff --git a/src/rcldb/searchdata.h b/src/rcldb/searchdata.h index 5287ee7f..2ba0af83 100644 --- a/src/rcldb/searchdata.h +++ b/src/rcldb/searchdata.h @@ -16,7 +16,7 @@ */ #ifndef _SEARCHDATA_H_INCLUDED_ #define _SEARCHDATA_H_INCLUDED_ -/* @(#$Id: searchdata.h,v 1.9 2007-01-25 15:50:54 dockes Exp $ (C) 2004 J.F.Dockes */ +/* @(#$Id: searchdata.h,v 1.10 2007-02-13 10:58:32 dockes Exp $ (C) 2004 J.F.Dockes */ /** * Structures to hold data coming almost directly from the gui @@ -121,28 +121,37 @@ private: class SearchDataClause { public: - SearchDataClause(SClType tp) : m_tp(tp), m_parentSearch(0) {} + SearchDataClause(SClType tp) + : m_tp(tp), m_parentSearch(0), m_modifiers(SDCM_NONE) + {} + virtual ~SearchDataClause() {} virtual bool toNativeQuery(Rcl::Db &db, void *, const string&) = 0; - virtual bool isFileName() const {return m_tp==SCLT_FILENAME ? true: false;} + bool isFileName() const {return m_tp==SCLT_FILENAME ? true: false;} virtual string getReason() const {return m_reason;} virtual bool getTerms(vector&, vector >&, vector&) const {return true;} - virtual SClType getTp() {return m_tp;} - virtual void setParent(SearchData *p) {m_parentSearch = p;} + SClType getTp() {return m_tp;} + + void setParent(SearchData *p) {m_parentSearch = p;} + friend class SearchData; + + enum Modifier {SDCM_NONE=0, SDCM_NOSTEMMING=1}; + virtual void setModifiers(Modifier mod) {m_modifiers = mod;} protected: - string m_reason; - SClType m_tp; + string m_reason; + SClType m_tp; SearchData *m_parentSearch; - bool m_haveWildCards; + bool m_haveWildCards; + Modifier m_modifiers; }; /**