Skip to content

Commit a677f62

Browse files
committed
Remove lazy query support
It turns out this only works inside a transaction, so the API will need to be rethought. Probably PostgresTransaction.prepare will return a special TransactionalPreparedStatement that has support for it or something.
1 parent 03e0ab2 commit a677f62

3 files changed

Lines changed: 36 additions & 130 deletions

File tree

src/lib.rs

Lines changed: 36 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@
44

55
extern mod extra;
66

7-
use extra::container::Deque;
87
use extra::digest::Digest;
98
use extra::md5::Md5;
109
use extra::url::{UserInfo, Url};
11-
use extra::ringbuf::RingBuf;
1210
use std::cell::Cell;
1311
use std::hashmap::HashMap;
1412
use 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
580564
pub 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
608569
impl<'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-
651580
pub struct PostgresRow<'self> {
652581
priv stmt: &'self PostgresStatement<'self>,
653582
priv data: ~[Option<~[u8]>]

src/message.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ pub enum BackendMessage {
4545
value: ~str
4646
},
4747
ParseComplete,
48-
PortalSuspended,
4948
ReadyForQuery {
5049
state: u8
5150
},
@@ -262,7 +261,6 @@ impl<R: Reader> ReadMessage for R {
262261
'n' => NoData,
263262
'N' => NoticeResponse { fields: read_fields(&mut buf) },
264263
'R' => read_auth_message(&mut buf),
265-
's' => PortalSuspended,
266264
'S' => ParameterStatus {
267265
parameter: buf.read_string(),
268266
value: buf.read_string()

src/test.rs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -74,27 +74,6 @@ fn test_nulls() {
7474
}
7575
}
7676
77-
#[test]
78-
fn test_lazy_query() {
79-
do test_in_transaction |trans| {
80-
trans.update("CREATE TABLE foo (
81-
id SERIAL PRIMARY KEY,
82-
val BIGINT
83-
)", []);
84-
let stmt = trans.prepare("INSERT INTO foo (val) VALUES ($1)");
85-
let data = ~[1i64, 2, 3, 4, 5, 6];
86-
for datum in data.iter() {
87-
stmt.update([datum as &ToSql]);
88-
}
89-
90-
let stmt = trans.prepare("SELECT val FROM foo ORDER BY id");
91-
let result = stmt.lazy_query(2, []);
92-
93-
assert_eq!(data,
94-
result.map(|row| { row[0] }).collect());
95-
}
96-
}
97-
9877
fn test_type<T: Eq+ToSql+FromSql>(sql_type: &str, values: &[T]) {
9978
do test_in_transaction |trans| {
10079
trans.update("CREATE TABLE foo (

0 commit comments

Comments
 (0)