Skip to content

Add ConnectionLike trait for Connection and Transaction in tokio-postgres #329

Closed
@asonix

Description

@asonix

This would allow for reusable functions that query for data, but can be used on a connection or a transaction.

A basic idea would be the following

trait ConnectionLike {
    fn batch_execute(self, query: &str) -> Box<Future<Item = Self, Error = (Error, Self)> + Send>;
    fn execute(self, query: &str) -> Box<Future<Item = Self, Error = (Error, Self)> + Send>;
    fn prepare(self, query: &str) -> Box<Future<Item = (Statement, Self), Error = (Error, Self)> + Send>;
    fn execute(self, statement: &Statement, params: &[&ToSql]) -> Box<Future<Item = (u64, Self), Error = (Error, Self)> + Send>;
    fn query(self, statement: &Statement, params: &[&ToSql]) -> Box<Future<Item = Row, State = Self, Error = Error> + Send>;
}

impl ConnectionLike for Connection {
    ...
}

impl ConnectionLike for Transaction {
    ...
}

Which could allow for things like the following. This example function, fetch_events could be called in production with a Connection, but could be called in tests with a Transaction, allowing for easy rollbacks.

fn fetch_events<C: ConnectionLike>(conn: C) -> impl Future<Item = (Vec<Event>, C), Error = (Error, C)> {
    conn.prepare("SELECT evt.id, evt.title FROM events AS evt")
        .and_then(move |(s, conn)| {
            conn.query(&s, &[&id])
                .map(move |row| Event {
                    id: row.get(0),
                    title: row.get(1),
                })
                .collect()
        })
}

// in the test (this could likely be extracted into a boilerplate function)
connection
    .transaction()
    .and_then(|transaction| {
        fetch_events(transaction)
        .map_err(|(error, transaction)| {
            transaction.rollback().map(|connection| (error, connection))
        })
        .map(|(events, transaction)| {
            transaction.rollback().map(|connection| (events, connection))
        })

// in the production code
fetch_events(connection)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions