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 ¤tStart, const QString::const_iterator ¤tPosition) { 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