rquickjs_extra_sqlite/
database.rs1use rquickjs::{class::Trace, Ctx, JsLifetime, Result};
2use rquickjs_extra_utils::result::ResultExt;
3use sqlx::{Executor, SqlitePool};
4
5use super::Statement;
6
7#[derive(Clone, Trace, JsLifetime)]
8#[rquickjs::class]
9pub struct Database {
10 #[qjs(skip_trace)]
11 pool: SqlitePool,
12}
13
14impl Database {
15 pub fn new(pool: SqlitePool) -> Self {
16 Self { pool }
17 }
18}
19
20#[rquickjs::methods(rename_all = "camelCase")]
21impl Database {
22 async fn exec(&self, ctx: Ctx<'_>, sql: String) -> Result<()> {
23 sqlx::raw_sql(&sql)
24 .execute(&self.pool)
25 .await
26 .or_throw(&ctx)?;
27 Ok(())
28 }
29
30 async fn prepare(&self, ctx: Ctx<'_>, sql: String) -> Result<Statement> {
31 let stmt = sqlx::Statement::to_owned(&self.pool.prepare(&sql).await.or_throw(&ctx)?);
32 Ok(Statement::new(stmt, self.pool.clone()))
33 }
34
35 async fn close(&mut self) -> Result<()> {
36 self.pool.close().await;
37 Ok(())
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use rquickjs::CatchResultExt;
44 use rquickjs_extra_test::{call_test, test_async_with, ModuleEvaluator};
45
46 use crate::SqliteModule;
47
48 #[tokio::test]
49 async fn test_database_exec() {
50 test_async_with(|ctx| {
51 Box::pin(async move {
52 ModuleEvaluator::eval_rust::<SqliteModule>(ctx.clone(), "sqlite")
53 .await
54 .unwrap();
55
56 let module = ModuleEvaluator::eval_js(
57 ctx.clone(),
58 "test",
59 r#"
60 import { open } from "sqlite";
61
62 export async function test() {
63 const db = await open({ inMemory: true });
64 await db.exec("CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT);");
65 await db.exec("INSERT INTO test (name) VALUES ('test');");
66 return "ok";
67 }
68 "#,
69 )
70 .await
71 .catch(&ctx)
72 .unwrap();
73
74 let result = call_test::<String, _>(&ctx, &module, ()).await;
75 assert_eq!(result, "ok");
76 })
77 })
78 .await;
79 }
80
81 #[tokio::test]
82 async fn test_database_close() {
83 test_async_with(|ctx| {
84 Box::pin(async move {
85 ModuleEvaluator::eval_rust::<SqliteModule>(ctx.clone(), "sqlite")
86 .await
87 .unwrap();
88
89 let module = ModuleEvaluator::eval_js(
90 ctx.clone(),
91 "test",
92 r#"
93 import { open } from "sqlite";
94
95 export async function test() {
96 const db = await open({ inMemory: true });
97 await db.exec("CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT);");
98 await db.close();
99 return "ok";
100 }
101 "#,
102 )
103 .await
104 .catch(&ctx)
105 .unwrap();
106
107 let result = call_test::<String, _>(&ctx, &module, ()).await;
108 assert_eq!(result, "ok");
109 })
110 })
111 .await;
112 }
113}