d0046a9f150eb5037ec34176fa1e2fb8b73ba0fb
[quassel.git] / src / core / abstractsqlstorage.h
1 /***************************************************************************
2  *   Copyright (C) 2005-07 by the Quassel Project                          *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) version 3.                                           *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 #ifndef ABSTRACTSQLSTORAGE_H
22 #define ABSTRACTSQLSTORAGE_H
23
24 #include "storage.h"
25
26 #include <QSqlDatabase>
27 #include <QSqlQuery>
28 #include <QSqlError>
29
30 class AbstractSqlMigrationReader;
31 class AbstractSqlMigrationWriter;
32
33 class AbstractSqlStorage : public Storage {
34   Q_OBJECT
35
36 public:
37   AbstractSqlStorage(QObject *parent = 0);
38   virtual ~AbstractSqlStorage();
39
40   virtual inline AbstractSqlMigrationReader *createMigrationReader() { return 0; }
41   virtual inline AbstractSqlMigrationWriter *createMigrationWriter() { return 0; }
42
43 public slots:
44   virtual State init(const QVariantMap &settings = QVariantMap());
45   virtual bool setup(const QVariantMap &settings = QVariantMap());
46
47 protected:
48   inline virtual void sync() {};
49
50   QSqlDatabase logDb();
51
52   QString queryString(const QString &queryName, int version);
53   inline QString queryString(const QString &queryName) { return queryString(queryName, 0); }
54
55   QStringList setupQueries();
56
57   QStringList upgradeQueries(int ver);
58   bool upgradeDb();
59
60   bool watchQuery(QSqlQuery &query);
61
62   int schemaVersion();
63   virtual int installedSchemaVersion() { return -1; };
64   virtual bool updateSchemaVersion(int newVersion) = 0;
65   virtual bool setupSchemaVersion(int version) = 0;
66
67   virtual void setConnectionProperties(const QVariantMap &properties) = 0;
68   virtual QString driverName() = 0;
69   inline virtual QString hostName() { return QString(); }
70   inline virtual int port() { return -1; }
71   virtual QString databaseName() = 0;
72   inline virtual QString userName() { return QString(); }
73   inline virtual QString password() { return QString(); }
74
75
76   //! Initialize db specific features on connect
77   /** This is called every time a connection to a specific SQL backend is established
78    *  the default implementation does nothing.
79    *
80    *  When reimplementing this method, don't use logDB() inside this function as
81    *  this would cause as we're just about to initialize that DB connection.
82    */
83   inline virtual void initDbSession(QSqlDatabase & /* db */) {}
84
85 private slots:
86   void connectionDestroyed();
87
88 private:
89   void addConnectionToPool();
90
91   int _schemaVersion;
92   bool _debug;
93
94   static int _nextConnectionId;
95   QMutex _connectionPoolMutex;
96   // we let a Connection Object manage each actual db connection
97   // those objects reside in the thread the connection belongs to
98   // which allows us thread safe termination of a connection
99   class Connection;
100   QHash<QThread *, Connection *> _connectionPool;
101 };
102
103 // ========================================
104 //  AbstractSqlStorage::Connection
105 // ========================================
106 class AbstractSqlStorage::Connection : public QObject {
107   Q_OBJECT
108
109 public:
110   Connection(const QString &name, QObject *parent = 0);
111   ~Connection();
112
113   inline QLatin1String name() const { return QLatin1String(_name); }
114
115 private:
116   QByteArray _name;
117 };
118
119
120 // ========================================
121 //  AbstractSqlMigrator
122 // ========================================
123 class AbstractSqlMigrator {
124 public:
125   // migration objects
126   struct QuasselUserMO {
127     UserId id;
128     QString username;
129     QString password;
130   };
131
132   struct SenderMO {
133     int senderId;
134     QString sender;
135     SenderMO() : senderId(0) {}
136   };
137
138   struct IdentityMO {
139     IdentityId id;
140     UserId userid;
141     QString identityname;
142     QString realname;
143     QString awayNick;
144     bool awayNickEnabled;
145     QString awayReason;
146     bool awayReasonEnabled;
147     bool autoAwayEnabled;
148     int autoAwayTime;
149     QString autoAwayReason;
150     bool autoAwayReasonEnabled;
151     bool detachAwayEnabled;
152     QString detachAwayReason;
153     bool detchAwayReasonEnabled;
154     QString ident;
155     QString kickReason;
156     QString partReason;
157     QString quitReason;
158     QByteArray sslCert;
159     QByteArray sslKey;
160   };
161
162   struct IdentityNickMO {
163     int nickid;
164     IdentityId identityId;
165     QString nick;
166   };
167
168   struct NetworkMO {
169     NetworkId networkid;
170     UserId userid;
171     QString networkname;
172     IdentityId identityid;
173     QString encodingcodec;
174     QString decodingcodec;
175     QString servercodec;
176     bool userandomserver;
177     QString perform;
178     bool useautoidentify;
179     QString autoidentifyservice;
180     QString autoidentifypassword;
181     bool useautoreconnect;
182     int autoreconnectinterval;
183     int autoreconnectretries;
184     bool unlimitedconnectretries;
185     bool rejoinchannels;
186     bool connected;
187     QString usermode;
188     QString awaymessage;
189     QString attachperform;
190     QString detachperform;
191     bool usesasl;
192     QString saslaccount;
193     QString saslpassword;
194   };
195
196   struct BufferMO {
197     BufferId bufferid;
198     UserId userid;
199     int groupid;
200     NetworkId networkid;
201     QString buffername;
202     QString buffercname;
203     int buffertype;
204     int lastseenmsgid;
205     int markerlinemsgid;
206     QString key;
207     bool joined;
208   };
209
210   struct BacklogMO {
211     MsgId messageid;
212     QDateTime time; // has to be in UTC!
213     BufferId bufferid;
214     int type;
215     int flags;
216     int senderid;
217     QString message;
218   };
219
220   struct IrcServerMO {
221     int serverid;
222     UserId userid;
223     NetworkId networkid;
224     QString hostname;
225     int port;
226     QString password;
227     bool ssl;
228     int sslversion;
229     bool useproxy;
230     int proxytype;
231     QString proxyhost;
232     int proxyport;
233     QString proxyuser;
234     QString proxypass;
235   };
236
237   struct UserSettingMO {
238     UserId userid;
239     QString settingname;
240     QByteArray settingvalue;
241   };
242
243   enum MigrationObject {
244     QuasselUser,
245     Sender,
246     Identity,
247     IdentityNick,
248     Network,
249     Buffer,
250     Backlog,
251     IrcServer,
252     UserSetting
253   };
254
255   AbstractSqlMigrator();
256   virtual ~AbstractSqlMigrator() {}
257
258   static QString migrationObject(MigrationObject moType);
259
260 protected:
261   void newQuery(const QString &query, QSqlDatabase db);
262   virtual void resetQuery();
263   virtual bool prepareQuery(MigrationObject mo) = 0;
264   bool exec();
265   inline bool next() { return _query->next(); }
266   inline QVariant value(int index) { return _query->value(index); }
267   inline void bindValue(const QString &placeholder, const QVariant &val) { _query->bindValue(placeholder, val); }
268   inline void bindValue(int pos, const QVariant &val) { _query->bindValue(pos, val); }
269
270   inline QSqlError lastError() { return _query ? _query->lastError() : QSqlError(); }
271   void dumpStatus();
272   inline QString executedQuery() { return _query ? _query->executedQuery() : QString(); }
273   inline QVariantList boundValues();
274
275   virtual bool transaction() = 0;
276   virtual void rollback() = 0;
277   virtual bool commit() = 0;
278
279 private:
280   QSqlQuery *_query;
281 };
282
283 class AbstractSqlMigrationReader : public AbstractSqlMigrator {
284 public:
285   AbstractSqlMigrationReader();
286
287   virtual bool readMo(QuasselUserMO &user) = 0;
288   virtual bool readMo(IdentityMO &identity) = 0;
289   virtual bool readMo(IdentityNickMO &identityNick) = 0;
290   virtual bool readMo(NetworkMO &network) = 0;
291   virtual bool readMo(BufferMO &buffer) = 0;
292   virtual bool readMo(SenderMO &sender) = 0;
293   virtual bool readMo(BacklogMO &backlog) = 0;
294   virtual bool readMo(IrcServerMO &ircserver) = 0;
295   virtual bool readMo(UserSettingMO &userSetting) = 0;
296
297   bool migrateTo(AbstractSqlMigrationWriter *writer);
298
299 private:
300   void abortMigration(const QString &errorMsg = QString());
301   bool finalizeMigration();
302
303   template<typename T> bool transferMo(MigrationObject moType, T &mo);
304
305   AbstractSqlMigrationWriter *_writer;
306 };
307
308 class AbstractSqlMigrationWriter : public AbstractSqlMigrator {
309 public:
310   virtual bool writeMo(const QuasselUserMO &user) = 0;
311   virtual bool writeMo(const IdentityMO &identity) = 0;
312   virtual bool writeMo(const IdentityNickMO &identityNick) = 0;
313   virtual bool writeMo(const NetworkMO &network) = 0;
314   virtual bool writeMo(const BufferMO &buffer) = 0;
315   virtual bool writeMo(const SenderMO &sender) = 0;
316   virtual bool writeMo(const BacklogMO &backlog) = 0;
317   virtual bool writeMo(const IrcServerMO &ircserver) = 0;
318   virtual bool writeMo(const UserSettingMO &userSetting) = 0;
319
320   inline bool migrateFrom(AbstractSqlMigrationReader *reader) { return reader->migrateTo(this); }
321
322   // called after migration process
323   virtual inline bool postProcess() { return true; }
324   friend class AbstractSqlMigrationReader;
325 };
326
327 #endif