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