1mod backup;
4mod database;
5mod lru_cache;
6mod session;
7mod sql_tag_store;
8mod statement;
9mod validators;
10
11pub use backup::op_node_database_backup;
12pub use database::DatabaseSync;
13pub use session::Session;
14pub use sql_tag_store::SQLTagStore;
15pub use statement::StatementSync;
16
17deno_core::extension!(
18 deno_node_sqlite,
19 ops = [op_node_database_backup,],
20 objects = [DatabaseSync, Session, SQLTagStore, StatementSync,],
21);
22
23#[derive(Debug, thiserror::Error, deno_error::JsError)]
24pub enum SqliteError {
25 #[class(inherit)]
26 #[error(transparent)]
27 #[property("code" = self.code())]
28 Permission(#[from] deno_permissions::PermissionCheckError),
29 #[class(generic)]
30 #[error(transparent)]
31 #[property("code" = self.code())]
32 SqliteError(#[from] rusqlite::Error),
33 #[class(generic)]
34 #[error("{message}")]
35 #[property("code" = self.code())]
36 #[property("errstr" = self.errstr())]
37 SqliteSysError {
38 message: String,
39 errstr: String,
40 #[property]
41 errcode: f64,
42 },
43 #[class(generic)]
44 #[error("Database is already in use")]
45 #[property("code" = self.code())]
46 InUse,
47 #[class(generic)]
48 #[error("Failed to load SQLite extension: {0}")]
49 #[property("code" = self.code())]
50 LoadExensionFailed(String),
51 #[class(generic)]
52 #[error("Failed to bind parameter. {0}")]
53 #[property("code" = self.code())]
54 FailedBind(&'static str),
55 #[class(type)]
56 #[error("Provided value cannot be bound to SQLite parameter {0}.")]
57 #[property("code" = self.code())]
58 InvalidBindType(i32),
59 #[class(type)]
60 #[error("{0}")]
61 #[property("code" = self.code())]
62 InvalidBindValue(&'static str),
63 #[class(generic)]
64 #[error(
65 "Cannot create bare named parameter '{0}' because of conflicting names '{1}' and '{2}'."
66 )]
67 #[property("code" = self.code())]
68 DuplicateNamedParameter(String, String, String),
69 #[class(generic)]
70 #[error("Unknown named parameter '{0}'")]
71 #[property("code" = self.code())]
72 UnknownNamedParameter(String),
73 #[class(generic)]
74 #[error("unknown column type")]
75 #[property("code" = self.code())]
76 UnknownColumnType,
77 #[class(generic)]
78 #[error("failed to get SQL")]
79 #[property("code" = self.code())]
80 GetSqlFailed,
81 #[class(generic)]
82 #[error("database is not open")]
83 #[property("code" = self.code())]
84 AlreadyClosed,
85 #[class(generic)]
86 #[error("database is already open")]
87 #[property("code" = self.code())]
88 AlreadyOpen,
89 #[class(generic)]
90 #[error("failed to create session")]
91 #[property("code" = self.code())]
92 SessionCreateFailed,
93 #[class(generic)]
94 #[error("failed to retrieve changeset")]
95 #[property("code" = self.code())]
96 SessionChangesetFailed,
97 #[class(generic)]
98 #[error("session is not open")]
99 #[property("code" = self.code())]
100 SessionClosed,
101 #[class(type)]
102 #[error("Illegal constructor")]
103 #[property("code" = self.code())]
104 InvalidConstructor,
105 #[class(generic)]
106 #[error("Expanded SQL text would exceed configured limits")]
107 #[property("code" = self.code())]
108 InvalidExpandedSql,
109 #[class(range)]
110 #[error("Value is too large to be represented as a JavaScript number: {0}")]
111 #[property("code" = self.code())]
112 NumberTooLarge(i64),
113 #[class(type)]
114 #[error("Invalid callback: {0}")]
115 #[property("code" = self.code())]
116 InvalidCallback(&'static str),
117 #[class(type)]
118 #[error("FromUtf8Error: {0}")]
119 #[property("code" = self.code())]
120 FromNullError(#[from] std::ffi::NulError),
121 #[class(type)]
122 #[error("FromUtf8Error: {0}")]
123 #[property("code" = self.code())]
124 FromUtf8Error(#[from] std::str::Utf8Error),
125 #[class(inherit)]
126 #[error(transparent)]
127 #[property("code" = self.code())]
128 Validation(#[from] validators::Error),
129 #[class(generic)]
130 #[error("statement has been finalized")]
131 #[property("code" = self.code())]
132 StatementFinalized,
133}
134
135#[derive(Debug, PartialEq, Eq)]
136#[allow(non_camel_case_types)]
137enum ErrorCode {
138 ERR_SQLITE_ERROR,
139 ERR_ILLEGAL_CONSTRUCTOR,
140 ERR_INVALID_STATE,
141 ERR_OUT_OF_RANGE,
142 ERR_LOAD_SQLITE_EXTENSION,
143 ERR_INVALID_ARG_TYPE,
144 ERR_INVALID_ARG_VALUE,
145}
146
147impl std::fmt::Display for ErrorCode {
148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149 write!(f, "{}", self.as_str())
150 }
151}
152
153impl ErrorCode {
154 pub fn as_str(&self) -> &str {
155 match self {
156 Self::ERR_SQLITE_ERROR => "ERR_SQLITE_ERROR",
157 Self::ERR_ILLEGAL_CONSTRUCTOR => "ERR_ILLEGAL_CONSTRUCTOR",
158 Self::ERR_INVALID_ARG_TYPE => "ERR_INVALID_ARG_TYPE",
159 Self::ERR_INVALID_ARG_VALUE => "ERR_INVALID_ARG_VALUE",
160 Self::ERR_INVALID_STATE => "ERR_INVALID_STATE",
161 Self::ERR_OUT_OF_RANGE => "ERR_OUT_OF_RANGE",
162 Self::ERR_LOAD_SQLITE_EXTENSION => "ERR_LOAD_SQLITE_EXTENSION",
163 }
164 }
165}
166
167impl From<ErrorCode> for deno_error::PropertyValue {
168 fn from(code: ErrorCode) -> Self {
169 deno_error::PropertyValue::from(code.as_str().to_string())
170 }
171}
172
173impl SqliteError {
174 fn errstr(&self) -> String {
175 match self {
176 Self::SqliteSysError { errstr, .. } => errstr.clone(),
177 _ => unreachable!(),
178 }
179 }
180
181 fn code(&self) -> ErrorCode {
182 match self {
183 Self::InvalidConstructor => ErrorCode::ERR_ILLEGAL_CONSTRUCTOR,
184 Self::InvalidBindType(_) => ErrorCode::ERR_INVALID_ARG_TYPE,
185 Self::InvalidBindValue(_) => ErrorCode::ERR_INVALID_ARG_VALUE,
186 Self::FailedBind(_)
187 | Self::UnknownNamedParameter(_)
188 | Self::DuplicateNamedParameter(..)
189 | Self::AlreadyClosed
190 | Self::InUse
191 | Self::AlreadyOpen
192 | Self::StatementFinalized => ErrorCode::ERR_INVALID_STATE,
193 Self::NumberTooLarge(_) => ErrorCode::ERR_OUT_OF_RANGE,
194 Self::LoadExensionFailed(_) => ErrorCode::ERR_LOAD_SQLITE_EXTENSION,
195 _ => ErrorCode::ERR_SQLITE_ERROR,
196 }
197 }
198}