|
a/src/query/wasatorcl.cpp |
|
b/src/query/wasatorcl.cpp |
|
... |
|
... |
62 |
for (it = wasa->m_subs.begin(); it != wasa->m_subs.end(); it++) {
|
62 |
for (it = wasa->m_subs.begin(); it != wasa->m_subs.end(); it++) {
|
63 |
|
63 |
|
64 |
if (!stringicmp("mime", (*it)->m_fieldspec) ||
|
64 |
if (!stringicmp("mime", (*it)->m_fieldspec) ||
|
65 |
!stringicmp("format", (*it)->m_fieldspec)) {
|
65 |
!stringicmp("format", (*it)->m_fieldspec)) {
|
66 |
if ((*it)->m_op == WasaQuery::OP_LEAF) {
|
66 |
if ((*it)->m_op == WasaQuery::OP_LEAF) {
|
67 |
sdata->addFiletype((*it)->m_value);
|
67 |
if ((*it)->m_exclude) {
|
68 |
} else if ((*it)->m_op == WasaQuery::OP_EXCL) {
|
|
|
69 |
sdata->remFiletype((*it)->m_value);
|
68 |
sdata->remFiletype((*it)->m_value);
|
|
|
69 |
} else {
|
|
|
70 |
sdata->addFiletype((*it)->m_value);
|
|
|
71 |
}
|
70 |
} else {
|
72 |
} else {
|
71 |
reason = "internal error: mime clause neither leaf not excl??";
|
73 |
reason = "internal error: mime clause not leaf??";
|
72 |
return 0;
|
74 |
return 0;
|
73 |
}
|
75 |
}
|
74 |
continue;
|
76 |
continue;
|
75 |
}
|
77 |
}
|
76 |
|
78 |
|
77 |
// Xesam uses "type", we also support "rclcat", for broad
|
79 |
// Xesam uses "type", we also support "rclcat", for broad
|
78 |
// categories like "audio", "presentation", etc.
|
80 |
// categories like "audio", "presentation", etc.
|
79 |
if (!stringicmp("rclcat", (*it)->m_fieldspec) ||
|
81 |
if (!stringicmp("rclcat", (*it)->m_fieldspec) ||
|
80 |
!stringicmp("type", (*it)->m_fieldspec)) {
|
82 |
!stringicmp("type", (*it)->m_fieldspec)) {
|
81 |
if ((*it)->m_op != WasaQuery::OP_LEAF &&
|
83 |
if ((*it)->m_op != WasaQuery::OP_LEAF) {
|
82 |
(*it)->m_op != WasaQuery::OP_EXCL) {
|
|
|
83 |
reason = "internal error: rclcat/type clause neither leaf"
|
84 |
reason = "internal error: rclcat/type clause not leaf??";
|
84 |
"nor excl??";
|
|
|
85 |
return 0;
|
85 |
return 0;
|
86 |
}
|
86 |
}
|
87 |
vector<string> mtypes;
|
87 |
vector<string> mtypes;
|
88 |
if (config && config->getMimeCatTypes((*it)->m_value, mtypes)
|
88 |
if (config && config->getMimeCatTypes((*it)->m_value, mtypes)
|
89 |
&& !mtypes.empty()) {
|
89 |
&& !mtypes.empty()) {
|
90 |
for (vector<string>::iterator mit = mtypes.begin();
|
90 |
for (vector<string>::iterator mit = mtypes.begin();
|
91 |
mit != mtypes.end(); mit++) {
|
91 |
mit != mtypes.end(); mit++) {
|
92 |
if ((*it)->m_op == WasaQuery::OP_LEAF)
|
92 |
if ((*it)->m_exclude) {
|
|
|
93 |
sdata->remFiletype(*mit);
|
|
|
94 |
} else {
|
93 |
sdata->addFiletype(*mit);
|
95 |
sdata->addFiletype(*mit);
|
94 |
else
|
96 |
}
|
95 |
sdata->remFiletype(*mit);
|
|
|
96 |
}
|
97 |
}
|
97 |
} else {
|
98 |
} else {
|
98 |
reason = "Unknown rclcat/type value: no mime types found";
|
99 |
reason = "Unknown rclcat/type value: no mime types found";
|
99 |
return 0;
|
100 |
return 0;
|
100 |
}
|
101 |
}
|
101 |
continue;
|
102 |
continue;
|
102 |
}
|
103 |
}
|
103 |
|
|
|
104 |
// Filtering on location
|
|
|
105 |
if (!stringicmp("dir", (*it)->m_fieldspec)) {
|
|
|
106 |
string dir = path_tildexpand((*it)->m_value);
|
|
|
107 |
sdata->addDirSpec(dir, (*it)->m_op == WasaQuery::OP_EXCL,
|
|
|
108 |
(*it)->m_weight);
|
|
|
109 |
continue;
|
|
|
110 |
}
|
|
|
111 |
|
104 |
|
112 |
// Handle "date" spec
|
105 |
// Handle "date" spec
|
113 |
if (!stringicmp("date", (*it)->m_fieldspec)) {
|
106 |
if (!stringicmp("date", (*it)->m_fieldspec)) {
|
114 |
if ((*it)->m_op != WasaQuery::OP_LEAF) {
|
107 |
if ((*it)->m_op != WasaQuery::OP_LEAF) {
|
115 |
reason = "Negative date filtering not supported";
|
108 |
reason = "Negative date filtering not supported";
|
|
... |
|
... |
179 |
reason = "Found bad NULL or AND query type in list";
|
172 |
reason = "Found bad NULL or AND query type in list";
|
180 |
LOGERR(("wasaQueryToRcl: found bad NULL or AND q type in list\n"));
|
173 |
LOGERR(("wasaQueryToRcl: found bad NULL or AND q type in list\n"));
|
181 |
continue;
|
174 |
continue;
|
182 |
|
175 |
|
183 |
case WasaQuery::OP_LEAF: {
|
176 |
case WasaQuery::OP_LEAF: {
|
184 |
LOGDEB0(("wasaQueryToRcl: leaf clause [%s]:[%s] slack %d\n",
|
177 |
LOGDEB0(("wasaQueryToRcl: leaf clause [%s:%s] slack %d excl %d\n",
|
185 |
(*it)->m_fieldspec.c_str(), (*it)->m_value.c_str(),
|
178 |
(*it)->m_fieldspec.c_str(), (*it)->m_value.c_str(),
|
186 |
(*it)->m_slack));
|
179 |
(*it)->m_slack, (*it)->m_exclude));
|
187 |
|
180 |
|
188 |
// Change terms found in the "autosuffs" list into "ext"
|
181 |
// Change terms found in the "autosuffs" list into "ext"
|
189 |
// field queries
|
182 |
// field queries
|
190 |
if ((*it)->m_fieldspec.empty() && !autosuffs.empty()) {
|
183 |
if ((*it)->m_fieldspec.empty() && !autosuffs.empty()) {
|
191 |
vector<string> asfv;
|
184 |
vector<string> asfv;
|
|
... |
|
... |
196 |
(*it)->m_modifiers |= WasaQuery::WQM_NOSTEM;
|
189 |
(*it)->m_modifiers |= WasaQuery::WQM_NOSTEM;
|
197 |
}
|
190 |
}
|
198 |
}
|
191 |
}
|
199 |
}
|
192 |
}
|
200 |
|
193 |
|
201 |
// I'm not sure I understand the phrase/near detection
|
194 |
if (!stringicmp("dir", (*it)->m_fieldspec)) {
|
202 |
// thereafter anymore, maybe it would be better to have an
|
195 |
// dir filtering special case
|
203 |
// explicit flag. Mods can only be set after a double
|
|
|
204 |
// quote.
|
|
|
205 |
if (TextSplit::hasVisibleWhite((*it)->m_value) || mods) {
|
|
|
206 |
Rcl::SClType tp = Rcl::SCLT_PHRASE;
|
|
|
207 |
if (mods & WasaQuery::WQM_PROX) {
|
|
|
208 |
tp = Rcl::SCLT_NEAR;
|
|
|
209 |
}
|
|
|
210 |
nclause = new Rcl::SearchDataClauseDist(tp, (*it)->m_value,
|
196 |
nclause = new Rcl::SearchDataClausePath((*it)->m_value,
|
211 |
(*it)->m_slack,
|
197 |
(*it)->m_exclude);
|
|
|
198 |
} else if ((*it)->m_exclude) {
|
|
|
199 |
if (wasa->m_op != WasaQuery::OP_AND) {
|
|
|
200 |
LOGERR(("wasaQueryToRcl: excl clause inside OR list!\n"));
|
|
|
201 |
continue;
|
|
|
202 |
}
|
|
|
203 |
// Note: have to add dquotes which will be translated to
|
|
|
204 |
// phrase if there are several words in there. Not pretty
|
|
|
205 |
// but should work. If there is actually a single
|
|
|
206 |
// word, it will not be taken as a phrase, and
|
|
|
207 |
// stem-expansion will work normally
|
|
|
208 |
// Have to do this because searchdata has nothing like and_not
|
|
|
209 |
nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_EXCL,
|
|
|
210 |
string("\"") +
|
|
|
211 |
(*it)->m_value + "\"",
|
212 |
(*it)->m_fieldspec);
|
212 |
(*it)->m_fieldspec);
|
213 |
} else {
|
213 |
} else {
|
214 |
nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_AND,
|
214 |
// I'm not sure I understand the phrase/near detection
|
|
|
215 |
// thereafter anymore, maybe it would be better to have an
|
|
|
216 |
// explicit flag. Mods can only be set after a double
|
|
|
217 |
// quote.
|
|
|
218 |
if (TextSplit::hasVisibleWhite((*it)->m_value) || mods) {
|
|
|
219 |
Rcl::SClType tp = Rcl::SCLT_PHRASE;
|
|
|
220 |
if (mods & WasaQuery::WQM_PROX) {
|
|
|
221 |
tp = Rcl::SCLT_NEAR;
|
|
|
222 |
}
|
|
|
223 |
nclause = new Rcl::SearchDataClauseDist(tp, (*it)->m_value,
|
215 |
(*it)->m_value,
|
224 |
(*it)->m_slack,
|
216 |
(*it)->m_fieldspec);
|
225 |
(*it)->m_fieldspec);
|
|
|
226 |
} else {
|
|
|
227 |
nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_AND,
|
|
|
228 |
(*it)->m_value,
|
|
|
229 |
(*it)->m_fieldspec);
|
|
|
230 |
}
|
217 |
}
|
231 |
}
|
|
|
232 |
|
218 |
if (nclause == 0) {
|
233 |
if (nclause == 0) {
|
219 |
reason = "Out of memory";
|
234 |
reason = "Out of memory";
|
220 |
LOGERR(("wasaQueryToRcl: out of memory\n"));
|
235 |
LOGERR(("wasaQueryToRcl: out of memory\n"));
|
221 |
return 0;
|
236 |
return 0;
|
222 |
}
|
237 |
}
|
223 |
}
|
238 |
}
|
224 |
break;
|
239 |
break;
|
225 |
|
240 |
|
226 |
case WasaQuery::OP_EXCL:
|
|
|
227 |
LOGDEB2(("wasaQueryToRcl: excl clause [%s]:[%s]\n",
|
|
|
228 |
(*it)->m_fieldspec.c_str(), (*it)->m_value.c_str()));
|
|
|
229 |
if (wasa->m_op != WasaQuery::OP_AND) {
|
|
|
230 |
LOGERR(("wasaQueryToRcl: negative clause inside OR list!\n"));
|
|
|
231 |
continue;
|
|
|
232 |
}
|
|
|
233 |
// Note: have to add dquotes which will be translated to
|
|
|
234 |
// phrase if there are several words in there. Not pretty
|
|
|
235 |
// but should work. If there is actually a single
|
|
|
236 |
// word, it will not be taken as a phrase, and
|
|
|
237 |
// stem-expansion will work normally
|
|
|
238 |
// Have to do this because searchdata has nothing like and_not
|
|
|
239 |
nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_EXCL,
|
|
|
240 |
string("\"") +
|
|
|
241 |
(*it)->m_value + "\"",
|
|
|
242 |
(*it)->m_fieldspec);
|
|
|
243 |
|
|
|
244 |
if (nclause == 0) {
|
|
|
245 |
reason = "Out of memory";
|
|
|
246 |
LOGERR(("wasaQueryToRcl: out of memory\n"));
|
|
|
247 |
return 0;
|
|
|
248 |
}
|
|
|
249 |
break;
|
|
|
250 |
|
|
|
251 |
case WasaQuery::OP_OR:
|
241 |
case WasaQuery::OP_OR:
|
252 |
LOGDEB2(("wasaQueryToRcl: OR clause [%s]:[%s]\n",
|
242 |
LOGDEB2(("wasaQueryToRcl: OR clause [%s]:[%s]\n",
|
253 |
(*it)->m_fieldspec.c_str(), (*it)->m_value.c_str()));
|
243 |
(*it)->m_fieldspec.c_str(), (*it)->m_value.c_str()));
|
254 |
// Create a subquery.
|
244 |
// Create a subquery.
|
255 |
Rcl::SearchData *sub =
|
245 |
Rcl::SearchData *sub =
|