From 532b9cbcdb148fa413dfbf0189b739c93b0e749c Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Thu, 26 Jun 2025 09:45:58 +0300 Subject: [PATCH] bindings/rust: API documentation --- bindings/rust/src/lib.rs | 55 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 402ee1c19..69e8dcecf 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -1,3 +1,34 @@ +//! # Limbo bindings for Rust +//! +//! Limbo is an in-process SQL database engine, compatible with SQLite. +//! +//! ## Getting Started +//! +//! To get started, you first need to create a [`Database`] object and then open a [`Connection`] to it, which you use to query: +//! +//! ```rust,no_run +//! # async fn run() { +//! use limbo::Builder; +//! +//! let db = Builder::new_local(":memory:").build().await.unwrap(); +//! let conn = db.connect().unwrap(); +//! conn.execute("CREATE TABLE IF NOT EXISTS users (email TEXT)", ()).await.unwrap(); +//! conn.execute("INSERT INTO users (email) VALUES ('alice@example.org')", ()).await.unwrap(); +//! # } +//! ``` +//! +//! You can also prepare statements with the [`Connection`] object and then execute the [`Statement`] objects: +//! +//! ```rust,no_run +//! # async fn run() { +//! let stmt = conn.prepare("SELECT * FROM users WHERE email = ?1").await.unwrap()a +//! let mut rows = stmt.query(["foo@example.com"]).await.unwrap(); +//! let row = rows.next().await.unwrap().unwrap(); +//! let value = row.get_value(0).unwrap(); +//! println!("Row: {:?}", value); +//! # } +//! ``` + pub mod params; pub mod value; @@ -29,17 +60,21 @@ impl From for Error { pub(crate) type BoxError = Box; pub type Result = std::result::Result; + +/// A builder for `Database`. pub struct Builder { path: String, } impl Builder { + /// Create a new local database. pub fn new_local(path: &str) -> Self { Self { path: path.to_string(), } } + /// Build the database. #[allow(unused_variables, clippy::arc_with_non_send_sync)] pub async fn build(self) -> Result { match self.path.as_str() { @@ -57,6 +92,9 @@ impl Builder { } } +/// A database. +/// +/// The `Database` object points to a database and allows you to connect to it #[derive(Clone)] pub struct Database { inner: Arc, @@ -72,6 +110,7 @@ impl Debug for Database { } impl Database { + /// Connect to the database. pub fn connect(&self) -> Result { let conn = self.inner.connect()?; #[allow(clippy::arc_with_non_send_sync)] @@ -82,6 +121,7 @@ impl Database { } } +/// A database connection. pub struct Connection { inner: Arc>>, } @@ -98,16 +138,19 @@ unsafe impl Send for Connection {} unsafe impl Sync for Connection {} impl Connection { + /// Query the database with SQL. pub async fn query(&self, sql: &str, params: impl IntoParams) -> Result { let mut stmt = self.prepare(sql).await?; stmt.query(params).await } + /// Execute SQL statement on the database. pub async fn execute(&self, sql: &str, params: impl IntoParams) -> Result { let mut stmt = self.prepare(sql).await?; stmt.execute(params).await } + /// Prepare a SQL statement for later execution. pub async fn prepare(&self, sql: &str) -> Result { let conn = self .inner @@ -123,6 +166,7 @@ impl Connection { Ok(statement) } + /// Query a pragma. pub fn pragma_query(&self, pragma_name: &str, mut f: F) -> Result<()> where F: FnMut(&Row) -> limbo_core::Result<()>, @@ -154,6 +198,7 @@ impl Debug for Connection { } } +/// A prepared statement. pub struct Statement { inner: Arc>, } @@ -170,6 +215,7 @@ unsafe impl Send for Statement {} unsafe impl Sync for Statement {} impl Statement { + /// Query the database with this prepared statement. pub async fn query(&mut self, params: impl IntoParams) -> Result { let params = params.into_params()?; match params { @@ -189,6 +235,7 @@ impl Statement { Ok(rows) } + /// Execute this prepared statement. pub async fn execute(&mut self, params: impl IntoParams) -> Result { { // Reset the statement before executing @@ -232,6 +279,7 @@ impl Statement { } } + /// Returns columns of the result of this prepared statement. pub fn columns(&self) -> Vec { let stmt = self.inner.lock().unwrap(); @@ -251,16 +299,19 @@ impl Statement { } } +/// Column information. pub struct Column { name: String, decl_type: Option, } impl Column { + /// Return the name of the column. pub fn name(&self) -> &str { &self.name } + /// Returns the type of the column. pub fn decl_type(&self) -> Option<&str> { self.decl_type.as_deref() } @@ -276,8 +327,10 @@ pub enum Params { Positional(Vec), Named(Vec<(String, Value)>), } + pub struct Transaction {} +/// Results of a prepared statement query. pub struct Rows { inner: Arc>, } @@ -294,6 +347,7 @@ unsafe impl Send for Rows {} unsafe impl Sync for Rows {} impl Rows { + /// Fetch the next row of this result set. pub async fn next(&mut self) -> Result> { loop { let mut stmt = self @@ -322,6 +376,7 @@ impl Rows { } } +/// Query result row. #[derive(Debug)] pub struct Row { values: Vec,