Skip to content

Commit a9b01b4

Browse files
authored
Merge pull request rust-postgres#384 from DarrenTsung/transaction-builder
Add a TransactionBuilder struct
2 parents ce7580d + f3777be commit a9b01b4

2 files changed

Lines changed: 73 additions & 1 deletion

File tree

tokio-postgres/src/lib.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,17 @@ impl Client {
107107
// FIXME error type?
108108
T::Error: From<Error>,
109109
{
110-
Transaction(proto::TransactionFuture::new(self.0.clone(), future))
110+
self.transaction_builder().build(future)
111+
}
112+
113+
/// Creates a TransactionBuilder, which can later be used to create
114+
/// a Transaction around a future.
115+
///
116+
/// Use this when Client is moved into the future being built.
117+
/// For example, when executing multiple statements that depend
118+
/// on the previous statement's result.
119+
pub fn transaction_builder(&self) -> TransactionBuilder {
120+
TransactionBuilder(self.0.clone())
111121
}
112122

113123
pub fn batch_execute(&mut self, query: &str) -> BatchExecute {
@@ -345,6 +355,19 @@ impl Row {
345355
}
346356
}
347357

358+
pub struct TransactionBuilder(proto::Client);
359+
360+
impl TransactionBuilder {
361+
pub fn build<T>(self, future: T) -> Transaction<T>
362+
where
363+
T: Future,
364+
// FIXME error type?
365+
T::Error: From<Error>,
366+
{
367+
Transaction(proto::TransactionFuture::new(self.0, future))
368+
}
369+
}
370+
348371
#[must_use = "futures do nothing unless polled"]
349372
pub struct Transaction<T>(proto::TransactionFuture<T, T::Item, T::Error>)
350373
where

tokio-postgres/tests/test.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,3 +693,52 @@ fn copy_out() {
693693
).unwrap();
694694
assert_eq!(&data[..], b"1\tjim\n2\tjoe\n");
695695
}
696+
697+
#[test]
698+
fn transaction_builder_around_moved_client() {
699+
let _ = env_logger::try_init();
700+
let mut runtime = Runtime::new().unwrap();
701+
702+
let (mut client, connection) = runtime
703+
.block_on(tokio_postgres::connect(
704+
"postgres://postgres@localhost:5433".parse().unwrap(),
705+
TlsMode::None,
706+
)).unwrap();
707+
let connection = connection.map_err(|e| panic!("{}", e));
708+
runtime.handle().spawn(connection).unwrap();
709+
710+
let transaction_builder = client.transaction_builder();
711+
let work = future::lazy(move || {
712+
let execute =
713+
client.batch_execute(
714+
"CREATE TEMPORARY TABLE transaction_foo (
715+
id SERIAL,
716+
name TEXT
717+
)");
718+
719+
execute.and_then(move |_| {
720+
client
721+
.prepare("INSERT INTO transaction_foo (name) VALUES ($1), ($2)")
722+
.map(|statement| (client, statement))
723+
})
724+
}).and_then(|(mut client, statement)| {
725+
client
726+
.query(&statement, &[&"jim", &"joe"])
727+
.collect()
728+
.map(|_res| client)
729+
});
730+
731+
let transaction = transaction_builder.build(work);
732+
let mut client = runtime.block_on(transaction).unwrap();
733+
734+
let data = runtime
735+
.block_on(
736+
client
737+
.prepare("COPY transaction_foo TO STDOUT")
738+
.and_then(|s| client.copy_out(&s, &[]).concat2()),
739+
).unwrap();
740+
assert_eq!(&data[..], b"1\tjim\n2\tjoe\n");
741+
742+
drop(client);
743+
runtime.run().unwrap();
744+
}

0 commit comments

Comments
 (0)