1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
use std::sync::Arc;
use crate::params::{IntoParams, Params};
use crate::rows::Rows;
use crate::statement::Statement;
use crate::transaction::Transaction;
use crate::{Result, TransactionBehavior};
#[async_trait::async_trait]
pub(crate) trait Conn {
async fn execute(&self, sql: &str, params: Params) -> Result<u64>;
async fn execute_batch(&self, sql: &str) -> Result<()>;
async fn prepare(&self, sql: &str) -> Result<Statement>;
async fn transaction(&self, tx_behavior: TransactionBehavior) -> Result<Transaction>;
fn is_autocommit(&self) -> bool;
fn changes(&self) -> u64;
fn last_insert_rowid(&self) -> i64;
}
/// A connection to some libsql database, this can be a remote one or a local one.
#[derive(Clone)]
pub struct Connection {
pub(crate) conn: Arc<dyn Conn + Send + Sync>,
}
impl Connection {
/// Execute sql query provided some type that implements [`IntoParams`] returning
/// on success the number of rows that were changed.
///
/// # Example
///
/// ```rust,no_run
/// # async fn run(conn: &libsql::Connection) {
/// # use libsql::params;
/// conn.execute("INSERT INTO foo (id) VALUES (?1)", [42]).await.unwrap();
/// conn.execute("INSERT INTO foo (id, name) VALUES (?1, ?2)", params![42, "baz"]).await.unwrap();
/// # }
/// ```
///
/// For more info on how to pass params check [`IntoParams`]'s docs.
pub async fn execute(&self, sql: &str, params: impl IntoParams) -> Result<u64> {
tracing::trace!("executing `{}`", sql);
self.conn.execute(sql, params.into_params()?).await
}
/// Execute a batch set of statements.
pub async fn execute_batch(&self, sql: &str) -> Result<()> {
tracing::trace!("executing batch `{}`", sql);
self.conn.execute_batch(sql).await
}
/// Execute sql query provided some type that implements [`IntoParams`] returning
/// on success the [`Rows`].
///
/// # Example
///
/// ```rust,no_run
/// # async fn run(conn: &libsql::Connection) {
/// # use libsql::params;
/// conn.query("SELECT foo FROM bar WHERE id = ?1", [42]).await.unwrap();
/// conn.query("SELECT foo FROM bar WHERE id = ?1 AND name = ?2", params![42, "baz"]).await.unwrap();
/// # }
/// ```
/// For more info on how to pass params check [`IntoParams`]'s docs and on how to
/// extract values out of the rows check the [`Rows`] docs.
pub async fn query(&self, sql: &str, params: impl IntoParams) -> Result<Rows> {
let mut stmt = self.prepare(sql).await?;
stmt.query(params).await
}
/// Prepares a cached statement.
pub async fn prepare(&self, sql: &str) -> Result<Statement> {
tracing::trace!("preparing `{}`", sql);
self.conn.prepare(sql).await
}
/// Begin a new transaction in `DEFERRED` mode, which is the default.
pub async fn transaction(&self) -> Result<Transaction> {
tracing::trace!("starting deferred transaction");
self.transaction_with_behavior(TransactionBehavior::Deferred)
.await
}
/// Begin a new transaction in the given [`TransactionBehavior`].
pub async fn transaction_with_behavior(
&self,
tx_behavior: TransactionBehavior,
) -> Result<Transaction> {
tracing::trace!("starting {:?} transaction", tx_behavior);
self.conn.transaction(tx_behavior).await
}
/// Check weather libsql is in `autocommit` or not.
pub fn is_autocommit(&self) -> bool {
self.conn.is_autocommit()
}
/// Check the amount of changes the last query created.
pub fn changes(&self) -> u64 {
self.conn.changes()
}
/// Check the last inserted row id.
pub fn last_insert_rowid(&self) -> i64 {
self.conn.last_insert_rowid()
}
}