defined data structure to pass around the search term description used for highlighting and other

This commit is contained in:
"Jean-Francois Dockes ext:(%22)
2012-08-17 10:45:00 +02:00
parent ebdd6faaf5
commit dc7b3420a0
16 changed files with 409 additions and 351 deletions
+52 -81
View File
@@ -498,23 +498,12 @@ bool SearchData::fileNameOnly()
return true;
}
// Extract all terms and term groups
bool SearchData::getTerms(vector<string>& terms,
vector<vector<string> >& groups,
vector<int>& gslks) const
// Extract all term data
void SearchData::getTerms(HighlightData &hld) const
{
for (qlist_cit_t it = m_query.begin(); it != m_query.end(); it++)
(*it)->getTerms(terms, groups, gslks);
return true;
}
// Extract user terms
void SearchData::getUTerms(vector<string>& terms) const
{
for (qlist_cit_t it = m_query.begin(); it != m_query.end(); it++)
(*it)->getUTerms(terms);
sort(terms.begin(), terms.end());
vector<string>::iterator it = unique(terms.begin(), terms.end());
terms.erase(it, terms.end());
(*it)->getTerms(hld);
return;
}
// Splitter callback for breaking a user string into simple terms and
@@ -590,10 +579,10 @@ private:
// translating.
class StringToXapianQ {
public:
StringToXapianQ(Db& db, const string& field,
StringToXapianQ(Db& db, HighlightData& hld, const string& field,
const string &stmlng, bool boostUser)
: m_db(db), m_field(field), m_stemlang(stmlng),
m_doBoostUserTerms(boostUser)
: m_db(db), m_field(field), m_stemlang(stmlng),
m_doBoostUserTerms(boostUser), m_hld(hld)
{ }
bool processUserString(const string &iq,
@@ -601,20 +590,6 @@ public:
vector<Xapian::Query> &pqueries,
const StopList &stops,
int slack = 0, bool useNear = false);
// After processing the string: return search terms and term
// groups (ie: for highlighting)
bool getTerms(vector<string>& terms, vector<vector<string> >& groups)
{
terms.insert(terms.end(), m_terms.begin(), m_terms.end());
groups.insert(groups.end(), m_groups.begin(), m_groups.end());
return true;
}
bool getUTerms(vector<string>& terms)
{
terms.insert(terms.end(), m_uterms.begin(), m_uterms.end());
return true;
}
private:
void expandTerm(bool dont, const string& term, vector<string>& exp,
string& sterm, const string& prefix);
@@ -630,10 +605,7 @@ private:
const string& m_field;
const string& m_stemlang;
bool m_doBoostUserTerms;
// Single terms and phrases resulting from breaking up text;
vector<string> m_uterms;
vector<string> m_terms;
vector<vector<string> > m_groups;
HighlightData& m_hld;
};
#if 1
@@ -647,7 +619,7 @@ static void listVector(const string& what, const vector<string>&l)
}
#endif
/** Expand stem and wildcards
/** Take simple term and expand stem and wildcards
*
* @param nostemexp don't perform stem expansion. This is mainly used to
* prevent stem expansion inside phrases (because the user probably
@@ -680,9 +652,11 @@ void StringToXapianQ::expandTerm(bool nostemexp,
nostemexp = true;
}
if (!haswild)
m_hld.uterms.insert(term);
if (nostemexp && !haswild) {
sterm = term;
m_uterms.push_back(sterm);
exp.resize(1);
exp[0] = prefix + term;
} else {
@@ -692,7 +666,6 @@ void StringToXapianQ::expandTerm(bool nostemexp,
m_field);
} else {
sterm = term;
m_uterms.push_back(sterm);
m_db.termMatch(Rcl::Db::ET_STEM, m_stemlang, term, res, -1,
m_field);
}
@@ -701,7 +674,6 @@ void StringToXapianQ::expandTerm(bool nostemexp,
exp.push_back(it->term);
}
}
//listVector("ExpandTerm:uterms now: ", m_uterms);
}
// Do distribution of string vectors: a,b c,d -> a,c a,d b,c b,d
@@ -753,12 +725,15 @@ void StringToXapianQ::processSimpleSpan(const string& span, bool nostemexp,
}
expandTerm(nostemexp, span, exp, sterm, prefix);
// m_terms is used for highlighting, we don't want prefixes in there.
// Set up the highlight data. No prefix should go in there
for (vector<string>::const_iterator it = exp.begin();
it != exp.end(); it++) {
m_terms.push_back(it->substr(prefix.size()));
m_hld.groups.push_back(vector<string>(1, it->substr(prefix.size())));
m_hld.slacks.push_back(0);
m_hld.grpsugidx.push_back(m_hld.ugroups.size() - 1);
}
// Push either term or OR of stem-expanded set
Xapian::Query xq(Xapian::Query::OP_OR, exp.begin(), exp.end());
@@ -786,7 +761,9 @@ void StringToXapianQ::processPhraseOrNear(TextSplitQ *splitData,
Xapian::Query::op op = useNear ? Xapian::Query::OP_NEAR :
Xapian::Query::OP_PHRASE;
vector<Xapian::Query> orqueries;
#ifdef XAPIAN_NEAR_EXPAND_SINGLE_BUF
bool hadmultiple = false;
#endif
vector<vector<string> >groups;
string prefix;
@@ -805,15 +782,19 @@ void StringToXapianQ::processPhraseOrNear(TextSplitQ *splitData,
for (vector<string>::iterator it = splitData->terms.begin();
it != splitData->terms.end(); it++, nxit++) {
LOGDEB0(("ProcessPhrase: processing [%s]\n", it->c_str()));
// Adjust when we do stem expansion. Not inside phrases, and
// some versions of xapian will accept only one OR clause
// inside NEAR, all others must be leafs.
bool nostemexp = *nxit || (op == Xapian::Query::OP_PHRASE) || hadmultiple;
// Adjust when we do stem expansion. Not if disabled by
// caller, not inside phrases, and some versions of xapian
// will accept only one OR clause inside NEAR.
bool nostemexp = *nxit || (op == Xapian::Query::OP_PHRASE)
#ifdef XAPIAN_NEAR_EXPAND_SINGLE_BUF
|| hadmultiple
#endif // single OR inside NEAR
;
string sterm;
vector<string> exp;
expandTerm(nostemexp, *it, exp, sterm, prefix);
LOGDEB0(("ProcessPhrase: exp size %d\n", exp.size()));
LOGDEB0(("ProcessPhraseOrNear: exp size %d\n", exp.size()));
listVector("", exp);
// groups is used for highlighting, we don't want prefixes in there.
vector<string> noprefs;
@@ -850,7 +831,13 @@ void StringToXapianQ::processPhraseOrNear(TextSplitQ *splitData,
vector<vector<string> > allcombs;
vector<string> comb;
multiply_groups(groups.begin(), groups.end(), comb, allcombs);
m_groups.insert(m_groups.end(), allcombs.begin(), allcombs.end());
// Insert the search groups and slacks in the highlight data, with
// a reference to the user entry that generated them:
m_hld.groups.insert(m_hld.groups.end(), allcombs.begin(), allcombs.end());
m_hld.slacks.insert(m_hld.slacks.end(), allcombs.size(), slack);
m_hld.grpsugidx.insert(m_hld.grpsugidx.end(), allcombs.size(),
m_hld.ugroups.size() - 1);
}
// Trim string beginning with ^ or ending with $ and convert to flags
@@ -875,7 +862,16 @@ static int stringToMods(string& s)
* We just separate words and phrases, and do wildcard and stem expansion,
*
* This is used to process data entered into an OR/AND/NEAR/PHRASE field of
* the GUI.
* the GUI (in the case of NEAR/PHRASE, clausedist adds dquotes to the user
* entry).
*
* This appears awful, and it would seem that the split into
* terms/phrases should be performed in the upper layer so that we
* only receive pure term or near/phrase pure elements here, but in
* fact there are things that would appear like terms to naive code,
* and which will actually may be turned into phrases (ie: tom:jerry),
* in a manner which intimately depends on the index implementation,
* so that it makes sense to process this here.
*
* The final list contains one query for each term or phrase
* - Elements corresponding to a stem-expanded part are an OP_OR
@@ -895,9 +891,6 @@ bool StringToXapianQ::processUserString(const string &iq,
{
LOGDEB(("StringToXapianQ:: query string: [%s], slack %d, near %d\n", iq.c_str(), slack, useNear));
ermsg.erase();
m_uterms.clear();
m_terms.clear();
m_groups.clear();
// Simple whitespace-split input into user-level words and
// double-quoted phrases: word1 word2 "this is a phrase".
@@ -952,10 +945,12 @@ bool StringToXapianQ::processUserString(const string &iq,
case 0:
continue;// ??
case 1:
m_hld.ugroups.push_back(vector<string>(1, *it));
processSimpleSpan(splitter.terms.front(),
splitter.nostemexps.front(), pqueries);
break;
default:
m_hld.ugroups.push_back(vector<string>(1, *it));
processPhraseOrNear(&splitter, pqueries, useNear, slack, mods);
}
}
@@ -984,8 +979,6 @@ bool SearchDataClauseSimple::toNativeQuery(Rcl::Db &db, void *p,
LOGDEB2(("SearchDataClauseSimple::toNativeQuery: stemlang [%s]\n",
stemlang.c_str()));
m_terms.clear();
m_groups.clear();
Xapian::Query *qp = (Xapian::Query *)p;
*qp = Xapian::Query();
@@ -1007,16 +1000,14 @@ bool SearchDataClauseSimple::toNativeQuery(Rcl::Db &db, void *p,
(m_parentSearch && !m_parentSearch->haveWildCards()) ||
(m_parentSearch == 0 && !m_haveWildCards);
StringToXapianQ tr(db, m_field, l_stemlang, doBoostUserTerm);
StringToXapianQ tr(db, m_hldata, m_field, l_stemlang, doBoostUserTerm);
if (!tr.processUserString(m_text, m_reason, pqueries, db.getStopList()))
return false;
if (pqueries.empty()) {
LOGERR(("SearchDataClauseSimple: resolved to null query\n"));
return true;
}
tr.getTerms(m_terms, m_groups);
tr.getUTerms(m_uterms);
//listVector("SearchDataClauseSimple: Uterms: ", m_uterms);
*qp = Xapian::Query(op, pqueries.begin(), pqueries.end());
if (m_weight != 1.0) {
*qp = Xapian::Query(Xapian::Query::OP_SCALE_WEIGHT, *qp, m_weight);
@@ -1056,8 +1047,6 @@ bool SearchDataClauseDist::toNativeQuery(Rcl::Db &db, void *p,
const string& l_stemlang = (m_modifiers&SDCM_NOSTEMMING)? cstr_null:
stemlang;
LOGDEB(("SearchDataClauseDist::toNativeQuery\n"));
m_terms.clear();
m_groups.clear();
Xapian::Query *qp = (Xapian::Query *)p;
*qp = Xapian::Query();
@@ -1080,7 +1069,7 @@ bool SearchDataClauseDist::toNativeQuery(Rcl::Db &db, void *p,
}
string s = cstr_dquote + m_text + cstr_dquote;
bool useNear = (m_tp == SCLT_NEAR);
StringToXapianQ tr(db, m_field, l_stemlang, doBoostUserTerm);
StringToXapianQ tr(db, m_hldata, m_field, l_stemlang, doBoostUserTerm);
if (!tr.processUserString(s, m_reason, pqueries, db.getStopList(),
m_slack, useNear))
return false;
@@ -1088,8 +1077,7 @@ bool SearchDataClauseDist::toNativeQuery(Rcl::Db &db, void *p,
LOGERR(("SearchDataClauseDist: resolved to null query\n"));
return true;
}
tr.getTerms(m_terms, m_groups);
tr.getUTerms(m_uterms);
*qp = *pqueries.begin();
if (m_weight != 1.0) {
*qp = Xapian::Query(Xapian::Query::OP_SCALE_WEIGHT, *qp, m_weight);
@@ -1097,21 +1085,4 @@ bool SearchDataClauseDist::toNativeQuery(Rcl::Db &db, void *p,
return true;
}
// Translate subquery
bool SearchDataClauseSub::toNativeQuery(Rcl::Db &db, void *p, const string&)
{
return m_sub->toNativeQuery(db, p);
}
bool SearchDataClauseSub::getTerms(vector<string>& terms,
vector<vector<string> >& groups,
vector<int>& gslks) const
{
return m_sub.getconstptr()->getTerms(terms, groups, gslks);
}
void SearchDataClauseSub::getUTerms(vector<string>& terms) const
{
m_sub.getconstptr()->getUTerms(terms);
}
} // Namespace Rcl
+136 -108
View File
@@ -31,14 +31,11 @@
#include "refcntr.h"
#include "smallut.h"
#include "cstr.h"
#include "hldata.h"
class RclConfig;
#ifndef NO_NAMESPACES
using std::vector;
using std::string;
namespace Rcl {
#endif // NO_NAMESPACES
/** Search clause types */
enum SClType {
@@ -50,33 +47,33 @@ enum SClType {
class SearchDataClause;
/**
Data structure representing a Recoll user query, for translation
into a Xapian query tree. This could probably better called a 'question'.
Data structure representing a Recoll user query, for translation
into a Xapian query tree. This could probably better called a 'question'.
This is a list of search clauses combined through either OR or AND.
This is a list of search clauses combined through either OR or AND.
Clauses either reflect user entry in a query field: some text, a
clause type (AND/OR/NEAR etc.), possibly a distance, or points to
another SearchData representing a subquery.
Clauses either reflect user entry in a query field: some text, a
clause type (AND/OR/NEAR etc.), possibly a distance, or points to
another SearchData representing a subquery.
The content of each clause when added may not be fully parsed yet
(may come directly from a gui field). It will be parsed and may be
translated to several queries in the Xapian sense, for exemple
several terms and phrases as would result from
["this is a phrase" term1 term2] .
The content of each clause when added may not be fully parsed yet
(may come directly from a gui field). It will be parsed and may be
translated to several queries in the Xapian sense, for exemple
several terms and phrases as would result from
["this is a phrase" term1 term2] .
This is why the clauses also have an AND/OR/... type.
This is why the clauses also have an AND/OR/... type.
A phrase clause could be added either explicitly or using double quotes:
{SCLT_PHRASE, [this is a phrase]} or as {SCLT_XXX, ["this is a phrase"]}
A phrase clause could be added either explicitly or using double quotes:
{SCLT_PHRASE, [this is a phrase]} or as {SCLT_XXX, ["this is a phrase"]}
*/
*/
class SearchData {
public:
SearchData(SClType tp)
: m_tp(tp), m_topdirexcl(false), m_topdirweight(1.0),
m_haveDates(false), m_maxSize(size_t(-1)),
m_minSize(size_t(-1)), m_haveWildCards(false)
: m_tp(tp), m_topdirexcl(false), m_topdirweight(1.0),
m_haveDates(false), m_maxSize(size_t(-1)),
m_minSize(size_t(-1)), m_haveWildCards(false)
{
if (m_tp != SCLT_OR && m_tp != SCLT_AND)
m_tp = SCLT_OR;
@@ -108,7 +105,7 @@ public:
bool maybeAddAutoPhrase(Rcl::Db &db, double threshold);
/** Set/get top subdirectory for filtering results */
void setTopdir(const string& t, bool excl = false, float w = 1.0)
void setTopdir(const std::string& t, bool excl = false, float w = 1.0)
{
m_topdir = t;
m_topdirexcl = excl;
@@ -122,38 +119,37 @@ public:
void setDateSpan(DateInterval *dip) {m_dates = *dip; m_haveDates = true;}
/** Add file type for filtering results */
void addFiletype(const string& ft) {m_filetypes.push_back(ft);}
void addFiletype(const std::string& ft) {m_filetypes.push_back(ft);}
/** Add file type to not wanted list */
void remFiletype(const string& ft) {m_nfiletypes.push_back(ft);}
void remFiletype(const std::string& ft) {m_nfiletypes.push_back(ft);}
void setStemlang(const string& lang = "english") {m_stemlang = lang;}
void setStemlang(const std::string& lang = "english") {m_stemlang = lang;}
/** Retrieve error description */
string getReason() {return m_reason;}
std::string getReason() {return m_reason;}
/** Get terms and phrase/near groups. Used in the GUI for highlighting
* The groups and gslks vectors are parallel and hold the phrases/near
* string groups and their associated slacks (distance in excess of group
* size)
/** Return term expansion data. Mostly used by caller for highlighting
*/
bool getTerms(vector<string>& terms,
vector<vector<string> >& groups, vector<int>& gslks) const;
/** Get user-input terms (before expansion etc.) */
void getUTerms(vector<string>& terms) const;
void getTerms(HighlightData& hldata) const;
/**
* Get/set the description field which is retrieved from xapian after
* initializing the query. It is stored here for usage in the GUI.
*/
string getDescription() {return m_description;}
void setDescription(const string& d) {m_description = d;}
std::string getDescription() {return m_description;}
void setDescription(const std::string& d) {m_description = d;}
private:
SClType m_tp; // Only SCLT_AND or SCLT_OR here
vector<SearchDataClause*> m_query;
vector<string> m_filetypes; // Restrict to filetypes if set.
vector<string> m_nfiletypes; // Unwanted file types
string m_topdir; // Restrict to subtree.
// Combine type. Only SCLT_AND or SCLT_OR here
SClType m_tp;
// Complex query descriptor
std::vector<SearchDataClause*> m_query;
// Restricted set of filetypes if not empty.
std::vector<std::string> m_filetypes;
// Excluded set of file types if not empty
std::vector<std::string> m_nfiletypes;
// Restrict to subtree.
std::string m_topdir;
bool m_topdirexcl; // Invert meaning
float m_topdirweight; // affect weight instead of filter
bool m_haveDates;
@@ -162,11 +158,11 @@ private:
size_t m_minSize;
// Printable expanded version of the complete query, retrieved/set
// from rcldb after the Xapian::setQuery() call
string m_description;
string m_reason;
std::string m_description;
std::string m_reason;
bool m_haveWildCards;
string m_stemlang;
bool expandFileTypes(RclConfig *cfg, vector<string>& exptps);
std::string m_stemlang;
bool expandFileTypes(RclConfig *cfg, std::vector<std::string>& exptps);
/* Copyconst and assignment private and forbidden */
SearchData(const SearchData &) {}
SearchData& operator=(const SearchData&) {return *this;};
@@ -178,39 +174,56 @@ public:
SDCM_ANCHOREND=4};
SearchDataClause(SClType tp)
: m_tp(tp), m_parentSearch(0), m_haveWildCards(0),
m_modifiers(SDCM_NONE), m_weight(1.0)
: m_tp(tp), m_parentSearch(0), m_haveWildCards(0),
m_modifiers(SDCM_NONE), m_weight(1.0)
{}
virtual ~SearchDataClause() {}
virtual bool toNativeQuery(Rcl::Db &db, void *, const string&) = 0;
virtual bool toNativeQuery(Rcl::Db &db, void *, const std::string&) = 0;
bool isFileName() const {return m_tp == SCLT_FILENAME ? true: false;}
virtual string getReason() const {return m_reason;}
virtual bool getTerms(vector<string>&, vector<vector<string> >&,
vector<int>&) const = 0;
virtual void getUTerms(vector<string>&) const = 0;
virtual std::string getReason() const {return m_reason;}
virtual void getTerms(HighlightData & hldata) const = 0;
SClType getTp() {return m_tp;}
void setParent(SearchData *p) {m_parentSearch = p;}
virtual void setModifiers(Modifier mod) {m_modifiers = mod;}
virtual int getModifiers() {return m_modifiers;}
virtual void addModifier(Modifier mod) {
SClType getTp()
{
return m_tp;
}
void setParent(SearchData *p)
{
m_parentSearch = p;
}
virtual void setModifiers(Modifier mod)
{
m_modifiers = mod;
}
virtual int getModifiers()
{
return m_modifiers;
}
virtual void addModifier(Modifier mod)
{
int imod = getModifiers();
imod |= mod;
setModifiers(Modifier(imod));
}
virtual void setWeight(float w) {m_weight = w;}
virtual void setWeight(float w)
{
m_weight = w;
}
friend class SearchData;
protected:
string m_reason;
std::string m_reason;
SClType m_tp;
SearchData *m_parentSearch;
bool m_haveWildCards;
Modifier m_modifiers;
float m_weight;
private:
SearchDataClause(const SearchDataClause&) {}
SearchDataClause& operator=(const SearchDataClause&) {
SearchDataClause(const SearchDataClause&)
{
}
SearchDataClause& operator=(const SearchDataClause&)
{
return *this;
}
};
@@ -221,45 +234,37 @@ private:
*/
class SearchDataClauseSimple : public SearchDataClause {
public:
SearchDataClauseSimple(SClType tp, const string& txt,
const string& fld = string())
: SearchDataClause(tp), m_text(txt), m_field(fld), m_slack(0) {
m_haveWildCards = (txt.find_first_of(cstr_minwilds) != string::npos);
SearchDataClauseSimple(SClType tp, const std::string& txt,
const std::string& fld = std::string())
: SearchDataClause(tp), m_text(txt), m_field(fld)
{
m_haveWildCards =
(txt.find_first_of(cstr_minwilds) != std::string::npos);
}
virtual ~SearchDataClauseSimple() {}
virtual ~SearchDataClauseSimple()
{
}
/** Translate to Xapian query */
virtual bool toNativeQuery(Rcl::Db &db, void *, const string& stemlang);
virtual bool toNativeQuery(Rcl::Db &, void *, const std::string& stemlang);
/** Retrieve query terms and term groups. This is used for highlighting */
virtual bool getTerms(vector<string>& terms, /* Single terms */
vector<vector<string> >& groups, /* Prox grps */
vector<int>& gslks) const /* Prox slacks */
virtual void getTerms(HighlightData& hldata) const
{
terms.insert(terms.end(), m_terms.begin(), m_terms.end());
groups.insert(groups.end(), m_groups.begin(), m_groups.end());
gslks.insert(gslks.end(), m_groups.size(), m_slack);
return true;
hldata.append(m_hldata);
}
virtual void getUTerms(vector<string>& terms) const
virtual const std::string& gettext()
{
terms.insert(terms.end(), m_uterms.begin(), m_uterms.end());
return m_text;
}
virtual const std::string& getfield()
{
return m_field;
}
virtual const string& gettext() {return m_text;}
virtual const string& getfield() {return m_field;}
protected:
string m_text; // Raw user entry text.
string m_field; // Field specification if any
// Single terms and phrases resulting from breaking up m_text;
// valid after toNativeQuery() call
vector<string> m_terms;
vector<vector<string> > m_groups;
// User terms before expansion
vector<string> m_uterms;
// Declare m_slack here. Always 0, but allows getTerms to work for
// SearchDataClauseDist
int m_slack;
std::string m_text; // Raw user entry text.
std::string m_field; // Field specification if any
HighlightData m_hldata;
};
/**
@@ -272,29 +277,39 @@ protected:
*/
class SearchDataClauseFilename : public SearchDataClauseSimple {
public:
SearchDataClauseFilename(const string& txt)
: SearchDataClauseSimple(SCLT_FILENAME, txt) {
SearchDataClauseFilename(const std::string& txt)
: SearchDataClauseSimple(SCLT_FILENAME, txt)
{
// File name searches don't count when looking for wild cards.
m_haveWildCards = false;
}
virtual ~SearchDataClauseFilename() {}
virtual bool toNativeQuery(Rcl::Db &db, void *, const string& stemlang);
virtual ~SearchDataClauseFilename()
{
}
virtual bool toNativeQuery(Rcl::Db &, void *, const std::string& stemlang);
};
/**
* A clause coming from a NEAR or PHRASE entry field. There is only one
* string group, and a specified distance, which applies to it.
* std::string group, and a specified distance, which applies to it.
*/
class SearchDataClauseDist : public SearchDataClauseSimple {
public:
SearchDataClauseDist(SClType tp, const string& txt, int slack,
const string& fld = string())
: SearchDataClauseSimple(tp, txt, fld) {m_slack = slack;}
virtual ~SearchDataClauseDist() {}
SearchDataClauseDist(SClType tp, const std::string& txt, int slack,
const std::string& fld = std::string())
: SearchDataClauseSimple(tp, txt, fld), m_slack(slack)
{
}
virtual bool toNativeQuery(Rcl::Db &db, void *, const string& stemlang);
virtual ~SearchDataClauseDist()
{
}
// m_slack is declared in SearchDataClauseSimple
virtual bool toNativeQuery(Rcl::Db &, void *, const std::string& stemlang);
private:
int m_slack;
};
/** Subquery */
@@ -302,15 +317,28 @@ class SearchDataClauseSub : public SearchDataClause {
public:
// We take charge of the SearchData * and will delete it.
SearchDataClauseSub(SClType tp, RefCntr<SearchData> sub)
: SearchDataClause(tp), m_sub(sub) {}
virtual ~SearchDataClauseSub() {}
virtual bool toNativeQuery(Rcl::Db &db, void *, const string& stemlang);
virtual bool getTerms(vector<string>&, vector<vector<string> >&,
vector<int>&) const;
virtual void getUTerms(vector<string>&) const;
: SearchDataClause(tp), m_sub(sub)
{
}
virtual ~SearchDataClauseSub()
{
}
virtual bool toNativeQuery(Rcl::Db &db, void *p, const std::string&)
{
return m_sub->toNativeQuery(db, p);
}
virtual void getTerms(HighlightData& hldata) const
{
m_sub.getconstptr()->getTerms(hldata);
}
protected:
RefCntr<SearchData> m_sub;
};
} // Namespace Rcl
#endif /* _SEARCHDATA_H_INCLUDED_ */