From 073cf64a9dfc665f1e1ee2e90517e7b310347e7f Mon Sep 17 00:00:00 2001 From: jsbot Date: Sat, 11 Apr 2015 23:54:05 +0300 Subject: [PATCH] exportsql: issue #242 --- CMakeLists.txt | 3 + src/ExportSqlDialog.cpp | 95 ++++++++++++++++++++++++++++ src/ExportSqlDialog.h | 28 +++++++++ src/ExportSqlDialog.ui | 136 ++++++++++++++++++++++++++++++++++++++++ src/MainWindow.cpp | 18 ++---- src/sqlitedb.cpp | 42 ++++++++++++- src/sqlitedb.h | 4 +- src/src.pro | 9 ++- 8 files changed, 316 insertions(+), 19 deletions(-) create mode 100644 src/ExportSqlDialog.cpp create mode 100644 src/ExportSqlDialog.h create mode 100644 src/ExportSqlDialog.ui diff --git a/CMakeLists.txt b/CMakeLists.txt index a776d4a9..dc8485ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,7 @@ set(SQLB_MOC_HDR src/DbStructureModel.h src/Application.h src/CipherDialog.h + src/ExportSqlDialog.h ) set(SQLB_SRC @@ -83,6 +84,7 @@ set(SQLB_SRC src/main.cpp src/Application.cpp src/CipherDialog.cpp + src/ExportSqlDialog.cpp ) set(SQLB_FORMS @@ -97,6 +99,7 @@ set(SQLB_FORMS src/SqlExecutionArea.ui src/VacuumDialog.ui src/CipherDialog.ui + src/ExportSqlDialog.ui ) set(SQLB_RESOURCES diff --git a/src/ExportSqlDialog.cpp b/src/ExportSqlDialog.cpp new file mode 100644 index 00000000..0c7b041a --- /dev/null +++ b/src/ExportSqlDialog.cpp @@ -0,0 +1,95 @@ +#include "ExportSqlDialog.h" +#include "ui_ExportSqlDialog.h" +#include "sqlitedb.h" +#include "PreferencesDialog.h" +#include "sqlitetablemodel.h" +#include "sqlite.h" + +#include +#include +#include +#include + +static QString sSettingsGroup("exportsql"); +static QString sSettingsInsertColNames("insertcolnames"); +static QString sSettingsInsertMultiply("insertmultiply"); + +ExportSqlDialog::ExportSqlDialog(DBBrowserDB* db, QWidget* parent, const QString& selection) + : QDialog(parent), + ui(new Ui::ExportSqlDialog), + pdb(db) +{ + // Create UI + ui->setupUi(this); + + QSettings settings(QApplication::organizationName(), QApplication::organizationName()); + settings.beginGroup(sSettingsGroup); + ui->checkColNames->setChecked(settings.value(sSettingsInsertColNames, false).toBool()); + ui->checkMultiply->setChecked(settings.value(sSettingsInsertMultiply, false).toBool()); + + // Get list of tables to export + objectMap objects = pdb->getBrowsableObjects(); + for(objectMap::ConstIterator i=objects.begin();i!=objects.end();++i) { + ui->listTables->addItem(new QListWidgetItem(QIcon(QString(":icons/%1").arg(i.value().gettype())), i.value().getname())); + } + + // Sort list of tables and select the table specified in the + // selection parameter or all tables if table not specifed + ui->listTables->model()->sort(0); + if(selection.isEmpty()) + { + for (int i = 0; i < ui->listTables->count(); ++i) + ui->listTables->item(i)->setSelected(true); + } + else + { + QList items = ui->listTables->findItems(selection, Qt::MatchExactly); + ui->listTables->setCurrentItem(items.at(0)); + } + ui->listTables->setFocus(); +} + +ExportSqlDialog::~ExportSqlDialog() +{ + delete ui; +} + +void ExportSqlDialog::accept() +{ + if(ui->listTables->selectedItems().isEmpty()) + { + QMessageBox::warning(this, QApplication::applicationName(), + tr("Please select at least 1 table.")); + return; + } + QString fileName = QFileDialog::getSaveFileName( + this, + tr("Choose a filename to export"), + PreferencesDialog::getSettingsValue("db", "defaultlocation").toString(), + tr("Text files(*.sql *.txt)")); + + if(fileName.isEmpty()) + return; + + // save settings + QSettings settings(QApplication::organizationName(), QApplication::organizationName()); + settings.beginGroup(sSettingsGroup); + settings.setValue(sSettingsInsertColNames, ui->checkColNames->isChecked()); + settings.setValue(sSettingsInsertMultiply, ui->checkMultiply->isChecked()); + settings.endGroup(); + + QStringList tables; + foreach (const QListWidgetItem * item, ui->listTables->selectedItems()) + tables.push_back(item->text()); + + bool dumpOk = pdb->dump(fileName, + tables, + ui->checkColNames->isChecked(), + ui->checkMultiply->isChecked()); + if (dumpOk) + QMessageBox::information(this, QApplication::applicationName(), tr("Export completed.")); + else + QMessageBox::warning(this, QApplication::applicationName(), tr("Export cancelled or failed.")); + + QDialog::accept(); +} diff --git a/src/ExportSqlDialog.h b/src/ExportSqlDialog.h new file mode 100644 index 00000000..51ee6141 --- /dev/null +++ b/src/ExportSqlDialog.h @@ -0,0 +1,28 @@ +#ifndef ExportSqlDialog_H +#define ExportSqlDialog_H + +#include + +class DBBrowserDB; + +namespace Ui { +class ExportSqlDialog; +} + +class ExportSqlDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ExportSqlDialog(DBBrowserDB* db, QWidget* parent = 0, const QString& selection = ""); + ~ExportSqlDialog(); + +private slots: + virtual void accept(); + +private: + Ui::ExportSqlDialog* ui; + DBBrowserDB* pdb; +}; + +#endif diff --git a/src/ExportSqlDialog.ui b/src/ExportSqlDialog.ui new file mode 100644 index 00000000..06752bed --- /dev/null +++ b/src/ExportSqlDialog.ui @@ -0,0 +1,136 @@ + + + ExportSqlDialog + + + + 0 + 0 + 497 + 300 + + + + Export SQL... + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + &Table(s) + + + listTables + + + + + + + QAbstractItemView::MultiSelection + + + false + + + + + + + &Options + + + + + + Keep column names in INSERT INTO + + + true + + + + + + + New INSERT INTO syntax (multiply rows in VALUES) + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + listTables + + + + + buttonBox + accepted() + ExportSqlDialog + accept() + + + 252 + 136 + + + 157 + 140 + + + + + buttonBox + rejected() + ExportSqlDialog + reject() + + + 320 + 136 + + + 286 + 140 + + + + + + showCustomCharEdits() + + diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 186c140e..645c89c3 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -17,6 +17,7 @@ #include "gen_version.h" #include "sqlite.h" #include "CipherDialog.h" +#include "ExportSqlDialog.h" #include #include @@ -897,19 +898,12 @@ void MainWindow::fileRevert() void MainWindow::exportDatabaseToSQL() { - QString fileName = QFileDialog::getSaveFileName( - this, - tr("Choose a filename to export"), - PreferencesDialog::getSettingsValue("db", "defaultlocation").toString(), - tr("Text files(*.sql *.txt)")); + QString current_table; + if(ui->mainTab->currentIndex() == 1) + current_table = ui->comboBrowseTable->currentText(); - if(fileName.size()) - { - if(!db.dump(fileName)) - QMessageBox::warning(this, QApplication::applicationName(), tr("Export cancelled or failed.")); - else - QMessageBox::information(this, QApplication::applicationName(), tr("Export completed.")); - } + ExportSqlDialog dialog(&db, this, current_table); + dialog.exec(); } void MainWindow::importDatabaseFromSQL() diff --git a/src/sqlitedb.cpp b/src/sqlitedb.cpp index 34e72b15..4e17ef38 100644 --- a/src/sqlitedb.cpp +++ b/src/sqlitedb.cpp @@ -372,7 +372,10 @@ bool DBBrowserDB::close() return true; } -bool DBBrowserDB::dump(const QString& filename) +bool DBBrowserDB::dump(const QString& filename, + const QStringList & tablesToDump, + bool insertColNames, + bool insertNewSyntx) { // Open file QFile file(filename); @@ -414,12 +417,19 @@ bool DBBrowserDB::dump(const QString& filename) // Loop through all tables first as they are required to generate views, indices etc. later for(QList::ConstIterator it=tables.begin();it!=tables.end();++it) { + if (tablesToDump.indexOf(it->getTableName()) == -1) + continue; + + // get columns + QStringList cols(tableColumns(it->getTableName())); + // Write the SQL string used to create this table to the output file stream << it->getsql() << ";\n"; QString sQuery = QString("SELECT * FROM `%1`;").arg(it->getTableName()); QByteArray utf8Query = sQuery.toUtf8(); sqlite3_stmt *stmt; + QString lineSep(QString(")%1\n").arg(insertNewSyntx?',':';')); int status = sqlite3_prepare_v2(this->_db, utf8Query.data(), utf8Query.size(), &stmt, NULL); if(SQLITE_OK == status) @@ -429,7 +439,20 @@ bool DBBrowserDB::dump(const QString& filename) qApp->processEvents(); while(sqlite3_step(stmt) == SQLITE_ROW) { - stream << "INSERT INTO `" << it->getTableName() << "` VALUES ("; + if (counter) stream << lineSep; + + if (!insertNewSyntx || !counter) + { + stream << "INSERT INTO `" << it->getTableName() << '`'; + if (insertColNames) + stream << " (" << cols.join(",") << ")"; + stream << " VALUES ("; + } + else + { + stream << " ("; + } + for (int i = 0; i < columns; ++i) { int fieldsize = sqlite3_column_bytes(stmt, i); @@ -466,7 +489,6 @@ bool DBBrowserDB::dump(const QString& filename) if(i != columns - 1) stream << ','; } - stream << ");\n"; progress.setValue(++numRecordsCurrent); if(counter % 5000 == 0) @@ -482,6 +504,7 @@ bool DBBrowserDB::dump(const QString& filename) return false; } } + stream << ");\n"; } sqlite3_finalize(stmt); } @@ -1200,3 +1223,16 @@ bool DBBrowserDB::loadExtension(const QString& filename) return false; } } + +QStringList DBBrowserDB::tableColumns(const QString & tableName) { + QStringList cols; + sqlite3_stmt* stmt = NULL; + QString q(QString("PRAGMA table_info('%1');").arg(tableName)); + int rc = sqlite3_prepare_v2(this->_db, q.toUtf8(), q.toUtf8().length(), &stmt, NULL); + if (rc == SQLITE_OK) { + while (sqlite3_step(stmt) == SQLITE_ROW) + cols.push_back(QString((const char*)sqlite3_column_text(stmt, 1))); + sqlite3_finalize(stmt); + } + return cols; +} diff --git a/src/sqlitedb.h b/src/sqlitedb.h index bf57812c..c54f8d4b 100644 --- a/src/sqlitedb.h +++ b/src/sqlitedb.h @@ -54,10 +54,12 @@ public: bool revert (const QString& pointname = "RESTOREPOINT"); bool saveAll(); bool revertAll(); - bool dump( const QString & filename); + bool dump(const QString & filename, const QStringList &tablesToDump, bool insertColNames, bool insertNew); bool executeSQL ( const QString & statement, bool dirtyDB=true, bool logsql=true); bool executeMultiSQL(const QString& statement, bool dirty = true, bool log = false); + QStringList tableColumns(const QString& tableName); + /** * @brief getRow Executes a sqlite statement to get the rowdata(columns) * for the given rowid. diff --git a/src/src.pro b/src/src.pro index 009ffd05..ef0dc700 100644 --- a/src/src.pro +++ b/src/src.pro @@ -49,7 +49,8 @@ HEADERS += \ DbStructureModel.h \ Application.h \ sqlite.h \ - CipherDialog.h + CipherDialog.h \ + ExportSqlDialog.h SOURCES += \ sqlitedb.cpp \ @@ -74,7 +75,8 @@ SOURCES += \ VacuumDialog.cpp \ DbStructureModel.cpp \ Application.cpp \ - CipherDialog.cpp + CipherDialog.cpp \ + ExportSqlDialog.cpp RESOURCES += icons/icons.qrc \ translations/flags/flags.qrc @@ -90,7 +92,8 @@ FORMS += \ ImportCsvDialog.ui \ SqlExecutionArea.ui \ VacuumDialog.ui \ - CipherDialog.ui + CipherDialog.ui \ + ExportSqlDialog.ui TRANSLATIONS += \ translations/sqlb_zh.ts \