Branch data Line data Source code
1 : : /* omquery.cc: External interface for running queries
2 : : *
3 : : * Copyright 1999,2000,2001 BrightStation PLC
4 : : * Copyright 2001,2002 Ananova Ltd
5 : : * Copyright 2003,2004,2005,2006,2007,2008,2009 Olly Betts
6 : : * Copyright 2006,2007,2008,2009 Lemur Consulting Ltd
7 : : *
8 : : * This program is free software; you can redistribute it and/or
9 : : * modify it under the terms of the GNU General Public License as
10 : : * published by the Free Software Foundation; either version 2 of the
11 : : * License, or (at your option) any later version.
12 : : *
13 : : * This program is distributed in the hope that it will be useful,
14 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : : * GNU General Public License for more details.
17 : : *
18 : : * You should have received a copy of the GNU General Public License
19 : : * along with this program; if not, write to the Free Software
20 : : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
21 : : * USA
22 : : */
23 : :
24 : : #include <config.h>
25 : :
26 : : #include "omqueryinternal.h"
27 : :
28 : : #include "debuglog.h"
29 : : #include "omassert.h"
30 : : #include "utils.h"
31 : :
32 : : #include "xapian/error.h"
33 : : #include "xapian/postingsource.h"
34 : : #include "xapian/registry.h"
35 : : #include "xapian/termiterator.h"
36 : :
37 : : #include <cmath>
38 : :
39 : : namespace Xapian {
40 : :
41 : : /// Add a subquery by reference
42 : : void
43 : 91452 : Query::add_subquery(const Query & subq)
44 : : {
45 : : LOGCALL_VOID(API, "Xapian::Query::add_subquery", subq);
46 : : Assert(internal.get());
47 : 91452 : internal->add_subquery(subq.internal.get());
48 : 91452 : }
49 : :
50 : : /// Add a subquery by pointer
51 : : void
52 : 4 : Query::add_subquery(const Query * subq)
53 : : {
54 : : LOGCALL_VOID(API, "Xapian::Query::add_subquery", subq);
55 [ - + ]: 4 : if (subq == 0) {
56 : 0 : throw InvalidArgumentError("Pointer to subquery may not be null");
57 : : }
58 : : Assert(internal.get());
59 : 4 : internal->add_subquery(subq->internal.get());
60 : 4 : }
61 : :
62 : : /// Add a subquery which is a single term
63 : : void
64 : 1226 : Query::add_subquery(const string & tname)
65 : : {
66 : : LOGCALL_VOID(API, "Xapian::Query::add_subquery", tname);
67 : : Assert(internal.get());
68 : 1226 : Query::Internal subqint(tname);
69 : 1226 : internal->add_subquery(&subqint);
70 : 1226 : }
71 : :
72 : : /// Setup the internals for the query, with the appropriate operator.
73 : : void
74 : 13841 : Query::start_construction(Query::op op_, termcount parameter)
75 : : {
76 : : LOGCALL_VOID(API, "Xapian::Query::start_construction", op_);
77 : : Assert(!internal.get());
78 : 13841 : internal = new Query::Internal(op_, parameter);
79 : 13841 : }
80 : :
81 : : /// Check that query has an appropriate number of arguments, etc,
82 : : void
83 : 31067 : Query::end_construction()
84 : : {
85 : : LOGCALL_VOID(API, "Xapian::Query::end_construction", NO_ARGS);
86 : : Assert(internal.get());
87 : 31067 : internal = internal->end_construction();
88 : 30637 : }
89 : :
90 : : /// Abort construction of the query: delete internal.
91 : : void
92 : 430 : Query::abort_construction()
93 : : {
94 : : LOGCALL_VOID(API, "Xapian::Query::abort_construction", NO_ARGS);
95 : : Assert(internal.get());
96 : 430 : internal = 0;
97 : 430 : }
98 : :
99 : 65876 : Query::Query(const string & tname_, termcount wqf_, termpos pos_)
100 : 65876 : : internal(new Query::Internal(tname_, wqf_, pos_))
101 : : {
102 : : LOGCALL_VOID(API, "Xapian::Query::Query", tname_ | wqf_ | pos_);
103 : 65876 : }
104 : :
105 : 17226 : Query::Query(Query::op op_, const Query &left, const Query &right)
106 : 17226 : : internal(new Query::Internal(op_, 0u))
107 : : {
108 : : LOGCALL_VOID(API, "Xapian::Query::Query", op_ | left | right);
109 : : try {
110 : 17226 : add_subquery(left);
111 : 17226 : add_subquery(right);
112 : 17226 : end_construction();
113 : 8 : } catch (...) {
114 : 4 : abort_construction();
115 : 4 : throw;
116 : : }
117 : 17226 : }
118 : :
119 : 4816 : Query::Query(Query::op op_, Xapian::Query q, double parameter)
120 : : {
121 : : LOGCALL_VOID(API, "Xapian::Query::Query", op_ | q | parameter);
122 [ + - # # ]: 4816 : if (op_ == OP_SCALE_WEIGHT) {
123 [ + + ][ + + ]: 4816 : if (!q.internal.get() ||
[ + + ][ - + ]
[ + + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
124 : : q.internal->op == OP_VALUE_RANGE ||
125 : : q.internal->op == OP_VALUE_GE ||
126 : : q.internal->op == OP_VALUE_LE) {
127 : : // Applying OP_SCALE_WEIGHT to Xapian::Query or OP_VALUE_*
128 : : // has no effect as they're all pure-boolean.
129 : 3761 : internal = q.internal;
130 : 3761 : return;
131 : : }
132 : : }
133 : : try {
134 : 1055 : start_construction(op_, 0);
135 : 1055 : internal->set_dbl_parameter(parameter);
136 : 1055 : add_subquery(q);
137 : 1055 : end_construction();
138 : 832 : } catch (...) {
139 : 416 : abort_construction();
140 : 416 : throw;
141 : : }
142 : 4816 : }
143 : :
144 : 5682 : Query::Query(Query::op op_, Xapian::valueno valno,
145 : : const string &begin, const string &end)
146 : 5682 : : internal(new Query::Internal(op_, valno, begin, end))
147 : : {
148 : : LOGCALL_VOID(API, "Xapian::Query::Query", op_ | valno | begin | end);
149 : 5682 : }
150 : :
151 : 352 : Query::Query(Query::op op_, Xapian::valueno valno, const std::string &value)
152 : 352 : : internal(new Query::Internal(op_, valno, value))
153 : : {
154 : : LOGCALL_VOID(API, "Xapian::Query::Query", op_ | valno | value);
155 : 352 : }
156 : :
157 : 680 : Query::Query(PostingSource * external_source)
158 : 680 : : internal(NULL)
159 : : {
160 : : LOGCALL_VOID(API, "Xapian::Query::Query", external_source);
161 [ + + # # ]: 680 : if (!external_source)
162 : 8 : throw Xapian::InvalidArgumentError("The external_source parameter can not be NULL");
163 : 672 : PostingSource * clone = external_source->clone();
164 [ + + # # ]: 672 : if (clone) {
165 : 664 : internal = new Query::Internal(clone, true);
166 : : } else {
167 : 8 : internal = new Query::Internal(external_source, false);
168 : : }
169 : 680 : }
170 : :
171 : : // Copy constructor
172 : 125134 : Query::Query(const Query & copyme)
173 : 125134 : : internal(copyme.internal)
174 : : {
175 : : LOGCALL_VOID(API, "Xapian::Query::Query", copyme);
176 : 125134 : }
177 : :
178 : : // Assignment
179 : : Query &
180 : 60088 : Query::operator=(const Query & copyme)
181 : : {
182 : : LOGCALL(API, Xapian::Query &, "Xapian::Query::operator=", copyme);
183 : 60088 : internal = copyme.internal;
184 : 60088 : RETURN(*this);
185 : : }
186 : :
187 : : // Default constructor
188 : 45956 : Query::Query() : internal(0)
189 : : {
190 : : LOGCALL_VOID(API, "Xapian::Query::Query", NO_ARGS);
191 : 45956 : }
192 : :
193 : : // Destructor
194 : 278070 : Query::~Query()
195 : : {
196 : : LOGCALL_VOID(API, "Xapian::Query::~Query", NO_ARGS);
197 : 278070 : }
198 : :
199 : : std::string
200 : 10 : Query::serialise() const
201 : : {
202 : : LOGCALL(API, std::string, "Xapian::Query::serialise", NO_ARGS);
203 [ + + ]: 10 : if (!internal.get()) return std::string();
204 : 10 : return internal->serialise();
205 : : }
206 : :
207 : : Query
208 : 7 : Query::unserialise(const std::string &s)
209 : : {
210 : : LOGCALL_STATIC(API, Xapian::Query, "Xapian::Query::unserialise", s);
211 : 7 : Query result;
212 [ + + ]: 7 : if (!s.empty()) {
213 : 8 : result.internal = Xapian::Query::Internal::unserialise(s, Registry());
214 : : }
215 : 1 : RETURN(result);
216 : : }
217 : :
218 : : Query
219 : 5 : Query::unserialise(const std::string & s, const Registry & reg)
220 : : {
221 : : LOGCALL_STATIC(API, Xapian::Query, "Xapian::Query::unserialise", s | reg);
222 : 5 : Query result;
223 [ + - ]: 5 : if (!s.empty()) {
224 : 5 : result.internal = Xapian::Query::Internal::unserialise(s, reg);
225 : : }
226 : 1 : RETURN(result);
227 : : }
228 : :
229 : : std::string
230 : 2095 : Query::get_description() const
231 : : {
232 : 2095 : std::string res("Xapian::Query(");
233 [ + + ]: 2095 : if (internal.get()) res += internal->get_description();
234 : 2095 : res += ")";
235 : 0 : return res;
236 : : }
237 : :
238 : 10516 : termcount Query::get_length() const
239 : : {
240 : : LOGCALL(API, Xapian::termcount, "Xapian::Query::get_length", NO_ARGS);
241 [ + + ]: 10516 : RETURN(internal.get() ? internal->get_length() : 0);
242 : : }
243 : :
244 : 190 : TermIterator Query::get_terms_begin() const
245 : : {
246 : : LOGCALL(API, Xapian::TermIterator, "Xapian::Query::get_terms_begin", NO_ARGS);
247 [ + + ]: 190 : if (!internal.get()) RETURN(TermIterator(NULL));
248 : 190 : RETURN(internal->get_terms());
249 : : }
250 : :
251 : : bool
252 : 354 : Query::empty() const
253 : : {
254 : : LOGCALL_VOID(API, "Xapian::Query::empty", NO_ARGS);
255 : 354 : return internal.get() == 0;
256 : : }
257 : :
258 : 17 : Query::Query(Query::op op_, const std::string & left, const std::string & right)
259 : 17 : : internal(0)
260 : : {
261 : : try {
262 : 17 : start_construction(op_, 0);
263 : 17 : add_subquery(left);
264 : 17 : add_subquery(right);
265 : 17 : end_construction();
266 : 0 : } catch (...) {
267 : 0 : abort_construction();
268 : 0 : throw;
269 : : }
270 : 17 : }
271 : :
272 : : /* Define static members. */
273 : 2335 : const Xapian::Query Xapian::Query::MatchAll = Xapian::Query(string());
274 : 2335 : const Xapian::Query Xapian::Query::MatchNothing = Xapian::Query();
275 : :
276 [ + - ][ + - ]: 7005 : }
|