Files
UUVPN/iOS-SwiftUI-Code/GRDB.swift-6.29.3/GRDB/Core/DatabaseError.swift
T

613 lines
31 KiB
Swift

import Foundation
/// An SQLite result code.
///
/// Related SQLite documentation: <https://www.sqlite.org/rescode.html>
public struct ResultCode: RawRepresentable, Equatable {
/// The raw SQLite result code.
public let rawValue: CInt
/// Creates a `ResultCode` from a raw SQLite result code.
public init(rawValue: CInt) {
self.rawValue = rawValue
}
/// A primary result code limited to the least significant 8 bits.
///
/// For example:
///
/// ```swift
/// let resultCode = .SQLITE_CONSTRAINT_FOREIGNKEY
/// resultCode.primaryResultCode == .SQLITE_CONSTRAINT // true
/// ```
public var primaryResultCode: ResultCode {
ResultCode(rawValue: rawValue & 0xFF)
}
var isPrimary: Bool { self == primaryResultCode }
/// Returns true if the code on the left matches the code on the right.
///
/// Primary result codes match themselves and their extended result codes,
/// while extended result codes match only themselves:
///
/// For example:
///
/// ```swift
/// switch error.extendedResultCode {
/// case .SQLITE_CONSTRAINT_FOREIGNKEY: // foreign key constraint error
/// case .SQLITE_CONSTRAINT: // any other constraint error
/// default: // any other database error
/// }
/// ```
public static func ~= (pattern: ResultCode, code: ResultCode) -> Bool {
if pattern.isPrimary {
return pattern == code.primaryResultCode
} else {
return pattern == code
}
}
// Primary Result codes
// https://www.sqlite.org/rescode.html#primary_result_code_list
// swiftlint:disable operator_usage_whitespace
public static let SQLITE_OK = ResultCode(rawValue: 0) // Successful result
public static let SQLITE_ERROR = ResultCode(rawValue: 1) // SQL error or missing database
public static let SQLITE_INTERNAL = ResultCode(rawValue: 2) // Internal logic error in SQLite
public static let SQLITE_PERM = ResultCode(rawValue: 3) // Access permission denied
public static let SQLITE_ABORT = ResultCode(rawValue: 4) // Callback routine requested an abort
public static let SQLITE_BUSY = ResultCode(rawValue: 5) // The database file is locked
public static let SQLITE_LOCKED = ResultCode(rawValue: 6) // A table in the database is locked
public static let SQLITE_NOMEM = ResultCode(rawValue: 7) // A malloc() failed
public static let SQLITE_READONLY = ResultCode(rawValue: 8) // Attempt to write a readonly database
public static let SQLITE_INTERRUPT = ResultCode(rawValue: 9) // Operation terminated by sqlite3_interrupt()
public static let SQLITE_IOERR = ResultCode(rawValue: 10) // Some kind of disk I/O error occurred
public static let SQLITE_CORRUPT = ResultCode(rawValue: 11) // The database disk image is malformed
public static let SQLITE_NOTFOUND = ResultCode(rawValue: 12) // Unknown opcode in sqlite3_file_control()
public static let SQLITE_FULL = ResultCode(rawValue: 13) // Insertion failed because database is full
public static let SQLITE_CANTOPEN = ResultCode(rawValue: 14) // Unable to open the database file
public static let SQLITE_PROTOCOL = ResultCode(rawValue: 15) // Database lock protocol error
public static let SQLITE_EMPTY = ResultCode(rawValue: 16) // Database is empty
public static let SQLITE_SCHEMA = ResultCode(rawValue: 17) // The database schema changed
public static let SQLITE_TOOBIG = ResultCode(rawValue: 18) // String or BLOB exceeds size limit
public static let SQLITE_CONSTRAINT = ResultCode(rawValue: 19) // Abort due to constraint violation
public static let SQLITE_MISMATCH = ResultCode(rawValue: 20) // Data type mismatch
public static let SQLITE_MISUSE = ResultCode(rawValue: 21) // Library used incorrectly
public static let SQLITE_NOLFS = ResultCode(rawValue: 22) // Uses OS features not supported on host
public static let SQLITE_AUTH = ResultCode(rawValue: 23) // Authorization denied
public static let SQLITE_FORMAT = ResultCode(rawValue: 24) // Auxiliary database format error
public static let SQLITE_RANGE = ResultCode(rawValue: 25) // 2nd parameter to sqlite3_bind out of range
public static let SQLITE_NOTADB = ResultCode(rawValue: 26) // File opened that is not a database file
public static let SQLITE_NOTICE = ResultCode(rawValue: 27) // Notifications from sqlite3_log()
public static let SQLITE_WARNING = ResultCode(rawValue: 28) // Warnings from sqlite3_log()
public static let SQLITE_ROW = ResultCode(rawValue: 100) // sqlite3_step() has another row ready
public static let SQLITE_DONE = ResultCode(rawValue: 101) // sqlite3_step() has finished executing
// swiftlint:enable operator_usage_whitespace
// Extended Result Code
// https://www.sqlite.org/rescode.html#extended_result_code_list
// swiftlint:disable operator_usage_whitespace line_length
public static let SQLITE_ERROR_MISSING_COLLSEQ = ResultCode(rawValue: (SQLITE_ERROR.rawValue | (1<<8)))
public static let SQLITE_ERROR_RETRY = ResultCode(rawValue: (SQLITE_ERROR.rawValue | (2<<8)))
public static let SQLITE_ERROR_SNAPSHOT = ResultCode(rawValue: (SQLITE_ERROR.rawValue | (3<<8)))
public static let SQLITE_IOERR_READ = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (1<<8)))
public static let SQLITE_IOERR_SHORT_READ = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (2<<8)))
public static let SQLITE_IOERR_WRITE = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (3<<8)))
public static let SQLITE_IOERR_FSYNC = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (4<<8)))
public static let SQLITE_IOERR_DIR_FSYNC = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (5<<8)))
public static let SQLITE_IOERR_TRUNCATE = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (6<<8)))
public static let SQLITE_IOERR_FSTAT = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (7<<8)))
public static let SQLITE_IOERR_UNLOCK = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (8<<8)))
public static let SQLITE_IOERR_RDLOCK = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (9<<8)))
public static let SQLITE_IOERR_DELETE = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (10<<8)))
public static let SQLITE_IOERR_BLOCKED = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (11<<8)))
public static let SQLITE_IOERR_NOMEM = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (12<<8)))
public static let SQLITE_IOERR_ACCESS = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (13<<8)))
public static let SQLITE_IOERR_CHECKRESERVEDLOCK = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (14<<8)))
public static let SQLITE_IOERR_LOCK = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (15<<8)))
public static let SQLITE_IOERR_CLOSE = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (16<<8)))
public static let SQLITE_IOERR_DIR_CLOSE = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (17<<8)))
public static let SQLITE_IOERR_SHMOPEN = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (18<<8)))
public static let SQLITE_IOERR_SHMSIZE = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (19<<8)))
public static let SQLITE_IOERR_SHMLOCK = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (20<<8)))
public static let SQLITE_IOERR_SHMMAP = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (21<<8)))
public static let SQLITE_IOERR_SEEK = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (22<<8)))
public static let SQLITE_IOERR_DELETE_NOENT = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (23<<8)))
public static let SQLITE_IOERR_MMAP = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (24<<8)))
public static let SQLITE_IOERR_GETTEMPPATH = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (25<<8)))
public static let SQLITE_IOERR_CONVPATH = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (26<<8)))
public static let SQLITE_IOERR_VNODE = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (27<<8)))
public static let SQLITE_IOERR_AUTH = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (28<<8)))
public static let SQLITE_IOERR_BEGIN_ATOMIC = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (29<<8)))
public static let SQLITE_IOERR_COMMIT_ATOMIC = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (30<<8)))
public static let SQLITE_IOERR_ROLLBACK_ATOMIC = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (31<<8)))
public static let SQLITE_IOERR_DATA = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (32<<8)))
public static let SQLITE_IOERR_CORRUPTFS = ResultCode(rawValue: (SQLITE_IOERR.rawValue | (33<<8)))
public static let SQLITE_LOCKED_SHAREDCACHE = ResultCode(rawValue: (SQLITE_LOCKED.rawValue | (1<<8)))
public static let SQLITE_LOCKED_VTAB = ResultCode(rawValue: (SQLITE_LOCKED.rawValue | (2<<8)))
public static let SQLITE_BUSY_RECOVERY = ResultCode(rawValue: (SQLITE_BUSY.rawValue | (1<<8)))
public static let SQLITE_BUSY_SNAPSHOT = ResultCode(rawValue: (SQLITE_BUSY.rawValue | (2<<8)))
public static let SQLITE_BUSY_TIMEOUT = ResultCode(rawValue: (SQLITE_BUSY.rawValue | (3<<8)))
public static let SQLITE_CANTOPEN_NOTEMPDIR = ResultCode(rawValue: (SQLITE_CANTOPEN.rawValue | (1<<8)))
public static let SQLITE_CANTOPEN_ISDIR = ResultCode(rawValue: (SQLITE_CANTOPEN.rawValue | (2<<8)))
public static let SQLITE_CANTOPEN_FULLPATH = ResultCode(rawValue: (SQLITE_CANTOPEN.rawValue | (3<<8)))
public static let SQLITE_CANTOPEN_CONVPATH = ResultCode(rawValue: (SQLITE_CANTOPEN.rawValue | (4<<8)))
public static let SQLITE_CANTOPEN_DIRTYWAL = ResultCode(rawValue: (SQLITE_CANTOPEN.rawValue | (5<<8))) /* Not Used */
public static let SQLITE_CANTOPEN_SYMLINK = ResultCode(rawValue: (SQLITE_CANTOPEN.rawValue | (6<<8)))
public static let SQLITE_CORRUPT_VTAB = ResultCode(rawValue: (SQLITE_CORRUPT.rawValue | (1<<8)))
public static let SQLITE_CORRUPT_SEQUENCE = ResultCode(rawValue: (SQLITE_CORRUPT.rawValue | (2<<8)))
public static let SQLITE_CORRUPT_INDEX = ResultCode(rawValue: (SQLITE_CORRUPT.rawValue | (3<<8)))
public static let SQLITE_READONLY_RECOVERY = ResultCode(rawValue: (SQLITE_READONLY.rawValue | (1<<8)))
public static let SQLITE_READONLY_CANTLOCK = ResultCode(rawValue: (SQLITE_READONLY.rawValue | (2<<8)))
public static let SQLITE_READONLY_ROLLBACK = ResultCode(rawValue: (SQLITE_READONLY.rawValue | (3<<8)))
public static let SQLITE_READONLY_DBMOVED = ResultCode(rawValue: (SQLITE_READONLY.rawValue | (4<<8)))
public static let SQLITE_READONLY_CANTINIT = ResultCode(rawValue: (SQLITE_READONLY.rawValue | (5<<8)))
public static let SQLITE_READONLY_DIRECTORY = ResultCode(rawValue: (SQLITE_READONLY.rawValue | (6<<8)))
public static let SQLITE_ABORT_ROLLBACK = ResultCode(rawValue: (SQLITE_ABORT.rawValue | (2<<8)))
public static let SQLITE_CONSTRAINT_CHECK = ResultCode(rawValue: (SQLITE_CONSTRAINT.rawValue | (1<<8)))
public static let SQLITE_CONSTRAINT_COMMITHOOK = ResultCode(rawValue: (SQLITE_CONSTRAINT.rawValue | (2<<8)))
public static let SQLITE_CONSTRAINT_FOREIGNKEY = ResultCode(rawValue: (SQLITE_CONSTRAINT.rawValue | (3<<8)))
public static let SQLITE_CONSTRAINT_FUNCTION = ResultCode(rawValue: (SQLITE_CONSTRAINT.rawValue | (4<<8)))
public static let SQLITE_CONSTRAINT_NOTNULL = ResultCode(rawValue: (SQLITE_CONSTRAINT.rawValue | (5<<8)))
public static let SQLITE_CONSTRAINT_PRIMARYKEY = ResultCode(rawValue: (SQLITE_CONSTRAINT.rawValue | (6<<8)))
public static let SQLITE_CONSTRAINT_TRIGGER = ResultCode(rawValue: (SQLITE_CONSTRAINT.rawValue | (7<<8)))
public static let SQLITE_CONSTRAINT_UNIQUE = ResultCode(rawValue: (SQLITE_CONSTRAINT.rawValue | (8<<8)))
public static let SQLITE_CONSTRAINT_VTAB = ResultCode(rawValue: (SQLITE_CONSTRAINT.rawValue | (9<<8)))
public static let SQLITE_CONSTRAINT_ROWID = ResultCode(rawValue: (SQLITE_CONSTRAINT.rawValue | (10<<8)))
public static let SQLITE_CONSTRAINT_PINNED = ResultCode(rawValue: (SQLITE_CONSTRAINT.rawValue | (11<<8)))
public static let SQLITE_CONSTRAINT_DATATYPE = ResultCode(rawValue: (SQLITE_CONSTRAINT.rawValue | (12<<8)))
public static let SQLITE_NOTICE_RECOVER_WAL = ResultCode(rawValue: (SQLITE_NOTICE.rawValue | (1<<8)))
public static let SQLITE_NOTICE_RECOVER_ROLLBACK = ResultCode(rawValue: (SQLITE_NOTICE.rawValue | (2<<8)))
public static let SQLITE_WARNING_AUTOINDEX = ResultCode(rawValue: (SQLITE_WARNING.rawValue | (1<<8)))
public static let SQLITE_AUTH_USER = ResultCode(rawValue: (SQLITE_AUTH.rawValue | (1<<8)))
public static let SQLITE_OK_LOAD_PERMANENTLY = ResultCode(rawValue: (SQLITE_OK.rawValue | (1<<8)))
public static let SQLITE_OK_SYMLINK = ResultCode(rawValue: (SQLITE_OK.rawValue | (2<<8)))
// swiftlint:enable operator_usage_whitespace line_length
}
extension ResultCode {
/// Returns true if the code on the left matches the error on the right.
///
/// Primary result codes match themselves and their extended result codes,
/// while extended result codes match only themselves.
///
/// For example:
///
/// ```swift
/// do {
/// try ...
/// } catch ResultCode.SQLITE_CONSTRAINT_FOREIGNKEY {
/// // foreign key constraint error
/// } catch ResultCode.SQLITE_CONSTRAINT {
/// // any other constraint error
/// } catch {
/// // any other database error
/// }
/// ```
public static func ~= (lhs: Self, rhs: Error) -> Bool {
guard let error = rhs as? DatabaseError else { return false }
return lhs ~= error.extendedResultCode
}
}
extension ResultCode: CustomStringConvertible {
var errorString: String? {
String(cString: sqlite3_errstr(rawValue))
}
public var description: String {
if let errorString {
return "\(rawValue) (\(errorString))"
} else {
return "\(rawValue)"
}
}
}
extension ResultCode: Sendable { }
/// A `DatabaseError` describes an SQLite error.
///
/// For example:
///
/// ```swift
/// do {
/// try player.insert(db)
/// } catch let error as DatabaseError {
/// print(error) // prints debugging information
///
/// switch error {
/// case DatabaseError.SQLITE_CONSTRAINT_FOREIGNKEY:
/// // foreign key constraint error
/// case DatabaseError.SQLITE_CONSTRAINT:
/// // any other constraint error
/// default:
/// // any other database error
/// }
/// }
/// ```
///
/// The above example can also be written in a shorter way:
///
/// ```swift
/// do {
/// try player.insert(db)
/// } catch DatabaseError.SQLITE_CONSTRAINT_FOREIGNKEY {
/// // foreign key constraint error
/// } catch DatabaseError.SQLITE_CONSTRAINT {
/// // any other constraint error
/// } catch {
/// // any other database error
/// }
/// ```
///
/// Related SQLite documentation: <https://www.sqlite.org/rescode.html>
///
/// ## Topics
///
/// ### Creating DatabaseError
///
/// - ``init(resultCode:message:sql:arguments:publicStatementArguments:)``
/// - ``ResultCode``
///
/// ### Error Information
///
/// - ``arguments``
/// - ``extendedResultCode``
/// - ``isInterruptionError``
/// - ``message``
/// - ``resultCode``
/// - ``sql``
///
/// ### Converting DatabaseError to String
///
/// - ``description``
/// - ``expandedDescription``
public struct DatabaseError: Error {
/// The SQLite primary result code.
///
/// This property returns a "primary result code", that is to say the least
/// significant 8 bits of any SQLite result code.
///
/// For example:
///
/// ```swift
/// do {
/// ...
/// } catch let error as DatabaseError where error.resultCode == .SQL_CONSTRAINT {
/// // A constraint error
/// }
/// ```
///
/// The above example can also be written in a shorter way:
///
/// ```swift
/// do {
/// ...
/// } catch DatabaseError.SQL_CONSTRAINT {
/// // A constraint error
/// }
/// ```
///
/// See also ``extendedResultCode``.
///
/// Related SQLite documentation: <https://www.sqlite.org/rescode.html>
public var resultCode: ResultCode {
extendedResultCode.primaryResultCode
}
/// The SQLite extended error code.
///
/// For example:
///
/// ```swift
/// do {
/// ...
/// } catch let error as DatabaseError where error.extendedResultCode == .SQLITE_CONSTRAINT_FOREIGNKEY {
/// // A foreign key constraint error
/// }
/// ```
///
/// The above example can also be written in a shorter way:
///
/// ```swift
/// do {
/// ...
/// } catch DatabaseError.SQLITE_CONSTRAINT_FOREIGNKEY {
/// // A foreign key constraint error
/// }
/// ```
///
/// See also ``resultCode``.
///
/// Related SQLite documentation: <https://www.sqlite.org/rescode.html>
public let extendedResultCode: ResultCode
/// The SQLite error message.
public let message: String?
/// The SQL query that yielded the error.
public let sql: String?
/// The query arguments that yielded the error.
public let arguments: StatementArguments?
/// See Configuration.publicStatementArguments
var publicStatementArguments: Bool
/// Creates a `DatabaseError`.
///
/// - parameters:
/// - resultCode: A ResultCode (defaults to .SQLITE_ERROR).
/// - message: An eventual error message. If nil, the error message is
/// derived from the result code.
/// - sql: An eventual SQL string.
/// - arguments: Eventual statement arguments.
/// - publicStatementArguments: If false (the default), statement
/// arguments are not visible in the error's ``description`` property.
public init(
resultCode: ResultCode = .SQLITE_ERROR,
message: String? = nil,
sql: String? = nil,
arguments: StatementArguments? = nil,
publicStatementArguments: Bool = false)
{
self.extendedResultCode = resultCode
self.message = message ?? resultCode.errorString
self.sql = sql
self.arguments = arguments
self.publicStatementArguments = publicStatementArguments
}
/// Creates a Database Error with a raw CInt result code.
///
/// This initializer is not public because library user is not supposed to
/// be exposed to raw result codes.
@usableFromInline
init(resultCode: CInt, message: String? = nil, sql: String? = nil) {
self.init(
resultCode: ResultCode(rawValue: resultCode),
message: message,
sql: sql)
}
/// Creates a Database Error with a raw CInt result code.
///
/// This initializer is not public because library user is not supposed to
/// be exposed to raw result codes.
@usableFromInline
init(
resultCode: CInt,
message: String? = nil,
sql: String? = nil,
arguments: StatementArguments?,
publicStatementArguments: Bool)
{
self.init(
resultCode: ResultCode(rawValue: resultCode),
message: message,
sql: sql,
arguments: arguments,
publicStatementArguments: publicStatementArguments)
}
static func noSuchTable(_ tableName: String) -> Self {
DatabaseError(message: "no such table: \(tableName)")
}
static func noSuchSchema(_ schemaName: String) -> Self {
DatabaseError(message: "no such schema: \(schemaName)")
}
}
extension DatabaseError {
static func connectionIsClosed() -> Self {
DatabaseError(resultCode: .SQLITE_MISUSE, message: "Connection is closed")
}
}
// Support for `catch DatabaseError.SQLITE_XXX`
extension DatabaseError {
public static let SQLITE_OK = ResultCode.SQLITE_OK
public static let SQLITE_ERROR = ResultCode.SQLITE_ERROR
public static let SQLITE_INTERNAL = ResultCode.SQLITE_INTERNAL
public static let SQLITE_PERM = ResultCode.SQLITE_PERM
public static let SQLITE_ABORT = ResultCode.SQLITE_ABORT
public static let SQLITE_BUSY = ResultCode.SQLITE_BUSY
public static let SQLITE_LOCKED = ResultCode.SQLITE_LOCKED
public static let SQLITE_NOMEM = ResultCode.SQLITE_NOMEM
public static let SQLITE_READONLY = ResultCode.SQLITE_READONLY
public static let SQLITE_INTERRUPT = ResultCode.SQLITE_INTERRUPT
public static let SQLITE_IOERR = ResultCode.SQLITE_IOERR
public static let SQLITE_CORRUPT = ResultCode.SQLITE_CORRUPT
public static let SQLITE_NOTFOUND = ResultCode.SQLITE_NOTFOUND
public static let SQLITE_FULL = ResultCode.SQLITE_FULL
public static let SQLITE_CANTOPEN = ResultCode.SQLITE_CANTOPEN
public static let SQLITE_PROTOCOL = ResultCode.SQLITE_PROTOCOL
public static let SQLITE_EMPTY = ResultCode.SQLITE_EMPTY
public static let SQLITE_SCHEMA = ResultCode.SQLITE_SCHEMA
public static let SQLITE_TOOBIG = ResultCode.SQLITE_TOOBIG
public static let SQLITE_CONSTRAINT = ResultCode.SQLITE_CONSTRAINT
public static let SQLITE_MISMATCH = ResultCode.SQLITE_MISMATCH
public static let SQLITE_MISUSE = ResultCode.SQLITE_MISUSE
public static let SQLITE_NOLFS = ResultCode.SQLITE_NOLFS
public static let SQLITE_AUTH = ResultCode.SQLITE_AUTH
public static let SQLITE_FORMAT = ResultCode.SQLITE_FORMAT
public static let SQLITE_RANGE = ResultCode.SQLITE_RANGE
public static let SQLITE_NOTADB = ResultCode.SQLITE_NOTADB
public static let SQLITE_NOTICE = ResultCode.SQLITE_NOTICE
public static let SQLITE_WARNING = ResultCode.SQLITE_WARNING
public static let SQLITE_ROW = ResultCode.SQLITE_ROW
public static let SQLITE_DONE = ResultCode.SQLITE_DONE
public static let SQLITE_ERROR_MISSING_COLLSEQ = ResultCode.SQLITE_ERROR_MISSING_COLLSEQ
public static let SQLITE_ERROR_RETRY = ResultCode.SQLITE_ERROR_RETRY
public static let SQLITE_ERROR_SNAPSHOT = ResultCode.SQLITE_ERROR_SNAPSHOT
public static let SQLITE_IOERR_READ = ResultCode.SQLITE_IOERR_READ
public static let SQLITE_IOERR_SHORT_READ = ResultCode.SQLITE_IOERR_SHORT_READ
public static let SQLITE_IOERR_WRITE = ResultCode.SQLITE_IOERR_WRITE
public static let SQLITE_IOERR_FSYNC = ResultCode.SQLITE_IOERR_FSYNC
public static let SQLITE_IOERR_DIR_FSYNC = ResultCode.SQLITE_IOERR_DIR_FSYNC
public static let SQLITE_IOERR_TRUNCATE = ResultCode.SQLITE_IOERR_TRUNCATE
public static let SQLITE_IOERR_FSTAT = ResultCode.SQLITE_IOERR_FSTAT
public static let SQLITE_IOERR_UNLOCK = ResultCode.SQLITE_IOERR_UNLOCK
public static let SQLITE_IOERR_RDLOCK = ResultCode.SQLITE_IOERR_RDLOCK
public static let SQLITE_IOERR_DELETE = ResultCode.SQLITE_IOERR_DELETE
public static let SQLITE_IOERR_BLOCKED = ResultCode.SQLITE_IOERR_BLOCKED
public static let SQLITE_IOERR_NOMEM = ResultCode.SQLITE_IOERR_NOMEM
public static let SQLITE_IOERR_ACCESS = ResultCode.SQLITE_IOERR_ACCESS
public static let SQLITE_IOERR_CHECKRESERVEDLOCK = ResultCode.SQLITE_IOERR_CHECKRESERVEDLOCK
public static let SQLITE_IOERR_LOCK = ResultCode.SQLITE_IOERR_LOCK
public static let SQLITE_IOERR_CLOSE = ResultCode.SQLITE_IOERR_CLOSE
public static let SQLITE_IOERR_DIR_CLOSE = ResultCode.SQLITE_IOERR_DIR_CLOSE
public static let SQLITE_IOERR_SHMOPEN = ResultCode.SQLITE_IOERR_SHMOPEN
public static let SQLITE_IOERR_SHMSIZE = ResultCode.SQLITE_IOERR_SHMSIZE
public static let SQLITE_IOERR_SHMLOCK = ResultCode.SQLITE_IOERR_SHMLOCK
public static let SQLITE_IOERR_SHMMAP = ResultCode.SQLITE_IOERR_SHMMAP
public static let SQLITE_IOERR_SEEK = ResultCode.SQLITE_IOERR_SEEK
public static let SQLITE_IOERR_DELETE_NOENT = ResultCode.SQLITE_IOERR_DELETE_NOENT
public static let SQLITE_IOERR_MMAP = ResultCode.SQLITE_IOERR_MMAP
public static let SQLITE_IOERR_GETTEMPPATH = ResultCode.SQLITE_IOERR_GETTEMPPATH
public static let SQLITE_IOERR_CONVPATH = ResultCode.SQLITE_IOERR_CONVPATH
public static let SQLITE_IOERR_VNODE = ResultCode.SQLITE_IOERR_VNODE
public static let SQLITE_IOERR_AUTH = ResultCode.SQLITE_IOERR_AUTH
public static let SQLITE_IOERR_BEGIN_ATOMIC = ResultCode.SQLITE_IOERR_BEGIN_ATOMIC
public static let SQLITE_IOERR_COMMIT_ATOMIC = ResultCode.SQLITE_IOERR_COMMIT_ATOMIC
public static let SQLITE_IOERR_ROLLBACK_ATOMIC = ResultCode.SQLITE_IOERR_ROLLBACK_ATOMIC
public static let SQLITE_IOERR_DATA = ResultCode.SQLITE_IOERR_DATA
public static let SQLITE_IOERR_CORRUPTFS = ResultCode.SQLITE_IOERR_CORRUPTFS
public static let SQLITE_LOCKED_SHAREDCACHE = ResultCode.SQLITE_LOCKED_SHAREDCACHE
public static let SQLITE_LOCKED_VTAB = ResultCode.SQLITE_LOCKED_VTAB
public static let SQLITE_BUSY_RECOVERY = ResultCode.SQLITE_BUSY_RECOVERY
public static let SQLITE_BUSY_SNAPSHOT = ResultCode.SQLITE_BUSY_SNAPSHOT
public static let SQLITE_BUSY_TIMEOUT = ResultCode.SQLITE_BUSY_TIMEOUT
public static let SQLITE_CANTOPEN_NOTEMPDIR = ResultCode.SQLITE_CANTOPEN_NOTEMPDIR
public static let SQLITE_CANTOPEN_ISDIR = ResultCode.SQLITE_CANTOPEN_ISDIR
public static let SQLITE_CANTOPEN_FULLPATH = ResultCode.SQLITE_CANTOPEN_FULLPATH
public static let SQLITE_CANTOPEN_CONVPATH = ResultCode.SQLITE_CANTOPEN_CONVPATH
public static let SQLITE_CANTOPEN_DIRTYWAL = ResultCode.SQLITE_CANTOPEN_DIRTYWAL
public static let SQLITE_CANTOPEN_SYMLINK = ResultCode.SQLITE_CANTOPEN_SYMLINK
public static let SQLITE_CORRUPT_VTAB = ResultCode.SQLITE_CORRUPT_VTAB
public static let SQLITE_CORRUPT_SEQUENCE = ResultCode.SQLITE_CORRUPT_SEQUENCE
public static let SQLITE_CORRUPT_INDEX = ResultCode.SQLITE_CORRUPT_INDEX
public static let SQLITE_READONLY_RECOVERY = ResultCode.SQLITE_READONLY_RECOVERY
public static let SQLITE_READONLY_CANTLOCK = ResultCode.SQLITE_READONLY_CANTLOCK
public static let SQLITE_READONLY_ROLLBACK = ResultCode.SQLITE_READONLY_ROLLBACK
public static let SQLITE_READONLY_DBMOVED = ResultCode.SQLITE_READONLY_DBMOVED
public static let SQLITE_READONLY_CANTINIT = ResultCode.SQLITE_READONLY_CANTINIT
public static let SQLITE_READONLY_DIRECTORY = ResultCode.SQLITE_READONLY_DIRECTORY
public static let SQLITE_ABORT_ROLLBACK = ResultCode.SQLITE_ABORT_ROLLBACK
public static let SQLITE_CONSTRAINT_CHECK = ResultCode.SQLITE_CONSTRAINT_CHECK
public static let SQLITE_CONSTRAINT_COMMITHOOK = ResultCode.SQLITE_CONSTRAINT_COMMITHOOK
public static let SQLITE_CONSTRAINT_FOREIGNKEY = ResultCode.SQLITE_CONSTRAINT_FOREIGNKEY
public static let SQLITE_CONSTRAINT_FUNCTION = ResultCode.SQLITE_CONSTRAINT_FUNCTION
public static let SQLITE_CONSTRAINT_NOTNULL = ResultCode.SQLITE_CONSTRAINT_NOTNULL
public static let SQLITE_CONSTRAINT_PRIMARYKEY = ResultCode.SQLITE_CONSTRAINT_PRIMARYKEY
public static let SQLITE_CONSTRAINT_TRIGGER = ResultCode.SQLITE_CONSTRAINT_TRIGGER
public static let SQLITE_CONSTRAINT_UNIQUE = ResultCode.SQLITE_CONSTRAINT_UNIQUE
public static let SQLITE_CONSTRAINT_VTAB = ResultCode.SQLITE_CONSTRAINT_VTAB
public static let SQLITE_CONSTRAINT_ROWID = ResultCode.SQLITE_CONSTRAINT_ROWID
public static let SQLITE_CONSTRAINT_PINNED = ResultCode.SQLITE_CONSTRAINT_PINNED
public static let SQLITE_CONSTRAINT_DATATYPE = ResultCode.SQLITE_CONSTRAINT_DATATYPE
public static let SQLITE_NOTICE_RECOVER_WAL = ResultCode.SQLITE_NOTICE_RECOVER_WAL
public static let SQLITE_NOTICE_RECOVER_ROLLBACK = ResultCode.SQLITE_NOTICE_RECOVER_ROLLBACK
public static let SQLITE_WARNING_AUTOINDEX = ResultCode.SQLITE_WARNING_AUTOINDEX
public static let SQLITE_AUTH_USER = ResultCode.SQLITE_AUTH_USER
public static let SQLITE_OK_LOAD_PERMANENTLY = ResultCode.SQLITE_OK_LOAD_PERMANENTLY
public static let SQLITE_OK_SYMLINK = ResultCode.SQLITE_OK_SYMLINK
}
extension DatabaseError {
/// A boolean value indicating if the error has code
/// `SQLITE_ABORT` or `SQLITE_INTERRUPT`.
///
/// Such an error can be thrown when a database has been interrupted, or
/// when the database is suspended.
///
/// See ``DatabaseReader/interrupt()`` and ``Database/suspendNotification``
/// for more information.
public var isInterruptionError: Bool {
switch resultCode {
case .SQLITE_ABORT, .SQLITE_INTERRUPT:
return true
default:
return false
}
}
}
extension DatabaseError: CustomStringConvertible {
/// The error description.
///
/// For example:
///
/// SQLite error 19: NOT NULL constraint failed: player.score
/// - while executing `UPDATE player SET score = ? WHERE email = ?
///
/// The format of the error description may change between GRDB releases,
/// without notice: don't have your application rely on any specific format.
public var description: String {
var description = "SQLite error \(resultCode.rawValue)"
if let message {
description += ": \(message)"
}
if let sql {
description += " - while executing `\(sql.trimmedSQLStatement)`"
}
if publicStatementArguments, let arguments, !arguments.isEmpty {
description += " with arguments \(arguments)"
}
return description
}
/// The error description, where bound parameters, if present, are visible.
///
/// For example:
///
/// SQLite error 19: NOT NULL constraint failed: player.score
/// - while executing `UPDATE player SET score = ? WHERE email = ?
/// with arguments [nil, "arthur@example.com"]
///
/// The format of the error description may change between GRDB releases,
/// without notice: don't have your application rely on any specific format.
///
/// - warning: It is your responsibility to prevent sensitive
/// information from leaking in unexpected locations, so use this
/// property with care.
public var expandedDescription: String {
var description = "SQLite error \(resultCode.rawValue)"
if let message {
description += ": \(message)"
}
if let sql {
description += " - while executing `\(sql.trimmedSQLStatement)`"
}
if let arguments, !arguments.isEmpty {
description += " with arguments \(arguments)"
}
return description
}
}
extension DatabaseError: CustomNSError {
/// Part of the `CustomNSError` conformance.
///
/// Returns `GRDB.DatabaseError`.
public static var errorDomain: String { "GRDB.DatabaseError" }
/// Part of the `CustomNSError` conformance.
///
/// Returns the ``extendedResultCode``.
public var errorCode: Int { Int(extendedResultCode.rawValue) }
/// Part of the `CustomNSError` conformance.
public var errorUserInfo: [String: Any] {
var userInfo = [NSLocalizedDescriptionKey: description]
if let message {
userInfo[NSLocalizedFailureReasonErrorKey] = message
}
return userInfo
}
}