1#[derive(Debug, thiserror::Error)]
2#[non_exhaustive]
3pub enum Error {
4 #[error("Failed to connect to database: `{0}`")]
5 ConnectionFailed(String),
6 #[error("SQLite failure: `{1}`")]
7 SqliteFailure(std::ffi::c_int, String),
8 #[error("Null value")]
9 NullValue, #[error("API misuse: `{0}`")]
11 Misuse(String), #[error("Execute returned rows")]
13 ExecuteReturnedRows,
14 #[error("Query returned no rows")]
15 QueryReturnedNoRows,
16 #[error("Invalid column name: `{0}`")]
17 InvalidColumnName(String),
18 #[error("SQL conversion failure: `{0}`")]
19 ToSqlConversionFailure(crate::BoxError),
20 #[error("Sync is not supported in databases opened in {0} mode.")]
21 SyncNotSupported(String), #[error("Loading extension is only supported in local databases.")]
23 LoadExtensionNotSupported, #[error("Authorizer is only supported in local databases.")]
25 AuthorizerNotSupported, #[error("Column not found: {0}")]
27 ColumnNotFound(i32), #[error("Hrana: `{0}`")]
29 Hrana(crate::BoxError), #[error("Write delegation: `{0}`")]
31 WriteDelegation(crate::BoxError), #[error("bincode: `{0}`")]
33 Bincode(crate::BoxError),
34 #[error("invalid column index")]
35 InvalidColumnIndex,
36 #[error("invalid column type")]
37 InvalidColumnType,
38 #[error("syntax error around L{0}:{1}: `{2}`")]
39 Sqlite3SyntaxError(u64, usize, String),
40 #[error("unsupported statement")]
41 Sqlite3UnsupportedStatement,
42 #[error("sqlite3 parser error: `{0}`")]
43 Sqlite3ParserError(crate::BoxError),
44 #[error("Remote SQlite failure: `{0}:{1}:{2}`")]
45 RemoteSqliteFailure(i32, i32, String),
46 #[error("replication error: {0}")]
47 Replication(crate::BoxError),
48 #[error("path has invalid UTF-8")]
49 InvalidUTF8Path,
50 #[error("freeze is not supported in {0} mode.")]
51 FreezeNotSupported(String),
52 #[error("connection has reached an invalid state, started with {0}")]
53 InvalidParserState(String),
54 #[error("TLS error: {0}")]
55 InvalidTlsConfiguration(std::io::Error),
56 #[error("Transactional batch error: {0}")]
57 TransactionalBatchError(String),
58 #[error("Invalid blob size, expected {0}")]
59 InvalidBlobSize(usize),
60 #[error("sync error: {0}")]
61 Sync(crate::BoxError),
62 #[error("WAL frame insert conflict")]
63 WalConflict,
64}
65
66#[cfg(feature = "hrana")]
67impl From<crate::hrana::HranaError> for Error {
68 fn from(e: crate::hrana::HranaError) -> Self {
69 Error::Hrana(e.into())
70 }
71}
72
73#[cfg(feature = "sync")]
74impl From<crate::sync::SyncError> for Error {
75 fn from(e: crate::sync::SyncError) -> Self {
76 Error::Sync(e.into())
77 }
78}
79
80impl From<std::convert::Infallible> for Error {
81 fn from(_: std::convert::Infallible) -> Self {
82 unreachable!()
83 }
84}
85
86#[cfg(feature = "core")]
87pub(crate) fn error_from_handle(raw: *mut libsql_sys::ffi::sqlite3) -> String {
88 let errmsg = unsafe { libsql_sys::ffi::sqlite3_errmsg(raw) };
89 sqlite_errmsg_to_string(errmsg)
90}
91
92#[cfg(feature = "core")]
93pub(crate) fn extended_error_code(raw: *mut libsql_sys::ffi::sqlite3) -> std::ffi::c_int {
94 unsafe { libsql_sys::ffi::sqlite3_extended_errcode(raw) }
95}
96
97#[cfg(feature = "core")]
98pub fn error_from_code(code: i32) -> String {
99 let errmsg = unsafe { libsql_sys::ffi::sqlite3_errstr(code) };
100 sqlite_errmsg_to_string(errmsg)
101}
102
103#[cfg(feature = "core")]
104#[allow(clippy::not_unsafe_ptr_arg_deref)]
105pub fn sqlite_errmsg_to_string(errmsg: *const std::ffi::c_char) -> String {
106 let errmsg = unsafe { std::ffi::CStr::from_ptr(errmsg) }.to_bytes();
107 String::from_utf8_lossy(errmsg).to_string()
108}
109
110#[cfg(feature = "replication")]
111impl From<bincode::Error> for Error {
112 fn from(e: bincode::Error) -> Self {
113 Error::Bincode(e.into())
114 }
115}