Fixed some indentation issues (and a typo).
[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 private slots:
76   void connectionDestroyed();
77
78 private:
79   void addConnectionToPool();
80
81   int _schemaVersion;
82
83   static int _nextConnectionId;
84   QMutex _connectionPoolMutex;
85   // we let a Connection Object manage each actual db connection
86   // those objects reside in the thread the connection belongs to
87   // which allows us thread safe termination of a connection
88   class Connection;
89   QHash<QThread *, Connection *> _connectionPool;
90 };
91
92 // ========================================
93 //  AbstractSqlStorage::Connection
94 // ========================================
95 class AbstractSqlStorage::Connection : public QObject {
96   Q_OBJECT
97
98 public:
99   Connection(const QString &name, QObject *parent = 0);
100   ~Connection();
101
102   inline QLatin1String name() const { return QLatin1String(_name); }
103
104 private:
105   QByteArray _name;
106 };
107
108
109 // ========================================
110 //  AbstractSqlMigrator
111 // ========================================
112 class AbstractSqlMigrator {
113 public:
114   // migration objects
115   struct QuasselUserMO {
116     UserId id;
117     QString username;
118     QString password;
119   };
120
121   struct SenderMO {
122     int senderId;
123     QString sender;
124     SenderMO() : senderId(0) {}
125   };
126
127   struct IdentityMO {
128     IdentityId id;
129     UserId userid;
130     QString identityname;
131     QString realname;
132     QString awayNick;
133     bool awayNickEnabled;
134     QString awayReason;
135     bool awayReasonEnabled;
136     bool autoAwayEnabled;
137     int autoAwayTime;
138     QString autoAwayReason;
139     bool autoAwayReasonEnabled;
140     bool detachAwayEnabled;
141     QString detachAwayReason;
142     bool detchAwayReasonEnabled;
143     QString ident;
144     QString kickReason;
145     QString partReason;
146     QString quitReason;
147     QByteArray sslCert;
148     QByteArray sslKey;
149   };
150
151   struct IdentityNickMO {
152     int nickid;
153     IdentityId identityId;
154     QString nick;
155   };
156
157   struct NetworkMO {
158     NetworkId networkid;
159     UserId userid;
160     QString networkname;
161     IdentityId identityid;
162     QString encodingcodec;
163     QString decodingcodec;
164     QString servercodec;
165     bool userandomserver;
166     QString perform;
167     bool useautoidentify;
168     QString autoidentifyservice;
169     QString autoidentifypassword;
170     bool useautoreconnect;
171     int autoreconnectinterval;
172     int autoreconnectretries;
173     bool unlimitedconnectretries;
174     bool rejoinchannels;
175     bool connected;
176     QString usermode;
177     QString awaymessage;
178     QString attachperform;
179     QString detachperform;
180   };
181
182   struct BufferMO {
183     BufferId bufferid;
184     UserId userid;
185     int groupid;
186     NetworkId networkid;
187     QString buffername;
188     QString buffercname;
189     int buffertype;
190     int lastseenmsgid;
191     QString key;
192     bool joined;
193   };
194
195   struct BacklogMO {
196     MsgId messageid;
197     QDateTime time; // has to be in UTC!
198     BufferId bufferid;
199     int type;
200     int flags;
201     int senderid;
202     QString message;
203   };
204
205   struct IrcServerMO {
206     int serverid;
207     UserId userid;
208     NetworkId networkid;
209     QString hostname;
210     int port;
211     QString password;
212     bool ssl;
213     int sslversion;
214     bool useproxy;
215     int proxytype;
216     QString proxyhost;
217     int proxyport;
218     QString proxyuser;
219     QString proxypass;
220   };
221
222   struct UserSettingMO {
223     UserId userid;
224     QString settingname;
225     QByteArray settingvalue;
226   };
227
228   enum MigrationObject {
229     QuasselUser,
230     Sender,
231     Identity,
232     IdentityNick,
233     Network,
234     Buffer,
235     Backlog,
236     IrcServer,
237     UserSetting
238   };
239
240   AbstractSqlMigrator();
241   virtual ~AbstractSqlMigrator() {}
242
243   static QString migrationObject(MigrationObject moType);
244
245 protected:
246   void newQuery(const QString &query, QSqlDatabase db);
247   virtual void resetQuery();
248   virtual bool prepareQuery(MigrationObject mo) = 0;
249   bool exec();
250   inline bool next() { return _query->next(); }
251   inline QVariant value(int index) { return _query->value(index); }
252   inline void bindValue(const QString &placeholder, const QVariant &val) { _query->bindValue(placeholder, val); }
253   inline void bindValue(int pos, const QVariant &val) { _query->bindValue(pos, val); }
254
255   inline QSqlError lastError() { return _query ? _query->lastError() : QSqlError(); }
256   void dumpStatus();
257   inline QString executedQuery() { return _query ? _query->executedQuery() : QString(); }
258   inline QVariantList boundValues();
259
260   virtual bool transaction() = 0;
261   virtual void rollback() = 0;
262   virtual bool commit() = 0;
263
264 private:
265   QSqlQuery *_query;
266 };
267
268 class AbstractSqlMigrationReader : public AbstractSqlMigrator {
269 public:
270   AbstractSqlMigrationReader();
271
272   virtual bool readMo(QuasselUserMO &user) = 0;
273   virtual bool readMo(IdentityMO &identity) = 0;
274   virtual bool readMo(IdentityNickMO &identityNick) = 0;
275   virtual bool readMo(NetworkMO &network) = 0;
276   virtual bool readMo(BufferMO &buffer) = 0;
277   virtual bool readMo(SenderMO &sender) = 0;
278   virtual bool readMo(BacklogMO &backlog) = 0;
279   virtual bool readMo(IrcServerMO &ircserver) = 0;
280   virtual bool readMo(UserSettingMO &userSetting) = 0;
281
282   bool migrateTo(AbstractSqlMigrationWriter *writer);
283
284 private:
285   void abortMigration(const QString &errorMsg = QString());
286   bool finalizeMigration();
287
288   template<typename T> bool transferMo(MigrationObject moType, T &mo);
289
290   AbstractSqlMigrationWriter *_writer;
291 };
292
293 class AbstractSqlMigrationWriter : public AbstractSqlMigrator {
294 public:
295   virtual bool writeMo(const QuasselUserMO &user) = 0;
296   virtual bool writeMo(const IdentityMO &identity) = 0;
297   virtual bool writeMo(const IdentityNickMO &identityNick) = 0;
298   virtual bool writeMo(const NetworkMO &network) = 0;
299   virtual bool writeMo(const BufferMO &buffer) = 0;
300   virtual bool writeMo(const SenderMO &sender) = 0;
301   virtual bool writeMo(const BacklogMO &backlog) = 0;
302   virtual bool writeMo(const IrcServerMO &ircserver) = 0;
303   virtual bool writeMo(const UserSettingMO &userSetting) = 0;
304
305   inline bool migrateFrom(AbstractSqlMigrationReader *reader) { return reader->migrateTo(this); }
306
307   // called after migration process
308   virtual inline bool postProcess() { return true; }
309   friend class AbstractSqlMigrationReader;
310 };
311
312 #endif