source: branches/release-0.3.0-rc1/src/MediaDBLib/dbdump.cpp @ 216

Last change on this file since 216 was 216, checked in by Joachim Langenbach, 11 years ago
  • refs #100
  • MSqlDatabase
    • returns correct table lists
  • DBDump
    • does the dump
    • not working: Export of Blobs
  • DBDumpDialog
    • dialog around DBDump
File size: 8.4 KB
Line 
1/*
2    MediaDB - A media management software
3    Copyright (C) 2010  Joachim Langenbach
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 3 of the License, or
8    (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
17
18*/
19
20#include "config.h"
21
22#include "dbdump.h"
23#include "msqldatabase.h"
24
25#include <QSqlQuery>
26#include <QSqlRecord>
27#include <QSqlError>
28#include <QSettings>
29#include <QDate>
30#include <QDateTime>
31#include <QTextCodec>
32
33#ifdef KDE
34        #include <KFileDialog>
35        #include <KUrl>
36#else
37        #include <QFileDialog>
38#endif
39
40DBDump::DBDump(SetupWizardObject* newObject, QWidget* parent, Qt::WindowFlags flags)
41        : SetupWizardWidget(newObject, parent, flags)
42{
43        codecName = "UTF-8";
44        doAbort = false;
45       
46        setupUi(this);
47        connect(fileButton, SIGNAL(clicked()), this, SLOT(setDumpFile()));
48#if QT_VERSION_MINOR < 6
49        fuleButton->setIcon(QIcon(":/icons/find.png"));
50#else
51        fileButton->setIcon(QIcon::fromTheme("edit-find",
52                                                                                                                                                                 QIcon(":/icons/find.png")));
53#endif
54       
55        // create default file name
56        QSettings settings;
57        QString lastDir = settings.value("lastDumpDir", "").toString();
58        if(!lastDir.isEmpty()){
59                dumpFile.setFile(lastDir +"/"+ settings.value("appNameShort").toString() +"-"+ QDate::currentDate().toString("yyyyMMdd"));
60                fileEdit->setText(dumpFile.absoluteFilePath());
61        }
62}
63
64QString DBDump::mysqlEscape(QString input)
65{
66        input.replace("\\", "\\\\");
67        input.replace("\\x00", "\\\\x00");
68        input.replace("\\n", "\\\\n");
69        input.replace("\\r", "\\\\r");
70        input.replace("\'", "\\\'");
71        input.replace("\"", "\\\"");
72        input.replace("\\x1a", "\\\\x1a");
73        return input;
74}
75
76bool DBDump::finish()
77{
78        logEdit->setPlainText("");
79        doAbort = false;
80        emit exportStarted();
81        actualStep(tr("Opening file"));
82        // create file if needed and open it for writing
83        QFile file(dumpFile.absoluteFilePath());
84        if(!dumpFile.isWritable()){
85                if(dumpFile.exists()){
86                        log(tr("Output file is not writable, please select a writeable file and try again!\n"
87                                                                                "File: %1")
88                                                                                .arg(dumpFile.absoluteFilePath()));
89                        setDumpFile();
90                        emit exportFinished(false);
91                        return false;
92                }
93                else{
94                        // create it
95                        if(!file.open(QFile::WriteOnly)){
96                                log(tr("Output file is not writable, please select a writeable file and try again!\n"
97                                                                                        "File: %1")
98                                                                                        .arg(dumpFile.absoluteFilePath()));
99                                setDumpFile();
100                                emit exportFinished(false);
101                                return false;
102                        }
103                }
104        }
105        if(!file.isOpen()){
106                if(!file.open(QFile::WriteOnly)){
107                        log(tr("Output file is not writable, please select a writeable file and try again!\n"
108                                                                                "File: %1")
109                                                                                .arg(dumpFile.absoluteFilePath()));
110                        setDumpFile();
111                        emit exportFinished(false);
112                        return false;
113                }
114        }
115        QSettings settings;
116        settings.setValue("lastDumpDir", dumpFile.absolutePath());
117       
118        // try to open database
119        MSqlDatabase db = MSqlDatabase::database();
120        bool closeDB = !db.isOpen();
121        if(closeDB){
122                if(!db.open()){
123                        log(tr("Could not connect to Database"));
124                        file.close();
125                        emit exportFinished(false);
126                        return false;
127                }
128        }
129       
130        // configure stream
131        actualStep(tr("Configure file"));
132        QTextStream stream(&file);
133        stream.setCodec(QTextCodec::codecForName(codecName.toAscii()));
134       
135        // write header
136        actualStep(tr("Writing header"));
137        stream << QString("-- %1 %2\n").arg(settings.value("appNameShort").toString()).arg(settings.value("appVersion").toString());
138        stream << QString("-- Host: %1\n").arg(db.hostName());
139        stream << QString("-- Database: %1\n").arg(db.databaseName());
140        stream << QString("-- User: %1\n").arg(db.userName());
141        stream << QString("-- Date: %1\n").arg(QDateTime::currentDateTime().toString(tr("MM/dd/yyyy hh:mm:ss")));
142        stream << QString("-- Codec: %1\n").arg(codecName);
143        stream << QString("-- -----------------------------------------------------------------\n");
144        stream << "\n";
145        stream << "-- Disableing foreignkeychecks during inserts\n";
146        stream << "SET foreign_key_checks = 0;\n";
147        stream << "\n";
148
149        // get list of tables and dump each table
150        actualStep(tr("Dumping tables"));
151        QStringList dbTables = db.tables ( QSql::Tables );
152        setRange(dbTables.size());
153        bool result = true;
154        foreach(QString table, dbTables){
155                QString resString = tr("OK");
156                if(!dumpTable(table, stream)){
157                        result = false;
158                        resString = tr("FAILED");
159                }
160                stream << "\n\n";
161                log(QString("  %1 - %2").arg(table).arg(resString));
162                finishedStep();
163                if(doAbort){
164                        result = false;
165                        break;
166                }
167                QApplication::processEvents();
168        }
169       
170        if(!doAbort){
171                actualStep(tr("Writing footer"));
172                stream << "\n";
173                stream << "-- Enable foreignkeychecks after inserts\n";
174                stream << "SET foreign_key_checks = 1;\n";
175        }
176       
177        if(closeDB)
178                db.close();
179        file.close();
180       
181        if(doAbort){
182                actualStep(tr("Aborted"));
183        }
184        else{
185                if(result){
186                        actualStep(tr("Finished without errors!"));
187                }
188                else{
189                        actualStep(tr("Finished with errors!"));
190                }
191        }
192       
193        emit exportFinished(result);
194        return result;
195}
196
197bool DBDump::saveSettings()
198{
199        return true;
200}
201
202void DBDump::abort()
203{
204        doAbort = true;
205}
206
207void DBDump::setDumpFile()
208{
209  QStringList filters;
210#ifdef KDE
211        QString defaultFilter = QString("*.sql|%1").arg(tr("SQL-Files"));
212#else
213        QString defaultFilter = QString("%1 (*.sql)").arg(tr("SQL-Files"));
214#endif
215filters << defaultFilter;
216#ifdef KDE
217        filters << QString("*.*|%1").arg(tr("All Files"));
218#else
219        filters << QString("%1 (*.*)").arg(tr("All Files"));
220#endif
221       
222       
223        QSettings settings;
224        QString lastDir = dumpFile.absolutePath();
225        if(lastDir.isEmpty()){
226                lastDir = settings.value("lastDumpDir", "").toString();
227        }
228        QString wTitle = tr("Search image");
229#ifdef KDE
230        dumpFile = QFileInfo(KFileDialog::getSaveFileName(KUrl(lastDir), filters.join("\n"), this, wTitle));
231#else
232        dumpFile = QFileInfo(QFileDialog::getSaveFileName(this, wTitle, lastDir, filters.join(";;"), &defaultFilter));
233#endif
234        fileEdit->setText(dumpFile.absoluteFilePath());
235}
236
237bool DBDump::dumpTable(QString table, QTextStream &stream)
238{
239        tableLabel->setText(table +":");
240        QSqlQuery query;
241       
242        // dump create statement
243        query.exec(QString("SHOW CREATE TABLE %1").arg(table));
244        if(!query.first())
245                return false;
246       
247        QString tableCreateStatement = query.record().value("Create Table").toString();
248        if(tableCreateStatement.isEmpty())
249                return false;
250       
251        stream << "--\n";
252        stream << QString("-- Table structure for table `%1`\n").arg(table);
253        stream << "--\n";
254        stream << QString("DROP TABLE IF EXISTS `%1`;\n").arg(table);
255        stream << tableCreateStatement +";";
256        stream << "\n";
257       
258        // dump content
259        query.exec(QString("SELECT * FROM %1").arg(table));
260        if(query.size() < 1){
261                stream << "--\n";
262                stream << QString("-- No data in table `%1`\n").arg(table);
263                stream << "--\n";
264        }
265        else{
266                stream << "--\n";
267                stream << QString("-- Dumping data for table `%1`\n").arg(table);
268                stream << "--\n";
269                stream << QString("LOCK TABLES `%1` WRITE;\n").arg(table);
270       
271                tableProgress->setRange(0, query.size());
272                stream << QString("INSERT INTO `%1` VALUES ").arg(table);
273                bool first = true;
274                while(query.next()){
275                        if(!first)
276                                stream << ",";
277                        if(first)
278                                first = false;
279                        stream << "(";
280                        for(int i = 0; i < query.record().count(); i++){
281                                QVariant field = query.record().value(i);
282                                if(field.type() == QMetaType::QByteArray){
283                                        stream << "'" + mysqlEscape(QString(field.toByteArray())) +"'";
284                                }
285                                else if(field.canConvert(QVariant::Int)){
286                                        stream << field.toString();
287                                }
288                                else{
289                                        stream << "'"+ mysqlEscape(field.toString()) +"'";
290                                }
291                                if(i < query.record().count() - 1)
292                                        stream << ",";
293                        }
294                        stream << ")";
295                        tableProgress->setValue(tableProgress->value() + 1);
296                }
297                stream << ";\n";
298                stream << "UNLOCK TABLES;\n";
299        }
300       
301        tableLabel->setText("");
302        tableProgress->setRange(0,100);
303        tableProgress->setValue(0);
304        return true;
305}
306
307void DBDump::setRange(int num)
308{
309        progressBar->setRange(0, num);
310}
311
312void DBDump::finishedStep()
313{
314        progressBar->setValue ( progressBar->value() + 1 );
315}
316
317void DBDump::actualStep(QString msg)
318{
319        stepLabel->setText(msg);
320        logEdit->appendPlainText(msg);
321}
322
323void DBDump::log(QString msg)
324{
325        logEdit->appendPlainText(msg);
326}
327
328#include "dbdump.moc"
Note: See TracBrowser for help on using the repository browser.