File indexing completed on 2024-05-12 05:11:21

0001 /*
0002  * This file is part of the KDE Akonadi Search Project
0003  * SPDX-FileCopyrightText: 2013 Vishesh Handa <me@vhanda.in>
0004  *
0005  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006  *
0007  */
0008 
0009 #pragma once
0010 
0011 #include <xapian.h>
0012 
0013 #include "core/searchstore.h"
0014 #include "core/term.h"
0015 #include "search_xapian_export.h"
0016 
0017 #include <QMutexLocker>
0018 
0019 namespace Akonadi
0020 {
0021 namespace Search
0022 {
0023 /**
0024  * Implements a search store using Xapian
0025  */
0026 class AKONADI_SEARCH_XAPIAN_EXPORT XapianSearchStore : public SearchStore
0027 {
0028     Q_OBJECT
0029 public:
0030     explicit XapianSearchStore(QObject *parent = nullptr);
0031     ~XapianSearchStore() override;
0032 
0033     int exec(const Query &query) override;
0034     void close(int queryId) override;
0035     bool next(int queryId) override;
0036 
0037     [[nodiscard]] QByteArray id(int queryId) override;
0038     [[nodiscard]] QUrl url(int queryId) override;
0039 
0040     /**
0041      * Set the path of the xapian database
0042      */
0043     virtual void setDbPath(const QString &path);
0044     virtual QString dbPath();
0045 
0046 protected:
0047     /**
0048      * The derived class should implement the logic for constructing the appropriate
0049      * Xapian::Query class from the given values.
0050      */
0051     virtual Xapian::Query constructQuery(const QString &property, const QVariant &value, Term::Comparator com) = 0;
0052 
0053     virtual Xapian::Query constructFilterQuery(int year, int month, int day);
0054 
0055     /**
0056      * Apply any final touches to the query
0057      */
0058     virtual Xapian::Query finalizeQuery(const Xapian::Query &query);
0059 
0060     /**
0061      * Create a query for any custom options.
0062      */
0063     virtual Xapian::Query applyCustomOptions(const Xapian::Query &q, const QVariantMap &options);
0064 
0065     /**
0066      * Returns the url for the document with id \p docid.
0067      */
0068     virtual QUrl constructUrl(const Xapian::docid &docid) = 0;
0069 
0070     /**
0071      * Gives a list of types which have been provided with the query.
0072      * This must return the appropriate query which will be ANDed with
0073      * the final query
0074      */
0075     virtual Xapian::Query convertTypes(const QStringList &types) = 0;
0076 
0077     /**
0078      * The prefix that should be used when converting an integer
0079      * id to a byte array
0080      */
0081     virtual QByteArray idPrefix() = 0;
0082 
0083     Xapian::Document docForQuery(int queryId);
0084 
0085     /**
0086      * Convenience function to AND two Xapian queries together.
0087      */
0088     Xapian::Query andQuery(const Xapian::Query &a, const Xapian::Query &b);
0089 
0090     Xapian::Database *xapianDb();
0091 
0092 protected:
0093     QRecursiveMutex m_mutex;
0094 
0095 private:
0096     Xapian::Query toXapianQuery(const Term &term);
0097     Xapian::Query toXapianQuery(Xapian::Query::op op, const QList<Term> &terms);
0098 
0099     Xapian::Query constructSearchQuery(const QString &str);
0100 
0101     struct Result {
0102         Xapian::MSet mset;
0103         Xapian::MSetIterator it;
0104 
0105         uint lastId;
0106         QUrl lastUrl;
0107     };
0108 
0109     QHash<int, Result> m_queryMap;
0110     int m_nextId = 1;
0111 
0112     QString m_dbPath;
0113 
0114     Xapian::Database *m_db = nullptr;
0115 };
0116 }
0117 }