-
-
Notifications
You must be signed in to change notification settings - Fork 0
Fix memory leaks, performance problems, and restore paged result browsing #113
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
Merged
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
7121998
Return const references from DbExport accessors to avoid dangling tem…
christianhelle fce4d4b
Free export progress and cancellation state instead of leaking it on …
christianhelle a4df182
Connect export orchestrator signals once instead of on every export
christianhelle 11b0607
Stop query result views and models accumulating on every execution
christianhelle 557cf37
Delete the recents file instead of calling deleteLater on a stack QFile
christianhelle ad9c4f9
Resolve text column types once per table instead of once per exported…
christianhelle d00928f
Iterate schema and statements by reference instead of copying each el…
christianhelle 049e38a
Hoist column count and reuse row buffers when reading query results
christianhelle e6354a3
Move the schema snapshot into the export worker instead of copying it
christianhelle e0f3967
Let QMainWindow own the status bar instead of double-owning it
christianhelle a1abbd7
Let the widget tree own the result scroll area and container
christianhelle b0c327e
Persist window state on exit rather than on every resize event
christianhelle ce6beea
Keep previous results on screen when a statement renders nothing
christianhelle c3f21ad
Keep the database open after analysis so queries and previews can run
christianhelle 614c43f
Cover the query result presenter with widget tests
christianhelle 4a5fbe3
Cap table previews so browsing a large database stays instant
christianhelle 69c738f
Report SQL errors instead of replacing them with the timing message
christianhelle 3c32eea
Let a statement read at most a given number of rows
christianhelle 0865d31
Pass a row cap through the executor and result presenter
christianhelle 5661ab3
Cap the rows an ad-hoc query renders and say when results were cut short
christianhelle 995a52c
Add a paged result model that fetches rows as they are scrolled into …
christianhelle f7af0bb
Browse query results and table data through the paged model
christianhelle ba3ec8e
Remove the row cap now that results are fetched a page at a time
christianhelle 65f678c
Share one result reader between the database adapters
christianhelle 5b91ef7
Share one base class between the database adapters
christianhelle c051877
Guard the export-in-progress check in one place
christianhelle 1b0b3fc
Keep newlines in SQL, escape identifiers, and tie export tasks to the…
christianhelle 007e35d
Copy the connection instead of pretending to move it
christianhelle File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,35 +1,20 @@ | ||
| #ifndef INMEMORYDATABASE_H | ||
| #define INMEMORYDATABASE_H | ||
|
|
||
| #include <QSqlDatabase> | ||
| #include <QString> | ||
|
|
||
| #include "idatabase.h" | ||
| #include "sqldatabaseadapter.h" | ||
|
|
||
| class InMemoryDatabase : public IDatabase { | ||
| // Test adapter: a SQLite database held in memory. | ||
| class InMemoryDatabase final : public SqlDatabaseAdapter { | ||
| public: | ||
| InMemoryDatabase(); | ||
|
|
||
| void setSource(const QString &filename) override; | ||
|
|
||
| bool open() override; | ||
|
|
||
| void close() override; | ||
|
|
||
| void shrink() override; | ||
|
|
||
| [[nodiscard]] QString getFilename() const override { return source; } | ||
|
|
||
| QueryResult runStatement(const QString &sql) override; | ||
|
|
||
| QueryResult streamRows(const QString &sql, | ||
| const std::function<bool(const QList<QVariant> &)> &onRow) override; | ||
|
|
||
| [[nodiscard]] QSqlDatabase getConnection() const { return database; } | ||
|
|
||
| private: | ||
| QSqlDatabase database; | ||
| QString source; | ||
| }; | ||
|
|
||
| #endif // INMEMORYDATABASE_H |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| #include "pagedresultmodel.h" | ||
|
|
||
| #include <QSqlError> | ||
| #include <QSqlQuery> | ||
| #include <QSqlRecord> | ||
|
|
||
| #include <utility> | ||
|
|
||
| PagedResultModel::PagedResultModel(const QSqlDatabase &database, QString sql, QObject *parent) | ||
| : QSqlQueryModel(parent), | ||
| database(database), | ||
| statement(std::move(sql)) { | ||
| run(statement); | ||
| } | ||
|
|
||
| bool PagedResultModel::run(const QString &sql) { | ||
| QSqlQuery query(this->database); | ||
| if (!query.exec(sql)) { | ||
| this->error = query.lastError().text(); | ||
| return false; | ||
| } | ||
|
|
||
| // QSqlQueryModel reads the first page here and the rest on demand. | ||
| setQuery(std::move(query)); | ||
| if (lastError().isValid()) { | ||
| this->error = lastError().text(); | ||
| return false; | ||
| } | ||
|
|
||
| this->error.clear(); | ||
| return true; | ||
| } | ||
|
|
||
| void PagedResultModel::sort(const int column, const Qt::SortOrder order) { | ||
| if (column < 0 || column >= columnCount()) | ||
| return; | ||
|
|
||
| QString columnName = record().fieldName(column); | ||
| if (columnName.isEmpty()) | ||
| return; | ||
|
|
||
| // A quoted identifier escapes a double quote by doubling it. | ||
| columnName.replace('"', "\"\""); | ||
|
|
||
| const QString sorted = QString("SELECT * FROM (%1) ORDER BY \"%2\" %3") | ||
| .arg(statement, | ||
| columnName, | ||
| order == Qt::AscendingOrder ? "ASC" : "DESC"); | ||
|
|
||
| // Not every statement can be wrapped in a subquery. run() leaves the model | ||
| // untouched when it fails, so there is nothing to restore -- and re-running | ||
| // the original would execute a statement with side effects a second time. | ||
| run(sorted); | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.