Skip to main content

deno_node_sqlite/
lib.rs

1// Copyright 2018-2026 the Deno authors. MIT license.
2
3mod 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}