• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / edge-runtime / 16259269683

14 Jul 2025 06:04AM UTC coverage: 51.235% (-0.5%) from 51.764%
16259269683

push

github

web-flow
feat: add v2.2.0 `node:sqlite` support (#557)

* chore: add dependencies

* chore: update `Cargo.lock`

* feat: v2.2.0 `node:sqlite` support

* stamp: perm check

0 of 362 new or added lines in 2 files covered. (0.0%)

3 existing lines in 3 files now uncovered.

18235 of 35591 relevant lines covered (51.23%)

5490.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/ext/node/ops/sqlite/database.rs
1
// Copyright 2018-2025 the Deno authors. MIT license.
2

3
use std::cell::Cell;
4
use std::cell::RefCell;
5
use std::rc::Rc;
6

7
use deno_core::anyhow;
8
use deno_core::anyhow::anyhow;
9
use deno_core::op2;
10
use deno_core::GarbageCollected;
11
use deno_core::OpState;
12
use deno_permissions::PermissionsContainer;
13
use serde::Deserialize;
14

15
use super::StatementSync;
16

NEW
17
#[derive(Deserialize)]
×
18
#[serde(rename_all = "camelCase")]
19
struct DatabaseSyncOptions {
20
  #[serde(default = "true_fn")]
21
  open: bool,
22
  #[serde(default = "true_fn")]
23
  enable_foreign_key_constraints: bool,
24
  read_only: bool,
25
}
26

NEW
27
fn true_fn() -> bool {
×
NEW
28
  true
×
NEW
29
}
×
30

31
impl Default for DatabaseSyncOptions {
NEW
32
  fn default() -> Self {
×
NEW
33
    DatabaseSyncOptions {
×
NEW
34
      open: true,
×
NEW
35
      enable_foreign_key_constraints: true,
×
NEW
36
      read_only: false,
×
NEW
37
    }
×
NEW
38
  }
×
39
}
40

41
pub struct DatabaseSync {
42
  conn: Rc<RefCell<Option<rusqlite::Connection>>>,
43
  options: DatabaseSyncOptions,
44
  location: String,
45
}
46

47
impl GarbageCollected for DatabaseSync {}
48

NEW
49
fn open_db(
×
NEW
50
  state: &mut OpState,
×
NEW
51
  readonly: bool,
×
NEW
52
  location: &str,
×
NEW
53
) -> Result<rusqlite::Connection, anyhow::Error> {
×
NEW
54
  if location == ":memory:" {
×
NEW
55
    return Ok(rusqlite::Connection::open_in_memory()?);
×
NEW
56
  }
×
NEW
57

×
NEW
58
  state
×
NEW
59
    .borrow::<PermissionsContainer>()
×
NEW
60
    .check_read_with_api_name(location, Some("node:sqlite"))?;
×
61

NEW
62
  if readonly {
×
NEW
63
    return Ok(rusqlite::Connection::open_with_flags(
×
NEW
64
      location,
×
NEW
65
      rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY,
×
NEW
66
    )?);
×
NEW
67
  }
×
NEW
68

×
NEW
69
  state
×
NEW
70
    .borrow::<PermissionsContainer>()
×
NEW
71
    .check_write_with_api_name(location, Some("node:sqlite"))?;
×
72

NEW
73
  Ok(rusqlite::Connection::open(location)?)
×
NEW
74
}
×
75

76
// Represents a single connection to a SQLite database.
NEW
77
#[op2]
×
78
impl DatabaseSync {
79
  // Constructs a new `DatabaseSync` instance.
80
  //
81
  // A SQLite database can be stored in a file or in memory. To
82
  // use a file-backed database, the `location` should be a path.
83
  // To use an in-memory database, the `location` should be special
84
  // name ":memory:".
85
  #[constructor]
86
  #[cppgc]
NEW
87
  fn new(
×
NEW
88
    state: &mut OpState,
×
NEW
89
    #[string] location: String,
×
NEW
90
    #[serde] options: Option<DatabaseSyncOptions>,
×
NEW
91
  ) -> Result<DatabaseSync, anyhow::Error> {
×
NEW
92
    let options = options.unwrap_or_default();
×
93

NEW
94
    let db = if options.open {
×
NEW
95
      let db = open_db(state, options.read_only, &location)?;
×
96

NEW
97
      if options.enable_foreign_key_constraints {
×
NEW
98
        db.execute("PRAGMA foreign_keys = ON", [])?;
×
NEW
99
      }
×
NEW
100
      Some(db)
×
101
    } else {
NEW
102
      None
×
103
    };
104

NEW
105
    Ok(DatabaseSync {
×
NEW
106
      conn: Rc::new(RefCell::new(db)),
×
NEW
107
      location,
×
NEW
108
      options,
×
NEW
109
    })
×
NEW
110
  }
×
111

112
  // Opens the database specified by `location` of this instance.
113
  //
114
  // This method should only be used when the database is not opened
115
  // via the constructor. An exception is thrown if the database is
116
  // already opened.
117
  #[fast]
NEW
118
  fn open(&self, state: &mut OpState) -> Result<(), anyhow::Error> {
×
NEW
119
    if self.conn.borrow().is_some() {
×
NEW
120
      return Err(anyhow!("Database is already open"));
×
NEW
121
    }
×
122

NEW
123
    let db = open_db(state, self.options.read_only, &self.location)?;
×
NEW
124
    if self.options.enable_foreign_key_constraints {
×
NEW
125
      db.execute("PRAGMA foreign_keys = ON", [])?;
×
NEW
126
    }
×
127

NEW
128
    *self.conn.borrow_mut() = Some(db);
×
NEW
129

×
NEW
130
    Ok(())
×
NEW
131
  }
×
132

133
  // Closes the database connection. An exception is thrown if the
134
  // database is not open.
135
  #[fast]
NEW
136
  fn close(&self) -> Result<(), anyhow::Error> {
×
NEW
137
    if self.conn.borrow().is_none() {
×
NEW
138
      return Err(anyhow!("Database is already closed"));
×
NEW
139
    }
×
NEW
140

×
NEW
141
    *self.conn.borrow_mut() = None;
×
NEW
142
    Ok(())
×
NEW
143
  }
×
144

145
  // This method allows one or more SQL statements to be executed
146
  // without returning any results.
147
  //
148
  // This method is a wrapper around sqlite3_exec().
149
  #[fast]
NEW
150
  fn exec(&self, #[string] sql: &str) -> Result<(), anyhow::Error> {
×
NEW
151
    let db = self.conn.borrow();
×
NEW
152
    let db = db.as_ref().ok_or(anyhow!("Database is already in use"))?;
×
153

NEW
154
    let mut stmt = db.prepare_cached(sql)?;
×
NEW
155
    stmt.raw_execute()?;
×
156

NEW
157
    Ok(())
×
NEW
158
  }
×
159

160
  // Compiles an SQL statement into a prepared statement.
161
  //
162
  // This method is a wrapper around `sqlite3_prepare_v2()`.
163
  #[cppgc]
NEW
164
  fn prepare(
×
NEW
165
    &self,
×
NEW
166
    #[string] sql: &str,
×
NEW
167
  ) -> Result<StatementSync, anyhow::Error> {
×
NEW
168
    let db = self.conn.borrow();
×
NEW
169
    let db = db.as_ref().ok_or(anyhow!("Database is already in use"))?;
×
170

171
    // SAFETY: lifetime of the connection is guaranteed by reference
172
    // counting.
NEW
173
    let raw_handle = unsafe { db.handle() };
×
NEW
174

×
NEW
175
    let mut raw_stmt = std::ptr::null_mut();
×
NEW
176

×
NEW
177
    // SAFETY: `sql` points to a valid memory location and its length
×
NEW
178
    // is correct.
×
NEW
179
    let r = unsafe {
×
NEW
180
      libsqlite3_sys::sqlite3_prepare_v2(
×
NEW
181
        raw_handle,
×
NEW
182
        sql.as_ptr() as *const _,
×
NEW
183
        sql.len() as i32,
×
NEW
184
        &mut raw_stmt,
×
NEW
185
        std::ptr::null_mut(),
×
NEW
186
      )
×
NEW
187
    };
×
NEW
188

×
NEW
189
    if r != libsqlite3_sys::SQLITE_OK {
×
NEW
190
      return Err(anyhow!("Failed to prepare statement"));
×
NEW
191
    }
×
NEW
192

×
NEW
193
    Ok(StatementSync {
×
NEW
194
      inner: raw_stmt,
×
NEW
195
      db: self.conn.clone(),
×
NEW
196
      use_big_ints: Cell::new(false),
×
NEW
197
    })
×
NEW
198
  }
×
199
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc