sql: Handle sqlite extended error codes
Qt 6.1 switched to using extended sqlite error codes: https://codereview.qt-project.org/c/qt/qtbase/+/329472 This is neat because it gives us more granularity for errors, but it also means that we now need to account for that by masking the error codes accordingly for checking their category. See unhandled I/O error here: https://crashes.qutebrowser.org/view/d9b26c2f
This commit is contained in:
parent
815374c6b6
commit
6ffc5174ea
|
|
@ -77,16 +77,16 @@ class SqliteErrorCode:
|
|||
in qutebrowser here.
|
||||
"""
|
||||
|
||||
ERROR = '1' # generic error code
|
||||
BUSY = '5' # database is locked
|
||||
READONLY = '8' # attempt to write a readonly database
|
||||
IOERR = '10' # disk I/O error
|
||||
CORRUPT = '11' # database disk image is malformed
|
||||
FULL = '13' # database or disk is full
|
||||
CANTOPEN = '14' # unable to open database file
|
||||
PROTOCOL = '15' # locking protocol error
|
||||
CONSTRAINT = '19' # UNIQUE constraint failed
|
||||
NOTADB = '26' # file is not a database
|
||||
ERROR = 1 # generic error code
|
||||
BUSY = 5 # database is locked
|
||||
READONLY = 8 # attempt to write a readonly database
|
||||
IOERR = 10 # disk I/O error
|
||||
CORRUPT = 11 # database disk image is malformed
|
||||
FULL = 13 # database or disk is full
|
||||
CANTOPEN = 14 # unable to open database file
|
||||
PROTOCOL = 15 # locking protocol error
|
||||
CONSTRAINT = 19 # UNIQUE constraint failed
|
||||
NOTADB = 26 # file is not a database
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
|
|
@ -128,6 +128,12 @@ class BugError(Error):
|
|||
def raise_sqlite_error(msg: str, error: QSqlError) -> None:
|
||||
"""Raise either a BugError or KnownError."""
|
||||
error_code = error.nativeErrorCode()
|
||||
try:
|
||||
# https://sqlite.org/rescode.html#pve
|
||||
primary_error_code = int(error_code) & 0xff
|
||||
except ValueError:
|
||||
primary_error_code = None
|
||||
|
||||
database_text = error.databaseText()
|
||||
driver_text = error.driverText()
|
||||
|
||||
|
|
@ -135,7 +141,7 @@ def raise_sqlite_error(msg: str, error: QSqlError) -> None:
|
|||
log.sql.debug(f"type: {debug.qenum_key(QSqlError, error.type())}")
|
||||
log.sql.debug(f"database text: {database_text}")
|
||||
log.sql.debug(f"driver text: {driver_text}")
|
||||
log.sql.debug(f"error code: {error_code}")
|
||||
log.sql.debug(f"error code: {error_code} -> {primary_error_code}")
|
||||
|
||||
known_errors = [
|
||||
SqliteErrorCode.BUSY,
|
||||
|
|
@ -151,12 +157,12 @@ def raise_sqlite_error(msg: str, error: QSqlError) -> None:
|
|||
# https://github.com/qutebrowser/qutebrowser/issues/4681
|
||||
# If the query we built was too long
|
||||
too_long_err = (
|
||||
error_code == SqliteErrorCode.ERROR and
|
||||
primary_error_code == SqliteErrorCode.ERROR and
|
||||
(database_text.startswith("Expression tree is too large") or
|
||||
database_text in ["too many SQL variables",
|
||||
"LIKE or GLOB pattern too complex"]))
|
||||
|
||||
if error_code in known_errors or too_long_err:
|
||||
if primary_error_code in known_errors or too_long_err:
|
||||
raise KnownError(msg, error)
|
||||
|
||||
raise BugError(msg, error)
|
||||
|
|
|
|||
|
|
@ -93,10 +93,16 @@ class TestSqlError:
|
|||
@pytest.mark.parametrize('error_code, exception', [
|
||||
(sql.SqliteErrorCode.BUSY, sql.KnownError),
|
||||
(sql.SqliteErrorCode.CONSTRAINT, sql.BugError),
|
||||
# extended error codes
|
||||
(sql.SqliteErrorCode.IOERR | (1<<8), sql.KnownError), # SQLITE_IOERR_READ
|
||||
(
|
||||
sql.SqliteErrorCode.CONSTRAINT | (1<<8), # SQLITE_CONSTRAINT_CHECK
|
||||
sql.BugError
|
||||
),
|
||||
])
|
||||
def test_known(self, error_code, exception):
|
||||
sql_err = QSqlError("driver text", "db text", QSqlError.ErrorType.UnknownError,
|
||||
error_code)
|
||||
str(error_code))
|
||||
with pytest.raises(exception):
|
||||
sql.raise_sqlite_error("Message", sql_err)
|
||||
|
||||
|
|
@ -109,7 +115,7 @@ class TestSqlError:
|
|||
'type: UnknownError',
|
||||
'database text: db text',
|
||||
'driver text: driver text',
|
||||
'error code: 23']
|
||||
'error code: 23 -> 23']
|
||||
|
||||
assert caplog.messages == expected
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue