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
use super::{IsolationLevel, ResultSet, Transaction, TransactionOptions};
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, returning the number of affected rows.
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, _: &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
where
Self: Sized,
{
/// Starts a new transaction
async fn start_transaction(&self, isolation: Option<IsolationLevel>) -> crate::Result<Transaction<'_>> {
let opts = TransactionOptions::new(isolation, self.requires_isolation_first());
Transaction::new(self, self.begin_statement(), opts).await
}
}