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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
use super::{IsolationLevel, ResultSet, Transaction};
use crate::ast::*;
use async_trait::async_trait;
pub trait GetRow {
fn get_result_row(&self) -> crate::Result<Vec<Value<'static>>>;
}
pub trait TakeRow {
fn take_result_row(&mut self) -> crate::Result<Vec<Value<'static>>>;
}
pub trait ToColumnNames {
fn to_column_names(&self) -> Vec<String>;
}
/// Represents a connection or a transaction that can be queried.
#[async_trait]
pub trait Queryable: Send + Sync {
/// Execute the given query.
async fn query(&self, q: Query<'_>) -> crate::Result<ResultSet>;
/// Execute a query given as SQL, interpolating the given parameters.
async fn query_raw(&self, sql: &str, params: &[Value<'_>]) -> crate::Result<ResultSet>;
/// Execute a query given as SQL, interpolating the given parameters.
///
/// On Postgres, query parameters types will be inferred from the values
/// instead of letting Postgres infer them based on their usage in the SQL query.
///
/// NOTE: This method will eventually be removed & merged into Queryable::query_raw().
async fn query_raw_typed(&self, sql: &str, params: &[Value<'_>]) -> crate::Result<ResultSet>;
/// Execute the given query, returning the number of affected rows.
async fn execute(&self, q: Query<'_>) -> crate::Result<u64>;
/// Execute a query given as SQL, interpolating the given parameters and
/// returning the number of affected rows.
async fn execute_raw(&self, sql: &str, params: &[Value<'_>]) -> crate::Result<u64>;
/// Execute a query given as SQL, interpolating the given parameters and
/// returning the number of affected rows.
///
/// On Postgres, query parameters types will be inferred from the values
/// instead of letting Postgres infer them based on their usage in the SQL query.
///
/// NOTE: This method will eventually be removed & merged into Queryable::query_raw().
async fn execute_raw_typed(&self, sql: &str, params: &[Value<'_>]) -> crate::Result<u64>;
/// Run a command in the database, for queries that can't be run using
/// prepared statements.
async fn raw_cmd(&self, cmd: &str) -> crate::Result<()>;
/// Return the version of the underlying database, queried directly from the
/// source. This corresponds to the `version()` function on PostgreSQL for
/// example. The version string is returned directly without any form of
/// parsing or normalization.
async fn version(&self) -> crate::Result<Option<String>>;
/// Returns false, if connection is considered to not be in a working state.
fn is_healthy(&self) -> bool;
/// Execute a `SELECT` query.
async fn select(&self, q: Select<'_>) -> crate::Result<ResultSet> {
self.query(q.into()).await
}
/// Execute an `INSERT` query.
async fn insert(&self, q: Insert<'_>) -> crate::Result<ResultSet> {
self.query(q.into()).await
}
/// Execute an `UPDATE` query, returning the number of affected rows.
async fn update(&self, q: Update<'_>) -> crate::Result<u64> {
self.execute(q.into()).await
}
/// Execute a `DELETE` query.
async fn delete(&self, q: Delete<'_>) -> crate::Result<()> {
self.query(q.into()).await?;
Ok(())
}
/// Execute an arbitrary function in the beginning of each transaction.
async fn server_reset_query(&self, _: &dyn Transaction) -> crate::Result<()> {
Ok(())
}
/// Statement to begin a transaction
fn begin_statement(&self) -> &'static str {
"BEGIN"
}
/// Sets the transaction isolation level to given value.
/// Implementers have to make sure that the passed isolation level is valid for the underlying database.
async fn set_tx_isolation_level(&self, isolation_level: IsolationLevel) -> crate::Result<()>;
/// Signals if the isolation level SET needs to happen before or after the tx BEGIN.
fn requires_isolation_first(&self) -> bool;
}
/// A thing that can start a new transaction.
#[async_trait]
pub trait TransactionCapable: Queryable {
/// Starts a new transaction
async fn start_transaction<'a>(
&'a self,
isolation: Option<IsolationLevel>,
) -> crate::Result<Box<dyn Transaction + 'a>>;
}
macro_rules! impl_default_TransactionCapable {
($t:ty) => {
#[async_trait]
impl TransactionCapable for $t {
async fn start_transaction<'a>(
&'a self,
isolation: Option<IsolationLevel>,
) -> crate::Result<Box<dyn crate::connector::Transaction + 'a>> {
let opts = crate::connector::TransactionOptions::new(isolation, self.requires_isolation_first());
Ok(Box::new(
crate::connector::DefaultTransaction::new(self, self.begin_statement(), opts).await?,
))
}
}
};
}
pub(crate) use impl_default_TransactionCapable;