File indexing completed on 2024-04-28 04:57:42

0001 /*
0002  *   SPDX-FileCopyrightText: 2014-2016 Ivan Cukic <ivan.cukic@kde.org>
0003  *
0004  *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #ifndef COMMON_DATABASE_H
0008 #define COMMON_DATABASE_H
0009 
0010 #include <QSqlQuery>
0011 #include <memory>
0012 #include <utils/d_ptr.h>
0013 
0014 namespace Common
0015 {
0016 
0017 class Database
0018 {
0019 public:
0020     typedef std::shared_ptr<Database> Ptr;
0021 
0022     enum Source { ResourcesDatabase };
0023 
0024     enum OpenMode { ReadWrite, ReadOnly };
0025 
0026     static Ptr instance(Source source, OpenMode openMode);
0027 
0028     QSqlQuery execQueries(const QStringList &queries) const;
0029     QSqlQuery execQuery(const QString &query, bool ignoreErrors = false) const;
0030     QSqlQuery createQuery() const;
0031 
0032     void setPragma(const QString &pragma);
0033     QVariant pragma(const QString &pragma) const;
0034     QVariant value(const QString &query) const;
0035 
0036     // For debugging purposes only
0037     QString lastQuery() const;
0038 
0039     ~Database();
0040     Database();
0041 
0042     friend class Locker;
0043     class Locker
0044     {
0045     public:
0046         explicit Locker(Database &database);
0047         ~Locker();
0048 
0049     private:
0050         QSqlDatabase &m_database;
0051     };
0052 
0053 #define DATABASE_TRANSACTION(A)                                                                                                                                \
0054     /* enable this for debugging only: qDebug() << "Location:" << __FILE__ << __LINE__; */                                                                     \
0055     Common::Database::Locker lock(A)
0056 
0057 private:
0058     D_PTR;
0059 };
0060 
0061 template<typename EscapeFunction>
0062 QString parseStarPattern(const QString &pattern, const QString &joker, EscapeFunction escape)
0063 {
0064     const auto begin = pattern.constBegin();
0065     const auto end = pattern.constEnd();
0066 
0067     auto currentStart = pattern.constBegin();
0068     auto currentPosition = pattern.constBegin();
0069 
0070     bool isEscaped = false;
0071 
0072     // This should be available in the QString class...
0073     auto stringFromIterators = [&](const QString::const_iterator &currentStart, const QString::const_iterator &currentPosition) {
0074         return pattern.mid(std::distance(begin, currentStart), std::distance(currentStart, currentPosition));
0075     };
0076 
0077     // Escaping % and _ for sql like
0078     // auto escape = [] (QString str) {
0079     //     return str.replace("%", "\\%").replace("_", "\\_");
0080     // };
0081 
0082     QString resultPattern;
0083     resultPattern.reserve(pattern.size() * 1.5);
0084 
0085     for (; currentPosition != end; ++currentPosition) {
0086         if (isEscaped) {
0087             // Just skip the current character
0088             isEscaped = false;
0089 
0090         } else if (*currentPosition == '\\') {
0091             // Skip two characters
0092             isEscaped = true;
0093 
0094         } else if (*currentPosition == '*') {
0095             // Replacing the star with the sql like joker - %
0096             resultPattern.append(escape(stringFromIterators(currentStart, currentPosition)) + joker);
0097             currentStart = currentPosition + 1;
0098 
0099         } else {
0100             // This one is boring, nothing to do
0101         }
0102     }
0103 
0104     if (currentStart != currentPosition) {
0105         resultPattern.append(escape(stringFromIterators(currentStart, currentPosition)));
0106     }
0107 
0108     return resultPattern;
0109 }
0110 
0111 inline QString starPatternToLike(const QString &pattern)
0112 {
0113     return parseStarPattern(pattern, QStringLiteral("%"), [](QString str) {
0114         return str.replace(QLatin1String("%"), QLatin1String("\\%")).replace(QLatin1String("_"), QLatin1String("\\_"));
0115     });
0116 }
0117 
0118 } // namespace Common
0119 
0120 #endif // COMMON_DATABASE_H