Skip to content

Commit c2b3768

Browse files
committed
Infrastructure for lazy queries in transactions
cc rust-postgres#13
1 parent 91d7c85 commit c2b3768

1 file changed

Lines changed: 73 additions & 27 deletions

File tree

src/lib.rs

Lines changed: 73 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ impl PostgresConnection {
257257
})
258258
}
259259
260-
pub fn prepare<'a>(&'a self, query: &str) -> PostgresStatement<'a> {
260+
pub fn prepare<'a>(&'a self, query: &str) -> NormalPostgresStatement<'a> {
261261
match self.try_prepare(query) {
262262
Ok(stmt) => stmt,
263263
Err(err) => fail2!("Error preparing \"{}\": {}", query,
@@ -266,7 +266,7 @@ impl PostgresConnection {
266266
}
267267
268268
pub fn try_prepare<'a>(&'a self, query: &str)
269-
-> Result<PostgresStatement<'a>, PostgresDbError> {
269+
-> Result<NormalPostgresStatement<'a>, PostgresDbError> {
270270
let id = self.next_stmt_id.take();
271271
let stmt_name = format!("statement_{}", id);
272272
self.next_stmt_id.put_back(id + 1);
@@ -303,7 +303,7 @@ impl PostgresConnection {
303303
304304
self.wait_for_ready();
305305
306-
Ok(PostgresStatement {
306+
Ok(NormalPostgresStatement {
307307
conn: self,
308308
name: stmt_name,
309309
param_types: param_types,
@@ -370,13 +370,16 @@ pub struct PostgresTransaction<'self> {
370370
}
371371
372372
impl<'self> PostgresTransaction<'self> {
373-
pub fn prepare<'a>(&'a self, query: &str) -> PostgresStatement<'a> {
374-
self.conn.prepare(query)
373+
pub fn prepare<'a>(&'a self, query: &str)
374+
-> TransactionalPostgresStatement<'a> {
375+
TransactionalPostgresStatement { stmt: self.conn.prepare(query) }
375376
}
376377
377378
pub fn try_prepare<'a>(&'a self, query: &str)
378-
-> Result<PostgresStatement<'a>, PostgresDbError> {
379-
self.conn.try_prepare(query)
379+
-> Result<TransactionalPostgresStatement<'a>, PostgresDbError> {
380+
do self.conn.try_prepare(query).map_move |stmt| {
381+
TransactionalPostgresStatement { stmt: stmt }
382+
}
380383
}
381384
382385
pub fn update(&self, query: &str, params: &[&ToSql]) -> uint {
@@ -405,15 +408,25 @@ impl<'self> PostgresTransaction<'self> {
405408
}
406409
}
407410
408-
pub struct PostgresStatement<'self> {
411+
pub trait PostgresStatement {
412+
fn num_params(&self) -> uint;
413+
fn update(&self, params: &[&ToSql]) -> uint;
414+
fn try_update(&self, params: &[&ToSql]) -> Result<uint, PostgresDbError>;
415+
fn query<'a>(&'a self, params: &[&ToSql]) -> PostgresResult<'a>;
416+
fn try_query<'a>(&'a self, params: &[&ToSql])
417+
-> Result<PostgresResult<'a>, PostgresDbError>;
418+
fn find_col_named(&self, col: &str) -> Option<uint>;
419+
}
420+
421+
pub struct NormalPostgresStatement<'self> {
409422
priv conn: &'self PostgresConnection,
410423
priv name: ~str,
411424
priv param_types: ~[Oid],
412425
priv result_desc: ~[RowDescriptionEntry],
413426
}
414427
415428
#[unsafe_destructor]
416-
impl<'self> Drop for PostgresStatement<'self> {
429+
impl<'self> Drop for NormalPostgresStatement<'self> {
417430
fn drop(&self) {
418431
do io_error::cond.trap(|_| {}).inside {
419432
self.conn.write_messages([
@@ -432,11 +445,7 @@ impl<'self> Drop for PostgresStatement<'self> {
432445
}
433446
}
434447
435-
impl<'self> PostgresStatement<'self> {
436-
pub fn num_params(&self) -> uint {
437-
self.param_types.len()
438-
}
439-
448+
impl<'self> NormalPostgresStatement<'self> {
440449
fn execute(&self, portal_name: &str, params: &[&ToSql])
441450
-> Option<PostgresDbError> {
442451
let mut formats = ~[];
@@ -473,15 +482,21 @@ impl<'self> PostgresStatement<'self> {
473482
}
474483
})
475484
}
485+
}
476486
477-
pub fn update(&self, params: &[&ToSql]) -> uint {
487+
impl<'self> PostgresStatement for NormalPostgresStatement<'self> {
488+
fn num_params(&self) -> uint {
489+
self.param_types.len()
490+
}
491+
492+
fn update(&self, params: &[&ToSql]) -> uint {
478493
match self.try_update(params) {
479494
Ok(count) => count,
480495
Err(err) => fail2!("Error running update: {}", err.to_str())
481496
}
482497
}
483498
484-
pub fn try_update(&self, params: &[&ToSql])
499+
fn try_update(&self, params: &[&ToSql])
485500
-> Result<uint, PostgresDbError> {
486501
match self.execute("", params) {
487502
Some(err) => {
@@ -518,16 +533,16 @@ impl<'self> PostgresStatement<'self> {
518533
Ok(num)
519534
}
520535
521-
pub fn query(&'self self, params: &[&ToSql])
522-
-> PostgresResult<'self> {
536+
fn query<'a>(&'a self, params: &[&ToSql])
537+
-> PostgresResult<'a> {
523538
match self.try_query(params) {
524539
Ok(result) => result,
525540
Err(err) => fail2!("Error running query: {}", err.to_str())
526541
}
527542
}
528543
529-
pub fn try_query(&'self self, params: &[&ToSql])
530-
-> Result<PostgresResult<'self>, PostgresDbError> {
544+
fn try_query<'a>(&'a self, params: &[&ToSql])
545+
-> Result<PostgresResult<'a>, PostgresDbError> {
531546
match self.execute("", params) {
532547
Some(err) => {
533548
return Err(err);
@@ -555,15 +570,46 @@ impl<'self> PostgresStatement<'self> {
555570
})
556571
}
557572
558-
pub fn find_col_named(&self, col: &str) -> Option<uint> {
573+
fn find_col_named(&self, col: &str) -> Option<uint> {
559574
do self.result_desc.iter().position |desc| {
560575
desc.name.as_slice() == col
561576
}
562577
}
563578
}
564579
580+
pub struct TransactionalPostgresStatement<'self> {
581+
priv stmt: NormalPostgresStatement<'self>
582+
}
583+
584+
impl<'self> PostgresStatement for TransactionalPostgresStatement<'self> {
585+
fn num_params(&self) -> uint {
586+
self.stmt.num_params()
587+
}
588+
589+
fn update(&self, params: &[&ToSql]) -> uint {
590+
self.stmt.update(params)
591+
}
592+
593+
fn try_update(&self, params: &[&ToSql]) -> Result<uint, PostgresDbError> {
594+
self.stmt.try_update(params)
595+
}
596+
597+
fn query<'a>(&'a self, params: &[&ToSql]) -> PostgresResult<'a> {
598+
self.stmt.query(params)
599+
}
600+
601+
fn try_query<'a>(&'a self, params: &[&ToSql])
602+
-> Result<PostgresResult<'a>, PostgresDbError> {
603+
self.stmt.try_query(params)
604+
}
605+
606+
fn find_col_named(&self, col: &str) -> Option<uint> {
607+
self.stmt.find_col_named(col)
608+
}
609+
}
610+
565611
pub struct PostgresResult<'self> {
566-
priv stmt: &'self PostgresStatement<'self>,
612+
priv stmt: &'self NormalPostgresStatement<'self>,
567613
priv data: ~[~[Option<~[u8]>]]
568614
}
569615
@@ -579,7 +625,7 @@ impl<'self> Iterator<PostgresRow<'self>> for PostgresResult<'self> {
579625
}
580626
581627
pub struct PostgresRow<'self> {
582-
priv stmt: &'self PostgresStatement<'self>,
628+
priv stmt: &'self NormalPostgresStatement<'self>,
583629
priv data: ~[Option<~[u8]>]
584630
}
585631
@@ -598,25 +644,25 @@ impl<'self, I: RowIndex, T: FromSql> Index<I, T> for PostgresRow<'self> {
598644
}
599645
600646
pub trait RowIndex {
601-
fn idx(&self, stmt: &PostgresStatement) -> uint;
647+
fn idx(&self, stmt: &NormalPostgresStatement) -> uint;
602648
}
603649
604650
impl RowIndex for uint {
605-
fn idx(&self, _stmt: &PostgresStatement) -> uint {
651+
fn idx(&self, _stmt: &NormalPostgresStatement) -> uint {
606652
*self
607653
}
608654
}
609655
610656
// This is a convenicence as the 0 in get[0] resolves to int :(
611657
impl RowIndex for int {
612-
fn idx(&self, _stmt: &PostgresStatement) -> uint {
658+
fn idx(&self, _stmt: &NormalPostgresStatement) -> uint {
613659
assert!(*self >= 0);
614660
*self as uint
615661
}
616662
}
617663
618664
impl<'self> RowIndex for &'self str {
619-
fn idx(&self, stmt: &PostgresStatement) -> uint {
665+
fn idx(&self, stmt: &NormalPostgresStatement) -> uint {
620666
match stmt.find_col_named(*self) {
621667
Some(idx) => idx,
622668
None => fail2!("No column with name {}", *self)

0 commit comments

Comments
 (0)