source: trunk/gsdl/src/recpt/querytools.cpp@ 11765

Last change on this file since 11765 was 11765, checked in by kjdon, 18 years ago

made mgpp query parsing better for plain searching. now handles bool operators and NEAR/WITHIN as part of the query. also, plain advanced searching, default operator is now always OR

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 21.5 KB
Line 
1/**********************************************************************
2 *
3 * querytools.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26#include "querytools.h"
27#include <ctype.h>
28#include "unitool.h" // for is_unicode_letdig
29
30// request.filterResultOptions and request.fields (if required) should
31// be set from the calling code
32void set_queryfilter_options (FilterRequest_t &request, const text_t &querystring,
33 cgiargsclass &args) {
34
35 request.filterName = "QueryFilter";
36
37 OptionValue_t option;
38
39 option.name = "Term";
40 option.value = querystring;
41 request.filterOptions.push_back (option);
42
43 option.name = "QueryType";
44 option.value = (args.getintarg("t")) ? "ranked" : "boolean";
45 request.filterOptions.push_back (option);
46
47 option.name = "MatchMode";
48 // mgpp in advanced mode, always use some query
49 if (args.getintarg("ct") !=0 && args.getintarg("b") == 1) {
50 option.value = "some";
51 } else {
52 option.value = (args.getintarg("t")) ? "some" : "all";
53 }
54 request.filterOptions.push_back (option);
55
56 option.name = "Casefold";
57 option.value = (args.getintarg("k")) ? "true" : "false";
58 request.filterOptions.push_back (option);
59
60 option.name = "Stem";
61 option.value = (args.getintarg("s")) ? "true" : "false";
62 request.filterOptions.push_back (option);
63
64 if (!args["h"].empty()) {
65 option.name = "Index";
66 option.value = args["h"];
67 request.filterOptions.push_back (option);
68 }
69
70 if (!args["j"].empty()) {
71 option.name = "Subcollection";
72 option.value = args["j"];
73 request.filterOptions.push_back (option);
74 }
75
76 if (!args["n"].empty()) {
77 option.name = "Language";
78 option.value = args["n"];
79 request.filterOptions.push_back (option);
80 }
81
82 if (!args["g"].empty()) { // granularity for mgpp
83 option.name = "Level";
84 option.value = args["g"];
85 request.filterOptions.push_back (option);
86 }
87
88 set_more_queryfilter_options (request, args);
89}
90
91void set_queryfilter_options (FilterRequest_t &request, const text_t &querystring1,
92 const text_t &querystring2, cgiargsclass &args) {
93
94 set_queryfilter_options (request, querystring1, args);
95
96 // fill in the second query if needed
97 if (!args["cq2"].empty()) {
98 OptionValue_t option;
99
100 option.name = "CombineQuery";
101 option.value = args["cq2"];
102 request.filterOptions.push_back (option);
103
104 option.name = "Term";
105 option.value = querystring2;
106 request.filterOptions.push_back (option);
107
108 option.name = "QueryType";
109 option.value = (args.getintarg("t")) ? "ranked" : "boolean";
110 request.filterOptions.push_back (option);
111
112 option.name = "Casefold";
113 option.value = (args.getintarg("k")) ? "true" : "false";
114 request.filterOptions.push_back (option);
115
116 option.name = "Stem";
117 option.value = (args.getintarg("s")) ? "true" : "false";
118 request.filterOptions.push_back (option);
119
120 if (!args["h2"].empty()) {
121 option.name = "Index";
122 option.value = args["h2"];
123 request.filterOptions.push_back (option);
124 }
125
126 if (!args["j2"].empty()) {
127 option.name = "Subcollection";
128 option.value = args["j2"];
129 request.filterOptions.push_back (option);
130 }
131
132 if (!args["n2"].empty()) {
133 option.name = "Language";
134 option.value = args["n2"];
135 request.filterOptions.push_back (option);
136 }
137 }
138 set_more_queryfilter_options (request, args);
139}
140
141void set_more_queryfilter_options (FilterRequest_t &request, cgiargsclass &args) {
142
143 OptionValue_t option;
144 int arg_m = args.getintarg("m");
145
146 option.name = "Maxdocs";
147 option.value = arg_m;
148 request.filterOptions.push_back (option);
149
150 // option.name = "StartResults";
151 // option.value = args["r"];
152 // request.filterOptions.push_back (option);
153
154 // option.name = "EndResults";
155 // int endresults = args.getintarg("o") + (args.getintarg("r") - 1);
156 // if ((endresults > arg_m) && (arg_m != -1)) endresults = arg_m;
157 // option.value = endresults;
158 // request.filterOptions.push_back (option);
159}
160
161void format_querystring (text_t &querystring, int querymode, bool segment) {
162 text_t formattedstring;
163
164 if (querymode == 1 && !segment) return;
165
166 text_t::const_iterator here = querystring.begin();
167 text_t::const_iterator end = querystring.end();
168
169 // space is used to insert spaces between Chinese
170 // characters. No space is needed before the first
171 // Chinese character.
172 bool space = false;
173
174 // want to remove ()|!& from querystring so boolean queries are just
175 // "all the words" queries (unless querymode is advanced)
176 while (here != end) {
177 if ((querymode == 0) && (*here == '(' || *here == ')' || *here == '|' ||
178 *here == '!' || *here == '&')) {
179 formattedstring.push_back(' ');
180 } else if (segment) {
181 if ((*here >= 0x4e00 && *here <= 0x9fa5) ||
182 (*here >= 0xf900 && *here <= 0xfa2d)) {
183 // Chinese character
184 if (!space) formattedstring.push_back (0x200b); // zero width space
185 formattedstring.push_back (*here);
186 formattedstring.push_back (0x200b);
187 space = true;
188 } else {
189
190 // non-Chinese character
191 formattedstring.push_back (*here);
192 space = false;
193
194 }
195
196 } else {
197 formattedstring.push_back (*here);
198 }
199 ++here;
200 }
201 querystring = formattedstring;
202}
203
204
205
206void add_dates(text_t &querystring, int startdate, int enddate,
207 int startbc, int endbc, int ct)
208{
209 if(startdate)
210 {
211 int querystringis = 0;
212 text_t::const_iterator here = querystring.begin();
213 text_t::const_iterator end = querystring.end();
214 while(here!=end)
215 {
216 if(!(isspace((*here)))){
217 here = end;
218 querystringis = 1;
219 }
220 else
221 ++here;
222 }
223 //converting BCE dates
224 if(startbc && startdate > 0)
225 {
226 startdate *= -1;
227 }
228 if(endbc && enddate > 0)
229 {
230 enddate *= -1;
231 }
232 if(enddate != 0 && enddate<startdate)
233 {
234 cout<<"enddate too small"<<endl;
235 return;
236 }
237 if(querystringis)
238 querystring.appendcstr(" AND");
239 if(!enddate)
240 {
241 if (ct==1) {
242 mgpp_adddateelem(querystring,startdate);
243 }
244 else { // lucene
245 lucene_adddateelem(querystring,startdate);
246 }
247 }
248 else{
249 int nextdate = startdate;
250 querystring.appendcstr(" (");
251 while(nextdate<=enddate)
252 {
253 if(nextdate!=0) {
254 if (ct==1) {
255 mgpp_adddateelem(querystring,nextdate);
256 }
257 else { // lucene
258 lucene_adddateelem(querystring,nextdate);
259 }
260 }
261 ++nextdate;
262 }
263 querystring.appendcstr(" )");
264 }
265 }
266
267}
268
269// search history tool
270// also used for form query macros
271text_t escape_quotes(const text_t &querystring) {
272
273 text_t::const_iterator here = querystring.begin();
274 text_t::const_iterator end = querystring.end();
275
276 text_t escquery = "";
277 while (here != end) {
278 if (*here != '\'' && *here != '\"' && *here != '\n' && *here != '\r') escquery.push_back(*here);
279 else if (*here == '\n' || *here == '\r') {
280 escquery.push_back(' ');
281 } else {
282 escquery +="\\\\";
283 escquery.push_back(*here);
284 }
285
286 ++here;
287 }
288 return escquery;
289
290}
291
292// some query form parsing functions for use with mgpp & lucene
293
294void parse_reg_query_form(text_t &querystring, cgiargsclass &args)
295{
296 querystring.clear();
297
298 const int ct = args.getintarg("ct");
299 int argt = args.getintarg("t");// t=0 -and, t=1 - or
300
301 text_t combine;
302 if (ct==1) {
303 if (argt == 0) combine = "&";
304 else combine = "|";
305 }
306 else { // lucene
307 if (argt == 0) combine = "AND";
308 else combine = "OR";
309 }
310
311 text_t field = args["fqf"];
312 if (field.empty()) return; // no query
313 text_tarray fields;
314 splitchar(field.begin(), field.end(), ',', fields);
315
316 text_t value = args["fqv"];
317 if (value.empty()) return; // somethings wrong
318 text_tarray values;
319 splitchar(value.begin(), value.end(), ',', values);
320
321
322 for (int i=0; i< values.size(); ++i) {
323 if (!values[i].empty()) {
324 if (ct == 1) {
325 mgpp_addqueryelem(querystring, fields[i], values[i], combine);
326 }
327 else { // lucene
328 lucene_addqueryelem(querystring, fields[i], values[i], combine);
329 }
330 }
331 }
332
333}
334
335
336void parse_adv_query_form(text_t &querystring, cgiargsclass &args){
337
338 querystring.clear();
339
340 const int ct = args.getintarg("ct");
341 text_t combine;
342 if (ct==1) {
343 combine = "&";
344 }
345 else { // lucene
346 combine = "AND";
347 }
348
349 text_t field = args["fqf"];
350 if (field.empty()) return; // no query
351 text_tarray fields;
352 splitchar(field.begin(), field.end(), ',', fields);
353
354 text_t value = args["fqv"];
355 if (value.empty()) return; // somethings wrong
356 text_tarray values;
357 splitchar(value.begin(), value.end(), ',', values);
358
359 text_t stem = args["fqs"];
360 if (stem.empty()) return; // somethings wrong
361 text_tarray stems;
362 splitchar(stem.begin(), stem.end(), ',', stems);
363
364 text_t fold = args["fqk"];
365 if (fold.empty()) return; // somethings wrong
366 text_tarray folds;
367 splitchar(fold.begin(), fold.end(), ',', folds);
368
369 text_t comb = args["fqc"];
370 if (comb.empty()) return; //somethings wrong
371 text_tarray combs;
372 splitchar(comb.begin(), comb.end(), ',', combs);
373
374 for(int i=0; i< values.size(); ++i) {
375 if (!values[i].empty()) {
376 if (i!=0) {
377 if (ct==1) {
378 if (combs[i-1]=="and") combine = "&";
379 else if (combs[i-1]=="or")combine = "|";
380 else if (combs[i-1]=="not")combine = "!";
381 }
382 else { // lucene
383 if (combs[i-1]=="and") combine = "AND";
384 else if (combs[i-1]=="or")combine = "OR";
385 else if (combs[i-1]=="not")combine = "NOT";
386 }
387 }
388 text_t term = addstemcase(values[i], stems[i], folds[i]);
389 mgpp_addqueryelem(querystring, fields[i], term, combine);
390 }
391
392 }
393}
394
395text_t addstemcase(const text_t &terms, const text_t &stem, const text_t &fold) {
396
397 text_t outtext;
398 text_t word;
399 //unsigned short c;
400 text_t::const_iterator here = terms.begin();
401 text_t::const_iterator end = terms.end();
402
403 while (here !=end) {
404
405 if (is_unicode_letdig(*here)) {
406 // not word boundary
407 word.push_back(*here);
408 ++here;
409 }
410 else {
411 // found word boundary
412 if (!word.empty() ) {
413 if (stem == "1" || fold =="1") {
414 word += "#";
415 if (stem == "1") word += "s";
416 //else word += "u";
417
418 if (fold == "1") word += "i";
419 //else word += "c";
420 }
421
422 word += " ";
423 outtext += word;
424 word.clear();
425 }
426 if (*here == '\"') {
427 outtext.push_back(*here);
428 }
429 ++here;
430 }
431 }
432
433 // get last word
434 if (!word.empty()) {
435 if (stem == "1"|| fold == "1") {
436 word += "#";
437 if (stem == "1") word += "s";
438 //else word += "u";
439
440 if (fold == "1") word += "i";
441 //else word += "c";
442 }
443 word += " ";
444 outtext += word;
445 }
446 return outtext;
447}
448
449
450void mgpp_adddateelem(text_t& querystring, const int date)
451{
452 querystring.appendcstr(" [");
453 if(date<0) {
454 querystring.appendcstr("bc");
455 querystring.appendint((date*-1));
456 }
457 else {
458 querystring.appendint(date);
459 }
460 querystring.appendcstr("]:CV");
461}
462
463void lucene_adddateelem(text_t& querystring, const int date)
464{
465 querystring.appendcstr(" CV:(");
466 if(date<0) {
467 querystring.appendcstr("bc");
468 querystring.appendint((date*-1));
469 }
470 else {
471 querystring.appendint(date);
472 }
473 querystring.appendcstr(")");
474}
475
476
477void mgpp_addqueryelem(text_t &querystring, text_t &tag,
478 text_t &query, text_t &combine) {
479 if (!querystring.empty()) { // have to put and/or
480 querystring += " " + combine + " ";
481
482 }
483 if (tag=="ZZ" || tag=="") { // just add onto querystring
484 querystring += query;
485 }
486 else {
487 querystring += "["+query+"]:"+tag;
488 }
489
490}
491
492void lucene_addqueryelem(text_t &querystring, text_t &tag,
493 text_t &query, text_t &combine) {
494 if (!querystring.empty()) { // have to put and/or
495 querystring += " " + combine + " ";
496
497 }
498 if (tag=="ZZ" || tag=="") { // just add onto querystring
499 querystring += query;
500 }
501 else {
502 querystring += tag+":("+query+")";
503 }
504}
505
506
507void addqueryelem_ex(text_t &querystring, const text_t &tag,
508 const text_t &terms, const text_t &stem, const text_t &fold,
509 const text_t& combine, const text_t& word_combine) {
510 if (!querystring.empty()) { // have to put and/or
511 querystring += " " + combine + " ";
512 }
513 text_t outtext; outtext.reserve(512);
514 text_t word; word.reserve(100);
515 //unsigned short c;
516 text_t::const_iterator here = terms.begin();
517 text_t::const_iterator end = terms.end();
518 bool inquote = false, firstword = true;
519
520 text_t word2; word2.reserve(256);
521
522 while (here !=end) {
523 if (is_unicode_space(*here)) {
524 if (word2 == "AND") { word2.clear(); word2.push_back(7527); word2.appendcarr("AND", 3); word2.push_back(7527); }
525 else if (word2 == "OR") { word2.clear(); word2.push_back(7527); word2.appendcarr("OR", 2); word2.push_back(7527); }
526 else if (word2 == "NOT") { word2.clear(); word2.push_back(7527); word2.appendcarr("NOT", 3); word2.push_back(7527); }
527 else if (word2 == "NEAR") { word2.clear(); word2.push_back(7527); word2.appendcarr("NEAR", 4); word2.push_back(7527); }
528 else if (word2 == "WITHIN") { word2.clear(); word2.push_back(7527); word2.appendcarr("WITHIN", 6); word2.push_back(7527); }
529 if (inquote) {
530 word2.push_back(*here);
531 }
532 word.append(word2); word2.clear();
533
534 if (!inquote && !word.empty() ) {
535 // found word boundary
536
537 if (stem == "1" || fold =="1") {
538 word += "#";
539 if (stem == "1") word += "s";
540 //else word += "u";
541
542 if (fold == "1") word += "i";
543 //else word += "c";
544 }
545 if (firstword) {
546 firstword = false;
547 } else {
548 outtext += " " + word_combine + " ";
549 }
550 outtext += "[" + word + "]:"+tag;
551 word.clear();
552 }
553 ++here;
554 } else if (*here == '\"') {
555 word2.push_back(*here);
556 inquote = !inquote;
557 ++here;
558 } else {
559 // not word boundary
560 word2.push_back(*here);
561 ++here;
562 }
563 }
564
565 // get last word
566 if (!word2.empty()) {
567 if (word2 == "AND") { word2.clear(); word2.push_back(7527); word2.appendcarr("AND", 3); word2.push_back(7527); }
568 else if (word2 == "OR") { word2.clear(); word2.push_back(7527); word2.appendcarr("OR", 2); word2.push_back(7527); }
569 else if (word2 == "NOT") { word2.clear(); word2.push_back(7527); word2.appendcarr("NOT", 3); word2.push_back(7527); }
570 else if (word2 == "NEAR") { word2.clear(); word2.push_back(7527); word2.appendcarr("NEAR", 4); word2.push_back(7527); }
571 else if (word2 == "WITHIN") { word2.clear(); word2.push_back(7527); word2.appendcarr("WITHIN", 6); word2.push_back(7527); }
572 word.append(word2); word2.clear();
573
574 if (stem == "1"|| fold == "1") {
575 word += "#";
576 if (stem == "1") word += "s";
577 //else word += "u";
578
579 if (fold == "1") word += "i";
580 //else word += "c";
581 }
582 if (!outtext.empty()) outtext += " " + word_combine + " ";
583 outtext += "[" + word + "]:"+tag;
584 }
585 querystring += "(" + outtext + ")";
586}
587
588
589void add_field_info(text_t &querystring, const text_t &tag, int type) {
590
591 if (tag == "") return; // do nothing
592 if (type == 1) { //mgpp
593 querystring = "["+querystring+"]:"+tag;
594 } else if (type == 2) { // lucene
595 querystring = tag+":("+querystring+")";
596 }
597
598}
599
600bool is_special_character(int indexer_type, unsigned short character) {
601 // mgpp
602 if (indexer_type == 1) {
603 return (character == '#' || character == '/' || character == '*');
604 }
605 // lucene
606 else if (indexer_type ==2) {
607 return (character == '?' || character == '*' || character == '~' ||
608 character == '^');
609 }
610 return false;
611}
612
613void format_field_info_lucene(text_t &querystring, cgiargsclass &args) {
614 text_t tag = args["fqf"];
615 if (tag == "ZZ") tag = ""; // ZZ is a special tag meaning no tag (all fields)
616 int type = 2; //lucene
617 int argt = args.getintarg("t");// t=0 -and, t=1 - or
618 int argb = args.getintarg("b"); // b=0 simple, b=1 advanced
619
620 // lucene simple OR - the string stays as is, but may need field tag
621 if (argb==0 && argt == 1) {
622 // just tag the entire thing
623 if (tag != "") {
624 add_field_info(querystring, tag, type);
625 }
626 return;
627 }
628 bool in_phrase = false;
629
630 text_t queryelem = "";
631 text_t finalquery = "";
632
633 // only add in + for simple AND search
634 text_t combine = ((argb==0)? "+" : "");
635
636 // for lucene, we need to change & to && and | to || if advanced search
637 // we need to tag the entire string, if we have a field
638 // if we are simple and search, then we put && in between words
639
640 text_t::const_iterator here = querystring.begin();
641 text_t::const_iterator end = querystring.end();
642 while (here != end) {
643 if (is_unicode_letdig(*here) || is_special_character(type, *here)) {
644 queryelem.push_back(*here);
645 }
646
647 // Detect phrase starts/finishes
648 else if (*here == '"') {
649 queryelem.push_back(*here);
650 if (in_phrase == false) in_phrase = true;
651 else {
652 finalquery += combine + queryelem;
653 queryelem.clear();
654 in_phrase = false;
655 }
656 }
657
658 // Found word boundary, in a phrase
659 else if (in_phrase) {
660 queryelem.push_back(*here);
661 }
662 // Word boundary, but not in a phrase
663 else {
664 if (*here == '&') {
665 queryelem.push_back('&');
666 queryelem.push_back('&');
667 } else if (*here == '|') {
668 queryelem.push_back('|');
669 queryelem.push_back('|');
670 } else {
671 if (!queryelem.empty()) {
672 finalquery += combine + queryelem;
673 queryelem.clear();
674 }
675 finalquery.push_back(*here);
676 }
677 }
678
679 ++here;
680 }
681
682 // Get last element
683 if (!queryelem.empty()) {
684 finalquery += combine + queryelem;
685 }
686
687 add_field_info(finalquery, tag, type);
688 querystring = finalquery;
689 cerr << "final query = "<<finalquery<<endl;
690}
691
692void format_field_info_mgpp(text_t &querystring, cgiargsclass &args) {
693
694 text_t tag = args["fqf"];
695 if (tag == "ZZ") tag = ""; // ZZ is a special tag meaning no tag (all fields)
696
697 int argt = args.getintarg("t");// t=0 -and, t=1 - or
698 int argb = args.getintarg("b"); // b=0 simple, b=1 advanced
699
700 if (tag == "" && argb ==1) {
701 return; // no field specifier, advanced mode, the query stays as written
702 }
703
704 int type = 1; // mgpp
705
706 bool simple_and = (argb==0 && argt==0);
707 text_t finalquery = "";
708 text_t fieldpart ="";
709 text_t queryelem = "";
710 bool in_phrase = false;
711 bool in_field = false;
712
713 text_t::const_iterator here = querystring.begin();
714 text_t::const_iterator end = querystring.end();
715 while (here != end) {
716 if (is_unicode_letdig(*here) || *here == '&' || is_special_character(type, *here)) {
717 queryelem.push_back(*here);
718 }
719 else if (*here == '|') {
720 in_field = false;
721 }
722 else if (*here == '!' || *here == '(' || *here == ')') {
723 if (!in_phrase) { // ignore these if in_phrase
724 // output field, then output operator
725 in_field = false;
726 if (!queryelem.empty()) {
727 if (!simple_and && !fieldpart.empty()) {
728 add_field_info(fieldpart, tag, type);
729 finalquery += fieldpart;
730 finalquery.push_back(' ');
731 fieldpart.clear();
732 }
733 fieldpart += queryelem;
734 }
735 if (!fieldpart.empty()) {
736 add_field_info(fieldpart, tag, type);
737 finalquery += fieldpart;
738 finalquery.push_back(' ');
739 }
740 fieldpart.clear();
741 queryelem.clear();
742 finalquery.push_back(*here);
743 finalquery.push_back(' ');
744 }
745 }
746 else if (*here == '"') {
747 queryelem.push_back(*here);
748 if (in_phrase == false) in_phrase = true;
749 else {
750 in_phrase = false;
751 }
752 }
753
754 // Found word boundary, in a phrase
755 else if (in_phrase) {
756 queryelem.push_back(*here);
757 }
758 // Found a word boundary
759 else {
760 if (!queryelem.empty()) {
761 if (queryelem == "&") {
762 in_field = true;
763 queryelem.clear();
764 }
765 else if (starts_with(queryelem, "NEAR") || starts_with(queryelem, "WITHIN")) {
766
767 if (argb==1) {
768 // simple search, these not allowed
769 in_field = true;
770 fieldpart += queryelem;
771 fieldpart.push_back(' ');
772 }
773 queryelem.clear();
774
775 }
776 else {
777 if (!simple_and && !in_field) {
778 if (!fieldpart.empty()) {
779 add_field_info(fieldpart, tag, type);
780 finalquery += fieldpart;
781 finalquery.push_back(' ');
782 fieldpart.clear();
783 }
784 }
785
786 fieldpart += queryelem;
787 fieldpart.push_back(' ');
788 queryelem.clear();
789 }
790 }
791 }
792 ++here;
793 }
794 // at the end
795 if (!queryelem.empty()) {
796 if (!simple_and && !in_field && !fieldpart.empty()) {
797 add_field_info(fieldpart, tag, type);
798 finalquery += fieldpart;
799 finalquery.push_back(' ');
800 fieldpart.clear();
801 }
802 fieldpart += queryelem;
803 }
804 if (!fieldpart.empty()) {
805 add_field_info(fieldpart, tag, type);
806 finalquery += fieldpart;
807 fieldpart.clear();
808 finalquery.push_back(' ');
809 }
810
811 querystring = finalquery;
812 cerr << "final query = "<<finalquery<<endl;
813}
814
815void format_field_info(text_t &querystring, cgiargsclass &args) {
816 int argct = args.getintarg("ct");
817 if (argct == 1) {
818 format_field_info_mgpp(querystring, args);
819 } else if (argct == 2) {
820 format_field_info_lucene(querystring, args);
821 }
822}
823
Note: See TracBrowser for help on using the repository browser.