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;