9#include "searchstore.h"
14#include "transaction.h"
15#include "enginequery.h"
16#include "termgenerator.h"
17#include "andpostingiterator.h"
18#include "orpostingiterator.h"
22#include <KFileMetaData/PropertyInfo>
23#include <KFileMetaData/TypeInfo>
24#include <KFileMetaData/Types>
37 if (
com == Term::Equal) {
39 auto start =
static_cast<quint32
>(
dt.date().startOfDay().toSecsSinceEpoch());
40 auto end =
static_cast<quint32
>(
dt.date().endOfDay().toSecsSinceEpoch());
44 quint32
timet =
dt.toSecsSinceEpoch();
45 if (
com == Term::LessEqual) {
48 if (
com == Term::Less) {
49 return {0,
timet - 1};
51 if (
com == Term::GreaterEqual) {
52 return {
timet, std::numeric_limits<quint32>::max()};
54 if (
com == Term::Greater) {
55 return {
timet + 1, std::numeric_limits<quint32>::max()};
62struct InternalProperty {
63 const char* propertyName;
67constexpr std::array<InternalProperty, 7> internalProperties{{{
"content",
"",
QMetaType::QString},
77 auto it = std::find_if(std::begin(internalProperties), std::end(internalProperties),
78 [&property] (
const InternalProperty& entry) {
return property == entry.propertyName; });
79 if (
it != std::end(internalProperties)) {
80 return { (*it).prefix, (*it).valueType };
83 if (
pi.property() == KFileMetaData::Property::Empty) {
105 queries << EngineQuery(
arr.left(25), EngineQuery::StartsWith);
107 queries << EngineQuery(
arr);
112 return EngineQuery();
113 }
else if (queries.
size() == 1) {
114 return queries.
first();
116 return EngineQuery(queries);
123 if (
query.op() == EngineQuery::Equal) {
125 query.setOp(EngineQuery::StartsWith);
136 if (
ti == KFileMetaData::Type::Empty) {
137 qCDebug(
BALOO) <<
"Type" << value <<
"does not exist";
138 return EngineQuery();
140 int num =
static_cast<int>(
ti.type());
146SearchStore::SearchStore()
149 m_db = globalDatabaseInstance();
150 if (!m_db->open(Database::ReadOnlyDatabase)) {
155SearchStore::~SearchStore()
160ResultList SearchStore::exec(
const Term& term, uint offset,
int limit,
bool sortResults)
162 if (!m_db || !m_db->isOpen()) {
166 Transaction tr(m_db, Transaction::ReadOnly);
167 std::unique_ptr<PostingIterator>
it(constructQuery(&tr, term));
175 quint64
id =
it->docId();
176 quint32
mtime = tr.documentTimeInfo(
id).mTime;
187 auto compFunc = [](
const std::pair<quint64, quint32>&
lhs,
188 const std::pair<quint64, quint32>&
rhs) {
189 return lhs.second >
rhs.second;
199 results.reserve(end - offset);
200 for (uint
i = offset;
i <
end;
i++) {
204 results.emplace_back(
res);
213 while (offset &&
it->next()) {
218 const quint64
id =
it->docId();
223 results.emplace_back(
res);
232PostingIterator* SearchStore::constructQuery(Transaction* tr,
const Term& term)
236 if (term.operation() == Term::And || term.operation() == Term::Or) {
241 for (
const Term&
t : subTerms) {
242 auto iterator = constructQuery(tr,
t);
246 }
else if (term.operation() == Term::And) {
257 if (term.operation() == Term::And) {
258 return new AndPostingIterator(
vec);
260 return new OrPostingIterator(
vec);
264 if (term.value().isNull()) {
268 Q_ASSERT(term.comparator() != Term::Auto);
271 const QVariant value = term.value();
274 if (property ==
"type" || property ==
"kind") {
276 return tr->postingIterator(q);
278 else if (property ==
"includefolder") {
288 quint64
id = tr->documentId(folder);
290 qCDebug(
BALOO) <<
"Folder" << value.
toString() <<
"not indexed";
294 return tr->docUrlIter(
id);
296 else if (property ==
"modified" || property ==
"mtime") {
302 int year =
ba.
mid(0, 4).toInt();
303 int month =
ba.
mid(4, 2).toInt();
304 int day =
ba.
mid(6, 2).toInt();
309 month = month >= 0 && month <= 12 ? month : 0;
310 day = day >= 0 && day <= 31 ? day : 0;
312 QDate startDate(year, month ? month : 1, day ? day : 1);
313 QDate endDate(startDate);
316 endDate.setDate(endDate.year(), 12, 31);
317 }
else if (day == 0) {
318 endDate.setDate(endDate.year(), endDate.month(), endDate.daysInMonth());
330 Q_ASSERT_X(0,
"SearchStore::constructQuery",
"modified property must contain date/datetime values");
333 }
else if (property ==
"tag") {
334 if (term.comparator() == Term::Equal) {
336 EngineQuery q = EngineQuery(prefix + value.
toByteArray());
337 return tr->postingIterator(q);
338 }
else if (term.comparator() == Term::Contains) {
341 return tr->postingIterator(q);
346 }
else if (property ==
"") {
347 Term
cterm(QStringLiteral(
"content"), term.value(), term.comparator());
348 Term
fterm(QStringLiteral(
"filename"), term.value(), term.comparator());
349 return constructQuery(tr, Term{
cterm, Term::Operation::Or,
fterm});
361 auto com = term.comparator();
365 if (
com == Term::Contains) {
367 return tr->postingIterator(q);
370 if (
com == Term::Equal) {
372 return tr->postingIterator(q);
375 PostingDB::Comparator
pcom;
376 if (
com == Term::Greater ||
com == Term::GreaterEqual) {
377 pcom = PostingDB::GreaterEqual;
378 }
else if (
com == Term::Less ||
com == Term::LessEqual) {
379 pcom = PostingDB::LessEqual;
387 if (term.comparator() == Term::Greater) {
389 }
else if (term.comparator() == Term::Less) {
393 return tr->postingCompIterator(prefix,
intVal,
pcom);
397 return tr->postingCompIterator(prefix,
dVal,
pcom);
402 return tr->postingCompIterator(prefix,
ba,
pcom);
405 qCDebug(
BALOO) <<
"Comparison must be with an integer";
The result class is where all the data extracted by the KFileMetaData extractors is saved to.
Q_SCRIPTABLE Q_NOREPLY void start()
Implements storage for docIds without any associated data Instantiated for:
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
const QList< QKeySequence > & end()
bool isEmpty() const const
QByteArray number(double n, char format, int precision)
bool startsWith(QByteArrayView bv) const const
QByteArray toLower() const const
QDateTime startOfDay() const const
qint64 toSecsSinceEpoch() const const
bool isEmpty() const const
QList< T > mid(qsizetype pos, qsizetype length) const const
void reserve(qsizetype size)
qsizetype size() const const
QString fromUtf8(QByteArrayView str)
bool isEmpty() const const
QByteArray toUtf8() const const
QByteArray toByteArray() const const
QDateTime toDateTime() const const
double toDouble(bool *ok) const const
qlonglong toLongLong(bool *ok) const const
QString toString() const const