44
55extern mod extra;
66
7- use extra:: container:: Deque ;
87use extra:: digest:: Digest ;
98use extra:: md5:: Md5 ;
109use extra:: url:: { UserInfo , Url } ;
11- use extra:: ringbuf:: RingBuf ;
1210use std:: cell:: Cell ;
1311use std:: hashmap:: HashMap ;
1412use std:: rt:: io:: { io_error, Decorator } ;
@@ -305,7 +303,6 @@ impl PostgresConnection {
305303 name: stmt_name,
306304 param_types: param_types,
307305 result_desc: result_desc,
308- next_portal_id: Cell::new(0)
309306 })
310307 }
311308
@@ -409,7 +406,6 @@ pub struct PostgresStatement<'self> {
409406 priv name: ~str,
410407 priv param_types: ~[Oid],
411408 priv result_desc: ~[RowDescriptionEntry],
412- priv next_portal_id: Cell<uint>
413409}
414410
415411#[unsafe_destructor]
@@ -437,7 +433,7 @@ impl<'self> PostgresStatement<'self> {
437433 self.param_types.len()
438434 }
439435
440- fn bind (&self, portal_name: &str, params: &[&ToSql])
436+ fn execute (&self, portal_name: &str, params: &[&ToSql])
441437 -> Option<PostgresDbError> {
442438 let mut formats = ~[];
443439 let mut values = ~[];
@@ -459,17 +455,20 @@ impl<'self> PostgresStatement<'self> {
459455 values: values,
460456 result_formats: result_formats
461457 },
458+ &Execute {
459+ portal: portal_name,
460+ max_rows: 0
461+ },
462462 &Sync]);
463463
464- let ret = match_read_message!(self.conn, {
464+ match_read_message!(self.conn, {
465465 BindComplete => None,
466- ErrorResponse { fields } => Some(PostgresDbError::new(fields)),
466+ ErrorResponse { fields } => {
467+ self.conn.wait_for_ready();
468+ Some(PostgresDbError::new(fields))
469+ },
467470 resp => fail!(" Bad response: %?", resp.to_str())
468- });
469-
470- self.conn.wait_for_ready();
471-
472- ret
471+ })
473472 }
474473
475474 pub fn update(&self, params: &[&ToSql]) -> uint {
@@ -481,21 +480,13 @@ impl<'self> PostgresStatement<'self> {
481480
482481 pub fn try_update(&self, params: &[&ToSql])
483482 -> Result<uint, PostgresDbError> {
484- // The unnamed portal is automatically cleaned up at sync time
485- match self.bind(" ", params) {
483+ match self.execute(" ", params) {
486484 Some(err) => {
487485 return Err(err);
488486 }
489487 None => ()
490488 }
491489
492- self.conn.write_messages([
493- &Execute {
494- portal: &" ",
495- max_rows: 0
496- },
497- &Sync]);
498-
499490 let num;
500491 loop {
501492 match_read_message!(self.conn, {
@@ -525,49 +516,42 @@ impl<'self> PostgresStatement<'self> {
525516 Ok(num)
526517 }
527518
528- pub fn query(&'self self, params: &[&ToSql]) -> PostgresResult<'self> {
529- self.lazy_query(0, params)
530- }
531-
532- pub fn try_query(&'self self, params: &[&ToSql])
533- -> Result<PostgresResult<'self>, PostgresDbError> {
534- self.try_lazy_query(0, params)
535- }
536-
537- pub fn lazy_query(&'self self, row_limit: uint, params: &[&ToSql])
519+ pub fn query(&'self self, params: &[&ToSql])
538520 -> PostgresResult<'self> {
539- match self.try_lazy_query(row_limit, params) {
521+ match self.try_query( params) {
540522 Ok(result) => result,
541523 Err(err) => fail!(" Error running query: %s", err.to_str())
542524 }
543525 }
544526
545- pub fn try_lazy_query (&'self self, row_limit: uint , params: &[&ToSql])
527+ pub fn try_query (&'self self, params: &[&ToSql])
546528 -> Result<PostgresResult<'self>, PostgresDbError> {
547- let id = self.next_portal_id.take();
548- let portal_name = format!(" { } _portal_{ } ", self.name.as_slice(), id);
549- self.next_portal_id.put_back(id + 1);
550-
551- match self.bind(portal_name, params) {
529+ match self.execute(" ", params) {
552530 Some(err) => {
553- self.conn.wait_for_ready();
554531 return Err(err);
555532 }
556533 None => ()
557534 }
558535
559- let mut result = PostgresResult {
560- stmt: self,
561- name: portal_name,
562- data: RingBuf::new(),
563- more_rows: true,
564- max_rows: row_limit
565- };
566- // We have to make sure to execute the result at least once since it
567- // may have side effects (e.g. INSERT ... RETURNING ...)
568- result.execute();
536+ let mut data = ~[];
537+ loop {
538+ match_read_message!(self.conn, {
539+ EmptyQueryResponse |
540+ CommandComplete {_} => {
541+ break;
542+ },
543+ DataRow { row } => data.push(row),
544+ resp => fail!(" Bad response: %?", resp.to_str())
545+ })
546+ }
547+ self.conn.wait_for_ready();
569548
570- Ok(result)
549+ // we're going to be popping off
550+ data.reverse();
551+ Ok(PostgresResult {
552+ stmt: self,
553+ data: data,
554+ })
571555 }
572556
573557 pub fn find_col_named(&self, col: &str) -> Option<uint> {
@@ -579,39 +563,12 @@ impl<'self> PostgresStatement<'self> {
579563
580564pub struct PostgresResult<'self> {
581565 priv stmt: &'self PostgresStatement<'self>,
582- priv name: ~str,
583- priv data: RingBuf<~[Option<~[u8]>]>,
584- priv max_rows: uint,
585- priv more_rows: bool
586- }
587-
588- #[unsafe_destructor]
589- impl<'self> Drop for PostgresResult<'self> {
590- fn drop(&self) {
591- do io_error::cond.trap(|_| {}).inside {
592- self.stmt.conn.write_messages([
593- &Close {
594- variant: 'P' as u8,
595- name: self.name.as_slice()
596- },
597- &Sync]);
598- loop {
599- match_read_message!(self.stmt.conn, {
600- ReadyForQuery {_} => break,
601- _ => ()
602- })
603- }
604- }
605- }
566+ priv data: ~[~[Option<~[u8]>]]
606567}
607568
608569impl<'self> Iterator<PostgresRow<'self>> for PostgresResult<'self> {
609570 fn next(&mut self) -> Option<PostgresRow<'self>> {
610- if self.data.is_empty() && self.more_rows {
611- self.execute();
612- }
613-
614- do self.data.pop_front().map_move |row| {
571+ do self.data.pop_opt().map_move |row| {
615572 PostgresRow {
616573 stmt: self.stmt,
617574 data: row
@@ -620,34 +577,6 @@ impl<'self> Iterator<PostgresRow<'self>> for PostgresResult<'self> {
620577 }
621578}
622579
623- impl<'self> PostgresResult<'self> {
624- fn execute(&mut self) {
625- self.stmt.conn.write_messages([
626- &Execute {
627- portal: self.name,
628- max_rows: self.max_rows as i32
629- },
630- &Sync]);
631-
632- loop {
633- match_read_message!(self.stmt.conn, {
634- EmptyQueryResponse |
635- CommandComplete {_} => {
636- self.more_rows = false;
637- break;
638- },
639- DataRow { row } => self.data.push_back(row),
640- PortalSuspended => {
641- self.more_rows = true;
642- break;
643- },
644- resp => fail!(" Bad response: %?", resp.to_str())
645- })
646- }
647- self.stmt.conn.wait_for_ready();
648- }
649- }
650-
651580pub struct PostgresRow<'self> {
652581 priv stmt: &'self PostgresStatement<'self>,
653582 priv data: ~[Option<~[u8]>]
0 commit comments