Skip to content

Commit d3c75d5

Browse files
committed
Use the unnamed portal for normal queries
There's no need to add extra round trips to close portals that don't need to exist.
1 parent dde0f64 commit d3c75d5

1 file changed

Lines changed: 96 additions & 87 deletions

File tree

src/lib.rs

Lines changed: 96 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,24 +1346,17 @@ impl<'conn> Statement<'conn> {
13461346
}
13471347
}
13481348

1349-
fn inner_lazy_query<'a>(&'a self, row_limit: i32, params: &[&ToSql]) -> Result<Rows<'a>> {
1350-
let id = self.next_portal_id.get();
1351-
self.next_portal_id.set(id + 1);
1352-
let portal_name = format!("{}p{}", self.name, id);
1353-
1354-
try!(self.inner_execute(&*portal_name, row_limit, params));
1349+
fn inner_query<'a>(&'a self, portal_name: &str, row_limit: i32, params: &[&ToSql])
1350+
-> Result<(Rows<'a>, bool)> {
1351+
try!(self.inner_execute(portal_name, row_limit, params));
13551352

13561353
let mut result = Rows {
13571354
stmt: self,
1358-
name: portal_name,
13591355
data: RingBuf::new(),
1360-
row_limit: row_limit,
1361-
more_rows: true,
1362-
finished: false,
13631356
};
1364-
try!(result.read_rows());
1357+
let more_rows = try!(result.read_rows());
13651358

1366-
Ok(result)
1359+
Ok((result, more_rows))
13671360
}
13681361

13691362
/// Returns a slice containing the expected parameter types.
@@ -1453,7 +1446,7 @@ impl<'conn> Statement<'conn> {
14531446
/// ```
14541447
pub fn query<'a>(&'a self, params: &[&ToSql]) -> Result<Rows<'a>> {
14551448
check_desync!(self.conn);
1456-
self.inner_lazy_query(0, params)
1449+
self.inner_query("", 0, params).map(|t| t.0)
14571450
}
14581451

14591452
/// Executes the prepared statement, returning a lazily loaded iterator
@@ -1481,12 +1474,24 @@ impl<'conn> Statement<'conn> {
14811474
return Err(Error::WrongTransaction);
14821475
}
14831476
drop(conn);
1484-
self.inner_lazy_query(row_limit, params).map(|result| {
1485-
LazyRows {
1486-
_trans: trans,
1487-
result: result
1477+
1478+
let id = self.next_portal_id.get();
1479+
self.next_portal_id.set(id + 1);
1480+
let portal_name = format!("{}p{}", self.name, id);
1481+
1482+
match self.inner_query(&*portal_name, row_limit, params) {
1483+
Ok((result, more_rows)) => {
1484+
Ok(LazyRows {
1485+
_trans: trans,
1486+
result: result,
1487+
name: portal_name,
1488+
row_limit: row_limit,
1489+
more_rows: more_rows,
1490+
finished: false,
1491+
})
14881492
}
1489-
})
1493+
Err(err) => Err(err),
1494+
}
14901495
}
14911496

14921497
/// Consumes the statement, clearing it from the Postgres session.
@@ -1510,46 +1515,27 @@ pub struct ResultDescription {
15101515
/// An iterator over the resulting rows of a query.
15111516
pub struct Rows<'stmt> {
15121517
stmt: &'stmt Statement<'stmt>,
1513-
name: String,
15141518
data: RingBuf<Vec<Option<Vec<u8>>>>,
1515-
row_limit: i32,
1516-
more_rows: bool,
1517-
finished: bool,
15181519
}
15191520

15201521
impl<'a> fmt::Debug for Rows<'a> {
15211522
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1522-
write!(fmt, "Rows {{ statement: {:?}, name: {:?}, remaining_rows: {:?} }}",
1523-
self.stmt, self.name, self.data.len())
1524-
}
1525-
}
1526-
1527-
#[unsafe_destructor]
1528-
impl<'stmt> Drop for Rows<'stmt> {
1529-
fn drop(&mut self) {
1530-
if !self.finished {
1531-
let _ = self.finish_inner();
1532-
}
1523+
write!(fmt, "Rows {{ statement: {:?}, remaining_rows: {:?} }}", self.stmt, self.data.len())
15331524
}
15341525
}
15351526

15361527
impl<'stmt> Rows<'stmt> {
1537-
fn finish_inner(&mut self) -> Result<()> {
1538-
let mut conn = self.stmt.conn.conn.borrow_mut();
1539-
check_desync!(conn);
1540-
conn.close_statement(&*self.name, b'P')
1541-
}
1542-
1543-
fn read_rows(&mut self) -> Result<()> {
1528+
fn read_rows(&mut self) -> Result<bool> {
15441529
let mut conn = self.stmt.conn.conn.borrow_mut();
1530+
let more_rows;
15451531
loop {
15461532
match try!(conn.read_message()) {
15471533
EmptyQueryResponse | CommandComplete { .. } => {
1548-
self.more_rows = false;
1534+
more_rows = false;
15491535
break;
15501536
}
15511537
PortalSuspended => {
1552-
self.more_rows = true;
1538+
more_rows = true;
15531539
break;
15541540
}
15551541
DataRow { row } => self.data.push_back(row),
@@ -1570,41 +1556,19 @@ impl<'stmt> Rows<'stmt> {
15701556
}
15711557
}
15721558
}
1573-
conn.wait_for_ready()
1574-
}
1575-
1576-
fn execute(&mut self) -> Result<()> {
1577-
try!(self.stmt.conn.write_messages(&[
1578-
Execute {
1579-
portal: &*self.name,
1580-
max_rows: self.row_limit
1581-
},
1582-
Sync]));
1583-
self.read_rows()
1559+
try!(conn.wait_for_ready());
1560+
Ok(more_rows)
15841561
}
15851562

15861563
/// Returns a slice describing the columns of the `Rows`.
15871564
pub fn result_descriptions(&self) -> &'stmt [ResultDescription] {
15881565
self.stmt.result_descriptions()
15891566
}
15901567

1591-
/// Consumes the `Rows`, cleaning up associated state.
1592-
///
1593-
/// Functionally identical to the `Drop` implementation on `Rows`
1594-
/// except that it returns any error to the caller.
1595-
pub fn finish(mut self) -> Result<()> {
1596-
self.finished = true;
1597-
self.finish_inner()
1598-
}
1599-
1600-
fn try_next(&mut self) -> Option<Result<Row<'stmt>>> {
1601-
if self.data.is_empty() && self.more_rows {
1602-
if let Err(err) = self.execute() {
1603-
return Some(Err(err));
1604-
}
1605-
}
1606-
1607-
self.data.pop_front().map(|row| Ok(Row { stmt: self.stmt, data: row }))
1568+
#[deprecated = "now a no-op"]
1569+
#[allow(missing_docs)]
1570+
pub fn finish(self) -> Result<()> {
1571+
Ok(())
16081572
}
16091573
}
16101574

@@ -1613,19 +1577,12 @@ impl<'stmt> Iterator for Rows<'stmt> {
16131577

16141578
#[inline]
16151579
fn next(&mut self) -> Option<Row<'stmt>> {
1616-
// we'll never hit the network on a non-lazy result
1617-
self.try_next().map(|r| r.unwrap())
1580+
self.data.pop_front().map(|row| Row { stmt: self.stmt, data: row })
16181581
}
16191582

16201583
#[inline]
16211584
fn size_hint(&self) -> (usize, Option<usize>) {
1622-
let lower = self.data.len();
1623-
let upper = if self.more_rows {
1624-
None
1625-
} else {
1626-
Some(lower)
1627-
};
1628-
(lower, upper)
1585+
(self.data.len(), Some(self.data.len()))
16291586
}
16301587
}
16311588

@@ -1721,38 +1678,90 @@ impl<'a> RowIndex for &'a str {
17211678
/// A lazily-loaded iterator over the resulting rows of a query
17221679
pub struct LazyRows<'trans, 'stmt> {
17231680
result: Rows<'stmt>,
1681+
name: String,
1682+
row_limit: i32,
1683+
more_rows: bool,
1684+
finished: bool,
17241685
_trans: &'trans Transaction<'trans>,
17251686
}
17261687

1688+
#[unsafe_destructor]
1689+
impl<'a, 'b> Drop for LazyRows<'a, 'b> {
1690+
fn drop(&mut self) {
1691+
if !self.finished {
1692+
let _ = self.finish_inner();
1693+
}
1694+
}
1695+
}
1696+
17271697
impl<'a, 'b> fmt::Debug for LazyRows<'a, 'b> {
17281698
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
17291699
write!(fmt,
17301700
"LazyRows {{ statement: {:?}, name: {:?}, row_limit: {:?}, remaining_rows: {:?}, \
17311701
more_rows: {:?} }}",
17321702
self.result.stmt,
1733-
self.result.name,
1734-
self.result.row_limit,
1703+
self.name,
1704+
self.row_limit,
17351705
self.result.data.len(),
1736-
self.result.more_rows)
1706+
self.more_rows)
17371707
}
17381708
}
17391709

17401710
impl<'trans, 'stmt> LazyRows<'trans, 'stmt> {
1741-
/// Like `Rows::finish`.
1742-
pub fn finish(self) -> Result<()> {
1743-
self.result.finish()
1711+
fn finish_inner(&mut self) -> Result<()> {
1712+
let mut conn = self.result.stmt.conn.conn.borrow_mut();
1713+
check_desync!(conn);
1714+
conn.close_statement(&*self.name, b'P')
1715+
}
1716+
1717+
fn execute(&mut self) -> Result<()> {
1718+
try!(self.result.stmt.conn.write_messages(&[
1719+
Execute {
1720+
portal: &*self.name,
1721+
max_rows: self.row_limit
1722+
},
1723+
Sync]));
1724+
self.result.read_rows().map(|more_rows| {
1725+
self.more_rows = more_rows;
1726+
()
1727+
})
1728+
}
1729+
1730+
/// Returns a slice describing the columns of the `Rows`.
1731+
pub fn result_descriptions(&self) -> &'stmt [ResultDescription] {
1732+
self.result.stmt.result_descriptions()
1733+
}
1734+
1735+
/// Consumes the `LazyRows`, cleaning up associated state.
1736+
///
1737+
/// Functionally identical to the `Drop` implementation on `LazyRows`
1738+
/// except that it returns any error to the caller.
1739+
pub fn finish(mut self) -> Result<()> {
1740+
self.finish_inner()
17441741
}
17451742
}
17461743

17471744
impl<'trans, 'stmt> Iterator for LazyRows<'trans, 'stmt> {
17481745
type Item = Result<Row<'stmt>>;
17491746

17501747
fn next(&mut self) -> Option<Result<Row<'stmt>>> {
1751-
self.result.try_next()
1748+
if self.result.data.is_empty() && self.more_rows {
1749+
if let Err(err) = self.execute() {
1750+
return Some(Err(err));
1751+
}
1752+
}
1753+
1754+
self.result.next().map(|r| Ok(r))
17521755
}
17531756

17541757
fn size_hint(&self) -> (usize, Option<usize>) {
1755-
self.result.size_hint()
1758+
let lower = self.result.data.len();
1759+
let upper = if self.more_rows {
1760+
None
1761+
} else {
1762+
Some(lower)
1763+
};
1764+
(lower, upper)
17561765
}
17571766
}
17581767

0 commit comments

Comments
 (0)