Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better multithreading code #1394

Merged
merged 4 commits into from Jun 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Expand Up @@ -117,6 +117,8 @@ set(SQLB_MOC_HDR
src/SqlExecutionArea.h
src/VacuumDialog.h
src/sqlitetablemodel.h
src/RowLoader.h
src/RowCache.h
src/sqltextedit.h
src/docktextedit.h
src/DbStructureModel.h
Expand Down Expand Up @@ -154,6 +156,7 @@ set(SQLB_SRC
src/VacuumDialog.cpp
src/sqlitedb.cpp
src/sqlitetablemodel.cpp
src/RowLoader.cpp
src/sqlitetypes.cpp
src/sqltextedit.cpp
src/docktextedit.cpp
Expand Down Expand Up @@ -287,6 +290,8 @@ if(WIN32)
ELSE( MINGW )
set(SQLB_SRC ${SQLB_SRC} "${CMAKE_CURRENT_SOURCE_DIR}/src/winapp.rc")
ENDIF( MINGW )
else()
set(LPTHREAD pthread)
endif(WIN32)

#enable version check for MacOS
Expand Down Expand Up @@ -371,6 +376,7 @@ endif()
target_link_libraries(${PROJECT_NAME}
qhexedit
qcustomplot
${LPTHREAD}
${QT_LIBRARIES}
${WIN32_STATIC_LINK}
${LIBSQLITE}
Expand Down
20 changes: 12 additions & 8 deletions src/DbStructureModel.cpp
Expand Up @@ -219,15 +219,19 @@ QMimeData* DbStructureModel::mimeData(const QModelIndexList& indices) const
sqlb::ObjectIdentifier objid(data(index.sibling(index.row(), ColumnSchema), Qt::DisplayRole).toString(),
data(index.sibling(index.row(), ColumnName), Qt::DisplayRole).toString());
tableModel.setTable(objid);
tableModel.waitForFetchingFinished();
for(int i=0; i < tableModel.rowCount(); ++i)
if(tableModel.completeCache())
{
QString insertStatement = "INSERT INTO " + objid.toString() + " VALUES(";
for(int j=1; j < tableModel.columnCount(); ++j)
insertStatement += QString("'%1',").arg(tableModel.data(tableModel.index(i, j), Qt::EditRole).toString());
insertStatement.chop(1);
insertStatement += ");\n";
sqlData.append(insertStatement);
// Only continue if all data was fetched

for(int i=0; i < tableModel.rowCount(); ++i)
{
QString insertStatement = "INSERT INTO " + objid.toString() + " VALUES(";
for(int j=1; j < tableModel.columnCount(); ++j)
insertStatement += QString("'%1',").arg(tableModel.data(tableModel.index(i, j), Qt::EditRole).toString());
insertStatement.chop(1);
insertStatement += ");\n";
sqlData.append(insertStatement);
}
}
}
}
Expand Down
28 changes: 24 additions & 4 deletions src/EditTableDialog.cpp
Expand Up @@ -388,7 +388,12 @@ void EditTableDialog::itemChanged(QTreeWidgetItem *item, int column)
.arg(sqlb::escapeIdentifier(pdb.getObjectByName(curTable).dynamicCast<sqlb::Table>()->rowidColumn()))
.arg(curTable.toString())
.arg(sqlb::escapeIdentifier(field->name())));
m.waitForFetchingFinished();
if(!m.completeCache())
{
// If we couldn't load all data because the cancel button was clicked, just unset the checkbox again and stop.
item->setCheckState(column, Qt::Unchecked);
return;
}
if(m.data(m.index(0, 0)).toInt() > 0)
{
// There is a NULL value, so print an error message, uncheck the combobox, and return here
Expand Down Expand Up @@ -416,7 +421,12 @@ void EditTableDialog::itemChanged(QTreeWidgetItem *item, int column)
.arg(curTable.toString())
.arg(sqlb::escapeIdentifier(field->name()))
.arg(sqlb::escapeIdentifier(field->name())));
m.waitForFetchingFinished();
if(!m.completeCache())
{
// If we couldn't load all data because the cancel button was clicked, just unset the checkbox again and stop.
item->setCheckState(column, Qt::Unchecked);
return;
}
if(m.data(m.index(0, 0)).toInt() > 0)
{
// There is a non-integer value, so print an error message, uncheck the combobox, and return here
Expand Down Expand Up @@ -458,10 +468,20 @@ void EditTableDialog::itemChanged(QTreeWidgetItem *item, int column)
// Because our renameColumn() function fails when setting a column to unique when it already contains the same values
SqliteTableModel m(pdb, this);
m.setQuery(QString("SELECT COUNT(%2) FROM %1;").arg(curTable.toString()).arg(sqlb::escapeIdentifier(field->name())));
m.waitForFetchingFinished();
if(!m.completeCache())
{
// If we couldn't load all data because the cancel button was clicked, just unset the checkbox again and stop.
item->setCheckState(column, Qt::Unchecked);
return;
}
int rowcount = m.data(m.index(0, 0)).toInt();
m.setQuery(QString("SELECT COUNT(DISTINCT %2) FROM %1;").arg(curTable.toString()).arg(sqlb::escapeIdentifier(field->name())));
m.waitForFetchingFinished();
if(!m.completeCache())
{
// If we couldn't load all data because the cancel button was clicked, just unset the checkbox again and stop.
item->setCheckState(column, Qt::Unchecked);
return;
}
int uniquecount = m.data(m.index(0, 0)).toInt();
if(rowcount != uniquecount)
{
Expand Down
7 changes: 5 additions & 2 deletions src/ExportDataDialog.cpp
Expand Up @@ -117,7 +117,8 @@ bool ExportDataDialog::exportQueryCsv(const QString& sQuery, const QString& sFil
QByteArray utf8Query = sQuery.toUtf8();
sqlite3_stmt *stmt;

int status = sqlite3_prepare_v2(pdb._db, utf8Query.data(), utf8Query.size(), &stmt, nullptr);
auto pDb = pdb.get(tr("exporting CSV"));
int status = sqlite3_prepare_v2(pDb.get(), utf8Query.data(), utf8Query.size(), &stmt, nullptr);
if(SQLITE_OK == status)
{
if(ui->checkHeader->isChecked())
Expand Down Expand Up @@ -199,7 +200,9 @@ bool ExportDataDialog::exportQueryJson(const QString& sQuery, const QString& sFi
{
QByteArray utf8Query = sQuery.toUtf8();
sqlite3_stmt *stmt;
int status = sqlite3_prepare_v2(pdb._db, utf8Query.data(), utf8Query.size(), &stmt, nullptr);

auto pDb = pdb.get(tr("exporting JSON"));
int status = sqlite3_prepare_v2(pDb.get(), utf8Query.data(), utf8Query.size(), &stmt, nullptr);

QJsonArray json_table;

Expand Down
22 changes: 14 additions & 8 deletions src/ExtendedTableWidget.cpp
Expand Up @@ -604,7 +604,7 @@ void ExtendedTableWidget::updateGeometries()
// If so and if it is a SqliteTableModel and if the parent implementation of this method decided that a scrollbar is needed, update its maximum value
SqliteTableModel* m = qobject_cast<SqliteTableModel*>(model());
if(m && verticalScrollBar()->maximum())
verticalScrollBar()->setMaximum(m->totalRowCount() - numVisibleRows() + 1);
verticalScrollBar()->setMaximum(m->rowCount() - numVisibleRows() + 1);
}
}

Expand All @@ -615,8 +615,16 @@ void ExtendedTableWidget::vscrollbarChanged(int value)
return;

// Fetch more data from the DB if necessary
if((value + numVisibleRows()) >= model()->rowCount() && model()->canFetchMore(QModelIndex()))
model()->fetchMore(QModelIndex());
const auto nrows = model()->rowCount();
if(nrows == 0)
return;

if(auto * m = dynamic_cast<SqliteTableModel*>(model()))
{
int row_begin = std::min(value, nrows - 1);
int row_end = std::min(value + numVisibleRows(), nrows);
m->triggerCacheLoad(row_begin, row_end);
}
}

int ExtendedTableWidget::numVisibleRows()
Expand Down Expand Up @@ -682,13 +690,11 @@ void ExtendedTableWidget::selectTableLine(int lineToSelect)
SqliteTableModel* m = qobject_cast<SqliteTableModel*>(model());

// Are there even that many lines?
if(lineToSelect >= m->totalRowCount())
if(lineToSelect >= m->rowCount())
return;

QApplication::setOverrideCursor( Qt::WaitCursor );
// Make sure this line has already been fetched
while(lineToSelect >= m->rowCount() && m->canFetchMore())
m->fetchMore();
m->triggerCacheLoad(lineToSelect);

// Select it
clearSelection();
Expand All @@ -703,7 +709,7 @@ void ExtendedTableWidget::selectTableLines(int firstLine, int count)

int lastLine = firstLine+count-1;
// Are there even that many lines?
if(lastLine >= m->totalRowCount())
if(lastLine >= m->rowCount())
return;

selectTableLine(firstLine);
Expand Down
3 changes: 2 additions & 1 deletion src/ImportCsvDialog.cpp
Expand Up @@ -607,7 +607,8 @@ bool ImportCsvDialog::importCsv(const QString& fileName, const QString& name)
sQuery.chop(1); // Remove last comma
sQuery.append(")");
sqlite3_stmt* stmt;
sqlite3_prepare_v2(pdb->_db, sQuery.toUtf8(), sQuery.toUtf8().length(), &stmt, nullptr);
auto pDb = pdb->get(tr("importing CSV"));
sqlite3_prepare_v2(pDb.get(), sQuery.toUtf8(), sQuery.toUtf8().length(), &stmt, nullptr);

// Parse entire file
size_t lastRowNum = 0;
Expand Down