|
a/src/rcldb/rclquery.cpp |
|
b/src/rcldb/rclquery.cpp |
1 |
#ifndef lint
|
1 |
#ifndef lint
|
2 |
static char rcsid[] = "@(#$Id: rclquery.cpp,v 1.5 2008-09-05 11:45:16 dockes Exp $ (C) 2008 J.F.Dockes";
|
2 |
static char rcsid[] = "@(#$Id: rclquery.cpp,v 1.6 2008-09-16 08:18:30 dockes Exp $ (C) 2008 J.F.Dockes";
|
3 |
#endif
|
3 |
#endif
|
4 |
|
4 |
|
5 |
#include <stdlib.h>
|
5 |
#include <stdlib.h>
|
6 |
#include <string.h>
|
6 |
#include <string.h>
|
7 |
|
7 |
|
8 |
#include <list>
|
8 |
#include <list>
|
9 |
#include <vector>
|
9 |
#include <vector>
|
|
|
10 |
|
|
|
11 |
#include "xapian/sorter.h"
|
10 |
|
12 |
|
11 |
#include "rcldb.h"
|
13 |
#include "rcldb.h"
|
12 |
#include "rcldb_p.h"
|
14 |
#include "rcldb_p.h"
|
13 |
#include "rclquery.h"
|
15 |
#include "rclquery.h"
|
14 |
#include "rclquery_p.h"
|
16 |
#include "rclquery_p.h"
|
|
... |
|
... |
18 |
#include "searchdata.h"
|
20 |
#include "searchdata.h"
|
19 |
|
21 |
|
20 |
#ifndef NO_NAMESPACES
|
22 |
#ifndef NO_NAMESPACES
|
21 |
namespace Rcl {
|
23 |
namespace Rcl {
|
22 |
#endif
|
24 |
#endif
|
|
|
25 |
|
|
|
26 |
|
23 |
class FilterMatcher : public Xapian::MatchDecider {
|
27 |
class FilterMatcher : public Xapian::MatchDecider {
|
24 |
public:
|
28 |
public:
|
25 |
FilterMatcher(const string &topdir)
|
29 |
FilterMatcher(const string &topdir)
|
26 |
: m_topdir(topdir)
|
30 |
: m_topdir(topdir)
|
27 |
{}
|
31 |
{}
|
|
... |
|
... |
39 |
string data = xdoc.get_data();
|
43 |
string data = xdoc.get_data();
|
40 |
ConfSimple parms(&data);
|
44 |
ConfSimple parms(&data);
|
41 |
|
45 |
|
42 |
// The only filtering for now is on file path (subtree)
|
46 |
// The only filtering for now is on file path (subtree)
|
43 |
string url;
|
47 |
string url;
|
44 |
parms.get(string("url"), url);
|
48 |
parms.get(Doc::keyurl, url);
|
45 |
LOGDEB2(("FilterMatcher topdir [%s] url [%s]\n",
|
49 |
LOGDEB2(("FilterMatcher topdir [%s] url [%s]\n",
|
46 |
m_topdir.c_str(), url.c_str()));
|
50 |
m_topdir.c_str(), url.c_str()));
|
47 |
if (url.find(m_topdir, 7) == 7) {
|
51 |
if (url.find(m_topdir, 7) == 7) {
|
48 |
return true;
|
52 |
return true;
|
49 |
} else {
|
53 |
} else {
|
|
... |
|
... |
53 |
|
57 |
|
54 |
private:
|
58 |
private:
|
55 |
string m_topdir;
|
59 |
string m_topdir;
|
56 |
};
|
60 |
};
|
57 |
|
61 |
|
|
|
62 |
// Sort helper class
|
|
|
63 |
class QSorter : public Xapian::Sorter {
|
|
|
64 |
public:
|
|
|
65 |
QSorter(const string& f) : m_fld(docfToDatf(f) + "=") {}
|
|
|
66 |
|
|
|
67 |
virtual std::string operator()(const Xapian::Document& xdoc) const {
|
|
|
68 |
string data = xdoc.get_data();
|
|
|
69 |
|
|
|
70 |
// It would be simpler to do the record->Rcl::Doc thing, but
|
|
|
71 |
// hand-doing this will be faster. It makes more assumptions
|
|
|
72 |
// about the format than a ConfTree though:
|
|
|
73 |
string::size_type i1, i2;
|
|
|
74 |
i1 = data.find(m_fld);
|
|
|
75 |
if (i1 == string::npos)
|
|
|
76 |
return string();
|
|
|
77 |
i1 += m_fld.length();
|
|
|
78 |
if (i1 >= data.length())
|
|
|
79 |
return string();
|
|
|
80 |
i2 = data.find_first_of("\n\r", i1);
|
|
|
81 |
if (i2 == string::npos)
|
|
|
82 |
return string();
|
|
|
83 |
return data.substr(i1, i2-i1);
|
|
|
84 |
}
|
|
|
85 |
|
|
|
86 |
private:
|
|
|
87 |
string m_fld;
|
|
|
88 |
};
|
|
|
89 |
|
58 |
Query::Query(Db *db)
|
90 |
Query::Query(Db *db)
|
59 |
: m_nq(new Native(this)), m_db(db)
|
91 |
: m_nq(new Native(this)), m_db(db), m_sorter(0)
|
60 |
{
|
92 |
{
|
61 |
}
|
93 |
}
|
62 |
|
94 |
|
63 |
Query::~Query()
|
95 |
Query::~Query()
|
64 |
{
|
96 |
{
|
65 |
deleteZ(m_nq);
|
97 |
deleteZ(m_nq);
|
|
|
98 |
if (m_sorter) {
|
|
|
99 |
delete (QSorter*)m_sorter;
|
|
|
100 |
m_sorter = 0;
|
|
|
101 |
}
|
66 |
}
|
102 |
}
|
67 |
|
103 |
|
68 |
string Query::getReason() const
|
104 |
string Query::getReason() const
|
69 |
{
|
105 |
{
|
70 |
return m_reason;
|
106 |
return m_reason;
|
|
... |
|
... |
72 |
|
108 |
|
73 |
Db *Query::whatDb()
|
109 |
Db *Query::whatDb()
|
74 |
{
|
110 |
{
|
75 |
return m_db;
|
111 |
return m_db;
|
76 |
}
|
112 |
}
|
|
|
113 |
|
77 |
|
114 |
|
78 |
//#define ISNULL(X) (X).isNull()
|
115 |
//#define ISNULL(X) (X).isNull()
|
79 |
#define ISNULL(X) !(X)
|
116 |
#define ISNULL(X) !(X)
|
80 |
|
117 |
|
81 |
// Prepare query out of user search data
|
118 |
// Prepare query out of user search data
|
|
... |
|
... |
112 |
string ermsg;
|
149 |
string ermsg;
|
113 |
string d;
|
150 |
string d;
|
114 |
try {
|
151 |
try {
|
115 |
m_nq->enquire = new Xapian::Enquire(m_db->m_ndb->db);
|
152 |
m_nq->enquire = new Xapian::Enquire(m_db->m_ndb->db);
|
116 |
m_nq->enquire->set_query(m_nq->query);
|
153 |
m_nq->enquire->set_query(m_nq->query);
|
|
|
154 |
if (!sdata->getSortBy().empty()) {
|
|
|
155 |
if (m_sorter) {
|
|
|
156 |
delete (QSorter*)m_sorter;
|
|
|
157 |
m_sorter = 0;
|
|
|
158 |
}
|
|
|
159 |
m_sorter = new QSorter(sdata->getSortBy());
|
|
|
160 |
// It really seems there is a xapian bug about sort order, we
|
|
|
161 |
// invert here.
|
|
|
162 |
m_nq->enquire->set_sort_by_key((QSorter*)m_sorter,
|
|
|
163 |
!sdata->getSortAscending());
|
|
|
164 |
}
|
117 |
m_nq->mset = Xapian::MSet();
|
165 |
m_nq->mset = Xapian::MSet();
|
118 |
// Get the query description and trim the "Xapian::Query"
|
166 |
// Get the query description and trim the "Xapian::Query"
|
119 |
d = m_nq->query.get_description();
|
167 |
d = m_nq->query.get_description();
|
120 |
} XCATCHERROR(ermsg);
|
168 |
} XCATCHERROR(ermsg);
|
121 |
if (!ermsg.empty()) {
|
169 |
if (!ermsg.empty()) {
|