Throws EmuFrontException.
[emufront] / src / db / dbcreator.cpp
1 // EmuFront
2 // Copyright 2010 Mikko Keinänen
3 //
4 // This file is part of EmuFront.
5 //
6 //
7 // EmuFront is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2 as published by
9 // the Free Software Foundation and appearing in the file gpl.txt included in the
10 // packaging of this file.
11 //
12 // EmuFront is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with EmuFront.  If not, see <http://www.gnu.org/licenses/>.
19
20 #include <QObject>
21 #include <QDir>
22 #include <QSqlDatabase>
23 #include <QSqlQuery>
24 #include <QSqlRecord>
25 #include <QSqlTableModel>
26 #include <QSqlError>
27 #include <QDebug>
28 #include <exception>
29 #include "dbcreator.h"
30 #include "../exceptions/emufrontexception.h"
31
32 using namespace std;
33
34 const int DbCreator::DB_VERSION = 1;
35 //const int DbCreator::TABLES_COUNT = 3;
36 //const QString DbCreator::TABLES[] = {"platform", "mediatype", "filepath", "mediaimagecontainer_filepath", "mediaimage", "mediaimagecontainer_mediaimage"};
37
38 DbCreator::DbCreator(QObject *parent) : QObject(parent)
39 {
40 }
41
42
43 bool DbCreator::createDB()
44 {
45     bool ret = false;
46     QSqlQuery query;
47
48     try
49     {
50
51         /*
52
53             N O T I C E
54             -----------
55
56             When adding a new table, remember to add a drop table
57             clause also!
58
59             When changing the database structure, increase
60             also the version number and create a sql command
61             for updating from last version to new version.
62
63             Update those version upgrade "patches" here as a version history:
64             -----------------------------------------------------------------
65
66         */
67
68         query.exec("DROP TABLE IF EXISTS mediaimagecontainer_mediaimage");
69         query.exec("DROP TABLE IF EXISTS mediaimagecontainer_filepath");
70         query.exec("DROP TABLE IF EXISTS filepath");
71         query.exec("DROP TABLE IF EXISTS setup");
72         query.exec("DROP TABLE IF EXISTS mediatype");
73         query.exec("DROP TABLE IF EXISTS platform");
74         query.exec("DROP TABLE IF EXISTS file") ;
75         query.exec("DROP TABLE IF EXISTS executable");
76         query.exec("DROP TABLE IF EXISTS config");
77
78         qDebug() << "Creating TABLE file";
79
80         ret = query.exec("CREATE TABLE IF NOT EXISTS config"
81                 "(tmpdirpath TEXT, "
82                 "dbversion INTEGER)"
83             );
84
85         if (ret) {
86             query.prepare("INSERT INTO config "
87                 "(tmpdirpath, dbversion) "
88                 "VALUES (:tmpdir, :dbversion)");
89             query.bindValue(":tmpdir", QDir::homePath());
90             query.bindValue(":dbversion", DbCreator::DB_VERSION);
91             ret = query.exec();
92         }
93
94         if (!ret) throw QString("tbl config");
95
96         ret = query.exec("CREATE TABLE IF NOT EXISTS file"
97                         "(id INTEGER PRIMARY KEY, "
98                         "name TEXT, "
99                         "type INTEGER, "
100                         "checksum TEXT, "
101                         "size INTEGER, "
102                         "updatetime NUMERIC, "
103                         "extname TEXT)");
104
105         if (!ret) throw QString("tbl file");
106
107         qDebug() << "Creating TABLE platform";
108
109         ret = query.exec("CREATE TABLE IF NOT EXISTS platform "
110                          "(id INTEGER PRIMARY KEY, "
111                          "name TEXT, "
112                          "fileid INTEGER REFERENCES file(id))");
113
114         if (!ret) throw QString("tbl platform");
115
116         qDebug() << "Creating TABLE mediatype ";
117
118         ret = query.exec("CREATE TABLE IF NOT EXISTS mediatype "
119                          "(id INTEGER PRIMARY KEY, "
120                          "name TEXT, "
121                          "fileid INTEGER REFERENCES file(id))");
122
123         if (!ret) throw QString("tbl mediatype");
124
125         qDebug() << "Creating TABLE setup";
126
127         ret = query.exec("CREATE TABLE IF NOT EXISTS setup "
128                         "(id INTEGER PRIMARY KEY, "
129                         "platformid INTEGER REFERENCES platform(id) ON DELETE CASCADE, "
130                         "mediatypeid INTEGER REFERENCES mediatype(id) ON DELETE CASCADE, "
131                         "filetypeextensions TEXT)");
132
133         if (!ret) throw QString("tbl setup");
134
135         qDebug() << "Creating table executable";
136
137         ret = query.exec("CREATE TABLE IF NOT EXISTS executable "
138                         "(id INTEGER PRIMARY KEY, "
139                         "name TEXT, "
140                         "executable TEXT, "
141                         "options TEXT, "
142                         "type INTEGER, "
143                         "setupid INTEGER REFERENCES setup(id))");
144
145         if (!ret) throw QString("tbl executable");
146
147         qDebug() << "Creating TABLE filepath";
148
149         ret = query.exec("CREATE TABLE IF NOT EXISTS filepath "
150                          "(id INTEGER PRIMARY KEY, "
151                          "name TEXT, "
152                          "filetypeid INTEGER, "
153                          "setupid INTEGER, "
154                          "lastscanned NUMERIC, "
155                          "FOREIGN KEY (setupid) REFERENCES setup(id))");
156
157         if (!ret) throw QString("tbl filepath");
158
159         qDebug() << "Creating TABLE mediaimagecontainer_filepath";
160
161         ret = query.exec("CREATE TABLE IF NOT EXISTS mediaimagecontainer_filepath "
162                         "(fileid INTEGER REFERENCES file(id), "
163                         "filepathid INTEGER REFERENCES filepath(id), "
164                         "updatetime NUMERIC)");
165
166         if (!ret) throw QString("tbl mediaimagecontainer_filepath");
167
168
169         qDebug() << "Creating TABLE mediaimagecontainer_mediaimage";
170
171         ret = query.exec("CREATE TABLE IF NOT EXISTS mediaimagecontainer_mediaimage "
172                         "(mediaimagecontainerid INTEGER REFERENCES file(id), "
173                         "mediaimageid INTEGER REFERENCES file(id))");
174
175         if (!ret) throw QString("tbl mediaimagecontainer_mediaimage");
176
177         query.exec(
178             "CREATE TRIGGER IF NOT EXISTS trg_onplatformdelete "
179             "AFTER DELETE ON platform "
180             "BEGIN "
181             "   DELETE FROM setup WHERE setup.platformid = old.id;"
182             "END;"
183             );
184
185         if (!ret) throw QString("trg_onplatformdelete");
186
187         query.exec(
188             "CREATE TRIGGER IF NOT EXISTS trg_onmediatypedelete "
189             "AFTER DELETE ON mediatype "
190             "BEGIN "
191             "   DELETE FROM setup WHERE setup.mediatypeid = old.id;"
192             "END;"
193             );
194
195         if (!ret) throw QString("trg_onmediatypedelete");
196
197         query.exec(
198             "CREATE TRIGGER IF NOT EXISTS trg_onsetupdelete "
199             "AFTER DELETE ON setup "
200             "BEGIN "
201             "   DELETE FROM filepath WHERE filepath.setupid = old.id; "
202             "   DELETE FROM executable WHERE executable.setupid = old.id; "
203             "END;"
204             );
205
206         if (!ret) throw QString("trg_onsetupdelete");
207
208         query.exec(
209             "CREATE TRIGGER IF NOT EXISTS trg_onfilepathdelete "
210             "AFTER DELETE ON filepath "
211             "BEGIN "
212             "   DELETE FROM mediaimagecontainer_filepath WHERE mediaimagecontainer_filepath.filepathid=old.id; "
213             "END;"
214         );
215
216         if (!ret) throw QString("trg_onfilepathdelete");
217
218         query.exec(
219             "CREATE TRIGGER IF NOT EXISTS trg_onmediaimagecontainerdelete "
220             "AFTER DELETE ON mediaimagecontainer_filepath "
221             "BEGIN "
222             "   DELETE FROM mediaimagecontainer_mediaimage WHERE mediaimagecontainer_mediaimage.mediaimagecontainerid=old.fileid;"
223             "END;"
224         );
225
226         if (!ret) throw QString("trg_onmediaimagecontainerdelete");
227
228         query.exec(
229             "CREATE TRIGGER IF NOT EXISTS trg_onmediaimagecontainer_mediaimagedelete "
230             "AFTER DELETE ON mediaimagecontainer_mediaimage "
231             "BEGIN "
232             "    DELETE FROM file WHERE file.id=old.mediaimageid; "
233             "    DELETE FROM file WHERE file.id=old.mediaimagecontainerid; "
234             "END;"
235         );
236         if (!ret) throw QString("trg_onmediaimagecontainer_mediaimagedelete");
237
238     }
239     catch (QString tbl)
240     {
241         QString err = query.lastError().text();
242         throw EmuFrontException(QString("Couldn't CREATE '%1'!").arg(tbl).append(err));
243     }
244     return ret;
245 }
246
247 /**
248  * Check if database already exists.
249  *
250  * Returns  0 if database doesn't exist
251  *          or database version number 1 if database exists
252  *
253 */
254 int DbCreator::dbExists()
255 {
256     int ret = 0;
257     QString sql("SELECT dbversion FROM config");
258     QSqlQuery q;
259     q.exec(sql);
260     if (q.next()) {
261         ret = q.value(0).toInt();
262         qDebug() << "Database version is " << ret
263             << " the application requires " << DB_VERSION;
264     }
265     return ret;
266     /*for (int i = 0; i < TABLES_COUNT; ++i)
267     {
268         if (!tableExists(TABLES[i]))
269         {
270             qDebug() << "Table " << TABLES[i] << " missing.";
271             return false;
272         }
273        qDebug() << "Table " << TABLES[i] << " exists.";
274     }
275     return true;*/
276 }
277
278 bool DbCreator::tableExists(QString TABLE)
279 {
280     QSqlQuery query;
281     query.exec(QString("SELECT name FROM sqlite_master WHERE name='%1'").arg(TABLE));
282     return query.next();
283 }
284
285 bool DbCreator::deleteDB()
286 {
287     // return QFile::remove(getDbPath());
288     return false;
289 }