Merge branch 'sqlitebrowser-master'

Signed-off-by: Navdeep Singh Sidhu <deepsidhu1313@users.noreply.github.com>
This commit is contained in:
Navdeep Singh Sidhu
2018-08-10 17:59:36 -05:00
10 changed files with 141 additions and 58 deletions

View File

@@ -1,5 +1,5 @@
project(sqlitebrowser)
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 2.8.12.2)
# BUILD_VERSION is the current date in YYYYMMDD format. It is only
# used by the nightly version to add the date of the build.
@@ -22,6 +22,7 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
add_definitions(-std=c++11)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 2.8.12.2)
set(ANTLR_SRC
src/ANTLRUtil.cpp

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 2.8.12.2)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 2.8.12.2)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 2.8.12.2)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

View File

@@ -1,6 +1,6 @@
#include "AboutDialog.h"
#include "ui_AboutDialog.h"
#include "sqlite.h"
#include "sqlitedb.h"
#include "Application.h"
AboutDialog::AboutDialog(QWidget *parent) :
@@ -11,13 +11,16 @@ AboutDialog::AboutDialog(QWidget *parent) :
this->setFixedSize(this->width(), this->height());
this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
QString sqlite_version, sqlcipher_version;
DBBrowserDB::getSqliteVersion(sqlite_version, sqlcipher_version);
if(sqlcipher_version.isNull())
sqlite_version = tr("SQLite Version ") + sqlite_version;
else
sqlite_version = tr("SQLCipher Version ") + sqlcipher_version + tr(" (based on SQLite %1)").arg(sqlite_version);
ui->label_version->setText(tr("Version ") + Application::versionString() + "\n\n" +
tr("Qt Version ") + QT_VERSION_STR + "\n\n" +
#ifdef ENABLE_SQLCIPHER
tr("SQLCipher Version ") + SQLITE_VERSION
#else
tr("SQLite Version ") + SQLITE_VERSION
#endif
sqlite_version
);
}

View File

@@ -601,33 +601,7 @@ void MainWindow::populateTable()
m_browseTableModel->setTable(tablename, storedData.sortOrderIndex, storedData.sortOrderMode, v);
// There is information stored for this table, so extract it and apply it
// Show rowid column. Needs to be done before the column widths setting because of the workaround in there and before the filter setting
// because of the filter row generation.
showRowidColumn(storedData.showRowid);
// Enable editing in general and (un)lock view editing depending on the settings
unlockViewEditing(!storedData.unlockViewPk.isEmpty(), storedData.unlockViewPk);
// Column hidden status
on_actionShowAllColumns_triggered();
for(auto hiddenIt=storedData.hiddenColumns.constBegin();hiddenIt!=storedData.hiddenColumns.constEnd();++hiddenIt)
hideColumns(hiddenIt.key(), hiddenIt.value());
// Column widths
for(auto widthIt=storedData.columnWidths.constBegin();widthIt!=storedData.columnWidths.constEnd();++widthIt)
ui->dataTable->setColumnWidth(widthIt.key(), widthIt.value());
// Sorting
ui->dataTable->filterHeader()->setSortIndicator(storedData.sortOrderIndex, storedData.sortOrderMode);
// Filters
FilterTableHeader* filterHeader = qobject_cast<FilterTableHeader*>(ui->dataTable->horizontalHeader());
for(auto filterIt=storedData.filterValues.constBegin();filterIt!=storedData.filterValues.constEnd();++filterIt)
filterHeader->setFilter(filterIt.key(), filterIt.value());
// Encoding
m_browseTableModel->setEncoding(storedData.encoding);
applyBrowseTableSettings(storedData);
setRecordsetLabel();
@@ -653,6 +627,39 @@ void MainWindow::populateTable()
QApplication::restoreOverrideCursor();
}
void MainWindow::applyBrowseTableSettings(const BrowseDataTableSettings& storedData, bool skipFilters)
{
// Show rowid column. Needs to be done before the column widths setting because of the workaround in there and before the filter setting
// because of the filter row generation.
showRowidColumn(storedData.showRowid, skipFilters);
// Enable editing in general and (un)lock view editing depending on the settings
unlockViewEditing(!storedData.unlockViewPk.isEmpty(), storedData.unlockViewPk);
// Column hidden status
on_actionShowAllColumns_triggered();
for(auto hiddenIt=storedData.hiddenColumns.constBegin();hiddenIt!=storedData.hiddenColumns.constEnd();++hiddenIt)
hideColumns(hiddenIt.key(), hiddenIt.value());
// Column widths
for(auto widthIt=storedData.columnWidths.constBegin();widthIt!=storedData.columnWidths.constEnd();++widthIt)
ui->dataTable->setColumnWidth(widthIt.key(), widthIt.value());
// Sorting
ui->dataTable->filterHeader()->setSortIndicator(storedData.sortOrderIndex, storedData.sortOrderMode);
// Filters
if(!skipFilters)
{
FilterTableHeader* filterHeader = qobject_cast<FilterTableHeader*>(ui->dataTable->horizontalHeader());
for(auto filterIt=storedData.filterValues.constBegin();filterIt!=storedData.filterValues.constEnd();++filterIt)
filterHeader->setFilter(filterIt.key(), filterIt.value());
}
// Encoding
m_browseTableModel->setEncoding(storedData.encoding);
}
bool MainWindow::fileClose()
{
// Close the database but stop the closing process here if the user pressed the cancel button in there
@@ -1824,9 +1831,8 @@ void MainWindow::browseTableHeaderClicked(int logicalindex)
attachPlot(ui->dataTable, m_browseTableModel, &browseTableSettings[currentlyBrowsedTableName()]);
// This seems to be necessary as a workaround for newer Qt versions. Otherwise the rowid column is always shown after changing the data view.
bool showRowid = browseTableSettings[currentlyBrowsedTableName()].showRowid;
ui->dataTable->setColumnHidden(0, !showRowid);
// Reapply the view settings. This seems to be necessary as a workaround for newer Qt versions.
applyBrowseTableSettings(settings);
}
void MainWindow::resizeEvent(QResizeEvent*)
@@ -2218,7 +2224,16 @@ void MainWindow::on_actionBug_report_triggered()
const QString kernelType = QSysInfo::kernelType();
const QString kernelVersion = QSysInfo::kernelVersion();
const QString arch = QSysInfo::currentCpuArchitecture();
const QString body = QString("\n\n\n\n\n\n\n\n> DB4S v%1 on %2 (%3/%4) [%5]").arg(version, os, kernelType, kernelVersion, arch);
QString sqlite_version, sqlcipher_version;
DBBrowserDB::getSqliteVersion(sqlite_version, sqlcipher_version);
if(sqlcipher_version.isNull())
sqlite_version = QString("SQLite Version ") + sqlite_version;
else
sqlite_version = QString("SQLCipher Version ") + sqlcipher_version + QString(" (based on SQLite %1)").arg(sqlite_version);
const QString body = QString("\n\n\n\n\n\n\n\n> DB4S v%1 on %2 (%3/%4) [%5]\n> using %6\n> and Qt %7")
.arg(version, os, kernelType, kernelVersion, arch, sqlite_version, QT_VERSION_STR);
QUrlQuery query;
query.addQueryItem("labels", "bug");
@@ -2666,12 +2681,12 @@ void MainWindow::fileAttach()
void MainWindow::updateFilter(int column, const QString& value)
{
m_browseTableModel->updateFilter(column, value);
browseTableSettings[currentlyBrowsedTableName()].filterValues[column] = value;
BrowseDataTableSettings& settings = browseTableSettings[currentlyBrowsedTableName()];
settings.filterValues[column] = value;
setRecordsetLabel();
// This seems to be necessary as a workaround for newer Qt versions. Otherwise the rowid column is always shown after changing the data view.
bool showRowid = browseTableSettings[currentlyBrowsedTableName()].showRowid;
ui->dataTable->setColumnHidden(0, !showRowid);
// Reapply the view settings. This seems to be necessary as a workaround for newer Qt versions.
applyBrowseTableSettings(settings, true);
}
void MainWindow::editEncryption()
@@ -2890,7 +2905,7 @@ void MainWindow::editDataColumnDisplayFormat()
}
}
void MainWindow::showRowidColumn(bool show)
void MainWindow::showRowidColumn(bool show, bool skipFilters)
{
// Block all signals from the horizontal header. Otherwise the QHeaderView::sectionResized signal causes us trouble
ui->dataTable->horizontalHeader()->blockSignals(true);
@@ -2915,7 +2930,8 @@ void MainWindow::showRowidColumn(bool show)
browseTableSettings[current_table].showRowid = show;
// Update the filter row
qobject_cast<FilterTableHeader*>(ui->dataTable->horizontalHeader())->generateFilters(m_browseTableModel->columnCount(), show);
if(!skipFilters)
qobject_cast<FilterTableHeader*>(ui->dataTable->horizontalHeader())->generateFilters(m_browseTableModel->columnCount(), show);
// Re-enable signals
ui->dataTable->horizontalHeader()->blockSignals(false);
@@ -3040,11 +3056,11 @@ void MainWindow::unlockViewEditing(bool unlock, QString pk)
ui->actionUnlockViewEditing->blockSignals(false);
// Save settings for this table
browseTableSettings[currentTable].unlockViewPk = pk;
BrowseDataTableSettings& settings = browseTableSettings[currentTable];
settings.unlockViewPk = pk;
// This seems to be necessary as a workaround for newer Qt versions. Otherwise the rowid column is always shown after changing the data view.
bool showRowid = browseTableSettings[currentlyBrowsedTableName()].showRowid;
ui->dataTable->setColumnHidden(0, !showRowid);
// Reapply the view settings. This seems to be necessary as a workaround for newer Qt versions.
applyBrowseTableSettings(settings);
}
sqlb::ObjectIdentifier MainWindow::currentlyBrowsedTableName() const

View File

@@ -193,6 +193,8 @@ private:
StatementType getQueryType(const QString& query) const;
void applyBrowseTableSettings(const BrowseDataTableSettings& storedData, bool skipFilters = false);
protected:
void closeEvent(QCloseEvent *);
void dragEnterEvent(QDragEnterEvent *event);
@@ -277,7 +279,7 @@ private slots:
void showDataColumnPopupMenu(const QPoint& pos);
void showRecordPopupMenu(const QPoint& pos);
void editDataColumnDisplayFormat();
void showRowidColumn(bool show);
void showRowidColumn(bool show, bool skipFilters = false);
void browseDataSetTableEncoding(bool forAllTables = false);
void browseDataSetDefaultTableEncoding();
void fileOpenReadOnly();

View File

@@ -375,6 +375,32 @@ bool DBBrowserDB::tryEncryptionSettings(const QString& filePath, bool* encrypted
}
}
void DBBrowserDB::getSqliteVersion(QString& sqlite, QString& sqlcipher)
{
sqlite = QString(SQLITE_VERSION);
// The SQLCipher version must be queried via a pragma and for a pragma we need a database connection.
// Because we want to be able to query the SQLCipher version without opening a database file first, we
// open a separate connection to an in-memory database here.
sqlcipher = QString();
#ifdef ENABLE_SQLCIPHER
sqlite3* dummy;
if(sqlite3_open(":memory:", &dummy) == SQLITE_OK)
{
sqlite3_stmt* stmt;
if(sqlite3_prepare_v2(dummy, "PRAGMA cipher_version", -1, &stmt, nullptr) == SQLITE_OK)
{
if(sqlite3_step(stmt) == SQLITE_ROW)
sqlcipher = QByteArray(static_cast<const char*>(sqlite3_column_blob(stmt, 0)), sqlite3_column_bytes(stmt, 0));
sqlite3_finalize(stmt);
}
sqlite3_close(dummy);
}
#endif
}
bool DBBrowserDB::setSavepoint(const QString& pointname)
{
if(!isOpen())
@@ -639,11 +665,8 @@ bool DBBrowserDB::dump(const QString& filePath,
it.remove();
} else {
// Otherwise get the number of records in this table
SqliteTableModel m(*this);
m.setQuery(QString("SELECT COUNT(*) FROM %1;")
.arg(sqlb::ObjectIdentifier("main", it.value()->name()).toString()));
if(m.completeCache())
numRecordsTotal += m.data(m.index(0, 0)).toUInt();
numRecordsTotal += querySingeValueFromDb(QString("SELECT COUNT(*) FROM %1;")
.arg(sqlb::ObjectIdentifier("main", it.value()->name()).toString())).toUInt();
}
}
@@ -955,6 +978,37 @@ bool DBBrowserDB::executeMultiSQL(const QString& statement, bool dirty, bool log
return true;
}
QVariant DBBrowserDB::querySingeValueFromDb(const QString& statement, bool log)
{
waitForDbRelease();
if(!_db)
return QVariant();
if(log)
logSQL(statement, kLogMsg_App);
QByteArray utf8Query = statement.toUtf8();
sqlite3_stmt* stmt;
if(sqlite3_prepare_v2(_db, utf8Query, utf8Query.size(), &stmt, nullptr) == SQLITE_OK)
{
if(sqlite3_step(stmt) == SQLITE_ROW)
{
if(sqlite3_column_count(stmt) > 0 && sqlite3_column_type(stmt, 0) != SQLITE_NULL)
{
int bytes = sqlite3_column_bytes(stmt, 0);
if(bytes)
return QByteArray(static_cast<const char*>(sqlite3_column_blob(stmt, 0)), bytes);
else
return "";
}
sqlite3_finalize(stmt);
}
}
return QVariant();
}
bool DBBrowserDB::getRow(const sqlb::ObjectIdentifier& table, const QString& rowid, QVector<QByteArray>& rowdata)
{
waitForDbRelease();

View File

@@ -61,6 +61,9 @@ public:
bool create ( const QString & db);
bool close();
// This returns the SQLite version as well as the SQLCipher if DB4S is compiled with encryption support
static void getSqliteVersion(QString& sqlite, QString& sqlcipher);
typedef std::unique_ptr<sqlite3, DatabaseReleaser> db_pointer_type;
/**
@@ -88,9 +91,13 @@ public:
bool revertToSavepoint(const QString& pointname = "RESTOREPOINT");
bool releaseAllSavepoints();
bool revertAll();
bool dump(const QString& filename, const QStringList& tablesToDump, bool insertColNames, bool insertNew, bool exportSchema, bool exportData, bool keepOldSchema);
bool executeSQL(QString statement, bool dirtyDB = true, bool logsql = true);
bool executeMultiSQL(const QString& statement, bool dirty = true, bool log = false);
QVariant querySingeValueFromDb(const QString& statement, bool log = true);
const QString& lastError() const { return lastErrorMessage; }
/**