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