diff options
author | Florian Bruhin <me@the-compiler.org> | 2021-07-09 17:06:23 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-09 17:06:23 +0200 |
commit | ae6d9009716c85c679b490ab4df92e80b77b3fa5 (patch) | |
tree | 3c03eb22447c3233533dc91679979ee3de8f8991 /qutebrowser/browser | |
parent | 8bdab79011680c13b3b2072a3b18a4471c168131 (diff) | |
parent | 71a7674a706b73dfaac5958e9c3bca414c4e8665 (diff) | |
download | qutebrowser-ae6d9009716c85c679b490ab4df92e80b77b3fa5.tar.gz qutebrowser-ae6d9009716c85c679b490ab4df92e80b77b3fa5.zip |
Merge pull request #6567 from lufte/issue6039
Database class
Diffstat (limited to 'qutebrowser/browser')
-rw-r--r-- | qutebrowser/browser/history.py | 96 |
1 files changed, 52 insertions, 44 deletions
diff --git a/qutebrowser/browser/history.py b/qutebrowser/browser/history.py index 773c6cc51..559992327 100644 --- a/qutebrowser/browser/history.py +++ b/qutebrowser/browser/history.py @@ -22,9 +22,10 @@ import os import time import contextlib -from typing import cast, Mapping, MutableSequence +import pathlib +from typing import cast, Mapping, MutableSequence, Optional -from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal +from PyQt5.QtCore import pyqtSlot, QUrl, QObject, pyqtSignal from PyQt5.QtWidgets import QProgressDialog, QApplication from qutebrowser.config import config @@ -91,13 +92,14 @@ class CompletionMetaInfo(sql.SqlTable): 'force_rebuild': False, } - def __init__(self, parent=None): + def __init__(self, database: sql.Database, + parent: Optional[QObject] = None) -> None: self._fields = ['key', 'value'] self._constraints = {'key': 'PRIMARY KEY'} - super().__init__( - "CompletionMetaInfo", self._fields, constraints=self._constraints) + super().__init__(database, "CompletionMetaInfo", self._fields, + constraints=self._constraints, parent=parent) - if sql.user_version_changed(): + if database.user_version_changed(): self._init_default_values() def _check_key(self, key): @@ -125,8 +127,8 @@ class CompletionMetaInfo(sql.SqlTable): def __getitem__(self, key): self._check_key(key) - query = sql.Query('SELECT value FROM CompletionMetaInfo ' - 'WHERE key = :key') + query = self.database.query('SELECT value FROM CompletionMetaInfo ' + 'WHERE key = :key') return query.run(key=key).value() def __setitem__(self, key, value): @@ -138,8 +140,9 @@ class CompletionHistory(sql.SqlTable): """History which only has the newest entry for each URL.""" - def __init__(self, parent=None): - super().__init__("CompletionHistory", ['url', 'title', 'last_atime'], + def __init__(self, database: sql.Database, + parent: Optional[QObject] = None) -> None: + super().__init__(database, "CompletionHistory", ['url', 'title', 'last_atime'], constraints={'url': 'PRIMARY KEY', 'title': 'NOT NULL', 'last_atime': 'NOT NULL'}, @@ -162,8 +165,9 @@ class WebHistory(sql.SqlTable): # one url cleared url_cleared = pyqtSignal(QUrl) - def __init__(self, progress, parent=None): - super().__init__("History", ['url', 'title', 'atime', 'redirect'], + def __init__(self, database: sql.Database, progress: HistoryProgress, + parent: Optional[QObject] = None) -> None: + super().__init__(database, "History", ['url', 'title', 'atime', 'redirect'], constraints={'url': 'NOT NULL', 'title': 'NOT NULL', 'atime': 'NOT NULL', @@ -173,8 +177,8 @@ class WebHistory(sql.SqlTable): # Store the last saved url to avoid duplicate immediate saves. self._last_url = None - self.completion = CompletionHistory(parent=self) - self.metainfo = CompletionMetaInfo(parent=self) + self.completion = CompletionHistory(database, parent=self) + self.metainfo = CompletionMetaInfo(database, parent=self) try: rebuild_completion = self.metainfo['force_rebuild'] @@ -184,16 +188,18 @@ class WebHistory(sql.SqlTable): self.metainfo.try_recover() rebuild_completion = self.metainfo['force_rebuild'] - if sql.user_version_changed(): - # If the DB user version changed, run a full cleanup and rebuild the - # completion history. - # - # In the future, this could be improved to only be done when actually needed - # - but version changes happen very infrequently, rebuilding everything - # gives us less corner-cases to deal with, and we can run a VACUUM to make - # things smaller. - self._cleanup_history() - rebuild_completion = True + if self.database.user_version_changed(): + with self.database.transaction(): + # If the DB user version changed, run a full cleanup and rebuild the + # completion history. + # + # In the future, this could be improved to only be done when actually + # needed - but version changes happen very infrequently, rebuilding + # everything gives us less corner-cases to deal with, and we can run a + # VACUUM to make things smaller. + self._cleanup_history() + rebuild_completion = True + self.database.upgrade_user_version() # Get a string of all patterns patterns = config.instance.get_str('completion.web_history.exclude') @@ -211,19 +217,19 @@ class WebHistory(sql.SqlTable): self.create_index('HistoryIndex', 'url') self.create_index('HistoryAtimeIndex', 'atime') self._contains_query = self.contains_query('url') - self._between_query = sql.Query('SELECT * FROM History ' - 'where not redirect ' - 'and not url like "qute://%" ' - 'and atime > :earliest ' - 'and atime <= :latest ' - 'ORDER BY atime desc') - - self._before_query = sql.Query('SELECT * FROM History ' - 'where not redirect ' - 'and not url like "qute://%" ' - 'and atime <= :latest ' - 'ORDER BY atime desc ' - 'limit :limit offset :offset') + self._between_query = self.database.query('SELECT * FROM History ' + 'where not redirect ' + 'and not url like "qute://%" ' + 'and atime > :earliest ' + 'and atime <= :latest ' + 'ORDER BY atime desc') + + self._before_query = self.database.query('SELECT * FROM History ' + 'where not redirect ' + 'and not url like "qute://%" ' + 'and atime <= :latest ' + 'ORDER BY atime desc ' + 'limit :limit offset :offset') def __repr__(self): return utils.get_repr(self, length=len(self)) @@ -271,7 +277,7 @@ class WebHistory(sql.SqlTable): 'qute://pdfjs%', ] where_clause = ' OR '.join(f"url LIKE '{term}'" for term in terms) - q = sql.Query(f'DELETE FROM History WHERE {where_clause}') + q = self.database.query(f'DELETE FROM History WHERE {where_clause}') entries = q.run() log.sql.debug(f"Cleanup removed {entries.rows_affected()} items") @@ -297,9 +303,9 @@ class WebHistory(sql.SqlTable): QApplication.processEvents() # Select the latest entry for each url - q = sql.Query('SELECT url, title, max(atime) AS atime FROM History ' - 'WHERE NOT redirect ' - 'GROUP BY url ORDER BY atime asc') + q = self.database.query('SELECT url, title, max(atime) AS atime FROM History ' + 'WHERE NOT redirect ' + 'GROUP BY url ORDER BY atime asc') result = q.run() QApplication.processEvents() entries = list(result) @@ -319,7 +325,7 @@ class WebHistory(sql.SqlTable): self._progress.set_maximum(0) # We might have caused fragmentation - let's clean up. - sql.Query('VACUUM').run() + self.database.query('VACUUM').run() QApplication.processEvents() self.completion.insert_batch(data, replace=True) @@ -472,15 +478,17 @@ def debug_dump_history(dest): raise cmdutils.CommandError(f'Could not write history: {e}') -def init(parent=None): +def init(db_path: pathlib.Path, parent: Optional[QObject] = None) -> None: """Initialize the web history. Args: + db_path: The path for the SQLite database. parent: The parent to use for WebHistory. """ global web_history progress = HistoryProgress() - web_history = WebHistory(progress=progress, parent=parent) + database = sql.Database(str(db_path)) + web_history = WebHistory(database=database, progress=progress, parent=parent) if objects.backend == usertypes.Backend.QtWebKit: # pragma: no cover from qutebrowser.browser.webkit import webkithistory |