File indexing completed on 2024-05-05 04:48:33

0001 /****************************************************************************************
0002  * Copyright (c) 2013 Konrad Zemek <konrad.zemek@gmail.com>                             *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #ifndef STATSYNCING_IMPORTER_SQL_CONNECTION_H
0018 #define STATSYNCING_IMPORTER_SQL_CONNECTION_H
0019 
0020 #include <QObject>
0021 
0022 #include "amarok_export.h"
0023 
0024 #include <QList>
0025 #include <QMutex>
0026 #include <QPointer>
0027 #include <QSharedPointer>
0028 #include <QSqlDatabase>
0029 #include <QString>
0030 #include <QVariant>
0031 #include <QVariantList>
0032 #include <QVariantMap>
0033 
0034 namespace StatSyncing
0035 {
0036 
0037 /**
0038  * A helper class encapsulating communication with the database. It guarantees that
0039  * a connection is only used in thread that created it, as per
0040  * http://doc.qt.io/qt-5/threads-modules.html#threads-and-the-sql-module
0041  * This class is very basic, e.g. returns a whole query result as a list of lists,
0042  * so it may not be suitable for more advanced usage.
0043  */
0044 class AMAROK_EXPORT ImporterSqlConnection : public QObject
0045 {
0046     Q_OBJECT
0047 
0048 public:
0049     /**
0050      * Constructor. Creates a new external database connection characterized by parameters
0051      * given. See @see QSqlDatabase class for details.
0052      */
0053     ImporterSqlConnection( const QString &driver, const QString &hostname,
0054                            const quint16 port, const QString &dbName, const QString &user,
0055                            const QString &password );
0056 
0057     /**
0058      * Constructor. Overload for creating a connection to SQLite database.
0059      */
0060     explicit ImporterSqlConnection( const QString &dbPath );
0061 
0062     /**
0063      * Destructor. Removes connection created in the constructor. If a transaction was
0064      * in progress it is rolled back.
0065      */
0066     ~ImporterSqlConnection() override;
0067 
0068     /**
0069      * Executes a query given in QString @p query, first using QSqlQuery::bindValue
0070      * to bind parameters given in @p bindValues. If @p ok is not null the bool
0071      * it points at is set to true if the query was successful and false if error occurred.
0072      * Note that if no transaction is started, the connection is opened for the query and
0073      * then closed again.
0074      * @param query the query
0075      * @param bindValues the bind parameters
0076      * @param ok whether the query was successful
0077      *
0078      * @returns The result of the query.
0079      */
0080     QList<QVariantList> query( const QString &query,
0081                                const QVariantMap &bindValues = QVariantMap(),
0082                                bool* const ok = nullptr );
0083 
0084     /**
0085      * Starts a transaction. Transaction is not started if the underlying driver has no
0086      * support for it. While transaction is started, the connection to the database
0087      * remains open and no other thread can use the ImporterSqlConnection object's api.
0088      */
0089     void transaction();
0090 
0091     /**
0092      * Rolls the transaction back. Nothing happens if the transaction was not started.
0093      * This method must be used from the same thread that called @see transaction() .
0094      */
0095     void rollback();
0096 
0097     /**
0098      * Commits the transaction. Nothing happens if the transaction was not started.
0099      * This method must be used from the same thread that called @see transaction() .
0100      */
0101     void commit();
0102 
0103 protected:
0104     /**
0105      * Constructor. Use this overload if you don't want to create a new connection in
0106      * constructor of a derived class.
0107      */
0108     ImporterSqlConnection();
0109 
0110     /**
0111      * Opens and returns current QSqlDatabase connection. Override this method if you need
0112      * to do something before the connection is used. This method should only be called
0113      * from object's main thread.
0114      */
0115     virtual QSqlDatabase connection();
0116 
0117     /**
0118      * Returns true if transaction is in progress. This method should only be called
0119      * from object's main thread.
0120      */
0121     bool isTransaction() const;
0122 
0123     /**
0124      * Name of the current connection.
0125      */
0126     const QString m_connectionName;
0127 
0128 private:
0129     Q_DISABLE_COPY( ImporterSqlConnection )
0130 
0131     Qt::ConnectionType blockingConnectionType() const;
0132 
0133     QMutex m_apiMutex;
0134     bool m_openTransaction;
0135     QList<QVariantList> m_result;
0136 
0137 private Q_SLOTS:
0138     void slotQuery( const QString &query, const QVariantMap &bindValues, bool* const ok );
0139     void slotTransaction();
0140     void slotRollback();
0141     void slotCommit();
0142 };
0143 
0144 typedef QSharedPointer<ImporterSqlConnection> ImporterSqlConnectionPtr;
0145 
0146 } // namespace StatSyncing
0147 
0148 #endif // STATSYNCING_IMPORTER_SQL_CONNECTION_H