quaint_forked/connector/sqlite/
error.rs

1use crate::error::*;
2use libsqlite3_sys as ffi;
3use rusqlite::types::FromSqlError;
4
5impl From<rusqlite::Error> for Error {
6    fn from(e: rusqlite::Error) -> Error {
7        match e {
8            rusqlite::Error::ToSqlConversionFailure(error) => match error.downcast::<Error>() {
9                Ok(error) => *error,
10                Err(error) => {
11                    let mut builder = Error::builder(ErrorKind::QueryError(error));
12
13                    builder.set_original_message("Could not interpret parameters in an SQLite query.");
14
15                    builder.build()
16                }
17            },
18            rusqlite::Error::InvalidQuery => {
19                let mut builder = Error::builder(ErrorKind::QueryError(e.into()));
20
21                builder.set_original_message(
22                    "Could not interpret the query or its parameters. Check the syntax and parameter types.",
23                );
24
25                builder.build()
26            }
27            rusqlite::Error::ExecuteReturnedResults => {
28                let mut builder = Error::builder(ErrorKind::QueryError(e.into()));
29                builder.set_original_message("Execute returned results, which is not allowed in SQLite.");
30
31                builder.build()
32            }
33
34            rusqlite::Error::QueryReturnedNoRows => Error::builder(ErrorKind::NotFound).build(),
35
36            rusqlite::Error::SqliteFailure(
37                ffi::Error {
38                    code: ffi::ErrorCode::ConstraintViolation,
39                    extended_code: 2067,
40                },
41                Some(description),
42            ) => {
43                let constraint = description
44                    .split(": ")
45                    .nth(1)
46                    .map(|s| s.split(", "))
47                    .map(|i| i.flat_map(|s| s.split('.').last()))
48                    .map(DatabaseConstraint::fields)
49                    .unwrap_or(DatabaseConstraint::CannotParse);
50
51                let kind = ErrorKind::UniqueConstraintViolation { constraint };
52                let mut builder = Error::builder(kind);
53
54                builder.set_original_code("2067");
55                builder.set_original_message(description);
56
57                builder.build()
58            }
59
60            rusqlite::Error::SqliteFailure(
61                ffi::Error {
62                    code: ffi::ErrorCode::ConstraintViolation,
63                    extended_code: 1555,
64                },
65                Some(description),
66            ) => {
67                let constraint = description
68                    .split(": ")
69                    .nth(1)
70                    .map(|s| s.split(", "))
71                    .map(|i| i.flat_map(|s| s.split('.').last()))
72                    .map(DatabaseConstraint::fields)
73                    .unwrap_or(DatabaseConstraint::CannotParse);
74
75                let kind = ErrorKind::UniqueConstraintViolation { constraint };
76                let mut builder = Error::builder(kind);
77
78                builder.set_original_code("1555");
79                builder.set_original_message(description);
80
81                builder.build()
82            }
83
84            rusqlite::Error::SqliteFailure(
85                ffi::Error {
86                    code: ffi::ErrorCode::ConstraintViolation,
87                    extended_code: 1299,
88                },
89                Some(description),
90            ) => {
91                let constraint = description
92                    .split(": ")
93                    .nth(1)
94                    .map(|s| s.split(", "))
95                    .map(|i| i.flat_map(|s| s.split('.').last()))
96                    .map(DatabaseConstraint::fields)
97                    .unwrap_or(DatabaseConstraint::CannotParse);
98
99                let kind = ErrorKind::NullConstraintViolation { constraint };
100                let mut builder = Error::builder(kind);
101
102                builder.set_original_code("1299");
103                builder.set_original_message(description);
104
105                builder.build()
106            }
107
108            rusqlite::Error::SqliteFailure(
109                ffi::Error {
110                    code: ffi::ErrorCode::ConstraintViolation,
111                    extended_code: 787,
112                },
113                Some(description),
114            ) => {
115                let mut builder = Error::builder(ErrorKind::ForeignKeyConstraintViolation {
116                    constraint: DatabaseConstraint::ForeignKey,
117                });
118
119                builder.set_original_code("787");
120                builder.set_original_message(description);
121
122                builder.build()
123            }
124
125            rusqlite::Error::SqliteFailure(
126                ffi::Error {
127                    code: ffi::ErrorCode::ConstraintViolation,
128                    extended_code: 1811,
129                },
130                Some(description),
131            ) => {
132                let mut builder = Error::builder(ErrorKind::ForeignKeyConstraintViolation {
133                    constraint: DatabaseConstraint::ForeignKey,
134                });
135
136                builder.set_original_code("1811");
137                builder.set_original_message(description);
138
139                builder.build()
140            }
141
142            rusqlite::Error::SqliteFailure(
143                ffi::Error {
144                    code: ffi::ErrorCode::DatabaseBusy,
145                    extended_code,
146                },
147                description,
148            ) => {
149                let mut builder = Error::builder(ErrorKind::SocketTimeout);
150                builder.set_original_code(format!("{extended_code}"));
151
152                if let Some(description) = description {
153                    builder.set_original_message(description);
154                }
155
156                builder.build()
157            }
158
159            rusqlite::Error::SqliteFailure(ffi::Error { extended_code, .. }, ref description) => match description {
160                Some(d) if d.starts_with("no such table") => {
161                    let table = d.split(": ").last().into();
162                    let kind = ErrorKind::TableDoesNotExist { table };
163
164                    let mut builder = Error::builder(kind);
165                    builder.set_original_code(format!("{extended_code}"));
166                    builder.set_original_message(d);
167
168                    builder.build()
169                }
170                Some(d) if d.contains("has no column named") => {
171                    let column = d.split(" has no column named ").last().into();
172                    let kind = ErrorKind::ColumnNotFound { column };
173
174                    let mut builder = Error::builder(kind);
175                    builder.set_original_code(format!("{extended_code}"));
176                    builder.set_original_message(d);
177
178                    builder.build()
179                }
180                Some(d) if d.starts_with("no such column: ") => {
181                    let column = d.split("no such column: ").last().into();
182                    let kind = ErrorKind::ColumnNotFound { column };
183
184                    let mut builder = Error::builder(kind);
185                    builder.set_original_code(format!("{extended_code}"));
186                    builder.set_original_message(d);
187
188                    builder.build()
189                }
190                _ => {
191                    let description = description.as_ref().map(|d| d.to_string());
192                    let mut builder = Error::builder(ErrorKind::QueryError(e.into()));
193                    builder.set_original_code(format!("{extended_code}"));
194
195                    if let Some(description) = description {
196                        builder.set_original_message(description);
197                    }
198
199                    builder.build()
200                }
201            },
202            e => Error::builder(ErrorKind::QueryError(e.into())).build(),
203        }
204    }
205}
206
207impl From<FromSqlError> for Error {
208    fn from(e: FromSqlError) -> Error {
209        Error::builder(ErrorKind::ColumnReadFailure(e.into())).build()
210    }
211}